Commit 6b48634166

Noam Preil <pleasantatk@gmail.com>
2020-07-08 20:05:07
CBE: Emit asm decls for now, but rename to make them valid
1 parent 9d92d62
Changed files (5)
src-self-hosted
test
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| {
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")) {
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;
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();
         \\}
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)