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 {
291291 .coff => return @fieldParentPtr(Coff, "base", base).updateDecl(module, decl),
292292 .elf => return @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),
293293 .macho => return @fieldParentPtr(MachO, "base", base).updateDecl(module, decl),
294 .c => return @fieldParentPtr(C, "base", base).updateDecl(module, decl),
294 .c => {},
295295 .wasm => return @fieldParentPtr(Wasm, "base", base).updateDecl(module, decl),
296296 }
297297 }
......@@ -412,7 +412,7 @@ pub const File = struct {
412412 .coff => @fieldParentPtr(Coff, "base", base).freeDecl(decl),
413413 .elf => @fieldParentPtr(Elf, "base", base).freeDecl(decl),
414414 .macho => @fieldParentPtr(MachO, "base", base).freeDecl(decl),
415 .c => unreachable,
415 .c => {},
416416 .wasm => @fieldParentPtr(Wasm, "base", base).freeDecl(decl),
417417 }
418418 }
src/link/C.zig+36-30
......@@ -8,10 +8,9 @@ const fs = std.fs;
88const codegen = @import("../codegen/c.zig");
99const link = @import("../link.zig");
1010const trace = @import("../tracy.zig").trace;
11const File = link.File;
1211const C = @This();
1312
14pub const base_tag: File.Tag = .c;
13pub const base_tag: link.File.Tag = .c;
1514
1615pub const Header = struct {
1716 buf: std.ArrayList(u8),
......@@ -40,13 +39,16 @@ pub const Header = struct {
4039 }
4140};
4241
43base: File,
42base: link.File,
4443
44path: []const u8,
45
46// These are only valid during a flush()!
4547header: Header,
4648constants: std.ArrayList(u8),
4749main: std.ArrayList(u8),
48
4950called: std.StringHashMap(void),
51
5052error_msg: *Compilation.ErrorMsg = undefined,
5153
5254pub 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
5557 if (options.use_llvm) return error.LLVMHasNoCBackend;
5658 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
6160 var c_file = try allocator.create(C);
6261 errdefer allocator.destroy(c_file);
6362
......@@ -65,13 +64,14 @@ pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Optio
6564 .base = .{
6665 .tag = .c,
6766 .options = options,
68 .file = file,
67 .file = null,
6968 .allocator = allocator,
7069 },
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,
7575 };
7676
7777 return c_file;
......@@ -82,21 +82,7 @@ pub fn fail(self: *C, src: usize, comptime format: []const u8, args: anytype) er
8282 return error.AnalysisFail;
8383}
8484
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}
85pub fn deinit(self: *C) void {}
10086
10187pub fn flush(self: *C, comp: *Compilation) !void {
10288 return self.flushModule(comp);
......@@ -106,7 +92,29 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
10692 const tracy = trace(@src());
10793 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();
110118 try self.header.flush(writer);
111119 if (self.header.buf.items.len > 0) {
112120 try writer.writeByte('\n');
......@@ -121,6 +129,4 @@ pub fn flushModule(self: *C, comp: *Compilation) !void {
121129 }
122130 }
123131 try writer.writeAll(self.main.items);
124 self.base.file.?.close();
125 self.base.file = null;
126132}
test/stage2/cbe.zig+15-15
......@@ -24,13 +24,13 @@ pub fn addCases(ctx: *TestContext) !void {
2424 // Now change the message only
2525 // TODO fix C backend not supporting updates
2626 // 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);
3434 }
3535
3636 {
......@@ -111,15 +111,15 @@ pub fn addCases(ctx: *TestContext) !void {
111111 ,
112112 \\static zig_noreturn void main(void);
113113 \\
114 \\zig_noreturn void _start(void) {
115 \\ main();
116 \\}
117 \\
118114 \\static zig_noreturn void main(void) {
119115 \\ zig_breakpoint();
120116 \\ zig_unreachable();
121117 \\}
122118 \\
119 \\zig_noreturn void _start(void) {
120 \\ main();
121 \\}
122 \\
123123 );
124124 // TODO: implement return values
125125 // TODO: figure out a way to prevent asm constants from being generated
......@@ -143,10 +143,6 @@ pub fn addCases(ctx: *TestContext) !void {
143143 \\static uint8_t exitGood__anon_1[6] = "{rdi}";
144144 \\static uint8_t exitGood__anon_2[8] = "syscall";
145145 \\
146 \\zig_noreturn void _start(void) {
147 \\ exitGood();
148 \\}
149 \\
150146 \\static zig_noreturn void exitGood(void) {
151147 \\ register uintptr_t rax_constant __asm__("rax") = 231;
152148 \\ register uintptr_t rdi_constant __asm__("rdi") = 0;
......@@ -155,6 +151,10 @@ pub fn addCases(ctx: *TestContext) !void {
155151 \\ zig_unreachable();
156152 \\}
157153 \\
154 \\zig_noreturn void _start(void) {
155 \\ exitGood();
156 \\}
157 \\
158158 );
159159 ctx.c("exit with parameter", linux_x64,
160160 \\export fn _start() noreturn {