authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-15 00:01:02-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-01-15 00:01:02-05:00
log7b57454cc11371b71097967656e19f0a1736d733
tree4eff514fcb0a0c1f95ac253624c4f705fe95b03e
parentd973b40884be1c7874805c81981cac7edca5605b

clean up error return tracing

* error return tracing is disabled in release-fast mode * add @errorReturnTrace * zig build API changes build return type from `void` to `%void` * allow `void`, `noreturn`, and `u8` from main. closes #535

22 files changed, 198 insertions(+), 112 deletions(-)

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 no4413 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 @@
1const Builder = @import("std").build.Builder;1const Builder = @import("std").build.Builder;
22
3pub fn build(b: &Builder) {3pub fn build(b: &Builder) -> %void {
4 const obj = b.addObject("base64", "base64.zig");4 const obj = b.addObject("base64", "base64.zig");
55
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 @@
1const Builder = @import("std").build.Builder;1const Builder = @import("std").build.Builder;
22
3pub fn build(b: &Builder) {3pub 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));
55
6 const exe = b.addCExecutable("test");6 const exe = b.addCExecutable("test");
src/all_types.hpp+7
...@@ -1274,6 +1274,7 @@ enum BuiltinFnId {...@@ -1274,6 +1274,7 @@ enum BuiltinFnId {
1274 BuiltinFnIdSetAlignStack,1274 BuiltinFnIdSetAlignStack,
1275 BuiltinFnIdArgType,1275 BuiltinFnIdArgType,
1276 BuiltinFnIdExport,1276 BuiltinFnIdExport,
1277 BuiltinFnIdErrorReturnTrace,
1277};1278};
12781279
1279struct BuiltinFnEntry {1280struct BuiltinFnEntry {
...@@ -1499,6 +1500,7 @@ struct CodeGen {...@@ -1499,6 +1500,7 @@ struct CodeGen {
1499 Buf triple_str;1500 Buf triple_str;
1500 BuildMode build_mode;1501 BuildMode build_mode;
1501 bool is_test_build;1502 bool is_test_build;
1503 bool have_err_ret_tracing;
1502 uint32_t target_os_index;1504 uint32_t target_os_index;
1503 uint32_t target_arch_index;1505 uint32_t target_arch_index;
1504 uint32_t target_environ_index;1506 uint32_t target_environ_index;
...@@ -1902,6 +1904,7 @@ enum IrInstructionId {...@@ -1902,6 +1904,7 @@ enum IrInstructionId {
1902 IrInstructionIdSetAlignStack,1904 IrInstructionIdSetAlignStack,
1903 IrInstructionIdArgType,1905 IrInstructionIdArgType,
1904 IrInstructionIdExport,1906 IrInstructionIdExport,
1907 IrInstructionIdErrorReturnTrace,
1905};1908};
19061909
1907struct IrInstruction {1910struct IrInstruction {
...@@ -2723,6 +2726,10 @@ struct IrInstructionExport {...@@ -2723,6 +2726,10 @@ struct IrInstructionExport {
2723 IrInstruction *target;2726 IrInstruction *target;
2724};2727};
27252728
2729struct IrInstructionErrorReturnTrace {
2730 IrInstruction base;
2731};
2732
2726static const size_t slice_ptr_index = 0;2733static const size_t slice_ptr_index = 0;
2727static const size_t slice_len_index = 1;2734static const size_t slice_len_index = 1;
27282735
src/analyze.cpp+3-9
...@@ -925,8 +925,9 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {...@@ -925,8 +925,9 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
925 if (!skip_debug_info) {925 if (!skip_debug_info) {
926 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) &&
927 handle_is_ptr(fn_type_id->return_type);927 handle_is_ptr(fn_type_id->return_type);
928 bool prefix_arg_error_return_trace = fn_type_id->return_type->id == TypeTableEntryIdErrorUnion || 928 bool prefix_arg_error_return_trace = g->have_err_ret_tracing &&
929 fn_type_id->return_type->id == TypeTableEntryIdPureError;929 (fn_type_id->return_type->id == TypeTableEntryIdErrorUnion ||
930 fn_type_id->return_type->id == TypeTableEntryIdPureError);
930 // +1 for maybe making the first argument the return value931 // +1 for maybe making the first argument the return value
931 // +1 for maybe last argument the error return trace932 // +1 for maybe last argument the error return trace
932 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(2 + fn_type_id->param_count);933 LLVMTypeRef *gen_param_types = allocate<LLVMTypeRef>(2 + fn_type_id->param_count);
...@@ -2711,13 +2712,6 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {...@@ -2711,13 +2712,6 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
2711 {2712 {
2712 if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {2713 if (g->have_pub_main && buf_eql_str(&fn_table_entry->symbol_name, "main")) {
2713 g->main_fn = fn_table_entry;2714 g->main_fn = fn_table_entry;
2714 TypeTableEntry *err_void = get_error_type(g, g->builtin_types.entry_void);
2715 TypeTableEntry *actual_return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type;
2716 if (actual_return_type != err_void) {
2717 add_node_error(g, fn_proto->return_type,
2718 buf_sprintf("expected return type of main to be '%%void', instead is '%s'",
2719 buf_ptr(&actual_return_type->name)));
2720 }
2721 } else if ((import->package == g->panic_package || g->have_pub_panic) &&2715 } else if ((import->package == g->panic_package || g->have_pub_panic) &&
2722 buf_eql_str(&fn_table_entry->symbol_name, "panic"))2716 buf_eql_str(&fn_table_entry->symbol_name, "panic"))
2723 {2717 {
src/codegen.cpp+49-29
...@@ -404,7 +404,10 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) {...@@ -404,7 +404,10 @@ static LLVMLinkage to_llvm_linkage(GlobalLinkageId id) {
404 zig_unreachable();404 zig_unreachable();
405}405}
406406
407static uint32_t get_err_ret_trace_arg_index(FnTableEntry *fn_table_entry) {407static 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 }
408 TypeTableEntry *fn_type = fn_table_entry->type_entry;411 TypeTableEntry *fn_type = fn_table_entry->type_entry;
409 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;412 TypeTableEntry *return_type = fn_type->data.fn.fn_type_id.return_type;
410 if (return_type->id != TypeTableEntryIdErrorUnion && return_type->id != TypeTableEntryIdPureError) {413 if (return_type->id != TypeTableEntryIdErrorUnion && return_type->id != TypeTableEntryIdPureError) {
...@@ -572,7 +575,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {...@@ -572,7 +575,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
572 }575 }
573 }576 }
574577
575 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(fn_table_entry);578 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
576 if (err_ret_trace_arg_index != UINT32_MAX) {579 if (err_ret_trace_arg_index != UINT32_MAX) {
577 addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull");580 addLLVMArgAttr(fn_table_entry->llvm_value, (unsigned)err_ret_trace_arg_index, "nonnull");
578 }581 }
...@@ -1415,31 +1418,33 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns...@@ -1415,31 +1418,33 @@ static LLVMValueRef ir_render_return(CodeGen *g, IrExecutable *executable, IrIns
1415 LLVMValueRef value = ir_llvm_value(g, return_instruction->value);1418 LLVMValueRef value = ir_llvm_value(g, return_instruction->value);
1416 TypeTableEntry *return_type = return_instruction->value->value.type;1419 TypeTableEntry *return_type = return_instruction->value->value.type;
14171420
1418 bool is_err_return = false;1421 if (g->have_err_ret_tracing) {
1419 if (return_type->id == TypeTableEntryIdErrorUnion) {1422 bool is_err_return = false;
1420 if (return_instruction->value->value.special == ConstValSpecialStatic) {1423 if (return_type->id == TypeTableEntryIdErrorUnion) {
1421 is_err_return = return_instruction->value->value.data.x_err_union.err != nullptr;1424 if (return_instruction->value->value.special == ConstValSpecialStatic) {
1422 } else if (return_instruction->value->value.special == ConstValSpecialRuntime) {1425 is_err_return = return_instruction->value->value.data.x_err_union.err != nullptr;
1423 is_err_return = return_instruction->value->value.data.rh_error_union == RuntimeHintErrorUnionError;1426 } else if (return_instruction->value->value.special == ConstValSpecialRuntime) {
1424 // TODO: emit a branch to check if the return value is an error1427 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);
1425 }1447 }
1426 } else if (return_type->id == TypeTableEntryIdPureError) {
1427 is_err_return = true;
1428 }
1429 if (is_err_return) {
1430 LLVMBasicBlockRef return_block = LLVMAppendBasicBlock(g->cur_fn_val, "ReturnError");
1431 LLVMValueRef block_address = LLVMBlockAddress(g->cur_fn_val, return_block);
1432
1433 LLVMValueRef return_err_fn = get_return_err_fn(g);
1434 LLVMValueRef args[] = {
1435 g->cur_err_ret_trace_val,
1436 block_address,
1437 };
1438 LLVMBuildBr(g->builder, return_block);
1439 LLVMPositionBuilderAtEnd(g->builder, return_block);
1440 LLVMValueRef call_instruction = ZigLLVMBuildCall(g->builder, return_err_fn, args, 2,
1441 get_llvm_cc(g, CallingConventionUnspecified), ZigLLVM_FnInlineAuto, "");
1442 LLVMSetTailCall(call_instruction, true);
1443 }1448 }
1444 if (handle_is_ptr(return_type)) {1449 if (handle_is_ptr(return_type)) {
1445 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)) {
...@@ -2475,7 +2480,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -2475,7 +2480,7 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
2475 TypeTableEntry *src_return_type = fn_type_id->return_type;2480 TypeTableEntry *src_return_type = fn_type_id->return_type;
2476 bool ret_has_bits = type_has_bits(src_return_type);2481 bool ret_has_bits = type_has_bits(src_return_type);
2477 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);
2478 bool prefix_arg_err_ret_stack = src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdPureError;2483 bool prefix_arg_err_ret_stack = g->have_err_ret_tracing && (src_return_type->id == TypeTableEntryIdErrorUnion || src_return_type->id == TypeTableEntryIdPureError);
2479 size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0);2484 size_t actual_param_count = instruction->arg_count + (first_arg_ret ? 1 : 0) + (prefix_arg_err_ret_stack ? 1 : 0);
2480 bool is_var_args = fn_type_id->is_var_args;2485 bool is_var_args = fn_type_id->is_var_args;
2481 LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count);2486 LLVMValueRef *gen_param_values = allocate<LLVMValueRef>(actual_param_count);
...@@ -3031,6 +3036,16 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I...@@ -3031,6 +3036,16 @@ static LLVMValueRef ir_render_align_cast(CodeGen *g, IrExecutable *executable, I
3031 return target_val;3036 return target_val;
3032}3037}
30333038
3039static 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
3034static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) {3049static LLVMAtomicOrdering to_LLVMAtomicOrdering(AtomicOrder atomic_order) {
3035 switch (atomic_order) {3050 switch (atomic_order) {
3036 case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered;3051 case AtomicOrderUnordered: return LLVMAtomicOrderingUnordered;
...@@ -3804,6 +3819,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -3804,6 +3819,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
3804 return ir_render_field_parent_ptr(g, executable, (IrInstructionFieldParentPtr *)instruction);3819 return ir_render_field_parent_ptr(g, executable, (IrInstructionFieldParentPtr *)instruction);
3805 case IrInstructionIdAlignCast:3820 case IrInstructionIdAlignCast:
3806 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);
3807 }3824 }
3808 zig_unreachable();3825 zig_unreachable();
3809}3826}
...@@ -4653,10 +4670,10 @@ static void do_code_gen(CodeGen *g) {...@@ -4653,10 +4670,10 @@ static void do_code_gen(CodeGen *g) {
4653 build_all_basic_blocks(g, fn_table_entry);4670 build_all_basic_blocks(g, fn_table_entry);
4654 clear_debug_source_node(g);4671 clear_debug_source_node(g);
46554672
4656 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(fn_table_entry);4673 uint32_t err_ret_trace_arg_index = get_err_ret_trace_arg_index(g, fn_table_entry);
4657 if (err_ret_trace_arg_index != UINT32_MAX) {4674 if (err_ret_trace_arg_index != UINT32_MAX) {
4658 g->cur_err_ret_trace_val = LLVMGetParam(fn, err_ret_trace_arg_index);4675 g->cur_err_ret_trace_val = LLVMGetParam(fn, err_ret_trace_arg_index);
4659 } else if (fn_table_entry->calls_errorable_function) {4676 } else if (g->have_err_ret_tracing && fn_table_entry->calls_errorable_function) {
4660 // TODO call graph analysis to find out what this number needs to be for every function4677 // TODO call graph analysis to find out what this number needs to be for every function
4661 static const size_t stack_trace_ptr_count = 30;4678 static const size_t stack_trace_ptr_count = 30;
46624679
...@@ -5251,6 +5268,7 @@ static void define_builtin_fns(CodeGen *g) {...@@ -5251,6 +5268,7 @@ static void define_builtin_fns(CodeGen *g) {
5251 create_builtin_fn(g, BuiltinFnIdSetAlignStack, "setAlignStack", 1);5268 create_builtin_fn(g, BuiltinFnIdSetAlignStack, "setAlignStack", 1);
5252 create_builtin_fn(g, BuiltinFnIdArgType, "ArgType", 2);5269 create_builtin_fn(g, BuiltinFnIdArgType, "ArgType", 2);
5253 create_builtin_fn(g, BuiltinFnIdExport, "export", 3);5270 create_builtin_fn(g, BuiltinFnIdExport, "export", 3);
5271 create_builtin_fn(g, BuiltinFnIdErrorReturnTrace, "errorReturnTrace", 0);
5254}5272}
52555273
5256static const char *bool_to_str(bool b) {5274static const char *bool_to_str(bool b) {
...@@ -5553,6 +5571,8 @@ static void init(CodeGen *g) {...@@ -5553,6 +5571,8 @@ static void init(CodeGen *g) {
5553 }5571 }
5554 }5572 }
55555573
5574 g->have_err_ret_tracing = g->build_mode != BuildModeFastRelease;
5575
5556 define_builtin_fns(g);5576 define_builtin_fns(g);
5557 define_builtin_compile_vars(g);5577 define_builtin_compile_vars(g);
5558}5578}
src/ir.cpp+35
...@@ -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}
574574
575static constexpr IrInstructionId ir_instruction_id(IrInstructionErrorReturnTrace *) {
576 return IrInstructionIdErrorReturnTrace;
577}
578
575template<typename T>579template<typename T>
576static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {580static 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}
23072311
2312static 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
2308static void ir_count_defers(IrBuilder *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {2318static 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
37313741
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}
...@@ -9568,6 +9582,24 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi...@@ -9568,6 +9582,24 @@ static TypeTableEntry *ir_analyze_instruction_export(IrAnalyze *ira, IrInstructi
9568 return ira->codegen->builtin_types.entry_void;9582 return ira->codegen->builtin_types.entry_void;
9569}9583}
95709584
9585static 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
9571static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,9603static bool ir_analyze_fn_call_inline_arg(IrAnalyze *ira, AstNode *fn_proto_node,
9572 IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i)9604 IrInstruction *arg, Scope **exec_scope, size_t *next_proto_i)
9573{9605{
...@@ -15324,6 +15356,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -15324,6 +15356,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
15324 return ir_analyze_instruction_tag_type(ira, (IrInstructionTagType *)instruction);15356 return ir_analyze_instruction_tag_type(ira, (IrInstructionTagType *)instruction);
15325 case IrInstructionIdExport:15357 case IrInstructionIdExport:
15326 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);
15327 }15361 }
15328 zig_unreachable();15362 zig_unreachable();
15329}15363}
...@@ -15507,6 +15541,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -15507,6 +15541,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
15507 case IrInstructionIdOpaqueType:15541 case IrInstructionIdOpaqueType:
15508 case IrInstructionIdArgType:15542 case IrInstructionIdArgType:
15509 case IrInstructionIdTagType:15543 case IrInstructionIdTagType:
15544 case IrInstructionIdErrorReturnTrace:
15510 return false;15545 return false;
15511 case IrInstructionIdAsm:15546 case IrInstructionIdAsm:
15512 {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}
998998
999static void ir_print_error_return_trace(IrPrint *irp, IrInstructionErrorReturnTrace *instruction) {
1000 fprintf(irp->f, "@errorReturnTrace()");
1001}
1002
9991003
1000static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {1004static 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+2-2
...@@ -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();
248248
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 }
257257
std/debug/index.zig+6-3
...@@ -56,7 +56,7 @@ pub fn dumpCurrentStackTrace() {...@@ -56,7 +56,7 @@ pub fn dumpCurrentStackTrace() {
56}56}
5757
58/// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned.58/// Tries to print a stack trace to stderr, unbuffered, and ignores any error returned.
59pub fn dumpStackTrace(stack_trace: &builtin.StackTrace) {59pub fn dumpStackTrace(stack_trace: &const builtin.StackTrace) {
60 const stderr = getStderrStream() catch return;60 const stderr = getStderrStream() catch return;
61 const debug_info = openSelfDebugInfo(global_allocator) catch |err| {61 const debug_info = openSelfDebugInfo(global_allocator) catch |err| {
62 stderr.print("Unable to open debug info: {}\n", @errorName(err)) catch return;62 stderr.print("Unable to open debug info: {}\n", @errorName(err)) catch return;
...@@ -127,7 +127,7 @@ const RESET = "\x1b[0m";...@@ -127,7 +127,7 @@ const RESET = "\x1b[0m";
127error PathNotFound;127error PathNotFound;
128error InvalidDebugInfo;128error InvalidDebugInfo;
129129
130pub fn writeStackTrace(stack_trace: &builtin.StackTrace, out_stream: &io.OutStream, allocator: &mem.Allocator,130pub fn writeStackTrace(stack_trace: &const builtin.StackTrace, out_stream: &io.OutStream, allocator: &mem.Allocator,
131 debug_info: &ElfStackTrace, tty_color: bool) -> %void131 debug_info: &ElfStackTrace, tty_color: bool) -> %void
132{132{
133 var frame_index: usize = undefined;133 var frame_index: usize = undefined;
...@@ -167,6 +167,9 @@ pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocat...@@ -167,6 +167,9 @@ pub fn writeCurrentStackTrace(out_stream: &io.OutStream, allocator: &mem.Allocat
167}167}
168168
169fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, address: usize) -> %void {169fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, address: usize) -> %void {
170 if (builtin.os == builtin.Os.windows) {
171 return error.UnsupportedDebugInfo;
172 }
170 // TODO we really should be able to convert @sizeOf(usize) * 2 to a string literal173 // TODO we really should be able to convert @sizeOf(usize) * 2 to a string literal
171 // at compile time. I'll call it issue #313174 // at compile time. I'll call it issue #313
172 const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}";175 const ptr_hex = if (@sizeOf(usize) == 4) "0x{x8}" else "0x{x16}";
...@@ -177,7 +180,7 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, a...@@ -177,7 +180,7 @@ fn printSourceAtAddress(debug_info: &ElfStackTrace, out_stream: &io.OutStream, a
177 return;180 return;
178 };181 };
179 const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name);182 const compile_unit_name = try compile_unit.die.getAttrString(debug_info, DW.AT_name);
180 if (getLineNumberInfo(debug_info, compile_unit, usize(address) - 1)) |line_info| {183 if (getLineNumberInfo(debug_info, compile_unit, address - 1)) |line_info| {
181 defer line_info.deinit();184 defer line_info.deinit();
182 try out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++185 try out_stream.print(WHITE ++ "{}:{}:{}" ++ RESET ++ ": " ++
183 DIM ++ ptr_hex ++ " in ??? ({})" ++ RESET ++ "\n",186 DIM ++ ptr_hex ++ " in ??? ({})" ++ RESET ++ "\n",
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 }
230230
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}
149149
150/// Exits the program cleanly with the specified status code.150/// Exits the program cleanly with the specified status code.
151pub coldcc fn exit(status: i32) -> noreturn {151pub 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 default160 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/special/bootstrap.zig+35-10
...@@ -21,8 +21,7 @@ comptime {...@@ -21,8 +21,7 @@ comptime {
21}21}
2222
23extern fn zenMain() -> noreturn {23extern 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}
2726
28nakedcc fn _start() -> noreturn {27nakedcc fn _start() -> noreturn {
...@@ -43,29 +42,55 @@ nakedcc fn _start() -> noreturn {...@@ -43,29 +42,55 @@ nakedcc fn _start() -> noreturn {
43extern fn WinMainCRTStartup() -> noreturn {42extern fn WinMainCRTStartup() -> noreturn {
44 @setAlignStack(16);43 @setAlignStack(16);
4544
46 root.main() catch std.os.windows.ExitProcess(1);45 std.os.windows.ExitProcess(callMain());
47 std.os.windows.ExitProcess(0);
48}46}
4947
50fn posixCallMainAndExit() -> noreturn {48fn 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}
5754
58fn callMain(argc: usize, argv: &&u8, envp: &?&u8) -> %void {55fn callMainWithArgs(argc: usize, argv: &&u8, envp: &?&u8) -> u8 {
59 std.os.ArgIteratorPosix.raw = argv[0..argc];56 std.os.ArgIteratorPosix.raw = argv[0..argc];
6057
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];
6461
65 return root.main();62 return callMain();
66}63}
6764
68extern fn main(c_argc: i32, c_argv: &&u8, c_envp: &?&u8) -> i32 {65extern 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
69fn 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();
1515
16 // TODO use a more general purpose allocator here16 // 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();
1919
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 }
113113
114 builder.setInstallPrefix(prefix);114 builder.setInstallPrefix(prefix);
115 root.build(&builder) catch unreachable;115 try root.build(&builder);
116116
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 options129 // 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) catch unreachable;132 try root.build(builder);
133 }133 }
134134
135 // This usage text has to be synchronized with src/main.cpp135 // This usage text has to be synchronized with src/main.cpp
std/special/test_runner.zig+1-8
...@@ -8,14 +8,7 @@ pub fn main() -> %void {...@@ -8,14 +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);
1010
11 if (builtin.is_test) {11 try test_fn.func();
12 test_fn.func() catch unreachable;
13 } else {
14 test_fn.func() catch |err| {
15 warn("{}\n", err);
16 return err;
17 };
18 }
1912
20 warn("OK\n");13 warn("OK\n");
21 }14 }
test/compile_errors.zig+9-9
...@@ -1,6 +1,15 @@...@@ -1,6 +1,15 @@
1const tests = @import("tests.zig");1const tests = @import("tests.zig");
22
3pub fn addCases(cases: &tests.CompileErrorContext) {3pub 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'");
10611070
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");
22
3pub fn addCases(cases: &tests.CompareOutputContext) {3pub 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 );
1212
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 );
2626
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 );
4040
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 );
5454
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 );
6868
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 );
8282
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 );
9696
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 );
110110
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 );
124124
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 );
138138
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 );
152152
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 );
165165
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 );
179179
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 );
193193
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 );
207207
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 );
221221
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); // good225 \\ @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 );
237237
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 );
249249
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 );
266266
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/issue_339/build.zig+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const Builder = @import("std").build.Builder;1const Builder = @import("std").build.Builder;
22
3pub fn build(b: &Builder) {3pub fn build(b: &Builder) -> %void {
4 const obj = b.addObject("test", "test.zig");4 const obj = b.addObject("test", "test.zig");
55
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 @@
1pub fn panic(msg: []const u8) -> noreturn { @breakpoint(); while (true) {} }1const StackTrace = @import("builtin").StackTrace;
2pub fn panic(msg: []const u8, stack_trace: ?&StackTrace) -> noreturn { @breakpoint(); while (true) {} }
23
3fn bar() -> %void {}4fn bar() -> %void {}
45
test/standalone/pkg_import/build.zig+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const Builder = @import("std").build.Builder;1const Builder = @import("std").build.Builder;
22
3pub fn build(b: &Builder) {3pub 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");
66
test/standalone/use_alias/build.zig+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1const Builder = @import("std").build.Builder;1const Builder = @import("std").build.Builder;
22
3pub fn build(b: &Builder) {3pub fn build(b: &Builder) -> %void {
4 b.addCIncludePath(".");4 b.addCIncludePath(".");
55
6 const main = b.addTest("main.zig");6 const main = b.addTest("main.zig");
test/tests.zig+2-2
...@@ -50,6 +50,7 @@ const test_targets = []TestTarget {...@@ -50,6 +50,7 @@ const test_targets = []TestTarget {
50};50};
5151
52error TestFailed;52error TestFailed;
53error CompilationIncorrectlySucceeded;
5354
54const max_stdout_size = 1 * 1024 * 1024; // 1 MB55const max_stdout_size = 1 * 1024 * 1024; // 1 MB
5556
...@@ -607,8 +608,7 @@ pub const CompileErrorContext = struct {...@@ -607,8 +608,7 @@ pub const CompileErrorContext = struct {
607 switch (term) {608 switch (term) {
608 Term.Exited => |code| {609 Term.Exited => |code| {
609 if (code == 0) {610 if (code == 0) {
610 warn("Compilation incorrectly succeeded\n");611 return error.CompilationIncorrectlySucceeded;
611 return error.TestFailed;
612 }612 }
613 },613 },
614 else => {614 else => {