diff options
| author | Tau <jonathan.haehne@hotmail.com> | 2024-06-21 00:53:11 +0200 |
|---|---|---|
| committer | Tau <jonathan.haehne@hotmail.com> | 2024-07-19 17:51:37 +0200 |
| commit | 359bbdd5748779a4e1b12706e0be704cfacb5078 (patch) | |
| tree | e68f19e9bec8e2771d6442aad19764848c0f80ee /src/codegen | |
| parent | 876258abe46273aeac7c9791c7ec69bceb29f5ae (diff) | |
| download | zig-359bbdd5748779a4e1b12706e0be704cfacb5078.tar.gz zig-359bbdd5748779a4e1b12706e0be704cfacb5078.zip | |
llvm: encode variables as DW_TAG_imported_declaration
Now we get working global variable lookup in GDB! LLDB still re-mangles,
and it looks like we can't do much about that for now.
Also: translate non-owning type declarations into typedefs.
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/llvm.zig | 801 | ||||
| -rw-r--r-- | src/codegen/llvm/Builder.zig | 136 | ||||
| -rw-r--r-- | src/codegen/llvm/ir.zig | 25 |
3 files changed, 550 insertions, 412 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 1017977bbc..4018c9eead 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -814,14 +814,17 @@ pub const Object = struct { debug_enums_fwd_ref: Builder.Metadata, debug_globals_fwd_ref: Builder.Metadata, + debug_imports_fwd_ref: Builder.Metadata, debug_enums: std.ArrayListUnmanaged(Builder.Metadata), debug_globals: std.ArrayListUnmanaged(Builder.Metadata), + debug_imports: std.ArrayListUnmanaged(Builder.Metadata), debug_file_map: std.AutoHashMapUnmanaged(*const Zcu.File, Builder.Metadata), debug_type_map: std.AutoHashMapUnmanaged(Type, Builder.Metadata), - debug_unresolved_namespace_scopes: std.AutoArrayHashMapUnmanaged(InternPool.NamespaceIndex, Builder.Metadata), + // The value says whether this namespace's type is runtime-required. + debug_unresolved_namespace_scopes: std.AutoArrayHashMapUnmanaged(Type, bool), target: std.Target, /// Ideally we would use `llvm_module.getNamedFunction` to go from *Decl to LLVM function, @@ -884,7 +887,7 @@ pub const Object = struct { builder.data_layout = try builder.fmt("{}", .{DataLayoutBuilder{ .target = target }}); - const debug_compile_unit, const debug_enums_fwd_ref, const debug_globals_fwd_ref = + const debug_compile_unit, const debug_enums_fwd_ref, const debug_globals_fwd_ref, const debug_imports_fwd_ref = if (!builder.strip) debug_info: { // We fully resolve all paths at this point to avoid lack of @@ -916,6 +919,7 @@ pub const Object = struct { const debug_enums_fwd_ref = try builder.debugForwardReference(); const debug_globals_fwd_ref = try builder.debugForwardReference(); + const debug_imports_fwd_ref = try builder.debugForwardReference(); const debug_compile_unit = try builder.debugCompileUnit( debug_file, @@ -928,6 +932,7 @@ pub const Object = struct { }), debug_enums_fwd_ref, debug_globals_fwd_ref, + debug_imports_fwd_ref, .{ .optimized = comp.root_mod.optimize_mode != .Debug }, ); @@ -983,8 +988,8 @@ pub const Object = struct { } try builder.debugNamed(try builder.metadataString("llvm.dbg.cu"), &.{debug_compile_unit}); - break :debug_info .{ debug_compile_unit, debug_enums_fwd_ref, debug_globals_fwd_ref }; - } else .{.none} ** 3; + break :debug_info .{ debug_compile_unit, debug_enums_fwd_ref, debug_globals_fwd_ref, debug_imports_fwd_ref }; + } else .{.none} ** 4; const obj = try arena.create(Object); obj.* = .{ @@ -997,8 +1002,10 @@ pub const Object = struct { .debug_compile_unit = debug_compile_unit, .debug_enums_fwd_ref = debug_enums_fwd_ref, .debug_globals_fwd_ref = debug_globals_fwd_ref, + .debug_imports_fwd_ref = debug_imports_fwd_ref, .debug_enums = .{}, .debug_globals = .{}, + .debug_imports = .{}, .debug_file_map = .{}, .debug_type_map = .{}, .debug_unresolved_namespace_scopes = .{}, @@ -1151,6 +1158,11 @@ pub const Object = struct { self.debug_globals_fwd_ref, try self.builder.debugTuple(self.debug_globals.items), ); + + self.builder.debugForwardReferenceSetType( + self.debug_imports_fwd_ref, + try self.builder.debugTuple(self.debug_imports.items), + ); } } @@ -1634,7 +1646,7 @@ pub const Object = struct { const line_number = decl.navSrcLine(zcu) + 1; const is_internal_linkage = decl.val.getExternFunc(zcu) == null; - const debug_decl_type = try o.lowerDebugType(decl.typeOf(zcu)); + const debug_decl_type = try o.lowerDebugType(decl.typeOf(zcu), true); const subprogram = try o.builder.debugSubprogram( file, @@ -1904,6 +1916,7 @@ pub const Object = struct { pub fn lowerDebugType( o: *Object, ty: Type, + required_by_runtime: bool, ) Allocator.Error!Builder.Metadata { assert(!o.builder.strip); @@ -1913,8 +1926,13 @@ pub const Object = struct { const zcu = pt.zcu; const ip = &zcu.intern_pool; - if (o.debug_type_map.get(ty)) |debug_type| return debug_type; - + if (o.debug_type_map.get(ty)) |debug_type| { + if (required_by_runtime) { + if (o.debug_unresolved_namespace_scopes.getEntry(ty)) |entry| + entry.value_ptr.* = true; + } + return debug_type; + } switch (ty.zigTypeTag(zcu)) { .Void, @@ -1988,7 +2006,7 @@ pub const Object = struct { }, }, }); - const debug_ptr_type = try o.lowerDebugType(bland_ptr_ty); + const debug_ptr_type = try o.lowerDebugType(bland_ptr_ty, required_by_runtime); try o.debug_type_map.put(gpa, ty, debug_ptr_type); return debug_ptr_type; } @@ -2019,7 +2037,7 @@ pub const Object = struct { .none, // File debug_fwd_ref, 0, // Line - try o.lowerDebugType(ptr_ty), + try o.lowerDebugType(ptr_ty, required_by_runtime), ptr_size * 8, (ptr_align.toByteUnits() orelse 0) * 8, 0, // Offset @@ -2030,7 +2048,7 @@ pub const Object = struct { .none, // File debug_fwd_ref, 0, // Line - try o.lowerDebugType(len_ty), + try o.lowerDebugType(len_ty, required_by_runtime), len_size * 8, (len_align.toByteUnits() orelse 0) * 8, len_offset * 8, @@ -2059,7 +2077,7 @@ pub const Object = struct { return debug_slice_type; } - const debug_elem_ty = try o.lowerDebugType(Type.fromInterned(ptr_info.child)); + const debug_elem_ty = try o.lowerDebugType(Type.fromInterned(ptr_info.child), required_by_runtime); const name = try o.allocTypeName(ty); defer gpa.free(name); @@ -2089,7 +2107,7 @@ pub const Object = struct { .none, // File .none, // Scope 0, // Line - try o.lowerDebugType(ty.childType(zcu)), + try o.lowerDebugType(ty.childType(zcu), required_by_runtime), ty.abiSize(pt) * 8, (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8, try o.builder.debugTuple(&.{ @@ -2124,7 +2142,7 @@ pub const Object = struct { try o.builder.metadataString("bool"), 1, ), - else => try o.lowerDebugType(ty.childType(zcu)), + else => try o.lowerDebugType(ty.childType(zcu), required_by_runtime), }; const debug_vector_type = try o.builder.debugVectorType( @@ -2166,7 +2184,7 @@ pub const Object = struct { try o.debug_type_map.put(gpa, ty, debug_fwd_ref); if (ty.optionalReprIsPayload(zcu)) { - const debug_optional_type = try o.lowerDebugType(child_ty); + const debug_optional_type = try o.lowerDebugType(child_ty, required_by_runtime); o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_optional_type); @@ -2189,7 +2207,7 @@ pub const Object = struct { .none, // File debug_fwd_ref, 0, // Line - try o.lowerDebugType(child_ty), + try o.lowerDebugType(child_ty, required_by_runtime), payload_size * 8, (payload_align.toByteUnits() orelse 0) * 8, 0, // Offset @@ -2200,7 +2218,7 @@ pub const Object = struct { .none, debug_fwd_ref, 0, - try o.lowerDebugType(non_null_ty), + try o.lowerDebugType(non_null_ty, required_by_runtime), non_null_size * 8, (non_null_align.toByteUnits() orelse 0) * 8, non_null_offset * 8, @@ -2232,7 +2250,7 @@ pub const Object = struct { const payload_ty = ty.errorUnionPayload(zcu); if (!payload_ty.hasRuntimeBitsIgnoreComptime(pt)) { // TODO: Maybe remove? - const debug_error_union_type = try o.lowerDebugType(Type.anyerror); + const debug_error_union_type = try o.lowerDebugType(Type.anyerror, required_by_runtime); try o.debug_type_map.put(gpa, ty, debug_error_union_type); return debug_error_union_type; } @@ -2269,7 +2287,7 @@ pub const Object = struct { .none, // File debug_fwd_ref, 0, // Line - try o.lowerDebugType(Type.anyerror), + try o.lowerDebugType(Type.anyerror, required_by_runtime), error_size * 8, (error_align.toByteUnits() orelse 0) * 8, error_offset * 8, @@ -2279,7 +2297,7 @@ pub const Object = struct { .none, // File debug_fwd_ref, 0, // Line - try o.lowerDebugType(payload_ty), + try o.lowerDebugType(payload_ty, required_by_runtime), payload_size * 8, (payload_align.toByteUnits() orelse 0) * 8, payload_offset * 8, @@ -2321,21 +2339,21 @@ pub const Object = struct { if (Type.fromInterned(fn_info.return_type).hasRuntimeBitsIgnoreComptime(pt)) { const sret = firstParamSRet(fn_info, pt, target); const ret_ty = if (sret) Type.void else Type.fromInterned(fn_info.return_type); - debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ret_ty)); + debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ret_ty, required_by_runtime)); if (sret) { const ptr_ty = try pt.singleMutPtrType(Type.fromInterned(fn_info.return_type)); - debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty)); + debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty, required_by_runtime)); } } else { - debug_param_types.appendAssumeCapacity(try o.lowerDebugType(Type.void)); + debug_param_types.appendAssumeCapacity(try o.lowerDebugType(Type.void, required_by_runtime)); } if (Type.fromInterned(fn_info.return_type).isError(zcu) and zcu.comp.config.any_error_tracing) { const ptr_ty = try pt.singleMutPtrType(try o.getStackTraceType()); - debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty)); + debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty, required_by_runtime)); } for (0..fn_info.param_types.len) |i| { @@ -2344,9 +2362,9 @@ pub const Object = struct { if (isByRef(param_ty, pt)) { const ptr_ty = try pt.singleMutPtrType(param_ty); - debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty)); + debug_param_types.appendAssumeCapacity(try o.lowerDebugType(ptr_ty, required_by_runtime)); } else { - debug_param_types.appendAssumeCapacity(try o.lowerDebugType(param_ty)); + debug_param_types.appendAssumeCapacity(try o.lowerDebugType(param_ty, required_by_runtime)); } } @@ -2367,421 +2385,419 @@ pub const Object = struct { .Frame => @panic("TODO implement lowerDebugType for Frame types"), .AnyFrame => @panic("TODO implement lowerDebugType for AnyFrame types"), // These are the types that need a correct scope. - .Enum, - .Struct, - .Union, - .Opaque => {} + .Enum, .Struct, .Union, .Opaque => {}, } + const fwd_ref = try o.builder.debugForwardReference(); + try o.debug_type_map.put(gpa, ty, fwd_ref); + try o.debug_unresolved_namespace_scopes.put(gpa, ty, required_by_runtime); + return fwd_ref; + } - const owner_decl_index = ty.getOwnerDeclOrNull(zcu); - const owner_decl: ?*Zcu.Decl = - if (owner_decl_index) |owner| zcu.declPtr(owner) else null; + fn genNamespaces(o: *Object) !void { + const gpa = o.gpa; + const pt = o.pt; + const zcu = pt.zcu; + const ip = &zcu.intern_pool; - const file = if (owner_decl) |owner| - try o.getDebugFile(zcu.namespacePtr(owner.src_namespace).fileScope(zcu)) else .none; - const scope = if (owner_decl) |owner| - try o.namespaceToDebugScope(owner.src_namespace) else o.debug_compile_unit; - const line = if (owner_decl) |owner| owner.typeSrcLine(zcu) + 1 else 0; + var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{}; + defer fields.deinit(gpa); + const unresolved = &o.debug_unresolved_namespace_scopes; + var unresolved_i: usize = 0; + while (unresolved_i < unresolved.count()) : (unresolved_i += 1) { + const ty = unresolved.keys()[unresolved_i]; + const required_by_runtime = unresolved.values()[unresolved_i]; - const name = if (owner_decl) |owner| owner.name.toSlice(ip) else try o.allocTypeName(ty); - defer if (owner_decl == null) gpa.free(name); + const owner_decl_index = ty.getOwnerDeclOrNull(zcu); + const owner_decl: ?*Zcu.Decl = + if (owner_decl_index) |owner| ip.declPtr(owner) else null; - switch (ty.zigTypeTag(zcu)) { - .Enum => { - if (!ty.hasRuntimeBitsIgnoreComptime(pt)) { - const debug_enum_type = try o.makeEmptyNamespaceDebugType(owner_decl_index.?); - try o.debug_type_map.put(gpa, ty, debug_enum_type); - return debug_enum_type; - } + const file = if (owner_decl) |owner| + try o.getDebugFile(zcu.namespacePtr(owner.src_namespace).fileScope(zcu)) + else + .none; + const scope = if (owner_decl) |owner| + try o.namespaceToDebugScope(owner.src_namespace) + else + o.debug_compile_unit; + const line = if (owner_decl) |owner| owner.typeSrcLine(zcu) + 1 else 0; - const enum_type = ip.loadEnumType(ty.toIntern()); + const name = if (owner_decl) |owner| owner.name.toSlice(ip) else try o.allocTypeName(ty); + defer if (owner_decl == null) gpa.free(name); - const enumerators = try gpa.alloc(Builder.Metadata, enum_type.names.len); - defer gpa.free(enumerators); + const fwd_ref = o.debug_type_map.get(ty).?; - const int_ty = Type.fromInterned(enum_type.tag_ty); - const int_info = ty.intInfo(zcu); - assert(int_info.bits != 0); + fields.clearRetainingCapacity(); - for (enum_type.names.get(ip), 0..) |field_name_ip, i| { - var bigint_space: Value.BigIntSpace = undefined; - const bigint = if (enum_type.values.len != 0) - Value.fromInterned(enum_type.values.get(ip)[i]).toBigInt(&bigint_space, pt) - else - std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst(); + const ns = if (ty.getNamespace(zcu)) |n| n.unwrap() else null; + if (ns) |ns_id| { + const namespace = ip.namespacePtr(ns_id); + try fields.ensureUnusedCapacity(gpa, namespace.decls.keys().len); - enumerators[i] = try o.builder.debugEnumerator( - try o.builder.metadataString(field_name_ip.toSlice(ip)), - int_info.signedness == .unsigned, - int_info.bits, - bigint, - ); - } + for (namespace.decls.keys()) |decl_id| { + const decl = ip.declPtr(decl_id); + const decl_name = decl.name.toSlice(ip); - const debug_enum_type = try o.builder.debugEnumerationType( - try o.builder.metadataString(name), - file, - scope, - line, - try o.lowerDebugType(int_ty), - ty.abiSize(pt) * 8, - (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8, - try o.builder.debugTuple(enumerators), - ); + if (!decl.has_tv) continue; + if (decl.kind != .named) continue; + if (decl.analysis != .complete) continue; - try o.debug_type_map.put(gpa, ty, debug_enum_type); - try o.debug_enums.append(gpa, debug_enum_type); - return debug_enum_type; - }, - .Opaque => { - if (ty.toIntern() == .anyopaque_type) { - const debug_opaque_type = try o.builder.debugSignedType( - try o.builder.metadataString("anyopaque"), - 0, - ); - try o.debug_type_map.put(gpa, ty, debug_opaque_type); - return debug_opaque_type; - } + const decl_line = decl.typeSrcLine(zcu) + 1; - const debug_opaque_type = try o.builder.debugStructType( - try o.builder.metadataString(name), - file, - scope, - line, - .none, // Underlying type - 0, // Size - 0, // Align - .none, // Fields - ); - try o.debug_type_map.put(gpa, ty, debug_opaque_type); - return debug_opaque_type; - }, - .Struct => { - if (zcu.typeToPackedStruct(ty)) |struct_type| { - const backing_int_ty = struct_type.backingIntTypeUnordered(ip); - if (backing_int_ty != .none) { - const info = Type.fromInterned(backing_int_ty).intInfo(zcu); - const builder_name = try o.builder.metadataString(name); - const debug_int_type = switch (info.signedness) { - .signed => try o.builder.debugSignedType(builder_name, ty.abiSize(pt) * 8), - .unsigned => try o.builder.debugUnsignedType(builder_name, ty.abiSize(pt) * 8), - }; - try o.debug_type_map.put(gpa, ty, debug_int_type); - return debug_int_type; + if (decl.val.typeOf(zcu).ip_index == .type_type) { + const nested_type = decl.val.toType(); + // If this decl is the owner of the type, it will + // already have been declared as a direct child and + // will not need to be typedef'd. + if (nested_type.getOwnerDeclOrNull(zcu)) |owner| { + if (owner == decl_id) continue; + } + + fields.appendAssumeCapacity(try o.builder.debugTypedef( + try o.builder.metadataString(decl_name), + try o.getDebugFile(namespace.fileScope(zcu)), + fwd_ref, + decl_line, + try o.lowerDebugType(nested_type, false), + 0, // Align + )); + } else if (decl.val.getVariable(zcu)) |v| { + fields.appendAssumeCapacity(try o.builder.debugStaticMemberType( + try o.builder.metadataString(decl_name), + try o.getDebugFile(namespace.fileScope(zcu)), + fwd_ref, + decl_line, + try o.lowerDebugType(Type.fromInterned(v.ty), false), + )); } } + } - switch (ip.indexToKey(ty.toIntern())) { - .anon_struct_type => |tuple| { - var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{}; - defer fields.deinit(gpa); - - try fields.ensureUnusedCapacity(gpa, tuple.types.len); - - comptime assert(struct_layout_version == 2); - var offset: u64 = 0; - - const debug_fwd_ref = try o.builder.debugForwardReference(); - - for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| { - if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(pt)) continue; - - const field_size = Type.fromInterned(field_ty).abiSize(pt); - const field_align = Type.fromInterned(field_ty).abiAlignment(pt); - const field_offset = field_align.forward(offset); - offset = field_offset + field_size; - - const field_name = if (tuple.names.len != 0) - tuple.names.get(ip)[i].toSlice(ip) - else - try std.fmt.allocPrintZ(gpa, "{d}", .{i}); - defer if (tuple.names.len == 0) gpa.free(field_name); - - fields.appendAssumeCapacity(try o.builder.debugMemberType( - try o.builder.metadataString(field_name), - .none, // File - debug_fwd_ref, - 0, - try o.lowerDebugType(Type.fromInterned(field_ty)), - field_size * 8, - (field_align.toByteUnits() orelse 0) * 8, - field_offset * 8, - )); - } - - const debug_struct_type = try o.builder.debugStructType( - try o.builder.metadataString(name), - file, - scope, - 0, // Line - .none, // Underlying type - ty.abiSize(pt) * 8, - (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8, - try o.builder.debugTuple(fields.items), - ); + if (!required_by_runtime) { + const res = try o.makeNamespaceDebugType(owner_decl_index.?, fields.items); + o.builder.debugForwardReferenceSetType(fwd_ref, res); + continue; + } - o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_struct_type); + const res = switch (ty.zigTypeTag(zcu)) { + .Enum => res: { + if (!ty.hasRuntimeBitsIgnoreComptime(pt)) { + break :res try o.makeNamespaceDebugType(owner_decl_index.?, fields.items); + } - try o.debug_type_map.put(gpa, ty, debug_struct_type); - return debug_struct_type; - }, - .struct_type => { - if (!ip.loadStructType(ty.toIntern()).haveFieldTypes(ip)) { - // This can happen if a struct type makes it all the way to - // flush() without ever being instantiated or referenced (even - // via pointer). The only reason we are hearing about it now is - // that it is being used as a namespace to put other debug types - // into. Therefore we can satisfy this by making an empty namespace, - // rather than changing the frontend to unnecessarily resolve the - // struct field types. - const debug_struct_type = try o.makeEmptyNamespaceDebugType(owner_decl_index.?); - try o.debug_type_map.put(gpa, ty, debug_struct_type); - return debug_struct_type; - } - }, - else => {}, - } + const enum_type = ip.loadEnumType(ty.toIntern()); - if (!ty.hasRuntimeBitsIgnoreComptime(pt)) { - const debug_struct_type = try o.makeEmptyNamespaceDebugType(owner_decl_index.?); - try o.debug_type_map.put(gpa, ty, debug_struct_type); - return debug_struct_type; - } + const enumerators = try gpa.alloc(Builder.Metadata, enum_type.names.len); + defer gpa.free(enumerators); - const struct_type = zcu.typeToStruct(ty).?; + const int_ty = Type.fromInterned(enum_type.tag_ty); + const int_info = ty.intInfo(zcu); + assert(int_info.bits != 0); - var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{}; - defer fields.deinit(gpa); + for (enum_type.names.get(ip), 0..) |field_name_ip, i| { + var bigint_space: Value.BigIntSpace = undefined; + const bigint = if (enum_type.values.len != 0) + Value.fromInterned(enum_type.values.get(ip)[i]).toBigInt(&bigint_space, pt) + else + std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst(); - try fields.ensureUnusedCapacity(gpa, struct_type.field_types.len); + enumerators[i] = try o.builder.debugEnumerator( + try o.builder.metadataString(field_name_ip.toSlice(ip)), + int_info.signedness == .unsigned, + int_info.bits, + bigint, + ); + } - const debug_fwd_ref = try o.builder.debugForwardReference(); + const debug_enum_type = try o.builder.debugEnumerationType( + try o.builder.metadataString(name), + file, + scope, + line, + try o.lowerDebugType(int_ty, required_by_runtime), + ty.abiSize(pt) * 8, + (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8, + try o.builder.debugTuple(enumerators), + ); - // Set as forward reference while the type is lowered in case it references itself - try o.debug_type_map.put(gpa, ty, debug_fwd_ref); + try o.debug_enums.append(gpa, debug_enum_type); + break :res debug_enum_type; + }, + .Opaque => res: { + if (ty.toIntern() == .anyopaque_type) { + break :res try o.builder.debugSignedType( + try o.builder.metadataString("anyopaque"), + 0, + ); + } - comptime assert(struct_layout_version == 2); - var it = struct_type.iterateRuntimeOrder(ip); - while (it.next()) |field_index| { - const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); - if (!field_ty.hasRuntimeBitsIgnoreComptime(pt)) continue; - const field_size = field_ty.abiSize(pt); - const field_align = pt.structFieldAlignment( - struct_type.fieldAlign(ip, field_index), - field_ty, - struct_type.layout, + const debug_opaque_type = try o.builder.debugStructType( + try o.builder.metadataString(name), + file, + scope, + line, + .none, // Underlying type + 0, // Size + 0, // Align + .none, // Fields ); - const field_offset = ty.structFieldOffset(field_index, pt); + break :res debug_opaque_type; + }, + .Struct => res: { + if (zcu.typeToPackedStruct(ty)) |struct_type| { + const backing_int_ty = struct_type.backingIntTypeUnordered(ip); + if (backing_int_ty != .none) { + const info = Type.fromInterned(backing_int_ty).intInfo(zcu); + const builder_name = try o.builder.metadataString(name); + const debug_int_type = switch (info.signedness) { + .signed => try o.builder.debugSignedType(builder_name, ty.abiSize(pt) * 8), + .unsigned => try o.builder.debugUnsignedType(builder_name, ty.abiSize(pt) * 8), + }; + break :res debug_int_type; + } + } - const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse - try ip.getOrPutStringFmt(gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls); + switch (ip.indexToKey(ty.toIntern())) { + .anon_struct_type => |tuple| { + try fields.ensureUnusedCapacity(gpa, tuple.types.len); + + comptime assert(struct_layout_version == 2); + var offset: u64 = 0; + + for (tuple.types.get(ip), tuple.values.get(ip), 0..) |field_ty, field_val, i| { + if (field_val != .none or !Type.fromInterned(field_ty).hasRuntimeBits(pt)) continue; + + const field_size = Type.fromInterned(field_ty).abiSize(pt); + const field_align = Type.fromInterned(field_ty).abiAlignment(pt); + const field_offset = field_align.forward(offset); + offset = field_offset + field_size; + + const field_name = if (tuple.names.len != 0) + tuple.names.get(ip)[i].toSlice(ip) + else + try std.fmt.allocPrintZ(gpa, "{d}", .{i}); + defer if (tuple.names.len == 0) gpa.free(field_name); + + fields.appendAssumeCapacity(try o.builder.debugMemberType( + try o.builder.metadataString(field_name), + .none, // File + fwd_ref, + 0, + try o.lowerDebugType(Type.fromInterned(field_ty), required_by_runtime), + field_size * 8, + (field_align.toByteUnits() orelse 0) * 8, + field_offset * 8, + )); + } - fields.appendAssumeCapacity(try o.builder.debugMemberType( - try o.builder.metadataString(field_name.toSlice(ip)), - file, - debug_fwd_ref, - 0, // Line - try o.lowerDebugType(field_ty), - field_size * 8, - (field_align.toByteUnits() orelse 0) * 8, - field_offset * 8, - )); - } + const debug_struct_type = try o.builder.debugStructType( + try o.builder.metadataString(name), + file, + scope, + 0, // Line + .none, // Underlying type + ty.abiSize(pt) * 8, + (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8, + try o.builder.debugTuple(fields.items), + ); - const debug_struct_type = try o.builder.debugStructType( - try o.builder.metadataString(name), - file, - scope, - line, - .none, // Underlying type - ty.abiSize(pt) * 8, - (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8, - try o.builder.debugTuple(fields.items), - ); + break :res debug_struct_type; + }, + else => {}, + } - o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_struct_type); + if (!ty.hasRuntimeBitsIgnoreComptime(pt)) { + break :res try o.makeNamespaceDebugType(owner_decl_index.?, fields.items); + } + const struct_type = zcu.typeToStruct(ty).?; - // Set to real type now that it has been lowered fully - const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable; - map_ptr.* = debug_struct_type; + if (!struct_type.haveLayout(ip) or !struct_type.haveFieldTypes(ip)) { + break :res try o.makeNamespaceDebugType(owner_decl_index.?, fields.items); + } - return debug_struct_type; - }, - .Union => { - const union_type = ip.loadUnionType(ty.toIntern()); - if (!union_type.haveFieldTypes(ip) or - !ty.hasRuntimeBitsIgnoreComptime(pt) or - !union_type.haveLayout(ip)) - { - const debug_union_type = try o.makeEmptyNamespaceDebugType(owner_decl_index.?); - try o.debug_type_map.put(gpa, ty, debug_union_type); - return debug_union_type; - } + try fields.ensureUnusedCapacity(gpa, struct_type.field_types.len); - const layout = pt.getUnionLayout(union_type); + comptime assert(struct_layout_version == 2); + var it = struct_type.iterateRuntimeOrder(ip); + while (it.next()) |field_index| { + const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); + if (!field_ty.hasRuntimeBitsIgnoreComptime(pt)) continue; + const field_size = field_ty.abiSize(pt); + const field_align = pt.structFieldAlignment( + struct_type.fieldAlign(ip, field_index), + field_ty, + struct_type.layout, + ); + const field_offset = ty.structFieldOffset(field_index, pt); - const debug_fwd_ref = try o.builder.debugForwardReference(); + const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse + try ip.getOrPutStringFmt(gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls); - // Set as forward reference while the type is lowered in case it references itself - try o.debug_type_map.put(gpa, ty, debug_fwd_ref); + fields.appendAssumeCapacity(try o.builder.debugMemberType( + try o.builder.metadataString(field_name.toSlice(ip)), + file, + fwd_ref, + 0, // Line + try o.lowerDebugType(field_ty, required_by_runtime), + field_size * 8, + (field_align.toByteUnits() orelse 0) * 8, + field_offset * 8, + )); + } - if (layout.payload_size == 0) { - const debug_union_type = try o.builder.debugStructType( + const debug_struct_type = try o.builder.debugStructType( try o.builder.metadataString(name), file, scope, - 0, // Line + line, .none, // Underlying type ty.abiSize(pt) * 8, (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8, - try o.builder.debugTuple( - &.{try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty))}, - ), + try o.builder.debugTuple(fields.items), ); - // Set to real type now that it has been lowered fully - const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable; - map_ptr.* = debug_union_type; - - return debug_union_type; - } - - var fields: std.ArrayListUnmanaged(Builder.Metadata) = .{}; - defer fields.deinit(gpa); - - try fields.ensureUnusedCapacity(gpa, union_type.loadTagType(ip).names.len); - - const debug_union_fwd_ref = if (layout.tag_size == 0) - debug_fwd_ref - else - try o.builder.debugForwardReference(); + break :res debug_struct_type; + }, + .Union => res: { + const union_type = ip.loadUnionType(ty.toIntern()); + if (!union_type.haveFieldTypes(ip) or + !ty.hasRuntimeBitsIgnoreComptime(pt) or + !union_type.haveLayout(ip)) + { + break :res try o.makeNamespaceDebugType(owner_decl_index.?, fields.items); + } - const tag_type = union_type.loadTagType(ip); + const layout = pt.getUnionLayout(union_type); - for (0..tag_type.names.len) |field_index| { - const field_ty = union_type.field_types.get(ip)[field_index]; - if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(pt)) continue; + if (layout.payload_size == 0) { + const debug_union_type = try o.builder.debugStructType( + try o.builder.metadataString(name), + file, + scope, + 0, // Line + .none, // Underlying type + ty.abiSize(pt) * 8, + (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8, + try o.builder.debugTuple( + &.{try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty), required_by_runtime)}, + ), + ); - const field_size = Type.fromInterned(field_ty).abiSize(pt); - const field_align: InternPool.Alignment = switch (union_type.flagsUnordered(ip).layout) { - .@"packed" => .none, - .auto, .@"extern" => pt.unionFieldNormalAlignment(union_type, @intCast(field_index)), - }; + break :res debug_union_type; + } - const field_name = tag_type.names.get(ip)[field_index]; - fields.appendAssumeCapacity(try o.builder.debugMemberType( - try o.builder.metadataString(field_name.toSlice(ip)), - file, - debug_union_fwd_ref, - 0, // Line - try o.lowerDebugType(Type.fromInterned(field_ty)), - field_size * 8, - (field_align.toByteUnits() orelse 0) * 8, - 0, // Offset - )); - } + try fields.ensureUnusedCapacity(gpa, union_type.loadTagType(ip).names.len); - var union_name_buf: ?[:0]const u8 = null; - defer if (union_name_buf) |buf| gpa.free(buf); - const union_name = if (layout.tag_size == 0) name else name: { - union_name_buf = try std.fmt.allocPrintZ(gpa, "{s}:Payload", .{name}); - break :name union_name_buf.?; - }; + const debug_union_fwd_ref = if (layout.tag_size == 0) + fwd_ref + else + try o.builder.debugForwardReference(); - const debug_union_type = try o.builder.debugUnionType( - try o.builder.metadataString(union_name), - file, - scope, - line, - .none, // Underlying type - ty.abiSize(pt) * 8, - (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8, - try o.builder.debugTuple(fields.items), - ); + const tag_type = union_type.loadTagType(ip); - o.builder.debugForwardReferenceSetType(debug_union_fwd_ref, debug_union_type); + for (0..tag_type.names.len) |field_index| { + const field_ty = union_type.field_types.get(ip)[field_index]; + if (!Type.fromInterned(field_ty).hasRuntimeBitsIgnoreComptime(pt)) continue; - if (layout.tag_size == 0) { - // Set to real type now that it has been lowered fully - const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable; - map_ptr.* = debug_union_type; + const field_size = Type.fromInterned(field_ty).abiSize(pt); + const field_align: InternPool.Alignment = switch (union_type.flagsUnordered(ip).layout) { + .@"packed" => .none, + .auto, .@"extern" => pt.unionFieldNormalAlignment(union_type, @intCast(field_index)), + }; - return debug_union_type; - } + const field_name = tag_type.names.get(ip)[field_index]; + fields.appendAssumeCapacity(try o.builder.debugMemberType( + try o.builder.metadataString(field_name.toSlice(ip)), + file, + debug_union_fwd_ref, + 0, // Line + try o.lowerDebugType(Type.fromInterned(field_ty), required_by_runtime), + field_size * 8, + (field_align.toByteUnits() orelse 0) * 8, + 0, // Offset + )); + } - var tag_offset: u64 = undefined; - var payload_offset: u64 = undefined; - if (layout.tag_align.compare(.gte, layout.payload_align)) { - tag_offset = 0; - payload_offset = layout.payload_align.forward(layout.tag_size); - } else { - payload_offset = 0; - tag_offset = layout.tag_align.forward(layout.payload_size); - } + var union_name_buf: ?[:0]const u8 = null; + defer if (union_name_buf) |buf| gpa.free(buf); + const union_name = if (layout.tag_size == 0) name else name: { + union_name_buf = try std.fmt.allocPrintZ(gpa, "{s}:Payload", .{name}); + break :name union_name_buf.?; + }; - const debug_tag_type = try o.builder.debugMemberType( - try o.builder.metadataString("tag"), - file, // File - debug_fwd_ref, - 0, // Line - try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty)), - layout.tag_size * 8, - (layout.tag_align.toByteUnits() orelse 0) * 8, - tag_offset * 8, - ); + const debug_union_type = try o.builder.debugUnionType( + try o.builder.metadataString(union_name), + file, + scope, + line, + .none, // Underlying type + ty.abiSize(pt) * 8, + (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8, + try o.builder.debugTuple(fields.items), + ); - const debug_payload_type = try o.builder.debugMemberType( - try o.builder.metadataString("payload"), - file, - debug_fwd_ref, - 0, // Line - debug_union_type, - layout.payload_size * 8, - (layout.payload_align.toByteUnits() orelse 0) * 8, - payload_offset * 8, - ); + if (layout.tag_size == 0) { + break :res debug_union_type; + } - const full_fields: [2]Builder.Metadata = - if (layout.tag_align.compare(.gte, layout.payload_align)) - .{ debug_tag_type, debug_payload_type } - else - .{ debug_payload_type, debug_tag_type }; + o.builder.debugForwardReferenceSetType(debug_union_fwd_ref, debug_union_type); - const debug_tagged_union_type = try o.builder.debugStructType( - try o.builder.metadataString(name), - file, // File - scope, - line, - .none, // Underlying type - ty.abiSize(pt) * 8, - (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8, - try o.builder.debugTuple(&full_fields), - ); + var tag_offset: u64 = undefined; + var payload_offset: u64 = undefined; + if (layout.tag_align.compare(.gte, layout.payload_align)) { + tag_offset = 0; + payload_offset = layout.payload_align.forward(layout.tag_size); + } else { + payload_offset = 0; + tag_offset = layout.tag_align.forward(layout.payload_size); + } - o.builder.debugForwardReferenceSetType(debug_fwd_ref, debug_tagged_union_type); + const debug_tag_type = try o.builder.debugMemberType( + try o.builder.metadataString("tag"), + file, // File + fwd_ref, + 0, // Line + try o.lowerDebugType(Type.fromInterned(union_type.enum_tag_ty), required_by_runtime), + layout.tag_size * 8, + (layout.tag_align.toByteUnits() orelse 0) * 8, + tag_offset * 8, + ); - // Set to real type now that it has been lowered fully - const map_ptr = o.debug_type_map.getPtr(ty) orelse unreachable; - map_ptr.* = debug_tagged_union_type; + const debug_payload_type = try o.builder.debugMemberType( + try o.builder.metadataString("payload"), + file, + fwd_ref, + 0, // Line + debug_union_type, + layout.payload_size * 8, + (layout.payload_align.toByteUnits() orelse 0) * 8, + payload_offset * 8, + ); - return debug_tagged_union_type; - }, - else => unreachable, // Handled above. - } - } + const full_fields: [2]Builder.Metadata = + if (layout.tag_align.compare(.gte, layout.payload_align)) + .{ debug_tag_type, debug_payload_type } + else + .{ debug_payload_type, debug_tag_type }; - fn genNamespaces(o: *Object) !void { - var i: usize = 0; - while (i < o.debug_unresolved_namespace_scopes.count()) : (i += 1) { - const namespace_index = o.debug_unresolved_namespace_scopes.keys()[i]; - const fwd_ref = o.debug_unresolved_namespace_scopes.values()[i]; + const debug_tagged_union_type = try o.builder.debugStructType( + try o.builder.metadataString(name), + file, // File + scope, + line, + .none, // Underlying type + ty.abiSize(pt) * 8, + (ty.abiAlignment(pt).toByteUnits() orelse 0) * 8, + try o.builder.debugTuple(&full_fields), + ); - const namespace = o.pt.zcu.namespacePtr(namespace_index); - const debug_type = try o.lowerDebugType(namespace.getType(o.pt.zcu)); + break :res debug_tagged_union_type; + }, + else => unreachable, // Handled above. + }; - o.builder.debugForwardReferenceSetType(fwd_ref, debug_type); + o.builder.debugForwardReferenceSetType(fwd_ref, res); } } @@ -2791,14 +2807,10 @@ pub const Object = struct { const file_scope = namespace.fileScope(zcu); if (namespace.parent == .none) return try o.getDebugFile(file_scope); - const gop = try o.debug_unresolved_namespace_scopes.getOrPut(o.gpa, namespace_index); - - if (!gop.found_existing) gop.value_ptr.* = try o.builder.debugForwardReference(); - - return gop.value_ptr.*; + return o.lowerDebugType(zcu.declPtr(namespace.decl_index).val.toType(), false); } - fn makeEmptyNamespaceDebugType(o: *Object, decl_index: InternPool.DeclIndex) !Builder.Metadata { + fn makeNamespaceDebugType(o: *Object, decl_index: InternPool.DeclIndex, fields: []const Builder.Metadata) !Builder.Metadata { const zcu = o.pt.zcu; const decl = zcu.declPtr(decl_index); const file_scope = zcu.namespacePtr(decl.src_namespace).fileScope(zcu); @@ -2810,7 +2822,7 @@ pub const Object = struct { .none, 0, 0, - .none, + if (fields.len == 0) .none else try o.builder.debugTuple(fields), ); } @@ -4723,6 +4735,7 @@ pub const DeclGen = struct { if (!owner_mod.strip) { const debug_file = try o.getDebugFile(file_scope); + const debug_scope = try o.namespaceToDebugScope(decl.src_namespace); const linkage_name = try o.builder.metadataStringFromStrtabString(variable_index.name(&o.builder)); @@ -4730,10 +4743,10 @@ pub const DeclGen = struct { // Imitate a C++ static member variable since neither // GDB or LLDB can really cope with regular variables // directly inside a struct type. - const ty = try o.lowerDebugType(decl.typeOf(zcu)); + const ty = try o.lowerDebugType(decl.typeOf(zcu), true); const name = try o.builder.metadataString(decl.name.toSlice(ip)); - break :blk try o.builder.debugGlobalVar( + const variable = try o.builder.debugGlobalVar( name, linkage_name, debug_file, @@ -4742,15 +4755,25 @@ pub const DeclGen = struct { ty, variable_index, .none, - .internal, + .external, ); + + try o.debug_imports.append(o.gpa, try o.builder.debugImportDeclaration( + name, + debug_file, + debug_scope, + line_number, + variable, + )); + + break :blk variable; } else try o.builder.debugGlobalVar( linkage_name, linkage_name, debug_file, debug_file, line_number, - try o.lowerDebugType(decl.typeOf(zcu)), + try o.lowerDebugType(decl.typeOf(zcu), true), variable_index, .none, .external, @@ -5209,7 +5232,7 @@ pub const FuncGen = struct { try o.builder.metadataString(decl.fqn.toSlice(&zcu.intern_pool)), line_number, line_number + func.lbrace_line, - try o.lowerDebugType(fn_ty), + try o.lowerDebugType(fn_ty, true), .{ .di_flags = .{ .StaticMember = true }, .sp_flags = .{ @@ -6759,7 +6782,7 @@ pub const FuncGen = struct { self.file, self.scope, self.prev_dbg_line, - try o.lowerDebugType(ptr_ty.childType(mod)), + try o.lowerDebugType(ptr_ty.childType(mod), true), ); _ = try self.wip.callIntrinsic( @@ -6792,7 +6815,7 @@ pub const FuncGen = struct { self.file, self.scope, self.prev_dbg_line, - try o.lowerDebugType(operand_ty), + try o.lowerDebugType(operand_ty, true), ); const pt = o.pt; @@ -8906,7 +8929,7 @@ pub const FuncGen = struct { self.file, self.scope, lbrace_line, - try o.lowerDebugType(inst_ty), + try o.lowerDebugType(inst_ty, true), @intCast(self.arg_index), ); diff --git a/src/codegen/llvm/Builder.zig b/src/codegen/llvm/Builder.zig index 5c82f0abb0..f42fc94dad 100644 --- a/src/codegen/llvm/Builder.zig +++ b/src/codegen/llvm/Builder.zig @@ -7652,6 +7652,8 @@ pub const Metadata = enum(u32) { derived_pointer_type, derived_member_type, derived_static_member_type, + derived_typedef, + imported_declaration, subroutine_type, enumerator_unsigned, enumerator_signed_positive, @@ -7699,6 +7701,8 @@ pub const Metadata = enum(u32) { .derived_pointer_type, .derived_member_type, .derived_static_member_type, + .derived_typedef, + .imported_declaration, .subroutine_type, .enumerator_unsigned, .enumerator_signed_positive, @@ -7816,6 +7820,7 @@ pub const Metadata = enum(u32) { producer: MetadataString, enums: Metadata, globals: Metadata, + imports: Metadata, }; pub const Subprogram = struct { @@ -7943,6 +7948,14 @@ pub const Metadata = enum(u32) { } }; + pub const ImportedEntity = struct { + name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + entity: Metadata, + }; + pub const SubroutineType = struct { types_tuple: Metadata, }; @@ -8232,6 +8245,7 @@ pub const Metadata = enum(u32) { DIBasicType, DICompositeType, DIDerivedType, + DIImportedEntity, DISubroutineType, DIEnumerator, DISubrange, @@ -9969,7 +9983,7 @@ pub fn printUnbuffered( .enums = extra.enums, .retainedTypes = null, .globals = extra.globals, - .imports = null, + .imports = extra.imports, .macros = null, .dwoId = null, .splitDebugInlining = false, @@ -10110,16 +10124,18 @@ pub fn printUnbuffered( .derived_pointer_type, .derived_member_type, .derived_static_member_type, + .derived_typedef, => |kind| { const extra = self.metadataExtraData(Metadata.DerivedType, metadata_item.data); try metadata_formatter.specialized(.@"!", .DIDerivedType, .{ .tag = @as(enum { DW_TAG_pointer_type, DW_TAG_member, + DW_TAG_typedef, }, switch (kind) { .derived_pointer_type => .DW_TAG_pointer_type, - .derived_member_type, - .derived_static_member_type => .DW_TAG_member, + .derived_member_type, .derived_static_member_type => .DW_TAG_member, + .derived_typedef => .DW_TAG_typedef, else => unreachable, }), .name = switch (extra.name) { @@ -10142,6 +10158,22 @@ pub fn printUnbuffered( .annotations = null, }, writer); }, + .imported_declaration => { + const extra = self.metadataExtraData(Metadata.ImportedEntity, metadata_item.data); + + try metadata_formatter.specialized(.@"!", .DIImportedEntity, .{ + .tag = .DW_TAG_imported_declaration, + .scope = extra.scope, + .entity = extra.entity, + .file = extra.file, + .line = extra.line, + .name = switch (extra.name) { + .none => null, + else => extra.name, + }, + .elements = null, + }, writer); + }, .subroutine_type => { const extra = self.metadataExtraData(Metadata.SubroutineType, metadata_item.data); try metadata_formatter.specialized(.@"!", .DISubroutineType, .{ @@ -11747,10 +11779,11 @@ pub fn debugCompileUnit( producer: MetadataString, enums: Metadata, globals: Metadata, + imports: Metadata, options: Metadata.CompileUnit.Options, ) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.CompileUnit, 0); - return self.debugCompileUnitAssumeCapacity(file, producer, enums, globals, options); + return self.debugCompileUnitAssumeCapacity(file, producer, enums, globals, imports, options); } pub fn debugSubprogram( @@ -12005,6 +12038,53 @@ pub fn debugMemberType( ); } +pub fn debugTypedef( + self: *Builder, + name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + underlying_type: Metadata, + align_in_bits: u64, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.DerivedType, 0); + + assert(!self.strip); + return self.metadataSimpleAssumeCapacity(.derived_typedef, Metadata.DerivedType{ + .name = name, + .file = file, + .scope = scope, + .line = line, + .underlying_type = underlying_type, + .size_in_bits_lo = 0, + .size_in_bits_hi = 0, + .align_in_bits_lo = @truncate(align_in_bits), + .align_in_bits_hi = @truncate(align_in_bits >> 32), + .offset_in_bits_lo = 0, + .offset_in_bits_hi = 0, + }); +} + +pub fn debugImportDeclaration( + self: *Builder, + name: MetadataString, + file: Metadata, + scope: Metadata, + line: u32, + entity: Metadata, +) Allocator.Error!Metadata { + try self.ensureUnusedMetadataCapacity(1, Metadata.ImportedEntity, 0); + + assert(!self.strip); + return self.metadataSimpleAssumeCapacity(.imported_declaration, Metadata.ImportedEntity{ + .name = name, + .file = file, + .scope = scope, + .line = line, + .entity = entity, + }); +} + pub fn debugSubroutineType( self: *Builder, types_tuple: Metadata, @@ -12241,6 +12321,7 @@ pub fn debugCompileUnitAssumeCapacity( producer: MetadataString, enums: Metadata, globals: Metadata, + imports: Metadata, options: Metadata.CompileUnit.Options, ) Metadata { assert(!self.strip); @@ -12251,6 +12332,7 @@ pub fn debugCompileUnitAssumeCapacity( .producer = producer, .enums = enums, .globals = globals, + .imports = imports, }, ); } @@ -12538,22 +12620,19 @@ fn debugMemberTypeAssumeCapacity( static: bool, ) Metadata { assert(!self.strip); - return self.metadataSimpleAssumeCapacity( - if (static) .derived_static_member_type else .derived_member_type, - Metadata.DerivedType{ - .name = name, - .file = file, - .scope = scope, - .line = line, - .underlying_type = underlying_type, - .size_in_bits_lo = @truncate(size_in_bits), - .size_in_bits_hi = @truncate(size_in_bits >> 32), - .align_in_bits_lo = @truncate(align_in_bits), - .align_in_bits_hi = @truncate(align_in_bits >> 32), - .offset_in_bits_lo = @truncate(offset_in_bits), - .offset_in_bits_hi = @truncate(offset_in_bits >> 32), - } - ); + return self.metadataSimpleAssumeCapacity(if (static) .derived_static_member_type else .derived_member_type, Metadata.DerivedType{ + .name = name, + .file = file, + .scope = scope, + .line = line, + .underlying_type = underlying_type, + .size_in_bits_lo = @truncate(size_in_bits), + .size_in_bits_hi = @truncate(size_in_bits >> 32), + .align_in_bits_lo = @truncate(align_in_bits), + .align_in_bits_hi = @truncate(align_in_bits >> 32), + .offset_in_bits_lo = @truncate(offset_in_bits), + .offset_in_bits_hi = @truncate(offset_in_bits >> 32), + }); } fn debugSubroutineTypeAssumeCapacity( @@ -13850,6 +13929,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co }, .enums = extra.enums, .globals = extra.globals, + .imports = extra.imports, }, metadata_adapter); }, .subprogram, @@ -13945,13 +14025,14 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co .derived_pointer_type, .derived_member_type, .derived_static_member_type, + .derived_typedef, => |kind| { const extra = self.metadataExtraData(Metadata.DerivedType, data); try metadata_block.writeAbbrevAdapted(MetadataBlock.DerivedType{ .tag = switch (kind) { .derived_pointer_type => DW.TAG.pointer_type, - .derived_member_type, - .derived_static_member_type => DW.TAG.member, + .derived_member_type, .derived_static_member_type => DW.TAG.member, + .derived_typedef => DW.TAG.typedef, else => unreachable, }, .name = extra.name, @@ -13967,6 +14048,17 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co }, }, metadata_adapter); }, + .imported_declaration => { + const extra = self.metadataExtraData(Metadata.ImportedEntity, data); + try metadata_block.writeAbbrevAdapted(MetadataBlock.ImportedEntity{ + .tag = DW.TAG.imported_declaration, + .scope = extra.scope, + .entity = extra.entity, + .line = extra.line, + .name = extra.name, + .file = extra.file, + }, metadata_adapter); + }, .subroutine_type => { const extra = self.metadataExtraData(Metadata.SubroutineType, data); diff --git a/src/codegen/llvm/ir.zig b/src/codegen/llvm/ir.zig index dc8c6e5b68..600538ef67 100644 --- a/src/codegen/llvm/ir.zig +++ b/src/codegen/llvm/ir.zig @@ -649,6 +649,7 @@ pub const MetadataBlock = struct { BasicType, CompositeType, DerivedType, + ImportedEntity, SubroutineType, Enumerator, Subrange, @@ -706,7 +707,7 @@ pub const MetadataBlock = struct { .{ .literal = 0 }, // retained types .{ .literal = 0 }, // subprograms MetadataAbbrev, // globals - .{ .literal = 0 }, // imported entities + MetadataAbbrev, // imported entities .{ .literal = 0 }, // DWO ID .{ .literal = 0 }, // macros .{ .literal = 0 }, // split debug inlining @@ -722,6 +723,7 @@ pub const MetadataBlock = struct { is_optimized: bool, enums: Builder.Metadata, globals: Builder.Metadata, + imports: Builder.Metadata, }; pub const Subprogram = struct { @@ -879,6 +881,27 @@ pub const MetadataBlock = struct { flags: Builder.Metadata.DIFlags, }; + pub const ImportedEntity = struct { + pub const ops = [_]AbbrevOp{ + .{ .literal = 31 }, + .{ .literal = 0 }, // is distinct + .{ .fixed = 32 }, // tag + MetadataAbbrev, // scope + MetadataAbbrev, // entity + LineAbbrev, // line + MetadataAbbrev, // name + MetadataAbbrev, // file + .{ .literal = 0 }, // elements + }; + + tag: u32, + scope: Builder.Metadata, + entity: Builder.Metadata, + line: u32, + name: Builder.MetadataString, + file: Builder.Metadata, + }; + pub const SubroutineType = struct { pub const ops = [_]AbbrevOp{ .{ .literal = 19 }, |
