add ZIR transform test case
parent
751903ba8f
commit
1d202008d8
|
@ -16,6 +16,7 @@ test "self-hosted" {
|
|||
|
||||
pub const TestContext = struct {
|
||||
zir_cmp_output_cases: std.ArrayList(ZIRCompareOutputCase),
|
||||
zir_transform_cases: std.ArrayList(ZIRTransformCase),
|
||||
|
||||
pub const ZIRCompareOutputCase = struct {
|
||||
name: []const u8,
|
||||
|
@ -23,6 +24,12 @@ pub const TestContext = struct {
|
|||
expected_stdout: []const u8,
|
||||
};
|
||||
|
||||
pub const ZIRTransformCase = struct {
|
||||
name: []const u8,
|
||||
src: [:0]const u8,
|
||||
expected_zir: []const u8,
|
||||
};
|
||||
|
||||
pub fn addZIRCompareOutput(
|
||||
ctx: *TestContext,
|
||||
name: []const u8,
|
||||
|
@ -36,20 +43,36 @@ pub const TestContext = struct {
|
|||
}) catch unreachable;
|
||||
}
|
||||
|
||||
pub fn addZIRTransform(
|
||||
ctx: *TestContext,
|
||||
name: []const u8,
|
||||
src: [:0]const u8,
|
||||
expected_zir: []const u8,
|
||||
) void {
|
||||
ctx.zir_transform_cases.append(.{
|
||||
.name = name,
|
||||
.src = src,
|
||||
.expected_zir = expected_zir,
|
||||
}) catch unreachable;
|
||||
}
|
||||
|
||||
fn init(self: *TestContext) !void {
|
||||
self.* = .{
|
||||
.zir_cmp_output_cases = std.ArrayList(ZIRCompareOutputCase).init(std.heap.page_allocator),
|
||||
.zir_transform_cases = std.ArrayList(ZIRTransformCase).init(std.heap.page_allocator),
|
||||
};
|
||||
}
|
||||
|
||||
fn deinit(self: *TestContext) void {
|
||||
self.zir_cmp_output_cases.deinit();
|
||||
self.zir_transform_cases.deinit();
|
||||
self.* = undefined;
|
||||
}
|
||||
|
||||
fn run(self: *TestContext) !void {
|
||||
var progress = std.Progress{};
|
||||
const root_node = try progress.start("zir", self.zir_cmp_output_cases.items.len);
|
||||
const root_node = try progress.start("zir", self.zir_cmp_output_cases.items.len +
|
||||
self.zir_transform_cases.items.len);
|
||||
defer root_node.end();
|
||||
|
||||
const native_info = try std.zig.system.NativeTargetInfo.detect(std.heap.page_allocator, .{});
|
||||
|
@ -59,6 +82,11 @@ pub const TestContext = struct {
|
|||
try self.runOneZIRCmpOutputCase(std.testing.allocator, root_node, case, native_info.target);
|
||||
try std.testing.allocator_instance.validate();
|
||||
}
|
||||
for (self.zir_transform_cases.items) |case| {
|
||||
std.testing.base_allocator_instance.reset();
|
||||
try self.runOneZIRTransformCase(std.testing.allocator, root_node, case, native_info.target);
|
||||
try std.testing.allocator_instance.validate();
|
||||
}
|
||||
}
|
||||
|
||||
fn runOneZIRCmpOutputCase(
|
||||
|
@ -93,7 +121,12 @@ pub const TestContext = struct {
|
|||
analyze_node.activate();
|
||||
defer analyze_node.end();
|
||||
|
||||
break :x try ir.analyze(allocator, zir_module, target);
|
||||
break :x try ir.analyze(allocator, zir_module, .{
|
||||
.target = target,
|
||||
.output_mode = .Exe,
|
||||
.link_mode = .Static,
|
||||
.optimize_mode = .Debug,
|
||||
});
|
||||
};
|
||||
defer analyzed_module.deinit(allocator);
|
||||
if (analyzed_module.errors.len != 0) {
|
||||
|
@ -106,12 +139,7 @@ pub const TestContext = struct {
|
|||
link_node.activate();
|
||||
defer link_node.end();
|
||||
|
||||
break :x try link.updateExecutableFilePath(
|
||||
allocator,
|
||||
analyzed_module,
|
||||
tmp.dir,
|
||||
"a.out",
|
||||
);
|
||||
break :x try link.updateFilePath(allocator, analyzed_module, tmp.dir, "a.out");
|
||||
};
|
||||
defer link_result.deinit(allocator);
|
||||
if (link_result.errors.len != 0) {
|
||||
|
@ -143,6 +171,58 @@ pub const TestContext = struct {
|
|||
}
|
||||
std.testing.expectEqualSlices(u8, case.expected_stdout, exec_result.stdout);
|
||||
}
|
||||
|
||||
fn runOneZIRTransformCase(
|
||||
self: *TestContext,
|
||||
allocator: *Allocator,
|
||||
root_node: *std.Progress.Node,
|
||||
case: ZIRTransformCase,
|
||||
target: std.Target,
|
||||
) !void {
|
||||
var prg_node = root_node.start(case.name, 4);
|
||||
prg_node.activate();
|
||||
defer prg_node.end();
|
||||
|
||||
var parse_node = prg_node.start("parse", null);
|
||||
parse_node.activate();
|
||||
var zir_module = try ir.text.parse(allocator, case.src);
|
||||
defer zir_module.deinit(allocator);
|
||||
if (zir_module.errors.len != 0) {
|
||||
debugPrintErrors(case.src, zir_module.errors);
|
||||
return error.ParseFailure;
|
||||
}
|
||||
parse_node.end();
|
||||
|
||||
var analyze_node = prg_node.start("analyze", null);
|
||||
analyze_node.activate();
|
||||
var analyzed_module = try ir.analyze(allocator, zir_module, .{
|
||||
.target = target,
|
||||
.output_mode = .Obj,
|
||||
.link_mode = .Static,
|
||||
.optimize_mode = .Debug,
|
||||
});
|
||||
defer analyzed_module.deinit(allocator);
|
||||
if (analyzed_module.errors.len != 0) {
|
||||
debugPrintErrors(case.src, analyzed_module.errors);
|
||||
return error.ParseFailure;
|
||||
}
|
||||
analyze_node.end();
|
||||
|
||||
var emit_node = prg_node.start("emit", null);
|
||||
emit_node.activate();
|
||||
var new_zir_module = try ir.text.emit_zir(allocator, analyzed_module);
|
||||
defer new_zir_module.deinit(allocator);
|
||||
emit_node.end();
|
||||
|
||||
var write_node = prg_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();
|
||||
|
||||
std.testing.expectEqualSlices(u8, case.expected_zir, out_zir.items);
|
||||
}
|
||||
};
|
||||
|
||||
fn debugPrintErrors(src: []const u8, errors: var) void {
|
||||
|
|
|
@ -1,6 +1,51 @@
|
|||
const TestContext = @import("../../src-self-hosted/test.zig").TestContext;
|
||||
|
||||
pub fn addCases(ctx: *TestContext) void {
|
||||
ctx.addZIRTransform("elemptr, add, cmp, condbr, return, breakpoint",
|
||||
\\@void = primitive(void)
|
||||
\\@usize = primitive(usize)
|
||||
\\@fnty = fntype([], @void, cc=C)
|
||||
\\@0 = int(0)
|
||||
\\@1 = int(1)
|
||||
\\@2 = int(2)
|
||||
\\@3 = int(3)
|
||||
\\
|
||||
\\@entry = fn(@fnty, {
|
||||
\\ %a = str("\x32\x08\x01\x0a")
|
||||
\\ %eptr0 = elemptr(%a, @0)
|
||||
\\ %eptr1 = elemptr(%a, @1)
|
||||
\\ %eptr2 = elemptr(%a, @2)
|
||||
\\ %eptr3 = elemptr(%a, @3)
|
||||
\\ %v0 = deref(%eptr0)
|
||||
\\ %v1 = deref(%eptr1)
|
||||
\\ %v2 = deref(%eptr2)
|
||||
\\ %v3 = deref(%eptr3)
|
||||
\\ %x0 = add(%v0, %v1)
|
||||
\\ %x1 = add(%v2, %v3)
|
||||
\\ %result = add(%x0, %x1)
|
||||
\\
|
||||
\\ %expected = int(69)
|
||||
\\ %ok = cmp(%result, eq, %expected)
|
||||
\\ %10 = condbr(%ok, {
|
||||
\\ %11 = return()
|
||||
\\ }, {
|
||||
\\ %12 = breakpoint()
|
||||
\\ })
|
||||
\\})
|
||||
\\
|
||||
\\@9 = str("entry")
|
||||
\\@10 = export(@9, @entry)
|
||||
,
|
||||
\\@0 = primitive(void)
|
||||
\\@1 = fntype([], @0, cc=C)
|
||||
\\@2 = fn(@1, {
|
||||
\\ %0 = return()
|
||||
\\})
|
||||
\\@3 = str("entry")
|
||||
\\@4 = export(@3, @2)
|
||||
\\
|
||||
);
|
||||
|
||||
if (@import("std").Target.current.os.tag != .linux or
|
||||
@import("std").Target.current.cpu.arch != .x86_64)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue