authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-23 08:12:10-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2022-10-25 05:11:29-04:00
log65a48df5324278c3d876e168b523894c8662e546
treec06ab8f0ddf444d82a8fa1524a6c9ac36cb5e1b0
parent8b6a3ba74ea50602284543382ff1729a60b75122

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.

2 files changed, 15 insertions(+), 19 deletions(-)

src/codegen/c.zig+11-9
......@@ -2027,10 +2027,10 @@ pub fn genDecl(o: *Object) !void {
20272027 .val = o.dg.decl.val,
20282028 };
20292029 if (tv.val.tag() == .extern_fn) {
2030 const writer = o.writer();
2031 try writer.writeAll("ZIG_EXTERN_C ");
2032 try o.dg.renderFunctionSignature(writer, .Forward);
2033 try writer.writeAll(";\n");
2030 const fwd_decl_writer = o.dg.fwd_decl.writer();
2031 try fwd_decl_writer.writeAll("ZIG_EXTERN_C ");
2032 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);
2033 try fwd_decl_writer.writeAll(";\n");
20342034 } else if (tv.val.castTag(.variable)) |var_payload| {
20352035 const variable: *Module.Var = var_payload.data;
20362036 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;
......@@ -2055,7 +2055,6 @@ pub fn genDecl(o: *Object) !void {
20552055 return;
20562056 }
20572057
2058 try o.indent_writer.insertNewline();
20592058 const w = o.writer();
20602059 try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
20612060 try w.writeAll(" = ");
......@@ -2065,15 +2064,18 @@ pub fn genDecl(o: *Object) !void {
20652064 try w.writeByte(';');
20662065 try o.indent_writer.insertNewline();
20672066 } else {
2067 const decl_c_value: CValue = .{ .decl = o.dg.decl_index };
2068
2069 const fwd_decl_writer = o.dg.fwd_decl.writer();
2070 try fwd_decl_writer.writeAll("static ");
2071 try o.dg.renderTypeAndName(fwd_decl_writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
2072 try fwd_decl_writer.writeAll(";\n");
2073
20682074 const writer = o.writer();
20692075 try writer.writeAll("static ");
2070
20712076 // TODO ask the Decl if it is const
20722077 // https://github.com/ziglang/zig/issues/7582
2073
2074 const decl_c_value: CValue = .{ .decl = o.dg.decl_index };
20752078 try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
2076
20772079 try writer.writeAll(" = ");
20782080 try o.dg.renderValue(writer, tv.ty, tv.val, .Initializer);
20792081 try writer.writeAll(";\n");
src/link/C.zig+4-10
......@@ -301,11 +301,10 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
301301 };
302302 f.file_size += f.typedef_buf.items.len;
303303
304 // Now the function bodies.
305 try f.all_buffers.ensureUnusedCapacity(gpa, f.fn_count);
306 for (decl_keys) |decl_index, i|
307 if (module.declPtr(decl_index).getFunction() != null)
308 f.appendBufAssumeCapacity(decl_values[i].code.items);
304 // Now the code.
305 try f.all_buffers.ensureUnusedCapacity(gpa, decl_values.len);
306 for (decl_values) |decl|
307 f.appendBufAssumeCapacity(decl.code.items);
309308
310309 const file = self.base.file.?;
311310 try file.setEndPos(f.file_size);
......@@ -322,7 +321,6 @@ const Flush = struct {
322321 all_buffers: std.ArrayListUnmanaged(std.os.iovec_const) = .{},
323322 /// Keeps track of the total bytes of `all_buffers`.
324323 file_size: u64 = 0,
325 fn_count: usize = 0,
326324
327325 const Typedefs = std.HashMapUnmanaged(
328326 Type,
......@@ -435,10 +433,6 @@ fn flushDecl(self: *C, f: *Flush, decl_index: Module.Decl.Index) FlushDeclError!
435433 try self.flushTypedefs(f, decl_block.typedefs);
436434 try f.all_buffers.ensureUnusedCapacity(gpa, 2);
437435 f.appendBufAssumeCapacity(decl_block.fwd_decl.items);
438 if (decl.getFunction()) |_|
439 f.fn_count += 1
440 else
441 f.appendBufAssumeCapacity(decl_block.code.items);
442436}
443437
444438pub fn flushEmitH(module: *Module) !void {