| ... | @@ -16,16 +16,24 @@ fn map(name: []const u8) ![]const u8 { | ... | @@ -16,16 +16,24 @@ fn map(name: []const u8) ![]const u8 { |
| 16 | return name; | 16 | return name; |
| 17 | } | 17 | } |
| 18 | | 18 | |
| 19 | fn renderFunctionSignature(writer: std.ArrayList(u8).Writer, decl: *Decl) !void { | 19 | fn renderType(file: *C, writer: std.ArrayList(u8).Writer, T: Type) !void { |
| 20 | const tv = decl.typed_value.most_recent.typed_value; | 20 | if (T.tag() == .usize) { |
| 21 | switch (tv.ty.fnReturnType().zigTypeTag()) { | 21 | file.need_stddef = true; |
| 22 | .NoReturn => { | 22 | try writer.writeAll("size_t"); |
| 23 | try writer.writeAll("_Noreturn void "); | 23 | } else { |
| 24 | }, | 24 | switch (T.zigTypeTag()) { |
| 25 | else => return error.Unimplemented, | 25 | .NoReturn => try writer.writeAll("_Noreturn void"), |
| | 26 | .Void => try writer.writeAll("void"), |
| | 27 | else => return error.Unimplemented, |
| | 28 | } |
| 26 | } | 29 | } |
| | 30 | } |
| | 31 | |
| | 32 | fn renderFunctionSignature(file: *C, writer: std.ArrayList(u8).Writer, decl: *Decl) !void { |
| | 33 | const tv = decl.typed_value.most_recent.typed_value; |
| | 34 | try renderType(file, writer, tv.ty.fnReturnType()); |
| 27 | const name = try map(mem.spanZ(decl.name)); | 35 | const name = try map(mem.spanZ(decl.name)); |
| 28 | try writer.print("{}(", .{name}); | 36 | try writer.print(" {}(", .{name}); |
| 29 | if (tv.ty.fnParamLen() == 0) { | 37 | if (tv.ty.fnParamLen() == 0) { |
| 30 | try writer.writeAll("void)"); | 38 | try writer.writeAll("void)"); |
| 31 | } else { | 39 | } else { |
| ... | @@ -39,7 +47,7 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void { | ... | @@ -39,7 +47,7 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void { |
| 39 | const tv = decl.typed_value.most_recent.typed_value; | 47 | const tv = decl.typed_value.most_recent.typed_value; |
| 40 | switch (tv.ty.zigTypeTag()) { | 48 | switch (tv.ty.zigTypeTag()) { |
| 41 | .Fn => { | 49 | .Fn => { |
| 42 | try renderFunctionSignature(writer, decl); | 50 | try renderFunctionSignature(file, writer, decl); |
| 43 | try writer.writeAll(" {"); | 51 | try writer.writeAll(" {"); |
| 44 | | 52 | |
| 45 | const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func; | 53 | const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func; |
| ... | @@ -48,6 +56,55 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void { | ... | @@ -48,6 +56,55 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void { |
| 48 | for (instructions) |inst| { | 56 | for (instructions) |inst| { |
| 49 | try writer.writeAll("\n\t"); | 57 | try writer.writeAll("\n\t"); |
| 50 | switch (inst.tag) { | 58 | switch (inst.tag) { |
| | 59 | .assembly => { |
| | 60 | const as = inst.cast(ir.Inst.Assembly).?.args; |
| | 61 | for (as.inputs) |i, index| { |
| | 62 | if (i[0] == '{' and i[i.len - 1] == '}') { |
| | 63 | const reg = i[1 .. i.len - 1]; |
| | 64 | const arg = as.args[index]; |
| | 65 | if (arg.cast(ir.Inst.Constant)) |c| { |
| | 66 | if (c.val.tag() == .int_u64) { |
| | 67 | try writer.writeAll("register "); |
| | 68 | try renderType(file, writer, arg.ty); |
| | 69 | try writer.print(" {}_constant __asm__(\"{}\") = {};\n\t", .{ reg, reg, c.val.toUnsignedInt() }); |
| | 70 | } else { |
| | 71 | return error.Unimplemented; |
| | 72 | } |
| | 73 | } else { |
| | 74 | return error.Unimplemented; |
| | 75 | } |
| | 76 | } else { |
| | 77 | return error.Unimplemented; |
| | 78 | } |
| | 79 | } |
| | 80 | try writer.print("__asm {} (\"{}\"", .{ if (as.is_volatile) @as([]const u8, "volatile") else "", as.asm_source }); |
| | 81 | if (as.output) |o| { |
| | 82 | return error.Unimplemented; |
| | 83 | } |
| | 84 | if (as.inputs.len > 0) { |
| | 85 | if (as.output == null) { |
| | 86 | try writer.writeAll(" :"); |
| | 87 | } |
| | 88 | try writer.writeAll(": "); |
| | 89 | for (as.inputs) |i, index| { |
| | 90 | if (i[0] == '{' and i[i.len - 1] == '}') { |
| | 91 | const reg = i[1 .. i.len - 1]; |
| | 92 | const arg = as.args[index]; |
| | 93 | if (index > 0) { |
| | 94 | try writer.writeAll(", "); |
| | 95 | } |
| | 96 | if (arg.cast(ir.Inst.Constant)) |c| { |
| | 97 | try writer.print("\"\"({}_constant)", .{reg}); |
| | 98 | } else { |
| | 99 | return error.Unimplemented; |
| | 100 | } |
| | 101 | } else { |
| | 102 | return error.Unimplemented; |
| | 103 | } |
| | 104 | } |
| | 105 | } |
| | 106 | try writer.writeAll(");"); |
| | 107 | }, |
| 51 | .call => { | 108 | .call => { |
| 52 | const call = inst.cast(ir.Inst.Call).?.args; | 109 | const call = inst.cast(ir.Inst.Call).?.args; |
| 53 | if (call.func.cast(ir.Inst.Constant)) |func_inst| { | 110 | if (call.func.cast(ir.Inst.Constant)) |func_inst| { |
| ... | @@ -56,17 +113,20 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void { | ... | @@ -56,17 +113,20 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void { |
| 56 | const tname = mem.spanZ(target.name); | 113 | const tname = mem.spanZ(target.name); |
| 57 | if (file.called.get(tname) == null) { | 114 | if (file.called.get(tname) == null) { |
| 58 | try file.called.put(tname, void{}); | 115 | try file.called.put(tname, void{}); |
| 59 | try renderFunctionSignature(header, target); | 116 | try renderFunctionSignature(file, header, target); |
| 60 | try header.writeAll(";\n"); | 117 | try header.writeAll(";\n"); |
| 61 | } | 118 | } |
| 62 | try writer.print("{}();", .{tname}); | 119 | try writer.print("{}();", .{tname}); |
| 63 | } else { | 120 | } else { |
| | 121 | std.debug.warn("non-function call target?\n", .{}); |
| 64 | return error.Unimplemented; | 122 | return error.Unimplemented; |
| 65 | } | 123 | } |
| 66 | if (call.args.len != 0) { | 124 | if (call.args.len != 0) { |
| | 125 | std.debug.warn("parameters\n", .{}); |
| 67 | return error.Unimplemented; | 126 | return error.Unimplemented; |
| 68 | } | 127 | } |
| 69 | } else { | 128 | } else { |
| | 129 | std.debug.warn("non-constant call inst?\n", .{}); |
| 70 | return error.Unimplemented; | 130 | return error.Unimplemented; |
| 71 | } | 131 | } |
| 72 | }, | 132 | }, |
| ... | @@ -80,6 +140,21 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void { | ... | @@ -80,6 +140,21 @@ pub fn generate(file: *C, decl: *Decl, standard: CStandard) !void { |
| 80 | | 140 | |
| 81 | try writer.writeAll("}\n\n"); | 141 | try writer.writeAll("}\n\n"); |
| 82 | }, | 142 | }, |
| 83 | else => return error.Unimplemented, | 143 | .Array => { |
| | 144 | if (mem.indexOf(u8, mem.span(decl.name), "$") == null) { |
| | 145 | // TODO: prevent inline asm constants from being emitted |
| | 146 | if (tv.val.cast(Value.Payload.Bytes)) |payload| { |
| | 147 | try writer.print("const char *const {} = \"{}\";\n", .{ decl.name, payload.data }); |
| | 148 | std.debug.warn("\n\nARRAYTRANS\n", .{}); |
| | 149 | if (tv.ty.arraySentinel()) |sentinel| {} |
| | 150 | } else { |
| | 151 | return error.Unimplemented; |
| | 152 | } |
| | 153 | } |
| | 154 | }, |
| | 155 | else => |e| { |
| | 156 | std.debug.warn("\nTODO implement {}\n", .{e}); |
| | 157 | return error.Unimplemented; |
| | 158 | }, |
| 84 | } | 159 | } |
| 85 | } | 160 | } |