diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2021-05-11 14:17:52 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2021-05-11 14:17:52 -0700 |
| commit | bcf15e39e2d4e2243f475852aca7749e40a70fbd (patch) | |
| tree | 367c697ea25a0649a263d13131ffaf0ec3f82ad4 /src/codegen | |
| parent | dae22a0a1f13cc963e96cd704941eed29b8dde27 (diff) | |
| download | zig-bcf15e39e2d4e2243f475852aca7749e40a70fbd.tar.gz zig-bcf15e39e2d4e2243f475852aca7749e40a70fbd.zip | |
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.
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/c.zig | 55 |
1 files changed, 51 insertions, 4 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 43b851019b..6f80ac6154 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -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); |
