authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2024-02-29 01:03:58+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-02-29 01:03:58+01:00
log69df00f657c567339d0d39c50381eaec4fab32a4
tree5349ca48e39be02749ae379fb0f5df05b4955b49
parent9410b11ca663231e367e3adfd668979c4b870a41
parent5c2e463ecd9070638fa623b3e5856188e4550a78
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #19115 from antlilja/llvm-misc

LLVM: Miscellaneous improvements to Builder

3 files changed, 217 insertions(+), 93 deletions(-)

src/codegen/llvm.zig+31-38
......@@ -1046,7 +1046,7 @@ pub const Object = struct {
10461046
10471047 fn genCmpLtErrorsLenFunction(o: *Object) !void {
10481048 // If there is no such function in the module, it means the source code does not need it.
1049 const name = o.builder.stringIfExists(lt_errors_fn_name) orelse return;
1049 const name = o.builder.strtabStringIfExists(lt_errors_fn_name) orelse return;
10501050 const llvm_fn = o.builder.getGlobal(name) orelse return;
10511051 const mod = o.module;
10521052 const errors_len = mod.global_error_set.count();
......@@ -1087,7 +1087,7 @@ pub const Object = struct {
10871087 for (object.extern_collisions.keys()) |decl_index| {
10881088 const global = object.decl_map.get(decl_index) orelse continue;
10891089 // Same logic as below but for externs instead of exports.
1090 const decl_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(mod.declPtr(decl_index).name)) orelse continue;
1090 const decl_name = object.builder.strtabStringIfExists(mod.intern_pool.stringToSlice(mod.declPtr(decl_index).name)) orelse continue;
10911091 const other_global = object.builder.getGlobal(decl_name) orelse continue;
10921092 if (other_global.toConst().getBase(&object.builder) ==
10931093 global.toConst().getBase(&object.builder)) continue;
......@@ -1117,7 +1117,7 @@ pub const Object = struct {
11171117 for (export_list) |exp| {
11181118 // Detect if the LLVM global has already been created as an extern. In such
11191119 // case, we need to replace all uses of it with this exported global.
1120 const exp_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(exp.opts.name)) orelse continue;
1120 const exp_name = object.builder.strtabStringIfExists(mod.intern_pool.stringToSlice(exp.opts.name)) orelse continue;
11211121
11221122 const other_global = object.builder.getGlobal(exp_name) orelse continue;
11231123 if (other_global.toConst().getBase(&object.builder) == global_base) continue;
......@@ -1662,7 +1662,7 @@ pub const Object = struct {
16621662 const subprogram = try o.builder.debugSubprogram(
16631663 file,
16641664 try o.builder.metadataString(ip.stringToSlice(decl.name)),
1665 try o.builder.metadataStringFromString(function_index.name(&o.builder)),
1665 try o.builder.metadataStringFromStrtabString(function_index.name(&o.builder)),
16661666 line_number,
16671667 line_number + func.lbrace_line,
16681668 debug_decl_type,
......@@ -1763,12 +1763,12 @@ pub const Object = struct {
17631763 if (mod.getTarget().isWasm() and try decl.isFunction(mod)) {
17641764 if (mod.intern_pool.stringToSliceUnwrap(decl.getOwnedExternFunc(mod).?.lib_name)) |lib_name| {
17651765 if (!std.mem.eql(u8, lib_name, "c")) {
1766 break :decl_name try self.builder.fmt("{s}|{s}", .{ decl_name, lib_name });
1766 break :decl_name try self.builder.strtabStringFmt("{s}|{s}", .{ decl_name, lib_name });
17671767 }
17681768 }
17691769 }
17701770
1771 break :decl_name try self.builder.string(decl_name);
1771 break :decl_name try self.builder.strtabString(decl_name);
17721772 };
17731773
17741774 if (self.builder.getGlobal(decl_name)) |other_global| {
......@@ -1791,7 +1791,7 @@ pub const Object = struct {
17911791 if (decl_var.is_weak_linkage) global_index.setLinkage(.extern_weak, &self.builder);
17921792 }
17931793 } else if (exports.len != 0) {
1794 const main_exp_name = try self.builder.string(
1794 const main_exp_name = try self.builder.strtabString(
17951795 mod.intern_pool.stringToSlice(exports[0].opts.name),
17961796 );
17971797 try global_index.rename(main_exp_name, &self.builder);
......@@ -1802,7 +1802,7 @@ pub const Object = struct {
18021802
18031803 return updateExportedGlobal(self, mod, global_index, exports);
18041804 } else {
1805 const fqn = try self.builder.string(
1805 const fqn = try self.builder.strtabString(
18061806 mod.intern_pool.stringToSlice(try decl.fullyQualifiedName(mod)),
18071807 );
18081808 try global_index.rename(fqn, &self.builder);
......@@ -1831,7 +1831,7 @@ pub const Object = struct {
18311831 exports: []const *Module.Export,
18321832 ) link.File.UpdateExportsError!void {
18331833 const gpa = mod.gpa;
1834 const main_exp_name = try o.builder.string(
1834 const main_exp_name = try o.builder.strtabString(
18351835 mod.intern_pool.stringToSlice(exports[0].opts.name),
18361836 );
18371837 const global_index = i: {
......@@ -1899,7 +1899,7 @@ pub const Object = struct {
18991899 // Until then we iterate over existing aliases and make them point
19001900 // to the correct decl, or otherwise add a new alias. Old aliases are leaked.
19011901 for (exports[1..]) |exp| {
1902 const exp_name = try o.builder.string(mod.intern_pool.stringToSlice(exp.opts.name));
1902 const exp_name = try o.builder.strtabString(mod.intern_pool.stringToSlice(exp.opts.name));
19031903 if (o.builder.getGlobal(exp_name)) |global| {
19041904 switch (global.ptrConst(&o.builder).kind) {
19051905 .alias => |alias| {
......@@ -2887,7 +2887,7 @@ pub const Object = struct {
28872887 const is_extern = decl.isExtern(zcu);
28882888 const function_index = try o.builder.addFunction(
28892889 try o.lowerType(zig_fn_type),
2890 try o.builder.string(ip.stringToSlice(if (is_extern)
2890 try o.builder.strtabString(ip.stringToSlice(if (is_extern)
28912891 decl.name
28922892 else
28932893 try decl.fullyQualifiedName(zcu))),
......@@ -3077,7 +3077,7 @@ pub const Object = struct {
30773077 const decl_ty = mod.intern_pool.typeOf(decl_val);
30783078
30793079 const variable_index = try o.builder.addVariable(
3080 try o.builder.fmt("__anon_{d}", .{@intFromEnum(decl_val)}),
3080 try o.builder.strtabStringFmt("__anon_{d}", .{@intFromEnum(decl_val)}),
30813081 try o.lowerType(Type.fromInterned(decl_ty)),
30823082 llvm_addr_space,
30833083 );
......@@ -3103,7 +3103,7 @@ pub const Object = struct {
31033103 const is_extern = decl.isExtern(mod);
31043104
31053105 const variable_index = try o.builder.addVariable(
3106 try o.builder.string(mod.intern_pool.stringToSlice(
3106 try o.builder.strtabString(mod.intern_pool.stringToSlice(
31073107 if (is_extern) decl.name else try decl.fullyQualifiedName(mod),
31083108 )),
31093109 try o.lowerType(decl.ty),
......@@ -4570,7 +4570,7 @@ pub const Object = struct {
45704570 }
45714571
45724572 fn getCmpLtErrorsLenFunction(o: *Object) !Builder.Function.Index {
4573 const name = try o.builder.string(lt_errors_fn_name);
4573 const name = try o.builder.strtabString(lt_errors_fn_name);
45744574 if (o.builder.getGlobal(name)) |llvm_fn| return llvm_fn.ptrConst(&o.builder).kind.function;
45754575
45764576 const zcu = o.module;
......@@ -4607,7 +4607,7 @@ pub const Object = struct {
46074607 const target = zcu.root_mod.resolved_target.result;
46084608 const function_index = try o.builder.addFunction(
46094609 try o.builder.fnType(ret_ty, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
4610 try o.builder.fmt("__zig_tag_name_{}", .{fqn.fmt(ip)}),
4610 try o.builder.strtabStringFmt("__zig_tag_name_{}", .{fqn.fmt(ip)}),
46114611 toLlvmAddressSpace(.generic, target),
46124612 );
46134613
......@@ -4730,7 +4730,7 @@ pub const DeclGen = struct {
47304730
47314731 const debug_global_var = try o.builder.debugGlobalVar(
47324732 try o.builder.metadataString(zcu.intern_pool.stringToSlice(decl.name)), // Name
4733 try o.builder.metadataStringFromString(variable_index.name(&o.builder)), // Linkage name
4733 try o.builder.metadataStringFromStrtabString(variable_index.name(&o.builder)), // Linkage name
47344734 debug_file, // File
47354735 debug_file, // Scope
47364736 line_number,
......@@ -6169,7 +6169,7 @@ pub const FuncGen = struct {
61696169 const compiler_rt_operand_abbrev = compilerRtIntAbbrev(rt_int_bits);
61706170 const compiler_rt_dest_abbrev = compilerRtFloatAbbrev(dest_bits);
61716171 const sign_prefix = if (is_signed_int) "" else "un";
6172 const fn_name = try o.builder.fmt("__float{s}{s}i{s}f", .{
6172 const fn_name = try o.builder.strtabStringFmt("__float{s}{s}i{s}f", .{
61736173 sign_prefix,
61746174 compiler_rt_operand_abbrev,
61756175 compiler_rt_dest_abbrev,
......@@ -6239,7 +6239,7 @@ pub const FuncGen = struct {
62396239 const compiler_rt_dest_abbrev = compilerRtIntAbbrev(rt_int_bits);
62406240 const sign_prefix = if (dest_scalar_ty.isSignedInt(mod)) "" else "uns";
62416241
6242 const fn_name = try o.builder.fmt("__fix{s}{s}f{s}i", .{
6242 const fn_name = try o.builder.strtabStringFmt("__fix{s}{s}f{s}i", .{
62436243 sign_prefix,
62446244 compiler_rt_operand_abbrev,
62456245 compiler_rt_dest_abbrev,
......@@ -6637,7 +6637,7 @@ pub const FuncGen = struct {
66376637 .return_type = .void_type,
66386638 });
66396639
6640 const subprogram = try o.builder.debugSubprogram(
6640 self.scope = try o.builder.debugSubprogram(
66416641 self.file,
66426642 try o.builder.metadataString(zcu.intern_pool.stringToSlice(decl.name)),
66436643 try o.builder.metadataString(zcu.intern_pool.stringToSlice(fqn)),
......@@ -6655,13 +6655,6 @@ pub const FuncGen = struct {
66556655 o.debug_compile_unit,
66566656 );
66576657
6658 const lexical_block = try o.builder.debugLexicalBlock(
6659 subprogram,
6660 self.file,
6661 line_number,
6662 1,
6663 );
6664 self.scope = lexical_block;
66656658 self.base_line = decl.src_line;
66666659 const inlined_at_location = try self.wip.debug_location.toMetadata(&o.builder);
66676660 self.wip.debug_location = .{
......@@ -8117,7 +8110,7 @@ pub const FuncGen = struct {
81178110
81188111 fn getLibcFunction(
81198112 self: *FuncGen,
8120 fn_name: Builder.String,
8113 fn_name: Builder.StrtabString,
81218114 param_types: []const Builder.Type,
81228115 return_type: Builder.Type,
81238116 ) Allocator.Error!Builder.Function.Index {
......@@ -8171,7 +8164,7 @@ pub const FuncGen = struct {
81718164 .gt => "gt",
81728165 .gte => "ge",
81738166 };
8174 const fn_name = try o.builder.fmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev });
8167 const fn_name = try o.builder.strtabStringFmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev });
81758168
81768169 const libc_fn = try self.getLibcFunction(fn_name, &.{ scalar_llvm_ty, scalar_llvm_ty }, .i32);
81778170
......@@ -8329,7 +8322,7 @@ pub const FuncGen = struct {
83298322 const result = try self.wip.bin(.xor, bitcasted_operand, sign_mask, "");
83308323 return self.wip.cast(.bitcast, result, llvm_ty, "");
83318324 },
8332 .add, .sub, .div, .mul => try o.builder.fmt("__{s}{s}f3", .{
8325 .add, .sub, .div, .mul => try o.builder.strtabStringFmt("__{s}{s}f3", .{
83338326 @tagName(op), compilerRtFloatAbbrev(float_bits),
83348327 }),
83358328 .ceil,
......@@ -8350,7 +8343,7 @@ pub const FuncGen = struct {
83508343 .sqrt,
83518344 .tan,
83528345 .trunc,
8353 => try o.builder.fmt("{s}{s}{s}", .{
8346 => try o.builder.strtabStringFmt("{s}{s}{s}", .{
83548347 libcFloatPrefix(float_bits), @tagName(op), libcFloatSuffix(float_bits),
83558348 }),
83568349 };
......@@ -8614,7 +8607,7 @@ pub const FuncGen = struct {
86148607 const operand_llvm_ty = try o.lowerType(operand_ty);
86158608 const dest_llvm_ty = try o.lowerType(dest_ty);
86168609
8617 const fn_name = try o.builder.fmt("__trunc{s}f{s}f2", .{
8610 const fn_name = try o.builder.strtabStringFmt("__trunc{s}f{s}f2", .{
86188611 compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits),
86198612 });
86208613
......@@ -8648,7 +8641,7 @@ pub const FuncGen = struct {
86488641
86498642 const dest_bits = dest_ty.scalarType(mod).floatBits(target);
86508643 const src_bits = operand_ty.scalarType(mod).floatBits(target);
8651 const fn_name = try o.builder.fmt("__extend{s}f{s}f2", .{
8644 const fn_name = try o.builder.strtabStringFmt("__extend{s}f{s}f2", .{
86528645 compilerRtFloatAbbrev(src_bits), compilerRtFloatAbbrev(dest_bits),
86538646 });
86548647
......@@ -9644,7 +9637,7 @@ pub const FuncGen = struct {
96449637 const target = zcu.root_mod.resolved_target.result;
96459638 const function_index = try o.builder.addFunction(
96469639 try o.builder.fnType(.i1, &.{try o.lowerType(Type.fromInterned(enum_type.tag_ty))}, .normal),
9647 try o.builder.fmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&zcu.intern_pool)}),
9640 try o.builder.strtabStringFmt("__zig_is_named_enum_value_{}", .{fqn.fmt(&zcu.intern_pool)}),
96489641 toLlvmAddressSpace(.generic, target),
96499642 );
96509643
......@@ -9909,16 +9902,16 @@ pub const FuncGen = struct {
99099902 // Use a manual loop over a softfloat call instead.
99109903 const float_bits = scalar_ty.floatBits(target);
99119904 const fn_name = switch (reduce.operation) {
9912 .Min => try o.builder.fmt("{s}fmin{s}", .{
9905 .Min => try o.builder.strtabStringFmt("{s}fmin{s}", .{
99139906 libcFloatPrefix(float_bits), libcFloatSuffix(float_bits),
99149907 }),
9915 .Max => try o.builder.fmt("{s}fmax{s}", .{
9908 .Max => try o.builder.strtabStringFmt("{s}fmax{s}", .{
99169909 libcFloatPrefix(float_bits), libcFloatSuffix(float_bits),
99179910 }),
9918 .Add => try o.builder.fmt("__add{s}f3", .{
9911 .Add => try o.builder.strtabStringFmt("__add{s}f3", .{
99199912 compilerRtFloatAbbrev(float_bits),
99209913 }),
9921 .Mul => try o.builder.fmt("__mul{s}f3", .{
9914 .Mul => try o.builder.strtabStringFmt("__mul{s}f3", .{
99229915 compilerRtFloatAbbrev(float_bits),
99239916 }),
99249917 else => unreachable,
......@@ -10323,7 +10316,7 @@ pub const FuncGen = struct {
1032310316
1032410317 // TODO: Address space
1032510318 const variable_index =
10326 try o.builder.addVariable(try o.builder.string("__zig_err_name_table"), .ptr, .default);
10319 try o.builder.addVariable(try o.builder.strtabString("__zig_err_name_table"), .ptr, .default);
1032710320 variable_index.setLinkage(.private, &o.builder);
1032810321 variable_index.setMutability(.constant, &o.builder);
1032910322 variable_index.setUnnamedAddr(.unnamed_addr, &o.builder);
src/codegen/llvm/Builder.zig+174-50
......@@ -24,14 +24,18 @@ attributes_extra: std.ArrayListUnmanaged(u32),
2424
2525function_attributes_set: std.AutoArrayHashMapUnmanaged(FunctionAttributes, void),
2626
27globals: std.AutoArrayHashMapUnmanaged(String, Global),
28next_unnamed_global: String,
29next_replaced_global: String,
30next_unique_global_id: std.AutoHashMapUnmanaged(String, u32),
27globals: std.AutoArrayHashMapUnmanaged(StrtabString, Global),
28next_unnamed_global: StrtabString,
29next_replaced_global: StrtabString,
30next_unique_global_id: std.AutoHashMapUnmanaged(StrtabString, u32),
3131aliases: std.ArrayListUnmanaged(Alias),
3232variables: std.ArrayListUnmanaged(Variable),
3333functions: std.ArrayListUnmanaged(Function),
3434
35strtab_string_map: std.AutoArrayHashMapUnmanaged(void, void),
36strtab_string_indices: std.ArrayListUnmanaged(u32),
37strtab_string_bytes: std.ArrayListUnmanaged(u8),
38
3539constant_map: std.AutoArrayHashMapUnmanaged(void, void),
3640constant_items: std.MultiArrayList(Constant.Item),
3741constant_extra: std.ArrayListUnmanaged(u32),
......@@ -194,11 +198,6 @@ pub const CmpPredicate = enum(u6) {
194198 icmp_sle = 41,
195199};
196200
197pub const StrtabString = struct {
198 offset: usize,
199 size: usize,
200};
201
202201pub const Type = enum(u32) {
203202 void,
204203 half,
......@@ -2136,6 +2135,122 @@ pub const CallConv = enum(u10) {
21362135 }
21372136};
21382137
2138pub const StrtabString = enum(u32) {
2139 none = std.math.maxInt(u31),
2140 empty,
2141 _,
2142
2143 pub fn isAnon(self: StrtabString) bool {
2144 assert(self != .none);
2145 return self.toIndex() == null;
2146 }
2147
2148 pub fn slice(self: StrtabString, builder: *const Builder) ?[]const u8 {
2149 const index = self.toIndex() orelse return null;
2150 const start = builder.strtab_string_indices.items[index];
2151 const end = builder.strtab_string_indices.items[index + 1];
2152 return builder.strtab_string_bytes.items[start..end];
2153 }
2154
2155 const FormatData = struct {
2156 string: StrtabString,
2157 builder: *const Builder,
2158 };
2159 fn format(
2160 data: FormatData,
2161 comptime fmt_str: []const u8,
2162 _: std.fmt.FormatOptions,
2163 writer: anytype,
2164 ) @TypeOf(writer).Error!void {
2165 if (comptime std.mem.indexOfNone(u8, fmt_str, "\"r")) |_|
2166 @compileError("invalid format string: '" ++ fmt_str ++ "'");
2167 assert(data.string != .none);
2168 const string_slice = data.string.slice(data.builder) orelse
2169 return writer.print("{d}", .{@intFromEnum(data.string)});
2170 if (comptime std.mem.indexOfScalar(u8, fmt_str, 'r')) |_|
2171 return writer.writeAll(string_slice);
2172 try printEscapedString(
2173 string_slice,
2174 if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_|
2175 .always_quote
2176 else
2177 .quote_unless_valid_identifier,
2178 writer,
2179 );
2180 }
2181 pub fn fmt(self: StrtabString, builder: *const Builder) std.fmt.Formatter(format) {
2182 return .{ .data = .{ .string = self, .builder = builder } };
2183 }
2184
2185 fn fromIndex(index: ?usize) StrtabString {
2186 return @enumFromInt(@as(u32, @intCast((index orelse return .none) +
2187 @intFromEnum(StrtabString.empty))));
2188 }
2189
2190 fn toIndex(self: StrtabString) ?usize {
2191 return std.math.sub(u32, @intFromEnum(self), @intFromEnum(StrtabString.empty)) catch null;
2192 }
2193
2194 const Adapter = struct {
2195 builder: *const Builder,
2196 pub fn hash(_: Adapter, key: []const u8) u32 {
2197 return @truncate(std.hash.Wyhash.hash(0, key));
2198 }
2199 pub fn eql(ctx: Adapter, lhs_key: []const u8, _: void, rhs_index: usize) bool {
2200 return std.mem.eql(u8, lhs_key, StrtabString.fromIndex(rhs_index).slice(ctx.builder).?);
2201 }
2202 };
2203};
2204
2205pub fn strtabString(self: *Builder, bytes: []const u8) Allocator.Error!StrtabString {
2206 try self.strtab_string_bytes.ensureUnusedCapacity(self.gpa, bytes.len);
2207 try self.strtab_string_indices.ensureUnusedCapacity(self.gpa, 1);
2208 try self.strtab_string_map.ensureUnusedCapacity(self.gpa, 1);
2209
2210 const gop = self.strtab_string_map.getOrPutAssumeCapacityAdapted(bytes, StrtabString.Adapter{ .builder = self });
2211 if (!gop.found_existing) {
2212 self.strtab_string_bytes.appendSliceAssumeCapacity(bytes);
2213 self.strtab_string_indices.appendAssumeCapacity(@intCast(self.strtab_string_bytes.items.len));
2214 }
2215 return StrtabString.fromIndex(gop.index);
2216}
2217
2218pub fn strtabStringIfExists(self: *const Builder, bytes: []const u8) ?StrtabString {
2219 return StrtabString.fromIndex(
2220 self.strtab_string_map.getIndexAdapted(bytes, StrtabString.Adapter{ .builder = self }) orelse return null,
2221 );
2222}
2223
2224pub fn strtabStringFmt(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) Allocator.Error!StrtabString {
2225 try self.strtab_string_map.ensureUnusedCapacity(self.gpa, 1);
2226 try self.strtab_string_bytes.ensureUnusedCapacity(self.gpa, @intCast(std.fmt.count(fmt_str, fmt_args)));
2227 try self.strtab_string_indices.ensureUnusedCapacity(self.gpa, 1);
2228 return self.strtabStringFmtAssumeCapacity(fmt_str, fmt_args);
2229}
2230
2231pub fn strtabStringFmtAssumeCapacity(self: *Builder, comptime fmt_str: []const u8, fmt_args: anytype) StrtabString {
2232 self.strtab_string_bytes.writer(undefined).print(fmt_str, fmt_args) catch unreachable;
2233 return self.trailingStrtabStringAssumeCapacity();
2234}
2235
2236pub fn trailingStrtabString(self: *Builder) Allocator.Error!StrtabString {
2237 try self.strtab_string_indices.ensureUnusedCapacity(self.gpa, 1);
2238 try self.strtab_string_map.ensureUnusedCapacity(self.gpa, 1);
2239 return self.trailingStrtabStringAssumeCapacity();
2240}
2241
2242pub fn trailingStrtabStringAssumeCapacity(self: *Builder) StrtabString {
2243 const start = self.strtab_string_indices.getLast();
2244 const bytes: []const u8 = self.strtab_string_bytes.items[start..];
2245 const gop = self.strtab_string_map.getOrPutAssumeCapacityAdapted(bytes, StrtabString.Adapter{ .builder = self });
2246 if (gop.found_existing) {
2247 self.strtab_string_bytes.shrinkRetainingCapacity(start);
2248 } else {
2249 self.strtab_string_indices.appendAssumeCapacity(@intCast(self.strtab_string_bytes.items.len));
2250 }
2251 return StrtabString.fromIndex(gop.index);
2252}
2253
21392254pub const Global = struct {
21402255 linkage: Linkage = .external,
21412256 preemption: Preemption = .dso_preemptable,
......@@ -2179,19 +2294,23 @@ pub const Global = struct {
21792294 return &builder.globals.values()[@intFromEnum(self.unwrap(builder))];
21802295 }
21812296
2182 pub fn name(self: Index, builder: *const Builder) String {
2297 pub fn name(self: Index, builder: *const Builder) StrtabString {
21832298 return builder.globals.keys()[@intFromEnum(self.unwrap(builder))];
21842299 }
21852300
2186 pub fn strtab(self: Index, builder: *const Builder) StrtabString {
2301 pub fn strtab(self: Index, builder: *const Builder) struct {
2302 offset: u32,
2303 size: u32,
2304 } {
21872305 const name_index = self.name(builder).toIndex() orelse return .{
21882306 .offset = 0,
21892307 .size = 0,
21902308 };
21912309
21922310 return .{
2193 .offset = builder.string_indices.items[name_index],
2194 .size = builder.string_indices.items[name_index + 1] - builder.string_indices.items[name_index],
2311 .offset = builder.strtab_string_indices.items[name_index],
2312 .size = builder.strtab_string_indices.items[name_index + 1] -
2313 builder.strtab_string_indices.items[name_index],
21952314 };
21962315 }
21972316
......@@ -2243,7 +2362,7 @@ pub const Global = struct {
22432362 return .{ .data = .{ .global = self, .builder = builder } };
22442363 }
22452364
2246 pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void {
2365 pub fn rename(self: Index, new_name: StrtabString, builder: *Builder) Allocator.Error!void {
22472366 try builder.ensureUnusedGlobalCapacity(new_name);
22482367 self.renameAssumeCapacity(new_name, builder);
22492368 }
......@@ -2282,7 +2401,7 @@ pub const Global = struct {
22822401 }
22832402 }
22842403
2285 fn renameAssumeCapacity(self: Index, new_name: String, builder: *Builder) void {
2404 fn renameAssumeCapacity(self: Index, new_name: StrtabString, builder: *Builder) void {
22862405 const old_name = self.name(builder);
22872406 if (new_name == old_name) return;
22882407 const index = @intFromEnum(self.unwrap(builder));
......@@ -2333,11 +2452,11 @@ pub const Alias = struct {
23332452 return &builder.aliases.items[@intFromEnum(self)];
23342453 }
23352454
2336 pub fn name(self: Index, builder: *const Builder) String {
2455 pub fn name(self: Index, builder: *const Builder) StrtabString {
23372456 return self.ptrConst(builder).global.name(builder);
23382457 }
23392458
2340 pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void {
2459 pub fn rename(self: Index, new_name: StrtabString, builder: *Builder) Allocator.Error!void {
23412460 return self.ptrConst(builder).global.rename(new_name, builder);
23422461 }
23432462
......@@ -2385,11 +2504,11 @@ pub const Variable = struct {
23852504 return &builder.variables.items[@intFromEnum(self)];
23862505 }
23872506
2388 pub fn name(self: Index, builder: *const Builder) String {
2507 pub fn name(self: Index, builder: *const Builder) StrtabString {
23892508 return self.ptrConst(builder).global.name(builder);
23902509 }
23912510
2392 pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void {
2511 pub fn rename(self: Index, new_name: StrtabString, builder: *Builder) Allocator.Error!void {
23932512 return self.ptrConst(builder).global.rename(new_name, builder);
23942513 }
23952514
......@@ -3814,11 +3933,11 @@ pub const Function = struct {
38143933 return &builder.functions.items[@intFromEnum(self)];
38153934 }
38163935
3817 pub fn name(self: Index, builder: *const Builder) String {
3936 pub fn name(self: Index, builder: *const Builder) StrtabString {
38183937 return self.ptrConst(builder).global.name(builder);
38193938 }
38203939
3821 pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void {
3940 pub fn rename(self: Index, new_name: StrtabString, builder: *Builder) Allocator.Error!void {
38223941 return self.ptrConst(builder).global.rename(new_name, builder);
38233942 }
38243943
......@@ -8331,6 +8450,10 @@ pub fn init(options: Options) Allocator.Error!Builder {
83318450 .variables = .{},
83328451 .functions = .{},
83338452
8453 .strtab_string_map = .{},
8454 .strtab_string_indices = .{},
8455 .strtab_string_bytes = .{},
8456
83348457 .constant_map = .{},
83358458 .constant_items = .{},
83368459 .constant_extra = .{},
......@@ -8351,6 +8474,9 @@ pub fn init(options: Options) Allocator.Error!Builder {
83518474 try self.string_indices.append(self.gpa, 0);
83528475 assert(try self.string("") == .empty);
83538476
8477 try self.strtab_string_indices.append(self.gpa, 0);
8478 assert(try self.strtabString("") == .empty);
8479
83548480 if (options.name.len > 0) self.source_filename = try self.string(options.name);
83558481
83568482 if (options.triple.len > 0) {
......@@ -8423,6 +8549,10 @@ pub fn clearAndFree(self: *Builder) void {
84238549 for (self.functions.items) |*function| function.deinit(self.gpa);
84248550 self.functions.clearAndFree(self.gpa);
84258551
8552 self.strtab_string_map.clearAndFree(self.gpa);
8553 self.strtab_string_indices.clearAndFree(self.gpa);
8554 self.strtab_string_bytes.clearAndFree(self.gpa);
8555
84268556 self.constant_map.clearAndFree(self.gpa);
84278557 self.constant_items.shrinkAndFree(self.gpa, 0);
84288558 self.constant_extra.clearAndFree(self.gpa);
......@@ -8467,6 +8597,10 @@ pub fn deinit(self: *Builder) void {
84678597 for (self.functions.items) |*function| function.deinit(self.gpa);
84688598 self.functions.deinit(self.gpa);
84698599
8600 self.strtab_string_map.deinit(self.gpa);
8601 self.strtab_string_indices.deinit(self.gpa);
8602 self.strtab_string_bytes.deinit(self.gpa);
8603
84708604 self.constant_map.deinit(self.gpa);
84718605 self.constant_items.deinit(self.gpa);
84728606 self.constant_extra.deinit(self.gpa);
......@@ -8660,14 +8794,14 @@ pub fn fnAttrs(self: *Builder, fn_attributes: []const Attributes) Allocator.Erro
86608794 return function_attributes;
86618795}
86628796
8663pub fn addGlobal(self: *Builder, name: String, global: Global) Allocator.Error!Global.Index {
8797pub fn addGlobal(self: *Builder, name: StrtabString, global: Global) Allocator.Error!Global.Index {
86648798 assert(!name.isAnon());
86658799 try self.ensureUnusedTypeCapacity(1, NoExtra, 0);
86668800 try self.ensureUnusedGlobalCapacity(name);
86678801 return self.addGlobalAssumeCapacity(name, global);
86688802}
86698803
8670pub fn addGlobalAssumeCapacity(self: *Builder, name: String, global: Global) Global.Index {
8804pub fn addGlobalAssumeCapacity(self: *Builder, name: StrtabString, global: Global) Global.Index {
86718805 _ = self.ptrTypeAssumeCapacity(global.addr_space);
86728806 var id = name;
86738807 if (name == .empty) {
......@@ -8686,18 +8820,18 @@ pub fn addGlobalAssumeCapacity(self: *Builder, name: String, global: Global) Glo
86868820
86878821 const unique_gop = self.next_unique_global_id.getOrPutAssumeCapacity(name);
86888822 if (!unique_gop.found_existing) unique_gop.value_ptr.* = 2;
8689 id = self.fmtAssumeCapacity("{s}.{d}", .{ name.slice(self).?, unique_gop.value_ptr.* });
8823 id = self.strtabStringFmtAssumeCapacity("{s}.{d}", .{ name.slice(self).?, unique_gop.value_ptr.* });
86908824 unique_gop.value_ptr.* += 1;
86918825 }
86928826}
86938827
8694pub fn getGlobal(self: *const Builder, name: String) ?Global.Index {
8828pub fn getGlobal(self: *const Builder, name: StrtabString) ?Global.Index {
86958829 return @enumFromInt(self.globals.getIndex(name) orelse return null);
86968830}
86978831
86988832pub fn addAlias(
86998833 self: *Builder,
8700 name: String,
8834 name: StrtabString,
87018835 ty: Type,
87028836 addr_space: AddrSpace,
87038837 aliasee: Constant,
......@@ -8711,7 +8845,7 @@ pub fn addAlias(
87118845
87128846pub fn addAliasAssumeCapacity(
87138847 self: *Builder,
8714 name: String,
8848 name: StrtabString,
87158849 ty: Type,
87168850 addr_space: AddrSpace,
87178851 aliasee: Constant,
......@@ -8727,7 +8861,7 @@ pub fn addAliasAssumeCapacity(
87278861
87288862pub fn addVariable(
87298863 self: *Builder,
8730 name: String,
8864 name: StrtabString,
87318865 ty: Type,
87328866 addr_space: AddrSpace,
87338867) Allocator.Error!Variable.Index {
......@@ -8741,7 +8875,7 @@ pub fn addVariable(
87418875pub fn addVariableAssumeCapacity(
87428876 self: *Builder,
87438877 ty: Type,
8744 name: String,
8878 name: StrtabString,
87458879 addr_space: AddrSpace,
87468880) Variable.Index {
87478881 const variable_index: Variable.Index = @enumFromInt(self.variables.items.len);
......@@ -8756,7 +8890,7 @@ pub fn addVariableAssumeCapacity(
87568890pub fn addFunction(
87578891 self: *Builder,
87588892 ty: Type,
8759 name: String,
8893 name: StrtabString,
87608894 addr_space: AddrSpace,
87618895) Allocator.Error!Function.Index {
87628896 assert(!name.isAnon());
......@@ -8769,7 +8903,7 @@ pub fn addFunction(
87698903pub fn addFunctionAssumeCapacity(
87708904 self: *Builder,
87718905 ty: Type,
8772 name: String,
8906 name: StrtabString,
87738907 addr_space: AddrSpace,
87748908) Function.Index {
87758909 assert(ty.isFunction(self));
......@@ -8803,10 +8937,10 @@ pub fn getIntrinsic(
88038937 const allocator = stack.get();
88048938
88058939 const name = name: {
8806 const writer = self.string_bytes.writer(self.gpa);
8940 const writer = self.strtab_string_bytes.writer(self.gpa);
88078941 try writer.print("llvm.{s}", .{@tagName(id)});
88088942 for (overload) |ty| try writer.print(".{m}", .{ty.fmt(self)});
8809 break :name try self.trailingString();
8943 break :name try self.trailingStrtabString();
88108944 };
88118945 if (self.getGlobal(name)) |global| return global.ptrConst(self).kind.function;
88128946
......@@ -10366,13 +10500,13 @@ fn printEscapedString(
1036610500 if (need_quotes) try writer.writeByte('"');
1036710501}
1036810502
10369fn ensureUnusedGlobalCapacity(self: *Builder, name: String) Allocator.Error!void {
10370 try self.string_map.ensureUnusedCapacity(self.gpa, 1);
10503fn ensureUnusedGlobalCapacity(self: *Builder, name: StrtabString) Allocator.Error!void {
10504 try self.strtab_string_map.ensureUnusedCapacity(self.gpa, 1);
1037110505 if (name.slice(self)) |id| {
1037210506 const count: usize = comptime std.fmt.count("{d}", .{std.math.maxInt(u32)});
10373 try self.string_bytes.ensureUnusedCapacity(self.gpa, id.len + count);
10507 try self.strtab_string_bytes.ensureUnusedCapacity(self.gpa, id.len + count);
1037410508 }
10375 try self.string_indices.ensureUnusedCapacity(self.gpa, 1);
10509 try self.strtab_string_indices.ensureUnusedCapacity(self.gpa, 1);
1037610510 try self.globals.ensureUnusedCapacity(self.gpa, 1);
1037710511 try self.next_unique_global_id.ensureUnusedCapacity(self.gpa, 1);
1037810512}
......@@ -11893,7 +12027,7 @@ pub fn metadataString(self: *Builder, bytes: []const u8) Allocator.Error!Metadat
1189312027 return @enumFromInt(gop.index);
1189412028}
1189512029
11896pub fn metadataStringFromString(self: *Builder, str: String) Allocator.Error!MetadataString {
12030pub fn metadataStringFromStrtabString(self: *Builder, str: StrtabString) Allocator.Error!MetadataString {
1189712031 if (str == .none or str == .empty) return MetadataString.none;
1189812032 return try self.metadataString(str.slice(self).?);
1189912033}
......@@ -14045,17 +14179,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
1404514179 try bitcode.writeVBR(@as(u32, @intCast(slice.len)), 6);
1404614180 }
1404714181
14048 try bitcode.alignTo32();
14049
14050 for (1..self.metadata_string_map.count()) |metadata_string_index| {
14051 const metadata_string: MetadataString = @enumFromInt(metadata_string_index);
14052 const slice = metadata_string.slice(self);
14053 for (slice) |c| {
14054 try bitcode.writeBits(c, 8);
14055 }
14056 }
14057
14058 try bitcode.alignTo32();
14182 try bitcode.writeBlob(self.metadata_string_bytes.items);
1405914183 }
1406014184
1406114185 for (
......@@ -15069,7 +15193,7 @@ pub fn toBitcode(self: *Builder, allocator: Allocator) bitcode_writer.Error![]co
1506915193 const Strtab = ir.Strtab;
1507015194 var strtab_block = try bitcode.enterTopBlock(Strtab);
1507115195
15072 try strtab_block.writeAbbrev(Strtab.Blob{ .blob = self.string_bytes.items });
15196 try strtab_block.writeAbbrev(Strtab.Blob{ .blob = self.strtab_string_bytes.items });
1507315197
1507415198 try strtab_block.end();
1507515199 }
src/codegen/llvm/bitcode_writer.zig+12-5
......@@ -139,6 +139,17 @@ pub fn BitcodeWriter(comptime types: []const type) type {
139139 try self.writeBits(charTo6Bit(c), 6);
140140 }
141141
142 pub fn writeBlob(self: *BcWriter, blob: []const u8) Error!void {
143 const blob_word_size = std.mem.alignForward(usize, blob.len, 4);
144 try self.buffer.ensureUnusedCapacity(blob_word_size + 1);
145 self.alignTo32() catch unreachable;
146
147 const slice = self.buffer.addManyAsSliceAssumeCapacity(blob_word_size / 4);
148 const slice_bytes = std.mem.sliceAsBytes(slice);
149 @memcpy(slice_bytes[0..blob.len], blob);
150 @memset(slice_bytes[blob.len..], 0);
151 }
152
142153 pub fn alignTo32(self: *BcWriter) Error!void {
143154 if (self.bit_count == 0) return;
144155
......@@ -256,11 +267,7 @@ pub fn BitcodeWriter(comptime types: []const type) type {
256267 .char6 => try self.bitcode.write6BitChar(adapter.get(param, field_name)),
257268 .blob => {
258269 try self.bitcode.writeVBR(param.len, 6);
259 try self.bitcode.alignTo32();
260 for (param) |x| {
261 try self.bitcode.writeBits(x, 8);
262 }
263 try self.bitcode.alignTo32();
270 try self.bitcode.writeBlob(param);
264271 },
265272 .array_fixed => |len| {
266273 try self.bitcode.writeVBR(param.len, 6);