authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-06 03:10:32-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-06 03:10:32-05:00
log07a71fc3221dfba05caea5a50ebe3dac5c76d643
treea7c56f5069bd9a04cbc2b590f4120691deb8fa06
parent28f63b8a4f2e55d2596a0e3daea106500a479791

improved behavior on debug safety crash

* instead of emitting a breakpoint for a debug safety crash, zig calls a panic function which prints an error message and a stack trace and then calls abort. * on freestanding OS, this panic function has a default implementation of a simple infinite loop. * users can override the panic implementation by providing `pub fn panic(message: []const u8) -> unreachable { }` * workaround for LLVM segfaulting when you try to use cold calling convention on ARM. closes #245

10 files changed, 255 insertions(+), 64 deletions(-)

CMakeLists.txt+8-7
...@@ -68,6 +68,10 @@ set(TEST_SOURCES...@@ -68,6 +68,10 @@ set(TEST_SOURCES
68)68)
6969
70set(C_HEADERS70set(C_HEADERS
71 "${CMAKE_SOURCE_DIR}/c_headers/Intrin.h"
72 "${CMAKE_SOURCE_DIR}/c_headers/__stddef_max_align_t.h"
73 "${CMAKE_SOURCE_DIR}/c_headers/__wmmintrin_aes.h"
74 "${CMAKE_SOURCE_DIR}/c_headers/__wmmintrin_pclmul.h"
71 "${CMAKE_SOURCE_DIR}/c_headers/adxintrin.h"75 "${CMAKE_SOURCE_DIR}/c_headers/adxintrin.h"
72 "${CMAKE_SOURCE_DIR}/c_headers/ammintrin.h"76 "${CMAKE_SOURCE_DIR}/c_headers/ammintrin.h"
73 "${CMAKE_SOURCE_DIR}/c_headers/arm_acle.h"77 "${CMAKE_SOURCE_DIR}/c_headers/arm_acle.h"
...@@ -95,14 +99,13 @@ set(C_HEADERS...@@ -95,14 +99,13 @@ set(C_HEADERS
95 "${CMAKE_SOURCE_DIR}/c_headers/htmxlintrin.h"99 "${CMAKE_SOURCE_DIR}/c_headers/htmxlintrin.h"
96 "${CMAKE_SOURCE_DIR}/c_headers/ia32intrin.h"100 "${CMAKE_SOURCE_DIR}/c_headers/ia32intrin.h"
97 "${CMAKE_SOURCE_DIR}/c_headers/immintrin.h"101 "${CMAKE_SOURCE_DIR}/c_headers/immintrin.h"
98 "${CMAKE_SOURCE_DIR}/c_headers/Intrin.h"
99 "${CMAKE_SOURCE_DIR}/c_headers/inttypes.h"102 "${CMAKE_SOURCE_DIR}/c_headers/inttypes.h"
100 "${CMAKE_SOURCE_DIR}/c_headers/iso646.h"103 "${CMAKE_SOURCE_DIR}/c_headers/iso646.h"
101 "${CMAKE_SOURCE_DIR}/c_headers/limits.h"104 "${CMAKE_SOURCE_DIR}/c_headers/limits.h"
102 "${CMAKE_SOURCE_DIR}/c_headers/lzcntintrin.h"105 "${CMAKE_SOURCE_DIR}/c_headers/lzcntintrin.h"
103 "${CMAKE_SOURCE_DIR}/c_headers/mm3dnow.h"106 "${CMAKE_SOURCE_DIR}/c_headers/mm3dnow.h"
104 "${CMAKE_SOURCE_DIR}/c_headers/mmintrin.h"
105 "${CMAKE_SOURCE_DIR}/c_headers/mm_malloc.h"107 "${CMAKE_SOURCE_DIR}/c_headers/mm_malloc.h"
108 "${CMAKE_SOURCE_DIR}/c_headers/mmintrin.h"
106 "${CMAKE_SOURCE_DIR}/c_headers/nmmintrin.h"109 "${CMAKE_SOURCE_DIR}/c_headers/nmmintrin.h"
107 "${CMAKE_SOURCE_DIR}/c_headers/pmmintrin.h"110 "${CMAKE_SOURCE_DIR}/c_headers/pmmintrin.h"
108 "${CMAKE_SOURCE_DIR}/c_headers/popcntintrin.h"111 "${CMAKE_SOURCE_DIR}/c_headers/popcntintrin.h"
...@@ -117,7 +120,6 @@ set(C_HEADERS...@@ -117,7 +120,6 @@ set(C_HEADERS
117 "${CMAKE_SOURCE_DIR}/c_headers/stdatomic.h"120 "${CMAKE_SOURCE_DIR}/c_headers/stdatomic.h"
118 "${CMAKE_SOURCE_DIR}/c_headers/stdbool.h"121 "${CMAKE_SOURCE_DIR}/c_headers/stdbool.h"
119 "${CMAKE_SOURCE_DIR}/c_headers/stddef.h"122 "${CMAKE_SOURCE_DIR}/c_headers/stddef.h"
120 "${CMAKE_SOURCE_DIR}/c_headers/__stddef_max_align_t.h"
121 "${CMAKE_SOURCE_DIR}/c_headers/stdint.h"123 "${CMAKE_SOURCE_DIR}/c_headers/stdint.h"
122 "${CMAKE_SOURCE_DIR}/c_headers/stdnoreturn.h"124 "${CMAKE_SOURCE_DIR}/c_headers/stdnoreturn.h"
123 "${CMAKE_SOURCE_DIR}/c_headers/tbmintrin.h"125 "${CMAKE_SOURCE_DIR}/c_headers/tbmintrin.h"
...@@ -127,9 +129,7 @@ set(C_HEADERS...@@ -127,9 +129,7 @@ set(C_HEADERS
127 "${CMAKE_SOURCE_DIR}/c_headers/vadefs.h"129 "${CMAKE_SOURCE_DIR}/c_headers/vadefs.h"
128 "${CMAKE_SOURCE_DIR}/c_headers/varargs.h"130 "${CMAKE_SOURCE_DIR}/c_headers/varargs.h"
129 "${CMAKE_SOURCE_DIR}/c_headers/vecintrin.h"131 "${CMAKE_SOURCE_DIR}/c_headers/vecintrin.h"
130 "${CMAKE_SOURCE_DIR}/c_headers/__wmmintrin_aes.h"
131 "${CMAKE_SOURCE_DIR}/c_headers/wmmintrin.h"132 "${CMAKE_SOURCE_DIR}/c_headers/wmmintrin.h"
132 "${CMAKE_SOURCE_DIR}/c_headers/__wmmintrin_pclmul.h"
133 "${CMAKE_SOURCE_DIR}/c_headers/x86intrin.h"133 "${CMAKE_SOURCE_DIR}/c_headers/x86intrin.h"
134 "${CMAKE_SOURCE_DIR}/c_headers/xmmintrin.h"134 "${CMAKE_SOURCE_DIR}/c_headers/xmmintrin.h"
135 "${CMAKE_SOURCE_DIR}/c_headers/xopintrin.h"135 "${CMAKE_SOURCE_DIR}/c_headers/xopintrin.h"
...@@ -202,6 +202,8 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/bootstrap.zig" DESTINATION "${ZIG_STD_DES...@@ -202,6 +202,8 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/bootstrap.zig" DESTINATION "${ZIG_STD_DES
202install(FILES "${CMAKE_SOURCE_DIR}/std/builtin.zig" DESTINATION "${ZIG_STD_DEST}")202install(FILES "${CMAKE_SOURCE_DIR}/std/builtin.zig" DESTINATION "${ZIG_STD_DEST}")
203install(FILES "${CMAKE_SOURCE_DIR}/std/compiler_rt.zig" DESTINATION "${ZIG_STD_DEST}")203install(FILES "${CMAKE_SOURCE_DIR}/std/compiler_rt.zig" DESTINATION "${ZIG_STD_DEST}")
204install(FILES "${CMAKE_SOURCE_DIR}/std/cstr.zig" DESTINATION "${ZIG_STD_DEST}")204install(FILES "${CMAKE_SOURCE_DIR}/std/cstr.zig" DESTINATION "${ZIG_STD_DEST}")
205install(FILES "${CMAKE_SOURCE_DIR}/std/darwin.zig" DESTINATION "${ZIG_STD_DEST}")
206install(FILES "${CMAKE_SOURCE_DIR}/std/darwin_x86_64.zig" DESTINATION "${ZIG_STD_DEST}")
205install(FILES "${CMAKE_SOURCE_DIR}/std/debug.zig" DESTINATION "${ZIG_STD_DEST}")207install(FILES "${CMAKE_SOURCE_DIR}/std/debug.zig" DESTINATION "${ZIG_STD_DEST}")
206install(FILES "${CMAKE_SOURCE_DIR}/std/dwarf.zig" DESTINATION "${ZIG_STD_DEST}")208install(FILES "${CMAKE_SOURCE_DIR}/std/dwarf.zig" DESTINATION "${ZIG_STD_DEST}")
207install(FILES "${CMAKE_SOURCE_DIR}/std/elf.zig" DESTINATION "${ZIG_STD_DEST}")209install(FILES "${CMAKE_SOURCE_DIR}/std/elf.zig" DESTINATION "${ZIG_STD_DEST}")
...@@ -214,13 +216,12 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/io.zig" DESTINATION "${ZIG_STD_DEST}")...@@ -214,13 +216,12 @@ install(FILES "${CMAKE_SOURCE_DIR}/std/io.zig" DESTINATION "${ZIG_STD_DEST}")
214install(FILES "${CMAKE_SOURCE_DIR}/std/linux.zig" DESTINATION "${ZIG_STD_DEST}")216install(FILES "${CMAKE_SOURCE_DIR}/std/linux.zig" DESTINATION "${ZIG_STD_DEST}")
215install(FILES "${CMAKE_SOURCE_DIR}/std/linux_i386.zig" DESTINATION "${ZIG_STD_DEST}")217install(FILES "${CMAKE_SOURCE_DIR}/std/linux_i386.zig" DESTINATION "${ZIG_STD_DEST}")
216install(FILES "${CMAKE_SOURCE_DIR}/std/linux_x86_64.zig" DESTINATION "${ZIG_STD_DEST}")218install(FILES "${CMAKE_SOURCE_DIR}/std/linux_x86_64.zig" DESTINATION "${ZIG_STD_DEST}")
217install(FILES "${CMAKE_SOURCE_DIR}/std/darwin.zig" DESTINATION "${ZIG_STD_DEST}")
218install(FILES "${CMAKE_SOURCE_DIR}/std/darwin_x86_64.zig" DESTINATION "${ZIG_STD_DEST}")
219install(FILES "${CMAKE_SOURCE_DIR}/std/list.zig" DESTINATION "${ZIG_STD_DEST}")219install(FILES "${CMAKE_SOURCE_DIR}/std/list.zig" DESTINATION "${ZIG_STD_DEST}")
220install(FILES "${CMAKE_SOURCE_DIR}/std/math.zig" DESTINATION "${ZIG_STD_DEST}")220install(FILES "${CMAKE_SOURCE_DIR}/std/math.zig" DESTINATION "${ZIG_STD_DEST}")
221install(FILES "${CMAKE_SOURCE_DIR}/std/mem.zig" DESTINATION "${ZIG_STD_DEST}")221install(FILES "${CMAKE_SOURCE_DIR}/std/mem.zig" DESTINATION "${ZIG_STD_DEST}")
222install(FILES "${CMAKE_SOURCE_DIR}/std/net.zig" DESTINATION "${ZIG_STD_DEST}")222install(FILES "${CMAKE_SOURCE_DIR}/std/net.zig" DESTINATION "${ZIG_STD_DEST}")
223install(FILES "${CMAKE_SOURCE_DIR}/std/os.zig" DESTINATION "${ZIG_STD_DEST}")223install(FILES "${CMAKE_SOURCE_DIR}/std/os.zig" DESTINATION "${ZIG_STD_DEST}")
224install(FILES "${CMAKE_SOURCE_DIR}/std/panic.zig" DESTINATION "${ZIG_STD_DEST}")
224install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}")225install(FILES "${CMAKE_SOURCE_DIR}/std/rand.zig" DESTINATION "${ZIG_STD_DEST}")
225install(FILES "${CMAKE_SOURCE_DIR}/std/rand_test.zig" DESTINATION "${ZIG_STD_DEST}")226install(FILES "${CMAKE_SOURCE_DIR}/std/rand_test.zig" DESTINATION "${ZIG_STD_DEST}")
226install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}")227install(FILES "${CMAKE_SOURCE_DIR}/std/sort.zig" DESTINATION "${ZIG_STD_DEST}")
example/guess_number/main.zig+1-3
...@@ -18,9 +18,7 @@ pub fn main(args: [][]u8) -> %void {...@@ -18,9 +18,7 @@ pub fn main(args: [][]u8) -> %void {
18 var line_buf : [20]u8 = undefined;18 var line_buf : [20]u8 = undefined;
1919
20 const line_len = io.stdin.read(line_buf) %% |err| {20 const line_len = io.stdin.read(line_buf) %% |err| {
21 %%io.stdout.printf("Unable to read from stdin: ");21 %%io.stdout.printf("Unable to read from stdin: {}\n", @errorName(err));
22 %%io.stdout.printf(@errorName(err));
23 %%io.stdout.printf("\n");
24 return err;22 return err;
25 };23 };
2624
src/all_types.hpp+21
...@@ -1132,6 +1132,22 @@ struct BuiltinFnEntry {...@@ -1132,6 +1132,22 @@ struct BuiltinFnEntry {
1132 LLVMValueRef fn_val;1132 LLVMValueRef fn_val;
1133};1133};
11341134
1135enum PanicMsgId {
1136 PanicMsgIdUnreachable,
1137 PanicMsgIdBoundsCheckFailure,
1138 PanicMsgIdCastNegativeToUnsigned,
1139 PanicMsgIdCastTruncatedData,
1140 PanicMsgIdIntegerOverflow,
1141 PanicMsgIdShiftOverflowedBits,
1142 PanicMsgIdDivisionByZero,
1143 PanicMsgIdExactDivisionRemainder,
1144 PanicMsgIdSliceWidenRemainder,
1145 PanicMsgIdUnwrapMaybeFail,
1146 PanicMsgIdUnwrapErrFail,
1147
1148 PanicMsgIdCount,
1149};
1150
1135uint32_t fn_eval_hash(Scope*);1151uint32_t fn_eval_hash(Scope*);
1136bool fn_eval_eql(Scope *a, Scope *b);1152bool fn_eval_eql(Scope *a, Scope *b);
11371153
...@@ -1210,6 +1226,7 @@ struct CodeGen {...@@ -1210,6 +1226,7 @@ struct CodeGen {
1210 bool strip_debug_symbols;1226 bool strip_debug_symbols;
1211 bool want_h_file;1227 bool want_h_file;
1212 bool have_exported_main;1228 bool have_exported_main;
1229 bool have_exported_panic;
1213 bool link_libc;1230 bool link_libc;
1214 Buf *libc_lib_dir;1231 Buf *libc_lib_dir;
1215 Buf *libc_static_lib_dir;1232 Buf *libc_static_lib_dir;
...@@ -1230,6 +1247,7 @@ struct CodeGen {...@@ -1230,6 +1247,7 @@ struct CodeGen {
1230 bool is_native_target;1247 bool is_native_target;
1231 PackageTableEntry *root_package;1248 PackageTableEntry *root_package;
1232 PackageTableEntry *std_package;1249 PackageTableEntry *std_package;
1250 PackageTableEntry *panic_package;
1233 Buf *root_out_name;1251 Buf *root_out_name;
1234 bool windows_subsystem_windows;1252 bool windows_subsystem_windows;
1235 bool windows_subsystem_console;1253 bool windows_subsystem_console;
...@@ -1252,6 +1270,7 @@ struct CodeGen {...@@ -1252,6 +1270,7 @@ struct CodeGen {
1252 OutType out_type;1270 OutType out_type;
1253 FnTableEntry *cur_fn;1271 FnTableEntry *cur_fn;
1254 FnTableEntry *main_fn;1272 FnTableEntry *main_fn;
1273 FnTableEntry *panic_fn;
1255 LLVMValueRef cur_ret_ptr;1274 LLVMValueRef cur_ret_ptr;
1256 LLVMValueRef cur_fn_val;1275 LLVMValueRef cur_fn_val;
1257 ZigList<LLVMBasicBlockRef> break_block_stack;1276 ZigList<LLVMBasicBlockRef> break_block_stack;
...@@ -1292,6 +1311,8 @@ struct CodeGen {...@@ -1292,6 +1311,8 @@ struct CodeGen {
12921311
1293 IrInstruction *invalid_instruction;1312 IrInstruction *invalid_instruction;
1294 ConstExprValue const_void_val;1313 ConstExprValue const_void_val;
1314
1315 ConstExprValue panic_msg_vals[PanicMsgIdCount];
1295};1316};
12961317
1297enum VarLinkage {1318enum VarLinkage {
src/analyze.cpp+68-22
...@@ -713,7 +713,13 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {...@@ -713,7 +713,13 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
713 fn_type->data.fn.fn_type_id = *fn_type_id;713 fn_type->data.fn.fn_type_id = *fn_type_id;
714714
715 if (fn_type_id->is_cold) {715 if (fn_type_id->is_cold) {
716 fn_type->data.fn.calling_convention = LLVMColdCallConv;716 if (g->zig_target.arch.arch == ZigLLVM_arm) {
717 // TODO we want to use coldcc here but it's causing a segfault on ARM
718 // https://llvm.org/bugs/show_bug.cgi?id=31875
719 fn_type->data.fn.calling_convention = LLVMCCallConv;
720 } else {
721 fn_type->data.fn.calling_convention = LLVMColdCallConv;
722 }
717 } else if (fn_type_id->is_extern) {723 } else if (fn_type_id->is_extern) {
718 fn_type->data.fn.calling_convention = LLVMCCallConv;724 fn_type->data.fn.calling_convention = LLVMCCallConv;
719 } else {725 } else {
...@@ -725,8 +731,8 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {...@@ -725,8 +731,8 @@ TypeTableEntry *get_fn_type(CodeGen *g, FnTypeId *fn_type_id) {
725 // populate the name of the type731 // populate the name of the type
726 buf_resize(&fn_type->name, 0);732 buf_resize(&fn_type->name, 0);
727 const char *extern_str = fn_type_id->is_extern ? "extern " : "";733 const char *extern_str = fn_type_id->is_extern ? "extern " : "";
728 const char *naked_str = fn_type_id->is_naked ? "naked " : "";734 const char *naked_str = fn_type_id->is_naked ? "nakedcc " : "";
729 const char *cold_str = fn_type_id->is_cold ? "cold " : "";735 const char *cold_str = fn_type_id->is_cold ? "coldcc " : "";
730 buf_appendf(&fn_type->name, "%s%s%sfn(", extern_str, naked_str, cold_str);736 buf_appendf(&fn_type->name, "%s%s%sfn(", extern_str, naked_str, cold_str);
731 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {737 for (size_t i = 0; i < fn_type_id->param_count; i += 1) {
732 FnTypeParamInfo *param_info = &fn_type_id->param_info[i];738 FnTypeParamInfo *param_info = &fn_type_id->param_info[i];
...@@ -1572,6 +1578,33 @@ static bool scope_is_root_decls(Scope *scope) {...@@ -1572,6 +1578,33 @@ static bool scope_is_root_decls(Scope *scope) {
1572 zig_unreachable();1578 zig_unreachable();
1573}1579}
15741580
1581static void wrong_panic_prototype(CodeGen *g, AstNode *proto_node, TypeTableEntry *fn_type) {
1582 add_node_error(g, proto_node,
1583 buf_sprintf("expected 'fn([]const u8) -> unreachable', found '%s'",
1584 buf_ptr(&fn_type->name)));
1585}
1586
1587static void typecheck_panic_fn(CodeGen *g) {
1588 assert(g->panic_fn);
1589
1590 AstNode *proto_node = g->panic_fn->proto_node;
1591 assert(proto_node->type == NodeTypeFnProto);
1592 TypeTableEntry *fn_type = g->panic_fn->type_entry;
1593 FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id;
1594 if (fn_type_id->param_count != 1) {
1595 return wrong_panic_prototype(g, proto_node, fn_type);
1596 }
1597 TypeTableEntry *const_u8_slice = get_slice_type(g, g->builtin_types.entry_u8, true);
1598 if (fn_type_id->param_info[0].type != const_u8_slice) {
1599 return wrong_panic_prototype(g, proto_node, fn_type);
1600 }
1601
1602 TypeTableEntry *actual_return_type = fn_type_id->return_type;
1603 if (actual_return_type != g->builtin_types.entry_unreachable) {
1604 return wrong_panic_prototype(g, proto_node, fn_type);
1605 }
1606}
1607
1575static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {1608static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
1576 ImportTableEntry *import = tld_fn->base.import;1609 ImportTableEntry *import = tld_fn->base.import;
1577 AstNode *proto_node = tld_fn->base.source_node;1610 AstNode *proto_node = tld_fn->base.source_node;
...@@ -1612,27 +1645,39 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {...@@ -1612,27 +1645,39 @@ static void resolve_decl_fn(CodeGen *g, TldFn *tld_fn) {
1612 if (fn_def_node)1645 if (fn_def_node)
1613 g->fn_defs.append(fn_table_entry);1646 g->fn_defs.append(fn_table_entry);
16141647
1615 bool is_main_fn = scope_is_root_decls(tld_fn->base.parent_scope) &&1648 if (import == g->root_import && scope_is_root_decls(tld_fn->base.parent_scope)) {
1616 (import == g->root_import) && buf_eql_str(&fn_table_entry->symbol_name, "main");1649 if (buf_eql_str(&fn_table_entry->symbol_name, "main")) {
1617 if (is_main_fn)1650 g->main_fn = fn_table_entry;
1618 g->main_fn = fn_table_entry;1651
16191652 if (!g->link_libc && tld_fn->base.visib_mod != VisibModExport) {
1620 if (is_main_fn && !g->link_libc && tld_fn->base.visib_mod != VisibModExport) {1653 TypeTableEntry *err_void = get_error_type(g, g->builtin_types.entry_void);
1621 TypeTableEntry *err_void = get_error_type(g, g->builtin_types.entry_void);1654 TypeTableEntry *actual_return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type;
1622 TypeTableEntry *actual_return_type = fn_table_entry->type_entry->data.fn.fn_type_id.return_type;1655 if (actual_return_type != err_void) {
1623 if (actual_return_type != err_void) {1656 add_node_error(g, fn_proto->return_type,
1624 add_node_error(g, fn_proto->return_type,1657 buf_sprintf("expected return type of main to be '%%void', instead is '%s'",
1625 buf_sprintf("expected return type of main to be '%%void', instead is '%s'",1658 buf_ptr(&actual_return_type->name)));
1626 buf_ptr(&actual_return_type->name)));1659 }
1660 }
1661 } else if (buf_eql_str(&fn_table_entry->symbol_name, "panic")) {
1662 g->panic_fn = fn_table_entry;
1663 typecheck_panic_fn(g);
1664 }
1665 } else if (import->package == g->panic_package && scope_is_root_decls(tld_fn->base.parent_scope)) {
1666 if (buf_eql_str(&fn_table_entry->symbol_name, "panic")) {
1667 g->panic_fn = fn_table_entry;
1668 typecheck_panic_fn(g);
1627 }1669 }
1628 }1670 }
1629 }1671 }
1630}1672}
16311673
1632static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {1674static void add_top_level_decl(CodeGen *g, ScopeDecls *decls_scope, Tld *tld) {
1633 bool want_to_resolve = (g->check_unused || g->is_test_build || tld->visib_mod == VisibModExport);1675 if (g->check_unused || g->is_test_build || tld->visib_mod == VisibModExport ||
1634 if (want_to_resolve)1676 (buf_eql_str(tld->name, "panic") &&
1677 (decls_scope->import->package == g->panic_package || decls_scope->import == g->root_import)))
1678 {
1635 g->resolve_queue.append(tld);1679 g->resolve_queue.append(tld);
1680 }
16361681
1637 auto entry = decls_scope->decl_table.put_unique(tld->name, tld);1682 auto entry = decls_scope->decl_table.put_unique(tld->name, tld);
1638 if (entry) {1683 if (entry) {
...@@ -2548,9 +2593,6 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,...@@ -2548,9 +2593,6 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
2548 assert(import_entry->root);2593 assert(import_entry->root);
2549 if (g->verbose) {2594 if (g->verbose) {
2550 ast_print(stderr, import_entry->root, 0);2595 ast_print(stderr, import_entry->root, 0);
2551 //fprintf(stderr, "\nReformatted Source:\n");
2552 //fprintf(stderr, "---------------------\n");
2553 //ast_render(stderr, import_entry->root, 4);
2554 }2596 }
25552597
2556 import_entry->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));2598 import_entry->di_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(src_basename), buf_ptr(src_dirname));
...@@ -2571,8 +2613,12 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,...@@ -2571,8 +2613,12 @@ ImportTableEntry *add_source_file(CodeGen *g, PackageTableEntry *package,
25712613
2572 bool is_pub = (proto_node->data.fn_proto.visib_mod == VisibModPub);2614 bool is_pub = (proto_node->data.fn_proto.visib_mod == VisibModPub);
25732615
2574 if (buf_eql_str(proto_name, "main") && is_pub) {2616 if (is_pub) {
2575 g->have_exported_main = true;2617 if (buf_eql_str(proto_name, "main")) {
2618 g->have_exported_main = true;
2619 } else if (buf_eql_str(proto_name, "panic")) {
2620 g->have_exported_panic = true;
2621 }
2576 }2622 }
2577 }2623 }
2578 }2624 }
src/codegen.cpp+71-13
...@@ -450,8 +450,56 @@ static bool ir_want_debug_safety(CodeGen *g, IrInstruction *instruction) {...@@ -450,8 +450,56 @@ static bool ir_want_debug_safety(CodeGen *g, IrInstruction *instruction) {
450 return true;450 return true;
451}451}
452452
453static void gen_debug_safety_crash(CodeGen *g) {453static Buf *panic_msg_buf(PanicMsgId msg_id) {
454 LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");454 switch (msg_id) {
455 case PanicMsgIdCount:
456 zig_unreachable();
457 case PanicMsgIdBoundsCheckFailure:
458 return buf_create_from_str("index out of bounds");
459 case PanicMsgIdCastNegativeToUnsigned:
460 return buf_create_from_str("attempt to cast negative value to unsigned integer");
461 case PanicMsgIdCastTruncatedData:
462 return buf_create_from_str("integer cast truncated bits");
463 case PanicMsgIdIntegerOverflow:
464 return buf_create_from_str("integer overflow");
465 case PanicMsgIdShiftOverflowedBits:
466 return buf_create_from_str("left shift overflowed bits");
467 case PanicMsgIdDivisionByZero:
468 return buf_create_from_str("division by zero");
469 case PanicMsgIdExactDivisionRemainder:
470 return buf_create_from_str("exact division produced remainder");
471 case PanicMsgIdSliceWidenRemainder:
472 return buf_create_from_str("slice widening size mismatch");
473 case PanicMsgIdUnwrapMaybeFail:
474 return buf_create_from_str("attempt to unwrap null");
475 case PanicMsgIdUnwrapErrFail:
476 return buf_create_from_str("attempt to unwrap error");
477 case PanicMsgIdUnreachable:
478 return buf_create_from_str("reached unreachable code");
479 }
480 zig_unreachable();
481}
482
483static LLVMValueRef get_panic_msg_ptr_val(CodeGen *g, PanicMsgId msg_id) {
484 ConstExprValue *val = &g->panic_msg_vals[msg_id];
485 if (val->llvm_global)
486 return val->llvm_global;
487
488 Buf *buf_msg = panic_msg_buf(msg_id);
489 ConstExprValue *array_val = create_const_str_lit(g, buf_msg);
490 init_const_slice(g, val, array_val, 0, buf_len(buf_msg), true);
491
492 render_const_val_global(g, val, "");
493 render_const_val(g, val);
494
495 assert(val->llvm_global);
496 return val->llvm_global;
497}
498
499static void gen_debug_safety_crash(CodeGen *g, PanicMsgId msg_id) {
500 LLVMValueRef fn_val = fn_llvm_value(g, g->panic_fn);
501 LLVMValueRef msg_arg = get_panic_msg_ptr_val(g, msg_id);
502 ZigLLVMBuildCall(g->builder, fn_val, &msg_arg, 1, g->panic_fn->type_entry->data.fn.calling_convention, "");
455 LLVMBuildUnreachable(g->builder);503 LLVMBuildUnreachable(g->builder);
456}504}
457505
...@@ -477,7 +525,7 @@ static void add_bounds_check(CodeGen *g, LLVMValueRef target_val,...@@ -477,7 +525,7 @@ static void add_bounds_check(CodeGen *g, LLVMValueRef target_val,
477 LLVMBuildCondBr(g->builder, lower_ok_val, lower_ok_block, bounds_check_fail_block);525 LLVMBuildCondBr(g->builder, lower_ok_val, lower_ok_block, bounds_check_fail_block);
478526
479 LLVMPositionBuilderAtEnd(g->builder, bounds_check_fail_block);527 LLVMPositionBuilderAtEnd(g->builder, bounds_check_fail_block);
480 gen_debug_safety_crash(g);528 gen_debug_safety_crash(g, PanicMsgIdBoundsCheckFailure);
481529
482 if (upper_value) {530 if (upper_value) {
483 LLVMPositionBuilderAtEnd(g->builder, lower_ok_block);531 LLVMPositionBuilderAtEnd(g->builder, lower_ok_block);
...@@ -520,7 +568,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_debug_safety, Typ...@@ -520,7 +568,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_debug_safety, Typ
520 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);568 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
521569
522 LLVMPositionBuilderAtEnd(g->builder, fail_block);570 LLVMPositionBuilderAtEnd(g->builder, fail_block);
523 gen_debug_safety_crash(g);571 gen_debug_safety_crash(g, PanicMsgIdCastNegativeToUnsigned);
524572
525 LLVMPositionBuilderAtEnd(g->builder, ok_block);573 LLVMPositionBuilderAtEnd(g->builder, ok_block);
526 }574 }
...@@ -559,7 +607,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_debug_safety, Typ...@@ -559,7 +607,7 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_debug_safety, Typ
559 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);607 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
560608
561 LLVMPositionBuilderAtEnd(g->builder, fail_block);609 LLVMPositionBuilderAtEnd(g->builder, fail_block);
562 gen_debug_safety_crash(g);610 gen_debug_safety_crash(g, PanicMsgIdCastTruncatedData);
563611
564 LLVMPositionBuilderAtEnd(g->builder, ok_block);612 LLVMPositionBuilderAtEnd(g->builder, ok_block);
565 return trunc_val;613 return trunc_val;
...@@ -587,7 +635,7 @@ static LLVMValueRef gen_overflow_op(CodeGen *g, TypeTableEntry *type_entry, AddS...@@ -587,7 +635,7 @@ static LLVMValueRef gen_overflow_op(CodeGen *g, TypeTableEntry *type_entry, AddS
587 LLVMBuildCondBr(g->builder, overflow_bit, fail_block, ok_block);635 LLVMBuildCondBr(g->builder, overflow_bit, fail_block, ok_block);
588636
589 LLVMPositionBuilderAtEnd(g->builder, fail_block);637 LLVMPositionBuilderAtEnd(g->builder, fail_block);
590 gen_debug_safety_crash(g);638 gen_debug_safety_crash(g, PanicMsgIdIntegerOverflow);
591639
592 LLVMPositionBuilderAtEnd(g->builder, ok_block);640 LLVMPositionBuilderAtEnd(g->builder, ok_block);
593 return result;641 return result;
...@@ -748,7 +796,7 @@ static LLVMValueRef gen_overflow_shl_op(CodeGen *g, TypeTableEntry *type_entry,...@@ -748,7 +796,7 @@ static LLVMValueRef gen_overflow_shl_op(CodeGen *g, TypeTableEntry *type_entry,
748 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);796 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
749797
750 LLVMPositionBuilderAtEnd(g->builder, fail_block);798 LLVMPositionBuilderAtEnd(g->builder, fail_block);
751 gen_debug_safety_crash(g);799 gen_debug_safety_crash(g, PanicMsgIdShiftOverflowedBits);
752800
753 LLVMPositionBuilderAtEnd(g->builder, ok_block);801 LLVMPositionBuilderAtEnd(g->builder, ok_block);
754 return result;802 return result;
...@@ -773,7 +821,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, LLVMValueRef val...@@ -773,7 +821,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, LLVMValueRef val
773 LLVMBuildCondBr(g->builder, is_zero_bit, fail_block, ok_block);821 LLVMBuildCondBr(g->builder, is_zero_bit, fail_block, ok_block);
774822
775 LLVMPositionBuilderAtEnd(g->builder, fail_block);823 LLVMPositionBuilderAtEnd(g->builder, fail_block);
776 gen_debug_safety_crash(g);824 gen_debug_safety_crash(g, PanicMsgIdDivisionByZero);
777825
778 LLVMPositionBuilderAtEnd(g->builder, ok_block);826 LLVMPositionBuilderAtEnd(g->builder, ok_block);
779 }827 }
...@@ -801,7 +849,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, LLVMValueRef val...@@ -801,7 +849,7 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, LLVMValueRef val
801 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);849 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
802850
803 LLVMPositionBuilderAtEnd(g->builder, fail_block);851 LLVMPositionBuilderAtEnd(g->builder, fail_block);
804 gen_debug_safety_crash(g);852 gen_debug_safety_crash(g, PanicMsgIdExactDivisionRemainder);
805853
806 LLVMPositionBuilderAtEnd(g->builder, ok_block);854 LLVMPositionBuilderAtEnd(g->builder, ok_block);
807 }855 }
...@@ -1038,7 +1086,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,...@@ -1038,7 +1086,7 @@ static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutable *executable,
1038 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);1086 LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block);
10391087
1040 LLVMPositionBuilderAtEnd(g->builder, fail_block);1088 LLVMPositionBuilderAtEnd(g->builder, fail_block);
1041 gen_debug_safety_crash(g);1089 gen_debug_safety_crash(g, PanicMsgIdSliceWidenRemainder);
10421090
1043 LLVMPositionBuilderAtEnd(g->builder, ok_block);1091 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1044 }1092 }
...@@ -1162,7 +1210,7 @@ static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutable *executable,...@@ -1162,7 +1210,7 @@ static LLVMValueRef ir_render_unreachable(CodeGen *g, IrExecutable *executable,
1162 IrInstructionUnreachable *unreachable_instruction)1210 IrInstructionUnreachable *unreachable_instruction)
1163{1211{
1164 if (ir_want_debug_safety(g, &unreachable_instruction->base) || g->is_test_build) {1212 if (ir_want_debug_safety(g, &unreachable_instruction->base) || g->is_test_build) {
1165 gen_debug_safety_crash(g);1213 gen_debug_safety_crash(g, PanicMsgIdUnreachable);
1166 } else {1214 } else {
1167 LLVMBuildUnreachable(g->builder);1215 LLVMBuildUnreachable(g->builder);
1168 }1216 }
...@@ -1622,7 +1670,7 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,...@@ -1622,7 +1670,7 @@ static LLVMValueRef ir_render_unwrap_maybe(CodeGen *g, IrExecutable *executable,
1622 LLVMBuildCondBr(g->builder, non_null_bit, ok_block, fail_block);1670 LLVMBuildCondBr(g->builder, non_null_bit, ok_block, fail_block);
16231671
1624 LLVMPositionBuilderAtEnd(g->builder, fail_block);1672 LLVMPositionBuilderAtEnd(g->builder, fail_block);
1625 gen_debug_safety_crash(g);1673 gen_debug_safety_crash(g, PanicMsgIdUnwrapMaybeFail);
16261674
1627 LLVMPositionBuilderAtEnd(g->builder, ok_block);1675 LLVMPositionBuilderAtEnd(g->builder, ok_block);
1628 }1676 }
...@@ -2107,7 +2155,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu...@@ -2107,7 +2155,7 @@ static LLVMValueRef ir_render_unwrap_err_payload(CodeGen *g, IrExecutable *execu
2107 LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);2155 LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
21082156
2109 LLVMPositionBuilderAtEnd(g->builder, err_block);2157 LLVMPositionBuilderAtEnd(g->builder, err_block);
2110 gen_debug_safety_crash(g);2158 gen_debug_safety_crash(g, PanicMsgIdUnwrapErrFail);
21112159
2112 LLVMPositionBuilderAtEnd(g->builder, ok_block);2160 LLVMPositionBuilderAtEnd(g->builder, ok_block);
2113 }2161 }
...@@ -3849,6 +3897,12 @@ static PackageTableEntry *create_bootstrap_pkg(CodeGen *g) {...@@ -3849,6 +3897,12 @@ static PackageTableEntry *create_bootstrap_pkg(CodeGen *g) {
3849 return package;3897 return package;
3850}3898}
38513899
3900static PackageTableEntry *create_panic_pkg(CodeGen *g) {
3901 PackageTableEntry *package = new_package(buf_ptr(g->zig_std_dir), "");
3902 package->package_table.put(buf_create_from_str("std"), g->std_package);
3903 return package;
3904}
3905
3852void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) {3906void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *source_code) {
3853 Buf source_path = BUF_INIT;3907 Buf source_path = BUF_INIT;
3854 os_path_join(src_dir, src_basename, &source_path);3908 os_path_join(src_dir, src_basename, &source_path);
...@@ -3873,6 +3927,10 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou...@@ -3873,6 +3927,10 @@ void codegen_add_root_code(CodeGen *g, Buf *src_dir, Buf *src_basename, Buf *sou
3873 g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g), "bootstrap.zig");3927 g->bootstrap_import = add_special_code(g, create_bootstrap_pkg(g), "bootstrap.zig");
3874 }3928 }
3875 }3929 }
3930 if (!g->have_exported_panic) {
3931 g->panic_package = create_panic_pkg(g);
3932 add_special_code(g, g->panic_package, "panic.zig");
3933 }
38763934
3877 if (g->verbose) {3935 if (g->verbose) {
3878 fprintf(stderr, "\nIR Generation and Semantic Analysis:\n");3936 fprintf(stderr, "\nIR Generation and Semantic Analysis:\n");
src/ir.cpp-10
...@@ -3878,20 +3878,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -3878,20 +3878,10 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
3878 if (arg0_value == irb->codegen->invalid_instruction)3878 if (arg0_value == irb->codegen->invalid_instruction)
3879 return arg0_value;3879 return arg0_value;
38803880
3881 if (exec_fn_entry(irb->exec)) {
3882 add_node_error(irb->codegen, node, buf_sprintf("import valid only at global scope"));
3883 return irb->codegen->invalid_instruction;
3884 }
3885
3886 return ir_build_import(irb, scope, node, arg0_value);3881 return ir_build_import(irb, scope, node, arg0_value);
3887 }3882 }
3888 case BuiltinFnIdCImport:3883 case BuiltinFnIdCImport:
3889 {3884 {
3890 if (exec_fn_entry(irb->exec)) {
3891 add_node_error(irb->codegen, node, buf_sprintf("C import valid only at global scope"));
3892 return irb->codegen->invalid_instruction;
3893 }
3894
3895 return ir_build_c_import(irb, scope, node);3885 return ir_build_c_import(irb, scope, node);
3896 }3886 }
3897 case BuiltinFnIdCInclude:3887 case BuiltinFnIdCInclude:
std/bootstrap.zig+3-2
...@@ -1,8 +1,9 @@...@@ -1,8 +1,9 @@
1// This file is in a package which has the root source file exposed as "@root".1// This file is in a package which has the root source file exposed as "@root".
22
3const root = @import("@root");3const root = @import("@root");
4const linux = @import("linux.zig");4const std = @import("std");
5const cstr = @import("cstr.zig");5const linux = std.linux;
6const cstr = std.cstr;
67
7const want_start_symbol = switch(@compileVar("os")) {8const want_start_symbol = switch(@compileVar("os")) {
8 Os.linux => true,9 Os.linux => true,
std/debug.zig+2
...@@ -42,6 +42,8 @@ pub fn writeStackTrace(out_stream: &io.OutStream) -> %void {...@@ -42,6 +42,8 @@ pub fn writeStackTrace(out_stream: &io.OutStream) -> %void {
42 st.debug_str = (%return st.elf.findSection(".debug_str")) ?? return error.MissingDebugInfo;42 st.debug_str = (%return st.elf.findSection(".debug_str")) ?? return error.MissingDebugInfo;
43 %return scanAllCompileUnits(st);43 %return scanAllCompileUnits(st);
4444
45 %return out_stream.printf("(...work-in-progress stack unwinding code follows...)\n");
46
45 var maybe_fp: ?&const u8 = @frameAddress();47 var maybe_fp: ?&const u8 = @frameAddress();
46 while (true) {48 while (true) {
47 const fp = maybe_fp ?? break;49 const fp = maybe_fp ?? break;
std/panic.zig created+33
...@@ -0,0 +1,33 @@
1// This file is included if and only if the user's main source file does not
2// include a public panic function.
3// If this file wants to import other files *by name*, support for that would
4// have to be added in the compiler.
5
6var panicking = false;
7pub coldcc fn panic(message: []const u8) -> unreachable {
8 if (@compileVar("os") == Os.freestanding) {
9 while (true) {}
10 } else {
11 const std = @import("std");
12 const io = std.io;
13 const debug = std.debug;
14 const os = std.os;
15
16 // TODO
17 // if (@atomicRmw(AtomicOp.XChg, &panicking, true, AtomicOrder.SeqCst)) {
18 if (panicking) {
19 // Panicked during a panic.
20 // TODO detect if a different thread caused the panic, because in that case
21 // we would want to return here instead of calling abort, so that the thread
22 // which first called panic can finish printing a stack trace.
23 os.abort();
24 } else {
25 panicking = true;
26 }
27
28 %%io.stderr.printf("{}\n", message);
29 %%debug.printStackTrace();
30
31 os.abort();
32 }
33}
test/run_tests.cpp+48-7
...@@ -1167,13 +1167,6 @@ fn f(n: Number) -> i32 {...@@ -1167,13 +1167,6 @@ fn f(n: Number) -> i32 {
1167}1167}
1168 )SOURCE", 1, ".tmp_source.zig:9:5: error: enumeration value 'Number.Four' not handled in switch");1168 )SOURCE", 1, ".tmp_source.zig:9:5: error: enumeration value 'Number.Four' not handled in switch");
11691169
1170 add_compile_fail_case("import inside function body", R"SOURCE(
1171fn f() {
1172 const std = @import("std");
1173}
1174 )SOURCE", 1, ".tmp_source.zig:3:17: error: import valid only at global scope");
1175
1176
1177 add_compile_fail_case("normal string with newline", R"SOURCE(1170 add_compile_fail_case("normal string with newline", R"SOURCE(
1178const foo = "a1171const foo = "a
1179b";1172b";
...@@ -1675,6 +1668,10 @@ const some_data: [100]u8 = {...@@ -1675,6 +1668,10 @@ const some_data: [100]u8 = {
16751668
1676static void add_debug_safety_test_cases(void) {1669static void add_debug_safety_test_cases(void) {
1677 add_debug_safety_case("out of bounds slice access", R"SOURCE(1670 add_debug_safety_case("out of bounds slice access", R"SOURCE(
1671pub fn panic(message: []const u8) -> unreachable {
1672 @breakpoint();
1673 while (true) {}
1674}
1678pub fn main(args: [][]u8) -> %void {1675pub fn main(args: [][]u8) -> %void {
1679 const a = []i32{1, 2, 3, 4};1676 const a = []i32{1, 2, 3, 4};
1680 baz(bar(a));1677 baz(bar(a));
...@@ -1686,6 +1683,10 @@ fn baz(a: i32) { }...@@ -1686,6 +1683,10 @@ fn baz(a: i32) { }
1686 )SOURCE");1683 )SOURCE");
16871684
1688 add_debug_safety_case("integer addition overflow", R"SOURCE(1685 add_debug_safety_case("integer addition overflow", R"SOURCE(
1686pub fn panic(message: []const u8) -> unreachable {
1687 @breakpoint();
1688 while (true) {}
1689}
1689error Whatever;1690error Whatever;
1690pub fn main(args: [][]u8) -> %void {1691pub fn main(args: [][]u8) -> %void {
1691 const x = add(65530, 10);1692 const x = add(65530, 10);
...@@ -1697,6 +1698,10 @@ fn add(a: u16, b: u16) -> u16 {...@@ -1697,6 +1698,10 @@ fn add(a: u16, b: u16) -> u16 {
1697 )SOURCE");1698 )SOURCE");
16981699
1699 add_debug_safety_case("integer subtraction overflow", R"SOURCE(1700 add_debug_safety_case("integer subtraction overflow", R"SOURCE(
1701pub fn panic(message: []const u8) -> unreachable {
1702 @breakpoint();
1703 while (true) {}
1704}
1700error Whatever;1705error Whatever;
1701pub fn main(args: [][]u8) -> %void {1706pub fn main(args: [][]u8) -> %void {
1702 const x = sub(10, 20);1707 const x = sub(10, 20);
...@@ -1708,6 +1713,10 @@ fn sub(a: u16, b: u16) -> u16 {...@@ -1708,6 +1713,10 @@ fn sub(a: u16, b: u16) -> u16 {
1708 )SOURCE");1713 )SOURCE");
17091714
1710 add_debug_safety_case("integer multiplication overflow", R"SOURCE(1715 add_debug_safety_case("integer multiplication overflow", R"SOURCE(
1716pub fn panic(message: []const u8) -> unreachable {
1717 @breakpoint();
1718 while (true) {}
1719}
1711error Whatever;1720error Whatever;
1712pub fn main(args: [][]u8) -> %void {1721pub fn main(args: [][]u8) -> %void {
1713 const x = mul(300, 6000);1722 const x = mul(300, 6000);
...@@ -1719,6 +1728,10 @@ fn mul(a: u16, b: u16) -> u16 {...@@ -1719,6 +1728,10 @@ fn mul(a: u16, b: u16) -> u16 {
1719 )SOURCE");1728 )SOURCE");
17201729
1721 add_debug_safety_case("integer negation overflow", R"SOURCE(1730 add_debug_safety_case("integer negation overflow", R"SOURCE(
1731pub fn panic(message: []const u8) -> unreachable {
1732 @breakpoint();
1733 while (true) {}
1734}
1722error Whatever;1735error Whatever;
1723pub fn main(args: [][]u8) -> %void {1736pub fn main(args: [][]u8) -> %void {
1724 const x = neg(-32768);1737 const x = neg(-32768);
...@@ -1730,6 +1743,10 @@ fn neg(a: i16) -> i16 {...@@ -1730,6 +1743,10 @@ fn neg(a: i16) -> i16 {
1730 )SOURCE");1743 )SOURCE");
17311744
1732 add_debug_safety_case("signed shift left overflow", R"SOURCE(1745 add_debug_safety_case("signed shift left overflow", R"SOURCE(
1746pub fn panic(message: []const u8) -> unreachable {
1747 @breakpoint();
1748 while (true) {}
1749}
1733error Whatever;1750error Whatever;
1734pub fn main(args: [][]u8) -> %void {1751pub fn main(args: [][]u8) -> %void {
1735 const x = shl(-16385, 1);1752 const x = shl(-16385, 1);
...@@ -1741,6 +1758,10 @@ fn shl(a: i16, b: i16) -> i16 {...@@ -1741,6 +1758,10 @@ fn shl(a: i16, b: i16) -> i16 {
1741 )SOURCE");1758 )SOURCE");
17421759
1743 add_debug_safety_case("unsigned shift left overflow", R"SOURCE(1760 add_debug_safety_case("unsigned shift left overflow", R"SOURCE(
1761pub fn panic(message: []const u8) -> unreachable {
1762 @breakpoint();
1763 while (true) {}
1764}
1744error Whatever;1765error Whatever;
1745pub fn main(args: [][]u8) -> %void {1766pub fn main(args: [][]u8) -> %void {
1746 const x = shl(0b0010111111111111, 3);1767 const x = shl(0b0010111111111111, 3);
...@@ -1752,6 +1773,10 @@ fn shl(a: u16, b: u16) -> u16 {...@@ -1752,6 +1773,10 @@ fn shl(a: u16, b: u16) -> u16 {
1752 )SOURCE");1773 )SOURCE");
17531774
1754 add_debug_safety_case("integer division by zero", R"SOURCE(1775 add_debug_safety_case("integer division by zero", R"SOURCE(
1776pub fn panic(message: []const u8) -> unreachable {
1777 @breakpoint();
1778 while (true) {}
1779}
1755error Whatever;1780error Whatever;
1756pub fn main(args: [][]u8) -> %void {1781pub fn main(args: [][]u8) -> %void {
1757 const x = div0(999, 0);1782 const x = div0(999, 0);
...@@ -1762,6 +1787,10 @@ fn div0(a: i32, b: i32) -> i32 {...@@ -1762,6 +1787,10 @@ fn div0(a: i32, b: i32) -> i32 {
1762 )SOURCE");1787 )SOURCE");
17631788
1764 add_debug_safety_case("exact division failure", R"SOURCE(1789 add_debug_safety_case("exact division failure", R"SOURCE(
1790pub fn panic(message: []const u8) -> unreachable {
1791 @breakpoint();
1792 while (true) {}
1793}
1765error Whatever;1794error Whatever;
1766pub fn main(args: [][]u8) -> %void {1795pub fn main(args: [][]u8) -> %void {
1767 const x = divExact(10, 3);1796 const x = divExact(10, 3);
...@@ -1773,6 +1802,10 @@ fn divExact(a: i32, b: i32) -> i32 {...@@ -1773,6 +1802,10 @@ fn divExact(a: i32, b: i32) -> i32 {
1773 )SOURCE");1802 )SOURCE");
17741803
1775 add_debug_safety_case("cast []u8 to bigger slice of wrong size", R"SOURCE(1804 add_debug_safety_case("cast []u8 to bigger slice of wrong size", R"SOURCE(
1805pub fn panic(message: []const u8) -> unreachable {
1806 @breakpoint();
1807 while (true) {}
1808}
1776error Whatever;1809error Whatever;
1777pub fn main(args: [][]u8) -> %void {1810pub fn main(args: [][]u8) -> %void {
1778 const x = widenSlice([]u8{1, 2, 3, 4, 5});1811 const x = widenSlice([]u8{1, 2, 3, 4, 5});
...@@ -1784,6 +1817,10 @@ fn widenSlice(slice: []u8) -> []i32 {...@@ -1784,6 +1817,10 @@ fn widenSlice(slice: []u8) -> []i32 {
1784 )SOURCE");1817 )SOURCE");
17851818
1786 add_debug_safety_case("value does not fit in shortening cast", R"SOURCE(1819 add_debug_safety_case("value does not fit in shortening cast", R"SOURCE(
1820pub fn panic(message: []const u8) -> unreachable {
1821 @breakpoint();
1822 while (true) {}
1823}
1787error Whatever;1824error Whatever;
1788pub fn main(args: [][]u8) -> %void {1825pub fn main(args: [][]u8) -> %void {
1789 const x = shorten_cast(200);1826 const x = shorten_cast(200);
...@@ -1795,6 +1832,10 @@ fn shorten_cast(x: i32) -> i8 {...@@ -1795,6 +1832,10 @@ fn shorten_cast(x: i32) -> i8 {
1795 )SOURCE");1832 )SOURCE");
17961833
1797 add_debug_safety_case("signed integer not fitting in cast to unsigned integer", R"SOURCE(1834 add_debug_safety_case("signed integer not fitting in cast to unsigned integer", R"SOURCE(
1835pub fn panic(message: []const u8) -> unreachable {
1836 @breakpoint();
1837 while (true) {}
1838}
1798error Whatever;1839error Whatever;
1799pub fn main(args: [][]u8) -> %void {1840pub fn main(args: [][]u8) -> %void {
1800 const x = unsigned_cast(-10);1841 const x = unsigned_cast(-10);