Commit a17200dab1
src-self-hosted/link.zig
@@ -38,7 +38,11 @@ pub fn openBinFilePath(
errdefer file.close();
if (options.c_standard) |cstd| {
- return error.Unimplemented;
+ var bin_file = try allocator.create(File.C);
+ errdefer allocator.destroy(bin_file);
+ bin_file.* = try openCFile(allocator, file, options);
+ bin_file.owns_file_handle = true;
+ return &bin_file.base;
} else {
var bin_file = try allocator.create(File.Elf);
errdefer allocator.destroy(bin_file);
@@ -82,6 +86,17 @@ pub fn writeFilePath(
return result;
}
+pub fn openCFile(allocator: *Allocator, file: fs.File, options: Options) !File.C {
+ var self: File.C = .{
+ .allocator = allocator,
+ .file = file,
+ .options = options,
+ .owns_file_handle = false,
+ };
+ errdefer self.deinit();
+ return self;
+}
+
/// Attempts incremental linking, if the file already exists.
/// If incremental linking fails, falls back to truncating the file and rewriting it.
/// Returns an error if `file` is not already open with +read +write +seek abilities.
@@ -108,6 +123,7 @@ pub const File = struct {
pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void {
try switch (base.tag) {
.Elf => @fieldParentPtr(Elf, "base", base).makeWritable(dir, sub_path),
+ .C => @fieldParentPtr(C, "base", base).makeWritable(dir, sub_path),
else => unreachable,
};
}
@@ -122,6 +138,7 @@ pub const File = struct {
pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void {
try switch (base.tag) {
.Elf => @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),
+ .C => @fieldParentPtr(C, "base", base).updateDecl(module, decl),
else => unreachable,
};
}
@@ -129,6 +146,9 @@ pub const File = struct {
pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void {
try switch (base.tag) {
.Elf => @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl),
+ .C => {
+ //TODO
+ },
else => unreachable,
};
}
@@ -136,6 +156,7 @@ pub const File = struct {
pub fn deinit(base: *File) void {
switch (base.tag) {
.Elf => @fieldParentPtr(Elf, "base", base).deinit(),
+ .C => @fieldParentPtr(C, "base", base).deinit(),
else => unreachable,
}
}
@@ -143,6 +164,9 @@ pub const File = struct {
pub fn flush(base: *File) !void {
try switch (base.tag) {
.Elf => @fieldParentPtr(Elf, "base", base).flush(),
+ .C => {
+ //TODO
+ },
else => unreachable,
};
}
@@ -157,6 +181,7 @@ pub const File = struct {
pub fn errorFlags(base: *File) ErrorFlags {
return switch (base.tag) {
.Elf => @fieldParentPtr(Elf, "base", base).error_flags,
+ .C => return .{ .no_entry_point_found = false },
else => unreachable,
};
}
@@ -176,6 +201,38 @@ pub const File = struct {
pub const ErrorFlags = struct {
no_entry_point_found: bool = false,
};
+
+ pub const C = struct {
+ pub const base_tag: Tag = .C;
+ base: File = File{ .tag = base_tag },
+
+ allocator: *Allocator,
+ file: ?fs.File,
+ owns_file_handle: bool,
+ options: Options,
+
+ pub fn makeWritable(self: *File.C, dir: fs.Dir, sub_path: []const u8) !void {
+ assert(self.owns_file_handle);
+ if (self.file != null) return;
+ self.file = try dir.createFile(sub_path, .{
+ .truncate = false,
+ .read = true,
+ .mode = determineMode(self.options),
+ });
+ }
+
+ pub fn deinit(self: *File.C) void {
+ if (self.owns_file_handle) {
+ if (self.file) |f|
+ f.close();
+ }
+ }
+
+ pub fn updateDecl(self: *File.C, module: *Module, decl: *Module.Decl) !void {
+ return error.Unimplemented;
+ }
+ };
+
pub const Elf = struct {
pub const base_tag: Tag = .Elf;
base: File = File{ .tag = base_tag },
src-self-hosted/test.zig
@@ -464,33 +464,54 @@ pub const TestContext = struct {
switch (update.case) {
.Transformation => |expected_output| {
- update_node.estimated_total_items = 5;
- var emit_node = update_node.start("emit", null);
- emit_node.activate();
- var new_zir_module = try zir.emit(allocator, module);
- defer new_zir_module.deinit(allocator);
- emit_node.end();
-
- var write_node = update_node.start("write", null);
- write_node.activate();
- var out_zir = std.ArrayList(u8).init(allocator);
- defer out_zir.deinit();
- try new_zir_module.writeToStream(allocator, out_zir.outStream());
- write_node.end();
-
- var test_node = update_node.start("assert", null);
- test_node.activate();
- defer test_node.end();
- const label = if (case.c_standard) |_| "C" else "ZIR";
- if (expected_output.len != out_zir.items.len) {
- 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 });
- std.process.exit(1);
- }
- for (expected_output) |e, i| {
- if (out_zir.items[i] != e) {
- if (expected_output.len != out_zir.items.len) {
- 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 });
- std.process.exit(1);
+ var label: []const u8 = "ZIR";
+ if (case.c_standard) |cstd| {
+ label = @tagName(cstd);
+ var c: *link.File.C = module.bin_file.cast(link.File.C).?;
+ var out = c.file.?.reader().readAllAlloc(allocator, 1024 * 1024) catch @panic("Unable to read C output!");
+ defer allocator.free(out);
+
+ if (expected_output.len != out.len) {
+ std.debug.warn("{}\nTransformed {} length differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ case.name, label, expected_output, out });
+ std.process.exit(1);
+ }
+ for (expected_output) |e, i| {
+ if (out[i] != e) {
+ if (expected_output.len != out.len) {
+ std.debug.warn("{}\nTransformed {} differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ case.name, label, expected_output, out });
+ std.process.exit(1);
+ }
+ }
+ }
+ } else {
+ update_node.estimated_total_items = 5;
+ var emit_node = update_node.start("emit", null);
+ emit_node.activate();
+ var new_zir_module = try zir.emit(allocator, module);
+ defer new_zir_module.deinit(allocator);
+ emit_node.end();
+
+ var write_node = update_node.start("write", null);
+ write_node.activate();
+ var out_zir = std.ArrayList(u8).init(allocator);
+ defer out_zir.deinit();
+ try new_zir_module.writeToStream(allocator, out_zir.outStream());
+ write_node.end();
+
+ var test_node = update_node.start("assert", null);
+ test_node.activate();
+ defer test_node.end();
+
+ if (expected_output.len != out_zir.items.len) {
+ 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 });
+ std.process.exit(1);
+ }
+ for (expected_output) |e, i| {
+ if (out_zir.items[i] != e) {
+ if (expected_output.len != out_zir.items.len) {
+ 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 });
+ std.process.exit(1);
+ }
}
}
}
@@ -527,6 +548,8 @@ pub const TestContext = struct {
}
},
.Execution => |expected_stdout| {
+ std.debug.assert(case.c_standard == null);
+
update_node.estimated_total_items = 4;
var exec_result = x: {
var exec_node = update_node.start("execute", null);
test/stage2/cbe.zig
@@ -9,10 +9,10 @@ const linux_x64 = std.zig.CrossTarget{
};
pub fn addCases(ctx: *TestContext) !void {
- // // These tests should work on every platform
- // ctx.c11("empty start function", linux_x64,
- // \\export fn start() void {}
- // ,
- // \\void start(void) {}
- // );
+ // These tests should work on every platform
+ ctx.c11("empty start function", linux_x64,
+ \\export fn start() void {}
+ ,
+ \\void start(void) {}
+ );
}