authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-04-30 21:47:19-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2023-05-01 19:22:52-04:00
log47a34d038dd114533c3fcb130e03249ad846fe9c
tree6469bd38ce404ef80b0ad8258934c586cf0318e5
parent0489a63a432b31ce0fd9d6ec6c8e2fb72a920573

x86_64: implement tagName


9 files changed, 368 insertions(+), 71 deletions(-)

src/arch/x86_64/CodeGen.zig+266-26
......@@ -56,7 +56,10 @@ liveness: Liveness,
5656bin_file: *link.File,
5757debug_output: DebugInfoOutput,
5858target: *const std.Target,
59mod_fn: *const Module.Fn,
59owner: union(enum) {
60 mod_fn: *const Module.Fn,
61 decl: Module.Decl.Index,
62},
6063err_msg: ?*ErrorMsg,
6164args: []MCValue,
6265ret_mcv: InstTracking,
......@@ -617,7 +620,7 @@ pub fn generate(
617620 .target = &bin_file.options.target,
618621 .bin_file = bin_file,
619622 .debug_output = debug_output,
620 .mod_fn = module_fn,
623 .owner = .{ .mod_fn = module_fn },
621624 .err_msg = null,
622625 .args = undefined, // populated after `resolveCallingConventionValues`
623626 .ret_mcv = undefined, // populated after `resolveCallingConventionValues`
......@@ -745,6 +748,92 @@ pub fn generate(
745748 }
746749}
747750
751pub fn generateLazy(
752 bin_file: *link.File,
753 src_loc: Module.SrcLoc,
754 lazy_sym: link.File.LazySymbol,
755 code: *std.ArrayList(u8),
756 debug_output: DebugInfoOutput,
757) CodeGenError!Result {
758 const gpa = bin_file.allocator;
759 var function = Self{
760 .gpa = gpa,
761 .air = undefined,
762 .liveness = undefined,
763 .target = &bin_file.options.target,
764 .bin_file = bin_file,
765 .debug_output = debug_output,
766 .owner = .{ .decl = lazy_sym.ty.getOwnerDecl() },
767 .err_msg = null,
768 .args = undefined,
769 .ret_mcv = undefined,
770 .fn_type = undefined,
771 .arg_index = undefined,
772 .src_loc = src_loc,
773 .end_di_line = undefined, // no debug info yet
774 .end_di_column = undefined, // no debug info yet
775 };
776 defer {
777 function.mir_instructions.deinit(gpa);
778 function.mir_extra.deinit(gpa);
779 }
780
781 function.genLazy(lazy_sym) catch |err| switch (err) {
782 error.CodegenFail => return Result{ .fail = function.err_msg.? },
783 error.OutOfRegisters => return Result{
784 .fail = try ErrorMsg.create(bin_file.allocator, src_loc, "CodeGen ran out of registers. This is a bug in the Zig compiler.", .{}),
785 },
786 else => |e| return e,
787 };
788
789 var mir = Mir{
790 .instructions = function.mir_instructions.toOwnedSlice(),
791 .extra = try function.mir_extra.toOwnedSlice(bin_file.allocator),
792 .frame_locs = function.frame_locs.toOwnedSlice(),
793 };
794 defer mir.deinit(bin_file.allocator);
795
796 var emit = Emit{
797 .lower = .{
798 .allocator = bin_file.allocator,
799 .mir = mir,
800 .target = &bin_file.options.target,
801 .src_loc = src_loc,
802 },
803 .bin_file = bin_file,
804 .debug_output = debug_output,
805 .code = code,
806 .prev_di_pc = undefined, // no debug info yet
807 .prev_di_line = undefined, // no debug info yet
808 .prev_di_column = undefined, // no debug info yet
809 };
810 defer emit.deinit();
811 emit.emitMir() catch |err| switch (err) {
812 error.LowerFail, error.EmitFail => return Result{ .fail = emit.lower.err_msg.? },
813 error.InvalidInstruction, error.CannotEncode => |e| {
814 const msg = switch (e) {
815 error.InvalidInstruction => "CodeGen failed to find a viable instruction.",
816 error.CannotEncode => "CodeGen failed to encode the instruction.",
817 };
818 return Result{
819 .fail = try ErrorMsg.create(
820 bin_file.allocator,
821 src_loc,
822 "{s} This is a bug in the Zig compiler.",
823 .{msg},
824 ),
825 };
826 },
827 else => |e| return e,
828 };
829
830 if (function.err_msg) |em| {
831 return Result{ .fail = em };
832 } else {
833 return Result.ok;
834 }
835}
836
748837const FormatDeclData = struct {
749838 mod: *Module,
750839 decl_index: Module.Decl.Index,
......@@ -1545,6 +1634,103 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void {
15451634 verbose_tracking_log.debug("{}", .{self.fmtTracking()});
15461635}
15471636
1637fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
1638 switch (lazy_sym.ty.zigTypeTag()) {
1639 .Enum => {
1640 const enum_ty = lazy_sym.ty;
1641 wip_mir_log.debug("{}.@tagName:", .{enum_ty.fmt(self.bin_file.options.module.?)});
1642
1643 const param_regs = abi.getCAbiIntParamRegs(self.target.*);
1644 const param_locks = self.register_manager.lockRegsAssumeUnused(2, param_regs[0..2].*);
1645 defer for (param_locks) |lock| self.register_manager.unlockReg(lock);
1646
1647 const ret_reg = param_regs[0];
1648 const enum_mcv = MCValue{ .register = param_regs[1] };
1649
1650 var exitlude_jump_relocs = try self.gpa.alloc(u32, enum_ty.enumFieldCount());
1651 defer self.gpa.free(exitlude_jump_relocs);
1652
1653 const data_reg = try self.register_manager.allocReg(null, gp);
1654 const data_lock = self.register_manager.lockRegAssumeUnused(data_reg);
1655 defer self.register_manager.unlockReg(data_lock);
1656
1657 const data_lazy_sym = link.File.LazySymbol{ .kind = .const_data, .ty = enum_ty };
1658 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
1659 const atom_index = elf_file.getOrCreateAtomForLazySymbol(data_lazy_sym) catch |err|
1660 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
1661 const atom = elf_file.getAtom(atom_index);
1662 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
1663 const got_addr = atom.getOffsetTableAddress(elf_file);
1664 try self.asmRegisterMemory(
1665 .mov,
1666 data_reg.to64(),
1667 Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) }),
1668 );
1669 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
1670 const atom_index = coff_file.getOrCreateAtomForLazySymbol(data_lazy_sym) catch |err|
1671 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
1672 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
1673 try self.genSetReg(data_reg, Type.usize, .{ .lea_got = sym_index });
1674 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
1675 const atom_index = macho_file.getOrCreateAtomForLazySymbol(data_lazy_sym) catch |err|
1676 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
1677 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
1678 try self.genSetReg(data_reg, Type.usize, .{ .lea_got = sym_index });
1679 } else {
1680 return self.fail("TODO implement {s} for {}", .{
1681 @tagName(lazy_sym.kind),
1682 lazy_sym.ty.fmt(self.bin_file.options.module.?),
1683 });
1684 }
1685
1686 var data_off: i32 = 0;
1687 for (
1688 exitlude_jump_relocs,
1689 enum_ty.enumFields().keys(),
1690 0..,
1691 ) |*exitlude_jump_reloc, tag_name, index| {
1692 var tag_pl = Value.Payload.U32{
1693 .base = .{ .tag = .enum_field_index },
1694 .data = @intCast(u32, index),
1695 };
1696 const tag_val = Value.initPayload(&tag_pl.base);
1697 const tag_mcv = try self.genTypedValue(.{ .ty = enum_ty, .val = tag_val });
1698 try self.genBinOpMir(.cmp, enum_ty, enum_mcv, tag_mcv);
1699 const skip_reloc = try self.asmJccReloc(undefined, .ne);
1700
1701 try self.genSetMem(
1702 .{ .reg = ret_reg },
1703 0,
1704 Type.usize,
1705 .{ .register_offset = .{ .reg = data_reg, .off = data_off } },
1706 );
1707 try self.genSetMem(.{ .reg = ret_reg }, 8, Type.usize, .{ .immediate = tag_name.len });
1708
1709 exitlude_jump_reloc.* = try self.asmJmpReloc(undefined);
1710 try self.performReloc(skip_reloc);
1711
1712 data_off += @intCast(i32, tag_name.len + 1);
1713 }
1714
1715 try self.airTrap();
1716
1717 for (exitlude_jump_relocs) |reloc| try self.performReloc(reloc);
1718 try self.asmOpOnly(.ret);
1719 },
1720 else => return self.fail(
1721 "TODO implement {s} for {}",
1722 .{ @tagName(lazy_sym.kind), lazy_sym.ty.fmt(self.bin_file.options.module.?) },
1723 ),
1724 }
1725}
1726
1727fn getOwnerDecl(self: *const Self) Module.Decl.Index {
1728 return switch (self.owner) {
1729 .mod_fn => |mod_fn| mod_fn.owner_decl,
1730 .decl => |index| index,
1731 };
1732}
1733
15481734fn getValue(self: *Self, value: MCValue, inst: ?Air.Inst.Index) void {
15491735 const reg = value.getReg() orelse return;
15501736 if (self.register_manager.isRegFree(reg)) {
......@@ -6020,7 +6206,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void {
60206206
60216207 const ty = self.air.typeOfIndex(inst);
60226208 const src_index = self.air.instructions.items(.data)[inst].arg.src_index;
6023 const name = self.mod_fn.getParamName(self.bin_file.options.module.?, src_index);
6209 const name = self.owner.mod_fn.getParamName(self.bin_file.options.module.?, src_index);
60246210 try self.genArgDbgInfo(ty, name, dst_mcv);
60256211
60266212 break :result dst_mcv;
......@@ -6044,7 +6230,7 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void {
60446230 //},
60456231 else => unreachable, // not a valid function parameter
60466232 };
6047 try dw.genArgDbgInfo(name, ty, self.mod_fn.owner_decl, loc);
6233 try dw.genArgDbgInfo(name, ty, self.getOwnerDecl(), loc);
60486234 },
60496235 .plan9 => {},
60506236 .none => {},
......@@ -6085,7 +6271,7 @@ fn genVarDbgInfo(
60856271 break :blk .nop;
60866272 },
60876273 };
6088 try dw.genVarDbgInfo(name, ty, self.mod_fn.owner_decl, is_ptr, loc);
6274 try dw.genVarDbgInfo(name, ty, self.getOwnerDecl(), is_ptr, loc);
60896275 },
60906276 .plan9 => {},
60916277 .none => {},
......@@ -6243,7 +6429,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
62436429 const decl_name = mem.sliceTo(mod.declPtr(extern_fn.owner_decl).name, 0);
62446430 const lib_name = mem.sliceTo(extern_fn.lib_name, 0);
62456431 if (self.bin_file.cast(link.File.Coff)) |coff_file| {
6246 const atom_index = try self.getSymbolIndexForDecl(self.mod_fn.owner_decl);
6432 const atom_index = try self.getSymbolIndexForDecl(self.getOwnerDecl());
62476433 const sym_index = try coff_file.getGlobalSymbol(decl_name, lib_name);
62486434 _ = try self.addInst(.{
62496435 .tag = .mov_linker,
......@@ -6257,7 +6443,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
62576443 try self.asmRegister(.call, .rax);
62586444 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
62596445 const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name);
6260 const atom_index = try self.getSymbolIndexForDecl(self.mod_fn.owner_decl);
6446 const atom_index = try self.getSymbolIndexForDecl(self.getOwnerDecl());
62616447 _ = try self.addInst(.{
62626448 .tag = .call_extern,
62636449 .ops = undefined,
......@@ -6416,7 +6602,8 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {
64166602 const mod = self.bin_file.options.module.?;
64176603 const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, mod);
64186604 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
6419 const atom_index = try elf_file.getOrCreateAtomForLazySymbol(lazy_sym);
6605 const atom_index = elf_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
6606 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
64206607 const atom = elf_file.getAtom(atom_index);
64216608 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
64226609 const got_addr = atom.getOffsetTableAddress(elf_file);
......@@ -6426,11 +6613,13 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {
64266613 Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) }),
64276614 );
64286615 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
6429 const atom_index = try coff_file.getOrCreateAtomForLazySymbol(lazy_sym);
6616 const atom_index = coff_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
6617 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
64306618 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
64316619 try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index });
64326620 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
6433 const atom_index = try macho_file.getOrCreateAtomForLazySymbol(lazy_sym);
6621 const atom_index = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
6622 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
64346623 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
64356624 try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index });
64366625 } else {
......@@ -7530,7 +7719,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
75307719 }),
75317720 ),
75327721 .load_direct => |sym_index| if (try self.movMirTag(ty) == .mov) {
7533 const atom_index = try self.getSymbolIndexForDecl(self.mod_fn.owner_decl);
7722 const atom_index = try self.getSymbolIndexForDecl(self.getOwnerDecl());
75347723 _ = try self.addInst(.{
75357724 .tag = .mov_linker,
75367725 .ops = .direct_reloc,
......@@ -7557,7 +7746,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
75577746 );
75587747 },
75597748 .lea_direct, .lea_got => |sym_index| {
7560 const atom_index = try self.getSymbolIndexForDecl(self.mod_fn.owner_decl);
7749 const atom_index = try self.getSymbolIndexForDecl(self.getOwnerDecl());
75617750 _ = try self.addInst(.{
75627751 .tag = switch (src_mcv) {
75637752 .lea_direct => .lea_linker,
......@@ -7577,7 +7766,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr
75777766 });
75787767 },
75797768 .lea_tlv => |sym_index| {
7580 const atom_index = try self.getSymbolIndexForDecl(self.mod_fn.owner_decl);
7769 const atom_index = try self.getSymbolIndexForDecl(self.getOwnerDecl());
75817770 if (self.bin_file.cast(link.File.MachO)) |_| {
75827771 _ = try self.addInst(.{
75837772 .tag = .lea_linker,
......@@ -8475,10 +8664,64 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
84758664
84768665fn airTagName(self: *Self, inst: Air.Inst.Index) !void {
84778666 const un_op = self.air.instructions.items(.data)[inst].un_op;
8667 const inst_ty = self.air.typeOfIndex(inst);
8668 const enum_ty = self.air.typeOf(un_op);
8669
8670 // We need a properly aligned and sized call frame to be able to call this function.
8671 {
8672 const needed_call_frame = FrameAlloc.init(.{
8673 .size = inst_ty.abiSize(self.target.*),
8674 .alignment = inst_ty.abiAlignment(self.target.*),
8675 });
8676 const frame_allocs_slice = self.frame_allocs.slice();
8677 const stack_frame_size =
8678 &frame_allocs_slice.items(.abi_size)[@enumToInt(FrameIndex.call_frame)];
8679 stack_frame_size.* = @max(stack_frame_size.*, needed_call_frame.abi_size);
8680 const stack_frame_align =
8681 &frame_allocs_slice.items(.abi_align)[@enumToInt(FrameIndex.call_frame)];
8682 stack_frame_align.* = @max(stack_frame_align.*, needed_call_frame.abi_align);
8683 }
8684
8685 try self.spillEflagsIfOccupied();
8686 try self.spillRegisters(abi.getCallerPreservedRegs(self.target.*));
8687
8688 const param_regs = abi.getCAbiIntParamRegs(self.target.*);
8689
8690 const dst_mcv = try self.allocRegOrMem(inst, false);
8691 try self.genSetReg(param_regs[0], Type.usize, dst_mcv.address());
8692
84788693 const operand = try self.resolveInst(un_op);
8479 _ = operand;
8480 return self.fail("TODO implement airTagName for x86_64", .{});
8481 //return self.finishAir(inst, result, .{ un_op, .none, .none });
8694 try self.genSetReg(param_regs[1], enum_ty, operand);
8695
8696 const mod = self.bin_file.options.module.?;
8697 const lazy_sym = link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(), mod);
8698 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
8699 const atom_index = elf_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
8700 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
8701 const atom = elf_file.getAtom(atom_index);
8702 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
8703 const got_addr = atom.getOffsetTableAddress(elf_file);
8704 try self.asmMemory(
8705 .call,
8706 Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) }),
8707 );
8708 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
8709 const atom_index = coff_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
8710 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
8711 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
8712 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
8713 try self.asmRegister(.call, .rax);
8714 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
8715 const atom_index = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
8716 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
8717 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
8718 try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
8719 try self.asmRegister(.call, .rax);
8720 } else {
8721 return self.fail("TODO implement airTagName for x86_64 {s}", .{@tagName(self.bin_file.tag)});
8722 }
8723
8724 return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none });
84828725}
84838726
84848727fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
......@@ -8497,7 +8740,8 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
84978740 const mod = self.bin_file.options.module.?;
84988741 const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, mod);
84998742 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
8500 const atom_index = try elf_file.getOrCreateAtomForLazySymbol(lazy_sym);
8743 const atom_index = elf_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
8744 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
85018745 const atom = elf_file.getAtom(atom_index);
85028746 _ = try atom.getOrCreateOffsetTableEntry(elf_file);
85038747 const got_addr = atom.getOffsetTableAddress(elf_file);
......@@ -8507,11 +8751,13 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
85078751 Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) }),
85088752 );
85098753 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
8510 const atom_index = try coff_file.getOrCreateAtomForLazySymbol(lazy_sym);
8754 const atom_index = coff_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
8755 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
85118756 const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
85128757 try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index });
85138758 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
8514 const atom_index = try macho_file.getOrCreateAtomForLazySymbol(lazy_sym);
8759 const atom_index = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
8760 return self.fail("{s} creating lazy symbol", .{@errorName(err)});
85158761 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
85168762 try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index });
85178763 } else {
......@@ -8833,12 +9079,7 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV
88339079}
88349080
88359081fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
8836 const mcv: MCValue = switch (try codegen.genTypedValue(
8837 self.bin_file,
8838 self.src_loc,
8839 arg_tv,
8840 self.mod_fn.owner_decl,
8841 )) {
9082 return switch (try codegen.genTypedValue(self.bin_file, self.src_loc, arg_tv, self.getOwnerDecl())) {
88429083 .mcv => |mcv| switch (mcv) {
88439084 .none => .none,
88449085 .undef => .undef,
......@@ -8853,7 +9094,6 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
88539094 return error.CodegenFail;
88549095 },
88559096 };
8856 return mcv;
88579097}
88589098
88599099const CallMCValues = struct {
src/codegen.zig+34-6
......@@ -7,6 +7,7 @@ const link = @import("link.zig");
77const log = std.log.scoped(.codegen);
88const mem = std.mem;
99const math = std.math;
10const target_util = @import("target.zig");
1011const trace = @import("tracy.zig").trace;
1112
1213const Air = @import("Air.zig");
......@@ -89,6 +90,19 @@ pub fn generateFunction(
8990 }
9091}
9192
93pub fn generateLazyFunction(
94 bin_file: *link.File,
95 src_loc: Module.SrcLoc,
96 lazy_sym: link.File.LazySymbol,
97 code: *std.ArrayList(u8),
98 debug_output: DebugInfoOutput,
99) CodeGenError!Result {
100 switch (bin_file.options.target.cpu.arch) {
101 .x86_64 => return @import("arch/x86_64/CodeGen.zig").generateLazy(bin_file, src_loc, lazy_sym, code, debug_output),
102 else => unreachable,
103 }
104}
105
92106fn writeFloat(comptime F: type, f: F, target: Target, endian: std.builtin.Endian, code: []u8) void {
93107 _ = target;
94108 const bits = @typeInfo(F).Float.bits;
......@@ -101,11 +115,11 @@ pub fn generateLazySymbol(
101115 bin_file: *link.File,
102116 src_loc: Module.SrcLoc,
103117 lazy_sym: link.File.LazySymbol,
118 alignment: *u32,
104119 code: *std.ArrayList(u8),
105120 debug_output: DebugInfoOutput,
106121 reloc_info: RelocInfo,
107) CodeGenError!struct { res: Result, alignment: u32 } {
108 _ = debug_output;
122) CodeGenError!Result {
109123 _ = reloc_info;
110124
111125 const tracy = trace(@src());
......@@ -120,7 +134,13 @@ pub fn generateLazySymbol(
120134 lazy_sym.ty.fmt(mod),
121135 });
122136
123 if (lazy_sym.kind == .const_data and lazy_sym.ty.isAnyError()) {
137 if (lazy_sym.kind == .code) {
138 alignment.* = target_util.defaultFunctionAlignment(target);
139 return generateLazyFunction(bin_file, src_loc, lazy_sym, code, debug_output);
140 }
141
142 if (lazy_sym.ty.isAnyError()) {
143 alignment.* = 4;
124144 const err_names = mod.error_name_list.items;
125145 mem.writeInt(u32, try code.addManyAsArray(4), @intCast(u32, err_names.len), endian);
126146 var offset = code.items.len;
......@@ -133,13 +153,21 @@ pub fn generateLazySymbol(
133153 code.appendAssumeCapacity(0);
134154 }
135155 mem.writeInt(u32, code.items[offset..][0..4], @intCast(u32, code.items.len), endian);
136 return .{ .res = Result.ok, .alignment = 4 };
137 } else return .{ .res = .{ .fail = try ErrorMsg.create(
156 return Result.ok;
157 } else if (lazy_sym.ty.zigTypeTag() == .Enum) {
158 alignment.* = 1;
159 for (lazy_sym.ty.enumFields().keys()) |tag_name| {
160 try code.ensureUnusedCapacity(tag_name.len + 1);
161 code.appendSliceAssumeCapacity(tag_name);
162 code.appendAssumeCapacity(0);
163 }
164 return Result.ok;
165 } else return .{ .fail = try ErrorMsg.create(
138166 bin_file.allocator,
139167 src_loc,
140168 "TODO implement generateLazySymbol for {s} {}",
141169 .{ @tagName(lazy_sym.kind), lazy_sym.ty.fmt(mod) },
142 ) }, .alignment = undefined };
170 ) };
143171}
144172
145173pub fn generateSymbol(
src/link/Coff.zig+23-10
......@@ -1218,6 +1218,7 @@ fn updateLazySymbolAtom(
12181218 const gpa = self.base.allocator;
12191219 const mod = self.base.options.module.?;
12201220
1221 var required_alignment: u32 = undefined;
12211222 var code_buffer = std.ArrayList(u8).init(gpa);
12221223 defer code_buffer.deinit();
12231224
......@@ -1238,10 +1239,16 @@ fn updateLazySymbolAtom(
12381239 .parent_decl_node = undefined,
12391240 .lazy = .unneeded,
12401241 };
1241 const res = try codegen.generateLazySymbol(&self.base, src, sym, &code_buffer, .none, .{
1242 .parent_atom_index = local_sym_index,
1243 });
1244 const code = switch (res.res) {
1242 const res = try codegen.generateLazySymbol(
1243 &self.base,
1244 src,
1245 sym,
1246 &required_alignment,
1247 &code_buffer,
1248 .none,
1249 .{ .parent_atom_index = local_sym_index },
1250 );
1251 const code = switch (res) {
12451252 .ok => code_buffer.items,
12461253 .fail => |em| {
12471254 log.err("{s}", .{em.msg});
......@@ -1255,11 +1262,11 @@ fn updateLazySymbolAtom(
12551262 symbol.section_number = @intToEnum(coff.SectionNumber, section_index + 1);
12561263 symbol.type = .{ .complex_type = .NULL, .base_type = .NULL };
12571264
1258 const vaddr = try self.allocateAtom(atom_index, code_len, res.alignment);
1265 const vaddr = try self.allocateAtom(atom_index, code_len, required_alignment);
12591266 errdefer self.freeAtom(atom_index);
12601267
12611268 log.debug("allocated atom for {s} at 0x{x}", .{ name, vaddr });
1262 log.debug(" (required alignment 0x{x})", .{res.alignment});
1269 log.debug(" (required alignment 0x{x})", .{required_alignment});
12631270
12641271 atom.size = code_len;
12651272 symbol.value = vaddr;
......@@ -1270,14 +1277,20 @@ fn updateLazySymbolAtom(
12701277
12711278pub fn getOrCreateAtomForLazySymbol(self: *Coff, sym: link.File.LazySymbol) !Atom.Index {
12721279 const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl());
1273 errdefer _ = self.lazy_syms.pop();
1280 errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
12741281 if (!gop.found_existing) gop.value_ptr.* = .{};
1275 const atom = switch (sym.kind) {
1282 const atom_ptr = switch (sym.kind) {
12761283 .code => &gop.value_ptr.text_atom,
12771284 .const_data => &gop.value_ptr.rdata_atom,
12781285 };
1279 if (atom.* == null) atom.* = try self.createAtom();
1280 return atom.*.?;
1286 if (atom_ptr.*) |atom| return atom;
1287 const atom = try self.createAtom();
1288 atom_ptr.* = atom;
1289 try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) {
1290 .code => self.text_section_index.?,
1291 .const_data => self.rdata_section_index.?,
1292 });
1293 return atom;
12811294}
12821295
12831296pub fn getOrCreateAtomForDecl(self: *Coff, decl_index: Module.Decl.Index) !Atom.Index {
src/link/Elf.zig+22-9
......@@ -2376,14 +2376,20 @@ pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void {
23762376
23772377pub fn getOrCreateAtomForLazySymbol(self: *Elf, sym: File.LazySymbol) !Atom.Index {
23782378 const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl());
2379 errdefer _ = self.lazy_syms.pop();
2379 errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
23802380 if (!gop.found_existing) gop.value_ptr.* = .{};
2381 const atom = switch (sym.kind) {
2381 const atom_ptr = switch (sym.kind) {
23822382 .code => &gop.value_ptr.text_atom,
23832383 .const_data => &gop.value_ptr.rodata_atom,
23842384 };
2385 if (atom.* == null) atom.* = try self.createAtom();
2386 return atom.*.?;
2385 if (atom_ptr.*) |atom| return atom;
2386 const atom = try self.createAtom();
2387 atom_ptr.* = atom;
2388 try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) {
2389 .code => self.text_section_index.?,
2390 .const_data => self.rodata_section_index.?,
2391 });
2392 return atom;
23872393}
23882394
23892395pub fn getOrCreateAtomForDecl(self: *Elf, decl_index: Module.Decl.Index) !Atom.Index {
......@@ -2684,6 +2690,7 @@ fn updateLazySymbolAtom(
26842690 const gpa = self.base.allocator;
26852691 const mod = self.base.options.module.?;
26862692
2693 var required_alignment: u32 = undefined;
26872694 var code_buffer = std.ArrayList(u8).init(gpa);
26882695 defer code_buffer.deinit();
26892696
......@@ -2708,10 +2715,16 @@ fn updateLazySymbolAtom(
27082715 .parent_decl_node = undefined,
27092716 .lazy = .unneeded,
27102717 };
2711 const res = try codegen.generateLazySymbol(&self.base, src, sym, &code_buffer, .none, .{
2712 .parent_atom_index = local_sym_index,
2713 });
2714 const code = switch (res.res) {
2718 const res = try codegen.generateLazySymbol(
2719 &self.base,
2720 src,
2721 sym,
2722 &required_alignment,
2723 &code_buffer,
2724 .none,
2725 .{ .parent_atom_index = local_sym_index },
2726 );
2727 const code = switch (res) {
27152728 .ok => code_buffer.items,
27162729 .fail => |em| {
27172730 log.err("{s}", .{em.msg});
......@@ -2729,7 +2742,7 @@ fn updateLazySymbolAtom(
27292742 .st_value = 0,
27302743 .st_size = 0,
27312744 };
2732 const vaddr = try self.allocateAtom(atom_index, code.len, res.alignment);
2745 const vaddr = try self.allocateAtom(atom_index, code.len, required_alignment);
27332746 errdefer self.freeAtom(atom_index);
27342747 log.debug("allocated text block for {s} at 0x{x}", .{ name, vaddr });
27352748
src/link/MachO.zig+23-10
......@@ -2060,6 +2060,7 @@ fn updateLazySymbolAtom(
20602060 const gpa = self.base.allocator;
20612061 const mod = self.base.options.module.?;
20622062
2063 var required_alignment: u32 = undefined;
20632064 var code_buffer = std.ArrayList(u8).init(gpa);
20642065 defer code_buffer.deinit();
20652066
......@@ -2084,10 +2085,16 @@ fn updateLazySymbolAtom(
20842085 .parent_decl_node = undefined,
20852086 .lazy = .unneeded,
20862087 };
2087 const res = try codegen.generateLazySymbol(&self.base, src, sym, &code_buffer, .none, .{
2088 .parent_atom_index = local_sym_index,
2089 });
2090 const code = switch (res.res) {
2088 const res = try codegen.generateLazySymbol(
2089 &self.base,
2090 src,
2091 sym,
2092 &required_alignment,
2093 &code_buffer,
2094 .none,
2095 .{ .parent_atom_index = local_sym_index },
2096 );
2097 const code = switch (res) {
20912098 .ok => code_buffer.items,
20922099 .fail => |em| {
20932100 log.err("{s}", .{em.msg});
......@@ -2101,11 +2108,11 @@ fn updateLazySymbolAtom(
21012108 symbol.n_sect = section_index + 1;
21022109 symbol.n_desc = 0;
21032110
2104 const vaddr = try self.allocateAtom(atom_index, code.len, res.alignment);
2111 const vaddr = try self.allocateAtom(atom_index, code.len, required_alignment);
21052112 errdefer self.freeAtom(atom_index);
21062113
21072114 log.debug("allocated atom for {s} at 0x{x}", .{ name, vaddr });
2108 log.debug(" (required alignment 0x{x}", .{res.alignment});
2115 log.debug(" (required alignment 0x{x}", .{required_alignment});
21092116
21102117 atom.size = code.len;
21112118 symbol.n_value = vaddr;
......@@ -2116,14 +2123,20 @@ fn updateLazySymbolAtom(
21162123
21172124pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.Index {
21182125 const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl());
2119 errdefer _ = self.lazy_syms.pop();
2126 errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
21202127 if (!gop.found_existing) gop.value_ptr.* = .{};
2121 const atom = switch (sym.kind) {
2128 const atom_ptr = switch (sym.kind) {
21222129 .code => &gop.value_ptr.text_atom,
21232130 .const_data => &gop.value_ptr.data_const_atom,
21242131 };
2125 if (atom.* == null) atom.* = try self.createAtom();
2126 return atom.*.?;
2132 if (atom_ptr.*) |atom| return atom;
2133 const atom = try self.createAtom();
2134 atom_ptr.* = atom;
2135 try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) {
2136 .code => self.text_section_index.?,
2137 .const_data => self.data_const_section_index.?,
2138 });
2139 return atom;
21272140}
21282141
21292142fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.Decl.Index) !void {
test/behavior/enum.zig-5
......@@ -981,7 +981,6 @@ fn test3_2(f: Test3Foo) !void {
981981}
982982
983983test "@tagName" {
984 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
985984 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
986985 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
987986 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -997,7 +996,6 @@ fn testEnumTagNameBare(n: anytype) []const u8 {
997996const BareNumber = enum { One, Two, Three };
998997
999998test "@tagName non-exhaustive enum" {
1000 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1001999 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
10021000 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10031001 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1008,7 +1006,6 @@ test "@tagName non-exhaustive enum" {
10081006const NonExhaustive = enum(u8) { A, B, _ };
10091007
10101008test "@tagName is null-terminated" {
1011 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
10121009 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
10131010 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10141011 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1023,7 +1020,6 @@ test "@tagName is null-terminated" {
10231020}
10241021
10251022test "tag name with assigned enum values" {
1026 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
10271023 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
10281024 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
10291025 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -1113,7 +1109,6 @@ test "enum literal in array literal" {
11131109
11141110test "tag name functions are unique" {
11151111 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1116 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
11171112 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
11181113 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
11191114 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
test/behavior/memset.zig-2
......@@ -114,7 +114,6 @@ test "memset with large array element, runtime known" {
114114 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
115115 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
116116 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
117 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
118117
119118 const A = [128]u64;
120119 var buf: [5]A = undefined;
......@@ -132,7 +131,6 @@ test "memset with large array element, comptime known" {
132131 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
133132 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest;
134133 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest;
135 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
136134
137135 const A = [128]u64;
138136 var buf: [5]A = undefined;
test/behavior/type.zig-2
......@@ -258,7 +258,6 @@ test "Type.ErrorSet" {
258258
259259test "Type.Struct" {
260260 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
261 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
262261 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
263262 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
264263 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
......@@ -383,7 +382,6 @@ test "Type.Enum" {
383382
384383test "Type.Union" {
385384 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
386 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
387385 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
388386 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
389387
test/behavior/union.zig-1
......@@ -1094,7 +1094,6 @@ test "containers with single-field enums" {
10941094test "@unionInit on union with tag but no fields" {
10951095 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
10961096 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1097 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
10981097 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
10991098 if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO
11001099