| ... | @@ -18,6 +18,7 @@ llvm: if (build_options.have_llvm) struct { | ... | @@ -18,6 +18,7 @@ llvm: if (build_options.have_llvm) struct { |
| 18 | source_filename: String, | 18 | source_filename: String, |
| 19 | data_layout: String, | 19 | data_layout: String, |
| 20 | target_triple: String, | 20 | target_triple: String, |
| | 21 | module_asm: std.ArrayListUnmanaged(u8), |
| 21 | | 22 | |
| 22 | string_map: std.AutoArrayHashMapUnmanaged(void, void), | 23 | string_map: std.AutoArrayHashMapUnmanaged(void, void), |
| 23 | string_indices: std.ArrayListUnmanaged(u32), | 24 | string_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) orelse | 97 | 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) or | 102 | .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 = .{}, |
| 6093 | | 6089 | |
| 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 | } |
| 6208 | | 6204 | |
| 6209 | pub fn deinit(self: *Builder) void { | 6205 | pub 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 | } |
| 6442 | | 6440 | |
| | 6441 | pub fn setModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer { |
| | 6442 | self.module_asm.clearRetainingCapacity(); |
| | 6443 | return self.appendModuleAsm(); |
| | 6444 | } |
| | 6445 | |
| | 6446 | pub fn appendModuleAsm(self: *Builder) std.ArrayListUnmanaged(u8).Writer { |
| | 6447 | return self.module_asm.writer(self.gpa); |
| | 6448 | } |
| | 6449 | |
| | 6450 | pub 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 | |
| 6443 | pub fn string(self: *Builder, bytes: []const u8) Allocator.Error!String { | 6457 | pub 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'); | | |
| 7232 | | 7221 | |
| 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 | } |
| 7724 | | 7791 | |
| 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 | } |
| 7731 | | 7802 | |
| 7732 | pub inline fn useLibLlvm(self: *const Builder) bool { | 7803 | pub 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 { |
| 7736 | const NoExtra = struct {}; | 7807 | const NoExtra = struct {}; |
| 7737 | | 7808 | |
| 7738 | fn isValidIdentifier(id: []const u8) bool { | 7809 | fn 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 | } |
| 7746 | | 7817 | |
| | 7818 | const QuoteBehavior = enum { always_quote, quote_unless_valid_identifier }; |
| | 7819 | fn 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 | |
| 7747 | fn ensureUnusedGlobalCapacity(self: *Builder, name: String) Allocator.Error!void { | 7837 | fn 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, |