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

This commit is contained in:
Andrew Kelley 2020-12-28 18:43:01 -07:00
parent 37f04d66be
commit a54ccd8537
4 changed files with 48 additions and 64 deletions

View File

@ -232,7 +232,7 @@ pub fn generate(file: *C, decl: *Decl) !void {
.retvoid => try genRetVoid(file),
.arg => try genArg(&ctx),
.dbg_stmt => try genDbgStmt(&ctx, inst.castTag(.dbg_stmt).?),
.breakpoint => try genBreak(&ctx, inst.castTag(.breakpoint).?),
.breakpoint => try genBreakpoint(file, inst.castTag(.breakpoint).?),
.unreach => try genUnreach(file, inst.castTag(.unreach).?),
.intcast => try genIntCast(&ctx, file, inst.castTag(.intcast).?),
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 {
return null;
}
fn genBreak(ctx: *Context, inst: *Inst.NoOp) !?[]u8 {
// TODO ??
fn genBreakpoint(file: *C, inst: *Inst.NoOp) !?[]u8 {
try file.main.writer().writeAll("zig_breakpoint();\n");
return null;
}

View File

@ -1,5 +1,4 @@
#if __STDC_VERSION__ >= 199901L
// C99 or newer
#include <stdbool.h>
#else
#define bool unsigned char
@ -17,12 +16,28 @@
#define zig_noreturn
#endif
#if __GNUC__
#if defined(__GNUC__)
#define zig_unreachable() __builtin_unreachable()
#else
#define zig_unreachable()
#endif
#if defined(_MSC_VER)
#define zig_breakpoint __debugbreak()
#else
#if defined(__MINGW32__) || defined(__MINGW64__)
#define zig_breakpoint __debugbreak()
#elif defined(__clang__)
#define zig_breakpoint __builtin_debugtrap()
#elif defined(__GNUC__)
#define zig_breakpoint __builtin_trap()
#elif defined(__i386__) || defined(__x86_64__)
#define zig_breakpoint __asm__ volatile("int $0x03");
#else
#define zig_breakpoint raise(SIGTRAP)
#endif
#endif
#include <stdint.h>
#define int128_t __int128
#define uint128_t unsigned __int128

View File

@ -646,35 +646,16 @@ pub const TestContext = struct {
defer file.close();
var out = file.reader().readAllAlloc(arena, 1024 * 1024) catch @panic("Unable to read headeroutput!");
if (expected_output.len != out.len) {
std.debug.print("\nTransformed header length differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ expected_output, out });
std.process.exit(1);
}
for (expected_output) |e, i| {
if (out[i] != e) {
std.debug.print("\nTransformed header differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ expected_output, out });
std.process.exit(1);
}
}
std.testing.expectEqualStrings(expected_output, out);
},
.Transformation => |expected_output| {
if (case.cbe) {
// The C file is always closed after an update, because we don't support
// incremental updates
// incremental updates.
var file = try tmp.dir.openFile(bin_name, .{ .read = true });
defer file.close();
var out = file.reader().readAllAlloc(arena, 1024 * 1024) catch @panic("Unable to read C output!");
if (expected_output.len != out.len) {
std.debug.print("\nTransformed C length differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ expected_output, out });
std.process.exit(1);
}
for (expected_output) |e, i| {
if (out[i] != e) {
std.debug.print("\nTransformed C differs:\n================\nExpected:\n================\n{}\n================\nFound:\n================\n{}\n================\nTest failed.\n", .{ expected_output, out });
std.process.exit(1);
}
}
std.testing.expectEqualStrings(expected_output, out);
} else {
update_node.setEstimatedTotalItems(5);
var emit_node = update_node.start("emit", 0);
@ -694,16 +675,7 @@ pub const TestContext = struct {
test_node.activate();
defer test_node.end();
if (expected_output.len != out_zir.items.len) {
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 });
std.process.exit(1);
}
for (expected_output) |e, i| {
if (out_zir.items[i] != e) {
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 });
std.process.exit(1);
}
}
std.testing.expectEqualStrings(expected_output, out_zir.items);
}
},
.Error => |e| {

View File

@ -15,6 +15,7 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
,
\\zig_noreturn void _start(void) {
\\ zig_breakpoint();
\\ zig_unreachable();
\\}
\\
@ -41,6 +42,7 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
\\
\\zig_noreturn void main(void) {
\\ zig_breakpoint();
\\ zig_unreachable();
\\}
\\
@ -61,8 +63,6 @@ pub fn addCases(ctx: *TestContext) !void {
\\ exitGood();
\\}
,
\\#include <stddef.h>
\\
\\zig_noreturn void exitGood(void);
\\
\\const char *const exitGood__anon_0 = "{rax}";
@ -74,9 +74,10 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
\\
\\zig_noreturn void exitGood(void) {
\\ register size_t rax_constant __asm__("rax") = 231;
\\ register size_t rdi_constant __asm__("rdi") = 0;
\\ register uintptr_t rax_constant __asm__("rax") = 231;
\\ register uintptr_t rdi_constant __asm__("rdi") = 0;
\\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));
\\ zig_breakpoint();
\\ zig_unreachable();
\\}
\\
@ -96,9 +97,7 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
\\
,
\\#include <stddef.h>
\\
\\zig_noreturn void exit(size_t arg0);
\\zig_noreturn void exit(uintptr_t arg0);
\\
\\const char *const exit__anon_0 = "{rax}";
\\const char *const exit__anon_1 = "{rdi}";
@ -108,10 +107,11 @@ pub fn addCases(ctx: *TestContext) !void {
\\ exit(0);
\\}
\\
\\zig_noreturn void exit(size_t arg0) {
\\ register size_t rax_constant __asm__("rax") = 231;
\\ register size_t rdi_constant __asm__("rdi") = arg0;
\\zig_noreturn void exit(uintptr_t arg0) {
\\ register uintptr_t rax_constant __asm__("rax") = 231;
\\ register uintptr_t rdi_constant __asm__("rdi") = arg0;
\\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));
\\ zig_breakpoint();
\\ zig_unreachable();
\\}
\\
@ -131,7 +131,6 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
\\
,
\\#include <stddef.h>
\\#include <stdint.h>
\\
\\zig_noreturn void exit(uint8_t arg0);
@ -145,10 +144,11 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
\\
\\zig_noreturn void exit(uint8_t arg0) {
\\ const size_t __temp_0 = (size_t)arg0;
\\ register size_t rax_constant __asm__("rax") = 231;
\\ register size_t rdi_constant __asm__("rdi") = __temp_0;
\\ const uintptr_t __temp_0 = (uintptr_t)arg0;
\\ register uintptr_t rax_constant __asm__("rax") = 231;
\\ register uintptr_t rdi_constant __asm__("rdi") = __temp_0;
\\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));
\\ zig_breakpoint();
\\ zig_unreachable();
\\}
\\
@ -172,7 +172,6 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
\\
,
\\#include <stddef.h>
\\#include <stdint.h>
\\
\\zig_noreturn void exitMath(uint8_t arg0);
@ -193,10 +192,11 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
\\
\\zig_noreturn void exit(uint8_t arg0) {
\\ const size_t __temp_0 = (size_t)arg0;
\\ register size_t rax_constant __asm__("rax") = 231;
\\ register size_t rdi_constant __asm__("rdi") = __temp_0;
\\ const uintptr_t __temp_0 = (uintptr_t)arg0;
\\ register uintptr_t rax_constant __asm__("rax") = 231;
\\ register uintptr_t rdi_constant __asm__("rdi") = __temp_0;
\\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));
\\ zig_breakpoint();
\\ zig_unreachable();
\\}
\\
@ -220,7 +220,6 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
\\
,
\\#include <stddef.h>
\\#include <stdint.h>
\\
\\zig_noreturn void exitMath(uint8_t arg0);
@ -241,10 +240,11 @@ pub fn addCases(ctx: *TestContext) !void {
\\}
\\
\\zig_noreturn void exit(uint8_t arg0) {
\\ const size_t __temp_0 = (size_t)arg0;
\\ register size_t rax_constant __asm__("rax") = 231;
\\ register size_t rdi_constant __asm__("rdi") = __temp_0;
\\ const uintptr_t __temp_0 = (uintptr_t)arg0;
\\ register uintptr_t rax_constant __asm__("rax") = 231;
\\ register uintptr_t rdi_constant __asm__("rdi") = __temp_0;
\\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));
\\ zig_breakpoint();
\\ zig_unreachable();
\\}
\\
@ -276,9 +276,7 @@ pub fn addCases(ctx: *TestContext) !void {
ctx.h("header with usize param function", linux_x64,
\\export fn start(a: usize) void{}
,
\\#include <stddef.h>
\\
\\void start(size_t arg0);
\\void start(uintptr_t arg0);
\\
);
ctx.h("header with bool param function", linux_x64,
@ -308,10 +306,9 @@ pub fn addCases(ctx: *TestContext) !void {
ctx.h("header with multiple includes", linux_x64,
\\export fn start(a: u32, b: usize) void{}
,
\\#include <stddef.h>
\\#include <stdint.h>
\\
\\void start(uint32_t arg0, size_t arg1);
\\void start(uint32_t arg0, uintptr_t arg1);
\\
);
}