authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-15 01:48:36-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2016-11-15 01:48:36-05:00
log8d1c6138f950d7ce44d823ce870643b94b19ffb1
treece1542939f07d6d22acd4492dc91323dca5892de
parentaf4d4c882a588f82667ddfaf41a59ff3cbcc5832

IR: implement pointer dereferencing (even at compile time)


1 files changed, 55 insertions(+), 27 deletions(-)

src/ir.cpp+55-27
...@@ -1377,18 +1377,22 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) {...@@ -1377,18 +1377,22 @@ static IrInstruction *ir_gen_if_bool_expr(IrBuilder *irb, AstNode *node) {
1377 return ir_build_phi(irb, node, 2, incoming_blocks, incoming_values);1377 return ir_build_phi(irb, node, 2, incoming_blocks, incoming_values);
1378}1378}
13791379
1380static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, AstNode *node, IrUnOp op_id) {1380static IrInstruction *ir_gen_prefix_op_id_lval(IrBuilder *irb, AstNode *node, IrUnOp op_id, LValPurpose lval) {
1381 assert(node->type == NodeTypePrefixOpExpr);1381 assert(node->type == NodeTypePrefixOpExpr);
1382 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;1382 AstNode *expr_node = node->data.prefix_op_expr.primary_expr;
13831383
1384 IrInstruction *value = ir_gen_node(irb, expr_node, node->block_context);1384 IrInstruction *value = ir_gen_node_extra(irb, expr_node, node->block_context, lval);
1385 if (value == irb->codegen->invalid_instruction)1385 if (value == irb->codegen->invalid_instruction)
1386 return value;1386 return value;
13871387
1388 return ir_build_un_op(irb, node, op_id, value);1388 return ir_build_un_op(irb, node, op_id, value);
1389}1389}
13901390
1391static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, AstNode *node) {1391static IrInstruction *ir_gen_prefix_op_id(IrBuilder *irb, AstNode *node, IrUnOp op_id) {
1392 return ir_gen_prefix_op_id_lval(irb, node, op_id, LValPurposeNone);
1393}
1394
1395static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, AstNode *node, LValPurpose lval) {
1392 assert(node->type == NodeTypePrefixOpExpr);1396 assert(node->type == NodeTypePrefixOpExpr);
13931397
1394 PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op;1398 PrefixOp prefix_op = node->data.prefix_op_expr.prefix_op;
...@@ -1405,11 +1409,11 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, AstNode *node) {...@@ -1405,11 +1409,11 @@ static IrInstruction *ir_gen_prefix_op_expr(IrBuilder *irb, AstNode *node) {
1405 case PrefixOpNegationWrap:1409 case PrefixOpNegationWrap:
1406 return ir_gen_prefix_op_id(irb, node, IrUnOpNegationWrap);1410 return ir_gen_prefix_op_id(irb, node, IrUnOpNegationWrap);
1407 case PrefixOpAddressOf:1411 case PrefixOpAddressOf:
1408 return ir_gen_prefix_op_id(irb, node, IrUnOpAddressOf);1412 return ir_gen_prefix_op_id_lval(irb, node, IrUnOpAddressOf, LValPurposeAddressOf);
1409 case PrefixOpConstAddressOf:1413 case PrefixOpConstAddressOf:
1410 return ir_gen_prefix_op_id(irb, node, IrUnOpConstAddressOf);1414 return ir_gen_prefix_op_id_lval(irb, node, IrUnOpConstAddressOf, LValPurposeConstAddressOf);
1411 case PrefixOpDereference:1415 case PrefixOpDereference:
1412 return ir_gen_prefix_op_id(irb, node, IrUnOpDereference);1416 return ir_gen_prefix_op_id_lval(irb, node, IrUnOpDereference, lval);
1413 case PrefixOpMaybe:1417 case PrefixOpMaybe:
1414 return ir_gen_prefix_op_id(irb, node, IrUnOpMaybe);1418 return ir_gen_prefix_op_id(irb, node, IrUnOpMaybe);
1415 case PrefixOpError:1419 case PrefixOpError:
...@@ -1789,7 +1793,7 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont...@@ -1789,7 +1793,7 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont
1789 case NodeTypeIfBoolExpr:1793 case NodeTypeIfBoolExpr:
1790 return ir_gen_if_bool_expr(irb, node);1794 return ir_gen_if_bool_expr(irb, node);
1791 case NodeTypePrefixOpExpr:1795 case NodeTypePrefixOpExpr:
1792 return ir_gen_prefix_op_expr(irb, node);1796 return ir_gen_prefix_op_expr(irb, node, lval);
1793 case NodeTypeContainerInitExpr:1797 case NodeTypeContainerInitExpr:
1794 return ir_gen_container_init_expr(irb, node);1798 return ir_gen_container_init_expr(irb, node);
1795 case NodeTypeVariableDeclaration:1799 case NodeTypeVariableDeclaration:
...@@ -3168,24 +3172,18 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct...@@ -3168,24 +3172,18 @@ static TypeTableEntry *ir_analyze_unary_prefix_op_err(IrAnalyze *ira, IrInstruct
3168 zig_unreachable();3172 zig_unreachable();
3169}3173}
31703174
3171static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {3175static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction,
3176 bool is_const)
3177{
3172 IrInstruction *value = un_op_instruction->value->other;3178 IrInstruction *value = un_op_instruction->value->other;
3173 if (value->type_entry->id == TypeTableEntryIdInvalid)3179 if (value->type_entry->id == TypeTableEntryIdInvalid)
3174 return ira->codegen->builtin_types.entry_invalid;3180 return ira->codegen->builtin_types.entry_invalid;
31753181
3176 bool is_const;
3177 if (un_op_instruction->op_id == IrUnOpAddressOf) {
3178 is_const = false;
3179 } else if (un_op_instruction->op_id == IrUnOpConstAddressOf) {
3180 is_const = true;
3181 } else {
3182 zig_unreachable();
3183 }
3184
3185 TypeTableEntry *target_type = value->type_entry;3182 TypeTableEntry *target_type = value->type_entry;
3186 TypeTableEntry *canon_target_type = get_underlying_type(target_type);3183 TypeTableEntry *canon_target_type = get_underlying_type(target_type);
3187 switch (canon_target_type->id) {3184 switch (canon_target_type->id) {
3188 case TypeTableEntryIdTypeDecl:3185 case TypeTableEntryIdTypeDecl:
3186 // impossible because we look at the canonicalized type
3189 zig_unreachable();3187 zig_unreachable();
3190 case TypeTableEntryIdInvalid:3188 case TypeTableEntryIdInvalid:
3191 return ira->codegen->builtin_types.entry_invalid;3189 return ira->codegen->builtin_types.entry_invalid;
...@@ -3197,6 +3195,7 @@ static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstruction...@@ -3197,6 +3195,7 @@ static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstruction
3197 case TypeTableEntryIdBlock:3195 case TypeTableEntryIdBlock:
3198 case TypeTableEntryIdUnreachable:3196 case TypeTableEntryIdUnreachable:
3199 case TypeTableEntryIdVar:3197 case TypeTableEntryIdVar:
3198 case TypeTableEntryIdGenericFn:
3200 add_node_error(ira->codegen, un_op_instruction->base.source_node,3199 add_node_error(ira->codegen, un_op_instruction->base.source_node,
3201 buf_sprintf("unable to get address of type '%s'", buf_ptr(&target_type->name)));3200 buf_sprintf("unable to get address of type '%s'", buf_ptr(&target_type->name)));
3202 // TODO if type decl, add note pointing to type decl declaration3201 // TODO if type decl, add note pointing to type decl declaration
...@@ -3210,11 +3209,17 @@ static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstruction...@@ -3210,11 +3209,17 @@ static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstruction
3210 out_val->data.x_type = get_pointer_to_type(ira->codegen, child_type, is_const);3209 out_val->data.x_type = get_pointer_to_type(ira->codegen, child_type, is_const);
3211 return ira->codegen->builtin_types.entry_type;3210 return ira->codegen->builtin_types.entry_type;
3212 }3211 }
3212 case TypeTableEntryIdPointer:
3213 {
3214 // this instruction is a noop - we solved this in IR gen by passing
3215 // LValPurposeAddressOf which caused the loadptr to not do the load.
3216 ir_link_new_instruction(value, &un_op_instruction->base);
3217 return ir_finish_anal(ira, target_type);
3218 }
3213 case TypeTableEntryIdVoid:3219 case TypeTableEntryIdVoid:
3214 case TypeTableEntryIdBool:3220 case TypeTableEntryIdBool:
3215 case TypeTableEntryIdInt:3221 case TypeTableEntryIdInt:
3216 case TypeTableEntryIdFloat:3222 case TypeTableEntryIdFloat:
3217 case TypeTableEntryIdPointer:
3218 case TypeTableEntryIdArray:3223 case TypeTableEntryIdArray:
3219 case TypeTableEntryIdStruct:3224 case TypeTableEntryIdStruct:
3220 case TypeTableEntryIdMaybe:3225 case TypeTableEntryIdMaybe:
...@@ -3223,15 +3228,40 @@ static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstruction...@@ -3223,15 +3228,40 @@ static TypeTableEntry *ir_analyze_unary_address_of(IrAnalyze *ira, IrInstruction
3223 case TypeTableEntryIdEnum:3228 case TypeTableEntryIdEnum:
3224 case TypeTableEntryIdUnion:3229 case TypeTableEntryIdUnion:
3225 case TypeTableEntryIdFn:3230 case TypeTableEntryIdFn:
3226 case TypeTableEntryIdGenericFn:3231 zig_unreachable();
3227 {
3228 zig_panic("TODO address of operation");
3229 break;
3230 }
3231 }3232 }
3232 zig_unreachable();3233 zig_unreachable();
3233}3234}
32343235
3236static TypeTableEntry *ir_analyze_dereference(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
3237 IrInstruction *value = un_op_instruction->value->other;
3238
3239 TypeTableEntry *ptr_type = value->type_entry;
3240 TypeTableEntry *child_type;
3241 if (ptr_type->id == TypeTableEntryIdInvalid) {
3242 return ira->codegen->builtin_types.entry_invalid;
3243 } else if (ptr_type->id == TypeTableEntryIdPointer) {
3244 child_type = ptr_type->data.pointer.child_type;
3245 } else {
3246 add_node_error(ira->codegen, un_op_instruction->base.source_node,
3247 buf_sprintf("attempt to dereference non-pointer type '%s'",
3248 buf_ptr(&ptr_type->name)));
3249 return ira->codegen->builtin_types.entry_invalid;
3250 }
3251
3252 // this dereference is always an rvalue because in the IR gen we identify lvalue and emit
3253 // one of the ptr instructions
3254
3255 if (value->static_value.ok) {
3256 ConstExprValue *out_val = ir_build_const_from(ira, &un_op_instruction->base, false);
3257 *out_val = *value->static_value.data.x_ptr.ptr[0];
3258 return child_type;
3259 }
3260
3261 ir_build_un_op_from(&ira->new_irb, &un_op_instruction->base, IrUnOpDereference, value);
3262 return child_type;
3263}
3264
3235static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {3265static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
3236 IrUnOp op_id = un_op_instruction->op_id;3266 IrUnOp op_id = un_op_instruction->op_id;
3237 switch (op_id) {3267 switch (op_id) {
...@@ -3304,9 +3334,9 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio...@@ -3304,9 +3334,9 @@ static TypeTableEntry *ir_analyze_instruction_un_op(IrAnalyze *ira, IrInstructio
3304 //}3334 //}
3305 case IrUnOpAddressOf:3335 case IrUnOpAddressOf:
3306 case IrUnOpConstAddressOf:3336 case IrUnOpConstAddressOf:
3307 return ir_analyze_unary_address_of(ira, un_op_instruction);3337 return ir_analyze_unary_address_of(ira, un_op_instruction, op_id == IrUnOpConstAddressOf);
3308 case IrUnOpDereference:3338 case IrUnOpDereference:
3309 zig_panic("TODO remove this IrUnOp item");3339 return ir_analyze_dereference(ira, un_op_instruction);
3310 case IrUnOpMaybe:3340 case IrUnOpMaybe:
3311 zig_panic("TODO analyze PrefixOpMaybe");3341 zig_panic("TODO analyze PrefixOpMaybe");
3312 //{3342 //{
...@@ -3502,7 +3532,6 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct...@@ -3502,7 +3532,6 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct
3502 mem_slot->depends_on_compile_var);3532 mem_slot->depends_on_compile_var);
35033533
3504 out_val->data.x_ptr.len = 1;3534 out_val->data.x_ptr.len = 1;
3505 out_val->data.x_ptr.is_c_str = false;
3506 out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1);3535 out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1);
3507 out_val->data.x_ptr.ptr[0] = mem_slot;3536 out_val->data.x_ptr.ptr[0] = mem_slot;
3508 return ptr_type;3537 return ptr_type;
...@@ -3565,7 +3594,6 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc...@@ -3565,7 +3594,6 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc
3565 casted_elem_index->static_value.depends_on_compile_var;3594 casted_elem_index->static_value.depends_on_compile_var;
3566 ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base, depends_on_compile_var);3595 ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base, depends_on_compile_var);
3567 out_val->data.x_ptr.len = 1;3596 out_val->data.x_ptr.len = 1;
3568 out_val->data.x_ptr.is_c_str = false;
3569 out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1);3597 out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1);
3570 if (array_type->id == TypeTableEntryIdPointer) {3598 if (array_type->id == TypeTableEntryIdPointer) {
3571 uint64_t pointer_len = array_ptr->static_value.data.x_ptr.len;3599 uint64_t pointer_len = array_ptr->static_value.data.x_ptr.len;