diff options
author | Benjamin Kramer <benny.kra@googlemail.com> | 2010-03-12 09:27:41 +0000 |
---|---|---|
committer | Benjamin Kramer <benny.kra@googlemail.com> | 2010-03-12 09:27:41 +0000 |
commit | abd26d97b974242eee8af6a4fd38ae491a37eb61 (patch) | |
tree | 5b215ee4ea7339e068a16c0b92203d6c41f944c8 /lib/Transforms/Utils/BuildLibCalls.cpp | |
parent | 219a8bed7b44ee401da3ec15109f39daa5f31fa2 (diff) | |
download | external_llvm-abd26d97b974242eee8af6a4fd38ae491a37eb61.zip external_llvm-abd26d97b974242eee8af6a4fd38ae491a37eb61.tar.gz external_llvm-abd26d97b974242eee8af6a4fd38ae491a37eb61.tar.bz2 |
Factor checked library call optimization into a common helper class and use it
to unify the almost identical code in CodeGenPrepare and InstCombineCalls.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@98338 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Utils/BuildLibCalls.cpp')
-rw-r--r-- | lib/Transforms/Utils/BuildLibCalls.cpp | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/lib/Transforms/Utils/BuildLibCalls.cpp b/lib/Transforms/Utils/BuildLibCalls.cpp index a477634..82ccaea 100644 --- a/lib/Transforms/Utils/BuildLibCalls.cpp +++ b/lib/Transforms/Utils/BuildLibCalls.cpp @@ -342,3 +342,84 @@ void llvm::EmitFWrite(Value *Ptr, Value *Size, Value *File, if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts())) CI->setCallingConv(Fn->getCallingConv()); } + +bool SimplifyFortifiedLibCalls::fold(CallInst *CI, const TargetData *TD) { + this->CI = CI; + StringRef Name = CI->getCalledFunction()->getName(); + BasicBlock *BB = CI->getParent(); + IRBuilder<> B(CI->getParent()->getContext()); + + // Set the builder to the instruction after the call. + B.SetInsertPoint(BB, CI); + + if (Name == "__memcpy_chk") { + if (isFoldable(4, 3, false)) { + EmitMemCpy(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), + 1, B, TD); + replaceCall(CI->getOperand(1)); + return true; + } + return false; + } + + // Should be similar to memcpy. + if (Name == "__mempcpy_chk") { + return false; + } + + if (Name == "__memmove_chk") { + if (isFoldable(4, 3, false)) { + EmitMemMove(CI->getOperand(1), CI->getOperand(2), CI->getOperand(3), + 1, B, TD); + replaceCall(CI->getOperand(1)); + return true; + } + return false; + } + + if (Name == "__memset_chk") { + if (isFoldable(4, 3, false)) { + Value *Val = B.CreateIntCast(CI->getOperand(2), B.getInt8Ty(), + false); + EmitMemSet(CI->getOperand(1), Val, CI->getOperand(3), B, TD); + replaceCall(CI->getOperand(1)); + return true; + } + return false; + } + + if (Name == "__strcpy_chk" || Name == "__stpcpy_chk") { + // If a) we don't have any length information, or b) we know this will + // fit then just lower to a plain st[rp]cpy. Otherwise we'll keep our + // st[rp]cpy_chk call which may fail at runtime if the size is too long. + // TODO: It might be nice to get a maximum length out of the possible + // string lengths for varying. + if (isFoldable(3, 2, true)) { + Value *Ret = EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B, TD, + Name.substr(2, 6)); + replaceCall(Ret); + return true; + } + return false; + } + + if (Name == "__strncpy_chk") { + if (isFoldable(4, 3, false)) { + Value *Ret = EmitStrNCpy(CI->getOperand(1), CI->getOperand(2), + CI->getOperand(3), B, TD); + replaceCall(Ret); + return true; + } + return false; + } + + if (Name == "__strcat_chk") { + return false; + } + + if (Name == "__strncat_chk") { + return false; + } + + return false; +} |