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 {...@@ -2027,10 +2027,10 @@ pub fn genDecl(o: *Object) !void {
2027 .val = o.dg.decl.val,2027 .val = o.dg.decl.val,
2028 };2028 };
2029 if (tv.val.tag() == .extern_fn) {2029 if (tv.val.tag() == .extern_fn) {
2030 const writer = o.writer();2030 const fwd_decl_writer = o.dg.fwd_decl.writer();
2031 try writer.writeAll("ZIG_EXTERN_C ");2031 try fwd_decl_writer.writeAll("ZIG_EXTERN_C ");
2032 try o.dg.renderFunctionSignature(writer, .Forward);2032 try o.dg.renderFunctionSignature(fwd_decl_writer, .Forward);
2033 try writer.writeAll(";\n");2033 try fwd_decl_writer.writeAll(";\n");
2034 } else if (tv.val.castTag(.variable)) |var_payload| {2034 } else if (tv.val.castTag(.variable)) |var_payload| {
2035 const variable: *Module.Var = var_payload.data;2035 const variable: *Module.Var = var_payload.data;
2036 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;2036 const is_global = o.dg.declIsGlobal(tv) or variable.is_extern;
...@@ -2055,7 +2055,6 @@ pub fn genDecl(o: *Object) !void {...@@ -2055,7 +2055,6 @@ pub fn genDecl(o: *Object) !void {
2055 return;2055 return;
2056 }2056 }
20572057
2058 try o.indent_writer.insertNewline();
2059 const w = o.writer();2058 const w = o.writer();
2060 try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);2059 try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
2061 try w.writeAll(" = ");2060 try w.writeAll(" = ");
...@@ -2065,15 +2064,18 @@ pub fn genDecl(o: *Object) !void {...@@ -2065,15 +2064,18 @@ pub fn genDecl(o: *Object) !void {
2065 try w.writeByte(';');2064 try w.writeByte(';');
2066 try o.indent_writer.insertNewline();2065 try o.indent_writer.insertNewline();
2067 } else {2066 } 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
2068 const writer = o.writer();2074 const writer = o.writer();
2069 try writer.writeAll("static ");2075 try writer.writeAll("static ");
2070
2071 // TODO ask the Decl if it is const2076 // TODO ask the Decl if it is const
2072 // https://github.com/ziglang/zig/issues/75822077 // https://github.com/ziglang/zig/issues/7582
2073
2074 const decl_c_value: CValue = .{ .decl = o.dg.decl_index };
2075 try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);2078 try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align", .Complete);
2076
2077 try writer.writeAll(" = ");2079 try writer.writeAll(" = ");
2078 try o.dg.renderValue(writer, tv.ty, tv.val, .Initializer);2080 try o.dg.renderValue(writer, tv.ty, tv.val, .Initializer);
2079 try writer.writeAll(";\n");2081 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)...@@ -301,11 +301,10 @@ pub fn flushModule(self: *C, comp: *Compilation, prog_node: *std.Progress.Node)
301 };301 };
302 f.file_size += f.typedef_buf.items.len;302 f.file_size += f.typedef_buf.items.len;
303303
304 // Now the function bodies.304 // Now the code.
305 try f.all_buffers.ensureUnusedCapacity(gpa, f.fn_count);305 try f.all_buffers.ensureUnusedCapacity(gpa, decl_values.len);
306 for (decl_keys) |decl_index, i|306 for (decl_values) |decl|
307 if (module.declPtr(decl_index).getFunction() != null)307 f.appendBufAssumeCapacity(decl.code.items);
308 f.appendBufAssumeCapacity(decl_values[i].code.items);
309308
310 const file = self.base.file.?;309 const file = self.base.file.?;
311 try file.setEndPos(f.file_size);310 try file.setEndPos(f.file_size);
...@@ -322,7 +321,6 @@ const Flush = struct {...@@ -322,7 +321,6 @@ const Flush = struct {
322 all_buffers: std.ArrayListUnmanaged(std.os.iovec_const) = .{},321 all_buffers: std.ArrayListUnmanaged(std.os.iovec_const) = .{},
323 /// Keeps track of the total bytes of `all_buffers`.322 /// Keeps track of the total bytes of `all_buffers`.
324 file_size: u64 = 0,323 file_size: u64 = 0,
325 fn_count: usize = 0,
326324
327 const Typedefs = std.HashMapUnmanaged(325 const Typedefs = std.HashMapUnmanaged(
328 Type,326 Type,
...@@ -435,10 +433,6 @@ fn flushDecl(self: *C, f: *Flush, decl_index: Module.Decl.Index) FlushDeclError!...@@ -435,10 +433,6 @@ fn flushDecl(self: *C, f: *Flush, decl_index: Module.Decl.Index) FlushDeclError!
435 try self.flushTypedefs(f, decl_block.typedefs);433 try self.flushTypedefs(f, decl_block.typedefs);
436 try f.all_buffers.ensureUnusedCapacity(gpa, 2);434 try f.all_buffers.ensureUnusedCapacity(gpa, 2);
437 f.appendBufAssumeCapacity(decl_block.fwd_decl.items);435 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);
442}436}
443437
444pub fn flushEmitH(module: *Module) !void {438pub fn flushEmitH(module: *Module) !void {