authorgravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-12-30 05:22:50-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-05 17:41:14-07:00
log9360e5887ce0bf0ce204eb49f0d0b253348ef557
tree30d5775253ec1f8a913c8c87aa952534b6bc19ea
parent6c4924408b1957d493568271a0158b1190574dd0

integrate CBE with Compilation.update pipeline (closes #7589)

* 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 enabled

3 files changed, 53 insertions(+), 47 deletions(-)

src/link.zig+2-2
...@@ -291,7 +291,7 @@ pub const File = struct {...@@ -291,7 +291,7 @@ pub const File = struct {
291 .coff => return @fieldParentPtr(Coff, "base", base).updateDecl(module, decl),291 .coff => return @fieldParentPtr(Coff, "base", base).updateDecl(module, decl),
292 .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),292 .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),
293 .macho => return @fieldParentPtr(MachO, "base", base).updateDecl(module, decl),293 .macho => return @fieldParentPtr(MachO, "base", base).updateDecl(module, decl),
294 .c => return @fieldParentPtr(C, "base", base).updateDecl(module, decl),294 .c => {},
295 .wasm => return @fieldParentPtr(Wasm, "base", base).updateDecl(module, decl),295 .wasm => return @fieldParentPtr(Wasm, "base", base).updateDecl(module, decl),
296 }296 }
297 }297 }
...@@ -412,7 +412,7 @@ pub const File = struct {...@@ -412,7 +412,7 @@ pub const File = struct {
412 .coff => @fieldParentPtr(Coff, "base", base).freeDecl(decl),412 .coff => @fieldParentPtr(Coff, "base", base).freeDecl(decl),
413 .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl),413 .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl),
414 .macho => @fieldParentPtr(MachO, "base", base).freeDecl(decl),414 .macho => @fieldParentPtr(MachO, "base", base).freeDecl(decl),
415 .c => unreachable,415 .c => {},
416 .wasm => @fieldParentPtr(Wasm, "base", base).freeDecl(decl),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,10 +8,9 @@ const fs = std.fs;
8const codegen = @import("../codegen/c.zig");8const codegen = @import("../codegen/c.zig");
9const link = @import("../link.zig");9const link = @import("../link.zig");
10const trace = @import("../tracy.zig").trace;10const trace = @import("../tracy.zig").trace;
11const File = link.File;
12const C = @This();11const C = @This();
1312
14pub const base_tag: File.Tag = .c;13pub const base_tag: link.File.Tag = .c;
1514
16pub const Header = struct {15pub const Header = struct {
17 buf: std.ArrayList(u8),16 buf: std.ArrayList(u8),
...@@ -40,13 +39,16 @@ pub const Header = struct {...@@ -40,13 +39,16 @@ pub const Header = struct {
40 }39 }
41};40};
4241
43base: File,42base: link.File,
4443
44path: []const u8,
45
46// These are only valid during a flush()!
45header: Header,47header: Header,
46constants: std.ArrayList(u8),48constants: std.ArrayList(u8),
47main: std.ArrayList(u8),49main: std.ArrayList(u8),
48
49called: std.StringHashMap(void),50called: std.StringHashMap(void),
51
50error_msg: *Compilation.ErrorMsg = undefined,52error_msg: *Compilation.ErrorMsg = undefined,
5153
52pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*C {54pub 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,9 +57,6 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
55 if (options.use_llvm) return error.LLVMHasNoCBackend;57 if (options.use_llvm) return error.LLVMHasNoCBackend;
56 if (options.use_lld) return error.LLDHasNoCBackend;58 if (options.use_lld) return error.LLDHasNoCBackend;
5759
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 var c_file = try allocator.create(C);60 var c_file = try allocator.create(C);
62 errdefer allocator.destroy(c_file);61 errdefer allocator.destroy(c_file);
6362
...@@ -65,13 +64,14 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio...@@ -65,13 +64,14 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
65 .base = .{64 .base = .{
66 .tag = .c,65 .tag = .c,
67 .options = options,66 .options = options,
68 .file = file,67 .file = null,
69 .allocator = allocator,68 .allocator = allocator,
70 },69 },
71 .main = std.ArrayList(u8).init(allocator),70 .main = undefined,
72 .header = Header.init(allocator, null),71 .header = undefined,
73 .constants = std.ArrayList(u8).init(allocator),72 .constants = undefined,
74 .called = std.StringHashMap(void).init(allocator),73 .called = undefined,
74 .path = sub_path,
75 };75 };
7676
77 return c_file;77 return c_file;
...@@ -82,21 +82,7 @@ pub fn fail(self: *C, src: usize, comptime format: []const u8, args: anytype) er...@@ -82,21 +82,7 @@ pub fn fail(self: *C, src: usize, comptime format: []const u8, args: anytype) er
82 return error.AnalysisFail;82 return error.AnalysisFail;
83}83}
8484
85pub fn deinit(self: *C) void {85pub fn deinit(self: *C) void {}
86 self.main.deinit();
87 self.header.deinit();
88 self.constants.deinit();
89 self.called.deinit();
90}
91
92pub 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}
10086
101pub fn flush(self: *C, comp: *Compilation) !void {87pub fn flush(self: *C, comp: *Compilation) !void {
102 return self.flushModule(comp);88 return self.flushModule(comp);
...@@ -106,7 +92,29 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {...@@ -106,7 +92,29 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
106 const tracy = trace(@src());92 const tracy = trace(@src());
107 defer tracy.end();93 defer tracy.end();
10894
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 try self.header.flush(writer);118 try self.header.flush(writer);
111 if (self.header.buf.items.len > 0) {119 if (self.header.buf.items.len > 0) {
112 try writer.writeByte('\n');120 try writer.writeByte('\n');
...@@ -121,6 +129,4 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {...@@ -121,6 +129,4 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
121 }129 }
122 }130 }
123 try writer.writeAll(self.main.items);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,13 +24,13 @@ pub fn addCases(ctx: *TestContext) !void {
24 // Now change the message only24 // Now change the message only
25 // TODO fix C backend not supporting updates25 // TODO fix C backend not supporting updates
26 // https://github.com/ziglang/zig/issues/758926 // https://github.com/ziglang/zig/issues/7589
27 //case.addCompareOutput(27 case.addCompareOutput(
28 // \\extern fn puts(s: [*:0]const u8) c_int;28 \\extern fn puts(s: [*:0]const u8) c_int;
29 // \\export fn main() c_int {29 \\export fn main() c_int {
30 // \\ _ = puts("yo");30 \\ _ = puts("yo");
31 // \\ return 0;31 \\ return 0;
32 // \\}32 \\}
33 //, "yo" ++ std.cstr.line_sep);33 , "yo" ++ std.cstr.line_sep);
34 }34 }
3535
36 {36 {
...@@ -111,15 +111,15 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -111,15 +111,15 @@ pub fn addCases(ctx: *TestContext) !void {
111 ,111 ,
112 \\static zig_noreturn void main(void);112 \\static zig_noreturn void main(void);
113 \\113 \\
114 \\zig_noreturn void _start(void) {
115 \\ main();
116 \\}
117 \\
118 \\static zig_noreturn void main(void) {114 \\static zig_noreturn void main(void) {
119 \\ zig_breakpoint();115 \\ zig_breakpoint();
120 \\ zig_unreachable();116 \\ zig_unreachable();
121 \\}117 \\}
122 \\118 \\
119 \\zig_noreturn void _start(void) {
120 \\ main();
121 \\}
122 \\
123 );123 );
124 // TODO: implement return values124 // TODO: implement return values
125 // TODO: figure out a way to prevent asm constants from being generated125 // TODO: figure out a way to prevent asm constants from being generated
...@@ -143,10 +143,6 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -143,10 +143,6 @@ pub fn addCases(ctx: *TestContext) !void {
143 \\static uint8_t exitGood__anon_1[6] = "{rdi}";143 \\static uint8_t exitGood__anon_1[6] = "{rdi}";
144 \\static uint8_t exitGood__anon_2[8] = "syscall";144 \\static uint8_t exitGood__anon_2[8] = "syscall";
145 \\145 \\
146 \\zig_noreturn void _start(void) {
147 \\ exitGood();
148 \\}
149 \\
150 \\static zig_noreturn void exitGood(void) {146 \\static zig_noreturn void exitGood(void) {
151 \\ register uintptr_t rax_constant __asm__("rax") = 231;147 \\ register uintptr_t rax_constant __asm__("rax") = 231;
152 \\ register uintptr_t rdi_constant __asm__("rdi") = 0;148 \\ register uintptr_t rdi_constant __asm__("rdi") = 0;
...@@ -155,6 +151,10 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -155,6 +151,10 @@ pub fn addCases(ctx: *TestContext) !void {
155 \\ zig_unreachable();151 \\ zig_unreachable();
156 \\}152 \\}
157 \\153 \\
154 \\zig_noreturn void _start(void) {
155 \\ exitGood();
156 \\}
157 \\
158 );158 );
159 ctx.c("exit with parameter", linux_x64,159 ctx.c("exit with parameter", linux_x64,
160 \\export fn _start() noreturn {160 \\export fn _start() noreturn {