authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-28 18:43:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-12-28 18:43:01-07:00
loga54ccd85374407a5015c5d8e0173089e75da9be4
tree78bf30d38ba33fd9656a23cb0a3be8de96e672f1
parent37f04d66be014291303b7d8ba49ff4232dbdb696

stage2: C backend: implement `@breakpoint` and clean up test harness


4 files changed, 48 insertions(+), 64 deletions(-)

src/codegen/c.zig+3-3
...@@ -232,7 +232,7 @@ pub fn generate(file: *C, decl: *Decl) !void {...@@ -232,7 +232,7 @@ pub fn generate(file: *C, decl: *Decl) !void {
232 .retvoid => try genRetVoid(file),232 .retvoid => try genRetVoid(file),
233 .arg => try genArg(&ctx),233 .arg => try genArg(&ctx),
234 .dbg_stmt => try genDbgStmt(&ctx, inst.castTag(.dbg_stmt).?),234 .dbg_stmt => try genDbgStmt(&ctx, inst.castTag(.dbg_stmt).?),
235 .breakpoint => try genBreak(&ctx, inst.castTag(.breakpoint).?),235 .breakpoint => try genBreakpoint(file, inst.castTag(.breakpoint).?),
236 .unreach => try genUnreach(file, inst.castTag(.unreach).?),236 .unreach => try genUnreach(file, inst.castTag(.unreach).?),
237 .intcast => try genIntCast(&ctx, file, inst.castTag(.intcast).?),237 .intcast => try genIntCast(&ctx, file, inst.castTag(.intcast).?),
238 else => |e| return ctx.fail(decl.src(), "TODO: C backend: implement codegen for {}", .{e}),238 else => |e| return ctx.fail(decl.src(), "TODO: C backend: implement codegen for {}", .{e}),
...@@ -447,8 +447,8 @@ fn genDbgStmt(ctx: *Context, inst: *Inst.NoOp) !?[]u8 {...@@ -447,8 +447,8 @@ fn genDbgStmt(ctx: *Context, inst: *Inst.NoOp) !?[]u8 {
447 return null;447 return null;
448}448}
449449
450fn genBreak(ctx: *Context, inst: *Inst.NoOp) !?[]u8 {450fn genBreakpoint(file: *C, inst: *Inst.NoOp) !?[]u8 {
451 // TODO ??451 try file.main.writer().writeAll("zig_breakpoint();\n");
452 return null;452 return null;
453}453}
454454
src/link/cbe.h+17-2
...@@ -1,5 +1,4 @@...@@ -1,5 +1,4 @@
1#if __STDC_VERSION__ >= 199901L1#if __STDC_VERSION__ >= 199901L
2// C99 or newer
3#include <stdbool.h>2#include <stdbool.h>
4#else3#else
5#define bool unsigned char4#define bool unsigned char
...@@ -17,12 +16,28 @@...@@ -17,12 +16,28 @@
17#define zig_noreturn16#define zig_noreturn
18#endif17#endif
1918
20#if __GNUC__19#if defined(__GNUC__)
21#define zig_unreachable() __builtin_unreachable()20#define zig_unreachable() __builtin_unreachable()
22#else21#else
23#define zig_unreachable()22#define zig_unreachable()
24#endif23#endif
2524
25#if defined(_MSC_VER)
26#define zig_breakpoint __debugbreak()
27#else
28#if defined(__MINGW32__) || defined(__MINGW64__)
29#define zig_breakpoint __debugbreak()
30#elif defined(__clang__)
31#define zig_breakpoint __builtin_debugtrap()
32#elif defined(__GNUC__)
33#define zig_breakpoint __builtin_trap()
34#elif defined(__i386__) || defined(__x86_64__)
35#define zig_breakpoint __asm__ volatile("int $0x03");
36#else
37#define zig_breakpoint raise(SIGTRAP)
38#endif
39#endif
40
26#include <stdint.h>41#include <stdint.h>
27#define int128_t __int12842#define int128_t __int128
28#define uint128_t unsigned __int12843#define uint128_t unsigned __int128
src/test.zig+4-32
...@@ -646,35 +646,16 @@ pub const TestContext = struct {...@@ -646,35 +646,16 @@ pub const TestContext = struct {
646 defer file.close();646 defer file.close();
647 var out = file.reader().readAllAlloc(arena, 1024 * 1024) catch @panic("Unable to read headeroutput!");647 var out = file.reader().readAllAlloc(arena, 1024 * 1024) catch @panic("Unable to read headeroutput!");
648648
649 if (expected_output.len != out.len) {649 std.testing.expectEqualStrings(expected_output, out);
650 std.debug.print("\nTransformed header length differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ expected_output, out });
651 std.process.exit(1);
652 }
653 for (expected_output) |e, i| {
654 if (out[i] != e) {
655 std.debug.print("\nTransformed header differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ expected_output, out });
656 std.process.exit(1);
657 }
658 }
659 },650 },
660 .Transformation => |expected_output| {651 .Transformation => |expected_output| {
661 if (case.cbe) {652 if (case.cbe) {
662 // The C file is always closed after an update, because we don't support653 // The C file is always closed after an update, because we don't support
663 // incremental updates654 // incremental updates.
664 var file = try tmp.dir.openFile(bin_name, .{ .read = true });655 var file = try tmp.dir.openFile(bin_name, .{ .read = true });
665 defer file.close();656 defer file.close();
666 var out = file.reader().readAllAlloc(arena, 1024 * 1024) catch @panic("Unable to read C output!");657 var out = file.reader().readAllAlloc(arena, 1024 * 1024) catch @panic("Unable to read C output!");
667658 std.testing.expectEqualStrings(expected_output, out);
668 if (expected_output.len != out.len) {
669 std.debug.print("\nTransformed C length differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ expected_output, out });
670 std.process.exit(1);
671 }
672 for (expected_output) |e, i| {
673 if (out[i] != e) {
674 std.debug.print("\nTransformed C differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ expected_output, out });
675 std.process.exit(1);
676 }
677 }
678 } else {659 } else {
679 update_node.setEstimatedTotalItems(5);660 update_node.setEstimatedTotalItems(5);
680 var emit_node = update_node.start("emit", 0);661 var emit_node = update_node.start("emit", 0);
...@@ -694,16 +675,7 @@ pub const TestContext = struct {...@@ -694,16 +675,7 @@ pub const TestContext = struct {
694 test_node.activate();675 test_node.activate();
695 defer test_node.end();676 defer test_node.end();
696677
697 if (expected_output.len != out_zir.items.len) {678 std.testing.expectEqualStrings(expected_output, out_zir.items);
698 std.debug.print("{}\nTransformed ZIR length differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ case.name, expected_output, out_zir.items });
699 std.process.exit(1);
700 }
701 for (expected_output) |e, i| {
702 if (out_zir.items[i] != e) {
703 std.debug.print("{}\nTransformed ZIR differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ case.name, expected_output, out_zir.items });
704 std.process.exit(1);
705 }
706 }
707 }679 }
708 },680 },
709 .Error => |e| {681 .Error => |e| {
test/stage2/cbe.zig+24-27
...@@ -15,6 +15,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -15,6 +15,7 @@ pub fn addCases(ctx: *TestContext) !void {
15 \\}15 \\}
16 ,16 ,
17 \\zig_noreturn void _start(void) {17 \\zig_noreturn void _start(void) {
18 \\ zig_breakpoint();
18 \\ zig_unreachable();19 \\ zig_unreachable();
19 \\}20 \\}
20 \\21 \\
...@@ -41,6 +42,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -41,6 +42,7 @@ pub fn addCases(ctx: *TestContext) !void {
41 \\}42 \\}
42 \\43 \\
43 \\zig_noreturn void main(void) {44 \\zig_noreturn void main(void) {
45 \\ zig_breakpoint();
44 \\ zig_unreachable();46 \\ zig_unreachable();
45 \\}47 \\}
46 \\48 \\
...@@ -61,8 +63,6 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -61,8 +63,6 @@ pub fn addCases(ctx: *TestContext) !void {
61 \\ exitGood();63 \\ exitGood();
62 \\}64 \\}
63 ,65 ,
64 \\#include <stddef.h>
65 \\
66 \\zig_noreturn void exitGood(void);66 \\zig_noreturn void exitGood(void);
67 \\67 \\
68 \\const char *const exitGood__anon_0 = "{rax}";68 \\const char *const exitGood__anon_0 = "{rax}";
...@@ -74,9 +74,10 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -74,9 +74,10 @@ pub fn addCases(ctx: *TestContext) !void {
74 \\}74 \\}
75 \\75 \\
76 \\zig_noreturn void exitGood(void) {76 \\zig_noreturn void exitGood(void) {
77 \\ register size_t rax_constant __asm__("rax") = 231;77 \\ register uintptr_t rax_constant __asm__("rax") = 231;
78 \\ register size_t rdi_constant __asm__("rdi") = 0;78 \\ register uintptr_t rdi_constant __asm__("rdi") = 0;
79 \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));79 \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));
80 \\ zig_breakpoint();
80 \\ zig_unreachable();81 \\ zig_unreachable();
81 \\}82 \\}
82 \\83 \\
...@@ -96,9 +97,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -96,9 +97,7 @@ pub fn addCases(ctx: *TestContext) !void {
96 \\}97 \\}
97 \\98 \\
98 ,99 ,
99 \\#include <stddef.h>100 \\zig_noreturn void exit(uintptr_t arg0);
100 \\
101 \\zig_noreturn void exit(size_t arg0);
102 \\101 \\
103 \\const char *const exit__anon_0 = "{rax}";102 \\const char *const exit__anon_0 = "{rax}";
104 \\const char *const exit__anon_1 = "{rdi}";103 \\const char *const exit__anon_1 = "{rdi}";
...@@ -108,10 +107,11 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -108,10 +107,11 @@ pub fn addCases(ctx: *TestContext) !void {
108 \\ exit(0);107 \\ exit(0);
109 \\}108 \\}
110 \\109 \\
111 \\zig_noreturn void exit(size_t arg0) {110 \\zig_noreturn void exit(uintptr_t arg0) {
112 \\ register size_t rax_constant __asm__("rax") = 231;111 \\ register uintptr_t rax_constant __asm__("rax") = 231;
113 \\ register size_t rdi_constant __asm__("rdi") = arg0;112 \\ register uintptr_t rdi_constant __asm__("rdi") = arg0;
114 \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));113 \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));
114 \\ zig_breakpoint();
115 \\ zig_unreachable();115 \\ zig_unreachable();
116 \\}116 \\}
117 \\117 \\
...@@ -131,7 +131,6 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -131,7 +131,6 @@ pub fn addCases(ctx: *TestContext) !void {
131 \\}131 \\}
132 \\132 \\
133 ,133 ,
134 \\#include <stddef.h>
135 \\#include <stdint.h>134 \\#include <stdint.h>
136 \\135 \\
137 \\zig_noreturn void exit(uint8_t arg0);136 \\zig_noreturn void exit(uint8_t arg0);
...@@ -145,10 +144,11 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -145,10 +144,11 @@ pub fn addCases(ctx: *TestContext) !void {
145 \\}144 \\}
146 \\145 \\
147 \\zig_noreturn void exit(uint8_t arg0) {146 \\zig_noreturn void exit(uint8_t arg0) {
148 \\ const size_t __temp_0 = (size_t)arg0;147 \\ const uintptr_t __temp_0 = (uintptr_t)arg0;
149 \\ register size_t rax_constant __asm__("rax") = 231;148 \\ register uintptr_t rax_constant __asm__("rax") = 231;
150 \\ register size_t rdi_constant __asm__("rdi") = __temp_0;149 \\ register uintptr_t rdi_constant __asm__("rdi") = __temp_0;
151 \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));150 \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));
151 \\ zig_breakpoint();
152 \\ zig_unreachable();152 \\ zig_unreachable();
153 \\}153 \\}
154 \\154 \\
...@@ -172,7 +172,6 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -172,7 +172,6 @@ pub fn addCases(ctx: *TestContext) !void {
172 \\}172 \\}
173 \\173 \\
174 ,174 ,
175 \\#include <stddef.h>
176 \\#include <stdint.h>175 \\#include <stdint.h>
177 \\176 \\
178 \\zig_noreturn void exitMath(uint8_t arg0);177 \\zig_noreturn void exitMath(uint8_t arg0);
...@@ -193,10 +192,11 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -193,10 +192,11 @@ pub fn addCases(ctx: *TestContext) !void {
193 \\}192 \\}
194 \\193 \\
195 \\zig_noreturn void exit(uint8_t arg0) {194 \\zig_noreturn void exit(uint8_t arg0) {
196 \\ const size_t __temp_0 = (size_t)arg0;195 \\ const uintptr_t __temp_0 = (uintptr_t)arg0;
197 \\ register size_t rax_constant __asm__("rax") = 231;196 \\ register uintptr_t rax_constant __asm__("rax") = 231;
198 \\ register size_t rdi_constant __asm__("rdi") = __temp_0;197 \\ register uintptr_t rdi_constant __asm__("rdi") = __temp_0;
199 \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));198 \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));
199 \\ zig_breakpoint();
200 \\ zig_unreachable();200 \\ zig_unreachable();
201 \\}201 \\}
202 \\202 \\
...@@ -220,7 +220,6 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -220,7 +220,6 @@ pub fn addCases(ctx: *TestContext) !void {
220 \\}220 \\}
221 \\221 \\
222 ,222 ,
223 \\#include <stddef.h>
224 \\#include <stdint.h>223 \\#include <stdint.h>
225 \\224 \\
226 \\zig_noreturn void exitMath(uint8_t arg0);225 \\zig_noreturn void exitMath(uint8_t arg0);
...@@ -241,10 +240,11 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -241,10 +240,11 @@ pub fn addCases(ctx: *TestContext) !void {
241 \\}240 \\}
242 \\241 \\
243 \\zig_noreturn void exit(uint8_t arg0) {242 \\zig_noreturn void exit(uint8_t arg0) {
244 \\ const size_t __temp_0 = (size_t)arg0;243 \\ const uintptr_t __temp_0 = (uintptr_t)arg0;
245 \\ register size_t rax_constant __asm__("rax") = 231;244 \\ register uintptr_t rax_constant __asm__("rax") = 231;
246 \\ register size_t rdi_constant __asm__("rdi") = __temp_0;245 \\ register uintptr_t rdi_constant __asm__("rdi") = __temp_0;
247 \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));246 \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));
247 \\ zig_breakpoint();
248 \\ zig_unreachable();248 \\ zig_unreachable();
249 \\}249 \\}
250 \\250 \\
...@@ -276,9 +276,7 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -276,9 +276,7 @@ pub fn addCases(ctx: *TestContext) !void {
276 ctx.h("header with usize param function", linux_x64,276 ctx.h("header with usize param function", linux_x64,
277 \\export fn start(a: usize) void{}277 \\export fn start(a: usize) void{}
278 ,278 ,
279 \\#include <stddef.h>279 \\void start(uintptr_t arg0);
280 \\
281 \\void start(size_t arg0);
282 \\280 \\
283 );281 );
284 ctx.h("header with bool param function", linux_x64,282 ctx.h("header with bool param function", linux_x64,
...@@ -308,10 +306,9 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -308,10 +306,9 @@ pub fn addCases(ctx: *TestContext) !void {
308 ctx.h("header with multiple includes", linux_x64,306 ctx.h("header with multiple includes", linux_x64,
309 \\export fn start(a: u32, b: usize) void{}307 \\export fn start(a: u32, b: usize) void{}
310 ,308 ,
311 \\#include <stddef.h>
312 \\#include <stdint.h>309 \\#include <stdint.h>
313 \\310 \\
314 \\void start(uint32_t arg0, size_t arg1);311 \\void start(uint32_t arg0, uintptr_t arg1);
315 \\312 \\
316 );313 );
317}314}