aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2017-02-14 01:08:30 -0500
committerAndrew Kelley <superjoe30@gmail.com>2017-02-14 01:08:30 -0500
commit63d37b7cff0907cdf2361f1d61f19410fd6cc626 (patch)
tree9fb0e37d65a8cc01c6ff7fcba5a93cbed7075f6c /src/codegen.cpp
parent0931b85bd04fb671dce980728a3692de2bd496a5 (diff)
downloadzig-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.cpp26
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) {