authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-06-01 00:08:29+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-06-01 01:23:52+03:00
loge49fd39463be413a66920087d77eac983a91cb71
tree3692494fbbcd21e2f6a75b32f53baec89e312f35
parentd09d61be979fc97233bd53d9d082a86e4dcd9779

Sema: detect comptime values in `zirMakePtrConst`


1 files changed, 61 insertions(+), 6 deletions(-)

src/Sema.zig+61-6
......@@ -2711,17 +2711,72 @@ fn zirAllocComptime(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErr
27112711
27122712fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
27132713 const inst_data = sema.code.instructions.items(.data)[inst].un_node;
2714 const ptr = try sema.resolveInst(inst_data.operand);
2715 const ptr_ty = sema.typeOf(ptr);
2716 var ptr_info = ptr_ty.ptrInfo().data;
2714 const src = inst_data.src();
2715 const alloc = try sema.resolveInst(inst_data.operand);
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
27172770 ptr_info.mutable = false;
27182771 const const_ptr_ty = try Type.ptr(sema.arena, sema.mod, ptr_info);
27192772
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| {
27212775 return sema.addConstant(const_ptr_ty, val);
27222776 }
2723 try sema.requireRuntimeBlock(block, inst_data.src());
2724 return block.addBitCast(const_ptr_ty, ptr);
2777
2778 try sema.requireRuntimeBlock(block, src);
2779 return block.addBitCast(const_ptr_ty, alloc);
27252780}
27262781
27272782fn zirAllocInferredComptime(