aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2022-01-06 00:52:10 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-01-06 00:52:10 -0700
commit8c6175c1343a00278efc029a0be4091ff505dc3d (patch)
tree63f9c87d0f37757f5c0c0b543fc94ea4fe68ae22 /src/codegen
parent713d2a9b3883942491b40738245232680877cc66 (diff)
downloadzig-8c6175c1343a00278efc029a0be4091ff505dc3d.tar.gz
zig-8c6175c1343a00278efc029a0be4091ff505dc3d.zip
Sema: const inferred alloc infers comptime-ness
const locals now detect if the value ends up being comptime known. In such case, it replaces the runtime AIR instructions with a decl_ref const. In the backends, some more sophisticated logic for marking decls as alive was needed to prevent Decls incorrectly being garbage collected that were indirectly referenced in such manner.
Diffstat (limited to 'src/codegen')
-rw-r--r--src/codegen/c.zig15
-rw-r--r--src/codegen/llvm.zig27
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);