From e57f553c07cff62871927146e072be43f13432e3 Mon Sep 17 00:00:00 2001 From: antlilja Date: Wed, 21 Feb 2024 21:46:04 +0100 Subject: [PATCH] LLVM Builder: Rework MetadataString to not rely on String This fixes a problem where empty strings where not emitted as null. This should also emit a smaller stringtab as all metadata strings were emitted in both the strtab and in the strings block inside the metadata block. --- src/codegen/llvm.zig | 112 ++++++++--------- src/codegen/llvm/Builder.zig | 226 +++++++++++++++++++++-------------- 2 files changed, 193 insertions(+), 145 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 0650cecb2c..1a967a3fbc 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -872,8 +872,8 @@ pub const Object = struct { }; const debug_file = try builder.debugFile( - try builder.string(compile_unit_dir), - try builder.string(comp.root_name), + try builder.metadataString(compile_unit_dir), + try builder.metadataString(comp.root_name), ); const debug_enums_fwd_ref = try builder.debugForwardReference(); @@ -883,7 +883,7 @@ pub const Object = struct { debug_file, // Don't use the version string here; LLVM misparses it when it // includes the git revision. - try builder.fmt("zig {d}.{d}.{d}", .{ + try builder.metadataStringFmt("zig {d}.{d}.{d}", .{ build_options.semver.major, build_options.semver.minor, build_options.semver.patch, @@ -896,7 +896,7 @@ pub const Object = struct { if (!builder.strip) { const debug_info_version = try builder.debugModuleFlag( try builder.debugConstant(try builder.intConst(.i32, 2)), - try builder.string("Debug Info Version"), + try builder.metadataString("Debug Info Version"), try builder.debugConstant(try builder.intConst(.i32, 3)), ); @@ -904,12 +904,12 @@ pub const Object = struct { .dwarf => |f| { const dwarf_version = try builder.debugModuleFlag( try builder.debugConstant(try builder.intConst(.i32, 2)), - try builder.string("Dwarf Version"), + try builder.metadataString("Dwarf Version"), try builder.debugConstant(try builder.intConst(.i32, 4)), ); switch (f) { .@"32" => { - try builder.debugNamed(try builder.string("llvm.module.flags"), &.{ + try builder.debugNamed(try builder.metadataString("llvm.module.flags"), &.{ debug_info_version, dwarf_version, }); @@ -917,10 +917,10 @@ pub const Object = struct { .@"64" => { const dwarf64 = try builder.debugModuleFlag( try builder.debugConstant(try builder.intConst(.i32, 2)), - try builder.string("DWARF64"), + try builder.metadataString("DWARF64"), try builder.debugConstant(try builder.intConst(.i32, 1)), ); - try builder.debugNamed(try builder.string("llvm.module.flags"), &.{ + try builder.debugNamed(try builder.metadataString("llvm.module.flags"), &.{ debug_info_version, dwarf_version, dwarf64, @@ -931,10 +931,10 @@ pub const Object = struct { .code_view => { const code_view = try builder.debugModuleFlag( try builder.debugConstant(try builder.intConst(.i32, 2)), - try builder.string("CodeView"), + try builder.metadataString("CodeView"), try builder.debugConstant(try builder.intConst(.i32, 1)), ); - try builder.debugNamed(try builder.string("llvm.module.flags"), &.{ + try builder.debugNamed(try builder.metadataString("llvm.module.flags"), &.{ debug_info_version, code_view, }); @@ -942,7 +942,7 @@ pub const Object = struct { .strip => unreachable, } - try builder.debugNamed(try builder.string("llvm.dbg.cu"), &.{debug_compile_unit}); + try builder.debugNamed(try builder.metadataString("llvm.dbg.cu"), &.{debug_compile_unit}); } const obj = try arena.create(Object); @@ -1654,8 +1654,8 @@ pub const Object = struct { break :blk try o.builder.debugSubprogram( file, - try o.builder.string(ip.stringToSlice(decl.name)), - function_index.name(&o.builder), + try o.builder.metadataString(ip.stringToSlice(decl.name)), + try o.builder.metadataStringFromString(function_index.name(&o.builder)), line_number, line_number + func.lbrace_line, debug_decl_type, @@ -1914,8 +1914,8 @@ pub const Object = struct { fn getDebugFile(o: *Object, file: *const Module.File) Allocator.Error!Builder.Metadata { return try o.builder.debugFile( - if (std.fs.path.dirname(file.sub_file_path)) |dirname| try o.builder.string(dirname) else .empty, - try o.builder.string(std.fs.path.basename(file.sub_file_path)), + if (std.fs.path.dirname(file.sub_file_path)) |dirname| try o.builder.metadataString(dirname) else .none, + try o.builder.metadataString(std.fs.path.basename(file.sub_file_path)), ); } @@ -1936,7 +1936,7 @@ pub const Object = struct { .NoReturn, => { const debug_void_type = try o.builder.debugSignedType( - try o.builder.string("void"), + try o.builder.metadataString("void"), 0, ); try o.debug_type_map.put(gpa, ty, debug_void_type); @@ -1947,7 +1947,7 @@ pub const Object = struct { assert(info.bits != 0); const name = try o.allocTypeName(ty); defer gpa.free(name); - const builder_name = try o.builder.string(name); + const builder_name = try o.builder.metadataString(name); const debug_bits = ty.abiSize(mod) * 8; // lldb cannot handle non-byte sized types const debug_int_type = switch (info.signedness) { .signed => try o.builder.debugSignedType(builder_name, debug_bits), @@ -1984,7 +1984,7 @@ pub const Object = struct { std.math.big.int.Mutable.init(&bigint_space.limbs, i).toConst(); enumerators[i] = try o.builder.debugEnumerator( - try o.builder.string(ip.stringToSlice(field_name_ip)), + try o.builder.metadataString(ip.stringToSlice(field_name_ip)), int_ty.isUnsignedInt(mod), int_info.bits, bigint, @@ -1998,7 +1998,7 @@ pub const Object = struct { defer gpa.free(name); const debug_enum_type = try o.builder.debugEnumerationType( - try o.builder.string(name), + try o.builder.metadataString(name), file, scope, owner_decl.src_node + 1, // Line @@ -2017,7 +2017,7 @@ pub const Object = struct { const name = try o.allocTypeName(ty); defer gpa.free(name); const debug_float_type = try o.builder.debugFloatType( - try o.builder.string(name), + try o.builder.metadataString(name), bits, ); try o.debug_type_map.put(gpa, ty, debug_float_type); @@ -2025,7 +2025,7 @@ pub const Object = struct { }, .Bool => { const debug_bool_type = try o.builder.debugBoolType( - try o.builder.string("bool"), + try o.builder.metadataString("bool"), 8, // lldb cannot handle non-byte sized types ); try o.debug_type_map.put(gpa, ty, debug_bool_type); @@ -2085,7 +2085,7 @@ pub const Object = struct { const len_offset = len_align.forward(ptr_size); const debug_ptr_type = try o.builder.debugMemberType( - try o.builder.string("ptr"), + try o.builder.metadataString("ptr"), Builder.Metadata.none, // File debug_fwd_ref, 0, // Line @@ -2096,7 +2096,7 @@ pub const Object = struct { ); const debug_len_type = try o.builder.debugMemberType( - try o.builder.string("len"), + try o.builder.metadataString("len"), Builder.Metadata.none, // File debug_fwd_ref, 0, // Line @@ -2107,7 +2107,7 @@ pub const Object = struct { ); const debug_slice_type = try o.builder.debugStructType( - try o.builder.string(name), + try o.builder.metadataString(name), Builder.Metadata.none, // File o.debug_compile_unit, // Scope line, @@ -2135,7 +2135,7 @@ pub const Object = struct { defer gpa.free(name); const debug_ptr_type = try o.builder.debugPointerType( - try o.builder.string(name), + try o.builder.metadataString(name), Builder.Metadata.none, // File Builder.Metadata.none, // Scope 0, // Line @@ -2156,7 +2156,7 @@ pub const Object = struct { .Opaque => { if (ty.toIntern() == .anyopaque_type) { const debug_opaque_type = try o.builder.debugSignedType( - try o.builder.string("anyopaque"), + try o.builder.metadataString("anyopaque"), 0, ); try o.debug_type_map.put(gpa, ty, debug_opaque_type); @@ -2168,7 +2168,7 @@ pub const Object = struct { const owner_decl_index = ty.getOwnerDecl(mod); const owner_decl = o.module.declPtr(owner_decl_index); const debug_opaque_type = try o.builder.debugStructType( - try o.builder.string(name), + try o.builder.metadataString(name), try o.getDebugFile(mod.namespacePtr(owner_decl.src_namespace).file_scope), try o.namespaceToDebugScope(owner_decl.src_namespace), owner_decl.src_node + 1, // Line @@ -2182,7 +2182,7 @@ pub const Object = struct { }, .Array => { const debug_array_type = try o.builder.debugArrayType( - Builder.String.empty, // Name + Builder.MetadataString.none, // Name Builder.Metadata.none, // File Builder.Metadata.none, // Scope 0, // Line @@ -2211,21 +2211,21 @@ pub const Object = struct { assert(info.bits != 0); const name = try o.allocTypeName(ty); defer gpa.free(name); - const builder_name = try o.builder.string(name); + const builder_name = try o.builder.metadataString(name); break :blk switch (info.signedness) { .signed => try o.builder.debugSignedType(builder_name, info.bits), .unsigned => try o.builder.debugUnsignedType(builder_name, info.bits), }; }, .Bool => try o.builder.debugBoolType( - try o.builder.string("bool"), + try o.builder.metadataString("bool"), 1, ), else => try o.lowerDebugType(ty.childType(mod)), }; const debug_vector_type = try o.builder.debugArrayType( - Builder.String.empty, // Name + Builder.MetadataString.none, // Name Builder.Metadata.none, // File Builder.Metadata.none, // Scope 0, // Line @@ -2249,7 +2249,7 @@ pub const Object = struct { const child_ty = ty.optionalChild(mod); if (!child_ty.hasRuntimeBitsIgnoreComptime(mod)) { const debug_bool_type = try o.builder.debugBoolType( - try o.builder.string(name), + try o.builder.metadataString(name), 8, ); try o.debug_type_map.put(gpa, ty, debug_bool_type); @@ -2281,7 +2281,7 @@ pub const Object = struct { const non_null_offset = non_null_align.forward(payload_size); const debug_data_type = try o.builder.debugMemberType( - try o.builder.string("data"), + try o.builder.metadataString("data"), Builder.Metadata.none, // File debug_fwd_ref, 0, // Line @@ -2292,7 +2292,7 @@ pub const Object = struct { ); const debug_some_type = try o.builder.debugMemberType( - try o.builder.string("some"), + try o.builder.metadataString("some"), Builder.Metadata.none, debug_fwd_ref, 0, @@ -2303,7 +2303,7 @@ pub const Object = struct { ); const debug_optional_type = try o.builder.debugStructType( - try o.builder.string(name), + try o.builder.metadataString(name), Builder.Metadata.none, // File o.debug_compile_unit, // Scope 0, // Line @@ -2361,7 +2361,7 @@ pub const Object = struct { var fields: [2]Builder.Metadata = undefined; fields[error_index] = try o.builder.debugMemberType( - try o.builder.string("tag"), + try o.builder.metadataString("tag"), Builder.Metadata.none, // File debug_fwd_ref, 0, // Line @@ -2371,7 +2371,7 @@ pub const Object = struct { error_offset * 8, ); fields[payload_index] = try o.builder.debugMemberType( - try o.builder.string("value"), + try o.builder.metadataString("value"), Builder.Metadata.none, // File debug_fwd_ref, 0, // Line @@ -2382,7 +2382,7 @@ pub const Object = struct { ); const debug_error_union_type = try o.builder.debugStructType( - try o.builder.string(name), + try o.builder.metadataString(name), Builder.Metadata.none, // File o.debug_compile_unit, // Sope 0, // Line @@ -2399,7 +2399,7 @@ pub const Object = struct { }, .ErrorSet => { const debug_error_set = try o.builder.debugUnsignedType( - try o.builder.string("anyerror"), + try o.builder.metadataString("anyerror"), 16, ); try o.debug_type_map.put(gpa, ty, debug_error_set); @@ -2413,7 +2413,7 @@ pub const Object = struct { const backing_int_ty = struct_type.backingIntType(ip).*; if (backing_int_ty != .none) { const info = Type.fromInterned(backing_int_ty).intInfo(mod); - const builder_name = try o.builder.string(name); + const builder_name = try o.builder.metadataString(name); const debug_int_type = switch (info.signedness) { .signed => try o.builder.debugSignedType(builder_name, ty.abiSize(mod) * 8), .unsigned => try o.builder.debugUnsignedType(builder_name, ty.abiSize(mod) * 8), @@ -2450,7 +2450,7 @@ pub const Object = struct { defer if (tuple.names.len == 0) gpa.free(field_name); fields.appendAssumeCapacity(try o.builder.debugMemberType( - try o.builder.string(field_name), + try o.builder.metadataString(field_name), Builder.Metadata.none, // File debug_fwd_ref, 0, @@ -2462,7 +2462,7 @@ pub const Object = struct { } const debug_struct_type = try o.builder.debugStructType( - try o.builder.string(name), + try o.builder.metadataString(name), Builder.Metadata.none, // File o.debug_compile_unit, // Scope 0, // Line @@ -2531,7 +2531,7 @@ pub const Object = struct { try ip.getOrPutStringFmt(gpa, "{d}", .{field_index}); fields.appendAssumeCapacity(try o.builder.debugMemberType( - try o.builder.string(ip.stringToSlice(field_name)), + try o.builder.metadataString(ip.stringToSlice(field_name)), Builder.Metadata.none, // File debug_fwd_ref, 0, // Line @@ -2543,7 +2543,7 @@ pub const Object = struct { } const debug_struct_type = try o.builder.debugStructType( - try o.builder.string(name), + try o.builder.metadataString(name), Builder.Metadata.none, // File o.debug_compile_unit, // Scope 0, // Line @@ -2584,7 +2584,7 @@ pub const Object = struct { if (layout.payload_size == 0) { const debug_union_type = try o.builder.debugStructType( - try o.builder.string(name), + try o.builder.metadataString(name), Builder.Metadata.none, // File o.debug_compile_unit, // Scope 0, // Line @@ -2622,7 +2622,7 @@ pub const Object = struct { const field_name = union_obj.field_names.get(ip)[field_index]; fields.appendAssumeCapacity(try o.builder.debugMemberType( - try o.builder.string(ip.stringToSlice(field_name)), + try o.builder.metadataString(ip.stringToSlice(field_name)), Builder.Metadata.none, // File debug_union_fwd_ref, 0, // Line @@ -2641,7 +2641,7 @@ pub const Object = struct { }; const debug_union_type = try o.builder.debugUnionType( - try o.builder.string(union_name), + try o.builder.metadataString(union_name), Builder.Metadata.none, // File o.debug_compile_unit, // Scope 0, // Line @@ -2672,7 +2672,7 @@ pub const Object = struct { } const debug_tag_type = try o.builder.debugMemberType( - try o.builder.string("tag"), + try o.builder.metadataString("tag"), Builder.Metadata.none, // File debug_fwd_ref, 0, // Line @@ -2683,7 +2683,7 @@ pub const Object = struct { ); const debug_payload_type = try o.builder.debugMemberType( - try o.builder.string("payload"), + try o.builder.metadataString("payload"), Builder.Metadata.none, // File debug_fwd_ref, 0, // Line @@ -2700,7 +2700,7 @@ pub const Object = struct { .{ debug_payload_type, debug_tag_type }; const debug_tagged_union_type = try o.builder.debugStructType( - try o.builder.string(name), + try o.builder.metadataString(name), Builder.Metadata.none, // File o.debug_compile_unit, // Scope 0, // Line @@ -2794,7 +2794,7 @@ pub const Object = struct { const mod = o.module; const decl = mod.declPtr(decl_index); return o.builder.debugStructType( - try o.builder.string(mod.intern_pool.stringToSlice(decl.name)), // TODO use fully qualified name + try o.builder.metadataString(mod.intern_pool.stringToSlice(decl.name)), // TODO use fully qualified name try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope), try o.namespaceToDebugScope(decl.src_namespace), decl.src_line + 1, @@ -4699,8 +4699,8 @@ pub const DeclGen = struct { const debug_file = try o.getDebugFile(mod.namespacePtr(decl.src_namespace).file_scope); const debug_global_var = try o.builder.debugGlobalVar( - try o.builder.string(mod.intern_pool.stringToSlice(decl.name)), // Name - variable_index.name(&o.builder), // Linkage name + try o.builder.metadataString(mod.intern_pool.stringToSlice(decl.name)), // Name + try o.builder.metadataStringFromString(variable_index.name(&o.builder)), // Linkage name debug_file, // File debug_file, // Scope line_number, @@ -6678,7 +6678,7 @@ pub const FuncGen = struct { const ptr_ty = self.typeOf(pl_op.operand); const debug_local_var = try o.builder.debugLocalVar( - try o.builder.string(name), + try o.builder.metadataString(name), self.file, self.current_scope, self.prev_dbg_line, @@ -6712,7 +6712,7 @@ pub const FuncGen = struct { if (needDbgVarWorkaround(o)) return .none; const debug_local_var = try o.builder.debugLocalVar( - try o.builder.string(name), + try o.builder.metadataString(name), self.file, self.current_scope, self.prev_dbg_line, @@ -8796,7 +8796,7 @@ pub const FuncGen = struct { const lbrace_col = func.lbrace_column + 1; const debug_parameter = try o.builder.debugParameter( - try o.builder.string(mod.getParamName(func_index, src_index)), + try o.builder.metadataString(mod.getParamName(func_index, src_index)), self.file, self.current_scope, lbrace_line, diff --git a/src/codegen/llvm/Builder.zig b/src/codegen/llvm/Builder.zig index 23868a05d6..32d58ea7bc 100644 --- a/src/codegen/llvm/Builder.zig +++ b/src/codegen/llvm/Builder.zig @@ -40,14 +40,17 @@ constant_limbs: std.ArrayListUnmanaged(std.math.big.Limb), metadata_map: std.AutoArrayHashMapUnmanaged(void, void), metadata_items: std.MultiArrayList(Metadata.Item), metadata_extra: std.ArrayListUnmanaged(u32), -metadata_strings: std.AutoArrayHashMapUnmanaged(String, void), metadata_limbs: std.ArrayListUnmanaged(std.math.big.Limb), metadata_forward_references: std.ArrayListUnmanaged(Metadata), -metadata_named: std.AutoArrayHashMapUnmanaged(String, struct { +metadata_named: std.AutoArrayHashMapUnmanaged(MetadataString, struct { len: u32, index: Metadata.Item.ExtraIndex, }), +metadata_string_map: std.AutoArrayHashMapUnmanaged(void, void), +metadata_string_indices: std.ArrayListUnmanaged(u32), +metadata_string_bytes: std.ArrayListUnmanaged(u8), + pub const expected_args_len = 16; pub const expected_attrs_len = 16; pub const expected_fields_len = 32; @@ -7553,7 +7556,26 @@ pub const Value = enum(u32) { }; pub const MetadataString = enum(u32) { + none = 0, _, + + pub fn slice(self: MetadataString, b: *const Builder) []const u8 { + const index = @intFromEnum(self); + const start = b.metadata_string_indices.items[index]; + const end = b.metadata_string_indices.items[index + 1]; + return b.metadata_string_bytes.items[start..end]; + } + + const Adapter = struct { + builder: *const Builder, + pub fn hash(_: Adapter, key: []const u8) u32 { + return @truncate(std.hash.Wyhash.hash(0, key)); + } + pub fn eql(ctx: Adapter, lhs_key: []const u8, _: void, rhs_index: usize) bool { + const rhs_metadata_string: MetadataString = @enumFromInt(rhs_index); + return std.mem.eql(u8, lhs_key, rhs_metadata_string.slice(ctx.builder)); + } + }; }; pub const Metadata = enum(u32) { @@ -7829,10 +7851,12 @@ pub fn init(options: Options) InitError!Builder { .metadata_map = .{}, .metadata_items = .{}, .metadata_extra = .{}, - .metadata_strings = .{}, .metadata_limbs = .{}, .metadata_forward_references = .{}, .metadata_named = .{}, + .metadata_string_map = .{}, + .metadata_string_indices = .{}, + .metadata_string_bytes = .{}, }; errdefer self.deinit(); @@ -7876,6 +7900,9 @@ pub fn init(options: Options) InitError!Builder { assert(try self.noneConst(.token) == .none); assert(try self.debugNone() == .none); + try self.metadata_string_indices.append(self.gpa, 0); + assert(try self.metadataString("") == .none); + return self; } @@ -7914,11 +7941,14 @@ pub fn deinit(self: *Builder) void { self.metadata_map.deinit(self.gpa); self.metadata_items.deinit(self.gpa); self.metadata_extra.deinit(self.gpa); - self.metadata_strings.deinit(self.gpa); self.metadata_limbs.deinit(self.gpa); self.metadata_forward_references.deinit(self.gpa); self.metadata_named.deinit(self.gpa); + self.metadata_string_map.deinit(self.gpa); + self.metadata_string_indices.deinit(self.gpa); + self.metadata_string_bytes.deinit(self.gpa); + self.* = undefined; } @@ -10913,14 +10943,51 @@ fn metadataExtraData(self: *const Builder, comptime T: type, index: Metadata.Ite return self.metadataExtraDataTrail(T, index).data; } -fn metadataString(self: *Builder, str: String) Allocator.Error!MetadataString { - const gop = try self.metadata_strings.getOrPut(self.gpa, str); - if (!gop.found_existing) gop.key_ptr.* = str; +pub fn metadataString(self: *Builder, bytes: []const u8) Allocator.Error!MetadataString { + try self.metadata_string_bytes.ensureUnusedCapacity(self.gpa, bytes.len); + try self.metadata_string_indices.ensureUnusedCapacity(self.gpa, 1); + try self.metadata_string_map.ensureUnusedCapacity(self.gpa, 1); + const gop = self.metadata_string_map.getOrPutAssumeCapacityAdapted( + bytes, + MetadataString.Adapter{ .builder = self }, + ); + if (!gop.found_existing) { + self.metadata_string_bytes.appendSliceAssumeCapacity(bytes); + self.metadata_string_indices.appendAssumeCapacity(@intCast(self.metadata_string_bytes.items.len)); + } return @enumFromInt(gop.index); } -pub fn debugNamed(self: *Builder, name: String, operands: []const Metadata) Allocator.Error!void { +pub fn metadataStringFromString(self: *Builder, str: String) Allocator.Error!MetadataString { + if (str == .none or str == .empty) return MetadataString.none; + + const slice = str.slice(self) orelse unreachable; + return try self.metadataString(slice); +} + +pub fn metadataStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allocator.Error!MetadataString { + try self.metadata_string_map.ensureUnusedCapacity(self.gpa, 1); + try self.metadata_string_bytes.ensureUnusedCapacity(self.gpa, @intCast(std.fmt.count(fmt_str, fmt_args))); + try self.metadata_string_indices.ensureUnusedCapacity(self.gpa, 1); + return self.metadataStringFmtAssumeCapacity(fmt_str, fmt_args); +} + +pub fn metadataStringFmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) MetadataString { + const start = self.metadata_string_bytes.items.len; + self.metadata_string_bytes.writer(self.gpa).print(fmt_str, fmt_args) catch unreachable; + const bytes: []const u8 = self.metadata_string_bytes.items[start..self.metadata_string_bytes.items.len]; + + const gop = self.metadata_string_map.getOrPutAssumeCapacityAdapted(bytes, String.Adapter{ .builder = self }); + if (gop.found_existing) { + self.metadata_string_bytes.shrinkRetainingCapacity(start); + } else { + self.metadata_string_indices.appendAssumeCapacity(@intCast(self.metadata_string_bytes.items.len)); + } + return @enumFromInt(gop.index); +} + +pub fn debugNamed(self: *Builder, name: MetadataString, operands: []const Metadata) Allocator.Error!void { try self.metadata_extra.ensureUnusedCapacity( self.gpa, operands.len * @sizeOf(Metadata), @@ -10934,31 +11001,28 @@ fn debugNone(self: *Builder) Allocator.Error!Metadata { return self.debugNoneAssumeCapacity(); } -pub fn debugFile(self: *Builder, path: String, name: String) Allocator.Error!Metadata { +pub fn debugFile(self: *Builder, path: MetadataString, name: MetadataString) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.File, 0); - const metadata_path = try self.metadataString(path); - const metadata_name = try self.metadataString(name); - return self.debugFileAssumeCapacity(metadata_path, metadata_name); + return self.debugFileAssumeCapacity(path, name); } pub fn debugCompileUnit( self: *Builder, file: Metadata, - producer: String, + producer: MetadataString, enums: Metadata, globals: Metadata, flags: Metadata.CompileUnit.Flags, ) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.CompileUnit, 0); - const metadata_producer = try self.metadataString(producer); - return self.debugCompileUnitAssumeCapacity(file, metadata_producer, enums, globals, flags); + return self.debugCompileUnitAssumeCapacity(file, producer, enums, globals, flags); } pub fn debugSubprogram( self: *Builder, file: Metadata, - name: String, - linkage_name: String, + name: MetadataString, + linkage_name: MetadataString, line: u32, scope_line: u32, ty: Metadata, @@ -10966,12 +11030,10 @@ pub fn debugSubprogram( compile_unit: Metadata, ) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.Subprogram, 0); - const metadata_name = try self.metadataString(name); - const metadata_linkage_name = try self.metadataString(linkage_name); return self.debugSubprogramAssumeCapacity( file, - metadata_name, - metadata_linkage_name, + name, + linkage_name, line, scope_line, ty, @@ -10990,28 +11052,24 @@ pub fn debugLocation(self: *Builder, scope: Metadata, line: u32, column: u32, in return self.debugLocationAssumeCapacity(scope, line, column, inlined_at); } -pub fn debugBoolType(self: *Builder, name: String, size_in_bits: u64) Allocator.Error!Metadata { +pub fn debugBoolType(self: *Builder, name: MetadataString, size_in_bits: u64) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0); - const metadata_name = try self.metadataString(name); - return self.debugBoolTypeAssumeCapacity(metadata_name, size_in_bits); + return self.debugBoolTypeAssumeCapacity(name, size_in_bits); } -pub fn debugUnsignedType(self: *Builder, name: String, size_in_bits: u64) Allocator.Error!Metadata { +pub fn debugUnsignedType(self: *Builder, name: MetadataString, size_in_bits: u64) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0); - const metadata_name = try self.metadataString(name); - return self.debugUnsignedTypeAssumeCapacity(metadata_name, size_in_bits); + return self.debugUnsignedTypeAssumeCapacity(name, size_in_bits); } -pub fn debugSignedType(self: *Builder, name: String, size_in_bits: u64) Allocator.Error!Metadata { +pub fn debugSignedType(self: *Builder, name: MetadataString, size_in_bits: u64) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0); - const metadata_name = try self.metadataString(name); - return self.debugSignedTypeAssumeCapacity(metadata_name, size_in_bits); + return self.debugSignedTypeAssumeCapacity(name, size_in_bits); } -pub fn debugFloatType(self: *Builder, name: String, size_in_bits: u64) Allocator.Error!Metadata { +pub fn debugFloatType(self: *Builder, name: MetadataString, size_in_bits: u64) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.BasicType, 0); - const metadata_name = try self.metadataString(name); - return self.debugFloatTypeAssumeCapacity(metadata_name, size_in_bits); + return self.debugFloatTypeAssumeCapacity(name, size_in_bits); } pub fn debugForwardReference(self: *Builder) Allocator.Error!Metadata { @@ -11021,7 +11079,7 @@ pub fn debugForwardReference(self: *Builder) Allocator.Error!Metadata { pub fn debugStructType( self: *Builder, - name: String, + name: MetadataString, file: Metadata, scope: Metadata, line: u32, @@ -11031,9 +11089,8 @@ pub fn debugStructType( fields_tuple: Metadata, ) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0); - const metadata_name = try self.metadataString(name); return self.debugStructTypeAssumeCapacity( - metadata_name, + name, file, scope, line, @@ -11046,7 +11103,7 @@ pub fn debugStructType( pub fn debugUnionType( self: *Builder, - name: String, + name: MetadataString, file: Metadata, scope: Metadata, line: u32, @@ -11056,9 +11113,8 @@ pub fn debugUnionType( fields_tuple: Metadata, ) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0); - const metadata_name = try self.metadataString(name); return self.debugUnionTypeAssumeCapacity( - metadata_name, + name, file, scope, line, @@ -11071,7 +11127,7 @@ pub fn debugUnionType( pub fn debugEnumerationType( self: *Builder, - name: String, + name: MetadataString, file: Metadata, scope: Metadata, line: u32, @@ -11081,9 +11137,8 @@ pub fn debugEnumerationType( fields_tuple: Metadata, ) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0); - const metadata_name = try self.metadataString(name); return self.debugEnumerationTypeAssumeCapacity( - metadata_name, + name, file, scope, line, @@ -11096,7 +11151,7 @@ pub fn debugEnumerationType( pub fn debugArrayType( self: *Builder, - name: String, + name: MetadataString, file: Metadata, scope: Metadata, line: u32, @@ -11106,9 +11161,8 @@ pub fn debugArrayType( fields_tuple: Metadata, ) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.CompositeType, 0); - const metadata_name = try self.metadataString(name); return self.debugArrayTypeAssumeCapacity( - metadata_name, + name, file, scope, line, @@ -11121,7 +11175,7 @@ pub fn debugArrayType( pub fn debugPointerType( self: *Builder, - name: String, + name: MetadataString, file: Metadata, scope: Metadata, line: u32, @@ -11131,9 +11185,8 @@ pub fn debugPointerType( offset_in_bits: u64, ) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.DerivedType, 0); - const metadata_name = try self.metadataString(name); return self.debugPointerTypeAssumeCapacity( - metadata_name, + name, file, scope, line, @@ -11146,7 +11199,7 @@ pub fn debugPointerType( pub fn debugMemberType( self: *Builder, - name: String, + name: MetadataString, file: Metadata, scope: Metadata, line: u32, @@ -11156,9 +11209,8 @@ pub fn debugMemberType( offset_in_bits: u64, ) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.DerivedType, 0); - const metadata_name = try self.metadataString(name); return self.debugMemberTypeAssumeCapacity( - metadata_name, + name, file, scope, line, @@ -11179,7 +11231,7 @@ pub fn debugSubroutineType( pub fn debugEnumerator( self: *Builder, - name: String, + name: MetadataString, unsigned: bool, bit_width: u32, value: std.math.big.int.Const, @@ -11187,8 +11239,7 @@ pub fn debugEnumerator( std.debug.assert(!(unsigned and !value.positive)); try self.ensureUnusedMetadataCapacity(1, Metadata.Enumerator, 0); try self.metadata_limbs.ensureUnusedCapacity(self.gpa, value.limbs.len); - const metadata_name = try self.metadataString(name); - return self.debugEnumeratorAssumeCapacity(metadata_name, unsigned, bit_width, value); + return self.debugEnumeratorAssumeCapacity(name, unsigned, bit_width, value); } pub fn debugSubrange( @@ -11219,30 +11270,28 @@ pub fn debugTuple( pub fn debugModuleFlag( self: *Builder, behaviour: Metadata, - name: String, + name: MetadataString, constant: Metadata, ) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.ModuleFlag, 0); - const metadata_name = try self.metadataString(name); - return self.debugModuleFlagAssumeCapacity(behaviour, metadata_name, constant); + return self.debugModuleFlagAssumeCapacity(behaviour, name, constant); } pub fn debugLocalVar( self: *Builder, - name: String, + name: MetadataString, file: Metadata, scope: Metadata, line: u32, ty: Metadata, ) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.LocalVar, 0); - const metadata_name = try self.metadataString(name); - return self.debugLocalVarAssumeCapacity(metadata_name, file, scope, line, ty); + return self.debugLocalVarAssumeCapacity(name, file, scope, line, ty); } pub fn debugParameter( self: *Builder, - name: String, + name: MetadataString, file: Metadata, scope: Metadata, line: u32, @@ -11250,14 +11299,13 @@ pub fn debugParameter( arg_no: u32, ) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.Parameter, 0); - const metadata_name = try self.metadataString(name); - return self.debugParameterAssumeCapacity(metadata_name, file, scope, line, ty, arg_no); + return self.debugParameterAssumeCapacity(name, file, scope, line, ty, arg_no); } pub fn debugGlobalVar( self: *Builder, - name: String, - linkage_name: String, + name: MetadataString, + linkage_name: MetadataString, file: Metadata, scope: Metadata, line: u32, @@ -11266,11 +11314,9 @@ pub fn debugGlobalVar( flags: Metadata.GlobalVar.Flags, ) Allocator.Error!Metadata { try self.ensureUnusedMetadataCapacity(1, Metadata.GlobalVar, 0); - const metadata_name = try self.metadataString(name); - const metadata_linkage_name = try self.metadataString(linkage_name); return self.debugGlobalVarAssumeCapacity( - metadata_name, - metadata_linkage_name, + name, + linkage_name, file, scope, line, @@ -11347,7 +11393,8 @@ fn metadataSimpleAssumeCapacity(self: *Builder, tag: Metadata.Tag, value: anytyp return @enumFromInt(gop.index); } -fn debugNamedAssumeCapacity(self: *Builder, name: String, operands: []const Metadata) void { +fn debugNamedAssumeCapacity(self: *Builder, name: MetadataString, operands: []const Metadata) void { + std.debug.assert(name != .none); const extra_index: u32 = @intCast(self.metadata_extra.items.len); self.metadata_extra.appendSliceAssumeCapacity(@ptrCast(operands)); @@ -12953,12 +13000,12 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co pub fn getMetadataIndex(adapter: @This(), metadata: Metadata) u32 { if (metadata == .none) return 0; - return @intCast(adapter.builder.metadata_strings.count() + - @intFromEnum(metadata.unwrap(adapter.builder))); + return @intCast(adapter.builder.metadata_string_map.count() + + @intFromEnum(metadata.unwrap(adapter.builder)) - 1); } pub fn getMetadataStringIndex(_: @This(), metadata_string: MetadataString) u32 { - return @intFromEnum(metadata_string) + 1; + return @intFromEnum(metadata_string); } }; @@ -12976,11 +13023,11 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co const strings_offset, const strings_size = blk: { var strings_offset: u32 = 0; var strings_size: u32 = 0; - for (self.metadata_strings.keys()) |metadata_string| { - if (metadata_string.slice(self)) |slice| { - strings_offset += bitcode.bitsVBR(@as(u32, @intCast(slice.len)), 6); - strings_size += @intCast(slice.len * 8); - } + for (1..self.metadata_string_map.count()) |metadata_string_index| { + const metadata_string: MetadataString = @enumFromInt(metadata_string_index); + const slice = metadata_string.slice(self); + strings_offset += bitcode.bitsVBR(@as(u32, @intCast(slice.len)), 6); + strings_size += @intCast(slice.len * 8); } break :blk .{ std.mem.alignForward(u32, strings_offset, 32) / 8, @@ -12993,25 +13040,26 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co MetadataBlockWriter.abbrev_len, ); - try bitcode.writeVBR(@as(u32, @intCast(self.metadata_strings.count())), 6); + try bitcode.writeVBR(@as(u32, @intCast(self.metadata_string_map.count() - 1)), 6); try bitcode.writeVBR(strings_offset, 6); try bitcode.writeVBR(strings_size + strings_offset, 6); try bitcode.alignTo32(); - for (self.metadata_strings.keys()) |metadata_string| { - if (metadata_string.slice(self)) |slice| - try bitcode.writeVBR(@as(u32, @intCast(slice.len)), 6); + for (1..self.metadata_string_map.count()) |metadata_string_index| { + const metadata_string: MetadataString = @enumFromInt(metadata_string_index); + const slice = metadata_string.slice(self); + try bitcode.writeVBR(@as(u32, @intCast(slice.len)), 6); } try bitcode.alignTo32(); - for (self.metadata_strings.keys()) |metadata_string| { - if (metadata_string.slice(self)) |slice| { - for (slice) |c| { - try bitcode.writeBits(c, 8); - } + for (1..self.metadata_string_map.count()) |metadata_string_index| { + const metadata_string: MetadataString = @enumFromInt(metadata_string_index); + const slice = metadata_string.slice(self); + for (slice) |c| { + try bitcode.writeBits(c, 8); } } @@ -13335,7 +13383,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co // Write named metadata for (self.metadata_named.keys(), self.metadata_named.values()) |name, operands| { - const slice = name.slice(self).?; + const slice = name.slice(self); try metadata_block.writeAbbrev(MetadataBlock.Name{ .name = slice, }); @@ -13396,7 +13444,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co return @intCast(@intFromEnum(metadata) - Metadata.first_local_metadata + - adapter.metadata_adapter.builder.metadata_strings.count() + + adapter.metadata_adapter.builder.metadata_string_map.count() - 1 + adapter.metadata_adapter.builder.metadata_map.count() - 1); } else unreachable, });