diff options
author | Daniel Dunbar <daniel@zuster.org> | 2009-08-01 22:31:44 +0000 |
---|---|---|
committer | Daniel Dunbar <daniel@zuster.org> | 2009-08-01 22:31:44 +0000 |
commit | e07c9626f5ffeeef8fcb7cc9106efd732c79113c (patch) | |
tree | 8e06a3640e08bb17fcbc95514e33c50c6024ce36 /lib/Module/IntrinsicCleaner.cpp | |
parent | 3f22dfb755580dc8d608140f5b4274b0e7ba14cd (diff) | |
download | klee-e07c9626f5ffeeef8fcb7cc9106efd732c79113c.tar.gz |
Implement va_arg handling for x86_64.
- Based on a patch by Vladimir Kuznetsov! - x86_64 has a complicated calling convention for va_args; instead of dealing with this, this patch uses a clever workaround by initializing the va_list structure so that the callee believes all arguments were passed in the stack save area. git-svn-id: https://llvm.org/svn/llvm-project/klee/trunk@77819 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Module/IntrinsicCleaner.cpp')
-rw-r--r-- | lib/Module/IntrinsicCleaner.cpp | 36 |
1 files changed, 28 insertions, 8 deletions
diff --git a/lib/Module/IntrinsicCleaner.cpp b/lib/Module/IntrinsicCleaner.cpp index e59b7ff6..4f490e8e 100644 --- a/lib/Module/IntrinsicCleaner.cpp +++ b/lib/Module/IntrinsicCleaner.cpp @@ -33,13 +33,14 @@ bool IntrinsicCleanerPass::runOnModule(Module &M) { bool dirty = false; for (Module::iterator f = M.begin(), fe = M.end(); f != fe; ++f) for (Function::iterator b = f->begin(), be = f->end(); b != be; ++b) - dirty |= runOnBasicBlock(*b); + dirty |= runOnBasicBlock(*b); return dirty; } bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b) { bool dirty = false; - + + unsigned WordSize = TargetData.getPointerSizeInBits() / 8; for (BasicBlock::iterator i = b.begin(), ie = b.end(); i != ie;) { IntrinsicInst *ii = dyn_cast<IntrinsicInst>(&*i); // increment now since LowerIntrinsic deletion makes iterator invalid. @@ -51,15 +52,34 @@ bool IntrinsicCleanerPass::runOnBasicBlock(BasicBlock &b) { break; // Lower vacopy so that object resolution etc is handled by - // normal instructions. FIXME: This is broken for non-x86_32. + // normal instructions. + // + // FIXME: This is much more target dependent than just the word size, + // however this works for x86-32 and x86-64. case Intrinsic::vacopy: { // (dst, src) -> *((i8**) dst) = *((i8**) src) Value *dst = ii->getOperand(1); Value *src = ii->getOperand(2); - Type *i8pp = PointerType::getUnqual(PointerType::getUnqual(Type::Int8Ty)); - Value *castedDst = CastInst::CreatePointerCast(dst, i8pp, "vacopy.cast.dst", ii); - Value *castedSrc = CastInst::CreatePointerCast(src, i8pp, "vacopy.cast.src", ii); - Value *load = new LoadInst(castedSrc, "vacopy.read", ii); - new StoreInst(load, castedDst, false, ii); + + if (WordSize == 4) { + Type *i8pp = PointerType::getUnqual(PointerType::getUnqual(Type::Int8Ty)); + Value *castedDst = CastInst::CreatePointerCast(dst, i8pp, "vacopy.cast.dst", ii); + Value *castedSrc = CastInst::CreatePointerCast(src, i8pp, "vacopy.cast.src", ii); + Value *load = new LoadInst(castedSrc, "vacopy.read", ii); + new StoreInst(load, castedDst, false, ii); + } else { + assert(WordSize == 8 && "Invalid word size!"); + Type *i64p = PointerType::getUnqual(Type::Int64Ty); + Value *pDst = CastInst::CreatePointerCast(dst, i64p, "vacopy.cast.dst", ii); + Value *pSrc = CastInst::CreatePointerCast(src, i64p, "vacopy.cast.src", ii); + Value *val = new LoadInst(pSrc, std::string(), ii); new StoreInst(val, pDst, ii); + Value *off = ConstantInt::get(Type::Int64Ty, 1); + pDst = GetElementPtrInst::Create(pDst, off, std::string(), ii); + pSrc = GetElementPtrInst::Create(pSrc, off, std::string(), ii); + val = new LoadInst(pSrc, std::string(), ii); new StoreInst(val, pDst, ii); + pDst = GetElementPtrInst::Create(pDst, off, std::string(), ii); + pSrc = GetElementPtrInst::Create(pSrc, off, std::string(), ii); + val = new LoadInst(pSrc, std::string(), ii); new StoreInst(val, pDst, ii); + } ii->removeFromParent(); delete ii; break; |