Commit 5ad84e4724

Andrew Kelley <superjoe30@gmail.com>
2016-02-02 10:43:33
unreachable causes a trap in debug mode
1 parent 6f1a7a0
Changed files (5)
doc/vim/syntax/zig.vim
@@ -7,7 +7,7 @@ if exists("b:current_syntax")
   finish
 endif
 
-syn keyword zigStorage const var extern volatile export pub noalias
+syn keyword zigStorage const var extern volatile export pub noalias inline
 syn keyword zigStructure struct enum
 syn keyword zigStatement goto break return continue asm defer
 syn keyword zigConditional if else switch
src/all_types.hpp
@@ -1097,6 +1097,7 @@ struct CodeGen {
     ImportTableEntry *bootstrap_import;
     LLVMValueRef memcpy_fn_val;
     LLVMValueRef memset_fn_val;
+    LLVMValueRef trap_fn_val;
     bool error_during_imports;
     uint32_t next_node_index;
     uint32_t next_error_index;
src/codegen.cpp
@@ -991,9 +991,30 @@ static LLVMValueRef gen_prefix_op_expr(CodeGen *g, AstNode *node) {
                 TypeTableEntry *expr_type = get_expr_type(expr_node);
                 assert(expr_type->id == TypeTableEntryIdErrorUnion);
                 TypeTableEntry *child_type = expr_type->data.error.child_type;
-                // TODO in debug mode, put a panic here if the error is not 0
+
+                if (g->build_type != CodeGenBuildTypeRelease) {
+                    LLVMValueRef err_val;
+                    if (child_type->size_in_bits > 0) {
+                        add_debug_source_node(g, node);
+                        LLVMValueRef err_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 0, "");
+                        err_val = LLVMBuildLoad(g->builder, err_val_ptr, "");
+                    } else {
+                        err_val = expr_val;
+                    }
+                    LLVMValueRef zero = LLVMConstNull(g->err_tag_type->type_ref);
+                    LLVMValueRef cond_val = LLVMBuildICmp(g->builder, LLVMIntEQ, err_val, zero, "");
+                    LLVMBasicBlockRef err_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrError");
+                    LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn->fn_value, "UnwrapErrOk");
+                    LLVMBuildCondBr(g->builder, cond_val, ok_block, err_block);
+
+                    LLVMPositionBuilderAtEnd(g->builder, err_block);
+                    LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
+                    LLVMBuildUnreachable(g->builder);
+
+                    LLVMPositionBuilderAtEnd(g->builder, ok_block);
+                }
+
                 if (child_type->size_in_bits > 0) {
-                    add_debug_source_node(g, node);
                     LLVMValueRef child_val_ptr = LLVMBuildStructGEP(g->builder, expr_val, 1, "");
                     if (handle_is_ptr(child_type)) {
                         return child_val_ptr;
@@ -1898,6 +1919,9 @@ static LLVMValueRef gen_container_init_expr(CodeGen *g, AstNode *node) {
     } else if (type_entry->id == TypeTableEntryIdUnreachable) {
         assert(node->data.container_init_expr.entries.length == 0);
         add_debug_source_node(g, node);
+        if (g->build_type != CodeGenBuildTypeRelease) {
+            LLVMBuildCall(g->builder, g->trap_fn_val, nullptr, 0, "");
+        }
         return LLVMBuildUnreachable(g->builder);
     } else if (type_entry->id == TypeTableEntryIdVoid) {
         assert(node->data.container_init_expr.entries.length == 0);
@@ -3084,6 +3108,11 @@ static BuiltinFnEntry *create_builtin_fn_with_arg_count(CodeGen *g, BuiltinFnId
 }
 
 static void define_builtin_fns(CodeGen *g) {
+    {
+        LLVMTypeRef fn_type = LLVMFunctionType(LLVMVoidType(), nullptr, 0, false);
+        g->trap_fn_val = LLVMAddFunction(g->module, "llvm.debugtrap", fn_type);
+        assert(LLVMGetIntrinsicID(g->trap_fn_val));
+    }
     {
         BuiltinFnEntry *builtin_fn = create_builtin_fn(g, BuiltinFnIdMemcpy, "memcpy");
         builtin_fn->return_type = g->builtin_types.entry_void;
std/math.zig
@@ -27,3 +27,8 @@ pub fn f64_is_nan(f: f64) -> bool {
 pub fn f64_is_inf(f: f64) -> bool {
     f == f64_get_neg_inf() || f == f64_get_pos_inf()
 }
+
+pub fn min_isize(x: isize, y: isize) -> isize {
+    if (x < y) x else y
+}
+
std/std.zig
@@ -372,7 +372,3 @@ pub fn buf_print_f64(out_buf: []u8, x: f64, decimals: isize) -> isize {
 
     len
 }
-
-fn min_isize(x: isize, y: isize) -> isize {
-    if (x < y) x else y
-}