authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-05 13:59:33-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-05 17:41:14-07:00
logcd95444e4729761033f35d689a3b6ad6f4630552
treeda260237a3505ef174406590380364c36fbb3160
parent58cfaa5982fc6c216627fb6f2cfd0d0e4e89d92b

stage2: C backend: remove format() hackery

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) {
2727 arg: usize,
2828 /// By-value
2929 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 };
6630};
6731
6832pub const CValueMap = std.AutoHashMap(*Inst, CValue);
......@@ -103,6 +67,17 @@ pub const Object = struct {
10367 try o.code.writer().writeByteNTimes(' ', indent_amt);
10468 }
10569
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
10681 fn renderTypeAndName(
10782 o: *Object,
10883 writer: Writer,
......@@ -127,7 +102,9 @@ pub const Object = struct {
127102 .Const => "const ",
128103 .Mut => "",
129104 };
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);
131108 }
132109};
133110
......@@ -353,7 +330,7 @@ pub fn genDecl(o: *Object) !void {
353330 try writer.writeAll("\n");
354331 for (instructions) |inst| {
355332 const result_value = switch (inst.tag) {
356 .add => try genBinOp(o, inst.castTag(.add).?, "+"),
333 .add => try genBinOp(o, inst.castTag(.add).?, " + "),
357334 .alloc => try genAlloc(o, inst.castTag(.alloc).?),
358335 .arg => genArg(o),
359336 .assembly => try genAsm(o, inst.castTag(.assembly).?),
......@@ -361,19 +338,19 @@ pub fn genDecl(o: *Object) !void {
361338 .bitcast => try genBitcast(o, inst.castTag(.bitcast).?),
362339 .breakpoint => try genBreakpoint(o, inst.castTag(.breakpoint).?),
363340 .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).?, " != "),
370347 .dbg_stmt => try genDbgStmt(o, inst.castTag(.dbg_stmt).?),
371348 .intcast => try genIntCast(o, inst.castTag(.intcast).?),
372349 .load => try genLoad(o, inst.castTag(.load).?),
373350 .ret => try genRet(o, inst.castTag(.ret).?),
374351 .retvoid => try genRetVoid(o),
375352 .store => try genStore(o, inst.castTag(.store).?),
376 .sub => try genBinOp(o, inst.castTag(.sub).?, "-"),
353 .sub => try genBinOp(o, inst.castTag(.sub).?, " - "),
377354 .unreach => try genUnreach(o, inst.castTag(.unreach).?),
378355 else => |e| return o.dg.fail(o.dg.decl.src(), "TODO: C backend: implement codegen for {}", .{e}),
379356 };
......@@ -457,10 +434,14 @@ fn genLoad(o: *Object, inst: *Inst.UnOp) !CValue {
457434 switch (operand) {
458435 .local_ref => |i| {
459436 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");
461440 },
462441 else => {
463 try writer.print(" = *{};\n", .{operand.printed(o)});
442 try writer.writeAll(" = *");
443 try o.writeCValue(writer, operand);
444 try writer.writeAll(";\n");
464445 },
465446 }
466447 return local;
......@@ -469,7 +450,10 @@ fn genLoad(o: *Object, inst: *Inst.UnOp) !CValue {
469450fn genRet(o: *Object, inst: *Inst.UnOp) !CValue {
470451 const operand = try o.resolveInst(inst.operand);
471452 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");
473457 return CValue.none;
474458}
475459
......@@ -484,7 +468,9 @@ fn genIntCast(o: *Object, inst: *Inst.UnOp) !CValue {
484468 const local = try o.allocLocal(inst.base.ty, .Const);
485469 try writer.writeAll(" = (");
486470 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");
488474 return local;
489475}
490476
......@@ -498,10 +484,17 @@ fn genStore(o: *Object, inst: *Inst.BinOp) !CValue {
498484 switch (dest_ptr) {
499485 .local_ref => |i| {
500486 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");
502491 },
503492 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");
505498 },
506499 }
507500 return CValue.none;
......@@ -517,7 +510,13 @@ fn genBinOp(o: *Object, inst: *Inst.BinOp, operator: []const u8) !CValue {
517510 try o.indent();
518511 const writer = o.code.writer();
519512 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
521520 return local;
522521}
523522
......@@ -556,7 +555,7 @@ fn genCall(o: *Object, inst: *Inst.Call) !CValue {
556555 try o.dg.renderValue(writer, arg.ty, val);
557556 } else {
558557 const val = try o.resolveInst(arg);
559 try writer.print("{}", .{val.printed(o)});
558 try o.writeCValue(writer, val);
560559 }
561560 }
562561 }
......@@ -585,16 +584,25 @@ fn genBitcast(o: *Object, inst: *Inst.UnOp) !CValue {
585584 const local = try o.allocLocal(inst.base.ty, .Const);
586585 try writer.writeAll(" = (");
587586 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");
589591 return local;
590592 }
591593
592594 const local = try o.allocLocal(inst.base.ty, .Mut);
593595 try writer.writeAll(";\n");
594596 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
598606 return local;
599607}
600608
......@@ -623,9 +631,10 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
623631 try o.indent();
624632 try writer.writeAll("register ");
625633 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");
629638 } else {
630639 return o.dg.fail(o.dg.decl.src(), "TODO non-explicit inline asm regs", .{});
631640 }
......@@ -648,7 +657,7 @@ fn genAsm(o: *Object, as: *Inst.Assembly) !CValue {
648657 if (index > 0) {
649658 try writer.writeAll(", ");
650659 }
651 try writer.print("\"\"({s}_constant)", .{reg});
660 try writer.print("\"r\"({s}_constant)", .{reg});
652661 } else {
653662 // This is blocked by the earlier test
654663 unreachable;
src/link/C.zig+4-6
......@@ -101,14 +101,12 @@ pub fn updateDecl(self: *C, module: *Module, decl: *Module.Decl) !void {
101101 defer object.dg.fwd_decl.deinit();
102102
103103 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 },
105108 else => |e| return e,
106109 };
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 }
112110
113111 fwd_decl.* = object.dg.fwd_decl.moveToUnmanaged();
114112 code.* = object.code.moveToUnmanaged();
src/link/C/zig.h+17-10
......@@ -22,24 +22,31 @@
2222#define zig_unreachable()
2323#endif
2424
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
2729#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()
3037#elif defined(__clang__)
31#define zig_breakpoint __builtin_debugtrap()
38#define zig_breakpoint() __builtin_debugtrap()
3239#elif defined(__GNUC__)
33#define zig_breakpoint __builtin_trap()
40#define zig_breakpoint() __builtin_trap()
3441#elif defined(__i386__) || defined(__x86_64__)
35#define zig_breakpoint __asm__ volatile("int $0x03");
42#define zig_breakpoint() __asm__ volatile("int $0x03");
3643#else
37#define zig_breakpoint raise(SIGTRAP)
38#endif
44#define zig_breakpoint() raise(SIGTRAP)
3945#endif
4046
4147#include <stdint.h>
48#include <stddef.h>
4249#define int128_t __int128
4350#define uint128_t unsigned __int128
44#include <string.h>
51void *memcpy (void *zig_restrict, const void *zig_restrict, size_t);
4552
test/stage2/cbe.zig+96-217
......@@ -31,6 +31,100 @@ pub fn addCases(ctx: *TestContext) !void {
3131 , "yo" ++ std.cstr.line_sep);
3232 }
3333
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
34128 {
35129 var case = ctx.exeFromCompiledC("alloc and retptr", .{});
36130
......@@ -86,6 +180,8 @@ pub fn addCases(ctx: *TestContext) !void {
86180 \\ unreachable;
87181 \\}
88182 ,
183 \\zig_noreturn void _start(void);
184 \\
89185 \\zig_noreturn void _start(void) {
90186 \\ zig_breakpoint();
91187 \\ zig_unreachable();
......@@ -98,223 +194,6 @@ pub fn addCases(ctx: *TestContext) !void {
98194 \\void start(void);
99195 \\
100196 );
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 );
318197 ctx.h("header with single param function", linux_x64,
319198 \\export fn start(a: u8) void{}
320199 ,