aboutsummaryrefslogtreecommitdiff
path: root/src/codegen.cpp
diff options
context:
space:
mode:
authorAndrew Kelley <superjoe30@gmail.com>2017-08-19 01:32:15 -0400
committerAndrew Kelley <superjoe30@gmail.com>2017-08-19 01:43:43 -0400
commit987768778a67538299f84a6ab7ff0ca65f69d2ac (patch)
tree2e7551d76bf9a3e6d242a961eacf7c81aab6025f /src/codegen.cpp
parent558ece8f6f1889bc4773432c16cdf96a54ec1431 (diff)
downloadzig-987768778a67538299f84a6ab7ff0ca65f69d2ac.tar.gz
zig-987768778a67538299f84a6ab7ff0ca65f69d2ac.zip
bit shifting safety
* add u3, u4, u5, u6, u7 and i3, i4, i5, i6, i7 * shift operations shift amount parameter type is integer with log2 bit width of other param - This enforces not violating undefined behavior on shift amount >= bit width with the type system * clean up math.log, math.ln, math.log2, math.log10 closes #403
Diffstat (limited to 'src/codegen.cpp')
-rw-r--r--src/codegen.cpp40
1 files changed, 27 insertions, 13 deletions
diff --git a/src/codegen.cpp b/src/codegen.cpp
index b3de627d3e..bb95a3faae 100644
--- a/src/codegen.cpp
+++ b/src/codegen.cpp
@@ -1451,7 +1451,9 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
IrInstruction *op1 = bin_op_instruction->op1;
IrInstruction *op2 = bin_op_instruction->op2;
- assert(op1->value.type == op2->value.type);
+ assert(op1->value.type == op2->value.type || op_id == IrBinOpBitShiftLeftLossy ||
+ op_id == IrBinOpBitShiftLeftExact || op_id == IrBinOpBitShiftRightLossy ||
+ op_id == IrBinOpBitShiftRightExact);
TypeTableEntry *type_entry = op1->value.type;
bool want_debug_safety = bin_op_instruction->safety_check_on &&
@@ -1527,34 +1529,38 @@ static LLVMValueRef ir_render_bin_op(CodeGen *g, IrExecutable *executable,
case IrBinOpBitShiftLeftExact:
{
assert(type_entry->id == TypeTableEntryIdInt);
+ LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type,
+ type_entry, op2_value);
bool is_sloppy = (op_id == IrBinOpBitShiftLeftLossy);
if (is_sloppy) {
- return LLVMBuildShl(g->builder, op1_value, op2_value, "");
+ return LLVMBuildShl(g->builder, op1_value, op2_casted, "");
} else if (want_debug_safety) {
- return gen_overflow_shl_op(g, type_entry, op1_value, op2_value);
+ return gen_overflow_shl_op(g, type_entry, op1_value, op2_casted);
} else if (type_entry->data.integral.is_signed) {
- return ZigLLVMBuildNSWShl(g->builder, op1_value, op2_value, "");
+ return ZigLLVMBuildNSWShl(g->builder, op1_value, op2_casted, "");
} else {
- return ZigLLVMBuildNUWShl(g->builder, op1_value, op2_value, "");
+ return ZigLLVMBuildNUWShl(g->builder, op1_value, op2_casted, "");
}
}
case IrBinOpBitShiftRightLossy:
case IrBinOpBitShiftRightExact:
{
assert(type_entry->id == TypeTableEntryIdInt);
+ LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, op2->value.type,
+ type_entry, op2_value);
bool is_sloppy = (op_id == IrBinOpBitShiftRightLossy);
if (is_sloppy) {
if (type_entry->data.integral.is_signed) {
- return LLVMBuildAShr(g->builder, op1_value, op2_value, "");
+ return LLVMBuildAShr(g->builder, op1_value, op2_casted, "");
} else {
- return LLVMBuildLShr(g->builder, op1_value, op2_value, "");
+ return LLVMBuildLShr(g->builder, op1_value, op2_casted, "");
}
} else if (want_debug_safety) {
- return gen_overflow_shr_op(g, type_entry, op1_value, op2_value);
+ return gen_overflow_shr_op(g, type_entry, op1_value, op2_casted);
} else if (type_entry->data.integral.is_signed) {
- return ZigLLVMBuildAShrExact(g->builder, op1_value, op2_value, "");
+ return ZigLLVMBuildAShrExact(g->builder, op1_value, op2_casted, "");
} else {
- return ZigLLVMBuildLShrExact(g->builder, op1_value, op2_value, "");
+ return ZigLLVMBuildLShrExact(g->builder, op1_value, op2_casted, "");
}
}
case IrBinOpSub:
@@ -2824,12 +2830,15 @@ static LLVMValueRef render_shl_with_overflow(CodeGen *g, IrInstructionOverflowOp
LLVMValueRef op2 = ir_llvm_value(g, instruction->op2);
LLVMValueRef ptr_result = ir_llvm_value(g, instruction->result_ptr);
- LLVMValueRef result = LLVMBuildShl(g->builder, op1, op2, "");
+ LLVMValueRef op2_casted = gen_widen_or_shorten(g, false, instruction->op2->value.type,
+ instruction->op1->value.type, op2);
+
+ LLVMValueRef result = LLVMBuildShl(g->builder, op1, op2_casted, "");
LLVMValueRef orig_val;
if (int_type->data.integral.is_signed) {
- orig_val = LLVMBuildAShr(g->builder, result, op2, "");
+ orig_val = LLVMBuildAShr(g->builder, result, op2_casted, "");
} else {
- orig_val = LLVMBuildLShr(g->builder, result, op2, "");
+ orig_val = LLVMBuildLShr(g->builder, result, op2_casted, "");
}
LLVMValueRef overflow_bit = LLVMBuildICmp(g->builder, LLVMIntNE, op1, orig_val, "");
@@ -4212,6 +4221,11 @@ static void do_code_gen(CodeGen *g) {
}
static const uint8_t int_sizes_in_bits[] = {
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
8,
16,
32,