Commit 94cf4d2d81

Tau <jonathan.haehne@hotmail.com>
2024-06-29 16:19:55
llvm: add pass-by-reference info to debug types
Without this data, debugger expressions try to pass structs by-value, which mostly just crashes. Also: mark enums as enum classes to prevent the enumerators from shadowing other identifiers.
1 parent 177b335
Changed files (2)
src
codegen
src/codegen/llvm/Builder.zig
@@ -7911,6 +7911,10 @@ pub const Metadata = enum(u32) {
         align_in_bits_lo: u32,
         align_in_bits_hi: u32,
         fields_tuple: Metadata,
+        flags: packed struct(u32) {
+            is_byref: bool,
+            pad: u31 = 0,
+        },
 
         pub fn bitSize(self: CompositeType) u64 {
             return @as(u64, self.size_in_bits_hi) << 32 | self.size_in_bits_lo;
@@ -11638,7 +11642,17 @@ fn addMetadataExtraAssumeCapacity(self: *Builder, extra: anytype) Metadata.Item.
             u32 => value,
             MetadataString, Metadata, Variable.Index, Value => @intFromEnum(value),
             Metadata.DIFlags => @bitCast(value),
-            else => @compileError("bad field type: " ++ @typeName(field.type)),
+            else => blk: {
+                switch (@typeInfo(field.type)) {
+                    .Struct => |s| {
+                        if (s.backing_integer == u32)
+                            break :blk @bitCast(value);
+                        @compileLog(s.layout, s.backing_integer);
+                    },
+                    else => {},
+                }
+                @compileError("bad field type: " ++ @typeName(field.type));
+            },
         });
     }
     return result;
@@ -11677,7 +11691,7 @@ fn metadataExtraDataTrail(
             u32 => value,
             MetadataString, Metadata, Variable.Index, Value => @enumFromInt(value),
             Metadata.DIFlags => @bitCast(value),
-            else => @compileError("bad field type: " ++ @typeName(field.type)),
+            else => @bitCast(value),
         };
     return .{
         .data = result,
@@ -11844,6 +11858,7 @@ pub fn debugStructType(
     size_in_bits: u64,
     align_in_bits: u64,
     fields_tuple: Metadata,
+    is_byref: bool,
 ) Allocator.Error!Metadata {
     try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0);
     return self.debugStructTypeAssumeCapacity(
@@ -11855,6 +11870,7 @@ pub fn debugStructType(
         size_in_bits,
         align_in_bits,
         fields_tuple,
+        is_byref,
     );
 }
 
@@ -11868,6 +11884,7 @@ pub fn debugUnionType(
     size_in_bits: u64,
     align_in_bits: u64,
     fields_tuple: Metadata,
+    is_byref: bool,
 ) Allocator.Error!Metadata {
     try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0);
     return self.debugUnionTypeAssumeCapacity(
@@ -11879,6 +11896,7 @@ pub fn debugUnionType(
         size_in_bits,
         align_in_bits,
         fields_tuple,
+        is_byref,
     );
 }
 
@@ -12400,6 +12418,7 @@ fn debugStructTypeAssumeCapacity(
     size_in_bits: u64,
     align_in_bits: u64,
     fields_tuple: Metadata,
+    is_byref: bool,
 ) Metadata {
     assert(!self.strip);
     return self.debugCompositeTypeAssumeCapacity(
@@ -12412,6 +12431,7 @@ fn debugStructTypeAssumeCapacity(
         size_in_bits,
         align_in_bits,
         fields_tuple,
+        is_byref,
     );
 }
 
@@ -12425,6 +12445,7 @@ fn debugUnionTypeAssumeCapacity(
     size_in_bits: u64,
     align_in_bits: u64,
     fields_tuple: Metadata,
+    is_byref: bool,
 ) Metadata {
     assert(!self.strip);
     return self.debugCompositeTypeAssumeCapacity(
@@ -12437,6 +12458,7 @@ fn debugUnionTypeAssumeCapacity(
         size_in_bits,
         align_in_bits,
         fields_tuple,
+        is_byref,
     );
 }
 
@@ -12462,6 +12484,7 @@ fn debugEnumerationTypeAssumeCapacity(
         size_in_bits,
         align_in_bits,
         fields_tuple,
+        false, // is_byref
     );
 }
 
@@ -12487,6 +12510,7 @@ fn debugArrayTypeAssumeCapacity(
         size_in_bits,
         align_in_bits,
         fields_tuple,
+        size_in_bits > 0, // is_byref
     );
 }
 
@@ -12512,6 +12536,7 @@ fn debugVectorTypeAssumeCapacity(
         size_in_bits,
         align_in_bits,
         fields_tuple,
+        false,
     );
 }
 
