stage2: add owns_tv flag to Module.Decl
Decl objects need to know whether they are the owner of the Type/Value associated with them, in order to decide whether to destroy the associated Namespace, Fn, or Var when cleaning up.
This commit is contained in:
@@ -30,6 +30,7 @@ pub const CValue = union(enum) {
|
||||
arg: usize,
|
||||
/// By-value
|
||||
decl: *Decl,
|
||||
decl_ref: *Decl,
|
||||
};
|
||||
|
||||
pub const CValueMap = std.AutoHashMap(*Inst, CValue);
|
||||
@@ -117,6 +118,7 @@ pub const Object = struct {
|
||||
.constant => |inst| return o.dg.renderValue(w, inst.ty, inst.value().?),
|
||||
.arg => |i| return w.print("a{d}", .{i}),
|
||||
.decl => |decl| return w.writeAll(mem.span(decl.name)),
|
||||
.decl_ref => |decl| return w.print("&{s}", .{decl.name}),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -528,13 +530,17 @@ pub const DeclGen = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn functionIsGlobal(dg: *DeclGen, tv: TypedValue) bool {
|
||||
fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {
|
||||
switch (tv.val.tag()) {
|
||||
.extern_fn => return true,
|
||||
.function => {
|
||||
const func = tv.val.castTag(.function).?.data;
|
||||
return dg.module.decl_exports.contains(func.owner_decl);
|
||||
},
|
||||
.variable => {
|
||||
const variable = tv.val.castTag(.variable).?.data;
|
||||
return dg.module.decl_exports.contains(variable.owner_decl);
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
@@ -549,7 +555,7 @@ pub fn genDecl(o: *Object) !void {
|
||||
.val = o.dg.decl.val,
|
||||
};
|
||||
if (tv.val.castTag(.function)) |func_payload| {
|
||||
const is_global = o.dg.functionIsGlobal(tv);
|
||||
const is_global = o.dg.declIsGlobal(tv);
|
||||
const fwd_decl_writer = o.dg.fwd_decl.writer();
|
||||
if (is_global) {
|
||||
try fwd_decl_writer.writeAll("ZIG_EXTERN_C ");
|
||||
@@ -570,6 +576,30 @@ pub fn genDecl(o: *Object) !void {
|
||||
try writer.writeAll("ZIG_EXTERN_C ");
|
||||
try o.dg.renderFunctionSignature(writer, true);
|
||||
try writer.writeAll(";\n");
|
||||
} else if (tv.val.castTag(.variable)) |var_payload| {
|
||||
const variable: *Module.Var = var_payload.data;
|
||||
const is_global = o.dg.declIsGlobal(tv);
|
||||
const fwd_decl_writer = o.dg.fwd_decl.writer();
|
||||
if (is_global or variable.is_extern) {
|
||||
try fwd_decl_writer.writeAll("ZIG_EXTERN_C ");
|
||||
}
|
||||
if (variable.is_threadlocal) {
|
||||
try fwd_decl_writer.writeAll("zig_threadlocal ");
|
||||
}
|
||||
try o.dg.renderType(fwd_decl_writer, o.dg.decl.ty);
|
||||
const decl_name = mem.span(o.dg.decl.name);
|
||||
try fwd_decl_writer.print(" {s};\n", .{decl_name});
|
||||
|
||||
try o.indent_writer.insertNewline();
|
||||
const w = o.writer();
|
||||
try o.dg.renderType(w, o.dg.decl.ty);
|
||||
try w.print(" {s} = ", .{decl_name});
|
||||
if (variable.init.tag() != .unreachable_value) {
|
||||
try o.dg.renderValue(w, tv.ty, variable.init);
|
||||
}
|
||||
try w.writeAll(";");
|
||||
try o.indent_writer.insertNewline();
|
||||
|
||||
} else {
|
||||
const writer = o.writer();
|
||||
try writer.writeAll("static ");
|
||||
@@ -598,7 +628,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
|
||||
|
||||
switch (tv.ty.zigTypeTag()) {
|
||||
.Fn => {
|
||||
const is_global = dg.functionIsGlobal(tv);
|
||||
const is_global = dg.declIsGlobal(tv);
|
||||
if (is_global) {
|
||||
try writer.writeAll("ZIG_EXTERN_C ");
|
||||
}
|
||||
@@ -696,7 +726,7 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi
|
||||
.wrap_errunion_err => try genWrapErrUnionErr(o, inst.castTag(.wrap_errunion_err).?),
|
||||
.br_block_flat => return o.dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement codegen for br_block_flat", .{}),
|
||||
.ptrtoint => return o.dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement codegen for ptrtoint", .{}),
|
||||
.varptr => return o.dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement codegen for varptr", .{}),
|
||||
.varptr => try genVarPtr(o, inst.castTag(.varptr).?),
|
||||
.floatcast => return o.dg.fail(.{ .node_offset = 0 }, "TODO: C backend: implement codegen for floatcast", .{}),
|
||||
};
|
||||
switch (result_value) {
|
||||
@@ -709,6 +739,10 @@ pub fn genBody(o: *Object, body: ir.Body) error{ AnalysisFail, OutOfMemory }!voi
|
||||
try writer.writeAll("}");
|
||||
}
|
||||
|
||||
fn genVarPtr(o: *Object, inst: *Inst.VarPtr) !CValue {
|
||||
return CValue{ .decl_ref = inst.variable.owner_decl };
|
||||
}
|
||||
|
||||
fn genAlloc(o: *Object, alloc: *Inst.NoOp) !CValue {
|
||||
const writer = o.writer();
|
||||
|
||||
@@ -743,6 +777,12 @@ fn genLoad(o: *Object, inst: *Inst.UnOp) !CValue {
|
||||
try o.writeCValue(writer, wrapped);
|
||||
try writer.writeAll(";\n");
|
||||
},
|
||||
.decl_ref => |decl| {
|
||||
const wrapped: CValue = .{ .decl = decl };
|
||||
try writer.writeAll(" = ");
|
||||
try o.writeCValue(writer, wrapped);
|
||||
try writer.writeAll(";\n");
|
||||
},
|
||||
else => {
|
||||
try writer.writeAll(" = *");
|
||||
try o.writeCValue(writer, operand);
|
||||
@@ -791,6 +831,13 @@ fn genStore(o: *Object, inst: *Inst.BinOp) !CValue {
|
||||
try o.writeCValue(writer, src_val);
|
||||
try writer.writeAll(";\n");
|
||||
},
|
||||
.decl_ref => |decl| {
|
||||
const dest: CValue = .{ .decl = decl };
|
||||
try o.writeCValue(writer, dest);
|
||||
try writer.writeAll(" = ");
|
||||
try o.writeCValue(writer, src_val);
|
||||
try writer.writeAll(";\n");
|
||||
},
|
||||
else => {
|
||||
try writer.writeAll("*");
|
||||
try o.writeCValue(writer, dest_ptr);
|
||||
|
||||
Reference in New Issue
Block a user