diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2023-09-29 19:07:37 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2023-10-03 12:12:51 -0700 |
| commit | c4b0b7a30bf96590f9849f64a3d86fe2ebbc6a26 (patch) | |
| tree | d7c32643bbdd61d5ebf1d73e7b78ddac553a3818 /src/codegen/c.zig | |
| parent | 9d069d98e3e3773d76bfa4fb07cf4bcbf06e2b67 (diff) | |
| download | zig-c4b0b7a30bf96590f9849f64a3d86fe2ebbc6a26.tar.gz zig-c4b0b7a30bf96590f9849f64a3d86fe2ebbc6a26.zip | |
C backend: render anon decls
Introduce the new mechanism needed to render anonymous decls to C code
that the frontend is now using.
The current strategy is to collect the set of used anonymous decls into
one ArrayHashMap for the entire compilation, and then render them during
flush().
In the future this may need to be adjusted for incremental compilation
purposes, so that removing a Decl from decl_table means that newly
unused anonymous decls are no longer rendered. However, let's do one
thing at a time. The only goal of this branch is to stop using
Module.Decl objects for unnamed constants.
Diffstat (limited to 'src/codegen/c.zig')
| -rw-r--r-- | src/codegen/c.zig | 56 |
1 files changed, 37 insertions, 19 deletions
diff --git a/src/codegen/c.zig b/src/codegen/c.zig index 440d838f91..3278ed89b0 100644 --- a/src/codegen/c.zig +++ b/src/codegen/c.zig @@ -530,7 +530,7 @@ pub const DeclGen = struct { ctypes: CType.Store, /// Keeps track of anonymous decls that need to be rendered before this /// (named) Decl in the output C code. - anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, void), + anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.DeclBlock), fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } { @setCold(true); @@ -586,12 +586,13 @@ pub const DeclGen = struct { try dg.renderType(writer, ty); try writer.writeByte(')'); } - try writer.print("&__anon_{d}", .{@intFromEnum(decl_val)}); + try writer.writeByte('&'); + try renderAnonDeclName(writer, decl_val); if (need_typecast) try writer.writeByte(')'); // Indicate that the anon decl should be rendered to the output so that // our reference above is not undefined. - try dg.anon_decl_deps.put(dg.gpa, decl_val, {}); + _ = try dg.anon_decl_deps.getOrPut(dg.gpa, decl_val); } fn renderDeclValue( @@ -1806,7 +1807,7 @@ pub const DeclGen = struct { .none => unreachable, .local, .new_local => |i| return w.print("t{d}", .{i}), .local_ref => |i| return w.print("&t{d}", .{i}), - .constant => unreachable, + .constant => |val| return renderAnonDeclName(w, val), .arg => |i| return w.print("a{d}", .{i}), .arg_array => |i| return dg.writeCValueMember(w, .{ .arg = i }, .{ .identifier = "array" }), .field => |i| return w.print("f{d}", .{i}), @@ -1924,6 +1925,10 @@ pub const DeclGen = struct { } } + fn renderAnonDeclName(writer: anytype, anon_decl_val: InternPool.Index) !void { + return writer.print("__anon_{d}", .{@intFromEnum(anon_decl_val)}); + } + fn renderTypeForBuiltinFnName(dg: *DeclGen, writer: anytype, ty: Type) !void { try dg.renderCTypeForBuiltinFnName(writer, try dg.typeToCType(ty, .complete)); } @@ -2761,7 +2766,6 @@ pub fn genDecl(o: *Object) !void { const mod = o.dg.module; const decl_index = o.dg.decl_index.unwrap().?; - const decl_c_value = .{ .decl = decl_index }; const decl = mod.declPtr(decl_index); const tv: TypedValue = .{ .ty = decl.ty, .val = (try decl.internValue(mod)).toValue() }; @@ -2785,6 +2789,7 @@ pub fn genDecl(o: *Object) !void { if (variable.is_threadlocal) try w.writeAll("zig_threadlocal "); if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| try w.print("zig_linksection(\"{s}\", ", .{s}); + const decl_c_value = .{ .decl = decl_index }; try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, .{}, decl.alignment, .complete); if (decl.@"linksection" != .none) try w.writeAll(", read, write)"); try w.writeAll(" = "); @@ -2793,22 +2798,35 @@ pub fn genDecl(o: *Object) !void { try o.indent_writer.insertNewline(); } else { const is_global = o.dg.module.decl_exports.contains(decl_index); - const fwd_decl_writer = o.dg.fwd_decl.writer(); + const decl_c_value = .{ .decl = decl_index }; + return genDeclValue(o, tv, is_global, decl_c_value, decl.alignment, decl.@"linksection"); + } +} - try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); - try o.dg.renderTypeAndName(fwd_decl_writer, tv.ty, decl_c_value, Const, decl.alignment, .complete); - try fwd_decl_writer.writeAll(";\n"); +pub fn genDeclValue( + o: *Object, + tv: TypedValue, + is_global: bool, + decl_c_value: CValue, + alignment: Alignment, + link_section: InternPool.OptionalNullTerminatedString, +) !void { + const fwd_decl_writer = o.dg.fwd_decl.writer(); - const w = o.writer(); - if (!is_global) try w.writeAll("static "); - if (mod.intern_pool.stringToSliceUnwrap(decl.@"linksection")) |s| - try w.print("zig_linksection(\"{s}\", ", .{s}); - try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, Const, decl.alignment, .complete); - if (decl.@"linksection" != .none) try w.writeAll(", read)"); - try w.writeAll(" = "); - try o.dg.renderValue(w, tv.ty, tv.val, .StaticInitializer); - try w.writeAll(";\n"); - } + try fwd_decl_writer.writeAll(if (is_global) "zig_extern " else "static "); + try o.dg.renderTypeAndName(fwd_decl_writer, tv.ty, decl_c_value, Const, alignment, .complete); + try fwd_decl_writer.writeAll(";\n"); + + const mod = o.dg.module; + const w = o.writer(); + if (!is_global) try w.writeAll("static "); + if (mod.intern_pool.stringToSliceUnwrap(link_section)) |s| + try w.print("zig_linksection(\"{s}\", ", .{s}); + try o.dg.renderTypeAndName(w, tv.ty, decl_c_value, Const, alignment, .complete); + if (link_section != .none) try w.writeAll(", read)"); + try w.writeAll(" = "); + try o.dg.renderValue(w, tv.ty, tv.val, .StaticInitializer); + try w.writeAll(";\n"); } pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void { |
