mirror of
https://codeberg.org/ziglang/zig.git
synced 2025-12-06 13:54:21 +00:00
link: make Plan9 atoms fully owned by the linker
This commit is contained in:
parent
9fdc32c96e
commit
b3277c8936
8 changed files with 170 additions and 100 deletions
|
|
@ -5277,7 +5277,7 @@ pub fn clearDecl(
|
||||||
.coff => .{ .coff = {} },
|
.coff => .{ .coff = {} },
|
||||||
.elf => .{ .elf = {} },
|
.elf => .{ .elf = {} },
|
||||||
.macho => .{ .macho = {} },
|
.macho => .{ .macho = {} },
|
||||||
.plan9 => .{ .plan9 = link.File.Plan9.DeclBlock.empty },
|
.plan9 => .{ .plan9 = {} },
|
||||||
.c => .{ .c = {} },
|
.c => .{ .c = {} },
|
||||||
.wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },
|
.wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },
|
||||||
.spirv => .{ .spirv = {} },
|
.spirv => .{ .spirv = {} },
|
||||||
|
|
@ -5697,7 +5697,7 @@ pub fn allocateNewDecl(
|
||||||
.coff => .{ .coff = {} },
|
.coff => .{ .coff = {} },
|
||||||
.elf => .{ .elf = {} },
|
.elf => .{ .elf = {} },
|
||||||
.macho => .{ .macho = {} },
|
.macho => .{ .macho = {} },
|
||||||
.plan9 => .{ .plan9 = link.File.Plan9.DeclBlock.empty },
|
.plan9 => .{ .plan9 = {} },
|
||||||
.c => .{ .c = {} },
|
.c => .{ .c = {} },
|
||||||
.wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },
|
.wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },
|
||||||
.spirv => .{ .spirv = {} },
|
.spirv => .{ .spirv = {} },
|
||||||
|
|
|
||||||
|
|
@ -5568,7 +5568,7 @@ pub fn analyzeExport(
|
||||||
.coff => .{ .coff = {} },
|
.coff => .{ .coff = {} },
|
||||||
.elf => .{ .elf = {} },
|
.elf => .{ .elf = {} },
|
||||||
.macho => .{ .macho = {} },
|
.macho => .{ .macho = {} },
|
||||||
.plan9 => .{ .plan9 = null },
|
.plan9 => .{ .plan9 = {} },
|
||||||
.c => .{ .c = {} },
|
.c => .{ .c = {} },
|
||||||
.wasm => .{ .wasm = .{} },
|
.wasm => .{ .wasm = .{} },
|
||||||
.spirv => .{ .spirv = {} },
|
.spirv => .{ .spirv = {} },
|
||||||
|
|
|
||||||
|
|
@ -4307,7 +4307,6 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||||
if (self.air.value(callee)) |func_value| {
|
if (self.air.value(callee)) |func_value| {
|
||||||
if (func_value.castTag(.function)) |func_payload| {
|
if (func_value.castTag(.function)) |func_payload| {
|
||||||
const func = func_payload.data;
|
const func = func_payload.data;
|
||||||
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
|
||||||
|
|
||||||
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
|
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||||
const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
|
const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
|
||||||
|
|
@ -4333,11 +4332,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
|
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
|
||||||
try p9.seeDecl(func.owner_decl);
|
const decl_block_index = try p9.seeDecl(func.owner_decl);
|
||||||
|
const decl_block = p9.getDeclBlock(decl_block_index);
|
||||||
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
|
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
|
||||||
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
|
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
|
||||||
const got_addr = p9.bases.data;
|
const got_addr = p9.bases.data;
|
||||||
const got_index = fn_owner_decl.link.plan9.got_index.?;
|
const got_index = decl_block.got_index.?;
|
||||||
const fn_got_addr = got_addr + got_index * ptr_bytes;
|
const fn_got_addr = got_addr + got_index * ptr_bytes;
|
||||||
try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = fn_got_addr });
|
try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = fn_got_addr });
|
||||||
} else unreachable;
|
} else unreachable;
|
||||||
|
|
@ -6166,8 +6166,9 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
|
||||||
.sym_index = sym_index,
|
.sym_index = sym_index,
|
||||||
} };
|
} };
|
||||||
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
|
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
|
||||||
try p9.seeDecl(decl_index);
|
const decl_block_index = try p9.seeDecl(decl_index);
|
||||||
const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;
|
const decl_block = p9.getDeclBlock(decl_block_index);
|
||||||
|
const got_addr = p9.bases.data + decl_block.got_index.? * ptr_bytes;
|
||||||
return MCValue{ .memory = got_addr };
|
return MCValue{ .memory = got_addr };
|
||||||
} else {
|
} else {
|
||||||
return self.fail("TODO codegen non-ELF const Decl pointer", .{});
|
return self.fail("TODO codegen non-ELF const Decl pointer", .{});
|
||||||
|
|
|
||||||
|
|
@ -6091,8 +6091,9 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
|
||||||
} else if (self.bin_file.cast(link.File.Coff)) |_| {
|
} else if (self.bin_file.cast(link.File.Coff)) |_| {
|
||||||
return self.fail("TODO codegen COFF const Decl pointer", .{});
|
return self.fail("TODO codegen COFF const Decl pointer", .{});
|
||||||
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
|
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
|
||||||
try p9.seeDecl(decl_index);
|
const decl_block_index = try p9.seeDecl(decl_index);
|
||||||
const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;
|
const decl_block = p9.getDeclBlock(decl_block_index);
|
||||||
|
const got_addr = p9.bases.data + decl_block.got_index.? * ptr_bytes;
|
||||||
return MCValue{ .memory = got_addr };
|
return MCValue{ .memory = got_addr };
|
||||||
} else {
|
} else {
|
||||||
return self.fail("TODO codegen non-ELF const Decl pointer", .{});
|
return self.fail("TODO codegen non-ELF const Decl pointer", .{});
|
||||||
|
|
|
||||||
|
|
@ -2558,8 +2558,9 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
|
||||||
} else if (self.bin_file.cast(link.File.Coff)) |_| {
|
} else if (self.bin_file.cast(link.File.Coff)) |_| {
|
||||||
return self.fail("TODO codegen COFF const Decl pointer", .{});
|
return self.fail("TODO codegen COFF const Decl pointer", .{});
|
||||||
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
|
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
|
||||||
try p9.seeDecl(decl_index);
|
const decl_block_index = try p9.seeDecl(decl_index);
|
||||||
const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;
|
const decl_block = p9.getDeclBlock(decl_block_index);
|
||||||
|
const got_addr = p9.bases.data + decl_block.got_index.? * ptr_bytes;
|
||||||
return MCValue{ .memory = got_addr };
|
return MCValue{ .memory = got_addr };
|
||||||
} else {
|
} else {
|
||||||
return self.fail("TODO codegen non-ELF const Decl pointer", .{});
|
return self.fail("TODO codegen non-ELF const Decl pointer", .{});
|
||||||
|
|
|
||||||
|
|
@ -3996,7 +3996,6 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||||
if (self.air.value(callee)) |func_value| {
|
if (self.air.value(callee)) |func_value| {
|
||||||
if (func_value.castTag(.function)) |func_payload| {
|
if (func_value.castTag(.function)) |func_payload| {
|
||||||
const func = func_payload.data;
|
const func = func_payload.data;
|
||||||
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
|
||||||
|
|
||||||
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
|
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||||
const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
|
const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
|
||||||
|
|
@ -4042,11 +4041,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||||
.data = undefined,
|
.data = undefined,
|
||||||
});
|
});
|
||||||
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
|
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
|
||||||
try p9.seeDecl(func.owner_decl);
|
const decl_block_index = try p9.seeDecl(func.owner_decl);
|
||||||
|
const decl_block = p9.getDeclBlock(decl_block_index);
|
||||||
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
|
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
|
||||||
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
|
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
|
||||||
const got_addr = p9.bases.data;
|
const got_addr = p9.bases.data;
|
||||||
const got_index = fn_owner_decl.link.plan9.got_index.?;
|
const got_index = decl_block.got_index.?;
|
||||||
const fn_got_addr = got_addr + got_index * ptr_bytes;
|
const fn_got_addr = got_addr + got_index * ptr_bytes;
|
||||||
_ = try self.addInst(.{
|
_ = try self.addInst(.{
|
||||||
.tag = .call,
|
.tag = .call,
|
||||||
|
|
@ -6739,8 +6739,9 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
|
||||||
.sym_index = sym_index,
|
.sym_index = sym_index,
|
||||||
} };
|
} };
|
||||||
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
|
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
|
||||||
try p9.seeDecl(decl_index);
|
const decl_block_index = try p9.seeDecl(decl_index);
|
||||||
const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;
|
const decl_block = p9.getDeclBlock(decl_block_index);
|
||||||
|
const got_addr = p9.bases.data + decl_block.got_index.? * ptr_bytes;
|
||||||
return MCValue{ .memory = got_addr };
|
return MCValue{ .memory = got_addr };
|
||||||
} else {
|
} else {
|
||||||
return self.fail("TODO codegen non-ELF const Decl pointer", .{});
|
return self.fail("TODO codegen non-ELF const Decl pointer", .{});
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,7 @@ pub const File = struct {
|
||||||
elf: void,
|
elf: void,
|
||||||
coff: void,
|
coff: void,
|
||||||
macho: void,
|
macho: void,
|
||||||
plan9: Plan9.DeclBlock,
|
plan9: void,
|
||||||
c: void,
|
c: void,
|
||||||
wasm: Wasm.DeclBlock,
|
wasm: Wasm.DeclBlock,
|
||||||
spirv: void,
|
spirv: void,
|
||||||
|
|
@ -287,7 +287,7 @@ pub const File = struct {
|
||||||
elf: void,
|
elf: void,
|
||||||
coff: void,
|
coff: void,
|
||||||
macho: void,
|
macho: void,
|
||||||
plan9: Plan9.Export,
|
plan9: void,
|
||||||
c: void,
|
c: void,
|
||||||
wasm: Wasm.Export,
|
wasm: Wasm.Export,
|
||||||
spirv: void,
|
spirv: void,
|
||||||
|
|
|
||||||
|
|
@ -21,14 +21,7 @@ const Allocator = std.mem.Allocator;
|
||||||
const log = std.log.scoped(.link);
|
const log = std.log.scoped(.link);
|
||||||
const assert = std.debug.assert;
|
const assert = std.debug.assert;
|
||||||
|
|
||||||
const FnDeclOutput = struct {
|
pub const base_tag = .plan9;
|
||||||
/// this code is modified when relocated so it is mutable
|
|
||||||
code: []u8,
|
|
||||||
/// this might have to be modified in the linker, so thats why its mutable
|
|
||||||
lineinfo: []u8,
|
|
||||||
start_line: u32,
|
|
||||||
end_line: u32,
|
|
||||||
};
|
|
||||||
|
|
||||||
base: link.File,
|
base: link.File,
|
||||||
sixtyfour_bit: bool,
|
sixtyfour_bit: bool,
|
||||||
|
|
@ -101,6 +94,9 @@ got_index_free_list: std.ArrayListUnmanaged(usize) = .{},
|
||||||
|
|
||||||
syms_index_free_list: std.ArrayListUnmanaged(usize) = .{},
|
syms_index_free_list: std.ArrayListUnmanaged(usize) = .{},
|
||||||
|
|
||||||
|
decl_blocks: std.ArrayListUnmanaged(DeclBlock) = .{},
|
||||||
|
decls: std.AutoHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{},
|
||||||
|
|
||||||
const Reloc = struct {
|
const Reloc = struct {
|
||||||
target: Module.Decl.Index,
|
target: Module.Decl.Index,
|
||||||
offset: u64,
|
offset: u64,
|
||||||
|
|
@ -115,6 +111,42 @@ const Bases = struct {
|
||||||
|
|
||||||
const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(struct { info: DeclBlock, code: []const u8 }));
|
const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(struct { info: DeclBlock, code: []const u8 }));
|
||||||
|
|
||||||
|
pub const PtrWidth = enum { p32, p64 };
|
||||||
|
|
||||||
|
pub const DeclBlock = struct {
|
||||||
|
type: aout.Sym.Type,
|
||||||
|
/// offset in the text or data sects
|
||||||
|
offset: ?u64,
|
||||||
|
/// offset into syms
|
||||||
|
sym_index: ?usize,
|
||||||
|
/// offset into got
|
||||||
|
got_index: ?usize,
|
||||||
|
|
||||||
|
pub const Index = u32;
|
||||||
|
};
|
||||||
|
|
||||||
|
const DeclMetadata = struct {
|
||||||
|
index: DeclBlock.Index,
|
||||||
|
exports: std.ArrayListUnmanaged(usize) = .{},
|
||||||
|
|
||||||
|
fn getExport(m: DeclMetadata, p9: *const Plan9, name: []const u8) ?usize {
|
||||||
|
for (m.exports.items) |exp| {
|
||||||
|
const sym = p9.syms.items[exp];
|
||||||
|
if (mem.eql(u8, name, sym.name)) return exp;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const FnDeclOutput = struct {
|
||||||
|
/// this code is modified when relocated so it is mutable
|
||||||
|
code: []u8,
|
||||||
|
/// this might have to be modified in the linker, so thats why its mutable
|
||||||
|
lineinfo: []u8,
|
||||||
|
start_line: u32,
|
||||||
|
end_line: u32,
|
||||||
|
};
|
||||||
|
|
||||||
fn getAddr(self: Plan9, addr: u64, t: aout.Sym.Type) u64 {
|
fn getAddr(self: Plan9, addr: u64, t: aout.Sym.Type) u64 {
|
||||||
return addr + switch (t) {
|
return addr + switch (t) {
|
||||||
.T, .t, .l, .L => self.bases.text,
|
.T, .t, .l, .L => self.bases.text,
|
||||||
|
|
@ -127,22 +159,6 @@ fn getSymAddr(self: Plan9, s: aout.Sym) u64 {
|
||||||
return self.getAddr(s.value, s.type);
|
return self.getAddr(s.value, s.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DeclBlock = struct {
|
|
||||||
type: aout.Sym.Type,
|
|
||||||
/// offset in the text or data sects
|
|
||||||
offset: ?u64,
|
|
||||||
/// offset into syms
|
|
||||||
sym_index: ?usize,
|
|
||||||
/// offset into got
|
|
||||||
got_index: ?usize,
|
|
||||||
pub const empty = DeclBlock{
|
|
||||||
.type = .t,
|
|
||||||
.offset = null,
|
|
||||||
.sym_index = null,
|
|
||||||
.got_index = null,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases {
|
pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases {
|
||||||
return switch (arch) {
|
return switch (arch) {
|
||||||
.x86_64 => .{
|
.x86_64 => .{
|
||||||
|
|
@ -164,8 +180,6 @@ pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const PtrWidth = enum { p32, p64 };
|
|
||||||
|
|
||||||
pub fn createEmpty(gpa: Allocator, options: link.Options) !*Plan9 {
|
pub fn createEmpty(gpa: Allocator, options: link.Options) !*Plan9 {
|
||||||
if (options.use_llvm)
|
if (options.use_llvm)
|
||||||
return error.LLVMBackendDoesNotSupportPlan9;
|
return error.LLVMBackendDoesNotSupportPlan9;
|
||||||
|
|
@ -271,7 +285,7 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv
|
||||||
const decl = module.declPtr(decl_index);
|
const decl = module.declPtr(decl_index);
|
||||||
self.freeUnnamedConsts(decl_index);
|
self.freeUnnamedConsts(decl_index);
|
||||||
|
|
||||||
try self.seeDecl(decl_index);
|
_ = try self.seeDecl(decl_index);
|
||||||
log.debug("codegen decl {*} ({s})", .{ decl, decl.name });
|
log.debug("codegen decl {*} ({s})", .{ decl, decl.name });
|
||||||
|
|
||||||
var code_buffer = std.ArrayList(u8).init(self.base.allocator);
|
var code_buffer = std.ArrayList(u8).init(self.base.allocator);
|
||||||
|
|
@ -313,11 +327,11 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv
|
||||||
.end_line = end_line,
|
.end_line = end_line,
|
||||||
};
|
};
|
||||||
try self.putFn(decl_index, out);
|
try self.putFn(decl_index, out);
|
||||||
return self.updateFinish(decl);
|
return self.updateFinish(decl_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.Index) !u32 {
|
pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.Index) !u32 {
|
||||||
try self.seeDecl(decl_index);
|
_ = try self.seeDecl(decl_index);
|
||||||
var code_buffer = std.ArrayList(u8).init(self.base.allocator);
|
var code_buffer = std.ArrayList(u8).init(self.base.allocator);
|
||||||
defer code_buffer.deinit();
|
defer code_buffer.deinit();
|
||||||
|
|
||||||
|
|
@ -387,7 +401,7 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try self.seeDecl(decl_index);
|
_ = try self.seeDecl(decl_index);
|
||||||
|
|
||||||
log.debug("codegen decl {*} ({s}) ({d})", .{ decl, decl.name, decl_index });
|
log.debug("codegen decl {*} ({s}) ({d})", .{ decl, decl.name, decl_index });
|
||||||
|
|
||||||
|
|
@ -414,28 +428,31 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index)
|
||||||
if (self.data_decl_table.fetchPutAssumeCapacity(decl_index, duped_code)) |old_entry| {
|
if (self.data_decl_table.fetchPutAssumeCapacity(decl_index, duped_code)) |old_entry| {
|
||||||
self.base.allocator.free(old_entry.value);
|
self.base.allocator.free(old_entry.value);
|
||||||
}
|
}
|
||||||
return self.updateFinish(decl);
|
return self.updateFinish(decl_index);
|
||||||
}
|
}
|
||||||
/// called at the end of update{Decl,Func}
|
/// called at the end of update{Decl,Func}
|
||||||
fn updateFinish(self: *Plan9, decl: *Module.Decl) !void {
|
fn updateFinish(self: *Plan9, decl_index: Module.Decl.Index) !void {
|
||||||
|
const decl = self.base.options.module.?.declPtr(decl_index);
|
||||||
const is_fn = (decl.ty.zigTypeTag() == .Fn);
|
const is_fn = (decl.ty.zigTypeTag() == .Fn);
|
||||||
log.debug("update the symbol table and got for decl {*} ({s})", .{ decl, decl.name });
|
log.debug("update the symbol table and got for decl {*} ({s})", .{ decl, decl.name });
|
||||||
const sym_t: aout.Sym.Type = if (is_fn) .t else .d;
|
const sym_t: aout.Sym.Type = if (is_fn) .t else .d;
|
||||||
|
|
||||||
|
const decl_block = self.getDeclBlockPtr(self.decls.get(decl_index).?.index);
|
||||||
// write the internal linker metadata
|
// write the internal linker metadata
|
||||||
decl.link.plan9.type = sym_t;
|
decl_block.type = sym_t;
|
||||||
// write the symbol
|
// write the symbol
|
||||||
// we already have the got index
|
// we already have the got index
|
||||||
const sym: aout.Sym = .{
|
const sym: aout.Sym = .{
|
||||||
.value = undefined, // the value of stuff gets filled in in flushModule
|
.value = undefined, // the value of stuff gets filled in in flushModule
|
||||||
.type = decl.link.plan9.type,
|
.type = decl_block.type,
|
||||||
.name = mem.span(decl.name),
|
.name = mem.span(decl.name),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (decl.link.plan9.sym_index) |s| {
|
if (decl_block.sym_index) |s| {
|
||||||
self.syms.items[s] = sym;
|
self.syms.items[s] = sym;
|
||||||
} else {
|
} else {
|
||||||
const s = try self.allocateSymbolIndex();
|
const s = try self.allocateSymbolIndex();
|
||||||
decl.link.plan9.sym_index = s;
|
decl_block.sym_index = s;
|
||||||
self.syms.items[s] = sym;
|
self.syms.items[s] = sym;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -550,6 +567,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
|
||||||
while (it.next()) |entry| {
|
while (it.next()) |entry| {
|
||||||
const decl_index = entry.key_ptr.*;
|
const decl_index = entry.key_ptr.*;
|
||||||
const decl = mod.declPtr(decl_index);
|
const decl = mod.declPtr(decl_index);
|
||||||
|
const decl_block = self.getDeclBlockPtr(self.decls.get(decl_index).?.index);
|
||||||
const out = entry.value_ptr.*;
|
const out = entry.value_ptr.*;
|
||||||
log.debug("write text decl {*} ({s}), lines {d} to {d}", .{ decl, decl.name, out.start_line + 1, out.end_line });
|
log.debug("write text decl {*} ({s}), lines {d} to {d}", .{ decl, decl.name, out.start_line + 1, out.end_line });
|
||||||
{
|
{
|
||||||
|
|
@ -568,16 +586,16 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
|
||||||
iovecs_i += 1;
|
iovecs_i += 1;
|
||||||
const off = self.getAddr(text_i, .t);
|
const off = self.getAddr(text_i, .t);
|
||||||
text_i += out.code.len;
|
text_i += out.code.len;
|
||||||
decl.link.plan9.offset = off;
|
decl_block.offset = off;
|
||||||
if (!self.sixtyfour_bit) {
|
if (!self.sixtyfour_bit) {
|
||||||
mem.writeIntNative(u32, got_table[decl.link.plan9.got_index.? * 4 ..][0..4], @intCast(u32, off));
|
mem.writeIntNative(u32, got_table[decl_block.got_index.? * 4 ..][0..4], @intCast(u32, off));
|
||||||
mem.writeInt(u32, got_table[decl.link.plan9.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian());
|
mem.writeInt(u32, got_table[decl_block.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian());
|
||||||
} else {
|
} else {
|
||||||
mem.writeInt(u64, got_table[decl.link.plan9.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian());
|
mem.writeInt(u64, got_table[decl_block.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian());
|
||||||
}
|
}
|
||||||
self.syms.items[decl.link.plan9.sym_index.?].value = off;
|
self.syms.items[decl_block.sym_index.?].value = off;
|
||||||
if (mod.decl_exports.get(decl_index)) |exports| {
|
if (mod.decl_exports.get(decl_index)) |exports| {
|
||||||
try self.addDeclExports(mod, decl, exports.items);
|
try self.addDeclExports(mod, decl_index, exports.items);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -598,6 +616,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
|
||||||
while (it.next()) |entry| {
|
while (it.next()) |entry| {
|
||||||
const decl_index = entry.key_ptr.*;
|
const decl_index = entry.key_ptr.*;
|
||||||
const decl = mod.declPtr(decl_index);
|
const decl = mod.declPtr(decl_index);
|
||||||
|
const decl_block = self.getDeclBlockPtr(self.decls.get(decl_index).?.index);
|
||||||
const code = entry.value_ptr.*;
|
const code = entry.value_ptr.*;
|
||||||
log.debug("write data decl {*} ({s})", .{ decl, decl.name });
|
log.debug("write data decl {*} ({s})", .{ decl, decl.name });
|
||||||
|
|
||||||
|
|
@ -606,15 +625,15 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
|
||||||
iovecs_i += 1;
|
iovecs_i += 1;
|
||||||
const off = self.getAddr(data_i, .d);
|
const off = self.getAddr(data_i, .d);
|
||||||
data_i += code.len;
|
data_i += code.len;
|
||||||
decl.link.plan9.offset = off;
|
decl_block.offset = off;
|
||||||
if (!self.sixtyfour_bit) {
|
if (!self.sixtyfour_bit) {
|
||||||
mem.writeInt(u32, got_table[decl.link.plan9.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian());
|
mem.writeInt(u32, got_table[decl_block.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian());
|
||||||
} else {
|
} else {
|
||||||
mem.writeInt(u64, got_table[decl.link.plan9.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian());
|
mem.writeInt(u64, got_table[decl_block.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian());
|
||||||
}
|
}
|
||||||
self.syms.items[decl.link.plan9.sym_index.?].value = off;
|
self.syms.items[decl_block.sym_index.?].value = off;
|
||||||
if (mod.decl_exports.get(decl_index)) |exports| {
|
if (mod.decl_exports.get(decl_index)) |exports| {
|
||||||
try self.addDeclExports(mod, decl, exports.items);
|
try self.addDeclExports(mod, decl_index, exports.items);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// write the unnamed constants after the other data decls
|
// write the unnamed constants after the other data decls
|
||||||
|
|
@ -676,7 +695,8 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
|
||||||
for (kv.value_ptr.items) |reloc| {
|
for (kv.value_ptr.items) |reloc| {
|
||||||
const target_decl_index = reloc.target;
|
const target_decl_index = reloc.target;
|
||||||
const target_decl = mod.declPtr(target_decl_index);
|
const target_decl = mod.declPtr(target_decl_index);
|
||||||
const target_decl_offset = target_decl.link.plan9.offset.?;
|
const target_decl_block = self.getDeclBlock(self.decls.get(target_decl_index).?.index);
|
||||||
|
const target_decl_offset = target_decl_block.offset.?;
|
||||||
|
|
||||||
const offset = reloc.offset;
|
const offset = reloc.offset;
|
||||||
const addend = reloc.addend;
|
const addend = reloc.addend;
|
||||||
|
|
@ -709,28 +729,36 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
|
||||||
fn addDeclExports(
|
fn addDeclExports(
|
||||||
self: *Plan9,
|
self: *Plan9,
|
||||||
module: *Module,
|
module: *Module,
|
||||||
decl: *Module.Decl,
|
decl_index: Module.Decl.Index,
|
||||||
exports: []const *Module.Export,
|
exports: []const *Module.Export,
|
||||||
) !void {
|
) !void {
|
||||||
|
const metadata = self.decls.getPtr(decl_index).?;
|
||||||
|
const decl_block = self.getDeclBlock(metadata.index);
|
||||||
|
|
||||||
for (exports) |exp| {
|
for (exports) |exp| {
|
||||||
// plan9 does not support custom sections
|
// plan9 does not support custom sections
|
||||||
if (exp.options.section) |section_name| {
|
if (exp.options.section) |section_name| {
|
||||||
if (!mem.eql(u8, section_name, ".text") or !mem.eql(u8, section_name, ".data")) {
|
if (!mem.eql(u8, section_name, ".text") or !mem.eql(u8, section_name, ".data")) {
|
||||||
try module.failed_exports.put(module.gpa, exp, try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(), "plan9 does not support extra sections", .{}));
|
try module.failed_exports.put(module.gpa, exp, try Module.ErrorMsg.create(
|
||||||
|
self.base.allocator,
|
||||||
|
module.declPtr(decl_index).srcLoc(),
|
||||||
|
"plan9 does not support extra sections",
|
||||||
|
.{},
|
||||||
|
));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const sym = .{
|
const sym = .{
|
||||||
.value = decl.link.plan9.offset.?,
|
.value = decl_block.offset.?,
|
||||||
.type = decl.link.plan9.type.toGlobal(),
|
.type = decl_block.type.toGlobal(),
|
||||||
.name = exp.options.name,
|
.name = exp.options.name,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (exp.link.plan9) |i| {
|
if (metadata.getExport(self, exp.options.name)) |i| {
|
||||||
self.syms.items[i] = sym;
|
self.syms.items[i] = sym;
|
||||||
} else {
|
} else {
|
||||||
try self.syms.append(self.base.allocator, sym);
|
try self.syms.append(self.base.allocator, sym);
|
||||||
exp.link.plan9 = self.syms.items.len - 1;
|
try metadata.exports.append(self.base.allocator, self.syms.items.len - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -760,14 +788,19 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {
|
||||||
self.base.allocator.free(removed_entry.value);
|
self.base.allocator.free(removed_entry.value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (decl.link.plan9.got_index) |i| {
|
if (self.decls.fetchRemove(decl_index)) |const_kv| {
|
||||||
|
var kv = const_kv;
|
||||||
|
const decl_block = self.getDeclBlock(kv.value.index);
|
||||||
|
if (decl_block.got_index) |i| {
|
||||||
// TODO: if this catch {} is triggered, an assertion in flushModule will be triggered, because got_index_free_list will have the wrong length
|
// TODO: if this catch {} is triggered, an assertion in flushModule will be triggered, because got_index_free_list will have the wrong length
|
||||||
self.got_index_free_list.append(self.base.allocator, i) catch {};
|
self.got_index_free_list.append(self.base.allocator, i) catch {};
|
||||||
}
|
}
|
||||||
if (decl.link.plan9.sym_index) |i| {
|
if (decl_block.sym_index) |i| {
|
||||||
self.syms_index_free_list.append(self.base.allocator, i) catch {};
|
self.syms_index_free_list.append(self.base.allocator, i) catch {};
|
||||||
self.syms.items[i] = aout.Sym.undefined_symbol;
|
self.syms.items[i] = aout.Sym.undefined_symbol;
|
||||||
}
|
}
|
||||||
|
kv.value.exports.deinit(self.base.allocator);
|
||||||
|
}
|
||||||
self.freeUnnamedConsts(decl_index);
|
self.freeUnnamedConsts(decl_index);
|
||||||
{
|
{
|
||||||
const relocs = self.relocs.getPtr(decl_index) orelse return;
|
const relocs = self.relocs.getPtr(decl_index) orelse return;
|
||||||
|
|
@ -786,12 +819,30 @@ fn freeUnnamedConsts(self: *Plan9, decl_index: Module.Decl.Index) void {
|
||||||
unnamed_consts.clearAndFree(self.base.allocator);
|
unnamed_consts.clearAndFree(self.base.allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seeDecl(self: *Plan9, decl_index: Module.Decl.Index) !void {
|
fn createDeclBlock(self: *Plan9) !DeclBlock.Index {
|
||||||
const mod = self.base.options.module.?;
|
const gpa = self.base.allocator;
|
||||||
const decl = mod.declPtr(decl_index);
|
const index = @intCast(DeclBlock.Index, self.decl_blocks.items.len);
|
||||||
if (decl.link.plan9.got_index == null) {
|
const decl_block = try self.decl_blocks.addOne(gpa);
|
||||||
decl.link.plan9.got_index = self.allocateGotIndex();
|
decl_block.* = .{
|
||||||
|
.type = .t,
|
||||||
|
.offset = null,
|
||||||
|
.sym_index = null,
|
||||||
|
.got_index = null,
|
||||||
|
};
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn seeDecl(self: *Plan9, decl_index: Module.Decl.Index) !DeclBlock.Index {
|
||||||
|
const gop = try self.decls.getOrPut(self.base.allocator, decl_index);
|
||||||
|
if (!gop.found_existing) {
|
||||||
|
const index = try self.createDeclBlock();
|
||||||
|
self.getDeclBlockPtr(index).got_index = self.allocateGotIndex();
|
||||||
|
gop.value_ptr.* = .{
|
||||||
|
.index = index,
|
||||||
|
.exports = .{},
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
return gop.value_ptr.index;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn updateDeclExports(
|
pub fn updateDeclExports(
|
||||||
|
|
@ -800,7 +851,7 @@ pub fn updateDeclExports(
|
||||||
decl_index: Module.Decl.Index,
|
decl_index: Module.Decl.Index,
|
||||||
exports: []const *Module.Export,
|
exports: []const *Module.Export,
|
||||||
) !void {
|
) !void {
|
||||||
try self.seeDecl(decl_index);
|
_ = try self.seeDecl(decl_index);
|
||||||
// we do all the things in flush
|
// we do all the things in flush
|
||||||
_ = module;
|
_ = module;
|
||||||
_ = exports;
|
_ = exports;
|
||||||
|
|
@ -842,10 +893,17 @@ pub fn deinit(self: *Plan9) void {
|
||||||
self.syms_index_free_list.deinit(gpa);
|
self.syms_index_free_list.deinit(gpa);
|
||||||
self.file_segments.deinit(gpa);
|
self.file_segments.deinit(gpa);
|
||||||
self.path_arena.deinit();
|
self.path_arena.deinit();
|
||||||
|
self.decl_blocks.deinit(gpa);
|
||||||
|
|
||||||
|
{
|
||||||
|
var it = self.decls.iterator();
|
||||||
|
while (it.next()) |entry| {
|
||||||
|
entry.value_ptr.exports.deinit(gpa);
|
||||||
|
}
|
||||||
|
self.decls.deinit(gpa);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const Export = ?usize;
|
|
||||||
pub const base_tag = .plan9;
|
|
||||||
pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Plan9 {
|
pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Plan9 {
|
||||||
if (options.use_llvm)
|
if (options.use_llvm)
|
||||||
return error.LLVMBackendDoesNotSupportPlan9;
|
return error.LLVMBackendDoesNotSupportPlan9;
|
||||||
|
|
@ -911,20 +969,19 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mod = self.base.options.module.?;
|
|
||||||
|
|
||||||
// write the data symbols
|
// write the data symbols
|
||||||
{
|
{
|
||||||
var it = self.data_decl_table.iterator();
|
var it = self.data_decl_table.iterator();
|
||||||
while (it.next()) |entry| {
|
while (it.next()) |entry| {
|
||||||
const decl_index = entry.key_ptr.*;
|
const decl_index = entry.key_ptr.*;
|
||||||
const decl = mod.declPtr(decl_index);
|
const decl_metadata = self.decls.get(decl_index).?;
|
||||||
const sym = self.syms.items[decl.link.plan9.sym_index.?];
|
const decl_block = self.getDeclBlock(decl_metadata.index);
|
||||||
|
const sym = self.syms.items[decl_block.sym_index.?];
|
||||||
try self.writeSym(writer, sym);
|
try self.writeSym(writer, sym);
|
||||||
if (self.base.options.module.?.decl_exports.get(decl_index)) |exports| {
|
if (self.base.options.module.?.decl_exports.get(decl_index)) |exports| {
|
||||||
for (exports.items) |e| {
|
for (exports.items) |e| if (decl_metadata.getExport(self, e.options.name)) |exp_i| {
|
||||||
try self.writeSym(writer, self.syms.items[e.link.plan9.?]);
|
try self.writeSym(writer, self.syms.items[exp_i]);
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -943,16 +1000,17 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
|
||||||
var submap_it = symidx_and_submap.functions.iterator();
|
var submap_it = symidx_and_submap.functions.iterator();
|
||||||
while (submap_it.next()) |entry| {
|
while (submap_it.next()) |entry| {
|
||||||
const decl_index = entry.key_ptr.*;
|
const decl_index = entry.key_ptr.*;
|
||||||
const decl = mod.declPtr(decl_index);
|
const decl_metadata = self.decls.get(decl_index).?;
|
||||||
const sym = self.syms.items[decl.link.plan9.sym_index.?];
|
const decl_block = self.getDeclBlock(decl_metadata.index);
|
||||||
|
const sym = self.syms.items[decl_block.sym_index.?];
|
||||||
try self.writeSym(writer, sym);
|
try self.writeSym(writer, sym);
|
||||||
if (self.base.options.module.?.decl_exports.get(decl_index)) |exports| {
|
if (self.base.options.module.?.decl_exports.get(decl_index)) |exports| {
|
||||||
for (exports.items) |e| {
|
for (exports.items) |e| if (decl_metadata.getExport(self, e.options.name)) |exp_i| {
|
||||||
const s = self.syms.items[e.link.plan9.?];
|
const s = self.syms.items[exp_i];
|
||||||
if (mem.eql(u8, s.name, "_start"))
|
if (mem.eql(u8, s.name, "_start"))
|
||||||
self.entry_val = s.value;
|
self.entry_val = s.value;
|
||||||
try self.writeSym(writer, s);
|
try self.writeSym(writer, s);
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1004,3 +1062,11 @@ pub fn getDeclVAddr(
|
||||||
});
|
});
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn getDeclBlock(self: *const Plan9, index: DeclBlock.Index) DeclBlock {
|
||||||
|
return self.decl_blocks.items[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
fn getDeclBlockPtr(self: *Plan9, index: DeclBlock.Index) *DeclBlock {
|
||||||
|
return &self.decl_blocks.items[index];
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue