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