authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-07-23 06:15:26-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-07-23 23:48:19-04:00
log3fc2e36de2d125b2de255b03abc24bea30899caf
tree085e367b2948ddc20ecfd7e504695a915ec312c4
parent533111e849c5f8010f4e9b97c09c433058c5a3e0

llvm: convert global assembly


3 files changed, 632 insertions(+), 544 deletions(-)

src/codegen/llvm.zig+5-9
......@@ -1034,15 +1034,11 @@ pub const Object = struct {
10341034
10351035 fn genModuleLevelAssembly(object: *Object) !void {
10361036 const mod = object.module;
1037 if (mod.global_assembly.count() == 0) return;
1038 var buffer = std.ArrayList(u8).init(mod.gpa);
1039 defer buffer.deinit();
1040 var it = mod.global_assembly.iterator();
1041 while (it.next()) |kv| {
1042 try buffer.appendSlice(kv.value_ptr.*);
1043 try buffer.append('\n');
1044 }
1045 object.llvm_module.setModuleInlineAsm2(buffer.items.ptr, buffer.items.len - 1);
1037
1038 const writer = object.builder.setModuleAsm();
1039 var it = mod.global_assembly.valueIterator();
1040 while (it.next()) |assembly| try writer.print("{s}\n", .{assembly.*});
1041 try object.builder.finishModuleAsm();
10461042 }
10471043
10481044 fn resolveExportExternCollisions(object: *Object) !void {
src/codegen/llvm/Builder.zig+626-534
......@@ -18,6 +18,7 @@ llvm: if (build_options.have_llvm) struct {
1818source_filename: String,
1919data_layout: String,
2020target_triple: String,
21module_asm: std.ArrayListUnmanaged(u8),
2122
2223string_map: std.AutoArrayHashMapUnmanaged(void, void),
2324string_indices: std.ArrayListUnmanaged(u32),
......@@ -95,18 +96,12 @@ pub const String = enum(u32) {
9596 assert(data.string != .none);
9697 const sentinel_slice = data.string.slice(data.builder) orelse
9798 return writer.print("{d}", .{@intFromEnum(data.string)});
98 const full_slice = sentinel_slice[0 .. sentinel_slice.len + comptime @intFromBool(
99 try printEscapedString(sentinel_slice[0 .. sentinel_slice.len + comptime @intFromBool(
99100 std.mem.indexOfScalar(u8, fmt_str, '@') != null,
100 )];
101 const need_quotes = (comptime std.mem.indexOfScalar(u8, fmt_str, '"') != null) or
102 !isValidIdentifier(full_slice);
103 if (need_quotes) try writer.writeByte('"');
104 for (full_slice) |character| switch (character) {
105 '\\' => try writer.writeAll("\\\\"),
106 ' '...'"' - 1, '"' + 1...'\\' - 1, '\\' + 1...'~' => try writer.writeByte(character),
107 else => try writer.print("\\{X:0>2}", .{character}),
108 };
109 if (need_quotes) try writer.writeByte('"');
101 )], if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_|
102 .always_quote
103 else
104 .quote_unless_valid_identifier, writer);
110105 }
111106 pub fn fmt(self: String, builder: *const Builder) std.fmt.Formatter(format) {
112107 return .{ .data = .{ .string = self, .builder = builder } };
......@@ -3812,7 +3807,7 @@ pub const WipFunction = struct {
38123807 @intFromEnum(addr_space),
38133808 instruction.llvmName(self),
38143809 );
3815 if (alignment.toByteUnits()) |a| llvm_instruction.setAlignment(@intCast(a));
3810 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
38163811 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
38173812 }
38183813 return instruction.toValue();
......@@ -3868,7 +3863,7 @@ pub const WipFunction = struct {
38683863 instruction.llvmName(self),
38693864 );
38703865 if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering)));
3871 if (alignment.toByteUnits()) |a| llvm_instruction.setAlignment(@intCast(a));
3866 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
38723867 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
38733868 }
38743869 return instruction.toValue();
......@@ -3922,7 +3917,7 @@ pub const WipFunction = struct {
39223917 .@"volatile" => llvm_instruction.setVolatile(.True),
39233918 }
39243919 if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering)));
3925 if (alignment.toByteUnits()) |a| llvm_instruction.setAlignment(@intCast(a));
3920 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
39263921 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
39273922 }
39283923 return instruction;
......@@ -6090,6 +6085,7 @@ pub fn init(options: Options) InitError!Builder {
60906085 .source_filename = .none,
60916086 .data_layout = .none,
60926087 .target_triple = .none,
6088 .module_asm = .{},
60936089
60946090 .string_map = .{},
60956091 .string_indices = .{},
......@@ -6207,6 +6203,8 @@ pub fn init(options: Options) InitError!Builder {
62076203}
62086204
62096205pub fn deinit(self: *Builder) void {
6206 self.module_asm.deinit(self.gpa);
6207
62106208 self.string_map.deinit(self.gpa);
62116209 self.string_indices.deinit(self.gpa);
62126210 self.string_bytes.deinit(self.gpa);
......@@ -6440,6 +6438,22 @@ pub fn initializeLLVMTarget(self: *const Builder, arch: std.Target.Cpu.Arch) voi
64406438 }
64416439}
64426440
6441pub fn setModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer {
6442 self.module_asm.clearRetainingCapacity();
6443 return self.appendModuleAsm();
6444}
6445
6446pub fn appendModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer {
6447 return self.module_asm.writer(self.gpa);
6448}
6449
6450pub fn finishModuleAsm(self: *Builder) Allocator.Error!void {
6451 if (self.module_asm.getLastOrNull()) |last| if (last != '\n')
6452 try self.module_asm.append(self.gpa, '\n');
6453 if (self.useLibLlvm())
6454 self.llvm.module.?.setModuleInlineAsm(self.module_asm.items.ptr, self.module_asm.items.len);
6455}
6456
64436457pub fn string(self: *Builder, bytes: []const u8) Allocator.Error!String {
64446458 try self.string_bytes.ensureUnusedCapacity(self.gpa, bytes.len + 1);
64456459 try self.string_indices.ensureUnusedCapacity(self.gpa, 1);
......@@ -7185,548 +7199,605 @@ pub fn printUnbuffered(
71857199 self: *Builder,
71867200 writer: anytype,
71877201) (@TypeOf(writer).Error || Allocator.Error)!void {
7188 if (self.source_filename != .none) try writer.print(
7189 \\; ModuleID = '{s}'
7190 \\source_filename = {"}
7191 \\
7192 , .{ self.source_filename.slice(self).?, self.source_filename.fmt(self) });
7193 if (self.data_layout != .none) try writer.print(
7194 \\target datalayout = {"}
7195 \\
7196 , .{self.data_layout.fmt(self)});
7197 if (self.target_triple != .none) try writer.print(
7198 \\target triple = {"}
7199 \\
7200 , .{self.target_triple.fmt(self)});
7201 try writer.writeByte('\n');
7202
7203 for (self.types.keys(), self.types.values()) |id, ty| try writer.print(
7204 \\%{} = type {}
7205 \\
7206 , .{ id.fmt(self), ty.fmt(self) });
7207 try writer.writeByte('\n');
7208
7209 for (self.variables.items) |variable| {
7210 if (variable.global.getReplacement(self) != .none) continue;
7211 const global = variable.global.ptrConst(self);
7212 try writer.print(
7213 \\{} ={}{}{}{}{}{}{}{} {s} {%}{ }{,}
7202 var need_newline = false;
7203
7204 if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) {
7205 if (need_newline) try writer.writeByte('\n');
7206 if (self.source_filename != .none) try writer.print(
7207 \\; ModuleID = '{s}'
7208 \\source_filename = {"}
72147209 \\
7215 , .{
7216 variable.global.fmt(self),
7217 global.linkage,
7218 global.preemption,
7219 global.visibility,
7220 global.dll_storage_class,
7221 variable.thread_local,
7222 global.unnamed_addr,
7223 global.addr_space,
7224 global.externally_initialized,
7225 @tagName(variable.mutability),
7226 global.type.fmt(self),
7227 variable.init.fmt(self),
7228 variable.alignment,
7229 });
7210 , .{ self.source_filename.slice(self).?, self.source_filename.fmt(self) });
7211 if (self.data_layout != .none) try writer.print(
7212 \\target datalayout = {"}
7213 \\
7214 , .{self.data_layout.fmt(self)});
7215 if (self.target_triple != .none) try writer.print(
7216 \\target triple = {"}
7217 \\
7218 , .{self.target_triple.fmt(self)});
7219 need_newline = true;
72307220 }
7231 try writer.writeByte('\n');
72327221
7233 var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{};
7234 defer attribute_groups.deinit(self.gpa);
7235 for (0.., self.functions.items) |function_i, function| {
7236 const function_index: Function.Index = @enumFromInt(function_i);
7237 if (function.global.getReplacement(self) != .none) continue;
7238 const global = function.global.ptrConst(self);
7239 const params_len = global.type.functionParameters(self).len;
7240 const function_attributes = function.attributes.func(self);
7241 if (function_attributes != .none) try writer.print(
7242 \\; Function Attrs:{}
7222 if (self.module_asm.items.len > 0) {
7223 if (need_newline) try writer.writeByte('\n');
7224 var line_it = std.mem.tokenizeScalar(u8, self.module_asm.items, '\n');
7225 while (line_it.next()) |line| {
7226 try writer.writeAll("module asm ");
7227 try printEscapedString(line, .always_quote, writer);
7228 try writer.writeByte('\n');
7229 }
7230 need_newline = true;
7231 }
7232
7233 if (self.types.count() > 0) {
7234 if (need_newline) try writer.writeByte('\n');
7235 for (self.types.keys(), self.types.values()) |id, ty| try writer.print(
7236 \\%{} = type {}
72437237 \\
7244 , .{function_attributes.fmt(self)});
7245 try writer.print(
7246 \\{s}{}{}{}{}{}{"} {} {}(
7247 , .{
7248 if (function.instructions.len > 0) "define" else "declare",
7249 global.linkage,
7250 global.preemption,
7251 global.visibility,
7252 global.dll_storage_class,
7253 function.call_conv,
7254 function.attributes.ret(self).fmt(self),
7255 global.type.functionReturn(self).fmt(self),
7256 function.global.fmt(self),
7257 });
7258 for (0..params_len) |arg| {
7259 if (arg > 0) try writer.writeAll(", ");
7238 , .{ id.fmt(self), ty.fmt(self) });
7239 need_newline = true;
7240 }
7241
7242 if (self.variables.items.len > 0) {
7243 if (need_newline) try writer.writeByte('\n');
7244 for (self.variables.items) |variable| {
7245 if (variable.global.getReplacement(self) != .none) continue;
7246 const global = variable.global.ptrConst(self);
72607247 try writer.print(
7261 \\{%}{"}
7248 \\{} ={}{}{}{}{}{}{}{} {s} {%}{ }{,}
7249 \\
72627250 , .{
7263 global.type.functionParameters(self)[arg].fmt(self),
7264 function.attributes.param(arg, self).fmt(self),
7251 variable.global.fmt(self),
7252 global.linkage,
7253 global.preemption,
7254 global.visibility,
7255 global.dll_storage_class,
7256 variable.thread_local,
7257 global.unnamed_addr,
7258 global.addr_space,
7259 global.externally_initialized,
7260 @tagName(variable.mutability),
7261 global.type.fmt(self),
7262 variable.init.fmt(self),
7263 variable.alignment,
72657264 });
7266 if (function.instructions.len > 0)
7267 try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)});
7268 }
7269 switch (global.type.functionKind(self)) {
7270 .normal => {},
7271 .vararg => {
7272 if (params_len > 0) try writer.writeAll(", ");
7273 try writer.writeAll("...");
7274 },
72757265 }
7276 try writer.print("){}{}", .{ global.unnamed_addr, global.addr_space });
7277 if (function_attributes != .none) try writer.print(" #{d}", .{
7278 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,
7279 });
7280 try writer.print("{}", .{function.alignment});
7281 if (function.instructions.len > 0) {
7282 var block_incoming_len: u32 = undefined;
7283 try writer.writeAll(" {\n");
7284 for (params_len..function.instructions.len) |instruction_i| {
7285 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);
7286 const instruction = function.instructions.get(@intFromEnum(instruction_index));
7287 switch (instruction.tag) {
7288 .add,
7289 .@"add nsw",
7290 .@"add nuw",
7291 .@"add nuw nsw",
7292 .@"and",
7293 .ashr,
7294 .@"ashr exact",
7295 .fadd,
7296 .@"fadd fast",
7297 .@"fcmp false",
7298 .@"fcmp fast false",
7299 .@"fcmp fast oeq",
7300 .@"fcmp fast oge",
7301 .@"fcmp fast ogt",
7302 .@"fcmp fast ole",
7303 .@"fcmp fast olt",
7304 .@"fcmp fast one",
7305 .@"fcmp fast ord",
7306 .@"fcmp fast true",
7307 .@"fcmp fast ueq",
7308 .@"fcmp fast uge",
7309 .@"fcmp fast ugt",
7310 .@"fcmp fast ule",
7311 .@"fcmp fast ult",
7312 .@"fcmp fast une",
7313 .@"fcmp fast uno",
7314 .@"fcmp oeq",
7315 .@"fcmp oge",
7316 .@"fcmp ogt",
7317 .@"fcmp ole",
7318 .@"fcmp olt",
7319 .@"fcmp one",
7320 .@"fcmp ord",
7321 .@"fcmp true",
7322 .@"fcmp ueq",
7323 .@"fcmp uge",
7324 .@"fcmp ugt",
7325 .@"fcmp ule",
7326 .@"fcmp ult",
7327 .@"fcmp une",
7328 .@"fcmp uno",
7329 .fdiv,
7330 .@"fdiv fast",
7331 .fmul,
7332 .@"fmul fast",
7333 .frem,
7334 .@"frem fast",
7335 .fsub,
7336 .@"fsub fast",
7337 .@"icmp eq",
7338 .@"icmp ne",
7339 .@"icmp sge",
7340 .@"icmp sgt",
7341 .@"icmp sle",
7342 .@"icmp slt",
7343 .@"icmp uge",
7344 .@"icmp ugt",
7345 .@"icmp ule",
7346 .@"icmp ult",
7347 .lshr,
7348 .@"lshr exact",
7349 .mul,
7350 .@"mul nsw",
7351 .@"mul nuw",
7352 .@"mul nuw nsw",
7353 .@"or",
7354 .sdiv,
7355 .@"sdiv exact",
7356 .srem,
7357 .shl,
7358 .@"shl nsw",
7359 .@"shl nuw",
7360 .@"shl nuw nsw",
7361 .sub,
7362 .@"sub nsw",
7363 .@"sub nuw",
7364 .@"sub nuw nsw",
7365 .udiv,
7366 .@"udiv exact",
7367 .urem,
7368 .xor,
7369 => |tag| {
7370 const extra = function.extraData(Function.Instruction.Binary, instruction.data);
7371 try writer.print(" %{} = {s} {%}, {}\n", .{
7372 instruction_index.name(&function).fmt(self),
7373 @tagName(tag),
7374 extra.lhs.fmt(function_index, self),
7375 extra.rhs.fmt(function_index, self),
7376 });
7377 },
7378 .addrspacecast,
7379 .bitcast,
7380 .fpext,
7381 .fptosi,
7382 .fptoui,
7383 .fptrunc,
7384 .inttoptr,
7385 .ptrtoint,
7386 .sext,
7387 .sitofp,
7388 .trunc,
7389 .uitofp,
7390 .zext,
7391 => |tag| {
7392 const extra = function.extraData(Function.Instruction.Cast, instruction.data);
7393 try writer.print(" %{} = {s} {%} to {%}\n", .{
7394 instruction_index.name(&function).fmt(self),
7395 @tagName(tag),
7396 extra.val.fmt(function_index, self),
7397 extra.type.fmt(self),
7398 });
7399 },
7400 .alloca,
7401 .@"alloca inalloca",
7402 => |tag| {
7403 const extra = function.extraData(Function.Instruction.Alloca, instruction.data);
7404 try writer.print(" %{} = {s} {%}{,%}{,}{,}\n", .{
7405 instruction_index.name(&function).fmt(self),
7406 @tagName(tag),
7407 extra.type.fmt(self),
7408 extra.len.fmt(function_index, self),
7409 extra.info.alignment,
7410 extra.info.addr_space,
7411 });
7412 },
7413 .arg => unreachable,
7414 .block => {
7415 block_incoming_len = instruction.data;
7416 const name = instruction_index.name(&function);
7417 if (@intFromEnum(instruction_index) > params_len) try writer.writeByte('\n');
7418 try writer.print("{}:\n", .{name.fmt(self)});
7419 },
7420 .br => |tag| {
7421 const target: Function.Block.Index = @enumFromInt(instruction.data);
7422 try writer.print(" {s} {%}\n", .{
7423 @tagName(tag), target.toInst(&function).fmt(function_index, self),
7424 });
7425 },
7426 .br_cond => {
7427 const extra = function.extraData(Function.Instruction.BrCond, instruction.data);
7428 try writer.print(" br {%}, {%}, {%}\n", .{
7429 extra.cond.fmt(function_index, self),
7430 extra.then.toInst(&function).fmt(function_index, self),
7431 extra.@"else".toInst(&function).fmt(function_index, self),
7432 });
7433 },
7434 .call,
7435 .@"call fast",
7436 .@"musttail call",
7437 .@"musttail call fast",
7438 .@"notail call",
7439 .@"notail call fast",
7440 .@"tail call",
7441 .@"tail call fast",
7442 => |tag| {
7443 var extra =
7444 function.extraDataTrail(Function.Instruction.Call, instruction.data);
7445 const args = extra.trail.next(extra.data.args_len, Value, &function);
7446 try writer.writeAll(" ");
7447 const ret_ty = extra.data.ty.functionReturn(self);
7448 switch (ret_ty) {
7449 .void => {},
7450 else => try writer.print("%{} = ", .{
7266 need_newline = true;
7267 }
7268
7269 var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{};
7270 defer attribute_groups.deinit(self.gpa);
7271
7272 if (self.functions.items.len > 0) {
7273 if (need_newline) try writer.writeByte('\n');
7274 for (0.., self.functions.items) |function_i, function| {
7275 if (function_i > 0) try writer.writeByte('\n');
7276 const function_index: Function.Index = @enumFromInt(function_i);
7277 if (function.global.getReplacement(self) != .none) continue;
7278 const global = function.global.ptrConst(self);
7279 const params_len = global.type.functionParameters(self).len;
7280 const function_attributes = function.attributes.func(self);
7281 if (function_attributes != .none) try writer.print(
7282 \\; Function Attrs:{}
7283 \\
7284 , .{function_attributes.fmt(self)});
7285 try writer.print(
7286 \\{s}{}{}{}{}{}{"} {} {}(
7287 , .{
7288 if (function.instructions.len > 0) "define" else "declare",
7289 global.linkage,
7290 global.preemption,
7291 global.visibility,
7292 global.dll_storage_class,
7293 function.call_conv,
7294 function.attributes.ret(self).fmt(self),
7295 global.type.functionReturn(self).fmt(self),
7296 function.global.fmt(self),
7297 });
7298 for (0..params_len) |arg| {
7299 if (arg > 0) try writer.writeAll(", ");
7300 try writer.print(
7301 \\{%}{"}
7302 , .{
7303 global.type.functionParameters(self)[arg].fmt(self),
7304 function.attributes.param(arg, self).fmt(self),
7305 });
7306 if (function.instructions.len > 0)
7307 try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)});
7308 }
7309 switch (global.type.functionKind(self)) {
7310 .normal => {},
7311 .vararg => {
7312 if (params_len > 0) try writer.writeAll(", ");
7313 try writer.writeAll("...");
7314 },
7315 }
7316 try writer.print("){}{}", .{ global.unnamed_addr, global.addr_space });
7317 if (function_attributes != .none) try writer.print(" #{d}", .{
7318 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,
7319 });
7320 try writer.print("{}", .{function.alignment});
7321 if (function.instructions.len > 0) {
7322 var block_incoming_len: u32 = undefined;
7323 try writer.writeAll(" {\n");
7324 for (params_len..function.instructions.len) |instruction_i| {
7325 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);
7326 const instruction = function.instructions.get(@intFromEnum(instruction_index));
7327 switch (instruction.tag) {
7328 .add,
7329 .@"add nsw",
7330 .@"add nuw",
7331 .@"add nuw nsw",
7332 .@"and",
7333 .ashr,
7334 .@"ashr exact",
7335 .fadd,
7336 .@"fadd fast",
7337 .@"fcmp false",
7338 .@"fcmp fast false",
7339 .@"fcmp fast oeq",
7340 .@"fcmp fast oge",
7341 .@"fcmp fast ogt",
7342 .@"fcmp fast ole",
7343 .@"fcmp fast olt",
7344 .@"fcmp fast one",
7345 .@"fcmp fast ord",
7346 .@"fcmp fast true",
7347 .@"fcmp fast ueq",
7348 .@"fcmp fast uge",
7349 .@"fcmp fast ugt",
7350 .@"fcmp fast ule",
7351 .@"fcmp fast ult",
7352 .@"fcmp fast une",
7353 .@"fcmp fast uno",
7354 .@"fcmp oeq",
7355 .@"fcmp oge",
7356 .@"fcmp ogt",
7357 .@"fcmp ole",
7358 .@"fcmp olt",
7359 .@"fcmp one",
7360 .@"fcmp ord",
7361 .@"fcmp true",
7362 .@"fcmp ueq",
7363 .@"fcmp uge",
7364 .@"fcmp ugt",
7365 .@"fcmp ule",
7366 .@"fcmp ult",
7367 .@"fcmp une",
7368 .@"fcmp uno",
7369 .fdiv,
7370 .@"fdiv fast",
7371 .fmul,
7372 .@"fmul fast",
7373 .frem,
7374 .@"frem fast",
7375 .fsub,
7376 .@"fsub fast",
7377 .@"icmp eq",
7378 .@"icmp ne",
7379 .@"icmp sge",
7380 .@"icmp sgt",
7381 .@"icmp sle",
7382 .@"icmp slt",
7383 .@"icmp uge",
7384 .@"icmp ugt",
7385 .@"icmp ule",
7386 .@"icmp ult",
7387 .lshr,
7388 .@"lshr exact",
7389 .mul,
7390 .@"mul nsw",
7391 .@"mul nuw",
7392 .@"mul nuw nsw",
7393 .@"or",
7394 .sdiv,
7395 .@"sdiv exact",
7396 .srem,
7397 .shl,
7398 .@"shl nsw",
7399 .@"shl nuw",
7400 .@"shl nuw nsw",
7401 .sub,
7402 .@"sub nsw",
7403 .@"sub nuw",
7404 .@"sub nuw nsw",
7405 .udiv,
7406 .@"udiv exact",
7407 .urem,
7408 .xor,
7409 => |tag| {
7410 const extra =
7411 function.extraData(Function.Instruction.Binary, instruction.data);
7412 try writer.print(" %{} = {s} {%}, {}\n", .{
74517413 instruction_index.name(&function).fmt(self),
7452 }),
7453 .none => unreachable,
7454 }
7455 try writer.print("{s}{}{}{} {%} {}(", .{
7456 @tagName(tag),
7457 extra.data.info.call_conv,
7458 extra.data.attributes.ret(self).fmt(self),
7459 extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self),
7460 switch (extra.data.ty.functionKind(self)) {
7461 .normal => ret_ty,
7462 .vararg => extra.data.ty,
7463 }.fmt(self),
7464 extra.data.callee.fmt(function_index, self),
7465 });
7466 for (0.., args) |arg_index, arg| {
7467 if (arg_index > 0) try writer.writeAll(", ");
7468 try writer.print("{%}{} {}", .{
7469 arg.typeOf(function_index, self).fmt(self),
7470 extra.data.attributes.param(arg_index, self).fmt(self),
7471 arg.fmt(function_index, self),
7414 @tagName(tag),
7415 extra.lhs.fmt(function_index, self),
7416 extra.rhs.fmt(function_index, self),
74727417 });
7473 }
7474 try writer.writeByte(')');
7475 const call_function_attributes = extra.data.attributes.func(self);
7476 if (call_function_attributes != .none) try writer.print(" #{d}", .{
7477 (try attribute_groups.getOrPutValue(
7478 self.gpa,
7479 call_function_attributes,
7480 {},
7481 )).index,
7482 });
7483 },
7484 .extractelement => |tag| {
7485 const extra =
7486 function.extraData(Function.Instruction.ExtractElement, instruction.data);
7487 try writer.print(" %{} = {s} {%}, {%}\n", .{
7488 instruction_index.name(&function).fmt(self),
7489 @tagName(tag),
7490 extra.val.fmt(function_index, self),
7491 extra.index.fmt(function_index, self),
7492 });
7493 },
7494 .extractvalue => |tag| {
7495 var extra =
7496 function.extraDataTrail(Function.Instruction.ExtractValue, instruction.data);
7497 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
7498 try writer.print(" %{} = {s} {%}", .{
7499 instruction_index.name(&function).fmt(self),
7500 @tagName(tag),
7501 extra.data.val.fmt(function_index, self),
7502 });
7503 for (indices) |index| try writer.print(", {d}", .{index});
7504 try writer.writeByte('\n');
7505 },
7506 .fence => |tag| {
7507 const info: MemoryAccessInfo = @bitCast(instruction.data);
7508 try writer.print(" {s}{}{}", .{ @tagName(tag), info.scope, info.ordering });
7509 },
7510 .fneg,
7511 .@"fneg fast",
7512 .ret,
7513 => |tag| {
7514 const val: Value = @enumFromInt(instruction.data);
7515 try writer.print(" {s} {%}\n", .{
7516 @tagName(tag),
7517 val.fmt(function_index, self),
7518 });
7519 },
7520 .getelementptr,
7521 .@"getelementptr inbounds",
7522 => |tag| {
7523 var extra = function.extraDataTrail(
7524 Function.Instruction.GetElementPtr,
7525 instruction.data,
7526 );
7527 const indices = extra.trail.next(extra.data.indices_len, Value, &function);
7528 try writer.print(" %{} = {s} {%}, {%}", .{
7529 instruction_index.name(&function).fmt(self),
7530 @tagName(tag),
7531 extra.data.type.fmt(self),
7532 extra.data.base.fmt(function_index, self),
7533 });
7534 for (indices) |index| try writer.print(", {%}", .{
7535 index.fmt(function_index, self),
7536 });
7537 try writer.writeByte('\n');
7538 },
7539 .insertelement => |tag| {
7540 const extra =
7541 function.extraData(Function.Instruction.InsertElement, instruction.data);
7542 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
7543 instruction_index.name(&function).fmt(self),
7544 @tagName(tag),
7545 extra.val.fmt(function_index, self),
7546 extra.elem.fmt(function_index, self),
7547 extra.index.fmt(function_index, self),
7548 });
7549 },
7550 .insertvalue => |tag| {
7551 var extra =
7552 function.extraDataTrail(Function.Instruction.InsertValue, instruction.data);
7553 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
7554 try writer.print(" %{} = {s} {%}, {%}", .{
7555 instruction_index.name(&function).fmt(self),
7556 @tagName(tag),
7557 extra.data.val.fmt(function_index, self),
7558 extra.data.elem.fmt(function_index, self),
7559 });
7560 for (indices) |index| try writer.print(", {d}", .{index});
7561 try writer.writeByte('\n');
7562 },
7563 .@"llvm.maxnum.",
7564 .@"llvm.minnum.",
7565 .@"llvm.sadd.sat.",
7566 .@"llvm.smax.",
7567 .@"llvm.smin.",
7568 .@"llvm.smul.fix.sat.",
7569 .@"llvm.sshl.sat.",
7570 .@"llvm.ssub.sat.",
7571 .@"llvm.uadd.sat.",
7572 .@"llvm.umax.",
7573 .@"llvm.umin.",
7574 .@"llvm.umul.fix.sat.",
7575 .@"llvm.ushl.sat.",
7576 .@"llvm.usub.sat.",
7577 => |tag| {
7578 const extra = function.extraData(Function.Instruction.Binary, instruction.data);
7579 const ty = instruction_index.typeOf(function_index, self);
7580 try writer.print(" %{} = call {%} @{s}{m}({%}, {%}{s})\n", .{
7581 instruction_index.name(&function).fmt(self),
7582 ty.fmt(self),
7583 @tagName(tag),
7584 ty.fmt(self),
7585 extra.lhs.fmt(function_index, self),
7586 extra.rhs.fmt(function_index, self),
7587 switch (tag) {
7588 .@"llvm.smul.fix.sat.",
7589 .@"llvm.umul.fix.sat.",
7590 => ", i32 0",
7591 else => "",
7592 },
7593 });
7594 },
7595 .load,
7596 .@"load atomic",
7597 .@"load atomic volatile",
7598 .@"load volatile",
7599 => |tag| {
7600 const extra = function.extraData(Function.Instruction.Load, instruction.data);
7601 try writer.print(" %{} = {s} {%}, {%}{}{}{,}\n", .{
7602 instruction_index.name(&function).fmt(self),
7603 @tagName(tag),
7604 extra.type.fmt(self),
7605 extra.ptr.fmt(function_index, self),
7606 extra.info.scope,
7607 extra.info.ordering,
7608 extra.info.alignment,
7609 });
7610 },
7611 .phi,
7612 .@"phi fast",
7613 => |tag| {
7614 var extra = function.extraDataTrail(Function.Instruction.Phi, instruction.data);
7615 const vals = extra.trail.next(block_incoming_len, Value, &function);
7616 const blocks =
7617 extra.trail.next(block_incoming_len, Function.Block.Index, &function);
7618 try writer.print(" %{} = {s} {%} ", .{
7619 instruction_index.name(&function).fmt(self),
7620 @tagName(tag),
7621 vals[0].typeOf(function_index, self).fmt(self),
7622 });
7623 for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| {
7624 if (incoming_index > 0) try writer.writeAll(", ");
7625 try writer.print("[ {}, {} ]", .{
7626 incoming_val.fmt(function_index, self),
7627 incoming_block.toInst(&function).fmt(function_index, self),
7418 },
7419 .addrspacecast,
7420 .bitcast,
7421 .fpext,
7422 .fptosi,
7423 .fptoui,
7424 .fptrunc,
7425 .inttoptr,
7426 .ptrtoint,
7427 .sext,
7428 .sitofp,
7429 .trunc,
7430 .uitofp,
7431 .zext,
7432 => |tag| {
7433 const extra =
7434 function.extraData(Function.Instruction.Cast, instruction.data);
7435 try writer.print(" %{} = {s} {%} to {%}\n", .{
7436 instruction_index.name(&function).fmt(self),
7437 @tagName(tag),
7438 extra.val.fmt(function_index, self),
7439 extra.type.fmt(self),
76287440 });
7629 }
7630 try writer.writeByte('\n');
7631 },
7632 .@"ret void",
7633 .@"unreachable",
7634 => |tag| try writer.print(" {s}\n", .{@tagName(tag)}),
7635 .select,
7636 .@"select fast",
7637 => |tag| {
7638 const extra = function.extraData(Function.Instruction.Select, instruction.data);
7639 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
7640 instruction_index.name(&function).fmt(self),
7641 @tagName(tag),
7642 extra.cond.fmt(function_index, self),
7643 extra.lhs.fmt(function_index, self),
7644 extra.rhs.fmt(function_index, self),
7645 });
7646 },
7647 .shufflevector => |tag| {
7648 const extra =
7649 function.extraData(Function.Instruction.ShuffleVector, instruction.data);
7650 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
7651 instruction_index.name(&function).fmt(self),
7652 @tagName(tag),
7653 extra.lhs.fmt(function_index, self),
7654 extra.rhs.fmt(function_index, self),
7655 extra.mask.fmt(function_index, self),
7656 });
7657 },
7658 .store,
7659 .@"store atomic",
7660 .@"store atomic volatile",
7661 .@"store volatile",
7662 => |tag| {
7663 const extra = function.extraData(Function.Instruction.Store, instruction.data);
7664 try writer.print(" {s} {%}, {%}{}{}{,}\n", .{
7665 @tagName(tag),
7666 extra.val.fmt(function_index, self),
7667 extra.ptr.fmt(function_index, self),
7668 extra.info.scope,
7669 extra.info.ordering,
7670 extra.info.alignment,
7671 });
7672 },
7673 .@"switch" => |tag| {
7674 var extra =
7675 function.extraDataTrail(Function.Instruction.Switch, instruction.data);
7676 const vals = extra.trail.next(extra.data.cases_len, Constant, &function);
7677 const blocks =
7678 extra.trail.next(extra.data.cases_len, Function.Block.Index, &function);
7679 try writer.print(" {s} {%}, {%} [\n", .{
7680 @tagName(tag),
7681 extra.data.val.fmt(function_index, self),
7682 extra.data.default.toInst(&function).fmt(function_index, self),
7683 });
7684 for (vals, blocks) |case_val, case_block| try writer.print(" {%}, {%}\n", .{
7685 case_val.fmt(self),
7686 case_block.toInst(&function).fmt(function_index, self),
7687 });
7688 try writer.writeAll(" ]\n");
7689 },
7690 .unimplemented => |tag| {
7691 const ty: Type = @enumFromInt(instruction.data);
7692 if (true) {
7441 },
7442 .alloca,
7443 .@"alloca inalloca",
7444 => |tag| {
7445 const extra =
7446 function.extraData(Function.Instruction.Alloca, instruction.data);
7447 try writer.print(" %{} = {s} {%}{,%}{,}{,}\n", .{
7448 instruction_index.name(&function).fmt(self),
7449 @tagName(tag),
7450 extra.type.fmt(self),
7451 extra.len.fmt(function_index, self),
7452 extra.info.alignment,
7453 extra.info.addr_space,
7454 });
7455 },
7456 .arg => unreachable,
7457 .block => {
7458 block_incoming_len = instruction.data;
7459 const name = instruction_index.name(&function);
7460 if (@intFromEnum(instruction_index) > params_len)
7461 try writer.writeByte('\n');
7462 try writer.print("{}:\n", .{name.fmt(self)});
7463 },
7464 .br => |tag| {
7465 const target: Function.Block.Index = @enumFromInt(instruction.data);
7466 try writer.print(" {s} {%}\n", .{
7467 @tagName(tag), target.toInst(&function).fmt(function_index, self),
7468 });
7469 },
7470 .br_cond => {
7471 const extra =
7472 function.extraData(Function.Instruction.BrCond, instruction.data);
7473 try writer.print(" br {%}, {%}, {%}\n", .{
7474 extra.cond.fmt(function_index, self),
7475 extra.then.toInst(&function).fmt(function_index, self),
7476 extra.@"else".toInst(&function).fmt(function_index, self),
7477 });
7478 },
7479 .call,
7480 .@"call fast",
7481 .@"musttail call",
7482 .@"musttail call fast",
7483 .@"notail call",
7484 .@"notail call fast",
7485 .@"tail call",
7486 .@"tail call fast",
7487 => |tag| {
7488 var extra =
7489 function.extraDataTrail(Function.Instruction.Call, instruction.data);
7490 const args = extra.trail.next(extra.data.args_len, Value, &function);
76937491 try writer.writeAll(" ");
7694 switch (ty) {
7695 .none, .void => {},
7492 const ret_ty = extra.data.ty.functionReturn(self);
7493 switch (ret_ty) {
7494 .void => {},
76967495 else => try writer.print("%{} = ", .{
76977496 instruction_index.name(&function).fmt(self),
76987497 }),
7498 .none => unreachable,
7499 }
7500 try writer.print("{s}{}{}{} {%} {}(", .{
7501 @tagName(tag),
7502 extra.data.info.call_conv,
7503 extra.data.attributes.ret(self).fmt(self),
7504 extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self),
7505 switch (extra.data.ty.functionKind(self)) {
7506 .normal => ret_ty,
7507 .vararg => extra.data.ty,
7508 }.fmt(self),
7509 extra.data.callee.fmt(function_index, self),
7510 });
7511 for (0.., args) |arg_index, arg| {
7512 if (arg_index > 0) try writer.writeAll(", ");
7513 try writer.print("{%}{} {}", .{
7514 arg.typeOf(function_index, self).fmt(self),
7515 extra.data.attributes.param(arg_index, self).fmt(self),
7516 arg.fmt(function_index, self),
7517 });
76997518 }
7700 try writer.print("{s} {%}\n", .{ @tagName(tag), ty.fmt(self) });
7701 } else switch (ty) {
7702 .none, .void => {},
7703 else => try writer.print(" %{} = load {%}, ptr undef\n", .{
7519 try writer.writeByte(')');
7520 const call_function_attributes = extra.data.attributes.func(self);
7521 if (call_function_attributes != .none) try writer.print(" #{d}", .{
7522 (try attribute_groups.getOrPutValue(
7523 self.gpa,
7524 call_function_attributes,
7525 {},
7526 )).index,
7527 });
7528 try writer.writeByte('\n');
7529 },
7530 .extractelement => |tag| {
7531 const extra = function.extraData(
7532 Function.Instruction.ExtractElement,
7533 instruction.data,
7534 );
7535 try writer.print(" %{} = {s} {%}, {%}\n", .{
7536 instruction_index.name(&function).fmt(self),
7537 @tagName(tag),
7538 extra.val.fmt(function_index, self),
7539 extra.index.fmt(function_index, self),
7540 });
7541 },
7542 .extractvalue => |tag| {
7543 var extra = function.extraDataTrail(
7544 Function.Instruction.ExtractValue,
7545 instruction.data,
7546 );
7547 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
7548 try writer.print(" %{} = {s} {%}", .{
7549 instruction_index.name(&function).fmt(self),
7550 @tagName(tag),
7551 extra.data.val.fmt(function_index, self),
7552 });
7553 for (indices) |index| try writer.print(", {d}", .{index});
7554 try writer.writeByte('\n');
7555 },
7556 .fence => |tag| {
7557 const info: MemoryAccessInfo = @bitCast(instruction.data);
7558 try writer.print(" {s}{}{}", .{ @tagName(tag), info.scope, info.ordering });
7559 },
7560 .fneg,
7561 .@"fneg fast",
7562 .ret,
7563 => |tag| {
7564 const val: Value = @enumFromInt(instruction.data);
7565 try writer.print(" {s} {%}\n", .{
7566 @tagName(tag),
7567 val.fmt(function_index, self),
7568 });
7569 },
7570 .getelementptr,
7571 .@"getelementptr inbounds",
7572 => |tag| {
7573 var extra = function.extraDataTrail(
7574 Function.Instruction.GetElementPtr,
7575 instruction.data,
7576 );
7577 const indices = extra.trail.next(extra.data.indices_len, Value, &function);
7578 try writer.print(" %{} = {s} {%}, {%}", .{
7579 instruction_index.name(&function).fmt(self),
7580 @tagName(tag),
7581 extra.data.type.fmt(self),
7582 extra.data.base.fmt(function_index, self),
7583 });
7584 for (indices) |index| try writer.print(", {%}", .{
7585 index.fmt(function_index, self),
7586 });
7587 try writer.writeByte('\n');
7588 },
7589 .insertelement => |tag| {
7590 const extra = function.extraData(
7591 Function.Instruction.InsertElement,
7592 instruction.data,
7593 );
7594 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
7595 instruction_index.name(&function).fmt(self),
7596 @tagName(tag),
7597 extra.val.fmt(function_index, self),
7598 extra.elem.fmt(function_index, self),
7599 extra.index.fmt(function_index, self),
7600 });
7601 },
7602 .insertvalue => |tag| {
7603 var extra = function.extraDataTrail(
7604 Function.Instruction.InsertValue,
7605 instruction.data,
7606 );
7607 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
7608 try writer.print(" %{} = {s} {%}, {%}", .{
7609 instruction_index.name(&function).fmt(self),
7610 @tagName(tag),
7611 extra.data.val.fmt(function_index, self),
7612 extra.data.elem.fmt(function_index, self),
7613 });
7614 for (indices) |index| try writer.print(", {d}", .{index});
7615 try writer.writeByte('\n');
7616 },
7617 .@"llvm.maxnum.",
7618 .@"llvm.minnum.",
7619 .@"llvm.sadd.sat.",
7620 .@"llvm.smax.",
7621 .@"llvm.smin.",
7622 .@"llvm.smul.fix.sat.",
7623 .@"llvm.sshl.sat.",
7624 .@"llvm.ssub.sat.",
7625 .@"llvm.uadd.sat.",
7626 .@"llvm.umax.",
7627 .@"llvm.umin.",
7628 .@"llvm.umul.fix.sat.",
7629 .@"llvm.ushl.sat.",
7630 .@"llvm.usub.sat.",
7631 => |tag| {
7632 const extra =
7633 function.extraData(Function.Instruction.Binary, instruction.data);
7634 const ty = instruction_index.typeOf(function_index, self);
7635 try writer.print(" %{} = call {%} @{s}{m}({%}, {%}{s})\n", .{
77047636 instruction_index.name(&function).fmt(self),
77057637 ty.fmt(self),
7706 }),
7707 }
7708 },
7709 .va_arg => |tag| {
7710 const extra = function.extraData(Function.Instruction.VaArg, instruction.data);
7711 try writer.print(" %{} = {s} {%}, {%}\n", .{
7712 instruction_index.name(&function).fmt(self),
7713 @tagName(tag),
7714 extra.list.fmt(function_index, self),
7715 extra.type.fmt(self),
7716 });
7717 },
7638 @tagName(tag),
7639 ty.fmt(self),
7640 extra.lhs.fmt(function_index, self),
7641 extra.rhs.fmt(function_index, self),
7642 switch (tag) {
7643 .@"llvm.smul.fix.sat.",
7644 .@"llvm.umul.fix.sat.",
7645 => ", i32 0",
7646 else => "",
7647 },
7648 });
7649 },
7650 .load,
7651 .@"load atomic",
7652 .@"load atomic volatile",
7653 .@"load volatile",
7654 => |tag| {
7655 const extra =
7656 function.extraData(Function.Instruction.Load, instruction.data);
7657 try writer.print(" %{} = {s} {%}, {%}{}{}{,}\n", .{
7658 instruction_index.name(&function).fmt(self),
7659 @tagName(tag),
7660 extra.type.fmt(self),
7661 extra.ptr.fmt(function_index, self),
7662 extra.info.scope,
7663 extra.info.ordering,
7664 extra.info.alignment,
7665 });
7666 },
7667 .phi,
7668 .@"phi fast",
7669 => |tag| {
7670 var extra =
7671 function.extraDataTrail(Function.Instruction.Phi, instruction.data);
7672 const vals = extra.trail.next(block_incoming_len, Value, &function);
7673 const blocks =
7674 extra.trail.next(block_incoming_len, Function.Block.Index, &function);
7675 try writer.print(" %{} = {s} {%} ", .{
7676 instruction_index.name(&function).fmt(self),
7677 @tagName(tag),
7678 vals[0].typeOf(function_index, self).fmt(self),
7679 });
7680 for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| {
7681 if (incoming_index > 0) try writer.writeAll(", ");
7682 try writer.print("[ {}, {} ]", .{
7683 incoming_val.fmt(function_index, self),
7684 incoming_block.toInst(&function).fmt(function_index, self),
7685 });
7686 }
7687 try writer.writeByte('\n');
7688 },
7689 .@"ret void",
7690 .@"unreachable",
7691 => |tag| try writer.print(" {s}\n", .{@tagName(tag)}),
7692 .select,
7693 .@"select fast",
7694 => |tag| {
7695 const extra =
7696 function.extraData(Function.Instruction.Select, instruction.data);
7697 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
7698 instruction_index.name(&function).fmt(self),
7699 @tagName(tag),
7700 extra.cond.fmt(function_index, self),
7701 extra.lhs.fmt(function_index, self),
7702 extra.rhs.fmt(function_index, self),
7703 });
7704 },
7705 .shufflevector => |tag| {
7706 const extra = function.extraData(
7707 Function.Instruction.ShuffleVector,
7708 instruction.data,
7709 );
7710 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
7711 instruction_index.name(&function).fmt(self),
7712 @tagName(tag),
7713 extra.lhs.fmt(function_index, self),
7714 extra.rhs.fmt(function_index, self),
7715 extra.mask.fmt(function_index, self),
7716 });
7717 },
7718 .store,
7719 .@"store atomic",
7720 .@"store atomic volatile",
7721 .@"store volatile",
7722 => |tag| {
7723 const extra =
7724 function.extraData(Function.Instruction.Store, instruction.data);
7725 try writer.print(" {s} {%}, {%}{}{}{,}\n", .{
7726 @tagName(tag),
7727 extra.val.fmt(function_index, self),
7728 extra.ptr.fmt(function_index, self),
7729 extra.info.scope,
7730 extra.info.ordering,
7731 extra.info.alignment,
7732 });
7733 },
7734 .@"switch" => |tag| {
7735 var extra =
7736 function.extraDataTrail(Function.Instruction.Switch, instruction.data);
7737 const vals = extra.trail.next(extra.data.cases_len, Constant, &function);
7738 const blocks =
7739 extra.trail.next(extra.data.cases_len, Function.Block.Index, &function);
7740 try writer.print(" {s} {%}, {%} [\n", .{
7741 @tagName(tag),
7742 extra.data.val.fmt(function_index, self),
7743 extra.data.default.toInst(&function).fmt(function_index, self),
7744 });
7745 for (vals, blocks) |case_val, case_block| try writer.print(
7746 " {%}, {%}\n",
7747 .{
7748 case_val.fmt(self),
7749 case_block.toInst(&function).fmt(function_index, self),
7750 },
7751 );
7752 try writer.writeAll(" ]\n");
7753 },
7754 .unimplemented => |tag| {
7755 const ty: Type = @enumFromInt(instruction.data);
7756 if (true) {
7757 try writer.writeAll(" ");
7758 switch (ty) {
7759 .none, .void => {},
7760 else => try writer.print("%{} = ", .{
7761 instruction_index.name(&function).fmt(self),
7762 }),
7763 }
7764 try writer.print("{s} {%}\n", .{ @tagName(tag), ty.fmt(self) });
7765 } else switch (ty) {
7766 .none, .void => {},
7767 else => try writer.print(" %{} = load {%}, ptr undef\n", .{
7768 instruction_index.name(&function).fmt(self),
7769 ty.fmt(self),
7770 }),
7771 }
7772 },
7773 .va_arg => |tag| {
7774 const extra =
7775 function.extraData(Function.Instruction.VaArg, instruction.data);
7776 try writer.print(" %{} = {s} {%}, {%}\n", .{
7777 instruction_index.name(&function).fmt(self),
7778 @tagName(tag),
7779 extra.list.fmt(function_index, self),
7780 extra.type.fmt(self),
7781 });
7782 },
7783 }
77187784 }
7785 try writer.writeByte('}');
77197786 }
7720 try writer.writeByte('}');
7787 try writer.writeByte('\n');
77217788 }
7722 try writer.writeAll("\n\n");
7789 need_newline = true;
77237790 }
77247791
7725 for (0.., attribute_groups.keys()) |attribute_group_index, attribute_group|
7726 try writer.print(
7727 \\attributes #{d} = {{{#"} }}
7728 \\
7729 , .{ attribute_group_index, attribute_group.fmt(self) });
7792 if (attribute_groups.count() > 0) {
7793 if (need_newline) try writer.writeByte('\n') else need_newline = true;
7794 for (0.., attribute_groups.keys()) |attribute_group_index, attribute_group|
7795 try writer.print(
7796 \\attributes #{d} = {{{#"} }}
7797 \\
7798 , .{ attribute_group_index, attribute_group.fmt(self) });
7799 need_newline = true;
7800 }
77307801}
77317802
77327803pub inline fn useLibLlvm(self: *const Builder) bool {
......@@ -7736,7 +7807,7 @@ pub inline fn useLibLlvm(self: *const Builder) bool {
77367807const NoExtra = struct {};
77377808
77387809fn isValidIdentifier(id: []const u8) bool {
7739 for (id, 0..) |character, index| switch (character) {
7810 for (id, 0..) |byte, index| switch (byte) {
77407811 '$', '-', '.', 'A'...'Z', '_', 'a'...'z' => {},
77417812 '0'...'9' => if (index == 0) return false,
77427813 else => return false,
......@@ -7744,6 +7815,25 @@ fn isValidIdentifier(id: []const u8) bool {
77447815 return true;
77457816}
77467817
7818const QuoteBehavior = enum { always_quote, quote_unless_valid_identifier };
7819fn printEscapedString(
7820 slice: []const u8,
7821 quotes: QuoteBehavior,
7822 writer: anytype,
7823) @TypeOf(writer).Error!void {
7824 const need_quotes = switch (quotes) {
7825 .always_quote => true,
7826 .quote_unless_valid_identifier => !isValidIdentifier(slice),
7827 };
7828 if (need_quotes) try writer.writeByte('"');
7829 for (slice) |byte| switch (byte) {
7830 '\\' => try writer.writeAll("\\\\"),
7831 ' '...'"' - 1, '"' + 1...'\\' - 1, '\\' + 1...'~' => try writer.writeByte(byte),
7832 else => try writer.print("\\{X:0>2}", .{byte}),
7833 };
7834 if (need_quotes) try writer.writeByte('"');
7835}
7836
77477837fn ensureUnusedGlobalCapacity(self: *Builder, name: String) Allocator.Error!void {
77487838 if (self.useLibLlvm()) try self.llvm.globals.ensureUnusedCapacity(self.gpa, 1);
77497839 try self.string_map.ensureUnusedCapacity(self.gpa, 1);
......@@ -9318,6 +9408,8 @@ fn asmConstAssumeCapacity(
93189408 assembly: String,
93199409 constraints: String,
93209410) Constant {
9411 assert(ty.functionKind(self) == .normal);
9412
93219413 const Key = struct { tag: Constant.Tag, extra: Constant.Asm };
93229414 const Adapter = struct {
93239415 builder: *const Builder,
src/codegen/llvm/bindings.zig+1-1
......@@ -540,7 +540,7 @@ pub const Module = opaque {
540540 pub const createDIBuilder = ZigLLVMCreateDIBuilder;
541541 extern fn ZigLLVMCreateDIBuilder(module: *Module, allow_unresolved: bool) *DIBuilder;
542542
543 pub const setModuleInlineAsm2 = LLVMSetModuleInlineAsm2;
543 pub const setModuleInlineAsm = LLVMSetModuleInlineAsm2;
544544 extern fn LLVMSetModuleInlineAsm2(M: *Module, Asm: [*]const u8, Len: usize) void;
545545
546546 pub const printModuleToFile = LLVMPrintModuleToFile;