| 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,6 +3575,7 @@ static VariableTableEntry *add_local_var_shadowable(CodeGen *g, AstNode *source_ |
| 3575 | variable_entry->block_context = context; | 3575 | variable_entry->block_context = context; |
| 3576 | variable_entry->import = import; | 3576 | variable_entry->import = import; |
| 3577 | variable_entry->shadowable = shadowable; | 3577 | variable_entry->shadowable = shadowable; |
| 3578 | variable_entry->mem_slot_index = SIZE_MAX; | ||
| 3578 | 3579 | ||
| 3579 | if (name) { | 3580 | if (name) { |
| 3580 | buf_init_from_buf(&variable_entry->name, name); | 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,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 | switch (cmp_op) { | 1543 | switch (cmp_op) { |
| 1544 | case BinOpTypeCmpEq: | 1544 | case IrBinOpCmpEq: |
| 1545 | return LLVMIntEQ; | 1545 | return LLVMIntEQ; |
| 1546 | case BinOpTypeCmpNotEq: | 1546 | case IrBinOpCmpNotEq: |
| 1547 | return LLVMIntNE; | 1547 | return LLVMIntNE; |
| 1548 | case BinOpTypeCmpLessThan: | 1548 | case IrBinOpCmpLessThan: |
| 1549 | return is_signed ? LLVMIntSLT : LLVMIntULT; | 1549 | return is_signed ? LLVMIntSLT : LLVMIntULT; |
| 1550 | case BinOpTypeCmpGreaterThan: | 1550 | case IrBinOpCmpGreaterThan: |
| 1551 | return is_signed ? LLVMIntSGT : LLVMIntUGT; | 1551 | return is_signed ? LLVMIntSGT : LLVMIntUGT; |
| 1552 | case BinOpTypeCmpLessOrEq: | 1552 | case IrBinOpCmpLessOrEq: |
| 1553 | return is_signed ? LLVMIntSLE : LLVMIntULE; | 1553 | return is_signed ? LLVMIntSLE : LLVMIntULE; |
| 1554 | case BinOpTypeCmpGreaterOrEq: | 1554 | case IrBinOpCmpGreaterOrEq: |
| 1555 | return is_signed ? LLVMIntSGE : LLVMIntUGE; | 1555 | return is_signed ? LLVMIntSGE : LLVMIntUGE; |
| 1556 | default: | 1556 | default: |
| 1557 | zig_unreachable(); | 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 | switch (cmp_op) { | 1562 | switch (cmp_op) { |
| 1563 | case BinOpTypeCmpEq: | 1563 | case IrBinOpCmpEq: |
| 1564 | return LLVMRealOEQ; | 1564 | return LLVMRealOEQ; |
| 1565 | case BinOpTypeCmpNotEq: | 1565 | case IrBinOpCmpNotEq: |
| 1566 | return LLVMRealONE; | 1566 | return LLVMRealONE; |
| 1567 | case BinOpTypeCmpLessThan: | 1567 | case IrBinOpCmpLessThan: |
| 1568 | return LLVMRealOLT; | 1568 | return LLVMRealOLT; |
| 1569 | case BinOpTypeCmpGreaterThan: | 1569 | case IrBinOpCmpGreaterThan: |
| 1570 | return LLVMRealOGT; | 1570 | return LLVMRealOGT; |
| 1571 | case BinOpTypeCmpLessOrEq: | 1571 | case IrBinOpCmpLessOrEq: |
| 1572 | return LLVMRealOLE; | 1572 | return LLVMRealOLE; |
| 1573 | case BinOpTypeCmpGreaterOrEq: | 1573 | case IrBinOpCmpGreaterOrEq: |
| 1574 | return LLVMRealOGE; | 1574 | return LLVMRealOGE; |
| 1575 | default: | 1575 | default: |
| 1576 | zig_unreachable(); | 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 | static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) { | 1580 | static LLVMValueRef gen_bool_and_expr(CodeGen *g, AstNode *node) { |
| 1616 | assert(node->type == NodeTypeBinOpExpr); | 1581 | assert(node->type == NodeTypeBinOpExpr); |
| 1617 | 1582 | ||
| ... | @@ -1844,7 +1809,7 @@ static LLVMValueRef gen_bin_op_expr(CodeGen *g, AstNode *node) { | ... | @@ -1844,7 +1809,7 @@ static LLVMValueRef gen_bin_op_expr(CodeGen *g, AstNode *node) { |
| 1844 | case BinOpTypeCmpGreaterThan: | 1809 | case BinOpTypeCmpGreaterThan: |
| 1845 | case BinOpTypeCmpLessOrEq: | 1810 | case BinOpTypeCmpLessOrEq: |
| 1846 | case BinOpTypeCmpGreaterOrEq: | 1811 | case BinOpTypeCmpGreaterOrEq: |
| 1847 | return gen_cmp_expr(g, node); | 1812 | zig_panic("moved to ir_render"); |
| 1848 | case BinOpTypeUnwrapMaybe: | 1813 | case BinOpTypeUnwrapMaybe: |
| 1849 | return gen_unwrap_maybe_expr(g, node); | 1814 | return gen_unwrap_maybe_expr(g, node); |
| 1850 | case BinOpTypeBinOr: | 1815 | case BinOpTypeBinOr: |
| ... | @@ -2341,6 +2306,41 @@ static LLVMValueRef ir_render_bin_op_bool(CodeGen *g, IrExecutable *executable, | ... | @@ -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 | static LLVMValueRef ir_render_bin_op_add(CodeGen *g, IrExecutable *executable, | 2344 | static LLVMValueRef ir_render_bin_op_add(CodeGen *g, IrExecutable *executable, |
| 2345 | IrInstructionBinOp *bin_op_instruction) | 2345 | IrInstructionBinOp *bin_op_instruction) |
| 2346 | { | 2346 | { |
| ... | @@ -2389,7 +2389,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, | ... | @@ -2389,7 +2389,7 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable, |
| 2389 | case IrBinOpCmpGreaterThan: | 2389 | case IrBinOpCmpGreaterThan: |
| 2390 | case IrBinOpCmpLessOrEq: | 2390 | case IrBinOpCmpLessOrEq: |
| 2391 | case IrBinOpCmpGreaterOrEq: | 2391 | case IrBinOpCmpGreaterOrEq: |
| 2392 | zig_panic("TODO bin op cmp"); | 2392 | return ir_render_bin_op_cmp(g, executable, bin_op_instruction); |
| 2393 | case IrBinOpAdd: | 2393 | case IrBinOpAdd: |
| 2394 | case IrBinOpAddWrap: | 2394 | case IrBinOpAddWrap: |
| 2395 | return ir_render_bin_op_add(g, executable, bin_op_instruction); | 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,6 +2860,13 @@ static LLVMValueRef ir_render_load_ptr(CodeGen *g, IrExecutable *executable, IrI |
| 2860 | return LLVMBuildLoad(g->builder, ir_llvm_value(g, instruction->ptr), ""); | 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 | static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) { | 2870 | static LLVMValueRef ir_render_var_ptr(CodeGen *g, IrExecutable *executable, IrInstructionVarPtr *instruction) { |
| 2864 | return instruction->var->value_ref; | 2871 | return instruction->var->value_ref; |
| 2865 | } | 2872 | } |
| ... | @@ -2931,13 +2938,14 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -2931,13 +2938,14 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 2931 | return ir_render_un_op(g, executable, (IrInstructionUnOp *)instruction); | 2938 | return ir_render_un_op(g, executable, (IrInstructionUnOp *)instruction); |
| 2932 | case IrInstructionIdLoadPtr: | 2939 | case IrInstructionIdLoadPtr: |
| 2933 | return ir_render_load_ptr(g, executable, (IrInstructionLoadPtr *)instruction); | 2940 | return ir_render_load_ptr(g, executable, (IrInstructionLoadPtr *)instruction); |
| 2941 | case IrInstructionIdStorePtr: | ||
| 2942 | return ir_render_store_ptr(g, executable, (IrInstructionStorePtr *)instruction); | ||
| 2934 | case IrInstructionIdVarPtr: | 2943 | case IrInstructionIdVarPtr: |
| 2935 | return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction); | 2944 | return ir_render_var_ptr(g, executable, (IrInstructionVarPtr *)instruction); |
| 2936 | case IrInstructionIdCall: | 2945 | case IrInstructionIdCall: |
| 2937 | return ir_render_call(g, executable, (IrInstructionCall *)instruction); | 2946 | return ir_render_call(g, executable, (IrInstructionCall *)instruction); |
| 2938 | case IrInstructionIdSwitchBr: | 2947 | case IrInstructionIdSwitchBr: |
| 2939 | case IrInstructionIdPhi: | 2948 | case IrInstructionIdPhi: |
| 2940 | case IrInstructionIdStorePtr: | ||
| 2941 | case IrInstructionIdBuiltinCall: | 2949 | case IrInstructionIdBuiltinCall: |
| 2942 | case IrInstructionIdContainerInitList: | 2950 | case IrInstructionIdContainerInitList: |
| 2943 | case IrInstructionIdContainerInitFields: | 2951 | case IrInstructionIdContainerInitFields: |
src/ir.cpp+55-20| ... | @@ -21,7 +21,7 @@ struct IrAnalyze { | ... | @@ -21,7 +21,7 @@ struct IrAnalyze { |
| 21 | IrBuilder old_irb; | 21 | IrBuilder old_irb; |
| 22 | IrBuilder new_irb; | 22 | IrBuilder new_irb; |
| 23 | IrExecContext exec_context; | 23 | IrExecContext exec_context; |
| 24 | ZigList<IrBasicBlock *> block_queue; | 24 | ZigList<IrBasicBlock *> old_bb_queue; |
| 25 | size_t block_queue_index; | 25 | size_t block_queue_index; |
| 26 | size_t instruction_index; | 26 | size_t instruction_index; |
| 27 | TypeTableEntry *explicit_return_type; | 27 | TypeTableEntry *explicit_return_type; |
| ... | @@ -1609,15 +1609,15 @@ static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) { | ... | @@ -1609,15 +1609,15 @@ static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb) { |
| 1609 | if (old_bb->other) | 1609 | if (old_bb->other) |
| 1610 | return old_bb->other; | 1610 | return old_bb->other; |
| 1611 | IrBasicBlock *new_bb = ir_build_bb_from(&ira->new_irb, old_bb); | 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 | return new_bb; | 1613 | return new_bb; |
| 1614 | } | 1614 | } |
| 1615 | 1615 | ||
| 1616 | static void ir_finish_bb(IrAnalyze *ira) { | 1616 | static void ir_finish_bb(IrAnalyze *ira) { |
| 1617 | ira->block_queue_index += 1; | 1617 | ira->block_queue_index += 1; |
| 1618 | 1618 | ||
| 1619 | if (ira->block_queue_index < ira->block_queue.length) { | 1619 | if (ira->block_queue_index < ira->old_bb_queue.length) { |
| 1620 | IrBasicBlock *old_bb = ira->block_queue.at(ira->block_queue_index); | 1620 | IrBasicBlock *old_bb = ira->old_bb_queue.at(ira->block_queue_index); |
| 1621 | ira->instruction_index = 0; | 1621 | ira->instruction_index = 0; |
| 1622 | ira->new_irb.current_basic_block = ir_get_new_bb(ira, old_bb); | 1622 | ira->new_irb.current_basic_block = ir_get_new_bb(ira, old_bb); |
| 1623 | ira->old_irb.current_basic_block = old_bb; | 1623 | ira->old_irb.current_basic_block = old_bb; |
| ... | @@ -2260,9 +2260,18 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp | ... | @@ -2260,9 +2260,18 @@ static TypeTableEntry *ir_analyze_bin_op_math(IrAnalyze *ira, IrInstructionBinOp |
| 2260 | return ira->codegen->builtin_types.entry_invalid; | 2260 | return ira->codegen->builtin_types.entry_invalid; |
| 2261 | } | 2261 | } |
| 2262 | 2262 | ||
| 2263 | if (op1->static_value.ok && op2->static_value.ok) { | 2263 | IrInstruction *casted_op1 = ir_get_casted_value(ira, op1, resolved_type); |
| 2264 | ConstExprValue *op1_val = &op1->static_value; | 2264 | if (casted_op1 == ira->codegen->invalid_instruction) |
| 2265 | ConstExprValue *op2_val = &op2->static_value; | 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 | ConstExprValue *out_val = &bin_op_instruction->base.static_value; | 2275 | ConstExprValue *out_val = &bin_op_instruction->base.static_value; |
| 2267 | 2276 | ||
| 2268 | bin_op_instruction->base.other = &bin_op_instruction->base; | 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,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); | 2298 | ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, casted_op1, casted_op2); |
| 2290 | |||
| 2291 | return resolved_type; | 2299 | return resolved_type; |
| 2292 | } | 2300 | } |
| 2293 | 2301 | ||
| ... | @@ -4006,17 +4014,20 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP | ... | @@ -4006,17 +4014,20 @@ static TypeTableEntry *ir_analyze_instruction_phi(IrAnalyze *ira, IrInstructionP |
| 4006 | 4014 | ||
| 4007 | static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarPtr *var_ptr_instruction) { | 4015 | static TypeTableEntry *ir_analyze_instruction_var_ptr(IrAnalyze *ira, IrInstructionVarPtr *var_ptr_instruction) { |
| 4008 | VariableTableEntry *var = var_ptr_instruction->var; | 4016 | VariableTableEntry *var = var_ptr_instruction->var; |
| 4009 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; | ||
| 4010 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, var_ptr_instruction->var->type, false); | 4017 | TypeTableEntry *ptr_type = get_pointer_to_type(ira->codegen, var_ptr_instruction->var->type, false); |
| 4011 | if (mem_slot->ok) { | 4018 | // TODO once the anlayze code is fully ported over to IR we won't need this SIZE_MAX thing. |
| 4012 | ConstExprValue *out_val = ir_get_out_val(&var_ptr_instruction->base); | 4019 | if (var->mem_slot_index != SIZE_MAX) { |
| 4013 | 4020 | ConstExprValue *mem_slot = &ira->exec_context.mem_slot_list[var->mem_slot_index]; | |
| 4014 | out_val->ok = true; | 4021 | if (mem_slot->ok) { |
| 4015 | out_val->data.x_ptr.len = 1; | 4022 | ConstExprValue *out_val = ir_get_out_val(&var_ptr_instruction->base); |
| 4016 | out_val->data.x_ptr.is_c_str = false; | 4023 | |
| 4017 | out_val->data.x_ptr.ptr = allocate<ConstExprValue *>(1); | 4024 | out_val->ok = true; |
| 4018 | out_val->data.x_ptr.ptr[0] = mem_slot; | 4025 | out_val->data.x_ptr.len = 1; |
| 4019 | return ptr_type; | 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 | ir_build_var_ptr_from(&ira->new_irb, &var_ptr_instruction->base, var); | 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,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 | ir_build_store_ptr_from(&ira->new_irb, &store_ptr_instruction->base, ptr, casted_value); | 4103 | ir_build_store_ptr_from(&ira->new_irb, &store_ptr_instruction->base, ptr, casted_value); |
| 4069 | return ira->codegen->builtin_types.entry_void; | 4104 | return ira->codegen->builtin_types.entry_void; |
| 4070 | } | 4105 | } |
| ... | @@ -4153,7 +4188,7 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl | ... | @@ -4153,7 +4188,7 @@ TypeTableEntry *ir_analyze(CodeGen *codegen, IrExecutable *old_exec, IrExecutabl |
| 4153 | ira->block_queue_index = 0; | 4188 | ira->block_queue_index = 0; |
| 4154 | ira->instruction_index = 0; | 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 | IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); | 4192 | IrInstruction *old_instruction = ira->old_irb.current_basic_block->instruction_list.at(ira->instruction_index); |
| 4158 | if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) { | 4193 | if (old_instruction->ref_count == 0 && !ir_has_side_effects(old_instruction)) { |
| 4159 | ira->instruction_index += 1; | 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,11 +93,15 @@ static void ir_print_const_instruction(IrPrint *irp, IrInstruction *instruction) |
| 93 | ir_print_const_value(irp, type_entry, const_val); | 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 | static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) { | 100 | static void ir_print_other_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 97 | if (instruction->static_value.ok) { | 101 | if (instruction->static_value.ok) { |
| 98 | ir_print_const_instruction(irp, instruction); | 102 | ir_print_const_instruction(irp, instruction); |
| 99 | } else { | 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,7 +337,7 @@ static void ir_print_load_ptr(IrPrint *irp, IrInstructionLoadPtr *instruction) { |
| 333 | 337 | ||
| 334 | static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) { | 338 | static void ir_print_store_ptr(IrPrint *irp, IrInstructionStorePtr *instruction) { |
| 335 | fprintf(irp->f, "*"); | 339 | fprintf(irp->f, "*"); |
| 336 | ir_print_other_instruction(irp, instruction->ptr); | 340 | ir_print_var_instruction(irp, instruction->ptr); |
| 337 | fprintf(irp->f, " = "); | 341 | fprintf(irp->f, " = "); |
| 338 | ir_print_other_instruction(irp, instruction->value); | 342 | ir_print_other_instruction(irp, instruction->value); |
| 339 | } | 343 | } |