authorgravatar for samuel.tebbs@gmail.comSamTebbs33 <samuel.tebbs@gmail.com> 2019-06-21 00:29:47+01:00
committergravatar for sam.tebbs@arm.comSam Tebbs <sam.tebbs@arm.com> 2019-07-04 14:26:05+01:00
logf24b8f2a4a8ffc014231e6f294153ff05be16f38
tree9486ed7172dc0c8c553551e12e509517d4a56643
parent57d6724186ead79ac76491f42390c0d581a76b04

Support returning !u8 from main


5 files changed, 41 insertions(+), 14 deletions(-)

std/special/start.zig+22-12
...@@ -121,6 +121,9 @@ extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 {...@@ -121,6 +121,9 @@ extern fn main(c_argc: i32, c_argv: [*][*]u8, c_envp: [*]?[*]u8) i32 {
121// This is marked inline because for some reason LLVM in release mode fails to inline it,121// This is marked inline because for some reason LLVM in release mode fails to inline it,
122// and we want fewer call frames in stack traces.122// and we want fewer call frames in stack traces.
123inline fn callMain() u8 {123inline fn callMain() u8 {
124 // General error message for a malformed return type
125 const compile_err_prefix = "expected return type of main to be 'u8', 'noreturn', 'void', '!void', or '!u8', found '";
126 const compile_err = compile_err_prefix ++ @typeName(@typeOf(root.main).ReturnType) ++ "'";
124 switch (@typeId(@typeOf(root.main).ReturnType)) {127 switch (@typeId(@typeOf(root.main).ReturnType)) {
125 .NoReturn => {128 .NoReturn => {
126 root.main();129 root.main();
...@@ -131,23 +134,30 @@ inline fn callMain() u8 {...@@ -131,23 +134,30 @@ inline fn callMain() u8 {
131 },134 },
132 .Int => {135 .Int => {
133 if (@typeOf(root.main).ReturnType.bit_count != 8) {136 if (@typeOf(root.main).ReturnType.bit_count != 8) {
134 @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'");137 @compileError(compile_err);
135 }138 }
136 return root.main();139 return root.main();
137 },140 },
138 .ErrorUnion => {141 builtin.TypeId.ErrorUnion => {
139 root.main() catch |err| {142 const PayloadType = @typeOf(root.main).ReturnType.Payload;
140 std.debug.warn("error: {}\n", @errorName(err));143 // In this case the error should include the payload type
141 if (builtin.os != builtin.Os.zen) {144 const payload_err = compile_err_prefix ++ "!" ++ @typeName(PayloadType) ++ "'";
142 if (@errorReturnTrace()) |trace| {145 // If the payload is void or a u8
143 std.debug.dumpStackTrace(trace.*);146 if (@typeId(PayloadType) == builtin.TypeId.Void or (@typeId(PayloadType) == builtin.TypeId.Int and PayloadType.bit_count == 8)) {
147 const tmp = root.main() catch |err| {
148 std.debug.warn("error: {}\n", @errorName(err));
149 if (builtin.os != builtin.Os.zen) {
150 if (@errorReturnTrace()) |trace| {
151 std.debug.dumpStackTrace(trace.*);
152 }
144 }153 }
145 }154 return 1;
146 return 1;155 };
147 };156 // If main didn't error, return 0 or the exit code
148 return 0;157 return if (PayloadType == void) 0 else tmp;
158 } else @compileError(payload_err);
149 },159 },
150 else => @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '!void'"),160 else => @compileError(compile_err),
151 }161 }
152}162}
153163
test/build_examples.zig+2
...@@ -7,6 +7,8 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void {...@@ -7,6 +7,8 @@ pub fn addCases(cases: *tests.BuildExamplesContext) void {
7 cases.addC("example/hello_world/hello_libc.zig");7 cases.addC("example/hello_world/hello_libc.zig");
8 cases.add("example/cat/main.zig");8 cases.add("example/cat/main.zig");
9 cases.add("example/guess_number/main.zig");9 cases.add("example/guess_number/main.zig");
10 cases.add("test/standalone/main_return_error/error_u8.zig");
11 cases.add("test/standalone/main_return_error/error_u8_non_zero.zig");
10 cases.addBuildFile("test/standalone/main_pkg_path/build.zig");12 cases.addBuildFile("test/standalone/main_pkg_path/build.zig");
11 cases.addBuildFile("example/shared_library/build.zig");13 cases.addBuildFile("example/shared_library/build.zig");
12 cases.addBuildFile("example/mix_o_files/build.zig");14 cases.addBuildFile("example/mix_o_files/build.zig");
test/compile_errors.zig+2-2
...@@ -2213,7 +2213,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2213,7 +2213,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2213 "wrong return type for main",2213 "wrong return type for main",
2214 \\pub fn main() f32 { }2214 \\pub fn main() f32 { }
2215 ,2215 ,
2216 "error: expected return type of main to be 'u8', 'noreturn', 'void', or '!void'",2216 "error: expected return type of main to be 'u8', 'noreturn', 'void', '!void', or '!u8'",
2217 );2217 );
22182218
2219 cases.add(2219 cases.add(
...@@ -2221,7 +2221,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2221,7 +2221,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2221 \\pub fn main() ??void {2221 \\pub fn main() ??void {
2222 \\}2222 \\}
2223 ,2223 ,
2224 "error: expected return type of main to be 'u8', 'noreturn', 'void', or '!void'",2224 "error: expected return type of main to be 'u8', 'noreturn', 'void', '!void', or '!u8'",
2225 );2225 );
22262226
2227 cases.add(2227 cases.add(
test/standalone/main_return_error/error_u8.zig created+7
...@@ -0,0 +1,7 @@
1const Err = error {
2 Foo
3};
4
5pub fn main() !u8 {
6 return Err.Foo;
7}
test/standalone/main_return_error/error_u8_non_zero.zig created+8
...@@ -0,0 +1,8 @@
1const Err = error { Foo };
2
3fn foo() u8 { var x = @intCast(u8, 9); return x; }
4
5pub fn main() !u8 {
6 if (foo() == 7) return Err.Foo;
7 return 123;
8}