| ... | @@ -91,14 +91,6 @@ no_partial_func_ty: bool = false, | ... | @@ -91,14 +91,6 @@ no_partial_func_ty: bool = false, |
| 91 | /// here so the values can be dropped without any cleanup. | 91 | /// here so the values can be dropped without any cleanup. |
| 92 | unresolved_inferred_allocs: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, InferredAlloc) = .{}, | 92 | unresolved_inferred_allocs: std.AutoArrayHashMapUnmanaged(Air.Inst.Index, InferredAlloc) = .{}, |
| 93 | | 93 | |
| 94 | /// Indices of comptime-mutable decls created by this Sema. These decls' values | | |
| 95 | /// should be interned after analysis completes, as they may refer to memory in | | |
| 96 | /// the Sema arena. | | |
| 97 | /// TODO: this is a workaround for memory bugs triggered by the removal of | | |
| 98 | /// Decl.value_arena. A better solution needs to be found. Probably this will | | |
| 99 | /// involve transitioning comptime-mutable memory away from using Decls at all. | | |
| 100 | comptime_mutable_decls: *std.ArrayList(InternPool.DeclIndex), | | |
| 101 | | | |
| 102 | /// This is populated when `@setAlignStack` occurs so that if there is a duplicate | 94 | /// This is populated when `@setAlignStack` occurs so that if there is a duplicate |
| 103 | /// one encountered, the conflicting source location can be shown. | 95 | /// one encountered, the conflicting source location can be shown. |
| 104 | prev_stack_alignment_src: ?LazySrcLoc = null, | 96 | prev_stack_alignment_src: ?LazySrcLoc = null, |
| ... | @@ -123,19 +115,57 @@ base_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, Air.Inst.Index) = .{}, | ... | @@ -123,19 +115,57 @@ base_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, Air.Inst.Index) = .{}, |
| 123 | /// Backed by gpa. | 115 | /// Backed by gpa. |
| 124 | maybe_comptime_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, MaybeComptimeAlloc) = .{}, | 116 | maybe_comptime_allocs: std.AutoHashMapUnmanaged(Air.Inst.Index, MaybeComptimeAlloc) = .{}, |
| 125 | | 117 | |
| | 118 | /// Comptime-mutable allocs, and any comptime allocs which reference it, are |
| | 119 | /// stored as elements of this array. |
| | 120 | /// Pointers to such memory are represented via an index into this array. |
| | 121 | /// Backed by gpa. |
| | 122 | comptime_allocs: std.ArrayListUnmanaged(ComptimeAlloc) = .{}, |
| | 123 | |
| 126 | const MaybeComptimeAlloc = struct { | 124 | const MaybeComptimeAlloc = struct { |
| 127 | /// The runtime index of the `alloc` instruction. | 125 | /// The runtime index of the `alloc` instruction. |
| 128 | runtime_index: Value.RuntimeIndex, | 126 | runtime_index: Value.RuntimeIndex, |
| 129 | /// Backed by sema.arena. Tracks all comptime-known stores to this `alloc`. Due to | 127 | /// Backed by sema.arena. Tracks all comptime-known stores to this `alloc`. Due to |
| 130 | /// RLS, a single comptime-known allocation may have arbitrarily many stores. | 128 | /// RLS, a single comptime-known allocation may have arbitrarily many stores. |
| 131 | /// This may also contain `set_union_tag` instructions. | 129 | /// This may also contain `set_union_tag` instructions. |
| 132 | stores: std.ArrayListUnmanaged(Air.Inst.Index) = .{}, | 130 | stores: std.MultiArrayList(struct { |
| | 131 | inst: Air.Inst.Index, |
| | 132 | src_decl: InternPool.DeclIndex, |
| | 133 | src: LazySrcLoc, |
| | 134 | }) = .{}, |
| 133 | /// Backed by sema.arena. Contains instructions such as `optional_payload_ptr_set` | 135 | /// Backed by sema.arena. Contains instructions such as `optional_payload_ptr_set` |
| 134 | /// which have side effects so will not be elided by Liveness: we must rewrite these | 136 | /// which have side effects so will not be elided by Liveness: we must rewrite these |
| 135 | /// instructions to be nops instead of relying on Liveness. | 137 | /// instructions to be nops instead of relying on Liveness. |
| 136 | non_elideable_pointers: std.ArrayListUnmanaged(Air.Inst.Index) = .{}, | 138 | non_elideable_pointers: std.ArrayListUnmanaged(Air.Inst.Index) = .{}, |
| 137 | }; | 139 | }; |
| 138 | | 140 | |
| | 141 | const ComptimeAlloc = struct { |
| | 142 | ty: Type, |
| | 143 | val: Value, |
| | 144 | is_const: bool, |
| | 145 | /// `.none` indicates that the alignment is the natural alignment of `val`. |
| | 146 | alignment: Alignment, |
| | 147 | /// This is the `runtime_index` at the point of this allocation. If an store |
| | 148 | /// to this alloc ever occurs with a runtime index greater than this one, it |
| | 149 | /// is behind a runtime condition, so a compile error will be emitted. |
| | 150 | runtime_index: Value.RuntimeIndex, |
| | 151 | }; |
| | 152 | |
| | 153 | fn newComptimeAlloc(sema: *Sema, block: *Block, ty: Type, alignment: Alignment) !ComptimeAllocIndex { |
| | 154 | const idx = sema.comptime_allocs.items.len; |
| | 155 | try sema.comptime_allocs.append(sema.gpa, .{ |
| | 156 | .ty = ty, |
| | 157 | .val = Value.fromInterned(try sema.mod.intern(.{ .undef = ty.toIntern() })), |
| | 158 | .is_const = false, |
| | 159 | .alignment = alignment, |
| | 160 | .runtime_index = block.runtime_index, |
| | 161 | }); |
| | 162 | return @enumFromInt(idx); |
| | 163 | } |
| | 164 | |
| | 165 | pub fn getComptimeAlloc(sema: *Sema, idx: ComptimeAllocIndex) *ComptimeAlloc { |
| | 166 | return &sema.comptime_allocs.items[@intFromEnum(idx)]; |
| | 167 | } |
| | 168 | |
| 139 | const std = @import("std"); | 169 | const std = @import("std"); |
| 140 | const math = std.math; | 170 | const math = std.math; |
| 141 | const mem = std.mem; | 171 | const mem = std.mem; |
| ... | @@ -164,6 +194,7 @@ const build_options = @import("build_options"); | ... | @@ -164,6 +194,7 @@ const build_options = @import("build_options"); |
| 164 | const Compilation = @import("Compilation.zig"); | 194 | const Compilation = @import("Compilation.zig"); |
| 165 | const InternPool = @import("InternPool.zig"); | 195 | const InternPool = @import("InternPool.zig"); |
| 166 | const Alignment = InternPool.Alignment; | 196 | const Alignment = InternPool.Alignment; |
| | 197 | const ComptimeAllocIndex = InternPool.ComptimeAllocIndex; |
| 167 | | 198 | |
| 168 | pub const default_branch_quota = 1000; | 199 | pub const default_branch_quota = 1000; |
| 169 | pub const default_reference_trace_len = 2; | 200 | pub const default_reference_trace_len = 2; |
| ... | @@ -787,40 +818,6 @@ pub const Block = struct { | ... | @@ -787,40 +818,6 @@ pub const Block = struct { |
| 787 | const zcu = block.sema.mod; | 818 | const zcu = block.sema.mod; |
| 788 | return zcu.namespacePtr(block.namespace).file_scope.mod; | 819 | return zcu.namespacePtr(block.namespace).file_scope.mod; |
| 789 | } | 820 | } |
| 790 | | | |
| 791 | pub fn startAnonDecl(block: *Block) !WipAnonDecl { | | |
| 792 | return WipAnonDecl{ | | |
| 793 | .block = block, | | |
| 794 | .finished = false, | | |
| 795 | }; | | |
| 796 | } | | |
| 797 | | | |
| 798 | pub const WipAnonDecl = struct { | | |
| 799 | block: *Block, | | |
| 800 | finished: bool, | | |
| 801 | | | |
| 802 | pub fn deinit(wad: *WipAnonDecl) void { | | |
| 803 | wad.* = undefined; | | |
| 804 | } | | |
| 805 | | | |
| 806 | /// `alignment` value of 0 means to use ABI alignment. | | |
| 807 | pub fn finish(wad: *WipAnonDecl, ty: Type, val: Value, alignment: Alignment) !InternPool.DeclIndex { | | |
| 808 | const sema = wad.block.sema; | | |
| 809 | // Do this ahead of time because `createAnonymousDecl` depends on calling | | |
| 810 | // `type.hasRuntimeBits()`. | | |
| 811 | _ = try sema.typeHasRuntimeBits(ty); | | |
| 812 | const new_decl_index = try sema.mod.createAnonymousDecl(wad.block, .{ | | |
| 813 | .ty = ty, | | |
| 814 | .val = val, | | |
| 815 | }); | | |
| 816 | const new_decl = sema.mod.declPtr(new_decl_index); | | |
| 817 | new_decl.alignment = alignment; | | |
| 818 | errdefer sema.mod.abortAnonDecl(new_decl_index); | | |
| 819 | wad.finished = true; | | |
| 820 | try sema.mod.finalizeAnonDecl(new_decl_index); | | |
| 821 | return new_decl_index; | | |
| 822 | } | | |
| 823 | }; | | |
| 824 | }; | 821 | }; |
| 825 | | 822 | |
| 826 | const LabeledBlock = struct { | 823 | const LabeledBlock = struct { |
| ... | @@ -869,6 +866,7 @@ pub fn deinit(sema: *Sema) void { | ... | @@ -869,6 +866,7 @@ pub fn deinit(sema: *Sema) void { |
| 869 | sema.unresolved_inferred_allocs.deinit(gpa); | 866 | sema.unresolved_inferred_allocs.deinit(gpa); |
| 870 | sema.base_allocs.deinit(gpa); | 867 | sema.base_allocs.deinit(gpa); |
| 871 | sema.maybe_comptime_allocs.deinit(gpa); | 868 | sema.maybe_comptime_allocs.deinit(gpa); |
| | 869 | sema.comptime_allocs.deinit(gpa); |
| 872 | sema.* = undefined; | 870 | sema.* = undefined; |
| 873 | } | 871 | } |
| 874 | | 872 | |
| ... | @@ -1901,7 +1899,7 @@ pub fn resolveConstStringIntern( | ... | @@ -1901,7 +1899,7 @@ pub fn resolveConstStringIntern( |
| 1901 | const wanted_type = Type.slice_const_u8; | 1899 | const wanted_type = Type.slice_const_u8; |
| 1902 | const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); | 1900 | const coerced_inst = try sema.coerce(block, wanted_type, air_inst, src); |
| 1903 | const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason); | 1901 | const val = try sema.resolveConstDefinedValue(block, src, coerced_inst, reason); |
| 1904 | return val.toIpString(wanted_type, sema.mod); | 1902 | return sema.sliceToIpString(block, src, val, reason); |
| 1905 | } | 1903 | } |
| 1906 | | 1904 | |
| 1907 | pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type { | 1905 | pub fn resolveType(sema: *Sema, block: *Block, src: LazySrcLoc, zir_ref: Zir.Inst.Ref) !Type { |
| ... | @@ -2140,7 +2138,7 @@ fn resolveValueResolveLazy(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value | ... | @@ -2140,7 +2138,7 @@ fn resolveValueResolveLazy(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value |
| 2140 | fn resolveValueIntable(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value { | 2138 | fn resolveValueIntable(sema: *Sema, inst: Air.Inst.Ref) CompileError!?Value { |
| 2141 | const val = (try sema.resolveValue(inst)) orelse return null; | 2139 | const val = (try sema.resolveValue(inst)) orelse return null; |
| 2142 | if (sema.mod.intern_pool.getBackingAddrTag(val.toIntern())) |addr| switch (addr) { | 2140 | if (sema.mod.intern_pool.getBackingAddrTag(val.toIntern())) |addr| switch (addr) { |
| 2143 | .decl, .anon_decl, .mut_decl, .comptime_field => return null, | 2141 | .decl, .anon_decl, .comptime_alloc, .comptime_field => return null, |
| 2144 | .int => {}, | 2142 | .int => {}, |
| 2145 | .eu_payload, .opt_payload, .elem, .field => unreachable, | 2143 | .eu_payload, .opt_payload, .elem, .field => unreachable, |
| 2146 | }; | 2144 | }; |
| ... | @@ -2192,17 +2190,21 @@ fn resolveInstConst( | ... | @@ -2192,17 +2190,21 @@ fn resolveInstConst( |
| 2192 | } | 2190 | } |
| 2193 | | 2191 | |
| 2194 | /// Value Tag may be `undef` or `variable`. | 2192 | /// Value Tag may be `undef` or `variable`. |
| 2195 | pub fn resolveConstValueAllowVariables( | 2193 | pub fn resolveFinalDeclValue( |
| 2196 | sema: *Sema, | 2194 | sema: *Sema, |
| 2197 | block: *Block, | 2195 | block: *Block, |
| 2198 | src: LazySrcLoc, | 2196 | src: LazySrcLoc, |
| 2199 | air_ref: Air.Inst.Ref, | 2197 | air_ref: Air.Inst.Ref, |
| 2200 | reason: NeededComptimeReason, | | |
| 2201 | ) CompileError!TypedValue { | 2198 | ) CompileError!TypedValue { |
| 2202 | const val = try sema.resolveValueAllowVariables(air_ref) orelse { | 2199 | const val = try sema.resolveValueAllowVariables(air_ref) orelse { |
| 2203 | return sema.failWithNeededComptime(block, src, reason); | 2200 | return sema.failWithNeededComptime(block, src, .{ |
| | 2201 | .needed_comptime_reason = "global variable initializer must be comptime-known", |
| | 2202 | }); |
| 2204 | }; | 2203 | }; |
| 2205 | if (val.isGenericPoison()) return error.GenericPoison; | 2204 | if (val.isGenericPoison()) return error.GenericPoison; |
| | 2205 | if (val.canMutateComptimeVarState(sema.mod)) { |
| | 2206 | return sema.fail(block, src, "global variable contains reference to comptime var", .{}); |
| | 2207 | } |
| 2206 | return .{ | 2208 | return .{ |
| 2207 | .ty = sema.typeOf(air_ref), | 2209 | .ty = sema.typeOf(air_ref), |
| 2208 | .val = val, | 2210 | .val = val, |
| ... | @@ -2671,7 +2673,7 @@ fn analyzeAsInt( | ... | @@ -2671,7 +2673,7 @@ fn analyzeAsInt( |
| 2671 | | 2673 | |
| 2672 | /// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`, | 2674 | /// Given a ZIR extra index which points to a list of `Zir.Inst.Capture`, |
| 2673 | /// resolves this into a list of `InternPool.CaptureValue` allocated by `arena`. | 2675 | /// resolves this into a list of `InternPool.CaptureValue` allocated by `arena`. |
| 2674 | fn getCaptures(sema: *Sema, block: *Block, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue { | 2676 | fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: usize, captures_len: u32) ![]InternPool.CaptureValue { |
| 2675 | const zcu = sema.mod; | 2677 | const zcu = sema.mod; |
| 2676 | const ip = &zcu.intern_pool; | 2678 | const ip = &zcu.intern_pool; |
| 2677 | const parent_captures: InternPool.CaptureValue.Slice = zcu.namespacePtr(block.namespace).getType(zcu).getCaptures(zcu); | 2679 | const parent_captures: InternPool.CaptureValue.Slice = zcu.namespacePtr(block.namespace).getType(zcu).getCaptures(zcu); |
| ... | @@ -2682,9 +2684,29 @@ fn getCaptures(sema: *Sema, block: *Block, extra_index: usize, captures_len: u32 | ... | @@ -2682,9 +2684,29 @@ fn getCaptures(sema: *Sema, block: *Block, extra_index: usize, captures_len: u32 |
| 2682 | const zir_capture: Zir.Inst.Capture = @bitCast(raw); | 2684 | const zir_capture: Zir.Inst.Capture = @bitCast(raw); |
| 2683 | capture.* = switch (zir_capture.unwrap()) { | 2685 | capture.* = switch (zir_capture.unwrap()) { |
| 2684 | .nested => |parent_idx| parent_captures.get(ip)[parent_idx], | 2686 | .nested => |parent_idx| parent_captures.get(ip)[parent_idx], |
| | 2687 | .instruction_load => |ptr_inst| InternPool.CaptureValue.wrap(capture: { |
| | 2688 | const ptr_ref = try sema.resolveInst(ptr_inst.toRef()); |
| | 2689 | const ptr_val = try sema.resolveValue(ptr_ref) orelse { |
| | 2690 | break :capture .{ .runtime = sema.typeOf(ptr_ref).childType(zcu).toIntern() }; |
| | 2691 | }; |
| | 2692 | // TODO: better source location |
| | 2693 | const unresolved_loaded_val = try sema.pointerDeref(block, type_src, ptr_val, sema.typeOf(ptr_ref)) orelse { |
| | 2694 | break :capture .{ .runtime = sema.typeOf(ptr_ref).childType(zcu).toIntern() }; |
| | 2695 | }; |
| | 2696 | const loaded_val = try sema.resolveLazyValue(unresolved_loaded_val); |
| | 2697 | if (loaded_val.canMutateComptimeVarState(zcu)) { |
| | 2698 | // TODO: source location of captured value |
| | 2699 | return sema.fail(block, type_src, "type capture contains reference to comptime var", .{}); |
| | 2700 | } |
| | 2701 | break :capture .{ .@"comptime" = loaded_val.toIntern() }; |
| | 2702 | }), |
| 2685 | .instruction => |inst| InternPool.CaptureValue.wrap(capture: { | 2703 | .instruction => |inst| InternPool.CaptureValue.wrap(capture: { |
| 2686 | const air_ref = try sema.resolveInst(inst.toRef()); | 2704 | const air_ref = try sema.resolveInst(inst.toRef()); |
| 2687 | if (try sema.resolveValueResolveLazy(air_ref)) |val| { | 2705 | if (try sema.resolveValueResolveLazy(air_ref)) |val| { |
| | 2706 | if (val.canMutateComptimeVarState(zcu)) { |
| | 2707 | // TODO: source location of captured value |
| | 2708 | return sema.fail(block, type_src, "type capture contains reference to comptime var", .{}); |
| | 2709 | } |
| 2688 | break :capture .{ .@"comptime" = val.toIntern() }; | 2710 | break :capture .{ .@"comptime" = val.toIntern() }; |
| 2689 | } | 2711 | } |
| 2690 | break :capture .{ .runtime = sema.typeOf(air_ref).toIntern() }; | 2712 | break :capture .{ .runtime = sema.typeOf(air_ref).toIntern() }; |
| ... | @@ -2766,7 +2788,7 @@ fn zirStructDecl( | ... | @@ -2766,7 +2788,7 @@ fn zirStructDecl( |
| 2766 | break :blk decls_len; | 2788 | break :blk decls_len; |
| 2767 | } else 0; | 2789 | } else 0; |
| 2768 | | 2790 | |
| 2769 | const captures = try sema.getCaptures(block, extra_index, captures_len); | 2791 | const captures = try sema.getCaptures(block, src, extra_index, captures_len); |
| 2770 | extra_index += captures_len; | 2792 | extra_index += captures_len; |
| 2771 | | 2793 | |
| 2772 | if (small.has_backing_int) { | 2794 | if (small.has_backing_int) { |
| ... | @@ -2981,7 +3003,7 @@ fn zirEnumDecl( | ... | @@ -2981,7 +3003,7 @@ fn zirEnumDecl( |
| 2981 | break :blk decls_len; | 3003 | break :blk decls_len; |
| 2982 | } else 0; | 3004 | } else 0; |
| 2983 | | 3005 | |
| 2984 | const captures = try sema.getCaptures(block, extra_index, captures_len); | 3006 | const captures = try sema.getCaptures(block, src, extra_index, captures_len); |
| 2985 | extra_index += captures_len; | 3007 | extra_index += captures_len; |
| 2986 | | 3008 | |
| 2987 | const decls = sema.code.bodySlice(extra_index, decls_len); | 3009 | const decls = sema.code.bodySlice(extra_index, decls_len); |
| ... | @@ -3254,7 +3276,7 @@ fn zirUnionDecl( | ... | @@ -3254,7 +3276,7 @@ fn zirUnionDecl( |
| 3254 | break :blk decls_len; | 3276 | break :blk decls_len; |
| 3255 | } else 0; | 3277 | } else 0; |
| 3256 | | 3278 | |
| 3257 | const captures = try sema.getCaptures(block, extra_index, captures_len); | 3279 | const captures = try sema.getCaptures(block, src, extra_index, captures_len); |
| 3258 | extra_index += captures_len; | 3280 | extra_index += captures_len; |
| 3259 | | 3281 | |
| 3260 | const union_init: InternPool.UnionTypeInit = .{ | 3282 | const union_init: InternPool.UnionTypeInit = .{ |
| ... | @@ -3358,7 +3380,7 @@ fn zirOpaqueDecl( | ... | @@ -3358,7 +3380,7 @@ fn zirOpaqueDecl( |
| 3358 | break :blk decls_len; | 3380 | break :blk decls_len; |
| 3359 | } else 0; | 3381 | } else 0; |
| 3360 | | 3382 | |
| 3361 | const captures = try sema.getCaptures(block, extra_index, captures_len); | 3383 | const captures = try sema.getCaptures(block, src, extra_index, captures_len); |
| 3362 | extra_index += captures_len; | 3384 | extra_index += captures_len; |
| 3363 | | 3385 | |
| 3364 | const opaque_init: InternPool.OpaqueTypeInit = .{ | 3386 | const opaque_init: InternPool.OpaqueTypeInit = .{ |
| ... | @@ -3653,9 +3675,9 @@ fn zirAllocExtended( | ... | @@ -3653,9 +3675,9 @@ fn zirAllocExtended( |
| 3653 | try sema.air_instructions.append(gpa, .{ | 3675 | try sema.air_instructions.append(gpa, .{ |
| 3654 | .tag = .inferred_alloc_comptime, | 3676 | .tag = .inferred_alloc_comptime, |
| 3655 | .data = .{ .inferred_alloc_comptime = .{ | 3677 | .data = .{ .inferred_alloc_comptime = .{ |
| 3656 | .decl_index = undefined, | | |
| 3657 | .alignment = alignment, | 3678 | .alignment = alignment, |
| 3658 | .is_const = small.is_const, | 3679 | .is_const = small.is_const, |
| | 3680 | .ptr = undefined, |
| 3659 | } }, | 3681 | } }, |
| 3660 | }); | 3682 | }); |
| 3661 | return @as(Air.Inst.Index, @enumFromInt(sema.air_instructions.len - 1)).toRef(); | 3683 | return @as(Air.Inst.Index, @enumFromInt(sema.air_instructions.len - 1)).toRef(); |
| ... | @@ -3717,36 +3739,51 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro | ... | @@ -3717,36 +3739,51 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 3717 | const ptr_info = alloc_ty.ptrInfo(mod); | 3739 | const ptr_info = alloc_ty.ptrInfo(mod); |
| 3718 | const elem_ty = Type.fromInterned(ptr_info.child); | 3740 | const elem_ty = Type.fromInterned(ptr_info.child); |
| 3719 | | 3741 | |
| 3720 | if (try sema.resolveComptimeKnownAllocValue(block, alloc, null)) |val| { | 3742 | // If the alloc was created in a comptime scope, we already created a comptime alloc for it. |
| 3721 | const new_mut_ptr = Air.internedToRef((try mod.intern(.{ .ptr = .{ | 3743 | // However, if the final constructed value does not reference comptime-mutable memory, we wish |
| 3722 | .ty = alloc_ty.toIntern(), | 3744 | // to promote it to an anon decl. |
| 3723 | .addr = .{ .anon_decl = .{ | 3745 | already_ct: { |
| 3724 | .val = val, | 3746 | const ptr_val = try sema.resolveValue(alloc) orelse break :already_ct; |
| 3725 | .orig_ty = alloc_ty.toIntern(), | 3747 | |
| 3726 | } }, | 3748 | // If this was a comptime inferred alloc, then `storeToInferredAllocComptime` |
| 3727 | } }))); | 3749 | // might have already done our job and created an anon decl ref. |
| 3728 | return sema.makePtrConst(block, new_mut_ptr); | 3750 | switch (mod.intern_pool.indexToKey(ptr_val.toIntern())) { |
| 3729 | } | 3751 | .ptr => |ptr| switch (ptr.addr) { |
| 3730 | | 3752 | .anon_decl => { |
| 3731 | // If this is already a comptime-known allocation, we don't want to emit an error - the stores | 3753 | // The comptime-ification was already done for us. |
| 3732 | // were already performed at comptime! Just make the pointer constant as normal. | 3754 | // Just make sure the pointer is const. |
| 3733 | implicit_ct: { | 3755 | return sema.makePtrConst(block, alloc); |
| 3734 | const ptr_val = try sema.resolveValue(alloc) orelse break :implicit_ct; | | |
| 3735 | if (!ptr_val.isComptimeMutablePtr(mod)) { | | |
| 3736 | // It could still be a constant pointer to a decl. | | |
| 3737 | switch (mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr) { | | |
| 3738 | .anon_decl => |anon_decl| { | | |
| 3739 | if (mod.intern_pool.isVariable(anon_decl.val)) | | |
| 3740 | break :implicit_ct; | | |
| 3741 | }, | | |
| 3742 | else => { | | |
| 3743 | const decl_index = ptr_val.pointerDecl(mod) orelse break :implicit_ct; | | |
| 3744 | const decl_val = mod.declPtr(decl_index).val.toIntern(); | | |
| 3745 | if (mod.intern_pool.isVariable(decl_val)) break :implicit_ct; | | |
| 3746 | }, | 3756 | }, |
| 3747 | } | 3757 | else => {}, |
| | 3758 | }, |
| | 3759 | else => {}, |
| 3748 | } | 3760 | } |
| 3749 | return sema.makePtrConst(block, alloc); | 3761 | |
| | 3762 | if (!sema.isComptimeMutablePtr(ptr_val)) break :already_ct; |
| | 3763 | const alloc_index = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr.comptime_alloc; |
| | 3764 | const ct_alloc = sema.getComptimeAlloc(alloc_index); |
| | 3765 | const interned = try ct_alloc.val.intern(ct_alloc.ty, mod); |
| | 3766 | if (Value.fromInterned(interned).canMutateComptimeVarState(mod)) { |
| | 3767 | // Preserve the comptime alloc, just make the pointer const. |
| | 3768 | ct_alloc.val = Value.fromInterned(interned); |
| | 3769 | ct_alloc.is_const = true; |
| | 3770 | return sema.makePtrConst(block, alloc); |
| | 3771 | } else { |
| | 3772 | // Promote the constant to an anon decl. |
| | 3773 | const new_mut_ptr = Air.internedToRef(try mod.intern(.{ .ptr = .{ |
| | 3774 | .ty = alloc_ty.toIntern(), |
| | 3775 | .addr = .{ .anon_decl = .{ |
| | 3776 | .val = interned, |
| | 3777 | .orig_ty = alloc_ty.toIntern(), |
| | 3778 | } }, |
| | 3779 | } })); |
| | 3780 | return sema.makePtrConst(block, new_mut_ptr); |
| | 3781 | } |
| | 3782 | } |
| | 3783 | |
| | 3784 | // Otherwise, check if the alloc is comptime-known despite being in a runtime scope. |
| | 3785 | if (try sema.resolveComptimeKnownAllocPtr(block, alloc, null)) |ptr_val| { |
| | 3786 | return sema.makePtrConst(block, Air.internedToRef(ptr_val)); |
| 3750 | } | 3787 | } |
| 3751 | | 3788 | |
| 3752 | if (try sema.typeRequiresComptime(elem_ty)) { | 3789 | if (try sema.typeRequiresComptime(elem_ty)) { |
| ... | @@ -3762,7 +3799,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro | ... | @@ -3762,7 +3799,7 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 3762 | | 3799 | |
| 3763 | /// If `alloc` is an inferred allocation, `resolved_inferred_ty` is taken to be its resolved | 3800 | /// If `alloc` is an inferred allocation, `resolved_inferred_ty` is taken to be its resolved |
| 3764 | /// type. Otherwise, it may be `null`, and the type will be inferred from `alloc`. | 3801 | /// type. Otherwise, it may be `null`, and the type will be inferred from `alloc`. |
| 3765 | fn resolveComptimeKnownAllocValue(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, resolved_alloc_ty: ?Type) CompileError!?InternPool.Index { | 3802 | fn resolveComptimeKnownAllocPtr(sema: *Sema, block: *Block, alloc: Air.Inst.Ref, resolved_alloc_ty: ?Type) CompileError!?InternPool.Index { |
| 3766 | const mod = sema.mod; | 3803 | const mod = sema.mod; |
| 3767 | | 3804 | |
| 3768 | const alloc_ty = resolved_alloc_ty orelse sema.typeOf(alloc); | 3805 | const alloc_ty = resolved_alloc_ty orelse sema.typeOf(alloc); |
| ... | @@ -3771,7 +3808,7 @@ fn resolveComptimeKnownAllocValue(sema: *Sema, block: *Block, alloc: Air.Inst.Re | ... | @@ -3771,7 +3808,7 @@ fn resolveComptimeKnownAllocValue(sema: *Sema, block: *Block, alloc: Air.Inst.Re |
| 3771 | | 3808 | |
| 3772 | const alloc_inst = alloc.toIndex() orelse return null; | 3809 | const alloc_inst = alloc.toIndex() orelse return null; |
| 3773 | const comptime_info = sema.maybe_comptime_allocs.fetchRemove(alloc_inst) orelse return null; | 3810 | const comptime_info = sema.maybe_comptime_allocs.fetchRemove(alloc_inst) orelse return null; |
| 3774 | const stores = comptime_info.value.stores.items; | 3811 | const stores = comptime_info.value.stores.items(.inst); |
| 3775 | | 3812 | |
| 3776 | // Since the entry existed in `maybe_comptime_allocs`, the allocation is comptime-known. | 3813 | // Since the entry existed in `maybe_comptime_allocs`, the allocation is comptime-known. |
| 3777 | // We will resolve and return its value. | 3814 | // We will resolve and return its value. |
| ... | @@ -3779,7 +3816,7 @@ fn resolveComptimeKnownAllocValue(sema: *Sema, block: *Block, alloc: Air.Inst.Re | ... | @@ -3779,7 +3816,7 @@ fn resolveComptimeKnownAllocValue(sema: *Sema, block: *Block, alloc: Air.Inst.Re |
| 3779 | // We expect to have emitted at least one store, unless the elem type is OPV. | 3816 | // We expect to have emitted at least one store, unless the elem type is OPV. |
| 3780 | if (stores.len == 0) { | 3817 | if (stores.len == 0) { |
| 3781 | const val = (try sema.typeHasOnePossibleValue(elem_ty)).?.toIntern(); | 3818 | const val = (try sema.typeHasOnePossibleValue(elem_ty)).?.toIntern(); |
| 3782 | return sema.finishResolveComptimeKnownAllocValue(val, alloc_inst, comptime_info.value); | 3819 | return sema.finishResolveComptimeKnownAllocPtr(block, alloc_ty, val, null, alloc_inst, comptime_info.value); |
| 3783 | } | 3820 | } |
| 3784 | | 3821 | |
| 3785 | // In general, we want to create a comptime alloc of the correct type and | 3822 | // In general, we want to create a comptime alloc of the correct type and |
| ... | @@ -3794,28 +3831,23 @@ fn resolveComptimeKnownAllocValue(sema: *Sema, block: *Block, alloc: Air.Inst.Re | ... | @@ -3794,28 +3831,23 @@ fn resolveComptimeKnownAllocValue(sema: *Sema, block: *Block, alloc: Air.Inst.Re |
| 3794 | | 3831 | |
| 3795 | const val = store_data.rhs.toInterned().?; | 3832 | const val = store_data.rhs.toInterned().?; |
| 3796 | assert(mod.intern_pool.typeOf(val) == elem_ty.toIntern()); | 3833 | assert(mod.intern_pool.typeOf(val) == elem_ty.toIntern()); |
| 3797 | return sema.finishResolveComptimeKnownAllocValue(val, alloc_inst, comptime_info.value); | 3834 | return sema.finishResolveComptimeKnownAllocPtr(block, alloc_ty, val, null, alloc_inst, comptime_info.value); |
| 3798 | } | 3835 | } |
| 3799 | | 3836 | |
| 3800 | // The simple strategy failed: we must create a mutable comptime alloc and | 3837 | // The simple strategy failed: we must create a mutable comptime alloc and |
| 3801 | // perform all of the runtime store operations at comptime. | 3838 | // perform all of the runtime store operations at comptime. |
| 3802 | | 3839 | |
| 3803 | var anon_decl = try block.startAnonDecl(); // TODO: comptime value mutation without Decl | 3840 | const ct_alloc = try sema.newComptimeAlloc(block, elem_ty, ptr_info.flags.alignment); |
| 3804 | defer anon_decl.deinit(); | | |
| 3805 | const decl_index = try anon_decl.finish(elem_ty, try mod.undefValue(elem_ty), ptr_info.flags.alignment); | | |
| 3806 | | 3841 | |
| 3807 | const decl_ptr = try mod.intern(.{ .ptr = .{ | 3842 | const alloc_ptr = try mod.intern(.{ .ptr = .{ |
| 3808 | .ty = alloc_ty.toIntern(), | 3843 | .ty = alloc_ty.toIntern(), |
| 3809 | .addr = .{ .mut_decl = .{ | 3844 | .addr = .{ .comptime_alloc = ct_alloc }, |
| 3810 | .decl = decl_index, | | |
| 3811 | .runtime_index = block.runtime_index, | | |
| 3812 | } }, | | |
| 3813 | } }); | 3845 | } }); |
| 3814 | | 3846 | |
| 3815 | // Maps from pointers into the runtime allocs, to comptime-mutable pointers into the mut decl. | 3847 | // Maps from pointers into the runtime allocs, to comptime-mutable pointers into the comptime alloc |
| 3816 | var ptr_mapping = std.AutoHashMap(Air.Inst.Index, InternPool.Index).init(sema.arena); | 3848 | var ptr_mapping = std.AutoHashMap(Air.Inst.Index, InternPool.Index).init(sema.arena); |
| 3817 | try ptr_mapping.ensureTotalCapacity(@intCast(stores.len)); | 3849 | try ptr_mapping.ensureTotalCapacity(@intCast(stores.len)); |
| 3818 | ptr_mapping.putAssumeCapacity(alloc_inst, decl_ptr); | 3850 | ptr_mapping.putAssumeCapacity(alloc_inst, alloc_ptr); |
| 3819 | | 3851 | |
| 3820 | var to_map = try std.ArrayList(Air.Inst.Index).initCapacity(sema.arena, stores.len); | 3852 | var to_map = try std.ArrayList(Air.Inst.Index).initCapacity(sema.arena, stores.len); |
| 3821 | for (stores) |store_inst| { | 3853 | for (stores) |store_inst| { |
| ... | @@ -3953,14 +3985,27 @@ fn resolveComptimeKnownAllocValue(sema: *Sema, block: *Block, alloc: Air.Inst.Re | ... | @@ -3953,14 +3985,27 @@ fn resolveComptimeKnownAllocValue(sema: *Sema, block: *Block, alloc: Air.Inst.Re |
| 3953 | } | 3985 | } |
| 3954 | | 3986 | |
| 3955 | // The value is finalized - load it! | 3987 | // The value is finalized - load it! |
| 3956 | const val = (try sema.pointerDeref(block, .unneeded, Value.fromInterned(decl_ptr), alloc_ty)).?.toIntern(); | 3988 | const val = (try sema.pointerDeref(block, .unneeded, Value.fromInterned(alloc_ptr), alloc_ty)).?.toIntern(); |
| 3957 | return sema.finishResolveComptimeKnownAllocValue(val, alloc_inst, comptime_info.value); | 3989 | return sema.finishResolveComptimeKnownAllocPtr(block, alloc_ty, val, ct_alloc, alloc_inst, comptime_info.value); |
| 3958 | } | 3990 | } |
| 3959 | | 3991 | |
| 3960 | /// Given the resolved comptime-known value, rewrites the dead AIR to not | 3992 | /// Given the resolved comptime-known value, rewrites the dead AIR to not |
| 3961 | /// create a runtime stack allocation. | 3993 | /// create a runtime stack allocation. Also places the resulting value into |
| 3962 | /// Same return type as `resolveComptimeKnownAllocValue` so we can tail call. | 3994 | /// either an anon decl ref or a comptime alloc depending on whether it |
| 3963 | fn finishResolveComptimeKnownAllocValue(sema: *Sema, result_val: InternPool.Index, alloc_inst: Air.Inst.Index, comptime_info: MaybeComptimeAlloc) CompileError!?InternPool.Index { | 3995 | /// references comptime-mutable memory. If `existing_comptime_alloc` is |
| | 3996 | /// passed, it is a scratch allocation which already contains `result_val`. |
| | 3997 | /// Same return type as `resolveComptimeKnownAllocPtr` so we can tail call. |
| | 3998 | fn finishResolveComptimeKnownAllocPtr( |
| | 3999 | sema: *Sema, |
| | 4000 | block: *Block, |
| | 4001 | alloc_ty: Type, |
| | 4002 | result_val: InternPool.Index, |
| | 4003 | existing_comptime_alloc: ?ComptimeAllocIndex, |
| | 4004 | alloc_inst: Air.Inst.Index, |
| | 4005 | comptime_info: MaybeComptimeAlloc, |
| | 4006 | ) CompileError!?InternPool.Index { |
| | 4007 | const zcu = sema.mod; |
| | 4008 | |
| 3964 | // We're almost done - we have the resolved comptime value. We just need to | 4009 | // We're almost done - we have the resolved comptime value. We just need to |
| 3965 | // eliminate the now-dead runtime instructions. | 4010 | // eliminate the now-dead runtime instructions. |
| 3966 | | 4011 | |
| ... | @@ -3974,14 +4019,34 @@ fn finishResolveComptimeKnownAllocValue(sema: *Sema, result_val: InternPool.Inde | ... | @@ -3974,14 +4019,34 @@ fn finishResolveComptimeKnownAllocValue(sema: *Sema, result_val: InternPool.Inde |
| 3974 | const nop_inst: Air.Inst = .{ .tag = .bitcast, .data = .{ .ty_op = .{ .ty = .u8_type, .operand = .zero_u8 } } }; | 4019 | const nop_inst: Air.Inst = .{ .tag = .bitcast, .data = .{ .ty_op = .{ .ty = .u8_type, .operand = .zero_u8 } } }; |
| 3975 | | 4020 | |
| 3976 | sema.air_instructions.set(@intFromEnum(alloc_inst), nop_inst); | 4021 | sema.air_instructions.set(@intFromEnum(alloc_inst), nop_inst); |
| 3977 | for (comptime_info.stores.items) |store_inst| { | 4022 | for (comptime_info.stores.items(.inst)) |store_inst| { |
| 3978 | sema.air_instructions.set(@intFromEnum(store_inst), nop_inst); | 4023 | sema.air_instructions.set(@intFromEnum(store_inst), nop_inst); |
| 3979 | } | 4024 | } |
| 3980 | for (comptime_info.non_elideable_pointers.items) |ptr_inst| { | 4025 | for (comptime_info.non_elideable_pointers.items) |ptr_inst| { |
| 3981 | sema.air_instructions.set(@intFromEnum(ptr_inst), nop_inst); | 4026 | sema.air_instructions.set(@intFromEnum(ptr_inst), nop_inst); |
| 3982 | } | 4027 | } |
| 3983 | | 4028 | |
| 3984 | return result_val; | 4029 | if (Value.fromInterned(result_val).canMutateComptimeVarState(zcu)) { |
| | 4030 | const alloc_index = existing_comptime_alloc orelse a: { |
| | 4031 | const idx = try sema.newComptimeAlloc(block, alloc_ty.childType(zcu), alloc_ty.ptrAlignment(zcu)); |
| | 4032 | const alloc = sema.getComptimeAlloc(idx); |
| | 4033 | alloc.val = Value.fromInterned(result_val); |
| | 4034 | break :a idx; |
| | 4035 | }; |
| | 4036 | sema.getComptimeAlloc(alloc_index).is_const = true; |
| | 4037 | return try zcu.intern(.{ .ptr = .{ |
| | 4038 | .ty = alloc_ty.toIntern(), |
| | 4039 | .addr = .{ .comptime_alloc = alloc_index }, |
| | 4040 | } }); |
| | 4041 | } else { |
| | 4042 | return try zcu.intern(.{ .ptr = .{ |
| | 4043 | .ty = alloc_ty.toIntern(), |
| | 4044 | .addr = .{ .anon_decl = .{ |
| | 4045 | .orig_ty = alloc_ty.toIntern(), |
| | 4046 | .val = result_val, |
| | 4047 | } }, |
| | 4048 | } }); |
| | 4049 | } |
| 3985 | } | 4050 | } |
| 3986 | | 4051 | |
| 3987 | fn makePtrTyConst(sema: *Sema, ptr_ty: Type) CompileError!Type { | 4052 | fn makePtrTyConst(sema: *Sema, ptr_ty: Type) CompileError!Type { |
| ... | @@ -4011,9 +4076,9 @@ fn zirAllocInferredComptime( | ... | @@ -4011,9 +4076,9 @@ fn zirAllocInferredComptime( |
| 4011 | try sema.air_instructions.append(gpa, .{ | 4076 | try sema.air_instructions.append(gpa, .{ |
| 4012 | .tag = .inferred_alloc_comptime, | 4077 | .tag = .inferred_alloc_comptime, |
| 4013 | .data = .{ .inferred_alloc_comptime = .{ | 4078 | .data = .{ .inferred_alloc_comptime = .{ |
| 4014 | .decl_index = undefined, | | |
| 4015 | .alignment = .none, | 4079 | .alignment = .none, |
| 4016 | .is_const = is_const, | 4080 | .is_const = is_const, |
| | 4081 | .ptr = undefined, |
| 4017 | } }, | 4082 | } }, |
| 4018 | }); | 4083 | }); |
| 4019 | return @as(Air.Inst.Index, @enumFromInt(sema.air_instructions.len - 1)).toRef(); | 4084 | return @as(Air.Inst.Index, @enumFromInt(sema.air_instructions.len - 1)).toRef(); |
| ... | @@ -4076,9 +4141,9 @@ fn zirAllocInferred( | ... | @@ -4076,9 +4141,9 @@ fn zirAllocInferred( |
| 4076 | try sema.air_instructions.append(gpa, .{ | 4141 | try sema.air_instructions.append(gpa, .{ |
| 4077 | .tag = .inferred_alloc_comptime, | 4142 | .tag = .inferred_alloc_comptime, |
| 4078 | .data = .{ .inferred_alloc_comptime = .{ | 4143 | .data = .{ .inferred_alloc_comptime = .{ |
| 4079 | .decl_index = undefined, | | |
| 4080 | .alignment = .none, | 4144 | .alignment = .none, |
| 4081 | .is_const = is_const, | 4145 | .is_const = is_const, |
| | 4146 | .ptr = undefined, |
| 4082 | } }, | 4147 | } }, |
| 4083 | }); | 4148 | }); |
| 4084 | return @as(Air.Inst.Index, @enumFromInt(sema.air_instructions.len - 1)).toRef(); | 4149 | return @as(Air.Inst.Index, @enumFromInt(sema.air_instructions.len - 1)).toRef(); |
| ... | @@ -4092,8 +4157,10 @@ fn zirAllocInferred( | ... | @@ -4092,8 +4157,10 @@ fn zirAllocInferred( |
| 4092 | } }, | 4157 | } }, |
| 4093 | }); | 4158 | }); |
| 4094 | try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, .{}); | 4159 | try sema.unresolved_inferred_allocs.putNoClobber(gpa, result_index, .{}); |
| 4095 | try sema.maybe_comptime_allocs.put(gpa, result_index, .{ .runtime_index = block.runtime_index }); | 4160 | if (is_const) { |
| 4096 | try sema.base_allocs.put(sema.gpa, result_index, result_index); | 4161 | try sema.maybe_comptime_allocs.put(gpa, result_index, .{ .runtime_index = block.runtime_index }); |
| | 4162 | try sema.base_allocs.put(sema.gpa, result_index, result_index); |
| | 4163 | } |
| 4097 | return result_index.toRef(); | 4164 | return result_index.toRef(); |
| 4098 | } | 4165 | } |
| 4099 | | 4166 | |
| ... | @@ -4112,38 +4179,33 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com | ... | @@ -4112,38 +4179,33 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 4112 | | 4179 | |
| 4113 | switch (sema.air_instructions.items(.tag)[@intFromEnum(ptr_inst)]) { | 4180 | switch (sema.air_instructions.items(.tag)[@intFromEnum(ptr_inst)]) { |
| 4114 | .inferred_alloc_comptime => { | 4181 | .inferred_alloc_comptime => { |
| | 4182 | // The work was already done for us by `Sema.storeToInferredAllocComptime`. |
| | 4183 | // All we need to do is remap the pointer. |
| 4115 | const iac = sema.air_instructions.items(.data)[@intFromEnum(ptr_inst)].inferred_alloc_comptime; | 4184 | const iac = sema.air_instructions.items(.data)[@intFromEnum(ptr_inst)].inferred_alloc_comptime; |
| 4116 | const decl_index = iac.decl_index; | 4185 | const resolved_ptr = iac.ptr; |
| 4117 | | | |
| 4118 | const decl = mod.declPtr(decl_index); | | |
| 4119 | if (iac.is_const) _ = try decl.internValue(mod); | | |
| 4120 | const final_elem_ty = decl.ty; | | |
| 4121 | const final_ptr_ty = try sema.ptrType(.{ | | |
| 4122 | .child = final_elem_ty.toIntern(), | | |
| 4123 | .flags = .{ | | |
| 4124 | .is_const = false, | | |
| 4125 | .alignment = iac.alignment, | | |
| 4126 | .address_space = target_util.defaultAddressSpace(target, .local), | | |
| 4127 | }, | | |
| 4128 | }); | | |
| 4129 | | 4186 | |
| 4130 | if (std.debug.runtime_safety) { | 4187 | if (std.debug.runtime_safety) { |
| 4131 | // The inferred_alloc_comptime should never be referenced again | 4188 | // The inferred_alloc_comptime should never be referenced again |
| 4132 | sema.air_instructions.set(@intFromEnum(ptr_inst), .{ .tag = undefined, .data = undefined }); | 4189 | sema.air_instructions.set(@intFromEnum(ptr_inst), .{ .tag = undefined, .data = undefined }); |
| 4133 | } | 4190 | } |
| 4134 | | 4191 | |
| 4135 | try sema.maybeQueueFuncBodyAnalysis(decl_index); | 4192 | const val = switch (mod.intern_pool.indexToKey(resolved_ptr).ptr.addr) { |
| 4136 | | 4193 | .anon_decl => |a| a.val, |
| 4137 | const interned = try mod.intern(.{ .ptr = .{ | 4194 | .comptime_alloc => |i| val: { |
| 4138 | .ty = final_ptr_ty.toIntern(), | 4195 | const alloc = sema.getComptimeAlloc(i); |
| 4139 | .addr = if (!iac.is_const) .{ .mut_decl = .{ | 4196 | break :val try alloc.val.intern(alloc.ty, mod); |
| 4140 | .decl = decl_index, | 4197 | }, |
| 4141 | .runtime_index = block.runtime_index, | 4198 | else => unreachable, |
| 4142 | } } else .{ .decl = decl_index }, | 4199 | }; |
| 4143 | } }); | 4200 | if (mod.intern_pool.isFuncBody(val)) { |
| | 4201 | const ty = Type.fromInterned(mod.intern_pool.typeOf(val)); |
| | 4202 | if (try sema.fnHasRuntimeBits(ty)) { |
| | 4203 | try mod.ensureFuncBodyAnalysisQueued(val); |
| | 4204 | } |
| | 4205 | } |
| 4144 | | 4206 | |
| 4145 | // Remap the ZIR operand to the resolved pointer value | 4207 | // Remap the ZIR operand to the resolved pointer value |
| 4146 | sema.inst_map.putAssumeCapacity(inst_data.operand.toIndex().?, Air.internedToRef(interned)); | 4208 | sema.inst_map.putAssumeCapacity(inst_data.operand.toIndex().?, Air.internedToRef(resolved_ptr)); |
| 4147 | }, | 4209 | }, |
| 4148 | .inferred_alloc => { | 4210 | .inferred_alloc => { |
| 4149 | const ia1 = sema.air_instructions.items(.data)[@intFromEnum(ptr_inst)].inferred_alloc; | 4211 | const ia1 = sema.air_instructions.items(.data)[@intFromEnum(ptr_inst)].inferred_alloc; |
| ... | @@ -4166,18 +4228,12 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com | ... | @@ -4166,18 +4228,12 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 4166 | | 4228 | |
| 4167 | if (!ia1.is_const) { | 4229 | if (!ia1.is_const) { |
| 4168 | try sema.validateVarType(block, ty_src, final_elem_ty, false); | 4230 | try sema.validateVarType(block, ty_src, final_elem_ty, false); |
| 4169 | } else if (try sema.resolveComptimeKnownAllocValue(block, ptr, final_ptr_ty)) |val| { | 4231 | } else if (try sema.resolveComptimeKnownAllocPtr(block, ptr, final_ptr_ty)) |ptr_val| { |
| 4170 | const const_ptr_ty = (try sema.makePtrTyConst(final_ptr_ty)).toIntern(); | 4232 | const const_ptr_ty = try sema.makePtrTyConst(final_ptr_ty); |
| 4171 | const new_const_ptr = try mod.intern(.{ .ptr = .{ | 4233 | const new_const_ptr = try mod.getCoerced(Value.fromInterned(ptr_val), const_ptr_ty); |
| 4172 | .ty = const_ptr_ty, | | |
| 4173 | .addr = .{ .anon_decl = .{ | | |
| 4174 | .val = val, | | |
| 4175 | .orig_ty = const_ptr_ty, | | |
| 4176 | } }, | | |
| 4177 | } }); | | |
| 4178 | | 4234 | |
| 4179 | // Remap the ZIR oeprand to the resolved pointer value | 4235 | // Remap the ZIR oeprand to the resolved pointer value |
| 4180 | sema.inst_map.putAssumeCapacity(inst_data.operand.toIndex().?, Air.internedToRef(new_const_ptr)); | 4236 | sema.inst_map.putAssumeCapacity(inst_data.operand.toIndex().?, Air.internedToRef(new_const_ptr.toIntern())); |
| 4181 | | 4237 | |
| 4182 | // Unless the block is comptime, `alloc_inferred` always produces | 4238 | // Unless the block is comptime, `alloc_inferred` always produces |
| 4183 | // a runtime constant. The final inferred type needs to be | 4239 | // a runtime constant. The final inferred type needs to be |
| ... | @@ -4387,7 +4443,7 @@ fn optEuBasePtrInit(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, src: LazySrcL | ... | @@ -4387,7 +4443,7 @@ fn optEuBasePtrInit(sema: *Sema, block: *Block, ptr: Air.Inst.Ref, src: LazySrcL |
| 4387 | .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true), | 4443 | .Optional => base_ptr = try sema.analyzeOptionalPayloadPtr(block, src, base_ptr, false, true), |
| 4388 | else => break, | 4444 | else => break, |
| 4389 | }; | 4445 | }; |
| 4390 | try sema.checkKnownAllocPtr(ptr, base_ptr); | 4446 | try sema.checkKnownAllocPtr(block, ptr, base_ptr); |
| 4391 | return base_ptr; | 4447 | return base_ptr; |
| 4392 | } | 4448 | } |
| 4393 | | 4449 | |
| ... | @@ -4703,6 +4759,7 @@ fn validateUnionInit( | ... | @@ -4703,6 +4759,7 @@ fn validateUnionInit( |
| 4703 | var first_block_index = block.instructions.items.len; | 4759 | var first_block_index = block.instructions.items.len; |
| 4704 | var block_index = block.instructions.items.len - 1; | 4760 | var block_index = block.instructions.items.len - 1; |
| 4705 | var init_val: ?Value = null; | 4761 | var init_val: ?Value = null; |
| | 4762 | var init_ref: ?Air.Inst.Ref = null; |
| 4706 | while (block_index > 0) : (block_index -= 1) { | 4763 | while (block_index > 0) : (block_index -= 1) { |
| 4707 | const store_inst = block.instructions.items[block_index]; | 4764 | const store_inst = block.instructions.items[block_index]; |
| 4708 | if (store_inst.toRef() == field_ptr_ref) { | 4765 | if (store_inst.toRef() == field_ptr_ref) { |
| ... | @@ -4727,6 +4784,7 @@ fn validateUnionInit( | ... | @@ -4727,6 +4784,7 @@ fn validateUnionInit( |
| 4727 | ).? | 4784 | ).? |
| 4728 | else | 4785 | else |
| 4729 | block_index, first_block_index); | 4786 | block_index, first_block_index); |
| | 4787 | init_ref = bin_op.rhs; |
| 4730 | init_val = try sema.resolveValue(bin_op.rhs); | 4788 | init_val = try sema.resolveValue(bin_op.rhs); |
| 4731 | break; | 4789 | break; |
| 4732 | } | 4790 | } |
| ... | @@ -4779,10 +4837,11 @@ fn validateUnionInit( | ... | @@ -4779,10 +4837,11 @@ fn validateUnionInit( |
| 4779 | .needed_comptime_reason = "initializer of comptime only union must be comptime-known", | 4837 | .needed_comptime_reason = "initializer of comptime only union must be comptime-known", |
| 4780 | }); | 4838 | }); |
| 4781 | } | 4839 | } |
| | 4840 | if (init_ref) |v| try sema.validateRuntimeValue(block, field_ptr_data.src(), v); |
| 4782 | | 4841 | |
| 4783 | const new_tag = Air.internedToRef(tag_val.toIntern()); | 4842 | const new_tag = Air.internedToRef(tag_val.toIntern()); |
| 4784 | const set_tag_inst = try block.addBinOp(.set_union_tag, union_ptr, new_tag); | 4843 | const set_tag_inst = try block.addBinOp(.set_union_tag, union_ptr, new_tag); |
| 4785 | try sema.checkComptimeKnownStore(block, set_tag_inst); | 4844 | try sema.checkComptimeKnownStore(block, set_tag_inst, init_src); |
| 4786 | } | 4845 | } |
| 4787 | | 4846 | |
| 4788 | fn validateStructInit( | 4847 | fn validateStructInit( |
| ... | @@ -4887,6 +4946,8 @@ fn validateStructInit( | ... | @@ -4887,6 +4946,8 @@ fn validateStructInit( |
| 4887 | return; | 4946 | return; |
| 4888 | } | 4947 | } |
| 4889 | | 4948 | |
| | 4949 | var fields_allow_runtime = true; |
| | 4950 | |
| 4890 | var struct_is_comptime = true; | 4951 | var struct_is_comptime = true; |
| 4891 | var first_block_index = block.instructions.items.len; | 4952 | var first_block_index = block.instructions.items.len; |
| 4892 | | 4953 | |
| ... | @@ -4957,6 +5018,7 @@ fn validateStructInit( | ... | @@ -4957,6 +5018,7 @@ fn validateStructInit( |
| 4957 | ).? | 5018 | ).? |
| 4958 | else | 5019 | else |
| 4959 | block_index, first_block_index); | 5020 | block_index, first_block_index); |
| | 5021 | if (!sema.checkRuntimeValue(bin_op.rhs)) fields_allow_runtime = false; |
| 4960 | if (try sema.resolveValue(bin_op.rhs)) |val| { | 5022 | if (try sema.resolveValue(bin_op.rhs)) |val| { |
| 4961 | field_values[i] = val.toIntern(); | 5023 | field_values[i] = val.toIntern(); |
| 4962 | } else if (require_comptime) { | 5024 | } else if (require_comptime) { |
| ... | @@ -4996,6 +5058,11 @@ fn validateStructInit( | ... | @@ -4996,6 +5058,11 @@ fn validateStructInit( |
| 4996 | field_values[i] = default_val.toIntern(); | 5058 | field_values[i] = default_val.toIntern(); |
| 4997 | } | 5059 | } |
| 4998 | | 5060 | |
| | 5061 | if (!struct_is_comptime and !fields_allow_runtime and root_msg == null) { |
| | 5062 | root_msg = try sema.errMsg(block, init_src, "runtime value contains reference to comptime var", .{}); |
| | 5063 | try sema.errNote(block, init_src, root_msg.?, "comptime var pointers are not available at runtime", .{}); |
| | 5064 | } |
| | 5065 | |
| 4999 | if (root_msg) |msg| { | 5066 | if (root_msg) |msg| { |
| 5000 | if (mod.typeToStruct(struct_ty)) |struct_type| { | 5067 | if (mod.typeToStruct(struct_ty)) |struct_type| { |
| 5001 | const decl = mod.declPtr(struct_type.decl.unwrap().?); | 5068 | const decl = mod.declPtr(struct_type.decl.unwrap().?); |
| ... | @@ -5067,7 +5134,7 @@ fn validateStructInit( | ... | @@ -5067,7 +5134,7 @@ fn validateStructInit( |
| 5067 | try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(i), true) | 5134 | try sema.tupleFieldPtr(block, init_src, struct_ptr, field_src, @intCast(i), true) |
| 5068 | else | 5135 | else |
| 5069 | try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(i), field_src, struct_ty, true); | 5136 | try sema.structFieldPtrByIndex(block, init_src, struct_ptr, @intCast(i), field_src, struct_ty, true); |
| 5070 | try sema.checkKnownAllocPtr(struct_ptr, default_field_ptr); | 5137 | try sema.checkKnownAllocPtr(block, struct_ptr, default_field_ptr); |
| 5071 | const init = Air.internedToRef(field_values[i]); | 5138 | const init = Air.internedToRef(field_values[i]); |
| 5072 | try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store); | 5139 | try sema.storePtr2(block, init_src, default_field_ptr, init_src, init, field_src, .store); |
| 5073 | } | 5140 | } |
| ... | @@ -5474,7 +5541,7 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi | ... | @@ -5474,7 +5541,7 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi |
| 5474 | }, | 5541 | }, |
| 5475 | .inferred_alloc => { | 5542 | .inferred_alloc => { |
| 5476 | const ia = sema.unresolved_inferred_allocs.getPtr(ptr_inst).?; | 5543 | const ia = sema.unresolved_inferred_allocs.getPtr(ptr_inst).?; |
| 5477 | return sema.storeToInferredAlloc(block, ptr, operand, ia); | 5544 | return sema.storeToInferredAlloc(block, src, ptr, operand, ia); |
| 5478 | }, | 5545 | }, |
| 5479 | else => unreachable, | 5546 | else => unreachable, |
| 5480 | } | 5547 | } |
| ... | @@ -5483,6 +5550,7 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi | ... | @@ -5483,6 +5550,7 @@ fn zirStoreToInferredPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compi |
| 5483 | fn storeToInferredAlloc( | 5550 | fn storeToInferredAlloc( |
| 5484 | sema: *Sema, | 5551 | sema: *Sema, |
| 5485 | block: *Block, | 5552 | block: *Block, |
| | 5553 | src: LazySrcLoc, |
| 5486 | ptr: Air.Inst.Ref, | 5554 | ptr: Air.Inst.Ref, |
| 5487 | operand: Air.Inst.Ref, | 5555 | operand: Air.Inst.Ref, |
| 5488 | inferred_alloc: *InferredAlloc, | 5556 | inferred_alloc: *InferredAlloc, |
| ... | @@ -5490,7 +5558,7 @@ fn storeToInferredAlloc( | ... | @@ -5490,7 +5558,7 @@ fn storeToInferredAlloc( |
| 5490 | // Create a store instruction as a placeholder. This will be replaced by a | 5558 | // Create a store instruction as a placeholder. This will be replaced by a |
| 5491 | // proper store sequence once we know the stored type. | 5559 | // proper store sequence once we know the stored type. |
| 5492 | const dummy_store = try block.addBinOp(.store, ptr, operand); | 5560 | const dummy_store = try block.addBinOp(.store, ptr, operand); |
| 5493 | try sema.checkComptimeKnownStore(block, dummy_store); | 5561 | try sema.checkComptimeKnownStore(block, dummy_store, src); |
| 5494 | // Add the stored instruction to the set we will use to resolve peer types | 5562 | // Add the stored instruction to the set we will use to resolve peer types |
| 5495 | // for the inferred allocation. | 5563 | // for the inferred allocation. |
| 5496 | try inferred_alloc.prongs.append(sema.arena, dummy_store.toIndex().?); | 5564 | try inferred_alloc.prongs.append(sema.arena, dummy_store.toIndex().?); |
| ... | @@ -5503,20 +5571,38 @@ fn storeToInferredAllocComptime( | ... | @@ -5503,20 +5571,38 @@ fn storeToInferredAllocComptime( |
| 5503 | operand: Air.Inst.Ref, | 5571 | operand: Air.Inst.Ref, |
| 5504 | iac: *Air.Inst.Data.InferredAllocComptime, | 5572 | iac: *Air.Inst.Data.InferredAllocComptime, |
| 5505 | ) CompileError!void { | 5573 | ) CompileError!void { |
| | 5574 | const zcu = sema.mod; |
| 5506 | const operand_ty = sema.typeOf(operand); | 5575 | const operand_ty = sema.typeOf(operand); |
| 5507 | // There will be only one store_to_inferred_ptr because we are running at comptime. | 5576 | // There will be only one store_to_inferred_ptr because we are running at comptime. |
| 5508 | // The alloc will turn into a Decl. | 5577 | // The alloc will turn into a Decl or a ComptimeAlloc. |
| 5509 | if (try sema.resolveValue(operand)) |operand_val| { | 5578 | const operand_val = try sema.resolveValue(operand) orelse { |
| 5510 | var anon_decl = try block.startAnonDecl(); // TODO: comptime value mutation without Decl | 5579 | return sema.failWithNeededComptime(block, src, .{ |
| 5511 | defer anon_decl.deinit(); | 5580 | .needed_comptime_reason = "value being stored to a comptime variable must be comptime-known", |
| 5512 | iac.decl_index = try anon_decl.finish(operand_ty, operand_val, iac.alignment); | 5581 | }); |
| 5513 | try sema.comptime_mutable_decls.append(iac.decl_index); | 5582 | }; |
| 5514 | return; | 5583 | const alloc_ty = try sema.ptrType(.{ |
| 5515 | } | 5584 | .child = operand_ty.toIntern(), |
| 5516 | | 5585 | .flags = .{ |
| 5517 | return sema.failWithNeededComptime(block, src, .{ | 5586 | .alignment = iac.alignment, |
| 5518 | .needed_comptime_reason = "value being stored to a comptime variable must be comptime-known", | 5587 | .is_const = iac.is_const, |
| | 5588 | }, |
| 5519 | }); | 5589 | }); |
| | 5590 | if (iac.is_const and !operand_val.canMutateComptimeVarState(zcu)) { |
| | 5591 | iac.ptr = try zcu.intern(.{ .ptr = .{ |
| | 5592 | .ty = alloc_ty.toIntern(), |
| | 5593 | .addr = .{ .anon_decl = .{ |
| | 5594 | .val = operand_val.toIntern(), |
| | 5595 | .orig_ty = alloc_ty.toIntern(), |
| | 5596 | } }, |
| | 5597 | } }); |
| | 5598 | } else { |
| | 5599 | const alloc_index = try sema.newComptimeAlloc(block, operand_ty, iac.alignment); |
| | 5600 | sema.getComptimeAlloc(alloc_index).val = operand_val; |
| | 5601 | iac.ptr = try zcu.intern(.{ .ptr = .{ |
| | 5602 | .ty = alloc_ty.toIntern(), |
| | 5603 | .addr = .{ .comptime_alloc = alloc_index }, |
| | 5604 | } }); |
| | 5605 | } |
| 5520 | } | 5606 | } |
| 5521 | | 5607 | |
| 5522 | fn zirSetEvalBranchQuota(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { | 5608 | fn zirSetEvalBranchQuota(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void { |
| ... | @@ -6178,6 +6264,9 @@ fn resolveAnalyzedBlock( | ... | @@ -6178,6 +6264,9 @@ fn resolveAnalyzedBlock( |
| 6178 | }; | 6264 | }; |
| 6179 | return sema.failWithOwnedErrorMsg(child_block, msg); | 6265 | return sema.failWithOwnedErrorMsg(child_block, msg); |
| 6180 | } | 6266 | } |
| | 6267 | for (merges.results.items, merges.src_locs.items) |merge_inst, merge_src| { |
| | 6268 | try sema.validateRuntimeValue(child_block, merge_src orelse src, merge_inst); |
| | 6269 | } |
| 6181 | const ty_inst = Air.internedToRef(resolved_ty.toIntern()); | 6270 | const ty_inst = Air.internedToRef(resolved_ty.toIntern()); |
| 6182 | switch (block_tag) { | 6271 | switch (block_tag) { |
| 6183 | .block => { | 6272 | .block => { |
| ... | @@ -6579,6 +6668,9 @@ fn addDbgVar( | ... | @@ -6579,6 +6668,9 @@ fn addDbgVar( |
| 6579 | }; | 6668 | }; |
| 6580 | if (try sema.typeRequiresComptime(val_ty)) return; | 6669 | if (try sema.typeRequiresComptime(val_ty)) return; |
| 6581 | if (!(try sema.typeHasRuntimeBits(val_ty))) return; | 6670 | if (!(try sema.typeHasRuntimeBits(val_ty))) return; |
| | 6671 | if (try sema.resolveValue(operand)) |operand_val| { |
| | 6672 | if (operand_val.canMutateComptimeVarState(mod)) return; |
| | 6673 | } |
| 6582 | | 6674 | |
| 6583 | // To ensure the lexical scoping is known to backends, this alloc must be | 6675 | // To ensure the lexical scoping is known to backends, this alloc must be |
| 6584 | // within a real runtime block. We set a flag which communicates information | 6676 | // within a real runtime block. We set a flag which communicates information |
| ... | @@ -7741,20 +7833,24 @@ fn analyzeCall( | ... | @@ -7741,20 +7833,24 @@ fn analyzeCall( |
| 7741 | break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, merges, need_debug_scope); | 7833 | break :result try sema.resolveAnalyzedBlock(block, call_src, &child_block, merges, need_debug_scope); |
| 7742 | }; | 7834 | }; |
| 7743 | | 7835 | |
| 7744 | if (should_memoize and is_comptime_call) { | 7836 | if (is_comptime_call) { |
| 7745 | const result_val = try sema.resolveConstValue(block, .unneeded, result, undefined); | 7837 | const result_val = try sema.resolveConstValue(block, .unneeded, result, undefined); |
| 7746 | const result_interned = try result_val.intern2(sema.fn_ret_ty, mod); | 7838 | const result_interned = try result_val.intern2(sema.fn_ret_ty, mod); |
| 7747 | | 7839 | |
| 7748 | // Transform ad-hoc inferred error set types into concrete error sets. | 7840 | // Transform ad-hoc inferred error set types into concrete error sets. |
| 7749 | const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned); | 7841 | const result_transformed = try sema.resolveAdHocInferredErrorSet(block, call_src, result_interned); |
| 7750 | | 7842 | |
| | 7843 | // If the result can mutate comptime vars, we must not memoize it, as it contains |
| | 7844 | // a reference to `comptime_allocs` so is not stable across instances of `Sema`. |
| 7751 | // TODO: check whether any external comptime memory was mutated by the | 7845 | // TODO: check whether any external comptime memory was mutated by the |
| 7752 | // comptime function call. If so, then do not memoize the call here. | 7846 | // comptime function call. If so, then do not memoize the call here. |
| 7753 | _ = try mod.intern(.{ .memoized_call = .{ | 7847 | if (should_memoize and !Value.fromInterned(result_interned).canMutateComptimeVarState(mod)) { |
| 7754 | .func = module_fn_index, | 7848 | _ = try mod.intern(.{ .memoized_call = .{ |
| 7755 | .arg_values = memoized_arg_values, | 7849 | .func = module_fn_index, |
| 7756 | .result = result_transformed, | 7850 | .arg_values = memoized_arg_values, |
| 7757 | } }); | 7851 | .result = result_transformed, |
| | 7852 | } }); |
| | 7853 | } |
| 7758 | | 7854 | |
| 7759 | break :res2 Air.internedToRef(result_transformed); | 7855 | break :res2 Air.internedToRef(result_transformed); |
| 7760 | } | 7856 | } |
| ... | @@ -7787,6 +7883,7 @@ fn analyzeCall( | ... | @@ -7787,6 +7883,7 @@ fn analyzeCall( |
| 7787 | } else Type.fromInterned(InternPool.Index.var_args_param_type); | 7883 | } else Type.fromInterned(InternPool.Index.var_args_param_type); |
| 7788 | assert(!param_ty.isGenericPoison()); | 7884 | assert(!param_ty.isGenericPoison()); |
| 7789 | arg_out.* = try args_info.analyzeArg(sema, block, arg_idx, param_ty, func_ty_info, func); | 7885 | arg_out.* = try args_info.analyzeArg(sema, block, arg_idx, param_ty, func_ty_info, func); |
| | 7886 | try sema.validateRuntimeValue(block, args_info.argSrc(block, arg_idx), arg_out.*); |
| 7790 | if (sema.typeOf(arg_out.*).zigTypeTag(mod) == .NoReturn) { | 7887 | if (sema.typeOf(arg_out.*).zigTypeTag(mod) == .NoReturn) { |
| 7791 | return arg_out.*; | 7888 | return arg_out.*; |
| 7792 | } | 7889 | } |
| ... | @@ -8082,7 +8179,6 @@ fn instantiateGenericCall( | ... | @@ -8082,7 +8179,6 @@ fn instantiateGenericCall( |
| 8082 | .generic_call_decl = block.src_decl.toOptional(), | 8179 | .generic_call_decl = block.src_decl.toOptional(), |
| 8083 | .branch_quota = sema.branch_quota, | 8180 | .branch_quota = sema.branch_quota, |
| 8084 | .branch_count = sema.branch_count, | 8181 | .branch_count = sema.branch_count, |
| 8085 | .comptime_mutable_decls = sema.comptime_mutable_decls, | | |
| 8086 | .comptime_err_ret_trace = sema.comptime_err_ret_trace, | 8182 | .comptime_err_ret_trace = sema.comptime_err_ret_trace, |
| 8087 | }; | 8183 | }; |
| 8088 | defer child_sema.deinit(); | 8184 | defer child_sema.deinit(); |
| ... | @@ -8147,6 +8243,7 @@ fn instantiateGenericCall( | ... | @@ -8147,6 +8243,7 @@ fn instantiateGenericCall( |
| 8147 | }, | 8243 | }, |
| 8148 | }; | 8244 | }; |
| 8149 | const arg_ref = try args_info.analyzeArg(sema, block, arg_index, param_ty, generic_owner_ty_info, func); | 8245 | const arg_ref = try args_info.analyzeArg(sema, block, arg_index, param_ty, generic_owner_ty_info, func); |
| | 8246 | try sema.validateRuntimeValue(block, args_info.argSrc(block, arg_index), arg_ref); |
| 8150 | const arg_ty = sema.typeOf(arg_ref); | 8247 | const arg_ty = sema.typeOf(arg_ref); |
| 8151 | if (arg_ty.zigTypeTag(mod) == .NoReturn) { | 8248 | if (arg_ty.zigTypeTag(mod) == .NoReturn) { |
| 8152 | // This terminates argument analysis. | 8249 | // This terminates argument analysis. |
| ... | @@ -8859,12 +8956,12 @@ fn analyzeOptionalPayloadPtr( | ... | @@ -8859,12 +8956,12 @@ fn analyzeOptionalPayloadPtr( |
| 8859 | | 8956 | |
| 8860 | if (try sema.resolveDefinedValue(block, src, optional_ptr)) |ptr_val| { | 8957 | if (try sema.resolveDefinedValue(block, src, optional_ptr)) |ptr_val| { |
| 8861 | if (initializing) { | 8958 | if (initializing) { |
| 8862 | if (!ptr_val.isComptimeMutablePtr(mod)) { | 8959 | if (!sema.isComptimeMutablePtr(ptr_val)) { |
| 8863 | // If the pointer resulting from this function was stored at comptime, | 8960 | // If the pointer resulting from this function was stored at comptime, |
| 8864 | // the optional non-null bit would be set that way. But in this case, | 8961 | // the optional non-null bit would be set that way. But in this case, |
| 8865 | // we need to emit a runtime instruction to do it. | 8962 | // we need to emit a runtime instruction to do it. |
| 8866 | const opt_payload_ptr = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr); | 8963 | const opt_payload_ptr = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr); |
| 8867 | try sema.checkKnownAllocPtr(optional_ptr, opt_payload_ptr); | 8964 | try sema.checkKnownAllocPtr(block, optional_ptr, opt_payload_ptr); |
| 8868 | } | 8965 | } |
| 8869 | return Air.internedToRef((try mod.intern(.{ .ptr = .{ | 8966 | return Air.internedToRef((try mod.intern(.{ .ptr = .{ |
| 8870 | .ty = child_pointer.toIntern(), | 8967 | .ty = child_pointer.toIntern(), |
| ... | @@ -8891,7 +8988,7 @@ fn analyzeOptionalPayloadPtr( | ... | @@ -8891,7 +8988,7 @@ fn analyzeOptionalPayloadPtr( |
| 8891 | | 8988 | |
| 8892 | if (initializing) { | 8989 | if (initializing) { |
| 8893 | const opt_payload_ptr = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr); | 8990 | const opt_payload_ptr = try block.addTyOp(.optional_payload_ptr_set, child_pointer, optional_ptr); |
| 8894 | try sema.checkKnownAllocPtr(optional_ptr, opt_payload_ptr); | 8991 | try sema.checkKnownAllocPtr(block, optional_ptr, opt_payload_ptr); |
| 8895 | return opt_payload_ptr; | 8992 | return opt_payload_ptr; |
| 8896 | } else { | 8993 | } else { |
| 8897 | return block.addTyOp(.optional_payload_ptr, child_pointer, optional_ptr); | 8994 | return block.addTyOp(.optional_payload_ptr, child_pointer, optional_ptr); |
| ... | @@ -9050,13 +9147,13 @@ fn analyzeErrUnionPayloadPtr( | ... | @@ -9050,13 +9147,13 @@ fn analyzeErrUnionPayloadPtr( |
| 9050 | | 9147 | |
| 9051 | if (try sema.resolveDefinedValue(block, src, operand)) |ptr_val| { | 9148 | if (try sema.resolveDefinedValue(block, src, operand)) |ptr_val| { |
| 9052 | if (initializing) { | 9149 | if (initializing) { |
| 9053 | if (!ptr_val.isComptimeMutablePtr(mod)) { | 9150 | if (!sema.isComptimeMutablePtr(ptr_val)) { |
| 9054 | // If the pointer resulting from this function was stored at comptime, | 9151 | // If the pointer resulting from this function was stored at comptime, |
| 9055 | // the error union error code would be set that way. But in this case, | 9152 | // the error union error code would be set that way. But in this case, |
| 9056 | // we need to emit a runtime instruction to do it. | 9153 | // we need to emit a runtime instruction to do it. |
| 9057 | try sema.requireRuntimeBlock(block, src, null); | 9154 | try sema.requireRuntimeBlock(block, src, null); |
| 9058 | const eu_payload_ptr = try block.addTyOp(.errunion_payload_ptr_set, operand_pointer_ty, operand); | 9155 | const eu_payload_ptr = try block.addTyOp(.errunion_payload_ptr_set, operand_pointer_ty, operand); |
| 9059 | try sema.checkKnownAllocPtr(operand, eu_payload_ptr); | 9156 | try sema.checkKnownAllocPtr(block, operand, eu_payload_ptr); |
| 9060 | } | 9157 | } |
| 9061 | return Air.internedToRef((try mod.intern(.{ .ptr = .{ | 9158 | return Air.internedToRef((try mod.intern(.{ .ptr = .{ |
| 9062 | .ty = operand_pointer_ty.toIntern(), | 9159 | .ty = operand_pointer_ty.toIntern(), |
| ... | @@ -9085,7 +9182,7 @@ fn analyzeErrUnionPayloadPtr( | ... | @@ -9085,7 +9182,7 @@ fn analyzeErrUnionPayloadPtr( |
| 9085 | | 9182 | |
| 9086 | if (initializing) { | 9183 | if (initializing) { |
| 9087 | const eu_payload_ptr = try block.addTyOp(.errunion_payload_ptr_set, operand_pointer_ty, operand); | 9184 | const eu_payload_ptr = try block.addTyOp(.errunion_payload_ptr_set, operand_pointer_ty, operand); |
| 9088 | try sema.checkKnownAllocPtr(operand, eu_payload_ptr); | 9185 | try sema.checkKnownAllocPtr(block, operand, eu_payload_ptr); |
| 9089 | return eu_payload_ptr; | 9186 | return eu_payload_ptr; |
| 9090 | } else { | 9187 | } else { |
| 9091 | return block.addTyOp(.unwrap_errunion_payload_ptr, operand_pointer_ty, operand); | 9188 | return block.addTyOp(.unwrap_errunion_payload_ptr, operand_pointer_ty, operand); |
| ... | @@ -10089,6 +10186,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! | ... | @@ -10089,6 +10186,7 @@ fn zirIntFromPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError! |
| 10089 | } })); | 10186 | } })); |
| 10090 | } | 10187 | } |
| 10091 | try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src); | 10188 | try sema.requireRuntimeBlock(block, inst_data.src(), ptr_src); |
| | 10189 | try sema.validateRuntimeValue(block, ptr_src, operand); |
| 10092 | if (!is_vector) { | 10190 | if (!is_vector) { |
| 10093 | return block.addUnOp(.int_from_ptr, operand); | 10191 | return block.addUnOp(.int_from_ptr, operand); |
| 10094 | } | 10192 | } |
| ... | @@ -14743,7 +14841,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -14743,7 +14841,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14743 | // Optimization for the common pattern of a single element repeated N times, such | 14841 | // Optimization for the common pattern of a single element repeated N times, such |
| 14744 | // as zero-filling a byte array. | 14842 | // as zero-filling a byte array. |
| 14745 | if (lhs_len == 1 and lhs_info.sentinel == null) { | 14843 | if (lhs_len == 1 and lhs_info.sentinel == null) { |
| 14746 | const elem_val = try lhs_sub_val.elemValue(mod, 0); | 14844 | const elem_val = (try lhs_sub_val.maybeElemValueFull(sema, mod, 0)).?; |
| 14747 | break :v try mod.intern(.{ .aggregate = .{ | 14845 | break :v try mod.intern(.{ .aggregate = .{ |
| 14748 | .ty = result_ty.toIntern(), | 14846 | .ty = result_ty.toIntern(), |
| 14749 | .storage = .{ .repeated_elem = elem_val.toIntern() }, | 14847 | .storage = .{ .repeated_elem = elem_val.toIntern() }, |
| ... | @@ -14755,7 +14853,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai | ... | @@ -14755,7 +14853,7 @@ fn zirArrayMul(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai |
| 14755 | while (elem_i < result_len) { | 14853 | while (elem_i < result_len) { |
| 14756 | var lhs_i: usize = 0; | 14854 | var lhs_i: usize = 0; |
| 14757 | while (lhs_i < lhs_len) : (lhs_i += 1) { | 14855 | while (lhs_i < lhs_len) : (lhs_i += 1) { |
| 14758 | const elem_val = try lhs_sub_val.elemValue(mod, lhs_i); | 14856 | const elem_val = (try lhs_sub_val.maybeElemValueFull(sema, mod, lhs_i)).?; |
| 14759 | element_vals[elem_i] = elem_val.toIntern(); | 14857 | element_vals[elem_i] = elem_val.toIntern(); |
| 14760 | elem_i += 1; | 14858 | elem_i += 1; |
| 14761 | } | 14859 | } |
| ... | @@ -19585,6 +19683,8 @@ fn analyzeRet( | ... | @@ -19585,6 +19683,8 @@ fn analyzeRet( |
| 19585 | | 19683 | |
| 19586 | try sema.resolveTypeLayout(sema.fn_ret_ty); | 19684 | try sema.resolveTypeLayout(sema.fn_ret_ty); |
| 19587 | | 19685 | |
| | 19686 | try sema.validateRuntimeValue(block, operand_src, operand); |
| | 19687 | |
| 19588 | const air_tag: Air.Inst.Tag = if (block.wantSafety()) .ret_safe else .ret; | 19688 | const air_tag: Air.Inst.Tag = if (block.wantSafety()) .ret_safe else .ret; |
| 19589 | if (sema.wantErrorReturnTracing(sema.fn_ret_ty)) { | 19689 | if (sema.wantErrorReturnTracing(sema.fn_ret_ty)) { |
| 19590 | // Avoid adding a frame to the error return trace in case the value is comptime-known | 19690 | // Avoid adding a frame to the error return trace in case the value is comptime-known |
| ... | @@ -20013,6 +20113,8 @@ fn zirStructInit( | ... | @@ -20013,6 +20113,8 @@ fn zirStructInit( |
| 20013 | }); | 20113 | }); |
| 20014 | } | 20114 | } |
| 20015 | | 20115 | |
| | 20116 | try sema.validateRuntimeValue(block, field_src, init_inst); |
| | 20117 | |
| 20016 | if (is_ref) { | 20118 | if (is_ref) { |
| 20017 | const target = mod.getTarget(); | 20119 | const target = mod.getTarget(); |
| 20018 | const alloc_ty = try sema.ptrType(.{ | 20120 | const alloc_ty = try sema.ptrType(.{ |
| ... | @@ -20187,6 +20289,10 @@ fn finishStructInit( | ... | @@ -20187,6 +20289,10 @@ fn finishStructInit( |
| 20187 | }); | 20289 | }); |
| 20188 | } | 20290 | } |
| 20189 | | 20291 | |
| | 20292 | for (field_inits) |field_init| { |
| | 20293 | try sema.validateRuntimeValue(block, dest_src, field_init); |
| | 20294 | } |
| | 20295 | |
| 20190 | if (is_ref) { | 20296 | if (is_ref) { |
| 20191 | try sema.resolveStructLayout(struct_ty); | 20297 | try sema.resolveStructLayout(struct_ty); |
| 20192 | const target = sema.mod.getTarget(); | 20298 | const target = sema.mod.getTarget(); |
| ... | @@ -21023,7 +21129,7 @@ fn zirReify( | ... | @@ -21023,7 +21129,7 @@ fn zirReify( |
| 21023 | .needed_comptime_reason = "operand to @Type must be comptime-known", | 21129 | .needed_comptime_reason = "operand to @Type must be comptime-known", |
| 21024 | }); | 21130 | }); |
| 21025 | const union_val = ip.indexToKey(val.toIntern()).un; | 21131 | const union_val = ip.indexToKey(val.toIntern()).un; |
| 21026 | if (try Value.fromInterned(union_val.val).anyUndef(mod)) return sema.failWithUseOfUndef(block, src); | 21132 | if (try sema.anyUndef(Value.fromInterned(union_val.val))) return sema.failWithUseOfUndef(block, src); |
| 21027 | const tag_index = type_info_ty.unionTagFieldIndex(Value.fromInterned(union_val.tag), mod).?; | 21133 | const tag_index = type_info_ty.unionTagFieldIndex(Value.fromInterned(union_val.tag), mod).?; |
| 21028 | switch (@as(std.builtin.TypeId, @enumFromInt(tag_index))) { | 21134 | switch (@as(std.builtin.TypeId, @enumFromInt(tag_index))) { |
| 21029 | .Type => return .type_type, | 21135 | .Type => return .type_type, |
| ... | @@ -21268,14 +21374,16 @@ fn zirReify( | ... | @@ -21268,14 +21374,16 @@ fn zirReify( |
| 21268 | var names: InferredErrorSet.NameMap = .{}; | 21374 | var names: InferredErrorSet.NameMap = .{}; |
| 21269 | try names.ensureUnusedCapacity(sema.arena, len); | 21375 | try names.ensureUnusedCapacity(sema.arena, len); |
| 21270 | for (0..len) |i| { | 21376 | for (0..len) |i| { |
| 21271 | const elem_val = try payload_val.elemValue(mod, i); | 21377 | const elem_val = (try payload_val.maybeElemValueFull(sema, mod, i)).?; |
| 21272 | const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern())); | 21378 | const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern())); |
| 21273 | const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( | 21379 | const name_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( |
| 21274 | ip, | 21380 | ip, |
| 21275 | try ip.getOrPutString(gpa, "name"), | 21381 | try ip.getOrPutString(gpa, "name"), |
| 21276 | ).?); | 21382 | ).?); |
| 21277 | | 21383 | |
| 21278 | const name = try name_val.toIpString(Type.slice_const_u8, mod); | 21384 | const name = try sema.sliceToIpString(block, src, name_val, .{ |
| | 21385 | .needed_comptime_reason = "error set contents must be comptime-known", |
| | 21386 | }); |
| 21279 | _ = try mod.getErrorValue(name); | 21387 | _ = try mod.getErrorValue(name); |
| 21280 | const gop = names.getOrPutAssumeCapacity(name); | 21388 | const gop = names.getOrPutAssumeCapacity(name); |
| 21281 | if (gop.found_existing) { | 21389 | if (gop.found_existing) { |
| ... | @@ -21451,7 +21559,7 @@ fn zirReify( | ... | @@ -21451,7 +21559,7 @@ fn zirReify( |
| 21451 | | 21559 | |
| 21452 | var noalias_bits: u32 = 0; | 21560 | var noalias_bits: u32 = 0; |
| 21453 | for (param_types, 0..) |*param_type, i| { | 21561 | for (param_types, 0..) |*param_type, i| { |
| 21454 | const elem_val = try params_val.elemValue(mod, i); | 21562 | const elem_val = (try params_val.maybeElemValueFull(sema, mod, i)).?; |
| 21455 | const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern())); | 21563 | const elem_struct_type = ip.loadStructType(ip.typeOf(elem_val.toIntern())); |
| 21456 | const param_is_generic_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( | 21564 | const param_is_generic_val = try elem_val.fieldValue(mod, elem_struct_type.nameIndex( |
| 21457 | ip, | 21565 | ip, |
| ... | @@ -21526,12 +21634,14 @@ fn reifyEnum( | ... | @@ -21526,12 +21634,14 @@ fn reifyEnum( |
| 21526 | std.hash.autoHash(&hasher, fields_len); | 21634 | std.hash.autoHash(&hasher, fields_len); |
| 21527 | | 21635 | |
| 21528 | for (0..fields_len) |field_idx| { | 21636 | for (0..fields_len) |field_idx| { |
| 21529 | const field_info = try fields_val.elemValue(mod, field_idx); | 21637 | const field_info = (try fields_val.maybeElemValueFull(sema, mod, field_idx)).?; |
| 21530 | | 21638 | |
| 21531 | const field_name_val = try field_info.fieldValue(mod, 0); | 21639 | const field_name_val = try field_info.fieldValue(mod, 0); |
| 21532 | const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 1)); | 21640 | const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 1)); |
| 21533 | | 21641 | |
| 21534 | const field_name = try field_name_val.toIpString(Type.slice_const_u8, mod); | 21642 | const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ |
| | 21643 | .needed_comptime_reason = "enum field name must be comptime-known", |
| | 21644 | }); |
| 21535 | | 21645 | |
| 21536 | std.hash.autoHash(&hasher, .{ | 21646 | std.hash.autoHash(&hasher, .{ |
| 21537 | field_name, | 21647 | field_name, |
| ... | @@ -21569,12 +21679,13 @@ fn reifyEnum( | ... | @@ -21569,12 +21679,13 @@ fn reifyEnum( |
| 21569 | wip_ty.setTagTy(ip, tag_ty.toIntern()); | 21679 | wip_ty.setTagTy(ip, tag_ty.toIntern()); |
| 21570 | | 21680 | |
| 21571 | for (0..fields_len) |field_idx| { | 21681 | for (0..fields_len) |field_idx| { |
| 21572 | const field_info = try fields_val.elemValue(mod, field_idx); | 21682 | const field_info = (try fields_val.maybeElemValueFull(sema, mod, field_idx)).?; |
| 21573 | | 21683 | |
| 21574 | const field_name_val = try field_info.fieldValue(mod, 0); | 21684 | const field_name_val = try field_info.fieldValue(mod, 0); |
| 21575 | const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 1)); | 21685 | const field_value_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 1)); |
| 21576 | | 21686 | |
| 21577 | const field_name = try field_name_val.toIpString(Type.slice_const_u8, mod); | 21687 | // Don't pass a reason; first loop acts as an assertion that this is valid. |
| | 21688 | const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined); |
| 21578 | | 21689 | |
| 21579 | if (!try sema.intFitsInType(field_value_val, tag_ty, null)) { | 21690 | if (!try sema.intFitsInType(field_value_val, tag_ty, null)) { |
| 21580 | // TODO: better source location | 21691 | // TODO: better source location |
| ... | @@ -21646,13 +21757,15 @@ fn reifyUnion( | ... | @@ -21646,13 +21757,15 @@ fn reifyUnion( |
| 21646 | var any_aligns = false; | 21757 | var any_aligns = false; |
| 21647 | | 21758 | |
| 21648 | for (0..fields_len) |field_idx| { | 21759 | for (0..fields_len) |field_idx| { |
| 21649 | const field_info = try fields_val.elemValue(mod, field_idx); | 21760 | const field_info = (try fields_val.maybeElemValueFull(sema, mod, field_idx)).?; |
| 21650 | | 21761 | |
| 21651 | const field_name_val = try field_info.fieldValue(mod, 0); | 21762 | const field_name_val = try field_info.fieldValue(mod, 0); |
| 21652 | const field_type_val = try field_info.fieldValue(mod, 1); | 21763 | const field_type_val = try field_info.fieldValue(mod, 1); |
| 21653 | const field_align_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 2)); | 21764 | const field_align_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 2)); |
| 21654 | | 21765 | |
| 21655 | const field_name = try field_name_val.toIpString(Type.slice_const_u8, mod); | 21766 | const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ |
| | 21767 | .needed_comptime_reason = "union field name must be comptime-known", |
| | 21768 | }); |
| 21656 | | 21769 | |
| 21657 | std.hash.autoHash(&hasher, .{ | 21770 | std.hash.autoHash(&hasher, .{ |
| 21658 | field_name, | 21771 | field_name, |
| ... | @@ -21720,12 +21833,13 @@ fn reifyUnion( | ... | @@ -21720,12 +21833,13 @@ fn reifyUnion( |
| 21720 | var seen_tags = try std.DynamicBitSetUnmanaged.initEmpty(sema.arena, tag_ty_fields_len); | 21833 | var seen_tags = try std.DynamicBitSetUnmanaged.initEmpty(sema.arena, tag_ty_fields_len); |
| 21721 | | 21834 | |
| 21722 | for (field_types, 0..) |*field_ty, field_idx| { | 21835 | for (field_types, 0..) |*field_ty, field_idx| { |
| 21723 | const field_info = try fields_val.elemValue(mod, field_idx); | 21836 | const field_info = (try fields_val.maybeElemValueFull(sema, mod, field_idx)).?; |
| 21724 | | 21837 | |
| 21725 | const field_name_val = try field_info.fieldValue(mod, 0); | 21838 | const field_name_val = try field_info.fieldValue(mod, 0); |
| 21726 | const field_type_val = try field_info.fieldValue(mod, 1); | 21839 | const field_type_val = try field_info.fieldValue(mod, 1); |
| 21727 | | 21840 | |
| 21728 | const field_name = try field_name_val.toIpString(Type.slice_const_u8, mod); | 21841 | // Don't pass a reason; first loop acts as an assertion that this is valid. |
| | 21842 | const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined); |
| 21729 | | 21843 | |
| 21730 | const enum_index = enum_tag_ty.enumFieldIndex(field_name, mod) orelse { | 21844 | const enum_index = enum_tag_ty.enumFieldIndex(field_name, mod) orelse { |
| 21731 | // TODO: better source location | 21845 | // TODO: better source location |
| ... | @@ -21771,12 +21885,13 @@ fn reifyUnion( | ... | @@ -21771,12 +21885,13 @@ fn reifyUnion( |
| 21771 | try field_names.ensureTotalCapacity(sema.arena, fields_len); | 21885 | try field_names.ensureTotalCapacity(sema.arena, fields_len); |
| 21772 | | 21886 | |
| 21773 | for (field_types, 0..) |*field_ty, field_idx| { | 21887 | for (field_types, 0..) |*field_ty, field_idx| { |
| 21774 | const field_info = try fields_val.elemValue(mod, field_idx); | 21888 | const field_info = (try fields_val.maybeElemValueFull(sema, mod, field_idx)).?; |
| 21775 | | 21889 | |
| 21776 | const field_name_val = try field_info.fieldValue(mod, 0); | 21890 | const field_name_val = try field_info.fieldValue(mod, 0); |
| 21777 | const field_type_val = try field_info.fieldValue(mod, 1); | 21891 | const field_type_val = try field_info.fieldValue(mod, 1); |
| 21778 | | 21892 | |
| 21779 | const field_name = try field_name_val.toIpString(Type.slice_const_u8, mod); | 21893 | // Don't pass a reason; first loop acts as an assertion that this is valid. |
| | 21894 | const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined); |
| 21780 | const gop = field_names.getOrPutAssumeCapacity(field_name); | 21895 | const gop = field_names.getOrPutAssumeCapacity(field_name); |
| 21781 | if (gop.found_existing) { | 21896 | if (gop.found_existing) { |
| 21782 | // TODO: better source location | 21897 | // TODO: better source location |
| ... | @@ -21883,7 +21998,7 @@ fn reifyStruct( | ... | @@ -21883,7 +21998,7 @@ fn reifyStruct( |
| 21883 | var any_aligned_fields = false; | 21998 | var any_aligned_fields = false; |
| 21884 | | 21999 | |
| 21885 | for (0..fields_len) |field_idx| { | 22000 | for (0..fields_len) |field_idx| { |
| 21886 | const field_info = try fields_val.elemValue(mod, field_idx); | 22001 | const field_info = (try fields_val.maybeElemValueFull(sema, mod, field_idx)).?; |
| 21887 | | 22002 | |
| 21888 | const field_name_val = try field_info.fieldValue(mod, 0); | 22003 | const field_name_val = try field_info.fieldValue(mod, 0); |
| 21889 | const field_type_val = try field_info.fieldValue(mod, 1); | 22004 | const field_type_val = try field_info.fieldValue(mod, 1); |
| ... | @@ -21891,7 +22006,9 @@ fn reifyStruct( | ... | @@ -21891,7 +22006,9 @@ fn reifyStruct( |
| 21891 | const field_is_comptime_val = try field_info.fieldValue(mod, 3); | 22006 | const field_is_comptime_val = try field_info.fieldValue(mod, 3); |
| 21892 | const field_alignment_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 4)); | 22007 | const field_alignment_val = try sema.resolveLazyValue(try field_info.fieldValue(mod, 4)); |
| 21893 | | 22008 | |
| 21894 | const field_name = try field_name_val.toIpString(Type.slice_const_u8, mod); | 22009 | const field_name = try sema.sliceToIpString(block, src, field_name_val, .{ |
| | 22010 | .needed_comptime_reason = "struct field name must be comptime-known", |
| | 22011 | }); |
| 21895 | const field_is_comptime = field_is_comptime_val.toBool(); | 22012 | const field_is_comptime = field_is_comptime_val.toBool(); |
| 21896 | const field_default_value: InternPool.Index = if (field_default_value_val.optionalValue(mod)) |ptr_val| d: { | 22013 | const field_default_value: InternPool.Index = if (field_default_value_val.optionalValue(mod)) |ptr_val| d: { |
| 21897 | const ptr_ty = try mod.singleConstPtrType(field_type_val.toType()); | 22014 | const ptr_ty = try mod.singleConstPtrType(field_type_val.toType()); |
| ... | @@ -21959,7 +22076,7 @@ fn reifyStruct( | ... | @@ -21959,7 +22076,7 @@ fn reifyStruct( |
| 21959 | const struct_type = ip.loadStructType(wip_ty.index); | 22076 | const struct_type = ip.loadStructType(wip_ty.index); |
| 21960 | | 22077 | |
| 21961 | for (0..fields_len) |field_idx| { | 22078 | for (0..fields_len) |field_idx| { |
| 21962 | const field_info = try fields_val.elemValue(mod, field_idx); | 22079 | const field_info = (try fields_val.maybeElemValueFull(sema, mod, field_idx)).?; |
| 21963 | | 22080 | |
| 21964 | const field_name_val = try field_info.fieldValue(mod, 0); | 22081 | const field_name_val = try field_info.fieldValue(mod, 0); |
| 21965 | const field_type_val = try field_info.fieldValue(mod, 1); | 22082 | const field_type_val = try field_info.fieldValue(mod, 1); |
| ... | @@ -21968,7 +22085,8 @@ fn reifyStruct( | ... | @@ -21968,7 +22085,8 @@ fn reifyStruct( |
| 21968 | const field_alignment_val = try field_info.fieldValue(mod, 4); | 22085 | const field_alignment_val = try field_info.fieldValue(mod, 4); |
| 21969 | | 22086 | |
| 21970 | const field_ty = field_type_val.toType(); | 22087 | const field_ty = field_type_val.toType(); |
| 21971 | const field_name = try field_name_val.toIpString(Type.slice_const_u8, mod); | 22088 | // Don't pass a reason; first loop acts as an assertion that this is valid. |
| | 22089 | const field_name = try sema.sliceToIpString(block, src, field_name_val, undefined); |
| 21972 | if (is_tuple) { | 22090 | if (is_tuple) { |
| 21973 | const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail( | 22091 | const field_name_index = field_name.toUnsigned(ip) orelse return sema.fail( |
| 21974 | block, | 22092 | block, |
| ... | @@ -22914,6 +23032,7 @@ fn ptrCastFull( | ... | @@ -22914,6 +23032,7 @@ fn ptrCastFull( |
| 22914 | } | 23032 | } |
| 22915 | | 23033 | |
| 22916 | try sema.requireRuntimeBlock(block, src, null); | 23034 | try sema.requireRuntimeBlock(block, src, null); |
| | 23035 | try sema.validateRuntimeValue(block, operand_src, ptr); |
| 22917 | | 23036 | |
| 22918 | if (block.wantSafety() and operand_ty.ptrAllowsZero(mod) and !dest_ty.ptrAllowsZero(mod) and | 23037 | if (block.wantSafety() and operand_ty.ptrAllowsZero(mod) and !dest_ty.ptrAllowsZero(mod) and |
| 22919 | (try sema.typeHasRuntimeBits(Type.fromInterned(dest_info.child)) or Type.fromInterned(dest_info.child).zigTypeTag(mod) == .Fn)) | 23038 | (try sema.typeHasRuntimeBits(Type.fromInterned(dest_info.child)) or Type.fromInterned(dest_info.child).zigTypeTag(mod) == .Fn)) |
| ... | @@ -22986,7 +23105,7 @@ fn ptrCastFull( | ... | @@ -22986,7 +23105,7 @@ fn ptrCastFull( |
| 22986 | }); | 23105 | }); |
| 22987 | } else { | 23106 | } else { |
| 22988 | assert(dest_ptr_ty.eql(dest_ty, mod)); | 23107 | assert(dest_ptr_ty.eql(dest_ty, mod)); |
| 22989 | try sema.checkKnownAllocPtr(operand, result_ptr); | 23108 | try sema.checkKnownAllocPtr(block, operand, result_ptr); |
| 22990 | return result_ptr; | 23109 | return result_ptr; |
| 22991 | } | 23110 | } |
| 22992 | } | 23111 | } |
| ... | @@ -23022,7 +23141,7 @@ fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst | ... | @@ -23022,7 +23141,7 @@ fn zirPtrCastNoDest(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.Inst |
| 23022 | | 23141 | |
| 23023 | try sema.requireRuntimeBlock(block, src, null); | 23142 | try sema.requireRuntimeBlock(block, src, null); |
| 23024 | const new_ptr = try block.addBitCast(dest_ty, operand); | 23143 | const new_ptr = try block.addBitCast(dest_ty, operand); |
| 23025 | try sema.checkKnownAllocPtr(operand, new_ptr); | 23144 | try sema.checkKnownAllocPtr(block, operand, new_ptr); |
| 23026 | return new_ptr; | 23145 | return new_ptr; |
| 23027 | } | 23146 | } |
| 23028 | | 23147 | |
| ... | @@ -23568,7 +23687,7 @@ fn checkPtrIsNotComptimeMutable( | ... | @@ -23568,7 +23687,7 @@ fn checkPtrIsNotComptimeMutable( |
| 23568 | operand_src: LazySrcLoc, | 23687 | operand_src: LazySrcLoc, |
| 23569 | ) CompileError!void { | 23688 | ) CompileError!void { |
| 23570 | _ = operand_src; | 23689 | _ = operand_src; |
| 23571 | if (ptr_val.isComptimeMutablePtr(sema.mod)) { | 23690 | if (sema.isComptimeMutablePtr(ptr_val)) { |
| 23572 | return sema.fail(block, ptr_src, "cannot store runtime value in compile time variable", .{}); | 23691 | return sema.fail(block, ptr_src, "cannot store runtime value in compile time variable", .{}); |
| 23573 | } | 23692 | } |
| 23574 | } | 23693 | } |
| ... | @@ -23577,9 +23696,10 @@ fn checkComptimeVarStore( | ... | @@ -23577,9 +23696,10 @@ fn checkComptimeVarStore( |
| 23577 | sema: *Sema, | 23696 | sema: *Sema, |
| 23578 | block: *Block, | 23697 | block: *Block, |
| 23579 | src: LazySrcLoc, | 23698 | src: LazySrcLoc, |
| 23580 | decl_ref_mut: InternPool.Key.Ptr.Addr.MutDecl, | 23699 | alloc_index: ComptimeAllocIndex, |
| 23581 | ) CompileError!void { | 23700 | ) CompileError!void { |
| 23582 | if (@intFromEnum(decl_ref_mut.runtime_index) < @intFromEnum(block.runtime_index)) { | 23701 | const runtime_index = sema.getComptimeAlloc(alloc_index).runtime_index; |
| | 23702 | if (@intFromEnum(runtime_index) < @intFromEnum(block.runtime_index)) { |
| 23583 | if (block.runtime_cond) |cond_src| { | 23703 | if (block.runtime_cond) |cond_src| { |
| 23584 | const msg = msg: { | 23704 | const msg = msg: { |
| 23585 | const msg = try sema.errMsg(block, src, "store to comptime variable depends on runtime condition", .{}); | 23705 | const msg = try sema.errMsg(block, src, "store to comptime variable depends on runtime condition", .{}); |
| ... | @@ -24433,7 +24553,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -24433,7 +24553,7 @@ fn zirAtomicRmw(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 24433 | try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src); | 24553 | try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src); |
| 24434 | break :rs operand_src; | 24554 | break :rs operand_src; |
| 24435 | }; | 24555 | }; |
| 24436 | if (ptr_val.isComptimeMutablePtr(mod)) { | 24556 | if (sema.isComptimeMutablePtr(ptr_val)) { |
| 24437 | const ptr_ty = sema.typeOf(ptr); | 24557 | const ptr_ty = sema.typeOf(ptr); |
| 24438 | const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src; | 24558 | const stored_val = (try sema.pointerDeref(block, ptr_src, ptr_val, ptr_ty)) orelse break :rs ptr_src; |
| 24439 | const new_val = switch (op) { | 24559 | const new_val = switch (op) { |
| ... | @@ -25149,7 +25269,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -25149,7 +25269,7 @@ fn zirMemcpy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 25149 | } | 25269 | } |
| 25150 | | 25270 | |
| 25151 | const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: { | 25271 | const runtime_src = if (try sema.resolveDefinedValue(block, dest_src, dest_ptr)) |dest_ptr_val| rs: { |
| 25152 | if (!dest_ptr_val.isComptimeMutablePtr(mod)) break :rs dest_src; | 25272 | if (!sema.isComptimeMutablePtr(dest_ptr_val)) break :rs dest_src; |
| 25153 | if (try sema.resolveDefinedValue(block, src_src, src_ptr)) |_| { | 25273 | if (try sema.resolveDefinedValue(block, src_src, src_ptr)) |_| { |
| 25154 | const len_u64 = (try len_val.?.getUnsignedIntAdvanced(mod, sema)).?; | 25274 | const len_u64 = (try len_val.?.getUnsignedIntAdvanced(mod, sema)).?; |
| 25155 | const len = try sema.usizeCast(block, dest_src, len_u64); | 25275 | const len = try sema.usizeCast(block, dest_src, len_u64); |
| ... | @@ -25342,7 +25462,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void | ... | @@ -25342,7 +25462,7 @@ fn zirMemset(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!void |
| 25342 | return; | 25462 | return; |
| 25343 | } | 25463 | } |
| 25344 | | 25464 | |
| 25345 | if (!ptr_val.isComptimeMutablePtr(mod)) break :rs dest_src; | 25465 | if (!sema.isComptimeMutablePtr(ptr_val)) break :rs dest_src; |
| 25346 | const elem_val = try sema.resolveValue(elem) orelse break :rs value_src; | 25466 | const elem_val = try sema.resolveValue(elem) orelse break :rs value_src; |
| 25347 | const array_ty = try mod.arrayType(.{ | 25467 | const array_ty = try mod.arrayType(.{ |
| 25348 | .child = dest_elem_ty.toIntern(), | 25468 | .child = dest_elem_ty.toIntern(), |
| ... | @@ -25588,7 +25708,9 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A | ... | @@ -25588,7 +25708,9 @@ fn zirFuncFancy(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A |
| 25588 | if (val.isGenericPoison()) { | 25708 | if (val.isGenericPoison()) { |
| 25589 | break :blk .generic; | 25709 | break :blk .generic; |
| 25590 | } | 25710 | } |
| 25591 | break :blk .{ .explicit = try val.toIpString(ty, mod) }; | 25711 | break :blk .{ .explicit = try sema.sliceToIpString(block, section_src, val, .{ |
| | 25712 | .needed_comptime_reason = "linksection must be comptime-known", |
| | 25713 | }) }; |
| 25592 | } else if (extra.data.bits.has_section_ref) blk: { | 25714 | } else if (extra.data.bits.has_section_ref) blk: { |
| 25593 | const section_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); | 25715 | const section_ref: Zir.Inst.Ref = @enumFromInt(sema.code.extra[extra_index]); |
| 25594 | extra_index += 1; | 25716 | extra_index += 1; |
| ... | @@ -27115,7 +27237,7 @@ fn fieldPtr( | ... | @@ -27115,7 +27237,7 @@ fn fieldPtr( |
| 27115 | try sema.requireRuntimeBlock(block, src, null); | 27237 | try sema.requireRuntimeBlock(block, src, null); |
| 27116 | | 27238 | |
| 27117 | const field_ptr = try block.addTyOp(.ptr_slice_ptr_ptr, result_ty, inner_ptr); | 27239 | const field_ptr = try block.addTyOp(.ptr_slice_ptr_ptr, result_ty, inner_ptr); |
| 27118 | try sema.checkKnownAllocPtr(inner_ptr, field_ptr); | 27240 | try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr); |
| 27119 | return field_ptr; | 27241 | return field_ptr; |
| 27120 | } else if (ip.stringEqlSlice(field_name, "len")) { | 27242 | } else if (ip.stringEqlSlice(field_name, "len")) { |
| 27121 | const result_ty = try sema.ptrType(.{ | 27243 | const result_ty = try sema.ptrType(.{ |
| ... | @@ -27139,7 +27261,7 @@ fn fieldPtr( | ... | @@ -27139,7 +27261,7 @@ fn fieldPtr( |
| 27139 | try sema.requireRuntimeBlock(block, src, null); | 27261 | try sema.requireRuntimeBlock(block, src, null); |
| 27140 | | 27262 | |
| 27141 | const field_ptr = try block.addTyOp(.ptr_slice_len_ptr, result_ty, inner_ptr); | 27263 | const field_ptr = try block.addTyOp(.ptr_slice_len_ptr, result_ty, inner_ptr); |
| 27142 | try sema.checkKnownAllocPtr(inner_ptr, field_ptr); | 27264 | try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr); |
| 27143 | return field_ptr; | 27265 | return field_ptr; |
| 27144 | } else { | 27266 | } else { |
| 27145 | return sema.fail( | 27267 | return sema.fail( |
| ... | @@ -27238,7 +27360,7 @@ fn fieldPtr( | ... | @@ -27238,7 +27360,7 @@ fn fieldPtr( |
| 27238 | else | 27360 | else |
| 27239 | object_ptr; | 27361 | object_ptr; |
| 27240 | const field_ptr = try sema.structFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty, initializing); | 27362 | const field_ptr = try sema.structFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty, initializing); |
| 27241 | try sema.checkKnownAllocPtr(inner_ptr, field_ptr); | 27363 | try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr); |
| 27242 | return field_ptr; | 27364 | return field_ptr; |
| 27243 | }, | 27365 | }, |
| 27244 | .Union => { | 27366 | .Union => { |
| ... | @@ -27247,7 +27369,7 @@ fn fieldPtr( | ... | @@ -27247,7 +27369,7 @@ fn fieldPtr( |
| 27247 | else | 27369 | else |
| 27248 | object_ptr; | 27370 | object_ptr; |
| 27249 | const field_ptr = try sema.unionFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty, initializing); | 27371 | const field_ptr = try sema.unionFieldPtr(block, src, inner_ptr, field_name, field_name_src, inner_ty, initializing); |
| 27250 | try sema.checkKnownAllocPtr(inner_ptr, field_ptr); | 27372 | try sema.checkKnownAllocPtr(block, inner_ptr, field_ptr); |
| 27251 | return field_ptr; | 27373 | return field_ptr; |
| 27252 | }, | 27374 | }, |
| 27253 | else => {}, | 27375 | else => {}, |
| ... | @@ -28030,7 +28152,7 @@ fn elemPtr( | ... | @@ -28030,7 +28152,7 @@ fn elemPtr( |
| 28030 | }, | 28152 | }, |
| 28031 | }; | 28153 | }; |
| 28032 | | 28154 | |
| 28033 | try sema.checkKnownAllocPtr(indexable_ptr, elem_ptr); | 28155 | try sema.checkKnownAllocPtr(block, indexable_ptr, elem_ptr); |
| 28034 | return elem_ptr; | 28156 | return elem_ptr; |
| 28035 | } | 28157 | } |
| 28036 | | 28158 | |
| ... | @@ -28083,7 +28205,7 @@ fn elemPtrOneLayerOnly( | ... | @@ -28083,7 +28205,7 @@ fn elemPtrOneLayerOnly( |
| 28083 | }, | 28205 | }, |
| 28084 | else => unreachable, // Guaranteed by checkIndexable | 28206 | else => unreachable, // Guaranteed by checkIndexable |
| 28085 | }; | 28207 | }; |
| 28086 | try sema.checkKnownAllocPtr(indexable, elem_ptr); | 28208 | try sema.checkKnownAllocPtr(block, indexable, elem_ptr); |
| 28087 | return elem_ptr; | 28209 | return elem_ptr; |
| 28088 | }, | 28210 | }, |
| 28089 | } | 28211 | } |
| ... | @@ -28617,7 +28739,7 @@ fn coerceExtra( | ... | @@ -28617,7 +28739,7 @@ fn coerceExtra( |
| 28617 | try sema.requireRuntimeBlock(block, inst_src, null); | 28739 | try sema.requireRuntimeBlock(block, inst_src, null); |
| 28618 | try sema.queueFullTypeResolution(dest_ty); | 28740 | try sema.queueFullTypeResolution(dest_ty); |
| 28619 | const new_val = try block.addBitCast(dest_ty, inst); | 28741 | const new_val = try block.addBitCast(dest_ty, inst); |
| 28620 | try sema.checkKnownAllocPtr(inst, new_val); | 28742 | try sema.checkKnownAllocPtr(block, inst, new_val); |
| 28621 | return new_val; | 28743 | return new_val; |
| 28622 | } | 28744 | } |
| 28623 | | 28745 | |
| ... | @@ -30349,7 +30471,7 @@ fn storePtr2( | ... | @@ -30349,7 +30471,7 @@ fn storePtr2( |
| 30349 | try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src); | 30471 | try sema.checkPtrIsNotComptimeMutable(block, ptr_val, ptr_src, operand_src); |
| 30350 | break :rs operand_src; | 30472 | break :rs operand_src; |
| 30351 | }; | 30473 | }; |
| 30352 | if (ptr_val.isComptimeMutablePtr(mod)) { | 30474 | if (sema.isComptimeMutablePtr(ptr_val)) { |
| 30353 | try sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty); | 30475 | try sema.storePtrVal(block, src, ptr_val, operand_val, elem_ty); |
| 30354 | return; | 30476 | return; |
| 30355 | } else break :rs ptr_src; | 30477 | } else break :rs ptr_src; |
| ... | @@ -30392,7 +30514,7 @@ fn storePtr2( | ... | @@ -30392,7 +30514,7 @@ fn storePtr2( |
| 30392 | else | 30514 | else |
| 30393 | try block.addBinOp(air_tag, ptr, operand); | 30515 | try block.addBinOp(air_tag, ptr, operand); |
| 30394 | | 30516 | |
| 30395 | try sema.checkComptimeKnownStore(block, store_inst); | 30517 | try sema.checkComptimeKnownStore(block, store_inst, operand_src); |
| 30396 | | 30518 | |
| 30397 | return; | 30519 | return; |
| 30398 | } | 30520 | } |
| ... | @@ -30400,29 +30522,39 @@ fn storePtr2( | ... | @@ -30400,29 +30522,39 @@ fn storePtr2( |
| 30400 | /// Given an AIR store instruction, checks whether we are performing a | 30522 | /// Given an AIR store instruction, checks whether we are performing a |
| 30401 | /// comptime-known store to a local alloc, and updates `maybe_comptime_allocs` | 30523 | /// comptime-known store to a local alloc, and updates `maybe_comptime_allocs` |
| 30402 | /// accordingly. | 30524 | /// accordingly. |
| 30403 | fn checkComptimeKnownStore(sema: *Sema, block: *Block, store_inst_ref: Air.Inst.Ref) !void { | 30525 | /// Handles calling `validateRuntimeValue` if the store is runtime for any reason. |
| | 30526 | fn checkComptimeKnownStore(sema: *Sema, block: *Block, store_inst_ref: Air.Inst.Ref, store_src: LazySrcLoc) !void { |
| 30404 | const store_inst = store_inst_ref.toIndex().?; | 30527 | const store_inst = store_inst_ref.toIndex().?; |
| 30405 | const inst_data = sema.air_instructions.items(.data)[@intFromEnum(store_inst)].bin_op; | 30528 | const inst_data = sema.air_instructions.items(.data)[@intFromEnum(store_inst)].bin_op; |
| 30406 | const ptr = inst_data.lhs.toIndex() orelse return; | 30529 | const ptr = inst_data.lhs.toIndex() orelse return; |
| 30407 | const operand = inst_data.rhs; | 30530 | const operand = inst_data.rhs; |
| 30408 | | 30531 | |
| 30409 | const maybe_base_alloc = sema.base_allocs.get(ptr) orelse return; | 30532 | known: { |
| 30410 | const maybe_comptime_alloc = sema.maybe_comptime_allocs.getPtr(maybe_base_alloc) orelse return; | 30533 | const maybe_base_alloc = sema.base_allocs.get(ptr) orelse break :known; |
| | 30534 | const maybe_comptime_alloc = sema.maybe_comptime_allocs.getPtr(maybe_base_alloc) orelse break :known; |
| 30411 | | 30535 | |
| 30412 | ct: { | 30536 | if ((try sema.resolveValue(operand)) != null and |
| 30413 | if (null == try sema.resolveValue(operand)) break :ct; | 30537 | block.runtime_index == maybe_comptime_alloc.runtime_index) |
| 30414 | if (maybe_comptime_alloc.runtime_index != block.runtime_index) break :ct; | 30538 | { |
| 30415 | return maybe_comptime_alloc.stores.append(sema.arena, store_inst); | 30539 | try maybe_comptime_alloc.stores.append(sema.arena, .{ |
| | 30540 | .inst = store_inst, |
| | 30541 | .src_decl = block.src_decl, |
| | 30542 | .src = store_src, |
| | 30543 | }); |
| | 30544 | return; |
| | 30545 | } |
| | 30546 | |
| | 30547 | // We're newly discovering that this alloc is runtime-known. |
| | 30548 | try sema.markMaybeComptimeAllocRuntime(block, maybe_base_alloc); |
| 30416 | } | 30549 | } |
| 30417 | | 30550 | |
| 30418 | // Store is runtime-known | 30551 | try sema.validateRuntimeValue(block, store_src, operand); |
| 30419 | _ = sema.maybe_comptime_allocs.remove(maybe_base_alloc); | | |
| 30420 | } | 30552 | } |
| 30421 | | 30553 | |
| 30422 | /// Given an AIR instruction transforming a pointer (struct_field_ptr, | 30554 | /// Given an AIR instruction transforming a pointer (struct_field_ptr, |
| 30423 | /// ptr_elem_ptr, bitcast, etc), checks whether the base pointer refers to a | 30555 | /// ptr_elem_ptr, bitcast, etc), checks whether the base pointer refers to a |
| 30424 | /// local alloc, and updates `base_allocs` accordingly. | 30556 | /// local alloc, and updates `base_allocs` accordingly. |
| 30425 | fn checkKnownAllocPtr(sema: *Sema, base_ptr: Air.Inst.Ref, new_ptr: Air.Inst.Ref) !void { | 30557 | fn checkKnownAllocPtr(sema: *Sema, block: *Block, base_ptr: Air.Inst.Ref, new_ptr: Air.Inst.Ref) !void { |
| 30426 | const base_ptr_inst = base_ptr.toIndex() orelse return; | 30558 | const base_ptr_inst = base_ptr.toIndex() orelse return; |
| 30427 | const new_ptr_inst = new_ptr.toIndex() orelse return; | 30559 | const new_ptr_inst = new_ptr.toIndex() orelse return; |
| 30428 | const alloc_inst = sema.base_allocs.get(base_ptr_inst) orelse return; | 30560 | const alloc_inst = sema.base_allocs.get(base_ptr_inst) orelse return; |
| ... | @@ -30442,13 +30574,34 @@ fn checkKnownAllocPtr(sema: *Sema, base_ptr: Air.Inst.Ref, new_ptr: Air.Inst.Ref | ... | @@ -30442,13 +30574,34 @@ fn checkKnownAllocPtr(sema: *Sema, base_ptr: Air.Inst.Ref, new_ptr: Air.Inst.Ref |
| 30442 | // If the index value is runtime-known, this pointer is also runtime-known, so | 30574 | // If the index value is runtime-known, this pointer is also runtime-known, so |
| 30443 | // we must in turn make the alloc value runtime-known. | 30575 | // we must in turn make the alloc value runtime-known. |
| 30444 | if (null == try sema.resolveValue(index_ref)) { | 30576 | if (null == try sema.resolveValue(index_ref)) { |
| 30445 | _ = sema.maybe_comptime_allocs.remove(alloc_inst); | 30577 | try sema.markMaybeComptimeAllocRuntime(block, alloc_inst); |
| 30446 | } | 30578 | } |
| 30447 | }, | 30579 | }, |
| 30448 | else => {}, | 30580 | else => {}, |
| 30449 | } | 30581 | } |
| 30450 | } | 30582 | } |
| 30451 | | 30583 | |
| | 30584 | fn markMaybeComptimeAllocRuntime(sema: *Sema, block: *Block, alloc_inst: Air.Inst.Index) CompileError!void { |
| | 30585 | const maybe_comptime_alloc = (sema.maybe_comptime_allocs.fetchRemove(alloc_inst) orelse return).value; |
| | 30586 | // Since the alloc has been determined to be runtime, we must check that |
| | 30587 | // all other stores to it are permitted to be runtime values. |
| | 30588 | const mod = sema.mod; |
| | 30589 | const slice = maybe_comptime_alloc.stores.slice(); |
| | 30590 | for (slice.items(.inst), slice.items(.src_decl), slice.items(.src)) |other_inst, other_src_decl, other_src| { |
| | 30591 | const other_data = sema.air_instructions.items(.data)[@intFromEnum(other_inst)].bin_op; |
| | 30592 | const other_operand = other_data.rhs; |
| | 30593 | if (!sema.checkRuntimeValue(other_operand)) { |
| | 30594 | return sema.failWithOwnedErrorMsg(block, msg: { |
| | 30595 | const other_src_resolved = mod.declPtr(other_src_decl).toSrcLoc(other_src, mod); |
| | 30596 | const msg = try Module.ErrorMsg.create(sema.gpa, other_src_resolved, "runtime value contains reference to comptime var", .{}); |
| | 30597 | errdefer msg.destroy(sema.gpa); |
| | 30598 | try mod.errNoteNonLazy(other_src_resolved, msg, "comptime var pointers are not available at runtime", .{}); |
| | 30599 | break :msg msg; |
| | 30600 | }); |
| | 30601 | } |
| | 30602 | } |
| | 30603 | } |
| | 30604 | |
| 30452 | /// Traverse an arbitrary number of bitcasted pointers and return the underyling vector | 30605 | /// Traverse an arbitrary number of bitcasted pointers and return the underyling vector |
| 30453 | /// pointer. Only if the final element type matches the vector element type, and the | 30606 | /// pointer. Only if the final element type matches the vector element type, and the |
| 30454 | /// lengths match. | 30607 | /// lengths match. |
| ... | @@ -30491,13 +30644,16 @@ fn storePtrVal( | ... | @@ -30491,13 +30644,16 @@ fn storePtrVal( |
| 30491 | ) !void { | 30644 | ) !void { |
| 30492 | const mod = sema.mod; | 30645 | const mod = sema.mod; |
| 30493 | var mut_kit = try sema.beginComptimePtrMutation(block, src, ptr_val, operand_ty); | 30646 | var mut_kit = try sema.beginComptimePtrMutation(block, src, ptr_val, operand_ty); |
| 30494 | try sema.checkComptimeVarStore(block, src, mut_kit.mut_decl); | 30647 | switch (mut_kit.root) { |
| | 30648 | .alloc => |a| try sema.checkComptimeVarStore(block, src, a), |
| | 30649 | .comptime_field => {}, |
| | 30650 | } |
| 30495 | | 30651 | |
| 30496 | try sema.resolveTypeLayout(operand_ty); | 30652 | try sema.resolveTypeLayout(operand_ty); |
| 30497 | switch (mut_kit.pointee) { | 30653 | switch (mut_kit.pointee) { |
| 30498 | .opv => {}, | 30654 | .opv => {}, |
| 30499 | .direct => |val_ptr| { | 30655 | .direct => |val_ptr| { |
| 30500 | if (mut_kit.mut_decl.runtime_index == .comptime_field_ptr) { | 30656 | if (mut_kit.root == .comptime_field) { |
| 30501 | val_ptr.* = Value.fromInterned((try val_ptr.intern(operand_ty, mod))); | 30657 | val_ptr.* = Value.fromInterned((try val_ptr.intern(operand_ty, mod))); |
| 30502 | if (!operand_val.eql(val_ptr.*, operand_ty, mod)) { | 30658 | if (!operand_val.eql(val_ptr.*, operand_ty, mod)) { |
| 30503 | // TODO use failWithInvalidComptimeFieldStore | 30659 | // TODO use failWithInvalidComptimeFieldStore |
| ... | @@ -30552,7 +30708,11 @@ fn storePtrVal( | ... | @@ -30552,7 +30708,11 @@ fn storePtrVal( |
| 30552 | } | 30708 | } |
| 30553 | | 30709 | |
| 30554 | const ComptimePtrMutationKit = struct { | 30710 | const ComptimePtrMutationKit = struct { |
| 30555 | mut_decl: InternPool.Key.Ptr.Addr.MutDecl, | 30711 | const Root = union(enum) { |
| | 30712 | alloc: ComptimeAllocIndex, |
| | 30713 | comptime_field, |
| | 30714 | }; |
| | 30715 | root: Root, |
| 30556 | pointee: union(enum) { | 30716 | pointee: union(enum) { |
| 30557 | opv, | 30717 | opv, |
| 30558 | /// The pointer type matches the actual comptime Value so a direct | 30718 | /// The pointer type matches the actual comptime Value so a direct |
| ... | @@ -30591,17 +30751,21 @@ fn beginComptimePtrMutation( | ... | @@ -30591,17 +30751,21 @@ fn beginComptimePtrMutation( |
| 30591 | const ptr = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr; | 30751 | const ptr = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr; |
| 30592 | switch (ptr.addr) { | 30752 | switch (ptr.addr) { |
| 30593 | .decl, .anon_decl, .int => unreachable, // isComptimeMutablePtr has been checked already | 30753 | .decl, .anon_decl, .int => unreachable, // isComptimeMutablePtr has been checked already |
| 30594 | .mut_decl => |mut_decl| { | 30754 | .comptime_alloc => |alloc_index| { |
| 30595 | const decl = mod.declPtr(mut_decl.decl); | 30755 | const alloc = sema.getComptimeAlloc(alloc_index); |
| 30596 | return sema.beginComptimePtrMutationInner(block, src, decl.ty, &decl.val, ptr_elem_ty, mut_decl); | 30756 | return sema.beginComptimePtrMutationInner(block, src, alloc.ty, &alloc.val, ptr_elem_ty, .{ .alloc = alloc_index }); |
| 30597 | }, | 30757 | }, |
| 30598 | .comptime_field => |comptime_field| { | 30758 | .comptime_field => |comptime_field| { |
| 30599 | const duped = try sema.arena.create(Value); | 30759 | const duped = try sema.arena.create(Value); |
| 30600 | duped.* = Value.fromInterned(comptime_field); | 30760 | duped.* = Value.fromInterned(comptime_field); |
| 30601 | return sema.beginComptimePtrMutationInner(block, src, Type.fromInterned(mod.intern_pool.typeOf(comptime_field)), duped, ptr_elem_ty, .{ | 30761 | return sema.beginComptimePtrMutationInner( |
| 30602 | .decl = undefined, | 30762 | block, |
| 30603 | .runtime_index = .comptime_field_ptr, | 30763 | src, |
| 30604 | }); | 30764 | Type.fromInterned(mod.intern_pool.typeOf(comptime_field)), |
| | 30765 | duped, |
| | 30766 | ptr_elem_ty, |
| | 30767 | .comptime_field, |
| | 30768 | ); |
| 30605 | }, | 30769 | }, |
| 30606 | .eu_payload => |eu_ptr| { | 30770 | .eu_payload => |eu_ptr| { |
| 30607 | const eu_ty = Type.fromInterned(mod.intern_pool.typeOf(eu_ptr)).childType(mod); | 30771 | const eu_ty = Type.fromInterned(mod.intern_pool.typeOf(eu_ptr)).childType(mod); |
| ... | @@ -30612,7 +30776,7 @@ fn beginComptimePtrMutation( | ... | @@ -30612,7 +30776,7 @@ fn beginComptimePtrMutation( |
| 30612 | const payload_ty = parent.ty.errorUnionPayload(mod); | 30776 | const payload_ty = parent.ty.errorUnionPayload(mod); |
| 30613 | if (val_ptr.ip_index == .none and val_ptr.tag() == .eu_payload) { | 30777 | if (val_ptr.ip_index == .none and val_ptr.tag() == .eu_payload) { |
| 30614 | return ComptimePtrMutationKit{ | 30778 | return ComptimePtrMutationKit{ |
| 30615 | .mut_decl = parent.mut_decl, | 30779 | .root = parent.root, |
| 30616 | .pointee = .{ .direct = &val_ptr.castTag(.eu_payload).?.data }, | 30780 | .pointee = .{ .direct = &val_ptr.castTag(.eu_payload).?.data }, |
| 30617 | .ty = payload_ty, | 30781 | .ty = payload_ty, |
| 30618 | }; | 30782 | }; |
| ... | @@ -30630,7 +30794,7 @@ fn beginComptimePtrMutation( | ... | @@ -30630,7 +30794,7 @@ fn beginComptimePtrMutation( |
| 30630 | val_ptr.* = Value.initPayload(&payload.base); | 30794 | val_ptr.* = Value.initPayload(&payload.base); |
| 30631 | | 30795 | |
| 30632 | return ComptimePtrMutationKit{ | 30796 | return ComptimePtrMutationKit{ |
| 30633 | .mut_decl = parent.mut_decl, | 30797 | .root = parent.root, |
| 30634 | .pointee = .{ .direct = &payload.data }, | 30798 | .pointee = .{ .direct = &payload.data }, |
| 30635 | .ty = payload_ty, | 30799 | .ty = payload_ty, |
| 30636 | }; | 30800 | }; |
| ... | @@ -30640,7 +30804,7 @@ fn beginComptimePtrMutation( | ... | @@ -30640,7 +30804,7 @@ fn beginComptimePtrMutation( |
| 30640 | // Even though the parent value type has well-defined memory layout, our | 30804 | // Even though the parent value type has well-defined memory layout, our |
| 30641 | // pointer type does not. | 30805 | // pointer type does not. |
| 30642 | .reinterpret => return ComptimePtrMutationKit{ | 30806 | .reinterpret => return ComptimePtrMutationKit{ |
| 30643 | .mut_decl = parent.mut_decl, | 30807 | .root = parent.root, |
| 30644 | .pointee = .bad_ptr_ty, | 30808 | .pointee = .bad_ptr_ty, |
| 30645 | .ty = eu_ty, | 30809 | .ty = eu_ty, |
| 30646 | }, | 30810 | }, |
| ... | @@ -30655,7 +30819,7 @@ fn beginComptimePtrMutation( | ... | @@ -30655,7 +30819,7 @@ fn beginComptimePtrMutation( |
| 30655 | const payload_ty = parent.ty.optionalChild(mod); | 30819 | const payload_ty = parent.ty.optionalChild(mod); |
| 30656 | switch (val_ptr.ip_index) { | 30820 | switch (val_ptr.ip_index) { |
| 30657 | .none => return ComptimePtrMutationKit{ | 30821 | .none => return ComptimePtrMutationKit{ |
| 30658 | .mut_decl = parent.mut_decl, | 30822 | .root = parent.root, |
| 30659 | .pointee = .{ .direct = &val_ptr.castTag(.opt_payload).?.data }, | 30823 | .pointee = .{ .direct = &val_ptr.castTag(.opt_payload).?.data }, |
| 30660 | .ty = payload_ty, | 30824 | .ty = payload_ty, |
| 30661 | }, | 30825 | }, |
| ... | @@ -30682,7 +30846,7 @@ fn beginComptimePtrMutation( | ... | @@ -30682,7 +30846,7 @@ fn beginComptimePtrMutation( |
| 30682 | val_ptr.* = Value.initPayload(&payload.base); | 30846 | val_ptr.* = Value.initPayload(&payload.base); |
| 30683 | | 30847 | |
| 30684 | return ComptimePtrMutationKit{ | 30848 | return ComptimePtrMutationKit{ |
| 30685 | .mut_decl = parent.mut_decl, | 30849 | .root = parent.root, |
| 30686 | .pointee = .{ .direct = &payload.data }, | 30850 | .pointee = .{ .direct = &payload.data }, |
| 30687 | .ty = payload_ty, | 30851 | .ty = payload_ty, |
| 30688 | }; | 30852 | }; |
| ... | @@ -30693,7 +30857,7 @@ fn beginComptimePtrMutation( | ... | @@ -30693,7 +30857,7 @@ fn beginComptimePtrMutation( |
| 30693 | // Even though the parent value type has well-defined memory layout, our | 30857 | // Even though the parent value type has well-defined memory layout, our |
| 30694 | // pointer type does not. | 30858 | // pointer type does not. |
| 30695 | .reinterpret => return ComptimePtrMutationKit{ | 30859 | .reinterpret => return ComptimePtrMutationKit{ |
| 30696 | .mut_decl = parent.mut_decl, | 30860 | .root = parent.root, |
| 30697 | .pointee = .bad_ptr_ty, | 30861 | .pointee = .bad_ptr_ty, |
| 30698 | .ty = opt_ty, | 30862 | .ty = opt_ty, |
| 30699 | }, | 30863 | }, |
| ... | @@ -30717,7 +30881,7 @@ fn beginComptimePtrMutation( | ... | @@ -30717,7 +30881,7 @@ fn beginComptimePtrMutation( |
| 30717 | }); | 30881 | }); |
| 30718 | } | 30882 | } |
| 30719 | return .{ | 30883 | return .{ |
| 30720 | .mut_decl = parent.mut_decl, | 30884 | .root = parent.root, |
| 30721 | .pointee = .opv, | 30885 | .pointee = .opv, |
| 30722 | .ty = elem_ty, | 30886 | .ty = elem_ty, |
| 30723 | }; | 30887 | }; |
| ... | @@ -30742,7 +30906,7 @@ fn beginComptimePtrMutation( | ... | @@ -30742,7 +30906,7 @@ fn beginComptimePtrMutation( |
| 30742 | const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64); | 30906 | const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64); |
| 30743 | const elem_idx = try sema.usizeCast(block, src, elem_ptr.index); | 30907 | const elem_idx = try sema.usizeCast(block, src, elem_ptr.index); |
| 30744 | return .{ | 30908 | return .{ |
| 30745 | .mut_decl = parent.mut_decl, | 30909 | .root = parent.root, |
| 30746 | .pointee = .{ .reinterpret = .{ | 30910 | .pointee = .{ .reinterpret = .{ |
| 30747 | .val_ptr = val_ptr, | 30911 | .val_ptr = val_ptr, |
| 30748 | .byte_offset = elem_abi_size * elem_idx, | 30912 | .byte_offset = elem_abi_size * elem_idx, |
| ... | @@ -30759,7 +30923,7 @@ fn beginComptimePtrMutation( | ... | @@ -30759,7 +30923,7 @@ fn beginComptimePtrMutation( |
| 30759 | // If we wanted to avoid this, there would need to be special detection | 30923 | // If we wanted to avoid this, there would need to be special detection |
| 30760 | // elsewhere to identify when writing a value to an array element that is stored | 30924 | // elsewhere to identify when writing a value to an array element that is stored |
| 30761 | // using the `bytes` tag, and handle it without making a call to this function. | 30925 | // using the `bytes` tag, and handle it without making a call to this function. |
| 30762 | const arena = mod.tmp_hack_arena.allocator(); | 30926 | const arena = sema.arena; |
| 30763 | | 30927 | |
| 30764 | const bytes = val_ptr.castTag(.bytes).?.data; | 30928 | const bytes = val_ptr.castTag(.bytes).?.data; |
| 30765 | const dest_len = parent.ty.arrayLenIncludingSentinel(mod); | 30929 | const dest_len = parent.ty.arrayLenIncludingSentinel(mod); |
| ... | @@ -30780,7 +30944,7 @@ fn beginComptimePtrMutation( | ... | @@ -30780,7 +30944,7 @@ fn beginComptimePtrMutation( |
| 30780 | elem_ty, | 30944 | elem_ty, |
| 30781 | &elems[@intCast(elem_ptr.index)], | 30945 | &elems[@intCast(elem_ptr.index)], |
| 30782 | ptr_elem_ty, | 30946 | ptr_elem_ty, |
| 30783 | parent.mut_decl, | 30947 | parent.root, |
| 30784 | ); | 30948 | ); |
| 30785 | }, | 30949 | }, |
| 30786 | .repeated => { | 30950 | .repeated => { |
| ... | @@ -30791,7 +30955,7 @@ fn beginComptimePtrMutation( | ... | @@ -30791,7 +30955,7 @@ fn beginComptimePtrMutation( |
| 30791 | // need to be special detection elsewhere to identify when writing a value to an | 30955 | // need to be special detection elsewhere to identify when writing a value to an |
| 30792 | // array element that is stored using the `repeated` tag, and handle it | 30956 | // array element that is stored using the `repeated` tag, and handle it |
| 30793 | // without making a call to this function. | 30957 | // without making a call to this function. |
| 30794 | const arena = mod.tmp_hack_arena.allocator(); | 30958 | const arena = sema.arena; |
| 30795 | | 30959 | |
| 30796 | const repeated_val = try val_ptr.castTag(.repeated).?.data.intern(parent.ty.childType(mod), mod); | 30960 | const repeated_val = try val_ptr.castTag(.repeated).?.data.intern(parent.ty.childType(mod), mod); |
| 30797 | const array_len_including_sentinel = | 30961 | const array_len_including_sentinel = |
| ... | @@ -30808,7 +30972,7 @@ fn beginComptimePtrMutation( | ... | @@ -30808,7 +30972,7 @@ fn beginComptimePtrMutation( |
| 30808 | elem_ty, | 30972 | elem_ty, |
| 30809 | &elems[@intCast(elem_ptr.index)], | 30973 | &elems[@intCast(elem_ptr.index)], |
| 30810 | ptr_elem_ty, | 30974 | ptr_elem_ty, |
| 30811 | parent.mut_decl, | 30975 | parent.root, |
| 30812 | ); | 30976 | ); |
| 30813 | }, | 30977 | }, |
| 30814 | | 30978 | |
| ... | @@ -30819,7 +30983,7 @@ fn beginComptimePtrMutation( | ... | @@ -30819,7 +30983,7 @@ fn beginComptimePtrMutation( |
| 30819 | elem_ty, | 30983 | elem_ty, |
| 30820 | &val_ptr.castTag(.aggregate).?.data[@intCast(elem_ptr.index)], | 30984 | &val_ptr.castTag(.aggregate).?.data[@intCast(elem_ptr.index)], |
| 30821 | ptr_elem_ty, | 30985 | ptr_elem_ty, |
| 30822 | parent.mut_decl, | 30986 | parent.root, |
| 30823 | ), | 30987 | ), |
| 30824 | | 30988 | |
| 30825 | else => unreachable, | 30989 | else => unreachable, |
| ... | @@ -30829,7 +30993,7 @@ fn beginComptimePtrMutation( | ... | @@ -30829,7 +30993,7 @@ fn beginComptimePtrMutation( |
| 30829 | // An array has been initialized to undefined at comptime and now we | 30993 | // An array has been initialized to undefined at comptime and now we |
| 30830 | // are for the first time setting an element. We must change the representation | 30994 | // are for the first time setting an element. We must change the representation |
| 30831 | // of the array from `undef` to `array`. | 30995 | // of the array from `undef` to `array`. |
| 30832 | const arena = mod.tmp_hack_arena.allocator(); | 30996 | const arena = sema.arena; |
| 30833 | | 30997 | |
| 30834 | const array_len_including_sentinel = | 30998 | const array_len_including_sentinel = |
| 30835 | try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod)); | 30999 | try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod)); |
| ... | @@ -30845,7 +31009,7 @@ fn beginComptimePtrMutation( | ... | @@ -30845,7 +31009,7 @@ fn beginComptimePtrMutation( |
| 30845 | elem_ty, | 31009 | elem_ty, |
| 30846 | &elems[@intCast(elem_ptr.index)], | 31010 | &elems[@intCast(elem_ptr.index)], |
| 30847 | ptr_elem_ty, | 31011 | ptr_elem_ty, |
| 30848 | parent.mut_decl, | 31012 | parent.root, |
| 30849 | ); | 31013 | ); |
| 30850 | }, | 31014 | }, |
| 30851 | else => unreachable, | 31015 | else => unreachable, |
| ... | @@ -30866,7 +31030,7 @@ fn beginComptimePtrMutation( | ... | @@ -30866,7 +31030,7 @@ fn beginComptimePtrMutation( |
| 30866 | parent.ty, | 31030 | parent.ty, |
| 30867 | val_ptr, | 31031 | val_ptr, |
| 30868 | ptr_elem_ty, | 31032 | ptr_elem_ty, |
| 30869 | parent.mut_decl, | 31033 | parent.root, |
| 30870 | ); | 31034 | ); |
| 30871 | }, | 31035 | }, |
| 30872 | }, | 31036 | }, |
| ... | @@ -30875,7 +31039,7 @@ fn beginComptimePtrMutation( | ... | @@ -30875,7 +31039,7 @@ fn beginComptimePtrMutation( |
| 30875 | // Even though the parent value type has well-defined memory layout, our | 31039 | // Even though the parent value type has well-defined memory layout, our |
| 30876 | // pointer type does not. | 31040 | // pointer type does not. |
| 30877 | return ComptimePtrMutationKit{ | 31041 | return ComptimePtrMutationKit{ |
| 30878 | .mut_decl = parent.mut_decl, | 31042 | .root = parent.root, |
| 30879 | .pointee = .bad_ptr_ty, | 31043 | .pointee = .bad_ptr_ty, |
| 30880 | .ty = base_elem_ty, | 31044 | .ty = base_elem_ty, |
| 30881 | }; | 31045 | }; |
| ... | @@ -30885,7 +31049,7 @@ fn beginComptimePtrMutation( | ... | @@ -30885,7 +31049,7 @@ fn beginComptimePtrMutation( |
| 30885 | const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64); | 31049 | const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64); |
| 30886 | const elem_idx = try sema.usizeCast(block, src, elem_ptr.index); | 31050 | const elem_idx = try sema.usizeCast(block, src, elem_ptr.index); |
| 30887 | return ComptimePtrMutationKit{ | 31051 | return ComptimePtrMutationKit{ |
| 30888 | .mut_decl = parent.mut_decl, | 31052 | .root = parent.root, |
| 30889 | .pointee = .{ .reinterpret = .{ | 31053 | .pointee = .{ .reinterpret = .{ |
| 30890 | .val_ptr = reinterpret.val_ptr, | 31054 | .val_ptr = reinterpret.val_ptr, |
| 30891 | .byte_offset = reinterpret.byte_offset + elem_abi_size * elem_idx, | 31055 | .byte_offset = reinterpret.byte_offset + elem_abi_size * elem_idx, |
| ... | @@ -30914,7 +31078,7 @@ fn beginComptimePtrMutation( | ... | @@ -30914,7 +31078,7 @@ fn beginComptimePtrMutation( |
| 30914 | parent.ty.structFieldType(field_index, mod), | 31078 | parent.ty.structFieldType(field_index, mod), |
| 30915 | duped, | 31079 | duped, |
| 30916 | ptr_elem_ty, | 31080 | ptr_elem_ty, |
| 30917 | parent.mut_decl, | 31081 | parent.root, |
| 30918 | ); | 31082 | ); |
| 30919 | }, | 31083 | }, |
| 30920 | .none => switch (val_ptr.tag()) { | 31084 | .none => switch (val_ptr.tag()) { |
| ... | @@ -30925,10 +31089,10 @@ fn beginComptimePtrMutation( | ... | @@ -30925,10 +31089,10 @@ fn beginComptimePtrMutation( |
| 30925 | parent.ty.structFieldType(field_index, mod), | 31089 | parent.ty.structFieldType(field_index, mod), |
| 30926 | &val_ptr.castTag(.aggregate).?.data[field_index], | 31090 | &val_ptr.castTag(.aggregate).?.data[field_index], |
| 30927 | ptr_elem_ty, | 31091 | ptr_elem_ty, |
| 30928 | parent.mut_decl, | 31092 | parent.root, |
| 30929 | ), | 31093 | ), |
| 30930 | .repeated => { | 31094 | .repeated => { |
| 30931 | const arena = mod.tmp_hack_arena.allocator(); | 31095 | const arena = sema.arena; |
| 30932 | | 31096 | |
| 30933 | const elems = try arena.alloc(Value, parent.ty.structFieldCount(mod)); | 31097 | const elems = try arena.alloc(Value, parent.ty.structFieldCount(mod)); |
| 30934 | @memset(elems, val_ptr.castTag(.repeated).?.data); | 31098 | @memset(elems, val_ptr.castTag(.repeated).?.data); |
| ... | @@ -30941,7 +31105,7 @@ fn beginComptimePtrMutation( | ... | @@ -30941,7 +31105,7 @@ fn beginComptimePtrMutation( |
| 30941 | parent.ty.structFieldType(field_index, mod), | 31105 | parent.ty.structFieldType(field_index, mod), |
| 30942 | &elems[field_index], | 31106 | &elems[field_index], |
| 30943 | ptr_elem_ty, | 31107 | ptr_elem_ty, |
| 30944 | parent.mut_decl, | 31108 | parent.root, |
| 30945 | ); | 31109 | ); |
| 30946 | }, | 31110 | }, |
| 30947 | .@"union" => { | 31111 | .@"union" => { |
| ... | @@ -30962,7 +31126,7 @@ fn beginComptimePtrMutation( | ... | @@ -30962,7 +31126,7 @@ fn beginComptimePtrMutation( |
| 30962 | field_ty, | 31126 | field_ty, |
| 30963 | &payload.val, | 31127 | &payload.val, |
| 30964 | ptr_elem_ty, | 31128 | ptr_elem_ty, |
| 30965 | parent.mut_decl, | 31129 | parent.root, |
| 30966 | ); | 31130 | ); |
| 30967 | } else { | 31131 | } else { |
| 30968 | // Writing to a different field (a different or unknown tag is active) requires reinterpreting | 31132 | // Writing to a different field (a different or unknown tag is active) requires reinterpreting |
| ... | @@ -30973,7 +31137,7 @@ fn beginComptimePtrMutation( | ... | @@ -30973,7 +31137,7 @@ fn beginComptimePtrMutation( |
| 30973 | // The reinterpretation will read it back out as .none. | 31137 | // The reinterpretation will read it back out as .none. |
| 30974 | payload.val = try payload.val.unintern(sema.arena, mod); | 31138 | payload.val = try payload.val.unintern(sema.arena, mod); |
| 30975 | return ComptimePtrMutationKit{ | 31139 | return ComptimePtrMutationKit{ |
| 30976 | .mut_decl = parent.mut_decl, | 31140 | .root = parent.root, |
| 30977 | .pointee = .{ .reinterpret = .{ | 31141 | .pointee = .{ .reinterpret = .{ |
| 30978 | .val_ptr = val_ptr, | 31142 | .val_ptr = val_ptr, |
| 30979 | .byte_offset = 0, | 31143 | .byte_offset = 0, |
| ... | @@ -30991,7 +31155,7 @@ fn beginComptimePtrMutation( | ... | @@ -30991,7 +31155,7 @@ fn beginComptimePtrMutation( |
| 30991 | parent.ty.slicePtrFieldType(mod), | 31155 | parent.ty.slicePtrFieldType(mod), |
| 30992 | &val_ptr.castTag(.slice).?.data.ptr, | 31156 | &val_ptr.castTag(.slice).?.data.ptr, |
| 30993 | ptr_elem_ty, | 31157 | ptr_elem_ty, |
| 30994 | parent.mut_decl, | 31158 | parent.root, |
| 30995 | ), | 31159 | ), |
| 30996 | | 31160 | |
| 30997 | Value.slice_len_index => return beginComptimePtrMutationInner( | 31161 | Value.slice_len_index => return beginComptimePtrMutationInner( |
| ... | @@ -31001,7 +31165,7 @@ fn beginComptimePtrMutation( | ... | @@ -31001,7 +31165,7 @@ fn beginComptimePtrMutation( |
| 31001 | Type.usize, | 31165 | Type.usize, |
| 31002 | &val_ptr.castTag(.slice).?.data.len, | 31166 | &val_ptr.castTag(.slice).?.data.len, |
| 31003 | ptr_elem_ty, | 31167 | ptr_elem_ty, |
| 31004 | parent.mut_decl, | 31168 | parent.root, |
| 31005 | ), | 31169 | ), |
| 31006 | | 31170 | |
| 31007 | else => unreachable, | 31171 | else => unreachable, |
| ... | @@ -31013,7 +31177,7 @@ fn beginComptimePtrMutation( | ... | @@ -31013,7 +31177,7 @@ fn beginComptimePtrMutation( |
| 31013 | // A struct or union has been initialized to undefined at comptime and now we | 31177 | // A struct or union has been initialized to undefined at comptime and now we |
| 31014 | // are for the first time setting a field. We must change the representation | 31178 | // are for the first time setting a field. We must change the representation |
| 31015 | // of the struct/union from `undef` to `struct`/`union`. | 31179 | // of the struct/union from `undef` to `struct`/`union`. |
| 31016 | const arena = mod.tmp_hack_arena.allocator(); | 31180 | const arena = sema.arena; |
| 31017 | | 31181 | |
| 31018 | switch (parent.ty.zigTypeTag(mod)) { | 31182 | switch (parent.ty.zigTypeTag(mod)) { |
| 31019 | .Struct => { | 31183 | .Struct => { |
| ... | @@ -31031,7 +31195,7 @@ fn beginComptimePtrMutation( | ... | @@ -31031,7 +31195,7 @@ fn beginComptimePtrMutation( |
| 31031 | parent.ty.structFieldType(field_index, mod), | 31195 | parent.ty.structFieldType(field_index, mod), |
| 31032 | &fields[field_index], | 31196 | &fields[field_index], |
| 31033 | ptr_elem_ty, | 31197 | ptr_elem_ty, |
| 31034 | parent.mut_decl, | 31198 | parent.root, |
| 31035 | ); | 31199 | ); |
| 31036 | }, | 31200 | }, |
| 31037 | .Union => { | 31201 | .Union => { |
| ... | @@ -31052,7 +31216,7 @@ fn beginComptimePtrMutation( | ... | @@ -31052,7 +31216,7 @@ fn beginComptimePtrMutation( |
| 31052 | payload_ty, | 31216 | payload_ty, |
| 31053 | &payload.data.val, | 31217 | &payload.data.val, |
| 31054 | ptr_elem_ty, | 31218 | ptr_elem_ty, |
| 31055 | parent.mut_decl, | 31219 | parent.root, |
| 31056 | ); | 31220 | ); |
| 31057 | }, | 31221 | }, |
| 31058 | .Pointer => { | 31222 | .Pointer => { |
| ... | @@ -31071,7 +31235,7 @@ fn beginComptimePtrMutation( | ... | @@ -31071,7 +31235,7 @@ fn beginComptimePtrMutation( |
| 31071 | ptr_ty, | 31235 | ptr_ty, |
| 31072 | &val_ptr.castTag(.slice).?.data.ptr, | 31236 | &val_ptr.castTag(.slice).?.data.ptr, |
| 31073 | ptr_elem_ty, | 31237 | ptr_elem_ty, |
| 31074 | parent.mut_decl, | 31238 | parent.root, |
| 31075 | ), | 31239 | ), |
| 31076 | Value.slice_len_index => return beginComptimePtrMutationInner( | 31240 | Value.slice_len_index => return beginComptimePtrMutationInner( |
| 31077 | sema, | 31241 | sema, |
| ... | @@ -31080,7 +31244,7 @@ fn beginComptimePtrMutation( | ... | @@ -31080,7 +31244,7 @@ fn beginComptimePtrMutation( |
| 31080 | Type.usize, | 31244 | Type.usize, |
| 31081 | &val_ptr.castTag(.slice).?.data.len, | 31245 | &val_ptr.castTag(.slice).?.data.len, |
| 31082 | ptr_elem_ty, | 31246 | ptr_elem_ty, |
| 31083 | parent.mut_decl, | 31247 | parent.root, |
| 31084 | ), | 31248 | ), |
| 31085 | | 31249 | |
| 31086 | else => unreachable, | 31250 | else => unreachable, |
| ... | @@ -31096,7 +31260,7 @@ fn beginComptimePtrMutation( | ... | @@ -31096,7 +31260,7 @@ fn beginComptimePtrMutation( |
| 31096 | const field_offset_u64 = base_child_ty.structFieldOffset(field_index, mod); | 31260 | const field_offset_u64 = base_child_ty.structFieldOffset(field_index, mod); |
| 31097 | const field_offset = try sema.usizeCast(block, src, field_offset_u64); | 31261 | const field_offset = try sema.usizeCast(block, src, field_offset_u64); |
| 31098 | return ComptimePtrMutationKit{ | 31262 | return ComptimePtrMutationKit{ |
| 31099 | .mut_decl = parent.mut_decl, | 31263 | .root = parent.root, |
| 31100 | .pointee = .{ .reinterpret = .{ | 31264 | .pointee = .{ .reinterpret = .{ |
| 31101 | .val_ptr = reinterpret.val_ptr, | 31265 | .val_ptr = reinterpret.val_ptr, |
| 31102 | .byte_offset = reinterpret.byte_offset + field_offset, | 31266 | .byte_offset = reinterpret.byte_offset + field_offset, |
| ... | @@ -31117,7 +31281,7 @@ fn beginComptimePtrMutationInner( | ... | @@ -31117,7 +31281,7 @@ fn beginComptimePtrMutationInner( |
| 31117 | decl_ty: Type, | 31281 | decl_ty: Type, |
| 31118 | decl_val: *Value, | 31282 | decl_val: *Value, |
| 31119 | ptr_elem_ty: Type, | 31283 | ptr_elem_ty: Type, |
| 31120 | mut_decl: InternPool.Key.Ptr.Addr.MutDecl, | 31284 | root: ComptimePtrMutationKit.Root, |
| 31121 | ) CompileError!ComptimePtrMutationKit { | 31285 | ) CompileError!ComptimePtrMutationKit { |
| 31122 | const mod = sema.mod; | 31286 | const mod = sema.mod; |
| 31123 | const target = mod.getTarget(); | 31287 | const target = mod.getTarget(); |
| ... | @@ -31127,7 +31291,7 @@ fn beginComptimePtrMutationInner( | ... | @@ -31127,7 +31291,7 @@ fn beginComptimePtrMutationInner( |
| 31127 | | 31291 | |
| 31128 | if (coerce_ok) { | 31292 | if (coerce_ok) { |
| 31129 | return ComptimePtrMutationKit{ | 31293 | return ComptimePtrMutationKit{ |
| 31130 | .mut_decl = mut_decl, | 31294 | .root = root, |
| 31131 | .pointee = .{ .direct = decl_val }, | 31295 | .pointee = .{ .direct = decl_val }, |
| 31132 | .ty = decl_ty, | 31296 | .ty = decl_ty, |
| 31133 | }; | 31297 | }; |
| ... | @@ -31138,7 +31302,7 @@ fn beginComptimePtrMutationInner( | ... | @@ -31138,7 +31302,7 @@ fn beginComptimePtrMutationInner( |
| 31138 | const decl_elem_ty = decl_ty.childType(mod); | 31302 | const decl_elem_ty = decl_ty.childType(mod); |
| 31139 | if ((try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_elem_ty, true, target, src, src)) == .ok) { | 31303 | if ((try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_elem_ty, true, target, src, src)) == .ok) { |
| 31140 | return ComptimePtrMutationKit{ | 31304 | return ComptimePtrMutationKit{ |
| 31141 | .mut_decl = mut_decl, | 31305 | .root = root, |
| 31142 | .pointee = .{ .direct = decl_val }, | 31306 | .pointee = .{ .direct = decl_val }, |
| 31143 | .ty = decl_ty, | 31307 | .ty = decl_ty, |
| 31144 | }; | 31308 | }; |
| ... | @@ -31147,20 +31311,20 @@ fn beginComptimePtrMutationInner( | ... | @@ -31147,20 +31311,20 @@ fn beginComptimePtrMutationInner( |
| 31147 | | 31311 | |
| 31148 | if (!decl_ty.hasWellDefinedLayout(mod)) { | 31312 | if (!decl_ty.hasWellDefinedLayout(mod)) { |
| 31149 | return ComptimePtrMutationKit{ | 31313 | return ComptimePtrMutationKit{ |
| 31150 | .mut_decl = mut_decl, | 31314 | .root = root, |
| 31151 | .pointee = .bad_decl_ty, | 31315 | .pointee = .bad_decl_ty, |
| 31152 | .ty = decl_ty, | 31316 | .ty = decl_ty, |
| 31153 | }; | 31317 | }; |
| 31154 | } | 31318 | } |
| 31155 | if (!ptr_elem_ty.hasWellDefinedLayout(mod)) { | 31319 | if (!ptr_elem_ty.hasWellDefinedLayout(mod)) { |
| 31156 | return ComptimePtrMutationKit{ | 31320 | return ComptimePtrMutationKit{ |
| 31157 | .mut_decl = mut_decl, | 31321 | .root = root, |
| 31158 | .pointee = .bad_ptr_ty, | 31322 | .pointee = .bad_ptr_ty, |
| 31159 | .ty = ptr_elem_ty, | 31323 | .ty = ptr_elem_ty, |
| 31160 | }; | 31324 | }; |
| 31161 | } | 31325 | } |
| 31162 | return ComptimePtrMutationKit{ | 31326 | return ComptimePtrMutationKit{ |
| 31163 | .mut_decl = mut_decl, | 31327 | .root = root, |
| 31164 | .pointee = .{ .reinterpret = .{ | 31328 | .pointee = .{ .reinterpret = .{ |
| 31165 | .val_ptr = decl_val, | 31329 | .val_ptr = decl_val, |
| 31166 | .byte_offset = 0, | 31330 | .byte_offset = 0, |
| ... | @@ -31208,13 +31372,7 @@ fn beginComptimePtrLoad( | ... | @@ -31208,13 +31372,7 @@ fn beginComptimePtrLoad( |
| 31208 | | 31372 | |
| 31209 | var deref: ComptimePtrLoadKit = switch (ip.indexToKey(ptr_val.toIntern())) { | 31373 | var deref: ComptimePtrLoadKit = switch (ip.indexToKey(ptr_val.toIntern())) { |
| 31210 | .ptr => |ptr| switch (ptr.addr) { | 31374 | .ptr => |ptr| switch (ptr.addr) { |
| 31211 | .decl, .mut_decl => blk: { | 31375 | .decl => |decl_index| blk: { |
| 31212 | const decl_index = switch (ptr.addr) { | | |
| 31213 | .decl => |decl| decl, | | |
| 31214 | .mut_decl => |mut_decl| mut_decl.decl, | | |
| 31215 | else => unreachable, | | |
| 31216 | }; | | |
| 31217 | const is_mutable = ptr.addr == .mut_decl; | | |
| 31218 | const decl = mod.declPtr(decl_index); | 31376 | const decl = mod.declPtr(decl_index); |
| 31219 | const decl_tv = try decl.typedValue(); | 31377 | const decl_tv = try decl.typedValue(); |
| 31220 | try sema.declareDependency(.{ .decl_val = decl_index }); | 31378 | try sema.declareDependency(.{ .decl_val = decl_index }); |
| ... | @@ -31224,10 +31382,24 @@ fn beginComptimePtrLoad( | ... | @@ -31224,10 +31382,24 @@ fn beginComptimePtrLoad( |
| 31224 | break :blk ComptimePtrLoadKit{ | 31382 | break :blk ComptimePtrLoadKit{ |
| 31225 | .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null, | 31383 | .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null, |
| 31226 | .pointee = decl_tv, | 31384 | .pointee = decl_tv, |
| 31227 | .is_mutable = is_mutable, | 31385 | .is_mutable = false, |
| 31228 | .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null, | 31386 | .ty_without_well_defined_layout = if (!layout_defined) decl.ty else null, |
| 31229 | }; | 31387 | }; |
| 31230 | }, | 31388 | }, |
| | 31389 | .comptime_alloc => |alloc_index| kit: { |
| | 31390 | const alloc = sema.getComptimeAlloc(alloc_index); |
| | 31391 | const alloc_tv: TypedValue = .{ |
| | 31392 | .ty = alloc.ty, |
| | 31393 | .val = alloc.val, |
| | 31394 | }; |
| | 31395 | const layout_defined = alloc.ty.hasWellDefinedLayout(mod); |
| | 31396 | break :kit .{ |
| | 31397 | .parent = if (layout_defined) .{ .tv = alloc_tv, .byte_offset = 0 } else null, |
| | 31398 | .pointee = alloc_tv, |
| | 31399 | .is_mutable = true, |
| | 31400 | .ty_without_well_defined_layout = if (!layout_defined) alloc.ty else null, |
| | 31401 | }; |
| | 31402 | }, |
| 31231 | .anon_decl => |anon_decl| blk: { | 31403 | .anon_decl => |anon_decl| blk: { |
| 31232 | const decl_val = anon_decl.val; | 31404 | const decl_val = anon_decl.val; |
| 31233 | if (Value.fromInterned(decl_val).getVariable(mod) != null) return error.RuntimeLoad; | 31405 | if (Value.fromInterned(decl_val).getVariable(mod) != null) return error.RuntimeLoad; |
| ... | @@ -31352,7 +31524,7 @@ fn beginComptimePtrLoad( | ... | @@ -31352,7 +31524,7 @@ fn beginComptimePtrLoad( |
| 31352 | .len = len, | 31524 | .len = len, |
| 31353 | .child = elem_ty.toIntern(), | 31525 | .child = elem_ty.toIntern(), |
| 31354 | }), | 31526 | }), |
| 31355 | .val = try array_tv.val.sliceArray(mod, sema.arena, elem_idx, elem_idx + len), | 31527 | .val = try array_tv.val.sliceArray(sema, elem_idx, elem_idx + len), |
| 31356 | } else null; | 31528 | } else null; |
| 31357 | break :blk deref; | 31529 | break :blk deref; |
| 31358 | } | 31530 | } |
| ... | @@ -31481,6 +31653,7 @@ fn bitCast( | ... | @@ -31481,6 +31653,7 @@ fn bitCast( |
| 31481 | } | 31653 | } |
| 31482 | } | 31654 | } |
| 31483 | try sema.requireRuntimeBlock(block, inst_src, operand_src); | 31655 | try sema.requireRuntimeBlock(block, inst_src, operand_src); |
| | 31656 | try sema.validateRuntimeValue(block, inst_src, inst); |
| 31484 | return block.addBitCast(dest_ty, inst); | 31657 | return block.addBitCast(dest_ty, inst); |
| 31485 | } | 31658 | } |
| 31486 | | 31659 | |
| ... | @@ -31693,7 +31866,7 @@ fn coerceCompatiblePtrs( | ... | @@ -31693,7 +31866,7 @@ fn coerceCompatiblePtrs( |
| 31693 | try sema.addSafetyCheck(block, inst_src, ok, .cast_to_null); | 31866 | try sema.addSafetyCheck(block, inst_src, ok, .cast_to_null); |
| 31694 | } | 31867 | } |
| 31695 | const new_ptr = try sema.bitCast(block, dest_ty, inst, inst_src, null); | 31868 | const new_ptr = try sema.bitCast(block, dest_ty, inst, inst_src, null); |
| 31696 | try sema.checkKnownAllocPtr(inst, new_ptr); | 31869 | try sema.checkKnownAllocPtr(block, inst, new_ptr); |
| 31697 | return new_ptr; | 31870 | return new_ptr; |
| 31698 | } | 31871 | } |
| 31699 | | 31872 | |
| ... | @@ -35448,7 +35621,7 @@ fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value { | ... | @@ -35448,7 +35621,7 @@ fn resolveLazyValue(sema: *Sema, val: Value) CompileError!Value { |
| 35448 | }, | 35621 | }, |
| 35449 | .ptr => |ptr| { | 35622 | .ptr => |ptr| { |
| 35450 | switch (ptr.addr) { | 35623 | switch (ptr.addr) { |
| 35451 | .decl, .mut_decl, .anon_decl => return val, | 35624 | .decl, .comptime_alloc, .anon_decl => return val, |
| 35452 | .comptime_field => |field_val| { | 35625 | .comptime_field => |field_val| { |
| 35453 | const resolved_field_val = | 35626 | const resolved_field_val = |
| 35454 | (try sema.resolveLazyValue(Value.fromInterned(field_val))).toIntern(); | 35627 | (try sema.resolveLazyValue(Value.fromInterned(field_val))).toIntern(); |
| ... | @@ -35803,9 +35976,6 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) Co | ... | @@ -35803,9 +35976,6 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) Co |
| 35803 | var analysis_arena = std.heap.ArenaAllocator.init(gpa); | 35976 | var analysis_arena = std.heap.ArenaAllocator.init(gpa); |
| 35804 | defer analysis_arena.deinit(); | 35977 | defer analysis_arena.deinit(); |
| 35805 | | 35978 | |
| 35806 | var comptime_mutable_decls = std.ArrayList(InternPool.DeclIndex).init(gpa); | | |
| 35807 | defer comptime_mutable_decls.deinit(); | | |
| 35808 | | | |
| 35809 | var comptime_err_ret_trace = std.ArrayList(Module.SrcLoc).init(gpa); | 35979 | var comptime_err_ret_trace = std.ArrayList(Module.SrcLoc).init(gpa); |
| 35810 | defer comptime_err_ret_trace.deinit(); | 35980 | defer comptime_err_ret_trace.deinit(); |
| 35811 | | 35981 | |
| ... | @@ -35821,7 +35991,6 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) Co | ... | @@ -35821,7 +35991,6 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) Co |
| 35821 | .fn_ret_ty = Type.void, | 35991 | .fn_ret_ty = Type.void, |
| 35822 | .fn_ret_ty_ies = null, | 35992 | .fn_ret_ty_ies = null, |
| 35823 | .owner_func_index = .none, | 35993 | .owner_func_index = .none, |
| 35824 | .comptime_mutable_decls = &comptime_mutable_decls, | | |
| 35825 | .comptime_err_ret_trace = &comptime_err_ret_trace, | 35994 | .comptime_err_ret_trace = &comptime_err_ret_trace, |
| 35826 | }; | 35995 | }; |
| 35827 | defer sema.deinit(); | 35996 | defer sema.deinit(); |
| ... | @@ -35887,11 +36056,6 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) Co | ... | @@ -35887,11 +36056,6 @@ fn semaBackingIntType(mod: *Module, struct_type: InternPool.LoadedStructType) Co |
| 35887 | const backing_int_ty = try mod.intType(.unsigned, @intCast(fields_bit_sum)); | 36056 | const backing_int_ty = try mod.intType(.unsigned, @intCast(fields_bit_sum)); |
| 35888 | struct_type.backingIntType(ip).* = backing_int_ty.toIntern(); | 36057 | struct_type.backingIntType(ip).* = backing_int_ty.toIntern(); |
| 35889 | } | 36058 | } |
| 35890 | | | |
| 35891 | for (comptime_mutable_decls.items) |ct_decl_index| { | | |
| 35892 | const ct_decl = mod.declPtr(ct_decl_index); | | |
| 35893 | _ = try ct_decl.internValue(mod); | | |
| 35894 | } | | |
| 35895 | } | 36059 | } |
| 35896 | | 36060 | |
| 35897 | fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_ty: Type, fields_bit_sum: u64) CompileError!void { | 36061 | fn checkBackingIntType(sema: *Sema, block: *Block, src: LazySrcLoc, backing_int_ty: Type, fields_bit_sum: u64) CompileError!void { |
| ... | @@ -36640,9 +36804,6 @@ fn semaStructFields( | ... | @@ -36640,9 +36804,6 @@ fn semaStructFields( |
| 36640 | }, | 36804 | }, |
| 36641 | }; | 36805 | }; |
| 36642 | | 36806 | |
| 36643 | var comptime_mutable_decls = std.ArrayList(InternPool.DeclIndex).init(gpa); | | |
| 36644 | defer comptime_mutable_decls.deinit(); | | |
| 36645 | | | |
| 36646 | var comptime_err_ret_trace = std.ArrayList(Module.SrcLoc).init(gpa); | 36807 | var comptime_err_ret_trace = std.ArrayList(Module.SrcLoc).init(gpa); |
| 36647 | defer comptime_err_ret_trace.deinit(); | 36808 | defer comptime_err_ret_trace.deinit(); |
| 36648 | | 36809 | |
| ... | @@ -36658,7 +36819,6 @@ fn semaStructFields( | ... | @@ -36658,7 +36819,6 @@ fn semaStructFields( |
| 36658 | .fn_ret_ty = Type.void, | 36819 | .fn_ret_ty = Type.void, |
| 36659 | .fn_ret_ty_ies = null, | 36820 | .fn_ret_ty_ies = null, |
| 36660 | .owner_func_index = .none, | 36821 | .owner_func_index = .none, |
| 36661 | .comptime_mutable_decls = &comptime_mutable_decls, | | |
| 36662 | .comptime_err_ret_trace = &comptime_err_ret_trace, | 36822 | .comptime_err_ret_trace = &comptime_err_ret_trace, |
| 36663 | }; | 36823 | }; |
| 36664 | defer sema.deinit(); | 36824 | defer sema.deinit(); |
| ... | @@ -36872,11 +37032,6 @@ fn semaStructFields( | ... | @@ -36872,11 +37032,6 @@ fn semaStructFields( |
| 36872 | | 37032 | |
| 36873 | struct_type.clearTypesWip(ip); | 37033 | struct_type.clearTypesWip(ip); |
| 36874 | if (!any_inits) struct_type.setHaveFieldInits(ip); | 37034 | if (!any_inits) struct_type.setHaveFieldInits(ip); |
| 36875 | | | |
| 36876 | for (comptime_mutable_decls.items) |ct_decl_index| { | | |
| 36877 | const ct_decl = mod.declPtr(ct_decl_index); | | |
| 36878 | _ = try ct_decl.internValue(mod); | | |
| 36879 | } | | |
| 36880 | } | 37035 | } |
| 36881 | | 37036 | |
| 36882 | // This logic must be kept in sync with `semaStructFields` | 37037 | // This logic must be kept in sync with `semaStructFields` |
| ... | @@ -36897,9 +37052,6 @@ fn semaStructFieldInits( | ... | @@ -36897,9 +37052,6 @@ fn semaStructFieldInits( |
| 36897 | const zir_index = struct_type.zir_index.unwrap().?.resolve(ip); | 37052 | const zir_index = struct_type.zir_index.unwrap().?.resolve(ip); |
| 36898 | const fields_len, const small, var extra_index = structZirInfo(zir, zir_index); | 37053 | const fields_len, const small, var extra_index = structZirInfo(zir, zir_index); |
| 36899 | | 37054 | |
| 36900 | var comptime_mutable_decls = std.ArrayList(InternPool.DeclIndex).init(gpa); | | |
| 36901 | defer comptime_mutable_decls.deinit(); | | |
| 36902 | | | |
| 36903 | var comptime_err_ret_trace = std.ArrayList(Module.SrcLoc).init(gpa); | 37055 | var comptime_err_ret_trace = std.ArrayList(Module.SrcLoc).init(gpa); |
| 36904 | defer comptime_err_ret_trace.deinit(); | 37056 | defer comptime_err_ret_trace.deinit(); |
| 36905 | | 37057 | |
| ... | @@ -36915,7 +37067,6 @@ fn semaStructFieldInits( | ... | @@ -36915,7 +37067,6 @@ fn semaStructFieldInits( |
| 36915 | .fn_ret_ty = Type.void, | 37067 | .fn_ret_ty = Type.void, |
| 36916 | .fn_ret_ty_ies = null, | 37068 | .fn_ret_ty_ies = null, |
| 36917 | .owner_func_index = .none, | 37069 | .owner_func_index = .none, |
| 36918 | .comptime_mutable_decls = &comptime_mutable_decls, | | |
| 36919 | .comptime_err_ret_trace = &comptime_err_ret_trace, | 37070 | .comptime_err_ret_trace = &comptime_err_ret_trace, |
| 36920 | }; | 37071 | }; |
| 36921 | defer sema.deinit(); | 37072 | defer sema.deinit(); |
| ... | @@ -37024,14 +37175,16 @@ fn semaStructFieldInits( | ... | @@ -37024,14 +37175,16 @@ fn semaStructFieldInits( |
| 37024 | }; | 37175 | }; |
| 37025 | | 37176 | |
| 37026 | const field_init = try default_val.intern(field_ty, mod); | 37177 | const field_init = try default_val.intern(field_ty, mod); |
| | 37178 | if (Value.fromInterned(field_init).canMutateComptimeVarState(mod)) { |
| | 37179 | const init_src = mod.fieldSrcLoc(decl_index, .{ |
| | 37180 | .index = field_i, |
| | 37181 | .range = .value, |
| | 37182 | }).lazy; |
| | 37183 | return sema.fail(&block_scope, init_src, "field default value contains reference to comptime-mutable memory", .{}); |
| | 37184 | } |
| 37027 | struct_type.field_inits.get(ip)[field_i] = field_init; | 37185 | struct_type.field_inits.get(ip)[field_i] = field_init; |
| 37028 | } | 37186 | } |
| 37029 | } | 37187 | } |
| 37030 | | | |
| 37031 | for (comptime_mutable_decls.items) |ct_decl_index| { | | |
| 37032 | const ct_decl = mod.declPtr(ct_decl_index); | | |
| 37033 | _ = try ct_decl.internValue(mod); | | |
| 37034 | } | | |
| 37035 | } | 37188 | } |
| 37036 | | 37189 | |
| 37037 | fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.LoadedUnionType) CompileError!void { | 37190 | fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.LoadedUnionType) CompileError!void { |
| ... | @@ -37088,9 +37241,6 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded | ... | @@ -37088,9 +37241,6 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded |
| 37088 | | 37241 | |
| 37089 | const decl = mod.declPtr(decl_index); | 37242 | const decl = mod.declPtr(decl_index); |
| 37090 | | 37243 | |
| 37091 | var comptime_mutable_decls = std.ArrayList(InternPool.DeclIndex).init(gpa); | | |
| 37092 | defer comptime_mutable_decls.deinit(); | | |
| 37093 | | | |
| 37094 | var comptime_err_ret_trace = std.ArrayList(Module.SrcLoc).init(gpa); | 37244 | var comptime_err_ret_trace = std.ArrayList(Module.SrcLoc).init(gpa); |
| 37095 | defer comptime_err_ret_trace.deinit(); | 37245 | defer comptime_err_ret_trace.deinit(); |
| 37096 | | 37246 | |
| ... | @@ -37106,7 +37256,6 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded | ... | @@ -37106,7 +37256,6 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded |
| 37106 | .fn_ret_ty = Type.void, | 37256 | .fn_ret_ty = Type.void, |
| 37107 | .fn_ret_ty_ies = null, | 37257 | .fn_ret_ty_ies = null, |
| 37108 | .owner_func_index = .none, | 37258 | .owner_func_index = .none, |
| 37109 | .comptime_mutable_decls = &comptime_mutable_decls, | | |
| 37110 | .comptime_err_ret_trace = &comptime_err_ret_trace, | 37259 | .comptime_err_ret_trace = &comptime_err_ret_trace, |
| 37111 | }; | 37260 | }; |
| 37112 | defer sema.deinit(); | 37261 | defer sema.deinit(); |
| ... | @@ -37126,11 +37275,6 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded | ... | @@ -37126,11 +37275,6 @@ fn semaUnionFields(mod: *Module, arena: Allocator, union_type: InternPool.Loaded |
| 37126 | _ = try sema.analyzeInlineBody(&block_scope, body, zir_index); | 37275 | _ = try sema.analyzeInlineBody(&block_scope, body, zir_index); |
| 37127 | } | 37276 | } |
| 37128 | | 37277 | |
| 37129 | for (comptime_mutable_decls.items) |ct_decl_index| { | | |
| 37130 | const ct_decl = mod.declPtr(ct_decl_index); | | |
| 37131 | _ = try ct_decl.internValue(mod); | | |
| 37132 | } | | |
| 37133 | | | |
| 37134 | var int_tag_ty: Type = undefined; | 37278 | var int_tag_ty: Type = undefined; |
| 37135 | var enum_field_names: []InternPool.NullTerminatedString = &.{}; | 37279 | var enum_field_names: []InternPool.NullTerminatedString = &.{}; |
| 37136 | var enum_field_vals: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{}; | 37280 | var enum_field_vals: std.AutoArrayHashMapUnmanaged(InternPool.Index, void) = .{}; |
| ... | @@ -37734,7 +37878,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { | ... | @@ -37734,7 +37878,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value { |
| 37734 | .ptr_decl, | 37878 | .ptr_decl, |
| 37735 | .ptr_anon_decl, | 37879 | .ptr_anon_decl, |
| 37736 | .ptr_anon_decl_aligned, | 37880 | .ptr_anon_decl_aligned, |
| 37737 | .ptr_mut_decl, | 37881 | .ptr_comptime_alloc, |
| 37738 | .ptr_comptime_field, | 37882 | .ptr_comptime_field, |
| 37739 | .ptr_int, | 37883 | .ptr_int, |
| 37740 | .ptr_eu_payload, | 37884 | .ptr_eu_payload, |
| ... | @@ -38017,27 +38161,11 @@ fn analyzeComptimeAlloc( | ... | @@ -38017,27 +38161,11 @@ fn analyzeComptimeAlloc( |
| 38017 | }, | 38161 | }, |
| 38018 | }); | 38162 | }); |
| 38019 | | 38163 | |
| 38020 | var anon_decl = try block.startAnonDecl(); // TODO: comptime value mutation without Decl | 38164 | const alloc = try sema.newComptimeAlloc(block, var_type, alignment); |
| 38021 | defer anon_decl.deinit(); | | |
| 38022 | | 38165 | |
| 38023 | const decl_index = try anon_decl.finish( | | |
| 38024 | var_type, | | |
| 38025 | // There will be stores before the first load, but they may be to sub-elements or | | |
| 38026 | // sub-fields. So we need to initialize with undef to allow the mechanism to expand | | |
| 38027 | // into fields/elements and have those overridden with stored values. | | |
| 38028 | Value.fromInterned((try mod.intern(.{ .undef = var_type.toIntern() }))), | | |
| 38029 | alignment, | | |
| 38030 | ); | | |
| 38031 | const decl = mod.declPtr(decl_index); | | |
| 38032 | decl.alignment = alignment; | | |
| 38033 | | | |
| 38034 | try sema.comptime_mutable_decls.append(decl_index); | | |
| 38035 | return Air.internedToRef((try mod.intern(.{ .ptr = .{ | 38166 | return Air.internedToRef((try mod.intern(.{ .ptr = .{ |
| 38036 | .ty = ptr_type.toIntern(), | 38167 | .ty = ptr_type.toIntern(), |
| 38037 | .addr = .{ .mut_decl = .{ | 38168 | .addr = .{ .comptime_alloc = alloc }, |
| 38038 | .decl = decl_index, | | |
| 38039 | .runtime_index = block.runtime_index, | | |
| 38040 | } }, | | |
| 38041 | } }))); | 38169 | } }))); |
| 38042 | } | 38170 | } |
| 38043 | | 38171 | |
| ... | @@ -39073,3 +39201,130 @@ pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void { | ... | @@ -39073,3 +39201,130 @@ pub fn declareDependency(sema: *Sema, dependee: InternPool.Dependee) !void { |
| 39073 | ); | 39201 | ); |
| 39074 | try sema.mod.intern_pool.addDependency(sema.gpa, depender, dependee); | 39202 | try sema.mod.intern_pool.addDependency(sema.gpa, depender, dependee); |
| 39075 | } | 39203 | } |
| | 39204 | |
| | 39205 | fn isComptimeMutablePtr(sema: *Sema, val: Value) bool { |
| | 39206 | return switch (sema.mod.intern_pool.indexToKey(val.toIntern())) { |
| | 39207 | .slice => |slice| sema.isComptimeMutablePtr(Value.fromInterned(slice.ptr)), |
| | 39208 | .ptr => |ptr| switch (ptr.addr) { |
| | 39209 | .anon_decl, .decl, .int => false, |
| | 39210 | .comptime_field => true, |
| | 39211 | .comptime_alloc => |alloc_index| !sema.getComptimeAlloc(alloc_index).is_const, |
| | 39212 | .eu_payload, .opt_payload => |base| sema.isComptimeMutablePtr(Value.fromInterned(base)), |
| | 39213 | .elem, .field => |bi| sema.isComptimeMutablePtr(Value.fromInterned(bi.base)), |
| | 39214 | }, |
| | 39215 | else => false, |
| | 39216 | }; |
| | 39217 | } |
| | 39218 | |
| | 39219 | fn checkRuntimeValue(sema: *Sema, ptr: Air.Inst.Ref) bool { |
| | 39220 | const val = ptr.toInterned() orelse return true; |
| | 39221 | return !Value.fromInterned(val).canMutateComptimeVarState(sema.mod); |
| | 39222 | } |
| | 39223 | |
| | 39224 | fn validateRuntimeValue(sema: *Sema, block: *Block, val_src: LazySrcLoc, val: Air.Inst.Ref) CompileError!void { |
| | 39225 | if (sema.checkRuntimeValue(val)) return; |
| | 39226 | return sema.failWithOwnedErrorMsg(block, msg: { |
| | 39227 | const msg = try sema.errMsg(block, val_src, "runtime value contains reference to comptime var", .{}); |
| | 39228 | errdefer msg.destroy(sema.gpa); |
| | 39229 | try sema.errNote(block, val_src, msg, "comptime var pointers are not available at runtime", .{}); |
| | 39230 | break :msg msg; |
| | 39231 | }); |
| | 39232 | } |
| | 39233 | |
| | 39234 | /// Returns true if any value contained in `val` is undefined. |
| | 39235 | fn anyUndef(sema: *Sema, val: Value) !bool { |
| | 39236 | const mod = sema.mod; |
| | 39237 | if (val.ip_index == .none) return switch (val.tag()) { |
| | 39238 | .eu_payload => try sema.anyUndef(val.castTag(.eu_payload).?.data), |
| | 39239 | .opt_payload => try sema.anyUndef(val.castTag(.opt_payload).?.data), |
| | 39240 | .repeated => try sema.anyUndef(val.castTag(.repeated).?.data), |
| | 39241 | .slice => { |
| | 39242 | const slice = val.castTag(.slice).?.data; |
| | 39243 | for (0..@intCast(slice.len.toUnsignedInt(mod))) |idx| { |
| | 39244 | if (try sema.anyUndef((try slice.ptr.maybeElemValueFull(sema, mod, idx)).?)) return true; |
| | 39245 | } |
| | 39246 | return false; |
| | 39247 | }, |
| | 39248 | .bytes => false, |
| | 39249 | .aggregate => for (val.castTag(.aggregate).?.data) |elem| { |
| | 39250 | if (try sema.anyUndef(elem)) break true; |
| | 39251 | } else false, |
| | 39252 | .@"union" => { |
| | 39253 | const un = val.castTag(.@"union").?.data; |
| | 39254 | if (un.tag) |t| { |
| | 39255 | if (try sema.anyUndef(t)) return true; |
| | 39256 | } |
| | 39257 | return sema.anyUndef(un.val); |
| | 39258 | }, |
| | 39259 | }; |
| | 39260 | return switch (val.toIntern()) { |
| | 39261 | .undef => true, |
| | 39262 | else => switch (mod.intern_pool.indexToKey(val.toIntern())) { |
| | 39263 | .undef => true, |
| | 39264 | .simple_value => |v| v == .undefined, |
| | 39265 | .slice => |slice| for (0..@intCast(Value.fromInterned(slice.len).toUnsignedInt(mod))) |idx| { |
| | 39266 | if (try sema.anyUndef((try val.maybeElemValueFull(sema, mod, idx)).?)) break true; |
| | 39267 | } else false, |
| | 39268 | .aggregate => |aggregate| for (0..aggregate.storage.values().len) |i| { |
| | 39269 | const elem = mod.intern_pool.indexToKey(val.toIntern()).aggregate.storage.values()[i]; |
| | 39270 | if (try sema.anyUndef(Value.fromInterned(elem))) break true; |
| | 39271 | } else false, |
| | 39272 | else => false, |
| | 39273 | }, |
| | 39274 | }; |
| | 39275 | } |
| | 39276 | |
| | 39277 | /// Asserts that `slice_val` is a slice of `u8`. |
| | 39278 | fn sliceToIpString( |
| | 39279 | sema: *Sema, |
| | 39280 | block: *Block, |
| | 39281 | src: LazySrcLoc, |
| | 39282 | slice_val: Value, |
| | 39283 | reason: NeededComptimeReason, |
| | 39284 | ) CompileError!InternPool.NullTerminatedString { |
| | 39285 | const zcu = sema.mod; |
| | 39286 | const ip = &zcu.intern_pool; |
| | 39287 | const slice_ty = Type.fromInterned(ip.typeOf(slice_val.toIntern())); |
| | 39288 | assert(slice_ty.isSlice(zcu)); |
| | 39289 | assert(slice_ty.childType(zcu).toIntern() == .u8_type); |
| | 39290 | const array_val = try sema.derefSliceAsArray(block, src, slice_val, reason); |
| | 39291 | const array_ty = Type.fromInterned(ip.typeOf(array_val.toIntern())); |
| | 39292 | return array_val.toIpString(array_ty, zcu); |
| | 39293 | } |
| | 39294 | |
| | 39295 | /// Given a slice value, attempts to dereference it into a comptime-known array. |
| | 39296 | /// Emits a compile error if the contents of the slice are not comptime-known. |
| | 39297 | /// Asserts that `slice_val` is a slice. |
| | 39298 | fn derefSliceAsArray( |
| | 39299 | sema: *Sema, |
| | 39300 | block: *Block, |
| | 39301 | src: LazySrcLoc, |
| | 39302 | slice_val: Value, |
| | 39303 | reason: NeededComptimeReason, |
| | 39304 | ) CompileError!Value { |
| | 39305 | const zcu = sema.mod; |
| | 39306 | const ip = &zcu.intern_pool; |
| | 39307 | assert(Type.fromInterned(ip.typeOf(slice_val.toIntern())).isSlice(zcu)); |
| | 39308 | const slice = switch (ip.indexToKey(slice_val.toIntern())) { |
| | 39309 | .undef => return sema.failWithUseOfUndef(block, src), |
| | 39310 | .slice => |slice| slice, |
| | 39311 | else => unreachable, |
| | 39312 | }; |
| | 39313 | const elem_ty = Type.fromInterned(slice.ty).childType(zcu); |
| | 39314 | const len = try Value.fromInterned(slice.len).toUnsignedIntAdvanced(sema); |
| | 39315 | const array_ty = try zcu.arrayType(.{ |
| | 39316 | .child = elem_ty.toIntern(), |
| | 39317 | .len = len, |
| | 39318 | }); |
| | 39319 | const ptr_ty = try sema.ptrType(p: { |
| | 39320 | var p = Type.fromInterned(slice.ty).ptrInfo(zcu); |
| | 39321 | p.flags.size = .One; |
| | 39322 | p.child = array_ty.toIntern(); |
| | 39323 | p.sentinel = .none; |
| | 39324 | break :p p; |
| | 39325 | }); |
| | 39326 | const casted_ptr = try zcu.getCoerced(Value.fromInterned(slice.ptr), ptr_ty); |
| | 39327 | return try sema.pointerDeref(block, src, casted_ptr, ptr_ty) orelse { |
| | 39328 | return sema.failWithNeededComptime(block, src, reason); |
| | 39329 | }; |
| | 39330 | } |