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.
This commit is contained in:
Jacob Young 2022-10-23 08:12:10 -04:00
parent 8b6a3ba74e
commit 65a48df532
2 changed files with 15 additions and 19 deletions

View File

@ -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");

View File

@ -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 {