authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-08-08 11:40:51-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-08-08 21:32:50-04:00
log35cd56a3693d55eedb80e8bd1538420597b05ff5
tree3c82332603b02fc2c1dd4e4c26a54e5fdb5a842c
parent2bdd180c6f6c76940ccfe8c8532fefec208661ea

llvm: fix alias issues


2 files changed, 522 insertions(+), 508 deletions(-)

src/codegen/llvm.zig+11-12
......@@ -1079,7 +1079,8 @@ pub const Object = struct {
10791079 // Same logic as below but for externs instead of exports.
10801080 const decl_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(mod.declPtr(decl_index).name)) orelse continue;
10811081 const other_global = object.builder.getGlobal(decl_name) orelse continue;
1082 if (other_global.eql(global, &object.builder)) continue;
1082 if (other_global.toConst().getBase(&object.builder) ==
1083 global.toConst().getBase(&object.builder)) continue;
10831084
10841085 try global.replace(other_global, &object.builder);
10851086 }
......@@ -1087,13 +1088,14 @@ pub const Object = struct {
10871088
10881089 for (mod.decl_exports.keys(), mod.decl_exports.values()) |decl_index, export_list| {
10891090 const global = object.decl_map.get(decl_index) orelse continue;
1091 const global_base = global.toConst().getBase(&object.builder);
10901092 for (export_list.items) |exp| {
10911093 // Detect if the LLVM global has already been created as an extern. In such
10921094 // case, we need to replace all uses of it with this exported global.
10931095 const exp_name = object.builder.stringIfExists(mod.intern_pool.stringToSlice(exp.opts.name)) orelse continue;
10941096
10951097 const other_global = object.builder.getGlobal(exp_name) orelse continue;
1096 if (other_global.eql(global, &object.builder)) continue;
1098 if (other_global.toConst().getBase(&object.builder) == global_base) continue;
10971099
10981100 try global.takeName(other_global, &object.builder);
10991101 try other_global.replace(global, &object.builder);
......@@ -1714,7 +1716,7 @@ pub const Object = struct {
17141716 try self.builder.string(section),
17151717 &self.builder,
17161718 ),
1717 else => unreachable,
1719 .alias, .replaced => unreachable,
17181720 };
17191721 if (decl.val.getVariable(mod)) |decl_var| if (decl_var.is_threadlocal)
17201722 global_index.ptrConst(&self.builder).kind
......@@ -1735,15 +1737,16 @@ pub const Object = struct {
17351737 continue;
17361738 },
17371739 .variable, .function => {},
1738 else => unreachable,
1740 .replaced => unreachable,
17391741 }
17401742 }
1741 _ = try self.builder.addAlias(
1742 exp_name,
1743 const alias_index = try self.builder.addAlias(
1744 .empty,
17431745 global_index.typeOf(&self.builder),
17441746 .default,
17451747 global_index.toConst(),
17461748 );
1749 try alias_index.rename(exp_name, &self.builder);
17471750 }
17481751 } else {
17491752 const fqn = try self.builder.string(
......@@ -7703,7 +7706,7 @@ pub const FuncGen = struct {
77037706 if (o.builder.getGlobal(fn_name)) |global| return switch (global.ptrConst(&o.builder).kind) {
77047707 .alias => |alias| alias.getAliasee(&o.builder).ptrConst(&o.builder).kind.function,
77057708 .function => |function| function,
7706 else => unreachable,
7709 .variable, .replaced => unreachable,
77077710 };
77087711 return o.builder.addFunction(
77097712 try o.builder.fnType(return_type, param_types, .normal),
......@@ -7751,11 +7754,7 @@ pub const FuncGen = struct {
77517754 };
77527755 const fn_name = try o.builder.fmt("__{s}{s}f2", .{ fn_base_name, compiler_rt_float_abbrev });
77537756
7754 const libc_fn = try self.getLibcFunction(
7755 fn_name,
7756 ([1]Builder.Type{scalar_llvm_ty} ** 2)[0..],
7757 .i32,
7758 );
7757 const libc_fn = try self.getLibcFunction(fn_name, &.{ scalar_llvm_ty, scalar_llvm_ty }, .i32);
77597758
77607759 const zero = try o.builder.intConst(.i32, 0);
77617760 const int_cond: Builder.IntegerCondition = switch (pred) {
src/codegen/llvm/Builder.zig+511-496
......@@ -2320,6 +2320,10 @@ pub const Alias = struct {
23202320 return self.ptrConst(builder).global.name(builder);
23212321 }
23222322
2323 pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void {
2324 return self.ptrConst(builder).global.rename(new_name, builder);
2325 }
2326
23232327 pub fn typeOf(self: Index, builder: *const Builder) Type {
23242328 return self.ptrConst(builder).global.typeOf(builder);
23252329 }
......@@ -2373,6 +2377,10 @@ pub const Variable = struct {
23732377 return self.ptrConst(builder).global.name(builder);
23742378 }
23752379
2380 pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void {
2381 return self.ptrConst(builder).global.rename(new_name, builder);
2382 }
2383
23762384 pub fn typeOf(self: Index, builder: *const Builder) Type {
23772385 return self.ptrConst(builder).global.typeOf(builder);
23782386 }
......@@ -3812,6 +3820,10 @@ pub const Function = struct {
38123820 return self.ptrConst(builder).global.name(builder);
38133821 }
38143822
3823 pub fn rename(self: Index, new_name: String, builder: *Builder) Allocator.Error!void {
3824 return self.ptrConst(builder).global.rename(new_name, builder);
3825 }
3826
38153827 pub fn typeOf(self: Index, builder: *const Builder) Type {
38163828 return self.ptrConst(builder).global.typeOf(builder);
38173829 }
......@@ -9393,518 +9405,521 @@ pub fn printUnbuffered(
93939405 need_newline = true;
93949406 }
93959407
9396 var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{};
9397 defer attribute_groups.deinit(self.gpa);
9398
9399 if (self.functions.items.len > 0) {
9408 if (self.aliases.items.len > 0) {
94009409 if (need_newline) try writer.writeByte('\n');
9401 for (0.., self.functions.items) |function_i, function| {
9402 if (function_i > 0) try writer.writeByte('\n');
9403 const function_index: Function.Index = @enumFromInt(function_i);
9404 if (function.global.getReplacement(self) != .none) continue;
9405 const global = function.global.ptrConst(self);
9406 const params_len = global.type.functionParameters(self).len;
9407 const function_attributes = function.attributes.func(self);
9408 if (function_attributes != .none) try writer.print(
9409 \\; Function Attrs:{}
9410 \\
9411 , .{function_attributes.fmt(self)});
9410 for (self.aliases.items) |alias| {
9411 if (alias.global.getReplacement(self) != .none) continue;
9412 const global = alias.global.ptrConst(self);
94129413 try writer.print(
9413 \\{s}{}{}{}{}{}{"} {} {}(
9414 \\{} ={}{}{}{}{ }{} alias {%}, {%}
9415 \\
94149416 , .{
9415 if (function.instructions.len > 0) "define" else "declare",
9417 alias.global.fmt(self),
94169418 global.linkage,
94179419 global.preemption,
94189420 global.visibility,
94199421 global.dll_storage_class,
9420 function.call_conv,
9421 function.attributes.ret(self).fmt(self),
9422 global.type.functionReturn(self).fmt(self),
9423 function.global.fmt(self),
9422 alias.thread_local,
9423 global.unnamed_addr,
9424 global.type.fmt(self),
9425 alias.aliasee.fmt(self),
94249426 });
9425 for (0..params_len) |arg| {
9426 if (arg > 0) try writer.writeAll(", ");
9427 try writer.print(
9428 \\{%}{"}
9429 , .{
9430 global.type.functionParameters(self)[arg].fmt(self),
9431 function.attributes.param(arg, self).fmt(self),
9432 });
9433 if (function.instructions.len > 0)
9434 try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)})
9435 else
9436 try writer.print(" %{d}", .{arg});
9437 }
9438 switch (global.type.functionKind(self)) {
9439 .normal => {},
9440 .vararg => {
9441 if (params_len > 0) try writer.writeAll(", ");
9442 try writer.writeAll("...");
9443 },
9444 }
9445 try writer.print("){}{ }", .{ global.unnamed_addr, global.addr_space });
9446 if (function_attributes != .none) try writer.print(" #{d}", .{
9447 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,
9427 }
9428 need_newline = true;
9429 }
9430
9431 var attribute_groups: std.AutoArrayHashMapUnmanaged(Attributes, void) = .{};
9432 defer attribute_groups.deinit(self.gpa);
9433
9434 for (0.., self.functions.items) |function_i, function| {
9435 if (function.global.getReplacement(self) != .none) continue;
9436 if (need_newline) try writer.writeByte('\n');
9437 const function_index: Function.Index = @enumFromInt(function_i);
9438 const global = function.global.ptrConst(self);
9439 const params_len = global.type.functionParameters(self).len;
9440 const function_attributes = function.attributes.func(self);
9441 if (function_attributes != .none) try writer.print(
9442 \\; Function Attrs:{}
9443 \\
9444 , .{function_attributes.fmt(self)});
9445 try writer.print(
9446 \\{s}{}{}{}{}{}{"} {} {}(
9447 , .{
9448 if (function.instructions.len > 0) "define" else "declare",
9449 global.linkage,
9450 global.preemption,
9451 global.visibility,
9452 global.dll_storage_class,
9453 function.call_conv,
9454 function.attributes.ret(self).fmt(self),
9455 global.type.functionReturn(self).fmt(self),
9456 function.global.fmt(self),
9457 });
9458 for (0..params_len) |arg| {
9459 if (arg > 0) try writer.writeAll(", ");
9460 try writer.print(
9461 \\{%}{"}
9462 , .{
9463 global.type.functionParameters(self)[arg].fmt(self),
9464 function.attributes.param(arg, self).fmt(self),
94489465 });
9449 try writer.print("{ }", .{function.alignment});
9450 if (function.instructions.len > 0) {
9451 var block_incoming_len: u32 = undefined;
9452 try writer.writeAll(" {\n");
9453 for (params_len..function.instructions.len) |instruction_i| {
9454 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);
9455 const instruction = function.instructions.get(@intFromEnum(instruction_index));
9456 switch (instruction.tag) {
9457 .add,
9458 .@"add nsw",
9459 .@"add nuw",
9460 .@"add nuw nsw",
9461 .@"and",
9462 .ashr,
9463 .@"ashr exact",
9464 .fadd,
9465 .@"fadd fast",
9466 .@"fcmp false",
9467 .@"fcmp fast false",
9468 .@"fcmp fast oeq",
9469 .@"fcmp fast oge",
9470 .@"fcmp fast ogt",
9471 .@"fcmp fast ole",
9472 .@"fcmp fast olt",
9473 .@"fcmp fast one",
9474 .@"fcmp fast ord",
9475 .@"fcmp fast true",
9476 .@"fcmp fast ueq",
9477 .@"fcmp fast uge",
9478 .@"fcmp fast ugt",
9479 .@"fcmp fast ule",
9480 .@"fcmp fast ult",
9481 .@"fcmp fast une",
9482 .@"fcmp fast uno",
9483 .@"fcmp oeq",
9484 .@"fcmp oge",
9485 .@"fcmp ogt",
9486 .@"fcmp ole",
9487 .@"fcmp olt",
9488 .@"fcmp one",
9489 .@"fcmp ord",
9490 .@"fcmp true",
9491 .@"fcmp ueq",
9492 .@"fcmp uge",
9493 .@"fcmp ugt",
9494 .@"fcmp ule",
9495 .@"fcmp ult",
9496 .@"fcmp une",
9497 .@"fcmp uno",
9498 .fdiv,
9499 .@"fdiv fast",
9500 .fmul,
9501 .@"fmul fast",
9502 .frem,
9503 .@"frem fast",
9504 .fsub,
9505 .@"fsub fast",
9506 .@"icmp eq",
9507 .@"icmp ne",
9508 .@"icmp sge",
9509 .@"icmp sgt",
9510 .@"icmp sle",
9511 .@"icmp slt",
9512 .@"icmp uge",
9513 .@"icmp ugt",
9514 .@"icmp ule",
9515 .@"icmp ult",
9516 .lshr,
9517 .@"lshr exact",
9518 .mul,
9519 .@"mul nsw",
9520 .@"mul nuw",
9521 .@"mul nuw nsw",
9522 .@"or",
9523 .sdiv,
9524 .@"sdiv exact",
9525 .srem,
9526 .shl,
9527 .@"shl nsw",
9528 .@"shl nuw",
9529 .@"shl nuw nsw",
9530 .sub,
9531 .@"sub nsw",
9532 .@"sub nuw",
9533 .@"sub nuw nsw",
9534 .udiv,
9535 .@"udiv exact",
9536 .urem,
9537 .xor,
9538 => |tag| {
9539 const extra =
9540 function.extraData(Function.Instruction.Binary, instruction.data);
9541 try writer.print(" %{} = {s} {%}, {}\n", .{
9542 instruction_index.name(&function).fmt(self),
9543 @tagName(tag),
9544 extra.lhs.fmt(function_index, self),
9545 extra.rhs.fmt(function_index, self),
9546 });
9547 },
9548 .addrspacecast,
9549 .bitcast,
9550 .fpext,
9551 .fptosi,
9552 .fptoui,
9553 .fptrunc,
9554 .inttoptr,
9555 .ptrtoint,
9556 .sext,
9557 .sitofp,
9558 .trunc,
9559 .uitofp,
9560 .zext,
9561 => |tag| {
9562 const extra =
9563 function.extraData(Function.Instruction.Cast, instruction.data);
9564 try writer.print(" %{} = {s} {%} to {%}\n", .{
9565 instruction_index.name(&function).fmt(self),
9566 @tagName(tag),
9567 extra.val.fmt(function_index, self),
9568 extra.type.fmt(self),
9569 });
9570 },
9571 .alloca,
9572 .@"alloca inalloca",
9573 => |tag| {
9574 const extra =
9575 function.extraData(Function.Instruction.Alloca, instruction.data);
9576 try writer.print(" %{} = {s} {%}{,%}{, }{, }\n", .{
9577 instruction_index.name(&function).fmt(self),
9578 @tagName(tag),
9579 extra.type.fmt(self),
9580 extra.len.fmt(function_index, self),
9581 extra.info.alignment,
9582 extra.info.addr_space,
9583 });
9584 },
9585 .arg => unreachable,
9586 .atomicrmw => |tag| {
9587 const extra =
9588 function.extraData(Function.Instruction.AtomicRmw, instruction.data);
9589 try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }\n", .{
9590 instruction_index.name(&function).fmt(self),
9591 @tagName(tag),
9592 extra.info.access_kind,
9593 @tagName(extra.info.atomic_rmw_operation),
9594 extra.ptr.fmt(function_index, self),
9595 extra.val.fmt(function_index, self),
9596 extra.info.sync_scope,
9597 extra.info.success_ordering,
9598 extra.info.alignment,
9599 });
9600 },
9601 .block => {
9602 block_incoming_len = instruction.data;
9603 const name = instruction_index.name(&function);
9604 if (@intFromEnum(instruction_index) > params_len)
9605 try writer.writeByte('\n');
9606 try writer.print("{}:\n", .{name.fmt(self)});
9607 },
9608 .br => |tag| {
9609 const target: Function.Block.Index = @enumFromInt(instruction.data);
9610 try writer.print(" {s} {%}\n", .{
9611 @tagName(tag), target.toInst(&function).fmt(function_index, self),
9612 });
9613 },
9614 .br_cond => {
9615 const extra =
9616 function.extraData(Function.Instruction.BrCond, instruction.data);
9617 try writer.print(" br {%}, {%}, {%}\n", .{
9618 extra.cond.fmt(function_index, self),
9619 extra.then.toInst(&function).fmt(function_index, self),
9620 extra.@"else".toInst(&function).fmt(function_index, self),
9621 });
9622 },
9623 .call,
9624 .@"call fast",
9625 .@"musttail call",
9626 .@"musttail call fast",
9627 .@"notail call",
9628 .@"notail call fast",
9629 .@"tail call",
9630 .@"tail call fast",
9631 => |tag| {
9632 var extra =
9633 function.extraDataTrail(Function.Instruction.Call, instruction.data);
9634 const args = extra.trail.next(extra.data.args_len, Value, &function);
9635 try writer.writeAll(" ");
9636 const ret_ty = extra.data.ty.functionReturn(self);
9637 switch (ret_ty) {
9638 .void => {},
9639 else => try writer.print("%{} = ", .{
9640 instruction_index.name(&function).fmt(self),
9641 }),
9642 .none => unreachable,
9643 }
9644 try writer.print("{s}{}{}{} {%} {}(", .{
9645 @tagName(tag),
9646 extra.data.info.call_conv,
9647 extra.data.attributes.ret(self).fmt(self),
9648 extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self),
9649 switch (extra.data.ty.functionKind(self)) {
9650 .normal => ret_ty,
9651 .vararg => extra.data.ty,
9652 }.fmt(self),
9653 extra.data.callee.fmt(function_index, self),
9654 });
9655 for (0.., args) |arg_index, arg| {
9656 if (arg_index > 0) try writer.writeAll(", ");
9657 try writer.print("{%}{} {}", .{
9658 arg.typeOf(function_index, self).fmt(self),
9659 extra.data.attributes.param(arg_index, self).fmt(self),
9660 arg.fmt(function_index, self),
9661 });
9662 }
9663 try writer.writeByte(')');
9664 const call_function_attributes = extra.data.attributes.func(self);
9665 if (call_function_attributes != .none) try writer.print(" #{d}", .{
9666 (try attribute_groups.getOrPutValue(
9667 self.gpa,
9668 call_function_attributes,
9669 {},
9670 )).index,
9671 });
9672 try writer.writeByte('\n');
9673 },
9674 .cmpxchg,
9675 .@"cmpxchg weak",
9676 => |tag| {
9677 const extra =
9678 function.extraData(Function.Instruction.CmpXchg, instruction.data);
9679 try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }\n", .{
9680 instruction_index.name(&function).fmt(self),
9681 @tagName(tag),
9682 extra.info.access_kind,
9683 extra.ptr.fmt(function_index, self),
9684 extra.cmp.fmt(function_index, self),
9685 extra.new.fmt(function_index, self),
9686 extra.info.sync_scope,
9687 extra.info.success_ordering,
9688 extra.info.failure_ordering,
9689 extra.info.alignment,
9690 });
9691 },
9692 .extractelement => |tag| {
9693 const extra = function.extraData(
9694 Function.Instruction.ExtractElement,
9695 instruction.data,
9696 );
9697 try writer.print(" %{} = {s} {%}, {%}\n", .{
9698 instruction_index.name(&function).fmt(self),
9699 @tagName(tag),
9700 extra.val.fmt(function_index, self),
9701 extra.index.fmt(function_index, self),
9702 });
9703 },
9704 .extractvalue => |tag| {
9705 var extra = function.extraDataTrail(
9706 Function.Instruction.ExtractValue,
9707 instruction.data,
9708 );
9709 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
9710 try writer.print(" %{} = {s} {%}", .{
9711 instruction_index.name(&function).fmt(self),
9712 @tagName(tag),
9713 extra.data.val.fmt(function_index, self),
9714 });
9715 for (indices) |index| try writer.print(", {d}", .{index});
9716 try writer.writeByte('\n');
9717 },
9718 .fence => |tag| {
9719 const info: MemoryAccessInfo = @bitCast(instruction.data);
9720 try writer.print(" {s}{ }{ }", .{
9721 @tagName(tag),
9722 info.sync_scope,
9723 info.success_ordering,
9724 });
9725 },
9726 .fneg,
9727 .@"fneg fast",
9728 => |tag| {
9729 const val: Value = @enumFromInt(instruction.data);
9730 try writer.print(" %{} = {s} {%}\n", .{
9731 instruction_index.name(&function).fmt(self),
9732 @tagName(tag),
9733 val.fmt(function_index, self),
9734 });
9735 },
9736 .getelementptr,
9737 .@"getelementptr inbounds",
9738 => |tag| {
9739 var extra = function.extraDataTrail(
9740 Function.Instruction.GetElementPtr,
9741 instruction.data,
9742 );
9743 const indices = extra.trail.next(extra.data.indices_len, Value, &function);
9744 try writer.print(" %{} = {s} {%}, {%}", .{
9745 instruction_index.name(&function).fmt(self),
9746 @tagName(tag),
9747 extra.data.type.fmt(self),
9748 extra.data.base.fmt(function_index, self),
9749 });
9750 for (indices) |index| try writer.print(", {%}", .{
9751 index.fmt(function_index, self),
9752 });
9753 try writer.writeByte('\n');
9754 },
9755 .insertelement => |tag| {
9756 const extra = function.extraData(
9757 Function.Instruction.InsertElement,
9758 instruction.data,
9759 );
9760 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
9761 instruction_index.name(&function).fmt(self),
9762 @tagName(tag),
9763 extra.val.fmt(function_index, self),
9764 extra.elem.fmt(function_index, self),
9765 extra.index.fmt(function_index, self),
9766 });
9767 },
9768 .insertvalue => |tag| {
9769 var extra = function.extraDataTrail(
9770 Function.Instruction.InsertValue,
9771 instruction.data,
9772 );
9773 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
9774 try writer.print(" %{} = {s} {%}, {%}", .{
9775 instruction_index.name(&function).fmt(self),
9776 @tagName(tag),
9777 extra.data.val.fmt(function_index, self),
9778 extra.data.elem.fmt(function_index, self),
9779 });
9780 for (indices) |index| try writer.print(", {d}", .{index});
9781 try writer.writeByte('\n');
9782 },
9783 .load,
9784 .@"load atomic",
9785 => |tag| {
9786 const extra =
9787 function.extraData(Function.Instruction.Load, instruction.data);
9788 try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }\n", .{
9789 instruction_index.name(&function).fmt(self),
9790 @tagName(tag),
9791 extra.info.access_kind,
9792 extra.type.fmt(self),
9793 extra.ptr.fmt(function_index, self),
9794 extra.info.sync_scope,
9795 extra.info.success_ordering,
9796 extra.info.alignment,
9797 });
9798 },
9799 .phi,
9800 .@"phi fast",
9801 => |tag| {
9802 var extra =
9803 function.extraDataTrail(Function.Instruction.Phi, instruction.data);
9804 const vals = extra.trail.next(block_incoming_len, Value, &function);
9805 const blocks =
9806 extra.trail.next(block_incoming_len, Function.Block.Index, &function);
9807 try writer.print(" %{} = {s} {%} ", .{
9808 instruction_index.name(&function).fmt(self),
9809 @tagName(tag),
9810 vals[0].typeOf(function_index, self).fmt(self),
9811 });
9812 for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| {
9813 if (incoming_index > 0) try writer.writeAll(", ");
9814 try writer.print("[ {}, {} ]", .{
9815 incoming_val.fmt(function_index, self),
9816 incoming_block.toInst(&function).fmt(function_index, self),
9817 });
9818 }
9466 if (function.instructions.len > 0)
9467 try writer.print(" {}", .{function.arg(@intCast(arg)).fmt(function_index, self)})
9468 else
9469 try writer.print(" %{d}", .{arg});
9470 }
9471 switch (global.type.functionKind(self)) {
9472 .normal => {},
9473 .vararg => {
9474 if (params_len > 0) try writer.writeAll(", ");
9475 try writer.writeAll("...");
9476 },
9477 }
9478 try writer.print("){}{ }", .{ global.unnamed_addr, global.addr_space });
9479 if (function_attributes != .none) try writer.print(" #{d}", .{
9480 (try attribute_groups.getOrPutValue(self.gpa, function_attributes, {})).index,
9481 });
9482 try writer.print("{ }", .{function.alignment});
9483 if (function.instructions.len > 0) {
9484 var block_incoming_len: u32 = undefined;
9485 try writer.writeAll(" {\n");
9486 for (params_len..function.instructions.len) |instruction_i| {
9487 const instruction_index: Function.Instruction.Index = @enumFromInt(instruction_i);
9488 const instruction = function.instructions.get(@intFromEnum(instruction_index));
9489 switch (instruction.tag) {
9490 .add,
9491 .@"add nsw",
9492 .@"add nuw",
9493 .@"add nuw nsw",
9494 .@"and",
9495 .ashr,
9496 .@"ashr exact",
9497 .fadd,
9498 .@"fadd fast",
9499 .@"fcmp false",
9500 .@"fcmp fast false",
9501 .@"fcmp fast oeq",
9502 .@"fcmp fast oge",
9503 .@"fcmp fast ogt",
9504 .@"fcmp fast ole",
9505 .@"fcmp fast olt",
9506 .@"fcmp fast one",
9507 .@"fcmp fast ord",
9508 .@"fcmp fast true",
9509 .@"fcmp fast ueq",
9510 .@"fcmp fast uge",
9511 .@"fcmp fast ugt",
9512 .@"fcmp fast ule",
9513 .@"fcmp fast ult",
9514 .@"fcmp fast une",
9515 .@"fcmp fast uno",
9516 .@"fcmp oeq",
9517 .@"fcmp oge",
9518 .@"fcmp ogt",
9519 .@"fcmp ole",
9520 .@"fcmp olt",
9521 .@"fcmp one",
9522 .@"fcmp ord",
9523 .@"fcmp true",
9524 .@"fcmp ueq",
9525 .@"fcmp uge",
9526 .@"fcmp ugt",
9527 .@"fcmp ule",
9528 .@"fcmp ult",
9529 .@"fcmp une",
9530 .@"fcmp uno",
9531 .fdiv,
9532 .@"fdiv fast",
9533 .fmul,
9534 .@"fmul fast",
9535 .frem,
9536 .@"frem fast",
9537 .fsub,
9538 .@"fsub fast",
9539 .@"icmp eq",
9540 .@"icmp ne",
9541 .@"icmp sge",
9542 .@"icmp sgt",
9543 .@"icmp sle",
9544 .@"icmp slt",
9545 .@"icmp uge",
9546 .@"icmp ugt",
9547 .@"icmp ule",
9548 .@"icmp ult",
9549 .lshr,
9550 .@"lshr exact",
9551 .mul,
9552 .@"mul nsw",
9553 .@"mul nuw",
9554 .@"mul nuw nsw",
9555 .@"or",
9556 .sdiv,
9557 .@"sdiv exact",
9558 .srem,
9559 .shl,
9560 .@"shl nsw",
9561 .@"shl nuw",
9562 .@"shl nuw nsw",
9563 .sub,
9564 .@"sub nsw",
9565 .@"sub nuw",
9566 .@"sub nuw nsw",
9567 .udiv,
9568 .@"udiv exact",
9569 .urem,
9570 .xor,
9571 => |tag| {
9572 const extra = function.extraData(Function.Instruction.Binary, instruction.data);
9573 try writer.print(" %{} = {s} {%}, {}\n", .{
9574 instruction_index.name(&function).fmt(self),
9575 @tagName(tag),
9576 extra.lhs.fmt(function_index, self),
9577 extra.rhs.fmt(function_index, self),
9578 });
9579 },
9580 .addrspacecast,
9581 .bitcast,
9582 .fpext,
9583 .fptosi,
9584 .fptoui,
9585 .fptrunc,
9586 .inttoptr,
9587 .ptrtoint,
9588 .sext,
9589 .sitofp,
9590 .trunc,
9591 .uitofp,
9592 .zext,
9593 => |tag| {
9594 const extra = function.extraData(Function.Instruction.Cast, instruction.data);
9595 try writer.print(" %{} = {s} {%} to {%}\n", .{
9596 instruction_index.name(&function).fmt(self),
9597 @tagName(tag),
9598 extra.val.fmt(function_index, self),
9599 extra.type.fmt(self),
9600 });
9601 },
9602 .alloca,
9603 .@"alloca inalloca",
9604 => |tag| {
9605 const extra = function.extraData(Function.Instruction.Alloca, instruction.data);
9606 try writer.print(" %{} = {s} {%}{,%}{, }{, }\n", .{
9607 instruction_index.name(&function).fmt(self),
9608 @tagName(tag),
9609 extra.type.fmt(self),
9610 extra.len.fmt(function_index, self),
9611 extra.info.alignment,
9612 extra.info.addr_space,
9613 });
9614 },
9615 .arg => unreachable,
9616 .atomicrmw => |tag| {
9617 const extra =
9618 function.extraData(Function.Instruction.AtomicRmw, instruction.data);
9619 try writer.print(" %{} = {s}{ } {s} {%}, {%}{ }{ }{, }\n", .{
9620 instruction_index.name(&function).fmt(self),
9621 @tagName(tag),
9622 extra.info.access_kind,
9623 @tagName(extra.info.atomic_rmw_operation),
9624 extra.ptr.fmt(function_index, self),
9625 extra.val.fmt(function_index, self),
9626 extra.info.sync_scope,
9627 extra.info.success_ordering,
9628 extra.info.alignment,
9629 });
9630 },
9631 .block => {
9632 block_incoming_len = instruction.data;
9633 const name = instruction_index.name(&function);
9634 if (@intFromEnum(instruction_index) > params_len)
98199635 try writer.writeByte('\n');
9820 },
9821 .ret => |tag| {
9822 const val: Value = @enumFromInt(instruction.data);
9823 try writer.print(" {s} {%}\n", .{
9824 @tagName(tag),
9825 val.fmt(function_index, self),
9826 });
9827 },
9828 .@"ret void",
9829 .@"unreachable",
9830 => |tag| try writer.print(" {s}\n", .{@tagName(tag)}),
9831 .select,
9832 .@"select fast",
9833 => |tag| {
9834 const extra =
9835 function.extraData(Function.Instruction.Select, instruction.data);
9836 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
9837 instruction_index.name(&function).fmt(self),
9838 @tagName(tag),
9839 extra.cond.fmt(function_index, self),
9840 extra.lhs.fmt(function_index, self),
9841 extra.rhs.fmt(function_index, self),
9842 });
9843 },
9844 .shufflevector => |tag| {
9845 const extra = function.extraData(
9846 Function.Instruction.ShuffleVector,
9847 instruction.data,
9848 );
9849 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
9636 try writer.print("{}:\n", .{name.fmt(self)});
9637 },
9638 .br => |tag| {
9639 const target: Function.Block.Index = @enumFromInt(instruction.data);
9640 try writer.print(" {s} {%}\n", .{
9641 @tagName(tag), target.toInst(&function).fmt(function_index, self),
9642 });
9643 },
9644 .br_cond => {
9645 const extra = function.extraData(Function.Instruction.BrCond, instruction.data);
9646 try writer.print(" br {%}, {%}, {%}\n", .{
9647 extra.cond.fmt(function_index, self),
9648 extra.then.toInst(&function).fmt(function_index, self),
9649 extra.@"else".toInst(&function).fmt(function_index, self),
9650 });
9651 },
9652 .call,
9653 .@"call fast",
9654 .@"musttail call",
9655 .@"musttail call fast",
9656 .@"notail call",
9657 .@"notail call fast",
9658 .@"tail call",
9659 .@"tail call fast",
9660 => |tag| {
9661 var extra =
9662 function.extraDataTrail(Function.Instruction.Call, instruction.data);
9663 const args = extra.trail.next(extra.data.args_len, Value, &function);
9664 try writer.writeAll(" ");
9665 const ret_ty = extra.data.ty.functionReturn(self);
9666 switch (ret_ty) {
9667 .void => {},
9668 else => try writer.print("%{} = ", .{
98509669 instruction_index.name(&function).fmt(self),
9851 @tagName(tag),
9852 extra.lhs.fmt(function_index, self),
9853 extra.rhs.fmt(function_index, self),
9854 extra.mask.fmt(function_index, self),
9855 });
9856 },
9857 .store,
9858 .@"store atomic",
9859 => |tag| {
9860 const extra =
9861 function.extraData(Function.Instruction.Store, instruction.data);
9862 try writer.print(" {s}{ } {%}, {%}{ }{ }{, }\n", .{
9863 @tagName(tag),
9864 extra.info.access_kind,
9865 extra.val.fmt(function_index, self),
9866 extra.ptr.fmt(function_index, self),
9867 extra.info.sync_scope,
9868 extra.info.success_ordering,
9869 extra.info.alignment,
9870 });
9871 },
9872 .@"switch" => |tag| {
9873 var extra =
9874 function.extraDataTrail(Function.Instruction.Switch, instruction.data);
9875 const vals = extra.trail.next(extra.data.cases_len, Constant, &function);
9876 const blocks =
9877 extra.trail.next(extra.data.cases_len, Function.Block.Index, &function);
9878 try writer.print(" {s} {%}, {%} [\n", .{
9879 @tagName(tag),
9880 extra.data.val.fmt(function_index, self),
9881 extra.data.default.toInst(&function).fmt(function_index, self),
9670 }),
9671 .none => unreachable,
9672 }
9673 try writer.print("{s}{}{}{} {%} {}(", .{
9674 @tagName(tag),
9675 extra.data.info.call_conv,
9676 extra.data.attributes.ret(self).fmt(self),
9677 extra.data.callee.typeOf(function_index, self).pointerAddrSpace(self),
9678 switch (extra.data.ty.functionKind(self)) {
9679 .normal => ret_ty,
9680 .vararg => extra.data.ty,
9681 }.fmt(self),
9682 extra.data.callee.fmt(function_index, self),
9683 });
9684 for (0.., args) |arg_index, arg| {
9685 if (arg_index > 0) try writer.writeAll(", ");
9686 try writer.print("{%}{} {}", .{
9687 arg.typeOf(function_index, self).fmt(self),
9688 extra.data.attributes.param(arg_index, self).fmt(self),
9689 arg.fmt(function_index, self),
98829690 });
9883 for (vals, blocks) |case_val, case_block| try writer.print(
9884 " {%}, {%}\n",
9885 .{
9886 case_val.fmt(self),
9887 case_block.toInst(&function).fmt(function_index, self),
9888 },
9889 );
9890 try writer.writeAll(" ]\n");
9891 },
9892 .va_arg => |tag| {
9893 const extra =
9894 function.extraData(Function.Instruction.VaArg, instruction.data);
9895 try writer.print(" %{} = {s} {%}, {%}\n", .{
9896 instruction_index.name(&function).fmt(self),
9897 @tagName(tag),
9898 extra.list.fmt(function_index, self),
9899 extra.type.fmt(self),
9691 }
9692 try writer.writeByte(')');
9693 const call_function_attributes = extra.data.attributes.func(self);
9694 if (call_function_attributes != .none) try writer.print(" #{d}", .{
9695 (try attribute_groups.getOrPutValue(
9696 self.gpa,
9697 call_function_attributes,
9698 {},
9699 )).index,
9700 });
9701 try writer.writeByte('\n');
9702 },
9703 .cmpxchg,
9704 .@"cmpxchg weak",
9705 => |tag| {
9706 const extra =
9707 function.extraData(Function.Instruction.CmpXchg, instruction.data);
9708 try writer.print(" %{} = {s}{ } {%}, {%}, {%}{ }{ }{ }{, }\n", .{
9709 instruction_index.name(&function).fmt(self),
9710 @tagName(tag),
9711 extra.info.access_kind,
9712 extra.ptr.fmt(function_index, self),
9713 extra.cmp.fmt(function_index, self),
9714 extra.new.fmt(function_index, self),
9715 extra.info.sync_scope,
9716 extra.info.success_ordering,
9717 extra.info.failure_ordering,
9718 extra.info.alignment,
9719 });
9720 },
9721 .extractelement => |tag| {
9722 const extra =
9723 function.extraData(Function.Instruction.ExtractElement, instruction.data);
9724 try writer.print(" %{} = {s} {%}, {%}\n", .{
9725 instruction_index.name(&function).fmt(self),
9726 @tagName(tag),
9727 extra.val.fmt(function_index, self),
9728 extra.index.fmt(function_index, self),
9729 });
9730 },
9731 .extractvalue => |tag| {
9732 var extra = function.extraDataTrail(
9733 Function.Instruction.ExtractValue,
9734 instruction.data,
9735 );
9736 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
9737 try writer.print(" %{} = {s} {%}", .{
9738 instruction_index.name(&function).fmt(self),
9739 @tagName(tag),
9740 extra.data.val.fmt(function_index, self),
9741 });
9742 for (indices) |index| try writer.print(", {d}", .{index});
9743 try writer.writeByte('\n');
9744 },
9745 .fence => |tag| {
9746 const info: MemoryAccessInfo = @bitCast(instruction.data);
9747 try writer.print(" {s}{ }{ }", .{
9748 @tagName(tag),
9749 info.sync_scope,
9750 info.success_ordering,
9751 });
9752 },
9753 .fneg,
9754 .@"fneg fast",
9755 => |tag| {
9756 const val: Value = @enumFromInt(instruction.data);
9757 try writer.print(" %{} = {s} {%}\n", .{
9758 instruction_index.name(&function).fmt(self),
9759 @tagName(tag),
9760 val.fmt(function_index, self),
9761 });
9762 },
9763 .getelementptr,
9764 .@"getelementptr inbounds",
9765 => |tag| {
9766 var extra = function.extraDataTrail(
9767 Function.Instruction.GetElementPtr,
9768 instruction.data,
9769 );
9770 const indices = extra.trail.next(extra.data.indices_len, Value, &function);
9771 try writer.print(" %{} = {s} {%}, {%}", .{
9772 instruction_index.name(&function).fmt(self),
9773 @tagName(tag),
9774 extra.data.type.fmt(self),
9775 extra.data.base.fmt(function_index, self),
9776 });
9777 for (indices) |index| try writer.print(", {%}", .{
9778 index.fmt(function_index, self),
9779 });
9780 try writer.writeByte('\n');
9781 },
9782 .insertelement => |tag| {
9783 const extra =
9784 function.extraData(Function.Instruction.InsertElement, instruction.data);
9785 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
9786 instruction_index.name(&function).fmt(self),
9787 @tagName(tag),
9788 extra.val.fmt(function_index, self),
9789 extra.elem.fmt(function_index, self),
9790 extra.index.fmt(function_index, self),
9791 });
9792 },
9793 .insertvalue => |tag| {
9794 var extra =
9795 function.extraDataTrail(Function.Instruction.InsertValue, instruction.data);
9796 const indices = extra.trail.next(extra.data.indices_len, u32, &function);
9797 try writer.print(" %{} = {s} {%}, {%}", .{
9798 instruction_index.name(&function).fmt(self),
9799 @tagName(tag),
9800 extra.data.val.fmt(function_index, self),
9801 extra.data.elem.fmt(function_index, self),
9802 });
9803 for (indices) |index| try writer.print(", {d}", .{index});
9804 try writer.writeByte('\n');
9805 },
9806 .load,
9807 .@"load atomic",
9808 => |tag| {
9809 const extra = function.extraData(Function.Instruction.Load, instruction.data);
9810 try writer.print(" %{} = {s}{ } {%}, {%}{ }{ }{, }\n", .{
9811 instruction_index.name(&function).fmt(self),
9812 @tagName(tag),
9813 extra.info.access_kind,
9814 extra.type.fmt(self),
9815 extra.ptr.fmt(function_index, self),
9816 extra.info.sync_scope,
9817 extra.info.success_ordering,
9818 extra.info.alignment,
9819 });
9820 },
9821 .phi,
9822 .@"phi fast",
9823 => |tag| {
9824 var extra = function.extraDataTrail(Function.Instruction.Phi, instruction.data);
9825 const vals = extra.trail.next(block_incoming_len, Value, &function);
9826 const blocks =
9827 extra.trail.next(block_incoming_len, Function.Block.Index, &function);
9828 try writer.print(" %{} = {s} {%} ", .{
9829 instruction_index.name(&function).fmt(self),
9830 @tagName(tag),
9831 vals[0].typeOf(function_index, self).fmt(self),
9832 });
9833 for (0.., vals, blocks) |incoming_index, incoming_val, incoming_block| {
9834 if (incoming_index > 0) try writer.writeAll(", ");
9835 try writer.print("[ {}, {} ]", .{
9836 incoming_val.fmt(function_index, self),
9837 incoming_block.toInst(&function).fmt(function_index, self),
99009838 });
9901 },
9902 }
9839 }
9840 try writer.writeByte('\n');
9841 },
9842 .ret => |tag| {
9843 const val: Value = @enumFromInt(instruction.data);
9844 try writer.print(" {s} {%}\n", .{
9845 @tagName(tag),
9846 val.fmt(function_index, self),
9847 });
9848 },
9849 .@"ret void",
9850 .@"unreachable",
9851 => |tag| try writer.print(" {s}\n", .{@tagName(tag)}),
9852 .select,
9853 .@"select fast",
9854 => |tag| {
9855 const extra = function.extraData(Function.Instruction.Select, instruction.data);
9856 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
9857 instruction_index.name(&function).fmt(self),
9858 @tagName(tag),
9859 extra.cond.fmt(function_index, self),
9860 extra.lhs.fmt(function_index, self),
9861 extra.rhs.fmt(function_index, self),
9862 });
9863 },
9864 .shufflevector => |tag| {
9865 const extra =
9866 function.extraData(Function.Instruction.ShuffleVector, instruction.data);
9867 try writer.print(" %{} = {s} {%}, {%}, {%}\n", .{
9868 instruction_index.name(&function).fmt(self),
9869 @tagName(tag),
9870 extra.lhs.fmt(function_index, self),
9871 extra.rhs.fmt(function_index, self),
9872 extra.mask.fmt(function_index, self),
9873 });
9874 },
9875 .store,
9876 .@"store atomic",
9877 => |tag| {
9878 const extra = function.extraData(Function.Instruction.Store, instruction.data);
9879 try writer.print(" {s}{ } {%}, {%}{ }{ }{, }\n", .{
9880 @tagName(tag),
9881 extra.info.access_kind,
9882 extra.val.fmt(function_index, self),
9883 extra.ptr.fmt(function_index, self),
9884 extra.info.sync_scope,
9885 extra.info.success_ordering,
9886 extra.info.alignment,
9887 });
9888 },
9889 .@"switch" => |tag| {
9890 var extra =
9891 function.extraDataTrail(Function.Instruction.Switch, instruction.data);
9892 const vals = extra.trail.next(extra.data.cases_len, Constant, &function);
9893 const blocks =
9894 extra.trail.next(extra.data.cases_len, Function.Block.Index, &function);
9895 try writer.print(" {s} {%}, {%} [\n", .{
9896 @tagName(tag),
9897 extra.data.val.fmt(function_index, self),
9898 extra.data.default.toInst(&function).fmt(function_index, self),
9899 });
9900 for (vals, blocks) |case_val, case_block| try writer.print(
9901 " {%}, {%}\n",
9902 .{
9903 case_val.fmt(self),
9904 case_block.toInst(&function).fmt(function_index, self),
9905 },
9906 );
9907 try writer.writeAll(" ]\n");
9908 },
9909 .va_arg => |tag| {
9910 const extra = function.extraData(Function.Instruction.VaArg, instruction.data);
9911 try writer.print(" %{} = {s} {%}, {%}\n", .{
9912 instruction_index.name(&function).fmt(self),
9913 @tagName(tag),
9914 extra.list.fmt(function_index, self),
9915 extra.type.fmt(self),
9916 });
9917 },
99039918 }
9904 try writer.writeByte('}');
99059919 }
9906 try writer.writeByte('\n');
9920 try writer.writeByte('}');
99079921 }
9922 try writer.writeByte('\n');
99089923 need_newline = true;
99099924 }
99109925