CBE skeleton
parent
b4c571301b
commit
a17200dab1
|
@ -38,7 +38,11 @@ pub fn openBinFilePath(
|
||||||
errdefer file.close();
|
errdefer file.close();
|
||||||
|
|
||||||
if (options.c_standard) |cstd| {
|
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 {
|
} else {
|
||||||
var bin_file = try allocator.create(File.Elf);
|
var bin_file = try allocator.create(File.Elf);
|
||||||
errdefer allocator.destroy(bin_file);
|
errdefer allocator.destroy(bin_file);
|
||||||
|
@ -82,6 +86,17 @@ pub fn writeFilePath(
|
||||||
return result;
|
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.
|
/// Attempts incremental linking, if the file already exists.
|
||||||
/// If incremental linking fails, falls back to truncating the file and rewriting it.
|
/// 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.
|
/// 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 {
|
pub fn makeWritable(base: *File, dir: fs.Dir, sub_path: []const u8) !void {
|
||||||
try switch (base.tag) {
|
try switch (base.tag) {
|
||||||
.Elf => @fieldParentPtr(Elf, "base", base).makeWritable(dir, sub_path),
|
.Elf => @fieldParentPtr(Elf, "base", base).makeWritable(dir, sub_path),
|
||||||
|
.C => @fieldParentPtr(C, "base", base).makeWritable(dir, sub_path),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -122,6 +138,7 @@ pub const File = struct {
|
||||||
pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void {
|
pub fn updateDecl(base: *File, module: *Module, decl: *Module.Decl) !void {
|
||||||
try switch (base.tag) {
|
try switch (base.tag) {
|
||||||
.Elf => @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),
|
.Elf => @fieldParentPtr(Elf, "base", base).updateDecl(module, decl),
|
||||||
|
.C => @fieldParentPtr(C, "base", base).updateDecl(module, decl),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -129,6 +146,9 @@ pub const File = struct {
|
||||||
pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void {
|
pub fn allocateDeclIndexes(base: *File, decl: *Module.Decl) !void {
|
||||||
try switch (base.tag) {
|
try switch (base.tag) {
|
||||||
.Elf => @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl),
|
.Elf => @fieldParentPtr(Elf, "base", base).allocateDeclIndexes(decl),
|
||||||
|
.C => {
|
||||||
|
//TODO
|
||||||
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -136,6 +156,7 @@ pub const File = struct {
|
||||||
pub fn deinit(base: *File) void {
|
pub fn deinit(base: *File) void {
|
||||||
switch (base.tag) {
|
switch (base.tag) {
|
||||||
.Elf => @fieldParentPtr(Elf, "base", base).deinit(),
|
.Elf => @fieldParentPtr(Elf, "base", base).deinit(),
|
||||||
|
.C => @fieldParentPtr(C, "base", base).deinit(),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,6 +164,9 @@ pub const File = struct {
|
||||||
pub fn flush(base: *File) !void {
|
pub fn flush(base: *File) !void {
|
||||||
try switch (base.tag) {
|
try switch (base.tag) {
|
||||||
.Elf => @fieldParentPtr(Elf, "base", base).flush(),
|
.Elf => @fieldParentPtr(Elf, "base", base).flush(),
|
||||||
|
.C => {
|
||||||
|
//TODO
|
||||||
|
},
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -157,6 +181,7 @@ pub const File = struct {
|
||||||
pub fn errorFlags(base: *File) ErrorFlags {
|
pub fn errorFlags(base: *File) ErrorFlags {
|
||||||
return switch (base.tag) {
|
return switch (base.tag) {
|
||||||
.Elf => @fieldParentPtr(Elf, "base", base).error_flags,
|
.Elf => @fieldParentPtr(Elf, "base", base).error_flags,
|
||||||
|
.C => return .{ .no_entry_point_found = false },
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -176,6 +201,38 @@ pub const File = struct {
|
||||||
pub const ErrorFlags = struct {
|
pub const ErrorFlags = struct {
|
||||||
no_entry_point_found: bool = false,
|
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 Elf = struct {
|
||||||
pub const base_tag: Tag = .Elf;
|
pub const base_tag: Tag = .Elf;
|
||||||
base: File = File{ .tag = base_tag },
|
base: File = File{ .tag = base_tag },
|
||||||
|
|
|
@ -464,6 +464,26 @@ pub const TestContext = struct {
|
||||||
|
|
||||||
switch (update.case) {
|
switch (update.case) {
|
||||||
.Transformation => |expected_output| {
|
.Transformation => |expected_output| {
|
||||||
|
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;
|
update_node.estimated_total_items = 5;
|
||||||
var emit_node = update_node.start("emit", null);
|
var emit_node = update_node.start("emit", null);
|
||||||
emit_node.activate();
|
emit_node.activate();
|
||||||
|
@ -481,7 +501,7 @@ pub const TestContext = struct {
|
||||||
var test_node = update_node.start("assert", null);
|
var test_node = update_node.start("assert", null);
|
||||||
test_node.activate();
|
test_node.activate();
|
||||||
defer test_node.end();
|
defer test_node.end();
|
||||||
const label = if (case.c_standard) |_| "C" else "ZIR";
|
|
||||||
if (expected_output.len != out_zir.items.len) {
|
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.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);
|
std.process.exit(1);
|
||||||
|
@ -494,6 +514,7 @@ pub const TestContext = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
.Error => |e| {
|
.Error => |e| {
|
||||||
var test_node = update_node.start("assert", null);
|
var test_node = update_node.start("assert", null);
|
||||||
|
@ -527,6 +548,8 @@ pub const TestContext = struct {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
.Execution => |expected_stdout| {
|
.Execution => |expected_stdout| {
|
||||||
|
std.debug.assert(case.c_standard == null);
|
||||||
|
|
||||||
update_node.estimated_total_items = 4;
|
update_node.estimated_total_items = 4;
|
||||||
var exec_result = x: {
|
var exec_result = x: {
|
||||||
var exec_node = update_node.start("execute", null);
|
var exec_node = update_node.start("execute", null);
|
||||||
|
|
|
@ -9,10 +9,10 @@ const linux_x64 = std.zig.CrossTarget{
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn addCases(ctx: *TestContext) !void {
|
pub fn addCases(ctx: *TestContext) !void {
|
||||||
// // These tests should work on every platform
|
// These tests should work on every platform
|
||||||
// ctx.c11("empty start function", linux_x64,
|
ctx.c11("empty start function", linux_x64,
|
||||||
// \\export fn start() void {}
|
\\export fn start() void {}
|
||||||
// ,
|
,
|
||||||
// \\void start(void) {}
|
\\void start(void) {}
|
||||||
// );
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue