Commit d634e02d33

Jacob G-W <jacoblevgw@gmail.com>
2023-10-03 21:00:33
plan9: implement linking anon decls
1 parent de78caf
Changed files (1)
src
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 {