| ... | @@ -21,14 +21,7 @@ const Allocator = std.mem.Allocator; | ... | @@ -21,14 +21,7 @@ const Allocator = std.mem.Allocator; |
| 21 | const log = std.log.scoped(.link); | 21 | const log = std.log.scoped(.link); |
| 22 | const assert = std.debug.assert; | 22 | const assert = std.debug.assert; |
| 23 | | 23 | |
| 24 | const FnDeclOutput = struct { | 24 | pub const base_tag = .plan9; |
| 25 | /// this code is modified when relocated so it is mutable | | |
| 26 | code: []u8, | | |
| 27 | /// this might have to be modified in the linker, so thats why its mutable | | |
| 28 | lineinfo: []u8, | | |
| 29 | start_line: u32, | | |
| 30 | end_line: u32, | | |
| 31 | }; | | |
| 32 | | 25 | |
| 33 | base: link.File, | 26 | base: link.File, |
| 34 | sixtyfour_bit: bool, | 27 | sixtyfour_bit: bool, |
| ... | @@ -101,6 +94,9 @@ got_index_free_list: std.ArrayListUnmanaged(usize) = .{}, | ... | @@ -101,6 +94,9 @@ got_index_free_list: std.ArrayListUnmanaged(usize) = .{}, |
| 101 | | 94 | |
| 102 | syms_index_free_list: std.ArrayListUnmanaged(usize) = .{}, | 95 | syms_index_free_list: std.ArrayListUnmanaged(usize) = .{}, |
| 103 | | 96 | |
| | 97 | decl_blocks: std.ArrayListUnmanaged(DeclBlock) = .{}, |
| | 98 | decls: std.AutoHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{}, |
| | 99 | |
| 104 | const Reloc = struct { | 100 | const Reloc = struct { |
| 105 | target: Module.Decl.Index, | 101 | target: Module.Decl.Index, |
| 106 | offset: u64, | 102 | offset: u64, |
| ... | @@ -115,6 +111,42 @@ const Bases = struct { | ... | @@ -115,6 +111,42 @@ const Bases = struct { |
| 115 | | 111 | |
| 116 | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(struct { info: DeclBlock, code: []const u8 })); | 112 | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(struct { info: DeclBlock, code: []const u8 })); |
| 117 | | 113 | |
| | 114 | pub const PtrWidth = enum { p32, p64 }; |
| | 115 | |
| | 116 | pub const DeclBlock = struct { |
| | 117 | type: aout.Sym.Type, |
| | 118 | /// offset in the text or data sects |
| | 119 | offset: ?u64, |
| | 120 | /// offset into syms |
| | 121 | sym_index: ?usize, |
| | 122 | /// offset into got |
| | 123 | got_index: ?usize, |
| | 124 | |
| | 125 | pub const Index = u32; |
| | 126 | }; |
| | 127 | |
| | 128 | const DeclMetadata = struct { |
| | 129 | index: DeclBlock.Index, |
| | 130 | exports: std.ArrayListUnmanaged(usize) = .{}, |
| | 131 | |
| | 132 | fn getExport(m: DeclMetadata, p9: *const Plan9, name: []const u8) ?usize { |
| | 133 | for (m.exports.items) |exp| { |
| | 134 | const sym = p9.syms.items[exp]; |
| | 135 | if (mem.eql(u8, name, sym.name)) return exp; |
| | 136 | } |
| | 137 | return null; |
| | 138 | } |
| | 139 | }; |
| | 140 | |
| | 141 | const FnDeclOutput = struct { |
| | 142 | /// this code is modified when relocated so it is mutable |
| | 143 | code: []u8, |
| | 144 | /// this might have to be modified in the linker, so thats why its mutable |
| | 145 | lineinfo: []u8, |
| | 146 | start_line: u32, |
| | 147 | end_line: u32, |
| | 148 | }; |
| | 149 | |
| 118 | fn getAddr(self: Plan9, addr: u64, t: aout.Sym.Type) u64 { | 150 | fn getAddr(self: Plan9, addr: u64, t: aout.Sym.Type) u64 { |
| 119 | return addr + switch (t) { | 151 | return addr + switch (t) { |
| 120 | .T, .t, .l, .L => self.bases.text, | 152 | .T, .t, .l, .L => self.bases.text, |
| ... | @@ -127,22 +159,6 @@ fn getSymAddr(self: Plan9, s: aout.Sym) u64 { | ... | @@ -127,22 +159,6 @@ fn getSymAddr(self: Plan9, s: aout.Sym) u64 { |
| 127 | return self.getAddr(s.value, s.type); | 159 | return self.getAddr(s.value, s.type); |
| 128 | } | 160 | } |
| 129 | | 161 | |
| 130 | pub const DeclBlock = struct { | | |
| 131 | type: aout.Sym.Type, | | |
| 132 | /// offset in the text or data sects | | |
| 133 | offset: ?u64, | | |
| 134 | /// offset into syms | | |
| 135 | sym_index: ?usize, | | |
| 136 | /// offset into got | | |
| 137 | got_index: ?usize, | | |
| 138 | pub const empty = DeclBlock{ | | |
| 139 | .type = .t, | | |
| 140 | .offset = null, | | |
| 141 | .sym_index = null, | | |
| 142 | .got_index = null, | | |
| 143 | }; | | |
| 144 | }; | | |
| 145 | | | |
| 146 | pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases { | 162 | pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases { |
| 147 | return switch (arch) { | 163 | return switch (arch) { |
| 148 | .x86_64 => .{ | 164 | .x86_64 => .{ |
| ... | @@ -164,8 +180,6 @@ pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases { | ... | @@ -164,8 +180,6 @@ pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases { |
| 164 | }; | 180 | }; |
| 165 | } | 181 | } |
| 166 | | 182 | |
| 167 | pub const PtrWidth = enum { p32, p64 }; | | |
| 168 | | | |
| 169 | pub fn createEmpty(gpa: Allocator, options: link.Options) !*Plan9 { | 183 | pub fn createEmpty(gpa: Allocator, options: link.Options) !*Plan9 { |
| 170 | if (options.use_llvm) | 184 | if (options.use_llvm) |
| 171 | return error.LLVMBackendDoesNotSupportPlan9; | 185 | return error.LLVMBackendDoesNotSupportPlan9; |
| ... | @@ -271,7 +285,7 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv | ... | @@ -271,7 +285,7 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv |
| 271 | const decl = module.declPtr(decl_index); | 285 | const decl = module.declPtr(decl_index); |
| 272 | self.freeUnnamedConsts(decl_index); | 286 | self.freeUnnamedConsts(decl_index); |
| 273 | | 287 | |
| 274 | try self.seeDecl(decl_index); | 288 | _ = try self.seeDecl(decl_index); |
| 275 | log.debug("codegen decl {*} ({s})", .{ decl, decl.name }); | 289 | log.debug("codegen decl {*} ({s})", .{ decl, decl.name }); |
| 276 | | 290 | |
| 277 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | 291 | 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 | ... | @@ -313,11 +327,11 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv |
| 313 | .end_line = end_line, | 327 | .end_line = end_line, |
| 314 | }; | 328 | }; |
| 315 | try self.putFn(decl_index, out); | 329 | try self.putFn(decl_index, out); |
| 316 | return self.updateFinish(decl); | 330 | return self.updateFinish(decl_index); |
| 317 | } | 331 | } |
| 318 | | 332 | |
| 319 | pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.Index) !u32 { | 333 | pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.Index) !u32 { |
| 320 | try self.seeDecl(decl_index); | 334 | _ = try self.seeDecl(decl_index); |
| 321 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | 335 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 322 | defer code_buffer.deinit(); | 336 | defer code_buffer.deinit(); |
| 323 | | 337 | |
| ... | @@ -387,7 +401,7 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index) | ... | @@ -387,7 +401,7 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index) |
| 387 | } | 401 | } |
| 388 | } | 402 | } |
| 389 | | 403 | |
| 390 | try self.seeDecl(decl_index); | 404 | _ = try self.seeDecl(decl_index); |
| 391 | | 405 | |
| 392 | log.debug("codegen decl {*} ({s}) ({d})", .{ decl, decl.name, decl_index }); | 406 | log.debug("codegen decl {*} ({s}) ({d})", .{ decl, decl.name, decl_index }); |
| 393 | | 407 | |
| ... | @@ -414,28 +428,31 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index) | ... | @@ -414,28 +428,31 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index) |
| 414 | if (self.data_decl_table.fetchPutAssumeCapacity(decl_index, duped_code)) |old_entry| { | 428 | if (self.data_decl_table.fetchPutAssumeCapacity(decl_index, duped_code)) |old_entry| { |
| 415 | self.base.allocator.free(old_entry.value); | 429 | self.base.allocator.free(old_entry.value); |
| 416 | } | 430 | } |
| 417 | return self.updateFinish(decl); | 431 | return self.updateFinish(decl_index); |
| 418 | } | 432 | } |
| 419 | /// called at the end of update{Decl,Func} | 433 | /// called at the end of update{Decl,Func} |
| 420 | fn updateFinish(self: *Plan9, decl: *Module.Decl) !void { | 434 | fn updateFinish(self: *Plan9, decl_index: Module.Decl.Index) !void { |
| | 435 | const decl = self.base.options.module.?.declPtr(decl_index); |
| 421 | const is_fn = (decl.ty.zigTypeTag() == .Fn); | 436 | const is_fn = (decl.ty.zigTypeTag() == .Fn); |
| 422 | log.debug("update the symbol table and got for decl {*} ({s})", .{ decl, decl.name }); | 437 | log.debug("update the symbol table and got for decl {*} ({s})", .{ decl, decl.name }); |
| 423 | const sym_t: aout.Sym.Type = if (is_fn) .t else .d; | 438 | const sym_t: aout.Sym.Type = if (is_fn) .t else .d; |
| | 439 | |
| | 440 | const decl_block = self.getDeclBlockPtr(self.decls.get(decl_index).?.index); |
| 424 | // write the internal linker metadata | 441 | // write the internal linker metadata |
| 425 | decl.link.plan9.type = sym_t; | 442 | decl_block.type = sym_t; |
| 426 | // write the symbol | 443 | // write the symbol |
| 427 | // we already have the got index | 444 | // we already have the got index |
| 428 | const sym: aout.Sym = .{ | 445 | const sym: aout.Sym = .{ |
| 429 | .value = undefined, // the value of stuff gets filled in in flushModule | 446 | .value = undefined, // the value of stuff gets filled in in flushModule |
| 430 | .type = decl.link.plan9.type, | 447 | .type = decl_block.type, |
| 431 | .name = mem.span(decl.name), | 448 | .name = mem.span(decl.name), |
| 432 | }; | 449 | }; |
| 433 | | 450 | |
| 434 | if (decl.link.plan9.sym_index) |s| { | 451 | if (decl_block.sym_index) |s| { |
| 435 | self.syms.items[s] = sym; | 452 | self.syms.items[s] = sym; |
| 436 | } else { | 453 | } else { |
| 437 | const s = try self.allocateSymbolIndex(); | 454 | const s = try self.allocateSymbolIndex(); |
| 438 | decl.link.plan9.sym_index = s; | 455 | decl_block.sym_index = s; |
| 439 | self.syms.items[s] = sym; | 456 | self.syms.items[s] = sym; |
| 440 | } | 457 | } |
| 441 | } | 458 | } |
| ... | @@ -550,6 +567,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -550,6 +567,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No |
| 550 | while (it.next()) |entry| { | 567 | while (it.next()) |entry| { |
| 551 | const decl_index = entry.key_ptr.*; | 568 | const decl_index = entry.key_ptr.*; |
| 552 | const decl = mod.declPtr(decl_index); | 569 | const decl = mod.declPtr(decl_index); |
| | 570 | const decl_block = self.getDeclBlockPtr(self.decls.get(decl_index).?.index); |
| 553 | const out = entry.value_ptr.*; | 571 | const out = entry.value_ptr.*; |
| 554 | log.debug("write text decl {*} ({s}), lines {d} to {d}", .{ decl, decl.name, out.start_line + 1, out.end_line }); | 572 | log.debug("write text decl {*} ({s}), lines {d} to {d}", .{ decl, decl.name, out.start_line + 1, out.end_line }); |
| 555 | { | 573 | { |
| ... | @@ -568,16 +586,16 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -568,16 +586,16 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No |
| 568 | iovecs_i += 1; | 586 | iovecs_i += 1; |
| 569 | const off = self.getAddr(text_i, .t); | 587 | const off = self.getAddr(text_i, .t); |
| 570 | text_i += out.code.len; | 588 | text_i += out.code.len; |
| 571 | decl.link.plan9.offset = off; | 589 | decl_block.offset = off; |
| 572 | if (!self.sixtyfour_bit) { | 590 | if (!self.sixtyfour_bit) { |
| 573 | mem.writeIntNative(u32, got_table[decl.link.plan9.got_index.? * 4 ..][0..4], @intCast(u32, off)); | 591 | mem.writeIntNative(u32, got_table[decl_block.got_index.? * 4 ..][0..4], @intCast(u32, off)); |
| 574 | mem.writeInt(u32, got_table[decl.link.plan9.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian()); | 592 | mem.writeInt(u32, got_table[decl_block.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian()); |
| 575 | } else { | 593 | } else { |
| 576 | mem.writeInt(u64, got_table[decl.link.plan9.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); | 594 | mem.writeInt(u64, got_table[decl_block.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); |
| 577 | } | 595 | } |
| 578 | self.syms.items[decl.link.plan9.sym_index.?].value = off; | 596 | self.syms.items[decl_block.sym_index.?].value = off; |
| 579 | if (mod.decl_exports.get(decl_index)) |exports| { | 597 | if (mod.decl_exports.get(decl_index)) |exports| { |
| 580 | try self.addDeclExports(mod, decl, exports.items); | 598 | try self.addDeclExports(mod, decl_index, exports.items); |
| 581 | } | 599 | } |
| 582 | } | 600 | } |
| 583 | } | 601 | } |
| ... | @@ -598,6 +616,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -598,6 +616,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No |
| 598 | while (it.next()) |entry| { | 616 | while (it.next()) |entry| { |
| 599 | const decl_index = entry.key_ptr.*; | 617 | const decl_index = entry.key_ptr.*; |
| 600 | const decl = mod.declPtr(decl_index); | 618 | const decl = mod.declPtr(decl_index); |
| | 619 | const decl_block = self.getDeclBlockPtr(self.decls.get(decl_index).?.index); |
| 601 | const code = entry.value_ptr.*; | 620 | const code = entry.value_ptr.*; |
| 602 | log.debug("write data decl {*} ({s})", .{ decl, decl.name }); | 621 | log.debug("write data decl {*} ({s})", .{ decl, decl.name }); |
| 603 | | 622 | |
| ... | @@ -606,15 +625,15 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -606,15 +625,15 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No |
| 606 | iovecs_i += 1; | 625 | iovecs_i += 1; |
| 607 | const off = self.getAddr(data_i, .d); | 626 | const off = self.getAddr(data_i, .d); |
| 608 | data_i += code.len; | 627 | data_i += code.len; |
| 609 | decl.link.plan9.offset = off; | 628 | decl_block.offset = off; |
| 610 | if (!self.sixtyfour_bit) { | 629 | if (!self.sixtyfour_bit) { |
| 611 | mem.writeInt(u32, got_table[decl.link.plan9.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian()); | 630 | mem.writeInt(u32, got_table[decl_block.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian()); |
| 612 | } else { | 631 | } else { |
| 613 | mem.writeInt(u64, got_table[decl.link.plan9.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); | 632 | mem.writeInt(u64, got_table[decl_block.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); |
| 614 | } | 633 | } |
| 615 | self.syms.items[decl.link.plan9.sym_index.?].value = off; | 634 | self.syms.items[decl_block.sym_index.?].value = off; |
| 616 | if (mod.decl_exports.get(decl_index)) |exports| { | 635 | if (mod.decl_exports.get(decl_index)) |exports| { |
| 617 | try self.addDeclExports(mod, decl, exports.items); | 636 | try self.addDeclExports(mod, decl_index, exports.items); |
| 618 | } | 637 | } |
| 619 | } | 638 | } |
| 620 | // write the unnamed constants after the other data decls | 639 | // 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 | ... | @@ -676,7 +695,8 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No |
| 676 | for (kv.value_ptr.items) |reloc| { | 695 | for (kv.value_ptr.items) |reloc| { |
| 677 | const target_decl_index = reloc.target; | 696 | const target_decl_index = reloc.target; |
| 678 | const target_decl = mod.declPtr(target_decl_index); | 697 | const target_decl = mod.declPtr(target_decl_index); |
| 679 | const target_decl_offset = target_decl.link.plan9.offset.?; | 698 | const target_decl_block = self.getDeclBlock(self.decls.get(target_decl_index).?.index); |
| | 699 | const target_decl_offset = target_decl_block.offset.?; |
| 680 | | 700 | |
| 681 | const offset = reloc.offset; | 701 | const offset = reloc.offset; |
| 682 | const addend = reloc.addend; | 702 | const addend = reloc.addend; |
| ... | @@ -709,28 +729,36 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -709,28 +729,36 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No |
| 709 | fn addDeclExports( | 729 | fn addDeclExports( |
| 710 | self: *Plan9, | 730 | self: *Plan9, |
| 711 | module: *Module, | 731 | module: *Module, |
| 712 | decl: *Module.Decl, | 732 | decl_index: Module.Decl.Index, |
| 713 | exports: []const *Module.Export, | 733 | exports: []const *Module.Export, |
| 714 | ) !void { | 734 | ) !void { |
| | 735 | const metadata = self.decls.getPtr(decl_index).?; |
| | 736 | const decl_block = self.getDeclBlock(metadata.index); |
| | 737 | |
| 715 | for (exports) |exp| { | 738 | for (exports) |exp| { |
| 716 | // plan9 does not support custom sections | 739 | // plan9 does not support custom sections |
| 717 | if (exp.options.section) |section_name| { | 740 | if (exp.options.section) |section_name| { |
| 718 | if (!mem.eql(u8, section_name, ".text") or !mem.eql(u8, section_name, ".data")) { | 741 | if (!mem.eql(u8, section_name, ".text") or !mem.eql(u8, section_name, ".data")) { |
| 719 | try module.failed_exports.put(module.gpa, exp, try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(), "plan9 does not support extra sections", .{})); | 742 | try module.failed_exports.put(module.gpa, exp, try Module.ErrorMsg.create( |
| | 743 | self.base.allocator, |
| | 744 | module.declPtr(decl_index).srcLoc(), |
| | 745 | "plan9 does not support extra sections", |
| | 746 | .{}, |
| | 747 | )); |
| 720 | break; | 748 | break; |
| 721 | } | 749 | } |
| 722 | } | 750 | } |
| 723 | const sym = .{ | 751 | const sym = .{ |
| 724 | .value = decl.link.plan9.offset.?, | 752 | .value = decl_block.offset.?, |
| 725 | .type = decl.link.plan9.type.toGlobal(), | 753 | .type = decl_block.type.toGlobal(), |
| 726 | .name = exp.options.name, | 754 | .name = exp.options.name, |
| 727 | }; | 755 | }; |
| 728 | | 756 | |
| 729 | if (exp.link.plan9) |i| { | 757 | if (metadata.getExport(self, exp.options.name)) |i| { |
| 730 | self.syms.items[i] = sym; | 758 | self.syms.items[i] = sym; |
| 731 | } else { | 759 | } else { |
| 732 | try self.syms.append(self.base.allocator, sym); | 760 | try self.syms.append(self.base.allocator, sym); |
| 733 | exp.link.plan9 = self.syms.items.len - 1; | 761 | try metadata.exports.append(self.base.allocator, self.syms.items.len - 1); |
| 734 | } | 762 | } |
| 735 | } | 763 | } |
| 736 | } | 764 | } |
| ... | @@ -760,13 +788,18 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void { | ... | @@ -760,13 +788,18 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void { |
| 760 | self.base.allocator.free(removed_entry.value); | 788 | self.base.allocator.free(removed_entry.value); |
| 761 | } | 789 | } |
| 762 | } | 790 | } |
| 763 | if (decl.link.plan9.got_index) |i| { | 791 | if (self.decls.fetchRemove(decl_index)) |const_kv| { |
| 764 | // TODO: if this catch {} is triggered, an assertion in flushModule will be triggered, because got_index_free_list will have the wrong length | 792 | var kv = const_kv; |
| 765 | self.got_index_free_list.append(self.base.allocator, i) catch {}; | 793 | const decl_block = self.getDeclBlock(kv.value.index); |
| 766 | } | 794 | if (decl_block.got_index) |i| { |
| 767 | if (decl.link.plan9.sym_index) |i| { | 795 | // TODO: if this catch {} is triggered, an assertion in flushModule will be triggered, because got_index_free_list will have the wrong length |
| 768 | self.syms_index_free_list.append(self.base.allocator, i) catch {}; | 796 | self.got_index_free_list.append(self.base.allocator, i) catch {}; |
| 769 | self.syms.items[i] = aout.Sym.undefined_symbol; | 797 | } |
| | 798 | if (decl_block.sym_index) |i| { |
| | 799 | self.syms_index_free_list.append(self.base.allocator, i) catch {}; |
| | 800 | self.syms.items[i] = aout.Sym.undefined_symbol; |
| | 801 | } |
| | 802 | kv.value.exports.deinit(self.base.allocator); |
| 770 | } | 803 | } |
| 771 | self.freeUnnamedConsts(decl_index); | 804 | self.freeUnnamedConsts(decl_index); |
| 772 | { | 805 | { |
| ... | @@ -786,12 +819,30 @@ fn freeUnnamedConsts(self: *Plan9, decl_index: Module.Decl.Index) void { | ... | @@ -786,12 +819,30 @@ fn freeUnnamedConsts(self: *Plan9, decl_index: Module.Decl.Index) void { |
| 786 | unnamed_consts.clearAndFree(self.base.allocator); | 819 | unnamed_consts.clearAndFree(self.base.allocator); |
| 787 | } | 820 | } |
| 788 | | 821 | |
| 789 | pub fn seeDecl(self: *Plan9, decl_index: Module.Decl.Index) !void { | 822 | fn createDeclBlock(self: *Plan9) !DeclBlock.Index { |
| 790 | const mod = self.base.options.module.?; | 823 | const gpa = self.base.allocator; |
| 791 | const decl = mod.declPtr(decl_index); | 824 | const index = @intCast(DeclBlock.Index, self.decl_blocks.items.len); |
| 792 | if (decl.link.plan9.got_index == null) { | 825 | const decl_block = try self.decl_blocks.addOne(gpa); |
| 793 | decl.link.plan9.got_index = self.allocateGotIndex(); | 826 | decl_block.* = .{ |
| | 827 | .type = .t, |
| | 828 | .offset = null, |
| | 829 | .sym_index = null, |
| | 830 | .got_index = null, |
| | 831 | }; |
| | 832 | return index; |
| | 833 | } |
| | 834 | |
| | 835 | pub fn seeDecl(self: *Plan9, decl_index: Module.Decl.Index) !DeclBlock.Index { |
| | 836 | const gop = try self.decls.getOrPut(self.base.allocator, decl_index); |
| | 837 | if (!gop.found_existing) { |
| | 838 | const index = try self.createDeclBlock(); |
| | 839 | self.getDeclBlockPtr(index).got_index = self.allocateGotIndex(); |
| | 840 | gop.value_ptr.* = .{ |
| | 841 | .index = index, |
| | 842 | .exports = .{}, |
| | 843 | }; |
| 794 | } | 844 | } |
| | 845 | return gop.value_ptr.index; |
| 795 | } | 846 | } |
| 796 | | 847 | |
| 797 | pub fn updateDeclExports( | 848 | pub fn updateDeclExports( |
| ... | @@ -800,7 +851,7 @@ pub fn updateDeclExports( | ... | @@ -800,7 +851,7 @@ pub fn updateDeclExports( |
| 800 | decl_index: Module.Decl.Index, | 851 | decl_index: Module.Decl.Index, |
| 801 | exports: []const *Module.Export, | 852 | exports: []const *Module.Export, |
| 802 | ) !void { | 853 | ) !void { |
| 803 | try self.seeDecl(decl_index); | 854 | _ = try self.seeDecl(decl_index); |
| 804 | // we do all the things in flush | 855 | // we do all the things in flush |
| 805 | _ = module; | 856 | _ = module; |
| 806 | _ = exports; | 857 | _ = exports; |
| ... | @@ -842,10 +893,17 @@ pub fn deinit(self: *Plan9) void { | ... | @@ -842,10 +893,17 @@ pub fn deinit(self: *Plan9) void { |
| 842 | self.syms_index_free_list.deinit(gpa); | 893 | self.syms_index_free_list.deinit(gpa); |
| 843 | self.file_segments.deinit(gpa); | 894 | self.file_segments.deinit(gpa); |
| 844 | self.path_arena.deinit(); | 895 | self.path_arena.deinit(); |
| | 896 | self.decl_blocks.deinit(gpa); |
| | 897 | |
| | 898 | { |
| | 899 | var it = self.decls.iterator(); |
| | 900 | while (it.next()) |entry| { |
| | 901 | entry.value_ptr.exports.deinit(gpa); |
| | 902 | } |
| | 903 | self.decls.deinit(gpa); |
| | 904 | } |
| 845 | } | 905 | } |
| 846 | | 906 | |
| 847 | pub const Export = ?usize; | | |
| 848 | pub const base_tag = .plan9; | | |
| 849 | pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Plan9 { | 907 | pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Plan9 { |
| 850 | if (options.use_llvm) | 908 | if (options.use_llvm) |
| 851 | return error.LLVMBackendDoesNotSupportPlan9; | 909 | return error.LLVMBackendDoesNotSupportPlan9; |
| ... | @@ -911,20 +969,19 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { | ... | @@ -911,20 +969,19 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 911 | } | 969 | } |
| 912 | } | 970 | } |
| 913 | | 971 | |
| 914 | const mod = self.base.options.module.?; | | |
| 915 | | | |
| 916 | // write the data symbols | 972 | // write the data symbols |
| 917 | { | 973 | { |
| 918 | var it = self.data_decl_table.iterator(); | 974 | var it = self.data_decl_table.iterator(); |
| 919 | while (it.next()) |entry| { | 975 | while (it.next()) |entry| { |
| 920 | const decl_index = entry.key_ptr.*; | 976 | const decl_index = entry.key_ptr.*; |
| 921 | const decl = mod.declPtr(decl_index); | 977 | const decl_metadata = self.decls.get(decl_index).?; |
| 922 | const sym = self.syms.items[decl.link.plan9.sym_index.?]; | 978 | const decl_block = self.getDeclBlock(decl_metadata.index); |
| | 979 | const sym = self.syms.items[decl_block.sym_index.?]; |
| 923 | try self.writeSym(writer, sym); | 980 | try self.writeSym(writer, sym); |
| 924 | if (self.base.options.module.?.decl_exports.get(decl_index)) |exports| { | 981 | if (self.base.options.module.?.decl_exports.get(decl_index)) |exports| { |
| 925 | for (exports.items) |e| { | 982 | for (exports.items) |e| if (decl_metadata.getExport(self, e.options.name)) |exp_i| { |
| 926 | try self.writeSym(writer, self.syms.items[e.link.plan9.?]); | 983 | try self.writeSym(writer, self.syms.items[exp_i]); |
| 927 | } | 984 | }; |
| 928 | } | 985 | } |
| 929 | } | 986 | } |
| 930 | } | 987 | } |
| ... | @@ -943,16 +1000,17 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { | ... | @@ -943,16 +1000,17 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 943 | var submap_it = symidx_and_submap.functions.iterator(); | 1000 | var submap_it = symidx_and_submap.functions.iterator(); |
| 944 | while (submap_it.next()) |entry| { | 1001 | while (submap_it.next()) |entry| { |
| 945 | const decl_index = entry.key_ptr.*; | 1002 | const decl_index = entry.key_ptr.*; |
| 946 | const decl = mod.declPtr(decl_index); | 1003 | const decl_metadata = self.decls.get(decl_index).?; |
| 947 | const sym = self.syms.items[decl.link.plan9.sym_index.?]; | 1004 | const decl_block = self.getDeclBlock(decl_metadata.index); |
| | 1005 | const sym = self.syms.items[decl_block.sym_index.?]; |
| 948 | try self.writeSym(writer, sym); | 1006 | try self.writeSym(writer, sym); |
| 949 | if (self.base.options.module.?.decl_exports.get(decl_index)) |exports| { | 1007 | if (self.base.options.module.?.decl_exports.get(decl_index)) |exports| { |
| 950 | for (exports.items) |e| { | 1008 | for (exports.items) |e| if (decl_metadata.getExport(self, e.options.name)) |exp_i| { |
| 951 | const s = self.syms.items[e.link.plan9.?]; | 1009 | const s = self.syms.items[exp_i]; |
| 952 | if (mem.eql(u8, s.name, "_start")) | 1010 | if (mem.eql(u8, s.name, "_start")) |
| 953 | self.entry_val = s.value; | 1011 | self.entry_val = s.value; |
| 954 | try self.writeSym(writer, s); | 1012 | try self.writeSym(writer, s); |
| 955 | } | 1013 | }; |
| 956 | } | 1014 | } |
| 957 | } | 1015 | } |
| 958 | } | 1016 | } |
| ... | @@ -1004,3 +1062,11 @@ pub fn getDeclVAddr( | ... | @@ -1004,3 +1062,11 @@ pub fn getDeclVAddr( |
| 1004 | }); | 1062 | }); |
| 1005 | return undefined; | 1063 | return undefined; |
| 1006 | } | 1064 | } |
| | 1065 | |
| | 1066 | pub fn getDeclBlock(self: *const Plan9, index: DeclBlock.Index) DeclBlock { |
| | 1067 | return self.decl_blocks.items[index]; |
| | 1068 | } |
| | 1069 | |
| | 1070 | fn getDeclBlockPtr(self: *Plan9, index: DeclBlock.Index) *DeclBlock { |
| | 1071 | return &self.decl_blocks.items[index]; |
| | 1072 | } |