authorgravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-08-09 18:45:34-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2020-08-12 21:58:21-07:00
logd3eec7d46b1dea6c99dd4beea370a3629843c111
tree95fef8b8aae7882548c0ce66cc079810ec723a72
parent4d778e630a1902e59e2c0f92674d7f9bda026cf6

CBE: working parameters


2 files changed, 96 insertions(+), 20 deletions(-)

src-self-hosted/codegen/c.zig+62-20
......@@ -40,16 +40,33 @@ fn renderType(file: *C, writer: std.ArrayList(u8).Writer, T: Type, src: usize) !
4040 }
4141}
4242
43fn renderValue(file: *C, writer: std.ArrayList(u8).Writer, val: Value, src: usize) !void {
44 switch (val.tag()) {
45 .int_u64 => return writer.print("{}", .{val.toUnsignedInt()}),
46 else => |e| return file.fail(src, "TODO implement value {}", .{e}),
47 }
48}
49
4350fn renderFunctionSignature(file: *C, writer: std.ArrayList(u8).Writer, decl: *Decl) !void {
4451 const tv = decl.typed_value.most_recent.typed_value;
4552 try renderType(file, writer, tv.ty.fnReturnType(), decl.src());
4653 const name = try map(file.base.allocator, mem.spanZ(decl.name));
4754 defer file.base.allocator.free(name);
4855 try writer.print(" {}(", .{name});
49 if (tv.ty.fnParamLen() == 0)
50 try writer.writeAll("void)")
51 else
52 return file.fail(decl.src(), "TODO implement parameters", .{});
56 var param_len = tv.ty.fnParamLen();
57 if (param_len == 0)
58 try writer.writeAll("void")
59 else {
60 var index: usize = 0;
61 while (index < param_len) : (index += 1) {
62 if (index > 0) {
63 try writer.writeAll(", ");
64 }
65 try renderType(file, writer, tv.ty.fnParamType(index), decl.src());
66 try writer.print(" arg{}", .{index});
67 }
68 }
69 try writer.writeByte(')');
5370}
5471
5572pub fn generate(file: *C, decl: *Decl) !void {
......@@ -87,15 +104,19 @@ fn genFn(file: *C, decl: *Decl) !void {
87104
88105 const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func;
89106 const instructions = func.analysis.success.instructions;
107 var argdex: usize = 0;
90108 if (instructions.len > 0) {
91109 try writer.writeAll("\n");
92110 for (instructions) |inst| {
93111 switch (inst.tag) {
94 .assembly => try genAsm(file, inst.castTag(.assembly).?, decl),
112 .assembly => try genAsm(file, inst.castTag(.assembly).?, decl, &argdex),
95113 .call => try genCall(file, inst.castTag(.call).?, decl),
96114 .ret => try genRet(file, inst.castTag(.ret).?, decl, tv.ty.fnReturnType()),
97115 .retvoid => try file.main.writer().print(" return;\n", .{}),
116 .arg => {},
98117 .dbg_stmt => try genDbgStmt(file, inst.castTag(.dbg_stmt).?, decl),
118 .breakpoint => try genBreak(file, inst.castTag(.breakpoint).?, decl),
119 .unreach => try genUnreach(file, inst.castTag(.unreach).?, decl),
99120 else => |e| return file.fail(decl.src(), "TODO implement C codegen for {}", .{e}),
100121 }
101122 }
......@@ -126,13 +147,23 @@ fn genCall(file: *C, inst: *Inst.Call, decl: *Decl) !void {
126147 try renderFunctionSignature(file, header, target);
127148 try header.writeAll(";\n");
128149 }
129 try writer.print("{}();\n", .{tname});
150 try writer.print("{}(", .{tname});
151 if (inst.args.len != 0) {
152 for (inst.args) |arg, i| {
153 if (i > 0) {
154 try writer.writeAll(", ");
155 }
156 if (arg.cast(Inst.Constant)) |con| {
157 try renderValue(file, writer, con.val, decl.src());
158 } else {
159 return file.fail(decl.src(), "TODO call pass arg {}", .{arg});
160 }
161 }
162 }
163 try writer.writeAll(");\n");
130164 } else {
131165 return file.fail(decl.src(), "TODO non-function call target?", .{});
132166 }
133 if (inst.args.len != 0) {
134 return file.fail(decl.src(), "TODO function arguments", .{});
135 }
136167 } else {
137168 return file.fail(decl.src(), "TODO non-constant call inst?", .{});
138169 }
......@@ -142,24 +173,33 @@ fn genDbgStmt(file: *C, inst: *Inst.NoOp, decl: *Decl) !void {
142173 // TODO emit #line directive here with line number and filename
143174}
144175
145fn genAsm(file: *C, as: *Inst.Assembly, decl: *Decl) !void {
176fn genBreak(file: *C, inst: *Inst.NoOp, decl: *Decl) !void {
177 // TODO ??
178}
179
180fn genUnreach(file: *C, inst: *Inst.NoOp, decl: *Decl) !void {
181 // TODO ??
182}
183
184fn genAsm(file: *C, as: *Inst.Assembly, decl: *Decl, argdex: *usize) !void {
146185 const writer = file.main.writer();
147186 try writer.writeAll(" ");
148187 for (as.inputs) |i, index| {
149188 if (i[0] == '{' and i[i.len - 1] == '}') {
150189 const reg = i[1 .. i.len - 1];
151190 const arg = as.args[index];
191 try writer.writeAll("register ");
192 try renderType(file, writer, arg.ty, decl.src());
193 try writer.print(" {}_constant __asm__(\"{}\") = ", .{ reg, reg });
152194 if (arg.castTag(.constant)) |c| {
153 if (c.val.tag() == .int_u64) {
154 try writer.writeAll("register ");
155 try renderType(file, writer, arg.ty, decl.src());
156 try writer.print(" {}_constant __asm__(\"{}\") = {};\n ", .{ reg, reg, c.val.toUnsignedInt() });
157 } else {
158 return file.fail(decl.src(), "TODO inline asm {} args", .{c.val.tag()});
159 }
195 try renderValue(file, writer, c.val, decl.src());
196 } else if (arg.castTag(.arg)) |inst| {
197 try writer.print("arg{}", .{argdex.*});
198 argdex.* += 1;
160199 } else {
161 return file.fail(decl.src(), "TODO non-constant inline asm args", .{});
200 return file.fail(decl.src(), "TODO non-constant inline asm args ({})", .{arg.tag});
162201 }
202 try writer.writeAll(";\n ");
163203 } else {
164204 return file.fail(decl.src(), "TODO non-explicit inline asm regs", .{});
165205 }
......@@ -180,12 +220,14 @@ fn genAsm(file: *C, as: *Inst.Assembly, decl: *Decl) !void {
180220 if (index > 0) {
181221 try writer.writeAll(", ");
182222 }
183 if (arg.castTag(.constant)) |c| {
184 try writer.print("\"\"({}_constant)", .{reg});
223 try writer.writeAll("\"\"(");
224 if (arg.tag == .constant or arg.tag == .arg) {
225 try writer.print("{}_constant", .{reg});
185226 } else {
186227 // This is blocked by the earlier test
187228 unreachable;
188229 }
230 try writer.writeByte(')');
189231 } else {
190232 // This is blocked by the earlier test
191233 unreachable;
test/stage2/cbe.zig+34
......@@ -65,4 +65,38 @@ pub fn addCases(ctx: *TestContext) !void {
6565 \\}
6666 \\
6767 );
68 ctx.c("exit", linux_x64,
69 \\export fn _start() noreturn {
70 \\ exit(0);
71 \\}
72 \\
73 \\fn exit(code: usize) noreturn {
74 \\ asm volatile ("syscall"
75 \\ :
76 \\ : [number] "{rax}" (231),
77 \\ [arg1] "{rdi}" (code)
78 \\ );
79 \\ unreachable;
80 \\}
81 \\
82 ,
83 \\#include <stddef.h>
84 \\
85 \\zig_noreturn void exit(size_t arg0);
86 \\
87 \\const char *const exit__anon_0 = "{rax}";
88 \\const char *const exit__anon_1 = "{rdi}";
89 \\const char *const exit__anon_2 = "syscall";
90 \\
91 \\zig_noreturn void _start(void) {
92 \\ exit(0);
93 \\}
94 \\
95 \\zig_noreturn void exit(size_t arg0) {
96 \\ register size_t rax_constant __asm__("rax") = 231;
97 \\ register size_t rdi_constant __asm__("rdi") = arg0;
98 \\ __asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant));
99 \\}
100 \\
101 );
68102}