| ... | @@ -24,7 +24,7 @@ struct IrAnalyze { | ... | @@ -24,7 +24,7 @@ struct IrAnalyze { |
| 24 | }; | 24 | }; |
| 25 | | 25 | |
| 26 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope); | 26 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope); |
| 27 | static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext *scope); | 27 | static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext *scope, LValPurpose purpose); |
| 28 | | 28 | |
| 29 | static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) { | 29 | static void ir_instruction_append(IrBasicBlock *basic_block, IrInstruction *instruction) { |
| 30 | assert(basic_block); | 30 | assert(basic_block); |
| ... | @@ -293,37 +293,6 @@ static IrInstruction *ir_build_const_generic_fn(IrBuilder *irb, AstNode *source_ | ... | @@ -293,37 +293,6 @@ static IrInstruction *ir_build_const_generic_fn(IrBuilder *irb, AstNode *source_ |
| 293 | return &const_instruction->base; | 293 | return &const_instruction->base; |
| 294 | } | 294 | } |
| 295 | | 295 | |
| 296 | static IrInstruction *ir_build_const_ptr(IrBuilder *irb, AstNode *source_node, ConstExprValue *pointee) { | | |
| 297 | IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); | | |
| 298 | const_instruction->base.static_value.ok = true; | | |
| 299 | const_instruction->base.static_value.data.x_ptr.len = 1; | | |
| 300 | const_instruction->base.static_value.data.x_ptr.is_c_str = false; | | |
| 301 | const_instruction->base.static_value.data.x_ptr.ptr = allocate<ConstExprValue *>(1); | | |
| 302 | const_instruction->base.static_value.data.x_ptr.ptr[0] = pointee; | | |
| 303 | return &const_instruction->base; | | |
| 304 | } | | |
| 305 | | | |
| 306 | static IrInstruction *ir_build_const_ptr_from(IrBuilder *irb, IrInstruction *old_instruction, | | |
| 307 | ConstExprValue *pointee) | | |
| 308 | { | | |
| 309 | IrInstruction *new_instruction = ir_build_const_ptr(irb, old_instruction->source_node, pointee); | | |
| 310 | ir_link_new_instruction(new_instruction, old_instruction); | | |
| 311 | return new_instruction; | | |
| 312 | } | | |
| 313 | | | |
| 314 | static IrInstruction *ir_build_const(IrBuilder *irb, AstNode *source_node, ConstExprValue *value) { | | |
| 315 | IrInstructionConst *instruction = ir_build_instruction<IrInstructionConst>(irb, source_node); | | |
| 316 | instruction->base.static_value = *value; | | |
| 317 | instruction->base.static_value.ok = true; | | |
| 318 | return &instruction->base; | | |
| 319 | } | | |
| 320 | | | |
| 321 | static IrInstruction *ir_build_const_from(IrBuilder *irb, IrInstruction *old_instruction, ConstExprValue *value) { | | |
| 322 | IrInstruction *new_instruction = ir_build_const(irb, old_instruction->source_node, value); | | |
| 323 | ir_link_new_instruction(new_instruction, old_instruction); | | |
| 324 | return new_instruction; | | |
| 325 | } | | |
| 326 | | | |
| 327 | static IrInstruction *ir_build_bin_op(IrBuilder *irb, AstNode *source_node, IrBinOp op_id, | 296 | static IrInstruction *ir_build_bin_op(IrBuilder *irb, AstNode *source_node, IrBinOp op_id, |
| 328 | IrInstruction *op1, IrInstruction *op2) | 297 | IrInstruction *op1, IrInstruction *op2) |
| 329 | { | 298 | { |
| ... | @@ -515,6 +484,14 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, AstNode *source_node, | ... | @@ -515,6 +484,14 @@ static IrInstruction *ir_build_store_ptr(IrBuilder *irb, AstNode *source_node, |
| 515 | return &instruction->base; | 484 | return &instruction->base; |
| 516 | } | 485 | } |
| 517 | | 486 | |
| | 487 | static IrInstruction *ir_build_store_ptr_from(IrBuilder *irb, IrInstruction *old_instruction, |
| | 488 | IrInstruction *ptr, IrInstruction *value) |
| | 489 | { |
| | 490 | IrInstruction *new_instruction = ir_build_store_ptr(irb, old_instruction->source_node, ptr, value); |
| | 491 | ir_link_new_instruction(new_instruction, old_instruction); |
| | 492 | return new_instruction; |
| | 493 | } |
| | 494 | |
| 518 | static IrInstruction *ir_build_var_decl(IrBuilder *irb, AstNode *source_node, | 495 | static IrInstruction *ir_build_var_decl(IrBuilder *irb, AstNode *source_node, |
| 519 | VariableTableEntry *var, IrInstruction *var_type, IrInstruction *init_value) | 496 | VariableTableEntry *var, IrInstruction *var_type, IrInstruction *init_value) |
| 520 | { | 497 | { |
| ... | @@ -688,8 +665,21 @@ static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, AstNode *node, IrBinOp op | ... | @@ -688,8 +665,21 @@ static IrInstruction *ir_gen_bin_op_id(IrBuilder *irb, AstNode *node, IrBinOp op |
| 688 | return ir_build_bin_op(irb, node, op_id, op1, op2); | 665 | return ir_build_bin_op(irb, node, op_id, op1, op2); |
| 689 | } | 666 | } |
| 690 | | 667 | |
| | 668 | static IrInstruction *ir_gen_assign(IrBuilder *irb, AstNode *node) { |
| | 669 | IrInstruction *lvalue = ir_gen_lvalue(irb, node->data.bin_op_expr.op1, node->block_context, LValPurposeAssign); |
| | 670 | if (lvalue == irb->codegen->invalid_instruction) |
| | 671 | return lvalue; |
| | 672 | |
| | 673 | IrInstruction *rvalue = ir_gen_node(irb, node->data.bin_op_expr.op2, node->block_context); |
| | 674 | if (rvalue == irb->codegen->invalid_instruction) |
| | 675 | return rvalue; |
| | 676 | |
| | 677 | ir_build_store_ptr(irb, node, lvalue, rvalue); |
| | 678 | return ir_build_const_void(irb, node); |
| | 679 | } |
| | 680 | |
| 691 | static IrInstruction *ir_gen_assign_op(IrBuilder *irb, AstNode *node, IrBinOp op_id) { | 681 | static IrInstruction *ir_gen_assign_op(IrBuilder *irb, AstNode *node, IrBinOp op_id) { |
| 692 | IrInstruction *lvalue = ir_gen_lvalue(irb, node->data.bin_op_expr.op1, node->block_context); | 682 | IrInstruction *lvalue = ir_gen_lvalue(irb, node->data.bin_op_expr.op1, node->block_context, LValPurposeAssign); |
| 693 | if (lvalue == irb->codegen->invalid_instruction) | 683 | if (lvalue == irb->codegen->invalid_instruction) |
| 694 | return lvalue; | 684 | return lvalue; |
| 695 | IrInstruction *op1 = ir_build_load_ptr(irb, node->data.bin_op_expr.op1, lvalue); | 685 | IrInstruction *op1 = ir_build_load_ptr(irb, node->data.bin_op_expr.op1, lvalue); |
| ... | @@ -709,7 +699,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, AstNode *node) { | ... | @@ -709,7 +699,7 @@ static IrInstruction *ir_gen_bin_op(IrBuilder *irb, AstNode *node) { |
| 709 | case BinOpTypeInvalid: | 699 | case BinOpTypeInvalid: |
| 710 | zig_unreachable(); | 700 | zig_unreachable(); |
| 711 | case BinOpTypeAssign: | 701 | case BinOpTypeAssign: |
| 712 | zig_panic("TODO gen IR for assignment"); | 702 | return ir_gen_assign(irb, node); |
| 713 | case BinOpTypeAssignTimes: | 703 | case BinOpTypeAssignTimes: |
| 714 | return ir_gen_assign_op(irb, node, IrBinOpMult); | 704 | return ir_gen_assign_op(irb, node, IrBinOpMult); |
| 715 | case BinOpTypeAssignTimesWrap: | 705 | case BinOpTypeAssignTimesWrap: |
| ... | @@ -809,9 +799,9 @@ static IrInstruction *ir_gen_num_lit(IrBuilder *irb, AstNode *node) { | ... | @@ -809,9 +799,9 @@ static IrInstruction *ir_gen_num_lit(IrBuilder *irb, AstNode *node) { |
| 809 | } | 799 | } |
| 810 | | 800 | |
| 811 | static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, AstNode *decl_node, | 801 | static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, AstNode *decl_node, |
| 812 | bool pointer_only, BlockContext *scope) | 802 | LValPurpose lval, BlockContext *scope) |
| 813 | { | 803 | { |
| 814 | resolve_top_level_decl(irb->codegen, decl_node, pointer_only); | 804 | resolve_top_level_decl(irb->codegen, decl_node, lval); |
| 815 | TopLevelDecl *tld = get_as_top_level_decl(decl_node); | 805 | TopLevelDecl *tld = get_as_top_level_decl(decl_node); |
| 816 | if (tld->resolution == TldResolutionInvalid) | 806 | if (tld->resolution == TldResolutionInvalid) |
| 817 | return irb->codegen->invalid_instruction; | 807 | return irb->codegen->invalid_instruction; |
| ... | @@ -843,27 +833,33 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, AstN | ... | @@ -843,27 +833,33 @@ static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, AstN |
| 843 | } | 833 | } |
| 844 | } | 834 | } |
| 845 | | 835 | |
| 846 | static IrInstruction *ir_gen_symbol(IrBuilder *irb, AstNode *node, bool pointer_only) { | 836 | static IrInstruction *ir_gen_symbol(IrBuilder *irb, AstNode *node, LValPurpose lval) { |
| 847 | assert(node->type == NodeTypeSymbol); | 837 | assert(node->type == NodeTypeSymbol); |
| 848 | | 838 | |
| 849 | if (node->data.symbol_expr.override_type_entry) | 839 | if (node->data.symbol_expr.override_type_entry) { |
| 850 | return ir_build_const_type(irb, node, node->data.symbol_expr.override_type_entry); | 840 | zig_panic("TODO have parseh directly generate IR"); |
| | 841 | } |
| 851 | | 842 | |
| 852 | Buf *variable_name = node->data.symbol_expr.symbol; | 843 | Buf *variable_name = node->data.symbol_expr.symbol; |
| 853 | | 844 | |
| 854 | auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name); | 845 | auto primitive_table_entry = irb->codegen->primitive_type_table.maybe_get(variable_name); |
| 855 | if (primitive_table_entry) | 846 | if (primitive_table_entry) { |
| 856 | return ir_build_const_type(irb, node, primitive_table_entry->value); | 847 | return ir_build_const_type(irb, node, primitive_table_entry->value); |
| | 848 | } |
| 857 | | 849 | |
| 858 | VariableTableEntry *var = find_variable(irb->codegen, node->block_context, variable_name); | 850 | VariableTableEntry *var = find_variable(irb->codegen, node->block_context, variable_name); |
| 859 | if (var) { | 851 | if (var) { |
| 860 | IrInstruction *var_ptr = ir_build_var_ptr(irb, node, var); | 852 | IrInstruction *var_ptr = ir_build_var_ptr(irb, node, var); |
| 861 | return ir_build_load_ptr(irb, node, var_ptr); | 853 | if (lval != LValPurposeNone) |
| | 854 | return var_ptr; |
| | 855 | else |
| | 856 | return ir_build_load_ptr(irb, node, var_ptr); |
| 862 | } | 857 | } |
| 863 | | 858 | |
| 864 | AstNode *decl_node = find_decl(node->block_context, variable_name); | 859 | AstNode *decl_node = find_decl(node->block_context, variable_name); |
| 865 | if (decl_node) | 860 | if (decl_node) { |
| 866 | return ir_gen_decl_ref(irb, node, decl_node, pointer_only, node->block_context); | 861 | return ir_gen_decl_ref(irb, node, decl_node, lval, node->block_context); |
| | 862 | } |
| 867 | | 863 | |
| 868 | if (node->owner->any_imports_failed) { | 864 | if (node->owner->any_imports_failed) { |
| 869 | // skip the error message since we had a failing import in this file | 865 | // skip the error message since we had a failing import in this file |
| ... | @@ -1144,9 +1140,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) { | ... | @@ -1144,9 +1140,7 @@ static IrInstruction *ir_gen_while_expr(IrBuilder *irb, AstNode *node) { |
| 1144 | return ir_build_const_void(irb, node); | 1140 | return ir_build_const_void(irb, node); |
| 1145 | } | 1141 | } |
| 1146 | | 1142 | |
| 1147 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context, | 1143 | static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockContext *block_context, LValPurpose lval) { |
| 1148 | bool pointer_only) | | |
| 1149 | { | | |
| 1150 | assert(block_context); | 1144 | assert(block_context); |
| 1151 | node->block_context = block_context; | 1145 | node->block_context = block_context; |
| 1152 | | 1146 | |
| ... | @@ -1158,7 +1152,7 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont | ... | @@ -1158,7 +1152,7 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont |
| 1158 | case NodeTypeNumberLiteral: | 1152 | case NodeTypeNumberLiteral: |
| 1159 | return ir_gen_num_lit(irb, node); | 1153 | return ir_gen_num_lit(irb, node); |
| 1160 | case NodeTypeSymbol: | 1154 | case NodeTypeSymbol: |
| 1161 | return ir_gen_symbol(irb, node, pointer_only); | 1155 | return ir_gen_symbol(irb, node, lval); |
| 1162 | case NodeTypeFnCallExpr: | 1156 | case NodeTypeFnCallExpr: |
| 1163 | return ir_gen_fn_call(irb, node); | 1157 | return ir_gen_fn_call(irb, node); |
| 1164 | case NodeTypeIfBoolExpr: | 1158 | case NodeTypeIfBoolExpr: |
| ... | @@ -1215,16 +1209,15 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont | ... | @@ -1215,16 +1209,15 @@ static IrInstruction *ir_gen_node_extra(IrBuilder *irb, AstNode *node, BlockCont |
| 1215 | } | 1209 | } |
| 1216 | | 1210 | |
| 1217 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope) { | 1211 | static IrInstruction *ir_gen_node(IrBuilder *irb, AstNode *node, BlockContext *scope) { |
| 1218 | bool pointer_only_no = false; | 1212 | return ir_gen_node_extra(irb, node, scope, LValPurposeNone); |
| 1219 | return ir_gen_node_extra(irb, node, scope, pointer_only_no); | | |
| 1220 | } | 1213 | } |
| 1221 | | 1214 | |
| 1222 | static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext *scope) { | 1215 | static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext *scope, LValPurpose lval) { |
| 1223 | assert(scope); | 1216 | assert(scope); |
| 1224 | node->block_context = scope; | 1217 | node->block_context = scope; |
| 1225 | switch (node->type) { | 1218 | switch (node->type) { |
| 1226 | case NodeTypeSymbol: | 1219 | case NodeTypeSymbol: |
| 1227 | zig_panic("TODO symbol lvalue"); | 1220 | return ir_gen_symbol(irb, node, lval); |
| 1228 | case NodeTypeArrayAccessExpr: | 1221 | case NodeTypeArrayAccessExpr: |
| 1229 | zig_panic("TODO array access lvalue"); | 1222 | zig_panic("TODO array access lvalue"); |
| 1230 | case NodeTypeFieldAccessExpr: | 1223 | case NodeTypeFieldAccessExpr: |
| ... | @@ -1281,7 +1274,7 @@ static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext | ... | @@ -1281,7 +1274,7 @@ static IrInstruction *ir_gen_lvalue(IrBuilder *irb, AstNode *node, BlockContext |
| 1281 | } | 1274 | } |
| 1282 | | 1275 | |
| 1283 | static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext *scope, | 1276 | static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext *scope, |
| 1284 | IrExecutable *ir_executable, bool add_return, bool pointer_only) | 1277 | IrExecutable *ir_executable, bool add_return, LValPurpose lval) |
| 1285 | { | 1278 | { |
| 1286 | assert(node->owner); | 1279 | assert(node->owner); |
| 1287 | | 1280 | |
| ... | @@ -1295,7 +1288,7 @@ static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext | ... | @@ -1295,7 +1288,7 @@ static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext |
| 1295 | // Entry block gets a reference because we enter it to begin. | 1288 | // Entry block gets a reference because we enter it to begin. |
| 1296 | ir_ref_bb(irb->current_basic_block); | 1289 | ir_ref_bb(irb->current_basic_block); |
| 1297 | | 1290 | |
| 1298 | IrInstruction *result = ir_gen_node_extra(irb, node, scope, pointer_only); | 1291 | IrInstruction *result = ir_gen_node_extra(irb, node, scope, lval); |
| 1299 | assert(result); | 1292 | assert(result); |
| 1300 | | 1293 | |
| 1301 | if (result == g->invalid_instruction) | 1294 | if (result == g->invalid_instruction) |
| ... | @@ -1309,8 +1302,7 @@ static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext | ... | @@ -1309,8 +1302,7 @@ static IrInstruction *ir_gen_add_return(CodeGen *g, AstNode *node, BlockContext |
| 1309 | | 1302 | |
| 1310 | IrInstruction *ir_gen(CodeGen *codegen, AstNode *node, BlockContext *scope, IrExecutable *ir_executable) { | 1303 | IrInstruction *ir_gen(CodeGen *codegen, AstNode *node, BlockContext *scope, IrExecutable *ir_executable) { |
| 1311 | bool add_return_no = false; | 1304 | bool add_return_no = false; |
| 1312 | bool pointer_only_no = false; | 1305 | return ir_gen_add_return(codegen, node, scope, ir_executable, add_return_no, LValPurposeNone); |
| 1313 | return ir_gen_add_return(codegen, node, scope, ir_executable, add_return_no, pointer_only_no); | | |
| 1314 | } | 1306 | } |
| 1315 | | 1307 | |
| 1316 | IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { | 1308 | IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { |
| ... | @@ -1324,8 +1316,7 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { | ... | @@ -1324,8 +1316,7 @@ IrInstruction *ir_gen_fn(CodeGen *codegn, FnTableEntry *fn_entry) { |
| 1324 | BlockContext *scope = fn_def_node->data.fn_def.block_context; | 1316 | BlockContext *scope = fn_def_node->data.fn_def.block_context; |
| 1325 | | 1317 | |
| 1326 | bool add_return_yes = true; | 1318 | bool add_return_yes = true; |
| 1327 | bool pointer_only_no = false; | 1319 | return ir_gen_add_return(codegn, body_node, scope, ir_executable, add_return_yes, LValPurposeNone); |
| 1328 | return ir_gen_add_return(codegn, body_node, scope, ir_executable, add_return_yes, pointer_only_no); | | |
| 1329 | } | 1320 | } |
| 1330 | | 1321 | |
| 1331 | /* | 1322 | /* |
| ... | @@ -1620,6 +1611,11 @@ static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) { | ... | @@ -1620,6 +1611,11 @@ static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) { |
| 1620 | return ir_build_bb_from(&ira->new_irb, old_bb); | 1611 | return ir_build_bb_from(&ira->new_irb, old_bb); |
| 1621 | } | 1612 | } |
| 1622 | | 1613 | |
| | 1614 | static ConstExprValue *ir_get_out_val(IrInstruction *instruction) { |
| | 1615 | instruction->other = instruction; |
| | 1616 | return &instruction->static_value; |
| | 1617 | } |
| | 1618 | |
| 1623 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, | 1619 | static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_instr, |
| 1624 | IrInstruction *dest_type, IrInstruction *value) | 1620 | IrInstruction *dest_type, IrInstruction *value) |
| 1625 | { | 1621 | { |
| ... | @@ -1972,8 +1968,7 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -1972,8 +1968,7 @@ static TypeTableEntry *ir_analyze_bin_op_bool(IrAnalyze *ira, IrInstructionBinOp |
| 1972 | ConstExprValue *op1_val = &casted_op1->static_value; | 1968 | ConstExprValue *op1_val = &casted_op1->static_value; |
| 1973 | ConstExprValue *op2_val = &casted_op2->static_value; | 1969 | ConstExprValue *op2_val = &casted_op2->static_value; |
| 1974 | if (op1_val->ok && op2_val->ok) { | 1970 | if (op1_val->ok && op2_val->ok) { |
| 1975 | ConstExprValue *out_val = &bin_op_instruction->base.static_value; | 1971 | ConstExprValue *out_val = ir_get_out_val(&bin_op_instruction->base); |
| 1976 | bin_op_instruction->base.other = &bin_op_instruction->base; | | |
| 1977 | | 1972 | |
| 1978 | assert(op1->type_entry->id == TypeTableEntryIdBool); | 1973 | assert(op1->type_entry->id == TypeTableEntryIdBool); |
| 1979 | assert(op2->type_entry->id == TypeTableEntryIdBool); | 1974 | assert(op2->type_entry->id == TypeTableEntryIdBool); |
| ... | @@ -3909,7 +3904,13 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct | ... | @@ -3909,7 +3904,13 @@ static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstruct |
| 3909 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; | 3904 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; |
| 3910 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, var_ptr_instruction->var->type, false); | 3905 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, var_ptr_instruction->var->type, false); |
| 3911 | if (mem_slot->ok) { | 3906 | if (mem_slot->ok) { |
| 3912 | ir_build_const_ptr_from(&ira->new_irb, &var_ptr_instruction->base, mem_slot); | 3907 | ConstExprValue *out_val = ir_get_out_val(&var_ptr_instruction->base); |
| | 3908 | |
| | 3909 | out_val->ok = true; |
| | 3910 | out_val->data.x_ptr.len = 1; |
| | 3911 | out_val->data.x_ptr.is_c_str = false; |
| | 3912 | out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1); |
| | 3913 | out_val->data.x_ptr.ptr[0] = mem_slot; |
| 3913 | return ptr_type; | 3914 | return ptr_type; |
| 3914 | } | 3915 | } |
| 3915 | | 3916 | |
| ... | @@ -3927,7 +3928,8 @@ static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -3927,7 +3928,8 @@ static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruc |
| 3927 | if (ptr->static_value.ok) { | 3928 | if (ptr->static_value.ok) { |
| 3928 | ConstExprValue *pointee = ptr->static_value.data.x_ptr.ptr[0]; | 3929 | ConstExprValue *pointee = ptr->static_value.data.x_ptr.ptr[0]; |
| 3929 | if (pointee->ok) { | 3930 | if (pointee->ok) { |
| 3930 | ir_build_const_from(&ira->new_irb, &load_ptr_instruction->base, pointee); | 3931 | ConstExprValue *out_val = ir_get_out_val(&load_ptr_instruction->base); |
| | 3932 | *out_val = *pointee; |
| 3931 | return child_type; | 3933 | return child_type; |
| 3932 | } | 3934 | } |
| 3933 | } | 3935 | } |
| ... | @@ -3941,6 +3943,27 @@ static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -3941,6 +3943,27 @@ static TypeTableEntry *ir_analyze_instruction_load_ptr(IrAnalyze *ira, IrInstruc |
| 3941 | } | 3943 | } |
| 3942 | } | 3944 | } |
| 3943 | | 3945 | |
| | 3946 | static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstructionStorePtr *store_ptr_instruction) { |
| | 3947 | IrInstruction *ptr = store_ptr_instruction->ptr->other; |
| | 3948 | IrInstruction *value = store_ptr_instruction->value->other; |
| | 3949 | |
| | 3950 | TypeTableEntry *child_type = ptr->type_entry->data.pointer.child_type; |
| | 3951 | IrInstruction *casted_value = ir_get_casted_value(ira, value, child_type); |
| | 3952 | if (casted_value == ira->codegen->invalid_instruction) |
| | 3953 | return ira->codegen->builtin_types.entry_invalid; |
| | 3954 | |
| | 3955 | if (ptr->static_value.ok && casted_value->static_value.ok) { |
| | 3956 | ConstExprValue *dest_val = ptr->static_value.data.x_ptr.ptr[0]; |
| | 3957 | if (dest_val->ok) { |
| | 3958 | *dest_val = casted_value->static_value; |
| | 3959 | return ira->codegen->builtin_types.entry_void; |
| | 3960 | } |
| | 3961 | } |
| | 3962 | |
| | 3963 | ir_build_store_ptr_from(&ira->new_irb, &store_ptr_instruction->base, ptr, casted_value); |
| | 3964 | return ira->codegen->builtin_types.entry_void; |
| | 3965 | } |
| | 3966 | |
| 3944 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 3967 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { |
| 3945 | switch (instruction->id) { | 3968 | switch (instruction->id) { |
| 3946 | case IrInstructionIdInvalid: | 3969 | case IrInstructionIdInvalid: |
| ... | @@ -3958,7 +3981,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -3958,7 +3981,7 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 3958 | case IrInstructionIdLoadPtr: | 3981 | case IrInstructionIdLoadPtr: |
| 3959 | return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction); | 3982 | return ir_analyze_instruction_load_ptr(ira, (IrInstructionLoadPtr *)instruction); |
| 3960 | case IrInstructionIdStorePtr: | 3983 | case IrInstructionIdStorePtr: |
| 3961 | zig_panic("TODO store ptr"); | 3984 | return ir_analyze_instruction_store_ptr(ira, (IrInstructionStorePtr *)instruction); |
| 3962 | case IrInstructionIdFieldPtr: | 3985 | case IrInstructionIdFieldPtr: |
| 3963 | zig_panic("TODO field ptr"); | 3986 | zig_panic("TODO field ptr"); |
| 3964 | case IrInstructionIdElemPtr: | 3987 | case IrInstructionIdElemPtr: |