From 40f99862e1251dc0d4ef915308d8f0985d37fb2c Mon Sep 17 00:00:00 2001 From: antlilja Date: Tue, 27 Feb 2024 16:28:44 +0100 Subject: [PATCH] Builder: Implement StrtabString and use it for Global names --- src/codegen/llvm.zig | 60 +++++----- src/codegen/llvm/Builder.zig | 212 ++++++++++++++++++++++++++++------- 2 files changed, 203 insertions(+), 69 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 827fee9f0a..2682892ddb 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1046,7 +1046,7 @@ pub const Object = struct { fn genCmpLtErrorsLenFunction(o: *Object) !void { // If there is no such function in the module, it means the source code does not need it. - const name = o.builder.stringIfExists(lt_errors_fn_name) orelse return; + const name = o.builder.strtabStringIfExists(lt_errors_fn_name) orelse return; const llvm_fn = o.builder.getGlobal(name) orelse return; const mod = o.module; const errors_len = mod.global_error_set.count(); @@ -1087,7 +1087,7 @@ pub const Object = struct { for (object.extern_collisions.keys()) |decl_index| { const global = object.decl_map.get(decl_index) orelse continue; // Same logic as below but for externs instead of exports. - const decl_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(mod.declPtr(decl_index).name)) orelse continue; + const decl_name = object.builder.strtabStringIfExists(mod.intern_pool.stringToSlice(mod.declPtr(decl_index).name)) orelse continue; const other_global = object.builder.getGlobal(decl_name) orelse continue; if (other_global.toConst().getBase(&object.builder) == global.toConst().getBase(&object.builder)) continue; @@ -1117,7 +1117,7 @@ pub const Object = struct { for (export_list) |exp| { // Detect if the LLVM global has already been created as an extern. In such // case, we need to replace all uses of it with this exported global. - const exp_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(exp.opts.name)) orelse continue; + const exp_name = object.builder.strtabStringIfExists(mod.intern_pool.stringToSlice(exp.opts.name)) orelse continue; const other_global = object.builder.getGlobal(exp_name) orelse continue; if (other_global.toConst().getBase(&object.builder) == global_base) continue; @@ -1662,7 +1662,7 @@ pub const Object = struct { const subprogram = try o.builder.debugSubprogram( file, try o.builder.metadataString(ip.stringToSlice(decl.name)), - try o.builder.metadataStringFromString(function_index.name(&o.builder)), + try o.builder.metadataStringFromStrtabString(function_index.name(&o.builder)), line_number, line_number + func.lbrace_line, debug_decl_type, @@ -1763,12 +1763,12 @@ pub const Object = struct { if (mod.getTarget().isWasm() and try decl.isFunction(mod)) { if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| { if (!std.mem.eql(u8, lib_name, "c")) { - break :decl_name try self.builder.fmt("{s}|{s}", .{ decl_name, lib_name }); + break :decl_name try self.builder.strtabStringFmt("{s}|{s}", .{ decl_name, lib_name }); } } } - break :decl_name try self.builder.string(decl_name); + break :decl_name try self.builder.strtabString(decl_name); }; if (self.builder.getGlobal(decl_name)) |other_global| { @@ -1791,7 +1791,7 @@ pub const Object = struct { if (decl_var.is_weak_linkage) global_index.setLinkage(.extern_weak, &self.builder); } } else if (exports.len != 0) { - const main_exp_name = try self.builder.string( + const main_exp_name = try self.builder.strtabString( mod.intern_pool.stringToSlice(exports[0].opts.name), ); try global_index.rename(main_exp_name, &self.builder); @@ -1802,7 +1802,7 @@ pub const Object = struct { return updateExportedGlobal(self, mod, global_index, exports); } else { - const fqn = try self.builder.string( + const fqn = try self.builder.strtabString( mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)), ); try global_index.rename(fqn, &self.builder); @@ -1831,7 +1831,7 @@ pub const Object = struct { exports: []const *Module.Export, ) link.File.UpdateExportsError!void { const gpa = mod.gpa; - const main_exp_name = try o.builder.string( + const main_exp_name = try o.builder.strtabString( mod.intern_pool.stringToSlice(exports[0].opts.name), ); const global_index = i: { @@ -1899,7 +1899,7 @@ pub const Object = struct { // Until then we iterate over existing aliases and make them point // to the correct decl, or otherwise add a new alias. Old aliases are leaked. for (exports[1..]) |exp| { - const exp_name = try o.builder.string(mod.intern_pool.stringToSlice(exp.opts.name)); + const exp_name = try o.builder.strtabString(mod.intern_pool.stringToSlice(exp.opts.name)); if (o.builder.getGlobal(exp_name)) |global| { switch (global.ptrConst(&o.builder).kind) { .alias => |alias| { @@ -2887,7 +2887,7 @@ pub const Object = struct { const is_extern = decl.isExtern(zcu); const function_index = try o.builder.addFunction( try o.lowerType(zig_fn_type), - try o.builder.string(ip.stringToSlice(if (is_extern) + try o.builder.strtabString(ip.stringToSlice(if (is_extern) decl.name else try decl.fullyQualifiedName(zcu))), @@ -3077,7 +3077,7 @@ pub const Object = struct { const decl_ty = mod.intern_pool.typeOf(decl_val); const variable_index = try o.builder.addVariable( - try o.builder.fmt("__anon_{d}", .{@intFromEnum(decl_val)}), + try o.builder.strtabStringFmt("__anon_{d}", .{@intFromEnum(decl_val)}), try o.lowerType(Type.fromInterned(decl_ty)), llvm_addr_space, ); @@ -3103,7 +3103,7 @@ pub const Object = struct { const is_extern = decl.isExtern(mod); const variable_index = try o.builder.addVariable( - try o.builder.string(mod.intern_pool.stringToSlice( + try o.builder.strtabString(mod.intern_pool.stringToSlice( if (is_extern) decl.name else try decl.fullyQualifiedName(mod), )), try o.lowerType(decl.ty), @@ -4570,7 +4570,7 @@ pub const Object = struct { } fn getCmpLtErrorsLenFunction(o: *Object) !Builder.Function.Index { - const name = try o.builder.string(lt_errors_fn_name); + const name = try o.builder.strtabString(lt_errors_fn_name); if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function; const zcu = o.module; @@ -4607,7 +4607,7 @@ pub const Object = struct { const target = zcu.root_mod.resolved_target.result; const function_index = try o.builder.addFunction( try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal), - try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(ip)}), + try o.builder.strtabStringFmt("__zig_tag_name_{}", .{fqn.fmt(ip)}), toLlvmAddressSpace(.generic, target), ); @@ -4730,7 +4730,7 @@ pub const DeclGen = struct { const debug_global_var = try o.builder.debugGlobalVar( try o.builder.metadataString(zcu.intern_pool.stringToSlice(decl.name)), // Name - try o.builder.metadataStringFromString(variable_index.name(&o.builder)), // Linkage name + try o.builder.metadataStringFromStrtabString(variable_index.name(&o.builder)), // Linkage name debug_file, // File debug_file, // Scope line_number, @@ -6169,7 +6169,7 @@ pub const FuncGen = struct { const compiler_rt_operand_abbrev = compilerRtIntAbbrev(rt_int_bits); const compiler_rt_dest_abbrev = compilerRtFloatAbbrev(dest_bits); const sign_prefix = if (is_signed_int) "" else "un"; - const fn_name = try o.builder.fmt("__float{s}{s}i{s}f", .{ + const fn_name = try o.builder.strtabStringFmt("__float{s}{s}i{s}f", .{ sign_prefix, compiler_rt_operand_abbrev, compiler_rt_dest_abbrev, @@ -6239,7 +6239,7 @@ pub const FuncGen = struct { const compiler_rt_dest_abbrev = compilerRtIntAbbrev(rt_int_bits); const sign_prefix = if (dest_scalar_ty.isSignedInt(mod)) "" else "uns"; - const fn_name = try o.builder.fmt("__fix{s}{s}f{s}i", .{ + const fn_name = try o.builder.strtabStringFmt("__fix{s}{s}f{s}i", .{ sign_prefix, compiler_rt_operand_abbrev, compiler_rt_dest_abbrev, @@ -8117,7 +8117,7 @@ pub const FuncGen = struct { fn getLibcFunction( self: *FuncGen, - fn_name: Builder.String, + fn_name: Builder.StrtabString, param_types: []const Builder.Type, return_type: Builder.Type, ) Allocator.Error!Builder.Function.Index { @@ -8171,7 +8171,7 @@ pub const FuncGen = struct { .gt => "gt", .gte => "ge", }; - const fn_name = try o.builder.fmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev }); + const fn_name = try o.builder.strtabStringFmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev }); const libc_fn = try self.getLibcFunction(fn_name, &.{ scalar_llvm_ty, scalar_llvm_ty }, .i32); @@ -8329,7 +8329,7 @@ pub const FuncGen = struct { const result = try self.wip.bin(.xor, bitcasted_operand, sign_mask, ""); return self.wip.cast(.bitcast, result, llvm_ty, ""); }, - .add, .sub, .div, .mul => try o.builder.fmt("__{s}{s}f3", .{ + .add, .sub, .div, .mul => try o.builder.strtabStringFmt("__{s}{s}f3", .{ @tagName(op), compilerRtFloatAbbrev(float_bits), }), .ceil, @@ -8350,7 +8350,7 @@ pub const FuncGen = struct { .sqrt, .tan, .trunc, - => try o.builder.fmt("{s}{s}{s}", .{ + => try o.builder.strtabStringFmt("{s}{s}{s}", .{ libcFloatPrefix(float_bits), @tagName(op), libcFloatSuffix(float_bits), }), }; @@ -8614,7 +8614,7 @@ pub const FuncGen = struct { const operand_llvm_ty = try o.lowerType(operand_ty); const dest_llvm_ty = try o.lowerType(dest_ty); - const fn_name = try o.builder.fmt("__trunc{s}f{s}f2", .{ + const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{ compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), }); @@ -8648,7 +8648,7 @@ pub const FuncGen = struct { const dest_bits = dest_ty.scalarType(mod).floatBits(target); const src_bits = operand_ty.scalarType(mod).floatBits(target); - const fn_name = try o.builder.fmt("__extend{s}f{s}f2", .{ + const fn_name = try o.builder.strtabStringFmt("__extend{s}f{s}f2", .{ compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits), }); @@ -9644,7 +9644,7 @@ pub const FuncGen = struct { const target = zcu.root_mod.resolved_target.result; const function_index = try o.builder.addFunction( try o.builder.fnType(.i1, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal), - try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&zcu.intern_pool)}), + try o.builder.strtabStringFmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&zcu.intern_pool)}), toLlvmAddressSpace(.generic, target), ); @@ -9909,16 +9909,16 @@ pub const FuncGen = struct { // Use a manual loop over a softfloat call instead. const float_bits = scalar_ty.floatBits(target); const fn_name = switch (reduce.operation) { - .Min => try o.builder.fmt("{s}fmin{s}", .{ + .Min => try o.builder.strtabStringFmt("{s}fmin{s}", .{ libcFloatPrefix(float_bits), libcFloatSuffix(float_bits), }), - .Max => try o.builder.fmt("{s}fmax{s}", .{ + .Max => try o.builder.strtabStringFmt("{s}fmax{s}", .{ libcFloatPrefix(float_bits), libcFloatSuffix(float_bits), }), - .Add => try o.builder.fmt("__add{s}f3", .{ + .Add => try o.builder.strtabStringFmt("__add{s}f3", .{ compilerRtFloatAbbrev(float_bits), }), - .Mul => try o.builder.fmt("__mul{s}f3", .{ + .Mul => try o.builder.strtabStringFmt("__mul{s}f3", .{ compilerRtFloatAbbrev(float_bits), }), else => unreachable, @@ -10323,7 +10323,7 @@ pub const FuncGen = struct { // TODO: Address space const variable_index = - try o.builder.addVariable(try o.builder.string("__zig_err_name_table"), .ptr, .default); + try o.builder.addVariable(try o.builder.strtabString("__zig_err_name_table"), .ptr, .default); variable_index.setLinkage(.private, &o.builder); variable_index.setMutability(.constant, &o.builder); variable_index.setUnnamedAddr(.unnamed_addr, &o.builder); diff --git a/src/codegen/llvm/Builder.zig b/src/codegen/llvm/Builder.zig index 666b2b1921..45a253a9e3 100644 --- a/src/codegen/llvm/Builder.zig +++ b/src/codegen/llvm/Builder.zig @@ -24,14 +24,18 @@ attributes_extra: std.ArrayListUnmanaged(u32), function_attributes_set: std.AutoArrayHashMapUnmanaged(FunctionAttributes, void), -globals: std.AutoArrayHashMapUnmanaged(String, Global), -next_unnamed_global: String, -next_replaced_global: String, -next_unique_global_id: std.AutoHashMapUnmanaged(String, u32), +globals: std.AutoArrayHashMapUnmanaged(StrtabString, Global), +next_unnamed_global: StrtabString, +next_replaced_global: StrtabString, +next_unique_global_id: std.AutoHashMapUnmanaged(StrtabString, u32), aliases: std.ArrayListUnmanaged(Alias), variables: std.ArrayListUnmanaged(Variable), functions: std.ArrayListUnmanaged(Function), +strtab_string_map: std.AutoArrayHashMapUnmanaged(void, void), +strtab_string_indices: std.ArrayListUnmanaged(u32), +strtab_string_bytes: std.ArrayListUnmanaged(u8), + constant_map: std.AutoArrayHashMapUnmanaged(void, void), constant_items: std.MultiArrayList(Constant.Item), constant_extra: std.ArrayListUnmanaged(u32), @@ -194,11 +198,6 @@ pub const CmpPredicate = enum(u6) { icmp_sle = 41, }; -pub const StrtabString = struct { - offset: usize, - size: usize, -}; - pub const Type = enum(u32) { void, half, @@ -2136,6 +2135,122 @@ pub const CallConv = enum(u10) { } }; +pub const StrtabString = enum(u32) { + none = std.math.maxInt(u31), + empty, + _, + + pub fn isAnon(self: StrtabString) bool { + assert(self != .none); + return self.toIndex() == null; + } + + pub fn slice(self: StrtabString, builder: *const Builder) ?[]const u8 { + const index = self.toIndex() orelse return null; + const start = builder.strtab_string_indices.items[index]; + const end = builder.strtab_string_indices.items[index + 1]; + return builder.strtab_string_bytes.items[start..end]; + } + + const FormatData = struct { + string: StrtabString, + builder: *const Builder, + }; + fn format( + data: FormatData, + comptime fmt_str: []const u8, + _: std.fmt.FormatOptions, + writer: anytype, + ) @TypeOf(writer).Error!void { + if (comptime std.mem.indexOfNone(u8, fmt_str, "\"r")) |_| + @compileError("invalid format string: '" ++ fmt_str ++ "'"); + assert(data.string != .none); + const string_slice = data.string.slice(data.builder) orelse + return writer.print("{d}", .{@intFromEnum(data.string)}); + if (comptime std.mem.indexOfScalar(u8, fmt_str, 'r')) |_| + return writer.writeAll(string_slice); + try printEscapedString( + string_slice, + if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_| + .always_quote + else + .quote_unless_valid_identifier, + writer, + ); + } + pub fn fmt(self: StrtabString, builder: *const Builder) std.fmt.Formatter(format) { + return .{ .data = .{ .string = self, .builder = builder } }; + } + + fn fromIndex(index: ?usize) StrtabString { + return @enumFromInt(@as(u32, @intCast((index orelse return .none) + + @intFromEnum(StrtabString.empty)))); + } + + fn toIndex(self: StrtabString) ?usize { + return std.math.sub(u32, @intFromEnum(self), @intFromEnum(StrtabString.empty)) catch null; + } + + 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 { + return std.mem.eql(u8, lhs_key, StrtabString.fromIndex(rhs_index).slice(ctx.builder).?); + } + }; +}; + +pub fn strtabString(self: *Builder, bytes: []const u8) Allocator.Error!StrtabString { + try self.strtab_string_bytes.ensureUnusedCapacity(self.gpa, bytes.len); + try self.strtab_string_indices.ensureUnusedCapacity(self.gpa, 1); + try self.strtab_string_map.ensureUnusedCapacity(self.gpa, 1); + + const gop = self.strtab_string_map.getOrPutAssumeCapacityAdapted(bytes, StrtabString.Adapter{ .builder = self }); + if (!gop.found_existing) { + self.strtab_string_bytes.appendSliceAssumeCapacity(bytes); + self.strtab_string_indices.appendAssumeCapacity(@intCast(self.strtab_string_bytes.items.len)); + } + return StrtabString.fromIndex(gop.index); +} + +pub fn strtabStringIfExists(self: *const Builder, bytes: []const u8) ?StrtabString { + return StrtabString.fromIndex( + self.strtab_string_map.getIndexAdapted(bytes, StrtabString.Adapter{ .builder = self }) orelse return null, + ); +} + +pub fn strtabStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allocator.Error!StrtabString { + try self.strtab_string_map.ensureUnusedCapacity(self.gpa, 1); + try self.strtab_string_bytes.ensureUnusedCapacity(self.gpa, @intCast(std.fmt.count(fmt_str, fmt_args))); + try self.strtab_string_indices.ensureUnusedCapacity(self.gpa, 1); + return self.strtabStringFmtAssumeCapacity(fmt_str, fmt_args); +} + +pub fn strtabStringFmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) StrtabString { + self.strtab_string_bytes.writer(undefined).print(fmt_str, fmt_args) catch unreachable; + return self.trailingStrtabStringAssumeCapacity(); +} + +pub fn trailingStrtabString(self: *Builder) Allocator.Error!StrtabString { + try self.strtab_string_indices.ensureUnusedCapacity(self.gpa, 1); + try self.strtab_string_map.ensureUnusedCapacity(self.gpa, 1); + return self.trailingStrtabStringAssumeCapacity(); +} + +pub fn trailingStrtabStringAssumeCapacity(self: *Builder) StrtabString { + const start = self.strtab_string_indices.getLast(); + const bytes: []const u8 = self.strtab_string_bytes.items[start..]; + const gop = self.strtab_string_map.getOrPutAssumeCapacityAdapted(bytes, StrtabString.Adapter{ .builder = self }); + if (gop.found_existing) { + self.strtab_string_bytes.shrinkRetainingCapacity(start); + } else { + self.strtab_string_indices.appendAssumeCapacity(@intCast(self.strtab_string_bytes.items.len)); + } + return StrtabString.fromIndex(gop.index); +} + pub const Global = struct { linkage: Linkage = .external, preemption: Preemption = .dso_preemptable, @@ -2179,19 +2294,23 @@ pub const Global = struct { return &builder.globals.values()[@intFromEnum(self.unwrap(builder))]; } - pub fn name(self: Index, builder: *const Builder) String { + pub fn name(self: Index, builder: *const Builder) StrtabString { return builder.globals.keys()[@intFromEnum(self.unwrap(builder))]; } - pub fn strtab(self: Index, builder: *const Builder) StrtabString { + pub fn strtab(self: Index, builder: *const Builder) struct { + offset: u32, + size: u32, + } { const name_index = self.name(builder).toIndex() orelse return .{ .offset = 0, .size = 0, }; return .{ - .offset = builder.string_indices.items[name_index], - .size = builder.string_indices.items[name_index + 1] - builder.string_indices.items[name_index], + .offset = builder.strtab_string_indices.items[name_index], + .size = builder.strtab_string_indices.items[name_index + 1] - + builder.strtab_string_indices.items[name_index], }; } @@ -2243,7 +2362,7 @@ pub const Global = struct { return .{ .data = .{ .global = self, .builder = builder } }; } - pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void { + pub fn rename(self: Index, new_name: StrtabString, builder: *Builder) Allocator.Error!void { try builder.ensureUnusedGlobalCapacity(new_name); self.renameAssumeCapacity(new_name, builder); } @@ -2282,7 +2401,7 @@ pub const Global = struct { } } - fn renameAssumeCapacity(self: Index, new_name: String, builder: *Builder) void { + fn renameAssumeCapacity(self: Index, new_name: StrtabString, builder: *Builder) void { const old_name = self.name(builder); if (new_name == old_name) return; const index = @intFromEnum(self.unwrap(builder)); @@ -2333,11 +2452,11 @@ pub const Alias = struct { return &builder.aliases.items[@intFromEnum(self)]; } - pub fn name(self: Index, builder: *const Builder) String { + pub fn name(self: Index, builder: *const Builder) StrtabString { return self.ptrConst(builder).global.name(builder); } - pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void { + pub fn rename(self: Index, new_name: StrtabString, builder: *Builder) Allocator.Error!void { return self.ptrConst(builder).global.rename(new_name, builder); } @@ -2385,11 +2504,11 @@ pub const Variable = struct { return &builder.variables.items[@intFromEnum(self)]; } - pub fn name(self: Index, builder: *const Builder) String { + pub fn name(self: Index, builder: *const Builder) StrtabString { return self.ptrConst(builder).global.name(builder); } - pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void { + pub fn rename(self: Index, new_name: StrtabString, builder: *Builder) Allocator.Error!void { return self.ptrConst(builder).global.rename(new_name, builder); } @@ -3814,11 +3933,11 @@ pub const Function = struct { return &builder.functions.items[@intFromEnum(self)]; } - pub fn name(self: Index, builder: *const Builder) String { + pub fn name(self: Index, builder: *const Builder) StrtabString { return self.ptrConst(builder).global.name(builder); } - pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void { + pub fn rename(self: Index, new_name: StrtabString, builder: *Builder) Allocator.Error!void { return self.ptrConst(builder).global.rename(new_name, builder); } @@ -8331,6 +8450,10 @@ pub fn init(options: Options) Allocator.Error!Builder { .variables = .{}, .functions = .{}, + .strtab_string_map = .{}, + .strtab_string_indices = .{}, + .strtab_string_bytes = .{}, + .constant_map = .{}, .constant_items = .{}, .constant_extra = .{}, @@ -8351,6 +8474,9 @@ pub fn init(options: Options) Allocator.Error!Builder { try self.string_indices.append(self.gpa, 0); assert(try self.string("") == .empty); + try self.strtab_string_indices.append(self.gpa, 0); + assert(try self.strtabString("") == .empty); + if (options.name.len > 0) self.source_filename = try self.string(options.name); if (options.triple.len > 0) { @@ -8423,6 +8549,10 @@ pub fn clearAndFree(self: *Builder) void { for (self.functions.items) |*function| function.deinit(self.gpa); self.functions.clearAndFree(self.gpa); + self.strtab_string_map.clearAndFree(self.gpa); + self.strtab_string_indices.clearAndFree(self.gpa); + self.strtab_string_bytes.clearAndFree(self.gpa); + self.constant_map.clearAndFree(self.gpa); self.constant_items.shrinkAndFree(self.gpa, 0); self.constant_extra.clearAndFree(self.gpa); @@ -8467,6 +8597,10 @@ pub fn deinit(self: *Builder) void { for (self.functions.items) |*function| function.deinit(self.gpa); self.functions.deinit(self.gpa); + self.strtab_string_map.deinit(self.gpa); + self.strtab_string_indices.deinit(self.gpa); + self.strtab_string_bytes.deinit(self.gpa); + self.constant_map.deinit(self.gpa); self.constant_items.deinit(self.gpa); self.constant_extra.deinit(self.gpa); @@ -8660,14 +8794,14 @@ pub fn fnAttrs(self: *Builder, fn_attributes: []const Attributes) Allocator.Erro return function_attributes; } -pub fn addGlobal(self: *Builder, name: String, global: Global) Allocator.Error!Global.Index { +pub fn addGlobal(self: *Builder, name: StrtabString, global: Global) Allocator.Error!Global.Index { assert(!name.isAnon()); try self.ensureUnusedTypeCapacity(1, NoExtra, 0); try self.ensureUnusedGlobalCapacity(name); return self.addGlobalAssumeCapacity(name, global); } -pub fn addGlobalAssumeCapacity(self: *Builder, name: String, global: Global) Global.Index { +pub fn addGlobalAssumeCapacity(self: *Builder, name: StrtabString, global: Global) Global.Index { _ = self.ptrTypeAssumeCapacity(global.addr_space); var id = name; if (name == .empty) { @@ -8686,18 +8820,18 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: String, global: Global) Glo const unique_gop = self.next_unique_global_id.getOrPutAssumeCapacity(name); if (!unique_gop.found_existing) unique_gop.value_ptr.* = 2; - id = self.fmtAssumeCapacity("{s}.{d}", .{ name.slice(self).?, unique_gop.value_ptr.* }); + id = self.strtabStringFmtAssumeCapacity("{s}.{d}", .{ name.slice(self).?, unique_gop.value_ptr.* }); unique_gop.value_ptr.* += 1; } } -pub fn getGlobal(self: *const Builder, name: String) ?Global.Index { +pub fn getGlobal(self: *const Builder, name: StrtabString) ?Global.Index { return @enumFromInt(self.globals.getIndex(name) orelse return null); } pub fn addAlias( self: *Builder, - name: String, + name: StrtabString, ty: Type, addr_space: AddrSpace, aliasee: Constant, @@ -8711,7 +8845,7 @@ pub fn addAlias( pub fn addAliasAssumeCapacity( self: *Builder, - name: String, + name: StrtabString, ty: Type, addr_space: AddrSpace, aliasee: Constant, @@ -8727,7 +8861,7 @@ pub fn addAliasAssumeCapacity( pub fn addVariable( self: *Builder, - name: String, + name: StrtabString, ty: Type, addr_space: AddrSpace, ) Allocator.Error!Variable.Index { @@ -8741,7 +8875,7 @@ pub fn addVariable( pub fn addVariableAssumeCapacity( self: *Builder, ty: Type, - name: String, + name: StrtabString, addr_space: AddrSpace, ) Variable.Index { const variable_index: Variable.Index = @enumFromInt(self.variables.items.len); @@ -8756,7 +8890,7 @@ pub fn addVariableAssumeCapacity( pub fn addFunction( self: *Builder, ty: Type, - name: String, + name: StrtabString, addr_space: AddrSpace, ) Allocator.Error!Function.Index { assert(!name.isAnon()); @@ -8769,7 +8903,7 @@ pub fn addFunction( pub fn addFunctionAssumeCapacity( self: *Builder, ty: Type, - name: String, + name: StrtabString, addr_space: AddrSpace, ) Function.Index { assert(ty.isFunction(self)); @@ -8803,10 +8937,10 @@ pub fn getIntrinsic( const allocator = stack.get(); const name = name: { - const writer = self.string_bytes.writer(self.gpa); + const writer = self.strtab_string_bytes.writer(self.gpa); try writer.print("llvm.{s}", .{@tagName(id)}); for (overload) |ty| try writer.print(".{m}", .{ty.fmt(self)}); - break :name try self.trailingString(); + break :name try self.trailingStrtabString(); }; if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function; @@ -10366,13 +10500,13 @@ fn printEscapedString( if (need_quotes) try writer.writeByte('"'); } -fn ensureUnusedGlobalCapacity(self: *Builder, name: String) Allocator.Error!void { - try self.string_map.ensureUnusedCapacity(self.gpa, 1); +fn ensureUnusedGlobalCapacity(self: *Builder, name: StrtabString) Allocator.Error!void { + try self.strtab_string_map.ensureUnusedCapacity(self.gpa, 1); if (name.slice(self)) |id| { const count: usize = comptime std.fmt.count("{d}", .{std.math.maxInt(u32)}); - try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len + count); + try self.strtab_string_bytes.ensureUnusedCapacity(self.gpa, id.len + count); } - try self.string_indices.ensureUnusedCapacity(self.gpa, 1); + try self.strtab_string_indices.ensureUnusedCapacity(self.gpa, 1); try self.globals.ensureUnusedCapacity(self.gpa, 1); try self.next_unique_global_id.ensureUnusedCapacity(self.gpa, 1); } @@ -11893,7 +12027,7 @@ pub fn metadataString(self: *Builder, bytes: []const u8) Allocator.Error!Metadat return @enumFromInt(gop.index); } -pub fn metadataStringFromString(self: *Builder, str: String) Allocator.Error!MetadataString { +pub fn metadataStringFromStrtabString(self: *Builder, str: StrtabString) Allocator.Error!MetadataString { if (str == .none or str == .empty) return MetadataString.none; return try self.metadataString(str.slice(self).?); } @@ -15059,7 +15193,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co const Strtab = ir.Strtab; var strtab_block = try bitcode.enterTopBlock(Strtab); - try strtab_block.writeAbbrev(Strtab.Blob{ .blob = self.string_bytes.items }); + try strtab_block.writeAbbrev(Strtab.Blob{ .blob = self.strtab_string_bytes.items }); try strtab_block.end(); }