diff --git a/src/link.zig b/src/link.zig index 3dbfb3b922..488f8bf69b 100644 --- a/src/link.zig +++ b/src/link.zig @@ -291,7 +291,7 @@ pub const File = struct { .coff => return @fieldParentPtr(Coff, "base", base).updateDecl(module, decl), .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl), .macho => return @fieldParentPtr(MachO, "base", base).updateDecl(module, decl), - .c => return @fieldParentPtr(C, "base", base).updateDecl(module, decl), + .c => {}, .wasm => return @fieldParentPtr(Wasm, "base", base).updateDecl(module, decl), } } @@ -412,7 +412,7 @@ pub const File = struct { .coff => @fieldParentPtr(Coff, "base", base).freeDecl(decl), .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl), .macho => @fieldParentPtr(MachO, "base", base).freeDecl(decl), - .c => unreachable, + .c => {}, .wasm => @fieldParentPtr(Wasm, "base", base).freeDecl(decl), } } diff --git a/src/link/C.zig b/src/link/C.zig index c3ab506b2c..5f38c9324f 100644 --- a/src/link/C.zig +++ b/src/link/C.zig @@ -8,10 +8,9 @@ const fs = std.fs; const codegen = @import("../codegen/c.zig"); const link = @import("../link.zig"); const trace = @import("../tracy.zig").trace; -const File = link.File; const C = @This(); -pub const base_tag: File.Tag = .c; +pub const base_tag: link.File.Tag = .c; pub const Header = struct { buf: std.ArrayList(u8), @@ -40,13 +39,16 @@ pub const Header = struct { } }; -base: File, +base: link.File, +path: []const u8, + +// These are only valid during a flush()! header: Header, constants: std.ArrayList(u8), main: std.ArrayList(u8), - called: std.StringHashMap(void), + error_msg: *Compilation.ErrorMsg = undefined, pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*C { @@ -55,9 +57,6 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio if (options.use_llvm) return error.LLVMHasNoCBackend; if (options.use_lld) return error.LLDHasNoCBackend; - const file = try options.emit.?.directory.handle.createFile(sub_path, .{ .truncate = true, .read = true, .mode = link.determineMode(options) }); - errdefer file.close(); - var c_file = try allocator.create(C); errdefer allocator.destroy(c_file); @@ -65,13 +64,14 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio .base = .{ .tag = .c, .options = options, - .file = file, + .file = null, .allocator = allocator, }, - .main = std.ArrayList(u8).init(allocator), - .header = Header.init(allocator, null), - .constants = std.ArrayList(u8).init(allocator), - .called = std.StringHashMap(void).init(allocator), + .main = undefined, + .header = undefined, + .constants = undefined, + .called = undefined, + .path = sub_path, }; return c_file; @@ -82,21 +82,7 @@ pub fn fail(self: *C, src: usize, comptime format: []const u8, args: anytype) er return error.AnalysisFail; } -pub fn deinit(self: *C) void { - self.main.deinit(); - self.header.deinit(); - self.constants.deinit(); - self.called.deinit(); -} - -pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void { - codegen.generate(self, module, decl) catch |err| { - if (err == error.AnalysisFail) { - try module.failed_decls.put(module.gpa, decl, self.error_msg); - } - return err; - }; -} +pub fn deinit(self: *C) void {} pub fn flush(self: *C, comp: *Compilation) !void { return self.flushModule(comp); @@ -106,7 +92,29 @@ pub fn flushModule(self: *C, comp: *Compilation) !void { const tracy = trace(@src()); defer tracy.end(); - const writer = self.base.file.?.writer(); + self.main = std.ArrayList(u8).init(self.base.allocator); + self.header = Header.init(self.base.allocator, null); + self.constants = std.ArrayList(u8).init(self.base.allocator); + self.called = std.StringHashMap(void).init(self.base.allocator); + defer self.main.deinit(); + defer self.header.deinit(); + defer self.constants.deinit(); + defer self.called.deinit(); + + const module = self.base.options.module.?; + for (self.base.options.module.?.decl_table.entries.items) |kv| { + codegen.generate(self, module, kv.value) catch |err| { + if (err == error.AnalysisFail) { + try module.failed_decls.put(module.gpa, kv.value, self.error_msg); + } + return err; + }; + } + + const file = try self.base.options.emit.?.directory.handle.createFile(self.path, .{ .truncate = true, .read = true, .mode = link.determineMode(self.base.options) }); + defer file.close(); + + const writer = file.writer(); try self.header.flush(writer); if (self.header.buf.items.len > 0) { try writer.writeByte('\n'); @@ -121,6 +129,4 @@ pub fn flushModule(self: *C, comp: *Compilation) !void { } } try writer.writeAll(self.main.items); - self.base.file.?.close(); - self.base.file = null; } diff --git a/test/stage2/cbe.zig b/test/stage2/cbe.zig index b227d6a783..a740a8851a 100644 --- a/test/stage2/cbe.zig +++ b/test/stage2/cbe.zig @@ -24,13 +24,13 @@ pub fn addCases(ctx: *TestContext) !void { // Now change the message only // TODO fix C backend not supporting updates // https://github.com/ziglang/zig/issues/7589 - //case.addCompareOutput( - // \\extern fn puts(s: [*:0]const u8) c_int; - // \\export fn main() c_int { - // \\ _ = puts("yo"); - // \\ return 0; - // \\} - //, "yo" ++ std.cstr.line_sep); + case.addCompareOutput( + \\extern fn puts(s: [*:0]const u8) c_int; + \\export fn main() c_int { + \\ _ = puts("yo"); + \\ return 0; + \\} + , "yo" ++ std.cstr.line_sep); } { @@ -111,15 +111,15 @@ pub fn addCases(ctx: *TestContext) !void { , \\static zig_noreturn void main(void); \\ - \\zig_noreturn void _start(void) { - \\ main(); - \\} - \\ \\static zig_noreturn void main(void) { \\ zig_breakpoint(); \\ zig_unreachable(); \\} \\ + \\zig_noreturn void _start(void) { + \\ main(); + \\} + \\ ); // TODO: implement return values // TODO: figure out a way to prevent asm constants from being generated @@ -143,10 +143,6 @@ pub fn addCases(ctx: *TestContext) !void { \\static uint8_t exitGood__anon_1[6] = "{rdi}"; \\static uint8_t exitGood__anon_2[8] = "syscall"; \\ - \\zig_noreturn void _start(void) { - \\ exitGood(); - \\} - \\ \\static zig_noreturn void exitGood(void) { \\ register uintptr_t rax_constant __asm__("rax") = 231; \\ register uintptr_t rdi_constant __asm__("rdi") = 0; @@ -155,6 +151,10 @@ pub fn addCases(ctx: *TestContext) !void { \\ zig_unreachable(); \\} \\ + \\zig_noreturn void _start(void) { + \\ exitGood(); + \\} + \\ ); ctx.c("exit with parameter", linux_x64, \\export fn _start() noreturn {