Skip to content

Commit 220f80e

Browse files
jacobly0andrewrk
authored andcommitted
Dwarf: fix lowering of comptime-only optional pointer null values
Closes #22974
1 parent 4b0f77c commit 220f80e

File tree

4 files changed

+104
-76
lines changed

4 files changed

+104
-76
lines changed

src/Type.zig

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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.
812812
pub 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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3690,7 +3690,7 @@ pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type };
36903690
pub const empty_tuple: Value = .{ .ip_index = .empty_tuple };
36913691

36923692
pub 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

Lines changed: 88 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -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

4004+
fn 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+
39984021
pub 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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
660+
test "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+
}

0 commit comments

Comments
 (0)