aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/sparse-llvm.c
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-03-03 08:45:36 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-11-17 10:04:37 +0100
commit2d002eb75bfb092f6fed3ba600adfa8e7c13128c (patch)
treea79f97860dffba13312d0027c1556f56cdc21cad /sparse-llvm.c
parentaccf7112191ba29f0366c8a10332a8a63644db50 (diff)
downloadsparse-dev-2d002eb75bfb092f6fed3ba600adfa8e7c13128c.tar.gz
llvm: give correct type to binops
Pointer arithmetic and/or simplification can mixup pointer and integer types. Fix this by adding casts before all non-floating point binops and adjust the result type if needed to match the instructio. Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
Diffstat (limited to 'sparse-llvm.c')
-rw-r--r--sparse-llvm.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/sparse-llvm.c b/sparse-llvm.c
index c41781f3..e0838f4f 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -408,6 +408,33 @@ static LLVMValueRef pseudo_to_value(struct function *fn, struct instruction *ins
return result;
}
+static LLVMValueRef value_to_ivalue(struct function *fn, LLVMValueRef val)
+{
+ if (LLVMGetTypeKind(LLVMTypeOf(val)) == LLVMPointerTypeKind) {
+ LLVMTypeRef dtype = LLVMIntType(bits_in_pointer);
+ val = LLVMBuildPtrToInt(fn->builder, val, dtype, "");
+ }
+ return val;
+}
+
+static LLVMValueRef value_to_pvalue(struct function *fn, struct symbol *ctype, LLVMValueRef val)
+{
+ if (LLVMGetTypeKind(LLVMTypeOf(val)) == LLVMIntegerTypeKind) {
+ LLVMTypeRef dtype = symbol_type(ctype);
+ val = LLVMBuildIntToPtr(fn->builder, val, dtype, "");
+ }
+ return val;
+}
+
+static LLVMValueRef adjust_type(struct function *fn, struct symbol *ctype, LLVMValueRef val)
+{
+ if (is_int_type(ctype))
+ return value_to_ivalue(fn, val);
+ if (is_ptr_type(ctype))
+ return value_to_pvalue(fn, ctype, val);
+ return val;
+}
+
static LLVMValueRef calc_gep(LLVMBuilderRef builder, LLVMValueRef base, LLVMValueRef off)
{
LLVMTypeRef type = LLVMTypeOf(base);
@@ -467,8 +494,10 @@ static void output_op_binary(struct function *fn, struct instruction *insn)
char target_name[64];
lhs = pseudo_to_value(fn, insn, insn->src1);
+ lhs = value_to_ivalue(fn, lhs);
rhs = pseudo_to_value(fn, insn, insn->src2);
+ rhs = value_to_ivalue(fn, rhs);
pseudo_name(insn->target, target_name);
@@ -569,6 +598,7 @@ static void output_op_binary(struct function *fn, struct instruction *insn)
break;
}
+ target = adjust_type(fn, insn->type, target);
insn->target->priv = target;
}