| ... | @@ -22,7 +22,8 @@ const log = std.log.scoped(.link); | ... | @@ -22,7 +22,8 @@ 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 | const FnDeclOutput = struct { |
| 25 | code: []const u8, | 25 | /// this code is modified when relocated so it is mutable |
| | 26 | code: []u8, |
| 26 | /// this might have to be modified in the linker, so thats why its mutable | 27 | /// this might have to be modified in the linker, so thats why its mutable |
| 27 | lineinfo: []u8, | 28 | lineinfo: []u8, |
| 28 | start_line: u32, | 29 | start_line: u32, |
| ... | @@ -61,10 +62,34 @@ fn_decl_table: std.AutoArrayHashMapUnmanaged( | ... | @@ -61,10 +62,34 @@ fn_decl_table: std.AutoArrayHashMapUnmanaged( |
| 61 | *Module.File, | 62 | *Module.File, |
| 62 | struct { sym_index: u32, functions: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, FnDeclOutput) = .{} }, | 63 | struct { sym_index: u32, functions: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, FnDeclOutput) = .{} }, |
| 63 | ) = .{}, | 64 | ) = .{}, |
| 64 | data_decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, []const u8) = .{}, | 65 | /// the code is modified when relocated, so that is why it is mutable |
| 65 | | 66 | data_decl_table: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, []u8) = .{}, |
| | 67 | |
| | 68 | /// Table of unnamed constants associated with a parent `Decl`. |
| | 69 | /// We store them here so that we can free the constants whenever the `Decl` |
| | 70 | /// needs updating or is freed. |
| | 71 | /// |
| | 72 | /// For example, |
| | 73 | /// |
| | 74 | /// ```zig |
| | 75 | /// const Foo = struct{ |
| | 76 | /// a: u8, |
| | 77 | /// }; |
| | 78 | /// |
| | 79 | /// pub fn main() void { |
| | 80 | /// var foo = Foo{ .a = 1 }; |
| | 81 | /// _ = foo; |
| | 82 | /// } |
| | 83 | /// ``` |
| | 84 | /// |
| | 85 | /// value assigned to label `foo` is an unnamed constant belonging/associated |
| | 86 | /// with `Decl` `main`, and lives as long as that `Decl`. |
| | 87 | unnamed_const_atoms: UnnamedConstTable = .{}, |
| | 88 | |
| | 89 | relocs: std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Reloc)) = .{}, |
| 66 | hdr: aout.ExecHdr = undefined, | 90 | hdr: aout.ExecHdr = undefined, |
| 67 | | 91 | |
| | 92 | // relocs: std. |
| 68 | magic: u32, | 93 | magic: u32, |
| 69 | | 94 | |
| 70 | entry_val: ?u64 = null, | 95 | entry_val: ?u64 = null, |
| ... | @@ -76,12 +101,20 @@ got_index_free_list: std.ArrayListUnmanaged(usize) = .{}, | ... | @@ -76,12 +101,20 @@ got_index_free_list: std.ArrayListUnmanaged(usize) = .{}, |
| 76 | | 101 | |
| 77 | syms_index_free_list: std.ArrayListUnmanaged(usize) = .{}, | 102 | syms_index_free_list: std.ArrayListUnmanaged(usize) = .{}, |
| 78 | | 103 | |
| | 104 | const Reloc = struct { |
| | 105 | target: Module.Decl.Index, |
| | 106 | offset: u64, |
| | 107 | addend: u32, |
| | 108 | }; |
| | 109 | |
| 79 | const Bases = struct { | 110 | const Bases = struct { |
| 80 | text: u64, | 111 | text: u64, |
| 81 | /// the Global Offset Table starts at the beginning of the data section | 112 | /// the Global Offset Table starts at the beginning of the data section |
| 82 | data: u64, | 113 | data: u64, |
| 83 | }; | 114 | }; |
| 84 | | 115 | |
| | 116 | const UnnamedConstTable = std.AutoHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(struct { info: DeclBlock, code: []const u8 })); |
| | 117 | |
| 85 | fn getAddr(self: Plan9, addr: u64, t: aout.Sym.Type) u64 { | 118 | fn getAddr(self: Plan9, addr: u64, t: aout.Sym.Type) u64 { |
| 86 | return addr + switch (t) { | 119 | return addr + switch (t) { |
| 87 | .T, .t, .l, .L => self.bases.text, | 120 | .T, .t, .l, .L => self.bases.text, |
| ... | @@ -233,6 +266,7 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv | ... | @@ -233,6 +266,7 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv |
| 233 | | 266 | |
| 234 | const decl_index = func.owner_decl; | 267 | const decl_index = func.owner_decl; |
| 235 | const decl = module.declPtr(decl_index); | 268 | const decl = module.declPtr(decl_index); |
| | 269 | self.freeUnnamedConsts(decl_index); |
| 236 | | 270 | |
| 237 | try self.seeDecl(decl_index); | 271 | try self.seeDecl(decl_index); |
| 238 | log.debug("codegen decl {*} ({s})", .{ decl, decl.name }); | 272 | log.debug("codegen decl {*} ({s})", .{ decl, decl.name }); |
| ... | @@ -280,11 +314,62 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv | ... | @@ -280,11 +314,62 @@ pub fn updateFunc(self: *Plan9, module: *Module, func: *Module.Fn, air: Air, liv |
| 280 | } | 314 | } |
| 281 | | 315 | |
| 282 | pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.Index) !u32 { | 316 | pub fn lowerUnnamedConst(self: *Plan9, tv: TypedValue, decl_index: Module.Decl.Index) !u32 { |
| 283 | _ = self; | 317 | try self.seeDecl(decl_index); |
| 284 | _ = tv; | 318 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 285 | _ = decl_index; | 319 | defer code_buffer.deinit(); |
| 286 | log.debug("TODO lowerUnnamedConst for Plan9", .{}); | 320 | |
| 287 | return error.AnalysisFail; | 321 | const mod = self.base.options.module.?; |
| | 322 | const decl = mod.declPtr(decl_index); |
| | 323 | |
| | 324 | const gop = try self.unnamed_const_atoms.getOrPut(self.base.allocator, decl_index); |
| | 325 | if (!gop.found_existing) { |
| | 326 | gop.value_ptr.* = .{}; |
| | 327 | } |
| | 328 | const unnamed_consts = gop.value_ptr; |
| | 329 | |
| | 330 | const decl_name = try decl.getFullyQualifiedName(mod); |
| | 331 | defer self.base.allocator.free(decl_name); |
| | 332 | |
| | 333 | const index = unnamed_consts.items.len; |
| | 334 | // name is freed when the unnamed const is freed |
| | 335 | const name = try std.fmt.allocPrint(self.base.allocator, "__unnamed_{s}_{d}", .{ decl_name, index }); |
| | 336 | |
| | 337 | const sym_index = try self.allocateSymbolIndex(); |
| | 338 | |
| | 339 | const info: DeclBlock = .{ |
| | 340 | .type = .d, |
| | 341 | .offset = null, |
| | 342 | .sym_index = sym_index, |
| | 343 | .got_index = self.allocateGotIndex(), |
| | 344 | }; |
| | 345 | const sym: aout.Sym = .{ |
| | 346 | .value = undefined, |
| | 347 | .type = info.type, |
| | 348 | .name = name, |
| | 349 | }; |
| | 350 | self.syms.items[info.sym_index.?] = sym; |
| | 351 | |
| | 352 | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), tv, &code_buffer, .{ |
| | 353 | .none = {}, |
| | 354 | }, .{ |
| | 355 | .parent_atom_index = @enumToInt(decl_index), |
| | 356 | }); |
| | 357 | const code = switch (res) { |
| | 358 | .externally_managed => |x| x, |
| | 359 | .appended => code_buffer.items, |
| | 360 | .fail => |em| { |
| | 361 | decl.analysis = .codegen_failure; |
| | 362 | try mod.failed_decls.put(mod.gpa, decl_index, em); |
| | 363 | log.err("{s}", .{em.msg}); |
| | 364 | return error.AnalysisFail; |
| | 365 | }, |
| | 366 | }; |
| | 367 | // duped_code is freed when the unnamed const is freed |
| | 368 | var duped_code = try self.base.allocator.dupe(u8, code); |
| | 369 | errdefer self.base.allocator.free(duped_code); |
| | 370 | try unnamed_consts.append(self.base.allocator, .{ .info = info, .code = duped_code }); |
| | 371 | // we return the got_index to codegen so that it can reference to the place of the data in the got |
| | 372 | return @intCast(u32, info.got_index.?); |
| 288 | } | 373 | } |
| 289 | | 374 | |
| 290 | pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index) !void { | 375 | pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index) !void { |
| ... | @@ -302,18 +387,17 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index) | ... | @@ -302,18 +387,17 @@ pub fn updateDecl(self: *Plan9, module: *Module, decl_index: Module.Decl.Index) |
| 302 | | 387 | |
| 303 | try self.seeDecl(decl_index); | 388 | try self.seeDecl(decl_index); |
| 304 | | 389 | |
| 305 | log.debug("codegen decl {*} ({s})", .{ decl, decl.name }); | 390 | log.debug("codegen decl {*} ({s}) ({d})", .{ decl, decl.name, decl_index }); |
| 306 | | 391 | |
| 307 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); | 392 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 308 | defer code_buffer.deinit(); | 393 | defer code_buffer.deinit(); |
| 309 | const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val; | 394 | const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val; |
| 310 | // TODO we need the symbol index for symbol in the table of locals for the containing atom | 395 | // TODO we need the symbol index for symbol in the table of locals for the containing atom |
| 311 | const sym_index = decl.link.plan9.sym_index orelse 0; | | |
| 312 | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ | 396 | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ |
| 313 | .ty = decl.ty, | 397 | .ty = decl.ty, |
| 314 | .val = decl_val, | 398 | .val = decl_val, |
| 315 | }, &code_buffer, .{ .none = {} }, .{ | 399 | }, &code_buffer, .{ .none = {} }, .{ |
| 316 | .parent_atom_index = @intCast(u32, sym_index), | 400 | .parent_atom_index = @enumToInt(decl_index), |
| 317 | }); | 401 | }); |
| 318 | const code = switch (res) { | 402 | const code = switch (res) { |
| 319 | .externally_managed => |x| x, | 403 | .externally_managed => |x| x, |
| ... | @@ -347,12 +431,26 @@ fn updateFinish(self: *Plan9, decl: *Module.Decl) !void { | ... | @@ -347,12 +431,26 @@ fn updateFinish(self: *Plan9, decl: *Module.Decl) !void { |
| 347 | if (decl.link.plan9.sym_index) |s| { | 431 | if (decl.link.plan9.sym_index) |s| { |
| 348 | self.syms.items[s] = sym; | 432 | self.syms.items[s] = sym; |
| 349 | } else { | 433 | } else { |
| 350 | if (self.syms_index_free_list.popOrNull()) |i| { | 434 | const s = try self.allocateSymbolIndex(); |
| 351 | decl.link.plan9.sym_index = i; | 435 | decl.link.plan9.sym_index = s; |
| 352 | } else { | 436 | self.syms.items[s] = sym; |
| 353 | try self.syms.append(self.base.allocator, sym); | 437 | } |
| 354 | decl.link.plan9.sym_index = self.syms.items.len - 1; | 438 | } |
| 355 | } | 439 | |
| | 440 | fn allocateSymbolIndex(self: *Plan9) !usize { |
| | 441 | if (self.syms_index_free_list.popOrNull()) |i| { |
| | 442 | return i; |
| | 443 | } else { |
| | 444 | _ = try self.syms.addOne(self.base.allocator); |
| | 445 | return self.syms.items.len - 1; |
| | 446 | } |
| | 447 | } |
| | 448 | fn allocateGotIndex(self: *Plan9) usize { |
| | 449 | if (self.got_index_free_list.popOrNull()) |i| { |
| | 450 | return i; |
| | 451 | } else { |
| | 452 | self.got_len += 1; |
| | 453 | return self.got_len - 1; |
| 356 | } | 454 | } |
| 357 | } | 455 | } |
| 358 | | 456 | |
| ... | @@ -381,7 +479,8 @@ pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void { | ... | @@ -381,7 +479,8 @@ pub fn changeLine(l: *std.ArrayList(u8), delta_line: i32) !void { |
| 381 | } | 479 | } |
| 382 | } | 480 | } |
| 383 | | 481 | |
| 384 | fn declCount(self: *Plan9) usize { | 482 | // counts decls and unnamed consts |
| | 483 | fn atomCount(self: *Plan9) usize { |
| 385 | var fn_decl_count: usize = 0; | 484 | var fn_decl_count: usize = 0; |
| 386 | var itf_files = self.fn_decl_table.iterator(); | 485 | var itf_files = self.fn_decl_table.iterator(); |
| 387 | while (itf_files.next()) |ent| { | 486 | while (itf_files.next()) |ent| { |
| ... | @@ -389,7 +488,13 @@ fn declCount(self: *Plan9) usize { | ... | @@ -389,7 +488,13 @@ fn declCount(self: *Plan9) usize { |
| 389 | var submap = ent.value_ptr.functions; | 488 | var submap = ent.value_ptr.functions; |
| 390 | fn_decl_count += submap.count(); | 489 | fn_decl_count += submap.count(); |
| 391 | } | 490 | } |
| 392 | return self.data_decl_table.count() + fn_decl_count; | 491 | const data_decl_count = self.data_decl_table.count(); |
| | 492 | var unnamed_const_count: usize = 0; |
| | 493 | var it_unc = self.unnamed_const_atoms.iterator(); |
| | 494 | while (it_unc.next()) |unnamed_consts| { |
| | 495 | unnamed_const_count += unnamed_consts.value_ptr.items.len; |
| | 496 | } |
| | 497 | return data_decl_count + fn_decl_count + unnamed_const_count; |
| 393 | } | 498 | } |
| 394 | | 499 | |
| 395 | pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { | 500 | pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.Node) link.File.FlushError!void { |
| ... | @@ -411,13 +516,13 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -411,13 +516,13 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No |
| 411 | | 516 | |
| 412 | const mod = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; | 517 | const mod = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 413 | | 518 | |
| 414 | assert(self.got_len == self.declCount() + self.got_index_free_list.items.len); | 519 | assert(self.got_len == self.atomCount() + self.got_index_free_list.items.len); |
| 415 | const got_size = self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8; | 520 | const got_size = self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8; |
| 416 | var got_table = try self.base.allocator.alloc(u8, got_size); | 521 | var got_table = try self.base.allocator.alloc(u8, got_size); |
| 417 | defer self.base.allocator.free(got_table); | 522 | defer self.base.allocator.free(got_table); |
| 418 | | 523 | |
| 419 | // + 4 for header, got, symbols, linecountinfo | 524 | // + 4 for header, got, symbols, linecountinfo |
| 420 | var iovecs = try self.base.allocator.alloc(std.os.iovec_const, self.declCount() + 4); | 525 | var iovecs = try self.base.allocator.alloc(std.os.iovec_const, self.atomCount() + 4); |
| 421 | defer self.base.allocator.free(iovecs); | 526 | defer self.base.allocator.free(iovecs); |
| 422 | | 527 | |
| 423 | const file = self.base.file.?; | 528 | const file = self.base.file.?; |
| ... | @@ -509,6 +614,26 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -509,6 +614,26 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No |
| 509 | try self.addDeclExports(mod, decl, exports); | 614 | try self.addDeclExports(mod, decl, exports); |
| 510 | } | 615 | } |
| 511 | } | 616 | } |
| | 617 | // write the unnamed constants after the other data decls |
| | 618 | var it_unc = self.unnamed_const_atoms.iterator(); |
| | 619 | while (it_unc.next()) |unnamed_consts| { |
| | 620 | for (unnamed_consts.value_ptr.items) |*unnamed_const| { |
| | 621 | const code = unnamed_const.code; |
| | 622 | log.debug("write unnamed const: ({s})", .{self.syms.items[unnamed_const.info.sym_index.?].name}); |
| | 623 | foff += code.len; |
| | 624 | iovecs[iovecs_i] = .{ .iov_base = code.ptr, .iov_len = code.len }; |
| | 625 | iovecs_i += 1; |
| | 626 | const off = self.getAddr(data_i, .d); |
| | 627 | data_i += code.len; |
| | 628 | unnamed_const.info.offset = off; |
| | 629 | if (!self.sixtyfour_bit) { |
| | 630 | mem.writeInt(u32, got_table[unnamed_const.info.got_index.? * 4 ..][0..4], @intCast(u32, off), self.base.options.target.cpu.arch.endian()); |
| | 631 | } else { |
| | 632 | mem.writeInt(u64, got_table[unnamed_const.info.got_index.? * 8 ..][0..8], off, self.base.options.target.cpu.arch.endian()); |
| | 633 | } |
| | 634 | self.syms.items[unnamed_const.info.sym_index.?].value = off; |
| | 635 | } |
| | 636 | } |
| 512 | // edata symbol | 637 | // edata symbol |
| 513 | self.syms.items[0].value = self.getAddr(data_i, .b); | 638 | self.syms.items[0].value = self.getAddr(data_i, .b); |
| 514 | } | 639 | } |
| ... | @@ -518,7 +643,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -518,7 +643,7 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No |
| 518 | try self.writeSyms(&sym_buf); | 643 | try self.writeSyms(&sym_buf); |
| 519 | const syms = sym_buf.toOwnedSlice(); | 644 | const syms = sym_buf.toOwnedSlice(); |
| 520 | defer self.base.allocator.free(syms); | 645 | defer self.base.allocator.free(syms); |
| 521 | assert(2 + self.declCount() == iovecs_i); // we didn't write all the decls | 646 | assert(2 + self.atomCount() == iovecs_i); // we didn't write all the decls |
| 522 | iovecs[iovecs_i] = .{ .iov_base = syms.ptr, .iov_len = syms.len }; | 647 | iovecs[iovecs_i] = .{ .iov_base = syms.ptr, .iov_len = syms.len }; |
| 523 | iovecs_i += 1; | 648 | iovecs_i += 1; |
| 524 | iovecs[iovecs_i] = .{ .iov_base = linecountinfo.items.ptr, .iov_len = linecountinfo.items.len }; | 649 | iovecs[iovecs_i] = .{ .iov_base = linecountinfo.items.ptr, .iov_len = linecountinfo.items.len }; |
| ... | @@ -539,6 +664,42 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -539,6 +664,42 @@ pub fn flushModule(self: *Plan9, comp: *Compilation, prog_node: *std.Progress.No |
| 539 | if (self.sixtyfour_bit) { | 664 | if (self.sixtyfour_bit) { |
| 540 | mem.writeIntSliceBig(u64, hdr_buf[32..40], self.entry_val.?); | 665 | mem.writeIntSliceBig(u64, hdr_buf[32..40], self.entry_val.?); |
| 541 | } | 666 | } |
| | 667 | // perform the relocs |
| | 668 | { |
| | 669 | var it = self.relocs.iterator(); |
| | 670 | while (it.next()) |kv| { |
| | 671 | const source_decl_index = kv.key_ptr.*; |
| | 672 | const source_decl = mod.declPtr(source_decl_index); |
| | 673 | for (kv.value_ptr.items) |reloc| { |
| | 674 | const target_decl_index = reloc.target; |
| | 675 | const target_decl = mod.declPtr(target_decl_index); |
| | 676 | const target_decl_offset = target_decl.link.plan9.offset.?; |
| | 677 | |
| | 678 | const offset = reloc.offset; |
| | 679 | const addend = reloc.addend; |
| | 680 | |
| | 681 | log.debug("relocating the address of '{s}' + {d} into '{s}' + {d}", .{ target_decl.name, addend, source_decl.name, offset }); |
| | 682 | |
| | 683 | const code = blk: { |
| | 684 | const is_fn = source_decl.ty.zigTypeTag() == .Fn; |
| | 685 | if (is_fn) { |
| | 686 | const table = self.fn_decl_table.get(source_decl.getFileScope()).?.functions; |
| | 687 | const output = table.get(source_decl_index).?; |
| | 688 | break :blk output.code; |
| | 689 | } else { |
| | 690 | const code = self.data_decl_table.get(source_decl_index).?; |
| | 691 | break :blk code; |
| | 692 | } |
| | 693 | }; |
| | 694 | |
| | 695 | if (!self.sixtyfour_bit) { |
| | 696 | mem.writeInt(u32, code[@intCast(usize, offset)..][0..4], @intCast(u32, target_decl_offset + addend), self.base.options.target.cpu.arch.endian()); |
| | 697 | } else { |
| | 698 | mem.writeInt(u64, code[@intCast(usize, offset)..][0..8], target_decl_offset + addend, self.base.options.target.cpu.arch.endian()); |
| | 699 | } |
| | 700 | } |
| | 701 | } |
| | 702 | } |
| 542 | // write it all! | 703 | // write it all! |
| 543 | try file.pwritevAll(iovecs, 0); | 704 | try file.pwritevAll(iovecs, 0); |
| 544 | } | 705 | } |
| ... | @@ -599,18 +760,29 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void { | ... | @@ -599,18 +760,29 @@ pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void { |
| 599 | self.syms_index_free_list.append(self.base.allocator, i) catch {}; | 760 | self.syms_index_free_list.append(self.base.allocator, i) catch {}; |
| 600 | self.syms.items[i] = aout.Sym.undefined_symbol; | 761 | self.syms.items[i] = aout.Sym.undefined_symbol; |
| 601 | } | 762 | } |
| | 763 | self.freeUnnamedConsts(decl_index); |
| | 764 | { |
| | 765 | const relocs = self.relocs.getPtr(decl_index) orelse return; |
| | 766 | relocs.clearAndFree(self.base.allocator); |
| | 767 | assert(self.relocs.remove(decl_index)); |
| | 768 | } |
| | 769 | } |
| | 770 | fn freeUnnamedConsts(self: *Plan9, decl_index: Module.Decl.Index) void { |
| | 771 | const unnamed_consts = self.unnamed_const_atoms.getPtr(decl_index) orelse return; |
| | 772 | for (unnamed_consts.items) |c| { |
| | 773 | self.base.allocator.free(self.syms.items[c.info.sym_index.?].name); |
| | 774 | self.base.allocator.free(c.code); |
| | 775 | self.syms.items[c.info.sym_index.?] = aout.Sym.undefined_symbol; |
| | 776 | self.syms_index_free_list.append(self.base.allocator, c.info.sym_index.?) catch {}; |
| | 777 | } |
| | 778 | unnamed_consts.clearAndFree(self.base.allocator); |
| 602 | } | 779 | } |
| 603 | | 780 | |
| 604 | pub fn seeDecl(self: *Plan9, decl_index: Module.Decl.Index) !void { | 781 | pub fn seeDecl(self: *Plan9, decl_index: Module.Decl.Index) !void { |
| 605 | const mod = self.base.options.module.?; | 782 | const mod = self.base.options.module.?; |
| 606 | const decl = mod.declPtr(decl_index); | 783 | const decl = mod.declPtr(decl_index); |
| 607 | if (decl.link.plan9.got_index == null) { | 784 | if (decl.link.plan9.got_index == null) { |
| 608 | if (self.got_index_free_list.popOrNull()) |i| { | 785 | decl.link.plan9.got_index = self.allocateGotIndex(); |
| 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 | } | | |
| 614 | } | 786 | } |
| 615 | } | 787 | } |
| 616 | | 788 | |
| ... | @@ -627,6 +799,19 @@ pub fn updateDeclExports( | ... | @@ -627,6 +799,19 @@ pub fn updateDeclExports( |
| 627 | } | 799 | } |
| 628 | pub fn deinit(self: *Plan9) void { | 800 | pub fn deinit(self: *Plan9) void { |
| 629 | const gpa = self.base.allocator; | 801 | const gpa = self.base.allocator; |
| | 802 | { |
| | 803 | var it = self.relocs.valueIterator(); |
| | 804 | while (it.next()) |relocs| { |
| | 805 | relocs.deinit(self.base.allocator); |
| | 806 | } |
| | 807 | self.relocs.deinit(self.base.allocator); |
| | 808 | } |
| | 809 | // free the unnamed consts |
| | 810 | var it_unc = self.unnamed_const_atoms.iterator(); |
| | 811 | while (it_unc.next()) |kv| { |
| | 812 | self.freeUnnamedConsts(kv.key_ptr.*); |
| | 813 | } |
| | 814 | self.unnamed_const_atoms.deinit(gpa); |
| 630 | var itf_files = self.fn_decl_table.iterator(); | 815 | var itf_files = self.fn_decl_table.iterator(); |
| 631 | while (itf_files.next()) |ent| { | 816 | while (itf_files.next()) |ent| { |
| 632 | // get the submap | 817 | // get the submap |
| ... | @@ -771,12 +956,18 @@ pub fn allocateDeclIndexes(self: *Plan9, decl_index: Module.Decl.Index) !void { | ... | @@ -771,12 +956,18 @@ pub fn allocateDeclIndexes(self: *Plan9, decl_index: Module.Decl.Index) !void { |
| 771 | _ = self; | 956 | _ = self; |
| 772 | _ = decl_index; | 957 | _ = decl_index; |
| 773 | } | 958 | } |
| | 959 | /// Must be called only after a successful call to `updateDecl`. |
| | 960 | pub fn updateDeclLineNumber(self: *Plan9, mod: *Module, decl: *const Module.Decl) !void { |
| | 961 | _ = self; |
| | 962 | _ = mod; |
| | 963 | _ = decl; |
| | 964 | } |
| | 965 | |
| 774 | pub fn getDeclVAddr( | 966 | pub fn getDeclVAddr( |
| 775 | self: *Plan9, | 967 | self: *Plan9, |
| 776 | decl_index: Module.Decl.Index, | 968 | decl_index: Module.Decl.Index, |
| 777 | reloc_info: link.File.RelocInfo, | 969 | reloc_info: link.File.RelocInfo, |
| 778 | ) !u64 { | 970 | ) !u64 { |
| 779 | _ = reloc_info; | | |
| 780 | const mod = self.base.options.module.?; | 971 | const mod = self.base.options.module.?; |
| 781 | const decl = mod.declPtr(decl_index); | 972 | const decl = mod.declPtr(decl_index); |
| 782 | if (decl.ty.zigTypeTag() == .Fn) { | 973 | if (decl.ty.zigTypeTag() == .Fn) { |
| ... | @@ -790,7 +981,6 @@ pub fn getDeclVAddr( | ... | @@ -790,7 +981,6 @@ pub fn getDeclVAddr( |
| 790 | start += entry.value_ptr.code.len; | 981 | start += entry.value_ptr.code.len; |
| 791 | } | 982 | } |
| 792 | } | 983 | } |
| 793 | unreachable; | | |
| 794 | } else { | 984 | } else { |
| 795 | var start = self.bases.data + self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8; | 985 | var start = self.bases.data + self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8; |
| 796 | var it = self.data_decl_table.iterator(); | 986 | var it = self.data_decl_table.iterator(); |
| ... | @@ -798,6 +988,16 @@ pub fn getDeclVAddr( | ... | @@ -798,6 +988,16 @@ pub fn getDeclVAddr( |
| 798 | if (decl_index == kv.key_ptr.*) return start; | 988 | if (decl_index == kv.key_ptr.*) return start; |
| 799 | start += kv.value_ptr.len; | 989 | start += kv.value_ptr.len; |
| 800 | } | 990 | } |
| 801 | unreachable; | | |
| 802 | } | 991 | } |
| | 992 | // the parent_atom_index in this case is just the decl_index of the parent |
| | 993 | const gop = try self.relocs.getOrPut(self.base.allocator, @intToEnum(Module.Decl.Index, reloc_info.parent_atom_index)); |
| | 994 | if (!gop.found_existing) { |
| | 995 | gop.value_ptr.* = .{}; |
| | 996 | } |
| | 997 | try gop.value_ptr.append(self.base.allocator, .{ |
| | 998 | .target = decl_index, |
| | 999 | .offset = reloc_info.offset, |
| | 1000 | .addend = reloc_info.addend, |
| | 1001 | }); |
| | 1002 | return undefined; |
| 803 | } | 1003 | } |