Commit 51f7e5412a

Jacob Young <jacobly0@users.noreply.github.com>
2023-10-25 16:07:41
cbe: update `DeclGen.decl_index` to support anon decls
1 parent 405ba26
Changed files (3)
src
src/codegen/c.zig
@@ -522,7 +522,7 @@ pub const Object = struct {
 pub const DeclGen = struct {
     gpa: mem.Allocator,
     module: *Module,
-    decl_index: Decl.OptionalIndex,
+    pass: Pass,
     is_naked_fn: bool,
     /// This is a borrowed reference from `link.C`.
     fwd_decl: std.ArrayList(u8),
@@ -533,10 +533,16 @@ pub const DeclGen = struct {
     anon_decl_deps: std.AutoArrayHashMapUnmanaged(InternPool.Index, C.DeclBlock),
     aligned_anon_decls: std.AutoArrayHashMapUnmanaged(InternPool.Index, Alignment),
 
+    pub const Pass = union(enum) {
+        decl: Decl.Index,
+        anon: InternPool.Index,
+        flush,
+    };
+
     fn fail(dg: *DeclGen, comptime format: []const u8, args: anytype) error{ AnalysisFail, OutOfMemory } {
         @setCold(true);
         const mod = dg.module;
-        const decl_index = dg.decl_index.unwrap().?;
+        const decl_index = dg.pass.decl;
         const decl = mod.declPtr(decl_index);
         const src = LazySrcLoc.nodeOffset(0);
         const src_loc = src.toSrcLoc(decl, mod);
@@ -1566,18 +1572,11 @@ pub const DeclGen = struct {
                 else => unreachable,
             }
         }
-        if (fn_decl.val.getFunction(mod)) |func| if (func.analysis(ip).is_cold) try w.writeAll("zig_cold ");
+        if (fn_decl.val.getFunction(mod)) |func| if (func.analysis(ip).is_cold)
+            try w.writeAll("zig_cold ");
         if (fn_info.return_type == .noreturn_type) try w.writeAll("zig_noreturn ");
 
-        const trailing = try renderTypePrefix(
-            dg.decl_index,
-            store.*,
-            mod,
-            w,
-            fn_cty_idx,
-            .suffix,
-            .{},
-        );
+        const trailing = try renderTypePrefix(dg.pass, store.*, mod, w, fn_cty_idx, .suffix, .{});
         try w.print("{}", .{trailing});
 
         if (toCallingConvention(fn_info.cc)) |call_conv| {
@@ -1597,7 +1596,7 @@ pub const DeclGen = struct {
         }
 
         try renderTypeSuffix(
-            dg.decl_index,
+            dg.pass,
             store.*,
             mod,
             w,
@@ -1652,8 +1651,8 @@ pub const DeclGen = struct {
     fn renderCType(dg: *DeclGen, w: anytype, idx: CType.Index) error{ OutOfMemory, AnalysisFail }!void {
         const store = &dg.ctypes.set;
         const mod = dg.module;
-        _ = try renderTypePrefix(dg.decl_index, store.*, mod, w, idx, .suffix, .{});
-        try renderTypeSuffix(dg.decl_index, store.*, mod, w, idx, .suffix, .{});
+        _ = try renderTypePrefix(dg.pass, store.*, mod, w, idx, .suffix, .{});
+        try renderTypeSuffix(dg.pass, store.*, mod, w, idx, .suffix, .{});
     }
 
     const IntCastContext = union(enum) {
@@ -1799,11 +1798,10 @@ pub const DeclGen = struct {
             .gt => try w.print("zig_align({}) ", .{alignas.toByteUnits()}),
         }
 
-        const trailing =
-            try renderTypePrefix(dg.decl_index, store.*, mod, w, cty_idx, .suffix, qualifiers);
+        const trailing = try renderTypePrefix(dg.pass, store.*, mod, w, cty_idx, .suffix, qualifiers);
         try w.print("{}", .{trailing});
         try dg.writeCValue(w, name);
-        try renderTypeSuffix(dg.decl_index, store.*, mod, w, cty_idx, .suffix, .{});
+        try renderTypeSuffix(dg.pass, store.*, mod, w, cty_idx, .suffix, .{});
     }
 
     fn declIsGlobal(dg: *DeclGen, tv: TypedValue) bool {
@@ -2070,7 +2068,7 @@ fn renderTypeName(
     }
 }
 fn renderTypePrefix(
-    decl: Decl.OptionalIndex,
+    pass: DeclGen.Pass,
     store: CType.Store.Set,
     mod: *Module,
     w: anytype,
@@ -2128,7 +2126,7 @@ fn renderTypePrefix(
         => |tag| {
             const child_idx = cty.cast(CType.Payload.Child).?.data;
             const child_trailing = try renderTypePrefix(
-                decl,
+                pass,
                 store,
                 mod,
                 w,
@@ -2152,15 +2150,8 @@ fn renderTypePrefix(
         .vector,
         => {
             const child_idx = cty.cast(CType.Payload.Sequence).?.data.elem_type;
-            const child_trailing = try renderTypePrefix(
-                decl,
-                store,
-                mod,
-                w,
-                child_idx,
-                .suffix,
-                qualifiers,
-            );
+            const child_trailing =
+                try renderTypePrefix(pass, store, mod, w, child_idx, .suffix, qualifiers);
             switch (parent_fix) {
                 .prefix => {
                     try w.print("{}(", .{child_trailing});
@@ -2172,10 +2163,11 @@ fn renderTypePrefix(
 
         .fwd_anon_struct,
         .fwd_anon_union,
-        => if (decl.unwrap()) |decl_index|
-            try w.print("anon__{d}_{d}", .{ @intFromEnum(decl_index), idx })
-        else
-            try renderTypeName(mod, w, idx, cty, ""),
+        => switch (pass) {
+            .decl => |decl_index| try w.print("decl__{d}_{d}", .{ @intFromEnum(decl_index), idx }),
+            .anon => |anon_decl| try w.print("anon__{d}_{d}", .{ @intFromEnum(anon_decl), idx }),
+            .flush => try renderTypeName(mod, w, idx, cty, ""),
+        },
 
         .fwd_struct,
         .fwd_union,
@@ -2201,7 +2193,7 @@ fn renderTypePrefix(
         .packed_struct,
         .packed_union,
         => return renderTypePrefix(
-            decl,
+            pass,
             store,
             mod,
             w,
@@ -2214,7 +2206,7 @@ fn renderTypePrefix(
         .varargs_function,
         => {
             const child_trailing = try renderTypePrefix(
-                decl,
+                pass,
                 store,
                 mod,
                 w,
@@ -2241,7 +2233,7 @@ fn renderTypePrefix(
     return trailing;
 }
 fn renderTypeSuffix(
-    decl: Decl.OptionalIndex,
+    pass: DeclGen.Pass,
     store: CType.Store.Set,
     mod: *Module,
     w: anytype,
@@ -2295,7 +2287,7 @@ fn renderTypeSuffix(
         .pointer_volatile,
         .pointer_const_volatile,
         => try renderTypeSuffix(
-            decl,
+            pass,
             store,
             mod,
             w,
@@ -2314,7 +2306,7 @@ fn renderTypeSuffix(
 
             try w.print("[{}]", .{cty.cast(CType.Payload.Sequence).?.data.len});
             try renderTypeSuffix(
-                decl,
+                pass,
                 store,
                 mod,
                 w,
@@ -2356,9 +2348,9 @@ fn renderTypeSuffix(
                 if (need_comma) try w.writeAll(", ");
                 need_comma = true;
                 const trailing =
-                    try renderTypePrefix(decl, store, mod, w, param_type, .suffix, qualifiers);
+                    try renderTypePrefix(pass, store, mod, w, param_type, .suffix, qualifiers);
                 if (qualifiers.contains(.@"const")) try w.print("{}a{d}", .{ trailing, param_i });
-                try renderTypeSuffix(decl, store, mod, w, param_type, .suffix, .{});
+                try renderTypeSuffix(pass, store, mod, w, param_type, .suffix, .{});
             }
             switch (tag) {
                 .function => {},
@@ -2372,7 +2364,7 @@ fn renderTypeSuffix(
             if (!need_comma) try w.writeAll("void");
             try w.writeByte(')');
 
-            try renderTypeSuffix(decl, store, mod, w, data.return_type, .suffix, .{});
+            try renderTypeSuffix(pass, store, mod, w, data.return_type, .suffix, .{});
         },
     }
 }
@@ -2392,9 +2384,9 @@ fn renderAggregateFields(
             .eq => {},
             .gt => try writer.print("zig_align({}) ", .{field.alignas.toByteUnits()}),
         }
-        const trailing = try renderTypePrefix(.none, store, mod, writer, field.type, .suffix, .{});
+        const trailing = try renderTypePrefix(.flush, store, mod, writer, field.type, .suffix, .{});
         try writer.print("{}{ }", .{ trailing, fmtIdent(mem.span(field.name)) });
-        try renderTypeSuffix(.none, store, mod, writer, field.type, .suffix, .{});
+        try renderTypeSuffix(.flush, store, mod, writer, field.type, .suffix, .{});
         try writer.writeAll(";\n");
     }
     try writer.writeByteNTimes(' ', indent);
@@ -2406,18 +2398,18 @@ pub fn genTypeDecl(
     writer: anytype,
     global_store: CType.Store.Set,
     global_idx: CType.Index,
-    decl: Decl.OptionalIndex,
+    pass: DeclGen.Pass,
     decl_store: CType.Store.Set,
     decl_idx: CType.Index,
     found_existing: bool,
 ) !void {
     const global_cty = global_store.indexToCType(global_idx);
     switch (global_cty.tag()) {
-        .fwd_anon_struct => if (decl != .none) {
+        .fwd_anon_struct => if (pass != .flush) {
             try writer.writeAll("typedef ");
-            _ = try renderTypePrefix(.none, global_store, mod, writer, global_idx, .suffix, .{});
+            _ = try renderTypePrefix(.flush, global_store, mod, writer, global_idx, .suffix, .{});
             try writer.writeByte(' ');
-            _ = try renderTypePrefix(decl, decl_store, mod, writer, decl_idx, .suffix, .{});
+            _ = try renderTypePrefix(pass, decl_store, mod, writer, decl_idx, .suffix, .{});
             try writer.writeAll(";\n");
         },
 
@@ -2435,7 +2427,15 @@ pub fn genTypeDecl(
                 .fwd_union,
                 => {
                     const owner_decl = global_cty.cast(CType.Payload.FwdDecl).?.data;
-                    _ = try renderTypePrefix(.none, global_store, mod, writer, global_idx, .suffix, .{});
+                    _ = try renderTypePrefix(
+                        .flush,
+                        global_store,
+                        mod,
+                        writer,
+                        global_idx,
+                        .suffix,
+                        .{},
+                    );
                     try writer.writeAll("; // ");
                     try mod.declPtr(owner_decl).renderFullyQualifiedName(mod, writer);
                     try writer.writeByte('\n');
@@ -2552,7 +2552,7 @@ fn genExports(o: *Object) !void {
 
     const mod = o.dg.module;
     const ip = &mod.intern_pool;
-    const decl_index = o.dg.decl_index.unwrap().?;
+    const decl_index = o.dg.pass.decl;
     const decl = mod.declPtr(decl_index);
     const tv: TypedValue = .{ .ty = decl.ty, .val = (try decl.internValue(mod)).toValue() };
     const fwd = o.dg.fwd_decl.writer();
@@ -2692,7 +2692,7 @@ pub fn genFunc(f: *Function) !void {
     const o = &f.object;
     const mod = o.dg.module;
     const gpa = o.dg.gpa;
-    const decl_index = o.dg.decl_index.unwrap().?;
+    const decl_index = o.dg.pass.decl;
     const decl = mod.declPtr(decl_index);
     const tv: TypedValue = .{
         .ty = decl.ty,
@@ -2779,7 +2779,7 @@ pub fn genDecl(o: *Object) !void {
     defer tracy.end();
 
     const mod = o.dg.module;
-    const decl_index = o.dg.decl_index.unwrap().?;
+    const decl_index = o.dg.pass.decl;
     const decl = mod.declPtr(decl_index);
     const tv: TypedValue = .{ .ty = decl.ty, .val = (try decl.internValue(mod)).toValue() };
 
@@ -2825,13 +2825,13 @@ pub fn genDeclValue(
     alignment: Alignment,
     link_section: InternPool.OptionalNullTerminatedString,
 ) !void {
+    const mod = o.dg.module;
     const fwd_decl_writer = o.dg.fwd_decl.writer();
 
     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|
@@ -2848,7 +2848,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
     defer tracy.end();
 
     const mod = dg.module;
-    const decl_index = dg.decl_index.unwrap().?;
+    const decl_index = dg.pass.decl;
     const decl = mod.declPtr(decl_index);
     const tv: TypedValue = .{
         .ty = decl.ty,
@@ -2861,7 +2861,7 @@ pub fn genHeader(dg: *DeclGen) error{ AnalysisFail, OutOfMemory }!void {
             const is_global = dg.declIsGlobal(tv);
             if (is_global) {
                 try writer.writeAll("zig_extern ");
-                try dg.renderFunctionSignature(writer, dg.decl_index.unwrap().?, .complete, .{ .export_index = 0 });
+                try dg.renderFunctionSignature(writer, dg.pass.decl, .complete, .{ .export_index = 0 });
                 try dg.fwd_decl.appendSlice(";\n");
             }
         },
@@ -7279,7 +7279,7 @@ fn airMulAdd(f: *Function, inst: Air.Inst.Index) !CValue {
 fn airCVaStart(f: *Function, inst: Air.Inst.Index) !CValue {
     const mod = f.object.dg.module;
     const inst_ty = f.typeOfIndex(inst);
-    const decl_index = f.object.dg.decl_index.unwrap().?;
+    const decl_index = f.object.dg.pass.decl;
     const decl = mod.declPtr(decl_index);
     const fn_cty = try f.typeToCType(decl.ty, .complete);
     const param_len = fn_cty.castTag(.varargs_function).?.data.param_types.len;
src/link/C.zig
@@ -158,9 +158,7 @@ pub fn updateFunc(
     const decl_index = func.owner_decl;
     const decl = module.declPtr(decl_index);
     const gop = try self.decl_table.getOrPut(gpa, decl_index);
-    if (!gop.found_existing) {
-        gop.value_ptr.* = .{};
-    }
+    if (!gop.found_existing) gop.value_ptr.* = .{};
     const ctypes = &gop.value_ptr.ctypes;
     const lazy_fns = &gop.value_ptr.lazy_fns;
     const fwd_decl = &self.fwd_decl_buf;
@@ -180,7 +178,7 @@ pub fn updateFunc(
                 .gpa = gpa,
                 .module = module,
                 .error_msg = null,
-                .decl_index = decl_index.toOptional(),
+                .pass = .{ .decl = decl_index },
                 .is_naked_fn = decl.ty.fnCallingConvention(module) == .Naked,
                 .fwd_decl = fwd_decl.toManaged(gpa),
                 .ctypes = ctypes.*,
@@ -235,7 +233,7 @@ fn updateAnonDecl(self: *C, module: *Module, i: usize) !void {
             .gpa = gpa,
             .module = module,
             .error_msg = null,
-            .decl_index = .none,
+            .pass = .{ .anon = anon_decl },
             .is_naked_fn = false,
             .fwd_decl = fwd_decl.toManaged(gpa),
             .ctypes = .{},
@@ -302,7 +300,7 @@ pub fn updateDecl(self: *C, module: *Module, decl_index: Module.Decl.Index) !voi
             .gpa = gpa,
             .module = module,
             .error_msg = null,
-            .decl_index = decl_index.toOptional(),
+            .pass = .{ .decl = decl_index },
             .is_naked_fn = false,
             .fwd_decl = fwd_decl.toManaged(gpa),
             .ctypes = ctypes.*,
@@ -438,14 +436,14 @@ pub fn flushModule(self: *C, _: *Compilation, prog_node: *std.Progress.Node) !vo
         // We need to flush lazy ctypes after flushing all decls but before flushing any decl ctypes.
         // This ensures that every lazy CType.Index exactly matches the global CType.Index.
         assert(f.ctypes.count() == 0);
-        try self.flushCTypes(&f, .none, f.lazy_ctypes);
+        try self.flushCTypes(&f, .flush, f.lazy_ctypes);
 
-        for (self.anon_decls.values()) |decl_block| {
-            try self.flushCTypes(&f, .none, decl_block.ctypes);
+        for (self.anon_decls.keys(), self.anon_decls.values()) |anon_decl, decl_block| {
+            try self.flushCTypes(&f, .{ .anon = anon_decl }, decl_block.ctypes);
         }
 
         for (self.decl_table.keys(), self.decl_table.values()) |decl_index, decl_block| {
-            try self.flushCTypes(&f, decl_index.toOptional(), decl_block.ctypes);
+            try self.flushCTypes(&f, .{ .decl = decl_index }, decl_block.ctypes);
         }
     }
 
@@ -516,7 +514,7 @@ const FlushDeclError = error{
 fn flushCTypes(
     self: *C,
     f: *Flush,
-    decl_index: Module.Decl.OptionalIndex,
+    pass: codegen.DeclGen.Pass,
     decl_ctypes: codegen.CType.Store,
 ) FlushDeclError!void {
     const gpa = self.base.allocator;
@@ -591,7 +589,7 @@ fn flushCTypes(
             writer,
             global_ctypes.set,
             global_idx,
-            decl_index,
+            pass,
             decl_ctypes.set,
             decl_idx,
             gop.found_existing,
@@ -610,7 +608,7 @@ fn flushErrDecls(self: *C, ctypes: *codegen.CType.Store) FlushDeclError!void {
             .gpa = gpa,
             .module = self.base.options.module.?,
             .error_msg = null,
-            .decl_index = .none,
+            .pass = .flush,
             .is_naked_fn = false,
             .fwd_decl = fwd_decl.toManaged(gpa),
             .ctypes = ctypes.*,
@@ -652,7 +650,7 @@ fn flushLazyFn(
             .gpa = gpa,
             .module = self.base.options.module.?,
             .error_msg = null,
-            .decl_index = .none,
+            .pass = .flush,
             .is_naked_fn = false,
             .fwd_decl = fwd_decl.toManaged(gpa),
             .ctypes = ctypes.*,
src/Compilation.zig
@@ -3556,7 +3556,7 @@ fn processOneJob(comp: *Compilation, job: Job, prog_node: *std.Progress.Node) !v
                         .gpa = gpa,
                         .module = module,
                         .error_msg = null,
-                        .decl_index = decl_index.toOptional(),
+                        .pass = .{ .decl = decl_index },
                         .is_naked_fn = false,
                         .fwd_decl = fwd_decl.toManaged(gpa),
                         .ctypes = .{},