Commit 9a738c0be5

Jacob Young <jacobly0@users.noreply.github.com>
2023-05-26 06:24:29
Module: intern the values of decls when they are marked alive
I'm not sure if this is the right place for this to happen, and it should become obsolete when comptime mutation is rewritten and the remaining legacy value tags are remove, so keeping this as a separate revertable commit.
1 parent f37c0a4
src/arch/wasm/CodeGen.zig
@@ -3019,7 +3019,7 @@ fn lowerParentPtr(func: *CodeGen, ptr_val: Value) InnerError!WValue {
 fn lowerParentPtrDecl(func: *CodeGen, ptr_val: Value, decl_index: Module.Decl.Index, offset: u32) InnerError!WValue {
     const mod = func.bin_file.base.options.module.?;
     const decl = mod.declPtr(decl_index);
-    mod.markDeclAlive(decl);
+    try mod.markDeclAlive(decl);
     const ptr_ty = try mod.singleMutPtrType(decl.ty);
     return func.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index, offset);
 }
@@ -3035,7 +3035,7 @@ fn lowerDeclRefValue(func: *CodeGen, tv: TypedValue, decl_index: Module.Decl.Ind
         return WValue{ .imm32 = 0xaaaaaaaa };
     }
 
-    mod.markDeclAlive(decl);
+    try mod.markDeclAlive(decl);
     const atom_index = try func.bin_file.getOrCreateAtomForDecl(decl_index);
     const atom = func.bin_file.getAtom(atom_index);
 
