authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-02-22 11:47:22-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-02-22 22:47:32-05:00
log220f80e71dbcb9dac4ed71845573a95b75299e4c
treed9ea138fd8c4c56284ad4cb767afb2b07077f3bd
parent4b0f77cc1f2f4939c59e92175f6e69394eb3bcef

Dwarf: fix lowering of comptime-only optional pointer `null` values

Closes #22974

4 files changed, 104 insertions(+), 76 deletions(-)

src/Type.zig+4-10
......@@ -808,7 +808,7 @@ pub fn isNoReturn(ty: Type, zcu: *const Zcu) bool {
808808 return zcu.intern_pool.isNoReturn(ty.toIntern());
809809}
810810
811/// Returns `none` if the pointer is naturally aligned and the element type is 0-bit.
811/// Never returns `none`. Asserts that all necessary type resolution is already done.
812812pub fn ptrAlignment(ty: Type, zcu: *Zcu) Alignment {
813813 return ptrAlignmentInner(ty, .normal, zcu, {}) catch unreachable;
814814}
......@@ -825,15 +825,9 @@ pub fn ptrAlignmentInner(
825825) !Alignment {
826826 return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
827827 .ptr_type => |ptr_type| {
828 if (ptr_type.flags.alignment != .none)
829 return ptr_type.flags.alignment;
830
831 if (strat == .sema) {
832 const res = try Type.fromInterned(ptr_type.child).abiAlignmentInner(.sema, zcu, tid);
833 return res.scalar;
834 }
835
836 return Type.fromInterned(ptr_type.child).abiAlignment(zcu);
828 if (ptr_type.flags.alignment != .none) return ptr_type.flags.alignment;
829 const res = try Type.fromInterned(ptr_type.child).abiAlignmentInner(strat.toLazy(), zcu, tid);
830 return res.scalar;
837831 },
838832 .opt_type => |child| Type.fromInterned(child).ptrAlignmentInner(strat, zcu, tid),
839833 else => unreachable,
src/Value.zig+1-1
......@@ -3690,7 +3690,7 @@ pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type };
36903690pub const empty_tuple: Value = .{ .ip_index = .empty_tuple };
36913691
36923692pub fn makeBool(x: bool) Value {
3693 return if (x) Value.true else Value.false;
3693 return if (x) .true else .false;
36943694}
36953695
36963696/// `parent_ptr` must be a single-pointer to some optional.
src/link/Dwarf.zig+88-65
......@@ -3248,75 +3248,72 @@ fn updateLazyType(
32483248 },
32493249 .opt_type => |opt_child_type_index| {
32503250 const opt_child_type: Type = .fromInterned(opt_child_type_index);
3251 const opt_repr = optRepr(opt_child_type, zcu);
32513252 try wip_nav.abbrevCode(.generated_union_type);
32523253 try wip_nav.strp(name);
32533254 try uleb128(diw, ty.abiSize(zcu));
32543255 try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?);
3255 if (opt_child_type.isNoReturn(zcu)) {
3256 try wip_nav.abbrevCode(.generated_field);
3257 try wip_nav.strp("null");
3258 try wip_nav.refType(.null);
3259 try uleb128(diw, 0);
3260 } else {
3261 try wip_nav.abbrevCode(.tagged_union);
3262 try wip_nav.infoSectionOffset(
3263 .debug_info,
3264 wip_nav.unit,
3265 wip_nav.entry,
3266 @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()),
3267 );
3268 {
3256 switch (opt_repr) {
3257 .opv_null => {
32693258 try wip_nav.abbrevCode(.generated_field);
3270 try wip_nav.strp("has_value");
3271 const repr: enum { unpacked, error_set, pointer } = switch (opt_child_type_index) {
3272 .anyerror_type => .error_set,
3273 else => switch (ip.indexToKey(opt_child_type_index)) {
3274 else => .unpacked,
3275 .error_set_type, .inferred_error_set_type => .error_set,
3276 .ptr_type => |ptr_type| if (ptr_type.flags.is_allowzero) .unpacked else .pointer,
3277 },
3278 };
3279 switch (repr) {
3280 .unpacked => {
3281 try wip_nav.refType(.bool);
3282 try uleb128(diw, if (opt_child_type.hasRuntimeBits(zcu))
3283 opt_child_type.abiSize(zcu)
3284 else
3285 0);
3286 },
3287 .error_set => {
3288 try wip_nav.refType(.fromInterned(try pt.intern(.{ .int_type = .{
3289 .signedness = .unsigned,
3290 .bits = zcu.errorSetBits(),
3291 } })));
3292 try uleb128(diw, 0);
3293 },
3294 .pointer => {
3295 try wip_nav.refType(.usize);
3296 try uleb128(diw, 0);
3297 },
3298 }
3299
3300 try wip_nav.abbrevCode(.unsigned_tagged_union_field);
3259 try wip_nav.strp("null");
3260 try wip_nav.refType(.null);
33013261 try uleb128(diw, 0);
3262 },
3263 .unpacked, .error_set, .pointer => {
3264 try wip_nav.abbrevCode(.tagged_union);
3265 try wip_nav.infoSectionOffset(
3266 .debug_info,
3267 wip_nav.unit,
3268 wip_nav.entry,
3269 @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()),
3270 );
33023271 {
33033272 try wip_nav.abbrevCode(.generated_field);
3304 try wip_nav.strp("null");
3305 try wip_nav.refType(.null);
3306 try uleb128(diw, 0);
3307 }
3308 try uleb128(diw, @intFromEnum(AbbrevCode.null));
3273 try wip_nav.strp("has_value");
3274 switch (opt_repr) {
3275 .opv_null => unreachable,
3276 .unpacked => {
3277 try wip_nav.refType(.bool);
3278 try uleb128(diw, if (opt_child_type.hasRuntimeBits(zcu))
3279 opt_child_type.abiSize(zcu)
3280 else
3281 0);
3282 },
3283 .error_set => {
3284 try wip_nav.refType(.fromInterned(try pt.intern(.{ .int_type = .{
3285 .signedness = .unsigned,
3286 .bits = zcu.errorSetBits(),
3287 } })));
3288 try uleb128(diw, 0);
3289 },
3290 .pointer => {
3291 try wip_nav.refType(.usize);
3292 try uleb128(diw, 0);
3293 },
3294 }
33093295
3310 try wip_nav.abbrevCode(.tagged_union_default_field);
3311 {
3312 try wip_nav.abbrevCode(.generated_field);
3313 try wip_nav.strp("?");
3314 try wip_nav.refType(opt_child_type);
3296 try wip_nav.abbrevCode(.unsigned_tagged_union_field);
33153297 try uleb128(diw, 0);
3298 {
3299 try wip_nav.abbrevCode(.generated_field);
3300 try wip_nav.strp("null");
3301 try wip_nav.refType(.null);
3302 try uleb128(diw, 0);
3303 }
3304 try uleb128(diw, @intFromEnum(AbbrevCode.null));
3305
3306 try wip_nav.abbrevCode(.tagged_union_default_field);
3307 {
3308 try wip_nav.abbrevCode(.generated_field);
3309 try wip_nav.strp("?");
3310 try wip_nav.refType(opt_child_type);
3311 try uleb128(diw, 0);
3312 }
3313 try uleb128(diw, @intFromEnum(AbbrevCode.null));
33163314 }
33173315 try uleb128(diw, @intFromEnum(AbbrevCode.null));
3318 }
3319 try uleb128(diw, @intFromEnum(AbbrevCode.null));
3316 },
33203317 }
33213318 try uleb128(diw, @intFromEnum(AbbrevCode.null));
33223319 },
......@@ -3850,22 +3847,31 @@ fn updateLazyValue(
38503847 try uleb128(diw, @intFromEnum(AbbrevCode.null));
38513848 },
38523849 .opt => |opt| {
3853 const child_type: Type = .fromInterned(ip.indexToKey(opt.ty).opt_type);
3850 const opt_child_type: Type = .fromInterned(ip.indexToKey(opt.ty).opt_type);
38543851 try wip_nav.abbrevCode(.aggregate_comptime_value);
38553852 try wip_nav.refType(.fromInterned(opt.ty));
38563853 {
38573854 try wip_nav.abbrevCode(.comptime_value_field_runtime_bits);
38583855 try wip_nav.strp("has_value");
3859 if (Type.fromInterned(opt.ty).optionalReprIsPayload(zcu)) {
3860 try wip_nav.blockValue(src_loc, .fromInterned(opt.val));
3861 } else {
3862 try uleb128(diw, 1);
3863 try diw.writeByte(@intFromBool(opt.val != .none));
3856 switch (optRepr(opt_child_type, zcu)) {
3857 .opv_null => try uleb128(diw, 0),
3858 .unpacked => try wip_nav.blockValue(src_loc, .makeBool(opt.val != .none)),
3859 .error_set => try wip_nav.blockValue(src_loc, .fromInterned(value_index)),
3860 .pointer => if (opt_child_type.comptimeOnly(zcu)) {
3861 var buf: [8]u8 = undefined;
3862 const bytes = buf[0..@divExact(zcu.getTarget().ptrBitWidth(), 8)];
3863 dwarf.writeInt(bytes, switch (opt.val) {
3864 .none => 0,
3865 else => opt_child_type.ptrAlignment(zcu).toByteUnits().?,
3866 });
3867 try uleb128(diw, bytes.len);
3868 try diw.writeAll(bytes);
3869 } else try wip_nav.blockValue(src_loc, .fromInterned(value_index)),
38643870 }
38653871 }
38663872 if (opt.val != .none) child_field: {
3867 const has_runtime_bits = child_type.hasRuntimeBits(zcu);
3868 const has_comptime_state = child_type.comptimeOnly(zcu) and try child_type.onePossibleValue(pt) == null;
3873 const has_runtime_bits = opt_child_type.hasRuntimeBits(zcu);
3874 const has_comptime_state = opt_child_type.comptimeOnly(zcu) and try opt_child_type.onePossibleValue(pt) == null;
38693875 try wip_nav.abbrevCode(if (has_comptime_state)
38703876 .comptime_value_field_comptime_state
38713877 else if (has_runtime_bits)
......@@ -3995,6 +4001,23 @@ fn updateLazyValue(
39954001 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items);
39964002}
39974003
4004fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum {
4005 unpacked,
4006 opv_null,
4007 error_set,
4008 pointer,
4009} {
4010 if (opt_child_type.isNoReturn(zcu)) return .opv_null;
4011 return switch (opt_child_type.toIntern()) {
4012 .anyerror_type => .error_set,
4013 else => switch (zcu.intern_pool.indexToKey(opt_child_type.toIntern())) {
4014 else => .unpacked,
4015 .error_set_type, .inferred_error_set_type => .error_set,
4016 .ptr_type => |ptr_type| if (ptr_type.flags.is_allowzero) .unpacked else .pointer,
4017 },
4018 };
4019}
4020
39984021pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternPool.Index) UpdateError!void {
39994022 const zcu = pt.zcu;
40004023 const ip = &zcu.intern_pool;
test/behavior/optional.zig+11
......@@ -656,3 +656,14 @@ test "result location initialization of optional with OPV payload" {
656656 _ = &c;
657657 try expectEqual(0, (c orelse return error.TestFailed).x);
658658}
659
660test "global comptime only optional" {
661 const S = struct {
662 const @"null": ?*type = null;
663 const @"void": ?*const type = &void;
664 };
665 comptime {
666 assert(S.null == null);
667 assert(S.void.?.* == void);
668 }
669}