| ... | @@ -2711,17 +2711,72 @@ fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr | ... | @@ -2711,17 +2711,72 @@ fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr |
| 2711 | | 2711 | |
| 2712 | fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { | 2712 | fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref { |
| 2713 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; | 2713 | const inst_data = sema.code.instructions.items(.data)[inst].un_node; |
| 2714 | const ptr = try sema.resolveInst(inst_data.operand); | 2714 | const src = inst_data.src(); |
| 2715 | const ptr_ty = sema.typeOf(ptr); | 2715 | const alloc = try sema.resolveInst(inst_data.operand); |
| 2716 | var ptr_info = ptr_ty.ptrInfo().data; | 2716 | const alloc_ty = sema.typeOf(alloc); |
| | 2717 | |
| | 2718 | var ptr_info = alloc_ty.ptrInfo().data; |
| | 2719 | const elem_ty = ptr_info.pointee_type; |
| | 2720 | |
| | 2721 | // Detect if all stores to an `.alloc` were comptime known. |
| | 2722 | ct: { |
| | 2723 | var search_index: usize = block.instructions.items.len; |
| | 2724 | const air_tags = sema.air_instructions.items(.tag); |
| | 2725 | const air_datas = sema.air_instructions.items(.data); |
| | 2726 | |
| | 2727 | const store_inst = while (true) { |
| | 2728 | if (search_index == 0) break :ct; |
| | 2729 | search_index -= 1; |
| | 2730 | |
| | 2731 | const candidate = block.instructions.items[search_index]; |
| | 2732 | switch (air_tags[candidate]) { |
| | 2733 | .dbg_stmt => continue, |
| | 2734 | .store => break candidate, |
| | 2735 | else => break :ct, |
| | 2736 | } |
| | 2737 | } else unreachable; // TODO shouldn't need this |
| | 2738 | |
| | 2739 | while (true) { |
| | 2740 | if (search_index == 0) break :ct; |
| | 2741 | search_index -= 1; |
| | 2742 | |
| | 2743 | const candidate = block.instructions.items[search_index]; |
| | 2744 | switch (air_tags[candidate]) { |
| | 2745 | .dbg_stmt => continue, |
| | 2746 | .alloc => { |
| | 2747 | if (Air.indexToRef(candidate) != alloc) break :ct; |
| | 2748 | break; |
| | 2749 | }, |
| | 2750 | else => break :ct, |
| | 2751 | } |
| | 2752 | } |
| | 2753 | |
| | 2754 | const store_op = air_datas[store_inst].bin_op; |
| | 2755 | const store_val = (try sema.resolveMaybeUndefVal(block, src, store_op.rhs)) orelse break :ct; |
| | 2756 | if (store_op.lhs != alloc) break :ct; |
| | 2757 | |
| | 2758 | // Remove all the unnecessary runtime instructions. |
| | 2759 | block.instructions.shrinkRetainingCapacity(search_index); |
| | 2760 | |
| | 2761 | var anon_decl = try block.startAnonDecl(src); |
| | 2762 | defer anon_decl.deinit(); |
| | 2763 | return sema.analyzeDeclRef(try anon_decl.finish( |
| | 2764 | try elem_ty.copy(anon_decl.arena()), |
| | 2765 | try store_val.copy(anon_decl.arena()), |
| | 2766 | ptr_info.@"align", |
| | 2767 | )); |
| | 2768 | } |
| | 2769 | |
| 2717 | ptr_info.mutable = false; | 2770 | ptr_info.mutable = false; |
| 2718 | const const_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_info); | 2771 | const const_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_info); |
| 2719 | | 2772 | |
| 2720 | if (try sema.resolveMaybeUndefVal(block, inst_data.src(), ptr)) |val| { | 2773 | // Detect if a comptime value simply needs to have its type changed. |
| | 2774 | if (try sema.resolveMaybeUndefVal(block, inst_data.src(), alloc)) |val| { |
| 2721 | return sema.addConstant(const_ptr_ty, val); | 2775 | return sema.addConstant(const_ptr_ty, val); |
| 2722 | } | 2776 | } |
| 2723 | try sema.requireRuntimeBlock(block, inst_data.src()); | 2777 | |
| 2724 | return block.addBitCast(const_ptr_ty, ptr); | 2778 | try sema.requireRuntimeBlock(block, src); |
| | 2779 | return block.addBitCast(const_ptr_ty, alloc); |
| 2725 | } | 2780 | } |
| 2726 | | 2781 | |
| 2727 | fn zirAllocInferredComptime( | 2782 | fn zirAllocInferredComptime( |