src/codegen/c.zig
@@ -1923,7 +1923,7 @@ pub const DeclGen = struct {
     fn renderDeclName(dg: *DeclGen, writer: anytype, decl_index: Decl.Index, export_index: u32) !void {
         const mod = dg.module;
         const decl = mod.declPtr(decl_index);
-        mod.markDeclAlive(decl);
+        try mod.markDeclAlive(decl);
 
         if (mod.decl_exports.get(decl_index)) |exports| {
             try writer.writeAll(exports.items[export_index].options.name);
src/codegen/llvm.zig
@@ -3252,7 +3252,7 @@ pub const DeclGen = struct {
                     else => unreachable,
                 };
                 const fn_decl = dg.module.declPtr(fn_decl_index);
-                dg.module.markDeclAlive(fn_decl);
+                try dg.module.markDeclAlive(fn_decl);
                 return dg.resolveLlvmFunction(fn_decl_index);
             },
             .int => |int| {
@@ -3831,7 +3831,7 @@ pub const DeclGen = struct {
     ) Error!*llvm.Value {
         const mod = dg.module;
         const decl = mod.declPtr(decl_index);
-        mod.markDeclAlive(decl);
+        try mod.markDeclAlive(decl);
         const ptr_ty = try mod.singleMutPtrType(decl.ty);
         return try dg.lowerDeclRefValue(.{ .ty = ptr_ty, .val = ptr_val }, decl_index);
     }
@@ -4006,7 +4006,7 @@ pub const DeclGen = struct {
             return self.lowerPtrToVoid(tv.ty);
         }
 
-        mod.markDeclAlive(decl);
+        try mod.markDeclAlive(decl);
 
         const llvm_decl_val = if (is_fn_body)
             try self.resolveLlvmFunction(decl_index)
src/codegen/spirv.zig
@@ -256,7 +256,7 @@ pub const DeclGen = struct {
     /// Note: Function does not actually generate the decl.
     fn resolveDecl(self: *DeclGen, decl_index: Module.Decl.Index) !SpvModule.Decl.Index {
         const decl = self.module.declPtr(decl_index);
-        self.module.markDeclAlive(decl);
+        try self.module.markDeclAlive(decl);
 
         const entry = try self.decl_link.getOrPut(decl_index);
         if (!entry.found_existing) {
src/codegen.zig
@@ -673,7 +673,7 @@ fn lowerDeclRef(
         return Result.ok;
     }
 
-    mod.markDeclAlive(decl);
+    try mod.markDeclAlive(decl);
 
     const vaddr = try bin_file.getDeclVAddr(decl_index, .{
         .parent_atom_index = reloc_info.parent_atom_index,
@@ -782,7 +782,7 @@ fn genDeclRef(
         }
     }
 
-    mod.markDeclAlive(decl);
+    try mod.markDeclAlive(decl);
 
     const is_threadlocal = tv.val.isPtrToThreadLocal(mod) and !bin_file.options.single_threaded;
 
src/Module.zig
@@ -6603,47 +6603,49 @@ fn reportRetryableFileError(
     gop.value_ptr.* = err_msg;
 }
 
-pub fn markReferencedDeclsAlive(mod: *Module, val: Value) void {
+pub fn markReferencedDeclsAlive(mod: *Module, val: Value) Allocator.Error!void {
     switch (mod.intern_pool.indexToKey(val.toIntern())) {
-        .variable => |variable| mod.markDeclIndexAlive(variable.decl),
-        .extern_func => |extern_func| mod.markDeclIndexAlive(extern_func.decl),
-        .func => |func| mod.markDeclIndexAlive(mod.funcPtr(func.index).owner_decl),
+        .variable => |variable| try mod.markDeclIndexAlive(variable.decl),
+        .extern_func => |extern_func| try mod.markDeclIndexAlive(extern_func.decl),
+        .func => |func| try mod.markDeclIndexAlive(mod.funcPtr(func.index).owner_decl),
         .error_union => |error_union| switch (error_union.val) {
             .err_name => {},
-            .payload => |payload| mod.markReferencedDeclsAlive(payload.toValue()),
+            .payload => |payload| try mod.markReferencedDeclsAlive(payload.toValue()),
         },
         .ptr => |ptr| {
             switch (ptr.addr) {
-                .decl => |decl| mod.markDeclIndexAlive(decl),
-                .mut_decl => |mut_decl| mod.markDeclIndexAlive(mut_decl.decl),
+                .decl => |decl| try mod.markDeclIndexAlive(decl),
+                .mut_decl => |mut_decl| try mod.markDeclIndexAlive(mut_decl.decl),
                 .int, .comptime_field => {},
-                .eu_payload, .opt_payload => |parent| mod.markReferencedDeclsAlive(parent.toValue()),
-                .elem, .field => |base_index| mod.markReferencedDeclsAlive(base_index.base.toValue()),
+                .eu_payload, .opt_payload => |parent| try mod.markReferencedDeclsAlive(parent.toValue()),
+                .elem, .field => |base_index| try mod.markReferencedDeclsAlive(base_index.base.toValue()),
             }
-            if (ptr.len != .none) mod.markReferencedDeclsAlive(ptr.len.toValue());
+            if (ptr.len != .none) try mod.markReferencedDeclsAlive(ptr.len.toValue());
         },
-        .opt => |opt| if (opt.val != .none) mod.markReferencedDeclsAlive(opt.val.toValue()),
+        .opt => |opt| if (opt.val != .none) try mod.markReferencedDeclsAlive(opt.val.toValue()),
         .aggregate => |aggregate| for (aggregate.storage.values()) |elem|
-            mod.markReferencedDeclsAlive(elem.toValue()),
+            try mod.markReferencedDeclsAlive(elem.toValue()),
         .un => |un| {
-            mod.markReferencedDeclsAlive(un.tag.toValue());
-            mod.markReferencedDeclsAlive(un.val.toValue());
+            try mod.markReferencedDeclsAlive(un.tag.toValue());
+            try mod.markReferencedDeclsAlive(un.val.toValue());
         },
         else => {},
     }
 }
 
-pub fn markDeclAlive(mod: *Module, decl: *Decl) void {
+pub fn markDeclAlive(mod: *Module, decl: *Decl) Allocator.Error!void {
     if (decl.alive) return;
     decl.alive = true;
 
+    decl.val = (try decl.val.intern(decl.ty, mod)).toValue();
+
     // This is the first time we are marking this Decl alive. We must
     // therefore recurse into its value and mark any Decl it references
     // as also alive, so that any Decl referenced does not get garbage collected.
-    mod.markReferencedDeclsAlive(decl.val);
+    try mod.markReferencedDeclsAlive(decl.val);
 }
 
-fn markDeclIndexAlive(mod: *Module, decl_index: Decl.Index) void {
+fn markDeclIndexAlive(mod: *Module, decl_index: Decl.Index) Allocator.Error!void {
     return mod.markDeclAlive(mod.declPtr(decl_index));
 }
 
src/Sema.zig
@@ -5807,7 +5807,7 @@ pub fn analyzeExport(
     }
 
     // This decl is alive no matter what, since it's being exported
-    mod.markDeclAlive(exported_decl);
+    try mod.markDeclAlive(exported_decl);
     try sema.maybeQueueFuncBodyAnalysis(exported_decl_index);
 
     const gpa = sema.gpa;