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
This commit is contained in:
Noam Preil 2020-12-30 05:22:50 -05:00 committed by Andrew Kelley
parent 6c4924408b
commit 9360e5887c
3 changed files with 53 additions and 47 deletions

View File

@ -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),
}
}

View File

@ -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;
}

View File

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