diff options
| author | Andrew Kelley <superjoe30@gmail.com> | 2017-02-14 01:08:30 -0500 |
|---|---|---|
| committer | Andrew Kelley <superjoe30@gmail.com> | 2017-02-14 01:08:30 -0500 |
| commit | 63d37b7cff0907cdf2361f1d61f19410fd6cc626 (patch) | |
| tree | 9fb0e37d65a8cc01c6ff7fcba5a93cbed7075f6c /src/codegen.cpp | |
| parent | 0931b85bd04fb671dce980728a3692de2bd496a5 (diff) | |
| download | zig-63d37b7cff0907cdf2361f1d61f19410fd6cc626.tar.gz zig-63d37b7cff0907cdf2361f1d61f19410fd6cc626.zip | |
add runtime debug safety for dividing integer min value by -1
closes #260
Diffstat (limited to 'src/codegen.cpp')
| -rw-r--r-- | src/codegen.cpp | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp index b98d549e84..df4b6fcf7c 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -846,14 +846,30 @@ static LLVMValueRef gen_div(CodeGen *g, bool want_debug_safety, LLVMValueRef val } else { zig_unreachable(); } - LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivZeroOk"); - LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivZeroFail"); - LLVMBuildCondBr(g->builder, is_zero_bit, fail_block, ok_block); + LLVMBasicBlockRef div_zero_ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivZeroOk"); + LLVMBasicBlockRef div_zero_fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivZeroFail"); + LLVMBuildCondBr(g->builder, is_zero_bit, div_zero_fail_block, div_zero_ok_block); - LLVMPositionBuilderAtEnd(g->builder, fail_block); + LLVMPositionBuilderAtEnd(g->builder, div_zero_fail_block); gen_debug_safety_crash(g, PanicMsgIdDivisionByZero); - LLVMPositionBuilderAtEnd(g->builder, ok_block); + LLVMPositionBuilderAtEnd(g->builder, div_zero_ok_block); + + if (type_entry->id == TypeTableEntryIdInt && type_entry->data.integral.is_signed) { + LLVMValueRef neg_1_value = LLVMConstInt(type_entry->type_ref, -1, true); + LLVMValueRef int_min_value = LLVMConstInt(type_entry->type_ref, min_signed_val(type_entry), true); + LLVMBasicBlockRef overflow_ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivOverflowOk"); + LLVMBasicBlockRef overflow_fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "DivOverflowFail"); + LLVMValueRef num_is_int_min = LLVMBuildICmp(g->builder, LLVMIntEQ, val1, int_min_value, ""); + LLVMValueRef den_is_neg_1 = LLVMBuildICmp(g->builder, LLVMIntEQ, val2, neg_1_value, ""); + LLVMValueRef overflow_fail_bit = LLVMBuildAnd(g->builder, num_is_int_min, den_is_neg_1, ""); + LLVMBuildCondBr(g->builder, overflow_fail_bit, overflow_fail_block, overflow_ok_block); + + LLVMPositionBuilderAtEnd(g->builder, overflow_fail_block); + gen_debug_safety_crash(g, PanicMsgIdIntegerOverflow); + + LLVMPositionBuilderAtEnd(g->builder, overflow_ok_block); + } } if (type_entry->id == TypeTableEntryIdFloat) { |
