mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-09 15:19:07 +00:00
x86_64: cleanup lazy symbols
In theory fixes updating lazy symbols during incremental compilation.
This commit is contained in:
parent
db88b41472
commit
3b1ea390a3
4 changed files with 207 additions and 213 deletions
|
|
@ -112,7 +112,7 @@ const Owner = union(enum) {
|
|||
mod_fn: *const Module.Fn,
|
||||
lazy_sym: link.File.LazySymbol,
|
||||
|
||||
fn getOwnerDecl(owner: Owner) Module.Decl.Index {
|
||||
fn getDecl(owner: Owner) Module.Decl.Index {
|
||||
return switch (owner) {
|
||||
.mod_fn => |mod_fn| mod_fn.owner_decl,
|
||||
.lazy_sym => |lazy_sym| lazy_sym.ty.getOwnerDecl(),
|
||||
|
|
@ -1688,35 +1688,7 @@ fn genLazy(self: *Self, lazy_sym: link.File.LazySymbol) InnerError!void {
|
|||
const data_reg = try self.register_manager.allocReg(null, gp);
|
||||
const data_lock = self.register_manager.lockRegAssumeUnused(data_reg);
|
||||
defer self.register_manager.unlockReg(data_lock);
|
||||
|
||||
const data_lazy_sym = link.File.LazySymbol{ .kind = .const_data, .ty = enum_ty };
|
||||
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||
const atom_index = elf_file.getOrCreateAtomForLazySymbol(data_lazy_sym) catch |err|
|
||||
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
|
||||
const atom = elf_file.getAtom(atom_index);
|
||||
_ = try atom.getOrCreateOffsetTableEntry(elf_file);
|
||||
const got_addr = atom.getOffsetTableAddress(elf_file);
|
||||
try self.asmRegisterMemory(
|
||||
.mov,
|
||||
data_reg.to64(),
|
||||
Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) }),
|
||||
);
|
||||
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
|
||||
const atom_index = coff_file.getOrCreateAtomForLazySymbol(data_lazy_sym) catch |err|
|
||||
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
|
||||
const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
|
||||
try self.genSetReg(data_reg, Type.usize, .{ .lea_got = sym_index });
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
const atom_index = macho_file.getOrCreateAtomForLazySymbol(data_lazy_sym) catch |err|
|
||||
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
|
||||
const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
|
||||
try self.genSetReg(data_reg, Type.usize, .{ .lea_got = sym_index });
|
||||
} else {
|
||||
return self.fail("TODO implement {s} for {}", .{
|
||||
@tagName(lazy_sym.kind),
|
||||
lazy_sym.ty.fmt(self.bin_file.options.module.?),
|
||||
});
|
||||
}
|
||||
try self.genLazySymbolRef(.lea, data_reg, .{ .kind = .const_data, .ty = enum_ty });
|
||||
|
||||
var data_off: i32 = 0;
|
||||
for (
|
||||
|
|
@ -6262,7 +6234,7 @@ fn genArgDbgInfo(self: Self, ty: Type, name: [:0]const u8, mcv: MCValue) !void {
|
|||
// TODO: this might need adjusting like the linkers do.
|
||||
// Instead of flattening the owner and passing Decl.Index here we may
|
||||
// want to special case LazySymbol in DWARF linker too.
|
||||
try dw.genArgDbgInfo(name, ty, self.owner.getOwnerDecl(), loc);
|
||||
try dw.genArgDbgInfo(name, ty, self.owner.getDecl(), loc);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
|
|
@ -6306,7 +6278,7 @@ fn genVarDbgInfo(
|
|||
// TODO: this might need adjusting like the linkers do.
|
||||
// Instead of flattening the owner and passing Decl.Index here we may
|
||||
// want to special case LazySymbol in DWARF linker too.
|
||||
try dw.genVarDbgInfo(name, ty, self.owner.getOwnerDecl(), is_ptr, loc);
|
||||
try dw.genVarDbgInfo(name, ty, self.owner.getDecl(), is_ptr, loc);
|
||||
},
|
||||
.plan9 => {},
|
||||
.none => {},
|
||||
|
|
@ -6630,38 +6602,13 @@ fn airCmpVector(self: *Self, inst: Air.Inst.Index) !void {
|
|||
}
|
||||
|
||||
fn airCmpLtErrorsLen(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const un_op = self.air.instructions.items(.data)[inst].un_op;
|
||||
|
||||
const addr_reg = try self.register_manager.allocReg(null, gp);
|
||||
const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
|
||||
defer self.register_manager.unlockReg(addr_lock);
|
||||
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, mod);
|
||||
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||
const atom_index = elf_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
|
||||
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
|
||||
const atom = elf_file.getAtom(atom_index);
|
||||
_ = try atom.getOrCreateOffsetTableEntry(elf_file);
|
||||
const got_addr = atom.getOffsetTableAddress(elf_file);
|
||||
try self.asmRegisterMemory(
|
||||
.mov,
|
||||
addr_reg.to64(),
|
||||
Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) }),
|
||||
);
|
||||
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
|
||||
const atom_index = coff_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
|
||||
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
|
||||
const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
|
||||
try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index });
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
const atom_index = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
|
||||
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
|
||||
const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
|
||||
try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index });
|
||||
} else {
|
||||
return self.fail("TODO implement airCmpLtErrorsLen for x86_64 {s}", .{@tagName(self.bin_file.tag)});
|
||||
}
|
||||
try self.genLazySymbolRef(.lea, addr_reg, link.File.LazySymbol.initDecl(.const_data, null, mod));
|
||||
|
||||
try self.spillEflagsIfOccupied();
|
||||
self.eflags_inst = inst;
|
||||
|
|
@ -7999,6 +7946,67 @@ fn genInlineMemset(self: *Self, dst_ptr: MCValue, value: MCValue, len: MCValue)
|
|||
});
|
||||
}
|
||||
|
||||
fn genLazySymbolRef(
|
||||
self: *Self,
|
||||
comptime tag: Mir.Inst.Tag,
|
||||
reg: Register,
|
||||
lazy_sym: link.File.LazySymbol,
|
||||
) InnerError!void {
|
||||
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||
const atom_index = elf_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
|
||||
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
|
||||
const atom = elf_file.getAtom(atom_index);
|
||||
_ = try atom.getOrCreateOffsetTableEntry(elf_file);
|
||||
const got_addr = atom.getOffsetTableAddress(elf_file);
|
||||
const got_mem =
|
||||
Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) });
|
||||
switch (tag) {
|
||||
.lea, .mov => try self.asmRegisterMemory(.mov, reg.to64(), got_mem),
|
||||
.call => try self.asmMemory(.call, got_mem),
|
||||
else => unreachable,
|
||||
}
|
||||
switch (tag) {
|
||||
.lea, .call => {},
|
||||
.mov => try self.asmRegisterMemory(
|
||||
tag,
|
||||
reg.to64(),
|
||||
Memory.sib(.qword, .{ .base = .{ .reg = reg.to64() } }),
|
||||
),
|
||||
else => unreachable,
|
||||
}
|
||||
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
|
||||
const atom_index = coff_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
|
||||
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
|
||||
const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
|
||||
switch (tag) {
|
||||
.lea, .call => try self.genSetReg(reg, Type.usize, .{ .lea_got = sym_index }),
|
||||
.mov => try self.genSetReg(reg, Type.usize, .{ .load_got = sym_index }),
|
||||
else => unreachable,
|
||||
}
|
||||
switch (tag) {
|
||||
.lea, .mov => {},
|
||||
.call => try self.asmRegister(.call, reg),
|
||||
else => unreachable,
|
||||
}
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
const atom_index = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
|
||||
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
|
||||
const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
|
||||
switch (tag) {
|
||||
.lea, .call => try self.genSetReg(reg, Type.usize, .{ .lea_got = sym_index }),
|
||||
.mov => try self.genSetReg(reg, Type.usize, .{ .load_got = sym_index }),
|
||||
else => unreachable,
|
||||
}
|
||||
switch (tag) {
|
||||
.lea, .mov => {},
|
||||
.call => try self.asmRegister(.call, reg),
|
||||
else => unreachable,
|
||||
}
|
||||
} else {
|
||||
return self.fail("TODO implement genLazySymbol for x86_64 {s}", .{@tagName(self.bin_file.tag)});
|
||||
}
|
||||
}
|
||||
|
||||
fn airPtrToInt(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const un_op = self.air.instructions.items(.data)[inst].un_op;
|
||||
const result = result: {
|
||||
|
|
@ -8701,6 +8709,7 @@ fn airMemcpy(self: *Self, inst: Air.Inst.Index) !void {
|
|||
}
|
||||
|
||||
fn airTagName(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const un_op = self.air.instructions.items(.data)[inst].un_op;
|
||||
const inst_ty = self.air.typeOfIndex(inst);
|
||||
const enum_ty = self.air.typeOf(un_op);
|
||||
|
|
@ -8731,38 +8740,17 @@ fn airTagName(self: *Self, inst: Air.Inst.Index) !void {
|
|||
const operand = try self.resolveInst(un_op);
|
||||
try self.genSetReg(param_regs[1], enum_ty, operand);
|
||||
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const lazy_sym = link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(), mod);
|
||||
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||
const atom_index = elf_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
|
||||
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
|
||||
const atom = elf_file.getAtom(atom_index);
|
||||
_ = try atom.getOrCreateOffsetTableEntry(elf_file);
|
||||
const got_addr = atom.getOffsetTableAddress(elf_file);
|
||||
try self.asmMemory(
|
||||
.call,
|
||||
Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) }),
|
||||
);
|
||||
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
|
||||
const atom_index = coff_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
|
||||
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
|
||||
const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
|
||||
try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
|
||||
try self.asmRegister(.call, .rax);
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
const atom_index = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
|
||||
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
|
||||
const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
|
||||
try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index });
|
||||
try self.asmRegister(.call, .rax);
|
||||
} else {
|
||||
return self.fail("TODO implement airTagName for x86_64 {s}", .{@tagName(self.bin_file.tag)});
|
||||
}
|
||||
try self.genLazySymbolRef(
|
||||
.call,
|
||||
.rax,
|
||||
link.File.LazySymbol.initDecl(.code, enum_ty.getOwnerDecl(), mod),
|
||||
);
|
||||
|
||||
return self.finishAir(inst, dst_mcv, .{ un_op, .none, .none });
|
||||
}
|
||||
|
||||
fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const un_op = self.air.instructions.items(.data)[inst].un_op;
|
||||
|
||||
const err_ty = self.air.typeOf(un_op);
|
||||
|
|
@ -8774,33 +8762,7 @@ fn airErrorName(self: *Self, inst: Air.Inst.Index) !void {
|
|||
const addr_reg = try self.register_manager.allocReg(null, gp);
|
||||
const addr_lock = self.register_manager.lockRegAssumeUnused(addr_reg);
|
||||
defer self.register_manager.unlockReg(addr_lock);
|
||||
|
||||
const mod = self.bin_file.options.module.?;
|
||||
const lazy_sym = link.File.LazySymbol.initDecl(.const_data, null, mod);
|
||||
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||
const atom_index = elf_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
|
||||
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
|
||||
const atom = elf_file.getAtom(atom_index);
|
||||
_ = try atom.getOrCreateOffsetTableEntry(elf_file);
|
||||
const got_addr = atom.getOffsetTableAddress(elf_file);
|
||||
try self.asmRegisterMemory(
|
||||
.mov,
|
||||
addr_reg.to64(),
|
||||
Memory.sib(.qword, .{ .base = .{ .reg = .ds }, .disp = @intCast(i32, got_addr) }),
|
||||
);
|
||||
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
|
||||
const atom_index = coff_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
|
||||
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
|
||||
const sym_index = coff_file.getAtom(atom_index).getSymbolIndex().?;
|
||||
try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index });
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
const atom_index = macho_file.getOrCreateAtomForLazySymbol(lazy_sym) catch |err|
|
||||
return self.fail("{s} creating lazy symbol", .{@errorName(err)});
|
||||
const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
|
||||
try self.genSetReg(addr_reg, Type.usize, .{ .lea_got = sym_index });
|
||||
} else {
|
||||
return self.fail("TODO implement airErrorName for x86_64 {s}", .{@tagName(self.bin_file.tag)});
|
||||
}
|
||||
try self.genLazySymbolRef(.lea, addr_reg, link.File.LazySymbol.initDecl(.const_data, null, mod));
|
||||
|
||||
const start_reg = try self.register_manager.allocReg(null, gp);
|
||||
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
|
|||
}
|
||||
|
||||
fn genTypedValue(self: *Self, arg_tv: TypedValue) InnerError!MCValue {
|
||||
return switch (try codegen.genTypedValue(self.bin_file, self.src_loc, arg_tv, self.owner.getOwnerDecl())) {
|
||||
return switch (try codegen.genTypedValue(self.bin_file, self.src_loc, arg_tv, self.owner.getDecl())) {
|
||||
.mcv => |mcv| switch (mcv) {
|
||||
.none => .none,
|
||||
.undef => .undef,
|
||||
|
|
|
|||
|
|
@ -143,8 +143,11 @@ const Section = struct {
|
|||
const LazySymbolTable = std.AutoArrayHashMapUnmanaged(Module.Decl.OptionalIndex, LazySymbolMetadata);
|
||||
|
||||
const LazySymbolMetadata = struct {
|
||||
text_atom: ?Atom.Index = null,
|
||||
rdata_atom: ?Atom.Index = null,
|
||||
const State = enum { unused, pending_flush, flushed };
|
||||
text_atom: Atom.Index = undefined,
|
||||
rdata_atom: Atom.Index = undefined,
|
||||
text_state: State = .unused,
|
||||
rdata_state: State = .unused,
|
||||
};
|
||||
|
||||
const DeclMetadata = struct {
|
||||
|
|
@ -1150,8 +1153,6 @@ pub fn updateDecl(
|
|||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
try self.updateLazySymbol(decl_index);
|
||||
|
||||
const decl = module.declPtr(decl_index);
|
||||
|
||||
if (decl.val.tag() == .extern_fn) {
|
||||
|
|
@ -1194,21 +1195,6 @@ pub fn updateDecl(
|
|||
return self.updateDeclExports(module, decl_index, module.getDeclExports(decl_index));
|
||||
}
|
||||
|
||||
fn updateLazySymbol(self: *Coff, decl: ?Module.Decl.Index) !void {
|
||||
const metadata = self.lazy_syms.get(Module.Decl.OptionalIndex.init(decl)) orelse return;
|
||||
const mod = self.base.options.module.?;
|
||||
if (metadata.text_atom) |atom| try self.updateLazySymbolAtom(
|
||||
link.File.LazySymbol.initDecl(.code, decl, mod),
|
||||
atom,
|
||||
self.text_section_index.?,
|
||||
);
|
||||
if (metadata.rdata_atom) |atom| try self.updateLazySymbolAtom(
|
||||
link.File.LazySymbol.initDecl(.const_data, decl, mod),
|
||||
atom,
|
||||
self.rdata_section_index.?,
|
||||
);
|
||||
}
|
||||
|
||||
fn updateLazySymbolAtom(
|
||||
self: *Coff,
|
||||
sym: link.File.LazySymbol,
|
||||
|
|
@ -1279,14 +1265,19 @@ pub fn getOrCreateAtomForLazySymbol(self: *Coff, sym: link.File.LazySymbol) !Ato
|
|||
const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl());
|
||||
errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
|
||||
if (!gop.found_existing) gop.value_ptr.* = .{};
|
||||
const atom_ptr = switch (sym.kind) {
|
||||
.code => &gop.value_ptr.text_atom,
|
||||
.const_data => &gop.value_ptr.rdata_atom,
|
||||
const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) {
|
||||
.code => .{ .atom = &gop.value_ptr.text_atom, .state = &gop.value_ptr.text_state },
|
||||
.const_data => .{ .atom = &gop.value_ptr.rdata_atom, .state = &gop.value_ptr.rdata_state },
|
||||
};
|
||||
if (atom_ptr.*) |atom| return atom;
|
||||
const atom = try self.createAtom();
|
||||
atom_ptr.* = atom;
|
||||
try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) {
|
||||
switch (metadata.state.*) {
|
||||
.unused => metadata.atom.* = try self.createAtom(),
|
||||
.pending_flush => return metadata.atom.*,
|
||||
.flushed => {},
|
||||
}
|
||||
metadata.state.* = .pending_flush;
|
||||
const atom = metadata.atom.*;
|
||||
// anyerror needs to be deferred until flushModule
|
||||
if (sym.getDecl() != .none) try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) {
|
||||
.code => self.text_section_index.?,
|
||||
.const_data => self.rdata_section_index.?,
|
||||
});
|
||||
|
|
@ -1617,15 +1608,35 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
|
|||
sub_prog_node.activate();
|
||||
defer sub_prog_node.end();
|
||||
|
||||
// Most lazy symbols can be updated when the corresponding decl is,
|
||||
// so we only have to worry about the one without an associated decl.
|
||||
self.updateLazySymbol(null) catch |err| switch (err) {
|
||||
error.CodegenFail => return error.FlushFailure,
|
||||
else => |e| return e,
|
||||
};
|
||||
|
||||
const gpa = self.base.allocator;
|
||||
|
||||
const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
|
||||
|
||||
if (self.lazy_syms.getPtr(.none)) |metadata| {
|
||||
// Most lazy symbols can be updated on first use, but
|
||||
// anyerror needs to wait for everything to be flushed.
|
||||
if (metadata.text_state != .unused) self.updateLazySymbolAtom(
|
||||
link.File.LazySymbol.initDecl(.code, null, module),
|
||||
metadata.text_atom,
|
||||
self.text_section_index.?,
|
||||
) catch |err| return switch (err) {
|
||||
error.CodegenFail => error.FlushFailure,
|
||||
else => |e| e,
|
||||
};
|
||||
if (metadata.rdata_state != .unused) self.updateLazySymbolAtom(
|
||||
link.File.LazySymbol.initDecl(.const_data, null, module),
|
||||
metadata.rdata_atom,
|
||||
self.rdata_section_index.?,
|
||||
) catch |err| return switch (err) {
|
||||
error.CodegenFail => error.FlushFailure,
|
||||
else => |e| e,
|
||||
};
|
||||
}
|
||||
for (self.lazy_syms.values()) |*metadata| {
|
||||
if (metadata.text_state != .unused) metadata.text_state = .flushed;
|
||||
if (metadata.rdata_state != .unused) metadata.rdata_state = .flushed;
|
||||
}
|
||||
|
||||
while (self.unresolved.popOrNull()) |entry| {
|
||||
assert(entry.value); // We only expect imports generated by the incremental linker for now.
|
||||
const global = self.globals.items[entry.key];
|
||||
|
|
|
|||
|
|
@ -65,8 +65,11 @@ const Section = struct {
|
|||
};
|
||||
|
||||
const LazySymbolMetadata = struct {
|
||||
text_atom: ?Atom.Index = null,
|
||||
rodata_atom: ?Atom.Index = null,
|
||||
const State = enum { unused, pending_flush, flushed };
|
||||
text_atom: Atom.Index = undefined,
|
||||
rodata_atom: Atom.Index = undefined,
|
||||
text_state: State = .unused,
|
||||
rodata_state: State = .unused,
|
||||
};
|
||||
|
||||
const DeclMetadata = struct {
|
||||
|
|
@ -1032,17 +1035,35 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
|
|||
sub_prog_node.activate();
|
||||
defer sub_prog_node.end();
|
||||
|
||||
// Most lazy symbols can be updated when the corresponding decl is,
|
||||
// so we only have to worry about the one without an associated decl.
|
||||
self.updateLazySymbol(null) catch |err| switch (err) {
|
||||
error.CodegenFail => return error.FlushFailure,
|
||||
else => |e| return e,
|
||||
};
|
||||
|
||||
// TODO This linker code currently assumes there is only 1 compilation unit and it
|
||||
// corresponds to the Zig source code.
|
||||
const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
|
||||
|
||||
if (self.lazy_syms.getPtr(.none)) |metadata| {
|
||||
// Most lazy symbols can be updated on first use, but
|
||||
// anyerror needs to wait for everything to be flushed.
|
||||
if (metadata.text_state != .unused) self.updateLazySymbolAtom(
|
||||
File.LazySymbol.initDecl(.code, null, module),
|
||||
metadata.text_atom,
|
||||
self.text_section_index.?,
|
||||
) catch |err| return switch (err) {
|
||||
error.CodegenFail => error.FlushFailure,
|
||||
else => |e| e,
|
||||
};
|
||||
if (metadata.rodata_state != .unused) self.updateLazySymbolAtom(
|
||||
File.LazySymbol.initDecl(.const_data, null, module),
|
||||
metadata.rodata_atom,
|
||||
self.rodata_section_index.?,
|
||||
) catch |err| return switch (err) {
|
||||
error.CodegenFail => error.FlushFailure,
|
||||
else => |e| e,
|
||||
};
|
||||
}
|
||||
for (self.lazy_syms.values()) |*metadata| {
|
||||
if (metadata.text_state != .unused) metadata.text_state = .flushed;
|
||||
if (metadata.rodata_state != .unused) metadata.rodata_state = .flushed;
|
||||
}
|
||||
|
||||
const target_endian = self.base.options.target.cpu.arch.endian();
|
||||
const foreign_endian = target_endian != builtin.cpu.arch.endian();
|
||||
|
||||
|
|
@ -2378,14 +2399,19 @@ pub fn getOrCreateAtomForLazySymbol(self: *Elf, sym: File.LazySymbol) !Atom.Inde
|
|||
const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl());
|
||||
errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
|
||||
if (!gop.found_existing) gop.value_ptr.* = .{};
|
||||
const atom_ptr = switch (sym.kind) {
|
||||
.code => &gop.value_ptr.text_atom,
|
||||
.const_data => &gop.value_ptr.rodata_atom,
|
||||
const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) {
|
||||
.code => .{ .atom = &gop.value_ptr.text_atom, .state = &gop.value_ptr.text_state },
|
||||
.const_data => .{ .atom = &gop.value_ptr.rodata_atom, .state = &gop.value_ptr.rodata_state },
|
||||
};
|
||||
if (atom_ptr.*) |atom| return atom;
|
||||
const atom = try self.createAtom();
|
||||
atom_ptr.* = atom;
|
||||
try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) {
|
||||
switch (metadata.state.*) {
|
||||
.unused => metadata.atom.* = try self.createAtom(),
|
||||
.pending_flush => return metadata.atom.*,
|
||||
.flushed => {},
|
||||
}
|
||||
metadata.state.* = .pending_flush;
|
||||
const atom = metadata.atom.*;
|
||||
// anyerror needs to be deferred until flushModule
|
||||
if (sym.getDecl() != .none) try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) {
|
||||
.code => self.text_section_index.?,
|
||||
.const_data => self.rodata_section_index.?,
|
||||
});
|
||||
|
|
@ -2598,8 +2624,6 @@ pub fn updateDecl(
|
|||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
try self.updateLazySymbol(decl_index);
|
||||
|
||||
const decl = module.declPtr(decl_index);
|
||||
|
||||
if (decl.val.tag() == .extern_fn) {
|
||||
|
|
@ -2666,21 +2690,6 @@ pub fn updateDecl(
|
|||
return self.updateDeclExports(module, decl_index, module.getDeclExports(decl_index));
|
||||
}
|
||||
|
||||
fn updateLazySymbol(self: *Elf, decl: ?Module.Decl.Index) !void {
|
||||
const metadata = self.lazy_syms.get(Module.Decl.OptionalIndex.init(decl)) orelse return;
|
||||
const mod = self.base.options.module.?;
|
||||
if (metadata.text_atom) |atom| try self.updateLazySymbolAtom(
|
||||
File.LazySymbol.initDecl(.code, decl, mod),
|
||||
atom,
|
||||
self.text_section_index.?,
|
||||
);
|
||||
if (metadata.rodata_atom) |atom| try self.updateLazySymbolAtom(
|
||||
File.LazySymbol.initDecl(.const_data, decl, mod),
|
||||
atom,
|
||||
self.rodata_section_index.?,
|
||||
);
|
||||
}
|
||||
|
||||
fn updateLazySymbolAtom(
|
||||
self: *Elf,
|
||||
sym: File.LazySymbol,
|
||||
|
|
|
|||
|
|
@ -236,8 +236,11 @@ const is_hot_update_compatible = switch (builtin.target.os.tag) {
|
|||
const LazySymbolTable = std.AutoArrayHashMapUnmanaged(Module.Decl.OptionalIndex, LazySymbolMetadata);
|
||||
|
||||
const LazySymbolMetadata = struct {
|
||||
text_atom: ?Atom.Index = null,
|
||||
data_const_atom: ?Atom.Index = null,
|
||||
const State = enum { unused, pending_flush, flushed };
|
||||
text_atom: Atom.Index = undefined,
|
||||
data_const_atom: Atom.Index = undefined,
|
||||
text_state: State = .unused,
|
||||
data_const_state: State = .unused,
|
||||
};
|
||||
|
||||
const TlvSymbolTable = std.AutoArrayHashMapUnmanaged(SymbolWithLoc, Atom.Index);
|
||||
|
|
@ -493,15 +496,33 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
|
|||
sub_prog_node.activate();
|
||||
defer sub_prog_node.end();
|
||||
|
||||
// Most lazy symbols can be updated when the corresponding decl is,
|
||||
// so we only have to worry about the one without an associated decl.
|
||||
self.updateLazySymbol(null) catch |err| switch (err) {
|
||||
error.CodegenFail => return error.FlushFailure,
|
||||
else => |e| return e,
|
||||
};
|
||||
|
||||
const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
|
||||
|
||||
if (self.lazy_syms.getPtr(.none)) |metadata| {
|
||||
// Most lazy symbols can be updated on first use, but
|
||||
// anyerror needs to wait for everything to be flushed.
|
||||
if (metadata.text_state != .unused) self.updateLazySymbolAtom(
|
||||
File.LazySymbol.initDecl(.code, null, module),
|
||||
metadata.text_atom,
|
||||
self.text_section_index.?,
|
||||
) catch |err| return switch (err) {
|
||||
error.CodegenFail => error.FlushFailure,
|
||||
else => |e| e,
|
||||
};
|
||||
if (metadata.data_const_state != .unused) self.updateLazySymbolAtom(
|
||||
File.LazySymbol.initDecl(.const_data, null, module),
|
||||
metadata.data_const_atom,
|
||||
self.data_const_section_index.?,
|
||||
) catch |err| return switch (err) {
|
||||
error.CodegenFail => error.FlushFailure,
|
||||
else => |e| e,
|
||||
};
|
||||
}
|
||||
for (self.lazy_syms.values()) |*metadata| {
|
||||
if (metadata.text_state != .unused) metadata.text_state = .flushed;
|
||||
if (metadata.data_const_state != .unused) metadata.data_const_state = .flushed;
|
||||
}
|
||||
|
||||
if (self.d_sym) |*d_sym| {
|
||||
try d_sym.dwarf.flushModule(module);
|
||||
}
|
||||
|
|
@ -1960,8 +1981,6 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
|
|||
const tracy = trace(@src());
|
||||
defer tracy.end();
|
||||
|
||||
try self.updateLazySymbol(decl_index);
|
||||
|
||||
const decl = module.declPtr(decl_index);
|
||||
|
||||
if (decl.val.tag() == .extern_fn) {
|
||||
|
|
@ -2036,21 +2055,6 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
|
|||
try self.updateDeclExports(module, decl_index, module.getDeclExports(decl_index));
|
||||
}
|
||||
|
||||
fn updateLazySymbol(self: *MachO, decl: ?Module.Decl.Index) !void {
|
||||
const metadata = self.lazy_syms.get(Module.Decl.OptionalIndex.init(decl)) orelse return;
|
||||
const mod = self.base.options.module.?;
|
||||
if (metadata.text_atom) |atom| try self.updateLazySymbolAtom(
|
||||
File.LazySymbol.initDecl(.code, decl, mod),
|
||||
atom,
|
||||
self.text_section_index.?,
|
||||
);
|
||||
if (metadata.data_const_atom) |atom| try self.updateLazySymbolAtom(
|
||||
File.LazySymbol.initDecl(.const_data, decl, mod),
|
||||
atom,
|
||||
self.data_const_section_index.?,
|
||||
);
|
||||
}
|
||||
|
||||
fn updateLazySymbolAtom(
|
||||
self: *MachO,
|
||||
sym: File.LazySymbol,
|
||||
|
|
@ -2125,14 +2129,22 @@ pub fn getOrCreateAtomForLazySymbol(self: *MachO, sym: File.LazySymbol) !Atom.In
|
|||
const gop = try self.lazy_syms.getOrPut(self.base.allocator, sym.getDecl());
|
||||
errdefer _ = if (!gop.found_existing) self.lazy_syms.pop();
|
||||
if (!gop.found_existing) gop.value_ptr.* = .{};
|
||||
const atom_ptr = switch (sym.kind) {
|
||||
.code => &gop.value_ptr.text_atom,
|
||||
.const_data => &gop.value_ptr.data_const_atom,
|
||||
const metadata: struct { atom: *Atom.Index, state: *LazySymbolMetadata.State } = switch (sym.kind) {
|
||||
.code => .{ .atom = &gop.value_ptr.text_atom, .state = &gop.value_ptr.text_state },
|
||||
.const_data => .{
|
||||
.atom = &gop.value_ptr.data_const_atom,
|
||||
.state = &gop.value_ptr.data_const_state,
|
||||
},
|
||||
};
|
||||
if (atom_ptr.*) |atom| return atom;
|
||||
const atom = try self.createAtom();
|
||||
atom_ptr.* = atom;
|
||||
try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) {
|
||||
switch (metadata.state.*) {
|
||||
.unused => metadata.atom.* = try self.createAtom(),
|
||||
.pending_flush => return metadata.atom.*,
|
||||
.flushed => {},
|
||||
}
|
||||
metadata.state.* = .pending_flush;
|
||||
const atom = metadata.atom.*;
|
||||
// anyerror needs to be deferred until flushModule
|
||||
if (sym.getDecl() != .none) try self.updateLazySymbolAtom(sym, atom, switch (sym.kind) {
|
||||
.code => self.text_section_index.?,
|
||||
.const_data => self.data_const_section_index.?,
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue