plan9: implement linking anon decls

This commit is contained in:
Jacob G-W 2023-10-03 15:00:33 -04:00 committed by Andrew Kelley
parent de78caf9c4
commit d634e02d33

View File

@ -82,6 +82,8 @@ unnamed_const_atoms: UnnamedConstTable = .{},
lazy_syms: LazySymbolTable = .{},
anon_decls: std.AutoHashMapUnmanaged(InternPool.Index, Atom.Index) = .{},
relocs: std.AutoHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Reloc)) = .{},
hdr: aout.ExecHdr = undefined,
@ -166,6 +168,9 @@ pub const Atom = struct {
code_len: usize,
decl_index: Module.Decl.Index,
},
fn fromSlice(slice: []u8) CodePtr {
return .{ .code_ptr = slice.ptr, .other = .{ .code_len = slice.len } };
}
fn getCode(self: CodePtr, plan9: *const Plan9) []u8 {
const mod = plan9.base.options.module.?;
return if (self.code_ptr) |p| p[0..self.other.code_len] else blk: {
@ -608,8 +613,9 @@ fn atomCount(self: *Plan9) usize {
while (it_lazy.next()) |kv| {
lazy_atom_count += kv.value_ptr.numberOfAtoms();
}
const anon_atom_count = self.anon_decls.count();
const extern_atom_count = self.externCount();
return data_decl_count + fn_decl_count + unnamed_const_count + lazy_atom_count + extern_atom_count;
return data_decl_count + fn_decl_count + unnamed_const_count + lazy_atom_count + extern_atom_count + anon_atom_count;
}
pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void {
@ -804,6 +810,27 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
self.syms.items[atom.sym_index.?].value = off;
}
}
// the anon decls
{
var it_anon = self.anon_decls.iterator();
while (it_anon.next()) |kv| {
const atom = self.getAtomPtr(kv.value_ptr.*);
const code = atom.code.getOwnedCode().?;
log.debug("write anon decl: {s}", .{self.syms.items[atom.sym_index.?].name});
foff += code.len;
iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len };
iovecs_i += 1;
const off = self.getAddr(data_i, .d);
data_i += code.len;
atom.offset = off;
if (!self.sixtyfour_bit) {
mem.writeInt(u32, got_table[atom.got_index.? * 4 ..][0..4], @as(u32, @intCast(off)), self.base.options.target.cpu.arch.endian());
} else {
mem.writeInt(u64, got_table[atom.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian());
}
self.syms.items[atom.sym_index.?].value = off;
}
}
// the lazy data symbols
var it_lazy = self.lazy_syms.iterator();
while (it_lazy.next()) |kv| {
@ -1196,6 +1223,11 @@ pub fn deinit(self: *Plan9) void {
while (itd.next()) |entry| {
gpa.free(entry.value_ptr.*);
}
var it_anon = self.anon_decls.iterator();
while (it_anon.next()) |entry| {
const sym_index = self.getAtom(entry.value_ptr.*).sym_index.?;
gpa.free(self.syms.items[sym_index].name);
}
self.data_decl_table.deinit(gpa);
self.syms.deinit(gpa);
self.got_index_free_list.deinit(gpa);
@ -1428,17 +1460,51 @@ pub fn lowerAnonDecl(self: *Plan9, decl_val: InternPool.Index, src_loc: Module.S
// be used by more than one function, however, its address is being used so we need
// to put it in some location.
// ...
_ = self;
_ = decl_val;
_ = src_loc;
_ = @panic("TODO: link/Plan9 lowerAnonDecl");
const gpa = self.base.allocator;
var gop = try self.anon_decls.getOrPut(gpa, decl_val);
const mod = self.base.options.module.?;
if (!gop.found_existing) {
const ty = mod.intern_pool.typeOf(decl_val).toType();
const val = decl_val.toValue();
const tv = TypedValue{ .ty = ty, .val = val };
const name = try std.fmt.allocPrint(gpa, "__anon_{d}", .{@intFromEnum(decl_val)});
const index = try self.createAtom();
const got_index = self.allocateGotIndex();
gop.value_ptr.* = index;
// we need to free name latex
var code_buffer = std.ArrayList(u8).init(gpa);
const res = try codegen.generateSymbol(&self.base, src_loc, tv, &code_buffer, .{ .none = {} }, .{ .parent_atom_index = index });
const code = switch (res) {
.ok => code_buffer.items,
.fail => |em| return .{ .fail = em },
};
const atom_ptr = self.getAtomPtr(index);
atom_ptr.* = .{
.type = .d,
.offset = undefined,
.sym_index = null,
.got_index = got_index,
.code = Atom.CodePtr.fromSlice(code),
};
_ = try atom_ptr.getOrCreateSymbolTableEntry(self);
self.syms.items[atom_ptr.sym_index.?] = .{
.type = .d,
.value = undefined,
.name = name,
};
}
return .ok;
}
pub fn getAnonDeclVAddr(self: *Plan9, decl_val: InternPool.Index, reloc_info: link.File.RelocInfo) !u64 {
_ = self;
_ = decl_val;
_ = reloc_info;
_ = @panic("TODO: link/Plan9 getAnonDeclVAddr");
const atom_index = self.anon_decls.get(decl_val).?;
try self.addReloc(reloc_info.parent_atom_index, .{
.target = atom_index,
.offset = reloc_info.offset,
.addend = reloc_info.addend,
});
return undefined;
}
pub fn addReloc(self: *Plan9, parent_index: Atom.Index, reloc: Reloc) !void {