| author | |
| committer | |
| log | cd95444e4729761033f35d689a3b6ad6f4630552 |
| tree | da260237a3505ef174406590380364c36fbb3160 |
| parent | 58cfaa5982fc6c216627fb6f2cfd0d0e4e89d92b |
All C backend tests passing now, except for emit-h tests. Next task in
the branch is to restore emit-h.4 files changed, 187 insertions(+), 294 deletions(-)
src/codegen/c.zig+70-61| ... | ... | @@ -27,42 +27,6 @@ pub const CValue = union(enum) { |
| 27 | 27 | arg: usize, |
| 28 | 28 | /// By-value |
| 29 | 29 | decl: *Decl, |
| 30 | ||
| 31 | pub fn printed(value: CValue, object: *Object) Printed { | |
| 32 | return .{ | |
| 33 | .value = value, | |
| 34 | .object = object, | |
| 35 | }; | |
| 36 | } | |
| 37 | ||
| 38 | pub const Printed = struct { | |
| 39 | value: CValue, | |
| 40 | object: *Object, | |
| 41 | ||
| 42 | /// TODO this got unwieldly, I want to remove the ability to print this way | |
| 43 | pub fn format( | |
| 44 | self: Printed, | |
| 45 | comptime fmt: []const u8, | |
| 46 | options: std.fmt.FormatOptions, | |
| 47 | writer: anytype, | |
| 48 | ) error{OutOfMemory}!void { | |
| 49 | if (fmt.len != 0) @compileError("Unknown format string: '" ++ fmt ++ "'"); | |
| 50 | switch (self.value) { | |
| 51 | .none => unreachable, | |
| 52 | .local => |i| return std.fmt.format(writer, "t{d}", .{i}), | |
| 53 | .local_ref => |i| return std.fmt.format(writer, "&t{d}", .{i}), | |
| 54 | .constant => |inst| { | |
| 55 | const o = self.object; | |
| 56 | o.dg.renderValue(writer, inst.ty, inst.value().?) catch |err| switch (err) { | |
| 57 | error.OutOfMemory => return error.OutOfMemory, | |
| 58 | error.AnalysisFail => return, | |
| 59 | }; | |
| 60 | }, | |
| 61 | .arg => |i| return std.fmt.format(writer, "a{d}", .{i}), | |
| 62 | .decl => |decl| return writer.writeAll(mem.span(decl.name)), | |
| 63 | } | |
| 64 | } | |
| 65 | }; | |
| 66 | 30 | }; |
| 67 | 31 | |
| 68 | 32 | pub const CValueMap = std.AutoHashMap(*Inst, CValue); |
| ... | ... | @@ -103,6 +67,17 @@ pub const Object = struct { |
| 103 | 67 | try o.code.writer().writeByteNTimes(' ', indent_amt); |
| 104 | 68 | } |
| 105 | 69 | |
| 70 | fn writeCValue(o: *Object, writer: Writer, c_value: CValue) !void { | |
| 71 | switch (c_value) { | |
| 72 | .none => unreachable, | |
| 73 | .local => |i| return writer.print("t{d}", .{i}), | |
| 74 | .local_ref => |i| return writer.print("&t{d}", .{i}), | |
| 75 | .constant => |inst| return o.dg.renderValue(writer, inst.ty, inst.value().?), | |
| 76 | .arg => |i| return writer.print("a{d}", .{i}), | |
| 77 | .decl => |decl| return writer.writeAll(mem.span(decl.name)), | |
| 78 | } | |
| 79 | } | |
| 80 | ||
| 106 | 81 | fn renderTypeAndName( |
| 107 | 82 | o: *Object, |
| 108 | 83 | writer: Writer, |
| ... | ... | @@ -127,7 +102,9 @@ pub const Object = struct { |
| 127 | 102 | .Const => "const ", |
| 128 | 103 | .Mut => "", |
| 129 | 104 | }; |
| 130 | try writer.print(" {s}{}{s}", .{ const_prefix, name.printed(o), suffix.items }); | |
| 105 | try writer.print(" {s}", .{const_prefix}); | |
| 106 | try o.writeCValue(writer, name); | |
| 107 | try writer.writeAll(suffix.items); | |
| 131 | 108 | } |
| 132 | 109 | }; |
| 133 | 110 | |
| ... | ... | @@ -353,7 +330,7 @@ pub fn genDecl(o: *Object) !void { |
| 353 | 330 | try writer.writeAll("\n"); |
| 354 | 331 | for (instructions) |inst| { |
| 355 | 332 | const result_value = switch (inst.tag) { |
| 356 | .add => try genBinOp(o, inst.castTag(.add).?, "+"), | |
| 333 | .add => try genBinOp(o, inst.castTag(.add).?, " + "), | |
| 357 | 334 | .alloc => try genAlloc(o, inst.castTag(.alloc).?), |
| 358 | 335 | .arg => genArg(o), |
| 359 | 336 | .assembly => try genAsm(o, inst.castTag(.assembly).?), |
| ... | ... | @@ -361,19 +338,19 @@ pub fn genDecl(o: *Object) !void { |
| 361 | 338 | .bitcast => try genBitcast(o, inst.castTag(.bitcast).?), |
| 362 | 339 | .breakpoint => try genBreakpoint(o, inst.castTag(.breakpoint).?), |
| 363 | 340 | .call => try genCall(o, inst.castTag(.call).?), |
| 364 | .cmp_eq => try genBinOp(o, inst.castTag(.cmp_eq).?, "=="), | |
| 365 | .cmp_gt => try genBinOp(o, inst.castTag(.cmp_gt).?, ">"), | |
| 366 | .cmp_gte => try genBinOp(o, inst.castTag(.cmp_gte).?, ">="), | |
| 367 | .cmp_lt => try genBinOp(o, inst.castTag(.cmp_lt).?, "<"), | |
| 368 | .cmp_lte => try genBinOp(o, inst.castTag(.cmp_lte).?, "<="), | |
| 369 | .cmp_neq => try genBinOp(o, inst.castTag(.cmp_neq).?, "!="), | |
| 341 | .cmp_eq => try genBinOp(o, inst.castTag(.cmp_eq).?, " == "), | |
| 342 | .cmp_gt => try genBinOp(o, inst.castTag(.cmp_gt).?, " > "), | |
| 343 | .cmp_gte => try genBinOp(o, inst.castTag(.cmp_gte).?, " >= "), | |
| 344 | .cmp_lt => try genBinOp(o, inst.castTag(.cmp_lt).?, " < "), | |
| 345 | .cmp_lte => try genBinOp(o, inst.castTag(.cmp_lte).?, " <= "), | |
| 346 | .cmp_neq => try genBinOp(o, inst.castTag(.cmp_neq).?, " != "), | |
| 370 | 347 | .dbg_stmt => try genDbgStmt(o, inst.castTag(.dbg_stmt).?), |
| 371 | 348 | .intcast => try genIntCast(o, inst.castTag(.intcast).?), |
| 372 | 349 | .load => try genLoad(o, inst.castTag(.load).?), |
| 373 | 350 | .ret => try genRet(o, inst.castTag(.ret).?), |
| 374 | 351 | .retvoid => try genRetVoid(o), |
| 375 | 352 | .store => try genStore(o, inst.castTag(.store).?), |
| 376 | .sub => try genBinOp(o, inst.castTag(.sub).?, "-"), | |
| 353 | .sub => try genBinOp(o, inst.castTag(.sub).?, " - "), | |
| 377 | 354 | .unreach => try genUnreach(o, inst.castTag(.unreach).?), |
| 378 | 355 | else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}), |
| 379 | 356 | }; |
| ... | ... | @@ -457,10 +434,14 @@ fn genLoad(o: *Object, inst: *Inst.UnOp) !CValue { |
| 457 | 434 | switch (operand) { |
| 458 | 435 | .local_ref => |i| { |
| 459 | 436 | const wrapped: CValue = .{ .local = i }; |
| 460 | try writer.print(" = {};\n", .{wrapped.printed(o)}); | |
| 437 | try writer.writeAll(" = "); | |
| 438 | try o.writeCValue(writer, wrapped); | |
| 439 | try writer.writeAll(";\n"); | |
| 461 | 440 | }, |
| 462 | 441 | else => { |
| 463 | try writer.print(" = *{};\n", .{operand.printed(o)}); | |
| 442 | try writer.writeAll(" = *"); | |
| 443 | try o.writeCValue(writer, operand); | |
| 444 | try writer.writeAll(";\n"); | |
| 464 | 445 | }, |
| 465 | 446 | } |
| 466 | 447 | return local; |
| ... | ... | @@ -469,7 +450,10 @@ fn genLoad(o: *Object, inst: *Inst.UnOp) !CValue { |
| 469 | 450 | fn genRet(o: *Object, inst: *Inst.UnOp) !CValue { |
| 470 | 451 | const operand = try o.resolveInst(inst.operand); |
| 471 | 452 | try o.indent(); |
| 472 | try o.code.writer().print("return {};\n", .{operand.printed(o)}); | |
| 453 | const writer = o.code.writer(); | |
| 454 | try writer.writeAll("return "); | |
| 455 | try o.writeCValue(writer, operand); | |
| 456 | try writer.writeAll(";\n"); | |
| 473 | 457 | return CValue.none; |
| 474 | 458 | } |
| 475 | 459 | |
| ... | ... | @@ -484,7 +468,9 @@ fn genIntCast(o: *Object, inst: *Inst.UnOp) !CValue { |
| 484 | 468 | const local = try o.allocLocal(inst.base.ty, .Const); |
| 485 | 469 | try writer.writeAll(" = ("); |
| 486 | 470 | try o.dg.renderType(writer, inst.base.ty); |
| 487 | try writer.print("){};\n", .{from.printed(o)}); | |
| 471 | try writer.writeAll(")"); | |
| 472 | try o.writeCValue(writer, from); | |
| 473 | try writer.writeAll(";\n"); | |
| 488 | 474 | return local; |
| 489 | 475 | } |
| 490 | 476 | |
| ... | ... | @@ -498,10 +484,17 @@ fn genStore(o: *Object, inst: *Inst.BinOp) !CValue { |
| 498 | 484 | switch (dest_ptr) { |
| 499 | 485 | .local_ref => |i| { |
| 500 | 486 | const dest: CValue = .{ .local = i }; |
| 501 | try writer.print("{} = {};\n", .{ dest.printed(o), src_val.printed(o) }); | |
| 487 | try o.writeCValue(writer, dest); | |
| 488 | try writer.writeAll(" = "); | |
| 489 | try o.writeCValue(writer, src_val); | |
| 490 | try writer.writeAll(";\n"); | |
| 502 | 491 | }, |
| 503 | 492 | else => { |
| 504 | try writer.print("*{} = {};\n", .{ dest_ptr.printed(o), src_val.printed(o) }); | |
| 493 | try writer.writeAll("*"); | |
| 494 | try o.writeCValue(writer, dest_ptr); | |
| 495 | try writer.writeAll(" = "); | |
| 496 | try o.writeCValue(writer, src_val); | |
| 497 | try writer.writeAll(";\n"); | |
| 505 | 498 | }, |
| 506 | 499 | } |
| 507 | 500 | return CValue.none; |
| ... | ... | @@ -517,7 +510,13 @@ fn genBinOp(o: *Object, inst: *Inst.BinOp, operator: []const u8) !CValue { |
| 517 | 510 | try o.indent(); |
| 518 | 511 | const writer = o.code.writer(); |
| 519 | 512 | const local = try o.allocLocal(inst.base.ty, .Const); |
| 520 | try writer.print(" = {} {s} {};\n", .{ lhs.printed(o), operator, rhs.printed(o) }); | |
| 513 | ||
| 514 | try writer.writeAll(" = "); | |
| 515 | try o.writeCValue(writer, lhs); | |
| 516 | try writer.writeAll(operator); | |
| 517 | try o.writeCValue(writer, rhs); | |
| 518 | try writer.writeAll(";\n"); | |
| 519 | ||
| 521 | 520 | return local; |
| 522 | 521 | } |
| 523 | 522 | |
| ... | ... | @@ -556,7 +555,7 @@ fn genCall(o: *Object, inst: *Inst.Call) !CValue { |
| 556 | 555 | try o.dg.renderValue(writer, arg.ty, val); |
| 557 | 556 | } else { |
| 558 | 557 | const val = try o.resolveInst(arg); |
| 559 | try writer.print("{}", .{val.printed(o)}); | |
| 558 | try o.writeCValue(writer, val); | |
| 560 | 559 | } |
| 561 | 560 | } |
| 562 | 561 | } |
| ... | ... | @@ -585,16 +584,25 @@ fn genBitcast(o: *Object, inst: *Inst.UnOp) !CValue { |
| 585 | 584 | const local = try o.allocLocal(inst.base.ty, .Const); |
| 586 | 585 | try writer.writeAll(" = ("); |
| 587 | 586 | try o.dg.renderType(writer, inst.base.ty); |
| 588 | try writer.print("){};\n", .{operand.printed(o)}); | |
| 587 | ||
| 588 | try writer.writeAll(")"); | |
| 589 | try o.writeCValue(writer, operand); | |
| 590 | try writer.writeAll(";\n"); | |
| 589 | 591 | return local; |
| 590 | 592 | } |
| 591 | 593 | |
| 592 | 594 | const local = try o.allocLocal(inst.base.ty, .Mut); |
| 593 | 595 | try writer.writeAll(";\n"); |
| 594 | 596 | try o.indent(); |
| 595 | try writer.print("memcpy(&{}, &{}, sizeof {});\n", .{ | |
| 596 | local.printed(o), operand.printed(o), local.printed(o), | |
| 597 | }); | |
| 597 | ||
| 598 | try writer.writeAll("memcpy(&"); | |
| 599 | try o.writeCValue(writer, local); | |
| 600 | try writer.writeAll(", &"); | |
| 601 | try o.writeCValue(writer, operand); | |
| 602 | try writer.writeAll(", sizeof "); | |
| 603 | try o.writeCValue(writer, local); | |
| 604 | try writer.writeAll(");\n"); | |
| 605 | ||
| 598 | 606 | return local; |
| 599 | 607 | } |
| 600 | 608 | |
| ... | ... | @@ -623,9 +631,10 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue { |
| 623 | 631 | try o.indent(); |
| 624 | 632 | try writer.writeAll("register "); |
| 625 | 633 | try o.dg.renderType(writer, arg.ty); |
| 626 | try writer.print(" {s}_constant __asm__(\"{s}\") = {};\n", .{ | |
| 627 | reg, reg, arg_c_value.printed(o), | |
| 628 | }); | |
| 634 | ||
| 635 | try writer.print(" {s}_constant __asm__(\"{s}\") = ", .{ reg, reg }); | |
| 636 | try o.writeCValue(writer, arg_c_value); | |
| 637 | try writer.writeAll(";\n"); | |
| 629 | 638 | } else { |
| 630 | 639 | return o.dg.fail(o.dg.decl.src(), "TODO non-explicit inline asm regs", .{}); |
| 631 | 640 | } |
| ... | ... | @@ -648,7 +657,7 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue { |
| 648 | 657 | if (index > 0) { |
| 649 | 658 | try writer.writeAll(", "); |
| 650 | 659 | } |
| 651 | try writer.print("\"\"({s}_constant)", .{reg}); | |
| 660 | try writer.print("\"r\"({s}_constant)", .{reg}); | |
| 652 | 661 | } else { |
| 653 | 662 | // This is blocked by the earlier test |
| 654 | 663 | unreachable; |
src/link/C.zig+4-6| ... | ... | @@ -101,14 +101,12 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void { |
| 101 | 101 | defer object.dg.fwd_decl.deinit(); |
| 102 | 102 | |
| 103 | 103 | codegen.genDecl(&object) catch |err| switch (err) { |
| 104 | error.AnalysisFail => {}, | |
| 104 | error.AnalysisFail => { | |
| 105 | try module.failed_decls.put(module.gpa, decl, object.dg.error_msg.?); | |
| 106 | return; | |
| 107 | }, | |
| 105 | 108 | else => |e| return e, |
| 106 | 109 | }; |
| 107 | // The code may populate this error without returning error.AnalysisFail. | |
| 108 | if (object.dg.error_msg) |msg| { | |
| 109 | try module.failed_decls.put(module.gpa, decl, msg); | |
| 110 | return; | |
| 111 | } | |
| 112 | 110 | |
| 113 | 111 | fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged(); |
| 114 | 112 | code.* = object.code.moveToUnmanaged(); |
src/link/C/zig.h+17-10| ... | ... | @@ -22,24 +22,31 @@ |
| 22 | 22 | #define zig_unreachable() |
| 23 | 23 | #endif |
| 24 | 24 | |
| 25 | #if defined(_MSC_VER) | |
| 26 | #define zig_breakpoint __debugbreak() | |
| 25 | #if __STDC_VERSION__ >= 199901L | |
| 26 | #define zig_restrict restrict | |
| 27 | #elif defined(__GNUC__) | |
| 28 | #define zig_restrict __restrict | |
| 27 | 29 | #else |
| 28 | #if defined(__MINGW32__) || defined(__MINGW64__) | |
| 29 | #define zig_breakpoint __debugbreak() | |
| 30 | #define zig_restrict | |
| 31 | #endif | |
| 32 | ||
| 33 | #if defined(_MSC_VER) | |
| 34 | #define zig_breakpoint() __debugbreak() | |
| 35 | #elif defined(__MINGW32__) || defined(__MINGW64__) | |
| 36 | #define zig_breakpoint() __debugbreak() | |
| 30 | 37 | #elif defined(__clang__) |
| 31 | #define zig_breakpoint __builtin_debugtrap() | |
| 38 | #define zig_breakpoint() __builtin_debugtrap() | |
| 32 | 39 | #elif defined(__GNUC__) |
| 33 | #define zig_breakpoint __builtin_trap() | |
| 40 | #define zig_breakpoint() __builtin_trap() | |
| 34 | 41 | #elif defined(__i386__) || defined(__x86_64__) |
| 35 | #define zig_breakpoint __asm__ volatile("int $0x03"); | |
| 42 | #define zig_breakpoint() __asm__ volatile("int $0x03"); | |
| 36 | 43 | #else |
| 37 | #define zig_breakpoint raise(SIGTRAP) | |
| 38 | #endif | |
| 44 | #define zig_breakpoint() raise(SIGTRAP) | |
| 39 | 45 | #endif |
| 40 | 46 | |
| 41 | 47 | #include <stdint.h> |
| 48 | #include <stddef.h> | |
| 42 | 49 | #define int128_t __int128 |
| 43 | 50 | #define uint128_t unsigned __int128 |
| 44 | #include <string.h> | |
| 51 | void *memcpy (void *zig_restrict, const void *zig_restrict, size_t); | |
| 45 | 52 |
test/stage2/cbe.zig+96-217| ... | ... | @@ -31,6 +31,100 @@ pub fn addCases(ctx: *TestContext) !void { |
| 31 | 31 | , "yo" ++ std.cstr.line_sep); |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | { | |
| 35 | var case = ctx.exeFromCompiledC("x86_64-linux inline assembly", linux_x64); | |
| 36 | ||
| 37 | // Exit with 0 | |
| 38 | case.addCompareOutput( | |
| 39 | \\fn exitGood() noreturn { | |
| 40 | \\ asm volatile ("syscall" | |
| 41 | \\ : | |
| 42 | \\ : [number] "{rax}" (231), | |
| 43 | \\ [arg1] "{rdi}" (0) | |
| 44 | \\ ); | |
| 45 | \\ unreachable; | |
| 46 | \\} | |
| 47 | \\ | |
| 48 | \\export fn main() c_int { | |
| 49 | \\ exitGood(); | |
| 50 | \\} | |
| 51 | , ""); | |
| 52 | ||
| 53 | // Pass a usize parameter to exit | |
| 54 | case.addCompareOutput( | |
| 55 | \\export fn main() c_int { | |
| 56 | \\ exit(0); | |
| 57 | \\} | |
| 58 | \\ | |
| 59 | \\fn exit(code: usize) noreturn { | |
| 60 | \\ asm volatile ("syscall" | |
| 61 | \\ : | |
| 62 | \\ : [number] "{rax}" (231), | |
| 63 | \\ [arg1] "{rdi}" (code) | |
| 64 | \\ ); | |
| 65 | \\ unreachable; | |
| 66 | \\} | |
| 67 | , ""); | |
| 68 | ||
| 69 | // Change the parameter to u8 | |
| 70 | case.addCompareOutput( | |
| 71 | \\export fn main() c_int { | |
| 72 | \\ exit(0); | |
| 73 | \\} | |
| 74 | \\ | |
| 75 | \\fn exit(code: u8) noreturn { | |
| 76 | \\ asm volatile ("syscall" | |
| 77 | \\ : | |
| 78 | \\ : [number] "{rax}" (231), | |
| 79 | \\ [arg1] "{rdi}" (code) | |
| 80 | \\ ); | |
| 81 | \\ unreachable; | |
| 82 | \\} | |
| 83 | , ""); | |
| 84 | ||
| 85 | // Do some arithmetic at the exit callsite | |
| 86 | case.addCompareOutput( | |
| 87 | \\export fn main() c_int { | |
| 88 | \\ exitMath(1); | |
| 89 | \\} | |
| 90 | \\ | |
| 91 | \\fn exitMath(a: u8) noreturn { | |
| 92 | \\ exit(0 + a - a); | |
| 93 | \\} | |
| 94 | \\ | |
| 95 | \\fn exit(code: u8) noreturn { | |
| 96 | \\ asm volatile ("syscall" | |
| 97 | \\ : | |
| 98 | \\ : [number] "{rax}" (231), | |
| 99 | \\ [arg1] "{rdi}" (code) | |
| 100 | \\ ); | |
| 101 | \\ unreachable; | |
| 102 | \\} | |
| 103 | \\ | |
| 104 | , ""); | |
| 105 | ||
| 106 | // Invert the arithmetic | |
| 107 | case.addCompareOutput( | |
| 108 | \\export fn main() c_int { | |
| 109 | \\ exitMath(1); | |
| 110 | \\} | |
| 111 | \\ | |
| 112 | \\fn exitMath(a: u8) noreturn { | |
| 113 | \\ exit(a + 0 - a); | |
| 114 | \\} | |
| 115 | \\ | |
| 116 | \\fn exit(code: u8) noreturn { | |
| 117 | \\ asm volatile ("syscall" | |
| 118 | \\ : | |
| 119 | \\ : [number] "{rax}" (231), | |
| 120 | \\ [arg1] "{rdi}" (code) | |
| 121 | \\ ); | |
| 122 | \\ unreachable; | |
| 123 | \\} | |
| 124 | \\ | |
| 125 | , ""); | |
| 126 | } | |
| 127 | ||
| 34 | 128 | { |
| 35 | 129 | var case = ctx.exeFromCompiledC("alloc and retptr", .{}); |
| 36 | 130 | |
| ... | ... | @@ -86,6 +180,8 @@ pub fn addCases(ctx: *TestContext) !void { |
| 86 | 180 | \\ unreachable; |
| 87 | 181 | \\} |
| 88 | 182 | , |
| 183 | \\zig_noreturn void _start(void); | |
| 184 | \\ | |
| 89 | 185 | \\zig_noreturn void _start(void) { |
| 90 | 186 | \\ zig_breakpoint(); |
| 91 | 187 | \\ zig_unreachable(); |
| ... | ... | @@ -98,223 +194,6 @@ pub fn addCases(ctx: *TestContext) !void { |
| 98 | 194 | \\void start(void); |
| 99 | 195 | \\ |
| 100 | 196 | ); |
| 101 | ctx.c("less empty start function", linux_x64, | |
| 102 | \\fn main() noreturn { | |
| 103 | \\ unreachable; | |
| 104 | \\} | |
| 105 | \\ | |
| 106 | \\export fn _start() noreturn { | |
| 107 | \\ main(); | |
| 108 | \\} | |
| 109 | , | |
| 110 | \\static zig_noreturn void main(void); | |
| 111 | \\ | |
| 112 | \\static zig_noreturn void main(void) { | |
| 113 | \\ zig_breakpoint(); | |
| 114 | \\ zig_unreachable(); | |
| 115 | \\} | |
| 116 | \\ | |
| 117 | \\zig_noreturn void _start(void) { | |
| 118 | \\ main(); | |
| 119 | \\} | |
| 120 | \\ | |
| 121 | ); | |
| 122 | // TODO: implement return values | |
| 123 | // TODO: figure out a way to prevent asm constants from being generated | |
| 124 | ctx.c("inline asm", linux_x64, | |
| 125 | \\fn exitGood() noreturn { | |
| 126 | \\ asm volatile ("syscall" | |
| 127 | \\ : | |
| 128 | \\ : [number] "{rax}" (231), | |
| 129 | \\ [arg1] "{rdi}" (0) | |
| 130 | \\ ); | |
| 131 | \\ unreachable; | |
| 132 | \\} | |
| 133 | \\ | |
| 134 | \\export fn _start() noreturn { | |
| 135 | \\ exitGood(); | |
| 136 | \\} | |
| 137 | , | |
| 138 | \\static zig_noreturn void exitGood(void); | |
| 139 | \\ | |
| 140 | \\static uint8_t exitGood__anon_0[6] = "{rax}"; | |
| 141 | \\static uint8_t exitGood__anon_1[6] = "{rdi}"; | |
| 142 | \\static uint8_t exitGood__anon_2[8] = "syscall"; | |
| 143 | \\ | |
| 144 | \\static zig_noreturn void exitGood(void) { | |
| 145 | \\ register uintptr_t rax_constant __asm__("rax") = 231; | |
| 146 | \\ register uintptr_t rdi_constant __asm__("rdi") = 0; | |
| 147 | \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant)); | |
| 148 | \\ zig_breakpoint(); | |
| 149 | \\ zig_unreachable(); | |
| 150 | \\} | |
| 151 | \\ | |
| 152 | \\zig_noreturn void _start(void) { | |
| 153 | \\ exitGood(); | |
| 154 | \\} | |
| 155 | \\ | |
| 156 | ); | |
| 157 | ctx.c("exit with parameter", linux_x64, | |
| 158 | \\export fn _start() noreturn { | |
| 159 | \\ exit(0); | |
| 160 | \\} | |
| 161 | \\ | |
| 162 | \\fn exit(code: usize) noreturn { | |
| 163 | \\ asm volatile ("syscall" | |
| 164 | \\ : | |
| 165 | \\ : [number] "{rax}" (231), | |
| 166 | \\ [arg1] "{rdi}" (code) | |
| 167 | \\ ); | |
| 168 | \\ unreachable; | |
| 169 | \\} | |
| 170 | \\ | |
| 171 | , | |
| 172 | \\static zig_noreturn void exit(uintptr_t arg0); | |
| 173 | \\ | |
| 174 | \\static uint8_t exit__anon_0[6] = "{rax}"; | |
| 175 | \\static uint8_t exit__anon_1[6] = "{rdi}"; | |
| 176 | \\static uint8_t exit__anon_2[8] = "syscall"; | |
| 177 | \\ | |
| 178 | \\zig_noreturn void _start(void) { | |
| 179 | \\ exit(0); | |
| 180 | \\} | |
| 181 | \\ | |
| 182 | \\static zig_noreturn void exit(uintptr_t arg0) { | |
| 183 | \\ register uintptr_t rax_constant __asm__("rax") = 231; | |
| 184 | \\ register uintptr_t rdi_constant __asm__("rdi") = arg0; | |
| 185 | \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant)); | |
| 186 | \\ zig_breakpoint(); | |
| 187 | \\ zig_unreachable(); | |
| 188 | \\} | |
| 189 | \\ | |
| 190 | ); | |
| 191 | ctx.c("exit with u8 parameter", linux_x64, | |
| 192 | \\export fn _start() noreturn { | |
| 193 | \\ exit(0); | |
| 194 | \\} | |
| 195 | \\ | |
| 196 | \\fn exit(code: u8) noreturn { | |
| 197 | \\ asm volatile ("syscall" | |
| 198 | \\ : | |
| 199 | \\ : [number] "{rax}" (231), | |
| 200 | \\ [arg1] "{rdi}" (code) | |
| 201 | \\ ); | |
| 202 | \\ unreachable; | |
| 203 | \\} | |
| 204 | \\ | |
| 205 | , | |
| 206 | \\static zig_noreturn void exit(uint8_t arg0); | |
| 207 | \\ | |
| 208 | \\static uint8_t exit__anon_0[6] = "{rax}"; | |
| 209 | \\static uint8_t exit__anon_1[6] = "{rdi}"; | |
| 210 | \\static uint8_t exit__anon_2[8] = "syscall"; | |
| 211 | \\ | |
| 212 | \\zig_noreturn void _start(void) { | |
| 213 | \\ exit(0); | |
| 214 | \\} | |
| 215 | \\ | |
| 216 | \\static zig_noreturn void exit(uint8_t arg0) { | |
| 217 | \\ uintptr_t const __temp_0 = (uintptr_t)arg0; | |
| 218 | \\ register uintptr_t rax_constant __asm__("rax") = 231; | |
| 219 | \\ register uintptr_t rdi_constant __asm__("rdi") = __temp_0; | |
| 220 | \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant)); | |
| 221 | \\ zig_breakpoint(); | |
| 222 | \\ zig_unreachable(); | |
| 223 | \\} | |
| 224 | \\ | |
| 225 | ); | |
| 226 | ctx.c("exit with u8 arithmetic", linux_x64, | |
| 227 | \\export fn _start() noreturn { | |
| 228 | \\ exitMath(1); | |
| 229 | \\} | |
| 230 | \\ | |
| 231 | \\fn exitMath(a: u8) noreturn { | |
| 232 | \\ exit(0 + a - a); | |
| 233 | \\} | |
| 234 | \\ | |
| 235 | \\fn exit(code: u8) noreturn { | |
| 236 | \\ asm volatile ("syscall" | |
| 237 | \\ : | |
| 238 | \\ : [number] "{rax}" (231), | |
| 239 | \\ [arg1] "{rdi}" (code) | |
| 240 | \\ ); | |
| 241 | \\ unreachable; | |
| 242 | \\} | |
| 243 | \\ | |
| 244 | , | |
| 245 | \\static zig_noreturn void exitMath(uint8_t arg0); | |
| 246 | \\static zig_noreturn void exit(uint8_t arg0); | |
| 247 | \\ | |
| 248 | \\static uint8_t exit__anon_0[6] = "{rax}"; | |
| 249 | \\static uint8_t exit__anon_1[6] = "{rdi}"; | |
| 250 | \\static uint8_t exit__anon_2[8] = "syscall"; | |
| 251 | \\ | |
| 252 | \\zig_noreturn void _start(void) { | |
| 253 | \\ exitMath(1); | |
| 254 | \\} | |
| 255 | \\ | |
| 256 | \\static zig_noreturn void exitMath(uint8_t arg0) { | |
| 257 | \\ uint8_t const __temp_0 = 0 + arg0; | |
| 258 | \\ uint8_t const __temp_1 = __temp_0 - arg0; | |
| 259 | \\ exit(__temp_1); | |
| 260 | \\} | |
| 261 | \\ | |
| 262 | \\static zig_noreturn void exit(uint8_t arg0) { | |
| 263 | \\ uintptr_t const __temp_0 = (uintptr_t)arg0; | |
| 264 | \\ register uintptr_t rax_constant __asm__("rax") = 231; | |
| 265 | \\ register uintptr_t rdi_constant __asm__("rdi") = __temp_0; | |
| 266 | \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant)); | |
| 267 | \\ zig_breakpoint(); | |
| 268 | \\ zig_unreachable(); | |
| 269 | \\} | |
| 270 | \\ | |
| 271 | ); | |
| 272 | ctx.c("exit with u8 arithmetic inverted", linux_x64, | |
| 273 | \\export fn _start() noreturn { | |
| 274 | \\ exitMath(1); | |
| 275 | \\} | |
| 276 | \\ | |
| 277 | \\fn exitMath(a: u8) noreturn { | |
| 278 | \\ exit(a + 0 - a); | |
| 279 | \\} | |
| 280 | \\ | |
| 281 | \\fn exit(code: u8) noreturn { | |
| 282 | \\ asm volatile ("syscall" | |
| 283 | \\ : | |
| 284 | \\ : [number] "{rax}" (231), | |
| 285 | \\ [arg1] "{rdi}" (code) | |
| 286 | \\ ); | |
| 287 | \\ unreachable; | |
| 288 | \\} | |
| 289 | \\ | |
| 290 | , | |
| 291 | \\static zig_noreturn void exitMath(uint8_t arg0); | |
| 292 | \\static zig_noreturn void exit(uint8_t arg0); | |
| 293 | \\ | |
| 294 | \\static uint8_t exit__anon_0[6] = "{rax}"; | |
| 295 | \\static uint8_t exit__anon_1[6] = "{rdi}"; | |
| 296 | \\static uint8_t exit__anon_2[8] = "syscall"; | |
| 297 | \\ | |
| 298 | \\zig_noreturn void _start(void) { | |
| 299 | \\ exitMath(1); | |
| 300 | \\} | |
| 301 | \\ | |
| 302 | \\static zig_noreturn void exitMath(uint8_t arg0) { | |
| 303 | \\ uint8_t const __temp_0 = arg0 + 0; | |
| 304 | \\ uint8_t const __temp_1 = __temp_0 - arg0; | |
| 305 | \\ exit(__temp_1); | |
| 306 | \\} | |
| 307 | \\ | |
| 308 | \\static zig_noreturn void exit(uint8_t arg0) { | |
| 309 | \\ uintptr_t const __temp_0 = (uintptr_t)arg0; | |
| 310 | \\ register uintptr_t rax_constant __asm__("rax") = 231; | |
| 311 | \\ register uintptr_t rdi_constant __asm__("rdi") = __temp_0; | |
| 312 | \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant)); | |
| 313 | \\ zig_breakpoint(); | |
| 314 | \\ zig_unreachable(); | |
| 315 | \\} | |
| 316 | \\ | |
| 317 | ); | |
| 318 | 197 | ctx.h("header with single param function", linux_x64, |
| 319 | 198 | \\export fn start(a: u8) void{} |
| 320 | 199 | , |