Commit 65a48df532

Jacob Young <jacobly0@users.noreply.github.com>
2022-10-23 14:12:10
cbe: fix globals that reference functions
Global constant initializers can reference functions, so forward declare the constants and initialize them later with the function definitions, which guarantees that they appear after all declarations.
1 parent 8b6a3ba
Changed files (2)
src
codegen
link
src/codegen/c.zig
@@ -2027,10 +2027,10 @@ pub fn genDecl(o: *Object) !void {
         .val = o.dg.decl.val,
     };
     if (tv.val.tag() == .extern_fn) {
-        const writer = o.writer();
-        try writer.writeAll("ZIG_EXTERN_C ");
-        try o.dg.renderFunctionSignature(writer, .Forward);
-        try writer.writeAll(";\n");
+        const fwd_decl_writer = o.dg.fwd_decl.writer();
+        try fwd_decl_writer.writeAll("ZIG_EXTERN_C ");
+        try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);
+        try fwd_decl_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) or variable.is_extern;
@@ -2055,7 +2055,6 @@ pub fn genDecl(o: *Object) !void {
             return;
         }
 
-        try o.indent_writer.insertNewline();
         const w = o.writer();
         try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
         try w.writeAll(" = ");
@@ -2065,15 +2064,18 @@ pub fn genDecl(o: *Object) !void {
         try w.writeByte(';');
         try o.indent_writer.insertNewline();
     } else {
+        const decl_c_value: CValue = .{ .decl = o.dg.decl_index };
+
+        const fwd_decl_writer = o.dg.fwd_decl.writer();
+        try fwd_decl_writer.writeAll("static ");
+        try o.dg.renderTypeAndName(fwd_decl_writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
+        try fwd_decl_writer.writeAll(";\n");
+
         const writer = o.writer();
         try writer.writeAll("static ");
-
         // TODO ask the Decl if it is const
         // https://github.com/ziglang/zig/issues/7582
-
-        const decl_c_value: CValue = .{ .decl = o.dg.decl_index };
         try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
-
         try writer.writeAll(" = ");
         try o.dg.renderValue(writer, tv.ty, tv.val, .Initializer);
         try writer.writeAll(";\n");
src/link/C.zig
@@ -301,11 +301,10 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
     };
     f.file_size += f.typedef_buf.items.len;
 
-    // Now the function bodies.
-    try f.all_buffers.ensureUnusedCapacity(gpa, f.fn_count);
-    for (decl_keys) |decl_index, i|
-        if (module.declPtr(decl_index).getFunction() != null)
-            f.appendBufAssumeCapacity(decl_values[i].code.items);
+    // Now the code.
+    try f.all_buffers.ensureUnusedCapacity(gpa, decl_values.len);
+    for (decl_values) |decl|
+        f.appendBufAssumeCapacity(decl.code.items);
 
     const file = self.base.file.?;
     try file.setEndPos(f.file_size);
@@ -322,7 +321,6 @@ const Flush = struct {
     all_buffers: std.ArrayListUnmanaged(std.os.iovec_const) = .{},
     /// Keeps track of the total bytes of `all_buffers`.
     file_size: u64 = 0,
-    fn_count: usize = 0,
 
     const Typedefs = std.HashMapUnmanaged(
         Type,
@@ -435,10 +433,6 @@ fn flushDecl(self: *C, f: *Flush, decl_index: Module.Decl.Index) FlushDeclError!
     try self.flushTypedefs(f, decl_block.typedefs);
     try f.all_buffers.ensureUnusedCapacity(gpa, 2);
     f.appendBufAssumeCapacity(decl_block.fwd_decl.items);
-    if (decl.getFunction()) |_|
-        f.fn_count += 1
-    else
-        f.appendBufAssumeCapacity(decl_block.code.items);
 }
 
 pub fn flushEmitH(module: *Module) !void {