authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-02-15 02:26:32+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-02-15 02:46:18-08:00
log6fe90a913a8876e78692d5e89652559f72e7644f
tree94c14895d96b669ed2f9d10d95a68f746dd73b5a
parentc280811d1d5b5d73e1eb4243c577f86375447e99

llvm: fix lowering of recursive debug info

This change allows recursing over types that are currently being resolved fully with a second pass of forward resolution. Closes #16414

2 files changed, 61 insertions(+), 34 deletions(-)

src/codegen/llvm.zig+49-34
......@@ -1928,17 +1928,26 @@ pub const Object = struct {
19281928 const gop = try o.di_type_map.getOrPut(gpa, ty.toIntern());
19291929 if (gop.found_existing) {
19301930 const annotated = gop.value_ptr.*;
1931 const di_type = annotated.toDIType();
1932 if (!annotated.isFwdOnly() or resolve == .fwd) {
1933 return di_type;
1931 switch (annotated) {
1932 // This type is currently attempting to be resolved fully, so make
1933 // sure a second recursion through the types uses forward resolution.
1934 .null => assert(resolve == .fwd),
1935 // This type already has at least forward resolution, only resolve
1936 // fully during full resolution.
1937 _ => {
1938 const di_type = annotated.toDIType();
1939 if (!annotated.isFwdOnly() or resolve == .fwd) {
1940 return di_type;
1941 }
1942 const entry: Object.DITypeMap.Entry = .{
1943 .key_ptr = gop.key_ptr,
1944 .value_ptr = gop.value_ptr,
1945 };
1946 return o.lowerDebugTypeImpl(entry, resolve, di_type);
1947 },
19341948 }
1935 const entry: Object.DITypeMap.Entry = .{
1936 .key_ptr = gop.key_ptr,
1937 .value_ptr = gop.value_ptr,
1938 };
1939 return o.lowerDebugTypeImpl(entry, resolve, di_type);
1940 }
1941 errdefer assert(o.di_type_map.orderedRemove(ty.toIntern()));
1949 } else gop.value_ptr.* = .null;
1950 errdefer if (!gop.found_existing) assert(o.di_type_map.orderedRemove(ty.toIntern()));
19421951 const entry: Object.DITypeMap.Entry = .{
19431952 .key_ptr = gop.key_ptr,
19441953 .value_ptr = gop.value_ptr,
......@@ -2041,7 +2050,7 @@ pub const Object = struct {
20412050 ty.abiAlignment(mod).toByteUnits(0) * 8,
20422051 enumerators.ptr,
20432052 @intCast(enumerators.len),
2044 try o.lowerDebugType(int_ty, .full),
2053 try o.lowerDebugType(int_ty, resolve),
20452054 "",
20462055 );
20472056 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
......@@ -2139,7 +2148,7 @@ pub const Object = struct {
21392148 ptr_align.toByteUnits(0) * 8, // align in bits
21402149 0, // offset in bits
21412150 0, // flags
2142 try o.lowerDebugType(ptr_ty, .full),
2151 try o.lowerDebugType(ptr_ty, resolve),
21432152 ),
21442153 dib.createMemberType(
21452154 fwd_decl.toScope(),
......@@ -2150,7 +2159,7 @@ pub const Object = struct {
21502159 len_align.toByteUnits(0) * 8, // align in bits
21512160 len_offset * 8, // offset in bits
21522161 0, // flags
2153 try o.lowerDebugType(len_ty, .full),
2162 try o.lowerDebugType(len_ty, resolve),
21542163 ),
21552164 };
21562165
......@@ -2214,7 +2223,7 @@ pub const Object = struct {
22142223 const array_di_ty = dib.createArrayType(
22152224 ty.abiSize(mod) * 8,
22162225 ty.abiAlignment(mod).toByteUnits(0) * 8,
2217 try o.lowerDebugType(ty.childType(mod), .full),
2226 try o.lowerDebugType(ty.childType(mod), resolve),
22182227 @intCast(ty.arrayLen(mod)),
22192228 );
22202229 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
......@@ -2240,7 +2249,7 @@ pub const Object = struct {
22402249 break :blk dib.createBasicType(name, info.bits, dwarf_encoding);
22412250 },
22422251 .Bool => dib.createBasicType("bool", 1, DW.ATE.boolean),
2243 else => try o.lowerDebugType(ty.childType(mod), .full),
2252 else => try o.lowerDebugType(ty.childType(mod), resolve),
22442253 };
22452254
22462255 const vector_di_ty = dib.createVectorType(
......@@ -2307,7 +2316,7 @@ pub const Object = struct {
23072316 payload_align.toByteUnits(0) * 8, // align in bits
23082317 0, // offset in bits
23092318 0, // flags
2310 try o.lowerDebugType(child_ty, .full),
2319 try o.lowerDebugType(child_ty, resolve),
23112320 ),
23122321 dib.createMemberType(
23132322 fwd_decl.toScope(),
......@@ -2318,7 +2327,7 @@ pub const Object = struct {
23182327 non_null_align.toByteUnits(0) * 8, // align in bits
23192328 non_null_offset * 8, // offset in bits
23202329 0, // flags
2321 try o.lowerDebugType(non_null_ty, .full),
2330 try o.lowerDebugType(non_null_ty, resolve),
23222331 ),
23232332 };
23242333
......@@ -2345,7 +2354,7 @@ pub const Object = struct {
23452354 .ErrorUnion => {
23462355 const payload_ty = ty.errorUnionPayload(mod);
23472356 if (!payload_ty.hasRuntimeBitsIgnoreComptime(mod)) {
2348 const err_set_di_ty = try o.lowerDebugType(Type.anyerror, .full);
2357 const err_set_di_ty = try o.lowerDebugType(Type.anyerror, resolve);
23492358 // The recursive call to `lowerDebugType` means we can't use `gop` anymore.
23502359 try o.di_type_map.put(gpa, ty.toIntern(), AnnotatedDITypePtr.initFull(err_set_di_ty));
23512360 return err_set_di_ty;
......@@ -2399,7 +2408,7 @@ pub const Object = struct {
23992408 error_align.toByteUnits(0) * 8, // align in bits
24002409 error_offset * 8, // offset in bits
24012410 0, // flags
2402 try o.lowerDebugType(Type.anyerror, .full),
2411 try o.lowerDebugType(Type.anyerror, resolve),
24032412 );
24042413 fields[payload_index] = dib.createMemberType(
24052414 fwd_decl.toScope(),
......@@ -2410,7 +2419,7 @@ pub const Object = struct {
24102419 payload_align.toByteUnits(0) * 8, // align in bits
24112420 payload_offset * 8, // offset in bits
24122421 0, // flags
2413 try o.lowerDebugType(payload_ty, .full),
2422 try o.lowerDebugType(payload_ty, resolve),
24142423 );
24152424
24162425 const full_di_ty = dib.createStructType(
......@@ -2506,7 +2515,7 @@ pub const Object = struct {
25062515 field_align.toByteUnits(0) * 8, // align in bits
25072516 field_offset * 8, // offset in bits
25082517 0, // flags
2509 try o.lowerDebugType(Type.fromInterned(field_ty), .full),
2518 try o.lowerDebugType(Type.fromInterned(field_ty), resolve),
25102519 ));
25112520 }
25122521
......@@ -2584,7 +2593,7 @@ pub const Object = struct {
25842593 const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse
25852594 try ip.getOrPutStringFmt(gpa, "{d}", .{field_index});
25862595
2587 const field_di_ty = try o.lowerDebugType(field_ty, .full);
2596 const field_di_ty = try o.lowerDebugType(field_ty, resolve);
25882597
25892598 try di_fields.append(gpa, dib.createMemberType(
25902599 fwd_decl.toScope(),
......@@ -2653,7 +2662,7 @@ pub const Object = struct {
26532662 const layout = mod.getUnionLayout(union_obj);
26542663
26552664 if (layout.payload_size == 0) {
2656 const tag_di_ty = try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty), .full);
2665 const tag_di_ty = try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty), resolve);
26572666 const di_fields = [_]*llvm.DIType{tag_di_ty};
26582667 const full_di_ty = dib.createStructType(
26592668 compile_unit_scope,
......@@ -2689,7 +2698,7 @@ pub const Object = struct {
26892698 const field_size = Type.fromInterned(field_ty).abiSize(mod);
26902699 const field_align = mod.unionFieldNormalAlignment(union_obj, @intCast(field_index));
26912700
2692 const field_di_ty = try o.lowerDebugType(Type.fromInterned(field_ty), .full);
2701 const field_di_ty = try o.lowerDebugType(Type.fromInterned(field_ty), resolve);
26932702 const field_name = union_obj.field_names.get(ip)[field_index];
26942703 di_fields.appendAssumeCapacity(dib.createMemberType(
26952704 fwd_decl.toScope(),
......@@ -2751,7 +2760,7 @@ pub const Object = struct {
27512760 layout.tag_align.toByteUnits(0) * 8,
27522761 tag_offset * 8, // offset in bits
27532762 0, // flags
2754 try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty), .full),
2763 try o.lowerDebugType(Type.fromInterned(union_obj.enum_tag_ty), resolve),
27552764 );
27562765
27572766 const payload_di = dib.createMemberType(
......@@ -2802,21 +2811,21 @@ pub const Object = struct {
28022811 if (Type.fromInterned(fn_info.return_type).hasRuntimeBitsIgnoreComptime(mod)) {
28032812 const sret = firstParamSRet(fn_info, mod);
28042813 const di_ret_ty = if (sret) Type.void else Type.fromInterned(fn_info.return_type);
2805 try param_di_types.append(try o.lowerDebugType(di_ret_ty, .full));
2814 try param_di_types.append(try o.lowerDebugType(di_ret_ty, resolve));
28062815
28072816 if (sret) {
28082817 const ptr_ty = try mod.singleMutPtrType(Type.fromInterned(fn_info.return_type));
2809 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
2818 try param_di_types.append(try o.lowerDebugType(ptr_ty, resolve));
28102819 }
28112820 } else {
2812 try param_di_types.append(try o.lowerDebugType(Type.void, .full));
2821 try param_di_types.append(try o.lowerDebugType(Type.void, resolve));
28132822 }
28142823
28152824 if (Type.fromInterned(fn_info.return_type).isError(mod) and
28162825 o.module.comp.config.any_error_tracing)
28172826 {
28182827 const ptr_ty = try mod.singleMutPtrType(try o.getStackTraceType());
2819 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
2828 try param_di_types.append(try o.lowerDebugType(ptr_ty, resolve));
28202829 }
28212830
28222831 for (0..fn_info.param_types.len) |i| {
......@@ -2825,9 +2834,9 @@ pub const Object = struct {
28252834
28262835 if (isByRef(param_ty, mod)) {
28272836 const ptr_ty = try mod.singleMutPtrType(param_ty);
2828 try param_di_types.append(try o.lowerDebugType(ptr_ty, .full));
2837 try param_di_types.append(try o.lowerDebugType(ptr_ty, resolve));
28292838 } else {
2830 try param_di_types.append(try o.lowerDebugType(param_ty, .full));
2839 try param_di_types.append(try o.lowerDebugType(param_ty, resolve));
28312840 }
28322841 }
28332842
......@@ -11682,6 +11691,7 @@ const optional_layout_version = 3;
1168211691/// whether the type is fully resolved. Types that are only fwd declared
1168311692/// have the LSB flipped to a 1.
1168411693const AnnotatedDITypePtr = enum(usize) {
11694 null,
1168511695 _,
1168611696
1168711697 fn initFwd(di_type: *llvm.DIType) AnnotatedDITypePtr {
......@@ -11702,12 +11712,17 @@ const AnnotatedDITypePtr = enum(usize) {
1170211712 }
1170311713
1170411714 fn toDIType(self: AnnotatedDITypePtr) *llvm.DIType {
11705 const fixed_addr = @intFromEnum(self) & ~@as(usize, 1);
11706 return @ptrFromInt(fixed_addr);
11715 switch (self) {
11716 .null => unreachable,
11717 _ => return @ptrFromInt(@intFromEnum(self) & ~@as(usize, 1)),
11718 }
1170711719 }
1170811720
1170911721 fn isFwdOnly(self: AnnotatedDITypePtr) bool {
11710 return @as(u1, @truncate(@intFromEnum(self))) != 0;
11722 switch (self) {
11723 .null => unreachable,
11724 _ => return @as(u1, @truncate(@intFromEnum(self))) != 0,
11725 }
1171111726 }
1171211727};
1171311728
test/behavior/struct.zig+12
......@@ -2114,3 +2114,15 @@ test "initiate global variable with runtime value" {
21142114 };
21152115 try expect(S.some_struct.field == 1);
21162116}
2117
2118test "struct containing optional pointer to array of @This()" {
2119 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest;
2120
2121 const S = struct {
2122 x: ?*const [1]@This(),
2123 };
2124
2125 var s: S = .{ .x = &.{.{ .x = null }} };
2126 _ = &s;
2127 try expect(s.x.?[0].x == null);
2128}