aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Transforms/Utils/BuildLibCalls.cpp
diff options
context:
space:
mode:
authorBenjamin Kramer <benny.kra@googlemail.com>2010-03-12 09:27:41 +0000
committerBenjamin Kramer <benny.kra@googlemail.com>2010-03-12 09:27:41 +0000
commitabd26d97b974242eee8af6a4fd38ae491a37eb61 (patch)
tree5b215ee4ea7339e068a16c0b92203d6c41f944c8 /lib/Transforms/Utils/BuildLibCalls.cpp
parent219a8bed7b44ee401da3ec15109f39daa5f31fa2 (diff)
downloadexternal_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.cpp81
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;
+}