| author | |
| committer | |
| log | 3bad1c16ccbe9d77df373a0dbbe934dccac13175 |
| tree | 7a965444ba29e01816da57cbc7fad0485b389eae |
| parent | 2c882b2e651386399fd48c24302fd2d4ba430ef3 |
| signature | Commit is signed but in an unrecognized format. |
4 files changed, 145 insertions(+), 28 deletions(-)
src-self-hosted/Module.zig+28-6| ... | ... | @@ -989,14 +989,22 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void { |
| 989 | 989 | error.AnalysisFail => { |
| 990 | 990 | decl.analysis = .dependency_failure; |
| 991 | 991 | }, |
| 992 | error.CGenFailure => { | |
| 993 | // Error is handled by CBE, don't try adding it again | |
| 994 | }, | |
| 992 | 995 | else => { |
| 993 | 996 | try self.failed_decls.ensureCapacity(self.gpa, self.failed_decls.items().len + 1); |
| 994 | self.failed_decls.putAssumeCapacityNoClobber(decl, try ErrorMsg.create( | |
| 995 | self.gpa, | |
| 996 | decl.src(), | |
| 997 | "unable to codegen: {}", | |
| 998 | .{@errorName(err)}, | |
| 999 | )); | |
| 997 | const result = self.failed_decls.getOrPutAssumeCapacity(decl); | |
| 998 | if (result.found_existing) { | |
| 999 | std.debug.panic("Internal error: attempted to override error '{}' with 'unable to codegen: {}'", .{ result.entry.value.msg, @errorName(err) }); | |
| 1000 | } else { | |
| 1001 | result.entry.value = try ErrorMsg.create( | |
| 1002 | self.gpa, | |
| 1003 | decl.src(), | |
| 1004 | "unable to codegen: {}", | |
| 1005 | .{@errorName(err)}, | |
| 1006 | ); | |
| 1007 | } | |
| 1000 | 1008 | decl.analysis = .codegen_failure_retryable; |
| 1001 | 1009 | }, |
| 1002 | 1010 | }; |
| ... | ... | @@ -1300,6 +1308,20 @@ fn astGenExpr(self: *Module, scope: *Scope, ast_node: *ast.Node) InnerError!*zir |
| 1300 | 1308 | |
| 1301 | 1309 | fn astGenInfixOp(self: *Module, scope: *Scope, infix_node: *ast.Node.InfixOp) InnerError!*zir.Inst { |
| 1302 | 1310 | switch (infix_node.op) { |
| 1311 | .Assign => { | |
| 1312 | if (infix_node.lhs.id == .Identifier) { | |
| 1313 | const ident = @fieldParentPtr(ast.Node.Identifier, "base", infix_node.lhs); | |
| 1314 | const tree = scope.tree(); | |
| 1315 | const ident_name = tree.tokenSlice(ident.token); | |
| 1316 | if (std.mem.eql(u8, ident_name, "_")) { | |
| 1317 | return self.astGenExpr(scope, infix_node.rhs); | |
| 1318 | } else { | |
| 1319 | return self.failNode(scope, &infix_node.base, "TODO implement infix operator assign", .{}); | |
| 1320 | } | |
| 1321 | } else { | |
| 1322 | return self.failNode(scope, &infix_node.base, "TODO implement infix operator assign", .{}); | |
| 1323 | } | |
| 1324 | }, | |
| 1303 | 1325 | .Add => { |
| 1304 | 1326 | const lhs = try self.astGenExpr(scope, infix_node.lhs); |
| 1305 | 1327 | const rhs = try self.astGenExpr(scope, infix_node.rhs); |
src-self-hosted/cgen.zig+36| ... | ... | @@ -26,6 +26,14 @@ fn renderType(file: *C, writer: std.ArrayList(u8).Writer, T: Type, src: usize) ! |
| 26 | 26 | try writer.writeAll("noreturn void"); |
| 27 | 27 | }, |
| 28 | 28 | .Void => try writer.writeAll("void"), |
| 29 | .Int => { | |
| 30 | if (T.tag() == .u8) { | |
| 31 | file.need_stdint = true; | |
| 32 | try writer.writeAll("uint8_t"); | |
| 33 | } else { | |
| 34 | return file.fail(src, "TODO implement int types", .{}); | |
| 35 | } | |
| 36 | }, | |
| 29 | 37 | else => |e| return file.fail(src, "TODO implement type {}", .{e}), |
| 30 | 38 | } |
| 31 | 39 | } |
| ... | ... | @@ -116,6 +124,12 @@ pub fn generate(file: *C, decl: *Decl) !void { |
| 116 | 124 | if (call.func.cast(ir.Inst.Constant)) |func_inst| { |
| 117 | 125 | if (func_inst.val.cast(Value.Payload.Function)) |func_val| { |
| 118 | 126 | const target = func_val.func.owner_decl; |
| 127 | const target_ty = target.typed_value.most_recent.typed_value.ty; | |
| 128 | const ret_ty = target_ty.fnReturnType().tag(); | |
| 129 | if (ret_ty != .void and ret_ty != .noreturn) { | |
| 130 | // TODO: don't do this if we're actually using the value | |
| 131 | try writer.print("(void)", .{}); | |
| 132 | } | |
| 119 | 133 | const tname = mem.spanZ(target.name); |
| 120 | 134 | if (file.called.get(tname) == null) { |
| 121 | 135 | try file.called.put(tname, void{}); |
| ... | ... | @@ -133,6 +147,28 @@ pub fn generate(file: *C, decl: *Decl) !void { |
| 133 | 147 | return file.fail(decl.src(), "TODO non-constant call inst?", .{}); |
| 134 | 148 | } |
| 135 | 149 | }, |
| 150 | .ret => { | |
| 151 | const ret_value: *ir.Inst = inst.cast(ir.Inst.Ret).?.args.operand; | |
| 152 | const expected_return_type = tv.ty.fnReturnType(); | |
| 153 | const value = ret_value.value().?; | |
| 154 | if (expected_return_type.eql(ret_value.ty)) { | |
| 155 | return file.fail(decl.src(), "TODO return {}", .{expected_return_type}); | |
| 156 | } else { | |
| 157 | if (expected_return_type.isInt() and ret_value.ty.tag() == .comptime_int) { | |
| 158 | if (value.intFitsInType(expected_return_type, file.options.target)) { | |
| 159 | if (expected_return_type.intInfo(file.options.target).bits <= 64) { | |
| 160 | try writer.print("return {};", .{value.toUnsignedInt()}); | |
| 161 | } else { | |
| 162 | return file.fail(decl.src(), "TODO return ints > 64 bits", .{}); | |
| 163 | } | |
| 164 | } else { | |
| 165 | return file.fail(decl.src(), "comptime int {} does not fit in {}", .{ value.toUnsignedInt(), expected_return_type }); | |
| 166 | } | |
| 167 | } else { | |
| 168 | return file.fail(decl.src(), "return type mismatch: expected {}, found {}", .{ expected_return_type, ret_value.ty }); | |
| 169 | } | |
| 170 | } | |
| 171 | }, | |
| 136 | 172 | else => |e| { |
| 137 | 173 | return file.fail(decl.src(), "TODO {}", .{e}); |
| 138 | 174 | }, |
src-self-hosted/type.zig+59| ... | ... | @@ -921,6 +921,11 @@ pub const Type = extern union { |
| 921 | 921 | }; |
| 922 | 922 | } |
| 923 | 923 | |
| 924 | /// Returns true if and only if the type is a fixed-width integer. | |
| 925 | pub fn isInt(self: Type) bool { | |
| 926 | return self.isSignedInt() or self.isUnsignedInt(); | |
| 927 | } | |
| 928 | ||
| 924 | 929 | /// Returns true if and only if the type is a fixed-width, signed integer. |
| 925 | 930 | pub fn isSignedInt(self: Type) bool { |
| 926 | 931 | return switch (self.tag()) { |
| ... | ... | @@ -975,6 +980,60 @@ pub const Type = extern union { |
| 975 | 980 | }; |
| 976 | 981 | } |
| 977 | 982 | |
| 983 | /// Returns true if and only if the type is a fixed-width, unsigned integer. | |
| 984 | pub fn isUnsignedInt(self: Type) bool { | |
| 985 | return switch (self.tag()) { | |
| 986 | .f16, | |
| 987 | .f32, | |
| 988 | .f64, | |
| 989 | .f128, | |
| 990 | .c_longdouble, | |
| 991 | .c_void, | |
| 992 | .bool, | |
| 993 | .void, | |
| 994 | .type, | |
| 995 | .anyerror, | |
| 996 | .comptime_int, | |
| 997 | .comptime_float, | |
| 998 | .noreturn, | |
| 999 | .@"null", | |
| 1000 | .@"undefined", | |
| 1001 | .fn_noreturn_no_args, | |
| 1002 | .fn_void_no_args, | |
| 1003 | .fn_naked_noreturn_no_args, | |
| 1004 | .fn_ccc_void_no_args, | |
| 1005 | .function, | |
| 1006 | .array, | |
| 1007 | .single_const_pointer, | |
| 1008 | .single_const_pointer_to_comptime_int, | |
| 1009 | .array_u8_sentinel_0, | |
| 1010 | .const_slice_u8, | |
| 1011 | .int_signed, | |
| 1012 | .i8, | |
| 1013 | .isize, | |
| 1014 | .c_short, | |
| 1015 | .c_int, | |
| 1016 | .c_long, | |
| 1017 | .c_longlong, | |
| 1018 | .i16, | |
| 1019 | .i32, | |
| 1020 | .i64, | |
| 1021 | => false, | |
| 1022 | ||
| 1023 | .int_unsigned, | |
| 1024 | .u8, | |
| 1025 | .usize, | |
| 1026 | .c_ushort, | |
| 1027 | .c_uint, | |
| 1028 | .c_ulong, | |
| 1029 | .c_ulonglong, | |
| 1030 | .u16, | |
| 1031 | .u32, | |
| 1032 | .u64, | |
| 1033 | => true, | |
| 1034 | }; | |
| 1035 | } | |
| 1036 | ||
| 978 | 1037 | /// Asserts the type is an integer. |
| 979 | 1038 | pub fn intInfo(self: Type, target: Target) struct { signed: bool, bits: u16 } { |
| 980 | 1039 | return switch (self.tag()) { |
test/stage2/cbe.zig+22-22| ... | ... | @@ -65,26 +65,26 @@ pub fn addCases(ctx: *TestContext) !void { |
| 65 | 65 | \\} |
| 66 | 66 | \\ |
| 67 | 67 | ); |
| 68 | //ctx.c("basic return", linux_x64, | |
| 69 | // \\fn main() u8 { | |
| 70 | // \\	return 103; | |
| 71 | // \\} | |
| 72 | // \\ | |
| 73 | // \\export fn _start() noreturn { | |
| 74 | // \\	_ = main(); | |
| 75 | // \\} | |
| 76 | //, | |
| 77 | // \\#include <stdint.h> | |
| 78 | // \\ | |
| 79 | // \\uint8_t main(void); | |
| 80 | // \\ | |
| 81 | // \\noreturn void _start(void) { | |
| 82 | // \\	(void)main(); | |
| 83 | // \\} | |
| 84 | // \\ | |
| 85 | // \\uint8_t main(void) { | |
| 86 | // \\	return 103; | |
| 87 | // \\} | |
| 88 | // \\ | |
| 89 | //); | |
| 68 | ctx.c("basic return", linux_x64, | |
| 69 | \\fn main() u8 { | |
| 70 | \\	return 103; | |
| 71 | \\} | |
| 72 | \\ | |
| 73 | \\export fn _start() noreturn { | |
| 74 | \\	_ = main(); | |
| 75 | \\} | |
| 76 | , | |
| 77 | \\#include <stdint.h> | |
| 78 | \\ | |
| 79 | \\uint8_t main(void); | |
| 80 | \\ | |
| 81 | \\noreturn void _start(void) { | |
| 82 | \\	(void)main(); | |
| 83 | \\} | |
| 84 | \\ | |
| 85 | \\uint8_t main(void) { | |
| 86 | \\	return 103; | |
| 87 | \\} | |
| 88 | \\ | |
| 89 | ); | |
| 90 | 90 | } |