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 {...@@ -1034,15 +1034,11 @@ pub const Object = struct {
10341034
1035 fn genModuleLevelAssembly(object: *Object) !void {1035 fn genModuleLevelAssembly(object: *Object) !void {
1036 const mod = object.module;1036 const mod = object.module;
1037 if (mod.global_assembly.count() == 0) return;1037
1038 var buffer = std.ArrayList(u8).init(mod.gpa);1038 const writer = object.builder.setModuleAsm();
1039 defer buffer.deinit();1039 var it = mod.global_assembly.valueIterator();
1040 var it = mod.global_assembly.iterator();1040 while (it.next()) |assembly| try writer.print("{s}\n", .{assembly.*});
1041 while (it.next()) |kv| {1041 try object.builder.finishModuleAsm();
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);
1046 }1042 }
10471043
1048 fn resolveExportExternCollisions(object: *Object) !void {1044 fn resolveExportExternCollisions(object: *Object) !void {
src/codegen/llvm/Builder.zig+626-534
...@@ -18,6 +18,7 @@ llvm: if (build_options.have_llvm) struct {...@@ -18,6 +18,7 @@ llvm: if (build_options.have_llvm) struct {
18source_filename: String,18source_filename: String,
19data_layout: String,19data_layout: String,
20target_triple: String,20target_triple: String,
21module_asm: std.ArrayListUnmanaged(u8),
2122
22string_map: std.AutoArrayHashMapUnmanaged(void, void),23string_map: std.AutoArrayHashMapUnmanaged(void, void),
23string_indices: std.ArrayListUnmanaged(u32),24string_indices: std.ArrayListUnmanaged(u32),
...@@ -95,18 +96,12 @@ pub const String = enum(u32) {...@@ -95,18 +96,12 @@ pub const String = enum(u32) {
95 assert(data.string != .none);96 assert(data.string != .none);
96 const sentinel_slice = data.string.slice(data.builder) orelse97 const sentinel_slice = data.string.slice(data.builder) orelse
97 return writer.print("{d}", .{@intFromEnum(data.string)});98 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(
99 std.mem.indexOfScalar(u8, fmt_str, '@') != null,100 std.mem.indexOfScalar(u8, fmt_str, '@') != null,
100 )];101 )], if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_|
101 const need_quotes = (comptime std.mem.indexOfScalar(u8, fmt_str, '"') != null) or102 .always_quote
102 !isValidIdentifier(full_slice);103 else
103 if (need_quotes) try writer.writeByte('"');104 .quote_unless_valid_identifier, writer);
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('"');
110 }105 }
111 pub fn fmt(self: String, builder: *const Builder) std.fmt.Formatter(format) {106 pub fn fmt(self: String, builder: *const Builder) std.fmt.Formatter(format) {
112 return .{ .data = .{ .string = self, .builder = builder } };107 return .{ .data = .{ .string = self, .builder = builder } };
...@@ -3812,7 +3807,7 @@ pub const WipFunction = struct {...@@ -3812,7 +3807,7 @@ pub const WipFunction = struct {
3812 @intFromEnum(addr_space),3807 @intFromEnum(addr_space),
3813 instruction.llvmName(self),3808 instruction.llvmName(self),
3814 );3809 );
3815 if (alignment.toByteUnits()) |a| llvm_instruction.setAlignment(@intCast(a));3810 if (alignment.toByteUnits()) |bytes| llvm_instruction.setAlignment(@intCast(bytes));
3816 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);3811 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
3817 }3812 }
3818 return instruction.toValue();3813 return instruction.toValue();
...@@ -3868,7 +3863,7 @@ pub const WipFunction = struct {...@@ -3868,7 +3863,7 @@ pub const WipFunction = struct {
3868 instruction.llvmName(self),3863 instruction.llvmName(self),
3869 );3864 );
3870 if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering)));3865 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));
3872 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);3867 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
3873 }3868 }
3874 return instruction.toValue();3869 return instruction.toValue();
...@@ -3922,7 +3917,7 @@ pub const WipFunction = struct {...@@ -3922,7 +3917,7 @@ pub const WipFunction = struct {
3922 .@"volatile" => llvm_instruction.setVolatile(.True),3917 .@"volatile" => llvm_instruction.setVolatile(.True),
3923 }3918 }
3924 if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering)));3919 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));
3926 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);3921 self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
3927 }3922 }
3928 return instruction;3923 return instruction;
...@@ -6090,6 +6085,7 @@ pub fn init(options: Options) InitError!Builder {...@@ -6090,6 +6085,7 @@ pub fn init(options: Options) InitError!Builder {
6090 .source_filename = .none,6085 .source_filename = .none,
6091 .data_layout = .none,6086 .data_layout = .none,
6092 .target_triple = .none,6087 .target_triple = .none,
6088 .module_asm = .{},
60936089
6094 .string_map = .{},6090 .string_map = .{},
6095 .string_indices = .{},6091 .string_indices = .{},
...@@ -6207,6 +6203,8 @@ pub fn init(options: Options) InitError!Builder {...@@ -6207,6 +6203,8 @@ pub fn init(options: Options) InitError!Builder {
6207}6203}
62086204
6209pub fn deinit(self: *Builder) void {6205pub fn deinit(self: *Builder) void {
6206 self.module_asm.deinit(self.gpa);
6207
6210 self.string_map.deinit(self.gpa);6208 self.string_map.deinit(self.gpa);
6211 self.string_indices.deinit(self.gpa);6209 self.string_indices.deinit(self.gpa);
6212 self.string_bytes.deinit(self.gpa);6210 self.string_bytes.deinit(self.gpa);
...@@ -6440,6 +6438,22 @@ pub fn initializeLLVMTarget(self: *const Builder, arch: std.Target.Cpu.Arch) voi...@@ -6440,6 +6438,22 @@ pub fn initializeLLVMTarget(self: *const Builder, arch: std.Target.Cpu.Arch) voi
6440 }6438 }
6441}6439}
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
6443pub fn string(self: *Builder, bytes: []const u8) Allocator.Error!String {6457pub fn string(self: *Builder, bytes: []const u8) Allocator.Error!String {
6444 try self.string_bytes.ensureUnusedCapacity(self.gpa, bytes.len + 1);6458 try self.string_bytes.ensureUnusedCapacity(self.gpa, bytes.len + 1);
6445 try self.string_indices.ensureUnusedCapacity(self.gpa, 1);6459 try self.string_indices.ensureUnusedCapacity(self.gpa, 1);
...@@ -7185,548 +7199,605 @@ pub fn printUnbuffered(...@@ -7185,548 +7199,605 @@ pub fn printUnbuffered(
7185 self: *Builder,7199 self: *Builder,
7186 writer: anytype,7200 writer: anytype,
7187) (@TypeOf(writer).Error || Allocator.Error)!void {7201) (@TypeOf(writer).Error || Allocator.Error)!void {
7188 if (self.source_filename != .none) try writer.print(7202 var need_newline = false;
7189 \\; ModuleID = '{s}'7203
7190 \\source_filename = {"}7204 if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) {
7191 \\7205 if (need_newline) try writer.writeByte('\n');
7192 , .{ self.source_filename.slice(self).?, self.source_filename.fmt(self) });7206 if (self.source_filename != .none) try writer.print(
7193 if (self.data_layout != .none) try writer.print(7207 \\; ModuleID = '{s}'
7194 \\target datalayout = {"}7208 \\source_filename = {"}
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} {%}{ }{,}
7214 \\7209 \\
7215 , .{7210 , .{ self.source_filename.slice(self).?, self.source_filename.fmt(self) });
7216 variable.global.fmt(self),7211 if (self.data_layout != .none) try writer.print(
7217 global.linkage,7212 \\target datalayout = {"}
7218 global.preemption,7213 \\
7219 global.visibility,7214 , .{self.data_layout.fmt(self)});
7220 global.dll_storage_class,7215 if (self.target_triple != .none) try writer.print(
7221 variable.thread_local,7216 \\target triple = {"}
7222 global.unnamed_addr,7217 \\
7223 global.addr_space,7218 , .{self.target_triple.fmt(self)});
7224 global.externally_initialized,7219 need_newline = true;
7225 @tagName(variable.mutability),
7226 global.type.fmt(self),
7227 variable.init.fmt(self),
7228 variable.alignment,
7229 });
7230 }7220 }
7231 try writer.writeByte('\n');
72327221
7233 var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{};7222 if (self.module_asm.items.len > 0) {
7234 defer attribute_groups.deinit(self.gpa);7223 if (need_newline) try writer.writeByte('\n');
7235 for (0.., self.functions.items) |function_i, function| {7224 var line_it = std.mem.tokenizeScalar(u8, self.module_asm.items, '\n');
7236 const function_index: Function.Index = @enumFromInt(function_i);7225 while (line_it.next()) |line| {
7237 if (function.global.getReplacement(self) != .none) continue;7226 try writer.writeAll("module asm ");
7238 const global = function.global.ptrConst(self);7227 try printEscapedString(line, .always_quote, writer);
7239 const params_len = global.type.functionParameters(self).len;7228 try writer.writeByte('\n');
7240 const function_attributes = function.attributes.func(self);7229 }
7241 if (function_attributes != .none) try writer.print(7230 need_newline = true;
7242 \\; Function Attrs:{}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 {}
7243 \\7237 \\
7244 , .{function_attributes.fmt(self)});7238 , .{ id.fmt(self), ty.fmt(self) });
7245 try writer.print(7239 need_newline = true;
7246 \\{s}{}{}{}{}{}{"} {} {}(7240 }
7247 , .{7241
7248 if (function.instructions.len > 0) "define" else "declare",7242 if (self.variables.items.len > 0) {
7249 global.linkage,7243 if (need_newline) try writer.writeByte('\n');
7250 global.preemption,7244 for (self.variables.items) |variable| {
7251 global.visibility,7245 if (variable.global.getReplacement(self) != .none) continue;
7252 global.dll_storage_class,7246 const global = variable.global.ptrConst(self);
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(", ");
7260 try writer.print(7247 try writer.print(
7261 \\{%}{"}7248 \\{} ={}{}{}{}{}{}{}{} {s} {%}{ }{,}
7249 \\
7262 , .{7250 , .{
7263 global.type.functionParameters(self)[arg].fmt(self),7251 variable.global.fmt(self),
7264 function.attributes.param(arg, self).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,
7265 });7264 });
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 },
7275 }7265 }
7276 try writer.print("){}{}", .{ global.unnamed_addr, global.addr_space });7266 need_newline = true;
7277 if (function_attributes != .none) try writer.print(" #{d}", .{7267 }
7278 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,7268
7279 });7269 var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{};
7280 try writer.print("{}", .{function.alignment});7270 defer attribute_groups.deinit(self.gpa);
7281 if (function.instructions.len > 0) {7271
7282 var block_incoming_len: u32 = undefined;7272 if (self.functions.items.len > 0) {
7283 try writer.writeAll(" {\n");7273 if (need_newline) try writer.writeByte('\n');
7284 for (params_len..function.instructions.len) |instruction_i| {7274 for (0.., self.functions.items) |function_i, function| {
7285 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);7275 if (function_i > 0) try writer.writeByte('\n');
7286 const instruction = function.instructions.get(@intFromEnum(instruction_index));7276 const function_index: Function.Index = @enumFromInt(function_i);
7287 switch (instruction.tag) {7277 if (function.global.getReplacement(self) != .none) continue;
7288 .add,7278 const global = function.global.ptrConst(self);
7289 .@"add nsw",7279 const params_len = global.type.functionParameters(self).len;
7290 .@"add nuw",7280 const function_attributes = function.attributes.func(self);
7291 .@"add nuw nsw",7281 if (function_attributes != .none) try writer.print(
7292 .@"and",7282 \\; Function Attrs:{}
7293 .ashr,7283 \\
7294 .@"ashr exact",7284 , .{function_attributes.fmt(self)});
7295 .fadd,7285 try writer.print(
7296 .@"fadd fast",7286 \\{s}{}{}{}{}{}{"} {} {}(
7297 .@"fcmp false",7287 , .{
7298 .@"fcmp fast false",7288 if (function.instructions.len > 0) "define" else "declare",
7299 .@"fcmp fast oeq",7289 global.linkage,
7300 .@"fcmp fast oge",7290 global.preemption,
7301 .@"fcmp fast ogt",7291 global.visibility,
7302 .@"fcmp fast ole",7292 global.dll_storage_class,
7303 .@"fcmp fast olt",7293 function.call_conv,
7304 .@"fcmp fast one",7294 function.attributes.ret(self).fmt(self),
7305 .@"fcmp fast ord",7295 global.type.functionReturn(self).fmt(self),
7306 .@"fcmp fast true",7296 function.global.fmt(self),
7307 .@"fcmp fast ueq",7297 });
7308 .@"fcmp fast uge",7298 for (0..params_len) |arg| {
7309 .@"fcmp fast ugt",7299 if (arg > 0) try writer.writeAll(", ");
7310 .@"fcmp fast ule",7300 try writer.print(
7311 .@"fcmp fast ult",7301 \\{%}{"}
7312 .@"fcmp fast une",7302 , .{
7313 .@"fcmp fast uno",7303 global.type.functionParameters(self)[arg].fmt(self),
7314 .@"fcmp oeq",7304 function.attributes.param(arg, self).fmt(self),
7315 .@"fcmp oge",7305 });
7316 .@"fcmp ogt",7306 if (function.instructions.len > 0)
7317 .@"fcmp ole",7307 try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)});
7318 .@"fcmp olt",7308 }
7319 .@"fcmp one",7309 switch (global.type.functionKind(self)) {
7320 .@"fcmp ord",7310 .normal => {},
7321 .@"fcmp true",7311 .vararg => {
7322 .@"fcmp ueq",7312 if (params_len > 0) try writer.writeAll(", ");
7323 .@"fcmp uge",7313 try writer.writeAll("...");
7324 .@"fcmp ugt",7314 },
7325 .@"fcmp ule",7315 }
7326 .@"fcmp ult",7316 try writer.print("){}{}", .{ global.unnamed_addr, global.addr_space });
7327 .@"fcmp une",7317 if (function_attributes != .none) try writer.print(" #{d}", .{
7328 .@"fcmp uno",7318 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,
7329 .fdiv,7319 });
7330 .@"fdiv fast",7320 try writer.print("{}", .{function.alignment});
7331 .fmul,7321 if (function.instructions.len > 0) {
7332 .@"fmul fast",7322 var block_incoming_len: u32 = undefined;
7333 .frem,7323 try writer.writeAll(" {\n");
7334 .@"frem fast",7324 for (params_len..function.instructions.len) |instruction_i| {
7335 .fsub,7325 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);
7336 .@"fsub fast",7326 const instruction = function.instructions.get(@intFromEnum(instruction_index));
7337 .@"icmp eq",7327 switch (instruction.tag) {
7338 .@"icmp ne",7328 .add,
7339 .@"icmp sge",7329 .@"add nsw",
7340 .@"icmp sgt",7330 .@"add nuw",
7341 .@"icmp sle",7331 .@"add nuw nsw",
7342 .@"icmp slt",7332 .@"and",
7343 .@"icmp uge",7333 .ashr,
7344 .@"icmp ugt",7334 .@"ashr exact",
7345 .@"icmp ule",7335 .fadd,
7346 .@"icmp ult",7336 .@"fadd fast",
7347 .lshr,7337 .@"fcmp false",
7348 .@"lshr exact",7338 .@"fcmp fast false",
7349 .mul,7339 .@"fcmp fast oeq",
7350 .@"mul nsw",7340 .@"fcmp fast oge",
7351 .@"mul nuw",7341 .@"fcmp fast ogt",
7352 .@"mul nuw nsw",7342 .@"fcmp fast ole",
7353 .@"or",7343 .@"fcmp fast olt",
7354 .sdiv,7344 .@"fcmp fast one",
7355 .@"sdiv exact",7345 .@"fcmp fast ord",
7356 .srem,7346 .@"fcmp fast true",
7357 .shl,7347 .@"fcmp fast ueq",
7358 .@"shl nsw",7348 .@"fcmp fast uge",
7359 .@"shl nuw",7349 .@"fcmp fast ugt",
7360 .@"shl nuw nsw",7350 .@"fcmp fast ule",
7361 .sub,7351 .@"fcmp fast ult",
7362 .@"sub nsw",7352 .@"fcmp fast une",
7363 .@"sub nuw",7353 .@"fcmp fast uno",
7364 .@"sub nuw nsw",7354 .@"fcmp oeq",
7365 .udiv,7355 .@"fcmp oge",
7366 .@"udiv exact",7356 .@"fcmp ogt",
7367 .urem,7357 .@"fcmp ole",
7368 .xor,7358 .@"fcmp olt",
7369 => |tag| {7359 .@"fcmp one",
7370 const extra = function.extraData(Function.Instruction.Binary, instruction.data);7360 .@"fcmp ord",
7371 try writer.print(" %{} = {s} {%}, {}\n", .{7361 .@"fcmp true",
7372 instruction_index.name(&function).fmt(self),7362 .@"fcmp ueq",
7373 @tagName(tag),7363 .@"fcmp uge",
7374 extra.lhs.fmt(function_index, self),7364 .@"fcmp ugt",
7375 extra.rhs.fmt(function_index, self),7365 .@"fcmp ule",
7376 });7366 .@"fcmp ult",
7377 },7367 .@"fcmp une",
7378 .addrspacecast,7368 .@"fcmp uno",
7379 .bitcast,7369 .fdiv,
7380 .fpext,7370 .@"fdiv fast",
7381 .fptosi,7371 .fmul,
7382 .fptoui,7372 .@"fmul fast",
7383 .fptrunc,7373 .frem,
7384 .inttoptr,7374 .@"frem fast",
7385 .ptrtoint,7375 .fsub,
7386 .sext,7376 .@"fsub fast",
7387 .sitofp,7377 .@"icmp eq",
7388 .trunc,7378 .@"icmp ne",
7389 .uitofp,7379 .@"icmp sge",
7390 .zext,7380 .@"icmp sgt",
7391 => |tag| {7381 .@"icmp sle",
7392 const extra = function.extraData(Function.Instruction.Cast, instruction.data);7382 .@"icmp slt",
7393 try writer.print(" %{} = {s} {%} to {%}\n", .{7383 .@"icmp uge",
7394 instruction_index.name(&function).fmt(self),7384 .@"icmp ugt",
7395 @tagName(tag),7385 .@"icmp ule",
7396 extra.val.fmt(function_index, self),7386 .@"icmp ult",
7397 extra.type.fmt(self),7387 .lshr,
7398 });7388 .@"lshr exact",
7399 },7389 .mul,
7400 .alloca,7390 .@"mul nsw",
7401 .@"alloca inalloca",7391 .@"mul nuw",
7402 => |tag| {7392 .@"mul nuw nsw",
7403 const extra = function.extraData(Function.Instruction.Alloca, instruction.data);7393 .@"or",
7404 try writer.print(" %{} = {s} {%}{,%}{,}{,}\n", .{7394 .sdiv,
7405 instruction_index.name(&function).fmt(self),7395 .@"sdiv exact",
7406 @tagName(tag),7396 .srem,
7407 extra.type.fmt(self),7397 .shl,
7408 extra.len.fmt(function_index, self),7398 .@"shl nsw",
7409 extra.info.alignment,7399 .@"shl nuw",
7410 extra.info.addr_space,7400 .@"shl nuw nsw",
7411 });7401 .sub,
7412 },7402 .@"sub nsw",
7413 .arg => unreachable,7403 .@"sub nuw",
7414 .block => {7404 .@"sub nuw nsw",
7415 block_incoming_len = instruction.data;7405 .udiv,
7416 const name = instruction_index.name(&function);7406 .@"udiv exact",
7417 if (@intFromEnum(instruction_index) > params_len) try writer.writeByte('\n');7407 .urem,
7418 try writer.print("{}:\n", .{name.fmt(self)});7408 .xor,
7419 },7409 => |tag| {
7420 .br => |tag| {7410 const extra =
7421 const target: Function.Block.Index = @enumFromInt(instruction.data);7411 function.extraData(Function.Instruction.Binary, instruction.data);
7422 try writer.print(" {s} {%}\n", .{7412 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("%{} = ", .{
7451 instruction_index.name(&function).fmt(self),7413 instruction_index.name(&function).fmt(self),
7452 }),7414 @tagName(tag),
7453 .none => unreachable,7415 extra.lhs.fmt(function_index, self),
7454 }7416 extra.rhs.fmt(function_index, self),
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),
7472 });7417 });
7473 }7418 },
7474 try writer.writeByte(')');7419 .addrspacecast,
7475 const call_function_attributes = extra.data.attributes.func(self);7420 .bitcast,
7476 if (call_function_attributes != .none) try writer.print(" #{d}", .{7421 .fpext,
7477 (try attribute_groups.getOrPutValue(7422 .fptosi,
7478 self.gpa,7423 .fptoui,
7479 call_function_attributes,7424 .fptrunc,
7480 {},7425 .inttoptr,
7481 )).index,7426 .ptrtoint,
7482 });7427 .sext,
7483 },7428 .sitofp,
7484 .extractelement => |tag| {7429 .trunc,
7485 const extra =7430 .uitofp,
7486 function.extraData(Function.Instruction.ExtractElement, instruction.data);7431 .zext,
7487 try writer.print(" %{} = {s} {%}, {%}\n", .{7432 => |tag| {
7488 instruction_index.name(&function).fmt(self),7433 const extra =
7489 @tagName(tag),7434 function.extraData(Function.Instruction.Cast, instruction.data);
7490 extra.val.fmt(function_index, self),7435 try writer.print(" %{} = {s} {%} to {%}\n", .{
7491 extra.index.fmt(function_index, self),7436 instruction_index.name(&function).fmt(self),
7492 });7437 @tagName(tag),
7493 },7438 extra.val.fmt(function_index, self),
7494 .extractvalue => |tag| {7439 extra.type.fmt(self),
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),
7628 });7440 });
7629 }7441 },
7630 try writer.writeByte('\n');7442 .alloca,
7631 },7443 .@"alloca inalloca",
7632 .@"ret void",7444 => |tag| {
7633 .@"unreachable",7445 const extra =
7634 => |tag| try writer.print(" {s}\n", .{@tagName(tag)}),7446 function.extraData(Function.Instruction.Alloca, instruction.data);
7635 .select,7447 try writer.print(" %{} = {s} {%}{,%}{,}{,}\n", .{
7636 .@"select fast",7448 instruction_index.name(&function).fmt(self),
7637 => |tag| {7449 @tagName(tag),
7638 const extra = function.extraData(Function.Instruction.Select, instruction.data);7450 extra.type.fmt(self),
7639 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{7451 extra.len.fmt(function_index, self),
7640 instruction_index.name(&function).fmt(self),7452 extra.info.alignment,
7641 @tagName(tag),7453 extra.info.addr_space,
7642 extra.cond.fmt(function_index, self),7454 });
7643 extra.lhs.fmt(function_index, self),7455 },
7644 extra.rhs.fmt(function_index, self),7456 .arg => unreachable,
7645 });7457 .block => {
7646 },7458 block_incoming_len = instruction.data;
7647 .shufflevector => |tag| {7459 const name = instruction_index.name(&function);
7648 const extra =7460 if (@intFromEnum(instruction_index) > params_len)
7649 function.extraData(Function.Instruction.ShuffleVector, instruction.data);7461 try writer.writeByte('\n');
7650 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{7462 try writer.print("{}:\n", .{name.fmt(self)});
7651 instruction_index.name(&function).fmt(self),7463 },
7652 @tagName(tag),7464 .br => |tag| {
7653 extra.lhs.fmt(function_index, self),7465 const target: Function.Block.Index = @enumFromInt(instruction.data);
7654 extra.rhs.fmt(function_index, self),7466 try writer.print(" {s} {%}\n", .{
7655 extra.mask.fmt(function_index, self),7467 @tagName(tag), target.toInst(&function).fmt(function_index, self),
7656 });7468 });
7657 },7469 },
7658 .store,7470 .br_cond => {
7659 .@"store atomic",7471 const extra =
7660 .@"store atomic volatile",7472 function.extraData(Function.Instruction.BrCond, instruction.data);
7661 .@"store volatile",7473 try writer.print(" br {%}, {%}, {%}\n", .{
7662 => |tag| {7474 extra.cond.fmt(function_index, self),
7663 const extra = function.extraData(Function.Instruction.Store, instruction.data);7475 extra.then.toInst(&function).fmt(function_index, self),
7664 try writer.print(" {s} {%}, {%}{}{}{,}\n", .{7476 extra.@"else".toInst(&function).fmt(function_index, self),
7665 @tagName(tag),7477 });
7666 extra.val.fmt(function_index, self),7478 },
7667 extra.ptr.fmt(function_index, self),7479 .call,
7668 extra.info.scope,7480 .@"call fast",
7669 extra.info.ordering,7481 .@"musttail call",
7670 extra.info.alignment,7482 .@"musttail call fast",
7671 });7483 .@"notail call",
7672 },7484 .@"notail call fast",
7673 .@"switch" => |tag| {7485 .@"tail call",
7674 var extra =7486 .@"tail call fast",
7675 function.extraDataTrail(Function.Instruction.Switch, instruction.data);7487 => |tag| {
7676 const vals = extra.trail.next(extra.data.cases_len, Constant, &function);7488 var extra =
7677 const blocks =7489 function.extraDataTrail(Function.Instruction.Call, instruction.data);
7678 extra.trail.next(extra.data.cases_len, Function.Block.Index, &function);7490 const args = extra.trail.next(extra.data.args_len, Value, &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) {
7693 try writer.writeAll(" ");7491 try writer.writeAll(" ");
7694 switch (ty) {7492 const ret_ty = extra.data.ty.functionReturn(self);
7695 .none, .void => {},7493 switch (ret_ty) {
7494 .void => {},
7696 else => try writer.print("%{} = ", .{7495 else => try writer.print("%{} = ", .{
7697 instruction_index.name(&function).fmt(self),7496 instruction_index.name(&function).fmt(self),
7698 }),7497 }),
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 });
7699 }7518 }
7700 try writer.print("{s} {%}\n", .{ @tagName(tag), ty.fmt(self) });7519 try writer.writeByte(')');
7701 } else switch (ty) {7520 const call_function_attributes = extra.data.attributes.func(self);
7702 .none, .void => {},7521 if (call_function_attributes != .none) try writer.print(" #{d}", .{
7703 else => try writer.print(" %{} = load {%}, ptr undef\n", .{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", .{
7704 instruction_index.name(&function).fmt(self),7636 instruction_index.name(&function).fmt(self),
7705 ty.fmt(self),7637 ty.fmt(self),
7706 }),7638 @tagName(tag),
7707 }7639 ty.fmt(self),
7708 },7640 extra.lhs.fmt(function_index, self),
7709 .va_arg => |tag| {7641 extra.rhs.fmt(function_index, self),
7710 const extra = function.extraData(Function.Instruction.VaArg, instruction.data);7642 switch (tag) {
7711 try writer.print(" %{} = {s} {%}, {%}\n", .{7643 .@"llvm.smul.fix.sat.",
7712 instruction_index.name(&function).fmt(self),7644 .@"llvm.umul.fix.sat.",
7713 @tagName(tag),7645 => ", i32 0",
7714 extra.list.fmt(function_index, self),7646 else => "",
7715 extra.type.fmt(self),7647 },
7716 });7648 });
7717 },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 }
7718 }7784 }
7785 try writer.writeByte('}');
7719 }7786 }
7720 try writer.writeByte('}');7787 try writer.writeByte('\n');
7721 }7788 }
7722 try writer.writeAll("\n\n");7789 need_newline = true;
7723 }7790 }
77247791
7725 for (0.., attribute_groups.keys()) |attribute_group_index, attribute_group|7792 if (attribute_groups.count() > 0) {
7726 try writer.print(7793 if (need_newline) try writer.writeByte('\n') else need_newline = true;
7727 \\attributes #{d} = {{{#"} }}7794 for (0.., attribute_groups.keys()) |attribute_group_index, attribute_group|
7728 \\7795 try writer.print(
7729 , .{ attribute_group_index, attribute_group.fmt(self) });7796 \\attributes #{d} = {{{#"} }}
7797 \\
7798 , .{ attribute_group_index, attribute_group.fmt(self) });
7799 need_newline = true;
7800 }
7730}7801}
77317802
7732pub inline fn useLibLlvm(self: *const Builder) bool {7803pub inline fn useLibLlvm(self: *const Builder) bool {
...@@ -7736,7 +7807,7 @@ pub inline fn useLibLlvm(self: *const Builder) bool {...@@ -7736,7 +7807,7 @@ pub inline fn useLibLlvm(self: *const Builder) bool {
7736const NoExtra = struct {};7807const NoExtra = struct {};
77377808
7738fn isValidIdentifier(id: []const u8) bool {7809fn isValidIdentifier(id: []const u8) bool {
7739 for (id, 0..) |character, index| switch (character) {7810 for (id, 0..) |byte, index| switch (byte) {
7740 '$', '-', '.', 'A'...'Z', '_', 'a'...'z' => {},7811 '$', '-', '.', 'A'...'Z', '_', 'a'...'z' => {},
7741 '0'...'9' => if (index == 0) return false,7812 '0'...'9' => if (index == 0) return false,
7742 else => return false,7813 else => return false,
...@@ -7744,6 +7815,25 @@ fn isValidIdentifier(id: []const u8) bool {...@@ -7744,6 +7815,25 @@ fn isValidIdentifier(id: []const u8) bool {
7744 return true;7815 return true;
7745}7816}
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
7747fn ensureUnusedGlobalCapacity(self: *Builder, name: String) Allocator.Error!void {7837fn ensureUnusedGlobalCapacity(self: *Builder, name: String) Allocator.Error!void {
7748 if (self.useLibLlvm()) try self.llvm.globals.ensureUnusedCapacity(self.gpa, 1);7838 if (self.useLibLlvm()) try self.llvm.globals.ensureUnusedCapacity(self.gpa, 1);
7749 try self.string_map.ensureUnusedCapacity(self.gpa, 1);7839 try self.string_map.ensureUnusedCapacity(self.gpa, 1);
...@@ -9318,6 +9408,8 @@ fn asmConstAssumeCapacity(...@@ -9318,6 +9408,8 @@ fn asmConstAssumeCapacity(
9318 assembly: String,9408 assembly: String,
9319 constraints: String,9409 constraints: String,
9320) Constant {9410) Constant {
9411 assert(ty.functionKind(self) == .normal);
9412
9321 const Key = struct { tag: Constant.Tag, extra: Constant.Asm };9413 const Key = struct { tag: Constant.Tag, extra: Constant.Asm };
9322 const Adapter = struct {9414 const Adapter = struct {
9323 builder: *const Builder,9415 builder: *const Builder,
src/codegen/llvm/bindings.zig+1-1
...@@ -540,7 +540,7 @@ pub const Module = opaque {...@@ -540,7 +540,7 @@ pub const Module = opaque {
540 pub const createDIBuilder = ZigLLVMCreateDIBuilder;540 pub const createDIBuilder = ZigLLVMCreateDIBuilder;
541 extern fn ZigLLVMCreateDIBuilder(module: *Module, allow_unresolved: bool) *DIBuilder;541 extern fn ZigLLVMCreateDIBuilder(module: *Module, allow_unresolved: bool) *DIBuilder;
542542
543 pub const setModuleInlineAsm2 = LLVMSetModuleInlineAsm2;543 pub const setModuleInlineAsm = LLVMSetModuleInlineAsm2;
544 extern fn LLVMSetModuleInlineAsm2(M: *Module, Asm: [*]const u8, Len: usize) void;544 extern fn LLVMSetModuleInlineAsm2(M: *Module, Asm: [*]const u8, Len: usize) void;
545545
546 pub const printModuleToFile = LLVMPrintModuleToFile;546 pub const printModuleToFile = LLVMPrintModuleToFile;