diff options
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/c.zig | 15 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 27 |
2 files changed, 36 insertions, 6 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 191be36494..922e1d9c3e 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -195,7 +195,7 @@ pub const DeclGen = struct { val: Value, decl: *Decl, ) error{ OutOfMemory, AnalysisFail }!void { - decl.alive = true; + markDeclAlive(decl); if (ty.isSlice()) { try writer.writeByte('('); @@ -227,6 +227,19 @@ pub const DeclGen = struct { try dg.renderDeclName(decl, writer); } + fn markDeclAlive(decl: *Decl) void { + if (decl.alive) return; + decl.alive = true; + + // 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. + + if (decl.val.pointerDecl()) |pointee| { + return markDeclAlive(pointee); + } + } + fn renderInt128( writer: anytype, int_val: anytype, diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 070c667e6b..4bf719f4c0 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -749,7 +749,6 @@ pub const DeclGen = struct { fn llvmType(dg: *DeclGen, t: Type) Error!*const llvm.Type { const gpa = dg.gpa; - log.debug("llvmType for {}", .{t}); switch (t.zigTypeTag()) { .Void, .NoReturn => return dg.context.voidType(), .Int => { @@ -1168,7 +1167,7 @@ pub const DeclGen = struct { .decl_ref => return lowerDeclRefValue(dg, tv, tv.val.castTag(.decl_ref).?.data), .variable => { const decl = tv.val.castTag(.variable).?.data.owner_decl; - decl.alive = true; + dg.markDeclAlive(decl); const val = try dg.resolveGlobalDecl(decl); const llvm_var_type = try dg.llvmType(tv.ty); const llvm_addrspace = dg.llvmAddressSpace(decl.@"addrspace"); @@ -1317,7 +1316,7 @@ pub const DeclGen = struct { .function => tv.val.castTag(.function).?.data.owner_decl, else => unreachable, }; - fn_decl.alive = true; + dg.markDeclAlive(fn_decl); return dg.resolveLlvmFunction(fn_decl); }, .ErrorSet => { @@ -1625,7 +1624,7 @@ pub const DeclGen = struct { ptr_val: Value, decl: *Module.Decl, ) Error!ParentPtr { - decl.alive = true; + dg.markDeclAlive(decl); var ptr_ty_payload: Type.Payload.ElemType = .{ .base = .{ .tag = .single_mut_pointer }, .data = decl.ty, @@ -1707,7 +1706,7 @@ pub const DeclGen = struct { return self.lowerPtrToVoid(tv.ty); } - decl.alive = true; + self.markDeclAlive(decl); const llvm_val = if (decl.ty.zigTypeTag() == .Fn) try self.resolveLlvmFunction(decl) @@ -1718,6 +1717,24 @@ pub const DeclGen = struct { return llvm_val.constBitCast(llvm_type); } + fn markDeclAlive(dg: *DeclGen, decl: *Module.Decl) void { + if (decl.alive) return; + decl.alive = true; + + log.debug("{*} ({s}) marked alive by {*} ({s})", .{ + decl, decl.name, + dg.decl, dg.decl.name, + }); + + // 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. + + if (decl.val.pointerDecl()) |pointee| { + return dg.markDeclAlive(pointee); + } + } + fn lowerPtrToVoid(dg: *DeclGen, ptr_ty: Type) !*const llvm.Value { const target = dg.module.getTarget(); const alignment = ptr_ty.ptrAlignment(target); |
