| ... | @@ -139,8 +139,7 @@ const MaybeComptimeAlloc = struct { | ... | @@ -139,8 +139,7 @@ const MaybeComptimeAlloc = struct { |
| 139 | }; | 139 | }; |
| 140 | | 140 | |
| 141 | const ComptimeAlloc = struct { | 141 | const ComptimeAlloc = struct { |
| 142 | ty: Type, | 142 | val: MutableValue, |
| 143 | val: Value, | | |
| 144 | is_const: bool, | 143 | is_const: bool, |
| 145 | /// `.none` indicates that the alignment is the natural alignment of `val`. | 144 | /// `.none` indicates that the alignment is the natural alignment of `val`. |
| 146 | alignment: Alignment, | 145 | alignment: Alignment, |
| ... | @@ -153,8 +152,7 @@ const ComptimeAlloc = struct { | ... | @@ -153,8 +152,7 @@ const ComptimeAlloc = struct { |
| 153 | fn newComptimeAlloc(sema: *Sema, block: *Block, ty: Type, alignment: Alignment) !ComptimeAllocIndex { | 152 | fn newComptimeAlloc(sema: *Sema, block: *Block, ty: Type, alignment: Alignment) !ComptimeAllocIndex { |
| 154 | const idx = sema.comptime_allocs.items.len; | 153 | const idx = sema.comptime_allocs.items.len; |
| 155 | try sema.comptime_allocs.append(sema.gpa, .{ | 154 | try sema.comptime_allocs.append(sema.gpa, .{ |
| 156 | .ty = ty, | 155 | .val = .{ .interned = try sema.mod.intern(.{ .undef = ty.toIntern() }) }, |
| 157 | .val = Value.fromInterned(try sema.mod.intern(.{ .undef = ty.toIntern() })), | | |
| 158 | .is_const = false, | 156 | .is_const = false, |
| 159 | .alignment = alignment, | 157 | .alignment = alignment, |
| 160 | .runtime_index = block.runtime_index, | 158 | .runtime_index = block.runtime_index, |
| ... | @@ -175,6 +173,7 @@ const log = std.log.scoped(.sema); | ... | @@ -175,6 +173,7 @@ const log = std.log.scoped(.sema); |
| 175 | | 173 | |
| 176 | const Sema = @This(); | 174 | const Sema = @This(); |
| 177 | const Value = @import("Value.zig"); | 175 | const Value = @import("Value.zig"); |
| | 176 | const MutableValue = @import("mutable_value.zig").MutableValue; |
| 178 | const Type = @import("type.zig").Type; | 177 | const Type = @import("type.zig").Type; |
| 179 | const TypedValue = @import("TypedValue.zig"); | 178 | const TypedValue = @import("TypedValue.zig"); |
| 180 | const Air = @import("Air.zig"); | 179 | const Air = @import("Air.zig"); |
| ... | @@ -3762,10 +3761,10 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro | ... | @@ -3762,10 +3761,10 @@ fn zirMakePtrConst(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileErro |
| 3762 | if (!sema.isComptimeMutablePtr(ptr_val)) break :already_ct; | 3761 | if (!sema.isComptimeMutablePtr(ptr_val)) break :already_ct; |
| 3763 | const alloc_index = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr.comptime_alloc; | 3762 | const alloc_index = mod.intern_pool.indexToKey(ptr_val.toIntern()).ptr.addr.comptime_alloc; |
| 3764 | const ct_alloc = sema.getComptimeAlloc(alloc_index); | 3763 | const ct_alloc = sema.getComptimeAlloc(alloc_index); |
| 3765 | const interned = try ct_alloc.val.intern(ct_alloc.ty, mod); | 3764 | const interned = try ct_alloc.val.intern(mod, sema.arena); |
| 3766 | if (Value.fromInterned(interned).canMutateComptimeVarState(mod)) { | 3765 | if (Value.fromInterned(interned).canMutateComptimeVarState(mod)) { |
| 3767 | // Preserve the comptime alloc, just make the pointer const. | 3766 | // Preserve the comptime alloc, just make the pointer const. |
| 3768 | ct_alloc.val = Value.fromInterned(interned); | 3767 | ct_alloc.val = .{ .interned = interned }; |
| 3769 | ct_alloc.is_const = true; | 3768 | ct_alloc.is_const = true; |
| 3770 | return sema.makePtrConst(block, alloc); | 3769 | return sema.makePtrConst(block, alloc); |
| 3771 | } else { | 3770 | } else { |
| ... | @@ -4030,7 +4029,7 @@ fn finishResolveComptimeKnownAllocPtr( | ... | @@ -4030,7 +4029,7 @@ fn finishResolveComptimeKnownAllocPtr( |
| 4030 | const alloc_index = existing_comptime_alloc orelse a: { | 4029 | const alloc_index = existing_comptime_alloc orelse a: { |
| 4031 | const idx = try sema.newComptimeAlloc(block, alloc_ty.childType(zcu), alloc_ty.ptrAlignment(zcu)); | 4030 | const idx = try sema.newComptimeAlloc(block, alloc_ty.childType(zcu), alloc_ty.ptrAlignment(zcu)); |
| 4032 | const alloc = sema.getComptimeAlloc(idx); | 4031 | const alloc = sema.getComptimeAlloc(idx); |
| 4033 | alloc.val = Value.fromInterned(result_val); | 4032 | alloc.val = .{ .interned = result_val }; |
| 4034 | break :a idx; | 4033 | break :a idx; |
| 4035 | }; | 4034 | }; |
| 4036 | sema.getComptimeAlloc(alloc_index).is_const = true; | 4035 | sema.getComptimeAlloc(alloc_index).is_const = true; |
| ... | @@ -4193,7 +4192,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com | ... | @@ -4193,7 +4192,7 @@ fn zirResolveInferredAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Com |
| 4193 | .anon_decl => |a| a.val, | 4192 | .anon_decl => |a| a.val, |
| 4194 | .comptime_alloc => |i| val: { | 4193 | .comptime_alloc => |i| val: { |
| 4195 | const alloc = sema.getComptimeAlloc(i); | 4194 | const alloc = sema.getComptimeAlloc(i); |
| 4196 | break :val try alloc.val.intern(alloc.ty, mod); | 4195 | break :val try alloc.val.intern(mod, sema.arena); |
| 4197 | }, | 4196 | }, |
| 4198 | else => unreachable, | 4197 | else => unreachable, |
| 4199 | }; | 4198 | }; |
| ... | @@ -5597,7 +5596,7 @@ fn storeToInferredAllocComptime( | ... | @@ -5597,7 +5596,7 @@ fn storeToInferredAllocComptime( |
| 5597 | } }); | 5596 | } }); |
| 5598 | } else { | 5597 | } else { |
| 5599 | const alloc_index = try sema.newComptimeAlloc(block, operand_ty, iac.alignment); | 5598 | const alloc_index = try sema.newComptimeAlloc(block, operand_ty, iac.alignment); |
| 5600 | sema.getComptimeAlloc(alloc_index).val = operand_val; | 5599 | sema.getComptimeAlloc(alloc_index).val = .{ .interned = operand_val.toIntern() }; |
| 5601 | iac.ptr = try zcu.intern(.{ .ptr = .{ | 5600 | iac.ptr = try zcu.intern(.{ .ptr = .{ |
| 5602 | .ty = alloc_ty.toIntern(), | 5601 | .ty = alloc_ty.toIntern(), |
| 5603 | .addr = .{ .comptime_alloc = alloc_index }, | 5602 | .addr = .{ .comptime_alloc = alloc_index }, |
| ... | @@ -30655,21 +30654,22 @@ fn storePtrVal( | ... | @@ -30655,21 +30654,22 @@ fn storePtrVal( |
| 30655 | .opv => {}, | 30654 | .opv => {}, |
| 30656 | .direct => |val_ptr| { | 30655 | .direct => |val_ptr| { |
| 30657 | if (mut_kit.root == .comptime_field) { | 30656 | if (mut_kit.root == .comptime_field) { |
| 30658 | val_ptr.* = Value.fromInterned((try val_ptr.intern(operand_ty, mod))); | 30657 | val_ptr.* = .{ .interned = try val_ptr.intern(mod, sema.arena) }; |
| 30659 | if (!operand_val.eql(val_ptr.*, operand_ty, mod)) { | 30658 | if (operand_val.toIntern() != val_ptr.interned) { |
| 30660 | // TODO use failWithInvalidComptimeFieldStore | 30659 | // TODO use failWithInvalidComptimeFieldStore |
| 30661 | return sema.fail(block, src, "value stored in comptime field does not match the default value of the field", .{}); | 30660 | return sema.fail(block, src, "value stored in comptime field does not match the default value of the field", .{}); |
| 30662 | } | 30661 | } |
| 30663 | return; | 30662 | return; |
| 30664 | } | 30663 | } |
| 30665 | val_ptr.* = Value.fromInterned((try operand_val.intern(operand_ty, mod))); | 30664 | val_ptr.* = .{ .interned = operand_val.toIntern() }; |
| 30666 | }, | 30665 | }, |
| 30667 | .reinterpret => |reinterpret| { | 30666 | .reinterpret => |reinterpret| { |
| 30668 | try sema.resolveTypeLayout(mut_kit.ty); | 30667 | try sema.resolveTypeLayout(mut_kit.ty); |
| 30669 | const abi_size = try sema.usizeCast(block, src, mut_kit.ty.abiSize(mod)); | 30668 | const abi_size = try sema.usizeCast(block, src, mut_kit.ty.abiSize(mod)); |
| 30670 | const buffer = try sema.gpa.alloc(u8, abi_size); | 30669 | const buffer = try sema.gpa.alloc(u8, abi_size); |
| 30671 | defer sema.gpa.free(buffer); | 30670 | defer sema.gpa.free(buffer); |
| 30672 | reinterpret.val_ptr.*.writeToMemory(mut_kit.ty, mod, buffer) catch |err| switch (err) { | 30671 | const interned_old = Value.fromInterned(try reinterpret.val_ptr.intern(mod, sema.arena)); |
| | 30672 | interned_old.writeToMemory(mut_kit.ty, mod, buffer) catch |err| switch (err) { |
| 30673 | error.OutOfMemory => return error.OutOfMemory, | 30673 | error.OutOfMemory => return error.OutOfMemory, |
| 30674 | error.ReinterpretDeclRef => unreachable, | 30674 | error.ReinterpretDeclRef => unreachable, |
| 30675 | error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already | 30675 | error.IllDefinedMemoryLayout => unreachable, // Sema was supposed to emit a compile error already |
| ... | @@ -30693,7 +30693,7 @@ fn storePtrVal( | ... | @@ -30693,7 +30693,7 @@ fn storePtrVal( |
| 30693 | error.IllDefinedMemoryLayout => unreachable, | 30693 | error.IllDefinedMemoryLayout => unreachable, |
| 30694 | error.Unimplemented => return sema.fail(block, src, "TODO: implement readFromMemory for type '{}'", .{mut_kit.ty.fmt(mod)}), | 30694 | error.Unimplemented => return sema.fail(block, src, "TODO: implement readFromMemory for type '{}'", .{mut_kit.ty.fmt(mod)}), |
| 30695 | }; | 30695 | }; |
| 30696 | reinterpret.val_ptr.* = Value.fromInterned((try val.intern(mut_kit.ty, mod))); | 30696 | reinterpret.val_ptr.* = .{ .interned = val.toIntern() }; |
| 30697 | }, | 30697 | }, |
| 30698 | .bad_decl_ty, .bad_ptr_ty => { | 30698 | .bad_decl_ty, .bad_ptr_ty => { |
| 30699 | // TODO show the decl declaration site in a note and explain whether the decl | 30699 | // TODO show the decl declaration site in a note and explain whether the decl |
| ... | @@ -30718,11 +30718,11 @@ const ComptimePtrMutationKit = struct { | ... | @@ -30718,11 +30718,11 @@ const ComptimePtrMutationKit = struct { |
| 30718 | opv, | 30718 | opv, |
| 30719 | /// The pointer type matches the actual comptime Value so a direct | 30719 | /// The pointer type matches the actual comptime Value so a direct |
| 30720 | /// modification is possible. | 30720 | /// modification is possible. |
| 30721 | direct: *Value, | 30721 | direct: *MutableValue, |
| 30722 | /// The largest parent Value containing pointee and having a well-defined memory layout. | 30722 | /// The largest parent Value containing pointee and having a well-defined memory layout. |
| 30723 | /// This is used for bitcasting, if direct dereferencing failed. | 30723 | /// This is used for bitcasting, if direct dereferencing failed. |
| 30724 | reinterpret: struct { | 30724 | reinterpret: struct { |
| 30725 | val_ptr: *Value, | 30725 | val_ptr: *MutableValue, |
| 30726 | byte_offset: usize, | 30726 | byte_offset: usize, |
| 30727 | /// If set, write the operand to packed memory | 30727 | /// If set, write the operand to packed memory |
| 30728 | write_packed: bool = false, | 30728 | write_packed: bool = false, |
| ... | @@ -30754,15 +30754,15 @@ fn beginComptimePtrMutation( | ... | @@ -30754,15 +30754,15 @@ fn beginComptimePtrMutation( |
| 30754 | .decl, .anon_decl, .int => unreachable, // isComptimeMutablePtr has been checked already | 30754 | .decl, .anon_decl, .int => unreachable, // isComptimeMutablePtr has been checked already |
| 30755 | .comptime_alloc => |alloc_index| { | 30755 | .comptime_alloc => |alloc_index| { |
| 30756 | const alloc = sema.getComptimeAlloc(alloc_index); | 30756 | const alloc = sema.getComptimeAlloc(alloc_index); |
| 30757 | return sema.beginComptimePtrMutationInner(block, src, alloc.ty, &alloc.val, ptr_elem_ty, .{ .alloc = alloc_index }); | 30757 | return sema.beginComptimePtrMutationInner(block, src, alloc.val.typeOf(mod), &alloc.val, ptr_elem_ty, .{ .alloc = alloc_index }); |
| 30758 | }, | 30758 | }, |
| 30759 | .comptime_field => |comptime_field| { | 30759 | .comptime_field => |comptime_field| { |
| 30760 | const duped = try sema.arena.create(Value); | 30760 | const duped = try sema.arena.create(MutableValue); |
| 30761 | duped.* = Value.fromInterned(comptime_field); | 30761 | duped.* = .{ .interned = comptime_field }; |
| 30762 | return sema.beginComptimePtrMutationInner( | 30762 | return sema.beginComptimePtrMutationInner( |
| 30763 | block, | 30763 | block, |
| 30764 | src, | 30764 | src, |
| 30765 | Type.fromInterned(mod.intern_pool.typeOf(comptime_field)), | 30765 | duped.typeOf(mod), |
| 30766 | duped, | 30766 | duped, |
| 30767 | ptr_elem_ty, | 30767 | ptr_elem_ty, |
| 30768 | .comptime_field, | 30768 | .comptime_field, |
| ... | @@ -30775,36 +30775,28 @@ fn beginComptimePtrMutation( | ... | @@ -30775,36 +30775,28 @@ fn beginComptimePtrMutation( |
| 30775 | .opv => unreachable, | 30775 | .opv => unreachable, |
| 30776 | .direct => |val_ptr| { | 30776 | .direct => |val_ptr| { |
| 30777 | const payload_ty = parent.ty.errorUnionPayload(mod); | 30777 | const payload_ty = parent.ty.errorUnionPayload(mod); |
| 30778 | if (val_ptr.ip_index == .none and val_ptr.tag() == .eu_payload) { | 30778 | try val_ptr.unintern(mod, sema.arena, false, false); |
| 30779 | return ComptimePtrMutationKit{ | 30779 | if (val_ptr.* == .interned) { |
| 30780 | .root = parent.root, | | |
| 30781 | .pointee = .{ .direct = &val_ptr.castTag(.eu_payload).?.data }, | | |
| 30782 | .ty = payload_ty, | | |
| 30783 | }; | | |
| 30784 | } else { | | |
| 30785 | // An error union has been initialized to undefined at comptime and now we | 30780 | // An error union has been initialized to undefined at comptime and now we |
| 30786 | // are for the first time setting the payload. We must change the | 30781 | // are for the first time setting the payload. We must change the |
| 30787 | // representation of the error union from `undef` to `opt_payload`. | 30782 | // representation of the error union to `eu_payload`. |
| 30788 | | 30783 | const child = try sema.arena.create(MutableValue); |
| 30789 | const payload = try sema.arena.create(Value.Payload.SubValue); | 30784 | child.* = .{ .interned = try mod.intern(.{ .undef = payload_ty.toIntern() }) }; |
| 30790 | payload.* = .{ | 30785 | val_ptr.* = .{ .eu_payload = .{ |
| 30791 | .base = .{ .tag = .eu_payload }, | 30786 | .ty = parent.ty.toIntern(), |
| 30792 | .data = Value.fromInterned((try mod.intern(.{ .undef = payload_ty.toIntern() }))), | 30787 | .child = child, |
| 30793 | }; | 30788 | } }; |
| 30794 | | | |
| 30795 | val_ptr.* = Value.initPayload(&payload.base); | | |
| 30796 | | | |
| 30797 | return ComptimePtrMutationKit{ | | |
| 30798 | .root = parent.root, | | |
| 30799 | .pointee = .{ .direct = &payload.data }, | | |
| 30800 | .ty = payload_ty, | | |
| 30801 | }; | | |
| 30802 | } | 30789 | } |
| | 30790 | return .{ |
| | 30791 | .root = parent.root, |
| | 30792 | .pointee = .{ .direct = val_ptr.eu_payload.child }, |
| | 30793 | .ty = payload_ty, |
| | 30794 | }; |
| 30803 | }, | 30795 | }, |
| 30804 | .bad_decl_ty, .bad_ptr_ty => return parent, | 30796 | .bad_decl_ty, .bad_ptr_ty => return parent, |
| 30805 | // Even though the parent value type has well-defined memory layout, our | 30797 | // Even though the parent value type has well-defined memory layout, our |
| 30806 | // pointer type does not. | 30798 | // pointer type does not. |
| 30807 | .reinterpret => return ComptimePtrMutationKit{ | 30799 | .reinterpret => return .{ |
| 30808 | .root = parent.root, | 30800 | .root = parent.root, |
| 30809 | .pointee = .bad_ptr_ty, | 30801 | .pointee = .bad_ptr_ty, |
| 30810 | .ty = eu_ty, | 30802 | .ty = eu_ty, |
| ... | @@ -30818,46 +30810,28 @@ fn beginComptimePtrMutation( | ... | @@ -30818,46 +30810,28 @@ fn beginComptimePtrMutation( |
| 30818 | .opv => unreachable, | 30810 | .opv => unreachable, |
| 30819 | .direct => |val_ptr| { | 30811 | .direct => |val_ptr| { |
| 30820 | const payload_ty = parent.ty.optionalChild(mod); | 30812 | const payload_ty = parent.ty.optionalChild(mod); |
| 30821 | switch (val_ptr.ip_index) { | 30813 | try val_ptr.unintern(mod, sema.arena, false, false); |
| 30822 | .none => return ComptimePtrMutationKit{ | 30814 | if (val_ptr.* == .interned) { |
| 30823 | .root = parent.root, | 30815 | // An optional has been initialized to undefined at comptime and now we |
| 30824 | .pointee = .{ .direct = &val_ptr.castTag(.opt_payload).?.data }, | 30816 | // are for the first time setting the payload. We must change the |
| 30825 | .ty = payload_ty, | 30817 | // representation of the optional to `opt_payload`. |
| 30826 | }, | 30818 | const child = try sema.arena.create(MutableValue); |
| 30827 | else => { | 30819 | child.* = .{ .interned = try mod.intern(.{ .undef = payload_ty.toIntern() }) }; |
| 30828 | const payload_val = switch (mod.intern_pool.indexToKey(val_ptr.ip_index)) { | 30820 | val_ptr.* = .{ .opt_payload = .{ |
| 30829 | .undef => try mod.intern(.{ .undef = payload_ty.toIntern() }), | 30821 | .ty = parent.ty.toIntern(), |
| 30830 | .opt => |opt| switch (opt.val) { | 30822 | .child = child, |
| 30831 | .none => try mod.intern(.{ .undef = payload_ty.toIntern() }), | 30823 | } }; |
| 30832 | else => |payload| payload, | | |
| 30833 | }, | | |
| 30834 | else => unreachable, | | |
| 30835 | }; | | |
| 30836 | | | |
| 30837 | // An optional has been initialized to undefined at comptime and now we | | |
| 30838 | // are for the first time setting the payload. We must change the | | |
| 30839 | // representation of the optional from `undef` to `opt_payload`. | | |
| 30840 | | | |
| 30841 | const payload = try sema.arena.create(Value.Payload.SubValue); | | |
| 30842 | payload.* = .{ | | |
| 30843 | .base = .{ .tag = .opt_payload }, | | |
| 30844 | .data = Value.fromInterned(payload_val), | | |
| 30845 | }; | | |
| 30846 | | | |
| 30847 | val_ptr.* = Value.initPayload(&payload.base); | | |
| 30848 | | | |
| 30849 | return ComptimePtrMutationKit{ | | |
| 30850 | .root = parent.root, | | |
| 30851 | .pointee = .{ .direct = &payload.data }, | | |
| 30852 | .ty = payload_ty, | | |
| 30853 | }; | | |
| 30854 | }, | | |
| 30855 | } | 30824 | } |
| | 30825 | return .{ |
| | 30826 | .root = parent.root, |
| | 30827 | .pointee = .{ .direct = val_ptr.opt_payload.child }, |
| | 30828 | .ty = payload_ty, |
| | 30829 | }; |
| 30856 | }, | 30830 | }, |
| 30857 | .bad_decl_ty, .bad_ptr_ty => return parent, | 30831 | .bad_decl_ty, .bad_ptr_ty => return parent, |
| 30858 | // Even though the parent value type has well-defined memory layout, our | 30832 | // Even though the parent value type has well-defined memory layout, our |
| 30859 | // pointer type does not. | 30833 | // pointer type does not. |
| 30860 | .reinterpret => return ComptimePtrMutationKit{ | 30834 | .reinterpret => return .{ |
| 30861 | .root = parent.root, | 30835 | .root = parent.root, |
| 30862 | .pointee = .bad_ptr_ty, | 30836 | .pointee = .bad_ptr_ty, |
| 30863 | .ty = opt_ty, | 30837 | .ty = opt_ty, |
| ... | @@ -30916,106 +30890,28 @@ fn beginComptimePtrMutation( | ... | @@ -30916,106 +30890,28 @@ fn beginComptimePtrMutation( |
| 30916 | }; | 30890 | }; |
| 30917 | } | 30891 | } |
| 30918 | | 30892 | |
| 30919 | switch (val_ptr.ip_index) { | 30893 | try val_ptr.unintern(mod, sema.arena, false, false); |
| 30920 | .none => switch (val_ptr.tag()) { | 30894 | |
| 30921 | .bytes => { | 30895 | const aggregate = switch (val_ptr.*) { |
| 30922 | // An array is memory-optimized to store a slice of bytes, but we are about | 30896 | .interned, |
| 30923 | // to modify an individual field and the representation has to change. | 30897 | .bytes, |
| 30924 | // If we wanted to avoid this, there would need to be special detection | 30898 | .repeated, |
| 30925 | // elsewhere to identify when writing a value to an array element that is stored | 30899 | .eu_payload, |
| 30926 | // using the `bytes` tag, and handle it without making a call to this function. | 30900 | .opt_payload, |
| 30927 | const arena = sema.arena; | 30901 | .slice, |
| 30928 | | 30902 | .un, |
| 30929 | const bytes = val_ptr.castTag(.bytes).?.data; | 30903 | => unreachable, |
| 30930 | const dest_len = parent.ty.arrayLenIncludingSentinel(mod); | 30904 | .aggregate => |*a| a, |
| 30931 | // bytes.len may be one greater than dest_len because of the case when | 30905 | }; |
| 30932 | // assigning `[N:S]T` to `[N]T`. This is allowed; the sentinel is omitted. | | |
| 30933 | assert(bytes.len >= dest_len); | | |
| 30934 | const elems = try arena.alloc(Value, @intCast(dest_len)); | | |
| 30935 | for (elems, 0..) |*elem, i| { | | |
| 30936 | elem.* = try mod.intValue(elem_ty, bytes[i]); | | |
| 30937 | } | | |
| 30938 | | | |
| 30939 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); | | |
| 30940 | | | |
| 30941 | return beginComptimePtrMutationInner( | | |
| 30942 | sema, | | |
| 30943 | block, | | |
| 30944 | src, | | |
| 30945 | elem_ty, | | |
| 30946 | &elems[@intCast(elem_ptr.index)], | | |
| 30947 | ptr_elem_ty, | | |
| 30948 | parent.root, | | |
| 30949 | ); | | |
| 30950 | }, | | |
| 30951 | .repeated => { | | |
| 30952 | // An array is memory-optimized to store only a single element value, and | | |
| 30953 | // that value is understood to be the same for the entire length of the array. | | |
| 30954 | // However, now we want to modify an individual field and so the | | |
| 30955 | // representation has to change. If we wanted to avoid this, there would | | |
| 30956 | // need to be special detection elsewhere to identify when writing a value to an | | |
| 30957 | // array element that is stored using the `repeated` tag, and handle it | | |
| 30958 | // without making a call to this function. | | |
| 30959 | const arena = sema.arena; | | |
| 30960 | | | |
| 30961 | const repeated_val = try val_ptr.castTag(.repeated).?.data.intern(parent.ty.childType(mod), mod); | | |
| 30962 | const array_len_including_sentinel = | | |
| 30963 | try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod)); | | |
| 30964 | const elems = try arena.alloc(Value, array_len_including_sentinel); | | |
| 30965 | @memset(elems, Value.fromInterned(repeated_val)); | | |
| 30966 | | | |
| 30967 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); | | |
| 30968 | | | |
| 30969 | return beginComptimePtrMutationInner( | | |
| 30970 | sema, | | |
| 30971 | block, | | |
| 30972 | src, | | |
| 30973 | elem_ty, | | |
| 30974 | &elems[@intCast(elem_ptr.index)], | | |
| 30975 | ptr_elem_ty, | | |
| 30976 | parent.root, | | |
| 30977 | ); | | |
| 30978 | }, | | |
| 30979 | | | |
| 30980 | .aggregate => return beginComptimePtrMutationInner( | | |
| 30981 | sema, | | |
| 30982 | block, | | |
| 30983 | src, | | |
| 30984 | elem_ty, | | |
| 30985 | &val_ptr.castTag(.aggregate).?.data[@intCast(elem_ptr.index)], | | |
| 30986 | ptr_elem_ty, | | |
| 30987 | parent.root, | | |
| 30988 | ), | | |
| 30989 | | 30906 | |
| 30990 | else => unreachable, | 30907 | return sema.beginComptimePtrMutationInner( |
| 30991 | }, | 30908 | block, |
| 30992 | else => switch (mod.intern_pool.indexToKey(val_ptr.toIntern())) { | 30909 | src, |
| 30993 | .undef => { | 30910 | elem_ty, |
| 30994 | // An array has been initialized to undefined at comptime and now we | 30911 | &aggregate.elems[@intCast(elem_ptr.index)], |
| 30995 | // are for the first time setting an element. We must change the representation | 30912 | ptr_elem_ty, |
| 30996 | // of the array from `undef` to `array`. | 30913 | parent.root, |
| 30997 | const arena = sema.arena; | 30914 | ); |
| 30998 | | | |
| 30999 | const array_len_including_sentinel = | | |
| 31000 | try sema.usizeCast(block, src, parent.ty.arrayLenIncludingSentinel(mod)); | | |
| 31001 | const elems = try arena.alloc(Value, array_len_including_sentinel); | | |
| 31002 | @memset(elems, Value.fromInterned((try mod.intern(.{ .undef = elem_ty.toIntern() })))); | | |
| 31003 | | | |
| 31004 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); | | |
| 31005 | | | |
| 31006 | return beginComptimePtrMutationInner( | | |
| 31007 | sema, | | |
| 31008 | block, | | |
| 31009 | src, | | |
| 31010 | elem_ty, | | |
| 31011 | &elems[@intCast(elem_ptr.index)], | | |
| 31012 | ptr_elem_ty, | | |
| 31013 | parent.root, | | |
| 31014 | ); | | |
| 31015 | }, | | |
| 31016 | else => unreachable, | | |
| 31017 | }, | | |
| 31018 | } | | |
| 31019 | }, | 30915 | }, |
| 31020 | else => { | 30916 | else => { |
| 31021 | if (elem_ptr.index != 0) { | 30917 | if (elem_ptr.index != 0) { |
| ... | @@ -31039,7 +30935,7 @@ fn beginComptimePtrMutation( | ... | @@ -31039,7 +30935,7 @@ fn beginComptimePtrMutation( |
| 31039 | if (!base_elem_ty.hasWellDefinedLayout(mod)) { | 30935 | if (!base_elem_ty.hasWellDefinedLayout(mod)) { |
| 31040 | // Even though the parent value type has well-defined memory layout, our | 30936 | // Even though the parent value type has well-defined memory layout, our |
| 31041 | // pointer type does not. | 30937 | // pointer type does not. |
| 31042 | return ComptimePtrMutationKit{ | 30938 | return .{ |
| 31043 | .root = parent.root, | 30939 | .root = parent.root, |
| 31044 | .pointee = .bad_ptr_ty, | 30940 | .pointee = .bad_ptr_ty, |
| 31045 | .ty = base_elem_ty, | 30941 | .ty = base_elem_ty, |
| ... | @@ -31049,7 +30945,7 @@ fn beginComptimePtrMutation( | ... | @@ -31049,7 +30945,7 @@ fn beginComptimePtrMutation( |
| 31049 | const elem_abi_size_u64 = try sema.typeAbiSize(base_elem_ty); | 30945 | const elem_abi_size_u64 = try sema.typeAbiSize(base_elem_ty); |
| 31050 | const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64); | 30946 | const elem_abi_size = try sema.usizeCast(block, src, elem_abi_size_u64); |
| 31051 | const elem_idx = try sema.usizeCast(block, src, elem_ptr.index); | 30947 | const elem_idx = try sema.usizeCast(block, src, elem_ptr.index); |
| 31052 | return ComptimePtrMutationKit{ | 30948 | return .{ |
| 31053 | .root = parent.root, | 30949 | .root = parent.root, |
| 31054 | .pointee = .{ .reinterpret = .{ | 30950 | .pointee = .{ .reinterpret = .{ |
| 31055 | .val_ptr = reinterpret.val_ptr, | 30951 | .val_ptr = reinterpret.val_ptr, |
| ... | @@ -31068,56 +30964,68 @@ fn beginComptimePtrMutation( | ... | @@ -31068,56 +30964,68 @@ fn beginComptimePtrMutation( |
| 31068 | var parent = try sema.beginComptimePtrMutation(block, src, Value.fromInterned(field_ptr.base), base_child_ty); | 30964 | var parent = try sema.beginComptimePtrMutation(block, src, Value.fromInterned(field_ptr.base), base_child_ty); |
| 31069 | switch (parent.pointee) { | 30965 | switch (parent.pointee) { |
| 31070 | .opv => unreachable, | 30966 | .opv => unreachable, |
| 31071 | .direct => |val_ptr| switch (val_ptr.ip_index) { | 30967 | .direct => |val_ptr| { |
| 31072 | .empty_struct => { | 30968 | try val_ptr.unintern(mod, sema.arena, false, false); |
| 31073 | const duped = try sema.arena.create(Value); | 30969 | switch (val_ptr.*) { |
| 31074 | duped.* = val_ptr.*; | 30970 | .interned, |
| 31075 | return beginComptimePtrMutationInner( | 30971 | .eu_payload, |
| 31076 | sema, | 30972 | .opt_payload, |
| 31077 | block, | 30973 | .repeated, |
| 31078 | src, | 30974 | .bytes, |
| 31079 | parent.ty.structFieldType(field_index, mod), | 30975 | => unreachable, |
| 31080 | duped, | 30976 | .aggregate => |*a| return sema.beginComptimePtrMutationInner( |
| 31081 | ptr_elem_ty, | | |
| 31082 | parent.root, | | |
| 31083 | ); | | |
| 31084 | }, | | |
| 31085 | .none => switch (val_ptr.tag()) { | | |
| 31086 | .aggregate => return beginComptimePtrMutationInner( | | |
| 31087 | sema, | | |
| 31088 | block, | 30977 | block, |
| 31089 | src, | 30978 | src, |
| 31090 | parent.ty.structFieldType(field_index, mod), | 30979 | parent.ty.structFieldType(field_index, mod), |
| 31091 | &val_ptr.castTag(.aggregate).?.data[field_index], | 30980 | &a.elems[field_index], |
| 31092 | ptr_elem_ty, | 30981 | ptr_elem_ty, |
| 31093 | parent.root, | 30982 | parent.root, |
| 31094 | ), | 30983 | ), |
| 31095 | .repeated => { | 30984 | .slice => |*s| switch (field_index) { |
| 31096 | const arena = sema.arena; | 30985 | Value.slice_ptr_index => return sema.beginComptimePtrMutationInner( |
| 31097 | | | |
| 31098 | const elems = try arena.alloc(Value, parent.ty.structFieldCount(mod)); | | |
| 31099 | @memset(elems, val_ptr.castTag(.repeated).?.data); | | |
| 31100 | val_ptr.* = try Value.Tag.aggregate.create(arena, elems); | | |
| 31101 | | | |
| 31102 | return beginComptimePtrMutationInner( | | |
| 31103 | sema, | | |
| 31104 | block, | 30986 | block, |
| 31105 | src, | 30987 | src, |
| 31106 | parent.ty.structFieldType(field_index, mod), | 30988 | parent.ty.slicePtrFieldType(mod), |
| 31107 | &elems[field_index], | 30989 | s.ptr, |
| 31108 | ptr_elem_ty, | 30990 | ptr_elem_ty, |
| 31109 | parent.root, | 30991 | parent.root, |
| 31110 | ); | 30992 | ), |
| | 30993 | Value.slice_len_index => return sema.beginComptimePtrMutationInner( |
| | 30994 | block, |
| | 30995 | src, |
| | 30996 | Type.usize, |
| | 30997 | s.len, |
| | 30998 | ptr_elem_ty, |
| | 30999 | parent.root, |
| | 31000 | ), |
| | 31001 | else => unreachable, |
| 31111 | }, | 31002 | }, |
| 31112 | .@"union" => { | 31003 | .un => |*un| { |
| 31113 | const payload = &val_ptr.castTag(.@"union").?.data; | | |
| 31114 | const layout = base_child_ty.containerLayout(mod); | 31004 | const layout = base_child_ty.containerLayout(mod); |
| 31115 | | 31005 | |
| 31116 | const tag_type = base_child_ty.unionTagTypeHypothetical(mod); | 31006 | const tag_type = base_child_ty.unionTagTypeHypothetical(mod); |
| 31117 | const hypothetical_tag = try mod.enumValueFieldIndex(tag_type, field_index); | 31007 | const hypothetical_tag = try mod.enumValueFieldIndex(tag_type, field_index); |
| 31118 | if (layout == .auto or (payload.tag != null and hypothetical_tag.eql(payload.tag.?, tag_type, mod))) { | 31008 | if (un.tag == .none and un.payload.* == .interned and un.payload.interned == .undef) { |
| | 31009 | // A union has been initialized to undefined at comptime and now we |
| | 31010 | // are for the first time setting the payload. We must change the |
| | 31011 | // tag implicitly. |
| | 31012 | const payload_ty = parent.ty.structFieldType(field_index, mod); |
| | 31013 | un.tag = hypothetical_tag.toIntern(); |
| | 31014 | un.payload.* = .{ .interned = try mod.intern(.{ .undef = payload_ty.toIntern() }) }; |
| | 31015 | return beginComptimePtrMutationInner( |
| | 31016 | sema, |
| | 31017 | block, |
| | 31018 | src, |
| | 31019 | payload_ty, |
| | 31020 | un.payload, |
| | 31021 | ptr_elem_ty, |
| | 31022 | parent.root, |
| | 31023 | ); |
| | 31024 | } |
| | 31025 | |
| | 31026 | if (layout == .auto or hypothetical_tag.toIntern() == un.tag) { |
| 31119 | // We need to set the active field of the union. | 31027 | // We need to set the active field of the union. |
| 31120 | payload.tag = hypothetical_tag; | 31028 | un.tag = hypothetical_tag.toIntern(); |
| 31121 | | 31029 | |
| 31122 | const field_ty = parent.ty.structFieldType(field_index, mod); | 31030 | const field_ty = parent.ty.structFieldType(field_index, mod); |
| 31123 | return beginComptimePtrMutationInner( | 31031 | return beginComptimePtrMutationInner( |
| ... | @@ -31125,7 +31033,7 @@ fn beginComptimePtrMutation( | ... | @@ -31125,7 +31033,7 @@ fn beginComptimePtrMutation( |
| 31125 | block, | 31033 | block, |
| 31126 | src, | 31034 | src, |
| 31127 | field_ty, | 31035 | field_ty, |
| 31128 | &payload.val, | 31036 | un.payload, |
| 31129 | ptr_elem_ty, | 31037 | ptr_elem_ty, |
| 31130 | parent.root, | 31038 | parent.root, |
| 31131 | ); | 31039 | ); |
| ... | @@ -31133,11 +31041,10 @@ fn beginComptimePtrMutation( | ... | @@ -31133,11 +31041,10 @@ fn beginComptimePtrMutation( |
| 31133 | // Writing to a different field (a different or unknown tag is active) requires reinterpreting | 31041 | // Writing to a different field (a different or unknown tag is active) requires reinterpreting |
| 31134 | // memory of the entire union, which requires knowing its abiSize. | 31042 | // memory of the entire union, which requires knowing its abiSize. |
| 31135 | try sema.resolveTypeLayout(parent.ty); | 31043 | try sema.resolveTypeLayout(parent.ty); |
| 31136 | | | |
| 31137 | // This union value no longer has a well-defined tag type. | 31044 | // This union value no longer has a well-defined tag type. |
| 31138 | // The reinterpretation will read it back out as .none. | 31045 | // The reinterpretation will read it back out as .none. |
| 31139 | payload.val = try payload.val.unintern(sema.arena, mod); | 31046 | try un.payload.unintern(mod, sema.arena, false, false); |
| 31140 | return ComptimePtrMutationKit{ | 31047 | return .{ |
| 31141 | .root = parent.root, | 31048 | .root = parent.root, |
| 31142 | .pointee = .{ .reinterpret = .{ | 31049 | .pointee = .{ .reinterpret = .{ |
| 31143 | .val_ptr = val_ptr, | 31050 | .val_ptr = val_ptr, |
| ... | @@ -31148,119 +31055,12 @@ fn beginComptimePtrMutation( | ... | @@ -31148,119 +31055,12 @@ fn beginComptimePtrMutation( |
| 31148 | }; | 31055 | }; |
| 31149 | } | 31056 | } |
| 31150 | }, | 31057 | }, |
| 31151 | .slice => switch (field_index) { | 31058 | } |
| 31152 | Value.slice_ptr_index => return beginComptimePtrMutationInner( | | |
| 31153 | sema, | | |
| 31154 | block, | | |
| 31155 | src, | | |
| 31156 | parent.ty.slicePtrFieldType(mod), | | |
| 31157 | &val_ptr.castTag(.slice).?.data.ptr, | | |
| 31158 | ptr_elem_ty, | | |
| 31159 | parent.root, | | |
| 31160 | ), | | |
| 31161 | | | |
| 31162 | Value.slice_len_index => return beginComptimePtrMutationInner( | | |
| 31163 | sema, | | |
| 31164 | block, | | |
| 31165 | src, | | |
| 31166 | Type.usize, | | |
| 31167 | &val_ptr.castTag(.slice).?.data.len, | | |
| 31168 | ptr_elem_ty, | | |
| 31169 | parent.root, | | |
| 31170 | ), | | |
| 31171 | | | |
| 31172 | else => unreachable, | | |
| 31173 | }, | | |
| 31174 | else => unreachable, | | |
| 31175 | }, | | |
| 31176 | else => switch (mod.intern_pool.indexToKey(val_ptr.toIntern())) { | | |
| 31177 | .undef => { | | |
| 31178 | // A struct or union has been initialized to undefined at comptime and now we | | |
| 31179 | // are for the first time setting a field. We must change the representation | | |
| 31180 | // of the struct/union from `undef` to `struct`/`union`. | | |
| 31181 | const arena = sema.arena; | | |
| 31182 | | | |
| 31183 | switch (parent.ty.zigTypeTag(mod)) { | | |
| 31184 | .Struct => { | | |
| 31185 | const fields = try arena.alloc(Value, parent.ty.structFieldCount(mod)); | | |
| 31186 | for (fields, 0..) |*field, i| field.* = Value.fromInterned((try mod.intern(.{ | | |
| 31187 | .undef = parent.ty.structFieldType(i, mod).toIntern(), | | |
| 31188 | }))); | | |
| 31189 | | | |
| 31190 | val_ptr.* = try Value.Tag.aggregate.create(arena, fields); | | |
| 31191 | | | |
| 31192 | return beginComptimePtrMutationInner( | | |
| 31193 | sema, | | |
| 31194 | block, | | |
| 31195 | src, | | |
| 31196 | parent.ty.structFieldType(field_index, mod), | | |
| 31197 | &fields[field_index], | | |
| 31198 | ptr_elem_ty, | | |
| 31199 | parent.root, | | |
| 31200 | ); | | |
| 31201 | }, | | |
| 31202 | .Union => { | | |
| 31203 | const payload = try arena.create(Value.Payload.Union); | | |
| 31204 | const tag_ty = parent.ty.unionTagTypeHypothetical(mod); | | |
| 31205 | const payload_ty = parent.ty.structFieldType(field_index, mod); | | |
| 31206 | payload.* = .{ .data = .{ | | |
| 31207 | .tag = try mod.enumValueFieldIndex(tag_ty, field_index), | | |
| 31208 | .val = Value.fromInterned((try mod.intern(.{ .undef = payload_ty.toIntern() }))), | | |
| 31209 | } }; | | |
| 31210 | | | |
| 31211 | val_ptr.* = Value.initPayload(&payload.base); | | |
| 31212 | | | |
| 31213 | return beginComptimePtrMutationInner( | | |
| 31214 | sema, | | |
| 31215 | block, | | |
| 31216 | src, | | |
| 31217 | payload_ty, | | |
| 31218 | &payload.data.val, | | |
| 31219 | ptr_elem_ty, | | |
| 31220 | parent.root, | | |
| 31221 | ); | | |
| 31222 | }, | | |
| 31223 | .Pointer => { | | |
| 31224 | assert(parent.ty.isSlice(mod)); | | |
| 31225 | const ptr_ty = parent.ty.slicePtrFieldType(mod); | | |
| 31226 | val_ptr.* = try Value.Tag.slice.create(arena, .{ | | |
| 31227 | .ptr = Value.fromInterned((try mod.intern(.{ .undef = ptr_ty.toIntern() }))), | | |
| 31228 | .len = Value.fromInterned((try mod.intern(.{ .undef = .usize_type }))), | | |
| 31229 | }); | | |
| 31230 | | | |
| 31231 | switch (field_index) { | | |
| 31232 | Value.slice_ptr_index => return beginComptimePtrMutationInner( | | |
| 31233 | sema, | | |
| 31234 | block, | | |
| 31235 | src, | | |
| 31236 | ptr_ty, | | |
| 31237 | &val_ptr.castTag(.slice).?.data.ptr, | | |
| 31238 | ptr_elem_ty, | | |
| 31239 | parent.root, | | |
| 31240 | ), | | |
| 31241 | Value.slice_len_index => return beginComptimePtrMutationInner( | | |
| 31242 | sema, | | |
| 31243 | block, | | |
| 31244 | src, | | |
| 31245 | Type.usize, | | |
| 31246 | &val_ptr.castTag(.slice).?.data.len, | | |
| 31247 | ptr_elem_ty, | | |
| 31248 | parent.root, | | |
| 31249 | ), | | |
| 31250 | | | |
| 31251 | else => unreachable, | | |
| 31252 | } | | |
| 31253 | }, | | |
| 31254 | else => unreachable, | | |
| 31255 | } | | |
| 31256 | }, | | |
| 31257 | else => unreachable, | | |
| 31258 | }, | | |
| 31259 | }, | 31059 | }, |
| 31260 | .reinterpret => |reinterpret| { | 31060 | .reinterpret => |reinterpret| { |
| 31261 | const field_offset_u64 = base_child_ty.structFieldOffset(field_index, mod); | 31061 | const field_offset_u64 = base_child_ty.structFieldOffset(field_index, mod); |
| 31262 | const field_offset = try sema.usizeCast(block, src, field_offset_u64); | 31062 | const field_offset = try sema.usizeCast(block, src, field_offset_u64); |
| 31263 | return ComptimePtrMutationKit{ | 31063 | return .{ |
| 31264 | .root = parent.root, | 31064 | .root = parent.root, |
| 31265 | .pointee = .{ .reinterpret = .{ | 31065 | .pointee = .{ .reinterpret = .{ |
| 31266 | .val_ptr = reinterpret.val_ptr, | 31066 | .val_ptr = reinterpret.val_ptr, |
| ... | @@ -31280,7 +31080,7 @@ fn beginComptimePtrMutationInner( | ... | @@ -31280,7 +31080,7 @@ fn beginComptimePtrMutationInner( |
| 31280 | block: *Block, | 31080 | block: *Block, |
| 31281 | src: LazySrcLoc, | 31081 | src: LazySrcLoc, |
| 31282 | decl_ty: Type, | 31082 | decl_ty: Type, |
| 31283 | decl_val: *Value, | 31083 | decl_val: *MutableValue, |
| 31284 | ptr_elem_ty: Type, | 31084 | ptr_elem_ty: Type, |
| 31285 | root: ComptimePtrMutationKit.Root, | 31085 | root: ComptimePtrMutationKit.Root, |
| 31286 | ) CompileError!ComptimePtrMutationKit { | 31086 | ) CompileError!ComptimePtrMutationKit { |
| ... | @@ -31288,7 +31088,13 @@ fn beginComptimePtrMutationInner( | ... | @@ -31288,7 +31088,13 @@ fn beginComptimePtrMutationInner( |
| 31288 | const target = mod.getTarget(); | 31088 | const target = mod.getTarget(); |
| 31289 | const coerce_ok = (try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_ty, true, target, src, src)) == .ok; | 31089 | const coerce_ok = (try sema.coerceInMemoryAllowed(block, ptr_elem_ty, decl_ty, true, target, src, src)) == .ok; |
| 31290 | | 31090 | |
| 31291 | decl_val.* = try decl_val.unintern(sema.arena, mod); | 31091 | const old_decl_val = decl_val.*; |
| | 31092 | try decl_val.unintern(mod, sema.arena, false, false); |
| | 31093 | if (decl_val.* == .un and decl_val.un.tag == .none and decl_val.un.payload.* == .interned and decl_val.un.payload.interned == .undef) { |
| | 31094 | // HACKHACK: undefined union - re-intern it for now |
| | 31095 | // `unintern` probably should just leave these as is, but I'm leaving it until I rewrite comptime pointer access. |
| | 31096 | decl_val.* = old_decl_val; |
| | 31097 | } |
| 31292 | | 31098 | |
| 31293 | if (coerce_ok) { | 31099 | if (coerce_ok) { |
| 31294 | return ComptimePtrMutationKit{ | 31100 | return ComptimePtrMutationKit{ |
| ... | @@ -31334,21 +31140,16 @@ fn beginComptimePtrMutationInner( | ... | @@ -31334,21 +31140,16 @@ fn beginComptimePtrMutationInner( |
| 31334 | }; | 31140 | }; |
| 31335 | } | 31141 | } |
| 31336 | | 31142 | |
| 31337 | const TypedValueAndOffset = struct { | | |
| 31338 | tv: TypedValue, | | |
| 31339 | byte_offset: usize, | | |
| 31340 | }; | | |
| 31341 | | | |
| 31342 | const ComptimePtrLoadKit = struct { | 31143 | const ComptimePtrLoadKit = struct { |
| 31343 | /// The Value and Type corresponding to the pointee of the provided pointer. | 31144 | /// The Value and Type corresponding to the pointee of the provided pointer. |
| 31344 | /// If a direct dereference is not possible, this is null. | 31145 | /// If a direct dereference is not possible, this is null. |
| 31345 | pointee: ?TypedValue, | 31146 | pointee: ?MutableValue, |
| 31346 | /// The largest parent Value containing `pointee` and having a well-defined memory layout. | 31147 | /// The largest parent Value containing `pointee` and having a well-defined memory layout. |
| 31347 | /// This is used for bitcasting, if direct dereferencing failed (i.e. `pointee` is null). | 31148 | /// This is used for bitcasting, if direct dereferencing failed (i.e. `pointee` is null). |
| 31348 | parent: ?TypedValueAndOffset, | 31149 | parent: ?struct { |
| 31349 | /// Whether the `pointee` could be mutated by further | 31150 | val: MutableValue, |
| 31350 | /// semantic analysis and a copy must be performed. | 31151 | byte_offset: usize, |
| 31351 | is_mutable: bool, | 31152 | }, |
| 31352 | /// If the root decl could not be used as `parent`, this is the type that | 31153 | /// If the root decl could not be used as `parent`, this is the type that |
| 31353 | /// caused that by not having a well-defined layout | 31154 | /// caused that by not having a well-defined layout |
| 31354 | ty_without_well_defined_layout: ?Type, | 31155 | ty_without_well_defined_layout: ?Type, |
| ... | @@ -31375,53 +31176,41 @@ fn beginComptimePtrLoad( | ... | @@ -31375,53 +31176,41 @@ fn beginComptimePtrLoad( |
| 31375 | .ptr => |ptr| switch (ptr.addr) { | 31176 | .ptr => |ptr| switch (ptr.addr) { |
| 31376 | .decl => |decl_index| blk: { | 31177 | .decl => |decl_index| blk: { |
| 31377 | const decl = mod.declPtr(decl_index); | 31178 | const decl = mod.declPtr(decl_index); |
| 31378 | const decl_tv = try decl.typedValue(mod); | | |
| 31379 | try sema.declareDependency(.{ .decl_val = decl_index }); | 31179 | try sema.declareDependency(.{ .decl_val = decl_index }); |
| 31380 | if (decl.val.getVariable(mod) != null) return error.RuntimeLoad; | 31180 | if (decl.val.getVariable(mod) != null) return error.RuntimeLoad; |
| 31381 | | 31181 | const decl_val: MutableValue = .{ .interned = decl.val.toIntern() }; |
| 31382 | const layout_defined = decl.typeOf(mod).hasWellDefinedLayout(mod); | 31182 | const layout_defined = decl.typeOf(mod).hasWellDefinedLayout(mod); |
| 31383 | break :blk ComptimePtrLoadKit{ | 31183 | break :blk ComptimePtrLoadKit{ |
| 31384 | .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null, | 31184 | .parent = if (layout_defined) .{ .val = decl_val, .byte_offset = 0 } else null, |
| 31385 | .pointee = decl_tv, | 31185 | .pointee = decl_val, |
| 31386 | .is_mutable = false, | | |
| 31387 | .ty_without_well_defined_layout = if (!layout_defined) decl.typeOf(mod) else null, | 31186 | .ty_without_well_defined_layout = if (!layout_defined) decl.typeOf(mod) else null, |
| 31388 | }; | 31187 | }; |
| 31389 | }, | 31188 | }, |
| 31390 | .comptime_alloc => |alloc_index| kit: { | 31189 | .comptime_alloc => |alloc_index| kit: { |
| 31391 | const alloc = sema.getComptimeAlloc(alloc_index); | 31190 | const alloc = sema.getComptimeAlloc(alloc_index); |
| 31392 | const alloc_tv: TypedValue = .{ | 31191 | const alloc_ty = alloc.val.typeOf(mod); |
| 31393 | .ty = alloc.ty, | 31192 | const layout_defined = alloc_ty.hasWellDefinedLayout(mod); |
| 31394 | .val = alloc.val, | | |
| 31395 | }; | | |
| 31396 | const layout_defined = alloc.ty.hasWellDefinedLayout(mod); | | |
| 31397 | break :kit .{ | 31193 | break :kit .{ |
| 31398 | .parent = if (layout_defined) .{ .tv = alloc_tv, .byte_offset = 0 } else null, | 31194 | .parent = if (layout_defined) .{ .val = alloc.val, .byte_offset = 0 } else null, |
| 31399 | .pointee = alloc_tv, | 31195 | .pointee = alloc.val, |
| 31400 | .is_mutable = true, | 31196 | .ty_without_well_defined_layout = if (!layout_defined) alloc_ty else null, |
| 31401 | .ty_without_well_defined_layout = if (!layout_defined) alloc.ty else null, | | |
| 31402 | }; | 31197 | }; |
| 31403 | }, | 31198 | }, |
| 31404 | .anon_decl => |anon_decl| blk: { | 31199 | .anon_decl => |anon_decl| blk: { |
| 31405 | const decl_val = anon_decl.val; | 31200 | const decl_val = anon_decl.val; |
| 31406 | if (Value.fromInterned(decl_val).getVariable(mod) != null) return error.RuntimeLoad; | 31201 | if (Value.fromInterned(decl_val).getVariable(mod) != null) return error.RuntimeLoad; |
| 31407 | const decl_ty = Type.fromInterned(ip.typeOf(decl_val)); | 31202 | const decl_ty = Type.fromInterned(ip.typeOf(decl_val)); |
| 31408 | const decl_tv: TypedValue = .{ .ty = decl_ty, .val = Value.fromInterned(decl_val) }; | 31203 | const decl_mv: MutableValue = .{ .interned = decl_val }; |
| 31409 | const layout_defined = decl_ty.hasWellDefinedLayout(mod); | 31204 | const layout_defined = decl_ty.hasWellDefinedLayout(mod); |
| 31410 | break :blk ComptimePtrLoadKit{ | 31205 | break :blk ComptimePtrLoadKit{ |
| 31411 | .parent = if (layout_defined) .{ .tv = decl_tv, .byte_offset = 0 } else null, | 31206 | .parent = if (layout_defined) .{ .val = decl_mv, .byte_offset = 0 } else null, |
| 31412 | .pointee = decl_tv, | 31207 | .pointee = decl_mv, |
| 31413 | .is_mutable = false, | | |
| 31414 | .ty_without_well_defined_layout = if (!layout_defined) decl_ty else null, | 31208 | .ty_without_well_defined_layout = if (!layout_defined) decl_ty else null, |
| 31415 | }; | 31209 | }; |
| 31416 | }, | 31210 | }, |
| 31417 | .int => return error.RuntimeLoad, | 31211 | .int => return error.RuntimeLoad, |
| 31418 | .eu_payload, .opt_payload => |container_ptr| blk: { | 31212 | .eu_payload, .opt_payload => |container_ptr| blk: { |
| 31419 | const container_ty = Type.fromInterned(ip.typeOf(container_ptr)).childType(mod); | 31213 | const container_ty = Type.fromInterned(ip.typeOf(container_ptr)).childType(mod); |
| 31420 | const payload_ty = switch (ptr.addr) { | | |
| 31421 | .eu_payload => container_ty.errorUnionPayload(mod), | | |
| 31422 | .opt_payload => container_ty.optionalChild(mod), | | |
| 31423 | else => unreachable, | | |
| 31424 | }; | | |
| 31425 | var deref = try sema.beginComptimePtrLoad(block, src, Value.fromInterned(container_ptr), container_ty); | 31214 | var deref = try sema.beginComptimePtrLoad(block, src, Value.fromInterned(container_ptr), container_ty); |
| 31426 | | 31215 | |
| 31427 | // eu_payload and opt_payload never have a well-defined layout | 31216 | // eu_payload and opt_payload never have a well-defined layout |
| ... | @@ -31430,15 +31219,14 @@ fn beginComptimePtrLoad( | ... | @@ -31430,15 +31219,14 @@ fn beginComptimePtrLoad( |
| 31430 | deref.ty_without_well_defined_layout = container_ty; | 31219 | deref.ty_without_well_defined_layout = container_ty; |
| 31431 | } | 31220 | } |
| 31432 | | 31221 | |
| 31433 | if (deref.pointee) |*tv| { | 31222 | if (deref.pointee) |pointee| { |
| | 31223 | const pointee_ty = pointee.typeOf(mod); |
| 31434 | const coerce_in_mem_ok = | 31224 | const coerce_in_mem_ok = |
| 31435 | (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or | 31225 | (try sema.coerceInMemoryAllowed(block, container_ty, pointee_ty, false, target, src, src)) == .ok or |
| 31436 | (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok; | 31226 | (try sema.coerceInMemoryAllowed(block, pointee_ty, container_ty, false, target, src, src)) == .ok; |
| 31437 | if (coerce_in_mem_ok) { | 31227 | if (coerce_in_mem_ok) { |
| 31438 | const payload_val = switch (tv.val.ip_index) { | 31228 | deref.pointee = switch (pointee) { |
| 31439 | .none => tv.val.cast(Value.Payload.SubValue).?.data, | 31229 | .interned => |ip_index| .{ .interned = switch (ip.indexToKey(ip_index)) { |
| 31440 | .null_value => return sema.fail(block, src, "attempt to use null value", .{}), | | |
| 31441 | else => Value.fromInterned(switch (ip.indexToKey(tv.val.toIntern())) { | | |
| 31442 | .error_union => |error_union| switch (error_union.val) { | 31230 | .error_union => |error_union| switch (error_union.val) { |
| 31443 | .err_name => |err_name| return sema.fail( | 31231 | .err_name => |err_name| return sema.fail( |
| 31444 | block, | 31232 | block, |
| ... | @@ -31453,23 +31241,20 @@ fn beginComptimePtrLoad( | ... | @@ -31453,23 +31241,20 @@ fn beginComptimePtrLoad( |
| 31453 | else => |payload| payload, | 31241 | else => |payload| payload, |
| 31454 | }, | 31242 | }, |
| 31455 | else => unreachable, | 31243 | else => unreachable, |
| 31456 | }), | 31244 | } }, |
| | 31245 | .eu_payload, .opt_payload => |p| p.child.*, |
| | 31246 | else => unreachable, |
| 31457 | }; | 31247 | }; |
| 31458 | tv.* = TypedValue{ .ty = payload_ty, .val = payload_val }; | | |
| 31459 | break :blk deref; | 31248 | break :blk deref; |
| 31460 | } | 31249 | } |
| 31461 | } | 31250 | } |
| 31462 | deref.pointee = null; | 31251 | deref.pointee = null; |
| 31463 | break :blk deref; | 31252 | break :blk deref; |
| 31464 | }, | 31253 | }, |
| 31465 | .comptime_field => |comptime_field| blk: { | 31254 | .comptime_field => |field_val| .{ |
| 31466 | const field_ty = Type.fromInterned(ip.typeOf(comptime_field)); | 31255 | .parent = null, |
| 31467 | break :blk ComptimePtrLoadKit{ | 31256 | .pointee = .{ .interned = field_val }, |
| 31468 | .parent = null, | 31257 | .ty_without_well_defined_layout = Type.fromInterned(ip.typeOf(field_val)), |
| 31469 | .pointee = .{ .ty = field_ty, .val = Value.fromInterned(comptime_field) }, | | |
| 31470 | .is_mutable = false, | | |
| 31471 | .ty_without_well_defined_layout = field_ty, | | |
| 31472 | }; | | |
| 31473 | }, | 31258 | }, |
| 31474 | .elem => |elem_ptr| blk: { | 31259 | .elem => |elem_ptr| blk: { |
| 31475 | const elem_ty = Type.fromInterned(ip.typeOf(elem_ptr.base)).elemType2(mod); | 31260 | const elem_ty = Type.fromInterned(ip.typeOf(elem_ptr.base)).elemType2(mod); |
| ... | @@ -31502,30 +31287,37 @@ fn beginComptimePtrLoad( | ... | @@ -31502,30 +31287,37 @@ fn beginComptimePtrLoad( |
| 31502 | | 31287 | |
| 31503 | // If we're loading an elem that was derived from a different type | 31288 | // If we're loading an elem that was derived from a different type |
| 31504 | // than the true type of the underlying decl, we cannot deref directly | 31289 | // than the true type of the underlying decl, we cannot deref directly |
| 31505 | const ty_matches = if (deref.pointee != null and deref.pointee.?.ty.isArrayOrVector(mod)) x: { | 31290 | const ty_matches = if (deref.pointee) |pointee| match: { |
| 31506 | const deref_elem_ty = deref.pointee.?.ty.childType(mod); | 31291 | const ty = pointee.typeOf(mod); |
| 31507 | break :x (try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok or | 31292 | if (!ty.isArrayOrVector(mod)) break :match false; |
| 31508 | (try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok; | 31293 | const deref_elem_ty = ty.childType(mod); |
| | 31294 | if ((try sema.coerceInMemoryAllowed(block, deref_elem_ty, elem_ty, false, target, src, src)) == .ok) break :match true; |
| | 31295 | if ((try sema.coerceInMemoryAllowed(block, elem_ty, deref_elem_ty, false, target, src, src)) == .ok) break :match true; |
| | 31296 | break :match false; |
| 31509 | } else false; | 31297 | } else false; |
| 31510 | if (!ty_matches) { | 31298 | if (!ty_matches) { |
| 31511 | deref.pointee = null; | 31299 | deref.pointee = null; |
| 31512 | break :blk deref; | 31300 | break :blk deref; |
| 31513 | } | 31301 | } |
| 31514 | | 31302 | |
| 31515 | var array_tv = deref.pointee.?; | 31303 | var array_val = deref.pointee.?; |
| 31516 | const check_len = array_tv.ty.arrayLenIncludingSentinel(mod); | 31304 | const check_len = array_val.typeOf(mod).arrayLenIncludingSentinel(mod); |
| 31517 | if (maybe_array_ty) |load_ty| { | 31305 | if (maybe_array_ty) |load_ty| { |
| 31518 | // It's possible that we're loading a [N]T, in which case we'd like to slice | 31306 | // It's possible that we're loading a [N]T, in which case we'd like to slice |
| 31519 | // the pointee array directly from our parent array. | 31307 | // the pointee array directly from our parent array. |
| 31520 | if (load_ty.isArrayOrVector(mod) and load_ty.childType(mod).eql(elem_ty, mod)) { | 31308 | if (load_ty.isArrayOrVector(mod) and load_ty.childType(mod).eql(elem_ty, mod)) { |
| 31521 | const len = try sema.usizeCast(block, src, load_ty.arrayLenIncludingSentinel(mod)); | 31309 | const len = try sema.usizeCast(block, src, load_ty.arrayLenIncludingSentinel(mod)); |
| 31522 | const elem_idx = try sema.usizeCast(block, src, elem_ptr.index); | 31310 | const elem_idx = try sema.usizeCast(block, src, elem_ptr.index); |
| 31523 | deref.pointee = if (elem_ptr.index + len <= check_len) TypedValue{ | 31311 | deref.pointee = if (elem_ptr.index + len <= check_len) switch (array_val) { |
| 31524 | .ty = try mod.arrayType(.{ | 31312 | .aggregate => |a| .{ .aggregate = .{ |
| 31525 | .len = len, | 31313 | .ty = (try mod.arrayType(.{ .len = len, .child = elem_ty.toIntern() })).toIntern(), |
| 31526 | .child = elem_ty.toIntern(), | 31314 | .elems = a.elems[elem_idx..][0..len], |
| 31527 | }), | 31315 | } }, |
| 31528 | .val = try array_tv.val.sliceArray(sema, elem_idx, elem_idx + len), | 31316 | else => .{ |
| | 31317 | .interned = (try (Value.fromInterned( |
| | 31318 | try array_val.intern(mod, sema.arena), |
| | 31319 | ).sliceArray(sema, elem_idx, elem_idx + len))).toIntern(), |
| | 31320 | }, |
| 31529 | } else null; | 31321 | } else null; |
| 31530 | break :blk deref; | 31322 | break :blk deref; |
| 31531 | } | 31323 | } |
| ... | @@ -31536,18 +31328,12 @@ fn beginComptimePtrLoad( | ... | @@ -31536,18 +31328,12 @@ fn beginComptimePtrLoad( |
| 31536 | break :blk deref; | 31328 | break :blk deref; |
| 31537 | } | 31329 | } |
| 31538 | if (elem_ptr.index == check_len - 1) { | 31330 | if (elem_ptr.index == check_len - 1) { |
| 31539 | if (array_tv.ty.sentinel(mod)) |sent| { | 31331 | if (array_val.typeOf(mod).sentinel(mod)) |sent| { |
| 31540 | deref.pointee = TypedValue{ | 31332 | deref.pointee = .{ .interned = sent.toIntern() }; |
| 31541 | .ty = elem_ty, | | |
| 31542 | .val = sent, | | |
| 31543 | }; | | |
| 31544 | break :blk deref; | 31333 | break :blk deref; |
| 31545 | } | 31334 | } |
| 31546 | } | 31335 | } |
| 31547 | deref.pointee = TypedValue{ | 31336 | deref.pointee = try array_val.getElem(mod, @intCast(elem_ptr.index)); |
| 31548 | .ty = elem_ty, | | |
| 31549 | .val = try array_tv.val.elemValue(mod, @intCast(elem_ptr.index)), | | |
| 31550 | }; | | |
| 31551 | break :blk deref; | 31337 | break :blk deref; |
| 31552 | }, | 31338 | }, |
| 31553 | .field => |field_ptr| blk: { | 31339 | .field => |field_ptr| blk: { |
| ... | @@ -31571,37 +31357,17 @@ fn beginComptimePtrLoad( | ... | @@ -31571,37 +31357,17 @@ fn beginComptimePtrLoad( |
| 31571 | deref.ty_without_well_defined_layout = container_ty; | 31357 | deref.ty_without_well_defined_layout = container_ty; |
| 31572 | } | 31358 | } |
| 31573 | | 31359 | |
| 31574 | const tv = deref.pointee orelse { | 31360 | const pointee = deref.pointee orelse break :blk deref; |
| 31575 | deref.pointee = null; | 31361 | const pointee_ty = pointee.typeOf(mod); |
| 31576 | break :blk deref; | | |
| 31577 | }; | | |
| 31578 | const coerce_in_mem_ok = | 31362 | const coerce_in_mem_ok = |
| 31579 | (try sema.coerceInMemoryAllowed(block, container_ty, tv.ty, false, target, src, src)) == .ok or | 31363 | (try sema.coerceInMemoryAllowed(block, container_ty, pointee_ty, false, target, src, src)) == .ok or |
| 31580 | (try sema.coerceInMemoryAllowed(block, tv.ty, container_ty, false, target, src, src)) == .ok; | 31364 | (try sema.coerceInMemoryAllowed(block, pointee_ty, container_ty, false, target, src, src)) == .ok; |
| 31581 | if (!coerce_in_mem_ok) { | 31365 | if (!coerce_in_mem_ok) { |
| 31582 | deref.pointee = null; | 31366 | deref.pointee = null; |
| 31583 | break :blk deref; | 31367 | break :blk deref; |
| 31584 | } | 31368 | } |
| 31585 | | 31369 | |
| 31586 | if (container_ty.isSlice(mod)) { | 31370 | deref.pointee = try pointee.getElem(mod, field_index); |
| 31587 | deref.pointee = switch (field_index) { | | |
| 31588 | Value.slice_ptr_index => TypedValue{ | | |
| 31589 | .ty = container_ty.slicePtrFieldType(mod), | | |
| 31590 | .val = tv.val.slicePtr(mod), | | |
| 31591 | }, | | |
| 31592 | Value.slice_len_index => TypedValue{ | | |
| 31593 | .ty = Type.usize, | | |
| 31594 | .val = Value.fromInterned(ip.indexToKey(try tv.val.intern(tv.ty, mod)).slice.len), | | |
| 31595 | }, | | |
| 31596 | else => unreachable, | | |
| 31597 | }; | | |
| 31598 | } else { | | |
| 31599 | const field_ty = container_ty.structFieldType(field_index, mod); | | |
| 31600 | deref.pointee = TypedValue{ | | |
| 31601 | .ty = field_ty, | | |
| 31602 | .val = try tv.val.fieldValue(mod, field_index), | | |
| 31603 | }; | | |
| 31604 | } | | |
| 31605 | break :blk deref; | 31371 | break :blk deref; |
| 31606 | }, | 31372 | }, |
| 31607 | }, | 31373 | }, |
| ... | @@ -31612,9 +31378,9 @@ fn beginComptimePtrLoad( | ... | @@ -31612,9 +31378,9 @@ fn beginComptimePtrLoad( |
| 31612 | else => unreachable, | 31378 | else => unreachable, |
| 31613 | }; | 31379 | }; |
| 31614 | | 31380 | |
| 31615 | if (deref.pointee) |tv| { | 31381 | if (deref.pointee) |val| { |
| 31616 | if (deref.parent == null and tv.ty.hasWellDefinedLayout(mod)) { | 31382 | if (deref.parent == null and val.typeOf(mod).hasWellDefinedLayout(mod)) { |
| 31617 | deref.parent = .{ .tv = tv, .byte_offset = 0 }; | 31383 | deref.parent = .{ .val = val, .byte_offset = 0 }; |
| 31618 | } | 31384 | } |
| 31619 | } | 31385 | } |
| 31620 | return deref; | 31386 | return deref; |
| ... | @@ -38289,17 +38055,18 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value | ... | @@ -38289,17 +38055,18 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value |
| 38289 | else => |e| return e, | 38055 | else => |e| return e, |
| 38290 | }; | 38056 | }; |
| 38291 | | 38057 | |
| 38292 | if (deref.pointee) |tv| { | 38058 | if (deref.pointee) |pointee| { |
| | 38059 | const uncoerced_val = Value.fromInterned(try pointee.intern(mod, sema.arena)); |
| | 38060 | const ty = Type.fromInterned(mod.intern_pool.typeOf(uncoerced_val.toIntern())); |
| 38293 | const coerce_in_mem_ok = | 38061 | const coerce_in_mem_ok = |
| 38294 | (try sema.coerceInMemoryAllowed(block, load_ty, tv.ty, false, target, src, src)) == .ok or | 38062 | (try sema.coerceInMemoryAllowed(block, load_ty, ty, false, target, src, src)) == .ok or |
| 38295 | (try sema.coerceInMemoryAllowed(block, tv.ty, load_ty, false, target, src, src)) == .ok; | 38063 | (try sema.coerceInMemoryAllowed(block, ty, load_ty, false, target, src, src)) == .ok; |
| 38296 | if (coerce_in_mem_ok) { | 38064 | if (coerce_in_mem_ok) { |
| 38297 | // We have a Value that lines up in virtual memory exactly with what we want to load, | 38065 | // We have a Value that lines up in virtual memory exactly with what we want to load, |
| 38298 | // and it is in-memory coercible to load_ty. It may be returned without modifications. | 38066 | // and it is in-memory coercible to load_ty. It may be returned without modifications. |
| 38299 | // Move mutable decl values to the InternPool and assert other decls are already in | 38067 | // Move mutable decl values to the InternPool and assert other decls are already in |
| 38300 | // the InternPool. | 38068 | // the InternPool. |
| 38301 | const uncoerced_val = if (deref.is_mutable) try tv.val.intern(tv.ty, mod) else tv.val.toIntern(); | 38069 | const coerced_val = try mod.getCoerced(uncoerced_val, load_ty); |
| 38302 | const coerced_val = try mod.getCoerced(Value.fromInterned(uncoerced_val), load_ty); | | |
| 38303 | return .{ .val = coerced_val }; | 38070 | return .{ .val = coerced_val }; |
| 38304 | } | 38071 | } |
| 38305 | } | 38072 | } |
| ... | @@ -38313,21 +38080,35 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value | ... | @@ -38313,21 +38080,35 @@ fn pointerDerefExtra(sema: *Sema, block: *Block, src: LazySrcLoc, ptr_val: Value |
| 38313 | const load_sz = try sema.typeAbiSize(load_ty); | 38080 | const load_sz = try sema.typeAbiSize(load_ty); |
| 38314 | | 38081 | |
| 38315 | // Try the smaller bit-cast first, since that's more efficient than using the larger `parent` | 38082 | // Try the smaller bit-cast first, since that's more efficient than using the larger `parent` |
| 38316 | if (deref.pointee) |tv| if (load_sz <= try sema.typeAbiSize(tv.ty)) | 38083 | if (deref.pointee) |pointee| { |
| 38317 | return DerefResult{ .val = (try sema.bitCastVal(block, src, tv.val, tv.ty, load_ty, 0)) orelse return .runtime_load }; | 38084 | const val_ip_index = try pointee.intern(mod, sema.arena); |
| | 38085 | const val = Value.fromInterned(val_ip_index); |
| | 38086 | const ty = Type.fromInterned(mod.intern_pool.typeOf(val_ip_index)); |
| | 38087 | if (load_sz <= try sema.typeAbiSize(ty)) { |
| | 38088 | return .{ .val = (try sema.bitCastVal(block, src, val, ty, load_ty, 0)) orelse return .runtime_load }; |
| | 38089 | } |
| | 38090 | } |
| 38318 | | 38091 | |
| 38319 | // If that fails, try to bit-cast from the largest parent value with a well-defined layout | 38092 | // If that fails, try to bit-cast from the largest parent value with a well-defined layout |
| 38320 | if (deref.parent) |parent| if (load_sz + parent.byte_offset <= try sema.typeAbiSize(parent.tv.ty)) | 38093 | if (deref.parent) |parent| { |
| 38321 | return DerefResult{ .val = (try sema.bitCastVal(block, src, parent.tv.val, parent.tv.ty, load_ty, parent.byte_offset)) orelse return .runtime_load }; | 38094 | const parent_ip_index = try parent.val.intern(mod, sema.arena); |
| | 38095 | const parent_val = Value.fromInterned(parent_ip_index); |
| | 38096 | const parent_ty = Type.fromInterned(mod.intern_pool.typeOf(parent_ip_index)); |
| | 38097 | if (load_sz + parent.byte_offset <= try sema.typeAbiSize(parent_ty)) { |
| | 38098 | return .{ .val = (try sema.bitCastVal(block, src, parent_val, parent_ty, load_ty, parent.byte_offset)) orelse return .runtime_load }; |
| | 38099 | } |
| | 38100 | } |
| 38322 | | 38101 | |
| 38323 | if (deref.ty_without_well_defined_layout) |bad_ty| { | 38102 | if (deref.ty_without_well_defined_layout) |bad_ty| { |
| 38324 | // We got no parent for bit-casting, or the parent we got was too small. Either way, the problem | 38103 | // We got no parent for bit-casting, or the parent we got was too small. Either way, the problem |
| 38325 | // is that some type we encountered when de-referencing does not have a well-defined layout. | 38104 | // is that some type we encountered when de-referencing does not have a well-defined layout. |
| 38326 | return DerefResult{ .needed_well_defined = bad_ty }; | 38105 | return .{ .needed_well_defined = bad_ty }; |
| 38327 | } else { | 38106 | } else { |
| 38328 | // If all encountered types had well-defined layouts, the parent is the root decl and it just | 38107 | // If all encountered types had well-defined layouts, the parent is the root decl and it just |
| 38329 | // wasn't big enough for the load. | 38108 | // wasn't big enough for the load. |
| 38330 | return DerefResult{ .out_of_bounds = deref.parent.?.tv.ty }; | 38109 | const parent_ip_index = try deref.parent.?.val.intern(mod, sema.arena); |
| | 38110 | const parent_ty = Type.fromInterned(mod.intern_pool.typeOf(parent_ip_index)); |
| | 38111 | return .{ .out_of_bounds = parent_ty }; |
| 38331 | } | 38112 | } |
| 38332 | } | 38113 | } |
| 38333 | | 38114 | |