aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
authorLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-03-05 12:20:38 +0100
committerLuc Van Oostenryck <luc.vanoostenryck@gmail.com>2017-11-17 10:04:37 +0100
commit163f2aab9dd33c14af762da9ac7175c5f416c5c6 (patch)
treec242e09b04db66883575207036a64cea9d9752b3
parente39241c956b801728e9c4b60a8b2da6a0116c634 (diff)
downloadsparse-dev-163f2aab9dd33c14af762da9ac7175c5f416c5c6.tar.gz
llvm: fix output_op_[ptr]cast()
OP_PTRCASTs can't always be directly translated into LLVM bitcasts and OP_[S]CASTs can't always be translated into LLVM's trunc/sext/zext because integer to pointer and pointer to integer must be handled too. Fix this in output_op_ptrcast() & output_op_cast() by issuing LLVMBuildIntToPtr/PtrToInt when appropriate. Reported-by: Dibyendu Majumdar <mobile@majumdar.org.uk> Signed-off-by: Luc Van Oostenryck <luc.vanoostenryck@gmail.com>
-rw-r--r--sparse-llvm.c40
1 files changed, 35 insertions, 5 deletions
diff --git a/sparse-llvm.c b/sparse-llvm.c
index c83911a1..99b18ae8 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -791,6 +791,8 @@ static void output_op_phi(struct function *fn, struct instruction *insn)
static void output_op_ptrcast(struct function *fn, struct instruction *insn)
{
LLVMValueRef src, target;
+ LLVMTypeRef dtype;
+ LLVMOpcode op;
char target_name[64];
src = insn->src->priv;
@@ -801,15 +803,31 @@ static void output_op_ptrcast(struct function *fn, struct instruction *insn)
assert(!is_float_type(insn->type));
- target = LLVMBuildBitCast(fn->builder, src, insn_symbol_type(insn), target_name);
+ dtype = insn_symbol_type(insn);
+ switch (LLVMGetTypeKind(LLVMTypeOf(src))) {
+ case LLVMPointerTypeKind:
+ op = LLVMBitCast;
+ break;
+ case LLVMIntegerTypeKind:
+ op = LLVMIntToPtr;
+ break;
+ default:
+ assert(0);
+ }
+ target = LLVMBuildCast(fn->builder, op, src, dtype, target_name);
insn->target->priv = target;
}
static void output_op_cast(struct function *fn, struct instruction *insn, LLVMOpcode op)
{
LLVMValueRef src, target;
+ LLVMTypeRef dtype;
char target_name[64];
+ unsigned int width;
+
+ if (is_ptr_type(insn->type)) // cast to void* is OP_CAST ...
+ return output_op_ptrcast(fn, insn);
src = insn->src->priv;
if (!src)
@@ -819,11 +837,23 @@ static void output_op_cast(struct function *fn, struct instruction *insn, LLVMOp
assert(!is_float_type(insn->type));
- if (insn->size < LLVMGetIntTypeWidth(LLVMTypeOf(src)))
- target = LLVMBuildTrunc(fn->builder, src, insn_symbol_type(insn), target_name);
- else
- target = LLVMBuildCast(fn->builder, op, src, insn_symbol_type(insn), target_name);
+ dtype = insn_symbol_type(insn);
+ switch (LLVMGetTypeKind(LLVMTypeOf(src))) {
+ case LLVMPointerTypeKind:
+ op = LLVMPtrToInt;
+ break;
+ case LLVMIntegerTypeKind:
+ width = LLVMGetIntTypeWidth(LLVMTypeOf(src));
+ if (insn->size < width)
+ op = LLVMTrunc;
+ else if (insn->size == width)
+ op = LLVMBitCast;
+ break;
+ default:
+ assert(0);
+ }
+ target = LLVMBuildCast(fn->builder, op, src, dtype, target_name);
insn->target->priv = target;
}