| author | |
| committer | |
| log | 3b1ea390a301dbdc992043d97cf618a94e8801de |
| tree | 7a3889971c17987ed1644945f1399e3c4309ed92 |
| parent | db88b414722e698a392ec65a3ef46730341aea25 |
In theory fixes updating lazy symbols during incremental compilation.4 files changed, 207 insertions(+), 213 deletions(-)
src/arch/x86_64/CodeGen.zig+76-114| ... | ... | @@ -112,7 +112,7 @@ const Owner = union(enum) { |
| 112 | 112 | mod_fn: *const Module.Fn, |
| 113 | 113 | lazy_sym: link.File.LazySymbol, |
| 114 | 114 | |
| 115 | fn getOwnerDecl(owner: Owner) Module.Decl.Index { | |
| 115 | fn getDecl(owner: Owner) Module.Decl.Index { | |
| 116 | 116 | return switch (owner) { |
| 117 | 117 | .mod_fn => |mod_fn| mod_fn.owner_decl, |
| 118 | 118 | .lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(), |
| ... | ... | @@ -1688,35 +1688,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void { |
| 1688 | 1688 | const data_reg = try self.register_manager.allocReg(null, gp); |
| 1689 | 1689 | const data_lock = self.register_manager.lockRegAssumeUnused(data_reg); |
| 1690 | 1690 | defer self.register_manager.unlockReg(data_lock); |
| 1691 | ||
| 1692 | const data_lazy_sym = link.File.LazySymbol{ .kind = .const_data, .ty = enum_ty }; | |
| 1693 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 1694 | const atom_index = elf_file.getOrCreateAtomForLazySymbol(data_lazy_sym) catch |err| | |
| 1695 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 1696 | const atom = elf_file.getAtom(atom_index); | |
| 1697 | _ = try atom.getOrCreateOffsetTableEntry(elf_file); | |
| 1698 | const got_addr = atom.getOffsetTableAddress(elf_file); | |
| 1699 | try self.asmRegisterMemory( | |
| 1700 | .mov, | |
| 1701 | data_reg.to64(), | |
| 1702 | Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) }), | |
| 1703 | ); | |
| 1704 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 1705 | const atom_index = coff_file.getOrCreateAtomForLazySymbol(data_lazy_sym) catch |err| | |
| 1706 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 1707 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; | |
| 1708 | try self.genSetReg(data_reg, Type.usize, .{ .lea_got = sym_index }); | |
| 1709 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 1710 | const atom_index = macho_file.getOrCreateAtomForLazySymbol(data_lazy_sym) catch |err| | |
| 1711 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 1712 | const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; | |
| 1713 | try self.genSetReg(data_reg, Type.usize, .{ .lea_got = sym_index }); | |
| 1714 | } else { | |
| 1715 | return self.fail("TODO implement {s} for {}", .{ | |
| 1716 | @tagName(lazy_sym.kind), | |
| 1717 | lazy_sym.ty.fmt(self.bin_file.options.module.?), | |
| 1718 | }); | |
| 1719 | } | |
| 1691 | try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = enum_ty }); | |
| 1720 | 1692 | |
| 1721 | 1693 | var data_off: i32 = 0; |
| 1722 | 1694 | for ( |
| ... | ... | @@ -6262,7 +6234,7 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void { |
| 6262 | 6234 | // TODO: this might need adjusting like the linkers do. |
| 6263 | 6235 | // Instead of flattening the owner and passing Decl.Index here we may |
| 6264 | 6236 | // want to special case LazySymbol in DWARF linker too. |
| 6265 | try dw.genArgDbgInfo(name, ty, self.owner.getOwnerDecl(), loc); | |
| 6237 | try dw.genArgDbgInfo(name, ty, self.owner.getDecl(), loc); | |
| 6266 | 6238 | }, |
| 6267 | 6239 | .plan9 => {}, |
| 6268 | 6240 | .none => {}, |
| ... | ... | @@ -6306,7 +6278,7 @@ fn genVarDbgInfo( |
| 6306 | 6278 | // TODO: this might need adjusting like the linkers do. |
| 6307 | 6279 | // Instead of flattening the owner and passing Decl.Index here we may |
| 6308 | 6280 | // want to special case LazySymbol in DWARF linker too. |
| 6309 | try dw.genVarDbgInfo(name, ty, self.owner.getOwnerDecl(), is_ptr, loc); | |
| 6281 | try dw.genVarDbgInfo(name, ty, self.owner.getDecl(), is_ptr, loc); | |
| 6310 | 6282 | }, |
| 6311 | 6283 | .plan9 => {}, |
| 6312 | 6284 | .none => {}, |
| ... | ... | @@ -6630,38 +6602,13 @@ fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void { |
| 6630 | 6602 | } |
| 6631 | 6603 | |
| 6632 | 6604 | fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void { |
| 6605 | const mod = self.bin_file.options.module.?; | |
| 6633 | 6606 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 6634 | 6607 | |
| 6635 | 6608 | const addr_reg = try self.register_manager.allocReg(null, gp); |
| 6636 | 6609 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 6637 | 6610 | defer self.register_manager.unlockReg(addr_lock); |
| 6638 | ||
| 6639 | const mod = self.bin_file.options.module.?; | |
| 6640 | const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, mod); | |
| 6641 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 6642 | const atom_index = elf_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| | |
| 6643 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 6644 | const atom = elf_file.getAtom(atom_index); | |
| 6645 | _ = try atom.getOrCreateOffsetTableEntry(elf_file); | |
| 6646 | const got_addr = atom.getOffsetTableAddress(elf_file); | |
| 6647 | try self.asmRegisterMemory( | |
| 6648 | .mov, | |
| 6649 | addr_reg.to64(), | |
| 6650 | Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) }), | |
| 6651 | ); | |
| 6652 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 6653 | const atom_index = coff_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| | |
| 6654 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 6655 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; | |
| 6656 | try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index }); | |
| 6657 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 6658 | const atom_index = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| | |
| 6659 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 6660 | const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; | |
| 6661 | try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index }); | |
| 6662 | } else { | |
| 6663 | return self.fail("TODO implement airCmpLtErrorsLen for x86_64 {s}", .{@tagName(self.bin_file.tag)}); | |
| 6664 | } | |
| 6611 | try self.genLazySymbolRef(.lea, addr_reg, link.File.LazySymbol.initDecl(.const_data, null, mod)); | |
| 6665 | 6612 | |
| 6666 | 6613 | try self.spillEflagsIfOccupied(); |
| 6667 | 6614 | self.eflags_inst = inst; |
| ... | ... | @@ -7999,6 +7946,67 @@ fn genInlineMemset(self: *Self, dst_ptr: MCValue, value: MCValue, len: MCValue) |
| 7999 | 7946 | }); |
| 8000 | 7947 | } |
| 8001 | 7948 | |
| 7949 | fn genLazySymbolRef( | |
| 7950 | self: *Self, | |
| 7951 | comptime tag: Mir.Inst.Tag, | |
| 7952 | reg: Register, | |
| 7953 | lazy_sym: link.File.LazySymbol, | |
| 7954 | ) InnerError!void { | |
| 7955 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 7956 | const atom_index = elf_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| | |
| 7957 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 7958 | const atom = elf_file.getAtom(atom_index); | |
| 7959 | _ = try atom.getOrCreateOffsetTableEntry(elf_file); | |
| 7960 | const got_addr = atom.getOffsetTableAddress(elf_file); | |
| 7961 | const got_mem = | |
| 7962 | Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) }); | |
| 7963 | switch (tag) { | |
| 7964 | .lea, .mov => try self.asmRegisterMemory(.mov, reg.to64(), got_mem), | |
| 7965 | .call => try self.asmMemory(.call, got_mem), | |
| 7966 | else => unreachable, | |
| 7967 | } | |
| 7968 | switch (tag) { | |
| 7969 | .lea, .call => {}, | |
| 7970 | .mov => try self.asmRegisterMemory( | |
| 7971 | tag, | |
| 7972 | reg.to64(), | |
| 7973 | Memory.sib(.qword, .{ .base = .{ .reg = reg.to64() } }), | |
| 7974 | ), | |
| 7975 | else => unreachable, | |
| 7976 | } | |
| 7977 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 7978 | const atom_index = coff_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| | |
| 7979 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 7980 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; | |
| 7981 | switch (tag) { | |
| 7982 | .lea, .call => try self.genSetReg(reg, Type.usize, .{ .lea_got = sym_index }), | |
| 7983 | .mov => try self.genSetReg(reg, Type.usize, .{ .load_got = sym_index }), | |
| 7984 | else => unreachable, | |
| 7985 | } | |
| 7986 | switch (tag) { | |
| 7987 | .lea, .mov => {}, | |
| 7988 | .call => try self.asmRegister(.call, reg), | |
| 7989 | else => unreachable, | |
| 7990 | } | |
| 7991 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 7992 | const atom_index = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| | |
| 7993 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 7994 | const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; | |
| 7995 | switch (tag) { | |
| 7996 | .lea, .call => try self.genSetReg(reg, Type.usize, .{ .lea_got = sym_index }), | |
| 7997 | .mov => try self.genSetReg(reg, Type.usize, .{ .load_got = sym_index }), | |
| 7998 | else => unreachable, | |
| 7999 | } | |
| 8000 | switch (tag) { | |
| 8001 | .lea, .mov => {}, | |
| 8002 | .call => try self.asmRegister(.call, reg), | |
| 8003 | else => unreachable, | |
| 8004 | } | |
| 8005 | } else { | |
| 8006 | return self.fail("TODO implement genLazySymbol for x86_64 {s}", .{@tagName(self.bin_file.tag)}); | |
| 8007 | } | |
| 8008 | } | |
| 8009 | ||
| 8002 | 8010 | fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void { |
| 8003 | 8011 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 8004 | 8012 | const result = result: { |
| ... | ... | @@ -8701,6 +8709,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void { |
| 8701 | 8709 | } |
| 8702 | 8710 | |
| 8703 | 8711 | fn airTagName(self: *Self, inst: Air.Inst.Index) !void { |
| 8712 | const mod = self.bin_file.options.module.?; | |
| 8704 | 8713 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 8705 | 8714 | const inst_ty = self.air.typeOfIndex(inst); |
| 8706 | 8715 | const enum_ty = self.air.typeOf(un_op); |
| ... | ... | @@ -8731,38 +8740,17 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void { |
| 8731 | 8740 | const operand = try self.resolveInst(un_op); |
| 8732 | 8741 | try self.genSetReg(param_regs[1], enum_ty, operand); |
| 8733 | 8742 | |
| 8734 | const mod = self.bin_file.options.module.?; | |
| 8735 | const lazy_sym = link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(), mod); | |
| 8736 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 8737 | const atom_index = elf_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| | |
| 8738 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 8739 | const atom = elf_file.getAtom(atom_index); | |
| 8740 | _ = try atom.getOrCreateOffsetTableEntry(elf_file); | |
| 8741 | const got_addr = atom.getOffsetTableAddress(elf_file); | |
| 8742 | try self.asmMemory( | |
| 8743 | .call, | |
| 8744 | Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) }), | |
| 8745 | ); | |
| 8746 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 8747 | const atom_index = coff_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| | |
| 8748 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 8749 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; | |
| 8750 | try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index }); | |
| 8751 | try self.asmRegister(.call, .rax); | |
| 8752 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 8753 | const atom_index = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| | |
| 8754 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 8755 | const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; | |
| 8756 | try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index }); | |
| 8757 | try self.asmRegister(.call, .rax); | |
| 8758 | } else { | |
| 8759 | return self.fail("TODO implement airTagName for x86_64 {s}", .{@tagName(self.bin_file.tag)}); | |
| 8760 | } | |
| 8743 | try self.genLazySymbolRef( | |
| 8744 | .call, | |
| 8745 | .rax, | |
| 8746 | link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(), mod), | |
| 8747 | ); | |
| 8761 | 8748 | |
| 8762 | 8749 | return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none }); |
| 8763 | 8750 | } |
| 8764 | 8751 | |
| 8765 | 8752 | fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { |
| 8753 | const mod = self.bin_file.options.module.?; | |
| 8766 | 8754 | const un_op = self.air.instructions.items(.data)[inst].un_op; |
| 8767 | 8755 | |
| 8768 | 8756 | const err_ty = self.air.typeOf(un_op); |
| ... | ... | @@ -8774,33 +8762,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void { |
| 8774 | 8762 | const addr_reg = try self.register_manager.allocReg(null, gp); |
| 8775 | 8763 | const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg); |
| 8776 | 8764 | defer self.register_manager.unlockReg(addr_lock); |
| 8777 | ||
| 8778 | const mod = self.bin_file.options.module.?; | |
| 8779 | const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, mod); | |
| 8780 | if (self.bin_file.cast(link.File.Elf)) |elf_file| { | |
| 8781 | const atom_index = elf_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| | |
| 8782 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 8783 | const atom = elf_file.getAtom(atom_index); | |
| 8784 | _ = try atom.getOrCreateOffsetTableEntry(elf_file); | |
| 8785 | const got_addr = atom.getOffsetTableAddress(elf_file); | |
| 8786 | try self.asmRegisterMemory( | |
| 8787 | .mov, | |
| 8788 | addr_reg.to64(), | |
| 8789 | Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) }), | |
| 8790 | ); | |
| 8791 | } else if (self.bin_file.cast(link.File.Coff)) |coff_file| { | |
| 8792 | const atom_index = coff_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| | |
| 8793 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 8794 | const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?; | |
| 8795 | try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index }); | |
| 8796 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | |
| 8797 | const atom_index = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err| | |
| 8798 | return self.fail("{s} creating lazy symbol", .{@errorName(err)}); | |
| 8799 | const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; | |
| 8800 | try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index }); | |
| 8801 | } else { | |
| 8802 | return self.fail("TODO implement airErrorName for x86_64 {s}", .{@tagName(self.bin_file.tag)}); | |
| 8803 | } | |
| 8765 | try self.genLazySymbolRef(.lea, addr_reg, link.File.LazySymbol.initDecl(.const_data, null, mod)); | |
| 8804 | 8766 | |
| 8805 | 8767 | const start_reg = try self.register_manager.allocReg(null, gp); |
| 8806 | 8768 | const start_lock = self.register_manager.lockRegAssumeUnused(start_reg); |
| ... | ... | @@ -9117,7 +9079,7 @@ fn limitImmediateType(self: *Self, operand: Air.Inst.Ref, comptime T: type) !MCV |
| 9117 | 9079 | } |
| 9118 | 9080 | |
| 9119 | 9081 | fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue { |
| 9120 | return switch (try codegen.genTypedValue(self.bin_file, self.src_loc, arg_tv, self.owner.getOwnerDecl())) { | |
| 9082 | return switch (try codegen.genTypedValue(self.bin_file, self.src_loc, arg_tv, self.owner.getDecl())) { | |
| 9121 | 9083 | .mcv => |mcv| switch (mcv) { |
| 9122 | 9084 | .none => .none, |
| 9123 | 9085 | .undef => .undef, |
src/link/Coff.zig+44-33| ... | ... | @@ -143,8 +143,11 @@ const Section = struct { |
| 143 | 143 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(Module.Decl.OptionalIndex, LazySymbolMetadata); |
| 144 | 144 | |
| 145 | 145 | const LazySymbolMetadata = struct { |
| 146 | text_atom: ?Atom.Index = null, | |
| 147 | rdata_atom: ?Atom.Index = null, | |
| 146 | const State = enum { unused, pending_flush, flushed }; | |
| 147 | text_atom: Atom.Index = undefined, | |
| 148 | rdata_atom: Atom.Index = undefined, | |
| 149 | text_state: State = .unused, | |
| 150 | rdata_state: State = .unused, | |
| 148 | 151 | }; |
| 149 | 152 | |
| 150 | 153 | const DeclMetadata = struct { |
| ... | ... | @@ -1150,8 +1153,6 @@ pub fn updateDecl( |
| 1150 | 1153 | const tracy = trace(@src()); |
| 1151 | 1154 | defer tracy.end(); |
| 1152 | 1155 | |
| 1153 | try self.updateLazySymbol(decl_index); | |
| 1154 | ||
| 1155 | 1156 | const decl = module.declPtr(decl_index); |
| 1156 | 1157 | |
| 1157 | 1158 | if (decl.val.tag() == .extern_fn) { |
| ... | ... | @@ -1194,21 +1195,6 @@ pub fn updateDecl( |
| 1194 | 1195 | return self.updateDeclExports(module, decl_index, module.getDeclExports(decl_index)); |
| 1195 | 1196 | } |
| 1196 | 1197 | |
| 1197 | fn updateLazySymbol(self: *Coff, decl: ?Module.Decl.Index) !void { | |
| 1198 | const metadata = self.lazy_syms.get(Module.Decl.OptionalIndex.init(decl)) orelse return; | |
| 1199 | const mod = self.base.options.module.?; | |
| 1200 | if (metadata.text_atom) |atom| try self.updateLazySymbolAtom( | |
| 1201 | link.File.LazySymbol.initDecl(.code, decl, mod), | |
| 1202 | atom, | |
| 1203 | self.text_section_index.?, | |
| 1204 | ); | |
| 1205 | if (metadata.rdata_atom) |atom| try self.updateLazySymbolAtom( | |
| 1206 | link.File.LazySymbol.initDecl(.const_data, decl, mod), | |
| 1207 | atom, | |
| 1208 | self.rdata_section_index.?, | |
| 1209 | ); | |
| 1210 | } | |
| 1211 | ||
| 1212 | 1198 | fn updateLazySymbolAtom( |
| 1213 | 1199 | self: *Coff, |
| 1214 | 1200 | sym: link.File.LazySymbol, |
| ... | ... | @@ -1279,14 +1265,19 @@ pub fn getOrCreateAtomForLazySymbol(self: *Coff, sym: link.File.LazySymbol) !Ato |
| 1279 | 1265 | const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl()); |
| 1280 | 1266 | errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); |
| 1281 | 1267 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 1282 | const atom_ptr = switch (sym.kind) { | |
| 1283 | .code => &gop.value_ptr.text_atom, | |
| 1284 | .const_data => &gop.value_ptr.rdata_atom, | |
| 1268 | const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) { | |
| 1269 | .code => .{ .atom = &gop.value_ptr.text_atom, .state = &gop.value_ptr.text_state }, | |
| 1270 | .const_data => .{ .atom = &gop.value_ptr.rdata_atom, .state = &gop.value_ptr.rdata_state }, | |
| 1285 | 1271 | }; |
| 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) { | |
| 1272 | switch (metadata.state.*) { | |
| 1273 | .unused => metadata.atom.* = try self.createAtom(), | |
| 1274 | .pending_flush => return metadata.atom.*, | |
| 1275 | .flushed => {}, | |
| 1276 | } | |
| 1277 | metadata.state.* = .pending_flush; | |
| 1278 | const atom = metadata.atom.*; | |
| 1279 | // anyerror needs to be deferred until flushModule | |
| 1280 | if (sym.getDecl() != .none) try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) { | |
| 1290 | 1281 | .code => self.text_section_index.?, |
| 1291 | 1282 | .const_data => self.rdata_section_index.?, |
| 1292 | 1283 | }); |
| ... | ... | @@ -1617,15 +1608,35 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod |
| 1617 | 1608 | sub_prog_node.activate(); |
| 1618 | 1609 | defer sub_prog_node.end(); |
| 1619 | 1610 | |
| 1620 | // Most lazy symbols can be updated when the corresponding decl is, | |
| 1621 | // so we only have to worry about the one without an associated decl. | |
| 1622 | self.updateLazySymbol(null) catch |err| switch (err) { | |
| 1623 | error.CodegenFail => return error.FlushFailure, | |
| 1624 | else => |e| return e, | |
| 1625 | }; | |
| 1626 | ||
| 1627 | 1611 | const gpa = self.base.allocator; |
| 1628 | 1612 | |
| 1613 | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; | |
| 1614 | ||
| 1615 | if (self.lazy_syms.getPtr(.none)) |metadata| { | |
| 1616 | // Most lazy symbols can be updated on first use, but | |
| 1617 | // anyerror needs to wait for everything to be flushed. | |
| 1618 | if (metadata.text_state != .unused) self.updateLazySymbolAtom( | |
| 1619 | link.File.LazySymbol.initDecl(.code, null, module), | |
| 1620 | metadata.text_atom, | |
| 1621 | self.text_section_index.?, | |
| 1622 | ) catch |err| return switch (err) { | |
| 1623 | error.CodegenFail => error.FlushFailure, | |
| 1624 | else => |e| e, | |
| 1625 | }; | |
| 1626 | if (metadata.rdata_state != .unused) self.updateLazySymbolAtom( | |
| 1627 | link.File.LazySymbol.initDecl(.const_data, null, module), | |
| 1628 | metadata.rdata_atom, | |
| 1629 | self.rdata_section_index.?, | |
| 1630 | ) catch |err| return switch (err) { | |
| 1631 | error.CodegenFail => error.FlushFailure, | |
| 1632 | else => |e| e, | |
| 1633 | }; | |
| 1634 | } | |
| 1635 | for (self.lazy_syms.values()) |*metadata| { | |
| 1636 | if (metadata.text_state != .unused) metadata.text_state = .flushed; | |
| 1637 | if (metadata.rdata_state != .unused) metadata.rdata_state = .flushed; | |
| 1638 | } | |
| 1639 | ||
| 1629 | 1640 | while (self.unresolved.popOrNull()) |entry| { |
| 1630 | 1641 | assert(entry.value); // We only expect imports generated by the incremental linker for now. |
| 1631 | 1642 | const global = self.globals.items[entry.key]; |
src/link/Elf.zig+42-33| ... | ... | @@ -65,8 +65,11 @@ const Section = struct { |
| 65 | 65 | }; |
| 66 | 66 | |
| 67 | 67 | const LazySymbolMetadata = struct { |
| 68 | text_atom: ?Atom.Index = null, | |
| 69 | rodata_atom: ?Atom.Index = null, | |
| 68 | const State = enum { unused, pending_flush, flushed }; | |
| 69 | text_atom: Atom.Index = undefined, | |
| 70 | rodata_atom: Atom.Index = undefined, | |
| 71 | text_state: State = .unused, | |
| 72 | rodata_state: State = .unused, | |
| 70 | 73 | }; |
| 71 | 74 | |
| 72 | 75 | const DeclMetadata = struct { |
| ... | ... | @@ -1032,17 +1035,35 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node |
| 1032 | 1035 | sub_prog_node.activate(); |
| 1033 | 1036 | defer sub_prog_node.end(); |
| 1034 | 1037 | |
| 1035 | // Most lazy symbols can be updated when the corresponding decl is, | |
| 1036 | // so we only have to worry about the one without an associated decl. | |
| 1037 | self.updateLazySymbol(null) catch |err| switch (err) { | |
| 1038 | error.CodegenFail => return error.FlushFailure, | |
| 1039 | else => |e| return e, | |
| 1040 | }; | |
| 1041 | ||
| 1042 | 1038 | // TODO This linker code currently assumes there is only 1 compilation unit and it |
| 1043 | 1039 | // corresponds to the Zig source code. |
| 1044 | 1040 | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 1045 | 1041 | |
| 1042 | if (self.lazy_syms.getPtr(.none)) |metadata| { | |
| 1043 | // Most lazy symbols can be updated on first use, but | |
| 1044 | // anyerror needs to wait for everything to be flushed. | |
| 1045 | if (metadata.text_state != .unused) self.updateLazySymbolAtom( | |
| 1046 | File.LazySymbol.initDecl(.code, null, module), | |
| 1047 | metadata.text_atom, | |
| 1048 | self.text_section_index.?, | |
| 1049 | ) catch |err| return switch (err) { | |
| 1050 | error.CodegenFail => error.FlushFailure, | |
| 1051 | else => |e| e, | |
| 1052 | }; | |
| 1053 | if (metadata.rodata_state != .unused) self.updateLazySymbolAtom( | |
| 1054 | File.LazySymbol.initDecl(.const_data, null, module), | |
| 1055 | metadata.rodata_atom, | |
| 1056 | self.rodata_section_index.?, | |
| 1057 | ) catch |err| return switch (err) { | |
| 1058 | error.CodegenFail => error.FlushFailure, | |
| 1059 | else => |e| e, | |
| 1060 | }; | |
| 1061 | } | |
| 1062 | for (self.lazy_syms.values()) |*metadata| { | |
| 1063 | if (metadata.text_state != .unused) metadata.text_state = .flushed; | |
| 1064 | if (metadata.rodata_state != .unused) metadata.rodata_state = .flushed; | |
| 1065 | } | |
| 1066 | ||
| 1046 | 1067 | const target_endian = self.base.options.target.cpu.arch.endian(); |
| 1047 | 1068 | const foreign_endian = target_endian != builtin.cpu.arch.endian(); |
| 1048 | 1069 | |
| ... | ... | @@ -2378,14 +2399,19 @@ pub fn getOrCreateAtomForLazySymbol(self: *Elf, sym: File.LazySymbol) !Atom.Inde |
| 2378 | 2399 | const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl()); |
| 2379 | 2400 | errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); |
| 2380 | 2401 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 2381 | const atom_ptr = switch (sym.kind) { | |
| 2382 | .code => &gop.value_ptr.text_atom, | |
| 2383 | .const_data => &gop.value_ptr.rodata_atom, | |
| 2402 | const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) { | |
| 2403 | .code => .{ .atom = &gop.value_ptr.text_atom, .state = &gop.value_ptr.text_state }, | |
| 2404 | .const_data => .{ .atom = &gop.value_ptr.rodata_atom, .state = &gop.value_ptr.rodata_state }, | |
| 2384 | 2405 | }; |
| 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) { | |
| 2406 | switch (metadata.state.*) { | |
| 2407 | .unused => metadata.atom.* = try self.createAtom(), | |
| 2408 | .pending_flush => return metadata.atom.*, | |
| 2409 | .flushed => {}, | |
| 2410 | } | |
| 2411 | metadata.state.* = .pending_flush; | |
| 2412 | const atom = metadata.atom.*; | |
| 2413 | // anyerror needs to be deferred until flushModule | |
| 2414 | if (sym.getDecl() != .none) try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) { | |
| 2389 | 2415 | .code => self.text_section_index.?, |
| 2390 | 2416 | .const_data => self.rodata_section_index.?, |
| 2391 | 2417 | }); |
| ... | ... | @@ -2598,8 +2624,6 @@ pub fn updateDecl( |
| 2598 | 2624 | const tracy = trace(@src()); |
| 2599 | 2625 | defer tracy.end(); |
| 2600 | 2626 | |
| 2601 | try self.updateLazySymbol(decl_index); | |
| 2602 | ||
| 2603 | 2627 | const decl = module.declPtr(decl_index); |
| 2604 | 2628 | |
| 2605 | 2629 | if (decl.val.tag() == .extern_fn) { |
| ... | ... | @@ -2666,21 +2690,6 @@ pub fn updateDecl( |
| 2666 | 2690 | return self.updateDeclExports(module, decl_index, module.getDeclExports(decl_index)); |
| 2667 | 2691 | } |
| 2668 | 2692 | |
| 2669 | fn updateLazySymbol(self: *Elf, decl: ?Module.Decl.Index) !void { | |
| 2670 | const metadata = self.lazy_syms.get(Module.Decl.OptionalIndex.init(decl)) orelse return; | |
| 2671 | const mod = self.base.options.module.?; | |
| 2672 | if (metadata.text_atom) |atom| try self.updateLazySymbolAtom( | |
| 2673 | File.LazySymbol.initDecl(.code, decl, mod), | |
| 2674 | atom, | |
| 2675 | self.text_section_index.?, | |
| 2676 | ); | |
| 2677 | if (metadata.rodata_atom) |atom| try self.updateLazySymbolAtom( | |
| 2678 | File.LazySymbol.initDecl(.const_data, decl, mod), | |
| 2679 | atom, | |
| 2680 | self.rodata_section_index.?, | |
| 2681 | ); | |
| 2682 | } | |
| 2683 | ||
| 2684 | 2693 | fn updateLazySymbolAtom( |
| 2685 | 2694 | self: *Elf, |
| 2686 | 2695 | sym: File.LazySymbol, |
src/link/MachO.zig+45-33| ... | ... | @@ -236,8 +236,11 @@ const is_hot_update_compatible = switch (builtin.target.os.tag) { |
| 236 | 236 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(Module.Decl.OptionalIndex, LazySymbolMetadata); |
| 237 | 237 | |
| 238 | 238 | const LazySymbolMetadata = struct { |
| 239 | text_atom: ?Atom.Index = null, | |
| 240 | data_const_atom: ?Atom.Index = null, | |
| 239 | const State = enum { unused, pending_flush, flushed }; | |
| 240 | text_atom: Atom.Index = undefined, | |
| 241 | data_const_atom: Atom.Index = undefined, | |
| 242 | text_state: State = .unused, | |
| 243 | data_const_state: State = .unused, | |
| 241 | 244 | }; |
| 242 | 245 | |
| 243 | 246 | const TlvSymbolTable = std.AutoArrayHashMapUnmanaged(SymbolWithLoc, Atom.Index); |
| ... | ... | @@ -493,15 +496,33 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 493 | 496 | sub_prog_node.activate(); |
| 494 | 497 | defer sub_prog_node.end(); |
| 495 | 498 | |
| 496 | // Most lazy symbols can be updated when the corresponding decl is, | |
| 497 | // so we only have to worry about the one without an associated decl. | |
| 498 | self.updateLazySymbol(null) catch |err| switch (err) { | |
| 499 | error.CodegenFail => return error.FlushFailure, | |
| 500 | else => |e| return e, | |
| 501 | }; | |
| 502 | ||
| 503 | 499 | const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 504 | 500 | |
| 501 | if (self.lazy_syms.getPtr(.none)) |metadata| { | |
| 502 | // Most lazy symbols can be updated on first use, but | |
| 503 | // anyerror needs to wait for everything to be flushed. | |
| 504 | if (metadata.text_state != .unused) self.updateLazySymbolAtom( | |
| 505 | File.LazySymbol.initDecl(.code, null, module), | |
| 506 | metadata.text_atom, | |
| 507 | self.text_section_index.?, | |
| 508 | ) catch |err| return switch (err) { | |
| 509 | error.CodegenFail => error.FlushFailure, | |
| 510 | else => |e| e, | |
| 511 | }; | |
| 512 | if (metadata.data_const_state != .unused) self.updateLazySymbolAtom( | |
| 513 | File.LazySymbol.initDecl(.const_data, null, module), | |
| 514 | metadata.data_const_atom, | |
| 515 | self.data_const_section_index.?, | |
| 516 | ) catch |err| return switch (err) { | |
| 517 | error.CodegenFail => error.FlushFailure, | |
| 518 | else => |e| e, | |
| 519 | }; | |
| 520 | } | |
| 521 | for (self.lazy_syms.values()) |*metadata| { | |
| 522 | if (metadata.text_state != .unused) metadata.text_state = .flushed; | |
| 523 | if (metadata.data_const_state != .unused) metadata.data_const_state = .flushed; | |
| 524 | } | |
| 525 | ||
| 505 | 526 | if (self.d_sym) |*d_sym| { |
| 506 | 527 | try d_sym.dwarf.flushModule(module); |
| 507 | 528 | } |
| ... | ... | @@ -1960,8 +1981,6 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index) |
| 1960 | 1981 | const tracy = trace(@src()); |
| 1961 | 1982 | defer tracy.end(); |
| 1962 | 1983 | |
| 1963 | try self.updateLazySymbol(decl_index); | |
| 1964 | ||
| 1965 | 1984 | const decl = module.declPtr(decl_index); |
| 1966 | 1985 | |
| 1967 | 1986 | if (decl.val.tag() == .extern_fn) { |
| ... | ... | @@ -2036,21 +2055,6 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index) |
| 2036 | 2055 | try self.updateDeclExports(module, decl_index, module.getDeclExports(decl_index)); |
| 2037 | 2056 | } |
| 2038 | 2057 | |
| 2039 | fn updateLazySymbol(self: *MachO, decl: ?Module.Decl.Index) !void { | |
| 2040 | const metadata = self.lazy_syms.get(Module.Decl.OptionalIndex.init(decl)) orelse return; | |
| 2041 | const mod = self.base.options.module.?; | |
| 2042 | if (metadata.text_atom) |atom| try self.updateLazySymbolAtom( | |
| 2043 | File.LazySymbol.initDecl(.code, decl, mod), | |
| 2044 | atom, | |
| 2045 | self.text_section_index.?, | |
| 2046 | ); | |
| 2047 | if (metadata.data_const_atom) |atom| try self.updateLazySymbolAtom( | |
| 2048 | File.LazySymbol.initDecl(.const_data, decl, mod), | |
| 2049 | atom, | |
| 2050 | self.data_const_section_index.?, | |
| 2051 | ); | |
| 2052 | } | |
| 2053 | ||
| 2054 | 2058 | fn updateLazySymbolAtom( |
| 2055 | 2059 | self: *MachO, |
| 2056 | 2060 | sym: File.LazySymbol, |
| ... | ... | @@ -2125,14 +2129,22 @@ pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.In |
| 2125 | 2129 | const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl()); |
| 2126 | 2130 | errdefer _ = if (!gop.found_existing) self.lazy_syms.pop(); |
| 2127 | 2131 | if (!gop.found_existing) gop.value_ptr.* = .{}; |
| 2128 | const atom_ptr = switch (sym.kind) { | |
| 2129 | .code => &gop.value_ptr.text_atom, | |
| 2130 | .const_data => &gop.value_ptr.data_const_atom, | |
| 2132 | const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) { | |
| 2133 | .code => .{ .atom = &gop.value_ptr.text_atom, .state = &gop.value_ptr.text_state }, | |
| 2134 | .const_data => .{ | |
| 2135 | .atom = &gop.value_ptr.data_const_atom, | |
| 2136 | .state = &gop.value_ptr.data_const_state, | |
| 2137 | }, | |
| 2131 | 2138 | }; |
| 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) { | |
| 2139 | switch (metadata.state.*) { | |
| 2140 | .unused => metadata.atom.* = try self.createAtom(), | |
| 2141 | .pending_flush => return metadata.atom.*, | |
| 2142 | .flushed => {}, | |
| 2143 | } | |
| 2144 | metadata.state.* = .pending_flush; | |
| 2145 | const atom = metadata.atom.*; | |
| 2146 | // anyerror needs to be deferred until flushModule | |
| 2147 | if (sym.getDecl() != .none) try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) { | |
| 2136 | 2148 | .code => self.text_section_index.?, |
| 2137 | 2149 | .const_data => self.data_const_section_index.?, |
| 2138 | 2150 | }); |