| ... | @@ -39,6 +39,11 @@ magic: u32, | ... | @@ -39,6 +39,11 @@ magic: u32, |
| 39 | entry_val: ?u64 = null, | 39 | entry_val: ?u64 = null, |
| 40 | | 40 | |
| 41 | got_len: usize = 0, | 41 | got_len: usize = 0, |
| | 42 | // A list of all the free got indexes, so when making a new decl |
| | 43 | // don't make a new one, just use one from here. |
| | 44 | got_index_free_list: std.ArrayListUnmanaged(u64) = .{}, |
| | 45 | |
| | 46 | syms_index_free_list: std.ArrayListUnmanaged(u64) = .{}, |
| 42 | | 47 | |
| 43 | const Bases = struct { | 48 | const Bases = struct { |
| 44 | text: u64, | 49 | text: u64, |
| ... | @@ -212,8 +217,12 @@ fn updateFinish(self: *Plan9, decl: *Module.Decl) !void { | ... | @@ -212,8 +217,12 @@ fn updateFinish(self: *Plan9, decl: *Module.Decl) !void { |
| 212 | if (decl.link.plan9.sym_index) |s| { | 217 | if (decl.link.plan9.sym_index) |s| { |
| 213 | self.syms.items[s] = sym; | 218 | self.syms.items[s] = sym; |
| 214 | } else { | 219 | } else { |
| 215 | try self.syms.append(self.base.allocator, sym); | 220 | if (self.syms_index_free_list.popOrNull()) |i| { |
| 216 | decl.link.plan9.sym_index = self.syms.items.len - 1; | 221 | decl.link.plan9.sym_index = i; |
| | 222 | } else { |
| | 223 | try self.syms.append(self.base.allocator, sym); |
| | 224 | decl.link.plan9.sym_index = self.syms.items.len - 1; |
| | 225 | } |
| 217 | } | 226 | } |
| 218 | } | 227 | } |
| 219 | | 228 | |
| ... | @@ -244,14 +253,12 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { | ... | @@ -244,14 +253,12 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 244 | | 253 | |
| 245 | const mod = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; | 254 | const mod = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 246 | | 255 | |
| 247 | // TODO I changed this assert from == to >= but this code all needs to be audited; see | 256 | assert(self.got_len == self.fn_decl_table.count() + self.data_decl_table.count() + self.got_index_free_list.items.len); |
| 248 | // the comment in `freeDecl`. | | |
| 249 | assert(self.got_len >= self.fn_decl_table.count() + self.data_decl_table.count()); | | |
| 250 | const got_size = self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8; | 257 | const got_size = self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8; |
| 251 | var got_table = try self.base.allocator.alloc(u8, got_size); | 258 | var got_table = try self.base.allocator.alloc(u8, got_size); |
| 252 | defer self.base.allocator.free(got_table); | 259 | defer self.base.allocator.free(got_table); |
| 253 | | 260 | |
| 254 | // + 2 for header, got, symbols | 261 | // + 3 for header, got, symbols |
| 255 | var iovecs = try self.base.allocator.alloc(std.os.iovec_const, self.fn_decl_table.count() + self.data_decl_table.count() + 3); | 262 | var iovecs = try self.base.allocator.alloc(std.os.iovec_const, self.fn_decl_table.count() + self.data_decl_table.count() + 3); |
| 256 | defer self.base.allocator.free(iovecs); | 263 | defer self.base.allocator.free(iovecs); |
| 257 | | 264 | |
| ... | @@ -380,18 +387,24 @@ fn addDeclExports( | ... | @@ -380,18 +387,24 @@ fn addDeclExports( |
| 380 | } | 387 | } |
| 381 | | 388 | |
| 382 | pub fn freeDecl(self: *Plan9, decl: *Module.Decl) void { | 389 | pub fn freeDecl(self: *Plan9, decl: *Module.Decl) void { |
| 383 | // TODO this is not the correct check for being function body, | | |
| 384 | // it could just be a function pointer. | | |
| 385 | // TODO audit the lifetimes of decls table entries. It's possible to get | 390 | // TODO audit the lifetimes of decls table entries. It's possible to get |
| 386 | // allocateDeclIndexes and then freeDecl without any updateDecl in between. | 391 | // allocateDeclIndexes and then freeDecl without any updateDecl in between. |
| 387 | // However that is planned to change, see the TODO comment in Module.zig | 392 | // However that is planned to change, see the TODO comment in Module.zig |
| 388 | // in the deleteUnusedDecl function. | 393 | // in the deleteUnusedDecl function. |
| 389 | const is_fn = (decl.ty.zigTypeTag() == .Fn); | 394 | const is_fn = (decl.val.tag() == .function); |
| 390 | if (is_fn) { | 395 | if (is_fn) { |
| 391 | _ = self.fn_decl_table.swapRemove(decl); | 396 | _ = self.fn_decl_table.swapRemove(decl); |
| 392 | } else { | 397 | } else { |
| 393 | _ = self.data_decl_table.swapRemove(decl); | 398 | _ = self.data_decl_table.swapRemove(decl); |
| 394 | } | 399 | } |
| | 400 | if (decl.link.plan9.got_index) |i| { |
| | 401 | // TODO: if this catch {} is triggered, an assertion in flushModule will be triggered, because got_index_free_list will have the wrong length |
| | 402 | self.got_index_free_list.append(self.base.allocator, i) catch {}; |
| | 403 | } |
| | 404 | if (decl.link.plan9.sym_index) |i| { |
| | 405 | self.syms_index_free_list.append(self.base.allocator, i) catch {}; |
| | 406 | self.syms.items[i] = undefined; |
| | 407 | } |
| 395 | } | 408 | } |
| 396 | | 409 | |
| 397 | pub fn updateDeclExports( | 410 | pub fn updateDeclExports( |
| ... | @@ -418,6 +431,8 @@ pub fn deinit(self: *Plan9) void { | ... | @@ -418,6 +431,8 @@ pub fn deinit(self: *Plan9) void { |
| 418 | } | 431 | } |
| 419 | self.data_decl_table.deinit(self.base.allocator); | 432 | self.data_decl_table.deinit(self.base.allocator); |
| 420 | self.syms.deinit(self.base.allocator); | 433 | self.syms.deinit(self.base.allocator); |
| | 434 | self.got_index_free_list.deinit(self.base.allocator); |
| | 435 | self.syms_index_free_list.deinit(self.base.allocator); |
| 421 | } | 436 | } |
| 422 | | 437 | |
| 423 | pub const Export = ?usize; | 438 | pub const Export = ?usize; |
| ... | @@ -481,7 +496,11 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { | ... | @@ -481,7 +496,11 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 481 | | 496 | |
| 482 | pub fn allocateDeclIndexes(self: *Plan9, decl: *Module.Decl) !void { | 497 | pub fn allocateDeclIndexes(self: *Plan9, decl: *Module.Decl) !void { |
| 483 | if (decl.link.plan9.got_index == null) { | 498 | if (decl.link.plan9.got_index == null) { |
| 484 | self.got_len += 1; | 499 | if (self.got_index_free_list.popOrNull()) |i| { |
| 485 | decl.link.plan9.got_index = self.got_len - 1; | 500 | decl.link.plan9.got_index = i; |
| | 501 | } else { |
| | 502 | self.got_len += 1; |
| | 503 | decl.link.plan9.got_index = self.got_len - 1; |
| | 504 | } |
| 486 | } | 505 | } |
| 487 | } | 506 | } |