authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-24 21:28:42-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-06-24 21:28:42-04:00
log20b4a2cf2cded8904a57714ed2b90c857f12c6b1
treeb37d1fbc232319fd4e6e358183c80f1aa42f09ca
parent5aa3f56773f4b06629184a1e3753c3132b18e0bd

self-hosted: add compare output test for new AST->ZIR code


5 files changed, 372 insertions(+), 300 deletions(-)

lib/std/zig.zig+21
......@@ -43,6 +43,27 @@ pub fn findLineColumn(source: []const u8, byte_offset: usize) struct { line: usi
4343 return .{ .line = line, .column = column };
4444}
4545
46/// Returns the standard file system basename of a binary generated by the Zig compiler.
47pub fn binNameAlloc(
48 allocator: *std.mem.Allocator,
49 root_name: []const u8,
50 target: std.Target,
51 output_mode: std.builtin.OutputMode,
52 link_mode: ?std.builtin.LinkMode,
53) error{OutOfMemory}![]u8 {
54 switch (output_mode) {
55 .Exe => return std.fmt.allocPrint(allocator, "{}{}", .{ root_name, target.exeFileExt() }),
56 .Lib => {
57 const suffix = switch (link_mode orelse .Static) {
58 .Static => target.staticLibSuffix(),
59 .Dynamic => target.dynamicLibSuffix(),
60 };
61 return std.fmt.allocPrint(allocator, "{}{}{}", .{ target.libPrefix(), root_name, suffix });
62 },
63 .Obj => return std.fmt.allocPrint(allocator, "{}{}", .{ root_name, target.oFileExt() }),
64 }
65}
66
4667test "" {
4768 @import("std").meta.refAllDecls(@This());
4869}
src-self-hosted/main.zig+2-17
......@@ -50,8 +50,7 @@ pub fn log(
5050 const scope_prefix = "(" ++ switch (scope) {
5151 // Uncomment to hide logs
5252 //.compiler,
53 .link,
54 => return,
53 .link => return,
5554
5655 else => @tagName(scope),
5756 } ++ "): ";
......@@ -431,21 +430,7 @@ fn buildOutputType(
431430 std.debug.warn("-fno-emit-bin not supported yet", .{});
432431 process.exit(1);
433432 },
434 .yes_default_path => switch (output_mode) {
435 .Exe => try std.fmt.allocPrint(arena, "{}{}", .{ root_name, target_info.target.exeFileExt() }),
436 .Lib => blk: {
437 const suffix = switch (link_mode orelse .Static) {
438 .Static => target_info.target.staticLibSuffix(),
439 .Dynamic => target_info.target.dynamicLibSuffix(),
440 };
441 break :blk try std.fmt.allocPrint(arena, "{}{}{}", .{
442 target_info.target.libPrefix(),
443 root_name,
444 suffix,
445 });
446 },
447 .Obj => try std.fmt.allocPrint(arena, "{}{}", .{ root_name, target_info.target.oFileExt() }),
448 },
433 .yes_default_path => try std.zig.binNameAlloc(arena, root_name, target_info.target, output_mode, link_mode),
449434 .yes => |p| p,
450435 };
451436
src-self-hosted/test.zig+138-157
......@@ -21,32 +21,7 @@ const ErrorMsg = struct {
2121};
2222
2323pub const TestContext = struct {
24 // TODO: remove these. They are deprecated.
25 zir_cmp_output_cases: std.ArrayList(ZIRCompareOutputCase),
26
27 /// TODO: find a way to treat cases as individual tests (shouldn't show "1 test passed" if there are 200 cases)
28 zir_cases: std.ArrayList(ZIRCase),
29
30 // TODO: remove
31 pub const ZIRCompareOutputCase = struct {
32 name: []const u8,
33 src_list: []const []const u8,
34 expected_stdout_list: []const []const u8,
35 };
36
37 pub const ZIRUpdateType = enum {
38 /// A transformation update transforms the input ZIR and tests against
39 /// the expected output
40 Transformation,
41 /// An error update attempts to compile bad code, and ensures that it
42 /// fails to compile, and for the expected reasons
43 Error,
44 /// An execution update compiles and runs the input ZIR, feeding in
45 /// provided input and ensuring that the outputs match what is expected
46 Execution,
47 /// A compilation update checks that the ZIR compiles without any issues
48 Compiles,
49 };
24 zir_cases: std.ArrayList(Case),
5025
5126 pub const ZIRUpdate = struct {
5227 /// The input to the current update. We simulate an incremental update
......@@ -57,58 +32,55 @@ pub const TestContext = struct {
5732 /// you can keep it mostly consistent, with small changes, testing the
5833 /// effects of the incremental compilation.
5934 src: [:0]const u8,
60 case: union(ZIRUpdateType) {
61 /// The expected output ZIR
35 case: union(enum) {
36 /// A transformation update transforms the input ZIR and tests against
37 /// the expected output ZIR.
6238 Transformation: [:0]const u8,
39 /// An error update attempts to compile bad code, and ensures that it
40 /// fails to compile, and for the expected reasons.
6341 /// A slice containing the expected errors *in sequential order*.
6442 Error: []const ErrorMsg,
65
66 /// Input to feed to the program, and expected outputs.
67 ///
68 /// If stdout, stderr, and exit_code are all null, addZIRCase will
69 /// discard the test. To test for successful compilation, use a
70 /// dedicated Compile update instead.
71 Execution: struct {
72 stdin: ?[]const u8,
73 stdout: ?[]const u8,
74 stderr: ?[]const u8,
75 exit_code: ?u8,
76 },
77 /// A Compiles test checks only that compilation of the given ZIR
78 /// succeeds. To test outputs, use an Execution test. It is good to
79 /// use a Compiles test before an Execution, as the overhead should
80 /// be low (due to incremental compilation) and TODO: provide a way
81 /// to check changed / new / etc decls in testing mode
82 /// (usingnamespace a debug info struct with a comptime flag?)
83 Compiles: void,
43 /// An execution update compiles and runs the input ZIR, feeding in
44 /// provided input and ensuring that the stdout match what is expected.
45 Execution: []const u8,
8446 },
8547 };
8648
87 /// A ZIRCase consists of a set of *updates*. A update can transform ZIR,
49 /// A Case consists of a set of *updates*. A update can transform ZIR,
8850 /// compile it, ensure that compilation fails, and more. The same Module is
8951 /// used for each update, so each update's source is treated as a single file
9052 /// being updated by the test harness and incrementally compiled.
91 pub const ZIRCase = struct {
53 pub const Case = struct {
9254 name: []const u8,
9355 /// The platform the ZIR targets. For non-native platforms, an emulator
9456 /// such as QEMU is required for tests to complete.
9557 target: std.zig.CrossTarget,
9658 updates: std.ArrayList(ZIRUpdate),
59 output_mode: std.builtin.OutputMode,
60 /// Either ".zir" or ".zig"
61 extension: [4]u8,
9762
9863 /// Adds a subcase in which the module is updated with new ZIR, and the
9964 /// resulting ZIR is validated.
100 pub fn addTransform(self: *ZIRCase, src: [:0]const u8, result: [:0]const u8) void {
65 pub fn addTransform(self: *Case, src: [:0]const u8, result: [:0]const u8) void {
10166 self.updates.append(.{
10267 .src = src,
10368 .case = .{ .Transformation = result },
10469 }) catch unreachable;
10570 }
10671
72 pub fn addCompareOutput(self: *Case, src: [:0]const u8, result: []const u8) void {
73 self.updates.append(.{
74 .src = src,
75 .case = .{ .Execution = result },
76 }) catch unreachable;
77 }
78
10779 /// Adds a subcase in which the module is updated with invalid ZIR, and
10880 /// ensures that compilation fails for the expected reasons.
10981 ///
11082 /// Errors must be specified in sequential order.
111 pub fn addError(self: *ZIRCase, src: [:0]const u8, errors: []const []const u8) void {
83 pub fn addError(self: *Case, src: [:0]const u8, errors: []const []const u8) void {
11284 var array = self.updates.allocator.alloc(ErrorMsg, errors.len) catch unreachable;
11385 for (errors) |e, i| {
11486 if (e[0] != ':') {
......@@ -146,15 +118,65 @@ pub const TestContext = struct {
146118 }
147119 };
148120
149 pub fn addZIRMulti(
121 pub fn addExeZIR(
122 ctx: *TestContext,
123 name: []const u8,
124 target: std.zig.CrossTarget,
125 ) *Case {
126 const case = Case{
127 .name = name,
128 .target = target,
129 .updates = std.ArrayList(ZIRUpdate).init(ctx.zir_cases.allocator),
130 .output_mode = .Exe,
131 .extension = ".zir".*,
132 };
133 ctx.zir_cases.append(case) catch unreachable;
134 return &ctx.zir_cases.items[ctx.zir_cases.items.len - 1];
135 }
136
137 pub fn addObjZIR(
138 ctx: *TestContext,
139 name: []const u8,
140 target: std.zig.CrossTarget,
141 ) *Case {
142 const case = Case{
143 .name = name,
144 .target = target,
145 .updates = std.ArrayList(ZIRUpdate).init(ctx.zir_cases.allocator),
146 .output_mode = .Obj,
147 .extension = ".zir".*,
148 };
149 ctx.zir_cases.append(case) catch unreachable;
150 return &ctx.zir_cases.items[ctx.zir_cases.items.len - 1];
151 }
152
153 pub fn addExe(
150154 ctx: *TestContext,
151155 name: []const u8,
152156 target: std.zig.CrossTarget,
153 ) *ZIRCase {
154 const case = ZIRCase{
157 ) *Case {
158 const case = Case{
155159 .name = name,
156160 .target = target,
157161 .updates = std.ArrayList(ZIRUpdate).init(ctx.zir_cases.allocator),
162 .output_mode = .Exe,
163 .extension = ".zig".*,
164 };
165 ctx.zir_cases.append(case) catch unreachable;
166 return &ctx.zir_cases.items[ctx.zir_cases.items.len - 1];
167 }
168
169 pub fn addObj(
170 ctx: *TestContext,
171 name: []const u8,
172 target: std.zig.CrossTarget,
173 ) *Case {
174 const case = Case{
175 .name = name,
176 .target = target,
177 .updates = std.ArrayList(ZIRUpdate).init(ctx.zir_cases.allocator),
178 .output_mode = .Obj,
179 .extension = ".zig".*,
158180 };
159181 ctx.zir_cases.append(case) catch unreachable;
160182 return &ctx.zir_cases.items[ctx.zir_cases.items.len - 1];
......@@ -163,14 +185,21 @@ pub const TestContext = struct {
163185 pub fn addZIRCompareOutput(
164186 ctx: *TestContext,
165187 name: []const u8,
166 src_list: []const []const u8,
167 expected_stdout_list: []const []const u8,
188 src: [:0]const u8,
189 expected_stdout: []const u8,
168190 ) void {
169 ctx.zir_cmp_output_cases.append(.{
170 .name = name,
171 .src_list = src_list,
172 .expected_stdout_list = expected_stdout_list,
173 }) catch unreachable;
191 var c = ctx.addExeZIR(name, .{});
192 c.addCompareOutput(src, expected_stdout);
193 }
194
195 pub fn addCompareOutput(
196 ctx: *TestContext,
197 name: []const u8,
198 src: [:0]const u8,
199 expected_stdout: []const u8,
200 ) void {
201 var c = ctx.addExe(name, .{});
202 c.addCompareOutput(src, expected_stdout);
174203 }
175204
176205 pub fn addZIRTransform(
......@@ -180,7 +209,7 @@ pub const TestContext = struct {
180209 src: [:0]const u8,
181210 result: [:0]const u8,
182211 ) void {
183 var c = ctx.addZIRMulti(name, target);
212 var c = ctx.addObjZIR(name, target);
184213 c.addTransform(src, result);
185214 }
186215
......@@ -191,20 +220,18 @@ pub const TestContext = struct {
191220 src: [:0]const u8,
192221 expected_errors: []const []const u8,
193222 ) void {
194 var c = ctx.addZIRMulti(name, target);
223 var c = ctx.addObjZIR(name, target);
195224 c.addError(src, expected_errors);
196225 }
197226
198227 fn init() TestContext {
199228 const allocator = std.heap.page_allocator;
200229 return .{
201 .zir_cmp_output_cases = std.ArrayList(ZIRCompareOutputCase).init(allocator),
202 .zir_cases = std.ArrayList(ZIRCase).init(allocator),
230 .zir_cases = std.ArrayList(Case).init(allocator),
203231 };
204232 }
205233
206234 fn deinit(self: *TestContext) void {
207 self.zir_cmp_output_cases.deinit();
208235 for (self.zir_cases.items) |c| {
209236 for (c.updates.items) |u| {
210237 if (u.case == .Error) {
......@@ -235,34 +262,24 @@ pub const TestContext = struct {
235262 progress.refresh();
236263
237264 const info = try std.zig.system.NativeTargetInfo.detect(std.testing.allocator, case.target);
238 try self.runOneZIRCase(std.testing.allocator, &prg_node, case, info.target);
239 try std.testing.allocator_instance.validate();
240 }
241
242 // TODO: wipe the rest of this function
243 for (self.zir_cmp_output_cases.items) |case| {
244 std.testing.base_allocator_instance.reset();
245
246 var prg_node = root_node.start(case.name, case.src_list.len);
247 prg_node.activate();
248 defer prg_node.end();
249
250 // So that we can see which test case failed when the leak checker goes off.
251 progress.refresh();
252
253 try self.runOneZIRCmpOutputCase(std.testing.allocator, &prg_node, case, native_info.target);
265 try self.runOneCase(std.testing.allocator, &prg_node, case, info.target);
254266 try std.testing.allocator_instance.validate();
255267 }
256268 }
257269
258 fn runOneZIRCase(self: *TestContext, allocator: *Allocator, prg_node: *std.Progress.Node, case: ZIRCase, target: std.Target) !void {
270 fn runOneCase(self: *TestContext, allocator: *Allocator, prg_node: *std.Progress.Node, case: Case, target: std.Target) !void {
259271 var tmp = std.testing.tmpDir(.{});
260272 defer tmp.cleanup();
261273
262 const tmp_src_path = "test_case.zir";
274 const root_name = "test_case";
275 const tmp_src_path = try std.fmt.allocPrint(allocator, "{}{}", .{ root_name, case.extension });
276 defer allocator.free(tmp_src_path);
263277 const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path);
264278 defer root_pkg.destroy();
265279
280 const bin_name = try std.zig.binNameAlloc(allocator, root_name, target, case.output_mode, null);
281 defer allocator.free(bin_name);
282
266283 var module = try Module.init(allocator, .{
267284 .target = target,
268285 // This is an Executable, as opposed to e.g. a *library*. This does
......@@ -271,17 +288,17 @@ pub const TestContext = struct {
271288 // TODO: support tests for object file building, and library builds
272289 // and linking. This will require a rework to support multi-file
273290 // tests.
274 .output_mode = .Obj,
291 .output_mode = case.output_mode,
275292 // TODO: support testing optimizations
276293 .optimize_mode = .Debug,
277294 .bin_file_dir = tmp.dir,
278 .bin_file_path = "test_case.o",
295 .bin_file_path = bin_name,
279296 .root_pkg = root_pkg,
280297 .keep_source_files_loaded = true,
281298 });
282299 defer module.deinit();
283300
284 for (case.updates.items) |update| {
301 for (case.updates.items) |update, update_index| {
285302 var update_node = prg_node.start("update", 4);
286303 update_node.activate();
287304 defer update_node.end();
......@@ -293,6 +310,7 @@ pub const TestContext = struct {
293310
294311 var module_node = update_node.start("parse/analysis/codegen", null);
295312 module_node.activate();
313 try module.makeBinFileWritable();
296314 try module.update();
297315 module_node.end();
298316
......@@ -341,78 +359,41 @@ pub const TestContext = struct {
341359 }
342360 }
343361 },
344
345 else => return error.Unimplemented,
346 }
347 }
348 }
349
350 fn runOneZIRCmpOutputCase(
351 self: *TestContext,
352 allocator: *Allocator,
353 prg_node: *std.Progress.Node,
354 case: ZIRCompareOutputCase,
355 target: std.Target,
356 ) !void {
357 var tmp = std.testing.tmpDir(.{});
358 defer tmp.cleanup();
359
360 const tmp_src_path = "test-case.zir";
361 const root_pkg = try Package.create(allocator, tmp.dir, ".", tmp_src_path);
362 defer root_pkg.destroy();
363
364 var module = try Module.init(allocator, .{
365 .target = target,
366 .output_mode = .Exe,
367 .optimize_mode = .Debug,
368 .bin_file_dir = tmp.dir,
369 .bin_file_path = "a.out",
370 .root_pkg = root_pkg,
371 });
372 defer module.deinit();
373
374 for (case.src_list) |source, i| {
375 var src_node = prg_node.start("update", 2);
376 src_node.activate();
377 defer src_node.end();
378
379 try tmp.dir.writeFile(tmp_src_path, source);
380
381 var update_node = src_node.start("parse,analysis,codegen", null);
382 update_node.activate();
383 try module.makeBinFileWritable();
384 try module.update();
385 update_node.end();
386
387 var exec_result = x: {
388 var exec_node = src_node.start("execute", null);
389 exec_node.activate();
390 defer exec_node.end();
391
392 try module.makeBinFileExecutable();
393 break :x try std.ChildProcess.exec(.{
394 .allocator = allocator,
395 .argv = &[_][]const u8{"./a.out"},
396 .cwd_dir = tmp.dir,
397 });
398 };
399 defer allocator.free(exec_result.stdout);
400 defer allocator.free(exec_result.stderr);
401 switch (exec_result.term) {
402 .Exited => |code| {
403 if (code != 0) {
404 std.debug.warn("elf file exited with code {}\n", .{code});
405 return error.BinaryBadExitCode;
362 .Execution => |expected_stdout| {
363 var exec_result = x: {
364 var exec_node = update_node.start("execute", null);
365 exec_node.activate();
366 defer exec_node.end();
367
368 try module.makeBinFileExecutable();
369
370 const exe_path = try std.fmt.allocPrint(allocator, "." ++ std.fs.path.sep_str ++ "{}", .{bin_name});
371 defer allocator.free(exe_path);
372
373 break :x try std.ChildProcess.exec(.{
374 .allocator = allocator,
375 .argv = &[_][]const u8{exe_path},
376 .cwd_dir = tmp.dir,
377 });
378 };
379 defer allocator.free(exec_result.stdout);
380 defer allocator.free(exec_result.stderr);
381 switch (exec_result.term) {
382 .Exited => |code| {
383 if (code != 0) {
384 std.debug.warn("elf file exited with code {}\n", .{code});
385 return error.BinaryBadExitCode;
386 }
387 },
388 else => return error.BinaryCrashed,
389 }
390 if (!std.mem.eql(u8, expected_stdout, exec_result.stdout)) {
391 std.debug.panic(
392 "update index {}, mismatched stdout\n====Expected (len={}):====\n{}\n====Actual (len={}):====\n{}\n========\n",
393 .{ update_index, expected_stdout.len, expected_stdout, exec_result.stdout.len, exec_result.stdout },
394 );
406395 }
407396 },
408 else => return error.BinaryCrashed,
409 }
410 const expected_stdout = case.expected_stdout_list[i];
411 if (!std.mem.eql(u8, expected_stdout, exec_result.stdout)) {
412 std.debug.panic(
413 "update index {}, mismatched stdout\n====Expected (len={}):====\n{}\n====Actual (len={}):====\n{}\n========\n",
414 .{ i, expected_stdout.len, expected_stdout, exec_result.stdout.len, exec_result.stdout },
415 );
416397 }
417398 }
418399 }
test/stage2/compare_output.zig+115-22
......@@ -1,28 +1,121 @@
11const std = @import("std");
22const TestContext = @import("../../src-self-hosted/test.zig").TestContext;
3// self-hosted does not yet support PE executable files / COFF object files
4// or mach-o files. So we do these test cases cross compiling for x86_64-linux.
5const linux_x64 = std.zig.CrossTarget{
6 .cpu_arch = .x86_64,
7 .os_tag = .linux,
8};
39
410pub fn addCases(ctx: *TestContext) !void {
5 // TODO: re-enable these tests.
6 // https://github.com/ziglang/zig/issues/1364
11 if (std.Target.current.os.tag != .linux or
12 std.Target.current.cpu.arch != .x86_64)
13 {
14 // TODO implement self-hosted PE (.exe file) linking
15 // TODO implement more ZIR so we don't depend on x86_64-linux
16 return;
17 }
718
8 //// hello world
9 //try ctx.testCompareOutputLibC(
10 // \\extern fn puts([*]const u8) void;
11 // \\pub export fn main() c_int {
12 // \\ puts("Hello, world!");
13 // \\ return 0;
14 // \\}
15 //, "Hello, world!" ++ std.cstr.line_sep);
16
17 //// function calling another function
18 //try ctx.testCompareOutputLibC(
19 // \\extern fn puts(s: [*]const u8) void;
20 // \\pub export fn main() c_int {
21 // \\ return foo("OK");
22 // \\}
23 // \\fn foo(s: [*]const u8) c_int {
24 // \\ puts(s);
25 // \\ return 0;
26 // \\}
27 //, "OK" ++ std.cstr.line_sep);
19 {
20 var case = ctx.addExe("hello world with updates", linux_x64);
21 // Regular old hello world
22 case.addCompareOutput(
23 \\export fn _start() noreturn {
24 \\ print();
25 \\
26 \\ exit();
27 \\}
28 \\
29 \\fn print() void {
30 \\ asm volatile ("syscall"
31 \\ :
32 \\ : [number] "{rax}" (1),
33 \\ [arg1] "{rdi}" (1),
34 \\ [arg2] "{rsi}" (@ptrToInt("Hello, World!\n")),
35 \\ [arg3] "{rdx}" (14)
36 \\ : "rcx", "r11", "memory"
37 \\ );
38 \\ return;
39 \\}
40 \\
41 \\fn exit() noreturn {
42 \\ asm volatile ("syscall"
43 \\ :
44 \\ : [number] "{rax}" (231),
45 \\ [arg1] "{rdi}" (0)
46 \\ : "rcx", "r11", "memory"
47 \\ );
48 \\ unreachable;
49 \\}
50 ,
51 "Hello, World!\n",
52 );
53 // Now change the message only
54 case.addCompareOutput(
55 \\export fn _start() noreturn {
56 \\ print();
57 \\
58 \\ exit();
59 \\}
60 \\
61 \\fn print() void {
62 \\ asm volatile ("syscall"
63 \\ :
64 \\ : [number] "{rax}" (1),
65 \\ [arg1] "{rdi}" (1),
66 \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
67 \\ [arg3] "{rdx}" (104)
68 \\ : "rcx", "r11", "memory"
69 \\ );
70 \\ return;
71 \\}
72 \\
73 \\fn exit() noreturn {
74 \\ asm volatile ("syscall"
75 \\ :
76 \\ : [number] "{rax}" (231),
77 \\ [arg1] "{rdi}" (0)
78 \\ : "rcx", "r11", "memory"
79 \\ );
80 \\ unreachable;
81 \\}
82 ,
83 "What is up? This is a longer message that will force the data to be relocated in virtual address space.\n",
84 );
85 // Now we print it twice.
86 case.addCompareOutput(
87 \\export fn _start() noreturn {
88 \\ print();
89 \\ print();
90 \\
91 \\ exit();
92 \\}
93 \\
94 \\fn print() void {
95 \\ asm volatile ("syscall"
96 \\ :
97 \\ : [number] "{rax}" (1),
98 \\ [arg1] "{rdi}" (1),
99 \\ [arg2] "{rsi}" (@ptrToInt("What is up? This is a longer message that will force the data to be relocated in virtual address space.\n")),
100 \\ [arg3] "{rdx}" (104)
101 \\ : "rcx", "r11", "memory"
102 \\ );
103 \\ return;
104 \\}
105 \\
106 \\fn exit() noreturn {
107 \\ asm volatile ("syscall"
108 \\ :
109 \\ : [number] "{rax}" (231),
110 \\ [arg1] "{rdi}" (0)
111 \\ : "rcx", "r11", "memory"
112 \\ );
113 \\ unreachable;
114 \\}
115 ,
116 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
117 \\What is up? This is a longer message that will force the data to be relocated in virtual address space.
118 \\
119 );
120 }
28121}
test/stage2/zir.zig+96-104
......@@ -86,7 +86,7 @@ pub fn addCases(ctx: *TestContext) void {
8686 );
8787
8888 {
89 var case = ctx.addZIRMulti("reference cycle with compile error in the cycle", linux_x64);
89 var case = ctx.addObjZIR("reference cycle with compile error in the cycle", linux_x64);
9090 case.addTransform(
9191 \\@void = primitive(void)
9292 \\@fnty = fntype([], @void, cc=C)
......@@ -207,109 +207,101 @@ pub fn addCases(ctx: *TestContext) void {
207207 return;
208208 }
209209
210 ctx.addZIRCompareOutput(
211 "hello world ZIR",
212 &[_][]const u8{
213 \\@noreturn = primitive(noreturn)
214 \\@void = primitive(void)
215 \\@usize = primitive(usize)
216 \\@0 = int(0)
217 \\@1 = int(1)
218 \\@2 = int(2)
219 \\@3 = int(3)
220 \\
221 \\@msg = str("Hello, world!\n")
222 \\
223 \\@start_fnty = fntype([], @noreturn, cc=Naked)
224 \\@start = fn(@start_fnty, {
225 \\ %SYS_exit_group = int(231)
226 \\ %exit_code = as(@usize, @0)
227 \\
228 \\ %syscall = str("syscall")
229 \\ %sysoutreg = str("={rax}")
230 \\ %rax = str("{rax}")
231 \\ %rdi = str("{rdi}")
232 \\ %rcx = str("rcx")
233 \\ %rdx = str("{rdx}")
234 \\ %rsi = str("{rsi}")
235 \\ %r11 = str("r11")
236 \\ %memory = str("memory")
237 \\
238 \\ %SYS_write = as(@usize, @1)
239 \\ %STDOUT_FILENO = as(@usize, @1)
240 \\
241 \\ %msg_addr = ptrtoint(@msg)
242 \\
243 \\ %len_name = str("len")
244 \\ %msg_len_ptr = fieldptr(@msg, %len_name)
245 \\ %msg_len = deref(%msg_len_ptr)
246 \\ %rc_write = asm(%syscall, @usize,
247 \\ volatile=1,
248 \\ output=%sysoutreg,
249 \\ inputs=[%rax, %rdi, %rsi, %rdx],
250 \\ clobbers=[%rcx, %r11, %memory],
251 \\ args=[%SYS_write, %STDOUT_FILENO, %msg_addr, %msg_len])
252 \\
253 \\ %rc_exit = asm(%syscall, @usize,
254 \\ volatile=1,
255 \\ output=%sysoutreg,
256 \\ inputs=[%rax, %rdi],
257 \\ clobbers=[%rcx, %r11, %memory],
258 \\ args=[%SYS_exit_group, %exit_code])
259 \\
260 \\ %99 = unreachable()
261 \\});
262 \\
263 \\@9 = str("_start")
264 \\@11 = export(@9, "start")
265 },
266 &[_][]const u8{
267 \\Hello, world!
268 \\
269 },
210 ctx.addZIRCompareOutput("hello world ZIR",
211 \\@noreturn = primitive(noreturn)
212 \\@void = primitive(void)
213 \\@usize = primitive(usize)
214 \\@0 = int(0)
215 \\@1 = int(1)
216 \\@2 = int(2)
217 \\@3 = int(3)
218 \\
219 \\@msg = str("Hello, world!\n")
220 \\
221 \\@start_fnty = fntype([], @noreturn, cc=Naked)
222 \\@start = fn(@start_fnty, {
223 \\ %SYS_exit_group = int(231)
224 \\ %exit_code = as(@usize, @0)
225 \\
226 \\ %syscall = str("syscall")
227 \\ %sysoutreg = str("={rax}")
228 \\ %rax = str("{rax}")
229 \\ %rdi = str("{rdi}")
230 \\ %rcx = str("rcx")
231 \\ %rdx = str("{rdx}")
232 \\ %rsi = str("{rsi}")
233 \\ %r11 = str("r11")
234 \\ %memory = str("memory")
235 \\
236 \\ %SYS_write = as(@usize, @1)
237 \\ %STDOUT_FILENO = as(@usize, @1)
238 \\
239 \\ %msg_addr = ptrtoint(@msg)
240 \\
241 \\ %len_name = str("len")
242 \\ %msg_len_ptr = fieldptr(@msg, %len_name)
243 \\ %msg_len = deref(%msg_len_ptr)
244 \\ %rc_write = asm(%syscall, @usize,
245 \\ volatile=1,
246 \\ output=%sysoutreg,
247 \\ inputs=[%rax, %rdi, %rsi, %rdx],
248 \\ clobbers=[%rcx, %r11, %memory],
249 \\ args=[%SYS_write, %STDOUT_FILENO, %msg_addr, %msg_len])
250 \\
251 \\ %rc_exit = asm(%syscall, @usize,
252 \\ volatile=1,
253 \\ output=%sysoutreg,
254 \\ inputs=[%rax, %rdi],
255 \\ clobbers=[%rcx, %r11, %memory],
256 \\ args=[%SYS_exit_group, %exit_code])
257 \\
258 \\ %99 = unreachable()
259 \\});
260 \\
261 \\@9 = str("_start")
262 \\@11 = export(@9, "start")
263 ,
264 \\Hello, world!
265 \\
270266 );
271267
272 ctx.addZIRCompareOutput(
273 "function call with no args no return value",
274 &[_][]const u8{
275 \\@noreturn = primitive(noreturn)
276 \\@void = primitive(void)
277 \\@usize = primitive(usize)
278 \\@0 = int(0)
279 \\@1 = int(1)
280 \\@2 = int(2)
281 \\@3 = int(3)
282 \\
283 \\@exit0_fnty = fntype([], @noreturn)
284 \\@exit0 = fn(@exit0_fnty, {
285 \\ %SYS_exit_group = int(231)
286 \\ %exit_code = as(@usize, @0)
287 \\
288 \\ %syscall = str("syscall")
289 \\ %sysoutreg = str("={rax}")
290 \\ %rax = str("{rax}")
291 \\ %rdi = str("{rdi}")
292 \\ %rcx = str("rcx")
293 \\ %r11 = str("r11")
294 \\ %memory = str("memory")
295 \\
296 \\ %rc = asm(%syscall, @usize,
297 \\ volatile=1,
298 \\ output=%sysoutreg,
299 \\ inputs=[%rax, %rdi],
300 \\ clobbers=[%rcx, %r11, %memory],
301 \\ args=[%SYS_exit_group, %exit_code])
302 \\
303 \\ %99 = unreachable()
304 \\});
305 \\
306 \\@start_fnty = fntype([], @noreturn, cc=Naked)
307 \\@start = fn(@start_fnty, {
308 \\ %0 = call(@exit0, [])
309 \\})
310 \\@9 = str("_start")
311 \\@11 = export(@9, "start")
312 },
313 &[_][]const u8{""},
314 );
268 ctx.addZIRCompareOutput("function call with no args no return value",
269 \\@noreturn = primitive(noreturn)
270 \\@void = primitive(void)
271 \\@usize = primitive(usize)
272 \\@0 = int(0)
273 \\@1 = int(1)
274 \\@2 = int(2)
275 \\@3 = int(3)
276 \\
277 \\@exit0_fnty = fntype([], @noreturn)
278 \\@exit0 = fn(@exit0_fnty, {
279 \\ %SYS_exit_group = int(231)
280 \\ %exit_code = as(@usize, @0)
281 \\
282 \\ %syscall = str("syscall")
283 \\ %sysoutreg = str("={rax}")
284 \\ %rax = str("{rax}")
285 \\ %rdi = str("{rdi}")
286 \\ %rcx = str("rcx")
287 \\ %r11 = str("r11")
288 \\ %memory = str("memory")
289 \\
290 \\ %rc = asm(%syscall, @usize,
291 \\ volatile=1,
292 \\ output=%sysoutreg,
293 \\ inputs=[%rax, %rdi],
294 \\ clobbers=[%rcx, %r11, %memory],
295 \\ args=[%SYS_exit_group, %exit_code])
296 \\
297 \\ %99 = unreachable()
298 \\});
299 \\
300 \\@start_fnty = fntype([], @noreturn, cc=Naked)
301 \\@start = fn(@start_fnty, {
302 \\ %0 = call(@exit0, [])
303 \\})
304 \\@9 = str("_start")
305 \\@11 = export(@9, "start")
306 , "");
315307}