authorgravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-07-07 16:40:14-04:00
committergravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-07-07 16:40:14-04:00
loga17200dab1b0b373e85c6c2cc266078012a81948
tree320be8b1150cd3396d3e428d463fdbbb6836de78
parentb4c571301be7dd2174b2d067d643a2a093797e7e
signaturelock-open Commit is signed but in an unrecognized format.

CBE skeleton


3 files changed, 114 insertions(+), 34 deletions(-)

src-self-hosted/link.zig+58-1
......@@ -38,7 +38,11 @@ pub fn openBinFilePath(
3838 errdefer file.close();
3939
4040 if (options.c_standard) |cstd| {
41 return error.Unimplemented;
41 var bin_file = try allocator.create(File.C);
42 errdefer allocator.destroy(bin_file);
43 bin_file.* = try openCFile(allocator, file, options);
44 bin_file.owns_file_handle = true;
45 return &bin_file.base;
4246 } else {
4347 var bin_file = try allocator.create(File.Elf);
4448 errdefer allocator.destroy(bin_file);
......@@ -82,6 +86,17 @@ pub fn writeFilePath(
8286 return result;
8387}
8488
89pub fn openCFile(allocator: *Allocator, file: fs.File, options: Options) !File.C {
90 var self: File.C = .{
91 .allocator = allocator,
92 .file = file,
93 .options = options,
94 .owns_file_handle = false,
95 };
96 errdefer self.deinit();
97 return self;
98}
99
85100/// Attempts incremental linking, if the file already exists.
86101/// If incremental linking fails, falls back to truncating the file and rewriting it.
87102/// Returns an error if `file` is not already open with +read +write +seek abilities.
......@@ -108,6 +123,7 @@ pub const File = struct {
108123 pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void {
109124 try switch (base.tag) {
110125 .Elf => @fieldParentPtr(Elf, "base", base).makeWritable(dir, sub_path),
126 .C => @fieldParentPtr(C, "base", base).makeWritable(dir, sub_path),
111127 else => unreachable,
112128 };
113129 }
......@@ -122,6 +138,7 @@ pub const File = struct {
122138 pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void {
123139 try switch (base.tag) {
124140 .Elf => @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),
141 .C => @fieldParentPtr(C, "base", base).updateDecl(module, decl),
125142 else => unreachable,
126143 };
127144 }
......@@ -129,6 +146,9 @@ pub const File = struct {
129146 pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void {
130147 try switch (base.tag) {
131148 .Elf => @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl),
149 .C => {
150 //TODO
151 },
132152 else => unreachable,
133153 };
134154 }
......@@ -136,6 +156,7 @@ pub const File = struct {
136156 pub fn deinit(base: *File) void {
137157 switch (base.tag) {
138158 .Elf => @fieldParentPtr(Elf, "base", base).deinit(),
159 .C => @fieldParentPtr(C, "base", base).deinit(),
139160 else => unreachable,
140161 }
141162 }
......@@ -143,6 +164,9 @@ pub const File = struct {
143164 pub fn flush(base: *File) !void {
144165 try switch (base.tag) {
145166 .Elf => @fieldParentPtr(Elf, "base", base).flush(),
167 .C => {
168 //TODO
169 },
146170 else => unreachable,
147171 };
148172 }
......@@ -157,6 +181,7 @@ pub const File = struct {
157181 pub fn errorFlags(base: *File) ErrorFlags {
158182 return switch (base.tag) {
159183 .Elf => @fieldParentPtr(Elf, "base", base).error_flags,
184 .C => return .{ .no_entry_point_found = false },
160185 else => unreachable,
161186 };
162187 }
......@@ -176,6 +201,38 @@ pub const File = struct {
176201 pub const ErrorFlags = struct {
177202 no_entry_point_found: bool = false,
178203 };
204
205 pub const C = struct {
206 pub const base_tag: Tag = .C;
207 base: File = File{ .tag = base_tag },
208
209 allocator: *Allocator,
210 file: ?fs.File,
211 owns_file_handle: bool,
212 options: Options,
213
214 pub fn makeWritable(self: *File.C, dir: fs.Dir, sub_path: []const u8) !void {
215 assert(self.owns_file_handle);
216 if (self.file != null) return;
217 self.file = try dir.createFile(sub_path, .{
218 .truncate = false,
219 .read = true,
220 .mode = determineMode(self.options),
221 });
222 }
223
224 pub fn deinit(self: *File.C) void {
225 if (self.owns_file_handle) {
226 if (self.file) |f|
227 f.close();
228 }
229 }
230
231 pub fn updateDecl(self: *File.C, module: *Module, decl: *Module.Decl) !void {
232 return error.Unimplemented;
233 }
234 };
235
179236 pub const Elf = struct {
180237 pub const base_tag: Tag = .Elf;
181238 base: File = File{ .tag = base_tag },
src-self-hosted/test.zig+50-27
......@@ -464,33 +464,54 @@ pub const TestContext = struct {
464464
465465 switch (update.case) {
466466 .Transformation => |expected_output| {
467 update_node.estimated_total_items = 5;
468 var emit_node = update_node.start("emit", null);
469 emit_node.activate();
470 var new_zir_module = try zir.emit(allocator, module);
471 defer new_zir_module.deinit(allocator);
472 emit_node.end();
473
474 var write_node = update_node.start("write", null);
475 write_node.activate();
476 var out_zir = std.ArrayList(u8).init(allocator);
477 defer out_zir.deinit();
478 try new_zir_module.writeToStream(allocator, out_zir.outStream());
479 write_node.end();
480
481 var test_node = update_node.start("assert", null);
482 test_node.activate();
483 defer test_node.end();
484 const label = if (case.c_standard) |_| "C" else "ZIR";
485 if (expected_output.len != out_zir.items.len) {
486 std.debug.warn("{}\nTransformed {} length differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ case.name, label, expected_output, out_zir.items });
487 std.process.exit(1);
488 }
489 for (expected_output) |e, i| {
490 if (out_zir.items[i] != e) {
491 if (expected_output.len != out_zir.items.len) {
492 std.debug.warn("{}\nTransformed {} differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ case.name, label, expected_output, out_zir.items });
493 std.process.exit(1);
467 var label: []const u8 = "ZIR";
468 if (case.c_standard) |cstd| {
469 label = @tagName(cstd);
470 var c: *link.File.C = module.bin_file.cast(link.File.C).?;
471 var out = c.file.?.reader().readAllAlloc(allocator, 1024 * 1024) catch @panic("Unable to read C output!");
472 defer allocator.free(out);
473
474 if (expected_output.len != out.len) {
475 std.debug.warn("{}\nTransformed {} length differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ case.name, label, expected_output, out });
476 std.process.exit(1);
477 }
478 for (expected_output) |e, i| {
479 if (out[i] != e) {
480 if (expected_output.len != out.len) {
481 std.debug.warn("{}\nTransformed {} differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ case.name, label, expected_output, out });
482 std.process.exit(1);
483 }
484 }
485 }
486 } else {
487 update_node.estimated_total_items = 5;
488 var emit_node = update_node.start("emit", null);
489 emit_node.activate();
490 var new_zir_module = try zir.emit(allocator, module);
491 defer new_zir_module.deinit(allocator);
492 emit_node.end();
493
494 var write_node = update_node.start("write", null);
495 write_node.activate();
496 var out_zir = std.ArrayList(u8).init(allocator);
497 defer out_zir.deinit();
498 try new_zir_module.writeToStream(allocator, out_zir.outStream());
499 write_node.end();
500
501 var test_node = update_node.start("assert", null);
502 test_node.activate();
503 defer test_node.end();
504
505 if (expected_output.len != out_zir.items.len) {
506 std.debug.warn("{}\nTransformed {} length differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ case.name, label, expected_output, out_zir.items });
507 std.process.exit(1);
508 }
509 for (expected_output) |e, i| {
510 if (out_zir.items[i] != e) {
511 if (expected_output.len != out_zir.items.len) {
512 std.debug.warn("{}\nTransformed {} differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ case.name, label, expected_output, out_zir.items });
513 std.process.exit(1);
514 }
494515 }
495516 }
496517 }
......@@ -527,6 +548,8 @@ pub const TestContext = struct {
527548 }
528549 },
529550 .Execution => |expected_stdout| {
551 std.debug.assert(case.c_standard == null);
552
530553 update_node.estimated_total_items = 4;
531554 var exec_result = x: {
532555 var exec_node = update_node.start("execute", null);
test/stage2/cbe.zig+6-6
......@@ -9,10 +9,10 @@ const linux_x64 = std.zig.CrossTarget{
99};
1010
1111pub fn addCases(ctx: *TestContext) !void {
12 // // These tests should work on every platform
13 // ctx.c11("empty start function", linux_x64,
14 // \\export fn start() void {}
15 // ,
16 // \\void start(void) {}
17 // );
12 // These tests should work on every platform
13 ctx.c11("empty start function", linux_x64,
14 \\export fn start() void {}
15 ,
16 \\void start(void) {}
17 );
1818}