| author | |
| committer | |
| log | 9360e5887ce0bf0ce204eb49f0d0b253348ef557 |
| tree | 30d5775253ec1f8a913c8c87aa952534b6bc19ea |
| parent | 6c4924408b1957d493568271a0158b1190574dd0 |
* CBE buffers are only valid during a flush()
* the file is reopened and truncated during each flush()
* CBE now explicitly ignores updateDecl and deleteDecl
* CBE updateDecl is gone
* test case is enabled3 files changed, 53 insertions(+), 47 deletions(-)
src/link.zig+2-2| ... | ... | @@ -291,7 +291,7 @@ pub const File = struct { |
| 291 | 291 | .coff => return @fieldParentPtr(Coff, "base", base).updateDecl(module, decl), |
| 292 | 292 | .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl), |
| 293 | 293 | .macho => return @fieldParentPtr(MachO, "base", base).updateDecl(module, decl), |
| 294 | .c => return @fieldParentPtr(C, "base", base).updateDecl(module, decl), | |
| 294 | .c => {}, | |
| 295 | 295 | .wasm => return @fieldParentPtr(Wasm, "base", base).updateDecl(module, decl), |
| 296 | 296 | } |
| 297 | 297 | } |
| ... | ... | @@ -412,7 +412,7 @@ pub const File = struct { |
| 412 | 412 | .coff => @fieldParentPtr(Coff, "base", base).freeDecl(decl), |
| 413 | 413 | .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl), |
| 414 | 414 | .macho => @fieldParentPtr(MachO, "base", base).freeDecl(decl), |
| 415 | .c => unreachable, | |
| 415 | .c => {}, | |
| 416 | 416 | .wasm => @fieldParentPtr(Wasm, "base", base).freeDecl(decl), |
| 417 | 417 | } |
| 418 | 418 | } |
src/link/C.zig+36-30| ... | ... | @@ -8,10 +8,9 @@ const fs = std.fs; |
| 8 | 8 | const codegen = @import("../codegen/c.zig"); |
| 9 | 9 | const link = @import("../link.zig"); |
| 10 | 10 | const trace = @import("../tracy.zig").trace; |
| 11 | const File = link.File; | |
| 12 | 11 | const C = @This(); |
| 13 | 12 | |
| 14 | pub const base_tag: File.Tag = .c; | |
| 13 | pub const base_tag: link.File.Tag = .c; | |
| 15 | 14 | |
| 16 | 15 | pub const Header = struct { |
| 17 | 16 | buf: std.ArrayList(u8), |
| ... | ... | @@ -40,13 +39,16 @@ pub const Header = struct { |
| 40 | 39 | } |
| 41 | 40 | }; |
| 42 | 41 | |
| 43 | base: File, | |
| 42 | base: link.File, | |
| 44 | 43 | |
| 44 | path: []const u8, | |
| 45 | ||
| 46 | // These are only valid during a flush()! | |
| 45 | 47 | header: Header, |
| 46 | 48 | constants: std.ArrayList(u8), |
| 47 | 49 | main: std.ArrayList(u8), |
| 48 | ||
| 49 | 50 | called: std.StringHashMap(void), |
| 51 | ||
| 50 | 52 | error_msg: *Compilation.ErrorMsg = undefined, |
| 51 | 53 | |
| 52 | 54 | 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 |
| 55 | 57 | if (options.use_llvm) return error.LLVMHasNoCBackend; |
| 56 | 58 | if (options.use_lld) return error.LLDHasNoCBackend; |
| 57 | 59 | |
| 58 | const file = try options.emit.?.directory.handle.createFile(sub_path, .{ .truncate = true, .read = true, .mode = link.determineMode(options) }); | |
| 59 | errdefer file.close(); | |
| 60 | ||
| 61 | 60 | var c_file = try allocator.create(C); |
| 62 | 61 | errdefer allocator.destroy(c_file); |
| 63 | 62 | |
| ... | ... | @@ -65,13 +64,14 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio |
| 65 | 64 | .base = .{ |
| 66 | 65 | .tag = .c, |
| 67 | 66 | .options = options, |
| 68 | .file = file, | |
| 67 | .file = null, | |
| 69 | 68 | .allocator = allocator, |
| 70 | 69 | }, |
| 71 | .main = std.ArrayList(u8).init(allocator), | |
| 72 | .header = Header.init(allocator, null), | |
| 73 | .constants = std.ArrayList(u8).init(allocator), | |
| 74 | .called = std.StringHashMap(void).init(allocator), | |
| 70 | .main = undefined, | |
| 71 | .header = undefined, | |
| 72 | .constants = undefined, | |
| 73 | .called = undefined, | |
| 74 | .path = sub_path, | |
| 75 | 75 | }; |
| 76 | 76 | |
| 77 | 77 | return c_file; |
| ... | ... | @@ -82,21 +82,7 @@ pub fn fail(self: *C, src: usize, comptime format: []const u8, args: anytype) er |
| 82 | 82 | return error.AnalysisFail; |
| 83 | 83 | } |
| 84 | 84 | |
| 85 | pub fn deinit(self: *C) void { | |
| 86 | self.main.deinit(); | |
| 87 | self.header.deinit(); | |
| 88 | self.constants.deinit(); | |
| 89 | self.called.deinit(); | |
| 90 | } | |
| 91 | ||
| 92 | pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void { | |
| 93 | codegen.generate(self, module, decl) catch |err| { | |
| 94 | if (err == error.AnalysisFail) { | |
| 95 | try module.failed_decls.put(module.gpa, decl, self.error_msg); | |
| 96 | } | |
| 97 | return err; | |
| 98 | }; | |
| 99 | } | |
| 85 | pub fn deinit(self: *C) void {} | |
| 100 | 86 | |
| 101 | 87 | pub fn flush(self: *C, comp: *Compilation) !void { |
| 102 | 88 | return self.flushModule(comp); |
| ... | ... | @@ -106,7 +92,29 @@ pub fn flushModule(self: *C, comp: *Compilation) !void { |
| 106 | 92 | const tracy = trace(@src()); |
| 107 | 93 | defer tracy.end(); |
| 108 | 94 | |
| 109 | const writer = self.base.file.?.writer(); | |
| 95 | self.main = std.ArrayList(u8).init(self.base.allocator); | |
| 96 | self.header = Header.init(self.base.allocator, null); | |
| 97 | self.constants = std.ArrayList(u8).init(self.base.allocator); | |
| 98 | self.called = std.StringHashMap(void).init(self.base.allocator); | |
| 99 | defer self.main.deinit(); | |
| 100 | defer self.header.deinit(); | |
| 101 | defer self.constants.deinit(); | |
| 102 | defer self.called.deinit(); | |
| 103 | ||
| 104 | const module = self.base.options.module.?; | |
| 105 | for (self.base.options.module.?.decl_table.entries.items) |kv| { | |
| 106 | codegen.generate(self, module, kv.value) catch |err| { | |
| 107 | if (err == error.AnalysisFail) { | |
| 108 | try module.failed_decls.put(module.gpa, kv.value, self.error_msg); | |
| 109 | } | |
| 110 | return err; | |
| 111 | }; | |
| 112 | } | |
| 113 | ||
| 114 | const file = try self.base.options.emit.?.directory.handle.createFile(self.path, .{ .truncate = true, .read = true, .mode = link.determineMode(self.base.options) }); | |
| 115 | defer file.close(); | |
| 116 | ||
| 117 | const writer = file.writer(); | |
| 110 | 118 | try self.header.flush(writer); |
| 111 | 119 | if (self.header.buf.items.len > 0) { |
| 112 | 120 | try writer.writeByte('\n'); |
| ... | ... | @@ -121,6 +129,4 @@ pub fn flushModule(self: *C, comp: *Compilation) !void { |
| 121 | 129 | } |
| 122 | 130 | } |
| 123 | 131 | try writer.writeAll(self.main.items); |
| 124 | self.base.file.?.close(); | |
| 125 | self.base.file = null; | |
| 126 | 132 | } |
test/stage2/cbe.zig+15-15| ... | ... | @@ -24,13 +24,13 @@ pub fn addCases(ctx: *TestContext) !void { |
| 24 | 24 | // Now change the message only |
| 25 | 25 | // TODO fix C backend not supporting updates |
| 26 | 26 | // https://github.com/ziglang/zig/issues/7589 |
| 27 | //case.addCompareOutput( | |
| 28 | // \\extern fn puts(s: [*:0]const u8) c_int; | |
| 29 | // \\export fn main() c_int { | |
| 30 | // \\ _ = puts("yo"); | |
| 31 | // \\ return 0; | |
| 32 | // \\} | |
| 33 | //, "yo" ++ std.cstr.line_sep); | |
| 27 | case.addCompareOutput( | |
| 28 | \\extern fn puts(s: [*:0]const u8) c_int; | |
| 29 | \\export fn main() c_int { | |
| 30 | \\ _ = puts("yo"); | |
| 31 | \\ return 0; | |
| 32 | \\} | |
| 33 | , "yo" ++ std.cstr.line_sep); | |
| 34 | 34 | } |
| 35 | 35 | |
| 36 | 36 | { |
| ... | ... | @@ -111,15 +111,15 @@ pub fn addCases(ctx: *TestContext) !void { |
| 111 | 111 | , |
| 112 | 112 | \\static zig_noreturn void main(void); |
| 113 | 113 | \\ |
| 114 | \\zig_noreturn void _start(void) { | |
| 115 | \\ main(); | |
| 116 | \\} | |
| 117 | \\ | |
| 118 | 114 | \\static zig_noreturn void main(void) { |
| 119 | 115 | \\ zig_breakpoint(); |
| 120 | 116 | \\ zig_unreachable(); |
| 121 | 117 | \\} |
| 122 | 118 | \\ |
| 119 | \\zig_noreturn void _start(void) { | |
| 120 | \\ main(); | |
| 121 | \\} | |
| 122 | \\ | |
| 123 | 123 | ); |
| 124 | 124 | // TODO: implement return values |
| 125 | 125 | // TODO: figure out a way to prevent asm constants from being generated |
| ... | ... | @@ -143,10 +143,6 @@ pub fn addCases(ctx: *TestContext) !void { |
| 143 | 143 | \\static uint8_t exitGood__anon_1[6] = "{rdi}"; |
| 144 | 144 | \\static uint8_t exitGood__anon_2[8] = "syscall"; |
| 145 | 145 | \\ |
| 146 | \\zig_noreturn void _start(void) { | |
| 147 | \\ exitGood(); | |
| 148 | \\} | |
| 149 | \\ | |
| 150 | 146 | \\static zig_noreturn void exitGood(void) { |
| 151 | 147 | \\ register uintptr_t rax_constant __asm__("rax") = 231; |
| 152 | 148 | \\ register uintptr_t rdi_constant __asm__("rdi") = 0; |
| ... | ... | @@ -155,6 +151,10 @@ pub fn addCases(ctx: *TestContext) !void { |
| 155 | 151 | \\ zig_unreachable(); |
| 156 | 152 | \\} |
| 157 | 153 | \\ |
| 154 | \\zig_noreturn void _start(void) { | |
| 155 | \\ exitGood(); | |
| 156 | \\} | |
| 157 | \\ | |
| 158 | 158 | ); |
| 159 | 159 | ctx.c("exit with parameter", linux_x64, |
| 160 | 160 | \\export fn _start() noreturn { |