@@ -12526,6 +12551,7 @@ fn debugCompositeTypeAssumeCapacity(
     size_in_bits: u64,
     align_in_bits: u64,
     fields_tuple: Metadata,
+    is_byref: bool,
 ) Metadata {
     assert(!self.strip);
     return self.metadataSimpleAssumeCapacity(tag, Metadata.CompositeType{
@@ -12539,6 +12565,7 @@ fn debugCompositeTypeAssumeCapacity(
         .align_in_bits_lo = @truncate(align_in_bits),
         .align_in_bits_hi = @truncate(align_in_bits >> 32),
         .fields_tuple = fields_tuple,
+        .flags = .{ .is_byref = is_byref },
     });
 }
 
@@ -13973,7 +14000,11 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
                             .underlying_type = extra.underlying_type,
                             .size_in_bits = extra.bitSize(),
                             .align_in_bits = extra.bitAlign(),
-                            .flags = if (kind == .composite_vector_type) .{ .Vector = true } else .{},
+                            .flags = .{
+                                .Vector = kind == .composite_vector_type,
+                                .EnumClass = kind == .composite_enumeration_type,
+                                .TypePassbyReference = extra.flags.is_byref,
+                            },
                             .elements = extra.fields_tuple,
                         }, metadata_adapter);
                     },
src/codegen/llvm.zig
@@ -2068,6 +2068,7 @@ pub const Object = struct {
                             debug_ptr_type,
                             debug_len_type,
                         }),
+                        isByRef(ty, pt),
                     );
 
                     o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_slice_type);
@@ -2237,6 +2238,7 @@ pub const Object = struct {
                         debug_data_type,
                         debug_some_type,
                     }),
+                    isByRef(ty, pt),
                 );
 
                 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_optional_type);
@@ -2313,6 +2315,7 @@ pub const Object = struct {
                     ty.abiSize(pt) * 8,
                     (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
                     try o.builder.debugTuple(&fields),
+                    isByRef(ty, pt),
                 );
 
                 o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_error_union_type);
@@ -2542,6 +2545,7 @@ pub const Object = struct {
                         0, // Size
                         0, // Align
                         .none, // Fields
+                        false, // ByRef
                     );
                     break :res debug_opaque_type;
                 },
@@ -2601,6 +2605,7 @@ pub const Object = struct {
                                 ty.abiSize(pt) * 8,
                                 (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
                                 try o.builder.debugTuple(fields.items),
+                                isByRef(ty, pt),
                             );
 
                             break :res debug_struct_type;
@@ -2656,6 +2661,7 @@ pub const Object = struct {
                         ty.abiSize(pt) * 8,
                         (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
                         try o.builder.debugTuple(fields.items),
+                        isByRef(ty, pt),
                     );
 
                     break :res debug_struct_type;
@@ -2683,6 +2689,7 @@ pub const Object = struct {
                             try o.builder.debugTuple(
                                 &.{try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty), required_by_runtime)},
                             ),
+                            isByRef(ty, pt),
                         );
 
                         break :res debug_union_type;
@@ -2736,6 +2743,7 @@ pub const Object = struct {
                         ty.abiSize(pt) * 8,
                         (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
                         try o.builder.debugTuple(fields.items),
+                        isByRef(ty, pt),
                     );
 
                     if (layout.tag_size == 0) {
@@ -2791,6 +2799,7 @@ pub const Object = struct {
                         ty.abiSize(pt) * 8,
                         (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8,
                         try o.builder.debugTuple(&full_fields),
+                        isByRef(ty, pt),
                     );
 
                     break :res debug_tagged_union_type;
@@ -2824,6 +2833,7 @@ pub const Object = struct {
             0,
             0,
             if (fields.len == 0) .none else try o.builder.debugTuple(fields),
+            false, // is_byref
         );
     }