aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
diff options
context:
space:
mode:
authorJonas Paulsson <paulsson@linux.vnet.ibm.com>2022-04-20 18:19:37 +0200
committerJonas Paulsson <paulsson@linux.vnet.ibm.com>2022-05-02 19:37:00 +0200
commit304378fd096755950939f2d3dbb4f724bba0d6cb (patch)
tree1f2c4ab1b76b5ef6d2c1493fef7c9729821a31f8 /llvm/lib/Transforms/Utils/BuildLibCalls.cpp
parentc685f8212689665968de47f8bd4b1146296e8cc2 (diff)
downloadllvm-304378fd096755950939f2d3dbb4f724bba0d6cb.zip
llvm-304378fd096755950939f2d3dbb4f724bba0d6cb.tar.gz
llvm-304378fd096755950939f2d3dbb4f724bba0d6cb.tar.bz2
Reapply "[BuildLibCalls] Introduce getOrInsertLibFunc() for use when building
libcalls." (was 0f8c626). This reverts commit 14d9390. The patch previously failed to recognize cases where user had defined a function alias with an identical name as that of the library function. Module::getFunction() would then return nullptr which is what the sanitizer discovered. In this updated version a new function isLibFuncEmittable() has as well been introduced which is now used instead of TLI->has() anytime a library function is to be emitted . It additionally also makes sure there is e.g. no function alias with the same name in the module. Reviewed By: Eli Friedman Differential Revision: https://reviews.llvm.org/D123198
Diffstat (limited to 'llvm/lib/Transforms/Utils/BuildLibCalls.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/BuildLibCalls.cpp288
1 files changed, 198 insertions, 90 deletions
diff --git a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
index 44ce808..40fd407 100644
--- a/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/BuildLibCalls.cpp
@@ -39,7 +39,6 @@ STATISTIC(NumInaccessibleMemOrArgMemOnly,
STATISTIC(NumNoUnwind, "Number of functions inferred as nounwind");
STATISTIC(NumNoCapture, "Number of arguments inferred as nocapture");
STATISTIC(NumWriteOnlyArg, "Number of arguments inferred as writeonly");
-STATISTIC(NumExtArg, "Number of arguments inferred as signext/zeroext.");
STATISTIC(NumReadOnlyArg, "Number of arguments inferred as readonly");
STATISTIC(NumNoAlias, "Number of function returns inferred as noalias");
STATISTIC(NumNoUndef, "Number of function returns inferred as noundef returns");
@@ -147,16 +146,6 @@ static bool setOnlyWritesMemory(Function &F, unsigned ArgNo) {
return true;
}
-static bool setArgExtAttr(Function &F, unsigned ArgNo,
- const TargetLibraryInfo &TLI, bool Signed = true) {
- Attribute::AttrKind ExtAttr = TLI.getExtAttrForI32Param(Signed);
- if (ExtAttr == Attribute::None || F.hasParamAttribute(ArgNo, ExtAttr))
- return false;
- F.addParamAttr(ArgNo, ExtAttr);
- ++NumExtArg;
- return true;
-}
-
static bool setRetNoUndef(Function &F) {
if (!F.getReturnType()->isVoidTy() &&
!F.hasRetAttribute(Attribute::NoUndef)) {
@@ -254,15 +243,16 @@ static bool setAllocFamily(Function &F, StringRef Family) {
return true;
}
-bool llvm::inferLibFuncAttributes(Module *M, StringRef Name,
- const TargetLibraryInfo &TLI) {
+bool llvm::inferNonMandatoryLibFuncAttrs(Module *M, StringRef Name,
+ const TargetLibraryInfo &TLI) {
Function *F = M->getFunction(Name);
if (!F)
return false;
- return inferLibFuncAttributes(*F, TLI);
+ return inferNonMandatoryLibFuncAttrs(*F, TLI);
}
-bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
+bool llvm::inferNonMandatoryLibFuncAttrs(Function &F,
+ const TargetLibraryInfo &TLI) {
LibFunc TheLibFunc;
if (!(TLI.getLibFunc(F, TheLibFunc) && TLI.has(TheLibFunc)))
return false;
@@ -875,7 +865,6 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
case LibFunc_putchar:
case LibFunc_putchar_unlocked:
Changed |= setRetAndArgsNoUndef(F);
- Changed |= setArgExtAttr(F, 0, TLI);
Changed |= setDoesNotThrow(F);
return Changed;
case LibFunc_popen:
@@ -1096,7 +1085,6 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
case LibFunc_ldexp:
case LibFunc_ldexpf:
case LibFunc_ldexpl:
- Changed |= setArgExtAttr(F, 1, TLI);
Changed |= setWillReturn(F);
return Changed;
case LibFunc_abs:
@@ -1233,34 +1221,141 @@ bool llvm::inferLibFuncAttributes(Function &F, const TargetLibraryInfo &TLI) {
}
}
-bool llvm::hasFloatFn(const TargetLibraryInfo *TLI, Type *Ty,
+static void setArgExtAttr(Function &F, unsigned ArgNo,
+ const TargetLibraryInfo &TLI, bool Signed = true) {
+ Attribute::AttrKind ExtAttr = TLI.getExtAttrForI32Param(Signed);
+ if (ExtAttr != Attribute::None && !F.hasParamAttribute(ArgNo, ExtAttr))
+ F.addParamAttr(ArgNo, ExtAttr);
+}
+
+FunctionCallee llvm::getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI,
+ LibFunc TheLibFunc, FunctionType *T,
+ AttributeList AttributeList) {
+ assert(TLI.has(TheLibFunc) &&
+ "Creating call to non-existing library function.");
+ StringRef Name = TLI.getName(TheLibFunc);
+ FunctionCallee C = M->getOrInsertFunction(Name, T, AttributeList);
+
+ // Make sure any mandatory argument attributes are added.
+
+ // Any outgoing i32 argument should be handled with setArgExtAttr() which
+ // will add an extension attribute if the target ABI requires it. Adding
+ // argument extensions is typically done by the front end but when an
+ // optimizer is building a library call on its own it has to take care of
+ // this. Each such generated function must be handled here with sign or
+ // zero extensions as needed. F is retreived with cast<> because we demand
+ // of the caller to have called isLibFuncEmittable() first.
+ Function *F = cast<Function>(C.getCallee());
+ assert(F->getFunctionType() == T && "Function type does not match.");
+ switch (TheLibFunc) {
+ case LibFunc_fputc:
+ case LibFunc_putchar:
+ setArgExtAttr(*F, 0, TLI);
+ break;
+ case LibFunc_ldexp:
+ case LibFunc_ldexpf:
+ case LibFunc_ldexpl:
+ case LibFunc_memchr:
+ case LibFunc_strchr:
+ setArgExtAttr(*F, 1, TLI);
+ break;
+ case LibFunc_memccpy:
+ setArgExtAttr(*F, 2, TLI);
+ break;
+
+ // These are functions that are known to not need any argument extension
+ // on any target: A size_t argument (which may be an i32 on some targets)
+ // should not trigger the assert below.
+ case LibFunc_bcmp:
+ case LibFunc_calloc:
+ case LibFunc_fwrite:
+ case LibFunc_malloc:
+ case LibFunc_memcmp:
+ case LibFunc_memcpy_chk:
+ case LibFunc_mempcpy:
+ case LibFunc_memset_pattern16:
+ case LibFunc_snprintf:
+ case LibFunc_stpncpy:
+ case LibFunc_strlcat:
+ case LibFunc_strlcpy:
+ case LibFunc_strncat:
+ case LibFunc_strncmp:
+ case LibFunc_strncpy:
+ case LibFunc_vsnprintf:
+ break;
+
+ default:
+#ifndef NDEBUG
+ for (unsigned i = 0; i < T->getNumParams(); i++)
+ assert(!isa<IntegerType>(T->getParamType(i)) &&
+ "Unhandled integer argument.");
+#endif
+ break;
+ }
+
+ return C;
+}
+
+FunctionCallee llvm::getOrInsertLibFunc(Module *M, const TargetLibraryInfo &TLI,
+ LibFunc TheLibFunc, FunctionType *T) {
+ return getOrInsertLibFunc(M, TLI, TheLibFunc, T, AttributeList());
+}
+
+bool llvm::isLibFuncEmittable(const Module *M, const TargetLibraryInfo *TLI,
+ LibFunc TheLibFunc) {
+ StringRef FuncName = TLI->getName(TheLibFunc);
+ if (!TLI->has(TheLibFunc))
+ return false;
+
+ // Check if the Module already has a GlobalValue with the same name, in
+ // which case it must be a Function with the expected type.
+ if (GlobalValue *GV = M->getNamedValue(FuncName)) {
+ if (auto *F = dyn_cast<Function>(GV))
+ return TLI->isValidProtoForLibFunc(*F->getFunctionType(), TheLibFunc, *M);
+ return false;
+ }
+
+ return true;
+}
+
+bool llvm::isLibFuncEmittable(const Module *M, const TargetLibraryInfo *TLI,
+ StringRef Name) {
+ LibFunc TheLibFunc;
+ return TLI->getLibFunc(Name, TheLibFunc) &&
+ isLibFuncEmittable(M, TLI, TheLibFunc);
+}
+
+bool llvm::hasFloatFn(const Module *M, const TargetLibraryInfo *TLI, Type *Ty,
LibFunc DoubleFn, LibFunc FloatFn, LibFunc LongDoubleFn) {
switch (Ty->getTypeID()) {
case Type::HalfTyID:
return false;
case Type::FloatTyID:
- return TLI->has(FloatFn);
+ return isLibFuncEmittable(M, TLI, FloatFn);
case Type::DoubleTyID:
- return TLI->has(DoubleFn);
+ return isLibFuncEmittable(M, TLI, DoubleFn);
default:
- return TLI->has(LongDoubleFn);
+ return isLibFuncEmittable(M, TLI, LongDoubleFn);
}
}
-StringRef llvm::getFloatFnName(const TargetLibraryInfo *TLI, Type *Ty,
- LibFunc DoubleFn, LibFunc FloatFn,
- LibFunc LongDoubleFn) {
- assert(hasFloatFn(TLI, Ty, DoubleFn, FloatFn, LongDoubleFn) &&
+StringRef llvm::getFloatFn(const Module *M, const TargetLibraryInfo *TLI,
+ Type *Ty, LibFunc DoubleFn, LibFunc FloatFn,
+ LibFunc LongDoubleFn, LibFunc &TheLibFunc) {
+ assert(hasFloatFn(M, TLI, Ty, DoubleFn, FloatFn, LongDoubleFn) &&
"Cannot get name for unavailable function!");
switch (Ty->getTypeID()) {
case Type::HalfTyID:
llvm_unreachable("No name for HalfTy!");
case Type::FloatTyID:
+ TheLibFunc = FloatFn;
return TLI->getName(FloatFn);
case Type::DoubleTyID:
+ TheLibFunc = DoubleFn;
return TLI->getName(DoubleFn);
default:
+ TheLibFunc = LongDoubleFn;
return TLI->getName(LongDoubleFn);
}
}
@@ -1277,14 +1372,14 @@ static Value *emitLibCall(LibFunc TheLibFunc, Type *ReturnType,
ArrayRef<Value *> Operands, IRBuilderBase &B,
const TargetLibraryInfo *TLI,
bool IsVaArgs = false) {
- if (!TLI->has(TheLibFunc))
+ Module *M = B.GetInsertBlock()->getModule();
+ if (!isLibFuncEmittable(M, TLI, TheLibFunc))
return nullptr;
- Module *M = B.GetInsertBlock()->getModule();
StringRef FuncName = TLI->getName(TheLibFunc);
FunctionType *FuncType = FunctionType::get(ReturnType, ParamTypes, IsVaArgs);
- FunctionCallee Callee = M->getOrInsertFunction(FuncName, FuncType);
- inferLibFuncAttributes(M, FuncName, *TLI);
+ FunctionCallee Callee = getOrInsertLibFunc(M, *TLI, TheLibFunc, FuncType);
+ inferNonMandatoryLibFuncAttrs(M, FuncName, *TLI);
CallInst *CI = B.CreateCall(Callee, Operands, FuncName);
if (const Function *F =
dyn_cast<Function>(Callee.getCallee()->stripPointerCasts()))
@@ -1353,16 +1448,16 @@ Value *llvm::emitStpNCpy(Value *Dst, Value *Src, Value *Len, IRBuilderBase &B,
Value *llvm::emitMemCpyChk(Value *Dst, Value *Src, Value *Len, Value *ObjSize,
IRBuilderBase &B, const DataLayout &DL,
const TargetLibraryInfo *TLI) {
- if (!TLI->has(LibFunc_memcpy_chk))
+ Module *M = B.GetInsertBlock()->getModule();
+ if (!isLibFuncEmittable(M, TLI, LibFunc_memcpy_chk))
return nullptr;
- Module *M = B.GetInsertBlock()->getModule();
AttributeList AS;
AS = AttributeList::get(M->getContext(), AttributeList::FunctionIndex,
Attribute::NoUnwind);
LLVMContext &Context = B.GetInsertBlock()->getContext();
- FunctionCallee MemCpy = M->getOrInsertFunction(
- "__memcpy_chk", AttributeList::get(M->getContext(), AS), B.getInt8PtrTy(),
+ FunctionCallee MemCpy = getOrInsertLibFunc(M, *TLI, LibFunc_memcpy_chk,
+ AttributeList::get(M->getContext(), AS), B.getInt8PtrTy(),
B.getInt8PtrTy(), B.getInt8PtrTy(), DL.getIntPtrType(Context),
DL.getIntPtrType(Context));
Dst = castToCStr(Dst, B);
@@ -1496,14 +1591,15 @@ static void appendTypeSuffix(Value *Op, StringRef &Name,
}
}
-static Value *emitUnaryFloatFnCallHelper(Value *Op, StringRef Name,
- IRBuilderBase &B,
- const AttributeList &Attrs) {
+static Value *emitUnaryFloatFnCallHelper(Value *Op, LibFunc TheLibFunc,
+ StringRef Name, IRBuilderBase &B,
+ const AttributeList &Attrs,
+ const TargetLibraryInfo *TLI) {
assert((Name != "") && "Must specify Name to emitUnaryFloatFnCall");
Module *M = B.GetInsertBlock()->getModule();
- FunctionCallee Callee =
- M->getOrInsertFunction(Name, Op->getType(), Op->getType());
+ FunctionCallee Callee = getOrInsertLibFunc(M, *TLI, TheLibFunc, Op->getType(),
+ Op->getType());
CallInst *CI = B.CreateCall(Callee, Op, Name);
// The incoming attribute set may have come from a speculatable intrinsic, but
@@ -1518,12 +1614,16 @@ static Value *emitUnaryFloatFnCallHelper(Value *Op, StringRef Name,
return CI;
}
-Value *llvm::emitUnaryFloatFnCall(Value *Op, StringRef Name, IRBuilderBase &B,
+Value *llvm::emitUnaryFloatFnCall(Value *Op, const TargetLibraryInfo *TLI,
+ StringRef Name, IRBuilderBase &B,
const AttributeList &Attrs) {
SmallString<20> NameBuffer;
appendTypeSuffix(Op, Name, NameBuffer);
- return emitUnaryFloatFnCallHelper(Op, Name, B, Attrs);
+ LibFunc TheLibFunc;
+ TLI->getLibFunc(Name, TheLibFunc);
+
+ return emitUnaryFloatFnCallHelper(Op, TheLibFunc, Name, B, Attrs, TLI);
}
Value *llvm::emitUnaryFloatFnCall(Value *Op, const TargetLibraryInfo *TLI,
@@ -1531,23 +1631,25 @@ Value *llvm::emitUnaryFloatFnCall(Value *Op, const TargetLibraryInfo *TLI,
LibFunc LongDoubleFn, IRBuilderBase &B,
const AttributeList &Attrs) {
// Get the name of the function according to TLI.
- StringRef Name = getFloatFnName(TLI, Op->getType(),
- DoubleFn, FloatFn, LongDoubleFn);
+ Module *M = B.GetInsertBlock()->getModule();
+ LibFunc TheLibFunc;
+ StringRef Name = getFloatFn(M, TLI, Op->getType(), DoubleFn, FloatFn,
+ LongDoubleFn, TheLibFunc);
- return emitUnaryFloatFnCallHelper(Op, Name, B, Attrs);
+ return emitUnaryFloatFnCallHelper(Op, TheLibFunc, Name, B, Attrs, TLI);
}
static Value *emitBinaryFloatFnCallHelper(Value *Op1, Value *Op2,
+ LibFunc TheLibFunc,
StringRef Name, IRBuilderBase &B,
const AttributeList &Attrs,
- const TargetLibraryInfo *TLI = nullptr) {
+ const TargetLibraryInfo *TLI) {
assert((Name != "") && "Must specify Name to emitBinaryFloatFnCall");
Module *M = B.GetInsertBlock()->getModule();
- FunctionCallee Callee = M->getOrInsertFunction(Name, Op1->getType(),
- Op1->getType(), Op2->getType());
- if (TLI != nullptr)
- inferLibFuncAttributes(M, Name, *TLI);
+ FunctionCallee Callee = getOrInsertLibFunc(M, *TLI, TheLibFunc, Op1->getType(),
+ Op1->getType(), Op2->getType());
+ inferNonMandatoryLibFuncAttrs(M, Name, *TLI);
CallInst *CI = B.CreateCall(Callee, { Op1, Op2 }, Name);
// The incoming attribute set may have come from a speculatable intrinsic, but
@@ -1562,15 +1664,19 @@ static Value *emitBinaryFloatFnCallHelper(Value *Op1, Value *Op2,
return CI;
}
-Value *llvm::emitBinaryFloatFnCall(Value *Op1, Value *Op2, StringRef Name,
- IRBuilderBase &B,
+Value *llvm::emitBinaryFloatFnCall(Value *Op1, Value *Op2,
+ const TargetLibraryInfo *TLI,
+ StringRef Name, IRBuilderBase &B,
const AttributeList &Attrs) {
assert((Name != "") && "Must specify Name to emitBinaryFloatFnCall");
SmallString<20> NameBuffer;
appendTypeSuffix(Op1, Name, NameBuffer);
- return emitBinaryFloatFnCallHelper(Op1, Op2, Name, B, Attrs);
+ LibFunc TheLibFunc;
+ TLI->getLibFunc(Name, TheLibFunc);
+
+ return emitBinaryFloatFnCallHelper(Op1, Op2, TheLibFunc, Name, B, Attrs, TLI);
}
Value *llvm::emitBinaryFloatFnCall(Value *Op1, Value *Op2,
@@ -1579,22 +1685,24 @@ Value *llvm::emitBinaryFloatFnCall(Value *Op1, Value *Op2,
LibFunc LongDoubleFn, IRBuilderBase &B,
const AttributeList &Attrs) {
// Get the name of the function according to TLI.
- StringRef Name = getFloatFnName(TLI, Op1->getType(),
- DoubleFn, FloatFn, LongDoubleFn);
+ Module *M = B.GetInsertBlock()->getModule();
+ LibFunc TheLibFunc;
+ StringRef Name = getFloatFn(M, TLI, Op1->getType(), DoubleFn, FloatFn,
+ LongDoubleFn, TheLibFunc);
- return emitBinaryFloatFnCallHelper(Op1, Op2, Name, B, Attrs, TLI);
+ return emitBinaryFloatFnCallHelper(Op1, Op2, TheLibFunc, Name, B, Attrs, TLI);
}
Value *llvm::emitPutChar(Value *Char, IRBuilderBase &B,
const TargetLibraryInfo *TLI) {
- if (!TLI->has(LibFunc_putchar))
+ Module *M = B.GetInsertBlock()->getModule();
+ if (!isLibFuncEmittable(M, TLI, LibFunc_putchar))
return nullptr;
- Module *M = B.GetInsertBlock()->getModule();
StringRef PutCharName = TLI->getName(LibFunc_putchar);
- FunctionCallee PutChar =
- M->getOrInsertFunction(PutCharName, B.getInt32Ty(), B.getInt32Ty());
- inferLibFuncAttributes(M, PutCharName, *TLI);
+ FunctionCallee PutChar = getOrInsertLibFunc(M, *TLI, LibFunc_putchar,
+ B.getInt32Ty(), B.getInt32Ty());
+ inferNonMandatoryLibFuncAttrs(M, PutCharName, *TLI);
CallInst *CI = B.CreateCall(PutChar,
B.CreateIntCast(Char,
B.getInt32Ty(),
@@ -1610,14 +1718,14 @@ Value *llvm::emitPutChar(Value *Char, IRBuilderBase &B,
Value *llvm::emitPutS(Value *Str, IRBuilderBase &B,
const TargetLibraryInfo *TLI) {
- if (!TLI->has(LibFunc_puts))
+ Module *M = B.GetInsertBlock()->getModule();
+ if (!isLibFuncEmittable(M, TLI, LibFunc_puts))
return nullptr;
- Module *M = B.GetInsertBlock()->getModule();
StringRef PutsName = TLI->getName(LibFunc_puts);
- FunctionCallee PutS =
- M->getOrInsertFunction(PutsName, B.getInt32Ty(), B.getInt8PtrTy());
- inferLibFuncAttributes(M, PutsName, *TLI);
+ FunctionCallee PutS = getOrInsertLibFunc(M, *TLI, LibFunc_puts, B.getInt32Ty(),
+ B.getInt8PtrTy());
+ inferNonMandatoryLibFuncAttrs(M, PutsName, *TLI);
CallInst *CI = B.CreateCall(PutS, castToCStr(Str, B), PutsName);
if (const Function *F =
dyn_cast<Function>(PutS.getCallee()->stripPointerCasts()))
@@ -1627,15 +1735,15 @@ Value *llvm::emitPutS(Value *Str, IRBuilderBase &B,
Value *llvm::emitFPutC(Value *Char, Value *File, IRBuilderBase &B,
const TargetLibraryInfo *TLI) {
- if (!TLI->has(LibFunc_fputc))
+ Module *M = B.GetInsertBlock()->getModule();
+ if (!isLibFuncEmittable(M, TLI, LibFunc_fputc))
return nullptr;
- Module *M = B.GetInsertBlock()->getModule();
StringRef FPutcName = TLI->getName(LibFunc_fputc);
- FunctionCallee F = M->getOrInsertFunction(FPutcName, B.getInt32Ty(),
- B.getInt32Ty(), File->getType());
+ FunctionCallee F = getOrInsertLibFunc(M, *TLI, LibFunc_fputc, B.getInt32Ty(),
+ B.getInt32Ty(), File->getType());
if (File->getType()->isPointerTy())
- inferLibFuncAttributes(M, FPutcName, *TLI);
+ inferNonMandatoryLibFuncAttrs(M, FPutcName, *TLI);
Char = B.CreateIntCast(Char, B.getInt32Ty(), /*isSigned*/true,
"chari");
CallInst *CI = B.CreateCall(F, {Char, File}, FPutcName);
@@ -1648,15 +1756,15 @@ Value *llvm::emitFPutC(Value *Char, Value *File, IRBuilderBase &B,
Value *llvm::emitFPutS(Value *Str, Value *File, IRBuilderBase &B,
const TargetLibraryInfo *TLI) {
- if (!TLI->has(LibFunc_fputs))
+ Module *M = B.GetInsertBlock()->getModule();
+ if (!isLibFuncEmittable(M, TLI, LibFunc_fputs))
return nullptr;
- Module *M = B.GetInsertBlock()->getModule();
StringRef FPutsName = TLI->getName(LibFunc_fputs);
- FunctionCallee F = M->getOrInsertFunction(FPutsName, B.getInt32Ty(),
- B.getInt8PtrTy(), File->getType());
+ FunctionCallee F = getOrInsertLibFunc(M, *TLI, LibFunc_fputs, B.getInt32Ty(),
+ B.getInt8PtrTy(), File->getType());
if (File->getType()->isPointerTy())
- inferLibFuncAttributes(M, FPutsName, *TLI);
+ inferNonMandatoryLibFuncAttrs(M, FPutsName, *TLI);
CallInst *CI = B.CreateCall(F, {castToCStr(Str, B), File}, FPutsName);
if (const Function *Fn =
@@ -1667,18 +1775,18 @@ Value *llvm::emitFPutS(Value *Str, Value *File, IRBuilderBase &B,
Value *llvm::emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilderBase &B,
const DataLayout &DL, const TargetLibraryInfo *TLI) {
- if (!TLI->has(LibFunc_fwrite))
+ Module *M = B.GetInsertBlock()->getModule();
+ if (!isLibFuncEmittable(M, TLI, LibFunc_fwrite))
return nullptr;
- Module *M = B.GetInsertBlock()->getModule();
LLVMContext &Context = B.GetInsertBlock()->getContext();
StringRef FWriteName = TLI->getName(LibFunc_fwrite);
- FunctionCallee F = M->getOrInsertFunction(
- FWriteName, DL.getIntPtrType(Context), B.getInt8PtrTy(),
- DL.getIntPtrType(Context), DL.getIntPtrType(Context), File->getType());
+ FunctionCallee F = getOrInsertLibFunc(M, *TLI, LibFunc_fwrite,
+ DL.getIntPtrType(Context), B.getInt8PtrTy(), DL.getIntPtrType(Context),
+ DL.getIntPtrType(Context), File->getType());
if (File->getType()->isPointerTy())
- inferLibFuncAttributes(M, FWriteName, *TLI);
+ inferNonMandatoryLibFuncAttrs(M, FWriteName, *TLI);
CallInst *CI =
B.CreateCall(F, {castToCStr(Ptr, B), Size,
ConstantInt::get(DL.getIntPtrType(Context), 1), File});
@@ -1691,15 +1799,15 @@ Value *llvm::emitFWrite(Value *Ptr, Value *Size, Value *File, IRBuilderBase &B,
Value *llvm::emitMalloc(Value *Num, IRBuilderBase &B, const DataLayout &DL,
const TargetLibraryInfo *TLI) {
- if (!TLI->has(LibFunc_malloc))
+ Module *M = B.GetInsertBlock()->getModule();
+ if (!isLibFuncEmittable(M, TLI, LibFunc_malloc))
return nullptr;
- Module *M = B.GetInsertBlock()->getModule();
StringRef MallocName = TLI->getName(LibFunc_malloc);
LLVMContext &Context = B.GetInsertBlock()->getContext();
- FunctionCallee Malloc = M->getOrInsertFunction(MallocName, B.getInt8PtrTy(),
- DL.getIntPtrType(Context));
- inferLibFuncAttributes(M, MallocName, *TLI);
+ FunctionCallee Malloc = getOrInsertLibFunc(M, *TLI, LibFunc_malloc,
+ B.getInt8PtrTy(), DL.getIntPtrType(Context));
+ inferNonMandatoryLibFuncAttrs(M, MallocName, *TLI);
CallInst *CI = B.CreateCall(Malloc, Num, MallocName);
if (const Function *F =
@@ -1711,16 +1819,16 @@ Value *llvm::emitMalloc(Value *Num, IRBuilderBase &B, const DataLayout &DL,
Value *llvm::emitCalloc(Value *Num, Value *Size, IRBuilderBase &B,
const TargetLibraryInfo &TLI) {
- if (!TLI.has(LibFunc_calloc))
+ Module *M = B.GetInsertBlock()->getModule();
+ if (!isLibFuncEmittable(M, &TLI, LibFunc_calloc))
return nullptr;
- Module *M = B.GetInsertBlock()->getModule();
StringRef CallocName = TLI.getName(LibFunc_calloc);
const DataLayout &DL = M->getDataLayout();
IntegerType *PtrType = DL.getIntPtrType((B.GetInsertBlock()->getContext()));
- FunctionCallee Calloc =
- M->getOrInsertFunction(CallocName, B.getInt8PtrTy(), PtrType, PtrType);
- inferLibFuncAttributes(M, CallocName, TLI);
+ FunctionCallee Calloc = getOrInsertLibFunc(M, TLI, LibFunc_calloc,
+ B.getInt8PtrTy(), PtrType, PtrType);
+ inferNonMandatoryLibFuncAttrs(M, CallocName, TLI);
CallInst *CI = B.CreateCall(Calloc, {Num, Size}, CallocName);
if (const auto *F =