diff options
author | Pekka Enberg <penberg@kernel.org> | 2011-08-30 19:46:29 +0300 |
---|---|---|
committer | Pekka Enberg <penberg@kernel.org> | 2011-08-30 20:29:10 +0300 |
commit | c19ad437aee130bfde2ac41494d3a46900670dc6 (patch) | |
tree | 24786de5a073aa960e0611b85370cf7065c6b7ac | |
parent | 014de231b87ad9ba3f62b21abd4a591de742a5f4 (diff) | |
download | sparse-c19ad437aee130bfde2ac41494d3a46900670dc6.tar.gz |
sparse, llvm: Fix code generation for casts
Signed-off-by: Pekka Enberg <penberg@kernel.org>
-rw-r--r-- | sparse-llvm.c | 16 | ||||
-rw-r--r-- | validation/backend/cast.c | 47 |
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 + */ |