summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Christopher <echristo@apple.com>2010-01-23 05:29:06 +0000
committerEric Christopher <echristo@apple.com>2010-01-23 05:29:06 +0000
commit7672d04f770c88b7b9152327a85936c01bab8035 (patch)
tree11e13b127c4adb7f82fba75028c1a9c7dca55333
parentd4acde2f493891ed082def4850e460c5a7056c7c (diff)
downloadllvm-7672d04f770c88b7b9152327a85936c01bab8035.tar.gz
llvm-7672d04f770c88b7b9152327a85936c01bab8035.tar.bz2
llvm-7672d04f770c88b7b9152327a85936c01bab8035.tar.xz
Reapply 94059 while fixing the calling convention setup
for strcpy. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@94287 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Transforms/Scalar/SimplifyLibCalls.cpp47
1 files changed, 47 insertions, 0 deletions
diff --git a/lib/Transforms/Scalar/SimplifyLibCalls.cpp b/lib/Transforms/Scalar/SimplifyLibCalls.cpp
index 9183f3aac1..a49da9ce9e 100644
--- a/lib/Transforms/Scalar/SimplifyLibCalls.cpp
+++ b/lib/Transforms/Scalar/SimplifyLibCalls.cpp
@@ -81,6 +81,10 @@ public:
/// and the return value has 'i8*' type.
Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B);
+ /// EmitStrCpy - Emit a call to the strcpy function to the builder, for the
+ /// specified pointer arguments.
+ Value *EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B);
+
/// EmitMemCpy - Emit a call to the memcpy function to the builder. This
/// always expects that the size has type 'intptr_t' and Dst/Src are pointers.
Value *EmitMemCpy(Value *Dst, Value *Src, Value *Len,
@@ -176,6 +180,22 @@ Value *LibCallOptimization::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B) {
return CI;
}
+/// EmitStrCpy - Emit a call to the strcpy function to the builder, for the
+/// specified pointer arguments.
+Value *LibCallOptimization::EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B) {
+ Module *M = Caller->getParent();
+ AttributeWithIndex AWI[2];
+ AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture);
+ AWI[1] = AttributeWithIndex::get(~0u, Attribute::NoUnwind);
+ const Type *I8Ptr = Type::getInt8PtrTy(*Context);
+ Value *StrCpy = M->getOrInsertFunction("strcpy", AttrListPtr::get(AWI, 2),
+ I8Ptr, I8Ptr, I8Ptr, NULL);
+ CallInst *CI = B.CreateCall2(StrCpy, CastToCStr(Dst, B), CastToCStr(Src, B),
+ "strcpy");
+ if (const Function *F = dyn_cast<Function>(StrCpy->stripPointerCasts()))
+ CI->setCallingConv(F->getCallingConv());
+ return CI;
+}
/// EmitMemCpy - Emit a call to the memcpy function to the builder. This always
/// expects that the size has type 'intptr_t' and Dst/Src are pointers.
@@ -1181,6 +1201,31 @@ struct MemMoveChkOpt : public LibCallOptimization {
}
};
+struct StrCpyChkOpt : public LibCallOptimization {
+ virtual Value *CallOptimizer(Function *Callee, CallInst *CI, IRBuilder<> &B) {
+ // These optimizations require TargetData.
+ if (!TD) return 0;
+
+ const FunctionType *FT = Callee->getFunctionType();
+ if (FT->getNumParams() != 3 || FT->getReturnType() != FT->getParamType(0) ||
+ !isa<PointerType>(FT->getParamType(0)) ||
+ !isa<PointerType>(FT->getParamType(1)) ||
+ !isa<IntegerType>(FT->getParamType(2)))
+ return 0;
+
+ ConstantInt *SizeCI = dyn_cast<ConstantInt>(CI->getOperand(3));
+ if (!SizeCI)
+ return 0;
+
+ // We don't have any length information, just lower to a plain strcpy.
+ if (SizeCI->isAllOnesValue())
+ return EmitStrCpy(CI->getOperand(1), CI->getOperand(2), B);
+
+ return 0;
+ }
+};
+
+
//===----------------------------------------------------------------------===//
// Math Library Optimizations
//===----------------------------------------------------------------------===//
@@ -1725,6 +1770,7 @@ namespace {
// Object Size Checking
MemCpyChkOpt MemCpyChk; MemSetChkOpt MemSetChk; MemMoveChkOpt MemMoveChk;
+ StrCpyChkOpt StrCpyChk;
bool Modified; // This is only used by doInitialization.
public:
@@ -1836,6 +1882,7 @@ void SimplifyLibCalls::InitOptimizations() {
Optimizations["__memcpy_chk"] = &MemCpyChk;
Optimizations["__memset_chk"] = &MemSetChk;
Optimizations["__memmove_chk"] = &MemMoveChk;
+ Optimizations["__strcpy_chk"] = &StrCpyChk;
}