From e2aad33d4eafe482fa145dc971a423307ae83a39 Mon Sep 17 00:00:00 2001 From: Noam Preil Date: Wed, 8 Jul 2020 00:11:41 -0400 Subject: [PATCH 1/4] Stage2: facepalm. --- src-self-hosted/main.zig | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src-self-hosted/main.zig b/src-self-hosted/main.zig index 3d859483a5..518be8c023 100644 --- a/src-self-hosted/main.zig +++ b/src-self-hosted/main.zig @@ -433,7 +433,10 @@ fn buildOutputType( std.debug.print("-fno-emit-bin not supported yet", .{}); process.exit(1); }, - .yes_default_path => try std.fmt.allocPrint(arena, "{}.c", .{root_name}), + .yes_default_path => if (cbe) + try std.fmt.allocPrint(arena, "{}.c", .{root_name}) + else + try std.zig.binNameAlloc(arena, root_name, target_info.target, output_mode, link_mode), .yes => |p| p, }; From 9d92d62525324453694190528021ab0216af0ed5 Mon Sep 17 00:00:00 2001 From: Noam Preil Date: Wed, 8 Jul 2020 00:33:44 -0400 Subject: [PATCH 2/4] CBE: Only try to use GNU attribute when __GNUC__is set --- src-self-hosted/cbe.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src-self-hosted/cbe.h b/src-self-hosted/cbe.h index 85b07eb48a..66e7b8bd3e 100644 --- a/src-self-hosted/cbe.h +++ b/src-self-hosted/cbe.h @@ -1,6 +1,6 @@ #if __STDC_VERSION__ >= 201112L #define noreturn _Noreturn -#elif !__STRICT_ANSI__ +#elif __GNUC__ && !__STRICT_ANSI__ #define noreturn __attribute__ ((noreturn)) #else #define noreturn From 6b4863416611253c68539136ae9e4b83359efe74 Mon Sep 17 00:00:00 2001 From: Noam Preil Date: Wed, 8 Jul 2020 14:05:07 -0400 Subject: [PATCH 3/4] CBE: Emit asm decls for now, but rename to make them valid --- src-self-hosted/Module.zig | 2 +- src-self-hosted/cgen.zig | 27 +++++++++++++++++---------- src-self-hosted/link.zig | 6 ++++++ test/stage2/cbe.zig | 5 +++++ test/stage2/zir.zig | 18 +++++++++--------- 5 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src-self-hosted/Module.zig b/src-self-hosted/Module.zig index 9df02dd186..733aac7c71 100644 --- a/src-self-hosted/Module.zig +++ b/src-self-hosted/Module.zig @@ -2456,7 +2456,7 @@ fn createAnonymousDecl( ) !*Decl { const name_index = self.getNextAnonNameIndex(); const scope_decl = scope.decl().?; - const name = try std.fmt.allocPrint(self.allocator, "{}${}", .{ scope_decl.name, name_index }); + const name = try std.fmt.allocPrint(self.allocator, "{}__anon_{}", .{ scope_decl.name, name_index }); defer self.allocator.free(name); const name_hash = scope.namespace().fullyQualifiedNameHash(name); const src_hash: std.zig.SrcHash = undefined; diff --git a/src-self-hosted/cgen.zig b/src-self-hosted/cgen.zig index 0de28748c6..75caddc131 100644 --- a/src-self-hosted/cgen.zig +++ b/src-self-hosted/cgen.zig @@ -11,8 +11,8 @@ const mem = std.mem; /// Maps a name from Zig source to C. This will always give the same output for /// any given input. -fn map(name: []const u8) ![]const u8 { - return name; +fn map(allocator: *std.mem.Allocator, name: []const u8) ![]const u8 { + return allocator.dupe(u8, name); } fn renderType(file: *C, writer: std.ArrayList(u8).Writer, T: Type, src: usize) !void { @@ -34,7 +34,8 @@ fn renderType(file: *C, writer: std.ArrayList(u8).Writer, T: Type, src: usize) ! fn renderFunctionSignature(file: *C, writer: std.ArrayList(u8).Writer, decl: *Decl) !void { const tv = decl.typed_value.most_recent.typed_value; try renderType(file, writer, tv.ty.fnReturnType(), decl.src()); - const name = try map(mem.spanZ(decl.name)); + const name = try map(file.allocator, mem.spanZ(decl.name)); + defer file.allocator.free(name); try writer.print(" {}(", .{name}); if (tv.ty.fnParamLen() == 0) { try writer.writeAll("void)"); @@ -143,15 +144,21 @@ pub fn generate(file: *C, decl: *Decl) !void { try writer.writeAll("}\n\n"); }, .Array => { - if (mem.indexOf(u8, mem.span(decl.name), "$") == null) { - // TODO: prevent inline asm constants from being emitted - if (tv.val.cast(Value.Payload.Bytes)) |payload| { - try writer.print("const char *const {} = \"{}\";\n", .{ decl.name, payload.data }); - std.debug.warn("\n\nARRAYTRANS\n", .{}); - if (tv.ty.arraySentinel()) |sentinel| {} + // TODO: prevent inline asm constants from being emitted + const name = try map(file.allocator, mem.span(decl.name)); + defer file.allocator.free(name); + if (tv.val.cast(Value.Payload.Bytes)) |payload| { + if (tv.ty.arraySentinel()) |sentinel| { + if (sentinel.toUnsignedInt() == 0) { + try file.constants.writer().print("const char *const {} = \"{}\";\n", .{ name, payload.data }); + } else { + return file.fail(decl.src(), "TODO byte arrays with non-zero sentinels", .{}); + } } else { - return file.fail(decl.src(), "TODO non-byte arrays", .{}); + return file.fail(decl.src(), "TODO byte arrays without sentinels", .{}); } + } else { + return file.fail(decl.src(), "TODO non-byte arrays", .{}); } }, else => |e| { diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index 0683a741c5..2f21dcbfde 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -93,6 +93,7 @@ pub fn openCFile(allocator: *Allocator, file: fs.File, options: Options) !File.C .options = options, .main = std.ArrayList(u8).init(allocator), .header = std.ArrayList(u8).init(allocator), + .constants = std.ArrayList(u8).init(allocator), .called = std.StringHashMap(void).init(allocator), }; } @@ -220,6 +221,7 @@ pub const File = struct { allocator: *Allocator, header: std.ArrayList(u8), + constants: std.ArrayList(u8), main: std.ArrayList(u8), file: ?fs.File, options: Options, @@ -237,6 +239,7 @@ pub const File = struct { pub fn deinit(self: *File.C) void { self.main.deinit(); self.header.deinit(); + self.constants.deinit(); self.called.deinit(); if (self.file) |f| f.close(); @@ -269,6 +272,9 @@ pub const File = struct { if (self.header.items.len > 0) { try writer.print("{}\n", .{self.header.items}); } + if (self.constants.items.len > 0) { + try writer.print("{}\n", .{self.constants.items}); + } if (self.main.items.len > 1) { const last_two = self.main.items[self.main.items.len - 2 ..]; if (std.mem.eql(u8, last_two, "\n\n")) { diff --git a/test/stage2/cbe.zig b/test/stage2/cbe.zig index e56507bd84..5961ab4c0c 100644 --- a/test/stage2/cbe.zig +++ b/test/stage2/cbe.zig @@ -32,6 +32,7 @@ pub fn addCases(ctx: *TestContext) !void { \\ ); // TODO: implement return values + // TODO: figure out a way to prevent asm constants from being generated ctx.c("inline asm", linux_x64, \\fn exitGood() void { \\ asm volatile ("syscall" @@ -49,6 +50,10 @@ pub fn addCases(ctx: *TestContext) !void { \\ \\void exitGood(void); \\ + \\const char *const exitGood__anon_0 = "{rax}"; + \\const char *const exitGood__anon_1 = "{rdi}"; + \\const char *const exitGood__anon_2 = "syscall"; + \\ \\noreturn void _start(void) { \\ exitGood(); \\} diff --git a/test/stage2/zir.zig b/test/stage2/zir.zig index 052ada667e..1a0aed85cf 100644 --- a/test/stage2/zir.zig +++ b/test/stage2/zir.zig @@ -22,8 +22,8 @@ pub fn addCases(ctx: *TestContext) !void { , \\@void = primitive(void) \\@fnty = fntype([], @void, cc=C) - \\@9 = declref("9$0") - \\@9$0 = str("entry") + \\@9 = declref("9__anon_0") + \\@9__anon_0 = str("entry") \\@unnamed$4 = str("entry") \\@unnamed$5 = export(@unnamed$4, "entry") \\@unnamed$6 = fntype([], @void, cc=C) @@ -77,9 +77,9 @@ pub fn addCases(ctx: *TestContext) !void { \\@entry = fn(@unnamed$6, { \\ %0 = returnvoid() \\}) - \\@entry$1 = str("2\x08\x01\n") - \\@9 = declref("9$0") - \\@9$0 = str("entry") + \\@entry__anon_1 = str("2\x08\x01\n") + \\@9 = declref("9__anon_0") + \\@9__anon_0 = str("entry") \\@unnamed$11 = str("entry") \\@unnamed$12 = export(@unnamed$11, "entry") \\ @@ -111,8 +111,8 @@ pub fn addCases(ctx: *TestContext) !void { , \\@void = primitive(void) \\@fnty = fntype([], @void, cc=C) - \\@9 = declref("9$0") - \\@9$0 = str("entry") + \\@9 = declref("9__anon_0") + \\@9__anon_0 = str("entry") \\@unnamed$4 = str("entry") \\@unnamed$5 = export(@unnamed$4, "entry") \\@unnamed$6 = fntype([], @void, cc=C) @@ -187,8 +187,8 @@ pub fn addCases(ctx: *TestContext) !void { , \\@void = primitive(void) \\@fnty = fntype([], @void, cc=C) - \\@9 = declref("9$2") - \\@9$2 = str("entry") + \\@9 = declref("9__anon_2") + \\@9__anon_2 = str("entry") \\@unnamed$4 = str("entry") \\@unnamed$5 = export(@unnamed$4, "entry") \\@unnamed$6 = fntype([], @void, cc=C) From d060be880460598dcf89cb3d59bfcdf5059a923d Mon Sep 17 00:00:00 2001 From: Noam Preil Date: Wed, 8 Jul 2020 14:10:11 -0400 Subject: [PATCH 4/4] CBE: Don't expose openCFile, always close file after an update --- src-self-hosted/link.zig | 4 +++- src-self-hosted/test.zig | 5 ++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src-self-hosted/link.zig b/src-self-hosted/link.zig index 2f21dcbfde..98a2578822 100644 --- a/src-self-hosted/link.zig +++ b/src-self-hosted/link.zig @@ -86,7 +86,7 @@ pub fn writeFilePath( return result; } -pub fn openCFile(allocator: *Allocator, file: fs.File, options: Options) !File.C { +fn openCFile(allocator: *Allocator, file: fs.File, options: Options) !File.C { return File.C{ .allocator = allocator, .file = file, @@ -282,6 +282,8 @@ pub const File = struct { } } try writer.writeAll(self.main.items); + self.file.?.close(); + self.file = null; } }; diff --git a/src-self-hosted/test.zig b/src-self-hosted/test.zig index 0a32008369..3e4958cc95 100644 --- a/src-self-hosted/test.zig +++ b/src-self-hosted/test.zig @@ -480,9 +480,8 @@ pub const TestContext = struct { switch (update.case) { .Transformation => |expected_output| { if (case.cbe) { - var cfile: *link.File.C = module.bin_file.cast(link.File.C).?; - cfile.file.?.close(); - cfile.file = null; + // The C file is always closed after an update, because we don't support + // incremental updates var file = try tmp.dir.openFile(bin_name, .{ .read = true }); defer file.close(); var out = file.reader().readAllAlloc(allocator, 1024 * 1024) catch @panic("Unable to read C output!");