| author | |
| committer | |
| log | 63d37b7cff0907cdf2361f1d61f19410fd6cc626 |
| tree | 9fb0e37d65a8cc01c6ff7fcba5a93cbed7075f6c |
| parent | 0931b85bd04fb671dce980728a3692de2bd496a5 |
closes #2604 files changed, 39 insertions(+), 7 deletions(-)
src/analyze.cpp+1-1| ... | @@ -3447,7 +3447,7 @@ static int64_t max_signed_val(TypeTableEntry *type_entry) { | ... | @@ -3447,7 +3447,7 @@ static int64_t max_signed_val(TypeTableEntry *type_entry) { |
| 3447 | } | 3447 | } |
| 3448 | } | 3448 | } |
| 3449 | 3449 | ||
| 3450 | static int64_t min_signed_val(TypeTableEntry *type_entry) { | 3450 | int64_t min_signed_val(TypeTableEntry *type_entry) { |
| 3451 | assert(type_entry->id == TypeTableEntryIdInt); | 3451 | assert(type_entry->id == TypeTableEntryIdInt); |
| 3452 | if (type_entry->data.integral.bit_count == 64) { | 3452 | if (type_entry->data.integral.bit_count == 64) { |
| 3453 | return INT64_MIN; | 3453 | return INT64_MIN; |
src/analyze.hpp+1| ... | @@ -81,6 +81,7 @@ void complete_enum(CodeGen *g, TypeTableEntry *enum_type); | ... | @@ -81,6 +81,7 @@ void complete_enum(CodeGen *g, TypeTableEntry *enum_type); |
| 81 | bool ir_get_var_is_comptime(VariableTableEntry *var); | 81 | bool ir_get_var_is_comptime(VariableTableEntry *var); |
| 82 | bool const_values_equal(ConstExprValue *a, ConstExprValue *b); | 82 | bool const_values_equal(ConstExprValue *a, ConstExprValue *b); |
| 83 | void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max); | 83 | void eval_min_max_value(CodeGen *g, TypeTableEntry *type_entry, ConstExprValue *const_val, bool is_max); |
| 84 | int64_t min_signed_val(TypeTableEntry *type_entry); | ||
| 84 | 85 | ||
| 85 | void render_const_value(Buf *buf, ConstExprValue *const_val); | 86 | void render_const_value(Buf *buf, ConstExprValue *const_val); |
| 86 | void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars); | 87 | void define_local_param_variables(CodeGen *g, FnTableEntry *fn_table_entry, VariableTableEntry **arg_vars); |
src/codegen.cpp+21-5| ... | @@ -846,14 +846,30 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, LLVMValueRef val | ... | @@ -846,14 +846,30 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, LLVMValueRef val |
| 846 | } else { | 846 | } else { |
| 847 | zig_unreachable(); | 847 | zig_unreachable(); |
| 848 | } | 848 | } |
| 849 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivZeroOk"); | 849 | LLVMBasicBlockRef div_zero_ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivZeroOk"); |
| 850 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivZeroFail"); | 850 | LLVMBasicBlockRef div_zero_fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivZeroFail"); |
| 851 | LLVMBuildCondBr(g->builder, is_zero_bit, fail_block, ok_block); | 851 | LLVMBuildCondBr(g->builder, is_zero_bit, div_zero_fail_block, div_zero_ok_block); |
| 852 | 852 | ||
| 853 | LLVMPositionBuilderAtEnd(g->builder, fail_block); | 853 | LLVMPositionBuilderAtEnd(g->builder, div_zero_fail_block); |
| 854 | gen_debug_safety_crash(g, PanicMsgIdDivisionByZero); | 854 | gen_debug_safety_crash(g, PanicMsgIdDivisionByZero); |
| 855 | 855 | ||
| 856 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | 856 | LLVMPositionBuilderAtEnd(g->builder, div_zero_ok_block); |
| 857 | |||
| 858 | if (type_entry->id == TypeTableEntryIdInt && type_entry->data.integral.is_signed) { | ||
| 859 | LLVMValueRef neg_1_value = LLVMConstInt(type_entry->type_ref, -1, true); | ||
| 860 | LLVMValueRef int_min_value = LLVMConstInt(type_entry->type_ref, min_signed_val(type_entry), true); | ||
| 861 | LLVMBasicBlockRef overflow_ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivOverflowOk"); | ||
| 862 | LLVMBasicBlockRef overflow_fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivOverflowFail"); | ||
| 863 | LLVMValueRef num_is_int_min = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, int_min_value, ""); | ||
| 864 | LLVMValueRef den_is_neg_1 = LLVMBuildICmp(g->builder, LLVMIntEQ, val2, neg_1_value, ""); | ||
| 865 | LLVMValueRef overflow_fail_bit = LLVMBuildAnd(g->builder, num_is_int_min, den_is_neg_1, ""); | ||
| 866 | LLVMBuildCondBr(g->builder, overflow_fail_bit, overflow_fail_block, overflow_ok_block); | ||
| 867 | |||
| 868 | LLVMPositionBuilderAtEnd(g->builder, overflow_fail_block); | ||
| 869 | gen_debug_safety_crash(g, PanicMsgIdIntegerOverflow); | ||
| 870 | |||
| 871 | LLVMPositionBuilderAtEnd(g->builder, overflow_ok_block); | ||
| 872 | } | ||
| 857 | } | 873 | } |
| 858 | 874 | ||
| 859 | if (type_entry->id == TypeTableEntryIdFloat) { | 875 | if (type_entry->id == TypeTableEntryIdFloat) { |
test/run_tests.cpp+16-1| ... | @@ -1700,13 +1700,28 @@ pub fn panic(message: []const u8) -> unreachable { | ... | @@ -1700,13 +1700,28 @@ pub fn panic(message: []const u8) -> unreachable { |
| 1700 | error Whatever; | 1700 | error Whatever; |
| 1701 | pub fn main(args: [][]u8) -> %void { | 1701 | pub fn main(args: [][]u8) -> %void { |
| 1702 | const x = neg(-32768); | 1702 | const x = neg(-32768); |
| 1703 | if (x == 0) return error.Whatever; | 1703 | if (x == 32767) return error.Whatever; |
| 1704 | } | 1704 | } |
| 1705 | fn neg(a: i16) -> i16 { | 1705 | fn neg(a: i16) -> i16 { |
| 1706 | -a | 1706 | -a |
| 1707 | } | 1707 | } |
| 1708 | )SOURCE"); | 1708 | )SOURCE"); |
| 1709 | 1709 | ||
| 1710 | add_debug_safety_case("signed integer division overflow", R"SOURCE( | ||
| 1711 | pub fn panic(message: []const u8) -> unreachable { | ||
| 1712 | @breakpoint(); | ||
| 1713 | while (true) {} | ||
| 1714 | } | ||
| 1715 | error Whatever; | ||
| 1716 | pub fn main(args: [][]u8) -> %void { | ||
| 1717 | const x = div(-32768, -1); | ||
| 1718 | if (x == 32767) return error.Whatever; | ||
| 1719 | } | ||
| 1720 | fn div(a: i16, b: i16) -> i16 { | ||
| 1721 | a / b | ||
| 1722 | } | ||
| 1723 | )SOURCE"); | ||
| 1724 | |||
| 1710 | add_debug_safety_case("signed shift left overflow", R"SOURCE( | 1725 | add_debug_safety_case("signed shift left overflow", R"SOURCE( |
| 1711 | pub fn panic(message: []const u8) -> unreachable { | 1726 | pub fn panic(message: []const u8) -> unreachable { |
| 1712 | @breakpoint(); | 1727 | @breakpoint(); |