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) !...@@ -40,16 +40,33 @@ fn renderType(file: *C, writer: std.ArrayList(u8).Writer, T: Type, src: usize) !
40 }40 }
41}41}
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
43fn renderFunctionSignature(file: *C, writer: std.ArrayList(u8).Writer, decl: *Decl) !void {50fn renderFunctionSignature(file: *C, writer: std.ArrayList(u8).Writer, decl: *Decl) !void {
44 const tv = decl.typed_value.most_recent.typed_value;51 const tv = decl.typed_value.most_recent.typed_value;
45 try renderType(file, writer, tv.ty.fnReturnType(), decl.src());52 try renderType(file, writer, tv.ty.fnReturnType(), decl.src());
46 const name = try map(file.base.allocator, mem.spanZ(decl.name));53 const name = try map(file.base.allocator, mem.spanZ(decl.name));
47 defer file.base.allocator.free(name);54 defer file.base.allocator.free(name);
48 try writer.print(" {}(", .{name});55 try writer.print(" {}(", .{name});
49 if (tv.ty.fnParamLen() == 0)56 var param_len = tv.ty.fnParamLen();
50 try writer.writeAll("void)")57 if (param_len == 0)
51 else58 try writer.writeAll("void")
52 return file.fail(decl.src(), "TODO implement parameters", .{});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(')');
53}70}
5471
55pub fn generate(file: *C, decl: *Decl) !void {72pub fn generate(file: *C, decl: *Decl) !void {
...@@ -87,15 +104,19 @@ fn genFn(file: *C, decl: *Decl) !void {...@@ -87,15 +104,19 @@ fn genFn(file: *C, decl: *Decl) !void {
87104
88 const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func;105 const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func;
89 const instructions = func.analysis.success.instructions;106 const instructions = func.analysis.success.instructions;
107 var argdex: usize = 0;
90 if (instructions.len > 0) {108 if (instructions.len > 0) {
91 try writer.writeAll("\n");109 try writer.writeAll("\n");
92 for (instructions) |inst| {110 for (instructions) |inst| {
93 switch (inst.tag) {111 switch (inst.tag) {
94 .assembly => try genAsm(file, inst.castTag(.assembly).?, decl),112 .assembly => try genAsm(file, inst.castTag(.assembly).?, decl, &argdex),
95 .call => try genCall(file, inst.castTag(.call).?, decl),113 .call => try genCall(file, inst.castTag(.call).?, decl),
96 .ret => try genRet(file, inst.castTag(.ret).?, decl, tv.ty.fnReturnType()),114 .ret => try genRet(file, inst.castTag(.ret).?, decl, tv.ty.fnReturnType()),
97 .retvoid => try file.main.writer().print(" return;\n", .{}),115 .retvoid => try file.main.writer().print(" return;\n", .{}),
116 .arg => {},
98 .dbg_stmt => try genDbgStmt(file, inst.castTag(.dbg_stmt).?, decl),117 .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),
99 else => |e| return file.fail(decl.src(), "TODO implement C codegen for {}", .{e}),120 else => |e| return file.fail(decl.src(), "TODO implement C codegen for {}", .{e}),
100 }121 }
101 }122 }
...@@ -126,13 +147,23 @@ fn genCall(file: *C, inst: *Inst.Call, decl: *Decl) !void {...@@ -126,13 +147,23 @@ fn genCall(file: *C, inst: *Inst.Call, decl: *Decl) !void {
126 try renderFunctionSignature(file, header, target);147 try renderFunctionSignature(file, header, target);
127 try header.writeAll(";\n");148 try header.writeAll(";\n");
128 }149 }
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");
130 } else {164 } else {
131 return file.fail(decl.src(), "TODO non-function call target?", .{});165 return file.fail(decl.src(), "TODO non-function call target?", .{});
132 }166 }
133 if (inst.args.len != 0) {
134 return file.fail(decl.src(), "TODO function arguments", .{});
135 }
136 } else {167 } else {
137 return file.fail(decl.src(), "TODO non-constant call inst?", .{});168 return file.fail(decl.src(), "TODO non-constant call inst?", .{});
138 }169 }
...@@ -142,24 +173,33 @@ fn genDbgStmt(file: *C, inst: *Inst.NoOp, decl: *Decl) !void {...@@ -142,24 +173,33 @@ fn genDbgStmt(file: *C, inst: *Inst.NoOp, decl: *Decl) !void {
142 // TODO emit #line directive here with line number and filename173 // TODO emit #line directive here with line number and filename
143}174}
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 {
146 const writer = file.main.writer();185 const writer = file.main.writer();
147 try writer.writeAll(" ");186 try writer.writeAll(" ");
148 for (as.inputs) |i, index| {187 for (as.inputs) |i, index| {
149 if (i[0] == '{' and i[i.len - 1] == '}') {188 if (i[0] == '{' and i[i.len - 1] == '}') {
150 const reg = i[1 .. i.len - 1];189 const reg = i[1 .. i.len - 1];
151 const arg = as.args[index];190 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 });
152 if (arg.castTag(.constant)) |c| {194 if (arg.castTag(.constant)) |c| {
153 if (c.val.tag() == .int_u64) {195 try renderValue(file, writer, c.val, decl.src());
154 try writer.writeAll("register ");196 } else if (arg.castTag(.arg)) |inst| {
155 try renderType(file, writer, arg.ty, decl.src());197 try writer.print("arg{}", .{argdex.*});
156 try writer.print(" {}_constant __asm__(\"{}\") = {};\n ", .{ reg, reg, c.val.toUnsignedInt() });198 argdex.* += 1;
157 } else {
158 return file.fail(decl.src(), "TODO inline asm {} args", .{c.val.tag()});
159 }
160 } else {199 } 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});
162 }201 }
202 try writer.writeAll(";\n ");
163 } else {203 } else {
164 return file.fail(decl.src(), "TODO non-explicit inline asm regs", .{});204 return file.fail(decl.src(), "TODO non-explicit inline asm regs", .{});
165 }205 }
...@@ -180,12 +220,14 @@ fn genAsm(file: *C, as: *Inst.Assembly, decl: *Decl) !void {...@@ -180,12 +220,14 @@ fn genAsm(file: *C, as: *Inst.Assembly, decl: *Decl) !void {
180 if (index > 0) {220 if (index > 0) {
181 try writer.writeAll(", ");221 try writer.writeAll(", ");
182 }222 }
183 if (arg.castTag(.constant)) |c| {223 try writer.writeAll("\"\"(");
184 try writer.print("\"\"({}_constant)", .{reg});224 if (arg.tag == .constant or arg.tag == .arg) {
225 try writer.print("{}_constant", .{reg});
185 } else {226 } else {
186 // This is blocked by the earlier test227 // This is blocked by the earlier test
187 unreachable;228 unreachable;
188 }229 }
230 try writer.writeByte(')');
189 } else {231 } else {
190 // This is blocked by the earlier test232 // This is blocked by the earlier test
191 unreachable;233 unreachable;
test/stage2/cbe.zig+34
...@@ -65,4 +65,38 @@ pub fn addCases(ctx: *TestContext) !void {...@@ -65,4 +65,38 @@ pub fn addCases(ctx: *TestContext) !void {
65 \\}65 \\}
66 \\66 \\
67 );67 );
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 );
68}102}