| author | |
| committer | |
| log | 08154c0deb653e016d6eb285c85094048eeded89 |
| tree | d90ce4372ed47afe3bea24245c359fad03820026 |
| parent | 25b1c00c72b51ef9e011867b3fc4f37b3e216223 |
5 files changed, 212 insertions(+), 209 deletions(-)
src-self-hosted/Module.zig+3-2| ... | @@ -1210,8 +1210,9 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { | ... | @@ -1210,8 +1210,9 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1210 | 1210 | ||
| 1211 | try self.astGenBlock(&gen_scope.base, body_block); | 1211 | try self.astGenBlock(&gen_scope.base, body_block); |
| 1212 | 1212 | ||
| 1213 | const last_inst = gen_scope.instructions.items[gen_scope.instructions.items.len - 1]; | 1213 | if (!fn_type.fnReturnType().isNoReturn() and (gen_scope.instructions.items.len == 0 or |
| 1214 | if (!last_inst.tag.isNoReturn()) { | 1214 | !gen_scope.instructions.items[gen_scope.instructions.items.len - 1].tag.isNoReturn())) |
| 1215 | { | ||
| 1215 | const src = tree.token_locs[body_block.rbrace].start; | 1216 | const src = tree.token_locs[body_block.rbrace].start; |
| 1216 | _ = try self.addZIRInst(&gen_scope.base, src, zir.Inst.ReturnVoid, .{}, .{}); | 1217 | _ = try self.addZIRInst(&gen_scope.base, src, zir.Inst.ReturnVoid, .{}, .{}); |
| 1217 | } | 1218 | } |
src-self-hosted/cgen.zig deleted-205| ... | @@ -1,205 +0,0 @@ | ||
| 1 | const link = @import("link.zig"); | ||
| 2 | const Module = @import("Module.zig"); | ||
| 3 | |||
| 4 | const std = @import("std"); | ||
| 5 | |||
| 6 | const Inst = @import("ir.zig").Inst; | ||
| 7 | const Value = @import("value.zig").Value; | ||
| 8 | const Type = @import("type.zig").Type; | ||
| 9 | |||
| 10 | const C = link.File.C; | ||
| 11 | const Decl = Module.Decl; | ||
| 12 | const mem = std.mem; | ||
| 13 | |||
| 14 | /// Maps a name from Zig source to C. This will always give the same output for | ||
| 15 | /// any given input. | ||
| 16 | fn map(allocator: *std.mem.Allocator, name: []const u8) ![]const u8 { | ||
| 17 | return allocator.dupe(u8, name); | ||
| 18 | } | ||
| 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 | file.need_noreturn = true; | ||
| 28 | try writer.writeAll("noreturn void"); | ||
| 29 | }, | ||
| 30 | .Void => try writer.writeAll("void"), | ||
| 31 | .Int => { | ||
| 32 | if (T.tag() == .u8) { | ||
| 33 | file.need_stdint = true; | ||
| 34 | try writer.writeAll("uint8_t"); | ||
| 35 | } else { | ||
| 36 | return file.fail(src, "TODO implement int types", .{}); | ||
| 37 | } | ||
| 38 | }, | ||
| 39 | else => |e| return file.fail(src, "TODO implement type {}", .{e}), | ||
| 40 | } | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | fn renderFunctionSignature(file: *C, writer: std.ArrayList(u8).Writer, decl: *Decl) !void { | ||
| 45 | const tv = decl.typed_value.most_recent.typed_value; | ||
| 46 | try renderType(file, writer, tv.ty.fnReturnType(), decl.src()); | ||
| 47 | const name = try map(file.allocator, mem.spanZ(decl.name)); | ||
| 48 | defer file.allocator.free(name); | ||
| 49 | try writer.print(" {}(", .{name}); | ||
| 50 | if (tv.ty.fnParamLen() == 0) | ||
| 51 | try writer.writeAll("void)") | ||
| 52 | else | ||
| 53 | return file.fail(decl.src(), "TODO implement parameters", .{}); | ||
| 54 | } | ||
| 55 | |||
| 56 | pub fn generate(file: *C, decl: *Decl) !void { | ||
| 57 | switch (decl.typed_value.most_recent.typed_value.ty.zigTypeTag()) { | ||
| 58 | .Fn => try genFn(file, decl), | ||
| 59 | .Array => try genArray(file, decl), | ||
| 60 | else => |e| return file.fail(decl.src(), "TODO {}", .{e}), | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | fn genArray(file: *C, decl: *Decl) !void { | ||
| 65 | const tv = decl.typed_value.most_recent.typed_value; | ||
| 66 | // TODO: prevent inline asm constants from being emitted | ||
| 67 | const name = try map(file.allocator, mem.span(decl.name)); | ||
| 68 | defer file.allocator.free(name); | ||
| 69 | if (tv.val.cast(Value.Payload.Bytes)) |payload| | ||
| 70 | if (tv.ty.arraySentinel()) |sentinel| | ||
| 71 | if (sentinel.toUnsignedInt() == 0) | ||
| 72 | try file.constants.writer().print("const char *const {} = \"{}\";\n", .{ name, payload.data }) | ||
| 73 | else | ||
| 74 | return file.fail(decl.src(), "TODO byte arrays with non-zero sentinels", .{}) | ||
| 75 | else | ||
| 76 | return file.fail(decl.src(), "TODO byte arrays without sentinels", .{}) | ||
| 77 | else | ||
| 78 | return file.fail(decl.src(), "TODO non-byte arrays", .{}); | ||
| 79 | } | ||
| 80 | |||
| 81 | fn genFn(file: *C, decl: *Decl) !void { | ||
| 82 | const writer = file.main.writer(); | ||
| 83 | const tv = decl.typed_value.most_recent.typed_value; | ||
| 84 | |||
| 85 | try renderFunctionSignature(file, writer, decl); | ||
| 86 | |||
| 87 | try writer.writeAll(" {"); | ||
| 88 | |||
| 89 | const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func; | ||
| 90 | const instructions = func.analysis.success.instructions; | ||
| 91 | if (instructions.len > 0) { | ||
| 92 | for (instructions) |inst| { | ||
| 93 | try writer.writeAll("\n\t"); | ||
| 94 | switch (inst.tag) { | ||
| 95 | .assembly => try genAsm(file, inst.cast(Inst.Assembly).?, decl), | ||
| 96 | .call => try genCall(file, inst.cast(Inst.Call).?, decl), | ||
| 97 | .ret => try genRet(file, inst.cast(Inst.Ret).?, decl, tv.ty.fnReturnType()), | ||
| 98 | else => |e| return file.fail(decl.src(), "TODO {}", .{e}), | ||
| 99 | } | ||
| 100 | } | ||
| 101 | try writer.writeAll("\n"); | ||
| 102 | } | ||
| 103 | |||
| 104 | try writer.writeAll("}\n\n"); | ||
| 105 | } | ||
| 106 | |||
| 107 | fn genRet(file: *C, inst: *Inst.Ret, decl: *Decl, expected_return_type: Type) !void { | ||
| 108 | const writer = file.main.writer(); | ||
| 109 | const ret_value = inst.args.operand; | ||
| 110 | const value = ret_value.value().?; | ||
| 111 | if (expected_return_type.eql(ret_value.ty)) | ||
| 112 | return file.fail(decl.src(), "TODO return {}", .{expected_return_type}) | ||
| 113 | else if (expected_return_type.isInt() and ret_value.ty.tag() == .comptime_int) | ||
| 114 | if (value.intFitsInType(expected_return_type, file.options.target)) | ||
| 115 | if (expected_return_type.intInfo(file.options.target).bits <= 64) | ||
| 116 | try writer.print("return {};", .{value.toUnsignedInt()}) | ||
| 117 | else | ||
| 118 | return file.fail(decl.src(), "TODO return ints > 64 bits", .{}) | ||
| 119 | else | ||
| 120 | return file.fail(decl.src(), "comptime int {} does not fit in {}", .{ value.toUnsignedInt(), expected_return_type }) | ||
| 121 | else | ||
| 122 | return file.fail(decl.src(), "return type mismatch: expected {}, found {}", .{ expected_return_type, ret_value.ty }); | ||
| 123 | } | ||
| 124 | |||
| 125 | fn genCall(file: *C, inst: *Inst.Call, decl: *Decl) !void { | ||
| 126 | const writer = file.main.writer(); | ||
| 127 | const header = file.header.writer(); | ||
| 128 | if (inst.args.func.cast(Inst.Constant)) |func_inst| { | ||
| 129 | if (func_inst.val.cast(Value.Payload.Function)) |func_val| { | ||
| 130 | const target = func_val.func.owner_decl; | ||
| 131 | const target_ty = target.typed_value.most_recent.typed_value.ty; | ||
| 132 | const ret_ty = target_ty.fnReturnType().tag(); | ||
| 133 | if (target_ty.fnReturnType().hasCodeGenBits() and inst.base.isUnused()) { | ||
| 134 | try writer.print("(void)", .{}); | ||
| 135 | } | ||
| 136 | const tname = mem.spanZ(target.name); | ||
| 137 | if (file.called.get(tname) == null) { | ||
| 138 | try file.called.put(tname, void{}); | ||
| 139 | try renderFunctionSignature(file, header, target); | ||
| 140 | try header.writeAll(";\n"); | ||
| 141 | } | ||
| 142 | try writer.print("{}();", .{tname}); | ||
| 143 | } else { | ||
| 144 | return file.fail(decl.src(), "TODO non-function call target?", .{}); | ||
| 145 | } | ||
| 146 | if (inst.args.args.len != 0) { | ||
| 147 | return file.fail(decl.src(), "TODO function arguments", .{}); | ||
| 148 | } | ||
| 149 | } else { | ||
| 150 | return file.fail(decl.src(), "TODO non-constant call inst?", .{}); | ||
| 151 | } | ||
| 152 | } | ||
| 153 | |||
| 154 | fn genAsm(file: *C, inst: *Inst.Assembly, decl: *Decl) !void { | ||
| 155 | const as = inst.args; | ||
| 156 | const writer = file.main.writer(); | ||
| 157 | for (as.inputs) |i, index| { | ||
| 158 | if (i[0] == '{' and i[i.len - 1] == '}') { | ||
| 159 | const reg = i[1 .. i.len - 1]; | ||
| 160 | const arg = as.args[index]; | ||
| 161 | if (arg.cast(Inst.Constant)) |c| { | ||
| 162 | if (c.val.tag() == .int_u64) { | ||
| 163 | try writer.writeAll("register "); | ||
| 164 | try renderType(file, writer, arg.ty, decl.src()); | ||
| 165 | try writer.print(" {}_constant __asm__(\"{}\") = {};\n\t", .{ reg, reg, c.val.toUnsignedInt() }); | ||
| 166 | } else { | ||
| 167 | return file.fail(decl.src(), "TODO inline asm {} args", .{c.val.tag()}); | ||
| 168 | } | ||
| 169 | } else { | ||
| 170 | return file.fail(decl.src(), "TODO non-constant inline asm args", .{}); | ||
| 171 | } | ||
| 172 | } else { | ||
| 173 | return file.fail(decl.src(), "TODO non-explicit inline asm regs", .{}); | ||
| 174 | } | ||
| 175 | } | ||
| 176 | try writer.print("__asm {} (\"{}\"", .{ if (as.is_volatile) @as([]const u8, "volatile") else "", as.asm_source }); | ||
| 177 | if (as.output) |o| { | ||
| 178 | return file.fail(decl.src(), "TODO inline asm output", .{}); | ||
| 179 | } | ||
| 180 | if (as.inputs.len > 0) { | ||
| 181 | if (as.output == null) { | ||
| 182 | try writer.writeAll(" :"); | ||
| 183 | } | ||
| 184 | try writer.writeAll(": "); | ||
| 185 | for (as.inputs) |i, index| { | ||
| 186 | if (i[0] == '{' and i[i.len - 1] == '}') { | ||
| 187 | const reg = i[1 .. i.len - 1]; | ||
| 188 | const arg = as.args[index]; | ||
| 189 | if (index > 0) { | ||
| 190 | try writer.writeAll(", "); | ||
| 191 | } | ||
| 192 | if (arg.cast(Inst.Constant)) |c| { | ||
| 193 | try writer.print("\"\"({}_constant)", .{reg}); | ||
| 194 | } else { | ||
| 195 | // This is blocked by the earlier test | ||
| 196 | unreachable; | ||
| 197 | } | ||
| 198 | } else { | ||
| 199 | // This is blocked by the earlier test | ||
| 200 | unreachable; | ||
| 201 | } | ||
| 202 | } | ||
| 203 | } | ||
| 204 | try writer.writeAll(");"); | ||
| 205 | } | ||
src-self-hosted/codegen/c.zig created+206| ... | @@ -0,0 +1,206 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | |||
| 3 | const link = @import("../link.zig"); | ||
| 4 | const Module = @import("../Module.zig"); | ||
| 5 | |||
| 6 | const Inst = @import("../ir.zig").Inst; | ||
| 7 | const Value = @import("../value.zig").Value; | ||
| 8 | const Type = @import("../type.zig").Type; | ||
| 9 | |||
| 10 | const C = link.File.C; | ||
| 11 | const Decl = Module.Decl; | ||
| 12 | const mem = std.mem; | ||
| 13 | |||
| 14 | /// Maps a name from Zig source to C. This will always give the same output for | ||
| 15 | /// any given input. | ||
| 16 | fn map(allocator: *std.mem.Allocator, name: []const u8) ![]const u8 { | ||
| 17 | return allocator.dupe(u8, name); | ||
| 18 | } | ||
| 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 | file.need_noreturn = true; | ||
| 28 | try writer.writeAll("noreturn void"); | ||
| 29 | }, | ||
| 30 | .Void => try writer.writeAll("void"), | ||
| 31 | .Int => { | ||
| 32 | if (T.tag() == .u8) { | ||
| 33 | file.need_stdint = true; | ||
| 34 | try writer.writeAll("uint8_t"); | ||
| 35 | } else { | ||
| 36 | return file.fail(src, "TODO implement int types", .{}); | ||
| 37 | } | ||
| 38 | }, | ||
| 39 | else => |e| return file.fail(src, "TODO implement type {}", .{e}), | ||
| 40 | } | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | fn renderFunctionSignature(file: *C, writer: std.ArrayList(u8).Writer, decl: *Decl) !void { | ||
| 45 | const tv = decl.typed_value.most_recent.typed_value; | ||
| 46 | try renderType(file, writer, tv.ty.fnReturnType(), decl.src()); | ||
| 47 | const name = try map(file.allocator, mem.spanZ(decl.name)); | ||
| 48 | defer file.allocator.free(name); | ||
| 49 | try writer.print(" {}(", .{name}); | ||
| 50 | if (tv.ty.fnParamLen() == 0) | ||
| 51 | try writer.writeAll("void)") | ||
| 52 | else | ||
| 53 | return file.fail(decl.src(), "TODO implement parameters", .{}); | ||
| 54 | } | ||
| 55 | |||
| 56 | pub fn generate(file: *C, decl: *Decl) !void { | ||
| 57 | switch (decl.typed_value.most_recent.typed_value.ty.zigTypeTag()) { | ||
| 58 | .Fn => try genFn(file, decl), | ||
| 59 | .Array => try genArray(file, decl), | ||
| 60 | else => |e| return file.fail(decl.src(), "TODO {}", .{e}), | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 64 | fn genArray(file: *C, decl: *Decl) !void { | ||
| 65 | const tv = decl.typed_value.most_recent.typed_value; | ||
| 66 | // TODO: prevent inline asm constants from being emitted | ||
| 67 | const name = try map(file.allocator, mem.span(decl.name)); | ||
| 68 | defer file.allocator.free(name); | ||
| 69 | if (tv.val.cast(Value.Payload.Bytes)) |payload| | ||
| 70 | if (tv.ty.arraySentinel()) |sentinel| | ||
| 71 | if (sentinel.toUnsignedInt() == 0) | ||
| 72 | try file.constants.writer().print("const char *const {} = \"{}\";\n", .{ name, payload.data }) | ||
| 73 | else | ||
| 74 | return file.fail(decl.src(), "TODO byte arrays with non-zero sentinels", .{}) | ||
| 75 | else | ||
| 76 | return file.fail(decl.src(), "TODO byte arrays without sentinels", .{}) | ||
| 77 | else | ||
| 78 | return file.fail(decl.src(), "TODO non-byte arrays", .{}); | ||
| 79 | } | ||
| 80 | |||
| 81 | fn genFn(file: *C, decl: *Decl) !void { | ||
| 82 | const writer = file.main.writer(); | ||
| 83 | const tv = decl.typed_value.most_recent.typed_value; | ||
| 84 | |||
| 85 | try renderFunctionSignature(file, writer, decl); | ||
| 86 | |||
| 87 | try writer.writeAll(" {"); | ||
| 88 | |||
| 89 | const func: *Module.Fn = tv.val.cast(Value.Payload.Function).?.func; | ||
| 90 | const instructions = func.analysis.success.instructions; | ||
| 91 | if (instructions.len > 0) { | ||
| 92 | for (instructions) |inst| { | ||
| 93 | try writer.writeAll("\n\t"); | ||
| 94 | switch (inst.tag) { | ||
| 95 | .assembly => try genAsm(file, inst.cast(Inst.Assembly).?, decl), | ||
| 96 | .call => try genCall(file, inst.cast(Inst.Call).?, decl), | ||
| 97 | .ret => try genRet(file, inst.cast(Inst.Ret).?, decl, tv.ty.fnReturnType()), | ||
| 98 | .retvoid => try file.main.writer().print("return;", .{}), | ||
| 99 | else => |e| return file.fail(decl.src(), "TODO implement C codegen for {}", .{e}), | ||
| 100 | } | ||
| 101 | } | ||
| 102 | try writer.writeAll("\n"); | ||
| 103 | } | ||
| 104 | |||
| 105 | try writer.writeAll("}\n\n"); | ||
| 106 | } | ||
| 107 | |||
| 108 | fn genRet(file: *C, inst: *Inst.Ret, decl: *Decl, expected_return_type: Type) !void { | ||
| 109 | const writer = file.main.writer(); | ||
| 110 | const ret_value = inst.args.operand; | ||
| 111 | const value = ret_value.value().?; | ||
| 112 | if (expected_return_type.eql(ret_value.ty)) | ||
| 113 | return file.fail(decl.src(), "TODO return {}", .{expected_return_type}) | ||
| 114 | else if (expected_return_type.isInt() and ret_value.ty.tag() == .comptime_int) | ||
| 115 | if (value.intFitsInType(expected_return_type, file.options.target)) | ||
| 116 | if (expected_return_type.intInfo(file.options.target).bits <= 64) | ||
| 117 | try writer.print("return {};", .{value.toUnsignedInt()}) | ||
| 118 | else | ||
| 119 | return file.fail(decl.src(), "TODO return ints > 64 bits", .{}) | ||
| 120 | else | ||
| 121 | return file.fail(decl.src(), "comptime int {} does not fit in {}", .{ value.toUnsignedInt(), expected_return_type }) | ||
| 122 | else | ||
| 123 | return file.fail(decl.src(), "return type mismatch: expected {}, found {}", .{ expected_return_type, ret_value.ty }); | ||
| 124 | } | ||
| 125 | |||
| 126 | fn genCall(file: *C, inst: *Inst.Call, decl: *Decl) !void { | ||
| 127 | const writer = file.main.writer(); | ||
| 128 | const header = file.header.writer(); | ||
| 129 | if (inst.args.func.cast(Inst.Constant)) |func_inst| { | ||
| 130 | if (func_inst.val.cast(Value.Payload.Function)) |func_val| { | ||
| 131 | const target = func_val.func.owner_decl; | ||
| 132 | const target_ty = target.typed_value.most_recent.typed_value.ty; | ||
| 133 | const ret_ty = target_ty.fnReturnType().tag(); | ||
| 134 | if (target_ty.fnReturnType().hasCodeGenBits() and inst.base.isUnused()) { | ||
| 135 | try writer.print("(void)", .{}); | ||
| 136 | } | ||
| 137 | const tname = mem.spanZ(target.name); | ||
| 138 | if (file.called.get(tname) == null) { | ||
| 139 | try file.called.put(tname, void{}); | ||
| 140 | try renderFunctionSignature(file, header, target); | ||
| 141 | try header.writeAll(";\n"); | ||
| 142 | } | ||
| 143 | try writer.print("{}();", .{tname}); | ||
| 144 | } else { | ||
| 145 | return file.fail(decl.src(), "TODO non-function call target?", .{}); | ||
| 146 | } | ||
| 147 | if (inst.args.args.len != 0) { | ||
| 148 | return file.fail(decl.src(), "TODO function arguments", .{}); | ||
| 149 | } | ||
| 150 | } else { | ||
| 151 | return file.fail(decl.src(), "TODO non-constant call inst?", .{}); | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | fn genAsm(file: *C, inst: *Inst.Assembly, decl: *Decl) !void { | ||
| 156 | const as = inst.args; | ||
| 157 | const writer = file.main.writer(); | ||
| 158 | for (as.inputs) |i, index| { | ||
| 159 | if (i[0] == '{' and i[i.len - 1] == '}') { | ||
| 160 | const reg = i[1 .. i.len - 1]; | ||
| 161 | const arg = as.args[index]; | ||
| 162 | if (arg.cast(Inst.Constant)) |c| { | ||
| 163 | if (c.val.tag() == .int_u64) { | ||
| 164 | try writer.writeAll("register "); | ||
| 165 | try renderType(file, writer, arg.ty, decl.src()); | ||
| 166 | try writer.print(" {}_constant __asm__(\"{}\") = {};\n\t", .{ reg, reg, c.val.toUnsignedInt() }); | ||
| 167 | } else { | ||
| 168 | return file.fail(decl.src(), "TODO inline asm {} args", .{c.val.tag()}); | ||
| 169 | } | ||
| 170 | } else { | ||
| 171 | return file.fail(decl.src(), "TODO non-constant inline asm args", .{}); | ||
| 172 | } | ||
| 173 | } else { | ||
| 174 | return file.fail(decl.src(), "TODO non-explicit inline asm regs", .{}); | ||
| 175 | } | ||
| 176 | } | ||
| 177 | try writer.print("__asm {} (\"{}\"", .{ if (as.is_volatile) @as([]const u8, "volatile") else "", as.asm_source }); | ||
| 178 | if (as.output) |o| { | ||
| 179 | return file.fail(decl.src(), "TODO inline asm output", .{}); | ||
| 180 | } | ||
| 181 | if (as.inputs.len > 0) { | ||
| 182 | if (as.output == null) { | ||
| 183 | try writer.writeAll(" :"); | ||
| 184 | } | ||
| 185 | try writer.writeAll(": "); | ||
| 186 | for (as.inputs) |i, index| { | ||
| 187 | if (i[0] == '{' and i[i.len - 1] == '}') { | ||
| 188 | const reg = i[1 .. i.len - 1]; | ||
| 189 | const arg = as.args[index]; | ||
| 190 | if (index > 0) { | ||
| 191 | try writer.writeAll(", "); | ||
| 192 | } | ||
| 193 | if (arg.cast(Inst.Constant)) |c| { | ||
| 194 | try writer.print("\"\"({}_constant)", .{reg}); | ||
| 195 | } else { | ||
| 196 | // This is blocked by the earlier test | ||
| 197 | unreachable; | ||
| 198 | } | ||
| 199 | } else { | ||
| 200 | // This is blocked by the earlier test | ||
| 201 | unreachable; | ||
| 202 | } | ||
| 203 | } | ||
| 204 | } | ||
| 205 | try writer.writeAll(");"); | ||
| 206 | } | ||
src-self-hosted/link.zig+2-2| ... | @@ -7,7 +7,7 @@ const Module = @import("Module.zig"); | ... | @@ -7,7 +7,7 @@ const Module = @import("Module.zig"); |
| 7 | const fs = std.fs; | 7 | const fs = std.fs; |
| 8 | const elf = std.elf; | 8 | const elf = std.elf; |
| 9 | const codegen = @import("codegen.zig"); | 9 | const codegen = @import("codegen.zig"); |
| 10 | const cgen = @import("cgen.zig"); | 10 | const c_codegen = @import("codegen/c.zig"); |
| 11 | 11 | ||
| 12 | const default_entry_addr = 0x8000000; | 12 | const default_entry_addr = 0x8000000; |
| 13 | 13 | ||
| ... | @@ -259,7 +259,7 @@ pub const File = struct { | ... | @@ -259,7 +259,7 @@ pub const File = struct { |
| 259 | } | 259 | } |
| 260 | 260 | ||
| 261 | pub fn updateDecl(self: *File.C, module: *Module, decl: *Module.Decl) !void { | 261 | pub fn updateDecl(self: *File.C, module: *Module, decl: *Module.Decl) !void { |
| 262 | cgen.generate(self, decl) catch |err| { | 262 | c_codegen.generate(self, decl) catch |err| { |
| 263 | if (err == error.CGenFailure) { | 263 | if (err == error.CGenFailure) { |
| 264 | try module.failed_decls.put(module.gpa, decl, self.error_msg); | 264 | try module.failed_decls.put(module.gpa, decl, self.error_msg); |
| 265 | } | 265 | } |
test/stage2/cbe.zig+1| ... | @@ -62,6 +62,7 @@ pub fn addCases(ctx: *TestContext) !void { | ... | @@ -62,6 +62,7 @@ pub fn addCases(ctx: *TestContext) !void { |
| 62 | \\	register size_t rax_constant __asm__("rax") = 231; | 62 | \\	register size_t rax_constant __asm__("rax") = 231; |
| 63 | \\	register size_t rdi_constant __asm__("rdi") = 0; | 63 | \\	register size_t rdi_constant __asm__("rdi") = 0; |
| 64 | \\	__asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant)); | 64 | \\	__asm volatile ("syscall" :: ""(rax_constant), ""(rdi_constant)); |
| 65 | \\	return; | ||
| 65 | \\} | 66 | \\} |
| 66 | \\ | 67 | \\ |
| 67 | ); | 68 | ); |