| ... | ... | @@ -18,6 +18,7 @@ llvm: if (build_options.have_llvm) struct { |
| 18 | 18 | source_filename: String, |
| 19 | 19 | data_layout: String, |
| 20 | 20 | target_triple: String, |
| 21 | module_asm: std.ArrayListUnmanaged(u8), |
| 21 | 22 | |
| 22 | 23 | string_map: std.AutoArrayHashMapUnmanaged(void, void), |
| 23 | 24 | string_indices: std.ArrayListUnmanaged(u32), |
| ... | ... | @@ -95,18 +96,12 @@ pub const String = enum(u32) { |
| 95 | 96 | assert(data.string != .none); |
| 96 | 97 | const sentinel_slice = data.string.slice(data.builder) orelse |
| 97 | 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 | 100 | std.mem.indexOfScalar(u8, fmt_str, '@') != null, |
| 100 | | )]; |
| 101 | | const need_quotes = (comptime std.mem.indexOfScalar(u8, fmt_str, '"') != null) or |
| 102 | | !isValidIdentifier(full_slice); |
| 103 | | if (need_quotes) try writer.writeByte('"'); |
| 104 | | for (full_slice) |character| switch (character) { |
| 105 | | '\\' => try writer.writeAll("\\\\"), |
| 106 | | ' '...'"' - 1, '"' + 1...'\\' - 1, '\\' + 1...'~' => try writer.writeByte(character), |
| 107 | | else => try writer.print("\\{X:0>2}", .{character}), |
| 108 | | }; |
| 109 | | if (need_quotes) try writer.writeByte('"'); |
| 101 | )], if (comptime std.mem.indexOfScalar(u8, fmt_str, '"')) |_| |
| 102 | .always_quote |
| 103 | else |
| 104 | .quote_unless_valid_identifier, writer); |
| 110 | 105 | } |
| 111 | 106 | pub fn fmt(self: String, builder: *const Builder) std.fmt.Formatter(format) { |
| 112 | 107 | return .{ .data = .{ .string = self, .builder = builder } }; |
| ... | ... | @@ -3812,7 +3807,7 @@ pub const WipFunction = struct { |
| 3812 | 3807 | @intFromEnum(addr_space), |
| 3813 | 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 | 3811 | self.llvm.instructions.appendAssumeCapacity(llvm_instruction); |
| 3817 | 3812 | } |
| 3818 | 3813 | return instruction.toValue(); |
| ... | ... | @@ -3868,7 +3863,7 @@ pub const WipFunction = struct { |
| 3868 | 3863 | instruction.llvmName(self), |
| 3869 | 3864 | ); |
| 3870 | 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 | 3867 | self.llvm.instructions.appendAssumeCapacity(llvm_instruction); |
| 3873 | 3868 | } |
| 3874 | 3869 | return instruction.toValue(); |
| ... | ... | @@ -3922,7 +3917,7 @@ pub const WipFunction = struct { |
| 3922 | 3917 | .@"volatile" => llvm_instruction.setVolatile(.True), |
| 3923 | 3918 | } |
| 3924 | 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 | 3921 | self.llvm.instructions.appendAssumeCapacity(llvm_instruction); |
| 3927 | 3922 | } |
| 3928 | 3923 | return instruction; |
| ... | ... | @@ -6090,6 +6085,7 @@ pub fn init(options: Options) InitError!Builder { |
| 6090 | 6085 | .source_filename = .none, |
| 6091 | 6086 | .data_layout = .none, |
| 6092 | 6087 | .target_triple = .none, |
| 6088 | .module_asm = .{}, |
| 6093 | 6089 | |
| 6094 | 6090 | .string_map = .{}, |
| 6095 | 6091 | .string_indices = .{}, |
| ... | ... | @@ -6207,6 +6203,8 @@ pub fn init(options: Options) InitError!Builder { |
| 6207 | 6203 | } |
| 6208 | 6204 | |
| 6209 | 6205 | pub fn deinit(self: *Builder) void { |
| 6206 | self.module_asm.deinit(self.gpa); |
| 6207 | |
| 6210 | 6208 | self.string_map.deinit(self.gpa); |
| 6211 | 6209 | self.string_indices.deinit(self.gpa); |
| 6212 | 6210 | self.string_bytes.deinit(self.gpa); |
| ... | ... | @@ -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 | 6457 | pub fn string(self: *Builder, bytes: []const u8) Allocator.Error!String { |
| 6444 | 6458 | try self.string_bytes.ensureUnusedCapacity(self.gpa, bytes.len + 1); |
| 6445 | 6459 | try self.string_indices.ensureUnusedCapacity(self.gpa, 1); |
| ... | ... | @@ -7185,548 +7199,605 @@ pub fn printUnbuffered( |
| 7185 | 7199 | self: *Builder, |
| 7186 | 7200 | writer: anytype, |
| 7187 | 7201 | ) (@TypeOf(writer).Error || Allocator.Error)!void { |
| 7188 | | if (self.source_filename != .none) try writer.print( |
| 7189 | | \\; ModuleID = '{s}' |
| 7190 | | \\source_filename = {"} |
| 7191 | | \\ |
| 7192 | | , .{ self.source_filename.slice(self).?, self.source_filename.fmt(self) }); |
| 7193 | | if (self.data_layout != .none) try writer.print( |
| 7194 | | \\target datalayout = {"} |
| 7195 | | \\ |
| 7196 | | , .{self.data_layout.fmt(self)}); |
| 7197 | | if (self.target_triple != .none) try writer.print( |
| 7198 | | \\target triple = {"} |
| 7199 | | \\ |
| 7200 | | , .{self.target_triple.fmt(self)}); |
| 7201 | | try writer.writeByte('\n'); |
| 7202 | | |
| 7203 | | for (self.types.keys(), self.types.values()) |id, ty| try writer.print( |
| 7204 | | \\%{} = type {} |
| 7205 | | \\ |
| 7206 | | , .{ id.fmt(self), ty.fmt(self) }); |
| 7207 | | try writer.writeByte('\n'); |
| 7208 | | |
| 7209 | | for (self.variables.items) |variable| { |
| 7210 | | if (variable.global.getReplacement(self) != .none) continue; |
| 7211 | | const global = variable.global.ptrConst(self); |
| 7212 | | try writer.print( |
| 7213 | | \\{} ={}{}{}{}{}{}{}{} {s} {%}{ }{,} |
| 7202 | var need_newline = false; |
| 7203 | |
| 7204 | if (self.source_filename != .none or self.data_layout != .none or self.target_triple != .none) { |
| 7205 | if (need_newline) try writer.writeByte('\n'); |
| 7206 | if (self.source_filename != .none) try writer.print( |
| 7207 | \\; ModuleID = '{s}' |
| 7208 | \\source_filename = {"} |
| 7214 | 7209 | \\ |
| 7215 | | , .{ |
| 7216 | | variable.global.fmt(self), |
| 7217 | | global.linkage, |
| 7218 | | global.preemption, |
| 7219 | | global.visibility, |
| 7220 | | global.dll_storage_class, |
| 7221 | | variable.thread_local, |
| 7222 | | global.unnamed_addr, |
| 7223 | | global.addr_space, |
| 7224 | | global.externally_initialized, |
| 7225 | | @tagName(variable.mutability), |
| 7226 | | global.type.fmt(self), |
| 7227 | | variable.init.fmt(self), |
| 7228 | | variable.alignment, |
| 7229 | | }); |
| 7210 | , .{ self.source_filename.slice(self).?, self.source_filename.fmt(self) }); |
| 7211 | if (self.data_layout != .none) try writer.print( |
| 7212 | \\target datalayout = {"} |
| 7213 | \\ |
| 7214 | , .{self.data_layout.fmt(self)}); |
| 7215 | if (self.target_triple != .none) try writer.print( |
| 7216 | \\target triple = {"} |
| 7217 | \\ |
| 7218 | , .{self.target_triple.fmt(self)}); |
| 7219 | need_newline = true; |
| 7230 | 7220 | } |
| 7231 | | try writer.writeByte('\n'); |
| 7232 | 7221 | |
| 7233 | | var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{}; |
| 7234 | | defer attribute_groups.deinit(self.gpa); |
| 7235 | | for (0.., self.functions.items) |function_i, function| { |
| 7236 | | const function_index: Function.Index = @enumFromInt(function_i); |
| 7237 | | if (function.global.getReplacement(self) != .none) continue; |
| 7238 | | const global = function.global.ptrConst(self); |
| 7239 | | const params_len = global.type.functionParameters(self).len; |
| 7240 | | const function_attributes = function.attributes.func(self); |
| 7241 | | if (function_attributes != .none) try writer.print( |
| 7242 | | \\; Function Attrs:{} |
| 7222 | if (self.module_asm.items.len > 0) { |
| 7223 | if (need_newline) try writer.writeByte('\n'); |
| 7224 | var line_it = std.mem.tokenizeScalar(u8, self.module_asm.items, '\n'); |
| 7225 | while (line_it.next()) |line| { |
| 7226 | try writer.writeAll("module asm "); |
| 7227 | try printEscapedString(line, .always_quote, writer); |
| 7228 | try writer.writeByte('\n'); |
| 7229 | } |
| 7230 | need_newline = true; |
| 7231 | } |
| 7232 | |
| 7233 | if (self.types.count() > 0) { |
| 7234 | if (need_newline) try writer.writeByte('\n'); |
| 7235 | for (self.types.keys(), self.types.values()) |id, ty| try writer.print( |
| 7236 | \\%{} = type {} |
| 7243 | 7237 | \\ |
| 7244 | | , .{function_attributes.fmt(self)}); |
| 7245 | | try writer.print( |
| 7246 | | \\{s}{}{}{}{}{}{"} {} {}( |
| 7247 | | , .{ |
| 7248 | | if (function.instructions.len > 0) "define" else "declare", |
| 7249 | | global.linkage, |
| 7250 | | global.preemption, |
| 7251 | | global.visibility, |
| 7252 | | global.dll_storage_class, |
| 7253 | | function.call_conv, |
| 7254 | | function.attributes.ret(self).fmt(self), |
| 7255 | | global.type.functionReturn(self).fmt(self), |
| 7256 | | function.global.fmt(self), |
| 7257 | | }); |
| 7258 | | for (0..params_len) |arg| { |
| 7259 | | if (arg > 0) try writer.writeAll(", "); |
| 7238 | , .{ id.fmt(self), ty.fmt(self) }); |
| 7239 | need_newline = true; |
| 7240 | } |
| 7241 | |
| 7242 | if (self.variables.items.len > 0) { |
| 7243 | if (need_newline) try writer.writeByte('\n'); |
| 7244 | for (self.variables.items) |variable| { |
| 7245 | if (variable.global.getReplacement(self) != .none) continue; |
| 7246 | const global = variable.global.ptrConst(self); |
| 7260 | 7247 | try writer.print( |
| 7261 | | \\{%}{"} |
| 7248 | \\{} ={}{}{}{}{}{}{}{} {s} {%}{ }{,} |
| 7249 | \\ |
| 7262 | 7250 | , .{ |
| 7263 | | global.type.functionParameters(self)[arg].fmt(self), |
| 7264 | | function.attributes.param(arg, self).fmt(self), |
| 7251 | variable.global.fmt(self), |
| 7252 | global.linkage, |
| 7253 | global.preemption, |
| 7254 | global.visibility, |
| 7255 | global.dll_storage_class, |
| 7256 | variable.thread_local, |
| 7257 | global.unnamed_addr, |
| 7258 | global.addr_space, |
| 7259 | global.externally_initialized, |
| 7260 | @tagName(variable.mutability), |
| 7261 | global.type.fmt(self), |
| 7262 | variable.init.fmt(self), |
| 7263 | variable.alignment, |
| 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 }); |
| 7277 | | if (function_attributes != .none) try writer.print(" #{d}", .{ |
| 7278 | | (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index, |
| 7279 | | }); |
| 7280 | | try writer.print("{}", .{function.alignment}); |
| 7281 | | if (function.instructions.len > 0) { |
| 7282 | | var block_incoming_len: u32 = undefined; |
| 7283 | | try writer.writeAll(" {\n"); |
| 7284 | | for (params_len..function.instructions.len) |instruction_i| { |
| 7285 | | const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i); |
| 7286 | | const instruction = function.instructions.get(@intFromEnum(instruction_index)); |
| 7287 | | switch (instruction.tag) { |
| 7288 | | .add, |
| 7289 | | .@"add nsw", |
| 7290 | | .@"add nuw", |
| 7291 | | .@"add nuw nsw", |
| 7292 | | .@"and", |
| 7293 | | .ashr, |
| 7294 | | .@"ashr exact", |
| 7295 | | .fadd, |
| 7296 | | .@"fadd fast", |
| 7297 | | .@"fcmp false", |
| 7298 | | .@"fcmp fast false", |
| 7299 | | .@"fcmp fast oeq", |
| 7300 | | .@"fcmp fast oge", |
| 7301 | | .@"fcmp fast ogt", |
| 7302 | | .@"fcmp fast ole", |
| 7303 | | .@"fcmp fast olt", |
| 7304 | | .@"fcmp fast one", |
| 7305 | | .@"fcmp fast ord", |
| 7306 | | .@"fcmp fast true", |
| 7307 | | .@"fcmp fast ueq", |
| 7308 | | .@"fcmp fast uge", |
| 7309 | | .@"fcmp fast ugt", |
| 7310 | | .@"fcmp fast ule", |
| 7311 | | .@"fcmp fast ult", |
| 7312 | | .@"fcmp fast une", |
| 7313 | | .@"fcmp fast uno", |
| 7314 | | .@"fcmp oeq", |
| 7315 | | .@"fcmp oge", |
| 7316 | | .@"fcmp ogt", |
| 7317 | | .@"fcmp ole", |
| 7318 | | .@"fcmp olt", |
| 7319 | | .@"fcmp one", |
| 7320 | | .@"fcmp ord", |
| 7321 | | .@"fcmp true", |
| 7322 | | .@"fcmp ueq", |
| 7323 | | .@"fcmp uge", |
| 7324 | | .@"fcmp ugt", |
| 7325 | | .@"fcmp ule", |
| 7326 | | .@"fcmp ult", |
| 7327 | | .@"fcmp une", |
| 7328 | | .@"fcmp uno", |
| 7329 | | .fdiv, |
| 7330 | | .@"fdiv fast", |
| 7331 | | .fmul, |
| 7332 | | .@"fmul fast", |
| 7333 | | .frem, |
| 7334 | | .@"frem fast", |
| 7335 | | .fsub, |
| 7336 | | .@"fsub fast", |
| 7337 | | .@"icmp eq", |
| 7338 | | .@"icmp ne", |
| 7339 | | .@"icmp sge", |
| 7340 | | .@"icmp sgt", |
| 7341 | | .@"icmp sle", |
| 7342 | | .@"icmp slt", |
| 7343 | | .@"icmp uge", |
| 7344 | | .@"icmp ugt", |
| 7345 | | .@"icmp ule", |
| 7346 | | .@"icmp ult", |
| 7347 | | .lshr, |
| 7348 | | .@"lshr exact", |
| 7349 | | .mul, |
| 7350 | | .@"mul nsw", |
| 7351 | | .@"mul nuw", |
| 7352 | | .@"mul nuw nsw", |
| 7353 | | .@"or", |
| 7354 | | .sdiv, |
| 7355 | | .@"sdiv exact", |
| 7356 | | .srem, |
| 7357 | | .shl, |
| 7358 | | .@"shl nsw", |
| 7359 | | .@"shl nuw", |
| 7360 | | .@"shl nuw nsw", |
| 7361 | | .sub, |
| 7362 | | .@"sub nsw", |
| 7363 | | .@"sub nuw", |
| 7364 | | .@"sub nuw nsw", |
| 7365 | | .udiv, |
| 7366 | | .@"udiv exact", |
| 7367 | | .urem, |
| 7368 | | .xor, |
| 7369 | | => |tag| { |
| 7370 | | const extra = function.extraData(Function.Instruction.Binary, instruction.data); |
| 7371 | | try writer.print(" %{} = {s} {%}, {}\n", .{ |
| 7372 | | instruction_index.name(&function).fmt(self), |
| 7373 | | @tagName(tag), |
| 7374 | | extra.lhs.fmt(function_index, self), |
| 7375 | | extra.rhs.fmt(function_index, self), |
| 7376 | | }); |
| 7377 | | }, |
| 7378 | | .addrspacecast, |
| 7379 | | .bitcast, |
| 7380 | | .fpext, |
| 7381 | | .fptosi, |
| 7382 | | .fptoui, |
| 7383 | | .fptrunc, |
| 7384 | | .inttoptr, |
| 7385 | | .ptrtoint, |
| 7386 | | .sext, |
| 7387 | | .sitofp, |
| 7388 | | .trunc, |
| 7389 | | .uitofp, |
| 7390 | | .zext, |
| 7391 | | => |tag| { |
| 7392 | | const extra = function.extraData(Function.Instruction.Cast, instruction.data); |
| 7393 | | try writer.print(" %{} = {s} {%} to {%}\n", .{ |
| 7394 | | instruction_index.name(&function).fmt(self), |
| 7395 | | @tagName(tag), |
| 7396 | | extra.val.fmt(function_index, self), |
| 7397 | | extra.type.fmt(self), |
| 7398 | | }); |
| 7399 | | }, |
| 7400 | | .alloca, |
| 7401 | | .@"alloca inalloca", |
| 7402 | | => |tag| { |
| 7403 | | const extra = function.extraData(Function.Instruction.Alloca, instruction.data); |
| 7404 | | try writer.print(" %{} = {s} {%}{,%}{,}{,}\n", .{ |
| 7405 | | instruction_index.name(&function).fmt(self), |
| 7406 | | @tagName(tag), |
| 7407 | | extra.type.fmt(self), |
| 7408 | | extra.len.fmt(function_index, self), |
| 7409 | | extra.info.alignment, |
| 7410 | | extra.info.addr_space, |
| 7411 | | }); |
| 7412 | | }, |
| 7413 | | .arg => unreachable, |
| 7414 | | .block => { |
| 7415 | | block_incoming_len = instruction.data; |
| 7416 | | const name = instruction_index.name(&function); |
| 7417 | | if (@intFromEnum(instruction_index) > params_len) try writer.writeByte('\n'); |
| 7418 | | try writer.print("{}:\n", .{name.fmt(self)}); |
| 7419 | | }, |
| 7420 | | .br => |tag| { |
| 7421 | | const target: Function.Block.Index = @enumFromInt(instruction.data); |
| 7422 | | try writer.print(" {s} {%}\n", .{ |
| 7423 | | @tagName(tag), target.toInst(&function).fmt(function_index, self), |
| 7424 | | }); |
| 7425 | | }, |
| 7426 | | .br_cond => { |
| 7427 | | const extra = function.extraData(Function.Instruction.BrCond, instruction.data); |
| 7428 | | try writer.print(" br {%}, {%}, {%}\n", .{ |
| 7429 | | extra.cond.fmt(function_index, self), |
| 7430 | | extra.then.toInst(&function).fmt(function_index, self), |
| 7431 | | extra.@"else".toInst(&function).fmt(function_index, self), |
| 7432 | | }); |
| 7433 | | }, |
| 7434 | | .call, |
| 7435 | | .@"call fast", |
| 7436 | | .@"musttail call", |
| 7437 | | .@"musttail call fast", |
| 7438 | | .@"notail call", |
| 7439 | | .@"notail call fast", |
| 7440 | | .@"tail call", |
| 7441 | | .@"tail call fast", |
| 7442 | | => |tag| { |
| 7443 | | var extra = |
| 7444 | | function.extraDataTrail(Function.Instruction.Call, instruction.data); |
| 7445 | | const args = extra.trail.next(extra.data.args_len, Value, &function); |
| 7446 | | try writer.writeAll(" "); |
| 7447 | | const ret_ty = extra.data.ty.functionReturn(self); |
| 7448 | | switch (ret_ty) { |
| 7449 | | .void => {}, |
| 7450 | | else => try writer.print("%{} = ", .{ |
| 7266 | need_newline = true; |
| 7267 | } |
| 7268 | |
| 7269 | var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{}; |
| 7270 | defer attribute_groups.deinit(self.gpa); |
| 7271 | |
| 7272 | if (self.functions.items.len > 0) { |
| 7273 | if (need_newline) try writer.writeByte('\n'); |
| 7274 | for (0.., self.functions.items) |function_i, function| { |
| 7275 | if (function_i > 0) try writer.writeByte('\n'); |
| 7276 | const function_index: Function.Index = @enumFromInt(function_i); |
| 7277 | if (function.global.getReplacement(self) != .none) continue; |
| 7278 | const global = function.global.ptrConst(self); |
| 7279 | const params_len = global.type.functionParameters(self).len; |
| 7280 | const function_attributes = function.attributes.func(self); |
| 7281 | if (function_attributes != .none) try writer.print( |
| 7282 | \\; Function Attrs:{} |
| 7283 | \\ |
| 7284 | , .{function_attributes.fmt(self)}); |
| 7285 | try writer.print( |
| 7286 | \\{s}{}{}{}{}{}{"} {} {}( |
| 7287 | , .{ |
| 7288 | if (function.instructions.len > 0) "define" else "declare", |
| 7289 | global.linkage, |
| 7290 | global.preemption, |
| 7291 | global.visibility, |
| 7292 | global.dll_storage_class, |
| 7293 | function.call_conv, |
| 7294 | function.attributes.ret(self).fmt(self), |
| 7295 | global.type.functionReturn(self).fmt(self), |
| 7296 | function.global.fmt(self), |
| 7297 | }); |
| 7298 | for (0..params_len) |arg| { |
| 7299 | if (arg > 0) try writer.writeAll(", "); |
| 7300 | try writer.print( |
| 7301 | \\{%}{"} |
| 7302 | , .{ |
| 7303 | global.type.functionParameters(self)[arg].fmt(self), |
| 7304 | function.attributes.param(arg, self).fmt(self), |
| 7305 | }); |
| 7306 | if (function.instructions.len > 0) |
| 7307 | try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)}); |
| 7308 | } |
| 7309 | switch (global.type.functionKind(self)) { |
| 7310 | .normal => {}, |
| 7311 | .vararg => { |
| 7312 | if (params_len > 0) try writer.writeAll(", "); |
| 7313 | try writer.writeAll("..."); |
| 7314 | }, |
| 7315 | } |
| 7316 | try writer.print("){}{}", .{ global.unnamed_addr, global.addr_space }); |
| 7317 | if (function_attributes != .none) try writer.print(" #{d}", .{ |
| 7318 | (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index, |
| 7319 | }); |
| 7320 | try writer.print("{}", .{function.alignment}); |
| 7321 | if (function.instructions.len > 0) { |
| 7322 | var block_incoming_len: u32 = undefined; |
| 7323 | try writer.writeAll(" {\n"); |
| 7324 | for (params_len..function.instructions.len) |instruction_i| { |
| 7325 | const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i); |
| 7326 | const instruction = function.instructions.get(@intFromEnum(instruction_index)); |
| 7327 | switch (instruction.tag) { |
| 7328 | .add, |
| 7329 | .@"add nsw", |
| 7330 | .@"add nuw", |
| 7331 | .@"add nuw nsw", |
| 7332 | .@"and", |
| 7333 | .ashr, |
| 7334 | .@"ashr exact", |
| 7335 | .fadd, |
| 7336 | .@"fadd fast", |
| 7337 | .@"fcmp false", |
| 7338 | .@"fcmp fast false", |
| 7339 | .@"fcmp fast oeq", |
| 7340 | .@"fcmp fast oge", |
| 7341 | .@"fcmp fast ogt", |
| 7342 | .@"fcmp fast ole", |
| 7343 | .@"fcmp fast olt", |
| 7344 | .@"fcmp fast one", |
| 7345 | .@"fcmp fast ord", |
| 7346 | .@"fcmp fast true", |
| 7347 | .@"fcmp fast ueq", |
| 7348 | .@"fcmp fast uge", |
| 7349 | .@"fcmp fast ugt", |
| 7350 | .@"fcmp fast ule", |
| 7351 | .@"fcmp fast ult", |
| 7352 | .@"fcmp fast une", |
| 7353 | .@"fcmp fast uno", |
| 7354 | .@"fcmp oeq", |
| 7355 | .@"fcmp oge", |
| 7356 | .@"fcmp ogt", |
| 7357 | .@"fcmp ole", |
| 7358 | .@"fcmp olt", |
| 7359 | .@"fcmp one", |
| 7360 | .@"fcmp ord", |
| 7361 | .@"fcmp true", |
| 7362 | .@"fcmp ueq", |
| 7363 | .@"fcmp uge", |
| 7364 | .@"fcmp ugt", |
| 7365 | .@"fcmp ule", |
| 7366 | .@"fcmp ult", |
| 7367 | .@"fcmp une", |
| 7368 | .@"fcmp uno", |
| 7369 | .fdiv, |
| 7370 | .@"fdiv fast", |
| 7371 | .fmul, |
| 7372 | .@"fmul fast", |
| 7373 | .frem, |
| 7374 | .@"frem fast", |
| 7375 | .fsub, |
| 7376 | .@"fsub fast", |
| 7377 | .@"icmp eq", |
| 7378 | .@"icmp ne", |
| 7379 | .@"icmp sge", |
| 7380 | .@"icmp sgt", |
| 7381 | .@"icmp sle", |
| 7382 | .@"icmp slt", |
| 7383 | .@"icmp uge", |
| 7384 | .@"icmp ugt", |
| 7385 | .@"icmp ule", |
| 7386 | .@"icmp ult", |
| 7387 | .lshr, |
| 7388 | .@"lshr exact", |
| 7389 | .mul, |
| 7390 | .@"mul nsw", |
| 7391 | .@"mul nuw", |
| 7392 | .@"mul nuw nsw", |
| 7393 | .@"or", |
| 7394 | .sdiv, |
| 7395 | .@"sdiv exact", |
| 7396 | .srem, |
| 7397 | .shl, |
| 7398 | .@"shl nsw", |
| 7399 | .@"shl nuw", |
| 7400 | .@"shl nuw nsw", |
| 7401 | .sub, |
| 7402 | .@"sub nsw", |
| 7403 | .@"sub nuw", |
| 7404 | .@"sub nuw nsw", |
| 7405 | .udiv, |
| 7406 | .@"udiv exact", |
| 7407 | .urem, |
| 7408 | .xor, |
| 7409 | => |tag| { |
| 7410 | const extra = |
| 7411 | function.extraData(Function.Instruction.Binary, instruction.data); |
| 7412 | try writer.print(" %{} = {s} {%}, {}\n", .{ |
| 7451 | 7413 | instruction_index.name(&function).fmt(self), |
| 7452 | | }), |
| 7453 | | .none => unreachable, |
| 7454 | | } |
| 7455 | | try writer.print("{s}{}{}{} {%} {}(", .{ |
| 7456 | | @tagName(tag), |
| 7457 | | extra.data.info.call_conv, |
| 7458 | | extra.data.attributes.ret(self).fmt(self), |
| 7459 | | extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self), |
| 7460 | | switch (extra.data.ty.functionKind(self)) { |
| 7461 | | .normal => ret_ty, |
| 7462 | | .vararg => extra.data.ty, |
| 7463 | | }.fmt(self), |
| 7464 | | extra.data.callee.fmt(function_index, self), |
| 7465 | | }); |
| 7466 | | for (0.., args) |arg_index, arg| { |
| 7467 | | if (arg_index > 0) try writer.writeAll(", "); |
| 7468 | | try writer.print("{%}{} {}", .{ |
| 7469 | | arg.typeOf(function_index, self).fmt(self), |
| 7470 | | extra.data.attributes.param(arg_index, self).fmt(self), |
| 7471 | | arg.fmt(function_index, self), |
| 7414 | @tagName(tag), |
| 7415 | extra.lhs.fmt(function_index, self), |
| 7416 | extra.rhs.fmt(function_index, self), |
| 7472 | 7417 | }); |
| 7473 | | } |
| 7474 | | try writer.writeByte(')'); |
| 7475 | | const call_function_attributes = extra.data.attributes.func(self); |
| 7476 | | if (call_function_attributes != .none) try writer.print(" #{d}", .{ |
| 7477 | | (try attribute_groups.getOrPutValue( |
| 7478 | | self.gpa, |
| 7479 | | call_function_attributes, |
| 7480 | | {}, |
| 7481 | | )).index, |
| 7482 | | }); |
| 7483 | | }, |
| 7484 | | .extractelement => |tag| { |
| 7485 | | const extra = |
| 7486 | | function.extraData(Function.Instruction.ExtractElement, instruction.data); |
| 7487 | | try writer.print(" %{} = {s} {%}, {%}\n", .{ |
| 7488 | | instruction_index.name(&function).fmt(self), |
| 7489 | | @tagName(tag), |
| 7490 | | extra.val.fmt(function_index, self), |
| 7491 | | extra.index.fmt(function_index, self), |
| 7492 | | }); |
| 7493 | | }, |
| 7494 | | .extractvalue => |tag| { |
| 7495 | | var extra = |
| 7496 | | function.extraDataTrail(Function.Instruction.ExtractValue, instruction.data); |
| 7497 | | const indices = extra.trail.next(extra.data.indices_len, u32, &function); |
| 7498 | | try writer.print(" %{} = {s} {%}", .{ |
| 7499 | | instruction_index.name(&function).fmt(self), |
| 7500 | | @tagName(tag), |
| 7501 | | extra.data.val.fmt(function_index, self), |
| 7502 | | }); |
| 7503 | | for (indices) |index| try writer.print(", {d}", .{index}); |
| 7504 | | try writer.writeByte('\n'); |
| 7505 | | }, |
| 7506 | | .fence => |tag| { |
| 7507 | | const info: MemoryAccessInfo = @bitCast(instruction.data); |
| 7508 | | try writer.print(" {s}{}{}", .{ @tagName(tag), info.scope, info.ordering }); |
| 7509 | | }, |
| 7510 | | .fneg, |
| 7511 | | .@"fneg fast", |
| 7512 | | .ret, |
| 7513 | | => |tag| { |
| 7514 | | const val: Value = @enumFromInt(instruction.data); |
| 7515 | | try writer.print(" {s} {%}\n", .{ |
| 7516 | | @tagName(tag), |
| 7517 | | val.fmt(function_index, self), |
| 7518 | | }); |
| 7519 | | }, |
| 7520 | | .getelementptr, |
| 7521 | | .@"getelementptr inbounds", |
| 7522 | | => |tag| { |
| 7523 | | var extra = function.extraDataTrail( |
| 7524 | | Function.Instruction.GetElementPtr, |
| 7525 | | instruction.data, |
| 7526 | | ); |
| 7527 | | const indices = extra.trail.next(extra.data.indices_len, Value, &function); |
| 7528 | | try writer.print(" %{} = {s} {%}, {%}", .{ |
| 7529 | | instruction_index.name(&function).fmt(self), |
| 7530 | | @tagName(tag), |
| 7531 | | extra.data.type.fmt(self), |
| 7532 | | extra.data.base.fmt(function_index, self), |
| 7533 | | }); |
| 7534 | | for (indices) |index| try writer.print(", {%}", .{ |
| 7535 | | index.fmt(function_index, self), |
| 7536 | | }); |
| 7537 | | try writer.writeByte('\n'); |
| 7538 | | }, |
| 7539 | | .insertelement => |tag| { |
| 7540 | | const extra = |
| 7541 | | function.extraData(Function.Instruction.InsertElement, instruction.data); |
| 7542 | | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ |
| 7543 | | instruction_index.name(&function).fmt(self), |
| 7544 | | @tagName(tag), |
| 7545 | | extra.val.fmt(function_index, self), |
| 7546 | | extra.elem.fmt(function_index, self), |
| 7547 | | extra.index.fmt(function_index, self), |
| 7548 | | }); |
| 7549 | | }, |
| 7550 | | .insertvalue => |tag| { |
| 7551 | | var extra = |
| 7552 | | function.extraDataTrail(Function.Instruction.InsertValue, instruction.data); |
| 7553 | | const indices = extra.trail.next(extra.data.indices_len, u32, &function); |
| 7554 | | try writer.print(" %{} = {s} {%}, {%}", .{ |
| 7555 | | instruction_index.name(&function).fmt(self), |
| 7556 | | @tagName(tag), |
| 7557 | | extra.data.val.fmt(function_index, self), |
| 7558 | | extra.data.elem.fmt(function_index, self), |
| 7559 | | }); |
| 7560 | | for (indices) |index| try writer.print(", {d}", .{index}); |
| 7561 | | try writer.writeByte('\n'); |
| 7562 | | }, |
| 7563 | | .@"llvm.maxnum.", |
| 7564 | | .@"llvm.minnum.", |
| 7565 | | .@"llvm.sadd.sat.", |
| 7566 | | .@"llvm.smax.", |
| 7567 | | .@"llvm.smin.", |
| 7568 | | .@"llvm.smul.fix.sat.", |
| 7569 | | .@"llvm.sshl.sat.", |
| 7570 | | .@"llvm.ssub.sat.", |
| 7571 | | .@"llvm.uadd.sat.", |
| 7572 | | .@"llvm.umax.", |
| 7573 | | .@"llvm.umin.", |
| 7574 | | .@"llvm.umul.fix.sat.", |
| 7575 | | .@"llvm.ushl.sat.", |
| 7576 | | .@"llvm.usub.sat.", |
| 7577 | | => |tag| { |
| 7578 | | const extra = function.extraData(Function.Instruction.Binary, instruction.data); |
| 7579 | | const ty = instruction_index.typeOf(function_index, self); |
| 7580 | | try writer.print(" %{} = call {%} @{s}{m}({%}, {%}{s})\n", .{ |
| 7581 | | instruction_index.name(&function).fmt(self), |
| 7582 | | ty.fmt(self), |
| 7583 | | @tagName(tag), |
| 7584 | | ty.fmt(self), |
| 7585 | | extra.lhs.fmt(function_index, self), |
| 7586 | | extra.rhs.fmt(function_index, self), |
| 7587 | | switch (tag) { |
| 7588 | | .@"llvm.smul.fix.sat.", |
| 7589 | | .@"llvm.umul.fix.sat.", |
| 7590 | | => ", i32 0", |
| 7591 | | else => "", |
| 7592 | | }, |
| 7593 | | }); |
| 7594 | | }, |
| 7595 | | .load, |
| 7596 | | .@"load atomic", |
| 7597 | | .@"load atomic volatile", |
| 7598 | | .@"load volatile", |
| 7599 | | => |tag| { |
| 7600 | | const extra = function.extraData(Function.Instruction.Load, instruction.data); |
| 7601 | | try writer.print(" %{} = {s} {%}, {%}{}{}{,}\n", .{ |
| 7602 | | instruction_index.name(&function).fmt(self), |
| 7603 | | @tagName(tag), |
| 7604 | | extra.type.fmt(self), |
| 7605 | | extra.ptr.fmt(function_index, self), |
| 7606 | | extra.info.scope, |
| 7607 | | extra.info.ordering, |
| 7608 | | extra.info.alignment, |
| 7609 | | }); |
| 7610 | | }, |
| 7611 | | .phi, |
| 7612 | | .@"phi fast", |
| 7613 | | => |tag| { |
| 7614 | | var extra = function.extraDataTrail(Function.Instruction.Phi, instruction.data); |
| 7615 | | const vals = extra.trail.next(block_incoming_len, Value, &function); |
| 7616 | | const blocks = |
| 7617 | | extra.trail.next(block_incoming_len, Function.Block.Index, &function); |
| 7618 | | try writer.print(" %{} = {s} {%} ", .{ |
| 7619 | | instruction_index.name(&function).fmt(self), |
| 7620 | | @tagName(tag), |
| 7621 | | vals[0].typeOf(function_index, self).fmt(self), |
| 7622 | | }); |
| 7623 | | for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| { |
| 7624 | | if (incoming_index > 0) try writer.writeAll(", "); |
| 7625 | | try writer.print("[ {}, {} ]", .{ |
| 7626 | | incoming_val.fmt(function_index, self), |
| 7627 | | incoming_block.toInst(&function).fmt(function_index, self), |
| 7418 | }, |
| 7419 | .addrspacecast, |
| 7420 | .bitcast, |
| 7421 | .fpext, |
| 7422 | .fptosi, |
| 7423 | .fptoui, |
| 7424 | .fptrunc, |
| 7425 | .inttoptr, |
| 7426 | .ptrtoint, |
| 7427 | .sext, |
| 7428 | .sitofp, |
| 7429 | .trunc, |
| 7430 | .uitofp, |
| 7431 | .zext, |
| 7432 | => |tag| { |
| 7433 | const extra = |
| 7434 | function.extraData(Function.Instruction.Cast, instruction.data); |
| 7435 | try writer.print(" %{} = {s} {%} to {%}\n", .{ |
| 7436 | instruction_index.name(&function).fmt(self), |
| 7437 | @tagName(tag), |
| 7438 | extra.val.fmt(function_index, self), |
| 7439 | extra.type.fmt(self), |
| 7628 | 7440 | }); |
| 7629 | | } |
| 7630 | | try writer.writeByte('\n'); |
| 7631 | | }, |
| 7632 | | .@"ret void", |
| 7633 | | .@"unreachable", |
| 7634 | | => |tag| try writer.print(" {s}\n", .{@tagName(tag)}), |
| 7635 | | .select, |
| 7636 | | .@"select fast", |
| 7637 | | => |tag| { |
| 7638 | | const extra = function.extraData(Function.Instruction.Select, instruction.data); |
| 7639 | | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ |
| 7640 | | instruction_index.name(&function).fmt(self), |
| 7641 | | @tagName(tag), |
| 7642 | | extra.cond.fmt(function_index, self), |
| 7643 | | extra.lhs.fmt(function_index, self), |
| 7644 | | extra.rhs.fmt(function_index, self), |
| 7645 | | }); |
| 7646 | | }, |
| 7647 | | .shufflevector => |tag| { |
| 7648 | | const extra = |
| 7649 | | function.extraData(Function.Instruction.ShuffleVector, instruction.data); |
| 7650 | | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ |
| 7651 | | instruction_index.name(&function).fmt(self), |
| 7652 | | @tagName(tag), |
| 7653 | | extra.lhs.fmt(function_index, self), |
| 7654 | | extra.rhs.fmt(function_index, self), |
| 7655 | | extra.mask.fmt(function_index, self), |
| 7656 | | }); |
| 7657 | | }, |
| 7658 | | .store, |
| 7659 | | .@"store atomic", |
| 7660 | | .@"store atomic volatile", |
| 7661 | | .@"store volatile", |
| 7662 | | => |tag| { |
| 7663 | | const extra = function.extraData(Function.Instruction.Store, instruction.data); |
| 7664 | | try writer.print(" {s} {%}, {%}{}{}{,}\n", .{ |
| 7665 | | @tagName(tag), |
| 7666 | | extra.val.fmt(function_index, self), |
| 7667 | | extra.ptr.fmt(function_index, self), |
| 7668 | | extra.info.scope, |
| 7669 | | extra.info.ordering, |
| 7670 | | extra.info.alignment, |
| 7671 | | }); |
| 7672 | | }, |
| 7673 | | .@"switch" => |tag| { |
| 7674 | | var extra = |
| 7675 | | function.extraDataTrail(Function.Instruction.Switch, instruction.data); |
| 7676 | | const vals = extra.trail.next(extra.data.cases_len, Constant, &function); |
| 7677 | | const blocks = |
| 7678 | | extra.trail.next(extra.data.cases_len, Function.Block.Index, &function); |
| 7679 | | try writer.print(" {s} {%}, {%} [\n", .{ |
| 7680 | | @tagName(tag), |
| 7681 | | extra.data.val.fmt(function_index, self), |
| 7682 | | extra.data.default.toInst(&function).fmt(function_index, self), |
| 7683 | | }); |
| 7684 | | for (vals, blocks) |case_val, case_block| try writer.print(" {%}, {%}\n", .{ |
| 7685 | | case_val.fmt(self), |
| 7686 | | case_block.toInst(&function).fmt(function_index, self), |
| 7687 | | }); |
| 7688 | | try writer.writeAll(" ]\n"); |
| 7689 | | }, |
| 7690 | | .unimplemented => |tag| { |
| 7691 | | const ty: Type = @enumFromInt(instruction.data); |
| 7692 | | if (true) { |
| 7441 | }, |
| 7442 | .alloca, |
| 7443 | .@"alloca inalloca", |
| 7444 | => |tag| { |
| 7445 | const extra = |
| 7446 | function.extraData(Function.Instruction.Alloca, instruction.data); |
| 7447 | try writer.print(" %{} = {s} {%}{,%}{,}{,}\n", .{ |
| 7448 | instruction_index.name(&function).fmt(self), |
| 7449 | @tagName(tag), |
| 7450 | extra.type.fmt(self), |
| 7451 | extra.len.fmt(function_index, self), |
| 7452 | extra.info.alignment, |
| 7453 | extra.info.addr_space, |
| 7454 | }); |
| 7455 | }, |
| 7456 | .arg => unreachable, |
| 7457 | .block => { |
| 7458 | block_incoming_len = instruction.data; |
| 7459 | const name = instruction_index.name(&function); |
| 7460 | if (@intFromEnum(instruction_index) > params_len) |
| 7461 | try writer.writeByte('\n'); |
| 7462 | try writer.print("{}:\n", .{name.fmt(self)}); |
| 7463 | }, |
| 7464 | .br => |tag| { |
| 7465 | const target: Function.Block.Index = @enumFromInt(instruction.data); |
| 7466 | try writer.print(" {s} {%}\n", .{ |
| 7467 | @tagName(tag), target.toInst(&function).fmt(function_index, self), |
| 7468 | }); |
| 7469 | }, |
| 7470 | .br_cond => { |
| 7471 | const extra = |
| 7472 | function.extraData(Function.Instruction.BrCond, instruction.data); |
| 7473 | try writer.print(" br {%}, {%}, {%}\n", .{ |
| 7474 | extra.cond.fmt(function_index, self), |
| 7475 | extra.then.toInst(&function).fmt(function_index, self), |
| 7476 | extra.@"else".toInst(&function).fmt(function_index, self), |
| 7477 | }); |
| 7478 | }, |
| 7479 | .call, |
| 7480 | .@"call fast", |
| 7481 | .@"musttail call", |
| 7482 | .@"musttail call fast", |
| 7483 | .@"notail call", |
| 7484 | .@"notail call fast", |
| 7485 | .@"tail call", |
| 7486 | .@"tail call fast", |
| 7487 | => |tag| { |
| 7488 | var extra = |
| 7489 | function.extraDataTrail(Function.Instruction.Call, instruction.data); |
| 7490 | const args = extra.trail.next(extra.data.args_len, Value, &function); |
| 7693 | 7491 | try writer.writeAll(" "); |
| 7694 | | switch (ty) { |
| 7695 | | .none, .void => {}, |
| 7492 | const ret_ty = extra.data.ty.functionReturn(self); |
| 7493 | switch (ret_ty) { |
| 7494 | .void => {}, |
| 7696 | 7495 | else => try writer.print("%{} = ", .{ |
| 7697 | 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) }); |
| 7701 | | } else switch (ty) { |
| 7702 | | .none, .void => {}, |
| 7703 | | else => try writer.print(" %{} = load {%}, ptr undef\n", .{ |
| 7519 | try writer.writeByte(')'); |
| 7520 | const call_function_attributes = extra.data.attributes.func(self); |
| 7521 | if (call_function_attributes != .none) try writer.print(" #{d}", .{ |
| 7522 | (try attribute_groups.getOrPutValue( |
| 7523 | self.gpa, |
| 7524 | call_function_attributes, |
| 7525 | {}, |
| 7526 | )).index, |
| 7527 | }); |
| 7528 | try writer.writeByte('\n'); |
| 7529 | }, |
| 7530 | .extractelement => |tag| { |
| 7531 | const extra = function.extraData( |
| 7532 | Function.Instruction.ExtractElement, |
| 7533 | instruction.data, |
| 7534 | ); |
| 7535 | try writer.print(" %{} = {s} {%}, {%}\n", .{ |
| 7536 | instruction_index.name(&function).fmt(self), |
| 7537 | @tagName(tag), |
| 7538 | extra.val.fmt(function_index, self), |
| 7539 | extra.index.fmt(function_index, self), |
| 7540 | }); |
| 7541 | }, |
| 7542 | .extractvalue => |tag| { |
| 7543 | var extra = function.extraDataTrail( |
| 7544 | Function.Instruction.ExtractValue, |
| 7545 | instruction.data, |
| 7546 | ); |
| 7547 | const indices = extra.trail.next(extra.data.indices_len, u32, &function); |
| 7548 | try writer.print(" %{} = {s} {%}", .{ |
| 7549 | instruction_index.name(&function).fmt(self), |
| 7550 | @tagName(tag), |
| 7551 | extra.data.val.fmt(function_index, self), |
| 7552 | }); |
| 7553 | for (indices) |index| try writer.print(", {d}", .{index}); |
| 7554 | try writer.writeByte('\n'); |
| 7555 | }, |
| 7556 | .fence => |tag| { |
| 7557 | const info: MemoryAccessInfo = @bitCast(instruction.data); |
| 7558 | try writer.print(" {s}{}{}", .{ @tagName(tag), info.scope, info.ordering }); |
| 7559 | }, |
| 7560 | .fneg, |
| 7561 | .@"fneg fast", |
| 7562 | .ret, |
| 7563 | => |tag| { |
| 7564 | const val: Value = @enumFromInt(instruction.data); |
| 7565 | try writer.print(" {s} {%}\n", .{ |
| 7566 | @tagName(tag), |
| 7567 | val.fmt(function_index, self), |
| 7568 | }); |
| 7569 | }, |
| 7570 | .getelementptr, |
| 7571 | .@"getelementptr inbounds", |
| 7572 | => |tag| { |
| 7573 | var extra = function.extraDataTrail( |
| 7574 | Function.Instruction.GetElementPtr, |
| 7575 | instruction.data, |
| 7576 | ); |
| 7577 | const indices = extra.trail.next(extra.data.indices_len, Value, &function); |
| 7578 | try writer.print(" %{} = {s} {%}, {%}", .{ |
| 7579 | instruction_index.name(&function).fmt(self), |
| 7580 | @tagName(tag), |
| 7581 | extra.data.type.fmt(self), |
| 7582 | extra.data.base.fmt(function_index, self), |
| 7583 | }); |
| 7584 | for (indices) |index| try writer.print(", {%}", .{ |
| 7585 | index.fmt(function_index, self), |
| 7586 | }); |
| 7587 | try writer.writeByte('\n'); |
| 7588 | }, |
| 7589 | .insertelement => |tag| { |
| 7590 | const extra = function.extraData( |
| 7591 | Function.Instruction.InsertElement, |
| 7592 | instruction.data, |
| 7593 | ); |
| 7594 | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ |
| 7595 | instruction_index.name(&function).fmt(self), |
| 7596 | @tagName(tag), |
| 7597 | extra.val.fmt(function_index, self), |
| 7598 | extra.elem.fmt(function_index, self), |
| 7599 | extra.index.fmt(function_index, self), |
| 7600 | }); |
| 7601 | }, |
| 7602 | .insertvalue => |tag| { |
| 7603 | var extra = function.extraDataTrail( |
| 7604 | Function.Instruction.InsertValue, |
| 7605 | instruction.data, |
| 7606 | ); |
| 7607 | const indices = extra.trail.next(extra.data.indices_len, u32, &function); |
| 7608 | try writer.print(" %{} = {s} {%}, {%}", .{ |
| 7609 | instruction_index.name(&function).fmt(self), |
| 7610 | @tagName(tag), |
| 7611 | extra.data.val.fmt(function_index, self), |
| 7612 | extra.data.elem.fmt(function_index, self), |
| 7613 | }); |
| 7614 | for (indices) |index| try writer.print(", {d}", .{index}); |
| 7615 | try writer.writeByte('\n'); |
| 7616 | }, |
| 7617 | .@"llvm.maxnum.", |
| 7618 | .@"llvm.minnum.", |
| 7619 | .@"llvm.sadd.sat.", |
| 7620 | .@"llvm.smax.", |
| 7621 | .@"llvm.smin.", |
| 7622 | .@"llvm.smul.fix.sat.", |
| 7623 | .@"llvm.sshl.sat.", |
| 7624 | .@"llvm.ssub.sat.", |
| 7625 | .@"llvm.uadd.sat.", |
| 7626 | .@"llvm.umax.", |
| 7627 | .@"llvm.umin.", |
| 7628 | .@"llvm.umul.fix.sat.", |
| 7629 | .@"llvm.ushl.sat.", |
| 7630 | .@"llvm.usub.sat.", |
| 7631 | => |tag| { |
| 7632 | const extra = |
| 7633 | function.extraData(Function.Instruction.Binary, instruction.data); |
| 7634 | const ty = instruction_index.typeOf(function_index, self); |
| 7635 | try writer.print(" %{} = call {%} @{s}{m}({%}, {%}{s})\n", .{ |
| 7704 | 7636 | instruction_index.name(&function).fmt(self), |
| 7705 | 7637 | ty.fmt(self), |
| 7706 | | }), |
| 7707 | | } |
| 7708 | | }, |
| 7709 | | .va_arg => |tag| { |
| 7710 | | const extra = function.extraData(Function.Instruction.VaArg, instruction.data); |
| 7711 | | try writer.print(" %{} = {s} {%}, {%}\n", .{ |
| 7712 | | instruction_index.name(&function).fmt(self), |
| 7713 | | @tagName(tag), |
| 7714 | | extra.list.fmt(function_index, self), |
| 7715 | | extra.type.fmt(self), |
| 7716 | | }); |
| 7717 | | }, |
| 7638 | @tagName(tag), |
| 7639 | ty.fmt(self), |
| 7640 | extra.lhs.fmt(function_index, self), |
| 7641 | extra.rhs.fmt(function_index, self), |
| 7642 | switch (tag) { |
| 7643 | .@"llvm.smul.fix.sat.", |
| 7644 | .@"llvm.umul.fix.sat.", |
| 7645 | => ", i32 0", |
| 7646 | else => "", |
| 7647 | }, |
| 7648 | }); |
| 7649 | }, |
| 7650 | .load, |
| 7651 | .@"load atomic", |
| 7652 | .@"load atomic volatile", |
| 7653 | .@"load volatile", |
| 7654 | => |tag| { |
| 7655 | const extra = |
| 7656 | function.extraData(Function.Instruction.Load, instruction.data); |
| 7657 | try writer.print(" %{} = {s} {%}, {%}{}{}{,}\n", .{ |
| 7658 | instruction_index.name(&function).fmt(self), |
| 7659 | @tagName(tag), |
| 7660 | extra.type.fmt(self), |
| 7661 | extra.ptr.fmt(function_index, self), |
| 7662 | extra.info.scope, |
| 7663 | extra.info.ordering, |
| 7664 | extra.info.alignment, |
| 7665 | }); |
| 7666 | }, |
| 7667 | .phi, |
| 7668 | .@"phi fast", |
| 7669 | => |tag| { |
| 7670 | var extra = |
| 7671 | function.extraDataTrail(Function.Instruction.Phi, instruction.data); |
| 7672 | const vals = extra.trail.next(block_incoming_len, Value, &function); |
| 7673 | const blocks = |
| 7674 | extra.trail.next(block_incoming_len, Function.Block.Index, &function); |
| 7675 | try writer.print(" %{} = {s} {%} ", .{ |
| 7676 | instruction_index.name(&function).fmt(self), |
| 7677 | @tagName(tag), |
| 7678 | vals[0].typeOf(function_index, self).fmt(self), |
| 7679 | }); |
| 7680 | for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| { |
| 7681 | if (incoming_index > 0) try writer.writeAll(", "); |
| 7682 | try writer.print("[ {}, {} ]", .{ |
| 7683 | incoming_val.fmt(function_index, self), |
| 7684 | incoming_block.toInst(&function).fmt(function_index, self), |
| 7685 | }); |
| 7686 | } |
| 7687 | try writer.writeByte('\n'); |
| 7688 | }, |
| 7689 | .@"ret void", |
| 7690 | .@"unreachable", |
| 7691 | => |tag| try writer.print(" {s}\n", .{@tagName(tag)}), |
| 7692 | .select, |
| 7693 | .@"select fast", |
| 7694 | => |tag| { |
| 7695 | const extra = |
| 7696 | function.extraData(Function.Instruction.Select, instruction.data); |
| 7697 | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ |
| 7698 | instruction_index.name(&function).fmt(self), |
| 7699 | @tagName(tag), |
| 7700 | extra.cond.fmt(function_index, self), |
| 7701 | extra.lhs.fmt(function_index, self), |
| 7702 | extra.rhs.fmt(function_index, self), |
| 7703 | }); |
| 7704 | }, |
| 7705 | .shufflevector => |tag| { |
| 7706 | const extra = function.extraData( |
| 7707 | Function.Instruction.ShuffleVector, |
| 7708 | instruction.data, |
| 7709 | ); |
| 7710 | try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ |
| 7711 | instruction_index.name(&function).fmt(self), |
| 7712 | @tagName(tag), |
| 7713 | extra.lhs.fmt(function_index, self), |
| 7714 | extra.rhs.fmt(function_index, self), |
| 7715 | extra.mask.fmt(function_index, self), |
| 7716 | }); |
| 7717 | }, |
| 7718 | .store, |
| 7719 | .@"store atomic", |
| 7720 | .@"store atomic volatile", |
| 7721 | .@"store volatile", |
| 7722 | => |tag| { |
| 7723 | const extra = |
| 7724 | function.extraData(Function.Instruction.Store, instruction.data); |
| 7725 | try writer.print(" {s} {%}, {%}{}{}{,}\n", .{ |
| 7726 | @tagName(tag), |
| 7727 | extra.val.fmt(function_index, self), |
| 7728 | extra.ptr.fmt(function_index, self), |
| 7729 | extra.info.scope, |
| 7730 | extra.info.ordering, |
| 7731 | extra.info.alignment, |
| 7732 | }); |
| 7733 | }, |
| 7734 | .@"switch" => |tag| { |
| 7735 | var extra = |
| 7736 | function.extraDataTrail(Function.Instruction.Switch, instruction.data); |
| 7737 | const vals = extra.trail.next(extra.data.cases_len, Constant, &function); |
| 7738 | const blocks = |
| 7739 | extra.trail.next(extra.data.cases_len, Function.Block.Index, &function); |
| 7740 | try writer.print(" {s} {%}, {%} [\n", .{ |
| 7741 | @tagName(tag), |
| 7742 | extra.data.val.fmt(function_index, self), |
| 7743 | extra.data.default.toInst(&function).fmt(function_index, self), |
| 7744 | }); |
| 7745 | for (vals, blocks) |case_val, case_block| try writer.print( |
| 7746 | " {%}, {%}\n", |
| 7747 | .{ |
| 7748 | case_val.fmt(self), |
| 7749 | case_block.toInst(&function).fmt(function_index, self), |
| 7750 | }, |
| 7751 | ); |
| 7752 | try writer.writeAll(" ]\n"); |
| 7753 | }, |
| 7754 | .unimplemented => |tag| { |
| 7755 | const ty: Type = @enumFromInt(instruction.data); |
| 7756 | if (true) { |
| 7757 | try writer.writeAll(" "); |
| 7758 | switch (ty) { |
| 7759 | .none, .void => {}, |
| 7760 | else => try writer.print("%{} = ", .{ |
| 7761 | instruction_index.name(&function).fmt(self), |
| 7762 | }), |
| 7763 | } |
| 7764 | try writer.print("{s} {%}\n", .{ @tagName(tag), ty.fmt(self) }); |
| 7765 | } else switch (ty) { |
| 7766 | .none, .void => {}, |
| 7767 | else => try writer.print(" %{} = load {%}, ptr undef\n", .{ |
| 7768 | instruction_index.name(&function).fmt(self), |
| 7769 | ty.fmt(self), |
| 7770 | }), |
| 7771 | } |
| 7772 | }, |
| 7773 | .va_arg => |tag| { |
| 7774 | const extra = |
| 7775 | function.extraData(Function.Instruction.VaArg, instruction.data); |
| 7776 | try writer.print(" %{} = {s} {%}, {%}\n", .{ |
| 7777 | instruction_index.name(&function).fmt(self), |
| 7778 | @tagName(tag), |
| 7779 | extra.list.fmt(function_index, self), |
| 7780 | extra.type.fmt(self), |
| 7781 | }); |
| 7782 | }, |
| 7783 | } |
| 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| |
| 7726 | | try writer.print( |
| 7727 | | \\attributes #{d} = {{{#"} }} |
| 7728 | | \\ |
| 7729 | | , .{ attribute_group_index, attribute_group.fmt(self) }); |
| 7792 | if (attribute_groups.count() > 0) { |
| 7793 | if (need_newline) try writer.writeByte('\n') else need_newline = true; |
| 7794 | for (0.., attribute_groups.keys()) |attribute_group_index, attribute_group| |
| 7795 | try writer.print( |
| 7796 | \\attributes #{d} = {{{#"} }} |
| 7797 | \\ |
| 7798 | , .{ attribute_group_index, attribute_group.fmt(self) }); |
| 7799 | need_newline = true; |
| 7800 | } |
| 7730 | 7801 | } |
| 7731 | 7802 | |
| 7732 | 7803 | pub inline fn useLibLlvm(self: *const Builder) bool { |
| ... | ... | @@ -7736,7 +7807,7 @@ pub inline fn useLibLlvm(self: *const Builder) bool { |
| 7736 | 7807 | const NoExtra = struct {}; |
| 7737 | 7808 | |
| 7738 | 7809 | fn isValidIdentifier(id: []const u8) bool { |
| 7739 | | for (id, 0..) |character, index| switch (character) { |
| 7810 | for (id, 0..) |byte, index| switch (byte) { |
| 7740 | 7811 | '$', '-', '.', 'A'...'Z', '_', 'a'...'z' => {}, |
| 7741 | 7812 | '0'...'9' => if (index == 0) return false, |
| 7742 | 7813 | else => return false, |
| ... | ... | @@ -7744,6 +7815,25 @@ fn isValidIdentifier(id: []const u8) bool { |
| 7744 | 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 | 7837 | fn ensureUnusedGlobalCapacity(self: *Builder, name: String) Allocator.Error!void { |
| 7748 | 7838 | if (self.useLibLlvm()) try self.llvm.globals.ensureUnusedCapacity(self.gpa, 1); |
| 7749 | 7839 | try self.string_map.ensureUnusedCapacity(self.gpa, 1); |
| ... | ... | @@ -9318,6 +9408,8 @@ fn asmConstAssumeCapacity( |
| 9318 | 9408 | assembly: String, |
| 9319 | 9409 | constraints: String, |
| 9320 | 9410 | ) Constant { |
| 9411 | assert(ty.functionKind(self) == .normal); |
| 9412 | |
| 9321 | 9413 | const Key = struct { tag: Constant.Tag, extra: Constant.Asm }; |
| 9322 | 9414 | const Adapter = struct { |
| 9323 | 9415 | builder: *const Builder, |