| author | |
| committer | |
| log | 114049a22031be63da511ea53f4e655fc72a4578 |
| tree | 86dd0e56e167de5574d31a85e61636e55fa0c832 |
| parent | 78e6314422bda10440dccf7e7fcfe294193cdca7 |
4 files changed, 122 insertions(+), 74 deletions(-)
src/analyze.cpp+1| ... | ... | @@ -3575,6 +3575,7 @@ static VariableTableEntry *add_local_var_shadowable(CodeGen *g, AstNode *source_ |
| 3575 | 3575 | variable_entry->block_context = context; |
| 3576 | 3576 | variable_entry->import = import; |
| 3577 | 3577 | variable_entry->shadowable = shadowable; |
| 3578 | variable_entry->mem_slot_index = SIZE_MAX; | |
| 3578 | 3579 | |
| 3579 | 3580 | if (name) { |
| 3580 | 3581 | buf_init_from_buf(&variable_entry->name, name); |
src/codegen.cpp+60-52| ... | ... | @@ -1539,79 +1539,44 @@ static LLVMValueRef gen_arithmetic_bin_op_expr(CodeGen *g, AstNode *node) { |
| 1539 | 1539 | |
| 1540 | 1540 | } |
| 1541 | 1541 | |
| 1542 | static LLVMIntPredicate cmp_op_to_int_predicate(BinOpType cmp_op, bool is_signed) { | |
| 1542 | static LLVMIntPredicate cmp_op_to_int_predicate(IrBinOp cmp_op, bool is_signed) { | |
| 1543 | 1543 | switch (cmp_op) { |
| 1544 | case BinOpTypeCmpEq: | |
| 1544 | case IrBinOpCmpEq: | |
| 1545 | 1545 | return LLVMIntEQ; |
| 1546 | case BinOpTypeCmpNotEq: | |
| 1546 | case IrBinOpCmpNotEq: | |
| 1547 | 1547 | return LLVMIntNE; |
| 1548 | case BinOpTypeCmpLessThan: | |
| 1548 | case IrBinOpCmpLessThan: | |
| 1549 | 1549 | return is_signed ? LLVMIntSLT : LLVMIntULT; |
| 1550 | case BinOpTypeCmpGreaterThan: | |
| 1550 | case IrBinOpCmpGreaterThan: | |
| 1551 | 1551 | return is_signed ? LLVMIntSGT : LLVMIntUGT; |
| 1552 | case BinOpTypeCmpLessOrEq: | |
| 1552 | case IrBinOpCmpLessOrEq: | |
| 1553 | 1553 | return is_signed ? LLVMIntSLE : LLVMIntULE; |
| 1554 | case BinOpTypeCmpGreaterOrEq: | |
| 1554 | case IrBinOpCmpGreaterOrEq: | |
| 1555 | 1555 | return is_signed ? LLVMIntSGE : LLVMIntUGE; |
| 1556 | 1556 | default: |
| 1557 | 1557 | zig_unreachable(); |
| 1558 | 1558 | } |
| 1559 | 1559 | } |
| 1560 | 1560 | |
| 1561 | static LLVMRealPredicate cmp_op_to_real_predicate(BinOpType cmp_op) { | |
| 1561 | static LLVMRealPredicate cmp_op_to_real_predicate(IrBinOp cmp_op) { | |
| 1562 | 1562 | switch (cmp_op) { |
| 1563 | case BinOpTypeCmpEq: | |
| 1563 | case IrBinOpCmpEq: | |
| 1564 | 1564 | return LLVMRealOEQ; |
| 1565 | case BinOpTypeCmpNotEq: | |
| 1565 | case IrBinOpCmpNotEq: | |
| 1566 | 1566 | return LLVMRealONE; |
| 1567 | case BinOpTypeCmpLessThan: | |
| 1567 | case IrBinOpCmpLessThan: | |
| 1568 | 1568 | return LLVMRealOLT; |
| 1569 | case BinOpTypeCmpGreaterThan: | |
| 1569 | case IrBinOpCmpGreaterThan: | |
| 1570 | 1570 | return LLVMRealOGT; |
| 1571 | case BinOpTypeCmpLessOrEq: | |
| 1571 | case IrBinOpCmpLessOrEq: | |
| 1572 | 1572 | return LLVMRealOLE; |
| 1573 | case BinOpTypeCmpGreaterOrEq: | |
| 1573 | case IrBinOpCmpGreaterOrEq: | |
| 1574 | 1574 | return LLVMRealOGE; |
| 1575 | 1575 | default: |
| 1576 | 1576 | zig_unreachable(); |
| 1577 | 1577 | } |
| 1578 | 1578 | } |
| 1579 | 1579 | |
| 1580 | static LLVMValueRef gen_cmp_expr(CodeGen *g, AstNode *node) { | |
| 1581 | assert(node->type == NodeTypeBinOpExpr); | |
| 1582 | ||
| 1583 | LLVMValueRef val1 = gen_expr(g, node->data.bin_op_expr.op1); | |
| 1584 | LLVMValueRef val2 = gen_expr(g, node->data.bin_op_expr.op2); | |
| 1585 | ||
| 1586 | TypeTableEntry *op1_type = get_expr_type(node->data.bin_op_expr.op1); | |
| 1587 | TypeTableEntry *op2_type = get_expr_type(node->data.bin_op_expr.op2); | |
| 1588 | assert(op1_type == op2_type); | |
| 1589 | ||
| 1590 | if (op1_type->id == TypeTableEntryIdFloat) { | |
| 1591 | LLVMRealPredicate pred = cmp_op_to_real_predicate(node->data.bin_op_expr.bin_op); | |
| 1592 | return LLVMBuildFCmp(g->builder, pred, val1, val2, ""); | |
| 1593 | } else if (op1_type->id == TypeTableEntryIdInt) { | |
| 1594 | LLVMIntPredicate pred = cmp_op_to_int_predicate(node->data.bin_op_expr.bin_op, | |
| 1595 | op1_type->data.integral.is_signed); | |
| 1596 | return LLVMBuildICmp(g->builder, pred, val1, val2, ""); | |
| 1597 | } else if (op1_type->id == TypeTableEntryIdEnum) { | |
| 1598 | if (op1_type->data.enumeration.gen_field_count == 0) { | |
| 1599 | LLVMIntPredicate pred = cmp_op_to_int_predicate(node->data.bin_op_expr.bin_op, false); | |
| 1600 | return LLVMBuildICmp(g->builder, pred, val1, val2, ""); | |
| 1601 | } else { | |
| 1602 | zig_unreachable(); | |
| 1603 | } | |
| 1604 | } else if (op1_type->id == TypeTableEntryIdPureError || | |
| 1605 | op1_type->id == TypeTableEntryIdPointer || | |
| 1606 | op1_type->id == TypeTableEntryIdBool) | |
| 1607 | { | |
| 1608 | LLVMIntPredicate pred = cmp_op_to_int_predicate(node->data.bin_op_expr.bin_op, false); | |
| 1609 | return LLVMBuildICmp(g->builder, pred, val1, val2, ""); | |
| 1610 | } else { | |
| 1611 | zig_unreachable(); | |
| 1612 | } | |
| 1613 | } | |
| 1614 | ||
| 1615 | 1580 | static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) { |
| 1616 | 1581 | assert(node->type == NodeTypeBinOpExpr); |
| 1617 | 1582 | |
| ... | ... | @@ -1844,7 +1809,7 @@ static LLVMValueRef gen_bin_op_expr(CodeGen *g, AstNode *node) { |
| 1844 | 1809 | case BinOpTypeCmpGreaterThan: |
| 1845 | 1810 | case BinOpTypeCmpLessOrEq: |
| 1846 | 1811 | case BinOpTypeCmpGreaterOrEq: |
| 1847 | return gen_cmp_expr(g, node); | |
| 1812 | zig_panic("moved to ir_render"); | |
| 1848 | 1813 | case BinOpTypeUnwrapMaybe: |
| 1849 | 1814 | return gen_unwrap_maybe_expr(g, node); |
| 1850 | 1815 | case BinOpTypeBinOr: |
| ... | ... | @@ -2341,6 +2306,41 @@ static LLVMValueRef ir_render_bin_op_bool(CodeGen *g, IrExecutable *executable, |
| 2341 | 2306 | } |
| 2342 | 2307 | } |
| 2343 | 2308 | |
| 2309 | static LLVMValueRef ir_render_bin_op_cmp(CodeGen *g, IrExecutable *executable, | |
| 2310 | IrInstructionBinOp *bin_op_instruction) | |
| 2311 | { | |
| 2312 | IrBinOp op_id = bin_op_instruction->op_id; | |
| 2313 | LLVMValueRef val1 = ir_llvm_value(g, bin_op_instruction->op1); | |
| 2314 | LLVMValueRef val2 = ir_llvm_value(g, bin_op_instruction->op2); | |
| 2315 | ||
| 2316 | TypeTableEntry *op1_type = bin_op_instruction->op1->type_entry; | |
| 2317 | TypeTableEntry *op2_type = bin_op_instruction->op2->type_entry; | |
| 2318 | assert(op1_type == op2_type); | |
| 2319 | ||
| 2320 | if (op1_type->id == TypeTableEntryIdFloat) { | |
| 2321 | LLVMRealPredicate pred = cmp_op_to_real_predicate(op_id); | |
| 2322 | return LLVMBuildFCmp(g->builder, pred, val1, val2, ""); | |
| 2323 | } else if (op1_type->id == TypeTableEntryIdInt) { | |
| 2324 | LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, op1_type->data.integral.is_signed); | |
| 2325 | return LLVMBuildICmp(g->builder, pred, val1, val2, ""); | |
| 2326 | } else if (op1_type->id == TypeTableEntryIdEnum) { | |
| 2327 | if (op1_type->data.enumeration.gen_field_count == 0) { | |
| 2328 | LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false); | |
| 2329 | return LLVMBuildICmp(g->builder, pred, val1, val2, ""); | |
| 2330 | } else { | |
| 2331 | zig_unreachable(); | |
| 2332 | } | |
| 2333 | } else if (op1_type->id == TypeTableEntryIdPureError || | |
| 2334 | op1_type->id == TypeTableEntryIdPointer || | |
| 2335 | op1_type->id == TypeTableEntryIdBool) | |
| 2336 | { | |
| 2337 | LLVMIntPredicate pred = cmp_op_to_int_predicate(op_id, false); | |
| 2338 | return LLVMBuildICmp(g->builder, pred, val1, val2, ""); | |
| 2339 | } else { | |
| 2340 | zig_unreachable(); | |
| 2341 | } | |
| 2342 | } | |
| 2343 | ||
| 2344 | 2344 | static LLVMValueRef ir_render_bin_op_add(CodeGen *g, IrExecutable *executable, |
| 2345 | 2345 | IrInstructionBinOp *bin_op_instruction) |
| 2346 | 2346 | { |
| ... | ... | @@ -2389,7 +2389,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 2389 | 2389 | case IrBinOpCmpGreaterThan: |
| 2390 | 2390 | case IrBinOpCmpLessOrEq: |
| 2391 | 2391 | case IrBinOpCmpGreaterOrEq: |
| 2392 | zig_panic("TODO bin op cmp"); | |
| 2392 | return ir_render_bin_op_cmp(g, executable, bin_op_instruction); | |
| 2393 | 2393 | case IrBinOpAdd: |
| 2394 | 2394 | case IrBinOpAddWrap: |
| 2395 | 2395 | return ir_render_bin_op_add(g, executable, bin_op_instruction); |
| ... | ... | @@ -2860,6 +2860,13 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 2860 | 2860 | return LLVMBuildLoad(g->builder, ir_llvm_value(g, instruction->ptr), ""); |
| 2861 | 2861 | } |
| 2862 | 2862 | |
| 2863 | static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, IrInstructionStorePtr *instruction) { | |
| 2864 | LLVMValueRef ptr = ir_llvm_value(g, instruction->ptr); | |
| 2865 | LLVMValueRef value = ir_llvm_value(g, instruction->value); | |
| 2866 | LLVMBuildStore(g->builder, value, ptr); | |
| 2867 | return nullptr; | |
| 2868 | } | |
| 2869 | ||
| 2863 | 2870 | static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) { |
| 2864 | 2871 | return instruction->var->value_ref; |
| 2865 | 2872 | } |
| ... | ... | @@ -2931,13 +2938,14 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 2931 | 2938 | return ir_render_un_op(g, executable, (IrInstructionUnOp *)instruction); |
| 2932 | 2939 | case IrInstructionIdLoadPtr: |
| 2933 | 2940 | return ir_render_load_ptr(g, executable, (IrInstructionLoadPtr *)instruction); |
| 2941 | case IrInstructionIdStorePtr: | |
| 2942 | return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction); | |
| 2934 | 2943 | case IrInstructionIdVarPtr: |
| 2935 | 2944 | return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction); |
| 2936 | 2945 | case IrInstructionIdCall: |
| 2937 | 2946 | return ir_render_call(g, executable, (IrInstructionCall *)instruction); |
| 2938 | 2947 | case IrInstructionIdSwitchBr: |
| 2939 | 2948 | case IrInstructionIdPhi: |
| 2940 | case IrInstructionIdStorePtr: | |
| 2941 | 2949 | case IrInstructionIdBuiltinCall: |
| 2942 | 2950 | case IrInstructionIdContainerInitList: |
| 2943 | 2951 | case IrInstructionIdContainerInitFields: |
src/ir.cpp+55-20| ... | ... | @@ -21,7 +21,7 @@ struct IrAnalyze { |
| 21 | 21 | IrBuilder old_irb; |
| 22 | 22 | IrBuilder new_irb; |
| 23 | 23 | IrExecContext exec_context; |
| 24 | ZigList<IrBasicBlock *> block_queue; | |
| 24 | ZigList<IrBasicBlock *> old_bb_queue; | |
| 25 | 25 | size_t block_queue_index; |
| 26 | 26 | size_t instruction_index; |
| 27 | 27 | TypeTableEntry *explicit_return_type; |
| ... | ... | @@ -1609,15 +1609,15 @@ static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) { |
| 1609 | 1609 | if (old_bb->other) |
| 1610 | 1610 | return old_bb->other; |
| 1611 | 1611 | IrBasicBlock *new_bb = ir_build_bb_from(&ira->new_irb, old_bb); |
| 1612 | ira->block_queue.append(new_bb); | |
| 1612 | ira->old_bb_queue.append(old_bb); | |
| 1613 | 1613 | return new_bb; |
| 1614 | 1614 | } |
| 1615 | 1615 | |
| 1616 | 1616 | static void ir_finish_bb(IrAnalyze *ira) { |
| 1617 | 1617 | ira->block_queue_index += 1; |
| 1618 | 1618 | |
| 1619 | if (ira->block_queue_index < ira->block_queue.length) { | |
| 1620 | IrBasicBlock *old_bb = ira->block_queue.at(ira->block_queue_index); | |
| 1619 | if (ira->block_queue_index < ira->old_bb_queue.length) { | |
| 1620 | IrBasicBlock *old_bb = ira->old_bb_queue.at(ira->block_queue_index); | |
| 1621 | 1621 | ira->instruction_index = 0; |
| 1622 | 1622 | ira->new_irb.current_basic_block = ir_get_new_bb(ira, old_bb); |
| 1623 | 1623 | ira->old_irb.current_basic_block = old_bb; |
| ... | ... | @@ -2260,9 +2260,18 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 2260 | 2260 | return ira->codegen->builtin_types.entry_invalid; |
| 2261 | 2261 | } |
| 2262 | 2262 | |
| 2263 | if (op1->static_value.ok && op2->static_value.ok) { | |
| 2264 | ConstExprValue *op1_val = &op1->static_value; | |
| 2265 | ConstExprValue *op2_val = &op2->static_value; | |
| 2263 | IrInstruction *casted_op1 = ir_get_casted_value(ira, op1, resolved_type); | |
| 2264 | if (casted_op1 == ira->codegen->invalid_instruction) | |
| 2265 | return ira->codegen->builtin_types.entry_invalid; | |
| 2266 | ||
| 2267 | IrInstruction *casted_op2 = ir_get_casted_value(ira, op2, resolved_type); | |
| 2268 | if (casted_op2 == ira->codegen->invalid_instruction) | |
| 2269 | return ira->codegen->builtin_types.entry_invalid; | |
| 2270 | ||
| 2271 | ||
| 2272 | if (casted_op1->static_value.ok && casted_op2->static_value.ok) { | |
| 2273 | ConstExprValue *op1_val = &casted_op1->static_value; | |
| 2274 | ConstExprValue *op2_val = &casted_op2->static_value; | |
| 2266 | 2275 | ConstExprValue *out_val = &bin_op_instruction->base.static_value; |
| 2267 | 2276 | |
| 2268 | 2277 | bin_op_instruction->base.other = &bin_op_instruction->base; |
| ... | ... | @@ -2286,8 +2295,7 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 2286 | 2295 | |
| 2287 | 2296 | } |
| 2288 | 2297 | |
| 2289 | ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, op1, op2); | |
| 2290 | ||
| 2298 | ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, casted_op1, casted_op2); | |
| 2291 | 2299 | return resolved_type; |
| 2292 | 2300 | } |
| 2293 | 2301 | |
| ... | ... | @@ -4006,17 +4014,20 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP |
| 4006 | 4014 | |
| 4007 | 4015 | static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarPtr *var_ptr_instruction) { |
| 4008 | 4016 | VariableTableEntry *var = var_ptr_instruction->var; |
| 4009 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; | |
| 4010 | 4017 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, var_ptr_instruction->var->type, false); |
| 4011 | if (mem_slot->ok) { | |
| 4012 | ConstExprValue *out_val = ir_get_out_val(&var_ptr_instruction->base); | |
| 4013 | ||
| 4014 | out_val->ok = true; | |
| 4015 | out_val->data.x_ptr.len = 1; | |
| 4016 | out_val->data.x_ptr.is_c_str = false; | |
| 4017 | out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1); | |
| 4018 | out_val->data.x_ptr.ptr[0] = mem_slot; | |
| 4019 | return ptr_type; | |
| 4018 | // TODO once the anlayze code is fully ported over to IR we won't need this SIZE_MAX thing. | |
| 4019 | if (var->mem_slot_index != SIZE_MAX) { | |
| 4020 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; | |
| 4021 | if (mem_slot->ok) { | |
| 4022 | ConstExprValue *out_val = ir_get_out_val(&var_ptr_instruction->base); | |
| 4023 | ||
| 4024 | out_val->ok = true; | |
| 4025 | out_val->data.x_ptr.len = 1; | |
| 4026 | out_val->data.x_ptr.is_c_str = false; | |
| 4027 | out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1); | |
| 4028 | out_val->data.x_ptr.ptr[0] = mem_slot; | |
| 4029 | return ptr_type; | |
| 4030 | } | |
| 4020 | 4031 | } |
| 4021 | 4032 | |
| 4022 | 4033 | ir_build_var_ptr_from(&ira->new_irb, &var_ptr_instruction->base, var); |
| ... | ... | @@ -4065,6 +4076,30 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru |
| 4065 | 4076 | } |
| 4066 | 4077 | } |
| 4067 | 4078 | |
| 4079 | if (ptr->static_value.ok) { | |
| 4080 | // This memory location is transforming from known at compile time to known at runtime. | |
| 4081 | // We must emit our own var ptr instruction. | |
| 4082 | ptr->static_value.ok = false; | |
| 4083 | IrInstruction *new_ptr_inst; | |
| 4084 | if (ptr->id == IrInstructionIdVarPtr) { | |
| 4085 | IrInstructionVarPtr *var_ptr_inst = (IrInstructionVarPtr *)ptr; | |
| 4086 | VariableTableEntry *var = var_ptr_inst->var; | |
| 4087 | new_ptr_inst = ir_build_var_ptr(&ira->new_irb, store_ptr_instruction->base.source_node, var); | |
| 4088 | assert(var->mem_slot_index != SIZE_MAX); | |
| 4089 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; | |
| 4090 | mem_slot->ok = false; | |
| 4091 | } else if (ptr->id == IrInstructionIdFieldPtr) { | |
| 4092 | zig_panic("TODO"); | |
| 4093 | } else if (ptr->id == IrInstructionIdElemPtr) { | |
| 4094 | zig_panic("TODO"); | |
| 4095 | } else { | |
| 4096 | zig_unreachable(); | |
| 4097 | } | |
| 4098 | new_ptr_inst->type_entry = ptr->type_entry; | |
| 4099 | ir_build_store_ptr(&ira->new_irb, store_ptr_instruction->base.source_node, new_ptr_inst, casted_value); | |
| 4100 | return ira->codegen->builtin_types.entry_void; | |
| 4101 | } | |
| 4102 | ||
| 4068 | 4103 | ir_build_store_ptr_from(&ira->new_irb, &store_ptr_instruction->base, ptr, casted_value); |
| 4069 | 4104 | return ira->codegen->builtin_types.entry_void; |
| 4070 | 4105 | } |
| ... | ... | @@ -4153,7 +4188,7 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl |
| 4153 | 4188 | ira->block_queue_index = 0; |
| 4154 | 4189 | ira->instruction_index = 0; |
| 4155 | 4190 | |
| 4156 | while (ira->block_queue_index < ira->block_queue.length) { | |
| 4191 | while (ira->block_queue_index < ira->old_bb_queue.length) { | |
| 4157 | 4192 | IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); |
| 4158 | 4193 | if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) { |
| 4159 | 4194 | ira->instruction_index += 1; |
src/ir_print.cpp+6-2| ... | ... | @@ -93,11 +93,15 @@ static void ir_print_const_instruction(IrPrint *irp, IrInstruction *instruction) |
| 93 | 93 | ir_print_const_value(irp, type_entry, const_val); |
| 94 | 94 | } |
| 95 | 95 | |
| 96 | static void ir_print_var_instruction(IrPrint *irp, IrInstruction *instruction) { | |
| 97 | fprintf(irp->f, "#%zu", instruction->debug_id); | |
| 98 | } | |
| 99 | ||
| 96 | 100 | static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 97 | 101 | if (instruction->static_value.ok) { |
| 98 | 102 | ir_print_const_instruction(irp, instruction); |
| 99 | 103 | } else { |
| 100 | fprintf(irp->f, "#%zu", instruction->debug_id); | |
| 104 | ir_print_var_instruction(irp, instruction); | |
| 101 | 105 | } |
| 102 | 106 | } |
| 103 | 107 | |
| ... | ... | @@ -333,7 +337,7 @@ static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) { |
| 333 | 337 | |
| 334 | 338 | static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) { |
| 335 | 339 | fprintf(irp->f, "*"); |
| 336 | ir_print_other_instruction(irp, instruction->ptr); | |
| 340 | ir_print_var_instruction(irp, instruction->ptr); | |
| 337 | 341 | fprintf(irp->f, " = "); |
| 338 | 342 | ir_print_other_instruction(irp, instruction->value); |
| 339 | 343 | } |