authorgravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-07-07 19:35:33-04:00
committergravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-07-07 19:35:33-04:00
logcf09b335d8b7ad5b43ceefd169b4c2e6be8ed249
tree9a0a75d48eb34dc75d75972bfc8362a9a7a83197
parentcf86aa8772f266cb475711aeee7b0c1b2083e6aa
signature Commit is signed but in an unrecognized format.

CBE: Working function call w/ no args or return value


3 files changed, 95 insertions(+), 25 deletions(-)

src-self-hosted/cgen.zig+53-18
...@@ -1,7 +1,9 @@...@@ -1,7 +1,9 @@
1const link = @import("link.zig");1const link = @import("link.zig");
2const Module = @import("Module.zig");2const Module = @import("Module.zig");
3const std = @import("std");3const ir = @import("ir.zig");
4const Value = @import("value.zig").Value;4const Value = @import("value.zig").Value;
5const Type = @import("type.zig").Type;
6const std = @import("std");
57
6const C = link.File.C;8const C = link.File.C;
7const Decl = Module.Decl;9const Decl = Module.Decl;
...@@ -14,36 +16,69 @@ fn map(name: []const u8) ![]const u8 {...@@ -14,36 +16,69 @@ fn map(name: []const u8) ![]const u8 {
14 return name;16 return name;
15}17}
1618
19fn renderFunctionSignature(writer: std.ArrayList(u8).Writer, decl: *Decl) !void {
20 const tv = decl.typed_value.most_recent.typed_value;
21 switch (tv.ty.fnReturnType().zigTypeTag()) {
22 .NoReturn => {
23 try writer.writeAll("_Noreturn void ");
24 },
25 else => return error.Unimplemented,
26 }
27 const name = try map(mem.spanZ(decl.name));
28 try writer.print("{}(", .{name});
29 if (tv.ty.fnParamLen() == 0) {
30 try writer.writeAll("void)");
31 } else {
32 return error.Unimplemented;
33 }
34}
35
17pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void {36pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void {
18 const writer = file.file.?.writer();37 const writer = file.main.writer();
38 const header = file.header.writer();
19 const tv = decl.typed_value.most_recent.typed_value;39 const tv = decl.typed_value.most_recent.typed_value;
20 switch (tv.ty.zigTypeTag()) {40 switch (tv.ty.zigTypeTag()) {
21 .Fn => {41 .Fn => {
22 const return_type = tv.ty.fnReturnType();42 try renderFunctionSignature(writer, decl);
23 switch (return_type.zigTypeTag()) {43 try writer.writeAll(" {");
24 .NoReturn => try writer.writeAll("_Noreturn void "),
25 else => return error.Unimplemented,
26 }
27
28 const name = try map(mem.spanZ(decl.name));
29 try writer.print("{} (", .{name});
30 if (tv.ty.fnParamLen() == 0) {
31 try writer.writeAll("void){");
32 } else {
33 return error.Unimplemented;
34 }
3544
36 const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func;45 const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func;
37 const instructions = func.analysis.success.instructions;46 const instructions = func.analysis.success.instructions;
38 if (instructions.len > 0) {47 if (instructions.len > 0) {
39 try writer.writeAll("\n\t");
40 for (instructions) |inst| {48 for (instructions) |inst| {
41 std.debug.warn("\nTranslating {}\n", .{inst.*});49 try writer.writeAll("\n\t");
50 switch (inst.tag) {
51 .call => {
52 const call = inst.cast(ir.Inst.Call).?.args;
53 if (call.func.cast(ir.Inst.Constant)) |func_inst| {
54 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
55 const target = func_val.func.owner_decl;
56 const tname = mem.spanZ(target.name);
57 if (file.called.get(tname) == null) {
58 try file.called.put(tname, void{});
59 try renderFunctionSignature(header, target);
60 try header.writeAll(";\n");
61 }
62 try writer.print("{}();", .{tname});
63 } else {
64 return error.Unimplemented;
65 }
66 if (call.args.len != 0) {
67 return error.Unimplemented;
68 }
69 } else {
70 return error.Unimplemented;
71 }
72 },
73 else => {
74 std.debug.warn("\nTranslating {}\n", .{inst.*});
75 },
76 }
42 }77 }
43 try writer.writeAll("\n");78 try writer.writeAll("\n");
44 }79 }
4580
46 try writer.writeAll("}\n");81 try writer.writeAll("}\n\n");
47 },82 },
48 else => return error.Unimplemented,83 else => return error.Unimplemented,
49 }84 }
src-self-hosted/link.zig+25-3
...@@ -93,6 +93,9 @@ pub fn openCFile(allocator: *Allocator, file: fs.File, options: Options) !File.C...@@ -93,6 +93,9 @@ pub fn openCFile(allocator: *Allocator, file: fs.File, options: Options) !File.C
93 .file = file,93 .file = file,
94 .options = options,94 .options = options,
95 .owns_file_handle = false,95 .owns_file_handle = false,
96 .main = std.ArrayList(u8).init(allocator),
97 .header = std.ArrayList(u8).init(allocator),
98 .called = std.StringHashMap(void).init(allocator),
96 };99 };
97 errdefer self.deinit();100 errdefer self.deinit();
98 return self;101 return self;
...@@ -165,9 +168,7 @@ pub const File = struct {...@@ -165,9 +168,7 @@ pub const File = struct {
165 pub fn flush(base: *File) !void {168 pub fn flush(base: *File) !void {
166 try switch (base.tag) {169 try switch (base.tag) {
167 .Elf => @fieldParentPtr(Elf, "base", base).flush(),170 .Elf => @fieldParentPtr(Elf, "base", base).flush(),
168 .C => {171 .C => @fieldParentPtr(C, "base", base).flush(),
169 //TODO
170 },
171 else => unreachable,172 else => unreachable,
172 };173 };
173 }174 }
...@@ -208,9 +209,12 @@ pub const File = struct {...@@ -208,9 +209,12 @@ pub const File = struct {
208 base: File = File{ .tag = base_tag },209 base: File = File{ .tag = base_tag },
209210
210 allocator: *Allocator,211 allocator: *Allocator,
212 header: std.ArrayList(u8),
213 main: std.ArrayList(u8),
211 file: ?fs.File,214 file: ?fs.File,
212 owns_file_handle: bool,215 owns_file_handle: bool,
213 options: Options,216 options: Options,
217 called: std.StringHashMap(void),
214218
215 pub fn makeWritable(self: *File.C, dir: fs.Dir, sub_path: []const u8) !void {219 pub fn makeWritable(self: *File.C, dir: fs.Dir, sub_path: []const u8) !void {
216 assert(self.owns_file_handle);220 assert(self.owns_file_handle);
...@@ -223,6 +227,9 @@ pub const File = struct {...@@ -223,6 +227,9 @@ pub const File = struct {
223 }227 }
224228
225 pub fn deinit(self: *File.C) void {229 pub fn deinit(self: *File.C) void {
230 self.main.deinit();
231 self.header.deinit();
232 self.called.deinit();
226 if (self.owns_file_handle) {233 if (self.owns_file_handle) {
227 if (self.file) |f|234 if (self.file) |f|
228 f.close();235 f.close();
...@@ -232,6 +239,21 @@ pub const File = struct {...@@ -232,6 +239,21 @@ pub const File = struct {
232 pub fn updateDecl(self: *File.C, module: *Module, decl: *Module.Decl) !void {239 pub fn updateDecl(self: *File.C, module: *Module, decl: *Module.Decl) !void {
233 try cgen.generate(self, decl, self.options.c_standard.?);240 try cgen.generate(self, decl, self.options.c_standard.?);
234 }241 }
242
243 pub fn flush(self: *File.C) !void {
244 const writer = self.file.?.writer();
245 if (self.header.items.len > 0) {
246 try self.header.append('\n');
247 }
248 try writer.writeAll(self.header.items);
249 if (self.main.items.len > 1) {
250 const last_two = self.main.items[self.main.items.len - 2 ..];
251 if (std.mem.eql(u8, last_two, "\n\n")) {
252 self.main.items.len -= 1;
253 }
254 }
255 try writer.writeAll(self.main.items);
256 }
235 };257 };
236258
237 pub const Elf = struct {259 pub const Elf = struct {
test/stage2/cbe.zig+17-4
...@@ -9,13 +9,26 @@ const linux_x64 = std.zig.CrossTarget{...@@ -9,13 +9,26 @@ const linux_x64 = std.zig.CrossTarget{
9};9};
1010
11pub fn addCases(ctx: *TestContext) !void {11pub fn addCases(ctx: *TestContext) !void {
12 // These tests should work on every platform
13 ctx.c11("empty start function", linux_x64,12 ctx.c11("empty start function", linux_x64,
14 \\export fn _start() noreturn {}13 \\export fn _start() noreturn {}
15 ,14 ,
16 // A newline is always generated after every function; this ensures, among15 \\_Noreturn void _start(void) {}
17 // other things, that there is always a newline at the end of the file16 \\
18 \\_Noreturn void _start(void) {}17 );
18 ctx.c11("less empty start function", linux_x64,
19 \\fn main() noreturn {}
20 \\
21 \\export fn _start() noreturn {
22 \\ main();
23 \\}
24 ,
25 \\_Noreturn void main(void);
26 \\
27 \\_Noreturn void _start(void) {
28 \\ main();
29 \\}
30 \\
31 \\_Noreturn void main(void) {}
19 \\32 \\
20 );33 );
21}34}