| ... | ... | @@ -17,41 +17,43 @@ fn map(allocator: *std.mem.Allocator, name: []const u8) ![]const u8 { |
| 17 | 17 | return allocator.dupe(u8, name); |
| 18 | 18 | } |
| 19 | 19 | |
| 20 | | fn renderType(file: *C, writer: std.ArrayList(u8).Writer, T: Type, src: usize) !void { |
| 21 | | if (T.tag() == .usize) { |
| 22 | | file.need_stddef = true; |
| 23 | | try writer.writeAll("size_t"); |
| 24 | | } else { |
| 25 | | switch (T.zigTypeTag()) { |
| 26 | | .NoReturn => { |
| 27 | | try writer.writeAll("zig_noreturn void"); |
| 28 | | }, |
| 29 | | .Void => try writer.writeAll("void"), |
| 30 | | .Int => { |
| 31 | | if (T.tag() == .u8) { |
| 32 | | file.need_stdint = true; |
| 33 | | try writer.writeAll("uint8_t"); |
| 34 | | } else { |
| 35 | | return file.fail(src, "TODO implement int types", .{}); |
| 36 | | } |
| 37 | | }, |
| 38 | | else => |e| return file.fail(src, "TODO implement type {}", .{e}), |
| 39 | | } |
| 20 | fn renderType(ctx: *Context, writer: std.ArrayList(u8).Writer, T: Type) !void { |
| 21 | switch (T.zigTypeTag()) { |
| 22 | .NoReturn => { |
| 23 | try writer.writeAll("zig_noreturn void"); |
| 24 | }, |
| 25 | .Void => try writer.writeAll("void"), |
| 26 | .Int => { |
| 27 | if (T.tag() == .u8) { |
| 28 | ctx.file.need_stdint = true; |
| 29 | try writer.writeAll("uint8_t"); |
| 30 | } else if (T.tag() == .usize) { |
| 31 | ctx.file.need_stddef = true; |
| 32 | try writer.writeAll("size_t"); |
| 33 | } else { |
| 34 | return ctx.file.fail(ctx.decl.src(), "TODO implement int types", .{}); |
| 35 | } |
| 36 | }, |
| 37 | else => |e| return ctx.file.fail(ctx.decl.src(), "TODO implement type {}", .{e}), |
| 40 | 38 | } |
| 41 | 39 | } |
| 42 | 40 | |
| 43 | | fn 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}), |
| 41 | fn renderValue(ctx: *Context, writer: std.ArrayList(u8).Writer, T: Type, val: Value) !void { |
| 42 | switch (T.zigTypeTag()) { |
| 43 | .Int => { |
| 44 | if (T.isSignedInt()) |
| 45 | return writer.print("{}", .{val.toSignedInt()}); |
| 46 | return writer.print("{}", .{val.toUnsignedInt()}); |
| 47 | }, |
| 48 | else => |e| return ctx.file.fail(ctx.decl.src(), "TODO implement value {}", .{e}), |
| 47 | 49 | } |
| 48 | 50 | } |
| 49 | 51 | |
| 50 | | fn renderFunctionSignature(file: *C, writer: std.ArrayList(u8).Writer, decl: *Decl) !void { |
| 52 | fn renderFunctionSignature(ctx: *Context, writer: std.ArrayList(u8).Writer, decl: *Decl) !void { |
| 51 | 53 | const tv = decl.typed_value.most_recent.typed_value; |
| 52 | | try renderType(file, writer, tv.ty.fnReturnType(), decl.src()); |
| 53 | | const name = try map(file.base.allocator, mem.spanZ(decl.name)); |
| 54 | | defer file.base.allocator.free(name); |
| 54 | try renderType(ctx, writer, tv.ty.fnReturnType()); |
| 55 | const name = try map(ctx.file.base.allocator, mem.spanZ(decl.name)); |
| 56 | defer ctx.file.base.allocator.free(name); |
| 55 | 57 | try writer.print(" {}(", .{name}); |
| 56 | 58 | var param_len = tv.ty.fnParamLen(); |
| 57 | 59 | if (param_len == 0) |
| ... | ... | @@ -62,7 +64,7 @@ fn renderFunctionSignature(file: *C, writer: std.ArrayList(u8).Writer, decl: *De |
| 62 | 64 | if (index > 0) { |
| 63 | 65 | try writer.writeAll(", "); |
| 64 | 66 | } |
| 65 | | try renderType(file, writer, tv.ty.fnParamType(index), decl.src()); |
| 67 | try renderType(ctx, writer, tv.ty.fnParamType(index)); |
| 66 | 68 | try writer.print(" arg{}", .{index}); |
| 67 | 69 | } |
| 68 | 70 | } |
| ... | ... | @@ -120,10 +122,6 @@ fn genFn(file: *C, decl: *Decl) !void { |
| 120 | 122 | const writer = file.main.writer(); |
| 121 | 123 | const tv = decl.typed_value.most_recent.typed_value; |
| 122 | 124 | |
| 123 | | try renderFunctionSignature(file, writer, decl); |
| 124 | | |
| 125 | | try writer.writeAll(" {"); |
| 126 | | |
| 127 | 125 | var ctx = Context{ |
| 128 | 126 | .file = file, |
| 129 | 127 | .decl = decl, |
| ... | ... | @@ -131,6 +129,10 @@ fn genFn(file: *C, decl: *Decl) !void { |
| 131 | 129 | }; |
| 132 | 130 | defer ctx.deinit(); |
| 133 | 131 | |
| 132 | try renderFunctionSignature(&ctx, writer, decl); |
| 133 | |
| 134 | try writer.writeAll(" {"); |
| 135 | |
| 134 | 136 | const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func; |
| 135 | 137 | const instructions = func.analysis.success.instructions; |
| 136 | 138 | if (instructions.len > 0) { |
| ... | ... | @@ -180,9 +182,9 @@ fn genIntCast(ctx: *Context, inst: *Inst.UnOp) !?[]u8 { |
| 180 | 182 | const from = ctx.inst_map.get(op) orelse |
| 181 | 183 | return ctx.file.fail(ctx.decl.src(), "Internal error in C backend: intCast argument not found in inst_map", .{}); |
| 182 | 184 | try writer.writeAll(" const "); |
| 183 | | try renderType(ctx.file, writer, inst.base.ty, ctx.decl.src()); |
| 185 | try renderType(ctx, writer, inst.base.ty); |
| 184 | 186 | try writer.print(" {} = (", .{name}); |
| 185 | | try renderType(ctx.file, writer, inst.base.ty, ctx.decl.src()); |
| 187 | try renderType(ctx, writer, inst.base.ty); |
| 186 | 188 | try writer.print("){};\n", .{from}); |
| 187 | 189 | return name; |
| 188 | 190 | } |
| ... | ... | @@ -202,7 +204,7 @@ fn genCall(ctx: *Context, inst: *Inst.Call) !?[]u8 { |
| 202 | 204 | const tname = mem.spanZ(target.name); |
| 203 | 205 | if (ctx.file.called.get(tname) == null) { |
| 204 | 206 | try ctx.file.called.put(tname, void{}); |
| 205 | | try renderFunctionSignature(ctx.file, header, target); |
| 207 | try renderFunctionSignature(ctx, header, target); |
| 206 | 208 | try header.writeAll(";\n"); |
| 207 | 209 | } |
| 208 | 210 | try writer.print("{}(", .{tname}); |
| ... | ... | @@ -212,7 +214,7 @@ fn genCall(ctx: *Context, inst: *Inst.Call) !?[]u8 { |
| 212 | 214 | try writer.writeAll(", "); |
| 213 | 215 | } |
| 214 | 216 | if (arg.cast(Inst.Constant)) |con| { |
| 215 | | try renderValue(ctx.file, writer, con.val, ctx.decl.src()); |
| 217 | try renderValue(ctx, writer, arg.ty, con.val); |
| 216 | 218 | } else { |
| 217 | 219 | return ctx.file.fail(ctx.decl.src(), "TODO call pass arg {}", .{arg}); |
| 218 | 220 | } |
| ... | ... | @@ -251,11 +253,11 @@ fn genAsm(ctx: *Context, as: *Inst.Assembly) !?[]u8 { |
| 251 | 253 | const reg = i[1 .. i.len - 1]; |
| 252 | 254 | const arg = as.args[index]; |
| 253 | 255 | try writer.writeAll("register "); |
| 254 | | try renderType(ctx.file, writer, arg.ty, ctx.decl.src()); |
| 256 | try renderType(ctx, writer, arg.ty); |
| 255 | 257 | try writer.print(" {}_constant __asm__(\"{}\") = ", .{ reg, reg }); |
| 256 | 258 | // TODO merge constant handling into inst_map as well |
| 257 | 259 | if (arg.castTag(.constant)) |c| { |
| 258 | | try renderValue(ctx.file, writer, c.val, ctx.decl.src()); |
| 260 | try renderValue(ctx, writer, arg.ty, c.val); |
| 259 | 261 | try writer.writeAll(";\n "); |
| 260 | 262 | } else { |
| 261 | 263 | const gop = try ctx.inst_map.getOrPut(arg); |