authorgravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2022-10-04 16:32:28-04:00
committergravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2022-10-24 16:53:12-04:00
log5cf3d10e35dd9f9e435af318d7c0055e77eee3a1
tree14eb840ea783228c0846abcd92bdd24649ea748c
parent4f04759c874d5fd41c7cadeb974b4459559bc2a7

Plan9: deal with unnamed decls

Hello World works again!

2 files changed, 162 insertions(+), 26 deletions(-)

src/arch/x86_64/CodeGen.zig+6-2
......@@ -6953,8 +6953,12 @@ fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
69536953 .@"type" = .direct,
69546954 .sym_index = local_sym_index,
69556955 } };
6956 } else if (self.bin_file.cast(link.File.Plan9)) |_| {
6957 return self.fail("TODO lower unnamed const in Plan9", .{});
6956 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
6957 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
6958 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
6959 const got_index = local_sym_index; // the plan9 backend returns the got_index
6960 const got_addr = p9.bases.data + got_index * ptr_bytes;
6961 return MCValue{ .memory = got_addr };
69586962 } else {
69596963 return self.fail("TODO lower unnamed const", .{});
69606964 }
src/link/Plan9.zig+156-24
......@@ -63,8 +63,29 @@ fn_decl_table: std.AutoArrayHashMapUnmanaged(
6363) = .{},
6464data_decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, []const u8) = .{},
6565
66/// Table of unnamed constants associated with a parent `Decl`.
67/// We store them here so that we can free the constants whenever the `Decl`
68/// needs updating or is freed.
69///
70/// For example,
71///
72/// ```zig
73/// const Foo = struct{
74/// a: u8,
75/// };
76///
77/// pub fn main() void {
78/// var foo = Foo{ .a = 1 };
79/// _ = foo;
80/// }
81/// ```
82///
83/// value assigned to label `foo` is an unnamed constant belonging/associated
84/// with `Decl` `main`, and lives as long as that `Decl`.
85unnamed_const_atoms: UnnamedConstTable = .{},
6686hdr: aout.ExecHdr = undefined,
6787
88// relocs: std.
6889magic: u32,
6990
7091entry_val: ?u64 = null,
......@@ -82,6 +103,8 @@ const Bases = struct {
82103 data: u64,
83104};
84105
106const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(struct { info: DeclBlock, code: []const u8 }));
107
85108fn getAddr(self: Plan9, addr: u64, t: aout.Sym.Type) u64 {
86109 return addr + switch (t) {
87110 .T, .t, .l, .L => self.bases.text,
......@@ -233,6 +256,7 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv
233256
234257 const decl_index = func.owner_decl;
235258 const decl = module.declPtr(decl_index);
259 self.freeUnnamedConsts(decl_index);
236260
237261 try self.seeDecl(decl_index);
238262 log.debug("codegen decl {*} ({s})", .{ decl, decl.name });
......@@ -280,11 +304,62 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv
280304}
281305
282306pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.Index) !u32 {
283 _ = self;
284 _ = tv;
285 _ = decl_index;
286 log.debug("TODO lowerUnnamedConst for Plan9", .{});
287 return error.AnalysisFail;
307 try self.seeDecl(decl_index);
308 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
309 defer code_buffer.deinit();
310
311 const mod = self.base.options.module.?;
312 const decl = mod.declPtr(decl_index);
313
314 const gop = try self.unnamed_const_atoms.getOrPut(self.base.allocator, decl_index);
315 if (!gop.found_existing) {
316 gop.value_ptr.* = .{};
317 }
318 const unnamed_consts = gop.value_ptr;
319
320 const decl_name = try decl.getFullyQualifiedName(mod);
321 defer self.base.allocator.free(decl_name);
322
323 const index = unnamed_consts.items.len;
324 // name is freed when the unnamed const is freed
325 const name = try std.fmt.allocPrint(self.base.allocator, "__unnamed_{s}_{d}", .{ decl_name, index });
326
327 const sym_index = try self.allocateSymbolIndex();
328
329 const info: DeclBlock = .{
330 .type = .d,
331 .offset = null,
332 .sym_index = sym_index,
333 .got_index = self.allocateGotIndex(),
334 };
335 const sym: aout.Sym = .{
336 .value = undefined,
337 .type = info.type,
338 .name = name,
339 };
340 self.syms.items[info.sym_index.?] = sym;
341
342 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), tv, &code_buffer, .{
343 .none = {},
344 }, .{
345 .parent_atom_index = undefined,
346 });
347 const code = switch (res) {
348 .externally_managed => |x| x,
349 .appended => code_buffer.items,
350 .fail => |em| {
351 decl.analysis = .codegen_failure;
352 try mod.failed_decls.put(mod.gpa, decl_index, em);
353 log.err("{s}", .{em.msg});
354 return error.AnalysisFail;
355 },
356 };
357 // duped_code is freed when the unnamed const is freed
358 var duped_code = try self.base.allocator.dupe(u8, code);
359 errdefer self.base.allocator.free(duped_code);
360 try unnamed_consts.append(self.base.allocator, .{ .info = info, .code = duped_code });
361 // we return the got_index to codegen so that it can reference to the place of the data in the got
362 return @intCast(u32, info.got_index.?);
288363}
289364
290365pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index) !void {
......@@ -347,12 +422,26 @@ fn updateFinish(self: *Plan9, decl: *Module.Decl) !void {
347422 if (decl.link.plan9.sym_index) |s| {
348423 self.syms.items[s] = sym;
349424 } else {
350 if (self.syms_index_free_list.popOrNull()) |i| {
351 decl.link.plan9.sym_index = i;
352 } else {
353 try self.syms.append(self.base.allocator, sym);
354 decl.link.plan9.sym_index = self.syms.items.len - 1;
355 }
425 const s = try self.allocateSymbolIndex();
426 decl.link.plan9.sym_index = s;
427 self.syms.items[s] = sym;
428 }
429}
430
431fn allocateSymbolIndex(self: *Plan9) !usize {
432 if (self.syms_index_free_list.popOrNull()) |i| {
433 return i;
434 } else {
435 _ = try self.syms.addOne(self.base.allocator);
436 return self.syms.items.len - 1;
437 }
438}
439fn allocateGotIndex(self: *Plan9) usize {
440 if (self.got_index_free_list.popOrNull()) |i| {
441 return i;
442 } else {
443 self.got_len += 1;
444 return self.got_len - 1;
356445 }
357446}
358447
......@@ -381,7 +470,8 @@ pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void {
381470 }
382471}
383472
384fn declCount(self: *Plan9) usize {
473// counts decls and unnamed consts
474fn atomCount(self: *Plan9) usize {
385475 var fn_decl_count: usize = 0;
386476 var itf_files = self.fn_decl_table.iterator();
387477 while (itf_files.next()) |ent| {
......@@ -389,7 +479,13 @@ fn declCount(self: *Plan9) usize {
389479 var submap = ent.value_ptr.functions;
390480 fn_decl_count += submap.count();
391481 }
392 return self.data_decl_table.count() + fn_decl_count;
482 const data_decl_count = self.data_decl_table.count();
483 var unnamed_const_count: usize = 0;
484 var it_unc = self.unnamed_const_atoms.iterator();
485 while (it_unc.next()) |unnamed_consts| {
486 unnamed_const_count += unnamed_consts.value_ptr.items.len;
487 }
488 return data_decl_count + fn_decl_count + unnamed_const_count;
393489}
394490
395491pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) !void {
......@@ -411,13 +507,13 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
411507
412508 const mod = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
413509
414 assert(self.got_len == self.declCount() + self.got_index_free_list.items.len);
510 assert(self.got_len == self.atomCount() + self.got_index_free_list.items.len);
415511 const got_size = self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8;
416512 var got_table = try self.base.allocator.alloc(u8, got_size);
417513 defer self.base.allocator.free(got_table);
418514
419515 // + 4 for header, got, symbols, linecountinfo
420 var iovecs = try self.base.allocator.alloc(std.os.iovec_const, self.declCount() + 4);
516 var iovecs = try self.base.allocator.alloc(std.os.iovec_const, self.atomCount() + 4);
421517 defer self.base.allocator.free(iovecs);
422518
423519 const file = self.base.file.?;
......@@ -509,6 +605,26 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
509605 try self.addDeclExports(mod, decl, exports);
510606 }
511607 }
608 // write the unnamed constants after the other data decls
609 var it_unc = self.unnamed_const_atoms.iterator();
610 while (it_unc.next()) |unnamed_consts| {
611 for (unnamed_consts.value_ptr.items) |*unnamed_const| {
612 const code = unnamed_const.code;
613 log.debug("write unnamed const: ({s})", .{self.syms.items[unnamed_const.info.sym_index.?].name});
614 foff += code.len;
615 iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len };
616 iovecs_i += 1;
617 const off = self.getAddr(data_i, .d);
618 data_i += code.len;
619 unnamed_const.info.offset = off;
620 if (!self.sixtyfour_bit) {
621 mem.writeInt(u32, got_table[unnamed_const.info.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian());
622 } else {
623 mem.writeInt(u64, got_table[unnamed_const.info.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian());
624 }
625 self.syms.items[unnamed_const.info.sym_index.?].value = off;
626 }
627 }
512628 // edata symbol
513629 self.syms.items[0].value = self.getAddr(data_i, .b);
514630 }
......@@ -518,7 +634,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No
518634 try self.writeSyms(&sym_buf);
519635 const syms = sym_buf.toOwnedSlice();
520636 defer self.base.allocator.free(syms);
521 assert(2 + self.declCount() == iovecs_i); // we didn't write all the decls
637 assert(2 + self.atomCount() == iovecs_i); // we didn't write all the decls
522638 iovecs[iovecs_i] = .{ .iov_base = syms.ptr, .iov_len = syms.len };
523639 iovecs_i += 1;
524640 iovecs[iovecs_i] = .{ .iov_base = linecountinfo.items.ptr, .iov_len = linecountinfo.items.len };
......@@ -599,18 +715,24 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void {
599715 self.syms_index_free_list.append(self.base.allocator, i) catch {};
600716 self.syms.items[i] = aout.Sym.undefined_symbol;
601717 }
718 self.freeUnnamedConsts(decl_index);
719}
720fn freeUnnamedConsts(self: *Plan9, decl_index: Module.Decl.Index) void {
721 const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return;
722 for (unnamed_consts.items) |c| {
723 self.base.allocator.free(self.syms.items[c.info.sym_index.?].name);
724 self.base.allocator.free(c.code);
725 self.syms.items[c.info.sym_index.?] = aout.Sym.undefined_symbol;
726 self.syms_index_free_list.append(self.base.allocator, c.info.sym_index.?) catch {};
727 }
728 unnamed_consts.clearAndFree(self.base.allocator);
602729}
603730
604731pub fn seeDecl(self: *Plan9, decl_index: Module.Decl.Index) !void {
605732 const mod = self.base.options.module.?;
606733 const decl = mod.declPtr(decl_index);
607734 if (decl.link.plan9.got_index == null) {
608 if (self.got_index_free_list.popOrNull()) |i| {
609 decl.link.plan9.got_index = i;
610 } else {
611 self.got_len += 1;
612 decl.link.plan9.got_index = self.got_len - 1;
613 }
735 decl.link.plan9.got_index = self.allocateGotIndex();
614736 }
615737}
616738
......@@ -627,6 +749,12 @@ pub fn updateDeclExports(
627749}
628750pub fn deinit(self: *Plan9) void {
629751 const gpa = self.base.allocator;
752 // free the unnamed consts
753 var it_unc = self.unnamed_const_atoms.iterator();
754 while (it_unc.next()) |kv| {
755 self.freeUnnamedConsts(kv.key_ptr.*);
756 }
757 self.unnamed_const_atoms.deinit(gpa);
630758 var itf_files = self.fn_decl_table.iterator();
631759 while (itf_files.next()) |ent| {
632760 // get the submap
......@@ -790,7 +918,9 @@ pub fn getDeclVAddr(
790918 start += entry.value_ptr.code.len;
791919 }
792920 }
793 unreachable;
921 // TODO
922 return undefined;
923 // unreachable;
794924 } else {
795925 var start = self.bases.data + self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8;
796926 var it = self.data_decl_table.iterator();
......@@ -798,6 +928,8 @@ pub fn getDeclVAddr(
798928 if (decl_index == kv.key_ptr.*) return start;
799929 start += kv.value_ptr.len;
800930 }
801 unreachable;
931 // TODO
932 return undefined;
933 // unreachable;
802934 }
803935}