authorgravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-07-07 21:35:00-04:00
committergravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-07-07 21:35:42-04:00
log64bf1301822866904f52a70213dd71eefce4b99a
tree1a8d540dab89453096386c0a61d13a676492c045
parentcf09b335d8b7ad5b43ceefd169b4c2e6be8ed249
signature Commit is signed but in an unrecognized format.

CBE: working asm Inputs and Outputs; std{int,def}.h auto-inclusion


3 files changed, 153 insertions(+), 14 deletions(-)

src-self-hosted/cgen.zig+86-11
...@@ -16,16 +16,24 @@ fn map(name: []const u8) ![]const u8 {...@@ -16,16 +16,24 @@ fn map(name: []const u8) ![]const u8 {
16 return name;16 return name;
17}17}
1818
19fn renderFunctionSignature(writer: std.ArrayList(u8).Writer, decl: *Decl) !void {19fn renderType(file: *C, writer: std.ArrayList(u8).Writer, T: Type) !void {
20 const tv = decl.typed_value.most_recent.typed_value;20 if (T.tag() == .usize) {
21 switch (tv.ty.fnReturnType().zigTypeTag()) {21 file.need_stddef = true;
22 .NoReturn => {22 try writer.writeAll("size_t");
23 try writer.writeAll("_Noreturn void ");23 } else {
24 },24 switch (T.zigTypeTag()) {
25 else => return error.Unimplemented,25 .NoReturn => try writer.writeAll("_Noreturn void"),
26 .Void => try writer.writeAll("void"),
27 else => return error.Unimplemented,
28 }
26 }29 }
30}
31
32fn renderFunctionSignature(file: *C, writer: std.ArrayList(u8).Writer, decl: *Decl) !void {
33 const tv = decl.typed_value.most_recent.typed_value;
34 try renderType(file, writer, tv.ty.fnReturnType());
27 const name = try map(mem.spanZ(decl.name));35 const name = try map(mem.spanZ(decl.name));
28 try writer.print("{}(", .{name});36 try writer.print(" {}(", .{name});
29 if (tv.ty.fnParamLen() == 0) {37 if (tv.ty.fnParamLen() == 0) {
30 try writer.writeAll("void)");38 try writer.writeAll("void)");
31 } else {39 } else {
...@@ -39,7 +47,7 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void {...@@ -39,7 +47,7 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void {
39 const tv = decl.typed_value.most_recent.typed_value;47 const tv = decl.typed_value.most_recent.typed_value;
40 switch (tv.ty.zigTypeTag()) {48 switch (tv.ty.zigTypeTag()) {
41 .Fn => {49 .Fn => {
42 try renderFunctionSignature(writer, decl);50 try renderFunctionSignature(file, writer, decl);
43 try writer.writeAll(" {");51 try writer.writeAll(" {");
4452
45 const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func;53 const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func;
...@@ -48,6 +56,55 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void {...@@ -48,6 +56,55 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void {
48 for (instructions) |inst| {56 for (instructions) |inst| {
49 try writer.writeAll("\n\t");57 try writer.writeAll("\n\t");
50 switch (inst.tag) {58 switch (inst.tag) {
59 .assembly => {
60 const as = inst.cast(ir.Inst.Assembly).?.args;
61 for (as.inputs) |i, index| {
62 if (i[0] == '{' and i[i.len - 1] == '}') {
63 const reg = i[1 .. i.len - 1];
64 const arg = as.args[index];
65 if (arg.cast(ir.Inst.Constant)) |c| {
66 if (c.val.tag() == .int_u64) {
67 try writer.writeAll("register ");
68 try renderType(file, writer, arg.ty);
69 try writer.print(" {}_constant __asm__(\"{}\") = {};\n\t", .{ reg, reg, c.val.toUnsignedInt() });
70 } else {
71 return error.Unimplemented;
72 }
73 } else {
74 return error.Unimplemented;
75 }
76 } else {
77 return error.Unimplemented;
78 }
79 }
80 try writer.print("__asm {} (\"{}\"", .{ if (as.is_volatile) @as([]const u8, "volatile") else "", as.asm_source });
81 if (as.output) |o| {
82 return error.Unimplemented;
83 }
84 if (as.inputs.len > 0) {
85 if (as.output == null) {
86 try writer.writeAll(" :");
87 }
88 try writer.writeAll(": ");
89 for (as.inputs) |i, index| {
90 if (i[0] == '{' and i[i.len - 1] == '}') {
91 const reg = i[1 .. i.len - 1];
92 const arg = as.args[index];
93 if (index > 0) {
94 try writer.writeAll(", ");
95 }
96 if (arg.cast(ir.Inst.Constant)) |c| {
97 try writer.print("\"\"({}_constant)", .{reg});
98 } else {
99 return error.Unimplemented;
100 }
101 } else {
102 return error.Unimplemented;
103 }
104 }
105 }
106 try writer.writeAll(");");
107 },
51 .call => {108 .call => {
52 const call = inst.cast(ir.Inst.Call).?.args;109 const call = inst.cast(ir.Inst.Call).?.args;
53 if (call.func.cast(ir.Inst.Constant)) |func_inst| {110 if (call.func.cast(ir.Inst.Constant)) |func_inst| {
...@@ -56,17 +113,20 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void {...@@ -56,17 +113,20 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void {
56 const tname = mem.spanZ(target.name);113 const tname = mem.spanZ(target.name);
57 if (file.called.get(tname) == null) {114 if (file.called.get(tname) == null) {
58 try file.called.put(tname, void{});115 try file.called.put(tname, void{});
59 try renderFunctionSignature(header, target);116 try renderFunctionSignature(file, header, target);
60 try header.writeAll(";\n");117 try header.writeAll(";\n");
61 }118 }
62 try writer.print("{}();", .{tname});119 try writer.print("{}();", .{tname});
63 } else {120 } else {
121 std.debug.warn("non-function call target?\n", .{});
64 return error.Unimplemented;122 return error.Unimplemented;
65 }123 }
66 if (call.args.len != 0) {124 if (call.args.len != 0) {
125 std.debug.warn("parameters\n", .{});
67 return error.Unimplemented;126 return error.Unimplemented;
68 }127 }
69 } else {128 } else {
129 std.debug.warn("non-constant call inst?\n", .{});
70 return error.Unimplemented;130 return error.Unimplemented;
71 }131 }
72 },132 },
...@@ -80,6 +140,21 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void {...@@ -80,6 +140,21 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void {
80140
81 try writer.writeAll("}\n\n");141 try writer.writeAll("}\n\n");
82 },142 },
83 else => return error.Unimplemented,143 .Array => {
144 if (mem.indexOf(u8, mem.span(decl.name), "$") == null) {
145 // TODO: prevent inline asm constants from being emitted
146 if (tv.val.cast(Value.Payload.Bytes)) |payload| {
147 try writer.print("const char *const {} = \"{}\";\n", .{ decl.name, payload.data });
148 std.debug.warn("\n\nARRAYTRANS\n", .{});
149 if (tv.ty.arraySentinel()) |sentinel| {}
150 } else {
151 return error.Unimplemented;
152 }
153 }
154 },
155 else => |e| {
156 std.debug.warn("\nTODO implement {}\n", .{e});
157 return error.Unimplemented;
158 },
84 }159 }
85}160}
src-self-hosted/link.zig+16-3
...@@ -191,7 +191,7 @@ pub const File = struct {...@@ -191,7 +191,7 @@ pub const File = struct {
191 pub fn options(base: *File) Options {191 pub fn options(base: *File) Options {
192 return switch (base.tag) {192 return switch (base.tag) {
193 .Elf => @fieldParentPtr(Elf, "base", base).options,193 .Elf => @fieldParentPtr(Elf, "base", base).options,
194 else => unreachable,194 .C => @fieldParentPtr(C, "base", base).options,
195 };195 };
196 }196 }
197197
...@@ -215,6 +215,8 @@ pub const File = struct {...@@ -215,6 +215,8 @@ pub const File = struct {
215 owns_file_handle: bool,215 owns_file_handle: bool,
216 options: Options,216 options: Options,
217 called: std.StringHashMap(void),217 called: std.StringHashMap(void),
218 need_stddef: bool = false,
219 need_stdint: bool = false,
218220
219 pub fn makeWritable(self: *File.C, dir: fs.Dir, sub_path: []const u8) !void {221 pub fn makeWritable(self: *File.C, dir: fs.Dir, sub_path: []const u8) !void {
220 assert(self.owns_file_handle);222 assert(self.owns_file_handle);
...@@ -242,10 +244,21 @@ pub const File = struct {...@@ -242,10 +244,21 @@ pub const File = struct {
242244
243 pub fn flush(self: *File.C) !void {245 pub fn flush(self: *File.C) !void {
244 const writer = self.file.?.writer();246 const writer = self.file.?.writer();
247 var includes = false;
248 if (self.need_stddef) {
249 try writer.writeAll("#include <stddef.h>\n");
250 includes = true;
251 }
252 if (self.need_stdint) {
253 try writer.writeAll("#include <stdint.h>\n");
254 includes = true;
255 }
256 if (includes) {
257 try writer.writeByte('\n');
258 }
245 if (self.header.items.len > 0) {259 if (self.header.items.len > 0) {
246 try self.header.append('\n');260 try writer.print("{}\n", .{self.header.items});
247 }261 }
248 try writer.writeAll(self.header.items);
249 if (self.main.items.len > 1) {262 if (self.main.items.len > 1) {
250 const last_two = self.main.items[self.main.items.len - 2 ..];263 const last_two = self.main.items[self.main.items.len - 2 ..];
251 if (std.mem.eql(u8, last_two, "\n\n")) {264 if (std.mem.eql(u8, last_two, "\n\n")) {
test/stage2/cbe.zig+51
...@@ -31,4 +31,55 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -31,4 +31,55 @@ pub fn addCases(ctx: *TestContext) !void {
31 \\_Noreturn void main(void) {}31 \\_Noreturn void main(void) {}
32 \\32 \\
33 );33 );
34 // TODO: implement return values
35 ctx.c11("inline asm", linux_x64,
36 \\fn exitGood() void {
37 \\ asm volatile ("syscall"
38 \\ :
39 \\ : [number] "{rax}" (231),
40 \\ [arg1] "{rdi}" (0)
41 \\ );
42 \\}
43 \\
44 \\export fn _start() noreturn {
45 \\ exitGood();
46 \\}
47 ,
48 \\#include <stddef.h>
49 \\
50 \\void exitGood(void);
51 \\
52 \\_Noreturn void _start(void) {
53 \\ exitGood();
54 \\}
55 \\
56 \\void exitGood(void) {
57 \\ register size_t rax_constant __asm__("rax") = 231;
58 \\ register size_t rdi_constant __asm__("rdi") = 0;
59 \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));
60 \\}
61 \\
62 );
63 //ctx.c11("basic return", linux_x64,
64 // \\fn main() u8 {
65 // \\ return 103;
66 // \\}
67 // \\
68 // \\export fn _start() noreturn {
69 // \\ _ = main();
70 // \\}
71 //,
72 // \\#include <stdint.h>
73 // \\
74 // \\uint8_t main(void);
75 // \\
76 // \\_Noreturn void _start(void) {
77 // \\ (void)main();
78 // \\}
79 // \\
80 // \\uint8_t main(void) {
81 // \\ return 103;
82 // \\}
83 // \\
84 //);
34}85}