From 35cd56a3693d55eedb80e8bd1538420597b05ff5 Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Tue, 8 Aug 2023 11:40:51 -0400 Subject: [PATCH] llvm: fix alias issues --- src/codegen/llvm.zig | 23 +- src/codegen/llvm/Builder.zig | 1021 +++++++++++++++++----------------- 2 files changed, 529 insertions(+), 515 deletions(-) diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index a443a2184e..d5856bcb52 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -1079,7 +1079,8 @@ pub const Object = struct { // Same logic as below but for externs instead of exports. const decl_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(mod.declPtr(decl_index).name)) orelse continue; const other_global = object.builder.getGlobal(decl_name) orelse continue; - if (other_global.eql(global, &object.builder)) continue; + if (other_global.toConst().getBase(&object.builder) == + global.toConst().getBase(&object.builder)) continue; try global.replace(other_global, &object.builder); } @@ -1087,13 +1088,14 @@ pub const Object = struct { for (mod.decl_exports.keys(), mod.decl_exports.values()) |decl_index, export_list| { const global = object.decl_map.get(decl_index) orelse continue; + const global_base = global.toConst().getBase(&object.builder); for (export_list.items) |exp| { // Detect if the LLVM global has already been created as an extern. In such // case, we need to replace all uses of it with this exported global. const exp_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(exp.opts.name)) orelse continue; const other_global = object.builder.getGlobal(exp_name) orelse continue; - if (other_global.eql(global, &object.builder)) continue; + if (other_global.toConst().getBase(&object.builder) == global_base) continue; try global.takeName(other_global, &object.builder); try other_global.replace(global, &object.builder); @@ -1714,7 +1716,7 @@ pub const Object = struct { try self.builder.string(section), &self.builder, ), - else => unreachable, + .alias, .replaced => unreachable, }; if (decl.val.getVariable(mod)) |decl_var| if (decl_var.is_threadlocal) global_index.ptrConst(&self.builder).kind @@ -1735,15 +1737,16 @@ pub const Object = struct { continue; }, .variable, .function => {}, - else => unreachable, + .replaced => unreachable, } } - _ = try self.builder.addAlias( - exp_name, + const alias_index = try self.builder.addAlias( + .empty, global_index.typeOf(&self.builder), .default, global_index.toConst(), ); + try alias_index.rename(exp_name, &self.builder); } } else { const fqn = try self.builder.string( @@ -7703,7 +7706,7 @@ pub const FuncGen = struct { if (o.builder.getGlobal(fn_name)) |global| return switch (global.ptrConst(&o.builder).kind) { .alias => |alias| alias.getAliasee(&o.builder).ptrConst(&o.builder).kind.function, .function => |function| function, - else => unreachable, + .variable, .replaced => unreachable, }; return o.builder.addFunction( try o.builder.fnType(return_type, param_types, .normal), @@ -7751,11 +7754,7 @@ pub const FuncGen = struct { }; const fn_name = try o.builder.fmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev }); - const libc_fn = try self.getLibcFunction( - fn_name, - ([1]Builder.Type{scalar_llvm_ty} ** 2)[0..], - .i32, - ); + const libc_fn = try self.getLibcFunction(fn_name, &.{ scalar_llvm_ty, scalar_llvm_ty }, .i32); const zero = try o.builder.intConst(.i32, 0); const int_cond: Builder.IntegerCondition = switch (pred) { diff --git a/src/codegen/llvm/Builder.zig b/src/codegen/llvm/Builder.zig index eb1df06c0b..316aca7a24 100644 --- a/src/codegen/llvm/Builder.zig +++ b/src/codegen/llvm/Builder.zig @@ -2320,6 +2320,10 @@ pub const Alias = struct { return self.ptrConst(builder).global.name(builder); } + pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void { + return self.ptrConst(builder).global.rename(new_name, builder); + } + pub fn typeOf(self: Index, builder: *const Builder) Type { return self.ptrConst(builder).global.typeOf(builder); } @@ -2373,6 +2377,10 @@ pub const Variable = struct { return self.ptrConst(builder).global.name(builder); } + pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void { + return self.ptrConst(builder).global.rename(new_name, builder); + } + pub fn typeOf(self: Index, builder: *const Builder) Type { return self.ptrConst(builder).global.typeOf(builder); } @@ -3812,6 +3820,10 @@ pub const Function = struct { return self.ptrConst(builder).global.name(builder); } + pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void { + return self.ptrConst(builder).global.rename(new_name, builder); + } + pub fn typeOf(self: Index, builder: *const Builder) Type { return self.ptrConst(builder).global.typeOf(builder); } @@ -9393,521 +9405,524 @@ pub fn printUnbuffered( need_newline = true; } - var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{}; - defer attribute_groups.deinit(self.gpa); - - if (self.functions.items.len > 0) { + if (self.aliases.items.len > 0) { if (need_newline) try writer.writeByte('\n'); - for (0.., self.functions.items) |function_i, function| { - if (function_i > 0) try writer.writeByte('\n'); - const function_index: Function.Index = @enumFromInt(function_i); - if (function.global.getReplacement(self) != .none) continue; - const global = function.global.ptrConst(self); - const params_len = global.type.functionParameters(self).len; - const function_attributes = function.attributes.func(self); - if (function_attributes != .none) try writer.print( - \\; Function Attrs:{} - \\ - , .{function_attributes.fmt(self)}); + for (self.aliases.items) |alias| { + if (alias.global.getReplacement(self) != .none) continue; + const global = alias.global.ptrConst(self); try writer.print( - \\{s}{}{}{}{}{}{"} {} {}( + \\{} ={}{}{}{}{ }{} alias {%}, {%} + \\ , .{ - if (function.instructions.len > 0) "define" else "declare", + alias.global.fmt(self), global.linkage, global.preemption, global.visibility, global.dll_storage_class, - function.call_conv, - function.attributes.ret(self).fmt(self), - global.type.functionReturn(self).fmt(self), - function.global.fmt(self), + alias.thread_local, + global.unnamed_addr, + global.type.fmt(self), + alias.aliasee.fmt(self), }); - for (0..params_len) |arg| { - if (arg > 0) try writer.writeAll(", "); - try writer.print( - \\{%}{"} - , .{ - global.type.functionParameters(self)[arg].fmt(self), - function.attributes.param(arg, self).fmt(self), - }); - if (function.instructions.len > 0) - try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)}) - else - try writer.print(" %{d}", .{arg}); - } - switch (global.type.functionKind(self)) { - .normal => {}, - .vararg => { - if (params_len > 0) try writer.writeAll(", "); - try writer.writeAll("..."); - }, - } - try writer.print("){}{ }", .{ global.unnamed_addr, global.addr_space }); - if (function_attributes != .none) try writer.print(" #{d}", .{ - (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index, - }); - try writer.print("{ }", .{function.alignment}); - if (function.instructions.len > 0) { - var block_incoming_len: u32 = undefined; - try writer.writeAll(" {\n"); - for (params_len..function.instructions.len) |instruction_i| { - const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i); - const instruction = function.instructions.get(@intFromEnum(instruction_index)); - switch (instruction.tag) { - .add, - .@"add nsw", - .@"add nuw", - .@"add nuw nsw", - .@"and", - .ashr, - .@"ashr exact", - .fadd, - .@"fadd fast", - .@"fcmp false", - .@"fcmp fast false", - .@"fcmp fast oeq", - .@"fcmp fast oge", - .@"fcmp fast ogt", - .@"fcmp fast ole", - .@"fcmp fast olt", - .@"fcmp fast one", - .@"fcmp fast ord", - .@"fcmp fast true", - .@"fcmp fast ueq", - .@"fcmp fast uge", - .@"fcmp fast ugt", - .@"fcmp fast ule", - .@"fcmp fast ult", - .@"fcmp fast une", - .@"fcmp fast uno", - .@"fcmp oeq", - .@"fcmp oge", - .@"fcmp ogt", - .@"fcmp ole", - .@"fcmp olt", - .@"fcmp one", - .@"fcmp ord", - .@"fcmp true", - .@"fcmp ueq", - .@"fcmp uge", - .@"fcmp ugt", - .@"fcmp ule", - .@"fcmp ult", - .@"fcmp une", - .@"fcmp uno", - .fdiv, - .@"fdiv fast", - .fmul, - .@"fmul fast", - .frem, - .@"frem fast", - .fsub, - .@"fsub fast", - .@"icmp eq", - .@"icmp ne", - .@"icmp sge", - .@"icmp sgt", - .@"icmp sle", - .@"icmp slt", - .@"icmp uge", - .@"icmp ugt", - .@"icmp ule", - .@"icmp ult", - .lshr, - .@"lshr exact", - .mul, - .@"mul nsw", - .@"mul nuw", - .@"mul nuw nsw", - .@"or", - .sdiv, - .@"sdiv exact", - .srem, - .shl, - .@"shl nsw", - .@"shl nuw", - .@"shl nuw nsw", - .sub, - .@"sub nsw", - .@"sub nuw", - .@"sub nuw nsw", - .udiv, - .@"udiv exact", - .urem, - .xor, - => |tag| { - const extra = - function.extraData(Function.Instruction.Binary, instruction.data); - try writer.print(" %{} = {s} {%}, {}\n", .{ - instruction_index.name(&function).fmt(self), - @tagName(tag), - extra.lhs.fmt(function_index, self), - extra.rhs.fmt(function_index, self), - }); - }, - .addrspacecast, - .bitcast, - .fpext, - .fptosi, - .fptoui, - .fptrunc, - .inttoptr, - .ptrtoint, - .sext, - .sitofp, - .trunc, - .uitofp, - .zext, - => |tag| { - const extra = - function.extraData(Function.Instruction.Cast, instruction.data); - try writer.print(" %{} = {s} {%} to {%}\n", .{ - instruction_index.name(&function).fmt(self), - @tagName(tag), - extra.val.fmt(function_index, self), - extra.type.fmt(self), - }); - }, - .alloca, - .@"alloca inalloca", - => |tag| { - const extra = - function.extraData(Function.Instruction.Alloca, instruction.data); - try writer.print(" %{} = {s} {%}{,%}{, }{, }\n", .{ - instruction_index.name(&function).fmt(self), - @tagName(tag), - extra.type.fmt(self), - extra.len.fmt(function_index, self), - extra.info.alignment, - extra.info.addr_space, - }); - }, - .arg => unreachable, - .atomicrmw => |tag| { - const extra = - function.extraData(Function.Instruction.AtomicRmw, instruction.data); - try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }\n", .{ - instruction_index.name(&function).fmt(self), - @tagName(tag), - extra.info.access_kind, - @tagName(extra.info.atomic_rmw_operation), - extra.ptr.fmt(function_index, self), - extra.val.fmt(function_index, self), - extra.info.sync_scope, - extra.info.success_ordering, - extra.info.alignment, - }); - }, - .block => { - block_incoming_len = instruction.data; - const name = instruction_index.name(&function); - if (@intFromEnum(instruction_index) > params_len) - try writer.writeByte('\n'); - try writer.print("{}:\n", .{name.fmt(self)}); - }, - .br => |tag| { - const target: Function.Block.Index = @enumFromInt(instruction.data); - try writer.print(" {s} {%}\n", .{ - @tagName(tag), target.toInst(&function).fmt(function_index, self), - }); - }, - .br_cond => { - const extra = - function.extraData(Function.Instruction.BrCond, instruction.data); - try writer.print(" br {%}, {%}, {%}\n", .{ - extra.cond.fmt(function_index, self), - extra.then.toInst(&function).fmt(function_index, self), - extra.@"else".toInst(&function).fmt(function_index, self), - }); - }, - .call, - .@"call fast", - .@"musttail call", - .@"musttail call fast", - .@"notail call", - .@"notail call fast", - .@"tail call", - .@"tail call fast", - => |tag| { - var extra = - function.extraDataTrail(Function.Instruction.Call, instruction.data); - const args = extra.trail.next(extra.data.args_len, Value, &function); - try writer.writeAll(" "); - const ret_ty = extra.data.ty.functionReturn(self); - switch (ret_ty) { - .void => {}, - else => try writer.print("%{} = ", .{ - instruction_index.name(&function).fmt(self), - }), - .none => unreachable, - } - try writer.print("{s}{}{}{} {%} {}(", .{ - @tagName(tag), - extra.data.info.call_conv, - extra.data.attributes.ret(self).fmt(self), - extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self), - switch (extra.data.ty.functionKind(self)) { - .normal => ret_ty, - .vararg => extra.data.ty, - }.fmt(self), - extra.data.callee.fmt(function_index, self), - }); - for (0.., args) |arg_index, arg| { - if (arg_index > 0) try writer.writeAll(", "); - try writer.print("{%}{} {}", .{ - arg.typeOf(function_index, self).fmt(self), - extra.data.attributes.param(arg_index, self).fmt(self), - arg.fmt(function_index, self), - }); - } - try writer.writeByte(')'); - const call_function_attributes = extra.data.attributes.func(self); - if (call_function_attributes != .none) try writer.print(" #{d}", .{ - (try attribute_groups.getOrPutValue( - self.gpa, - call_function_attributes, - {}, - )).index, - }); - try writer.writeByte('\n'); - }, - .cmpxchg, - .@"cmpxchg weak", - => |tag| { - const extra = - function.extraData(Function.Instruction.CmpXchg, instruction.data); - try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }\n", .{ - instruction_index.name(&function).fmt(self), - @tagName(tag), - extra.info.access_kind, - extra.ptr.fmt(function_index, self), - extra.cmp.fmt(function_index, self), - extra.new.fmt(function_index, self), - extra.info.sync_scope, - extra.info.success_ordering, - extra.info.failure_ordering, - extra.info.alignment, - }); - }, - .extractelement => |tag| { - const extra = function.extraData( - Function.Instruction.ExtractElement, - instruction.data, - ); - try writer.print(" %{} = {s} {%}, {%}\n", .{ - instruction_index.name(&function).fmt(self), - @tagName(tag), - extra.val.fmt(function_index, self), - extra.index.fmt(function_index, self), - }); - }, - .extractvalue => |tag| { - var extra = function.extraDataTrail( - Function.Instruction.ExtractValue, - instruction.data, - ); - const indices = extra.trail.next(extra.data.indices_len, u32, &function); - try writer.print(" %{} = {s} {%}", .{ - instruction_index.name(&function).fmt(self), - @tagName(tag), - extra.data.val.fmt(function_index, self), - }); - for (indices) |index| try writer.print(", {d}", .{index}); - try writer.writeByte('\n'); - }, - .fence => |tag| { - const info: MemoryAccessInfo = @bitCast(instruction.data); - try writer.print(" {s}{ }{ }", .{ - @tagName(tag), - info.sync_scope, - info.success_ordering, - }); - }, - .fneg, - .@"fneg fast", - => |tag| { - const val: Value = @enumFromInt(instruction.data); - try writer.print(" %{} = {s} {%}\n", .{ - instruction_index.name(&function).fmt(self), - @tagName(tag), - val.fmt(function_index, self), - }); - }, - .getelementptr, - .@"getelementptr inbounds", - => |tag| { - var extra = function.extraDataTrail( - Function.Instruction.GetElementPtr, - instruction.data, - ); - const indices = extra.trail.next(extra.data.indices_len, Value, &function); - try writer.print(" %{} = {s} {%}, {%}", .{ - instruction_index.name(&function).fmt(self), - @tagName(tag), - extra.data.type.fmt(self), - extra.data.base.fmt(function_index, self), - }); - for (indices) |index| try writer.print(", {%}", .{ - index.fmt(function_index, self), - }); - try writer.writeByte('\n'); - }, - .insertelement => |tag| { - const extra = function.extraData( - Function.Instruction.InsertElement, - instruction.data, - ); - try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ - instruction_index.name(&function).fmt(self), - @tagName(tag), - extra.val.fmt(function_index, self), - extra.elem.fmt(function_index, self), - extra.index.fmt(function_index, self), - }); - }, - .insertvalue => |tag| { - var extra = function.extraDataTrail( - Function.Instruction.InsertValue, - instruction.data, - ); - const indices = extra.trail.next(extra.data.indices_len, u32, &function); - try writer.print(" %{} = {s} {%}, {%}", .{ - instruction_index.name(&function).fmt(self), - @tagName(tag), - extra.data.val.fmt(function_index, self), - extra.data.elem.fmt(function_index, self), - }); - for (indices) |index| try writer.print(", {d}", .{index}); - try writer.writeByte('\n'); - }, - .load, - .@"load atomic", - => |tag| { - const extra = - function.extraData(Function.Instruction.Load, instruction.data); - try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }\n", .{ - instruction_index.name(&function).fmt(self), - @tagName(tag), - extra.info.access_kind, - extra.type.fmt(self), - extra.ptr.fmt(function_index, self), - extra.info.sync_scope, - extra.info.success_ordering, - extra.info.alignment, - }); - }, - .phi, - .@"phi fast", - => |tag| { - var extra = - function.extraDataTrail(Function.Instruction.Phi, instruction.data); - const vals = extra.trail.next(block_incoming_len, Value, &function); - const blocks = - extra.trail.next(block_incoming_len, Function.Block.Index, &function); - try writer.print(" %{} = {s} {%} ", .{ - instruction_index.name(&function).fmt(self), - @tagName(tag), - vals[0].typeOf(function_index, self).fmt(self), - }); - for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| { - if (incoming_index > 0) try writer.writeAll(", "); - try writer.print("[ {}, {} ]", .{ - incoming_val.fmt(function_index, self), - incoming_block.toInst(&function).fmt(function_index, self), - }); - } - try writer.writeByte('\n'); - }, - .ret => |tag| { - const val: Value = @enumFromInt(instruction.data); - try writer.print(" {s} {%}\n", .{ - @tagName(tag), - val.fmt(function_index, self), - }); - }, - .@"ret void", - .@"unreachable", - => |tag| try writer.print(" {s}\n", .{@tagName(tag)}), - .select, - .@"select fast", - => |tag| { - const extra = - function.extraData(Function.Instruction.Select, instruction.data); - try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ - instruction_index.name(&function).fmt(self), - @tagName(tag), - extra.cond.fmt(function_index, self), - extra.lhs.fmt(function_index, self), - extra.rhs.fmt(function_index, self), - }); - }, - .shufflevector => |tag| { - const extra = function.extraData( - Function.Instruction.ShuffleVector, - instruction.data, - ); - try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ - instruction_index.name(&function).fmt(self), - @tagName(tag), - extra.lhs.fmt(function_index, self), - extra.rhs.fmt(function_index, self), - extra.mask.fmt(function_index, self), - }); - }, - .store, - .@"store atomic", - => |tag| { - const extra = - function.extraData(Function.Instruction.Store, instruction.data); - try writer.print(" {s}{ } {%}, {%}{ }{ }{, }\n", .{ - @tagName(tag), - extra.info.access_kind, - extra.val.fmt(function_index, self), - extra.ptr.fmt(function_index, self), - extra.info.sync_scope, - extra.info.success_ordering, - extra.info.alignment, - }); - }, - .@"switch" => |tag| { - var extra = - function.extraDataTrail(Function.Instruction.Switch, instruction.data); - const vals = extra.trail.next(extra.data.cases_len, Constant, &function); - const blocks = - extra.trail.next(extra.data.cases_len, Function.Block.Index, &function); - try writer.print(" {s} {%}, {%} [\n", .{ - @tagName(tag), - extra.data.val.fmt(function_index, self), - extra.data.default.toInst(&function).fmt(function_index, self), - }); - for (vals, blocks) |case_val, case_block| try writer.print( - " {%}, {%}\n", - .{ - case_val.fmt(self), - case_block.toInst(&function).fmt(function_index, self), - }, - ); - try writer.writeAll(" ]\n"); - }, - .va_arg => |tag| { - const extra = - function.extraData(Function.Instruction.VaArg, instruction.data); - try writer.print(" %{} = {s} {%}, {%}\n", .{ - instruction_index.name(&function).fmt(self), - @tagName(tag), - extra.list.fmt(function_index, self), - extra.type.fmt(self), - }); - }, - } - } - try writer.writeByte('}'); - } - try writer.writeByte('\n'); } need_newline = true; } + var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{}; + defer attribute_groups.deinit(self.gpa); + + for (0.., self.functions.items) |function_i, function| { + if (function.global.getReplacement(self) != .none) continue; + if (need_newline) try writer.writeByte('\n'); + const function_index: Function.Index = @enumFromInt(function_i); + const global = function.global.ptrConst(self); + const params_len = global.type.functionParameters(self).len; + const function_attributes = function.attributes.func(self); + if (function_attributes != .none) try writer.print( + \\; Function Attrs:{} + \\ + , .{function_attributes.fmt(self)}); + try writer.print( + \\{s}{}{}{}{}{}{"} {} {}( + , .{ + if (function.instructions.len > 0) "define" else "declare", + global.linkage, + global.preemption, + global.visibility, + global.dll_storage_class, + function.call_conv, + function.attributes.ret(self).fmt(self), + global.type.functionReturn(self).fmt(self), + function.global.fmt(self), + }); + for (0..params_len) |arg| { + if (arg > 0) try writer.writeAll(", "); + try writer.print( + \\{%}{"} + , .{ + global.type.functionParameters(self)[arg].fmt(self), + function.attributes.param(arg, self).fmt(self), + }); + if (function.instructions.len > 0) + try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)}) + else + try writer.print(" %{d}", .{arg}); + } + switch (global.type.functionKind(self)) { + .normal => {}, + .vararg => { + if (params_len > 0) try writer.writeAll(", "); + try writer.writeAll("..."); + }, + } + try writer.print("){}{ }", .{ global.unnamed_addr, global.addr_space }); + if (function_attributes != .none) try writer.print(" #{d}", .{ + (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index, + }); + try writer.print("{ }", .{function.alignment}); + if (function.instructions.len > 0) { + var block_incoming_len: u32 = undefined; + try writer.writeAll(" {\n"); + for (params_len..function.instructions.len) |instruction_i| { + const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i); + const instruction = function.instructions.get(@intFromEnum(instruction_index)); + switch (instruction.tag) { + .add, + .@"add nsw", + .@"add nuw", + .@"add nuw nsw", + .@"and", + .ashr, + .@"ashr exact", + .fadd, + .@"fadd fast", + .@"fcmp false", + .@"fcmp fast false", + .@"fcmp fast oeq", + .@"fcmp fast oge", + .@"fcmp fast ogt", + .@"fcmp fast ole", + .@"fcmp fast olt", + .@"fcmp fast one", + .@"fcmp fast ord", + .@"fcmp fast true", + .@"fcmp fast ueq", + .@"fcmp fast uge", + .@"fcmp fast ugt", + .@"fcmp fast ule", + .@"fcmp fast ult", + .@"fcmp fast une", + .@"fcmp fast uno", + .@"fcmp oeq", + .@"fcmp oge", + .@"fcmp ogt", + .@"fcmp ole", + .@"fcmp olt", + .@"fcmp one", + .@"fcmp ord", + .@"fcmp true", + .@"fcmp ueq", + .@"fcmp uge", + .@"fcmp ugt", + .@"fcmp ule", + .@"fcmp ult", + .@"fcmp une", + .@"fcmp uno", + .fdiv, + .@"fdiv fast", + .fmul, + .@"fmul fast", + .frem, + .@"frem fast", + .fsub, + .@"fsub fast", + .@"icmp eq", + .@"icmp ne", + .@"icmp sge", + .@"icmp sgt", + .@"icmp sle", + .@"icmp slt", + .@"icmp uge", + .@"icmp ugt", + .@"icmp ule", + .@"icmp ult", + .lshr, + .@"lshr exact", + .mul, + .@"mul nsw", + .@"mul nuw", + .@"mul nuw nsw", + .@"or", + .sdiv, + .@"sdiv exact", + .srem, + .shl, + .@"shl nsw", + .@"shl nuw", + .@"shl nuw nsw", + .sub, + .@"sub nsw", + .@"sub nuw", + .@"sub nuw nsw", + .udiv, + .@"udiv exact", + .urem, + .xor, + => |tag| { + const extra = function.extraData(Function.Instruction.Binary, instruction.data); + try writer.print(" %{} = {s} {%}, {}\n", .{ + instruction_index.name(&function).fmt(self), + @tagName(tag), + extra.lhs.fmt(function_index, self), + extra.rhs.fmt(function_index, self), + }); + }, + .addrspacecast, + .bitcast, + .fpext, + .fptosi, + .fptoui, + .fptrunc, + .inttoptr, + .ptrtoint, + .sext, + .sitofp, + .trunc, + .uitofp, + .zext, + => |tag| { + const extra = function.extraData(Function.Instruction.Cast, instruction.data); + try writer.print(" %{} = {s} {%} to {%}\n", .{ + instruction_index.name(&function).fmt(self), + @tagName(tag), + extra.val.fmt(function_index, self), + extra.type.fmt(self), + }); + }, + .alloca, + .@"alloca inalloca", + => |tag| { + const extra = function.extraData(Function.Instruction.Alloca, instruction.data); + try writer.print(" %{} = {s} {%}{,%}{, }{, }\n", .{ + instruction_index.name(&function).fmt(self), + @tagName(tag), + extra.type.fmt(self), + extra.len.fmt(function_index, self), + extra.info.alignment, + extra.info.addr_space, + }); + }, + .arg => unreachable, + .atomicrmw => |tag| { + const extra = + function.extraData(Function.Instruction.AtomicRmw, instruction.data); + try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }\n", .{ + instruction_index.name(&function).fmt(self), + @tagName(tag), + extra.info.access_kind, + @tagName(extra.info.atomic_rmw_operation), + extra.ptr.fmt(function_index, self), + extra.val.fmt(function_index, self), + extra.info.sync_scope, + extra.info.success_ordering, + extra.info.alignment, + }); + }, + .block => { + block_incoming_len = instruction.data; + const name = instruction_index.name(&function); + if (@intFromEnum(instruction_index) > params_len) + try writer.writeByte('\n'); + try writer.print("{}:\n", .{name.fmt(self)}); + }, + .br => |tag| { + const target: Function.Block.Index = @enumFromInt(instruction.data); + try writer.print(" {s} {%}\n", .{ + @tagName(tag), target.toInst(&function).fmt(function_index, self), + }); + }, + .br_cond => { + const extra = function.extraData(Function.Instruction.BrCond, instruction.data); + try writer.print(" br {%}, {%}, {%}\n", .{ + extra.cond.fmt(function_index, self), + extra.then.toInst(&function).fmt(function_index, self), + extra.@"else".toInst(&function).fmt(function_index, self), + }); + }, + .call, + .@"call fast", + .@"musttail call", + .@"musttail call fast", + .@"notail call", + .@"notail call fast", + .@"tail call", + .@"tail call fast", + => |tag| { + var extra = + function.extraDataTrail(Function.Instruction.Call, instruction.data); + const args = extra.trail.next(extra.data.args_len, Value, &function); + try writer.writeAll(" "); + const ret_ty = extra.data.ty.functionReturn(self); + switch (ret_ty) { + .void => {}, + else => try writer.print("%{} = ", .{ + instruction_index.name(&function).fmt(self), + }), + .none => unreachable, + } + try writer.print("{s}{}{}{} {%} {}(", .{ + @tagName(tag), + extra.data.info.call_conv, + extra.data.attributes.ret(self).fmt(self), + extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self), + switch (extra.data.ty.functionKind(self)) { + .normal => ret_ty, + .vararg => extra.data.ty, + }.fmt(self), + extra.data.callee.fmt(function_index, self), + }); + for (0.., args) |arg_index, arg| { + if (arg_index > 0) try writer.writeAll(", "); + try writer.print("{%}{} {}", .{ + arg.typeOf(function_index, self).fmt(self), + extra.data.attributes.param(arg_index, self).fmt(self), + arg.fmt(function_index, self), + }); + } + try writer.writeByte(')'); + const call_function_attributes = extra.data.attributes.func(self); + if (call_function_attributes != .none) try writer.print(" #{d}", .{ + (try attribute_groups.getOrPutValue( + self.gpa, + call_function_attributes, + {}, + )).index, + }); + try writer.writeByte('\n'); + }, + .cmpxchg, + .@"cmpxchg weak", + => |tag| { + const extra = + function.extraData(Function.Instruction.CmpXchg, instruction.data); + try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }\n", .{ + instruction_index.name(&function).fmt(self), + @tagName(tag), + extra.info.access_kind, + extra.ptr.fmt(function_index, self), + extra.cmp.fmt(function_index, self), + extra.new.fmt(function_index, self), + extra.info.sync_scope, + extra.info.success_ordering, + extra.info.failure_ordering, + extra.info.alignment, + }); + }, + .extractelement => |tag| { + const extra = + function.extraData(Function.Instruction.ExtractElement, instruction.data); + try writer.print(" %{} = {s} {%}, {%}\n", .{ + instruction_index.name(&function).fmt(self), + @tagName(tag), + extra.val.fmt(function_index, self), + extra.index.fmt(function_index, self), + }); + }, + .extractvalue => |tag| { + var extra = function.extraDataTrail( + Function.Instruction.ExtractValue, + instruction.data, + ); + const indices = extra.trail.next(extra.data.indices_len, u32, &function); + try writer.print(" %{} = {s} {%}", .{ + instruction_index.name(&function).fmt(self), + @tagName(tag), + extra.data.val.fmt(function_index, self), + }); + for (indices) |index| try writer.print(", {d}", .{index}); + try writer.writeByte('\n'); + }, + .fence => |tag| { + const info: MemoryAccessInfo = @bitCast(instruction.data); + try writer.print(" {s}{ }{ }", .{ + @tagName(tag), + info.sync_scope, + info.success_ordering, + }); + }, + .fneg, + .@"fneg fast", + => |tag| { + const val: Value = @enumFromInt(instruction.data); + try writer.print(" %{} = {s} {%}\n", .{ + instruction_index.name(&function).fmt(self), + @tagName(tag), + val.fmt(function_index, self), + }); + }, + .getelementptr, + .@"getelementptr inbounds", + => |tag| { + var extra = function.extraDataTrail( + Function.Instruction.GetElementPtr, + instruction.data, + ); + const indices = extra.trail.next(extra.data.indices_len, Value, &function); + try writer.print(" %{} = {s} {%}, {%}", .{ + instruction_index.name(&function).fmt(self), + @tagName(tag), + extra.data.type.fmt(self), + extra.data.base.fmt(function_index, self), + }); + for (indices) |index| try writer.print(", {%}", .{ + index.fmt(function_index, self), + }); + try writer.writeByte('\n'); + }, + .insertelement => |tag| { + const extra = + function.extraData(Function.Instruction.InsertElement, instruction.data); + try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ + instruction_index.name(&function).fmt(self), + @tagName(tag), + extra.val.fmt(function_index, self), + extra.elem.fmt(function_index, self), + extra.index.fmt(function_index, self), + }); + }, + .insertvalue => |tag| { + var extra = + function.extraDataTrail(Function.Instruction.InsertValue, instruction.data); + const indices = extra.trail.next(extra.data.indices_len, u32, &function); + try writer.print(" %{} = {s} {%}, {%}", .{ + instruction_index.name(&function).fmt(self), + @tagName(tag), + extra.data.val.fmt(function_index, self), + extra.data.elem.fmt(function_index, self), + }); + for (indices) |index| try writer.print(", {d}", .{index}); + try writer.writeByte('\n'); + }, + .load, + .@"load atomic", + => |tag| { + const extra = function.extraData(Function.Instruction.Load, instruction.data); + try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }\n", .{ + instruction_index.name(&function).fmt(self), + @tagName(tag), + extra.info.access_kind, + extra.type.fmt(self), + extra.ptr.fmt(function_index, self), + extra.info.sync_scope, + extra.info.success_ordering, + extra.info.alignment, + }); + }, + .phi, + .@"phi fast", + => |tag| { + var extra = function.extraDataTrail(Function.Instruction.Phi, instruction.data); + const vals = extra.trail.next(block_incoming_len, Value, &function); + const blocks = + extra.trail.next(block_incoming_len, Function.Block.Index, &function); + try writer.print(" %{} = {s} {%} ", .{ + instruction_index.name(&function).fmt(self), + @tagName(tag), + vals[0].typeOf(function_index, self).fmt(self), + }); + for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| { + if (incoming_index > 0) try writer.writeAll(", "); + try writer.print("[ {}, {} ]", .{ + incoming_val.fmt(function_index, self), + incoming_block.toInst(&function).fmt(function_index, self), + }); + } + try writer.writeByte('\n'); + }, + .ret => |tag| { + const val: Value = @enumFromInt(instruction.data); + try writer.print(" {s} {%}\n", .{ + @tagName(tag), + val.fmt(function_index, self), + }); + }, + .@"ret void", + .@"unreachable", + => |tag| try writer.print(" {s}\n", .{@tagName(tag)}), + .select, + .@"select fast", + => |tag| { + const extra = function.extraData(Function.Instruction.Select, instruction.data); + try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ + instruction_index.name(&function).fmt(self), + @tagName(tag), + extra.cond.fmt(function_index, self), + extra.lhs.fmt(function_index, self), + extra.rhs.fmt(function_index, self), + }); + }, + .shufflevector => |tag| { + const extra = + function.extraData(Function.Instruction.ShuffleVector, instruction.data); + try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{ + instruction_index.name(&function).fmt(self), + @tagName(tag), + extra.lhs.fmt(function_index, self), + extra.rhs.fmt(function_index, self), + extra.mask.fmt(function_index, self), + }); + }, + .store, + .@"store atomic", + => |tag| { + const extra = function.extraData(Function.Instruction.Store, instruction.data); + try writer.print(" {s}{ } {%}, {%}{ }{ }{, }\n", .{ + @tagName(tag), + extra.info.access_kind, + extra.val.fmt(function_index, self), + extra.ptr.fmt(function_index, self), + extra.info.sync_scope, + extra.info.success_ordering, + extra.info.alignment, + }); + }, + .@"switch" => |tag| { + var extra = + function.extraDataTrail(Function.Instruction.Switch, instruction.data); + const vals = extra.trail.next(extra.data.cases_len, Constant, &function); + const blocks = + extra.trail.next(extra.data.cases_len, Function.Block.Index, &function); + try writer.print(" {s} {%}, {%} [\n", .{ + @tagName(tag), + extra.data.val.fmt(function_index, self), + extra.data.default.toInst(&function).fmt(function_index, self), + }); + for (vals, blocks) |case_val, case_block| try writer.print( + " {%}, {%}\n", + .{ + case_val.fmt(self), + case_block.toInst(&function).fmt(function_index, self), + }, + ); + try writer.writeAll(" ]\n"); + }, + .va_arg => |tag| { + const extra = function.extraData(Function.Instruction.VaArg, instruction.data); + try writer.print(" %{} = {s} {%}, {%}\n", .{ + instruction_index.name(&function).fmt(self), + @tagName(tag), + extra.list.fmt(function_index, self), + extra.type.fmt(self), + }); + }, + } + } + try writer.writeByte('}'); + } + try writer.writeByte('\n'); + need_newline = true; + } + if (attribute_groups.count() > 0) { if (need_newline) try writer.writeByte('\n') else need_newline = true; for (0.., attribute_groups.keys()) |attribute_group_index, attribute_group|