Commit 1d202008d8
src-self-hosted/test.zig
@@ -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 {
test/stage2/zir.zig
@@ -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)
{