| ... | @@ -474,6 +474,31 @@ static void clear_debug_source_node(CodeGen *g) { | ... | @@ -474,6 +474,31 @@ static void clear_debug_source_node(CodeGen *g) { |
| 474 | ZigLLVMClearCurrentDebugLocation(g->builder); | 474 | ZigLLVMClearCurrentDebugLocation(g->builder); |
| 475 | } | 475 | } |
| 476 | | 476 | |
| | 477 | struct BuilderState { |
| | 478 | LLVMValueRef debug_loc; |
| | 479 | LLVMBasicBlockRef basic_block; |
| | 480 | bool is_clear; |
| | 481 | }; |
| | 482 | |
| | 483 | static BuilderState save_and_clear_builder_state(CodeGen *g) { |
| | 484 | BuilderState prev_state; |
| | 485 | prev_state.debug_loc = LLVMGetCurrentDebugLocation(g->builder); |
| | 486 | prev_state.basic_block = LLVMGetInsertBlock(g->builder); |
| | 487 | prev_state.is_clear = g->dbg_clear; |
| | 488 | |
| | 489 | ZigLLVMClearCurrentDebugLocation(g->builder); |
| | 490 | g->dbg_clear = true; |
| | 491 | |
| | 492 | return prev_state; |
| | 493 | } |
| | 494 | |
| | 495 | static void restore_builder_state(CodeGen *g, const BuilderState &prev_state) { |
| | 496 | LLVMPositionBuilderAtEnd(g->builder, prev_state.basic_block); |
| | 497 | if (!prev_state.is_clear) |
| | 498 | LLVMSetCurrentDebugLocation(g->builder, prev_state.debug_loc); |
| | 499 | g->dbg_clear = prev_state.is_clear; |
| | 500 | } |
| | 501 | |
| 477 | static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, TypeTableEntry *type_entry, | 502 | static LLVMValueRef get_arithmetic_overflow_fn(CodeGen *g, TypeTableEntry *type_entry, |
| 478 | const char *signed_name, const char *unsigned_name) | 503 | const char *signed_name, const char *unsigned_name) |
| 479 | { | 504 | { |
| ... | @@ -662,9 +687,8 @@ static LLVMValueRef get_panic_slice_fn(CodeGen *g) { | ... | @@ -662,9 +687,8 @@ static LLVMValueRef get_panic_slice_fn(CodeGen *g) { |
| 662 | LLVMSetLinkage(fn_val, LLVMInternalLinkage); | 687 | LLVMSetLinkage(fn_val, LLVMInternalLinkage); |
| 663 | LLVMSetFunctionCallConv(fn_val, LLVMFastCallConv); | 688 | LLVMSetFunctionCallConv(fn_val, LLVMFastCallConv); |
| 664 | | 689 | |
| | 690 | auto prev_state = save_and_clear_builder_state(g); |
| 665 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry"); | 691 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry"); |
| 666 | LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder); | | |
| 667 | LLVMValueRef prev_debug_location = LLVMGetCurrentDebugLocation(g->builder); | | |
| 668 | LLVMPositionBuilderAtEnd(g->builder, entry_block); | 692 | LLVMPositionBuilderAtEnd(g->builder, entry_block); |
| 669 | | 693 | |
| 670 | LLVMValueRef msg_arg = LLVMGetParam(fn_val, 0); | 694 | LLVMValueRef msg_arg = LLVMGetParam(fn_val, 0); |
| ... | @@ -678,8 +702,7 @@ static LLVMValueRef get_panic_slice_fn(CodeGen *g) { | ... | @@ -678,8 +702,7 @@ static LLVMValueRef get_panic_slice_fn(CodeGen *g) { |
| 678 | LLVMValueRef msg_len = LLVMBuildLoad(g->builder, len_ptr, ""); | 702 | LLVMValueRef msg_len = LLVMBuildLoad(g->builder, len_ptr, ""); |
| 679 | gen_panic_raw(g, msg_ptr, msg_len); | 703 | gen_panic_raw(g, msg_ptr, msg_len); |
| 680 | | 704 | |
| 681 | LLVMPositionBuilderAtEnd(g->builder, prev_block); | 705 | restore_builder_state(g, prev_state); |
| 682 | LLVMSetCurrentDebugLocation(g->builder, prev_debug_location); | | |
| 683 | g->panic_slice_fn = fn_val; | 706 | g->panic_slice_fn = fn_val; |
| 684 | return g->panic_slice_fn; | 707 | return g->panic_slice_fn; |
| 685 | } | 708 | } |
| ... | @@ -744,11 +767,9 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { | ... | @@ -744,11 +767,9 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 744 | LLVMSetLinkage(fn_val, LLVMInternalLinkage); | 767 | LLVMSetLinkage(fn_val, LLVMInternalLinkage); |
| 745 | LLVMSetFunctionCallConv(fn_val, LLVMFastCallConv); | 768 | LLVMSetFunctionCallConv(fn_val, LLVMFastCallConv); |
| 746 | | 769 | |
| | 770 | auto prev_state = save_and_clear_builder_state(g); |
| 747 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry"); | 771 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry"); |
| 748 | LLVMBasicBlockRef prev_block = LLVMGetInsertBlock(g->builder); | | |
| 749 | LLVMValueRef prev_debug_location = LLVMGetCurrentDebugLocation(g->builder); | | |
| 750 | LLVMPositionBuilderAtEnd(g->builder, entry_block); | 772 | LLVMPositionBuilderAtEnd(g->builder, entry_block); |
| 751 | ZigLLVMClearCurrentDebugLocation(g->builder); | | |
| 752 | | 773 | |
| 753 | LLVMValueRef err_val = LLVMGetParam(fn_val, 0); | 774 | LLVMValueRef err_val = LLVMGetParam(fn_val, 0); |
| 754 | | 775 | |
| ... | @@ -779,8 +800,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { | ... | @@ -779,8 +800,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) { |
| 779 | | 800 | |
| 780 | gen_panic_raw(g, full_buf_ptr, full_buf_len); | 801 | gen_panic_raw(g, full_buf_ptr, full_buf_len); |
| 781 | | 802 | |
| 782 | LLVMPositionBuilderAtEnd(g->builder, prev_block); | 803 | restore_builder_state(g, prev_state); |
| 783 | LLVMSetCurrentDebugLocation(g->builder, prev_debug_location); | | |
| 784 | | 804 | |
| 785 | g->safety_crash_err_fn = fn_val; | 805 | g->safety_crash_err_fn = fn_val; |
| 786 | return fn_val; | 806 | return fn_val; |
| ... | @@ -905,26 +925,74 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_debug_safety, Typ | ... | @@ -905,26 +925,74 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_debug_safety, Typ |
| 905 | } | 925 | } |
| 906 | } | 926 | } |
| 907 | | 927 | |
| 908 | static LLVMValueRef gen_overflow_op(CodeGen *g, TypeTableEntry *type_entry, AddSubMul op, | 928 | static const char *add_sub_mul_name(AddSubMul op) { |
| 909 | LLVMValueRef val1, LLVMValueRef val2) | 929 | switch (op) { |
| 910 | { | 930 | case AddSubMulAdd: return "add"; |
| 911 | LLVMValueRef fn_val = get_int_overflow_fn(g, type_entry, op); | 931 | case AddSubMulSub: return "sub"; |
| | 932 | case AddSubMulMul: return "mul"; |
| | 933 | } |
| | 934 | zig_unreachable(); |
| | 935 | } |
| | 936 | static LLVMValueRef get_int_overflow_panic_fn(CodeGen *g, TypeTableEntry *type_entry, AddSubMul op) { |
| | 937 | ZigLLVMFnKey key = {}; |
| | 938 | key.id = ZigLLVMFnIdOverflowArithmeticPanic; |
| | 939 | key.data.overflow_arithmetic.is_signed = type_entry->data.integral.is_signed; |
| | 940 | key.data.overflow_arithmetic.add_sub_mul = op; |
| | 941 | key.data.overflow_arithmetic.bit_count = (uint32_t)type_entry->data.integral.bit_count; |
| | 942 | |
| | 943 | auto existing_entry = g->llvm_fn_table.maybe_get(key); |
| | 944 | if (existing_entry) |
| | 945 | return existing_entry->value; |
| | 946 | |
| | 947 | Buf *desired_name = buf_sprintf("__zig_checked_%s_%c%" PRIu32, add_sub_mul_name(op), |
| | 948 | type_entry->data.integral.is_signed ? 'i' : 'u', type_entry->data.integral.bit_count); |
| | 949 | Buf *fn_name = get_mangled_name(g, desired_name, false); |
| | 950 | LLVMTypeRef arg_types[] = { type_entry->type_ref, type_entry->type_ref }; |
| | 951 | LLVMTypeRef fn_type_ref = LLVMFunctionType(type_entry->type_ref, arg_types, 2, false); |
| | 952 | LLVMValueRef fn_val = LLVMAddFunction(g->module, buf_ptr(fn_name), fn_type_ref); |
| | 953 | LLVMSetLinkage(fn_val, LLVMInternalLinkage); |
| | 954 | LLVMSetFunctionCallConv(fn_val, LLVMFastCallConv); |
| | 955 | |
| | 956 | auto prev_state = save_and_clear_builder_state(g); |
| | 957 | |
| | 958 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn_val, "Entry"); |
| | 959 | LLVMPositionBuilderAtEnd(g->builder, entry_block); |
| | 960 | |
| | 961 | LLVMValueRef val1 = LLVMGetParam(fn_val, 0); |
| | 962 | LLVMValueRef val2 = LLVMGetParam(fn_val, 1); |
| | 963 | |
| | 964 | LLVMValueRef overflow_fn_val = get_int_overflow_fn(g, type_entry, op); |
| 912 | LLVMValueRef params[] = { | 965 | LLVMValueRef params[] = { |
| 913 | val1, | 966 | val1, |
| 914 | val2, | 967 | val2, |
| 915 | }; | 968 | }; |
| 916 | LLVMValueRef result_struct = LLVMBuildCall(g->builder, fn_val, params, 2, ""); | 969 | LLVMValueRef result_struct = LLVMBuildCall(g->builder, overflow_fn_val, params, 2, ""); |
| 917 | LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, ""); | | |
| 918 | LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, ""); | 970 | LLVMValueRef overflow_bit = LLVMBuildExtractValue(g->builder, result_struct, 1, ""); |
| 919 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowFail"); | 971 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(fn_val, "OverflowFail"); |
| 920 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "OverflowOk"); | 972 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(fn_val, "OverflowOk"); |
| 921 | LLVMBuildCondBr(g->builder, overflow_bit, fail_block, ok_block); | 973 | LLVMBuildCondBr(g->builder, overflow_bit, fail_block, ok_block); |
| 922 | | 974 | |
| 923 | LLVMPositionBuilderAtEnd(g->builder, fail_block); | 975 | LLVMPositionBuilderAtEnd(g->builder, fail_block); |
| 924 | gen_debug_safety_crash(g, PanicMsgIdIntegerOverflow); | 976 | gen_debug_safety_crash(g, PanicMsgIdIntegerOverflow); |
| 925 | | 977 | |
| 926 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | 978 | LLVMPositionBuilderAtEnd(g->builder, ok_block); |
| 927 | return result; | 979 | LLVMValueRef result = LLVMBuildExtractValue(g->builder, result_struct, 0, ""); |
| | 980 | LLVMBuildRet(g->builder, result); |
| | 981 | |
| | 982 | restore_builder_state(g, prev_state); |
| | 983 | g->llvm_fn_table.put(key, fn_val); |
| | 984 | return fn_val; |
| | 985 | } |
| | 986 | |
| | 987 | static LLVMValueRef gen_overflow_op(CodeGen *g, TypeTableEntry *type_entry, AddSubMul op, |
| | 988 | LLVMValueRef val1, LLVMValueRef val2) |
| | 989 | { |
| | 990 | LLVMValueRef fn_val = get_int_overflow_panic_fn(g, type_entry, op); |
| | 991 | LLVMValueRef params[] = { |
| | 992 | val1, |
| | 993 | val2, |
| | 994 | }; |
| | 995 | return LLVMBuildCall(g->builder, fn_val, params, 2, ""); |
| 928 | } | 996 | } |
| 929 | | 997 | |
| 930 | static LLVMIntPredicate cmp_op_to_int_predicate(IrBinOp cmp_op, bool is_signed) { | 998 | static LLVMIntPredicate cmp_op_to_int_predicate(IrBinOp cmp_op, bool is_signed) { |
| ... | @@ -2882,6 +2950,7 @@ static void set_debug_location(CodeGen *g, IrInstruction *instruction) { | ... | @@ -2882,6 +2950,7 @@ static void set_debug_location(CodeGen *g, IrInstruction *instruction) { |
| 2882 | | 2950 | |
| 2883 | ZigLLVMSetCurrentDebugLocation(g->builder, (int)source_node->line + 1, | 2951 | ZigLLVMSetCurrentDebugLocation(g->builder, (int)source_node->line + 1, |
| 2884 | (int)source_node->column + 1, get_di_scope(g, scope)); | 2952 | (int)source_node->column + 1, get_di_scope(g, scope)); |
| | 2953 | g->dbg_clear = false; |
| 2885 | } | 2954 | } |
| 2886 | | 2955 | |
| 2887 | static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) { | 2956 | static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable, IrInstruction *instruction) { |