Commit 220f80e71d
Changed files (4)
test
behavior
src/link/Dwarf.zig
@@ -3248,75 +3248,72 @@ fn updateLazyType(
},
.opt_type => |opt_child_type_index| {
const opt_child_type: Type = .fromInterned(opt_child_type_index);
+ const opt_repr = optRepr(opt_child_type, zcu);
try wip_nav.abbrevCode(.generated_union_type);
try wip_nav.strp(name);
try uleb128(diw, ty.abiSize(zcu));
try uleb128(diw, ty.abiAlignment(zcu).toByteUnits().?);
- if (opt_child_type.isNoReturn(zcu)) {
- try wip_nav.abbrevCode(.generated_field);
- try wip_nav.strp("null");
- try wip_nav.refType(.null);
- try uleb128(diw, 0);
- } else {
- try wip_nav.abbrevCode(.tagged_union);
- try wip_nav.infoSectionOffset(
- .debug_info,
- wip_nav.unit,
- wip_nav.entry,
- @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()),
- );
- {
+ switch (opt_repr) {
+ .opv_null => {
try wip_nav.abbrevCode(.generated_field);
- try wip_nav.strp("has_value");
- const repr: enum { unpacked, error_set, pointer } = switch (opt_child_type_index) {
- .anyerror_type => .error_set,
- else => switch (ip.indexToKey(opt_child_type_index)) {
- else => .unpacked,
- .error_set_type, .inferred_error_set_type => .error_set,
- .ptr_type => |ptr_type| if (ptr_type.flags.is_allowzero) .unpacked else .pointer,
- },
- };
- switch (repr) {
- .unpacked => {
- try wip_nav.refType(.bool);
- try uleb128(diw, if (opt_child_type.hasRuntimeBits(zcu))
- opt_child_type.abiSize(zcu)
- else
- 0);
- },
- .error_set => {
- try wip_nav.refType(.fromInterned(try pt.intern(.{ .int_type = .{
- .signedness = .unsigned,
- .bits = zcu.errorSetBits(),
- } })));
- try uleb128(diw, 0);
- },
- .pointer => {
- try wip_nav.refType(.usize);
- try uleb128(diw, 0);
- },
- }
-
- try wip_nav.abbrevCode(.unsigned_tagged_union_field);
+ try wip_nav.strp("null");
+ try wip_nav.refType(.null);
try uleb128(diw, 0);
+ },
+ .unpacked, .error_set, .pointer => {
+ try wip_nav.abbrevCode(.tagged_union);
+ try wip_nav.infoSectionOffset(
+ .debug_info,
+ wip_nav.unit,
+ wip_nav.entry,
+ @intCast(wip_nav.debug_info.items.len + dwarf.sectionOffsetBytes()),
+ );
{
try wip_nav.abbrevCode(.generated_field);
- try wip_nav.strp("null");
- try wip_nav.refType(.null);
- try uleb128(diw, 0);
- }
- try uleb128(diw, @intFromEnum(AbbrevCode.null));
+ try wip_nav.strp("has_value");
+ switch (opt_repr) {
+ .opv_null => unreachable,
+ .unpacked => {
+ try wip_nav.refType(.bool);
+ try uleb128(diw, if (opt_child_type.hasRuntimeBits(zcu))
+ opt_child_type.abiSize(zcu)
+ else
+ 0);
+ },
+ .error_set => {
+ try wip_nav.refType(.fromInterned(try pt.intern(.{ .int_type = .{
+ .signedness = .unsigned,
+ .bits = zcu.errorSetBits(),
+ } })));
+ try uleb128(diw, 0);
+ },
+ .pointer => {
+ try wip_nav.refType(.usize);
+ try uleb128(diw, 0);
+ },
+ }
- try wip_nav.abbrevCode(.tagged_union_default_field);
- {
- try wip_nav.abbrevCode(.generated_field);
- try wip_nav.strp("?");
- try wip_nav.refType(opt_child_type);
+ try wip_nav.abbrevCode(.unsigned_tagged_union_field);
try uleb128(diw, 0);
+ {
+ try wip_nav.abbrevCode(.generated_field);
+ try wip_nav.strp("null");
+ try wip_nav.refType(.null);
+ try uleb128(diw, 0);
+ }
+ try uleb128(diw, @intFromEnum(AbbrevCode.null));
+
+ try wip_nav.abbrevCode(.tagged_union_default_field);
+ {
+ try wip_nav.abbrevCode(.generated_field);
+ try wip_nav.strp("?");
+ try wip_nav.refType(opt_child_type);
+ try uleb128(diw, 0);
+ }
+ try uleb128(diw, @intFromEnum(AbbrevCode.null));
}
try uleb128(diw, @intFromEnum(AbbrevCode.null));
- }
- try uleb128(diw, @intFromEnum(AbbrevCode.null));
+ },
}
try uleb128(diw, @intFromEnum(AbbrevCode.null));
},
@@ -3850,22 +3847,31 @@ fn updateLazyValue(
try uleb128(diw, @intFromEnum(AbbrevCode.null));
},
.opt => |opt| {
- const child_type: Type = .fromInterned(ip.indexToKey(opt.ty).opt_type);
+ const opt_child_type: Type = .fromInterned(ip.indexToKey(opt.ty).opt_type);
try wip_nav.abbrevCode(.aggregate_comptime_value);
try wip_nav.refType(.fromInterned(opt.ty));
{
try wip_nav.abbrevCode(.comptime_value_field_runtime_bits);
try wip_nav.strp("has_value");
- if (Type.fromInterned(opt.ty).optionalReprIsPayload(zcu)) {
- try wip_nav.blockValue(src_loc, .fromInterned(opt.val));
- } else {
- try uleb128(diw, 1);
- try diw.writeByte(@intFromBool(opt.val != .none));
+ switch (optRepr(opt_child_type, zcu)) {
+ .opv_null => try uleb128(diw, 0),
+ .unpacked => try wip_nav.blockValue(src_loc, .makeBool(opt.val != .none)),
+ .error_set => try wip_nav.blockValue(src_loc, .fromInterned(value_index)),
+ .pointer => if (opt_child_type.comptimeOnly(zcu)) {
+ var buf: [8]u8 = undefined;
+ const bytes = buf[0..@divExact(zcu.getTarget().ptrBitWidth(), 8)];
+ dwarf.writeInt(bytes, switch (opt.val) {
+ .none => 0,
+ else => opt_child_type.ptrAlignment(zcu).toByteUnits().?,
+ });
+ try uleb128(diw, bytes.len);
+ try diw.writeAll(bytes);
+ } else try wip_nav.blockValue(src_loc, .fromInterned(value_index)),
}
}
if (opt.val != .none) child_field: {
- const has_runtime_bits = child_type.hasRuntimeBits(zcu);
- const has_comptime_state = child_type.comptimeOnly(zcu) and try child_type.onePossibleValue(pt) == null;
+ const has_runtime_bits = opt_child_type.hasRuntimeBits(zcu);
+ const has_comptime_state = opt_child_type.comptimeOnly(zcu) and try opt_child_type.onePossibleValue(pt) == null;
try wip_nav.abbrevCode(if (has_comptime_state)
.comptime_value_field_comptime_state
else if (has_runtime_bits)
@@ -3995,6 +4001,23 @@ fn updateLazyValue(
try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.items);
}
+fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum {
+ unpacked,
+ opv_null,
+ error_set,
+ pointer,
+} {
+ if (opt_child_type.isNoReturn(zcu)) return .opv_null;
+ return switch (opt_child_type.toIntern()) {
+ .anyerror_type => .error_set,
+ else => switch (zcu.intern_pool.indexToKey(opt_child_type.toIntern())) {
+ else => .unpacked,
+ .error_set_type, .inferred_error_set_type => .error_set,
+ .ptr_type => |ptr_type| if (ptr_type.flags.is_allowzero) .unpacked else .pointer,
+ },
+ };
+}
+
pub fn updateContainerType(dwarf: *Dwarf, pt: Zcu.PerThread, type_index: InternPool.Index) UpdateError!void {
const zcu = pt.zcu;
const ip = &zcu.intern_pool;
src/Type.zig
@@ -808,7 +808,7 @@ pub fn isNoReturn(ty: Type, zcu: *const Zcu) bool {
return zcu.intern_pool.isNoReturn(ty.toIntern());
}
-/// Returns `none` if the pointer is naturally aligned and the element type is 0-bit.
+/// Never returns `none`. Asserts that all necessary type resolution is already done.
pub fn ptrAlignment(ty: Type, zcu: *Zcu) Alignment {
return ptrAlignmentInner(ty, .normal, zcu, {}) catch unreachable;
}
@@ -825,15 +825,9 @@ pub fn ptrAlignmentInner(
) !Alignment {
return switch (zcu.intern_pool.indexToKey(ty.toIntern())) {
.ptr_type => |ptr_type| {
- if (ptr_type.flags.alignment != .none)
- return ptr_type.flags.alignment;
-
- if (strat == .sema) {
- const res = try Type.fromInterned(ptr_type.child).abiAlignmentInner(.sema, zcu, tid);
- return res.scalar;
- }
-
- return Type.fromInterned(ptr_type.child).abiAlignment(zcu);
+ if (ptr_type.flags.alignment != .none) return ptr_type.flags.alignment;
+ const res = try Type.fromInterned(ptr_type.child).abiAlignmentInner(strat.toLazy(), zcu, tid);
+ return res.scalar;
},
.opt_type => |child| Type.fromInterned(child).ptrAlignmentInner(strat, zcu, tid),
else => unreachable,
src/Value.zig
@@ -3690,7 +3690,7 @@ pub const generic_poison_type: Value = .{ .ip_index = .generic_poison_type };
pub const empty_tuple: Value = .{ .ip_index = .empty_tuple };
pub fn makeBool(x: bool) Value {
- return if (x) Value.true else Value.false;
+ return if (x) .true else .false;
}
/// `parent_ptr` must be a single-pointer to some optional.
test/behavior/optional.zig
@@ -656,3 +656,14 @@ test "result location initialization of optional with OPV payload" {
_ = &c;
try expectEqual(0, (c orelse return error.TestFailed).x);
}
+
+test "global comptime only optional" {
+ const S = struct {
+ const @"null": ?*type = null;
+ const @"void": ?*const type = &void;
+ };
+ comptime {
+ assert(S.null == null);
+ assert(S.void.?.* == void);
+ }
+}