| ... | @@ -682,28 +682,77 @@ fn varDecl( | ... | @@ -682,28 +682,77 @@ fn varDecl( |
| 682 | return &sub_scope.base; | 682 | return &sub_scope.base; |
| 683 | } | 683 | } |
| 684 | | 684 | |
| | 685 | // Detect whether the initialization expression actually uses the |
| | 686 | // result location pointer. |
| | 687 | var init_scope: Scope.GenZIR = .{ |
| | 688 | .parent = scope, |
| | 689 | .decl = scope.ownerDecl().?, |
| | 690 | .arena = scope.arena(), |
| | 691 | .instructions = .{}, |
| | 692 | }; |
| | 693 | defer init_scope.instructions.deinit(mod.gpa); |
| | 694 | |
| 685 | var resolve_inferred_alloc: ?*zir.Inst = null; | 695 | var resolve_inferred_alloc: ?*zir.Inst = null; |
| 686 | const result_loc = r: { | 696 | if (node.getTypeNode()) |type_node| { |
| 687 | if (node.getTypeNode()) |type_node| { | 697 | const type_inst = try typeExpr(mod, &init_scope.base, type_node); |
| 688 | const type_inst = try typeExpr(mod, scope, type_node); | 698 | const alloc = try addZIRUnOp(mod, &init_scope.base, name_src, .alloc, type_inst); |
| 689 | const alloc = try addZIRUnOp(mod, scope, name_src, .alloc, type_inst); | 699 | init_scope.rl_ptr = alloc; |
| 690 | break :r ResultLoc{ .ptr = alloc }; | 700 | } else { |
| 691 | } else { | 701 | const alloc = try addZIRNoOpT(mod, &init_scope.base, name_src, .alloc_inferred); |
| 692 | const alloc = try addZIRNoOpT(mod, scope, name_src, .alloc_inferred); | 702 | resolve_inferred_alloc = &alloc.base; |
| 693 | resolve_inferred_alloc = &alloc.base; | 703 | init_scope.rl_ptr = &alloc.base; |
| 694 | break :r ResultLoc{ .inferred_ptr = alloc }; | 704 | } |
| | 705 | const init_result_loc: ResultLoc = .{ .block_ptr = &init_scope }; |
| | 706 | const init_inst = try expr(mod, &init_scope.base, init_result_loc, init_node); |
| | 707 | const parent_zir = &scope.getGenZIR().instructions; |
| | 708 | if (init_scope.rvalue_rl_count == 1) { |
| | 709 | // Result location pointer not used. We don't need an alloc for this |
| | 710 | // const local, and type inference becomes trivial. |
| | 711 | // Move the init_scope instructions into the parent scope, eliding |
| | 712 | // the alloc instruction and the store_to_block_ptr instruction. |
| | 713 | const expected_len = parent_zir.items.len + init_scope.instructions.items.len - 2; |
| | 714 | try parent_zir.ensureCapacity(mod.gpa, expected_len); |
| | 715 | for (init_scope.instructions.items) |src_inst| { |
| | 716 | if (src_inst == init_scope.rl_ptr.?) continue; |
| | 717 | if (src_inst.castTag(.store_to_block_ptr)) |store| { |
| | 718 | if (store.positionals.lhs == init_scope.rl_ptr.?) continue; |
| | 719 | } |
| | 720 | parent_zir.appendAssumeCapacity(src_inst); |
| 695 | } | 721 | } |
| 696 | }; | 722 | assert(parent_zir.items.len == expected_len); |
| 697 | const init_inst = try expr(mod, scope, result_loc, init_node); | 723 | const sub_scope = try block_arena.create(Scope.LocalVal); |
| | 724 | sub_scope.* = .{ |
| | 725 | .parent = scope, |
| | 726 | .gen_zir = scope.getGenZIR(), |
| | 727 | .name = ident_name, |
| | 728 | .inst = init_inst, |
| | 729 | }; |
| | 730 | return &sub_scope.base; |
| | 731 | } |
| | 732 | // The initialization expression took advantage of the result location |
| | 733 | // of the const local. In this case we will create an alloc and a LocalPtr for it. |
| | 734 | // Move the init_scope instructions into the parent scope, swapping |
| | 735 | // store_to_block_ptr for store_to_inferred_ptr. |
| | 736 | const expected_len = parent_zir.items.len + init_scope.instructions.items.len; |
| | 737 | try parent_zir.ensureCapacity(mod.gpa, expected_len); |
| | 738 | for (init_scope.instructions.items) |src_inst| { |
| | 739 | if (src_inst.castTag(.store_to_block_ptr)) |store| { |
| | 740 | if (store.positionals.lhs == init_scope.rl_ptr.?) { |
| | 741 | src_inst.tag = .store_to_inferred_ptr; |
| | 742 | } |
| | 743 | } |
| | 744 | parent_zir.appendAssumeCapacity(src_inst); |
| | 745 | } |
| | 746 | assert(parent_zir.items.len == expected_len); |
| 698 | if (resolve_inferred_alloc) |inst| { | 747 | if (resolve_inferred_alloc) |inst| { |
| 699 | _ = try addZIRUnOp(mod, scope, name_src, .resolve_inferred_alloc, inst); | 748 | _ = try addZIRUnOp(mod, scope, name_src, .resolve_inferred_alloc, inst); |
| 700 | } | 749 | } |
| 701 | const sub_scope = try block_arena.create(Scope.LocalVal); | 750 | const sub_scope = try block_arena.create(Scope.LocalPtr); |
| 702 | sub_scope.* = .{ | 751 | sub_scope.* = .{ |
| 703 | .parent = scope, | 752 | .parent = scope, |
| 704 | .gen_zir = scope.getGenZIR(), | 753 | .gen_zir = scope.getGenZIR(), |
| 705 | .name = ident_name, | 754 | .name = ident_name, |
| 706 | .inst = init_inst, | 755 | .ptr = init_scope.rl_ptr.?, |
| 707 | }; | 756 | }; |
| 708 | return &sub_scope.base; | 757 | return &sub_scope.base; |
| 709 | }, | 758 | }, |
| ... | @@ -2810,13 +2859,15 @@ fn asRlPtr( | ... | @@ -2810,13 +2859,15 @@ fn asRlPtr( |
| 2810 | const expected_len = parent_zir.items.len + as_scope.instructions.items.len - 2; | 2859 | const expected_len = parent_zir.items.len + as_scope.instructions.items.len - 2; |
| 2811 | try parent_zir.ensureCapacity(mod.gpa, expected_len); | 2860 | try parent_zir.ensureCapacity(mod.gpa, expected_len); |
| 2812 | for (as_scope.instructions.items) |src_inst| { | 2861 | for (as_scope.instructions.items) |src_inst| { |
| 2813 | switch (src_inst.tag) { | 2862 | if (src_inst == as_scope.rl_ptr.?) continue; |
| 2814 | .store_to_block_ptr, .coerce_result_ptr => continue, | 2863 | if (src_inst.castTag(.store_to_block_ptr)) |store| { |
| 2815 | else => parent_zir.appendAssumeCapacity(src_inst), | 2864 | if (store.positionals.lhs == as_scope.rl_ptr.?) continue; |
| 2816 | } | 2865 | } |
| | 2866 | parent_zir.appendAssumeCapacity(src_inst); |
| 2817 | } | 2867 | } |
| 2818 | assert(parent_zir.items.len == expected_len); | 2868 | assert(parent_zir.items.len == expected_len); |
| 2819 | return rvalue(mod, scope, rl, result); | 2869 | const casted_result = try addZIRBinOp(mod, scope, result.src, .as, dest_type, result); |
| | 2870 | return rvalue(mod, scope, rl, casted_result); |
| 2820 | } else { | 2871 | } else { |
| 2821 | try parent_zir.appendSlice(mod.gpa, as_scope.instructions.items); | 2872 | try parent_zir.appendSlice(mod.gpa, as_scope.instructions.items); |
| 2822 | return result; | 2873 | return result; |