| author | |
| committer | |
| log | 66a24c9c00d63853cd50f792847f52f7b2d06cb3 |
| tree | 63224d479e266886257d6b403034dfa222094ee6 |
| parent | fa7b33549e43abbdb4fba1d686dfd63c2ca8e8ca |
| parent | 92fc5947fc18ea077f0e02bc4758e9050270e4bb |
50 files changed, 873 insertions(+), 361 deletions(-)
README.md+1-1| ... | @@ -54,7 +54,7 @@ that counts as "freestanding" for the purposes of this table. | ... | @@ -54,7 +54,7 @@ that counts as "freestanding" for the purposes of this table. |
| 54 | 54 | ||
| 55 | | | freestanding | linux | macosx | windows | other | | 55 | | | freestanding | linux | macosx | windows | other | |
| 56 | |-------------|--------------|---------|---------|---------|---------| | 56 | |-------------|--------------|---------|---------|---------|---------| |
| 57 | |i386 | OK | planned | OK | OK | planned | | 57 | |i386 | OK | planned | OK | planned | planned | |
| 58 | |x86_64 | OK | OK | OK | OK | planned | | 58 | |x86_64 | OK | OK | OK | OK | planned | |
| 59 | |arm | OK | planned | planned | N/A | planned | | 59 | |arm | OK | planned | planned | N/A | planned | |
| 60 | |aarch64 | OK | planned | planned | planned | planned | | 60 | |aarch64 | OK | planned | planned | planned | planned | |
build.zig+6-6| ... | @@ -10,7 +10,7 @@ const ArrayList = std.ArrayList; | ... | @@ -10,7 +10,7 @@ const ArrayList = std.ArrayList; |
| 10 | const Buffer = std.Buffer; | 10 | const Buffer = std.Buffer; |
| 11 | const io = std.io; | 11 | const io = std.io; |
| 12 | 12 | ||
| 13 | pub fn build(b: &Builder) { | 13 | pub fn build(b: &Builder) -> %void { |
| 14 | const mode = b.standardReleaseOptions(); | 14 | const mode = b.standardReleaseOptions(); |
| 15 | 15 | ||
| 16 | var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig"); | 16 | var docgen_exe = b.addExecutable("docgen", "doc/docgen.zig"); |
| ... | @@ -36,7 +36,7 @@ pub fn build(b: &Builder) { | ... | @@ -36,7 +36,7 @@ pub fn build(b: &Builder) { |
| 36 | const test_step = b.step("test", "Run all the tests"); | 36 | const test_step = b.step("test", "Run all the tests"); |
| 37 | 37 | ||
| 38 | // find the stage0 build artifacts because we're going to re-use config.h and zig_cpp library | 38 | // find the stage0 build artifacts because we're going to re-use config.h and zig_cpp library |
| 39 | const build_info = b.exec([][]const u8{b.zig_exe, "BUILD_INFO"}); | 39 | const build_info = try b.exec([][]const u8{b.zig_exe, "BUILD_INFO"}); |
| 40 | var index: usize = 0; | 40 | var index: usize = 0; |
| 41 | const cmake_binary_dir = nextValue(&index, build_info); | 41 | const cmake_binary_dir = nextValue(&index, build_info); |
| 42 | const cxx_compiler = nextValue(&index, build_info); | 42 | const cxx_compiler = nextValue(&index, build_info); |
| ... | @@ -68,7 +68,7 @@ pub fn build(b: &Builder) { | ... | @@ -68,7 +68,7 @@ pub fn build(b: &Builder) { |
| 68 | dependOnLib(exe, llvm); | 68 | dependOnLib(exe, llvm); |
| 69 | 69 | ||
| 70 | if (exe.target.getOs() == builtin.Os.linux) { | 70 | if (exe.target.getOs() == builtin.Os.linux) { |
| 71 | const libstdcxx_path_padded = b.exec([][]const u8{cxx_compiler, "-print-file-name=libstdc++.a"}); | 71 | const libstdcxx_path_padded = try b.exec([][]const u8{cxx_compiler, "-print-file-name=libstdc++.a"}); |
| 72 | const libstdcxx_path = ??mem.split(libstdcxx_path_padded, "\r\n").next(); | 72 | const libstdcxx_path = ??mem.split(libstdcxx_path_padded, "\r\n").next(); |
| 73 | exe.addObjectFile(libstdcxx_path); | 73 | exe.addObjectFile(libstdcxx_path); |
| 74 | 74 | ||
| ... | @@ -155,9 +155,9 @@ const LibraryDep = struct { | ... | @@ -155,9 +155,9 @@ const LibraryDep = struct { |
| 155 | }; | 155 | }; |
| 156 | 156 | ||
| 157 | fn findLLVM(b: &Builder, llvm_config_exe: []const u8) -> %LibraryDep { | 157 | fn findLLVM(b: &Builder, llvm_config_exe: []const u8) -> %LibraryDep { |
| 158 | const libs_output = b.exec([][]const u8{llvm_config_exe, "--libs", "--system-libs"}); | 158 | const libs_output = try b.exec([][]const u8{llvm_config_exe, "--libs", "--system-libs"}); |
| 159 | const includes_output = b.exec([][]const u8{llvm_config_exe, "--includedir"}); | 159 | const includes_output = try b.exec([][]const u8{llvm_config_exe, "--includedir"}); |
| 160 | const libdir_output = b.exec([][]const u8{llvm_config_exe, "--libdir"}); | 160 | const libdir_output = try b.exec([][]const u8{llvm_config_exe, "--libdir"}); |
| 161 | 161 | ||
| 162 | var result = LibraryDep { | 162 | var result = LibraryDep { |
| 163 | .libs = ArrayList([]const u8).init(b.allocator), | 163 | .libs = ArrayList([]const u8).init(b.allocator), |
doc/langref.html.in+8| ... | @@ -142,6 +142,7 @@ | ... | @@ -142,6 +142,7 @@ |
| 142 | <li><a href="#builtin-TagType">@TagType</a></li> | 142 | <li><a href="#builtin-TagType">@TagType</a></li> |
| 143 | <li><a href="#builtin-EnumTagType">@EnumTagType</a></li> | 143 | <li><a href="#builtin-EnumTagType">@EnumTagType</a></li> |
| 144 | <li><a href="#builtin-errorName">@errorName</a></li> | 144 | <li><a href="#builtin-errorName">@errorName</a></li> |
| 145 | <li><a href="#builtin-errorReturnTrace">@errorReturnTrace</a></li> | ||
| 145 | <li><a href="#builtin-fence">@fence</a></li> | 146 | <li><a href="#builtin-fence">@fence</a></li> |
| 146 | <li><a href="#builtin-fieldParentPtr">@fieldParentPtr</a></li> | 147 | <li><a href="#builtin-fieldParentPtr">@fieldParentPtr</a></li> |
| 147 | <li><a href="#builtin-frameAddress">@frameAddress</a></li> | 148 | <li><a href="#builtin-frameAddress">@frameAddress</a></li> |
| ... | @@ -4412,6 +4413,13 @@ test.zig:6:2: error: found compile log statement | ... | @@ -4412,6 +4413,13 @@ test.zig:6:2: error: found compile log statement |
| 4412 | or all calls have a compile-time known value for <code>err</code>, then no | 4413 | or all calls have a compile-time known value for <code>err</code>, then no |
| 4413 | error name table will be generated. | 4414 | error name table will be generated. |
| 4414 | </p> | 4415 | </p> |
| 4416 | <h3 id="builtin-errorReturnTrace">@errorReturnTrace</h3> | ||
| 4417 | <pre><code class="zig">@errorReturnTrace() -&gt; ?&amp;builtin.StackTrace</code></pre> | ||
| 4418 | <p> | ||
| 4419 | If the binary is built with error return tracing, and this function is invoked in a | ||
| 4420 | function that calls a function with an error or error union return type, returns a | ||
| 4421 | stack trace object. Otherwise returns `null`. | ||
| 4422 | </p> | ||
| 4415 | <h3 id="builtin-fence">@fence</h3> | 4423 | <h3 id="builtin-fence">@fence</h3> |
| 4416 | <pre><code class="zig">@fence(order: AtomicOrder)</code></pre> | 4424 | <pre><code class="zig">@fence(order: AtomicOrder)</code></pre> |
| 4417 | <p> | 4425 | <p> |
example/mix_o_files/build.zig+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const Builder = @import("std").build.Builder; | 1 | const Builder = @import("std").build.Builder; |
| 2 | 2 | ||
| 3 | pub fn build(b: &Builder) { | 3 | pub fn build(b: &Builder) -> %void { |
| 4 | const obj = b.addObject("base64", "base64.zig"); | 4 | const obj = b.addObject("base64", "base64.zig"); |
| 5 | 5 | ||
| 6 | const exe = b.addCExecutable("test"); | 6 | const exe = b.addCExecutable("test"); |
example/shared_library/build.zig+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const Builder = @import("std").build.Builder; | 1 | const Builder = @import("std").build.Builder; |
| 2 | 2 | ||
| 3 | pub fn build(b: &Builder) { | 3 | pub fn build(b: &Builder) -> %void { |
| 4 | const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0)); | 4 | const lib = b.addSharedLibrary("mathtest", "mathtest.zig", b.version(1, 0, 0)); |
| 5 | 5 | ||
| 6 | const exe = b.addCExecutable("test"); | 6 | const exe = b.addCExecutable("test"); |
src-self-hosted/parser.zig-6| ... | @@ -1146,12 +1146,6 @@ fn testCanonical(source: []const u8) { | ... | @@ -1146,12 +1146,6 @@ fn testCanonical(source: []const u8) { |
| 1146 | } | 1146 | } |
| 1147 | 1147 | ||
| 1148 | test "zig fmt" { | 1148 | test "zig fmt" { |
| 1149 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 1150 | // TODO get this test passing | ||
| 1151 | // https://github.com/zig-lang/zig/issues/537 | ||
| 1152 | return; | ||
| 1153 | } | ||
| 1154 | |||
| 1155 | testCanonical( | 1149 | testCanonical( |
| 1156 | \\extern fn puts(s: &const u8) -> c_int; | 1150 | \\extern fn puts(s: &const u8) -> c_int; |
| 1157 | \\ | 1151 | \\ |
src/all_types.hpp+13| ... | @@ -1205,6 +1205,7 @@ struct FnTableEntry { | ... | @@ -1205,6 +1205,7 @@ struct FnTableEntry { |
| 1205 | uint32_t alignstack_value; | 1205 | uint32_t alignstack_value; |
| 1206 | 1206 | ||
| 1207 | ZigList<FnExport> export_list; | 1207 | ZigList<FnExport> export_list; |
| 1208 | bool calls_errorable_function; | ||
| 1208 | }; | 1209 | }; |
| 1209 | 1210 | ||
| 1210 | uint32_t fn_table_entry_hash(FnTableEntry*); | 1211 | uint32_t fn_table_entry_hash(FnTableEntry*); |
| ... | @@ -1273,6 +1274,7 @@ enum BuiltinFnId { | ... | @@ -1273,6 +1274,7 @@ enum BuiltinFnId { |
| 1273 | BuiltinFnIdSetAlignStack, | 1274 | BuiltinFnIdSetAlignStack, |
| 1274 | BuiltinFnIdArgType, | 1275 | BuiltinFnIdArgType, |
| 1275 | BuiltinFnIdExport, | 1276 | BuiltinFnIdExport, |
| 1277 | BuiltinFnIdErrorReturnTrace, | ||
| 1276 | }; | 1278 | }; |
| 1277 | 1279 | ||
| 1278 | struct BuiltinFnEntry { | 1280 | struct BuiltinFnEntry { |
| ... | @@ -1498,6 +1500,7 @@ struct CodeGen { | ... | @@ -1498,6 +1500,7 @@ struct CodeGen { |
| 1498 | Buf triple_str; | 1500 | Buf triple_str; |
| 1499 | BuildMode build_mode; | 1501 | BuildMode build_mode; |
| 1500 | bool is_test_build; | 1502 | bool is_test_build; |
| 1503 | bool have_err_ret_tracing; | ||
| 1501 | uint32_t target_os_index; | 1504 | uint32_t target_os_index; |
| 1502 | uint32_t target_arch_index; | 1505 | uint32_t target_arch_index; |
| 1503 | uint32_t target_environ_index; | 1506 | uint32_t target_environ_index; |
| ... | @@ -1530,6 +1533,7 @@ struct CodeGen { | ... | @@ -1530,6 +1533,7 @@ struct CodeGen { |
| 1530 | FnTableEntry *panic_fn; | 1533 | FnTableEntry *panic_fn; |
| 1531 | LLVMValueRef cur_ret_ptr; | 1534 | LLVMValueRef cur_ret_ptr; |
| 1532 | LLVMValueRef cur_fn_val; | 1535 | LLVMValueRef cur_fn_val; |
| 1536 | LLVMValueRef cur_err_ret_trace_val; | ||
| 1533 | bool c_want_stdint; | 1537 | bool c_want_stdint; |
| 1534 | bool c_want_stdbool; | 1538 | bool c_want_stdbool; |
| 1535 | AstNode *root_export_decl; | 1539 | AstNode *root_export_decl; |
| ... | @@ -1572,6 +1576,8 @@ struct CodeGen { | ... | @@ -1572,6 +1576,8 @@ struct CodeGen { |
| 1572 | size_t largest_err_name_len; | 1576 | size_t largest_err_name_len; |
| 1573 | LLVMValueRef safety_crash_err_fn; | 1577 | LLVMValueRef safety_crash_err_fn; |
| 1574 | 1578 | ||
| 1579 | LLVMValueRef return_err_fn; | ||
| 1580 | |||
| 1575 | IrInstruction *invalid_instruction; | 1581 | IrInstruction *invalid_instruction; |
| 1576 | ConstExprValue const_void_val; | 1582 | ConstExprValue const_void_val; |
| 1577 | 1583 | ||
| ... | @@ -1595,6 +1601,8 @@ struct CodeGen { | ... | @@ -1595,6 +1601,8 @@ struct CodeGen { |
| 1595 | ZigList<AstNode *> tld_ref_source_node_stack; | 1601 | ZigList<AstNode *> tld_ref_source_node_stack; |
| 1596 | 1602 | ||
| 1597 | TypeTableEntry *align_amt_type; | 1603 | TypeTableEntry *align_amt_type; |
| 1604 | TypeTableEntry *stack_trace_type; | ||
| 1605 | TypeTableEntry *ptr_to_stack_trace_type; | ||
| 1598 | }; | 1606 | }; |
| 1599 | 1607 | ||
| 1600 | enum VarLinkage { | 1608 | enum VarLinkage { |
| ... | @@ -1896,6 +1904,7 @@ enum IrInstructionId { | ... | @@ -1896,6 +1904,7 @@ enum IrInstructionId { |
| 1896 | IrInstructionIdSetAlignStack, | 1904 | IrInstructionIdSetAlignStack, |
| 1897 | IrInstructionIdArgType, | 1905 | IrInstructionIdArgType, |
| 1898 | IrInstructionIdExport, | 1906 | IrInstructionIdExport, |
| 1907 | IrInstructionIdErrorReturnTrace, | ||
| 1899 | }; | 1908 | }; |
| 1900 | 1909 | ||
| 1901 | struct IrInstruction { | 1910 | struct IrInstruction { |
| ... | @@ -2717,6 +2726,10 @@ struct IrInstructionExport { | ... | @@ -2717,6 +2726,10 @@ struct IrInstructionExport { |
| 2717 | IrInstruction *target; | 2726 | IrInstruction *target; |
| 2718 | }; | 2727 | }; |
| 2719 | 2728 | ||
| 2729 | struct IrInstructionErrorReturnTrace { | ||
| 2730 | IrInstruction base; | ||
| 2731 | }; | ||
| 2732 | |||
| 2720 | static const size_t slice_ptr_index = 0; | 2733 | static const size_t slice_ptr_index = 0; |
| 2721 | static const size_t slice_len_index = 1; | 2734 | static const size_t slice_len_index = 1; |
| 2722 | 2735 |
src/analyze.cpp+48-12| ... | @@ -869,6 +869,16 @@ static const char *calling_convention_fn_type_str(CallingConvention cc) { | ... | @@ -869,6 +869,16 @@ static const char *calling_convention_fn_type_str(CallingConvention cc) { |
| 869 | zig_unreachable(); | 869 | zig_unreachable(); |
| 870 | } | 870 | } |
| 871 | 871 | ||
| 872 | TypeTableEntry *get_ptr_to_stack_trace_type(CodeGen *g) { | ||
| 873 | if (g->stack_trace_type == nullptr) { | ||
| 874 | ConstExprValue *stack_trace_type_val = get_builtin_value(g, "StackTrace"); | ||
| 875 | assert(stack_trace_type_val->type->id == TypeTableEntryIdMetaType); | ||
| 876 | g->stack_trace_type = stack_trace_type_val->data.x_type; | ||
| 877 | g->ptr_to_stack_trace_type = get_pointer_to_type(g, g->stack_trace_type, false); | ||
| 878 | } | ||
| 879 | return g->ptr_to_stack_trace_type; | ||
| 880 | } | ||
| 881 | |||
| 872 | TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { | 882 | TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 873 | auto table_entry = g->fn_type_table.maybe_get(fn_type_id); | 883 | auto table_entry = g->fn_type_table.maybe_get(fn_type_id); |
| 874 | if (table_entry) { | 884 | if (table_entry) { |
| ... | @@ -915,10 +925,16 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { | ... | @@ -915,10 +925,16 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 915 | if (!skip_debug_info) { | 925 | if (!skip_debug_info) { |
| 916 | bool first_arg_return = calling_convention_does_first_arg_return(fn_type_id->cc) && | 926 | bool first_arg_return = calling_convention_does_first_arg_return(fn_type_id->cc) && |
| 917 | handle_is_ptr(fn_type_id->return_type); | 927 | handle_is_ptr(fn_type_id->return_type); |
| 928 | bool prefix_arg_error_return_trace = g->have_err_ret_tracing && | ||
| 929 | (fn_type_id->return_type->id == TypeTableEntryIdErrorUnion || | ||
| 930 | fn_type_id->return_type->id == TypeTableEntryIdPureError); | ||
| 918 | // +1 for maybe making the first argument the return value | 931 | // +1 for maybe making the first argument the return value |
| 919 | LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(1 + fn_type_id->param_count); | 932 | // +1 for maybe last argument the error return trace |
| 920 | // +1 because 0 is the return type and +1 for maybe making first arg ret val | 933 | LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(2 + fn_type_id->param_count); |
| 921 | ZigLLVMDIType **param_di_types = allocate<ZigLLVMDIType*>(2 + fn_type_id->param_count); | 934 | // +1 because 0 is the return type and |
| 935 | // +1 for maybe making first arg ret val and | ||
| 936 | // +1 for maybe last argument the error return trace | ||
| 937 | ZigLLVMDIType **param_di_types = allocate<ZigLLVMDIType*>(3 + fn_type_id->param_count); | ||
| 922 | param_di_types[0] = fn_type_id->return_type->di_type; | 938 | param_di_types[0] = fn_type_id->return_type->di_type; |
| 923 | size_t gen_param_index = 0; | 939 | size_t gen_param_index = 0; |
| 924 | TypeTableEntry *gen_return_type; | 940 | TypeTableEntry *gen_return_type; |
| ... | @@ -936,6 +952,14 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { | ... | @@ -936,6 +952,14 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) { |
| 936 | } | 952 | } |
| 937 | fn_type->data.fn.gen_return_type = gen_return_type; | 953 | fn_type->data.fn.gen_return_type = gen_return_type; |
| 938 | 954 | ||
| 955 | if (prefix_arg_error_return_trace) { | ||
| 956 | TypeTableEntry *gen_type = get_ptr_to_stack_trace_type(g); | ||
| 957 | gen_param_types[gen_param_index] = gen_type->type_ref; | ||
| 958 | gen_param_index += 1; | ||
| 959 | // after the gen_param_index += 1 because 0 is the return type | ||
| 960 | param_di_types[gen_param_index] = gen_type->di_type; | ||
| 961 | } | ||
| 962 | |||
| 939 | fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(fn_type_id->param_count); | 963 | fn_type->data.fn.gen_param_info = allocate<FnGenParamInfo>(fn_type_id->param_count); |
| 940 | for (size_t i = 0; i < fn_type_id->param_count; i += 1) { | 964 | for (size_t i = 0; i < fn_type_id->param_count; i += 1) { |
| 941 | FnTypeParamInfo *src_param_info = &fn_type->data.fn.fn_type_id.param_info[i]; | 965 | FnTypeParamInfo *src_param_info = &fn_type->data.fn.fn_type_id.param_info[i]; |
| ... | @@ -1168,6 +1192,9 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c | ... | @@ -1168,6 +1192,9 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c |
| 1168 | } | 1192 | } |
| 1169 | 1193 | ||
| 1170 | TypeTableEntry *type_entry = analyze_type_expr(g, child_scope, param_node->data.param_decl.type); | 1194 | TypeTableEntry *type_entry = analyze_type_expr(g, child_scope, param_node->data.param_decl.type); |
| 1195 | if (type_is_invalid(type_entry)) { | ||
| 1196 | return g->builtin_types.entry_invalid; | ||
| 1197 | } | ||
| 1171 | if (fn_type_id.cc != CallingConventionUnspecified) { | 1198 | if (fn_type_id.cc != CallingConventionUnspecified) { |
| 1172 | type_ensure_zero_bits_known(g, type_entry); | 1199 | type_ensure_zero_bits_known(g, type_entry); |
| 1173 | if (!type_has_bits(type_entry)) { | 1200 | if (!type_has_bits(type_entry)) { |
| ... | @@ -2204,6 +2231,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { | ... | @@ -2204,6 +2231,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) { |
| 2204 | // is a pointer to this very struct, or a function pointer with parameters that | 2231 | // is a pointer to this very struct, or a function pointer with parameters that |
| 2205 | // reference such a type. | 2232 | // reference such a type. |
| 2206 | union_type->data.unionation.zero_bits_known = true; | 2233 | union_type->data.unionation.zero_bits_known = true; |
| 2234 | union_type->data.unionation.zero_bits_loop_flag = false; | ||
| 2207 | if (union_type->data.unionation.abi_alignment == 0) { | 2235 | if (union_type->data.unionation.abi_alignment == 0) { |
| 2208 | if (union_type->data.unionation.layout == ContainerLayoutPacked) { | 2236 | if (union_type->data.unionation.layout == ContainerLayoutPacked) { |
| 2209 | union_type->data.unionation.abi_alignment = 1; | 2237 | union_type->data.unionation.abi_alignment = 1; |
| ... | @@ -2558,7 +2586,7 @@ static bool scope_is_root_decls(Scope *scope) { | ... | @@ -2558,7 +2586,7 @@ static bool scope_is_root_decls(Scope *scope) { |
| 2558 | 2586 | ||
| 2559 | static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, TypeTableEntry *fn_type) { | 2587 | static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, TypeTableEntry *fn_type) { |
| 2560 | add_node_error(g, proto_node, | 2588 | add_node_error(g, proto_node, |
| 2561 | buf_sprintf("expected 'fn([]const u8) -> unreachable', found '%s'", | 2589 | buf_sprintf("expected 'fn([]const u8, ?&builtin.StackTrace) -> unreachable', found '%s'", |
| 2562 | buf_ptr(&fn_type->name))); | 2590 | buf_ptr(&fn_type->name))); |
| 2563 | } | 2591 | } |
| 2564 | 2592 | ||
| ... | @@ -2567,7 +2595,7 @@ static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) { | ... | @@ -2567,7 +2595,7 @@ static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) { |
| 2567 | assert(proto_node->type == NodeTypeFnProto); | 2595 | assert(proto_node->type == NodeTypeFnProto); |
| 2568 | TypeTableEntry *fn_type = panic_fn->type_entry; | 2596 | TypeTableEntry *fn_type = panic_fn->type_entry; |
| 2569 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; | 2597 | FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; |
| 2570 | if (fn_type_id->param_count != 1) { | 2598 | if (fn_type_id->param_count != 2) { |
| 2571 | return wrong_panic_prototype(g, proto_node, fn_type); | 2599 | return wrong_panic_prototype(g, proto_node, fn_type); |
| 2572 | } | 2600 | } |
| 2573 | TypeTableEntry *const_u8_ptr = get_pointer_to_type(g, g->builtin_types.entry_u8, true); | 2601 | TypeTableEntry *const_u8_ptr = get_pointer_to_type(g, g->builtin_types.entry_u8, true); |
| ... | @@ -2576,6 +2604,11 @@ static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) { | ... | @@ -2576,6 +2604,11 @@ static void typecheck_panic_fn(CodeGen *g, FnTableEntry *panic_fn) { |
| 2576 | return wrong_panic_prototype(g, proto_node, fn_type); | 2604 | return wrong_panic_prototype(g, proto_node, fn_type); |
| 2577 | } | 2605 | } |
| 2578 | 2606 | ||
| 2607 | TypeTableEntry *nullable_ptr_to_stack_trace_type = get_maybe_type(g, get_ptr_to_stack_trace_type(g)); | ||
| 2608 | if (fn_type_id->param_info[1].type != nullable_ptr_to_stack_trace_type) { | ||
| 2609 | return wrong_panic_prototype(g, proto_node, fn_type); | ||
| 2610 | } | ||
| 2611 | |||
| 2579 | TypeTableEntry *actual_return_type = fn_type_id->return_type; | 2612 | TypeTableEntry *actual_return_type = fn_type_id->return_type; |
| 2580 | if (actual_return_type != g->builtin_types.entry_unreachable) { | 2613 | if (actual_return_type != g->builtin_types.entry_unreachable) { |
| 2581 | return wrong_panic_prototype(g, proto_node, fn_type); | 2614 | return wrong_panic_prototype(g, proto_node, fn_type); |
| ... | @@ -2680,13 +2713,6 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { | ... | @@ -2680,13 +2713,6 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) { |
| 2680 | { | 2713 | { |
| 2681 | if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) { | 2714 | if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) { |
| 2682 | g->main_fn = fn_table_entry; | 2715 | g->main_fn = fn_table_entry; |
| 2683 | TypeTableEntry *err_void = get_error_type(g, g->builtin_types.entry_void); | ||
| 2684 | TypeTableEntry *actual_return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type; | ||
| 2685 | if (actual_return_type != err_void) { | ||
| 2686 | add_node_error(g, fn_proto->return_type, | ||
| 2687 | buf_sprintf("expected return type of main to be '%%void', instead is '%s'", | ||
| 2688 | buf_ptr(&actual_return_type->name))); | ||
| 2689 | } | ||
| 2690 | } else if ((import->package == g->panic_package || g->have_pub_panic) && | 2716 | } else if ((import->package == g->panic_package || g->have_pub_panic) && |
| 2691 | buf_eql_str(&fn_table_entry->symbol_name, "panic")) | 2717 | buf_eql_str(&fn_table_entry->symbol_name, "panic")) |
| 2692 | { | 2718 | { |
| ... | @@ -5527,3 +5553,13 @@ bool type_ptr_eql(const TypeTableEntry *a, const TypeTableEntry *b) { | ... | @@ -5527,3 +5553,13 @@ bool type_ptr_eql(const TypeTableEntry *a, const TypeTableEntry *b) { |
| 5527 | return a == b; | 5553 | return a == b; |
| 5528 | } | 5554 | } |
| 5529 | 5555 | ||
| 5556 | ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) { | ||
| 5557 | Tld *tld = codegen->compile_var_import->decls_scope->decl_table.get(buf_create_from_str(name)); | ||
| 5558 | resolve_top_level_decl(codegen, tld, false, nullptr); | ||
| 5559 | assert(tld->id == TldIdVar); | ||
| 5560 | TldVar *tld_var = (TldVar *)tld; | ||
| 5561 | ConstExprValue *var_value = tld_var->var->value; | ||
| 5562 | assert(var_value != nullptr); | ||
| 5563 | return var_value; | ||
| 5564 | } | ||
| 5565 |
src/analyze.hpp+5| ... | @@ -185,4 +185,9 @@ PackageTableEntry *new_anonymous_package(void); | ... | @@ -185,4 +185,9 @@ PackageTableEntry *new_anonymous_package(void); |
| 185 | Buf *const_value_to_buffer(ConstExprValue *const_val); | 185 | Buf *const_value_to_buffer(ConstExprValue *const_val); |
| 186 | void add_fn_export(CodeGen *g, FnTableEntry *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc); | 186 | void add_fn_export(CodeGen *g, FnTableEntry *fn_table_entry, Buf *symbol_name, GlobalLinkageId linkage, bool ccc); |
| 187 | 187 | ||
| 188 | |||
| 189 | ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name); | ||
| 190 | TypeTableEntry *get_ptr_to_stack_trace_type(CodeGen *g); | ||
| 191 | |||
| 192 | |||
| 188 | #endif | 193 | #endif |
src/codegen.cpp+231-16| ... | @@ -404,6 +404,19 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { | ... | @@ -404,6 +404,19 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) { |
| 404 | zig_unreachable(); | 404 | zig_unreachable(); |
| 405 | } | 405 | } |
| 406 | 406 | ||
| 407 | static uint32_t get_err_ret_trace_arg_index(CodeGen *g, FnTableEntry *fn_table_entry) { | ||
| 408 | if (!g->have_err_ret_tracing) { | ||
| 409 | return UINT32_MAX; | ||
| 410 | } | ||
| 411 | TypeTableEntry *fn_type = fn_table_entry->type_entry; | ||
| 412 | TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type; | ||
| 413 | if (return_type->id != TypeTableEntryIdErrorUnion && return_type->id != TypeTableEntryIdPureError) { | ||
| 414 | return UINT32_MAX; | ||
| 415 | } | ||
| 416 | bool first_arg_ret = type_has_bits(return_type) && handle_is_ptr(return_type); | ||
| 417 | return first_arg_ret ? 1 : 0; | ||
| 418 | } | ||
| 419 | |||
| 407 | static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { | 420 | static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 408 | if (fn_table_entry->llvm_value) | 421 | if (fn_table_entry->llvm_value) |
| 409 | return fn_table_entry->llvm_value; | 422 | return fn_table_entry->llvm_value; |
| ... | @@ -483,7 +496,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { | ... | @@ -483,7 +496,8 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 483 | LLVMSetUnnamedAddr(fn_table_entry->llvm_value, true); | 496 | LLVMSetUnnamedAddr(fn_table_entry->llvm_value, true); |
| 484 | } | 497 | } |
| 485 | 498 | ||
| 486 | if (fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdUnreachable) { | 499 | TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type; |
| 500 | if (return_type->id == TypeTableEntryIdUnreachable) { | ||
| 487 | addLLVMFnAttr(fn_table_entry->llvm_value, "noreturn"); | 501 | addLLVMFnAttr(fn_table_entry->llvm_value, "noreturn"); |
| 488 | } | 502 | } |
| 489 | 503 | ||
| ... | @@ -520,13 +534,11 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { | ... | @@ -520,13 +534,11 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 520 | // use the ABI alignment, which is fine. | 534 | // use the ABI alignment, which is fine. |
| 521 | } | 535 | } |
| 522 | 536 | ||
| 523 | if (!type_has_bits(fn_type->data.fn.fn_type_id.return_type)) { | 537 | if (!type_has_bits(return_type)) { |
| 524 | // nothing to do | 538 | // nothing to do |
| 525 | } else if (fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdPointer || | 539 | } else if (return_type->id == TypeTableEntryIdPointer || return_type->id == TypeTableEntryIdFn) { |
| 526 | fn_type->data.fn.fn_type_id.return_type->id == TypeTableEntryIdFn) | ||
| 527 | { | ||
| 528 | addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull"); | 540 | addLLVMAttr(fn_table_entry->llvm_value, 0, "nonnull"); |
| 529 | } else if (handle_is_ptr(fn_type->data.fn.fn_type_id.return_type) && | 541 | } else if (handle_is_ptr(return_type) && |
| 530 | calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc)) | 542 | calling_convention_does_first_arg_return(fn_type->data.fn.fn_type_id.cc)) |
| 531 | { | 543 | { |
| 532 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret"); | 544 | addLLVMArgAttr(fn_table_entry->llvm_value, 0, "sret"); |
| ... | @@ -563,6 +575,11 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { | ... | @@ -563,6 +575,11 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) { |
| 563 | } | 575 | } |
| 564 | } | 576 | } |
| 565 | 577 | ||
| 578 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry); | ||
| 579 | if (err_ret_trace_arg_index != UINT32_MAX) { | ||
| 580 | addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull"); | ||
| 581 | } | ||
| 582 | |||
| 566 | return fn_table_entry->llvm_value; | 583 | return fn_table_entry->llvm_value; |
| 567 | } | 584 | } |
| 568 | 585 | ||
| ... | @@ -864,16 +881,25 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) { | ... | @@ -864,16 +881,25 @@ static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) { |
| 864 | return LLVMConstBitCast(val->global_refs->llvm_global, LLVMPointerType(str_type->type_ref, 0)); | 881 | return LLVMConstBitCast(val->global_refs->llvm_global, LLVMPointerType(str_type->type_ref, 0)); |
| 865 | } | 882 | } |
| 866 | 883 | ||
| 867 | static void gen_panic(CodeGen *g, LLVMValueRef msg_arg) { | 884 | static void gen_panic(CodeGen *g, LLVMValueRef msg_arg, LLVMValueRef stack_trace_arg) { |
| 868 | assert(g->panic_fn != nullptr); | 885 | assert(g->panic_fn != nullptr); |
| 869 | LLVMValueRef fn_val = fn_llvm_value(g, g->panic_fn); | 886 | LLVMValueRef fn_val = fn_llvm_value(g, g->panic_fn); |
| 870 | LLVMCallConv llvm_cc = get_llvm_cc(g, g->panic_fn->type_entry->data.fn.fn_type_id.cc); | 887 | LLVMCallConv llvm_cc = get_llvm_cc(g, g->panic_fn->type_entry->data.fn.fn_type_id.cc); |
| 871 | ZigLLVMBuildCall(g->builder, fn_val, &msg_arg, 1, llvm_cc, ZigLLVM_FnInlineAuto, ""); | 888 | if (stack_trace_arg == nullptr) { |
| 889 | TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g); | ||
| 890 | stack_trace_arg = LLVMConstNull(ptr_to_stack_trace_type->type_ref); | ||
| 891 | } | ||
| 892 | LLVMValueRef args[] = { | ||
| 893 | msg_arg, | ||
| 894 | stack_trace_arg, | ||
| 895 | }; | ||
| 896 | LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, fn_val, args, 2, llvm_cc, ZigLLVM_FnInlineAuto, ""); | ||
| 897 | LLVMSetTailCall(call_instruction, true); | ||
| 872 | LLVMBuildUnreachable(g->builder); | 898 | LLVMBuildUnreachable(g->builder); |
| 873 | } | 899 | } |
| 874 | 900 | ||
| 875 | static void gen_debug_safety_crash(CodeGen *g, PanicMsgId msg_id) { | 901 | static void gen_debug_safety_crash(CodeGen *g, PanicMsgId msg_id) { |
| 876 | gen_panic(g, get_panic_msg_ptr_val(g, msg_id)); | 902 | gen_panic(g, get_panic_msg_ptr_val(g, msg_id), nullptr); |
| 877 | } | 903 | } |
| 878 | 904 | ||
| 879 | static LLVMValueRef get_memcpy_fn_val(CodeGen *g) { | 905 | static LLVMValueRef get_memcpy_fn_val(CodeGen *g) { |
| ... | @@ -895,6 +921,87 @@ static LLVMValueRef get_memcpy_fn_val(CodeGen *g) { | ... | @@ -895,6 +921,87 @@ static LLVMValueRef get_memcpy_fn_val(CodeGen *g) { |
| 895 | return g->memcpy_fn_val; | 921 | return g->memcpy_fn_val; |
| 896 | } | 922 | } |
| 897 | 923 | ||
| 924 | static LLVMValueRef get_return_err_fn(CodeGen *g) { | ||
| 925 | if (g->return_err_fn != nullptr) | ||
| 926 | return g->return_err_fn; | ||
| 927 | |||
| 928 | assert(g->err_tag_type != nullptr); | ||
| 929 | |||
| 930 | LLVMTypeRef ptr_u8 = LLVMPointerType(LLVMInt8Type(), 0); | ||
| 931 | |||
| 932 | LLVMTypeRef arg_types[] = { | ||
| 933 | // error return trace pointer | ||
| 934 | get_ptr_to_stack_trace_type(g)->type_ref, | ||
| 935 | // return address | ||
| 936 | ptr_u8, | ||
| 937 | }; | ||
| 938 | LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false); | ||
| 939 | |||
| 940 | Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_return_error"), false); | ||
| 941 | LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); | ||
| 942 | addLLVMFnAttr(fn_val, "cold"); | ||
| 943 | LLVMSetLinkage(fn_val, LLVMInternalLinkage); | ||
| 944 | LLVMSetFunctionCallConv(fn_val, get_llvm_cc(g, CallingConventionUnspecified)); | ||
| 945 | addLLVMFnAttr(fn_val, "nounwind"); | ||
| 946 | add_uwtable_attr(g, fn_val); | ||
| 947 | addLLVMArgAttr(fn_val, (unsigned)0, "nonnull"); | ||
| 948 | addLLVMArgAttr(fn_val, (unsigned)1, "nonnull"); | ||
| 949 | if (g->build_mode == BuildModeDebug) { | ||
| 950 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true"); | ||
| 951 | ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim-non-leaf", nullptr); | ||
| 952 | } | ||
| 953 | |||
| 954 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry"); | ||
| 955 | LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder); | ||
| 956 | LLVMValueRef prev_debug_location = LLVMGetCurrentDebugLocation(g->builder); | ||
| 957 | LLVMPositionBuilderAtEnd(g->builder, entry_block); | ||
| 958 | ZigLLVMClearCurrentDebugLocation(g->builder); | ||
| 959 | |||
| 960 | LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->type_ref; | ||
| 961 | |||
| 962 | // stack_trace.instruction_addresses[stack_trace.index % stack_trace.instruction_addresses.len] = return_address; | ||
| 963 | |||
| 964 | LLVMValueRef err_ret_trace_ptr = LLVMGetParam(fn_val, 0); | ||
| 965 | size_t index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index; | ||
| 966 | LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, err_ret_trace_ptr, (unsigned)index_field_index, ""); | ||
| 967 | size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index; | ||
| 968 | LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, err_ret_trace_ptr, (unsigned)addresses_field_index, ""); | ||
| 969 | |||
| 970 | TypeTableEntry *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry; | ||
| 971 | size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index; | ||
| 972 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)ptr_field_index, ""); | ||
| 973 | size_t len_field_index = slice_type->data.structure.fields[slice_len_index].gen_index; | ||
| 974 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)len_field_index, ""); | ||
| 975 | |||
| 976 | LLVMValueRef len_value = gen_load_untyped(g, len_field_ptr, 0, false, ""); | ||
| 977 | LLVMValueRef index_val = gen_load_untyped(g, index_field_ptr, 0, false, ""); | ||
| 978 | LLVMValueRef modded_val = LLVMBuildURem(g->builder, index_val, len_value, ""); | ||
| 979 | LLVMValueRef address_indices[] = { | ||
| 980 | modded_val, | ||
| 981 | }; | ||
| 982 | |||
| 983 | LLVMValueRef ptr_value = gen_load_untyped(g, ptr_field_ptr, 0, false, ""); | ||
| 984 | LLVMValueRef address_slot = LLVMBuildInBoundsGEP(g->builder, ptr_value, address_indices, 1, ""); | ||
| 985 | |||
| 986 | LLVMValueRef return_address = LLVMBuildPtrToInt(g->builder, LLVMGetParam(fn_val, 1), usize_type_ref, ""); | ||
| 987 | |||
| 988 | LLVMValueRef address_value = LLVMBuildPtrToInt(g->builder, return_address, usize_type_ref, ""); | ||
| 989 | gen_store_untyped(g, address_value, address_slot, 0, false); | ||
| 990 | |||
| 991 | // stack_trace.index += 1; | ||
| 992 | LLVMValueRef index_plus_one_val = LLVMBuildAdd(g->builder, index_val, LLVMConstInt(usize_type_ref, 1, false), ""); | ||
| 993 | gen_store_untyped(g, index_plus_one_val, index_field_ptr, 0, false); | ||
| 994 | |||
| 995 | // return; | ||
| 996 | LLVMBuildRetVoid(g->builder); | ||
| 997 | |||
| 998 | LLVMPositionBuilderAtEnd(g->builder, prev_block); | ||
| 999 | LLVMSetCurrentDebugLocation(g->builder, prev_debug_location); | ||
| 1000 | |||
| 1001 | g->return_err_fn = fn_val; | ||
| 1002 | return fn_val; | ||
| 1003 | } | ||
| 1004 | |||
| 898 | static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { | 1005 | static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 899 | if (g->safety_crash_err_fn != nullptr) | 1006 | if (g->safety_crash_err_fn != nullptr) |
| 900 | return g->safety_crash_err_fn; | 1007 | return g->safety_crash_err_fn; |
| ... | @@ -953,7 +1060,11 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { | ... | @@ -953,7 +1060,11 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 953 | LLVMValueRef offset_buf_ptr = LLVMConstInBoundsGEP(global_array, offset_ptr_indices, 2); | 1060 | LLVMValueRef offset_buf_ptr = LLVMConstInBoundsGEP(global_array, offset_ptr_indices, 2); |
| 954 | 1061 | ||
| 955 | Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_fail_unwrap"), false); | 1062 | Buf *fn_name = get_mangled_name(g, buf_create_from_str("__zig_fail_unwrap"), false); |
| 956 | LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), &g->err_tag_type->type_ref, 1, false); | 1063 | LLVMTypeRef arg_types[] = { |
| 1064 | g->ptr_to_stack_trace_type->type_ref, | ||
| 1065 | g->err_tag_type->type_ref, | ||
| 1066 | }; | ||
| 1067 | LLVMTypeRef fn_type_ref = LLVMFunctionType(LLVMVoidType(), arg_types, 2, false); | ||
| 957 | LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); | 1068 | LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); |
| 958 | addLLVMFnAttr(fn_val, "noreturn"); | 1069 | addLLVMFnAttr(fn_val, "noreturn"); |
| 959 | addLLVMFnAttr(fn_val, "cold"); | 1070 | addLLVMFnAttr(fn_val, "cold"); |
| ... | @@ -975,7 +1086,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { | ... | @@ -975,7 +1086,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 975 | LLVMPositionBuilderAtEnd(g->builder, entry_block); | 1086 | LLVMPositionBuilderAtEnd(g->builder, entry_block); |
| 976 | ZigLLVMClearCurrentDebugLocation(g->builder); | 1087 | ZigLLVMClearCurrentDebugLocation(g->builder); |
| 977 | 1088 | ||
| 978 | LLVMValueRef err_val = LLVMGetParam(fn_val, 0); | 1089 | LLVMValueRef err_val = LLVMGetParam(fn_val, 1); |
| 979 | 1090 | ||
| 980 | LLVMValueRef err_table_indices[] = { | 1091 | LLVMValueRef err_table_indices[] = { |
| 981 | LLVMConstNull(g->builtin_types.entry_usize->type_ref), | 1092 | LLVMConstNull(g->builtin_types.entry_usize->type_ref), |
| ... | @@ -1005,7 +1116,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { | ... | @@ -1005,7 +1116,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 1005 | LLVMValueRef global_slice_len_field_ptr = LLVMBuildStructGEP(g->builder, global_slice, slice_len_index, ""); | 1116 | LLVMValueRef global_slice_len_field_ptr = LLVMBuildStructGEP(g->builder, global_slice, slice_len_index, ""); |
| 1006 | gen_store(g, full_buf_len, global_slice_len_field_ptr, u8_ptr_type); | 1117 | gen_store(g, full_buf_len, global_slice_len_field_ptr, u8_ptr_type); |
| 1007 | 1118 | ||
| 1008 | gen_panic(g, global_slice); | 1119 | gen_panic(g, global_slice, LLVMGetParam(fn_val, 0)); |
| 1009 | 1120 | ||
| 1010 | LLVMPositionBuilderAtEnd(g->builder, prev_block); | 1121 | LLVMPositionBuilderAtEnd(g->builder, prev_block); |
| 1011 | LLVMSetCurrentDebugLocation(g->builder, prev_debug_location); | 1122 | LLVMSetCurrentDebugLocation(g->builder, prev_debug_location); |
| ... | @@ -1016,8 +1127,18 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { | ... | @@ -1016,8 +1127,18 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 1016 | 1127 | ||
| 1017 | static void gen_debug_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val) { | 1128 | static void gen_debug_safety_crash_for_err(CodeGen *g, LLVMValueRef err_val) { |
| 1018 | LLVMValueRef safety_crash_err_fn = get_safety_crash_err_fn(g); | 1129 | LLVMValueRef safety_crash_err_fn = get_safety_crash_err_fn(g); |
| 1019 | ZigLLVMBuildCall(g->builder, safety_crash_err_fn, &err_val, 1, get_llvm_cc(g, CallingConventionUnspecified), | 1130 | LLVMValueRef err_ret_trace_val = g->cur_err_ret_trace_val; |
| 1131 | if (err_ret_trace_val == nullptr) { | ||
| 1132 | TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g); | ||
| 1133 | err_ret_trace_val = LLVMConstNull(ptr_to_stack_trace_type->type_ref); | ||
| 1134 | } | ||
| 1135 | LLVMValueRef args[] = { | ||
| 1136 | err_ret_trace_val, | ||
| 1137 | err_val, | ||
| 1138 | }; | ||
| 1139 | LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, safety_crash_err_fn, args, 2, get_llvm_cc(g, CallingConventionUnspecified), | ||
| 1020 | ZigLLVM_FnInlineAuto, ""); | 1140 | ZigLLVM_FnInlineAuto, ""); |
| 1141 | LLVMSetTailCall(call_instruction, true); | ||
| 1021 | LLVMBuildUnreachable(g->builder); | 1142 | LLVMBuildUnreachable(g->builder); |
| 1022 | } | 1143 | } |
| 1023 | 1144 | ||
| ... | @@ -1296,6 +1417,35 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) { | ... | @@ -1296,6 +1417,35 @@ static LLVMValueRef ir_llvm_value(CodeGen *g, IrInstruction *instruction) { |
| 1296 | static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) { | 1417 | static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrInstructionReturn *return_instruction) { |
| 1297 | LLVMValueRef value = ir_llvm_value(g, return_instruction->value); | 1418 | LLVMValueRef value = ir_llvm_value(g, return_instruction->value); |
| 1298 | TypeTableEntry *return_type = return_instruction->value->value.type; | 1419 | TypeTableEntry *return_type = return_instruction->value->value.type; |
| 1420 | |||
| 1421 | if (g->have_err_ret_tracing) { | ||
| 1422 | bool is_err_return = false; | ||
| 1423 | if (return_type->id == TypeTableEntryIdErrorUnion) { | ||
| 1424 | if (return_instruction->value->value.special == ConstValSpecialStatic) { | ||
| 1425 | is_err_return = return_instruction->value->value.data.x_err_union.err != nullptr; | ||
| 1426 | } else if (return_instruction->value->value.special == ConstValSpecialRuntime) { | ||
| 1427 | is_err_return = return_instruction->value->value.data.rh_error_union == RuntimeHintErrorUnionError; | ||
| 1428 | // TODO: emit a branch to check if the return value is an error | ||
| 1429 | } | ||
| 1430 | } else if (return_type->id == TypeTableEntryIdPureError) { | ||
| 1431 | is_err_return = true; | ||
| 1432 | } | ||
| 1433 | if (is_err_return) { | ||
| 1434 | LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn_val, "ReturnError"); | ||
| 1435 | LLVMValueRef block_address = LLVMBlockAddress(g->cur_fn_val, return_block); | ||
| 1436 | |||
| 1437 | LLVMValueRef return_err_fn = get_return_err_fn(g); | ||
| 1438 | LLVMValueRef args[] = { | ||
| 1439 | g->cur_err_ret_trace_val, | ||
| 1440 | block_address, | ||
| 1441 | }; | ||
| 1442 | LLVMBuildBr(g->builder, return_block); | ||
| 1443 | LLVMPositionBuilderAtEnd(g->builder, return_block); | ||
| 1444 | LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 2, | ||
| 1445 | get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, ""); | ||
| 1446 | LLVMSetTailCall(call_instruction, true); | ||
| 1447 | } | ||
| 1448 | } | ||
| 1299 | if (handle_is_ptr(return_type)) { | 1449 | if (handle_is_ptr(return_type)) { |
| 1300 | if (calling_convention_does_first_arg_return(g->cur_fn->type_entry->data.fn.fn_type_id.cc)) { | 1450 | if (calling_convention_does_first_arg_return(g->cur_fn->type_entry->data.fn.fn_type_id.cc)) { |
| 1301 | assert(g->cur_ret_ptr); | 1451 | assert(g->cur_ret_ptr); |
| ... | @@ -2330,7 +2480,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -2330,7 +2480,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 2330 | TypeTableEntry *src_return_type = fn_type_id->return_type; | 2480 | TypeTableEntry *src_return_type = fn_type_id->return_type; |
| 2331 | bool ret_has_bits = type_has_bits(src_return_type); | 2481 | bool ret_has_bits = type_has_bits(src_return_type); |
| 2332 | bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type); | 2482 | bool first_arg_ret = ret_has_bits && handle_is_ptr(src_return_type); |
| 2333 | size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0); | 2483 | bool prefix_arg_err_ret_stack = g->have_err_ret_tracing && (src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdPureError); |
| 2484 | size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0); | ||
| 2334 | bool is_var_args = fn_type_id->is_var_args; | 2485 | bool is_var_args = fn_type_id->is_var_args; |
| 2335 | LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count); | 2486 | LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count); |
| 2336 | size_t gen_param_index = 0; | 2487 | size_t gen_param_index = 0; |
| ... | @@ -2338,6 +2489,10 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr | ... | @@ -2338,6 +2489,10 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr |
| 2338 | gen_param_values[gen_param_index] = instruction->tmp_ptr; | 2489 | gen_param_values[gen_param_index] = instruction->tmp_ptr; |
| 2339 | gen_param_index += 1; | 2490 | gen_param_index += 1; |
| 2340 | } | 2491 | } |
| 2492 | if (prefix_arg_err_ret_stack) { | ||
| 2493 | gen_param_values[gen_param_index] = g->cur_err_ret_trace_val; | ||
| 2494 | gen_param_index += 1; | ||
| 2495 | } | ||
| 2341 | for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) { | 2496 | for (size_t call_i = 0; call_i < instruction->arg_count; call_i += 1) { |
| 2342 | IrInstruction *param_instruction = instruction->args[call_i]; | 2497 | IrInstruction *param_instruction = instruction->args[call_i]; |
| 2343 | TypeTableEntry *param_type = param_instruction->value.type; | 2498 | TypeTableEntry *param_type = param_instruction->value.type; |
| ... | @@ -2881,6 +3036,16 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I | ... | @@ -2881,6 +3036,16 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I |
| 2881 | return target_val; | 3036 | return target_val; |
| 2882 | } | 3037 | } |
| 2883 | 3038 | ||
| 3039 | static LLVMValueRef ir_render_error_return_trace(CodeGen *g, IrExecutable *executable, | ||
| 3040 | IrInstructionErrorReturnTrace *instruction) | ||
| 3041 | { | ||
| 3042 | TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(g); | ||
| 3043 | if (g->cur_err_ret_trace_val == nullptr) { | ||
| 3044 | return LLVMConstNull(ptr_to_stack_trace_type->type_ref); | ||
| 3045 | } | ||
| 3046 | return g->cur_err_ret_trace_val; | ||
| 3047 | } | ||
| 3048 | |||
| 2884 | static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) { | 3049 | static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) { |
| 2885 | switch (atomic_order) { | 3050 | switch (atomic_order) { |
| 2886 | case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered; | 3051 | case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered; |
| ... | @@ -3474,7 +3639,7 @@ static LLVMValueRef ir_render_container_init_list(CodeGen *g, IrExecutable *exec | ... | @@ -3474,7 +3639,7 @@ static LLVMValueRef ir_render_container_init_list(CodeGen *g, IrExecutable *exec |
| 3474 | } | 3639 | } |
| 3475 | 3640 | ||
| 3476 | static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInstructionPanic *instruction) { | 3641 | static LLVMValueRef ir_render_panic(CodeGen *g, IrExecutable *executable, IrInstructionPanic *instruction) { |
| 3477 | gen_panic(g, ir_llvm_value(g, instruction->msg)); | 3642 | gen_panic(g, ir_llvm_value(g, instruction->msg), nullptr); |
| 3478 | return nullptr; | 3643 | return nullptr; |
| 3479 | } | 3644 | } |
| 3480 | 3645 | ||
| ... | @@ -3654,6 +3819,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, | ... | @@ -3654,6 +3819,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, |
| 3654 | return ir_render_field_parent_ptr(g, executable, (IrInstructionFieldParentPtr *)instruction); | 3819 | return ir_render_field_parent_ptr(g, executable, (IrInstructionFieldParentPtr *)instruction); |
| 3655 | case IrInstructionIdAlignCast: | 3820 | case IrInstructionIdAlignCast: |
| 3656 | return ir_render_align_cast(g, executable, (IrInstructionAlignCast *)instruction); | 3821 | return ir_render_align_cast(g, executable, (IrInstructionAlignCast *)instruction); |
| 3822 | case IrInstructionIdErrorReturnTrace: | ||
| 3823 | return ir_render_error_return_trace(g, executable, (IrInstructionErrorReturnTrace *)instruction); | ||
| 3657 | } | 3824 | } |
| 3658 | zig_unreachable(); | 3825 | zig_unreachable(); |
| 3659 | } | 3826 | } |
| ... | @@ -4493,7 +4660,8 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -4493,7 +4660,8 @@ static void do_code_gen(CodeGen *g) { |
| 4493 | LLVMValueRef fn = fn_llvm_value(g, fn_table_entry); | 4660 | LLVMValueRef fn = fn_llvm_value(g, fn_table_entry); |
| 4494 | g->cur_fn = fn_table_entry; | 4661 | g->cur_fn = fn_table_entry; |
| 4495 | g->cur_fn_val = fn; | 4662 | g->cur_fn_val = fn; |
| 4496 | if (handle_is_ptr(fn_table_entry->type_entry->data.fn.fn_type_id.return_type)) { | 4663 | TypeTableEntry *return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type; |
| 4664 | if (handle_is_ptr(return_type)) { | ||
| 4497 | g->cur_ret_ptr = LLVMGetParam(fn, 0); | 4665 | g->cur_ret_ptr = LLVMGetParam(fn, 0); |
| 4498 | } else { | 4666 | } else { |
| 4499 | g->cur_ret_ptr = nullptr; | 4667 | g->cur_ret_ptr = nullptr; |
| ... | @@ -4502,6 +4670,42 @@ static void do_code_gen(CodeGen *g) { | ... | @@ -4502,6 +4670,42 @@ static void do_code_gen(CodeGen *g) { |
| 4502 | build_all_basic_blocks(g, fn_table_entry); | 4670 | build_all_basic_blocks(g, fn_table_entry); |
| 4503 | clear_debug_source_node(g); | 4671 | clear_debug_source_node(g); |
| 4504 | 4672 | ||
| 4673 | uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry); | ||
| 4674 | if (err_ret_trace_arg_index != UINT32_MAX) { | ||
| 4675 | g->cur_err_ret_trace_val = LLVMGetParam(fn, err_ret_trace_arg_index); | ||
| 4676 | } else if (g->have_err_ret_tracing && fn_table_entry->calls_errorable_function) { | ||
| 4677 | // TODO call graph analysis to find out what this number needs to be for every function | ||
| 4678 | static const size_t stack_trace_ptr_count = 30; | ||
| 4679 | |||
| 4680 | TypeTableEntry *usize = g->builtin_types.entry_usize; | ||
| 4681 | TypeTableEntry *array_type = get_array_type(g, usize, stack_trace_ptr_count); | ||
| 4682 | LLVMValueRef err_ret_array_val = build_alloca(g, array_type, "error_return_trace_addresses", | ||
| 4683 | get_abi_alignment(g, array_type)); | ||
| 4684 | g->cur_err_ret_trace_val = build_alloca(g, g->stack_trace_type, "error_return_trace", get_abi_alignment(g, g->stack_trace_type)); | ||
| 4685 | size_t index_field_index = g->stack_trace_type->data.structure.fields[0].gen_index; | ||
| 4686 | LLVMValueRef index_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val, (unsigned)index_field_index, ""); | ||
| 4687 | gen_store_untyped(g, LLVMConstNull(usize->type_ref), index_field_ptr, 0, false); | ||
| 4688 | |||
| 4689 | size_t addresses_field_index = g->stack_trace_type->data.structure.fields[1].gen_index; | ||
| 4690 | LLVMValueRef addresses_field_ptr = LLVMBuildStructGEP(g->builder, g->cur_err_ret_trace_val, (unsigned)addresses_field_index, ""); | ||
| 4691 | |||
| 4692 | TypeTableEntry *slice_type = g->stack_trace_type->data.structure.fields[1].type_entry; | ||
| 4693 | size_t ptr_field_index = slice_type->data.structure.fields[slice_ptr_index].gen_index; | ||
| 4694 | LLVMValueRef ptr_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)ptr_field_index, ""); | ||
| 4695 | LLVMValueRef zero = LLVMConstNull(usize->type_ref); | ||
| 4696 | LLVMValueRef indices[] = {zero, zero}; | ||
| 4697 | LLVMValueRef err_ret_array_val_elem0_ptr = LLVMBuildInBoundsGEP(g->builder, err_ret_array_val, | ||
| 4698 | indices, 2, ""); | ||
| 4699 | gen_store(g, err_ret_array_val_elem0_ptr, ptr_field_ptr, | ||
| 4700 | get_pointer_to_type(g, get_pointer_to_type(g, usize, false), false)); | ||
| 4701 | |||
| 4702 | size_t len_field_index = slice_type->data.structure.fields[slice_len_index].gen_index; | ||
| 4703 | LLVMValueRef len_field_ptr = LLVMBuildStructGEP(g->builder, addresses_field_ptr, (unsigned)len_field_index, ""); | ||
| 4704 | gen_store(g, LLVMConstInt(usize->type_ref, stack_trace_ptr_count, false), len_field_ptr, get_pointer_to_type(g, usize, false)); | ||
| 4705 | } else { | ||
| 4706 | g->cur_err_ret_trace_val = nullptr; | ||
| 4707 | } | ||
| 4708 | |||
| 4505 | // allocate temporary stack data | 4709 | // allocate temporary stack data |
| 4506 | for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_list.length; alloca_i += 1) { | 4710 | for (size_t alloca_i = 0; alloca_i < fn_table_entry->alloca_list.length; alloca_i += 1) { |
| 4507 | IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i); | 4711 | IrInstruction *instruction = fn_table_entry->alloca_list.at(alloca_i); |
| ... | @@ -5064,6 +5268,7 @@ static void define_builtin_fns(CodeGen *g) { | ... | @@ -5064,6 +5268,7 @@ static void define_builtin_fns(CodeGen *g) { |
| 5064 | create_builtin_fn(g, BuiltinFnIdSetAlignStack, "setAlignStack", 1); | 5268 | create_builtin_fn(g, BuiltinFnIdSetAlignStack, "setAlignStack", 1); |
| 5065 | create_builtin_fn(g, BuiltinFnIdArgType, "ArgType", 2); | 5269 | create_builtin_fn(g, BuiltinFnIdArgType, "ArgType", 2); |
| 5066 | create_builtin_fn(g, BuiltinFnIdExport, "export", 3); | 5270 | create_builtin_fn(g, BuiltinFnIdExport, "export", 3); |
| 5271 | create_builtin_fn(g, BuiltinFnIdErrorReturnTrace, "errorReturnTrace", 0); | ||
| 5067 | } | 5272 | } |
| 5068 | 5273 | ||
| 5069 | static const char *bool_to_str(bool b) { | 5274 | static const char *bool_to_str(bool b) { |
| ... | @@ -5088,6 +5293,12 @@ static void define_builtin_compile_vars(CodeGen *g) { | ... | @@ -5088,6 +5293,12 @@ static void define_builtin_compile_vars(CodeGen *g) { |
| 5088 | os_path_join(g->cache_dir, buf_create_from_str(builtin_zig_basename), builtin_zig_path); | 5293 | os_path_join(g->cache_dir, buf_create_from_str(builtin_zig_basename), builtin_zig_path); |
| 5089 | Buf *contents = buf_alloc(); | 5294 | Buf *contents = buf_alloc(); |
| 5090 | 5295 | ||
| 5296 | buf_append_str(contents, | ||
| 5297 | "pub const StackTrace = struct {\n" | ||
| 5298 | " index: usize,\n" | ||
| 5299 | " instruction_addresses: []usize,\n" | ||
| 5300 | "};\n\n"); | ||
| 5301 | |||
| 5091 | const char *cur_os = nullptr; | 5302 | const char *cur_os = nullptr; |
| 5092 | { | 5303 | { |
| 5093 | buf_appendf(contents, "pub const Os = enum {\n"); | 5304 | buf_appendf(contents, "pub const Os = enum {\n"); |
| ... | @@ -5233,6 +5444,7 @@ static void define_builtin_compile_vars(CodeGen *g) { | ... | @@ -5233,6 +5444,7 @@ static void define_builtin_compile_vars(CodeGen *g) { |
| 5233 | buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt); | 5444 | buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt); |
| 5234 | buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode)); | 5445 | buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode)); |
| 5235 | buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->libc_link_lib != nullptr)); | 5446 | buf_appendf(contents, "pub const link_libc = %s;\n", bool_to_str(g->libc_link_lib != nullptr)); |
| 5447 | buf_appendf(contents, "pub const have_error_return_tracing = %s;\n", bool_to_str(g->have_err_ret_tracing)); | ||
| 5236 | 5448 | ||
| 5237 | buf_appendf(contents, "pub const __zig_test_fn_slice = {}; // overwritten later\n"); | 5449 | buf_appendf(contents, "pub const __zig_test_fn_slice = {}; // overwritten later\n"); |
| 5238 | 5450 | ||
| ... | @@ -5251,6 +5463,7 @@ static void define_builtin_compile_vars(CodeGen *g) { | ... | @@ -5251,6 +5463,7 @@ static void define_builtin_compile_vars(CodeGen *g) { |
| 5251 | g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); | 5463 | g->root_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); |
| 5252 | g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); | 5464 | g->std_package->package_table.put(buf_create_from_str("builtin"), g->compile_var_package); |
| 5253 | g->compile_var_import = add_source_file(g, g->compile_var_package, abs_full_path, contents); | 5465 | g->compile_var_import = add_source_file(g, g->compile_var_package, abs_full_path, contents); |
| 5466 | scan_import(g, g->compile_var_import); | ||
| 5254 | } | 5467 | } |
| 5255 | 5468 | ||
| 5256 | static void init(CodeGen *g) { | 5469 | static void init(CodeGen *g) { |
| ... | @@ -5359,6 +5572,8 @@ static void init(CodeGen *g) { | ... | @@ -5359,6 +5572,8 @@ static void init(CodeGen *g) { |
| 5359 | } | 5572 | } |
| 5360 | } | 5573 | } |
| 5361 | 5574 | ||
| 5575 | g->have_err_ret_tracing = g->build_mode != BuildModeFastRelease; | ||
| 5576 | |||
| 5362 | define_builtin_fns(g); | 5577 | define_builtin_fns(g); |
| 5363 | define_builtin_compile_vars(g); | 5578 | define_builtin_compile_vars(g); |
| 5364 | } | 5579 | } |
src/ir.cpp+49-12| ... | @@ -572,6 +572,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionArgType *) { | ... | @@ -572,6 +572,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionArgType *) { |
| 572 | return IrInstructionIdArgType; | 572 | return IrInstructionIdArgType; |
| 573 | } | 573 | } |
| 574 | 574 | ||
| 575 | static constexpr IrInstructionId ir_instruction_id(IrInstructionErrorReturnTrace *) { | ||
| 576 | return IrInstructionIdErrorReturnTrace; | ||
| 577 | } | ||
| 578 | |||
| 575 | template<typename T> | 579 | template<typename T> |
| 576 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { | 580 | static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) { |
| 577 | T *special_instruction = allocate<T>(1); | 581 | T *special_instruction = allocate<T>(1); |
| ... | @@ -2305,6 +2309,12 @@ static IrInstruction *ir_build_arg_type(IrBuilder *irb, Scope *scope, AstNode *s | ... | @@ -2305,6 +2309,12 @@ static IrInstruction *ir_build_arg_type(IrBuilder *irb, Scope *scope, AstNode *s |
| 2305 | return &instruction->base; | 2309 | return &instruction->base; |
| 2306 | } | 2310 | } |
| 2307 | 2311 | ||
| 2312 | static IrInstruction *ir_build_error_return_trace(IrBuilder *irb, Scope *scope, AstNode *source_node) { | ||
| 2313 | IrInstructionErrorReturnTrace *instruction = ir_build_instruction<IrInstructionErrorReturnTrace>(irb, scope, source_node); | ||
| 2314 | |||
| 2315 | return &instruction->base; | ||
| 2316 | } | ||
| 2317 | |||
| 2308 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { | 2318 | static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) { |
| 2309 | results[ReturnKindUnconditional] = 0; | 2319 | results[ReturnKindUnconditional] = 0; |
| 2310 | results[ReturnKindError] = 0; | 2320 | results[ReturnKindError] = 0; |
| ... | @@ -3731,6 +3741,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo | ... | @@ -3731,6 +3741,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo |
| 3731 | 3741 | ||
| 3732 | return ir_build_export(irb, scope, node, arg0_value, arg1_value, arg2_value); | 3742 | return ir_build_export(irb, scope, node, arg0_value, arg1_value, arg2_value); |
| 3733 | } | 3743 | } |
| 3744 | case BuiltinFnIdErrorReturnTrace: | ||
| 3745 | { | ||
| 3746 | return ir_build_error_return_trace(irb, scope, node); | ||
| 3747 | } | ||
| 3734 | } | 3748 | } |
| 3735 | zig_unreachable(); | 3749 | zig_unreachable(); |
| 3736 | } | 3750 | } |
| ... | @@ -8230,16 +8244,6 @@ static bool ir_resolve_comptime(IrAnalyze *ira, IrInstruction *value, bool *out) | ... | @@ -8230,16 +8244,6 @@ static bool ir_resolve_comptime(IrAnalyze *ira, IrInstruction *value, bool *out) |
| 8230 | return ir_resolve_bool(ira, value, out); | 8244 | return ir_resolve_bool(ira, value, out); |
| 8231 | } | 8245 | } |
| 8232 | 8246 | ||
| 8233 | static ConstExprValue *get_builtin_value(CodeGen *codegen, const char *name) { | ||
| 8234 | Tld *tld = codegen->compile_var_import->decls_scope->decl_table.get(buf_create_from_str(name)); | ||
| 8235 | resolve_top_level_decl(codegen, tld, false, nullptr); | ||
| 8236 | assert(tld->id == TldIdVar); | ||
| 8237 | TldVar *tld_var = (TldVar *)tld; | ||
| 8238 | ConstExprValue *var_value = tld_var->var->value; | ||
| 8239 | assert(var_value != nullptr); | ||
| 8240 | return var_value; | ||
| 8241 | } | ||
| 8242 | |||
| 8243 | static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, AtomicOrder *out) { | 8247 | static bool ir_resolve_atomic_order(IrAnalyze *ira, IrInstruction *value, AtomicOrder *out) { |
| 8244 | if (type_is_invalid(value->value.type)) | 8248 | if (type_is_invalid(value->value.type)) |
| 8245 | return false; | 8249 | return false; |
| ... | @@ -9578,6 +9582,24 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi | ... | @@ -9578,6 +9582,24 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi |
| 9578 | return ira->codegen->builtin_types.entry_void; | 9582 | return ira->codegen->builtin_types.entry_void; |
| 9579 | } | 9583 | } |
| 9580 | 9584 | ||
| 9585 | static TypeTableEntry *ir_analyze_instruction_error_return_trace(IrAnalyze *ira, | ||
| 9586 | IrInstructionErrorReturnTrace *instruction) | ||
| 9587 | { | ||
| 9588 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); | ||
| 9589 | TypeTableEntry *ptr_to_stack_trace_type = get_ptr_to_stack_trace_type(ira->codegen); | ||
| 9590 | TypeTableEntry *nullable_type = get_maybe_type(ira->codegen, ptr_to_stack_trace_type); | ||
| 9591 | if (fn_entry == nullptr || !fn_entry->calls_errorable_function || !ira->codegen->have_err_ret_tracing) { | ||
| 9592 | ConstExprValue *out_val = ir_build_const_from(ira, &instruction->base); | ||
| 9593 | out_val->data.x_maybe = nullptr; | ||
| 9594 | return nullable_type; | ||
| 9595 | } | ||
| 9596 | |||
| 9597 | IrInstruction *new_instruction = ir_build_error_return_trace(&ira->new_irb, instruction->base.scope, | ||
| 9598 | instruction->base.source_node); | ||
| 9599 | ir_link_new_instruction(new_instruction, &instruction->base); | ||
| 9600 | return nullable_type; | ||
| 9601 | } | ||
| 9602 | |||
| 9581 | static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node, | 9603 | static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node, |
| 9582 | IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i) | 9604 | IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i) |
| 9583 | { | 9605 | { |
| ... | @@ -9836,7 +9858,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -9836,7 +9858,7 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 9836 | 9858 | ||
| 9837 | if (fn_proto_node->data.fn_proto.is_var_args) { | 9859 | if (fn_proto_node->data.fn_proto.is_var_args) { |
| 9838 | ir_add_error(ira, &call_instruction->base, | 9860 | ir_add_error(ira, &call_instruction->base, |
| 9839 | buf_sprintf("compiler bug: unable to call var args function at compile time. https://github.com/andrewrk/zig/issues/313")); | 9861 | buf_sprintf("compiler bug: unable to call var args function at compile time. https://github.com/zig-lang/zig/issues/313")); |
| 9840 | return ira->codegen->builtin_types.entry_invalid; | 9862 | return ira->codegen->builtin_types.entry_invalid; |
| 9841 | } | 9863 | } |
| 9842 | 9864 | ||
| ... | @@ -10053,9 +10075,21 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal | ... | @@ -10053,9 +10075,21 @@ static TypeTableEntry *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCall *cal |
| 10053 | TypeTableEntry *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type; | 10075 | TypeTableEntry *return_type = impl_fn->type_entry->data.fn.fn_type_id.return_type; |
| 10054 | ir_add_alloca(ira, new_call_instruction, return_type); | 10076 | ir_add_alloca(ira, new_call_instruction, return_type); |
| 10055 | 10077 | ||
| 10078 | if (return_type->id == TypeTableEntryIdPureError || return_type->id == TypeTableEntryIdErrorUnion) { | ||
| 10079 | parent_fn_entry->calls_errorable_function = true; | ||
| 10080 | } | ||
| 10081 | |||
| 10056 | return ir_finish_anal(ira, return_type); | 10082 | return ir_finish_anal(ira, return_type); |
| 10057 | } | 10083 | } |
| 10058 | 10084 | ||
| 10085 | FnTableEntry *parent_fn_entry = exec_fn_entry(ira->new_irb.exec); | ||
| 10086 | assert(fn_type_id->return_type != nullptr); | ||
| 10087 | assert(parent_fn_entry != nullptr); | ||
| 10088 | if (fn_type_id->return_type->id == TypeTableEntryIdPureError || fn_type_id->return_type->id == TypeTableEntryIdErrorUnion) { | ||
| 10089 | parent_fn_entry->calls_errorable_function = true; | ||
| 10090 | } | ||
| 10091 | |||
| 10092 | |||
| 10059 | IrInstruction **casted_args = allocate<IrInstruction *>(call_param_count); | 10093 | IrInstruction **casted_args = allocate<IrInstruction *>(call_param_count); |
| 10060 | size_t next_arg_index = 0; | 10094 | size_t next_arg_index = 0; |
| 10061 | if (first_arg_ptr) { | 10095 | if (first_arg_ptr) { |
| ... | @@ -13977,7 +14011,7 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc | ... | @@ -13977,7 +14011,7 @@ static TypeTableEntry *ir_analyze_instruction_align_of(IrAnalyze *ira, IrInstruc |
| 13977 | return ira->codegen->builtin_types.entry_invalid; | 14011 | return ira->codegen->builtin_types.entry_invalid; |
| 13978 | TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); | 14012 | TypeTableEntry *type_entry = ir_resolve_type(ira, type_value); |
| 13979 | 14013 | ||
| 13980 | ensure_complete_type(ira->codegen, type_entry); | 14014 | type_ensure_zero_bits_known(ira->codegen, type_entry); |
| 13981 | if (type_is_invalid(type_entry)) | 14015 | if (type_is_invalid(type_entry)) |
| 13982 | return ira->codegen->builtin_types.entry_invalid; | 14016 | return ira->codegen->builtin_types.entry_invalid; |
| 13983 | 14017 | ||
| ... | @@ -15322,6 +15356,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi | ... | @@ -15322,6 +15356,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi |
| 15322 | return ir_analyze_instruction_tag_type(ira, (IrInstructionTagType *)instruction); | 15356 | return ir_analyze_instruction_tag_type(ira, (IrInstructionTagType *)instruction); |
| 15323 | case IrInstructionIdExport: | 15357 | case IrInstructionIdExport: |
| 15324 | return ir_analyze_instruction_export(ira, (IrInstructionExport *)instruction); | 15358 | return ir_analyze_instruction_export(ira, (IrInstructionExport *)instruction); |
| 15359 | case IrInstructionIdErrorReturnTrace: | ||
| 15360 | return ir_analyze_instruction_error_return_trace(ira, (IrInstructionErrorReturnTrace *)instruction); | ||
| 15325 | } | 15361 | } |
| 15326 | zig_unreachable(); | 15362 | zig_unreachable(); |
| 15327 | } | 15363 | } |
| ... | @@ -15505,6 +15541,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { | ... | @@ -15505,6 +15541,7 @@ bool ir_has_side_effects(IrInstruction *instruction) { |
| 15505 | case IrInstructionIdOpaqueType: | 15541 | case IrInstructionIdOpaqueType: |
| 15506 | case IrInstructionIdArgType: | 15542 | case IrInstructionIdArgType: |
| 15507 | case IrInstructionIdTagType: | 15543 | case IrInstructionIdTagType: |
| 15544 | case IrInstructionIdErrorReturnTrace: | ||
| 15508 | return false; | 15545 | return false; |
| 15509 | case IrInstructionIdAsm: | 15546 | case IrInstructionIdAsm: |
| 15510 | { | 15547 | { |
src/ir_print.cpp+7| ... | @@ -996,6 +996,10 @@ static void ir_print_export(IrPrint *irp, IrInstructionExport *instruction) { | ... | @@ -996,6 +996,10 @@ static void ir_print_export(IrPrint *irp, IrInstructionExport *instruction) { |
| 996 | } | 996 | } |
| 997 | } | 997 | } |
| 998 | 998 | ||
| 999 | static void ir_print_error_return_trace(IrPrint *irp, IrInstructionErrorReturnTrace *instruction) { | ||
| 1000 | fprintf(irp->f, "@errorReturnTrace()"); | ||
| 1001 | } | ||
| 1002 | |||
| 999 | 1003 | ||
| 1000 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | 1004 | static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1001 | ir_print_prefix(irp, instruction); | 1005 | ir_print_prefix(irp, instruction); |
| ... | @@ -1308,6 +1312,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { | ... | @@ -1308,6 +1312,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) { |
| 1308 | case IrInstructionIdExport: | 1312 | case IrInstructionIdExport: |
| 1309 | ir_print_export(irp, (IrInstructionExport *)instruction); | 1313 | ir_print_export(irp, (IrInstructionExport *)instruction); |
| 1310 | break; | 1314 | break; |
| 1315 | case IrInstructionIdErrorReturnTrace: | ||
| 1316 | ir_print_error_return_trace(irp, (IrInstructionErrorReturnTrace *)instruction); | ||
| 1317 | break; | ||
| 1311 | } | 1318 | } |
| 1312 | fprintf(irp->f, "\n"); | 1319 | fprintf(irp->f, "\n"); |
| 1313 | } | 1320 | } |
std/build.zig+4-6| ... | @@ -247,11 +247,11 @@ pub const Builder = struct { | ... | @@ -247,11 +247,11 @@ pub const Builder = struct { |
| 247 | defer wanted_steps.deinit(); | 247 | defer wanted_steps.deinit(); |
| 248 | 248 | ||
| 249 | if (step_names.len == 0) { | 249 | if (step_names.len == 0) { |
| 250 | wanted_steps.append(&self.default_step) catch unreachable; | 250 | try wanted_steps.append(&self.default_step); |
| 251 | } else { | 251 | } else { |
| 252 | for (step_names) |step_name| { | 252 | for (step_names) |step_name| { |
| 253 | const s = try self.getTopLevelStepByName(step_name); | 253 | const s = try self.getTopLevelStepByName(step_name); |
| 254 | wanted_steps.append(s) catch unreachable; | 254 | try wanted_steps.append(s); |
| 255 | } | 255 | } |
| 256 | } | 256 | } |
| 257 | 257 | ||
| ... | @@ -721,11 +721,9 @@ pub const Builder = struct { | ... | @@ -721,11 +721,9 @@ pub const Builder = struct { |
| 721 | return error.FileNotFound; | 721 | return error.FileNotFound; |
| 722 | } | 722 | } |
| 723 | 723 | ||
| 724 | pub fn exec(self: &Builder, argv: []const []const u8) -> []u8 { | 724 | pub fn exec(self: &Builder, argv: []const []const u8) -> %[]u8 { |
| 725 | const max_output_size = 100 * 1024; | 725 | const max_output_size = 100 * 1024; |
| 726 | const result = os.ChildProcess.exec(self.allocator, argv, null, null, max_output_size) catch |err| { | 726 | const result = try os.ChildProcess.exec(self.allocator, argv, null, null, max_output_size); |
| 727 | std.debug.panic("Unable to spawn {}: {}", argv[0], @errorName(err)); | ||
| 728 | }; | ||
| 729 | switch (result.term) { | 727 | switch (result.term) { |
| 730 | os.ChildProcess.Term.Exited => |code| { | 728 | os.ChildProcess.Term.Exited => |code| { |
| 731 | if (code != 0) { | 729 | if (code != 0) { |
std/crypto/sha2.zig-40| ... | @@ -267,22 +267,12 @@ fn Sha2_32(comptime params: Sha2Params32) -> type { return struct { | ... | @@ -267,22 +267,12 @@ fn Sha2_32(comptime params: Sha2Params32) -> type { return struct { |
| 267 | };} | 267 | };} |
| 268 | 268 | ||
| 269 | test "sha224 single" { | 269 | test "sha224 single" { |
| 270 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 271 | // https://github.com/zig-lang/zig/issues/537 | ||
| 272 | return; | ||
| 273 | } | ||
| 274 | |||
| 275 | htest.assertEqualHash(Sha224, "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", ""); | 270 | htest.assertEqualHash(Sha224, "d14a028c2a3a2bc9476102bb288234c415a2b01f828ea62ac5b3e42f", ""); |
| 276 | htest.assertEqualHash(Sha224, "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", "abc"); | 271 | htest.assertEqualHash(Sha224, "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7", "abc"); |
| 277 | htest.assertEqualHash(Sha224, "c97ca9a559850ce97a04a96def6d99a9e0e0e2ab14e6b8df265fc0b3", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); | 272 | htest.assertEqualHash(Sha224, "c97ca9a559850ce97a04a96def6d99a9e0e0e2ab14e6b8df265fc0b3", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); |
| 278 | } | 273 | } |
| 279 | 274 | ||
| 280 | test "sha224 streaming" { | 275 | test "sha224 streaming" { |
| 281 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 282 | // https://github.com/zig-lang/zig/issues/537 | ||
| 283 | return; | ||
| 284 | } | ||
| 285 | |||
| 286 | var h = Sha224.init(); | 276 | var h = Sha224.init(); |
| 287 | var out: [28]u8 = undefined; | 277 | var out: [28]u8 = undefined; |
| 288 | 278 | ||
| ... | @@ -303,22 +293,12 @@ test "sha224 streaming" { | ... | @@ -303,22 +293,12 @@ test "sha224 streaming" { |
| 303 | } | 293 | } |
| 304 | 294 | ||
| 305 | test "sha256 single" { | 295 | test "sha256 single" { |
| 306 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 307 | // https://github.com/zig-lang/zig/issues/537 | ||
| 308 | return; | ||
| 309 | } | ||
| 310 | |||
| 311 | htest.assertEqualHash(Sha256, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""); | 296 | htest.assertEqualHash(Sha256, "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855", ""); |
| 312 | htest.assertEqualHash(Sha256, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", "abc"); | 297 | htest.assertEqualHash(Sha256, "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad", "abc"); |
| 313 | htest.assertEqualHash(Sha256, "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); | 298 | htest.assertEqualHash(Sha256, "cf5b16a778af8380036ce59e7b0492370b249b11e8f07a51afac45037afee9d1", "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"); |
| 314 | } | 299 | } |
| 315 | 300 | ||
| 316 | test "sha256 streaming" { | 301 | test "sha256 streaming" { |
| 317 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 318 | // https://github.com/zig-lang/zig/issues/537 | ||
| 319 | return; | ||
| 320 | } | ||
| 321 | |||
| 322 | var h = Sha256.init(); | 302 | var h = Sha256.init(); |
| 323 | var out: [32]u8 = undefined; | 303 | var out: [32]u8 = undefined; |
| 324 | 304 | ||
| ... | @@ -622,11 +602,6 @@ fn Sha2_64(comptime params: Sha2Params64) -> type { return struct { | ... | @@ -622,11 +602,6 @@ fn Sha2_64(comptime params: Sha2Params64) -> type { return struct { |
| 622 | };} | 602 | };} |
| 623 | 603 | ||
| 624 | test "sha384 single" { | 604 | test "sha384 single" { |
| 625 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 626 | // https://github.com/zig-lang/zig/issues/537 | ||
| 627 | return; | ||
| 628 | } | ||
| 629 | |||
| 630 | const h1 = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"; | 605 | const h1 = "38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b"; |
| 631 | htest.assertEqualHash(Sha384, h1, ""); | 606 | htest.assertEqualHash(Sha384, h1, ""); |
| 632 | 607 | ||
| ... | @@ -638,11 +613,6 @@ test "sha384 single" { | ... | @@ -638,11 +613,6 @@ test "sha384 single" { |
| 638 | } | 613 | } |
| 639 | 614 | ||
| 640 | test "sha384 streaming" { | 615 | test "sha384 streaming" { |
| 641 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 642 | // https://github.com/zig-lang/zig/issues/537 | ||
| 643 | return; | ||
| 644 | } | ||
| 645 | |||
| 646 | var h = Sha384.init(); | 616 | var h = Sha384.init(); |
| 647 | var out: [48]u8 = undefined; | 617 | var out: [48]u8 = undefined; |
| 648 | 618 | ||
| ... | @@ -666,11 +636,6 @@ test "sha384 streaming" { | ... | @@ -666,11 +636,6 @@ test "sha384 streaming" { |
| 666 | } | 636 | } |
| 667 | 637 | ||
| 668 | test "sha512 single" { | 638 | test "sha512 single" { |
| 669 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 670 | // https://github.com/zig-lang/zig/issues/537 | ||
| 671 | return; | ||
| 672 | } | ||
| 673 | |||
| 674 | const h1 = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"; | 639 | const h1 = "cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"; |
| 675 | htest.assertEqualHash(Sha512, h1, ""); | 640 | htest.assertEqualHash(Sha512, h1, ""); |
| 676 | 641 | ||
| ... | @@ -682,11 +647,6 @@ test "sha512 single" { | ... | @@ -682,11 +647,6 @@ test "sha512 single" { |
| 682 | } | 647 | } |
| 683 | 648 | ||
| 684 | test "sha512 streaming" { | 649 | test "sha512 streaming" { |
| 685 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 686 | // https://github.com/zig-lang/zig/issues/537 | ||
| 687 | return; | ||
| 688 | } | ||
| 689 | |||
| 690 | var h = Sha512.init(); | 650 | var h = Sha512.init(); |
| 691 | var out: [64]u8 = undefined; | 651 | var out: [64]u8 = undefined; |
| 692 | 652 |
std/debug/index.zig+149-63| ... | @@ -13,6 +13,10 @@ pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator; | ... | @@ -13,6 +13,10 @@ pub const FailingAllocator = @import("failing_allocator.zig").FailingAllocator; |
| 13 | error MissingDebugInfo; | 13 | error MissingDebugInfo; |
| 14 | error InvalidDebugInfo; | 14 | error InvalidDebugInfo; |
| 15 | error UnsupportedDebugInfo; | 15 | error UnsupportedDebugInfo; |
| 16 | error UnknownObjectFormat; | ||
| 17 | error TodoSupportCoffDebugInfo; | ||
| 18 | error TodoSupportMachoDebugInfo; | ||
| 19 | error TodoSupportCOFFDebugInfo; | ||
| 16 | 20 | ||
| 17 | 21 | ||
| 18 | /// Tries to write to stderr, unbuffered, and ignores any error returned. | 22 | /// Tries to write to stderr, unbuffered, and ignores any error returned. |
| ... | @@ -37,10 +41,43 @@ fn getStderrStream() -> %&io.OutStream { | ... | @@ -37,10 +41,43 @@ fn getStderrStream() -> %&io.OutStream { |
| 37 | } | 41 | } |
| 38 | } | 42 | } |
| 39 | 43 | ||
| 44 | var self_debug_info: ?&ElfStackTrace = null; | ||
| 45 | pub fn getSelfDebugInfo() -> %&ElfStackTrace { | ||
| 46 | if (self_debug_info) |info| { | ||
| 47 | return info; | ||
| 48 | } else { | ||
| 49 | const info = try openSelfDebugInfo(global_allocator); | ||
| 50 | self_debug_info = info; | ||
| 51 | return info; | ||
| 52 | } | ||
| 53 | } | ||
| 54 | |||
| 55 | /// Tries to print the current stack trace to stderr, unbuffered, and ignores any error returned. | ||
| 56 | pub fn dumpCurrentStackTrace() { | ||
| 57 | const stderr = getStderrStream() catch return; | ||
| 58 | const debug_info = getSelfDebugInfo() catch |err| { | ||
| 59 | stderr.print("Unable to open debug info: {}\n", @errorName(err)) catch return; | ||
| 60 | return; | ||
| 61 | }; | ||
| 62 | defer debug_info.close(); | ||
| 63 | writeCurrentStackTrace(stderr, global_allocator, debug_info, stderr_file.isTty(), 1) catch |err| { | ||
| 64 | stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return; | ||
| 65 | return; | ||
| 66 | }; | ||
| 67 | } | ||
| 68 | |||
| 40 | /// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned. | 69 | /// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned. |
| 41 | pub fn dumpStackTrace() { | 70 | pub fn dumpStackTrace(stack_trace: &const builtin.StackTrace) { |
| 42 | const stderr = getStderrStream() catch return; | 71 | const stderr = getStderrStream() catch return; |
| 43 | writeStackTrace(stderr, global_allocator, stderr_file.isTty(), 1) catch return; | 72 | const debug_info = getSelfDebugInfo() catch |err| { |
| 73 | stderr.print("Unable to open debug info: {}\n", @errorName(err)) catch return; | ||
| 74 | return; | ||
| 75 | }; | ||
| 76 | defer debug_info.close(); | ||
| 77 | writeStackTrace(stack_trace, stderr, global_allocator, debug_info, stderr_file.isTty()) catch |err| { | ||
| 78 | stderr.print("Unable to dump stack trace: {}\n", @errorName(err)) catch return; | ||
| 79 | return; | ||
| 80 | }; | ||
| 44 | } | 81 | } |
| 45 | 82 | ||
| 46 | /// This function invokes undefined behavior when `ok` is `false`. | 83 | /// This function invokes undefined behavior when `ok` is `false`. |
| ... | @@ -88,7 +125,21 @@ pub fn panic(comptime format: []const u8, args: ...) -> noreturn { | ... | @@ -88,7 +125,21 @@ pub fn panic(comptime format: []const u8, args: ...) -> noreturn { |
| 88 | 125 | ||
| 89 | const stderr = getStderrStream() catch os.abort(); | 126 | const stderr = getStderrStream() catch os.abort(); |
| 90 | stderr.print(format ++ "\n", args) catch os.abort(); | 127 | stderr.print(format ++ "\n", args) catch os.abort(); |
| 91 | writeStackTrace(stderr, global_allocator, stderr_file.isTty(), 1) catch os.abort(); | 128 | dumpCurrentStackTrace(); |
| 129 | |||
| 130 | os.abort(); | ||
| 131 | } | ||
| 132 | |||
| 133 | pub fn panicWithTrace(trace: &const builtin.StackTrace, comptime format: []const u8, args: ...) -> noreturn { | ||
| 134 | if (panicking) { | ||
| 135 | os.abort(); | ||
| 136 | } else { | ||
| 137 | panicking = true; | ||
| 138 | } | ||
| 139 | const stderr = getStderrStream() catch os.abort(); | ||
| 140 | stderr.print(format ++ "\n", args) catch os.abort(); | ||
| 141 | dumpStackTrace(trace); | ||
| 142 | dumpCurrentStackTrace(); | ||
| 92 | 143 | ||
| 93 | os.abort(); | 144 | os.abort(); |
| 94 | } | 145 | } |
| ... | @@ -101,12 +152,91 @@ const RESET = "\x1b[0m"; | ... | @@ -101,12 +152,91 @@ const RESET = "\x1b[0m"; |
| 101 | error PathNotFound; | 152 | error PathNotFound; |
| 102 | error InvalidDebugInfo; | 153 | error InvalidDebugInfo; |
| 103 | 154 | ||
| 104 | pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty_color: bool, | 155 | pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: &io.OutStream, allocator: &mem.Allocator, |
| 105 | ignore_frame_count: usize) -> %void | 156 | debug_info: &ElfStackTrace, tty_color: bool) -> %void |
| 106 | { | 157 | { |
| 158 | var frame_index: usize = undefined; | ||
| 159 | var frames_left: usize = undefined; | ||
| 160 | if (stack_trace.index < stack_trace.instruction_addresses.len) { | ||
| 161 | frame_index = 0; | ||
| 162 | frames_left = stack_trace.index; | ||
| 163 | } else { | ||
| 164 | frame_index = (stack_trace.index + 1) % stack_trace.instruction_addresses.len; | ||
| 165 | frames_left = stack_trace.instruction_addresses.len; | ||
| 166 | } | ||
| 167 | |||
| 168 | while (frames_left != 0) : ({ | ||
| 169 | frames_left -= 1; | ||
| 170 | frame_index = (frame_index + 1) % stack_trace.instruction_addresses.len; | ||
| 171 | }) { | ||
| 172 | const return_address = stack_trace.instruction_addresses[frame_index]; | ||
| 173 | try printSourceAtAddress(debug_info, out_stream, return_address); | ||
| 174 | } | ||
| 175 | } | ||
| 176 | |||
| 177 | pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, | ||
| 178 | debug_info: &ElfStackTrace, tty_color: bool, ignore_frame_count: usize) -> %void | ||
| 179 | { | ||
| 180 | var ignored_count: usize = 0; | ||
| 181 | |||
| 182 | var fp = @ptrToInt(@frameAddress()); | ||
| 183 | while (fp != 0) : (fp = *@intToPtr(&const usize, fp)) { | ||
| 184 | if (ignored_count < ignore_frame_count) { | ||
| 185 | ignored_count += 1; | ||
| 186 | continue; | ||
| 187 | } | ||
| 188 | |||
| 189 | const return_address = *@intToPtr(&const usize, fp + @sizeOf(usize)); | ||
| 190 | try printSourceAtAddress(debug_info, out_stream, return_address); | ||
| 191 | } | ||
| 192 | } | ||
| 193 | |||
| 194 | fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, address: usize) -> %void { | ||
| 195 | if (builtin.os == builtin.Os.windows) { | ||
| 196 | return error.UnsupportedDebugInfo; | ||
| 197 | } | ||
| 198 | // TODO we really should be able to convert @sizeOf(usize) * 2 to a string literal | ||
| 199 | // at compile time. I'll call it issue #313 | ||
| 200 | const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}"; | ||
| 201 | |||
| 202 | const compile_unit = findCompileUnit(debug_info, address) catch { | ||
| 203 | try out_stream.print("???:?:?: " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n ???\n\n", | ||
| 204 | address); | ||
| 205 | return; | ||
| 206 | }; | ||
| 207 | const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name); | ||
| 208 | if (getLineNumberInfo(debug_info, compile_unit, address - 1)) |line_info| { | ||
| 209 | defer line_info.deinit(); | ||
| 210 | try out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++ | ||
| 211 | DIM ++ ptr_hex ++ " in ??? ({})" ++ RESET ++ "\n", | ||
| 212 | line_info.file_name, line_info.line, line_info.column, | ||
| 213 | address, compile_unit_name); | ||
| 214 | if (printLineFromFile(debug_info.allocator(), out_stream, line_info)) { | ||
| 215 | if (line_info.column == 0) { | ||
| 216 | try out_stream.write("\n"); | ||
| 217 | } else { | ||
| 218 | {var col_i: usize = 1; while (col_i < line_info.column) : (col_i += 1) { | ||
| 219 | try out_stream.writeByte(' '); | ||
| 220 | }} | ||
| 221 | try out_stream.write(GREEN ++ "^" ++ RESET ++ "\n"); | ||
| 222 | } | ||
| 223 | } else |err| switch (err) { | ||
| 224 | error.EndOfFile, error.PathNotFound => {}, | ||
| 225 | else => return err, | ||
| 226 | } | ||
| 227 | } else |err| switch (err) { | ||
| 228 | error.MissingDebugInfo, error.InvalidDebugInfo => { | ||
| 229 | try out_stream.print(ptr_hex ++ " in ??? ({})\n", address, compile_unit_name); | ||
| 230 | }, | ||
| 231 | else => return err, | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 235 | pub fn openSelfDebugInfo(allocator: &mem.Allocator) -> %&ElfStackTrace { | ||
| 107 | switch (builtin.object_format) { | 236 | switch (builtin.object_format) { |
| 108 | builtin.ObjectFormat.elf => { | 237 | builtin.ObjectFormat.elf => { |
| 109 | var stack_trace = ElfStackTrace { | 238 | const st = try allocator.create(ElfStackTrace); |
| 239 | *st = ElfStackTrace { | ||
| 110 | .self_exe_file = undefined, | 240 | .self_exe_file = undefined, |
| 111 | .elf = undefined, | 241 | .elf = undefined, |
| 112 | .debug_info = undefined, | 242 | .debug_info = undefined, |
| ... | @@ -117,12 +247,11 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty | ... | @@ -117,12 +247,11 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty |
| 117 | .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator), | 247 | .abbrev_table_list = ArrayList(AbbrevTableHeader).init(allocator), |
| 118 | .compile_unit_list = ArrayList(CompileUnit).init(allocator), | 248 | .compile_unit_list = ArrayList(CompileUnit).init(allocator), |
| 119 | }; | 249 | }; |
| 120 | const st = &stack_trace; | ||
| 121 | st.self_exe_file = try os.openSelfExe(); | 250 | st.self_exe_file = try os.openSelfExe(); |
| 122 | defer st.self_exe_file.close(); | 251 | %defer st.self_exe_file.close(); |
| 123 | 252 | ||
| 124 | try st.elf.openFile(allocator, &st.self_exe_file); | 253 | try st.elf.openFile(allocator, &st.self_exe_file); |
| 125 | defer st.elf.close(); | 254 | %defer st.elf.close(); |
| 126 | 255 | ||
| 127 | st.debug_info = (try st.elf.findSection(".debug_info")) ?? return error.MissingDebugInfo; | 256 | st.debug_info = (try st.elf.findSection(".debug_info")) ?? return error.MissingDebugInfo; |
| 128 | st.debug_abbrev = (try st.elf.findSection(".debug_abbrev")) ?? return error.MissingDebugInfo; | 257 | st.debug_abbrev = (try st.elf.findSection(".debug_abbrev")) ?? return error.MissingDebugInfo; |
| ... | @@ -130,67 +259,19 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty | ... | @@ -130,67 +259,19 @@ pub fn writeStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocator, tty |
| 130 | st.debug_line = (try st.elf.findSection(".debug_line")) ?? return error.MissingDebugInfo; | 259 | st.debug_line = (try st.elf.findSection(".debug_line")) ?? return error.MissingDebugInfo; |
| 131 | st.debug_ranges = (try st.elf.findSection(".debug_ranges")); | 260 | st.debug_ranges = (try st.elf.findSection(".debug_ranges")); |
| 132 | try scanAllCompileUnits(st); | 261 | try scanAllCompileUnits(st); |
| 133 | 262 | return st; | |
| 134 | var ignored_count: usize = 0; | ||
| 135 | |||
| 136 | var fp = @ptrToInt(@frameAddress()); | ||
| 137 | while (fp != 0) : (fp = *@intToPtr(&const usize, fp)) { | ||
| 138 | if (ignored_count < ignore_frame_count) { | ||
| 139 | ignored_count += 1; | ||
| 140 | continue; | ||
| 141 | } | ||
| 142 | |||
| 143 | const return_address = *@intToPtr(&const usize, fp + @sizeOf(usize)); | ||
| 144 | |||
| 145 | // TODO we really should be able to convert @sizeOf(usize) * 2 to a string literal | ||
| 146 | // at compile time. I'll call it issue #313 | ||
| 147 | const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}"; | ||
| 148 | |||
| 149 | const compile_unit = findCompileUnit(st, return_address) catch { | ||
| 150 | try out_stream.print("???:?:?: " ++ DIM ++ ptr_hex ++ " in ??? (???)" ++ RESET ++ "\n ???\n\n", | ||
| 151 | return_address); | ||
| 152 | continue; | ||
| 153 | }; | ||
| 154 | const compile_unit_name = try compile_unit.die.getAttrString(st, DW.AT_name); | ||
| 155 | if (getLineNumberInfo(st, compile_unit, usize(return_address) - 1)) |line_info| { | ||
| 156 | defer line_info.deinit(); | ||
| 157 | try out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++ | ||
| 158 | DIM ++ ptr_hex ++ " in ??? ({})" ++ RESET ++ "\n", | ||
| 159 | line_info.file_name, line_info.line, line_info.column, | ||
| 160 | return_address, compile_unit_name); | ||
| 161 | if (printLineFromFile(st.allocator(), out_stream, line_info)) { | ||
| 162 | if (line_info.column == 0) { | ||
| 163 | try out_stream.write("\n"); | ||
| 164 | } else { | ||
| 165 | {var col_i: usize = 1; while (col_i < line_info.column) : (col_i += 1) { | ||
| 166 | try out_stream.writeByte(' '); | ||
| 167 | }} | ||
| 168 | try out_stream.write(GREEN ++ "^" ++ RESET ++ "\n"); | ||
| 169 | } | ||
| 170 | } else |err| switch (err) { | ||
| 171 | error.EndOfFile, error.PathNotFound => {}, | ||
| 172 | else => return err, | ||
| 173 | } | ||
| 174 | } else |err| switch (err) { | ||
| 175 | error.MissingDebugInfo, error.InvalidDebugInfo => { | ||
| 176 | try out_stream.print(ptr_hex ++ " in ??? ({})\n", | ||
| 177 | return_address, compile_unit_name); | ||
| 178 | }, | ||
| 179 | else => return err, | ||
| 180 | } | ||
| 181 | } | ||
| 182 | }, | 263 | }, |
| 183 | builtin.ObjectFormat.coff => { | 264 | builtin.ObjectFormat.coff => { |
| 184 | try out_stream.write("(stack trace unavailable for COFF object format)\n"); | 265 | return error.TodoSupportCoffDebugInfo; |
| 185 | }, | 266 | }, |
| 186 | builtin.ObjectFormat.macho => { | 267 | builtin.ObjectFormat.macho => { |
| 187 | try out_stream.write("(stack trace unavailable for Mach-O object format)\n"); | 268 | return error.TodoSupportMachoDebugInfo; |
| 188 | }, | 269 | }, |
| 189 | builtin.ObjectFormat.wasm => { | 270 | builtin.ObjectFormat.wasm => { |
| 190 | try out_stream.write("(stack trace unavailable for WASM object format)\n"); | 271 | return error.TodoSupportCOFFDebugInfo; |
| 191 | }, | 272 | }, |
| 192 | builtin.ObjectFormat.unknown => { | 273 | builtin.ObjectFormat.unknown => { |
| 193 | try out_stream.write("(stack trace unavailable for unknown object format)\n"); | 274 | return error.UnknownObjectFormat; |
| 194 | }, | 275 | }, |
| 195 | } | 276 | } |
| 196 | } | 277 | } |
| ... | @@ -228,7 +309,7 @@ fn printLineFromFile(allocator: &mem.Allocator, out_stream: &io.OutStream, line_ | ... | @@ -228,7 +309,7 @@ fn printLineFromFile(allocator: &mem.Allocator, out_stream: &io.OutStream, line_ |
| 228 | } | 309 | } |
| 229 | } | 310 | } |
| 230 | 311 | ||
| 231 | const ElfStackTrace = struct { | 312 | pub const ElfStackTrace = struct { |
| 232 | self_exe_file: io.File, | 313 | self_exe_file: io.File, |
| 233 | elf: elf.Elf, | 314 | elf: elf.Elf, |
| 234 | debug_info: &elf.SectionHeader, | 315 | debug_info: &elf.SectionHeader, |
| ... | @@ -248,6 +329,11 @@ const ElfStackTrace = struct { | ... | @@ -248,6 +329,11 @@ const ElfStackTrace = struct { |
| 248 | const in_stream = &in_file_stream.stream; | 329 | const in_stream = &in_file_stream.stream; |
| 249 | return readStringRaw(self.allocator(), in_stream); | 330 | return readStringRaw(self.allocator(), in_stream); |
| 250 | } | 331 | } |
| 332 | |||
| 333 | pub fn close(self: &ElfStackTrace) { | ||
| 334 | self.self_exe_file.close(); | ||
| 335 | self.elf.close(); | ||
| 336 | } | ||
| 251 | }; | 337 | }; |
| 252 | 338 | ||
| 253 | const PcRange = struct { | 339 | const PcRange = struct { |
std/io.zig+1-1| ... | @@ -224,7 +224,7 @@ pub const File = struct { | ... | @@ -224,7 +224,7 @@ pub const File = struct { |
| 224 | }; | 224 | }; |
| 225 | } | 225 | } |
| 226 | }, | 226 | }, |
| 227 | else => @compileError("unsupported OS"), | 227 | else => @compileError("unsupported OS: " ++ @tagName(builtin.os)), |
| 228 | } | 228 | } |
| 229 | } | 229 | } |
| 230 | 230 |
std/io_test.zig-5| ... | @@ -8,11 +8,6 @@ const os = std.os; | ... | @@ -8,11 +8,6 @@ const os = std.os; |
| 8 | const builtin = @import("builtin"); | 8 | const builtin = @import("builtin"); |
| 9 | 9 | ||
| 10 | test "write a file, read it, then delete it" { | 10 | test "write a file, read it, then delete it" { |
| 11 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 12 | // TODO get this test passing | ||
| 13 | // https://github.com/zig-lang/zig/issues/537 | ||
| 14 | return; | ||
| 15 | } | ||
| 16 | var data: [1024]u8 = undefined; | 11 | var data: [1024]u8 = undefined; |
| 17 | var rng = Rand.init(1234); | 12 | var rng = Rand.init(1234); |
| 18 | rng.fillBytes(data[0..]); | 13 | rng.fillBytes(data[0..]); |
std/math/acosh.zig-5| ... | @@ -55,11 +55,6 @@ fn acosh64(x: f64) -> f64 { | ... | @@ -55,11 +55,6 @@ fn acosh64(x: f64) -> f64 { |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | test "math.acosh" { | 57 | test "math.acosh" { |
| 58 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 59 | // TODO get this test passing | ||
| 60 | // https://github.com/zig-lang/zig/issues/537 | ||
| 61 | return; | ||
| 62 | } | ||
| 63 | assert(acosh(f32(1.5)) == acosh32(1.5)); | 58 | assert(acosh(f32(1.5)) == acosh32(1.5)); |
| 64 | assert(acosh(f64(1.5)) == acosh64(1.5)); | 59 | assert(acosh(f64(1.5)) == acosh64(1.5)); |
| 65 | } | 60 | } |
std/math/cos.zig-5| ... | @@ -146,11 +146,6 @@ test "math.cos" { | ... | @@ -146,11 +146,6 @@ test "math.cos" { |
| 146 | } | 146 | } |
| 147 | 147 | ||
| 148 | test "math.cos32" { | 148 | test "math.cos32" { |
| 149 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 150 | // TODO get this test passing | ||
| 151 | // https://github.com/zig-lang/zig/issues/537 | ||
| 152 | return; | ||
| 153 | } | ||
| 154 | const epsilon = 0.000001; | 149 | const epsilon = 0.000001; |
| 155 | 150 | ||
| 156 | assert(math.approxEq(f32, cos32(0.0), 1.0, epsilon)); | 151 | assert(math.approxEq(f32, cos32(0.0), 1.0, epsilon)); |
std/math/cosh.zig-5| ... | @@ -81,11 +81,6 @@ fn cosh64(x: f64) -> f64 { | ... | @@ -81,11 +81,6 @@ fn cosh64(x: f64) -> f64 { |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | test "math.cosh" { | 83 | test "math.cosh" { |
| 84 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 85 | // TODO get this test passing | ||
| 86 | // https://github.com/zig-lang/zig/issues/537 | ||
| 87 | return; | ||
| 88 | } | ||
| 89 | assert(cosh(f32(1.5)) == cosh32(1.5)); | 84 | assert(cosh(f32(1.5)) == cosh32(1.5)); |
| 90 | assert(cosh(f64(1.5)) == cosh64(1.5)); | 85 | assert(cosh(f64(1.5)) == cosh64(1.5)); |
| 91 | } | 86 | } |
std/math/index.zig-15| ... | @@ -359,11 +359,6 @@ pub fn divTrunc(comptime T: type, numerator: T, denominator: T) -> %T { | ... | @@ -359,11 +359,6 @@ pub fn divTrunc(comptime T: type, numerator: T, denominator: T) -> %T { |
| 359 | } | 359 | } |
| 360 | 360 | ||
| 361 | test "math.divTrunc" { | 361 | test "math.divTrunc" { |
| 362 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 363 | // TODO get this test passing | ||
| 364 | // https://github.com/zig-lang/zig/issues/537 | ||
| 365 | return; | ||
| 366 | } | ||
| 367 | testDivTrunc(); | 362 | testDivTrunc(); |
| 368 | comptime testDivTrunc(); | 363 | comptime testDivTrunc(); |
| 369 | } | 364 | } |
| ... | @@ -389,11 +384,6 @@ pub fn divFloor(comptime T: type, numerator: T, denominator: T) -> %T { | ... | @@ -389,11 +384,6 @@ pub fn divFloor(comptime T: type, numerator: T, denominator: T) -> %T { |
| 389 | } | 384 | } |
| 390 | 385 | ||
| 391 | test "math.divFloor" { | 386 | test "math.divFloor" { |
| 392 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 393 | // TODO get this test passing | ||
| 394 | // https://github.com/zig-lang/zig/issues/537 | ||
| 395 | return; | ||
| 396 | } | ||
| 397 | testDivFloor(); | 387 | testDivFloor(); |
| 398 | comptime testDivFloor(); | 388 | comptime testDivFloor(); |
| 399 | } | 389 | } |
| ... | @@ -423,11 +413,6 @@ pub fn divExact(comptime T: type, numerator: T, denominator: T) -> %T { | ... | @@ -423,11 +413,6 @@ pub fn divExact(comptime T: type, numerator: T, denominator: T) -> %T { |
| 423 | } | 413 | } |
| 424 | 414 | ||
| 425 | test "math.divExact" { | 415 | test "math.divExact" { |
| 426 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 427 | // TODO get this test passing | ||
| 428 | // https://github.com/zig-lang/zig/issues/537 | ||
| 429 | return; | ||
| 430 | } | ||
| 431 | testDivExact(); | 416 | testDivExact(); |
| 432 | comptime testDivExact(); | 417 | comptime testDivExact(); |
| 433 | } | 418 | } |
std/math/ln.zig-5| ... | @@ -147,11 +147,6 @@ pub fn ln_64(x_: f64) -> f64 { | ... | @@ -147,11 +147,6 @@ pub fn ln_64(x_: f64) -> f64 { |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | test "math.ln" { | 149 | test "math.ln" { |
| 150 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 151 | // TODO get this test passing | ||
| 152 | // https://github.com/zig-lang/zig/issues/537 | ||
| 153 | return; | ||
| 154 | } | ||
| 155 | assert(ln(f32(0.2)) == ln_32(0.2)); | 150 | assert(ln(f32(0.2)) == ln_32(0.2)); |
| 156 | assert(ln(f64(0.2)) == ln_64(0.2)); | 151 | assert(ln(f64(0.2)) == ln_64(0.2)); |
| 157 | } | 152 | } |
std/math/log.zig-5| ... | @@ -56,11 +56,6 @@ test "math.log float" { | ... | @@ -56,11 +56,6 @@ test "math.log float" { |
| 56 | } | 56 | } |
| 57 | 57 | ||
| 58 | test "math.log float_special" { | 58 | test "math.log float_special" { |
| 59 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 60 | // TODO get this test passing | ||
| 61 | // https://github.com/zig-lang/zig/issues/537 | ||
| 62 | return; | ||
| 63 | } | ||
| 64 | assert(log(f32, 2, 0.2301974) == math.log2(f32(0.2301974))); | 59 | assert(log(f32, 2, 0.2301974) == math.log2(f32(0.2301974))); |
| 65 | assert(log(f32, 10, 0.2301974) == math.log10(f32(0.2301974))); | 60 | assert(log(f32, 10, 0.2301974) == math.log10(f32(0.2301974))); |
| 66 | 61 |
std/math/log10.zig-5| ... | @@ -172,11 +172,6 @@ pub fn log10_64(x_: f64) -> f64 { | ... | @@ -172,11 +172,6 @@ pub fn log10_64(x_: f64) -> f64 { |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | test "math.log10" { | 174 | test "math.log10" { |
| 175 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 176 | // TODO get this test passing | ||
| 177 | // https://github.com/zig-lang/zig/issues/537 | ||
| 178 | return; | ||
| 179 | } | ||
| 180 | assert(log10(f32(0.2)) == log10_32(0.2)); | 175 | assert(log10(f32(0.2)) == log10_32(0.2)); |
| 181 | assert(log10(f64(0.2)) == log10_64(0.2)); | 176 | assert(log10(f64(0.2)) == log10_64(0.2)); |
| 182 | } | 177 | } |
std/math/log2.zig-5| ... | @@ -170,11 +170,6 @@ pub fn log2_64(x_: f64) -> f64 { | ... | @@ -170,11 +170,6 @@ pub fn log2_64(x_: f64) -> f64 { |
| 170 | } | 170 | } |
| 171 | 171 | ||
| 172 | test "math.log2" { | 172 | test "math.log2" { |
| 173 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 174 | // TODO get this test passing | ||
| 175 | // https://github.com/zig-lang/zig/issues/537 | ||
| 176 | return; | ||
| 177 | } | ||
| 178 | assert(log2(f32(0.2)) == log2_32(0.2)); | 173 | assert(log2(f32(0.2)) == log2_32(0.2)); |
| 179 | assert(log2(f64(0.2)) == log2_64(0.2)); | 174 | assert(log2(f64(0.2)) == log2_64(0.2)); |
| 180 | } | 175 | } |
std/math/pow.zig-6| ... | @@ -176,12 +176,6 @@ fn isOddInteger(x: f64) -> bool { | ... | @@ -176,12 +176,6 @@ fn isOddInteger(x: f64) -> bool { |
| 176 | } | 176 | } |
| 177 | 177 | ||
| 178 | test "math.pow" { | 178 | test "math.pow" { |
| 179 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 180 | // TODO get this test passing | ||
| 181 | // https://github.com/zig-lang/zig/issues/537 | ||
| 182 | return; | ||
| 183 | } | ||
| 184 | |||
| 185 | const epsilon = 0.000001; | 179 | const epsilon = 0.000001; |
| 186 | 180 | ||
| 187 | assert(math.approxEq(f32, pow(f32, 0.0, 3.3), 0.0, epsilon)); | 181 | assert(math.approxEq(f32, pow(f32, 0.0, 3.3), 0.0, epsilon)); |
std/math/round.zig-5| ... | @@ -98,11 +98,6 @@ test "math.round" { | ... | @@ -98,11 +98,6 @@ test "math.round" { |
| 98 | } | 98 | } |
| 99 | 99 | ||
| 100 | test "math.round32" { | 100 | test "math.round32" { |
| 101 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 102 | // TODO get this test passing | ||
| 103 | // https://github.com/zig-lang/zig/issues/537 | ||
| 104 | return; | ||
| 105 | } | ||
| 106 | assert(round32(1.3) == 1.0); | 101 | assert(round32(1.3) == 1.0); |
| 107 | assert(round32(-1.3) == -1.0); | 102 | assert(round32(-1.3) == -1.0); |
| 108 | assert(round32(0.2) == 0.0); | 103 | assert(round32(0.2) == 0.0); |
std/math/sin.zig-5| ... | @@ -150,11 +150,6 @@ test "math.sin" { | ... | @@ -150,11 +150,6 @@ test "math.sin" { |
| 150 | } | 150 | } |
| 151 | 151 | ||
| 152 | test "math.sin32" { | 152 | test "math.sin32" { |
| 153 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 154 | // TODO get this test passing | ||
| 155 | // https://github.com/zig-lang/zig/issues/537 | ||
| 156 | return; | ||
| 157 | } | ||
| 158 | const epsilon = 0.000001; | 153 | const epsilon = 0.000001; |
| 159 | 154 | ||
| 160 | assert(math.approxEq(f32, sin32(0.0), 0.0, epsilon)); | 155 | assert(math.approxEq(f32, sin32(0.0), 0.0, epsilon)); |
std/math/sinh.zig-5| ... | @@ -88,11 +88,6 @@ fn sinh64(x: f64) -> f64 { | ... | @@ -88,11 +88,6 @@ fn sinh64(x: f64) -> f64 { |
| 88 | } | 88 | } |
| 89 | 89 | ||
| 90 | test "math.sinh" { | 90 | test "math.sinh" { |
| 91 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 92 | // TODO get this test passing | ||
| 93 | // https://github.com/zig-lang/zig/issues/537 | ||
| 94 | return; | ||
| 95 | } | ||
| 96 | assert(sinh(f32(1.5)) == sinh32(1.5)); | 91 | assert(sinh(f32(1.5)) == sinh32(1.5)); |
| 97 | assert(sinh(f64(1.5)) == sinh64(1.5)); | 92 | assert(sinh(f64(1.5)) == sinh64(1.5)); |
| 98 | } | 93 | } |
std/math/tan.zig-5| ... | @@ -136,11 +136,6 @@ test "math.tan" { | ... | @@ -136,11 +136,6 @@ test "math.tan" { |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | test "math.tan32" { | 138 | test "math.tan32" { |
| 139 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 140 | // TODO get this test passing | ||
| 141 | // https://github.com/zig-lang/zig/issues/537 | ||
| 142 | return; | ||
| 143 | } | ||
| 144 | const epsilon = 0.000001; | 139 | const epsilon = 0.000001; |
| 145 | 140 | ||
| 146 | assert(math.approxEq(f32, tan32(0.0), 0.0, epsilon)); | 141 | assert(math.approxEq(f32, tan32(0.0), 0.0, epsilon)); |
std/math/tanh.zig-5| ... | @@ -112,11 +112,6 @@ fn tanh64(x: f64) -> f64 { | ... | @@ -112,11 +112,6 @@ fn tanh64(x: f64) -> f64 { |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | test "math.tanh" { | 114 | test "math.tanh" { |
| 115 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 116 | // TODO get this test passing | ||
| 117 | // https://github.com/zig-lang/zig/issues/537 | ||
| 118 | return; | ||
| 119 | } | ||
| 120 | assert(tanh(f32(1.5)) == tanh32(1.5)); | 115 | assert(tanh(f32(1.5)) == tanh32(1.5)); |
| 121 | assert(tanh(f64(1.5)) == tanh64(1.5)); | 116 | assert(tanh(f64(1.5)) == tanh64(1.5)); |
| 122 | } | 117 | } |
std/os/index.zig+2-9| ... | @@ -148,7 +148,7 @@ pub coldcc fn abort() -> noreturn { | ... | @@ -148,7 +148,7 @@ pub coldcc fn abort() -> noreturn { |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | /// Exits the program cleanly with the specified status code. | 150 | /// Exits the program cleanly with the specified status code. |
| 151 | pub coldcc fn exit(status: i32) -> noreturn { | 151 | pub coldcc fn exit(status: u8) -> noreturn { |
| 152 | if (builtin.link_libc) { | 152 | if (builtin.link_libc) { |
| 153 | c.exit(status); | 153 | c.exit(status); |
| 154 | } | 154 | } |
| ... | @@ -157,14 +157,7 @@ pub coldcc fn exit(status: i32) -> noreturn { | ... | @@ -157,14 +157,7 @@ pub coldcc fn exit(status: i32) -> noreturn { |
| 157 | posix.exit(status); | 157 | posix.exit(status); |
| 158 | }, | 158 | }, |
| 159 | Os.windows => { | 159 | Os.windows => { |
| 160 | // Map a possibly negative status code to a non-negative status for the systems default | 160 | windows.ExitProcess(status); |
| 161 | // integer width. | ||
| 162 | const p_status = if (@sizeOf(c_uint) < @sizeOf(u32)) | ||
| 163 | @truncate(c_uint, @bitCast(u32, status)) | ||
| 164 | else | ||
| 165 | c_uint(@bitCast(u32, status)); | ||
| 166 | |||
| 167 | windows.ExitProcess(p_status); | ||
| 168 | }, | 161 | }, |
| 169 | else => @compileError("Unsupported OS"), | 162 | else => @compileError("Unsupported OS"), |
| 170 | } | 163 | } |
std/rand.zig-20| ... | @@ -194,11 +194,6 @@ fn MersenneTwister( | ... | @@ -194,11 +194,6 @@ fn MersenneTwister( |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | test "rand float 32" { | 196 | test "rand float 32" { |
| 197 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 198 | // TODO get this test passing | ||
| 199 | // https://github.com/zig-lang/zig/issues/537 | ||
| 200 | return; | ||
| 201 | } | ||
| 202 | var r = Rand.init(42); | 197 | var r = Rand.init(42); |
| 203 | var i: usize = 0; | 198 | var i: usize = 0; |
| 204 | while (i < 1000) : (i += 1) { | 199 | while (i < 1000) : (i += 1) { |
| ... | @@ -209,11 +204,6 @@ test "rand float 32" { | ... | @@ -209,11 +204,6 @@ test "rand float 32" { |
| 209 | } | 204 | } |
| 210 | 205 | ||
| 211 | test "rand.MT19937_64" { | 206 | test "rand.MT19937_64" { |
| 212 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 213 | // TODO get this test passing | ||
| 214 | // https://github.com/zig-lang/zig/issues/537 | ||
| 215 | return; | ||
| 216 | } | ||
| 217 | var rng = MT19937_64.init(rand_test.mt64_seed); | 207 | var rng = MT19937_64.init(rand_test.mt64_seed); |
| 218 | for (rand_test.mt64_data) |value| { | 208 | for (rand_test.mt64_data) |value| { |
| 219 | assert(value == rng.get()); | 209 | assert(value == rng.get()); |
| ... | @@ -221,11 +211,6 @@ test "rand.MT19937_64" { | ... | @@ -221,11 +211,6 @@ test "rand.MT19937_64" { |
| 221 | } | 211 | } |
| 222 | 212 | ||
| 223 | test "rand.MT19937_32" { | 213 | test "rand.MT19937_32" { |
| 224 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 225 | // TODO get this test passing | ||
| 226 | // https://github.com/zig-lang/zig/issues/537 | ||
| 227 | return; | ||
| 228 | } | ||
| 229 | var rng = MT19937_32.init(rand_test.mt32_seed); | 214 | var rng = MT19937_32.init(rand_test.mt32_seed); |
| 230 | for (rand_test.mt32_data) |value| { | 215 | for (rand_test.mt32_data) |value| { |
| 231 | assert(value == rng.get()); | 216 | assert(value == rng.get()); |
| ... | @@ -233,11 +218,6 @@ test "rand.MT19937_32" { | ... | @@ -233,11 +218,6 @@ test "rand.MT19937_32" { |
| 233 | } | 218 | } |
| 234 | 219 | ||
| 235 | test "rand.Rand.range" { | 220 | test "rand.Rand.range" { |
| 236 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 237 | // TODO get this test passing | ||
| 238 | // https://github.com/zig-lang/zig/issues/537 | ||
| 239 | return; | ||
| 240 | } | ||
| 241 | var r = Rand.init(42); | 221 | var r = Rand.init(42); |
| 242 | testRange(&r, -4, 3); | 222 | testRange(&r, -4, 3); |
| 243 | testRange(&r, -4, -1); | 223 | testRange(&r, -4, -1); |
std/sort.zig-20| ... | @@ -1020,11 +1020,6 @@ fn cmpByValue(a: &const IdAndValue, b: &const IdAndValue) -> bool { | ... | @@ -1020,11 +1020,6 @@ fn cmpByValue(a: &const IdAndValue, b: &const IdAndValue) -> bool { |
| 1020 | } | 1020 | } |
| 1021 | 1021 | ||
| 1022 | test "std.sort" { | 1022 | test "std.sort" { |
| 1023 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 1024 | // TODO get this test passing | ||
| 1025 | // https://github.com/zig-lang/zig/issues/537 | ||
| 1026 | return; | ||
| 1027 | } | ||
| 1028 | const u8cases = [][]const []const u8 { | 1023 | const u8cases = [][]const []const u8 { |
| 1029 | [][]const u8{"", ""}, | 1024 | [][]const u8{"", ""}, |
| 1030 | [][]const u8{"a", "a"}, | 1025 | [][]const u8{"a", "a"}, |
| ... | @@ -1061,11 +1056,6 @@ test "std.sort" { | ... | @@ -1061,11 +1056,6 @@ test "std.sort" { |
| 1061 | } | 1056 | } |
| 1062 | 1057 | ||
| 1063 | test "std.sort descending" { | 1058 | test "std.sort descending" { |
| 1064 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 1065 | // TODO get this test passing | ||
| 1066 | // https://github.com/zig-lang/zig/issues/537 | ||
| 1067 | return; | ||
| 1068 | } | ||
| 1069 | const rev_cases = [][]const []const i32 { | 1059 | const rev_cases = [][]const []const i32 { |
| 1070 | [][]const i32{[]i32{}, []i32{}}, | 1060 | [][]const i32{[]i32{}, []i32{}}, |
| 1071 | [][]const i32{[]i32{1}, []i32{1}}, | 1061 | [][]const i32{[]i32{1}, []i32{1}}, |
| ... | @@ -1085,11 +1075,6 @@ test "std.sort descending" { | ... | @@ -1085,11 +1075,6 @@ test "std.sort descending" { |
| 1085 | } | 1075 | } |
| 1086 | 1076 | ||
| 1087 | test "another sort case" { | 1077 | test "another sort case" { |
| 1088 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 1089 | // TODO get this test passing | ||
| 1090 | // https://github.com/zig-lang/zig/issues/537 | ||
| 1091 | return; | ||
| 1092 | } | ||
| 1093 | var arr = []i32{ 5, 3, 1, 2, 4 }; | 1078 | var arr = []i32{ 5, 3, 1, 2, 4 }; |
| 1094 | sort(i32, arr[0..], i32asc); | 1079 | sort(i32, arr[0..], i32asc); |
| 1095 | 1080 | ||
| ... | @@ -1097,11 +1082,6 @@ test "another sort case" { | ... | @@ -1097,11 +1082,6 @@ test "another sort case" { |
| 1097 | } | 1082 | } |
| 1098 | 1083 | ||
| 1099 | test "sort fuzz testing" { | 1084 | test "sort fuzz testing" { |
| 1100 | if (builtin.os == builtin.Os.windows and builtin.arch == builtin.Arch.i386) { | ||
| 1101 | // TODO get this test passing | ||
| 1102 | // https://github.com/zig-lang/zig/issues/537 | ||
| 1103 | return; | ||
| 1104 | } | ||
| 1105 | var rng = std.rand.Rand.init(0x12345678); | 1085 | var rng = std.rand.Rand.init(0x12345678); |
| 1106 | const test_case_count = 10; | 1086 | const test_case_count = 10; |
| 1107 | var i: usize = 0; | 1087 | var i: usize = 0; |
std/special/bootstrap.zig+35-10| ... | @@ -21,8 +21,7 @@ comptime { | ... | @@ -21,8 +21,7 @@ comptime { |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | extern fn zenMain() -> noreturn { | 23 | extern fn zenMain() -> noreturn { |
| 24 | root.main() catch std.os.posix.exit(1); | 24 | std.os.posix.exit(callMain()); |
| 25 | std.os.posix.exit(0); | ||
| 26 | } | 25 | } |
| 27 | 26 | ||
| 28 | nakedcc fn _start() -> noreturn { | 27 | nakedcc fn _start() -> noreturn { |
| ... | @@ -43,29 +42,55 @@ nakedcc fn _start() -> noreturn { | ... | @@ -43,29 +42,55 @@ nakedcc fn _start() -> noreturn { |
| 43 | extern fn WinMainCRTStartup() -> noreturn { | 42 | extern fn WinMainCRTStartup() -> noreturn { |
| 44 | @setAlignStack(16); | 43 | @setAlignStack(16); |
| 45 | 44 | ||
| 46 | root.main() catch std.os.windows.ExitProcess(1); | 45 | std.os.windows.ExitProcess(callMain()); |
| 47 | std.os.windows.ExitProcess(0); | ||
| 48 | } | 46 | } |
| 49 | 47 | ||
| 50 | fn posixCallMainAndExit() -> noreturn { | 48 | fn posixCallMainAndExit() -> noreturn { |
| 51 | const argc = *argc_ptr; | 49 | const argc = *argc_ptr; |
| 52 | const argv = @ptrCast(&&u8, &argc_ptr[1]); | 50 | const argv = @ptrCast(&&u8, &argc_ptr[1]); |
| 53 | const envp = @ptrCast(&?&u8, &argv[argc + 1]); | 51 | const envp = @ptrCast(&?&u8, &argv[argc + 1]); |
| 54 | callMain(argc, argv, envp) catch std.os.posix.exit(1); | 52 | std.os.posix.exit(callMainWithArgs(argc, argv, envp)); |
| 55 | std.os.posix.exit(0); | ||
| 56 | } | 53 | } |
| 57 | 54 | ||
| 58 | fn callMain(argc: usize, argv: &&u8, envp: &?&u8) -> %void { | 55 | fn callMainWithArgs(argc: usize, argv: &&u8, envp: &?&u8) -> u8 { |
| 59 | std.os.ArgIteratorPosix.raw = argv[0..argc]; | 56 | std.os.ArgIteratorPosix.raw = argv[0..argc]; |
| 60 | 57 | ||
| 61 | var env_count: usize = 0; | 58 | var env_count: usize = 0; |
| 62 | while (envp[env_count] != null) : (env_count += 1) {} | 59 | while (envp[env_count] != null) : (env_count += 1) {} |
| 63 | std.os.posix_environ_raw = @ptrCast(&&u8, envp)[0..env_count]; | 60 | std.os.posix_environ_raw = @ptrCast(&&u8, envp)[0..env_count]; |
| 64 | 61 | ||
| 65 | return root.main(); | 62 | return callMain(); |
| 66 | } | 63 | } |
| 67 | 64 | ||
| 68 | extern fn main(c_argc: i32, c_argv: &&u8, c_envp: &?&u8) -> i32 { | 65 | extern fn main(c_argc: i32, c_argv: &&u8, c_envp: &?&u8) -> i32 { |
| 69 | callMain(usize(c_argc), c_argv, c_envp) catch return 1; | 66 | return callMainWithArgs(usize(c_argc), c_argv, c_envp); |
| 70 | return 0; | 67 | } |
| 68 | |||
| 69 | fn callMain() -> u8 { | ||
| 70 | switch (@typeId(@typeOf(root.main).ReturnType)) { | ||
| 71 | builtin.TypeId.NoReturn => { | ||
| 72 | root.main(); | ||
| 73 | }, | ||
| 74 | builtin.TypeId.Void => { | ||
| 75 | root.main(); | ||
| 76 | return 0; | ||
| 77 | }, | ||
| 78 | builtin.TypeId.Int => { | ||
| 79 | if (@typeOf(root.main).ReturnType.bit_count != 8) { | ||
| 80 | @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '%void'"); | ||
| 81 | } | ||
| 82 | return root.main(); | ||
| 83 | }, | ||
| 84 | builtin.TypeId.ErrorUnion => { | ||
| 85 | root.main() catch |err| { | ||
| 86 | std.debug.warn("error: {}\n", @errorName(err)); | ||
| 87 | if (@errorReturnTrace()) |trace| { | ||
| 88 | std.debug.dumpStackTrace(trace); | ||
| 89 | } | ||
| 90 | return 1; | ||
| 91 | }; | ||
| 92 | return 0; | ||
| 93 | }, | ||
| 94 | else => @compileError("expected return type of main to be 'u8', 'noreturn', 'void', or '%void'"), | ||
| 95 | } | ||
| 71 | } | 96 | } |
std/special/build_runner.zig+4-4| ... | @@ -14,7 +14,7 @@ pub fn main() -> %void { | ... | @@ -14,7 +14,7 @@ pub fn main() -> %void { |
| 14 | var arg_it = os.args(); | 14 | var arg_it = os.args(); |
| 15 | 15 | ||
| 16 | // TODO use a more general purpose allocator here | 16 | // TODO use a more general purpose allocator here |
| 17 | var inc_allocator = std.heap.IncrementingAllocator.init(40 * 1024 * 1024) catch unreachable; | 17 | var inc_allocator = try std.heap.IncrementingAllocator.init(40 * 1024 * 1024); |
| 18 | defer inc_allocator.deinit(); | 18 | defer inc_allocator.deinit(); |
| 19 | 19 | ||
| 20 | const allocator = &inc_allocator.allocator; | 20 | const allocator = &inc_allocator.allocator; |
| ... | @@ -107,12 +107,12 @@ pub fn main() -> %void { | ... | @@ -107,12 +107,12 @@ pub fn main() -> %void { |
| 107 | return usageAndErr(&builder, false, try stderr_stream); | 107 | return usageAndErr(&builder, false, try stderr_stream); |
| 108 | } | 108 | } |
| 109 | } else { | 109 | } else { |
| 110 | targets.append(arg) catch unreachable; | 110 | try targets.append(arg); |
| 111 | } | 111 | } |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | builder.setInstallPrefix(prefix); | 114 | builder.setInstallPrefix(prefix); |
| 115 | root.build(&builder); | 115 | try root.build(&builder); |
| 116 | 116 | ||
| 117 | if (builder.validateUserInputDidItFail()) | 117 | if (builder.validateUserInputDidItFail()) |
| 118 | return usageAndErr(&builder, true, try stderr_stream); | 118 | return usageAndErr(&builder, true, try stderr_stream); |
| ... | @@ -129,7 +129,7 @@ fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream) | ... | @@ -129,7 +129,7 @@ fn usage(builder: &Builder, already_ran_build: bool, out_stream: &io.OutStream) |
| 129 | // run the build script to collect the options | 129 | // run the build script to collect the options |
| 130 | if (!already_ran_build) { | 130 | if (!already_ran_build) { |
| 131 | builder.setInstallPrefix(null); | 131 | builder.setInstallPrefix(null); |
| 132 | root.build(builder); | 132 | try root.build(builder); |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | // This usage text has to be synchronized with src/main.cpp | 135 | // This usage text has to be synchronized with src/main.cpp |
std/special/builtin.zig+1-1| ... | @@ -5,7 +5,7 @@ const builtin = @import("builtin"); | ... | @@ -5,7 +5,7 @@ const builtin = @import("builtin"); |
| 5 | 5 | ||
| 6 | // Avoid dragging in the debug safety mechanisms into this .o file, | 6 | // Avoid dragging in the debug safety mechanisms into this .o file, |
| 7 | // unless we're trying to test this file. | 7 | // unless we're trying to test this file. |
| 8 | pub coldcc fn panic(msg: []const u8) -> noreturn { | 8 | pub coldcc fn panic(msg: []const u8, error_return_trace: ?&builtin.StackTrace) -> noreturn { |
| 9 | if (builtin.is_test) { | 9 | if (builtin.is_test) { |
| 10 | @import("std").debug.panic("{}", msg); | 10 | @import("std").debug.panic("{}", msg); |
| 11 | } else { | 11 | } else { |
std/special/compiler_rt/index.zig+1-1| ... | @@ -74,7 +74,7 @@ const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4; | ... | @@ -74,7 +74,7 @@ const __udivmoddi4 = @import("udivmoddi4.zig").__udivmoddi4; |
| 74 | 74 | ||
| 75 | // Avoid dragging in the debug safety mechanisms into this .o file, | 75 | // Avoid dragging in the debug safety mechanisms into this .o file, |
| 76 | // unless we're trying to test this file. | 76 | // unless we're trying to test this file. |
| 77 | pub coldcc fn panic(msg: []const u8) -> noreturn { | 77 | pub coldcc fn panic(msg: []const u8, error_return_trace: ?&builtin.StackTrace) -> noreturn { |
| 78 | if (is_test) { | 78 | if (is_test) { |
| 79 | @import("std").debug.panic("{}", msg); | 79 | @import("std").debug.panic("{}", msg); |
| 80 | } else { | 80 | } else { |
std/special/panic.zig+5-1| ... | @@ -4,14 +4,18 @@ | ... | @@ -4,14 +4,18 @@ |
| 4 | // have to be added in the compiler. | 4 | // have to be added in the compiler. |
| 5 | 5 | ||
| 6 | const builtin = @import("builtin"); | 6 | const builtin = @import("builtin"); |
| 7 | const std = @import("std"); | ||
| 7 | 8 | ||
| 8 | pub coldcc fn panic(msg: []const u8) -> noreturn { | 9 | pub coldcc fn panic(msg: []const u8, error_return_trace: ?&builtin.StackTrace) -> noreturn { |
| 9 | switch (builtin.os) { | 10 | switch (builtin.os) { |
| 10 | // TODO: fix panic in zen. | 11 | // TODO: fix panic in zen. |
| 11 | builtin.Os.freestanding, builtin.Os.zen => { | 12 | builtin.Os.freestanding, builtin.Os.zen => { |
| 12 | while (true) {} | 13 | while (true) {} |
| 13 | }, | 14 | }, |
| 14 | else => { | 15 | else => { |
| 16 | if (error_return_trace) |trace| { | ||
| 17 | @import("std").debug.panicWithTrace(trace, "{}", msg); | ||
| 18 | } | ||
| 15 | @import("std").debug.panic("{}", msg); | 19 | @import("std").debug.panic("{}", msg); |
| 16 | }, | 20 | }, |
| 17 | } | 21 | } |
std/special/test_runner.zig+1-4| ... | @@ -8,10 +8,7 @@ pub fn main() -> %void { | ... | @@ -8,10 +8,7 @@ pub fn main() -> %void { |
| 8 | for (test_fn_list) |test_fn, i| { | 8 | for (test_fn_list) |test_fn, i| { |
| 9 | warn("Test {}/{} {}...", i + 1, test_fn_list.len, test_fn.name); | 9 | warn("Test {}/{} {}...", i + 1, test_fn_list.len, test_fn.name); |
| 10 | 10 | ||
| 11 | test_fn.func() catch |err| { | 11 | try test_fn.func(); |
| 12 | warn("{}\n", err); | ||
| 13 | return err; | ||
| 14 | }; | ||
| 15 | 12 | ||
| 16 | warn("OK\n"); | 13 | warn("OK\n"); |
| 17 | } | 14 | } |
test/build_examples.zig+1| ... | @@ -16,4 +16,5 @@ pub fn addCases(cases: &tests.BuildExamplesContext) { | ... | @@ -16,4 +16,5 @@ pub fn addCases(cases: &tests.BuildExamplesContext) { |
| 16 | cases.addBuildFile("test/standalone/issue_339/build.zig"); | 16 | cases.addBuildFile("test/standalone/issue_339/build.zig"); |
| 17 | cases.addBuildFile("test/standalone/pkg_import/build.zig"); | 17 | cases.addBuildFile("test/standalone/pkg_import/build.zig"); |
| 18 | cases.addBuildFile("test/standalone/use_alias/build.zig"); | 18 | cases.addBuildFile("test/standalone/use_alias/build.zig"); |
| 19 | cases.addBuildFile("test/standalone/brace_expansion/build.zig"); | ||
| 19 | } | 20 | } |
test/compile_errors.zig+9-9| ... | @@ -1,6 +1,15 @@ | ... | @@ -1,6 +1,15 @@ |
| 1 | const tests = @import("tests.zig"); | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | ||
| 3 | pub fn addCases(cases: &tests.CompileErrorContext) { | 3 | pub fn addCases(cases: &tests.CompileErrorContext) { |
| 4 | cases.add("wrong return type for main", | ||
| 5 | \\pub fn main() -> f32 { } | ||
| 6 | , "error: expected return type of main to be 'u8', 'noreturn', 'void', or '%void'"); | ||
| 7 | |||
| 8 | cases.add("double ?? on main return value", | ||
| 9 | \\pub fn main() -> ??void { | ||
| 10 | \\} | ||
| 11 | , "error: expected return type of main to be 'u8', 'noreturn', 'void', or '%void'"); | ||
| 12 | |||
| 4 | cases.add("bad identifier in function with struct defined inside function which references local const", | 13 | cases.add("bad identifier in function with struct defined inside function which references local const", |
| 5 | \\export fn entry() { | 14 | \\export fn entry() { |
| 6 | \\ const BlockKind = u32; | 15 | \\ const BlockKind = u32; |
| ... | @@ -1059,15 +1068,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) { | ... | @@ -1059,15 +1068,6 @@ pub fn addCases(cases: &tests.CompileErrorContext) { |
| 1059 | , | 1068 | , |
| 1060 | ".tmp_source.zig:2:5: error: expected type 'void', found 'error'"); | 1069 | ".tmp_source.zig:2:5: error: expected type 'void', found 'error'"); |
| 1061 | 1070 | ||
| 1062 | cases.add("wrong return type for main", | ||
| 1063 | \\pub fn main() { } | ||
| 1064 | , ".tmp_source.zig:1:15: error: expected return type of main to be '%void', instead is 'void'"); | ||
| 1065 | |||
| 1066 | cases.add("double ?? on main return value", | ||
| 1067 | \\pub fn main() -> ??void { | ||
| 1068 | \\} | ||
| 1069 | , ".tmp_source.zig:1:18: error: expected return type of main to be '%void', instead is '??void'"); | ||
| 1070 | |||
| 1071 | cases.add("invalid pointer for var type", | 1071 | cases.add("invalid pointer for var type", |
| 1072 | \\extern fn ext() -> usize; | 1072 | \\extern fn ext() -> usize; |
| 1073 | \\var bytes: [ext()]u8 = undefined; | 1073 | \\var bytes: [ext()]u8 = undefined; |
test/debug_safety.zig+20-20| ... | @@ -2,7 +2,7 @@ const tests = @import("tests.zig"); | ... | @@ -2,7 +2,7 @@ const tests = @import("tests.zig"); |
| 2 | 2 | ||
| 3 | pub fn addCases(cases: &tests.CompareOutputContext) { | 3 | pub fn addCases(cases: &tests.CompareOutputContext) { |
| 4 | cases.addDebugSafety("calling panic", | 4 | cases.addDebugSafety("calling panic", |
| 5 | \\pub fn panic(message: []const u8) -> noreturn { | 5 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 6 | \\ @import("std").os.exit(126); | 6 | \\ @import("std").os.exit(126); |
| 7 | \\} | 7 | \\} |
| 8 | \\pub fn main() -> %void { | 8 | \\pub fn main() -> %void { |
| ... | @@ -11,7 +11,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -11,7 +11,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 11 | ); | 11 | ); |
| 12 | 12 | ||
| 13 | cases.addDebugSafety("out of bounds slice access", | 13 | cases.addDebugSafety("out of bounds slice access", |
| 14 | \\pub fn panic(message: []const u8) -> noreturn { | 14 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 15 | \\ @import("std").os.exit(126); | 15 | \\ @import("std").os.exit(126); |
| 16 | \\} | 16 | \\} |
| 17 | \\pub fn main() -> %void { | 17 | \\pub fn main() -> %void { |
| ... | @@ -25,7 +25,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -25,7 +25,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 25 | ); | 25 | ); |
| 26 | 26 | ||
| 27 | cases.addDebugSafety("integer addition overflow", | 27 | cases.addDebugSafety("integer addition overflow", |
| 28 | \\pub fn panic(message: []const u8) -> noreturn { | 28 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 29 | \\ @import("std").os.exit(126); | 29 | \\ @import("std").os.exit(126); |
| 30 | \\} | 30 | \\} |
| 31 | \\error Whatever; | 31 | \\error Whatever; |
| ... | @@ -39,7 +39,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -39,7 +39,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 39 | ); | 39 | ); |
| 40 | 40 | ||
| 41 | cases.addDebugSafety("integer subtraction overflow", | 41 | cases.addDebugSafety("integer subtraction overflow", |
| 42 | \\pub fn panic(message: []const u8) -> noreturn { | 42 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 43 | \\ @import("std").os.exit(126); | 43 | \\ @import("std").os.exit(126); |
| 44 | \\} | 44 | \\} |
| 45 | \\error Whatever; | 45 | \\error Whatever; |
| ... | @@ -53,7 +53,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -53,7 +53,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 53 | ); | 53 | ); |
| 54 | 54 | ||
| 55 | cases.addDebugSafety("integer multiplication overflow", | 55 | cases.addDebugSafety("integer multiplication overflow", |
| 56 | \\pub fn panic(message: []const u8) -> noreturn { | 56 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 57 | \\ @import("std").os.exit(126); | 57 | \\ @import("std").os.exit(126); |
| 58 | \\} | 58 | \\} |
| 59 | \\error Whatever; | 59 | \\error Whatever; |
| ... | @@ -67,7 +67,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -67,7 +67,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 67 | ); | 67 | ); |
| 68 | 68 | ||
| 69 | cases.addDebugSafety("integer negation overflow", | 69 | cases.addDebugSafety("integer negation overflow", |
| 70 | \\pub fn panic(message: []const u8) -> noreturn { | 70 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 71 | \\ @import("std").os.exit(126); | 71 | \\ @import("std").os.exit(126); |
| 72 | \\} | 72 | \\} |
| 73 | \\error Whatever; | 73 | \\error Whatever; |
| ... | @@ -81,7 +81,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -81,7 +81,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 81 | ); | 81 | ); |
| 82 | 82 | ||
| 83 | cases.addDebugSafety("signed integer division overflow", | 83 | cases.addDebugSafety("signed integer division overflow", |
| 84 | \\pub fn panic(message: []const u8) -> noreturn { | 84 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 85 | \\ @import("std").os.exit(126); | 85 | \\ @import("std").os.exit(126); |
| 86 | \\} | 86 | \\} |
| 87 | \\error Whatever; | 87 | \\error Whatever; |
| ... | @@ -95,7 +95,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -95,7 +95,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 95 | ); | 95 | ); |
| 96 | 96 | ||
| 97 | cases.addDebugSafety("signed shift left overflow", | 97 | cases.addDebugSafety("signed shift left overflow", |
| 98 | \\pub fn panic(message: []const u8) -> noreturn { | 98 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 99 | \\ @import("std").os.exit(126); | 99 | \\ @import("std").os.exit(126); |
| 100 | \\} | 100 | \\} |
| 101 | \\error Whatever; | 101 | \\error Whatever; |
| ... | @@ -109,7 +109,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -109,7 +109,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 109 | ); | 109 | ); |
| 110 | 110 | ||
| 111 | cases.addDebugSafety("unsigned shift left overflow", | 111 | cases.addDebugSafety("unsigned shift left overflow", |
| 112 | \\pub fn panic(message: []const u8) -> noreturn { | 112 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 113 | \\ @import("std").os.exit(126); | 113 | \\ @import("std").os.exit(126); |
| 114 | \\} | 114 | \\} |
| 115 | \\error Whatever; | 115 | \\error Whatever; |
| ... | @@ -123,7 +123,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -123,7 +123,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 123 | ); | 123 | ); |
| 124 | 124 | ||
| 125 | cases.addDebugSafety("signed shift right overflow", | 125 | cases.addDebugSafety("signed shift right overflow", |
| 126 | \\pub fn panic(message: []const u8) -> noreturn { | 126 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 127 | \\ @import("std").os.exit(126); | 127 | \\ @import("std").os.exit(126); |
| 128 | \\} | 128 | \\} |
| 129 | \\error Whatever; | 129 | \\error Whatever; |
| ... | @@ -137,7 +137,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -137,7 +137,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 137 | ); | 137 | ); |
| 138 | 138 | ||
| 139 | cases.addDebugSafety("unsigned shift right overflow", | 139 | cases.addDebugSafety("unsigned shift right overflow", |
| 140 | \\pub fn panic(message: []const u8) -> noreturn { | 140 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 141 | \\ @import("std").os.exit(126); | 141 | \\ @import("std").os.exit(126); |
| 142 | \\} | 142 | \\} |
| 143 | \\error Whatever; | 143 | \\error Whatever; |
| ... | @@ -151,7 +151,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -151,7 +151,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 151 | ); | 151 | ); |
| 152 | 152 | ||
| 153 | cases.addDebugSafety("integer division by zero", | 153 | cases.addDebugSafety("integer division by zero", |
| 154 | \\pub fn panic(message: []const u8) -> noreturn { | 154 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 155 | \\ @import("std").os.exit(126); | 155 | \\ @import("std").os.exit(126); |
| 156 | \\} | 156 | \\} |
| 157 | \\error Whatever; | 157 | \\error Whatever; |
| ... | @@ -164,7 +164,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -164,7 +164,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 164 | ); | 164 | ); |
| 165 | 165 | ||
| 166 | cases.addDebugSafety("exact division failure", | 166 | cases.addDebugSafety("exact division failure", |
| 167 | \\pub fn panic(message: []const u8) -> noreturn { | 167 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 168 | \\ @import("std").os.exit(126); | 168 | \\ @import("std").os.exit(126); |
| 169 | \\} | 169 | \\} |
| 170 | \\error Whatever; | 170 | \\error Whatever; |
| ... | @@ -178,7 +178,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -178,7 +178,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 178 | ); | 178 | ); |
| 179 | 179 | ||
| 180 | cases.addDebugSafety("cast []u8 to bigger slice of wrong size", | 180 | cases.addDebugSafety("cast []u8 to bigger slice of wrong size", |
| 181 | \\pub fn panic(message: []const u8) -> noreturn { | 181 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 182 | \\ @import("std").os.exit(126); | 182 | \\ @import("std").os.exit(126); |
| 183 | \\} | 183 | \\} |
| 184 | \\error Whatever; | 184 | \\error Whatever; |
| ... | @@ -192,7 +192,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -192,7 +192,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 192 | ); | 192 | ); |
| 193 | 193 | ||
| 194 | cases.addDebugSafety("value does not fit in shortening cast", | 194 | cases.addDebugSafety("value does not fit in shortening cast", |
| 195 | \\pub fn panic(message: []const u8) -> noreturn { | 195 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 196 | \\ @import("std").os.exit(126); | 196 | \\ @import("std").os.exit(126); |
| 197 | \\} | 197 | \\} |
| 198 | \\error Whatever; | 198 | \\error Whatever; |
| ... | @@ -206,7 +206,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -206,7 +206,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 206 | ); | 206 | ); |
| 207 | 207 | ||
| 208 | cases.addDebugSafety("signed integer not fitting in cast to unsigned integer", | 208 | cases.addDebugSafety("signed integer not fitting in cast to unsigned integer", |
| 209 | \\pub fn panic(message: []const u8) -> noreturn { | 209 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 210 | \\ @import("std").os.exit(126); | 210 | \\ @import("std").os.exit(126); |
| 211 | \\} | 211 | \\} |
| 212 | \\error Whatever; | 212 | \\error Whatever; |
| ... | @@ -220,7 +220,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -220,7 +220,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 220 | ); | 220 | ); |
| 221 | 221 | ||
| 222 | cases.addDebugSafety("unwrap error", | 222 | cases.addDebugSafety("unwrap error", |
| 223 | \\pub fn panic(message: []const u8) -> noreturn { | 223 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 224 | \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) { | 224 | \\ if (@import("std").mem.eql(u8, message, "attempt to unwrap error: Whatever")) { |
| 225 | \\ @import("std").os.exit(126); // good | 225 | \\ @import("std").os.exit(126); // good |
| 226 | \\ } | 226 | \\ } |
| ... | @@ -236,7 +236,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -236,7 +236,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 236 | ); | 236 | ); |
| 237 | 237 | ||
| 238 | cases.addDebugSafety("cast integer to error and no code matches", | 238 | cases.addDebugSafety("cast integer to error and no code matches", |
| 239 | \\pub fn panic(message: []const u8) -> noreturn { | 239 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 240 | \\ @import("std").os.exit(126); | 240 | \\ @import("std").os.exit(126); |
| 241 | \\} | 241 | \\} |
| 242 | \\pub fn main() -> %void { | 242 | \\pub fn main() -> %void { |
| ... | @@ -248,7 +248,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -248,7 +248,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 248 | ); | 248 | ); |
| 249 | 249 | ||
| 250 | cases.addDebugSafety("@alignCast misaligned", | 250 | cases.addDebugSafety("@alignCast misaligned", |
| 251 | \\pub fn panic(message: []const u8) -> noreturn { | 251 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 252 | \\ @import("std").os.exit(126); | 252 | \\ @import("std").os.exit(126); |
| 253 | \\} | 253 | \\} |
| 254 | \\error Wrong; | 254 | \\error Wrong; |
| ... | @@ -265,7 +265,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { | ... | @@ -265,7 +265,7 @@ pub fn addCases(cases: &tests.CompareOutputContext) { |
| 265 | ); | 265 | ); |
| 266 | 266 | ||
| 267 | cases.addDebugSafety("bad union field access", | 267 | cases.addDebugSafety("bad union field access", |
| 268 | \\pub fn panic(message: []const u8) -> noreturn { | 268 | \\pub fn panic(message: []const u8, stack_trace: ?&@import("builtin").StackTrace) -> noreturn { |
| 269 | \\ @import("std").os.exit(126); | 269 | \\ @import("std").os.exit(126); |
| 270 | \\} | 270 | \\} |
| 271 | \\ | 271 | \\ |
test/standalone/brace_expansion/build.zig created+9| ... | @@ -0,0 +1,9 @@ | ||
| 1 | const Builder = @import("std").build.Builder; | ||
| 2 | |||
| 3 | pub fn build(b: &Builder) -> %void { | ||
| 4 | const main = b.addTest("main.zig"); | ||
| 5 | main.setBuildMode(b.standardReleaseOptions()); | ||
| 6 | |||
| 7 | const test_step = b.step("test", "Test it"); | ||
| 8 | test_step.dependOn(&main.step); | ||
| 9 | } | ||
test/standalone/brace_expansion/main.zig created+254| ... | @@ -0,0 +1,254 @@ | ||
| 1 | const std = @import("std"); | ||
| 2 | const io = std.io; | ||
| 3 | const mem = std.mem; | ||
| 4 | const debug = std.debug; | ||
| 5 | const assert = debug.assert; | ||
| 6 | const Buffer = std.Buffer; | ||
| 7 | const ArrayList = std.ArrayList; | ||
| 8 | |||
| 9 | error InvalidInput; | ||
| 10 | error OutOfMem; | ||
| 11 | |||
| 12 | const Token = union(enum) { | ||
| 13 | Word: []const u8, | ||
| 14 | OpenBrace, | ||
| 15 | CloseBrace, | ||
| 16 | Comma, | ||
| 17 | Eof, | ||
| 18 | }; | ||
| 19 | |||
| 20 | var global_allocator: &mem.Allocator = undefined; | ||
| 21 | |||
| 22 | fn tokenize(input:[] const u8) -> %ArrayList(Token) { | ||
| 23 | const State = enum { | ||
| 24 | Start, | ||
| 25 | Word, | ||
| 26 | }; | ||
| 27 | |||
| 28 | var token_list = ArrayList(Token).init(global_allocator); | ||
| 29 | var tok_begin: usize = undefined; | ||
| 30 | var state = State.Start; | ||
| 31 | |||
| 32 | for (input) |b, i| { | ||
| 33 | switch (state) { | ||
| 34 | State.Start => switch (b) { | ||
| 35 | 'a'...'z', 'A'...'Z' => { | ||
| 36 | state = State.Word; | ||
| 37 | tok_begin = i; | ||
| 38 | }, | ||
| 39 | '{' => try token_list.append(Token.OpenBrace), | ||
| 40 | '}' => try token_list.append(Token.CloseBrace), | ||
| 41 | ',' => try token_list.append(Token.Comma), | ||
| 42 | else => return error.InvalidInput, | ||
| 43 | }, | ||
| 44 | State.Word => switch (b) { | ||
| 45 | 'a'...'z', 'A'...'Z' => {}, | ||
| 46 | '{', '}', ',' => { | ||
| 47 | try token_list.append(Token { .Word = input[tok_begin..i] }); | ||
| 48 | switch (b) { | ||
| 49 | '{' => try token_list.append(Token.OpenBrace), | ||
| 50 | '}' => try token_list.append(Token.CloseBrace), | ||
| 51 | ',' => try token_list.append(Token.Comma), | ||
| 52 | else => unreachable, | ||
| 53 | } | ||
| 54 | state = State.Start; | ||
| 55 | }, | ||
| 56 | else => return error.InvalidInput, | ||
| 57 | }, | ||
| 58 | } | ||
| 59 | } | ||
| 60 | switch (state) { | ||
| 61 | State.Start => {}, | ||
| 62 | State.Word => try token_list.append(Token {.Word = input[tok_begin..] }), | ||
| 63 | } | ||
| 64 | try token_list.append(Token.Eof); | ||
| 65 | return token_list; | ||
| 66 | } | ||
| 67 | |||
| 68 | const Node = union(enum) { | ||
| 69 | Scalar: []const u8, | ||
| 70 | List: ArrayList(Node), | ||
| 71 | Combine: []Node, | ||
| 72 | }; | ||
| 73 | |||
| 74 | fn parse(tokens: &const ArrayList(Token), token_index: &usize) -> %Node { | ||
| 75 | const first_token = tokens.items[*token_index]; | ||
| 76 | *token_index += 1; | ||
| 77 | |||
| 78 | const result_node = switch (first_token) { | ||
| 79 | Token.Word => |word| Node { .Scalar = word }, | ||
| 80 | Token.OpenBrace => blk: { | ||
| 81 | var list = ArrayList(Node).init(global_allocator); | ||
| 82 | while (true) { | ||
| 83 | try list.append(try parse(tokens, token_index)); | ||
| 84 | |||
| 85 | const token = tokens.items[*token_index]; | ||
| 86 | *token_index += 1; | ||
| 87 | |||
| 88 | switch (token) { | ||
| 89 | Token.CloseBrace => break, | ||
| 90 | Token.Comma => continue, | ||
| 91 | else => return error.InvalidInput, | ||
| 92 | } | ||
| 93 | } | ||
| 94 | break :blk Node { .List = list }; | ||
| 95 | }, | ||
| 96 | else => return error.InvalidInput, | ||
| 97 | }; | ||
| 98 | |||
| 99 | switch (tokens.items[*token_index]) { | ||
| 100 | Token.Word, Token.OpenBrace => { | ||
| 101 | const pair = try global_allocator.alloc(Node, 2); | ||
| 102 | pair[0] = result_node; | ||
| 103 | pair[1] = try parse(tokens, token_index); | ||
| 104 | return Node { .Combine = pair }; | ||
| 105 | }, | ||
| 106 | else => return result_node, | ||
| 107 | } | ||
| 108 | } | ||
| 109 | |||
| 110 | fn expandString(input: []const u8, output: &Buffer) -> %void { | ||
| 111 | const tokens = try tokenize(input); | ||
| 112 | if (tokens.len == 1) { | ||
| 113 | return output.resize(0); | ||
| 114 | } | ||
| 115 | |||
| 116 | var token_index: usize = 0; | ||
| 117 | const root = try parse(tokens, &token_index); | ||
| 118 | const last_token = tokens.items[token_index]; | ||
| 119 | switch (last_token) { | ||
| 120 | Token.Eof => {}, | ||
| 121 | else => return error.InvalidInput, | ||
| 122 | } | ||
| 123 | |||
| 124 | var result_list = ArrayList(Buffer).init(global_allocator); | ||
| 125 | defer result_list.deinit(); | ||
| 126 | |||
| 127 | try expandNode(root, &result_list); | ||
| 128 | |||
| 129 | try output.resize(0); | ||
| 130 | for (result_list.toSliceConst()) |buf, i| { | ||
| 131 | if (i != 0) { | ||
| 132 | try output.appendByte(' '); | ||
| 133 | } | ||
| 134 | try output.append(buf.toSliceConst()); | ||
| 135 | } | ||
| 136 | } | ||
| 137 | |||
| 138 | const ListOfBuffer0 = ArrayList(Buffer); // TODO this is working around a compiler bug, fix and delete this | ||
| 139 | |||
| 140 | fn expandNode(node: &const Node, output: &ListOfBuffer0) -> %void { | ||
| 141 | assert(output.len == 0); | ||
| 142 | switch (*node) { | ||
| 143 | Node.Scalar => |scalar| { | ||
| 144 | try output.append(try Buffer.init(global_allocator, scalar)); | ||
| 145 | }, | ||
| 146 | Node.Combine => |pair| { | ||
| 147 | const a_node = pair[0]; | ||
| 148 | const b_node = pair[1]; | ||
| 149 | |||
| 150 | var child_list_a = ArrayList(Buffer).init(global_allocator); | ||
| 151 | try expandNode(a_node, &child_list_a); | ||
| 152 | |||
| 153 | var child_list_b = ArrayList(Buffer).init(global_allocator); | ||
| 154 | try expandNode(b_node, &child_list_b); | ||
| 155 | |||
| 156 | for (child_list_a.toSliceConst()) |buf_a| { | ||
| 157 | for (child_list_b.toSliceConst()) |buf_b| { | ||
| 158 | var combined_buf = try Buffer.initFromBuffer(buf_a); | ||
| 159 | try combined_buf.append(buf_b.toSliceConst()); | ||
| 160 | try output.append(combined_buf); | ||
| 161 | } | ||
| 162 | } | ||
| 163 | }, | ||
| 164 | Node.List => |list| { | ||
| 165 | for (list.toSliceConst()) |child_node| { | ||
| 166 | var child_list = ArrayList(Buffer).init(global_allocator); | ||
| 167 | try expandNode(child_node, &child_list); | ||
| 168 | |||
| 169 | for (child_list.toSliceConst()) |buf| { | ||
| 170 | try output.append(buf); | ||
| 171 | } | ||
| 172 | } | ||
| 173 | }, | ||
| 174 | } | ||
| 175 | } | ||
| 176 | |||
| 177 | pub fn main() -> %void { | ||
| 178 | var stdin_file = try io.getStdIn(); | ||
| 179 | var stdout_file = try io.getStdOut(); | ||
| 180 | |||
| 181 | var inc_allocator = try std.heap.IncrementingAllocator.init(2 * 1024 * 1024); | ||
| 182 | defer inc_allocator.deinit(); | ||
| 183 | |||
| 184 | global_allocator = &inc_allocator.allocator; | ||
| 185 | |||
| 186 | var stdin_buf = try Buffer.initSize(global_allocator, 0); | ||
| 187 | defer stdin_buf.deinit(); | ||
| 188 | |||
| 189 | var stdin_adapter = io.FileInStream.init(&stdin_file); | ||
| 190 | try stdin_adapter.stream.readAllBuffer(&stdin_buf, @maxValue(usize)); | ||
| 191 | |||
| 192 | var result_buf = try Buffer.initSize(global_allocator, 0); | ||
| 193 | defer result_buf.deinit(); | ||
| 194 | |||
| 195 | try expandString(stdin_buf.toSlice(), &result_buf); | ||
| 196 | try stdout_file.write(result_buf.toSliceConst()); | ||
| 197 | } | ||
| 198 | |||
| 199 | test "invalid inputs" { | ||
| 200 | global_allocator = std.debug.global_allocator; | ||
| 201 | |||
| 202 | expectError("}ABC", error.InvalidInput); | ||
| 203 | expectError("{ABC", error.InvalidInput); | ||
| 204 | expectError("}{", error.InvalidInput); | ||
| 205 | expectError("{}", error.InvalidInput); | ||
| 206 | expectError("A,B,C", error.InvalidInput); | ||
| 207 | expectError("{A{B,C}", error.InvalidInput); | ||
| 208 | expectError("{A,}", error.InvalidInput); | ||
| 209 | |||
| 210 | expectError("\n", error.InvalidInput); | ||
| 211 | } | ||
| 212 | |||
| 213 | fn expectError(test_input: []const u8, expected_err: error) { | ||
| 214 | var output_buf = Buffer.initSize(global_allocator, 0) catch unreachable; | ||
| 215 | defer output_buf.deinit(); | ||
| 216 | |||
| 217 | if (expandString("}ABC", &output_buf)) { | ||
| 218 | unreachable; | ||
| 219 | } else |err| { | ||
| 220 | assert(expected_err == err); | ||
| 221 | } | ||
| 222 | } | ||
| 223 | |||
| 224 | test "valid inputs" { | ||
| 225 | global_allocator = std.debug.global_allocator; | ||
| 226 | |||
| 227 | expectExpansion("{x,y,z}", "x y z"); | ||
| 228 | expectExpansion("{A,B}{x,y}", "Ax Ay Bx By"); | ||
| 229 | expectExpansion("{A,B{x,y}}", "A Bx By"); | ||
| 230 | |||
| 231 | expectExpansion("{ABC}", "ABC"); | ||
| 232 | expectExpansion("{A,B,C}", "A B C"); | ||
| 233 | expectExpansion("ABC", "ABC"); | ||
| 234 | |||
| 235 | expectExpansion("", ""); | ||
| 236 | expectExpansion("{A,B}{C,{x,y}}{g,h}", "ACg ACh Axg Axh Ayg Ayh BCg BCh Bxg Bxh Byg Byh"); | ||
| 237 | expectExpansion("{A,B}{C,C{x,y}}{g,h}", "ACg ACh ACxg ACxh ACyg ACyh BCg BCh BCxg BCxh BCyg BCyh"); | ||
| 238 | expectExpansion("{A,B}a", "Aa Ba"); | ||
| 239 | expectExpansion("{C,{x,y}}", "C x y"); | ||
| 240 | expectExpansion("z{C,{x,y}}", "zC zx zy"); | ||
| 241 | expectExpansion("a{b,c{d,e{f,g}}}", "ab acd acef aceg"); | ||
| 242 | expectExpansion("a{x,y}b", "axb ayb"); | ||
| 243 | expectExpansion("z{{a,b}}", "za zb"); | ||
| 244 | expectExpansion("a{b}", "ab"); | ||
| 245 | } | ||
| 246 | |||
| 247 | fn expectExpansion(test_input: []const u8, expected_result: []const u8) { | ||
| 248 | var result = Buffer.initSize(global_allocator, 0) catch unreachable; | ||
| 249 | defer result.deinit(); | ||
| 250 | |||
| 251 | expandString(test_input, &result) catch unreachable; | ||
| 252 | |||
| 253 | assert(mem.eql(u8, result.toSlice(), expected_result)); | ||
| 254 | } | ||
test/standalone/issue_339/build.zig+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const Builder = @import("std").build.Builder; | 1 | const Builder = @import("std").build.Builder; |
| 2 | 2 | ||
| 3 | pub fn build(b: &Builder) { | 3 | pub fn build(b: &Builder) -> %void { |
| 4 | const obj = b.addObject("test", "test.zig"); | 4 | const obj = b.addObject("test", "test.zig"); |
| 5 | 5 | ||
| 6 | const test_step = b.step("test", "Test the program"); | 6 | const test_step = b.step("test", "Test the program"); |
test/standalone/issue_339/test.zig+2-1| ... | @@ -1,4 +1,5 @@ | ... | @@ -1,4 +1,5 @@ |
| 1 | pub fn panic(msg: []const u8) -> noreturn { @breakpoint(); while (true) {} } | 1 | const StackTrace = @import("builtin").StackTrace; |
| 2 | pub fn panic(msg: []const u8, stack_trace: ?&StackTrace) -> noreturn { @breakpoint(); while (true) {} } | ||
| 2 | 3 | ||
| 3 | fn bar() -> %void {} | 4 | fn bar() -> %void {} |
| 4 | 5 |
test/standalone/pkg_import/build.zig+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const Builder = @import("std").build.Builder; | 1 | const Builder = @import("std").build.Builder; |
| 2 | 2 | ||
| 3 | pub fn build(b: &Builder) { | 3 | pub fn build(b: &Builder) -> %void { |
| 4 | const exe = b.addExecutable("test", "test.zig"); | 4 | const exe = b.addExecutable("test", "test.zig"); |
| 5 | exe.addPackagePath("my_pkg", "pkg.zig"); | 5 | exe.addPackagePath("my_pkg", "pkg.zig"); |
| 6 | 6 |
test/standalone/use_alias/build.zig+1-1| ... | @@ -1,6 +1,6 @@ | ... | @@ -1,6 +1,6 @@ |
| 1 | const Builder = @import("std").build.Builder; | 1 | const Builder = @import("std").build.Builder; |
| 2 | 2 | ||
| 3 | pub fn build(b: &Builder) { | 3 | pub fn build(b: &Builder) -> %void { |
| 4 | b.addCIncludePath("."); | 4 | b.addCIncludePath("."); |
| 5 | 5 | ||
| 6 | const main = b.addTest("main.zig"); | 6 | const main = b.addTest("main.zig"); |
test/tests.zig+2-7| ... | @@ -42,14 +42,10 @@ const test_targets = []TestTarget { | ... | @@ -42,14 +42,10 @@ const test_targets = []TestTarget { |
| 42 | .arch = builtin.Arch.x86_64, | 42 | .arch = builtin.Arch.x86_64, |
| 43 | .environ = builtin.Environ.msvc, | 43 | .environ = builtin.Environ.msvc, |
| 44 | }, | 44 | }, |
| 45 | TestTarget { | ||
| 46 | .os = builtin.Os.windows, | ||
| 47 | .arch = builtin.Arch.i386, | ||
| 48 | .environ = builtin.Environ.msvc, | ||
| 49 | }, | ||
| 50 | }; | 45 | }; |
| 51 | 46 | ||
| 52 | error TestFailed; | 47 | error TestFailed; |
| 48 | error CompilationIncorrectlySucceeded; | ||
| 53 | 49 | ||
| 54 | const max_stdout_size = 1 * 1024 * 1024; // 1 MB | 50 | const max_stdout_size = 1 * 1024 * 1024; // 1 MB |
| 55 | 51 | ||
| ... | @@ -607,8 +603,7 @@ pub const CompileErrorContext = struct { | ... | @@ -607,8 +603,7 @@ pub const CompileErrorContext = struct { |
| 607 | switch (term) { | 603 | switch (term) { |
| 608 | Term.Exited => |code| { | 604 | Term.Exited => |code| { |
| 609 | if (code == 0) { | 605 | if (code == 0) { |
| 610 | warn("Compilation incorrectly succeeded\n"); | 606 | return error.CompilationIncorrectlySucceeded; |
| 611 | return error.TestFailed; | ||
| 612 | } | 607 | } |
| 613 | }, | 608 | }, |
| 614 | else => { | 609 | else => { |