authorgravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-07-09 15:38:54-04:00
committergravatar for noam@pixelhero.devNoam Preil <noam@pixelhero.dev> 2020-07-13 01:49:04-04:00
log3bad1c16ccbe9d77df373a0dbbe934dccac13175
tree7a965444ba29e01816da57cbc7fad0485b389eae
parent2c882b2e651386399fd48c24302fd2d4ba430ef3
signature Commit is signed but in an unrecognized format.

Get basic return test working


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 {
989989 error.AnalysisFail => {
990990 decl.analysis = .dependency_failure;
991991 },
992 error.CGenFailure => {
993 // Error is handled by CBE, don't try adding it again
994 },
992995 else => {
993996 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 }
10001008 decl.analysis = .codegen_failure_retryable;
10011009 },
10021010 };
......@@ -1300,6 +1308,20 @@ fn astGenExpr(self: *Module, scope: *Scope, ast_node: *ast.Node) InnerError!*zir
13001308
13011309fn astGenInfixOp(self: *Module, scope: *Scope, infix_node: *ast.Node.InfixOp) InnerError!*zir.Inst {
13021310 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 },
13031325 .Add => {
13041326 const lhs = try self.astGenExpr(scope, infix_node.lhs);
13051327 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) !
2626 try writer.writeAll("noreturn void");
2727 },
2828 .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 },
2937 else => |e| return file.fail(src, "TODO implement type {}", .{e}),
3038 }
3139 }
......@@ -116,6 +124,12 @@ pub fn generate(file: *C, decl: *Decl) !void {
116124 if (call.func.cast(ir.Inst.Constant)) |func_inst| {
117125 if (func_inst.val.cast(Value.Payload.Function)) |func_val| {
118126 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 }
119133 const tname = mem.spanZ(target.name);
120134 if (file.called.get(tname) == null) {
121135 try file.called.put(tname, void{});
......@@ -133,6 +147,28 @@ pub fn generate(file: *C, decl: *Decl) !void {
133147 return file.fail(decl.src(), "TODO non-constant call inst?", .{});
134148 }
135149 },
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 },
136172 else => |e| {
137173 return file.fail(decl.src(), "TODO {}", .{e});
138174 },
src-self-hosted/type.zig+59
......@@ -921,6 +921,11 @@ pub const Type = extern union {
921921 };
922922 }
923923
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
924929 /// Returns true if and only if the type is a fixed-width, signed integer.
925930 pub fn isSignedInt(self: Type) bool {
926931 return switch (self.tag()) {
......@@ -975,6 +980,60 @@ pub const Type = extern union {
975980 };
976981 }
977982
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
9781037 /// Asserts the type is an integer.
9791038 pub fn intInfo(self: Type, target: Target) struct { signed: bool, bits: u16 } {
9801039 return switch (self.tag()) {
test/stage2/cbe.zig+22-22
......@@ -65,26 +65,26 @@ pub fn addCases(ctx: *TestContext) !void {
6565 \\}
6666 \\
6767 );
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 );
9090}