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 {...@@ -1517,8 +1517,6 @@ enum IrUnOp {
1517 IrUnOpBinNot,1517 IrUnOpBinNot,
1518 IrUnOpNegation,1518 IrUnOpNegation,
1519 IrUnOpNegationWrap,1519 IrUnOpNegationWrap,
1520 IrUnOpAddressOf,
1521 IrUnOpConstAddressOf,
1522 IrUnOpDereference,1520 IrUnOpDereference,
1523 IrUnOpError,1521 IrUnOpError,
1524 IrUnOpMaybe,1522 IrUnOpMaybe,
src/codegen.cpp-7
...@@ -1175,13 +1175,6 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst...@@ -1175,13 +1175,6 @@ static LLVMValueRef ir_render_un_op(CodeGen *g, IrExecutable *executable, IrInst
1175 }1175 }
1176 case IrUnOpBinNot:1176 case IrUnOpBinNot:
1177 return LLVMBuildNot(g->builder, expr, "");1177 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 //}
1185 case IrUnOpDereference:1178 case IrUnOpDereference:
1186 {1179 {
1187 assert(expr_type->id == TypeTableEntryIdPointer);1180 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,...@@ -2368,8 +2368,8 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
2368 auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name);2368 auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name);
2369 if (primitive_table_entry) {2369 if (primitive_table_entry) {
2370 IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_table_entry->value);2370 IrInstruction *value = ir_build_const_type(irb, scope, node, primitive_table_entry->value);
2371 if (lval == LValPurposeAddressOf) {2371 if (lval != LValPurposeNone) {
2372 return ir_build_un_op(irb, scope, node, IrUnOpAddressOf, value);2372 return ir_build_ref(irb, scope, node, value);
2373 } else {2373 } else {
2374 return value;2374 return value;
2375 }2375 }
...@@ -2947,10 +2947,6 @@ static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, Ast...@@ -2947,10 +2947,6 @@ static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, Scope *scope, Ast
2947 if (value == irb->codegen->invalid_instruction)2947 if (value == irb->codegen->invalid_instruction)
2948 return value;2948 return value;
29492949
2950 if (lval == LValPurposeAddressOf && (op_id == IrUnOpAddressOf || op_id == IrUnOpConstAddressOf)) {
2951 return value;
2952 }
2953
2954 return ir_build_un_op(irb, scope, node, op_id, value);2950 return ir_build_un_op(irb, scope, node, op_id, value);
2955}2951}
29562952
...@@ -2958,6 +2954,29 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode...@@ -2958,6 +2954,29 @@ static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, Scope *scope, AstNode
2958 return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValPurposeNone);2954 return ir_gen_prefix_op_id_lval(irb, scope, node, op_id, LValPurposeNone);
2959}2955}
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
2961static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {2980static IrInstruction *ir_gen_err_assert_ok(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {
2962 assert(node->type == NodeTypePrefixOpExpr);2981 assert(node->type == NodeTypePrefixOpExpr);
2963 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;2982 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...@@ -3002,17 +3021,6 @@ static IrInstruction *ir_gen_bool_not(IrBuilder *irb, Scope *scope, AstNode *nod
3002 return ir_build_bool_not(irb, scope, node, value);3021 return ir_build_bool_not(irb, scope, node, value);
3003}3022}
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
3016static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {3024static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNode *node, LValPurpose lval) {
3017 assert(node->type == NodeTypePrefixOpExpr);3025 assert(node->type == NodeTypePrefixOpExpr);
30183026
...@@ -3024,21 +3032,21 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod...@@ -3024,21 +3032,21 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, Scope *scope, AstNod
3024 case PrefixOpBoolNot:3032 case PrefixOpBoolNot:
3025 return ir_lval_wrap(irb, scope, ir_gen_bool_not(irb, scope, node), lval);3033 return ir_lval_wrap(irb, scope, ir_gen_bool_not(irb, scope, node), lval);
3026 case PrefixOpBinNot:3034 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);
3028 case PrefixOpNegation:3036 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);
3030 case PrefixOpNegationWrap:3038 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);
3032 case PrefixOpAddressOf:3040 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);
3034 case PrefixOpConstAddressOf:3042 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);
3036 case PrefixOpDereference:3044 case PrefixOpDereference:
3037 return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval);3045 return ir_gen_prefix_op_id_lval(irb, scope, node, IrUnOpDereference, lval);
3038 case PrefixOpMaybe:3046 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);
3040 case PrefixOpError:3048 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);
3042 case PrefixOpUnwrapError:3050 case PrefixOpUnwrapError:
3043 return ir_gen_err_assert_ok(irb, scope, node, lval);3051 return ir_gen_err_assert_ok(irb, scope, node, lval);
3044 case PrefixOpUnwrapMaybe:3052 case PrefixOpUnwrapMaybe:
...@@ -4501,13 +4509,20 @@ static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instr...@@ -4501,13 +4509,20 @@ static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instr
4501 ConstExprValue *pointee, TypeTableEntry *pointee_type, bool depends_on_compile_var,4509 ConstExprValue *pointee, TypeTableEntry *pointee_type, bool depends_on_compile_var,
4502 ConstPtrSpecial special, bool ptr_is_const)4510 ConstPtrSpecial special, bool ptr_is_const)
4503{4511{
4504 TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, pointee_type, ptr_is_const);4512 if (pointee_type->id == TypeTableEntryIdMetaType) {
4505 ConstExprValue *const_val = ir_build_const_from(ira, instruction,4513 TypeTableEntry *type_entry = pointee->data.x_type;
4506 depends_on_compile_var || pointee->depends_on_compile_var);4514 ConstExprValue *const_val = ir_build_const_from(ira, instruction, depends_on_compile_var || pointee->depends_on_compile_var);
4507 const_val->data.x_ptr.base_ptr = pointee;4515 const_val->data.x_type = get_pointer_to_type(ira->codegen, type_entry, ptr_is_const);
4508 const_val->data.x_ptr.index = SIZE_MAX;4516 return pointee_type;
4509 const_val->data.x_ptr.special = special;4517 } else {
4510 return ptr_type;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 }
4511}4526}
45124527
4513static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *instruction, uint64_t value,4528static 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...@@ -5004,6 +5019,20 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
5004 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope, source_instruction->source_node, ptr);5019 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope, source_instruction->source_node, ptr);
5005 load_ptr_instruction->type_entry = child_type;5020 load_ptr_instruction->type_entry = child_type;
5006 return load_ptr_instruction;5021 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 }
5007 } else {5036 } else {
5008 add_node_error(ira->codegen, source_instruction->source_node,5037 add_node_error(ira->codegen, source_instruction->source_node,
5009 buf_sprintf("attempt to dereference non pointer type '%s'",5038 buf_sprintf("attempt to dereference non pointer type '%s'",
...@@ -5034,7 +5063,6 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst...@@ -5034,7 +5063,6 @@ static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_inst
5034 return ptr_type;5063 return ptr_type;
5035}5064}
50365065
5037
5038static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) {5066static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) {
5039 if (value->type_entry->id == TypeTableEntryIdInvalid)5067 if (value->type_entry->id == TypeTableEntryIdInvalid)
5040 return false;5068 return false;
...@@ -6182,66 +6210,6 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct...@@ -6182,66 +6210,6 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct
6182 zig_unreachable();6210 zig_unreachable();
6183}6211}
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
6246static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {6214static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
6247 IrInstruction *value = un_op_instruction->value->other;6215 IrInstruction *value = un_op_instruction->value->other;
...@@ -6385,9 +6353,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio...@@ -6385,9 +6353,6 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
6385 case IrUnOpNegation:6353 case IrUnOpNegation:
6386 case IrUnOpNegationWrap:6354 case IrUnOpNegationWrap:
6387 return ir_analyze_negation(ira, un_op_instruction);6355 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);
6391 case IrUnOpDereference:6356 case IrUnOpDereference:
6392 return ir_analyze_dereference(ira, un_op_instruction);6357 return ir_analyze_dereference(ira, un_op_instruction);
6393 case IrUnOpMaybe:6358 case IrUnOpMaybe:
src/ir_print.cpp-4
...@@ -285,10 +285,6 @@ static const char *ir_un_op_id_str(IrUnOp op_id) {...@@ -285,10 +285,6 @@ static const char *ir_un_op_id_str(IrUnOp op_id) {
285 return "-";285 return "-";
286 case IrUnOpNegationWrap:286 case IrUnOpNegationWrap:
287 return "-%";287 return "-%";
288 case IrUnOpAddressOf:
289 return "&";
290 case IrUnOpConstAddressOf:
291 return "&const";
292 case IrUnOpDereference:288 case IrUnOpDereference:
293 return "*";289 return "*";
294 case IrUnOpMaybe:290 case IrUnOpMaybe: