authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-17 22:00:55-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-12-17 22:00:55-05:00
logd245fabb80c83d1f2b845c42658b6f82d3f89b6f
tree1d8bb1249a20545a4ce86bce3ef21639a81c0989
parent0f047337ac0bf65b5f6d92248adc1452047f2622

IR: consolidate Ref and PrefixOpAddressOf instructions


4 files changed, 60 insertions(+), 108 deletions(-)

src/all_types.hpp-2
......@@ -1517,8 +1517,6 @@ enum IrUnOp {
15171517 IrUnOpBinNot,
15181518 IrUnOpNegation,
15191519 IrUnOpNegationWrap,
1520 IrUnOpAddressOf,
1521 IrUnOpConstAddressOf,
15221520 IrUnOpDereference,
15231521 IrUnOpError,
15241522 IrUnOpMaybe,
src/codegen.cpp-7
......@@ -1175,13 +1175,6 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst
11751175 }
11761176 case IrUnOpBinNot:
11771177 return LLVMBuildNot(g->builder, expr, "");
1178 case IrUnOpAddressOf:
1179 case IrUnOpConstAddressOf:
1180 zig_panic("TODO address of codegen");
1181 //{
1182 // TypeTableEntry *lvalue_type;
1183 // return gen_lvalue(g, node, expr_node, &lvalue_type);
1184 //}
11851178 case IrUnOpDereference:
11861179 {
11871180 assert(expr_type->id == TypeTableEntryIdPointer);
src/ir.cpp+60-95
......@@ -2368,8 +2368,8 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
23682368 auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name);
23692369 if (primitive_table_entry) {
23702370 IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_table_entry->value);
2371 if (lval == LValPurposeAddressOf) {
2372 return ir_build_un_op(irb, scope, node, IrUnOpAddressOf, value);
2371 if (lval != LValPurposeNone) {
2372 return ir_build_ref(irb, scope, node, value);
23732373 } else {
23742374 return value;
23752375 }
......@@ -2947,10 +2947,6 @@ static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, Ast
29472947 if (value == irb->codegen->invalid_instruction)
29482948 return value;
29492949
2950 if (lval == LValPurposeAddressOf && (op_id == IrUnOpAddressOf || op_id == IrUnOpConstAddressOf)) {
2951 return value;
2952 }
2953
29542950 return ir_build_un_op(irb, scope, node, op_id, value);
29552951}
29562952
......@@ -2958,6 +2954,29 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode
29582954 return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValPurposeNone);
29592955}
29602956
2957static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LValPurpose lval) {
2958 if (lval == LValPurposeNone)
2959 return value;
2960 if (value == irb->codegen->invalid_instruction)
2961 return value;
2962
2963 // We needed a pointer to a value, but we got a value. So we create
2964 // an instruction which just makes a const pointer of it.
2965 return ir_build_ref(irb, scope, value->source_node, value);
2966}
2967
2968static IrInstruction *ir_gen_address_of(IrBuilder *irb, Scope *scope, AstNode *node, bool is_const, LValPurpose lval) {
2969 assert(node->type == NodeTypePrefixOpExpr);
2970 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
2971
2972 IrInstruction *value = ir_gen_node_extra(irb, expr_node, scope, LValPurposeAddressOf);
2973 if (value == irb->codegen->invalid_instruction)
2974 return value;
2975
2976
2977 return ir_lval_wrap(irb, scope, value, lval);
2978}
2979
29612980static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {
29622981 assert(node->type == NodeTypePrefixOpExpr);
29632982 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
......@@ -3002,17 +3021,6 @@ static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *nod
30023021 return ir_build_bool_not(irb, scope, node, value);
30033022}
30043023
3005static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LValPurpose lval) {
3006 if (lval == LValPurposeNone)
3007 return value;
3008 if (value == irb->codegen->invalid_instruction)
3009 return value;
3010
3011 // We needed a pointer to a value, but we got a value. So we create
3012 // an instruction which just makes a const pointer of it.
3013 return ir_build_ref(irb, scope, value->source_node, value);
3014}
3015
30163024static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {
30173025 assert(node->type == NodeTypePrefixOpExpr);
30183026
......@@ -3024,21 +3032,21 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
30243032 case PrefixOpBoolNot:
30253033 return ir_lval_wrap(irb, scope, ir_gen_bool_not(irb, scope, node), lval);
30263034 case PrefixOpBinNot:
3027 return ir_gen_prefix_op_id(irb, scope, node, IrUnOpBinNot);
3035 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpBinNot), lval);
30283036 case PrefixOpNegation:
3029 return ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation);
3037 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegation), lval);
30303038 case PrefixOpNegationWrap:
3031 return ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap);
3039 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpNegationWrap), lval);
30323040 case PrefixOpAddressOf:
3033 return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpAddressOf, LValPurposeAddressOf);
3041 return ir_gen_address_of(irb, scope, node, false, lval);
30343042 case PrefixOpConstAddressOf:
3035 return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpConstAddressOf, LValPurposeAddressOf);
3043 return ir_gen_address_of(irb, scope, node, true, lval);
30363044 case PrefixOpDereference:
30373045 return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval);
30383046 case PrefixOpMaybe:
3039 return ir_gen_prefix_op_id(irb, scope, node, IrUnOpMaybe);
3047 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpMaybe), lval);
30403048 case PrefixOpError:
3041 return ir_gen_prefix_op_id(irb, scope, node, IrUnOpError);
3049 return ir_lval_wrap(irb, scope, ir_gen_prefix_op_id(irb, scope, node, IrUnOpError), lval);
30423050 case PrefixOpUnwrapError:
30433051 return ir_gen_err_assert_ok(irb, scope, node, lval);
30443052 case PrefixOpUnwrapMaybe:
......@@ -4501,13 +4509,20 @@ static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instr
45014509 ConstExprValue *pointee, TypeTableEntry *pointee_type, bool depends_on_compile_var,
45024510 ConstPtrSpecial special, bool ptr_is_const)
45034511{
4504 TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, pointee_type, ptr_is_const);
4505 ConstExprValue *const_val = ir_build_const_from(ira, instruction,
4506 depends_on_compile_var || pointee->depends_on_compile_var);
4507 const_val->data.x_ptr.base_ptr = pointee;
4508 const_val->data.x_ptr.index = SIZE_MAX;
4509 const_val->data.x_ptr.special = special;
4510 return ptr_type;
4512 if (pointee_type->id == TypeTableEntryIdMetaType) {
4513 TypeTableEntry *type_entry = pointee->data.x_type;
4514 ConstExprValue *const_val = ir_build_const_from(ira, instruction, depends_on_compile_var || pointee->depends_on_compile_var);
4515 const_val->data.x_type = get_pointer_to_type(ira->codegen, type_entry, ptr_is_const);
4516 return pointee_type;
4517 } else {
4518 TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, pointee_type, ptr_is_const);
4519 ConstExprValue *const_val = ir_build_const_from(ira, instruction,
4520 depends_on_compile_var || pointee->depends_on_compile_var);
4521 const_val->data.x_ptr.base_ptr = pointee;
4522 const_val->data.x_ptr.index = SIZE_MAX;
4523 const_val->data.x_ptr.special = special;
4524 return ptr_type;
4525 }
45114526}
45124527
45134528static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *instruction, uint64_t value,
......@@ -5004,6 +5019,20 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
50045019 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope, source_instruction->source_node, ptr);
50055020 load_ptr_instruction->type_entry = child_type;
50065021 return load_ptr_instruction;
5022 } else if (type_entry->id == TypeTableEntryIdMetaType) {
5023 ConstExprValue *ptr_val = ir_resolve_const(ira, ptr);
5024 if (!ptr_val)
5025 return ira->codegen->invalid_instruction;
5026
5027 TypeTableEntry *ptr_type = ptr_val->data.x_type;
5028 if (ptr_type->id == TypeTableEntryIdPointer) {
5029 TypeTableEntry *child_type = ptr_type->data.pointer.child_type;
5030 return ir_create_const_type(&ira->new_irb, source_instruction->scope, source_instruction->source_node, child_type);
5031 } else {
5032 ir_add_error(ira, source_instruction,
5033 buf_sprintf("attempt to dereference non pointer type '%s'", buf_ptr(&ptr_type->name)));
5034 return ira->codegen->invalid_instruction;
5035 }
50075036 } else {
50085037 add_node_error(ira->codegen, source_instruction->source_node,
50095038 buf_sprintf("attempt to dereference non pointer type '%s'",
......@@ -5034,7 +5063,6 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst
50345063 return ptr_type;
50355064}
50365065
5037
50385066static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) {
50395067 if (value->type_entry->id == TypeTableEntryIdInvalid)
50405068 return false;
......@@ -6182,66 +6210,6 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct
61826210 zig_unreachable();
61836211}
61846212
6185static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction,
6186 bool is_const)
6187{
6188 IrInstruction *value = un_op_instruction->value->other;
6189 if (value->type_entry->id == TypeTableEntryIdInvalid)
6190 return ira->codegen->builtin_types.entry_invalid;
6191
6192 TypeTableEntry *target_type = value->type_entry;
6193 TypeTableEntry *canon_target_type = get_underlying_type(target_type);
6194 switch (canon_target_type->id) {
6195 case TypeTableEntryIdTypeDecl:
6196 // impossible because we look at the canonicalized type
6197 zig_unreachable();
6198 case TypeTableEntryIdInvalid:
6199 return ira->codegen->builtin_types.entry_invalid;
6200 case TypeTableEntryIdNumLitFloat:
6201 case TypeTableEntryIdNumLitInt:
6202 case TypeTableEntryIdUndefLit:
6203 case TypeTableEntryIdNullLit:
6204 case TypeTableEntryIdNamespace:
6205 case TypeTableEntryIdBlock:
6206 case TypeTableEntryIdUnreachable:
6207 case TypeTableEntryIdVar:
6208 case TypeTableEntryIdBoundFn:
6209 add_node_error(ira->codegen, un_op_instruction->base.source_node,
6210 buf_sprintf("unable to get address of type '%s'", buf_ptr(&target_type->name)));
6211 // TODO if type decl, add note pointing to type decl declaration
6212 return ira->codegen->builtin_types.entry_invalid;
6213 case TypeTableEntryIdMetaType:
6214 {
6215 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base,
6216 value->static_value.depends_on_compile_var);
6217 assert(value->static_value.special != ConstValSpecialRuntime);
6218 TypeTableEntry *child_type = value->static_value.data.x_type;
6219 out_val->data.x_type = get_pointer_to_type(ira->codegen, child_type, is_const);
6220 return ira->codegen->builtin_types.entry_type;
6221 }
6222 case TypeTableEntryIdPointer:
6223 {
6224 // this instruction is a noop - we solved this in IR gen by passing
6225 // LValPurposeAddressOf which caused the loadptr to not do the load.
6226 ir_link_new_instruction(value, &un_op_instruction->base);
6227 return ir_finish_anal(ira, target_type);
6228 }
6229 case TypeTableEntryIdVoid:
6230 case TypeTableEntryIdBool:
6231 case TypeTableEntryIdInt:
6232 case TypeTableEntryIdFloat:
6233 case TypeTableEntryIdArray:
6234 case TypeTableEntryIdStruct:
6235 case TypeTableEntryIdMaybe:
6236 case TypeTableEntryIdErrorUnion:
6237 case TypeTableEntryIdPureError:
6238 case TypeTableEntryIdEnum:
6239 case TypeTableEntryIdUnion:
6240 case TypeTableEntryIdFn:
6241 zig_unreachable();
6242 }
6243 zig_unreachable();
6244}
62456213
62466214static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
62476215 IrInstruction *value = un_op_instruction->value->other;
......@@ -6385,9 +6353,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
63856353 case IrUnOpNegation:
63866354 case IrUnOpNegationWrap:
63876355 return ir_analyze_negation(ira, un_op_instruction);
6388 case IrUnOpAddressOf:
6389 case IrUnOpConstAddressOf:
6390 return ir_analyze_unary_address_of(ira, un_op_instruction, op_id == IrUnOpConstAddressOf);
63916356 case IrUnOpDereference:
63926357 return ir_analyze_dereference(ira, un_op_instruction);
63936358 case IrUnOpMaybe:
src/ir_print.cpp-4
......@@ -285,10 +285,6 @@ static const char *ir_un_op_id_str(IrUnOp op_id) {
285285 return "-";
286286 case IrUnOpNegationWrap:
287287 return "-%";
288 case IrUnOpAddressOf:
289 return "&";
290 case IrUnOpConstAddressOf:
291 return "&const";
292288 case IrUnOpDereference:
293289 return "*";
294290 case IrUnOpMaybe: