authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2026-01-03 02:55:18-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-01-05 11:24:48+01:00
logac64c758761108ef7e07efea0936d7efc3eb2eca
tree5ee5d1bc78c01f5a2e5fddea5be372f2e41c1418
parent866989881927f256af1c495577007d715c6ae610

Dwarf: implement pointers to more comptime values

Closes #30600 Closes #30602

3 files changed, 126 insertions(+), 16 deletions(-)

src/link/Dwarf.zig+104-16
......@@ -3618,7 +3618,7 @@ fn updateLazyType(
36183618 try wip_nav.strp(name);
36193619 if (array_type.sentinel != .none) try wip_nav.blockValue(src_loc, .fromInterned(array_type.sentinel));
36203620 try wip_nav.refType(array_child_type);
3621 try wip_nav.abbrevCode(.array_index);
3621 try wip_nav.abbrevCode(.array_len);
36223622 try wip_nav.refType(.usize);
36233623 try diw.writeUleb128(array_type.len);
36243624 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
......@@ -3627,7 +3627,7 @@ fn updateLazyType(
36273627 try wip_nav.abbrevCode(.vector_type);
36283628 try wip_nav.strp(name);
36293629 try wip_nav.refType(.fromInterned(vector_type.child));
3630 try wip_nav.abbrevCode(.array_index);
3630 try wip_nav.abbrevCode(.array_len);
36313631 try wip_nav.refType(.usize);
36323632 try diw.writeUleb128(vector_type.len);
36333633 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
......@@ -4177,24 +4177,38 @@ fn updateLazyValue(
41774177 try wip_nav.refType(.fromInterned(float.ty));
41784178 },
41794179 .ptr => |ptr| {
4180 const Access = union(enum) {
4181 index: u64,
4182 field: InternPool.NullTerminatedString,
4183 synthetic_field: []const u8,
4184 tuple_index: u32,
4185 };
4186 var zero_bit_accesses: std.ArrayList(Access) = .empty;
4187 defer zero_bit_accesses.deinit(dwarf.gpa);
41804188 location: {
41814189 var base_addr = ptr.base_addr;
41824190 var byte_offset = ptr.byte_offset;
41834191 const base_unit, const base_entry = while (true) {
4184 const base_ptr = base_ptr: switch (base_addr) {
4192 const base_ptr, const access: Access = base_ptr_access: switch (base_addr) {
41854193 .nav => |nav_index| break try wip_nav.getNavEntry(nav_index),
41864194 .comptime_alloc, .comptime_field => unreachable,
41874195 .uav => |uav| {
41884196 const uav_ty: Type = .fromInterned(ip.typeOf(uav.val));
41894197 if (try uav_ty.onePossibleValue(pt)) |_| {
4190 try wip_nav.abbrevCode(.udata_comptime_value);
4198 try wip_nav.abbrevCode(if (zero_bit_accesses.items.len > 0)
4199 .aggregate_udata_comptime_value
4200 else
4201 .udata_comptime_value);
41914202 try diw.writeUleb128(ip.indexToKey(uav.orig_ty).ptr_type.flags.alignment.toByteUnits() orelse
41924203 uav_ty.abiAlignment(zcu).toByteUnits().?);
41934204 break :location;
41944205 } else break try wip_nav.getValueEntry(.fromInterned(uav.val));
41954206 },
41964207 .int => {
4197 try wip_nav.abbrevCode(.udata_comptime_value);
4208 try wip_nav.abbrevCode(if (zero_bit_accesses.items.len > 0)
4209 .aggregate_udata_comptime_value
4210 else
4211 .udata_comptime_value);
41984212 try diw.writeUleb128(byte_offset);
41994213 break :location;
42004214 },
......@@ -4203,16 +4217,40 @@ fn updateLazyValue(
42034217 byte_offset += codegen.errUnionPayloadOffset(.fromInterned(ip.indexToKey(
42044218 ip.indexToKey(base_ptr.ty).ptr_type.child,
42054219 ).error_union_type.payload_type), zcu);
4206 break :base_ptr base_ptr;
4220 break :base_ptr_access .{ base_ptr, .{ .synthetic_field = "value" } };
4221 },
4222 .opt_payload => |opt_ptr| .{ ip.indexToKey(opt_ptr).ptr, .{ .synthetic_field = "?" } },
4223 .field => |field| {
4224 const base_ptr = ip.indexToKey(field.base).ptr;
4225 const agg_ty: Type = .fromInterned(ip.indexToKey(base_ptr.ty).ptr_type.child);
4226 break :base_ptr_access .{
4227 base_ptr,
4228 if (agg_ty.isSlice(zcu)) .{ .synthetic_field = switch (field.index) {
4229 Value.slice_ptr_index => "ptr",
4230 Value.slice_len_index => "len",
4231 else => unreachable,
4232 } } else if (agg_ty.structFieldName(@intCast(field.index), zcu).unwrap()) |field_name|
4233 .{ .field = field_name }
4234 else
4235 .{ .tuple_index = @intCast(field.index) },
4236 };
4237 },
4238 .arr_elem => |arr_elem| .{
4239 ip.indexToKey(arr_elem.base).ptr,
4240 .{ .index = arr_elem.index },
42074241 },
4208 .opt_payload => |opt_ptr| ip.indexToKey(opt_ptr).ptr,
4209 .field => unreachable,
4210 .arr_elem => unreachable,
42114242 };
42124243 base_addr = base_ptr.base_addr;
42134244 byte_offset += base_ptr.byte_offset;
4245 if (Type.fromInterned(ip.indexToKey(base_ptr.ty).ptr_type.child).hasRuntimeBits(zcu))
4246 assert(access != .index)
4247 else
4248 try zero_bit_accesses.append(dwarf.gpa, access);
42144249 };
4215 try wip_nav.abbrevCode(.location_comptime_value);
4250 try wip_nav.abbrevCode(if (zero_bit_accesses.items.len > 0)
4251 .aggregate_location_comptime_value
4252 else
4253 .location_comptime_value);
42164254 try wip_nav.infoExprLoc(.{ .implicit_pointer = .{
42174255 .unit = base_unit,
42184256 .entry = base_entry,
......@@ -4220,6 +4258,29 @@ fn updateLazyValue(
42204258 } });
42214259 }
42224260 try wip_nav.refType(.fromInterned(ptr.ty));
4261 if (zero_bit_accesses.items.len > 0) {
4262 for (zero_bit_accesses.items) |access| switch (access) {
4263 .index => |index| {
4264 try wip_nav.abbrevCode(.array_index);
4265 try diw.writeUleb128(index);
4266 },
4267 .field => |field| {
4268 try wip_nav.abbrevCode(.field);
4269 try wip_nav.strp(field.toSlice(ip));
4270 },
4271 .synthetic_field => |field| {
4272 try wip_nav.abbrevCode(.field);
4273 try wip_nav.strp(field);
4274 },
4275 .tuple_index => |index| {
4276 try wip_nav.abbrevCode(.field);
4277 var field_name_buf: [std.fmt.count("{d}", .{std.math.maxInt(u32)})]u8 = undefined;
4278 const field_name = std.fmt.bufPrint(&field_name_buf, "{d}", .{index}) catch unreachable;
4279 try wip_nav.strp(field_name);
4280 },
4281 };
4282 try diw.writeUleb128(@intFromEnum(AbbrevCode.null));
4283 }
42234284 },
42244285 .slice => |slice| {
42254286 try wip_nav.abbrevCode(.aggregate_comptime_value);
......@@ -4387,12 +4448,7 @@ fn updateLazyValue(
43874448 try dwarf.debug_info.section.replaceEntry(wip_nav.unit, wip_nav.entry, dwarf, wip_nav.debug_info.written());
43884449}
43894450
4390fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum {
4391 unpacked,
4392 opv_null,
4393 error_set,
4394 pointer,
4395} {
4451fn optRepr(opt_child_type: Type, zcu: *const Zcu) enum { unpacked, opv_null, error_set, pointer } {
43964452 if (opt_child_type.isNoReturn(zcu)) return .opv_null;
43974453 return switch (opt_child_type.toIntern()) {
43984454 .anyerror_type => .error_set,
......@@ -5233,6 +5289,7 @@ const AbbrevCode = enum {
52335289 module,
52345290 empty_file,
52355291 file,
5292 field,
52365293 signed_enum_field,
52375294 unsigned_enum_field,
52385295 big_enum_field,
......@@ -5261,6 +5318,7 @@ const AbbrevCode = enum {
52615318 array_sentinel_type,
52625319 vector_type,
52635320 array_index,
5321 array_len,
52645322 nullary_func_type,
52655323 func_type,
52665324 func_type_param,
......@@ -5308,10 +5366,12 @@ const AbbrevCode = enum {
53085366 data16_comptime_value,
53095367 sdata_comptime_value,
53105368 udata_comptime_value,
5369 aggregate_udata_comptime_value,
53115370 block_comptime_value,
53125371 string_comptime_value,
53135372 location_comptime_value,
53145373 aggregate_comptime_value,
5374 aggregate_location_comptime_value,
53155375 comptime_value_field_runtime_bits,
53165376 comptime_value_field_comptime_state,
53175377 comptime_value_elem_runtime_bits,
......@@ -5721,6 +5781,12 @@ const AbbrevCode = enum {
57215781 .{ .alignment, .udata },
57225782 },
57235783 },
5784 .field = .{
5785 .tag = .member,
5786 .attrs = &.{
5787 .{ .name, .strp },
5788 },
5789 },
57245790 .signed_enum_field = .{
57255791 .tag = .enumerator,
57265792 .attrs = &.{
......@@ -5936,6 +6002,12 @@ const AbbrevCode = enum {
59366002 },
59376003 },
59386004 .array_index = .{
6005 .tag = .subrange_type,
6006 .attrs = &.{
6007 .{ .lower_bound, .udata },
6008 },
6009 },
6010 .array_len = .{
59396011 .tag = .subrange_type,
59406012 .attrs = &.{
59416013 .{ .type, .ref_addr },
......@@ -6325,6 +6397,14 @@ const AbbrevCode = enum {
63256397 .{ .type, .ref_addr },
63266398 },
63276399 },
6400 .aggregate_udata_comptime_value = .{
6401 .tag = .ZIG_comptime_value,
6402 .children = true,
6403 .attrs = &.{
6404 .{ .const_value, .udata },
6405 .{ .type, .ref_addr },
6406 },
6407 },
63286408 .block_comptime_value = .{
63296409 .tag = .ZIG_comptime_value,
63306410 .attrs = &.{
......@@ -6353,6 +6433,14 @@ const AbbrevCode = enum {
63536433 .{ .type, .ref_addr },
63546434 },
63556435 },
6436 .aggregate_location_comptime_value = .{
6437 .tag = .ZIG_comptime_value,
6438 .children = true,
6439 .attrs = &.{
6440 .{ .location, .exprloc },
6441 .{ .type, .ref_addr },
6442 },
6443 },
63566444 .comptime_value_field_runtime_bits = .{
63576445 .tag = .member,
63586446 .attrs = &.{
test/behavior/slice.zig+12
......@@ -158,6 +158,18 @@ test "slice of type" {
158158 }
159159}
160160
161test "pass a slice of types to a function" {
162 const S = struct {
163 fn checkTypesSlice(types_slice: []const type) !void {
164 try expect(types_slice.len == 2);
165 try expect(types_slice[0] == anyerror);
166 try expect(types_slice[1] == bool);
167 }
168 };
169 const types_array = [_]type{ void, anyerror, bool };
170 try S.checkTypesSlice(types_array[1..]);
171}
172
161173test "generic malloc free" {
162174 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
163175
test/behavior/struct.zig+10
......@@ -2174,3 +2174,13 @@ test "avoid unused field function body compile error" {
21742174
21752175 try expect(Case.entry() == 1);
21762176}
2177
2178test "pass a pointer to a comptime-only struct field to a function" {
2179 const S = struct {
2180 fn checkField(field_ptr: *const type) !void {
2181 try expect(field_ptr.* == u42);
2182 }
2183 };
2184 const s: struct { x: type } = .{ .x = u42 };
2185 try S.checkField(&s.x);
2186}