authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-02-01 11:12:53+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-02-01 11:12:53+01:00
logb3277c893691c462ec2e82577a78e7baafb42bf6
tree05c850c81f99ce1339c2fa3c045367c27702edd8
parent9fdc32c96e3961ae2f5287483c9638051df34180

link: make Plan9 atoms fully owned by the linker


8 files changed, 170 insertions(+), 100 deletions(-)

src/Module.zig+2-2
...@@ -5277,7 +5277,7 @@ pub fn clearDecl(...@@ -5277,7 +5277,7 @@ pub fn clearDecl(
5277 .coff => .{ .coff = {} },5277 .coff => .{ .coff = {} },
5278 .elf => .{ .elf = {} },5278 .elf => .{ .elf = {} },
5279 .macho => .{ .macho = {} },5279 .macho => .{ .macho = {} },
5280 .plan9 => .{ .plan9 = link.File.Plan9.DeclBlock.empty },5280 .plan9 => .{ .plan9 = {} },
5281 .c => .{ .c = {} },5281 .c => .{ .c = {} },
5282 .wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },5282 .wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },
5283 .spirv => .{ .spirv = {} },5283 .spirv => .{ .spirv = {} },
...@@ -5697,7 +5697,7 @@ pub fn allocateNewDecl(...@@ -5697,7 +5697,7 @@ pub fn allocateNewDecl(
5697 .coff => .{ .coff = {} },5697 .coff => .{ .coff = {} },
5698 .elf => .{ .elf = {} },5698 .elf => .{ .elf = {} },
5699 .macho => .{ .macho = {} },5699 .macho => .{ .macho = {} },
5700 .plan9 => .{ .plan9 = link.File.Plan9.DeclBlock.empty },5700 .plan9 => .{ .plan9 = {} },
5701 .c => .{ .c = {} },5701 .c => .{ .c = {} },
5702 .wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },5702 .wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },
5703 .spirv => .{ .spirv = {} },5703 .spirv => .{ .spirv = {} },
src/Sema.zig+1-1
...@@ -5568,7 +5568,7 @@ pub fn analyzeExport(...@@ -5568,7 +5568,7 @@ pub fn analyzeExport(
5568 .coff => .{ .coff = {} },5568 .coff => .{ .coff = {} },
5569 .elf => .{ .elf = {} },5569 .elf => .{ .elf = {} },
5570 .macho => .{ .macho = {} },5570 .macho => .{ .macho = {} },
5571 .plan9 => .{ .plan9 = null },5571 .plan9 => .{ .plan9 = {} },
5572 .c => .{ .c = {} },5572 .c => .{ .c = {} },
5573 .wasm => .{ .wasm = .{} },5573 .wasm => .{ .wasm = .{} },
5574 .spirv => .{ .spirv = {} },5574 .spirv => .{ .spirv = {} },
src/arch/aarch64/CodeGen.zig+6-5
...@@ -4307,7 +4307,6 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4307,7 +4307,6 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4307 if (self.air.value(callee)) |func_value| {4307 if (self.air.value(callee)) |func_value| {
4308 if (func_value.castTag(.function)) |func_payload| {4308 if (func_value.castTag(.function)) |func_payload| {
4309 const func = func_payload.data;4309 const func = func_payload.data;
4310 const fn_owner_decl = mod.declPtr(func.owner_decl);
43114310
4312 if (self.bin_file.cast(link.File.Elf)) |elf_file| {4311 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
4313 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);4312 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
...@@ -4333,11 +4332,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4333,11 +4332,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4333 },4332 },
4334 });4333 });
4335 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {4334 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
4336 try p9.seeDecl(func.owner_decl);4335 const decl_block_index = try p9.seeDecl(func.owner_decl);
4336 const decl_block = p9.getDeclBlock(decl_block_index);
4337 const ptr_bits = self.target.cpu.arch.ptrBitWidth();4337 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
4338 const ptr_bytes: u64 = @divExact(ptr_bits, 8);4338 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
4339 const got_addr = p9.bases.data;4339 const got_addr = p9.bases.data;
4340 const got_index = fn_owner_decl.link.plan9.got_index.?;4340 const got_index = decl_block.got_index.?;
4341 const fn_got_addr = got_addr + got_index * ptr_bytes;4341 const fn_got_addr = got_addr + got_index * ptr_bytes;
4342 try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = fn_got_addr });4342 try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = fn_got_addr });
4343 } else unreachable;4343 } else unreachable;
...@@ -6166,8 +6166,9 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne...@@ -6166,8 +6166,9 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
6166 .sym_index = sym_index,6166 .sym_index = sym_index,
6167 } };6167 } };
6168 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {6168 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
6169 try p9.seeDecl(decl_index);6169 const decl_block_index = try p9.seeDecl(decl_index);
6170 const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;6170 const decl_block = p9.getDeclBlock(decl_block_index);
6171 const got_addr = p9.bases.data + decl_block.got_index.? * ptr_bytes;
6171 return MCValue{ .memory = got_addr };6172 return MCValue{ .memory = got_addr };
6172 } else {6173 } else {
6173 return self.fail("TODO codegen non-ELF const Decl pointer", .{});6174 return self.fail("TODO codegen non-ELF const Decl pointer", .{});
src/arch/arm/CodeGen.zig+3-2
...@@ -6091,8 +6091,9 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne...@@ -6091,8 +6091,9 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
6091 } else if (self.bin_file.cast(link.File.Coff)) |_| {6091 } else if (self.bin_file.cast(link.File.Coff)) |_| {
6092 return self.fail("TODO codegen COFF const Decl pointer", .{});6092 return self.fail("TODO codegen COFF const Decl pointer", .{});
6093 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {6093 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
6094 try p9.seeDecl(decl_index);6094 const decl_block_index = try p9.seeDecl(decl_index);
6095 const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;6095 const decl_block = p9.getDeclBlock(decl_block_index);
6096 const got_addr = p9.bases.data + decl_block.got_index.? * ptr_bytes;
6096 return MCValue{ .memory = got_addr };6097 return MCValue{ .memory = got_addr };
6097 } else {6098 } else {
6098 return self.fail("TODO codegen non-ELF const Decl pointer", .{});6099 return self.fail("TODO codegen non-ELF const Decl pointer", .{});
src/arch/riscv64/CodeGen.zig+3-2
...@@ -2558,8 +2558,9 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne...@@ -2558,8 +2558,9 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
2558 } else if (self.bin_file.cast(link.File.Coff)) |_| {2558 } else if (self.bin_file.cast(link.File.Coff)) |_| {
2559 return self.fail("TODO codegen COFF const Decl pointer", .{});2559 return self.fail("TODO codegen COFF const Decl pointer", .{});
2560 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {2560 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
2561 try p9.seeDecl(decl_index);2561 const decl_block_index = try p9.seeDecl(decl_index);
2562 const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;2562 const decl_block = p9.getDeclBlock(decl_block_index);
2563 const got_addr = p9.bases.data + decl_block.got_index.? * ptr_bytes;
2563 return MCValue{ .memory = got_addr };2564 return MCValue{ .memory = got_addr };
2564 } else {2565 } else {
2565 return self.fail("TODO codegen non-ELF const Decl pointer", .{});2566 return self.fail("TODO codegen non-ELF const Decl pointer", .{});
src/arch/x86_64/CodeGen.zig+6-5
...@@ -3996,7 +3996,6 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -3996,7 +3996,6 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
3996 if (self.air.value(callee)) |func_value| {3996 if (self.air.value(callee)) |func_value| {
3997 if (func_value.castTag(.function)) |func_payload| {3997 if (func_value.castTag(.function)) |func_payload| {
3998 const func = func_payload.data;3998 const func = func_payload.data;
3999 const fn_owner_decl = mod.declPtr(func.owner_decl);
40003999
4001 if (self.bin_file.cast(link.File.Elf)) |elf_file| {4000 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
4002 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);4001 const atom_index = try elf_file.getOrCreateAtomForDecl(func.owner_decl);
...@@ -4042,11 +4041,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4042,11 +4041,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4042 .data = undefined,4041 .data = undefined,
4043 });4042 });
4044 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {4043 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
4045 try p9.seeDecl(func.owner_decl);4044 const decl_block_index = try p9.seeDecl(func.owner_decl);
4045 const decl_block = p9.getDeclBlock(decl_block_index);
4046 const ptr_bits = self.target.cpu.arch.ptrBitWidth();4046 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
4047 const ptr_bytes: u64 = @divExact(ptr_bits, 8);4047 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
4048 const got_addr = p9.bases.data;4048 const got_addr = p9.bases.data;
4049 const got_index = fn_owner_decl.link.plan9.got_index.?;4049 const got_index = decl_block.got_index.?;
4050 const fn_got_addr = got_addr + got_index * ptr_bytes;4050 const fn_got_addr = got_addr + got_index * ptr_bytes;
4051 _ = try self.addInst(.{4051 _ = try self.addInst(.{
4052 .tag = .call,4052 .tag = .call,
...@@ -6739,8 +6739,9 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne...@@ -6739,8 +6739,9 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
6739 .sym_index = sym_index,6739 .sym_index = sym_index,
6740 } };6740 } };
6741 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {6741 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
6742 try p9.seeDecl(decl_index);6742 const decl_block_index = try p9.seeDecl(decl_index);
6743 const got_addr = p9.bases.data + decl.link.plan9.got_index.? * ptr_bytes;6743 const decl_block = p9.getDeclBlock(decl_block_index);
6744 const got_addr = p9.bases.data + decl_block.got_index.? * ptr_bytes;
6744 return MCValue{ .memory = got_addr };6745 return MCValue{ .memory = got_addr };
6745 } else {6746 } else {
6746 return self.fail("TODO codegen non-ELF const Decl pointer", .{});6747 return self.fail("TODO codegen non-ELF const Decl pointer", .{});
src/link.zig+2-2
...@@ -265,7 +265,7 @@ pub const File = struct {...@@ -265,7 +265,7 @@ pub const File = struct {
265 elf: void,265 elf: void,
266 coff: void,266 coff: void,
267 macho: void,267 macho: void,
268 plan9: Plan9.DeclBlock,268 plan9: void,
269 c: void,269 c: void,
270 wasm: Wasm.DeclBlock,270 wasm: Wasm.DeclBlock,
271 spirv: void,271 spirv: void,
...@@ -287,7 +287,7 @@ pub const File = struct {...@@ -287,7 +287,7 @@ pub const File = struct {
287 elf: void,287 elf: void,
288 coff: void,288 coff: void,
289 macho: void,289 macho: void,
290 plan9: Plan9.Export,290 plan9: void,
291 c: void,291 c: void,
292 wasm: Wasm.Export,292 wasm: Wasm.Export,
293 spirv: void,293 spirv: void,
src/link/Plan9.zig+147-81
...@@ -21,14 +21,7 @@ const Allocator = std.mem.Allocator;...@@ -21,14 +21,7 @@ const Allocator = std.mem.Allocator;
21const log = std.log.scoped(.link);21const log = std.log.scoped(.link);
22const assert = std.debug.assert;22const assert = std.debug.assert;
2323
24const FnDeclOutput = struct {24pub 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};
3225
33base: link.File,26base: link.File,
34sixtyfour_bit: bool,27sixtyfour_bit: bool,
...@@ -101,6 +94,9 @@ got_index_free_list: std.ArrayListUnmanaged(usize) = .{},...@@ -101,6 +94,9 @@ got_index_free_list: std.ArrayListUnmanaged(usize) = .{},
10194
102syms_index_free_list: std.ArrayListUnmanaged(usize) = .{},95syms_index_free_list: std.ArrayListUnmanaged(usize) = .{},
10396
97decl_blocks: std.ArrayListUnmanaged(DeclBlock) = .{},
98decls: std.AutoHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{},
99
104const Reloc = struct {100const 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 {
115111
116const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(struct { info: DeclBlock, code: []const u8 }));112const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(struct { info: DeclBlock, code: []const u8 }));
117113
114pub const PtrWidth = enum { p32, p64 };
115
116pub 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
128const 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
141const 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
118fn getAddr(self: Plan9, addr: u64, t: aout.Sym.Type) u64 {150fn 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}
129161
130pub 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
146pub fn defaultBaseAddrs(arch: std.Target.Cpu.Arch) Bases {162pub 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}
166182
167pub const PtrWidth = enum { p32, p64 };
168
169pub fn createEmpty(gpa: Allocator, options: link.Options) !*Plan9 {183pub 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);
273287
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 });
276290
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}
318332
319pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.Index) !u32 {333pub 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();
323337
...@@ -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 }
389403
390 try self.seeDecl(decl_index);404 _ = try self.seeDecl(decl_index);
391405
392 log.debug("codegen decl {*} ({s}) ({d})", .{ decl, decl.name, decl_index });406 log.debug("codegen decl {*} ({s}) ({d})", .{ decl, decl.name, decl_index });
393407
...@@ -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}
420fn updateFinish(self: *Plan9, decl: *Module.Decl) !void {434fn 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 metadata441 // write the internal linker metadata
425 decl.link.plan9.type = sym_t;442 decl_block.type = sym_t;
426 // write the symbol443 // write the symbol
427 // we already have the got index444 // 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 flushModule446 .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 };
433450
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 });
603622
...@@ -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 decls639 // 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.?;
680700
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
709fn addDeclExports(729fn 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 sections739 // 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 };
728756
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 length792 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}
788821
789pub fn seeDecl(self: *Plan9, decl_index: Module.Decl.Index) !void {822fn 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
835pub 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}
796847
797pub fn updateDeclExports(848pub 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 flush855 // 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}
846906
847pub const Export = ?usize;
848pub const base_tag = .plan9;
849pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Options) !*Plan9 {907pub 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 }
913971
914 const mod = self.base.options.module.?;
915
916 // write the data symbols972 // 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
1066pub fn getDeclBlock(self: *const Plan9, index: DeclBlock.Index) DeclBlock {
1067 return self.decl_blocks.items[index];
1068}
1069
1070fn getDeclBlockPtr(self: *Plan9, index: DeclBlock.Index) *DeclBlock {
1071 return &self.decl_blocks.items[index];
1072}