| ... | ... | @@ -16,6 +16,7 @@ test "self-hosted" { |
| 16 | 16 | |
| 17 | 17 | pub const TestContext = struct { |
| 18 | 18 | zir_cmp_output_cases: std.ArrayList(ZIRCompareOutputCase), |
| 19 | zir_transform_cases: std.ArrayList(ZIRTransformCase), |
| 19 | 20 | |
| 20 | 21 | pub const ZIRCompareOutputCase = struct { |
| 21 | 22 | name: []const u8, |
| ... | ... | @@ -23,6 +24,12 @@ pub const TestContext = struct { |
| 23 | 24 | expected_stdout: []const u8, |
| 24 | 25 | }; |
| 25 | 26 | |
| 27 | pub const ZIRTransformCase = struct { |
| 28 | name: []const u8, |
| 29 | src: [:0]const u8, |
| 30 | expected_zir: []const u8, |
| 31 | }; |
| 32 | |
| 26 | 33 | pub fn addZIRCompareOutput( |
| 27 | 34 | ctx: *TestContext, |
| 28 | 35 | name: []const u8, |
| ... | ... | @@ -36,20 +43,36 @@ pub const TestContext = struct { |
| 36 | 43 | }) catch unreachable; |
| 37 | 44 | } |
| 38 | 45 | |
| 46 | pub fn addZIRTransform( |
| 47 | ctx: *TestContext, |
| 48 | name: []const u8, |
| 49 | src: [:0]const u8, |
| 50 | expected_zir: []const u8, |
| 51 | ) void { |
| 52 | ctx.zir_transform_cases.append(.{ |
| 53 | .name = name, |
| 54 | .src = src, |
| 55 | .expected_zir = expected_zir, |
| 56 | }) catch unreachable; |
| 57 | } |
| 58 | |
| 39 | 59 | fn init(self: *TestContext) !void { |
| 40 | 60 | self.* = .{ |
| 41 | 61 | .zir_cmp_output_cases = std.ArrayList(ZIRCompareOutputCase).init(std.heap.page_allocator), |
| 62 | .zir_transform_cases = std.ArrayList(ZIRTransformCase).init(std.heap.page_allocator), |
| 42 | 63 | }; |
| 43 | 64 | } |
| 44 | 65 | |
| 45 | 66 | fn deinit(self: *TestContext) void { |
| 46 | 67 | self.zir_cmp_output_cases.deinit(); |
| 68 | self.zir_transform_cases.deinit(); |
| 47 | 69 | self.* = undefined; |
| 48 | 70 | } |
| 49 | 71 | |
| 50 | 72 | fn run(self: *TestContext) !void { |
| 51 | 73 | var progress = std.Progress{}; |
| 52 | | const root_node = try progress.start("zir", self.zir_cmp_output_cases.items.len); |
| 74 | const root_node = try progress.start("zir", self.zir_cmp_output_cases.items.len + |
| 75 | self.zir_transform_cases.items.len); |
| 53 | 76 | defer root_node.end(); |
| 54 | 77 | |
| 55 | 78 | const native_info = try std.zig.system.NativeTargetInfo.detect(std.heap.page_allocator, .{}); |
| ... | ... | @@ -59,6 +82,11 @@ pub const TestContext = struct { |
| 59 | 82 | try self.runOneZIRCmpOutputCase(std.testing.allocator, root_node, case, native_info.target); |
| 60 | 83 | try std.testing.allocator_instance.validate(); |
| 61 | 84 | } |
| 85 | for (self.zir_transform_cases.items) |case| { |
| 86 | std.testing.base_allocator_instance.reset(); |
| 87 | try self.runOneZIRTransformCase(std.testing.allocator, root_node, case, native_info.target); |
| 88 | try std.testing.allocator_instance.validate(); |
| 89 | } |
| 62 | 90 | } |
| 63 | 91 | |
| 64 | 92 | fn runOneZIRCmpOutputCase( |
| ... | ... | @@ -93,7 +121,12 @@ pub const TestContext = struct { |
| 93 | 121 | analyze_node.activate(); |
| 94 | 122 | defer analyze_node.end(); |
| 95 | 123 | |
| 96 | | break :x try ir.analyze(allocator, zir_module, target); |
| 124 | break :x try ir.analyze(allocator, zir_module, .{ |
| 125 | .target = target, |
| 126 | .output_mode = .Exe, |
| 127 | .link_mode = .Static, |
| 128 | .optimize_mode = .Debug, |
| 129 | }); |
| 97 | 130 | }; |
| 98 | 131 | defer analyzed_module.deinit(allocator); |
| 99 | 132 | if (analyzed_module.errors.len != 0) { |
| ... | ... | @@ -106,12 +139,7 @@ pub const TestContext = struct { |
| 106 | 139 | link_node.activate(); |
| 107 | 140 | defer link_node.end(); |
| 108 | 141 | |
| 109 | | break :x try link.updateExecutableFilePath( |
| 110 | | allocator, |
| 111 | | analyzed_module, |
| 112 | | tmp.dir, |
| 113 | | "a.out", |
| 114 | | ); |
| 142 | break :x try link.updateFilePath(allocator, analyzed_module, tmp.dir, "a.out"); |
| 115 | 143 | }; |
| 116 | 144 | defer link_result.deinit(allocator); |
| 117 | 145 | if (link_result.errors.len != 0) { |
| ... | ... | @@ -143,6 +171,58 @@ pub const TestContext = struct { |
| 143 | 171 | } |
| 144 | 172 | std.testing.expectEqualSlices(u8, case.expected_stdout, exec_result.stdout); |
| 145 | 173 | } |
| 174 | |
| 175 | fn runOneZIRTransformCase( |
| 176 | self: *TestContext, |
| 177 | allocator: *Allocator, |
| 178 | root_node: *std.Progress.Node, |
| 179 | case: ZIRTransformCase, |
| 180 | target: std.Target, |
| 181 | ) !void { |
| 182 | var prg_node = root_node.start(case.name, 4); |
| 183 | prg_node.activate(); |
| 184 | defer prg_node.end(); |
| 185 | |
| 186 | var parse_node = prg_node.start("parse", null); |
| 187 | parse_node.activate(); |
| 188 | var zir_module = try ir.text.parse(allocator, case.src); |
| 189 | defer zir_module.deinit(allocator); |
| 190 | if (zir_module.errors.len != 0) { |
| 191 | debugPrintErrors(case.src, zir_module.errors); |
| 192 | return error.ParseFailure; |
| 193 | } |
| 194 | parse_node.end(); |
| 195 | |
| 196 | var analyze_node = prg_node.start("analyze", null); |
| 197 | analyze_node.activate(); |
| 198 | var analyzed_module = try ir.analyze(allocator, zir_module, .{ |
| 199 | .target = target, |
| 200 | .output_mode = .Obj, |
| 201 | .link_mode = .Static, |
| 202 | .optimize_mode = .Debug, |
| 203 | }); |
| 204 | defer analyzed_module.deinit(allocator); |
| 205 | if (analyzed_module.errors.len != 0) { |
| 206 | debugPrintErrors(case.src, analyzed_module.errors); |
| 207 | return error.ParseFailure; |
| 208 | } |
| 209 | analyze_node.end(); |
| 210 | |
| 211 | var emit_node = prg_node.start("emit", null); |
| 212 | emit_node.activate(); |
| 213 | var new_zir_module = try ir.text.emit_zir(allocator, analyzed_module); |
| 214 | defer new_zir_module.deinit(allocator); |
| 215 | emit_node.end(); |
| 216 | |
| 217 | var write_node = prg_node.start("write", null); |
| 218 | write_node.activate(); |
| 219 | var out_zir = std.ArrayList(u8).init(allocator); |
| 220 | defer out_zir.deinit(); |
| 221 | try new_zir_module.writeToStream(allocator, out_zir.outStream()); |
| 222 | write_node.end(); |
| 223 | |
| 224 | std.testing.expectEqualSlices(u8, case.expected_zir, out_zir.items); |
| 225 | } |
| 146 | 226 | }; |
| 147 | 227 | |
| 148 | 228 | fn debugPrintErrors(src: []const u8, errors: var) void { |