mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-28 03:25:23 +00:00
make all Emit*() functions consult the TargetLibraryInfo information before creating a call to a library function.
Update all clients to pass the TLI information around. Previous draft reviewed by Eli. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@160733 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -240,6 +240,8 @@ namespace llvm {
|
|||||||
cxa_guard_acquire,
|
cxa_guard_acquire,
|
||||||
/// void __cxa_guard_release(guard_t *guard);
|
/// void __cxa_guard_release(guard_t *guard);
|
||||||
cxa_guard_release,
|
cxa_guard_release,
|
||||||
|
/// void *__memcpy_chk(void *s1, const void *s2, size_t n, size_t s1size);
|
||||||
|
memcpy_chk,
|
||||||
|
|
||||||
NumLibFuncs
|
NumLibFuncs
|
||||||
};
|
};
|
||||||
|
@@ -28,41 +28,46 @@ namespace llvm {
|
|||||||
/// EmitStrLen - Emit a call to the strlen function to the builder, for the
|
/// EmitStrLen - Emit a call to the strlen function to the builder, for the
|
||||||
/// specified pointer. Ptr is required to be some pointer type, and the
|
/// specified pointer. Ptr is required to be some pointer type, and the
|
||||||
/// return value has 'intptr_t' type.
|
/// return value has 'intptr_t' type.
|
||||||
Value *EmitStrLen(Value *Ptr, IRBuilder<> &B, const TargetData *TD);
|
Value *EmitStrLen(Value *Ptr, IRBuilder<> &B, const TargetData *TD,
|
||||||
|
const TargetLibraryInfo *TLI);
|
||||||
|
|
||||||
/// EmitStrChr - Emit a call to the strchr function to the builder, for the
|
/// EmitStrChr - Emit a call to the strchr function to the builder, for the
|
||||||
/// specified pointer and character. Ptr is required to be some pointer type,
|
/// specified pointer and character. Ptr is required to be some pointer type,
|
||||||
/// and the return value has 'i8*' type.
|
/// and the return value has 'i8*' type.
|
||||||
Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B, const TargetData *TD);
|
Value *EmitStrChr(Value *Ptr, char C, IRBuilder<> &B, const TargetData *TD,
|
||||||
|
const TargetLibraryInfo *TLI);
|
||||||
|
|
||||||
/// EmitStrNCmp - Emit a call to the strncmp function to the builder.
|
/// EmitStrNCmp - Emit a call to the strncmp function to the builder.
|
||||||
Value *EmitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B,
|
Value *EmitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B,
|
||||||
const TargetData *TD);
|
const TargetData *TD, const TargetLibraryInfo *TLI);
|
||||||
|
|
||||||
/// EmitStrCpy - Emit a call to the strcpy function to the builder, for the
|
/// EmitStrCpy - Emit a call to the strcpy function to the builder, for the
|
||||||
/// specified pointer arguments.
|
/// specified pointer arguments.
|
||||||
Value *EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B,
|
Value *EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B,
|
||||||
const TargetData *TD, StringRef Name = "strcpy");
|
const TargetData *TD, const TargetLibraryInfo *TLI,
|
||||||
|
StringRef Name = "strcpy");
|
||||||
|
|
||||||
/// EmitStrNCpy - Emit a call to the strncpy function to the builder, for the
|
/// EmitStrNCpy - Emit a call to the strncpy function to the builder, for the
|
||||||
/// specified pointer arguments and length.
|
/// specified pointer arguments and length.
|
||||||
Value *EmitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B,
|
Value *EmitStrNCpy(Value *Dst, Value *Src, Value *Len, IRBuilder<> &B,
|
||||||
const TargetData *TD, StringRef Name = "strncpy");
|
const TargetData *TD, const TargetLibraryInfo *TLI,
|
||||||
|
StringRef Name = "strncpy");
|
||||||
|
|
||||||
/// EmitMemCpyChk - Emit a call to the __memcpy_chk function to the builder.
|
/// EmitMemCpyChk - Emit a call to the __memcpy_chk function to the builder.
|
||||||
/// This expects that the Len and ObjSize have type 'intptr_t' and Dst/Src
|
/// This expects that the Len and ObjSize have type 'intptr_t' and Dst/Src
|
||||||
/// are pointers.
|
/// are pointers.
|
||||||
Value *EmitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize,
|
Value *EmitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize,
|
||||||
IRBuilder<> &B, const TargetData *TD);
|
IRBuilder<> &B, const TargetData *TD,
|
||||||
|
const TargetLibraryInfo *TLI);
|
||||||
|
|
||||||
/// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is
|
/// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is
|
||||||
/// a pointer, Val is an i32 value, and Len is an 'intptr_t' value.
|
/// a pointer, Val is an i32 value, and Len is an 'intptr_t' value.
|
||||||
Value *EmitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B,
|
Value *EmitMemChr(Value *Ptr, Value *Val, Value *Len, IRBuilder<> &B,
|
||||||
const TargetData *TD);
|
const TargetData *TD, const TargetLibraryInfo *TLI);
|
||||||
|
|
||||||
/// EmitMemCmp - Emit a call to the memcmp function.
|
/// EmitMemCmp - Emit a call to the memcmp function.
|
||||||
Value *EmitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B,
|
Value *EmitMemCmp(Value *Ptr1, Value *Ptr2, Value *Len, IRBuilder<> &B,
|
||||||
const TargetData *TD);
|
const TargetData *TD, const TargetLibraryInfo *TLI);
|
||||||
|
|
||||||
/// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name'
|
/// EmitUnaryFloatFnCall - Emit a call to the unary function named 'Name'
|
||||||
/// (e.g. 'floor'). This function is known to take a single of type matching
|
/// (e.g. 'floor'). This function is known to take a single of type matching
|
||||||
@@ -74,26 +79,28 @@ namespace llvm {
|
|||||||
|
|
||||||
/// EmitPutChar - Emit a call to the putchar function. This assumes that Char
|
/// EmitPutChar - Emit a call to the putchar function. This assumes that Char
|
||||||
/// is an integer.
|
/// is an integer.
|
||||||
Value *EmitPutChar(Value *Char, IRBuilder<> &B, const TargetData *TD);
|
Value *EmitPutChar(Value *Char, IRBuilder<> &B, const TargetData *TD,
|
||||||
|
const TargetLibraryInfo *TLI);
|
||||||
|
|
||||||
/// EmitPutS - Emit a call to the puts function. This assumes that Str is
|
/// EmitPutS - Emit a call to the puts function. This assumes that Str is
|
||||||
/// some pointer.
|
/// some pointer.
|
||||||
void EmitPutS(Value *Str, IRBuilder<> &B, const TargetData *TD);
|
Value *EmitPutS(Value *Str, IRBuilder<> &B, const TargetData *TD,
|
||||||
|
const TargetLibraryInfo *TLI);
|
||||||
|
|
||||||
/// EmitFPutC - Emit a call to the fputc function. This assumes that Char is
|
/// EmitFPutC - Emit a call to the fputc function. This assumes that Char is
|
||||||
/// an i32, and File is a pointer to FILE.
|
/// an i32, and File is a pointer to FILE.
|
||||||
void EmitFPutC(Value *Char, Value *File, IRBuilder<> &B,
|
Value *EmitFPutC(Value *Char, Value *File, IRBuilder<> &B,
|
||||||
const TargetData *TD);
|
const TargetData *TD, const TargetLibraryInfo *TLI);
|
||||||
|
|
||||||
/// EmitFPutS - Emit a call to the puts function. Str is required to be a
|
/// EmitFPutS - Emit a call to the puts function. Str is required to be a
|
||||||
/// pointer and File is a pointer to FILE.
|
/// pointer and File is a pointer to FILE.
|
||||||
void EmitFPutS(Value *Str, Value *File, IRBuilder<> &B, const TargetData *TD,
|
Value *EmitFPutS(Value *Str, Value *File, IRBuilder<> &B, const TargetData *TD,
|
||||||
const TargetLibraryInfo *TLI);
|
const TargetLibraryInfo *TLI);
|
||||||
|
|
||||||
/// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is
|
/// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is
|
||||||
/// a pointer, Size is an 'intptr_t', and File is a pointer to FILE.
|
/// a pointer, Size is an 'intptr_t', and File is a pointer to FILE.
|
||||||
void EmitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B,
|
Value *EmitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilder<> &B,
|
||||||
const TargetData *TD, const TargetLibraryInfo *TLI);
|
const TargetData *TD, const TargetLibraryInfo *TLI);
|
||||||
|
|
||||||
/// SimplifyFortifiedLibCalls - Helper class for folding checked library
|
/// SimplifyFortifiedLibCalls - Helper class for folding checked library
|
||||||
/// calls (e.g. __strcpy_chk) into their unchecked counterparts.
|
/// calls (e.g. __strcpy_chk) into their unchecked counterparts.
|
||||||
@@ -105,7 +112,7 @@ namespace llvm {
|
|||||||
bool isString) const = 0;
|
bool isString) const = 0;
|
||||||
public:
|
public:
|
||||||
virtual ~SimplifyFortifiedLibCalls();
|
virtual ~SimplifyFortifiedLibCalls();
|
||||||
bool fold(CallInst *CI, const TargetData *TD);
|
bool fold(CallInst *CI, const TargetData *TD, const TargetLibraryInfo *TLI);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -133,7 +133,8 @@ const char* TargetLibraryInfo::StandardNames[LibFunc::NumLibFuncs] =
|
|||||||
"__cxa_atexit",
|
"__cxa_atexit",
|
||||||
"__cxa_guard_abort",
|
"__cxa_guard_abort",
|
||||||
"__cxa_guard_acquire",
|
"__cxa_guard_acquire",
|
||||||
"__cxa_guard_release"
|
"__cxa_guard_release",
|
||||||
|
"__memcpy_chk"
|
||||||
};
|
};
|
||||||
|
|
||||||
/// initialize - Initialize the set of available library functions based on the
|
/// initialize - Initialize the set of available library functions based on the
|
||||||
|
@@ -795,7 +795,7 @@ Instruction *InstCombiner::tryOptimizeCall(CallInst *CI, const TargetData *TD) {
|
|||||||
if (CI->getCalledFunction() == 0) return 0;
|
if (CI->getCalledFunction() == 0) return 0;
|
||||||
|
|
||||||
InstCombineFortifiedLibCalls Simplifier(this);
|
InstCombineFortifiedLibCalls Simplifier(this);
|
||||||
Simplifier.fold(CI, TD);
|
Simplifier.fold(CI, TD, TLI);
|
||||||
return Simplifier.NewInstruction;
|
return Simplifier.NewInstruction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -610,7 +610,7 @@ bool CodeGenPrepare::OptimizeCallInst(CallInst *CI) {
|
|||||||
// that have the default "don't know" as the objectsize. Anything else
|
// that have the default "don't know" as the objectsize. Anything else
|
||||||
// should be left alone.
|
// should be left alone.
|
||||||
CodeGenPrepareFortifiedLibCalls Simplifier;
|
CodeGenPrepareFortifiedLibCalls Simplifier;
|
||||||
return Simplifier.fold(CI, TD);
|
return Simplifier.fold(CI, TD, TLInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DupRetToEnableTailCallOpts - Look for opportunities to duplicate return
|
/// DupRetToEnableTailCallOpts - Look for opportunities to duplicate return
|
||||||
|
@@ -164,7 +164,7 @@ struct StrCatOpt : public LibCallOptimization {
|
|||||||
void EmitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len, IRBuilder<> &B) {
|
void EmitStrLenMemCpy(Value *Src, Value *Dst, uint64_t Len, IRBuilder<> &B) {
|
||||||
// We need to find the end of the destination string. That's where the
|
// We need to find the end of the destination string. That's where the
|
||||||
// memory is to be moved to. We just generate a call to strlen.
|
// memory is to be moved to. We just generate a call to strlen.
|
||||||
Value *DstLen = EmitStrLen(Dst, B, TD);
|
Value *DstLen = EmitStrLen(Dst, B, TD, TLI);
|
||||||
|
|
||||||
// Now that we have the destination's length, we must index into the
|
// Now that we have the destination's length, we must index into the
|
||||||
// destination's pointer to get the actual memcpy destination (end of
|
// destination's pointer to get the actual memcpy destination (end of
|
||||||
@@ -254,7 +254,7 @@ struct StrChrOpt : public LibCallOptimization {
|
|||||||
|
|
||||||
return EmitMemChr(SrcStr, CI->getArgOperand(1), // include nul.
|
return EmitMemChr(SrcStr, CI->getArgOperand(1), // include nul.
|
||||||
ConstantInt::get(TD->getIntPtrType(*Context), Len),
|
ConstantInt::get(TD->getIntPtrType(*Context), Len),
|
||||||
B, TD);
|
B, TD, TLI);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, the character is a constant, see if the first argument is
|
// Otherwise, the character is a constant, see if the first argument is
|
||||||
@@ -299,7 +299,7 @@ struct StrRChrOpt : public LibCallOptimization {
|
|||||||
if (!getConstantStringInfo(SrcStr, Str)) {
|
if (!getConstantStringInfo(SrcStr, Str)) {
|
||||||
// strrchr(s, 0) -> strchr(s, 0)
|
// strrchr(s, 0) -> strchr(s, 0)
|
||||||
if (TD && CharC->isZero())
|
if (TD && CharC->isZero())
|
||||||
return EmitStrChr(SrcStr, '\0', B, TD);
|
return EmitStrChr(SrcStr, '\0', B, TD, TLI);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -355,7 +355,7 @@ struct StrCmpOpt : public LibCallOptimization {
|
|||||||
|
|
||||||
return EmitMemCmp(Str1P, Str2P,
|
return EmitMemCmp(Str1P, Str2P,
|
||||||
ConstantInt::get(TD->getIntPtrType(*Context),
|
ConstantInt::get(TD->getIntPtrType(*Context),
|
||||||
std::min(Len1, Len2)), B, TD);
|
std::min(Len1, Len2)), B, TD, TLI);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -391,7 +391,7 @@ struct StrNCmpOpt : public LibCallOptimization {
|
|||||||
return ConstantInt::get(CI->getType(), 0);
|
return ConstantInt::get(CI->getType(), 0);
|
||||||
|
|
||||||
if (TD && Length == 1) // strncmp(x,y,1) -> memcmp(x,y,1)
|
if (TD && Length == 1) // strncmp(x,y,1) -> memcmp(x,y,1)
|
||||||
return EmitMemCmp(Str1P, Str2P, CI->getArgOperand(2), B, TD);
|
return EmitMemCmp(Str1P, Str2P, CI->getArgOperand(2), B, TD, TLI);
|
||||||
|
|
||||||
StringRef Str1, Str2;
|
StringRef Str1, Str2;
|
||||||
bool HasStr1 = getConstantStringInfo(Str1P, Str1);
|
bool HasStr1 = getConstantStringInfo(Str1P, Str1);
|
||||||
@@ -450,7 +450,7 @@ struct StrCpyOpt : public LibCallOptimization {
|
|||||||
if (OptChkCall)
|
if (OptChkCall)
|
||||||
EmitMemCpyChk(Dst, Src,
|
EmitMemCpyChk(Dst, Src,
|
||||||
ConstantInt::get(TD->getIntPtrType(*Context), Len),
|
ConstantInt::get(TD->getIntPtrType(*Context), Len),
|
||||||
CI->getArgOperand(2), B, TD);
|
CI->getArgOperand(2), B, TD, TLI);
|
||||||
else
|
else
|
||||||
B.CreateMemCpy(Dst, Src,
|
B.CreateMemCpy(Dst, Src,
|
||||||
ConstantInt::get(TD->getIntPtrType(*Context), Len), 1);
|
ConstantInt::get(TD->getIntPtrType(*Context), Len), 1);
|
||||||
@@ -480,8 +480,10 @@ struct StpCpyOpt: public LibCallOptimization {
|
|||||||
if (!TD) return 0;
|
if (!TD) return 0;
|
||||||
|
|
||||||
Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1);
|
Value *Dst = CI->getArgOperand(0), *Src = CI->getArgOperand(1);
|
||||||
if (Dst == Src) // stpcpy(x,x) -> x+strlen(x)
|
if (Dst == Src) { // stpcpy(x,x) -> x+strlen(x)
|
||||||
return B.CreateInBoundsGEP(Dst, EmitStrLen(Src, B, TD));
|
Value *StrLen = EmitStrLen(Src, B, TD, TLI);
|
||||||
|
return StrLen ? B.CreateInBoundsGEP(Dst, StrLen) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
// See if we can get the length of the input string.
|
// See if we can get the length of the input string.
|
||||||
uint64_t Len = GetStringLength(Src);
|
uint64_t Len = GetStringLength(Src);
|
||||||
@@ -495,7 +497,7 @@ struct StpCpyOpt: public LibCallOptimization {
|
|||||||
// We have enough information to now generate the memcpy call to do the
|
// We have enough information to now generate the memcpy call to do the
|
||||||
// copy for us. Make a memcpy to copy the nul byte with align = 1.
|
// copy for us. Make a memcpy to copy the nul byte with align = 1.
|
||||||
if (OptChkCall)
|
if (OptChkCall)
|
||||||
EmitMemCpyChk(Dst, Src, LenV, CI->getArgOperand(2), B, TD);
|
EmitMemCpyChk(Dst, Src, LenV, CI->getArgOperand(2), B, TD, TLI);
|
||||||
else
|
else
|
||||||
B.CreateMemCpy(Dst, Src, LenV, 1);
|
B.CreateMemCpy(Dst, Src, LenV, 1);
|
||||||
return DstEnd;
|
return DstEnd;
|
||||||
@@ -609,7 +611,7 @@ struct StrPBrkOpt : public LibCallOptimization {
|
|||||||
|
|
||||||
// strpbrk(s, "a") -> strchr(s, 'a')
|
// strpbrk(s, "a") -> strchr(s, 'a')
|
||||||
if (TD && HasS2 && S2.size() == 1)
|
if (TD && HasS2 && S2.size() == 1)
|
||||||
return EmitStrChr(CI->getArgOperand(0), S2[0], B, TD);
|
return EmitStrChr(CI->getArgOperand(0), S2[0], B, TD, TLI);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -698,7 +700,7 @@ struct StrCSpnOpt : public LibCallOptimization {
|
|||||||
|
|
||||||
// strcspn(s, "") -> strlen(s)
|
// strcspn(s, "") -> strlen(s)
|
||||||
if (TD && HasS2 && S2.empty())
|
if (TD && HasS2 && S2.empty())
|
||||||
return EmitStrLen(CI->getArgOperand(0), B, TD);
|
return EmitStrLen(CI->getArgOperand(0), B, TD, TLI);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -722,9 +724,13 @@ struct StrStrOpt : public LibCallOptimization {
|
|||||||
|
|
||||||
// fold strstr(a, b) == a -> strncmp(a, b, strlen(b)) == 0
|
// fold strstr(a, b) == a -> strncmp(a, b, strlen(b)) == 0
|
||||||
if (TD && IsOnlyUsedInEqualityComparison(CI, CI->getArgOperand(0))) {
|
if (TD && IsOnlyUsedInEqualityComparison(CI, CI->getArgOperand(0))) {
|
||||||
Value *StrLen = EmitStrLen(CI->getArgOperand(1), B, TD);
|
Value *StrLen = EmitStrLen(CI->getArgOperand(1), B, TD, TLI);
|
||||||
|
if (!StrLen)
|
||||||
|
return 0;
|
||||||
Value *StrNCmp = EmitStrNCmp(CI->getArgOperand(0), CI->getArgOperand(1),
|
Value *StrNCmp = EmitStrNCmp(CI->getArgOperand(0), CI->getArgOperand(1),
|
||||||
StrLen, B, TD);
|
StrLen, B, TD, TLI);
|
||||||
|
if (!StrNCmp)
|
||||||
|
return 0;
|
||||||
for (Value::use_iterator UI = CI->use_begin(), UE = CI->use_end();
|
for (Value::use_iterator UI = CI->use_begin(), UE = CI->use_end();
|
||||||
UI != UE; ) {
|
UI != UE; ) {
|
||||||
ICmpInst *Old = cast<ICmpInst>(*UI++);
|
ICmpInst *Old = cast<ICmpInst>(*UI++);
|
||||||
@@ -760,9 +766,10 @@ struct StrStrOpt : public LibCallOptimization {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// fold strstr(x, "y") -> strchr(x, 'y').
|
// fold strstr(x, "y") -> strchr(x, 'y').
|
||||||
if (HasStr2 && ToFindStr.size() == 1)
|
if (HasStr2 && ToFindStr.size() == 1) {
|
||||||
return B.CreateBitCast(EmitStrChr(CI->getArgOperand(0),
|
Value *StrChr= EmitStrChr(CI->getArgOperand(0), ToFindStr[0], B, TD, TLI);
|
||||||
ToFindStr[0], B, TD), CI->getType());
|
return StrChr ? B.CreateBitCast(StrChr, CI->getType()) : 0;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -1179,7 +1186,7 @@ struct PrintFOpt : public LibCallOptimization {
|
|||||||
|
|
||||||
// printf("x") -> putchar('x'), even for '%'.
|
// printf("x") -> putchar('x'), even for '%'.
|
||||||
if (FormatStr.size() == 1) {
|
if (FormatStr.size() == 1) {
|
||||||
Value *Res = EmitPutChar(B.getInt32(FormatStr[0]), B, TD);
|
Value *Res = EmitPutChar(B.getInt32(FormatStr[0]), B, TD, TLI);
|
||||||
if (CI->use_empty()) return CI;
|
if (CI->use_empty()) return CI;
|
||||||
return B.CreateIntCast(Res, CI->getType(), true);
|
return B.CreateIntCast(Res, CI->getType(), true);
|
||||||
}
|
}
|
||||||
@@ -1191,16 +1198,17 @@ struct PrintFOpt : public LibCallOptimization {
|
|||||||
// pass to be run after this pass, to merge duplicate strings.
|
// pass to be run after this pass, to merge duplicate strings.
|
||||||
FormatStr = FormatStr.drop_back();
|
FormatStr = FormatStr.drop_back();
|
||||||
Value *GV = B.CreateGlobalString(FormatStr, "str");
|
Value *GV = B.CreateGlobalString(FormatStr, "str");
|
||||||
EmitPutS(GV, B, TD);
|
Value *NewCI = EmitPutS(GV, B, TD, TLI);
|
||||||
return CI->use_empty() ? (Value*)CI :
|
return (CI->use_empty() || !NewCI) ?
|
||||||
ConstantInt::get(CI->getType(), FormatStr.size()+1);
|
NewCI :
|
||||||
|
ConstantInt::get(CI->getType(), FormatStr.size()+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optimize specific format strings.
|
// Optimize specific format strings.
|
||||||
// printf("%c", chr) --> putchar(chr)
|
// printf("%c", chr) --> putchar(chr)
|
||||||
if (FormatStr == "%c" && CI->getNumArgOperands() > 1 &&
|
if (FormatStr == "%c" && CI->getNumArgOperands() > 1 &&
|
||||||
CI->getArgOperand(1)->getType()->isIntegerTy()) {
|
CI->getArgOperand(1)->getType()->isIntegerTy()) {
|
||||||
Value *Res = EmitPutChar(CI->getArgOperand(1), B, TD);
|
Value *Res = EmitPutChar(CI->getArgOperand(1), B, TD, TLI);
|
||||||
|
|
||||||
if (CI->use_empty()) return CI;
|
if (CI->use_empty()) return CI;
|
||||||
return B.CreateIntCast(Res, CI->getType(), true);
|
return B.CreateIntCast(Res, CI->getType(), true);
|
||||||
@@ -1209,8 +1217,7 @@ struct PrintFOpt : public LibCallOptimization {
|
|||||||
// printf("%s\n", str) --> puts(str)
|
// printf("%s\n", str) --> puts(str)
|
||||||
if (FormatStr == "%s\n" && CI->getNumArgOperands() > 1 &&
|
if (FormatStr == "%s\n" && CI->getNumArgOperands() > 1 &&
|
||||||
CI->getArgOperand(1)->getType()->isPointerTy()) {
|
CI->getArgOperand(1)->getType()->isPointerTy()) {
|
||||||
EmitPutS(CI->getArgOperand(1), B, TD);
|
return EmitPutS(CI->getArgOperand(1), B, TD, TLI);
|
||||||
return CI;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1297,7 +1304,9 @@ struct SPrintFOpt : public LibCallOptimization {
|
|||||||
// sprintf(dest, "%s", str) -> llvm.memcpy(dest, str, strlen(str)+1, 1)
|
// sprintf(dest, "%s", str) -> llvm.memcpy(dest, str, strlen(str)+1, 1)
|
||||||
if (!CI->getArgOperand(2)->getType()->isPointerTy()) return 0;
|
if (!CI->getArgOperand(2)->getType()->isPointerTy()) return 0;
|
||||||
|
|
||||||
Value *Len = EmitStrLen(CI->getArgOperand(2), B, TD);
|
Value *Len = EmitStrLen(CI->getArgOperand(2), B, TD, TLI);
|
||||||
|
if (!Len)
|
||||||
|
return 0;
|
||||||
Value *IncLen = B.CreateAdd(Len,
|
Value *IncLen = B.CreateAdd(Len,
|
||||||
ConstantInt::get(Len->getType(), 1),
|
ConstantInt::get(Len->getType(), 1),
|
||||||
"leninc");
|
"leninc");
|
||||||
@@ -1364,8 +1373,8 @@ struct FWriteOpt : public LibCallOptimization {
|
|||||||
// This optimisation is only valid, if the return value is unused.
|
// This optimisation is only valid, if the return value is unused.
|
||||||
if (Bytes == 1 && CI->use_empty()) { // fwrite(S,1,1,F) -> fputc(S[0],F)
|
if (Bytes == 1 && CI->use_empty()) { // fwrite(S,1,1,F) -> fputc(S[0],F)
|
||||||
Value *Char = B.CreateLoad(CastToCStr(CI->getArgOperand(0), B), "char");
|
Value *Char = B.CreateLoad(CastToCStr(CI->getArgOperand(0), B), "char");
|
||||||
EmitFPutC(Char, CI->getArgOperand(3), B, TD);
|
Value *NewCI = EmitFPutC(Char, CI->getArgOperand(3), B, TD, TLI);
|
||||||
return ConstantInt::get(CI->getType(), 1);
|
return NewCI ? ConstantInt::get(CI->getType(), 1) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -1390,10 +1399,10 @@ struct FPutsOpt : public LibCallOptimization {
|
|||||||
// fputs(s,F) --> fwrite(s,1,strlen(s),F)
|
// fputs(s,F) --> fwrite(s,1,strlen(s),F)
|
||||||
uint64_t Len = GetStringLength(CI->getArgOperand(0));
|
uint64_t Len = GetStringLength(CI->getArgOperand(0));
|
||||||
if (!Len) return 0;
|
if (!Len) return 0;
|
||||||
EmitFWrite(CI->getArgOperand(0),
|
// Known to have no uses (see above).
|
||||||
ConstantInt::get(TD->getIntPtrType(*Context), Len-1),
|
return EmitFWrite(CI->getArgOperand(0),
|
||||||
CI->getArgOperand(1), B, TD, TLI);
|
ConstantInt::get(TD->getIntPtrType(*Context), Len-1),
|
||||||
return CI; // Known to have no uses (see above).
|
CI->getArgOperand(1), B, TD, TLI);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1417,11 +1426,11 @@ struct FPrintFOpt : public LibCallOptimization {
|
|||||||
// These optimizations require TargetData.
|
// These optimizations require TargetData.
|
||||||
if (!TD) return 0;
|
if (!TD) return 0;
|
||||||
|
|
||||||
EmitFWrite(CI->getArgOperand(1),
|
Value *NewCI = EmitFWrite(CI->getArgOperand(1),
|
||||||
ConstantInt::get(TD->getIntPtrType(*Context),
|
ConstantInt::get(TD->getIntPtrType(*Context),
|
||||||
FormatStr.size()),
|
FormatStr.size()),
|
||||||
CI->getArgOperand(0), B, TD, TLI);
|
CI->getArgOperand(0), B, TD, TLI);
|
||||||
return ConstantInt::get(CI->getType(), FormatStr.size());
|
return NewCI ? ConstantInt::get(CI->getType(), FormatStr.size()) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The remaining optimizations require the format string to be "%s" or "%c"
|
// The remaining optimizations require the format string to be "%s" or "%c"
|
||||||
@@ -1434,16 +1443,16 @@ struct FPrintFOpt : public LibCallOptimization {
|
|||||||
if (FormatStr[1] == 'c') {
|
if (FormatStr[1] == 'c') {
|
||||||
// fprintf(F, "%c", chr) --> fputc(chr, F)
|
// fprintf(F, "%c", chr) --> fputc(chr, F)
|
||||||
if (!CI->getArgOperand(2)->getType()->isIntegerTy()) return 0;
|
if (!CI->getArgOperand(2)->getType()->isIntegerTy()) return 0;
|
||||||
EmitFPutC(CI->getArgOperand(2), CI->getArgOperand(0), B, TD);
|
Value *NewCI = EmitFPutC(CI->getArgOperand(2), CI->getArgOperand(0), B,
|
||||||
return ConstantInt::get(CI->getType(), 1);
|
TD, TLI);
|
||||||
|
return NewCI ? ConstantInt::get(CI->getType(), 1) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (FormatStr[1] == 's') {
|
if (FormatStr[1] == 's') {
|
||||||
// fprintf(F, "%s", str) --> fputs(str, F)
|
// fprintf(F, "%s", str) --> fputs(str, F)
|
||||||
if (!CI->getArgOperand(2)->getType()->isPointerTy() || !CI->use_empty())
|
if (!CI->getArgOperand(2)->getType()->isPointerTy() || !CI->use_empty())
|
||||||
return 0;
|
return 0;
|
||||||
EmitFPutS(CI->getArgOperand(2), CI->getArgOperand(0), B, TD, TLI);
|
return EmitFPutS(CI->getArgOperand(2), CI->getArgOperand(0), B, TD, TLI);
|
||||||
return CI;
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -1494,7 +1503,8 @@ struct PutsOpt : public LibCallOptimization {
|
|||||||
|
|
||||||
if (Str.empty() && CI->use_empty()) {
|
if (Str.empty() && CI->use_empty()) {
|
||||||
// puts("") -> putchar('\n')
|
// puts("") -> putchar('\n')
|
||||||
Value *Res = EmitPutChar(B.getInt32('\n'), B, TD);
|
Value *Res = EmitPutChar(B.getInt32('\n'), B, TD, TLI);
|
||||||
|
if (!Res) return 0;
|
||||||
if (CI->use_empty()) return CI;
|
if (CI->use_empty()) return CI;
|
||||||
return B.CreateIntCast(Res, CI->getType(), true);
|
return B.CreateIntCast(Res, CI->getType(), true);
|
||||||
}
|
}
|
||||||
|
@@ -34,7 +34,11 @@ Value *llvm::CastToCStr(Value *V, IRBuilder<> &B) {
|
|||||||
|
|
||||||
/// EmitStrLen - Emit a call to the strlen function to the builder, for the
|
/// EmitStrLen - Emit a call to the strlen function to the builder, for the
|
||||||
/// specified pointer. This always returns an integer value of size intptr_t.
|
/// specified pointer. This always returns an integer value of size intptr_t.
|
||||||
Value *llvm::EmitStrLen(Value *Ptr, IRBuilder<> &B, const TargetData *TD) {
|
Value *llvm::EmitStrLen(Value *Ptr, IRBuilder<> &B, const TargetData *TD,
|
||||||
|
const TargetLibraryInfo *TLI) {
|
||||||
|
if (!TLI->has(LibFunc::strlen))
|
||||||
|
return 0;
|
||||||
|
|
||||||
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
||||||
AttributeWithIndex AWI[2];
|
AttributeWithIndex AWI[2];
|
||||||
AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
|
AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
|
||||||
@@ -57,7 +61,10 @@ Value *llvm::EmitStrLen(Value *Ptr, IRBuilder<> &B, const TargetData *TD) {
|
|||||||
/// specified pointer and character. Ptr is required to be some pointer type,
|
/// specified pointer and character. Ptr is required to be some pointer type,
|
||||||
/// and the return value has 'i8*' type.
|
/// and the return value has 'i8*' type.
|
||||||
Value *llvm::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B,
|
Value *llvm::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B,
|
||||||
const TargetData *TD) {
|
const TargetData *TD, const TargetLibraryInfo *TLI) {
|
||||||
|
if (!TLI->has(LibFunc::strchr))
|
||||||
|
return 0;
|
||||||
|
|
||||||
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
||||||
AttributeWithIndex AWI =
|
AttributeWithIndex AWI =
|
||||||
AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind);
|
AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind);
|
||||||
@@ -75,7 +82,11 @@ Value *llvm::EmitStrChr(Value *Ptr, char C, IRBuilder<> &B,
|
|||||||
|
|
||||||
/// EmitStrNCmp - Emit a call to the strncmp function to the builder.
|
/// EmitStrNCmp - Emit a call to the strncmp function to the builder.
|
||||||
Value *llvm::EmitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len,
|
Value *llvm::EmitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len,
|
||||||
IRBuilder<> &B, const TargetData *TD) {
|
IRBuilder<> &B, const TargetData *TD,
|
||||||
|
const TargetLibraryInfo *TLI) {
|
||||||
|
if (!TLI->has(LibFunc::strncmp))
|
||||||
|
return 0;
|
||||||
|
|
||||||
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
||||||
AttributeWithIndex AWI[3];
|
AttributeWithIndex AWI[3];
|
||||||
AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
|
AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
|
||||||
@@ -101,7 +112,11 @@ Value *llvm::EmitStrNCmp(Value *Ptr1, Value *Ptr2, Value *Len,
|
|||||||
/// EmitStrCpy - Emit a call to the strcpy function to the builder, for the
|
/// EmitStrCpy - Emit a call to the strcpy function to the builder, for the
|
||||||
/// specified pointer arguments.
|
/// specified pointer arguments.
|
||||||
Value *llvm::EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B,
|
Value *llvm::EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B,
|
||||||
const TargetData *TD, StringRef Name) {
|
const TargetData *TD, const TargetLibraryInfo *TLI,
|
||||||
|
StringRef Name) {
|
||||||
|
if (!TLI->has(LibFunc::strcpy))
|
||||||
|
return 0;
|
||||||
|
|
||||||
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
||||||
AttributeWithIndex AWI[2];
|
AttributeWithIndex AWI[2];
|
||||||
AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture);
|
AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture);
|
||||||
@@ -119,7 +134,11 @@ Value *llvm::EmitStrCpy(Value *Dst, Value *Src, IRBuilder<> &B,
|
|||||||
/// EmitStrNCpy - Emit a call to the strncpy function to the builder, for the
|
/// EmitStrNCpy - Emit a call to the strncpy function to the builder, for the
|
||||||
/// specified pointer arguments.
|
/// specified pointer arguments.
|
||||||
Value *llvm::EmitStrNCpy(Value *Dst, Value *Src, Value *Len,
|
Value *llvm::EmitStrNCpy(Value *Dst, Value *Src, Value *Len,
|
||||||
IRBuilder<> &B, const TargetData *TD, StringRef Name) {
|
IRBuilder<> &B, const TargetData *TD,
|
||||||
|
const TargetLibraryInfo *TLI, StringRef Name) {
|
||||||
|
if (!TLI->has(LibFunc::strncpy))
|
||||||
|
return 0;
|
||||||
|
|
||||||
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
||||||
AttributeWithIndex AWI[2];
|
AttributeWithIndex AWI[2];
|
||||||
AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture);
|
AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture);
|
||||||
@@ -139,7 +158,11 @@ Value *llvm::EmitStrNCpy(Value *Dst, Value *Src, Value *Len,
|
|||||||
/// This expects that the Len and ObjSize have type 'intptr_t' and Dst/Src
|
/// This expects that the Len and ObjSize have type 'intptr_t' and Dst/Src
|
||||||
/// are pointers.
|
/// are pointers.
|
||||||
Value *llvm::EmitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize,
|
Value *llvm::EmitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize,
|
||||||
IRBuilder<> &B, const TargetData *TD) {
|
IRBuilder<> &B, const TargetData *TD,
|
||||||
|
const TargetLibraryInfo *TLI) {
|
||||||
|
if (!TLI->has(LibFunc::memcpy_chk))
|
||||||
|
return 0;
|
||||||
|
|
||||||
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
||||||
AttributeWithIndex AWI;
|
AttributeWithIndex AWI;
|
||||||
AWI = AttributeWithIndex::get(~0u, Attribute::NoUnwind);
|
AWI = AttributeWithIndex::get(~0u, Attribute::NoUnwind);
|
||||||
@@ -162,7 +185,11 @@ Value *llvm::EmitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize,
|
|||||||
/// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is
|
/// EmitMemChr - Emit a call to the memchr function. This assumes that Ptr is
|
||||||
/// a pointer, Val is an i32 value, and Len is an 'intptr_t' value.
|
/// a pointer, Val is an i32 value, and Len is an 'intptr_t' value.
|
||||||
Value *llvm::EmitMemChr(Value *Ptr, Value *Val,
|
Value *llvm::EmitMemChr(Value *Ptr, Value *Val,
|
||||||
Value *Len, IRBuilder<> &B, const TargetData *TD) {
|
Value *Len, IRBuilder<> &B, const TargetData *TD,
|
||||||
|
const TargetLibraryInfo *TLI) {
|
||||||
|
if (!TLI->has(LibFunc::memchr))
|
||||||
|
return 0;
|
||||||
|
|
||||||
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
||||||
AttributeWithIndex AWI;
|
AttributeWithIndex AWI;
|
||||||
AWI = AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind);
|
AWI = AttributeWithIndex::get(~0u, Attribute::ReadOnly | Attribute::NoUnwind);
|
||||||
@@ -183,7 +210,11 @@ Value *llvm::EmitMemChr(Value *Ptr, Value *Val,
|
|||||||
|
|
||||||
/// EmitMemCmp - Emit a call to the memcmp function.
|
/// EmitMemCmp - Emit a call to the memcmp function.
|
||||||
Value *llvm::EmitMemCmp(Value *Ptr1, Value *Ptr2,
|
Value *llvm::EmitMemCmp(Value *Ptr1, Value *Ptr2,
|
||||||
Value *Len, IRBuilder<> &B, const TargetData *TD) {
|
Value *Len, IRBuilder<> &B, const TargetData *TD,
|
||||||
|
const TargetLibraryInfo *TLI) {
|
||||||
|
if (!TLI->has(LibFunc::memcmp))
|
||||||
|
return 0;
|
||||||
|
|
||||||
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
||||||
AttributeWithIndex AWI[3];
|
AttributeWithIndex AWI[3];
|
||||||
AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
|
AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
|
||||||
@@ -236,7 +267,11 @@ Value *llvm::EmitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilder<> &B,
|
|||||||
|
|
||||||
/// EmitPutChar - Emit a call to the putchar function. This assumes that Char
|
/// EmitPutChar - Emit a call to the putchar function. This assumes that Char
|
||||||
/// is an integer.
|
/// is an integer.
|
||||||
Value *llvm::EmitPutChar(Value *Char, IRBuilder<> &B, const TargetData *TD) {
|
Value *llvm::EmitPutChar(Value *Char, IRBuilder<> &B, const TargetData *TD,
|
||||||
|
const TargetLibraryInfo *TLI) {
|
||||||
|
if (!TLI->has(LibFunc::putchar))
|
||||||
|
return 0;
|
||||||
|
|
||||||
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
||||||
Value *PutChar = M->getOrInsertFunction("putchar", B.getInt32Ty(),
|
Value *PutChar = M->getOrInsertFunction("putchar", B.getInt32Ty(),
|
||||||
B.getInt32Ty(), NULL);
|
B.getInt32Ty(), NULL);
|
||||||
@@ -254,7 +289,11 @@ Value *llvm::EmitPutChar(Value *Char, IRBuilder<> &B, const TargetData *TD) {
|
|||||||
|
|
||||||
/// EmitPutS - Emit a call to the puts function. This assumes that Str is
|
/// EmitPutS - Emit a call to the puts function. This assumes that Str is
|
||||||
/// some pointer.
|
/// some pointer.
|
||||||
void llvm::EmitPutS(Value *Str, IRBuilder<> &B, const TargetData *TD) {
|
Value *llvm::EmitPutS(Value *Str, IRBuilder<> &B, const TargetData *TD,
|
||||||
|
const TargetLibraryInfo *TLI) {
|
||||||
|
if (!TLI->has(LibFunc::puts))
|
||||||
|
return 0;
|
||||||
|
|
||||||
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
||||||
AttributeWithIndex AWI[2];
|
AttributeWithIndex AWI[2];
|
||||||
AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
|
AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
|
||||||
@@ -267,13 +306,16 @@ void llvm::EmitPutS(Value *Str, IRBuilder<> &B, const TargetData *TD) {
|
|||||||
CallInst *CI = B.CreateCall(PutS, CastToCStr(Str, B), "puts");
|
CallInst *CI = B.CreateCall(PutS, CastToCStr(Str, B), "puts");
|
||||||
if (const Function *F = dyn_cast<Function>(PutS->stripPointerCasts()))
|
if (const Function *F = dyn_cast<Function>(PutS->stripPointerCasts()))
|
||||||
CI->setCallingConv(F->getCallingConv());
|
CI->setCallingConv(F->getCallingConv());
|
||||||
|
return CI;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// EmitFPutC - Emit a call to the fputc function. This assumes that Char is
|
/// EmitFPutC - Emit a call to the fputc function. This assumes that Char is
|
||||||
/// an integer and File is a pointer to FILE.
|
/// an integer and File is a pointer to FILE.
|
||||||
void llvm::EmitFPutC(Value *Char, Value *File, IRBuilder<> &B,
|
Value *llvm::EmitFPutC(Value *Char, Value *File, IRBuilder<> &B,
|
||||||
const TargetData *TD) {
|
const TargetData *TD, const TargetLibraryInfo *TLI) {
|
||||||
|
if (!TLI->has(LibFunc::fputc))
|
||||||
|
return 0;
|
||||||
|
|
||||||
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
||||||
AttributeWithIndex AWI[2];
|
AttributeWithIndex AWI[2];
|
||||||
AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture);
|
AWI[0] = AttributeWithIndex::get(2, Attribute::NoCapture);
|
||||||
@@ -295,12 +337,16 @@ void llvm::EmitFPutC(Value *Char, Value *File, IRBuilder<> &B,
|
|||||||
|
|
||||||
if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
|
if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
|
||||||
CI->setCallingConv(Fn->getCallingConv());
|
CI->setCallingConv(Fn->getCallingConv());
|
||||||
|
return CI;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// EmitFPutS - Emit a call to the puts function. Str is required to be a
|
/// EmitFPutS - Emit a call to the puts function. Str is required to be a
|
||||||
/// pointer and File is a pointer to FILE.
|
/// pointer and File is a pointer to FILE.
|
||||||
void llvm::EmitFPutS(Value *Str, Value *File, IRBuilder<> &B,
|
Value *llvm::EmitFPutS(Value *Str, Value *File, IRBuilder<> &B,
|
||||||
const TargetData *TD, const TargetLibraryInfo *TLI) {
|
const TargetData *TD, const TargetLibraryInfo *TLI) {
|
||||||
|
if (!TLI->has(LibFunc::fputs))
|
||||||
|
return 0;
|
||||||
|
|
||||||
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
||||||
AttributeWithIndex AWI[3];
|
AttributeWithIndex AWI[3];
|
||||||
AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
|
AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
|
||||||
@@ -321,13 +367,17 @@ void llvm::EmitFPutS(Value *Str, Value *File, IRBuilder<> &B,
|
|||||||
|
|
||||||
if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
|
if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
|
||||||
CI->setCallingConv(Fn->getCallingConv());
|
CI->setCallingConv(Fn->getCallingConv());
|
||||||
|
return CI;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is
|
/// EmitFWrite - Emit a call to the fwrite function. This assumes that Ptr is
|
||||||
/// a pointer, Size is an 'intptr_t', and File is a pointer to FILE.
|
/// a pointer, Size is an 'intptr_t', and File is a pointer to FILE.
|
||||||
void llvm::EmitFWrite(Value *Ptr, Value *Size, Value *File,
|
Value *llvm::EmitFWrite(Value *Ptr, Value *Size, Value *File,
|
||||||
IRBuilder<> &B, const TargetData *TD,
|
IRBuilder<> &B, const TargetData *TD,
|
||||||
const TargetLibraryInfo *TLI) {
|
const TargetLibraryInfo *TLI) {
|
||||||
|
if (!TLI->has(LibFunc::fwrite))
|
||||||
|
return 0;
|
||||||
|
|
||||||
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
Module *M = B.GetInsertBlock()->getParent()->getParent();
|
||||||
AttributeWithIndex AWI[3];
|
AttributeWithIndex AWI[3];
|
||||||
AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
|
AWI[0] = AttributeWithIndex::get(1, Attribute::NoCapture);
|
||||||
@@ -354,11 +404,13 @@ void llvm::EmitFWrite(Value *Ptr, Value *Size, Value *File,
|
|||||||
|
|
||||||
if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
|
if (const Function *Fn = dyn_cast<Function>(F->stripPointerCasts()))
|
||||||
CI->setCallingConv(Fn->getCallingConv());
|
CI->setCallingConv(Fn->getCallingConv());
|
||||||
|
return CI;
|
||||||
}
|
}
|
||||||
|
|
||||||
SimplifyFortifiedLibCalls::~SimplifyFortifiedLibCalls() { }
|
SimplifyFortifiedLibCalls::~SimplifyFortifiedLibCalls() { }
|
||||||
|
|
||||||
bool SimplifyFortifiedLibCalls::fold(CallInst *CI, const TargetData *TD) {
|
bool SimplifyFortifiedLibCalls::fold(CallInst *CI, const TargetData *TD,
|
||||||
|
const TargetLibraryInfo *TLI) {
|
||||||
// We really need TargetData for later.
|
// We really need TargetData for later.
|
||||||
if (!TD) return false;
|
if (!TD) return false;
|
||||||
|
|
||||||
@@ -446,7 +498,7 @@ bool SimplifyFortifiedLibCalls::fold(CallInst *CI, const TargetData *TD) {
|
|||||||
// string lengths for varying.
|
// string lengths for varying.
|
||||||
if (isFoldable(2, 1, true)) {
|
if (isFoldable(2, 1, true)) {
|
||||||
Value *Ret = EmitStrCpy(CI->getArgOperand(0), CI->getArgOperand(1), B, TD,
|
Value *Ret = EmitStrCpy(CI->getArgOperand(0), CI->getArgOperand(1), B, TD,
|
||||||
Name.substr(2, 6));
|
TLI, Name.substr(2, 6));
|
||||||
replaceCall(Ret);
|
replaceCall(Ret);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -464,7 +516,8 @@ bool SimplifyFortifiedLibCalls::fold(CallInst *CI, const TargetData *TD) {
|
|||||||
|
|
||||||
if (isFoldable(3, 2, false)) {
|
if (isFoldable(3, 2, false)) {
|
||||||
Value *Ret = EmitStrNCpy(CI->getArgOperand(0), CI->getArgOperand(1),
|
Value *Ret = EmitStrNCpy(CI->getArgOperand(0), CI->getArgOperand(1),
|
||||||
CI->getArgOperand(2), B, TD, Name.substr(2, 7));
|
CI->getArgOperand(2), B, TD, TLI,
|
||||||
|
Name.substr(2, 7));
|
||||||
replaceCall(Ret);
|
replaceCall(Ret);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user