diff options
author | Jeff Garzik <jeff@garzik.org> | 2011-08-31 00:39:49 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@redhat.com> | 2011-08-31 00:39:49 -0400 |
commit | 24b8e0ebe1c36a286621019e29b1c26f285df988 (patch) | |
tree | 304e426366238260714818cc07fcf1ac04d222b4 | |
parent | 85c19bf76ed7a4ce82790bdb1526d8b45f9cb454 (diff) | |
download | sparse-24b8e0ebe1c36a286621019e29b1c26f285df988.tar.gz |
sparse, llvm: support OP_STORE
testcase:
int foo(int *addr_i, int x)
{
*addr_i = x;
return x;
}
-rw-r--r-- | sparse-llvm.c | 32 |
1 files changed, 31 insertions, 1 deletions
diff --git a/sparse-llvm.c b/sparse-llvm.c index 41563833..dc80abb2 100644 --- a/sparse-llvm.c +++ b/sparse-llvm.c @@ -410,6 +410,33 @@ static void output_op_load(struct function *fn, struct instruction *insn) insn->target->priv = target; } +static void output_op_store(struct function *fn, struct instruction *insn) +{ + LLVMTypeRef int_type; + LLVMValueRef src_p, src_i, ofs_i, addr_i, addr, target, target_in; + + /* int type large enough to hold a pointer */ + int_type = LLVMIntType(bits_in_pointer); + + /* convert to integer, add src + offset */ + src_p = pseudo_to_value(fn, insn, insn->src); + src_i = LLVMBuildPtrToInt(fn->builder, src_p, int_type, "src_i"); + + ofs_i = LLVMConstInt(int_type, insn->offset, 0); + addr_i = LLVMBuildAdd(fn->builder, src_i, ofs_i, "addr_i"); + + /* convert address back to pointer */ + addr = LLVMBuildIntToPtr(fn->builder, addr_i, + LLVMPointerType(int_type, 0), "addr"); + + target_in = pseudo_to_value(fn, insn, insn->target); + + /* perform store */ + target = LLVMBuildStore(fn->builder, target_in, addr); + + insn->target->priv = target; +} + static void output_op_br(struct function *fn, struct instruction *br) { if (br->cond) { @@ -699,7 +726,10 @@ static void output_insn(struct function *fn, struct instruction *insn) case OP_LNOP: assert(0); break; - case OP_STORE: case OP_SNOP: + case OP_STORE: + output_op_store(fn, insn); + break; + case OP_SNOP: assert(0); break; case OP_INLINED_CALL: |