diff options
Diffstat (limited to 'src/Module.zig')
| -rw-r--r-- | src/Module.zig | 60 |
1 files changed, 38 insertions, 22 deletions
diff --git a/src/Module.zig b/src/Module.zig index de6770d3d7..2c51b0ab69 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -3039,10 +3039,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl: *Decl) SemaError!void { log.debug("insert {*} ({s}) dependant {*} ({s}) into deletion set", .{ decl, decl.name, dep, dep.name, }); - // We don't perform a deletion here, because this Decl or another one - // may end up referencing it before the update is complete. - dep.deletion_flag = true; - try mod.deletion_set.put(mod.gpa, dep, {}); + try mod.markDeclForDeletion(dep); } } decl.dependencies.clearRetainingCapacity(); @@ -3433,21 +3430,29 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { decl.owns_tv = false; var queue_linker_work = false; - if (decl_tv.val.castTag(.variable)) |payload| { - const variable = payload.data; - if (variable.owner_decl == decl) { - decl.owns_tv = true; - queue_linker_work = true; - - const copied_init = try variable.init.copy(&decl_arena.allocator); - variable.init = copied_init; - } - } else if (decl_tv.val.castTag(.extern_fn)) |payload| { - const owner_decl = payload.data; - if (decl == owner_decl) { - decl.owns_tv = true; + switch (decl_tv.val.tag()) { + .variable => { + const variable = decl_tv.val.castTag(.variable).?.data; + if (variable.owner_decl == decl) { + decl.owns_tv = true; + queue_linker_work = true; + + const copied_init = try variable.init.copy(&decl_arena.allocator); + variable.init = copied_init; + } + }, + .extern_fn => { + const owner_decl = decl_tv.val.castTag(.extern_fn).?.data; + if (decl == owner_decl) { + decl.owns_tv = true; + queue_linker_work = true; + } + }, + .array, .@"struct", .@"union" => { + log.debug("send global const to linker: {*} ({s})", .{ decl, decl.name }); queue_linker_work = true; - } + }, + else => {}, } decl.ty = try decl_tv.ty.copy(&decl_arena.allocator); @@ -3462,6 +3467,8 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool { decl.generation = mod.generation; if (queue_linker_work and decl.ty.hasCodeGenBits()) { + log.debug("queue linker work for {*} ({s})", .{ decl, decl.name }); + try mod.comp.bin_file.allocateDeclIndexes(decl); try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl }); @@ -3985,6 +3992,7 @@ pub fn clearDecl( decl.analysis = .unreferenced; } +/// This function is exclusively called for anonymous decls. pub fn deleteUnusedDecl(mod: *Module, decl: *Decl) void { log.debug("deleteUnusedDecl {*} ({s})", .{ decl, decl.name }); @@ -4019,6 +4027,13 @@ pub fn deleteUnusedDecl(mod: *Module, decl: *Decl) void { decl.destroy(mod); } +/// We don't perform a deletion here, because this Decl or another one +/// may end up referencing it before the update is complete. +fn markDeclForDeletion(mod: *Module, decl: *Decl) !void { + decl.deletion_flag = true; + try mod.deletion_set.put(mod.gpa, decl, {}); +} + /// Cancel the creation of an anon decl and delete any references to it. /// If other decls depend on this decl, they must be aborted first. pub fn abortAnonDecl(mod: *Module, decl: *Decl) void { @@ -4369,12 +4384,13 @@ pub fn createAnonymousDeclFromDeclNamed( namespace.anon_decls.putAssumeCapacityNoClobber(new_decl, {}); - // TODO: This generates the Decl into the machine code file if it is of a - // type that is non-zero size. We should be able to further improve the - // compiler to omit Decls which are only referenced at compile-time and not runtime. + // The Decl starts off with alive=false and the codegen backend will set alive=true + // if the Decl is referenced by an instruction or another constant. Otherwise, + // the Decl will be garbage collected by the `codegen_decl` task instead of sent + // to the linker. if (typed_value.ty.hasCodeGenBits()) { try mod.comp.bin_file.allocateDeclIndexes(new_decl); - try mod.comp.work_queue.writeItem(.{ .codegen_decl = new_decl }); + try mod.comp.anon_work_queue.writeItem(.{ .codegen_decl = new_decl }); } return new_decl; |
