aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPekka Enberg <penberg@kernel.org>2011-08-30 19:46:29 +0300
committerPekka Enberg <penberg@kernel.org>2011-08-30 20:29:10 +0300
commitc19ad437aee130bfde2ac41494d3a46900670dc6 (patch)
tree24786de5a073aa960e0611b85370cf7065c6b7ac
parent014de231b87ad9ba3f62b21abd4a591de742a5f4 (diff)
downloadsparse-c19ad437aee130bfde2ac41494d3a46900670dc6.tar.gz
sparse, llvm: Fix code generation for casts
Signed-off-by: Pekka Enberg <penberg@kernel.org>
-rw-r--r--sparse-llvm.c16
-rw-r--r--validation/backend/cast.c47
2 files changed, 57 insertions, 6 deletions
diff --git a/sparse-llvm.c b/sparse-llvm.c
index bf7389c9..bbf8646a 100644
--- a/sparse-llvm.c
+++ b/sparse-llvm.c
@@ -595,19 +595,23 @@ static void output_op_phi(struct function *fn, struct instruction *insn)
insn->target->priv = target;
}
-static void output_op_cast(struct function *fn, struct instruction *insn)
+static void output_op_cast(struct function *fn, struct instruction *insn, LLVMOpcode op)
{
LLVMValueRef src, target;
char target_name[64];
src = insn->src->priv;
+ if (!src)
+ src = pseudo_to_value(fn, insn, insn->src);
pseudo_name(insn->target, target_name);
- if (symbol_is_fp_type(insn->type))
- target = LLVMBuildFPCast(fn->builder, src, symbol_type(insn->type), target_name);
+ assert(!symbol_is_fp_type(insn->type));
+
+ if (insn->size < LLVMGetIntTypeWidth(LLVMTypeOf(src)))
+ target = LLVMBuildTrunc(fn->builder, src, symbol_type(insn->type), target_name);
else
- target = LLVMBuildZExt(fn->builder, src, symbol_type(insn->type), target_name);
+ target = LLVMBuildCast(fn->builder, op, src, symbol_type(insn->type), target_name);
insn->target->priv = target;
}
@@ -656,10 +660,10 @@ static void output_insn(struct function *fn, struct instruction *insn)
output_op_call(fn, insn);
break;
case OP_CAST:
- output_op_cast(fn, insn);
+ output_op_cast(fn, insn, LLVMZExt);
break;
case OP_SCAST:
- assert(0);
+ output_op_cast(fn, insn, LLVMSExt);
break;
case OP_FPCAST:
assert(0);
diff --git a/validation/backend/cast.c b/validation/backend/cast.c
new file mode 100644
index 00000000..3e677446
--- /dev/null
+++ b/validation/backend/cast.c
@@ -0,0 +1,47 @@
+typedef unsigned char uchar;
+typedef unsigned short ushort;
+typedef unsigned int uint;
+typedef unsigned long ulong;
+typedef long long longlong;
+typedef unsigned long long ulonglong;
+
+#define DEFINE_CAST(from, to) \
+ static to from##2##to(from x) { \
+ return x; \
+ }
+
+#define DEFINE_CASTS(from) \
+ DEFINE_CAST(from, char) \
+ DEFINE_CAST(from, uchar) \
+ DEFINE_CAST(from, short) \
+ DEFINE_CAST(from, ushort) \
+ DEFINE_CAST(from, int) \
+ DEFINE_CAST(from, uint) \
+ DEFINE_CAST(from, long) \
+ DEFINE_CAST(from, ulong) \
+ DEFINE_CAST(from, longlong) \
+ DEFINE_CAST(from, ulonglong) \
+/*
+ DEFINE_CAST(from, float) \
+ DEFINE_CAST(from, double)
+*/
+
+DEFINE_CASTS(char)
+DEFINE_CASTS(uchar)
+DEFINE_CASTS(short)
+DEFINE_CASTS(ushort)
+DEFINE_CASTS(int)
+DEFINE_CASTS(uint)
+DEFINE_CASTS(long)
+DEFINE_CASTS(ulong)
+DEFINE_CASTS(longlong)
+DEFINE_CASTS(ulonglong)
+/*
+DEFINE_CASTS(float)
+DEFINE_CASTS(double)
+*/
+
+/*
+ * check-name: Cast code generation
+ * check-command: ./sparsec -c $file -o tmp.o
+ */