| author | |
| committer | |
| log | 47a34d038dd114533c3fcb130e03249ad846fe9c |
| tree | 6469bd38ce404ef80b0ad8258934c586cf0318e5 |
| parent | 0489a63a432b31ce0fd9d6ec6c8e2fb72a920573 |
9 files changed, 368 insertions(+), 71 deletions(-)
src/arch/x86_64/CodeGen.zig+266-26| ... | @@ -56,7 +56,10 @@ liveness: Liveness, | ... | @@ -56,7 +56,10 @@ liveness: Liveness, |
| 56 | bin_file: *link.File, | 56 | bin_file: *link.File, |
| 57 | debug_output: DebugInfoOutput, | 57 | debug_output: DebugInfoOutput, |
| 58 | target: *const std.Target, | 58 | target: *const std.Target, |
| 59 | mod_fn: *const Module.Fn, | 59 | owner: union(enum) { |
| 60 | mod_fn: *const Module.Fn, | ||
| 61 | decl: Module.Decl.Index, | ||
| 62 | }, | ||
| 60 | err_msg: ?*ErrorMsg, | 63 | err_msg: ?*ErrorMsg, |
| 61 | args: []MCValue, | 64 | args: []MCValue, |
| 62 | ret_mcv: InstTracking, | 65 | ret_mcv: InstTracking, |
| ... | @@ -617,7 +620,7 @@ pub fn generate( | ... | @@ -617,7 +620,7 @@ pub fn generate( |
| 617 | .target = &bin_file.options.target, | 620 | .target = &bin_file.options.target, |
| 618 | .bin_file = bin_file, | 621 | .bin_file = bin_file, |
| 619 | .debug_output = debug_output, | 622 | .debug_output = debug_output, |
| 620 | .mod_fn = module_fn, | 623 | .owner = .{ .mod_fn = module_fn }, |
| 621 | .err_msg = null, | 624 | .err_msg = null, |
| 622 | .args = undefined, // populated after `resolveCallingConventionValues` | 625 | .args = undefined, // populated after `resolveCallingConventionValues` |
| 623 | .ret_mcv = undefined, // populated after `resolveCallingConventionValues` | 626 | .ret_mcv = undefined, // populated after `resolveCallingConventionValues` |
| ... | @@ -745,6 +748,92 @@ pub fn generate( | ... | @@ -745,6 +748,92 @@ pub fn generate( |
| 745 | } | 748 | } |
| 746 | } | 749 | } |
| 747 | 750 | ||
| 751 | pub 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 | |||
| 748 | const FormatDeclData = struct { | 837 | const FormatDeclData = struct { |
| 749 | mod: *Module, | 838 | mod: *Module, |
| 750 | decl_index: Module.Decl.Index, | 839 | decl_index: Module.Decl.Index, |
| ... | @@ -1545,6 +1634,103 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { | ... | @@ -1545,6 +1634,103 @@ fn genBody(self: *Self, body: []const Air.Inst.Index) InnerError!void { |
| 1545 | verbose_tracking_log.debug("{}", .{self.fmtTracking()}); | 1634 | verbose_tracking_log.debug("{}", .{self.fmtTracking()}); |
| 1546 | } | 1635 | } |
| 1547 | 1636 | ||
| 1637 | fn 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 | |||
| 1727 | fn 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 | |||
| 1548 | fn getValue(self: *Self, value: MCValue, inst: ?Air.Inst.Index) void { | 1734 | fn getValue(self: *Self, value: MCValue, inst: ?Air.Inst.Index) void { |
| 1549 | const reg = value.getReg() orelse return; | 1735 | const reg = value.getReg() orelse return; |
| 1550 | if (self.register_manager.isRegFree(reg)) { | 1736 | if (self.register_manager.isRegFree(reg)) { |
| ... | @@ -6020,7 +6206,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6020,7 +6206,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) !void { |
| 6020 | 6206 | ||
| 6021 | const ty = self.air.typeOfIndex(inst); | 6207 | const ty = self.air.typeOfIndex(inst); |
| 6022 | const src_index = self.air.instructions.items(.data)[inst].arg.src_index; | 6208 | 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); |
| 6024 | try self.genArgDbgInfo(ty, name, dst_mcv); | 6210 | try self.genArgDbgInfo(ty, name, dst_mcv); |
| 6025 | 6211 | ||
| 6026 | break :result dst_mcv; | 6212 | break :result dst_mcv; |
| ... | @@ -6044,7 +6230,7 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { | ... | @@ -6044,7 +6230,7 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { |
| 6044 | //}, | 6230 | //}, |
| 6045 | else => unreachable, // not a valid function parameter | 6231 | else => unreachable, // not a valid function parameter |
| 6046 | }; | 6232 | }; |
| 6047 | try dw.genArgDbgInfo(name, ty, self.mod_fn.owner_decl, loc); | 6233 | try dw.genArgDbgInfo(name, ty, self.getOwnerDecl(), loc); |
| 6048 | }, | 6234 | }, |
| 6049 | .plan9 => {}, | 6235 | .plan9 => {}, |
| 6050 | .none => {}, | 6236 | .none => {}, |
| ... | @@ -6085,7 +6271,7 @@ fn genVarDbgInfo( | ... | @@ -6085,7 +6271,7 @@ fn genVarDbgInfo( |
| 6085 | break :blk .nop; | 6271 | break :blk .nop; |
| 6086 | }, | 6272 | }, |
| 6087 | }; | 6273 | }; |
| 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); |
| 6089 | }, | 6275 | }, |
| 6090 | .plan9 => {}, | 6276 | .plan9 => {}, |
| 6091 | .none => {}, | 6277 | .none => {}, |
| ... | @@ -6243,7 +6429,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -6243,7 +6429,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 6243 | const decl_name = mem.sliceTo(mod.declPtr(extern_fn.owner_decl).name, 0); | 6429 | const decl_name = mem.sliceTo(mod.declPtr(extern_fn.owner_decl).name, 0); |
| 6244 | const lib_name = mem.sliceTo(extern_fn.lib_name, 0); | 6430 | const lib_name = mem.sliceTo(extern_fn.lib_name, 0); |
| 6245 | if (self.bin_file.cast(link.File.Coff)) |coff_file| { | 6431 | 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()); |
| 6247 | const sym_index = try coff_file.getGlobalSymbol(decl_name, lib_name); | 6433 | const sym_index = try coff_file.getGlobalSymbol(decl_name, lib_name); |
| 6248 | _ = try self.addInst(.{ | 6434 | _ = try self.addInst(.{ |
| 6249 | .tag = .mov_linker, | 6435 | .tag = .mov_linker, |
| ... | @@ -6257,7 +6443,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier | ... | @@ -6257,7 +6443,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier |
| 6257 | try self.asmRegister(.call, .rax); | 6443 | try self.asmRegister(.call, .rax); |
| 6258 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | 6444 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 6259 | const sym_index = try macho_file.getGlobalSymbol(decl_name, lib_name); | 6445 | 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()); |
| 6261 | _ = try self.addInst(.{ | 6447 | _ = try self.addInst(.{ |
| 6262 | .tag = .call_extern, | 6448 | .tag = .call_extern, |
| 6263 | .ops = undefined, | 6449 | .ops = undefined, |
| ... | @@ -6416,7 +6602,8 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6416,7 +6602,8 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { |
| 6416 | const mod = self.bin_file.options.module.?; | 6602 | const mod = self.bin_file.options.module.?; |
| 6417 | const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, mod); | 6603 | const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, mod); |
| 6418 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | 6604 | 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)}); | ||
| 6420 | const atom = elf_file.getAtom(atom_index); | 6607 | const atom = elf_file.getAtom(atom_index); |
| 6421 | _ = try atom.getOrCreateOffsetTableEntry(elf_file); | 6608 | _ = try atom.getOrCreateOffsetTableEntry(elf_file); |
| 6422 | const got_addr = atom.getOffsetTableAddress(elf_file); | 6609 | const got_addr = atom.getOffsetTableAddress(elf_file); |
| ... | @@ -6426,11 +6613,13 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -6426,11 +6613,13 @@ fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { |
| 6426 | Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) }), | 6613 | Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) }), |
| 6427 | ); | 6614 | ); |
| 6428 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | 6615 | } 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)}); | ||
| 6430 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; | 6618 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; |
| 6431 | try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index }); | 6619 | try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index }); |
| 6432 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | 6620 | } 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)}); | ||
| 6434 | const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; | 6623 | const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; |
| 6435 | try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index }); | 6624 | try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index }); |
| 6436 | } else { | 6625 | } else { |
| ... | @@ -7530,7 +7719,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -7530,7 +7719,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 7530 | }), | 7719 | }), |
| 7531 | ), | 7720 | ), |
| 7532 | .load_direct => |sym_index| if (try self.movMirTag(ty) == .mov) { | 7721 | .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()); |
| 7534 | _ = try self.addInst(.{ | 7723 | _ = try self.addInst(.{ |
| 7535 | .tag = .mov_linker, | 7724 | .tag = .mov_linker, |
| 7536 | .ops = .direct_reloc, | 7725 | .ops = .direct_reloc, |
| ... | @@ -7557,7 +7746,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -7557,7 +7746,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 7557 | ); | 7746 | ); |
| 7558 | }, | 7747 | }, |
| 7559 | .lea_direct, .lea_got => |sym_index| { | 7748 | .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()); |
| 7561 | _ = try self.addInst(.{ | 7750 | _ = try self.addInst(.{ |
| 7562 | .tag = switch (src_mcv) { | 7751 | .tag = switch (src_mcv) { |
| 7563 | .lea_direct => .lea_linker, | 7752 | .lea_direct => .lea_linker, |
| ... | @@ -7577,7 +7766,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr | ... | @@ -7577,7 +7766,7 @@ fn genSetReg(self: *Self, dst_reg: Register, ty: Type, src_mcv: MCValue) InnerEr |
| 7577 | }); | 7766 | }); |
| 7578 | }, | 7767 | }, |
| 7579 | .lea_tlv => |sym_index| { | 7768 | .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()); |
| 7581 | if (self.bin_file.cast(link.File.MachO)) |_| { | 7770 | if (self.bin_file.cast(link.File.MachO)) |_| { |
| 7582 | _ = try self.addInst(.{ | 7771 | _ = try self.addInst(.{ |
| 7583 | .tag = .lea_linker, | 7772 | .tag = .lea_linker, |
| ... | @@ -8475,10 +8664,64 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8475,10 +8664,64 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { |
| 8475 | 8664 | ||
| 8476 | fn airTagName(self: *Self, inst: Air.Inst.Index) !void { | 8665 | fn airTagName(self: *Self, inst: Air.Inst.Index) !void { |
| 8477 | const un_op = self.air.instructions.items(.data)[inst].un_op; | 8666 | 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 | |||
| 8478 | const operand = try self.resolveInst(un_op); | 8693 | const operand = try self.resolveInst(un_op); |
| 8479 | _ = operand; | 8694 | try self.genSetReg(param_regs[1], enum_ty, operand); |
| 8480 | return self.fail("TODO implement airTagName for x86_64", .{}); | 8695 | |
| 8481 | //return self.finishAir(inst, result, .{ un_op, .none, .none }); | 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 }); | ||
| 8482 | } | 8725 | } |
| 8483 | 8726 | ||
| 8484 | fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { | 8727 | fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { |
| ... | @@ -8497,7 +8740,8 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8497,7 +8740,8 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { |
| 8497 | const mod = self.bin_file.options.module.?; | 8740 | const mod = self.bin_file.options.module.?; |
| 8498 | const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, mod); | 8741 | const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, mod); |
| 8499 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | 8742 | 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)}); | ||
| 8501 | const atom = elf_file.getAtom(atom_index); | 8745 | const atom = elf_file.getAtom(atom_index); |
| 8502 | _ = try atom.getOrCreateOffsetTableEntry(elf_file); | 8746 | _ = try atom.getOrCreateOffsetTableEntry(elf_file); |
| 8503 | const got_addr = atom.getOffsetTableAddress(elf_file); | 8747 | const got_addr = atom.getOffsetTableAddress(elf_file); |
| ... | @@ -8507,11 +8751,13 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { | ... | @@ -8507,11 +8751,13 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { |
| 8507 | Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) }), | 8751 | Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) }), |
| 8508 | ); | 8752 | ); |
| 8509 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | 8753 | } 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)}); | ||
| 8511 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; | 8756 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; |
| 8512 | try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index }); | 8757 | try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index }); |
| 8513 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | 8758 | } 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)}); | ||
| 8515 | const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; | 8761 | const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; |
| 8516 | try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index }); | 8762 | try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index }); |
| 8517 | } else { | 8763 | } else { |
| ... | @@ -8833,12 +9079,7 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV | ... | @@ -8833,12 +9079,7 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV |
| 8833 | } | 9079 | } |
| 8834 | 9080 | ||
| 8835 | fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { | 9081 | fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { |
| 8836 | const mcv: MCValue = switch (try codegen.genTypedValue( | 9082 | return switch (try codegen.genTypedValue(self.bin_file, self.src_loc, arg_tv, self.getOwnerDecl())) { |
| 8837 | self.bin_file, | ||
| 8838 | self.src_loc, | ||
| 8839 | arg_tv, | ||
| 8840 | self.mod_fn.owner_decl, | ||
| 8841 | )) { | ||
| 8842 | .mcv => |mcv| switch (mcv) { | 9083 | .mcv => |mcv| switch (mcv) { |
| 8843 | .none => .none, | 9084 | .none => .none, |
| 8844 | .undef => .undef, | 9085 | .undef => .undef, |
| ... | @@ -8853,7 +9094,6 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { | ... | @@ -8853,7 +9094,6 @@ fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { |
| 8853 | return error.CodegenFail; | 9094 | return error.CodegenFail; |
| 8854 | }, | 9095 | }, |
| 8855 | }; | 9096 | }; |
| 8856 | return mcv; | ||
| 8857 | } | 9097 | } |
| 8858 | 9098 | ||
| 8859 | const CallMCValues = struct { | 9099 | const CallMCValues = struct { |
src/codegen.zig+34-6| ... | @@ -7,6 +7,7 @@ const link = @import("link.zig"); | ... | @@ -7,6 +7,7 @@ const link = @import("link.zig"); |
| 7 | const log = std.log.scoped(.codegen); | 7 | const log = std.log.scoped(.codegen); |
| 8 | const mem = std.mem; | 8 | const mem = std.mem; |
| 9 | const math = std.math; | 9 | const math = std.math; |
| 10 | const target_util = @import("target.zig"); | ||
| 10 | const trace = @import("tracy.zig").trace; | 11 | const trace = @import("tracy.zig").trace; |
| 11 | 12 | ||
| 12 | const Air = @import("Air.zig"); | 13 | const Air = @import("Air.zig"); |
| ... | @@ -89,6 +90,19 @@ pub fn generateFunction( | ... | @@ -89,6 +90,19 @@ pub fn generateFunction( |
| 89 | } | 90 | } |
| 90 | } | 91 | } |
| 91 | 92 | ||
| 93 | pub 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 | |||
| 92 | fn writeFloat(comptime F: type, f: F, target: Target, endian: std.builtin.Endian, code: []u8) void { | 106 | fn writeFloat(comptime F: type, f: F, target: Target, endian: std.builtin.Endian, code: []u8) void { |
| 93 | _ = target; | 107 | _ = target; |
| 94 | const bits = @typeInfo(F).Float.bits; | 108 | const bits = @typeInfo(F).Float.bits; |
| ... | @@ -101,11 +115,11 @@ pub fn generateLazySymbol( | ... | @@ -101,11 +115,11 @@ pub fn generateLazySymbol( |
| 101 | bin_file: *link.File, | 115 | bin_file: *link.File, |
| 102 | src_loc: Module.SrcLoc, | 116 | src_loc: Module.SrcLoc, |
| 103 | lazy_sym: link.File.LazySymbol, | 117 | lazy_sym: link.File.LazySymbol, |
| 118 | alignment: *u32, | ||
| 104 | code: *std.ArrayList(u8), | 119 | code: *std.ArrayList(u8), |
| 105 | debug_output: DebugInfoOutput, | 120 | debug_output: DebugInfoOutput, |
| 106 | reloc_info: RelocInfo, | 121 | reloc_info: RelocInfo, |
| 107 | ) CodeGenError!struct { res: Result, alignment: u32 } { | 122 | ) CodeGenError!Result { |
| 108 | _ = debug_output; | ||
| 109 | _ = reloc_info; | 123 | _ = reloc_info; |
| 110 | 124 | ||
| 111 | const tracy = trace(@src()); | 125 | const tracy = trace(@src()); |
| ... | @@ -120,7 +134,13 @@ pub fn generateLazySymbol( | ... | @@ -120,7 +134,13 @@ pub fn generateLazySymbol( |
| 120 | lazy_sym.ty.fmt(mod), | 134 | lazy_sym.ty.fmt(mod), |
| 121 | }); | 135 | }); |
| 122 | 136 | ||
| 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; | ||
| 124 | const err_names = mod.error_name_list.items; | 144 | const err_names = mod.error_name_list.items; |
| 125 | mem.writeInt(u32, try code.addManyAsArray(4), @intCast(u32, err_names.len), endian); | 145 | mem.writeInt(u32, try code.addManyAsArray(4), @intCast(u32, err_names.len), endian); |
| 126 | var offset = code.items.len; | 146 | var offset = code.items.len; |
| ... | @@ -133,13 +153,21 @@ pub fn generateLazySymbol( | ... | @@ -133,13 +153,21 @@ pub fn generateLazySymbol( |
| 133 | code.appendAssumeCapacity(0); | 153 | code.appendAssumeCapacity(0); |
| 134 | } | 154 | } |
| 135 | mem.writeInt(u32, code.items[offset..][0..4], @intCast(u32, code.items.len), endian); | 155 | mem.writeInt(u32, code.items[offset..][0..4], @intCast(u32, code.items.len), endian); |
| 136 | return .{ .res = Result.ok, .alignment = 4 }; | 156 | return Result.ok; |
| 137 | } else return .{ .res = .{ .fail = try ErrorMsg.create( | 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( | ||
| 138 | bin_file.allocator, | 166 | bin_file.allocator, |
| 139 | src_loc, | 167 | src_loc, |
| 140 | "TODO implement generateLazySymbol for {s} {}", | 168 | "TODO implement generateLazySymbol for {s} {}", |
| 141 | .{ @tagName(lazy_sym.kind), lazy_sym.ty.fmt(mod) }, | 169 | .{ @tagName(lazy_sym.kind), lazy_sym.ty.fmt(mod) }, |
| 142 | ) }, .alignment = undefined }; | 170 | ) }; |
| 143 | } | 171 | } |
| 144 | 172 | ||
| 145 | pub fn generateSymbol( | 173 | pub fn generateSymbol( |
src/link/Coff.zig+23-10| ... | @@ -1218,6 +1218,7 @@ fn updateLazySymbolAtom( | ... | @@ -1218,6 +1218,7 @@ fn updateLazySymbolAtom( |
| 1218 | const gpa = self.base.allocator; | 1218 | const gpa = self.base.allocator; |
| 1219 | const mod = self.base.options.module.?; | 1219 | const mod = self.base.options.module.?; |
| 1220 | 1220 | ||
| 1221 | var required_alignment: u32 = undefined; | ||
| 1221 | var code_buffer = std.ArrayList(u8).init(gpa); | 1222 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 1222 | defer code_buffer.deinit(); | 1223 | defer code_buffer.deinit(); |
| 1223 | 1224 | ||
| ... | @@ -1238,10 +1239,16 @@ fn updateLazySymbolAtom( | ... | @@ -1238,10 +1239,16 @@ fn updateLazySymbolAtom( |
| 1238 | .parent_decl_node = undefined, | 1239 | .parent_decl_node = undefined, |
| 1239 | .lazy = .unneeded, | 1240 | .lazy = .unneeded, |
| 1240 | }; | 1241 | }; |
| 1241 | const res = try codegen.generateLazySymbol(&self.base, src, sym, &code_buffer, .none, .{ | 1242 | const res = try codegen.generateLazySymbol( |
| 1242 | .parent_atom_index = local_sym_index, | 1243 | &self.base, |
| 1243 | }); | 1244 | src, |
| 1244 | const code = switch (res.res) { | 1245 | sym, |
| 1246 | &required_alignment, | ||
| 1247 | &code_buffer, | ||
| 1248 | .none, | ||
| 1249 | .{ .parent_atom_index = local_sym_index }, | ||
| 1250 | ); | ||
| 1251 | const code = switch (res) { | ||
| 1245 | .ok => code_buffer.items, | 1252 | .ok => code_buffer.items, |
| 1246 | .fail => |em| { | 1253 | .fail => |em| { |
| 1247 | log.err("{s}", .{em.msg}); | 1254 | log.err("{s}", .{em.msg}); |
| ... | @@ -1255,11 +1262,11 @@ fn updateLazySymbolAtom( | ... | @@ -1255,11 +1262,11 @@ fn updateLazySymbolAtom( |
| 1255 | symbol.section_number = @intToEnum(coff.SectionNumber, section_index + 1); | 1262 | symbol.section_number = @intToEnum(coff.SectionNumber, section_index + 1); |
| 1256 | symbol.type = .{ .complex_type = .NULL, .base_type = .NULL }; | 1263 | symbol.type = .{ .complex_type = .NULL, .base_type = .NULL }; |
| 1257 | 1264 | ||
| 1258 | const vaddr = try self.allocateAtom(atom_index, code_len, res.alignment); | 1265 | const vaddr = try self.allocateAtom(atom_index, code_len, required_alignment); |
| 1259 | errdefer self.freeAtom(atom_index); | 1266 | errdefer self.freeAtom(atom_index); |
| 1260 | 1267 | ||
| 1261 | log.debug("allocated atom for {s} at 0x{x}", .{ name, vaddr }); | 1268 | 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}); |
| 1263 | 1270 | ||
| 1264 | atom.size = code_len; | 1271 | atom.size = code_len; |
| 1265 | symbol.value = vaddr; | 1272 | symbol.value = vaddr; |
| ... | @@ -1270,14 +1277,20 @@ fn updateLazySymbolAtom( | ... | @@ -1270,14 +1277,20 @@ fn updateLazySymbolAtom( |
| 1270 | 1277 | ||
| 1271 | pub fn getOrCreateAtomForLazySymbol(self: *Coff, sym: link.File.LazySymbol) !Atom.Index { | 1278 | pub fn getOrCreateAtomForLazySymbol(self: *Coff, sym: link.File.LazySymbol) !Atom.Index { |
| 1272 | const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl()); | 1279 | 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(); |
| 1274 | if (!gop.found_existing) gop.value_ptr.* = .{}; | 1281 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 1275 | const atom = switch (sym.kind) { | 1282 | const atom_ptr = switch (sym.kind) { |
| 1276 | .code => &gop.value_ptr.text_atom, | 1283 | .code => &gop.value_ptr.text_atom, |
| 1277 | .const_data => &gop.value_ptr.rdata_atom, | 1284 | .const_data => &gop.value_ptr.rdata_atom, |
| 1278 | }; | 1285 | }; |
| 1279 | if (atom.* == null) atom.* = try self.createAtom(); | 1286 | if (atom_ptr.*) |atom| return atom; |
| 1280 | 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; | ||
| 1281 | } | 1294 | } |
| 1282 | 1295 | ||
| 1283 | pub fn getOrCreateAtomForDecl(self: *Coff, decl_index: Module.Decl.Index) !Atom.Index { | 1296 | pub 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 { | ... | @@ -2376,14 +2376,20 @@ pub fn freeDecl(self: *Elf, decl_index: Module.Decl.Index) void { |
| 2376 | 2376 | ||
| 2377 | pub fn getOrCreateAtomForLazySymbol(self: *Elf, sym: File.LazySymbol) !Atom.Index { | 2377 | pub fn getOrCreateAtomForLazySymbol(self: *Elf, sym: File.LazySymbol) !Atom.Index { |
| 2378 | const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl()); | 2378 | 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(); |
| 2380 | if (!gop.found_existing) gop.value_ptr.* = .{}; | 2380 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 2381 | const atom = switch (sym.kind) { | 2381 | const atom_ptr = switch (sym.kind) { |
| 2382 | .code => &gop.value_ptr.text_atom, | 2382 | .code => &gop.value_ptr.text_atom, |
| 2383 | .const_data => &gop.value_ptr.rodata_atom, | 2383 | .const_data => &gop.value_ptr.rodata_atom, |
| 2384 | }; | 2384 | }; |
| 2385 | if (atom.* == null) atom.* = try self.createAtom(); | 2385 | if (atom_ptr.*) |atom| return atom; |
| 2386 | 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; | ||
| 2387 | } | 2393 | } |
| 2388 | 2394 | ||
| 2389 | pub fn getOrCreateAtomForDecl(self: *Elf, decl_index: Module.Decl.Index) !Atom.Index { | 2395 | pub fn getOrCreateAtomForDecl(self: *Elf, decl_index: Module.Decl.Index) !Atom.Index { |
| ... | @@ -2684,6 +2690,7 @@ fn updateLazySymbolAtom( | ... | @@ -2684,6 +2690,7 @@ fn updateLazySymbolAtom( |
| 2684 | const gpa = self.base.allocator; | 2690 | const gpa = self.base.allocator; |
| 2685 | const mod = self.base.options.module.?; | 2691 | const mod = self.base.options.module.?; |
| 2686 | 2692 | ||
| 2693 | var required_alignment: u32 = undefined; | ||
| 2687 | var code_buffer = std.ArrayList(u8).init(gpa); | 2694 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 2688 | defer code_buffer.deinit(); | 2695 | defer code_buffer.deinit(); |
| 2689 | 2696 | ||
| ... | @@ -2708,10 +2715,16 @@ fn updateLazySymbolAtom( | ... | @@ -2708,10 +2715,16 @@ fn updateLazySymbolAtom( |
| 2708 | .parent_decl_node = undefined, | 2715 | .parent_decl_node = undefined, |
| 2709 | .lazy = .unneeded, | 2716 | .lazy = .unneeded, |
| 2710 | }; | 2717 | }; |
| 2711 | const res = try codegen.generateLazySymbol(&self.base, src, sym, &code_buffer, .none, .{ | 2718 | const res = try codegen.generateLazySymbol( |
| 2712 | .parent_atom_index = local_sym_index, | 2719 | &self.base, |
| 2713 | }); | 2720 | src, |
| 2714 | const code = switch (res.res) { | 2721 | sym, |
| 2722 | &required_alignment, | ||
| 2723 | &code_buffer, | ||
| 2724 | .none, | ||
| 2725 | .{ .parent_atom_index = local_sym_index }, | ||
| 2726 | ); | ||
| 2727 | const code = switch (res) { | ||
| 2715 | .ok => code_buffer.items, | 2728 | .ok => code_buffer.items, |
| 2716 | .fail => |em| { | 2729 | .fail => |em| { |
| 2717 | log.err("{s}", .{em.msg}); | 2730 | log.err("{s}", .{em.msg}); |
| ... | @@ -2729,7 +2742,7 @@ fn updateLazySymbolAtom( | ... | @@ -2729,7 +2742,7 @@ fn updateLazySymbolAtom( |
| 2729 | .st_value = 0, | 2742 | .st_value = 0, |
| 2730 | .st_size = 0, | 2743 | .st_size = 0, |
| 2731 | }; | 2744 | }; |
| 2732 | const vaddr = try self.allocateAtom(atom_index, code.len, res.alignment); | 2745 | const vaddr = try self.allocateAtom(atom_index, code.len, required_alignment); |
| 2733 | errdefer self.freeAtom(atom_index); | 2746 | errdefer self.freeAtom(atom_index); |
| 2734 | log.debug("allocated text block for {s} at 0x{x}", .{ name, vaddr }); | 2747 | log.debug("allocated text block for {s} at 0x{x}", .{ name, vaddr }); |
| 2735 | 2748 |
src/link/MachO.zig+23-10| ... | @@ -2060,6 +2060,7 @@ fn updateLazySymbolAtom( | ... | @@ -2060,6 +2060,7 @@ fn updateLazySymbolAtom( |
| 2060 | const gpa = self.base.allocator; | 2060 | const gpa = self.base.allocator; |
| 2061 | const mod = self.base.options.module.?; | 2061 | const mod = self.base.options.module.?; |
| 2062 | 2062 | ||
| 2063 | var required_alignment: u32 = undefined; | ||
| 2063 | var code_buffer = std.ArrayList(u8).init(gpa); | 2064 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 2064 | defer code_buffer.deinit(); | 2065 | defer code_buffer.deinit(); |
| 2065 | 2066 | ||
| ... | @@ -2084,10 +2085,16 @@ fn updateLazySymbolAtom( | ... | @@ -2084,10 +2085,16 @@ fn updateLazySymbolAtom( |
| 2084 | .parent_decl_node = undefined, | 2085 | .parent_decl_node = undefined, |
| 2085 | .lazy = .unneeded, | 2086 | .lazy = .unneeded, |
| 2086 | }; | 2087 | }; |
| 2087 | const res = try codegen.generateLazySymbol(&self.base, src, sym, &code_buffer, .none, .{ | 2088 | const res = try codegen.generateLazySymbol( |
| 2088 | .parent_atom_index = local_sym_index, | 2089 | &self.base, |
| 2089 | }); | 2090 | src, |
| 2090 | const code = switch (res.res) { | 2091 | sym, |
| 2092 | &required_alignment, | ||
| 2093 | &code_buffer, | ||
| 2094 | .none, | ||
| 2095 | .{ .parent_atom_index = local_sym_index }, | ||
| 2096 | ); | ||
| 2097 | const code = switch (res) { | ||
| 2091 | .ok => code_buffer.items, | 2098 | .ok => code_buffer.items, |
| 2092 | .fail => |em| { | 2099 | .fail => |em| { |
| 2093 | log.err("{s}", .{em.msg}); | 2100 | log.err("{s}", .{em.msg}); |
| ... | @@ -2101,11 +2108,11 @@ fn updateLazySymbolAtom( | ... | @@ -2101,11 +2108,11 @@ fn updateLazySymbolAtom( |
| 2101 | symbol.n_sect = section_index + 1; | 2108 | symbol.n_sect = section_index + 1; |
| 2102 | symbol.n_desc = 0; | 2109 | symbol.n_desc = 0; |
| 2103 | 2110 | ||
| 2104 | const vaddr = try self.allocateAtom(atom_index, code.len, res.alignment); | 2111 | const vaddr = try self.allocateAtom(atom_index, code.len, required_alignment); |
| 2105 | errdefer self.freeAtom(atom_index); | 2112 | errdefer self.freeAtom(atom_index); |
| 2106 | 2113 | ||
| 2107 | log.debug("allocated atom for {s} at 0x{x}", .{ name, vaddr }); | 2114 | 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}); |
| 2109 | 2116 | ||
| 2110 | atom.size = code.len; | 2117 | atom.size = code.len; |
| 2111 | symbol.n_value = vaddr; | 2118 | symbol.n_value = vaddr; |
| ... | @@ -2116,14 +2123,20 @@ fn updateLazySymbolAtom( | ... | @@ -2116,14 +2123,20 @@ fn updateLazySymbolAtom( |
| 2116 | 2123 | ||
| 2117 | pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.Index { | 2124 | pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.Index { |
| 2118 | const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl()); | 2125 | 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(); |
| 2120 | if (!gop.found_existing) gop.value_ptr.* = .{}; | 2127 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 2121 | const atom = switch (sym.kind) { | 2128 | const atom_ptr = switch (sym.kind) { |
| 2122 | .code => &gop.value_ptr.text_atom, | 2129 | .code => &gop.value_ptr.text_atom, |
| 2123 | .const_data => &gop.value_ptr.data_const_atom, | 2130 | .const_data => &gop.value_ptr.data_const_atom, |
| 2124 | }; | 2131 | }; |
| 2125 | if (atom.* == null) atom.* = try self.createAtom(); | 2132 | if (atom_ptr.*) |atom| return atom; |
| 2126 | 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; | ||
| 2127 | } | 2140 | } |
| 2128 | 2141 | ||
| 2129 | fn updateThreadlocalVariable(self: *MachO, module: *Module, decl_index: Module.Decl.Index) !void { | 2142 | fn 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 { | ... | @@ -981,7 +981,6 @@ fn test3_2(f: Test3Foo) !void { |
| 981 | } | 981 | } |
| 982 | 982 | ||
| 983 | test "@tagName" { | 983 | test "@tagName" { |
| 984 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 985 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 984 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 986 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 985 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 987 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 986 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | @@ -997,7 +996,6 @@ fn testEnumTagNameBare(n: anytype) []const u8 { | ... | @@ -997,7 +996,6 @@ fn testEnumTagNameBare(n: anytype) []const u8 { |
| 997 | const BareNumber = enum { One, Two, Three }; | 996 | const BareNumber = enum { One, Two, Three }; |
| 998 | 997 | ||
| 999 | test "@tagName non-exhaustive enum" { | 998 | test "@tagName non-exhaustive enum" { |
| 1000 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 1001 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 999 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 1002 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 1000 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1003 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1001 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | @@ -1008,7 +1006,6 @@ test "@tagName non-exhaustive enum" { | ... | @@ -1008,7 +1006,6 @@ test "@tagName non-exhaustive enum" { |
| 1008 | const NonExhaustive = enum(u8) { A, B, _ }; | 1006 | const NonExhaustive = enum(u8) { A, B, _ }; |
| 1009 | 1007 | ||
| 1010 | test "@tagName is null-terminated" { | 1008 | test "@tagName is null-terminated" { |
| 1011 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 1012 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 1009 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 1013 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 1010 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1014 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1011 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | @@ -1023,7 +1020,6 @@ test "@tagName is null-terminated" { | ... | @@ -1023,7 +1020,6 @@ test "@tagName is null-terminated" { |
| 1023 | } | 1020 | } |
| 1024 | 1021 | ||
| 1025 | test "tag name with assigned enum values" { | 1022 | test "tag name with assigned enum values" { |
| 1026 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 1027 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 1023 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 1028 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 1024 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1029 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1025 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | @@ -1113,7 +1109,6 @@ test "enum literal in array literal" { | ... | @@ -1113,7 +1109,6 @@ test "enum literal in array literal" { |
| 1113 | 1109 | ||
| 1114 | test "tag name functions are unique" { | 1110 | test "tag name functions are unique" { |
| 1115 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 1111 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1116 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 1117 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 1112 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 1118 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; | 1113 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; |
| 1119 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1114 | 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" { | ... | @@ -114,7 +114,6 @@ test "memset with large array element, runtime known" { |
| 114 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 114 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 115 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; | 115 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; |
| 116 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | 116 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 117 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 118 | 117 | ||
| 119 | const A = [128]u64; | 118 | const A = [128]u64; |
| 120 | var buf: [5]A = undefined; | 119 | var buf: [5]A = undefined; |
| ... | @@ -132,7 +131,6 @@ test "memset with large array element, comptime known" { | ... | @@ -132,7 +131,6 @@ test "memset with large array element, comptime known" { |
| 132 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; | 131 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; |
| 133 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; | 132 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; |
| 134 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | 133 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; |
| 135 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; | ||
| 136 | 134 | ||
| 137 | const A = [128]u64; | 135 | const A = [128]u64; |
| 138 | var buf: [5]A = undefined; | 136 | var buf: [5]A = undefined; |
test/behavior/type.zig-2| ... | @@ -258,7 +258,6 @@ test "Type.ErrorSet" { | ... | @@ -258,7 +258,6 @@ test "Type.ErrorSet" { |
| 258 | 258 | ||
| 259 | test "Type.Struct" { | 259 | test "Type.Struct" { |
| 260 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 260 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 261 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 262 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 261 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 263 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 262 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 264 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 263 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| ... | @@ -383,7 +382,6 @@ test "Type.Enum" { | ... | @@ -383,7 +382,6 @@ test "Type.Enum" { |
| 383 | 382 | ||
| 384 | test "Type.Union" { | 383 | test "Type.Union" { |
| 385 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 384 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 386 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 387 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 385 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 388 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 386 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 389 | 387 |
test/behavior/union.zig-1| ... | @@ -1094,7 +1094,6 @@ test "containers with single-field enums" { | ... | @@ -1094,7 +1094,6 @@ test "containers with single-field enums" { |
| 1094 | test "@unionInit on union with tag but no fields" { | 1094 | test "@unionInit on union with tag but no fields" { |
| 1095 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO | 1095 | if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO |
| 1096 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO | 1096 | if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO |
| 1097 | if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO | ||
| 1098 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO | 1097 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO |
| 1099 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO | 1098 | if (builtin.zig_backend == .stage2_sparc64) return error.SkipZigTest; // TODO |
| 1100 | 1099 |