diff --git a/doc/vim/syntax/zig.vim b/doc/vim/syntax/zig.vim index 28b347ba9c..5ecfb89a61 100644 --- a/doc/vim/syntax/zig.vim +++ b/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 diff --git a/src/all_types.hpp b/src/all_types.hpp index 65456291e6..1f87ee128e 100644 --- a/src/all_types.hpp +++ b/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; diff --git a/src/codegen.cpp b/src/codegen.cpp index b6cf0f2d96..63e1be54e5 100644 --- a/src/codegen.cpp +++ b/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; diff --git a/std/math.zig b/std/math.zig index c563b45678..dcaef45db7 100644 --- a/std/math.zig +++ b/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 +} + diff --git a/std/std.zig b/std/std.zig index 7f59a89dfa..d628692ae0 100644 --- a/std/std.zig +++ b/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 -}