Commit d634e02d33
Changed files (1)
src
link
src/link/Plan9.zig
@@ -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 {