| author | |
| committer | |
| log | a8987291390d80ad9e2bb45ba225313a108eed0b |
| tree | 47ff80a5d12a9f57808a83d5f965269686893289 |
| parent | b25efb86e1b1b2a9e8aa269bf83b717d54f7e276 |
4 files changed, 5 insertions(+), 66 deletions(-)
src/Module.zig-26| ... | @@ -4585,7 +4585,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4585,7 +4585,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4585 | // We don't fully codegen the decl until later, but we do need to reserve a global | 4585 | // We don't fully codegen the decl until later, but we do need to reserve a global |
| 4586 | // offset table index for it. This allows us to codegen decls out of dependency | 4586 | // offset table index for it. This allows us to codegen decls out of dependency |
| 4587 | // order, increasing how many computations can be done in parallel. | 4587 | // order, increasing how many computations can be done in parallel. |
| 4588 | try mod.comp.bin_file.allocateDeclIndexes(decl_index); | ||
| 4589 | try mod.comp.work_queue.writeItem(.{ .codegen_func = func }); | 4588 | try mod.comp.work_queue.writeItem(.{ .codegen_func = func }); |
| 4590 | if (type_changed and mod.emit_h != null) { | 4589 | if (type_changed and mod.emit_h != null) { |
| 4591 | try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index }); | 4590 | try mod.comp.work_queue.writeItem(.{ .emit_h_decl = decl_index }); |
| ... | @@ -4697,7 +4696,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { | ... | @@ -4697,7 +4696,6 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool { |
| 4697 | // codegen backend wants full access to the Decl Type. | 4696 | // codegen backend wants full access to the Decl Type. |
| 4698 | try sema.resolveTypeFully(decl.ty); | 4697 | try sema.resolveTypeFully(decl.ty); |
| 4699 | 4698 | ||
| 4700 | try mod.comp.bin_file.allocateDeclIndexes(decl_index); | ||
| 4701 | try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index }); | 4699 | try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index }); |
| 4702 | 4700 | ||
| 4703 | if (type_changed and mod.emit_h != null) { | 4701 | if (type_changed and mod.emit_h != null) { |
| ... | @@ -5315,29 +5313,6 @@ pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void { | ... | @@ -5315,29 +5313,6 @@ pub fn deleteUnusedDecl(mod: *Module, decl_index: Decl.Index) void { |
| 5315 | const decl = mod.declPtr(decl_index); | 5313 | const decl = mod.declPtr(decl_index); |
| 5316 | log.debug("deleteUnusedDecl {d} ({s})", .{ decl_index, decl.name }); | 5314 | log.debug("deleteUnusedDecl {d} ({s})", .{ decl_index, decl.name }); |
| 5317 | 5315 | ||
| 5318 | // TODO: remove `allocateDeclIndexes` and make the API that the linker backends | ||
| 5319 | // are required to notice the first time `updateDecl` happens and keep track | ||
| 5320 | // of it themselves. However they can rely on getting a `freeDecl` call if any | ||
| 5321 | // `updateDecl` or `updateFunc` calls happen. This will allow us to avoid any call | ||
| 5322 | // into the linker backend here, since the linker backend will never have been told | ||
| 5323 | // about the Decl in the first place. | ||
| 5324 | // Until then, we did call `allocateDeclIndexes` on this anonymous Decl and so we | ||
| 5325 | // must call `freeDecl` in the linker backend now. | ||
| 5326 | switch (mod.comp.bin_file.tag) { | ||
| 5327 | .coff, | ||
| 5328 | .elf, | ||
| 5329 | .macho, | ||
| 5330 | .c, | ||
| 5331 | .wasm, | ||
| 5332 | => {}, // this linker backend has already migrated to the new API | ||
| 5333 | |||
| 5334 | else => if (decl.has_tv) { | ||
| 5335 | if (decl.ty.isFnOrHasRuntimeBits()) { | ||
| 5336 | mod.comp.bin_file.freeDecl(decl_index); | ||
| 5337 | } | ||
| 5338 | }, | ||
| 5339 | } | ||
| 5340 | |||
| 5341 | assert(!mod.declIsRoot(decl_index)); | 5316 | assert(!mod.declIsRoot(decl_index)); |
| 5342 | assert(decl.src_namespace.anon_decls.swapRemove(decl_index)); | 5317 | assert(decl.src_namespace.anon_decls.swapRemove(decl_index)); |
| 5343 | 5318 | ||
| ... | @@ -5822,7 +5797,6 @@ pub fn initNewAnonDecl( | ... | @@ -5822,7 +5797,6 @@ pub fn initNewAnonDecl( |
| 5822 | // the Decl will be garbage collected by the `codegen_decl` task instead of sent | 5797 | // the Decl will be garbage collected by the `codegen_decl` task instead of sent |
| 5823 | // to the linker. | 5798 | // to the linker. |
| 5824 | if (typed_value.ty.isFnOrHasRuntimeBits()) { | 5799 | if (typed_value.ty.isFnOrHasRuntimeBits()) { |
| 5825 | try mod.comp.bin_file.allocateDeclIndexes(new_decl_index); | ||
| 5826 | try mod.comp.anon_work_queue.writeItem(.{ .codegen_decl = new_decl_index }); | 5800 | try mod.comp.anon_work_queue.writeItem(.{ .codegen_decl = new_decl_index }); |
| 5827 | } | 5801 | } |
| 5828 | } | 5802 | } |
src/Sema.zig-1| ... | @@ -7510,7 +7510,6 @@ fn resolveGenericInstantiationType( | ... | @@ -7510,7 +7510,6 @@ fn resolveGenericInstantiationType( |
| 7510 | // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field | 7510 | // Queue up a `codegen_func` work item for the new Fn. The `comptime_args` field |
| 7511 | // will be populated, ensuring it will have `analyzeBody` called with the ZIR | 7511 | // will be populated, ensuring it will have `analyzeBody` called with the ZIR |
| 7512 | // parameters mapped appropriately. | 7512 | // parameters mapped appropriately. |
| 7513 | try mod.comp.bin_file.allocateDeclIndexes(new_decl_index); | ||
| 7514 | try mod.comp.work_queue.writeItem(.{ .codegen_func = new_func }); | 7513 | try mod.comp.work_queue.writeItem(.{ .codegen_func = new_func }); |
| 7515 | return new_func; | 7514 | return new_func; |
| 7516 | } | 7515 | } |
src/link.zig+3-32| ... | @@ -533,8 +533,7 @@ pub const File = struct { | ... | @@ -533,8 +533,7 @@ pub const File = struct { |
| 533 | } | 533 | } |
| 534 | } | 534 | } |
| 535 | 535 | ||
| 536 | /// May be called before or after updateDeclExports but must be called | 536 | /// May be called before or after updateDeclExports for any given Decl. |
| 537 | /// after allocateDeclIndexes for any given Decl. | ||
| 538 | pub fn updateDecl(base: *File, module: *Module, decl_index: Module.Decl.Index) UpdateDeclError!void { | 537 | pub fn updateDecl(base: *File, module: *Module, decl_index: Module.Decl.Index) UpdateDeclError!void { |
| 539 | const decl = module.declPtr(decl_index); | 538 | const decl = module.declPtr(decl_index); |
| 540 | log.debug("updateDecl {*} ({s}), type={}", .{ decl, decl.name, decl.ty.fmtDebug() }); | 539 | log.debug("updateDecl {*} ({s}), type={}", .{ decl, decl.name, decl.ty.fmtDebug() }); |
| ... | @@ -557,8 +556,7 @@ pub const File = struct { | ... | @@ -557,8 +556,7 @@ pub const File = struct { |
| 557 | } | 556 | } |
| 558 | } | 557 | } |
| 559 | 558 | ||
| 560 | /// May be called before or after updateDeclExports but must be called | 559 | /// May be called before or after updateDeclExports for any given Decl. |
| 561 | /// after allocateDeclIndexes for any given Decl. | ||
| 562 | pub fn updateFunc(base: *File, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) UpdateDeclError!void { | 560 | pub fn updateFunc(base: *File, module: *Module, func: *Module.Fn, air: Air, liveness: Liveness) UpdateDeclError!void { |
| 563 | const owner_decl = module.declPtr(func.owner_decl); | 561 | const owner_decl = module.declPtr(func.owner_decl); |
| 564 | log.debug("updateFunc {*} ({s}), type={}", .{ | 562 | log.debug("updateFunc {*} ({s}), type={}", .{ |
| ... | @@ -602,32 +600,6 @@ pub const File = struct { | ... | @@ -602,32 +600,6 @@ pub const File = struct { |
| 602 | } | 600 | } |
| 603 | } | 601 | } |
| 604 | 602 | ||
| 605 | /// Must be called before any call to updateDecl or updateDeclExports for | ||
| 606 | /// any given Decl. | ||
| 607 | /// TODO we're transitioning to deleting this function and instead having | ||
| 608 | /// each linker backend notice the first time updateDecl or updateFunc is called, or | ||
| 609 | /// a callee referenced from AIR. | ||
| 610 | pub fn allocateDeclIndexes(base: *File, decl_index: Module.Decl.Index) error{OutOfMemory}!void { | ||
| 611 | const decl = base.options.module.?.declPtr(decl_index); | ||
| 612 | log.debug("allocateDeclIndexes {*} ({s})", .{ decl, decl.name }); | ||
| 613 | if (build_options.only_c) { | ||
| 614 | assert(base.tag == .c); | ||
| 615 | return; | ||
| 616 | } | ||
| 617 | switch (base.tag) { | ||
| 618 | .plan9 => return @fieldParentPtr(Plan9, "base", base).allocateDeclIndexes(decl_index), | ||
| 619 | |||
| 620 | .coff, | ||
| 621 | .elf, | ||
| 622 | .macho, | ||
| 623 | .c, | ||
| 624 | .spirv, | ||
| 625 | .nvptx, | ||
| 626 | .wasm, | ||
| 627 | => {}, | ||
| 628 | } | ||
| 629 | } | ||
| 630 | |||
| 631 | pub fn releaseLock(self: *File) void { | 603 | pub fn releaseLock(self: *File) void { |
| 632 | if (self.lock) |*lock| { | 604 | if (self.lock) |*lock| { |
| 633 | lock.release(); | 605 | lock.release(); |
| ... | @@ -878,8 +850,7 @@ pub const File = struct { | ... | @@ -878,8 +850,7 @@ pub const File = struct { |
| 878 | AnalysisFail, | 850 | AnalysisFail, |
| 879 | }; | 851 | }; |
| 880 | 852 | ||
| 881 | /// May be called before or after updateDecl, but must be called after | 853 | /// May be called before or after updateDecl for any given Decl. |
| 882 | /// allocateDeclIndexes for any given Decl. | ||
| 883 | pub fn updateDeclExports( | 854 | pub fn updateDeclExports( |
| 884 | base: *File, | 855 | base: *File, |
| 885 | module: *Module, | 856 | module: *Module, |
src/link/Plan9.zig+2-7| ... | @@ -424,7 +424,7 @@ fn updateFinish(self: *Plan9, decl: *Module.Decl) !void { | ... | @@ -424,7 +424,7 @@ fn updateFinish(self: *Plan9, decl: *Module.Decl) !void { |
| 424 | // write the internal linker metadata | 424 | // write the internal linker metadata |
| 425 | decl.link.plan9.type = sym_t; | 425 | decl.link.plan9.type = sym_t; |
| 426 | // write the symbol | 426 | // write the symbol |
| 427 | // we already have the got index because that got allocated in allocateDeclIndexes | 427 | // we already have the got index |
| 428 | const sym: aout.Sym = .{ | 428 | const sym: aout.Sym = .{ |
| 429 | .value = undefined, // the value of stuff gets filled in in flushModule | 429 | .value = undefined, // the value of stuff gets filled in in flushModule |
| 430 | .type = decl.link.plan9.type, | 430 | .type = decl.link.plan9.type, |
| ... | @@ -737,7 +737,7 @@ fn addDeclExports( | ... | @@ -737,7 +737,7 @@ fn addDeclExports( |
| 737 | 737 | ||
| 738 | pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void { | 738 | pub fn freeDecl(self: *Plan9, decl_index: Module.Decl.Index) void { |
| 739 | // TODO audit the lifetimes of decls table entries. It's possible to get | 739 | // TODO audit the lifetimes of decls table entries. It's possible to get |
| 740 | // allocateDeclIndexes and then freeDecl without any updateDecl in between. | 740 | // freeDecl without any updateDecl in between. |
| 741 | // However that is planned to change, see the TODO comment in Module.zig | 741 | // However that is planned to change, see the TODO comment in Module.zig |
| 742 | // in the deleteUnusedDecl function. | 742 | // in the deleteUnusedDecl function. |
| 743 | const mod = self.base.options.module.?; | 743 | const mod = self.base.options.module.?; |
| ... | @@ -959,11 +959,6 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { | ... | @@ -959,11 +959,6 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 959 | } | 959 | } |
| 960 | } | 960 | } |
| 961 | 961 | ||
| 962 | /// this will be removed, moved to updateFinish | ||
| 963 | pub fn allocateDeclIndexes(self: *Plan9, decl_index: Module.Decl.Index) !void { | ||
| 964 | _ = self; | ||
| 965 | _ = decl_index; | ||
| 966 | } | ||
| 967 | /// Must be called only after a successful call to `updateDecl`. | 962 | /// Must be called only after a successful call to `updateDecl`. |
| 968 | pub fn updateDeclLineNumber(self: *Plan9, mod: *Module, decl: *const Module.Decl) !void { | 963 | pub fn updateDeclLineNumber(self: *Plan9, mod: *Module, decl: *const Module.Decl) !void { |
| 969 | _ = self; | 964 | _ = self; |