| author | |
| committer | |
| log | a17200dab1b0b373e85c6c2cc266078012a81948 |
| tree | 320be8b1150cd3396d3e428d463fdbbb6836de78 |
| parent | b4c571301be7dd2174b2d067d643a2a093797e7e |
| signature | Commit is signed but in an unrecognized format. |
3 files changed, 114 insertions(+), 34 deletions(-)
src-self-hosted/link.zig+58-1| ... | ... | @@ -38,7 +38,11 @@ pub fn openBinFilePath( |
| 38 | 38 | errdefer file.close(); |
| 39 | 39 | |
| 40 | 40 | 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; | |
| 42 | 46 | } else { |
| 43 | 47 | var bin_file = try allocator.create(File.Elf); |
| 44 | 48 | errdefer allocator.destroy(bin_file); |
| ... | ... | @@ -82,6 +86,17 @@ pub fn writeFilePath( |
| 82 | 86 | return result; |
| 83 | 87 | } |
| 84 | 88 | |
| 89 | pub 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 | ||
| 85 | 100 | /// Attempts incremental linking, if the file already exists. |
| 86 | 101 | /// If incremental linking fails, falls back to truncating the file and rewriting it. |
| 87 | 102 | /// Returns an error if `file` is not already open with +read +write +seek abilities. |
| ... | ... | @@ -108,6 +123,7 @@ pub const File = struct { |
| 108 | 123 | pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void { |
| 109 | 124 | try switch (base.tag) { |
| 110 | 125 | .Elf => @fieldParentPtr(Elf, "base", base).makeWritable(dir, sub_path), |
| 126 | .C => @fieldParentPtr(C, "base", base).makeWritable(dir, sub_path), | |
| 111 | 127 | else => unreachable, |
| 112 | 128 | }; |
| 113 | 129 | } |
| ... | ... | @@ -122,6 +138,7 @@ pub const File = struct { |
| 122 | 138 | pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void { |
| 123 | 139 | try switch (base.tag) { |
| 124 | 140 | .Elf => @fieldParentPtr(Elf, "base", base).updateDecl(module, decl), |
| 141 | .C => @fieldParentPtr(C, "base", base).updateDecl(module, decl), | |
| 125 | 142 | else => unreachable, |
| 126 | 143 | }; |
| 127 | 144 | } |
| ... | ... | @@ -129,6 +146,9 @@ pub const File = struct { |
| 129 | 146 | pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void { |
| 130 | 147 | try switch (base.tag) { |
| 131 | 148 | .Elf => @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl), |
| 149 | .C => { | |
| 150 | //TODO | |
| 151 | }, | |
| 132 | 152 | else => unreachable, |
| 133 | 153 | }; |
| 134 | 154 | } |
| ... | ... | @@ -136,6 +156,7 @@ pub const File = struct { |
| 136 | 156 | pub fn deinit(base: *File) void { |
| 137 | 157 | switch (base.tag) { |
| 138 | 158 | .Elf => @fieldParentPtr(Elf, "base", base).deinit(), |
| 159 | .C => @fieldParentPtr(C, "base", base).deinit(), | |
| 139 | 160 | else => unreachable, |
| 140 | 161 | } |
| 141 | 162 | } |
| ... | ... | @@ -143,6 +164,9 @@ pub const File = struct { |
| 143 | 164 | pub fn flush(base: *File) !void { |
| 144 | 165 | try switch (base.tag) { |
| 145 | 166 | .Elf => @fieldParentPtr(Elf, "base", base).flush(), |
| 167 | .C => { | |
| 168 | //TODO | |
| 169 | }, | |
| 146 | 170 | else => unreachable, |
| 147 | 171 | }; |
| 148 | 172 | } |
| ... | ... | @@ -157,6 +181,7 @@ pub const File = struct { |
| 157 | 181 | pub fn errorFlags(base: *File) ErrorFlags { |
| 158 | 182 | return switch (base.tag) { |
| 159 | 183 | .Elf => @fieldParentPtr(Elf, "base", base).error_flags, |
| 184 | .C => return .{ .no_entry_point_found = false }, | |
| 160 | 185 | else => unreachable, |
| 161 | 186 | }; |
| 162 | 187 | } |
| ... | ... | @@ -176,6 +201,38 @@ pub const File = struct { |
| 176 | 201 | pub const ErrorFlags = struct { |
| 177 | 202 | no_entry_point_found: bool = false, |
| 178 | 203 | }; |
| 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 | ||
| 179 | 236 | pub const Elf = struct { |
| 180 | 237 | pub const base_tag: Tag = .Elf; |
| 181 | 238 | base: File = File{ .tag = base_tag }, |
src-self-hosted/test.zig+50-27| ... | ... | @@ -464,33 +464,54 @@ pub const TestContext = struct { |
| 464 | 464 | |
| 465 | 465 | switch (update.case) { |
| 466 | 466 | .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 | } | |
| 494 | 515 | } |
| 495 | 516 | } |
| 496 | 517 | } |
| ... | ... | @@ -527,6 +548,8 @@ pub const TestContext = struct { |
| 527 | 548 | } |
| 528 | 549 | }, |
| 529 | 550 | .Execution => |expected_stdout| { |
| 551 | std.debug.assert(case.c_standard == null); | |
| 552 | ||
| 530 | 553 | update_node.estimated_total_items = 4; |
| 531 | 554 | var exec_result = x: { |
| 532 | 555 | var exec_node = update_node.start("execute", null); |
test/stage2/cbe.zig+6-6| ... | ... | @@ -9,10 +9,10 @@ const linux_x64 = std.zig.CrossTarget{ |
| 9 | 9 | }; |
| 10 | 10 | |
| 11 | 11 | pub 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 | ); | |
| 18 | 18 | } |