aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/IR/Function.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/IR/Function.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/IR/Function.cpp230
1 files changed, 189 insertions, 41 deletions
diff --git a/contrib/llvm-project/llvm/lib/IR/Function.cpp b/contrib/llvm-project/llvm/lib/IR/Function.cpp
index 17247123f87f..4034b1505bd0 100644
--- a/contrib/llvm-project/llvm/lib/IR/Function.cpp
+++ b/contrib/llvm-project/llvm/lib/IR/Function.cpp
@@ -31,6 +31,7 @@
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/IntrinsicsAArch64.h"
#include "llvm/IR/IntrinsicsAMDGPU.h"
@@ -51,6 +52,7 @@
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/Operator.h"
#include "llvm/IR/SymbolTableListTraits.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
@@ -58,6 +60,7 @@
#include "llvm/IR/Value.h"
#include "llvm/IR/ValueSymbolTable.h"
#include "llvm/Support/Casting.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
@@ -74,6 +77,10 @@ using ProfileCount = Function::ProfileCount;
// are not in the public header file...
template class llvm::SymbolTableListTraits<BasicBlock>;
+static cl::opt<unsigned> NonGlobalValueMaxNameSize(
+ "non-global-value-max-name-size", cl::Hidden, cl::init(1024),
+ cl::desc("Maximum size for the name of non-global values."));
+
//===----------------------------------------------------------------------===//
// Argument Implementation
//===----------------------------------------------------------------------===//
@@ -160,14 +167,10 @@ static Type *getMemoryParamAllocType(AttributeSet ParamAttrs, Type *ArgTy) {
return ByRefTy;
if (Type *PreAllocTy = ParamAttrs.getPreallocatedType())
return PreAllocTy;
-
- // FIXME: sret and inalloca always depends on pointee element type. It's also
- // possible for byval to miss it.
- if (ParamAttrs.hasAttribute(Attribute::InAlloca) ||
- ParamAttrs.hasAttribute(Attribute::ByVal) ||
- ParamAttrs.hasAttribute(Attribute::StructRet) ||
- ParamAttrs.hasAttribute(Attribute::Preallocated))
- return cast<PointerType>(ArgTy)->getElementType();
+ if (Type *InAllocaTy = ParamAttrs.getInAllocaType())
+ return InAllocaTy;
+ if (Type *SRetTy = ParamAttrs.getStructRetType())
+ return SRetTy;
return nullptr;
}
@@ -196,6 +199,10 @@ MaybeAlign Argument::getParamAlign() const {
return getParent()->getParamAlign(getArgNo());
}
+MaybeAlign Argument::getParamStackAlign() const {
+ return getParent()->getParamStackAlign(getArgNo());
+}
+
Type *Argument::getParamByValType() const {
assert(getType()->isPointerTy() && "Only pointers have byval types");
return getParent()->getParamByValType(getArgNo());
@@ -207,10 +214,15 @@ Type *Argument::getParamStructRetType() const {
}
Type *Argument::getParamByRefType() const {
- assert(getType()->isPointerTy() && "Only pointers have byval types");
+ assert(getType()->isPointerTy() && "Only pointers have byref types");
return getParent()->getParamByRefType(getArgNo());
}
+Type *Argument::getParamInAllocaType() const {
+ assert(getType()->isPointerTy() && "Only pointers have inalloca types");
+ return getParent()->getParamInAllocaType(getArgNo());
+}
+
uint64_t Argument::getDereferenceableBytes() const {
assert(getType()->isPointerTy() &&
"Only pointers have dereferenceable bytes");
@@ -238,6 +250,11 @@ bool Argument::hasNoCaptureAttr() const {
return hasAttribute(Attribute::NoCapture);
}
+bool Argument::hasNoFreeAttr() const {
+ if (!getType()->isPointerTy()) return false;
+ return hasAttribute(Attribute::NoFree);
+}
+
bool Argument::hasStructRetAttr() const {
if (!getType()->isPointerTy()) return false;
return hasAttribute(Attribute::StructRet);
@@ -283,6 +300,12 @@ void Argument::removeAttr(Attribute::AttrKind Kind) {
getParent()->removeParamAttr(getArgNo(), Kind);
}
+void Argument::removeAttrs(const AttrBuilder &B) {
+ AttributeList AL = getParent()->getAttributes();
+ AL = AL.removeParamAttributes(Parent->getContext(), getArgNo(), B);
+ getParent()->setAttributes(AL);
+}
+
bool Argument::hasAttribute(Attribute::AttrKind Kind) const {
return getParent()->hasParamAttribute(getArgNo(), Kind);
}
@@ -312,6 +335,29 @@ Function *Function::Create(FunctionType *Ty, LinkageTypes Linkage,
return Create(Ty, Linkage, M.getDataLayout().getProgramAddressSpace(), N, &M);
}
+Function *Function::createWithDefaultAttr(FunctionType *Ty,
+ LinkageTypes Linkage,
+ unsigned AddrSpace, const Twine &N,
+ Module *M) {
+ auto *F = new Function(Ty, Linkage, AddrSpace, N, M);
+ AttrBuilder B;
+ if (M->getUwtable())
+ B.addAttribute(Attribute::UWTable);
+ switch (M->getFramePointer()) {
+ case FramePointerKind::None:
+ // 0 ("none") is the default.
+ break;
+ case FramePointerKind::NonLeaf:
+ B.addAttribute("frame-pointer", "non-leaf");
+ break;
+ case FramePointerKind::All:
+ B.addAttribute("frame-pointer", "all");
+ break;
+ }
+ F->addAttributes(AttributeList::FunctionIndex, B);
+ return F;
+}
+
void Function::removeFromParent() {
getParent()->getFunctionList().remove(getIterator());
}
@@ -344,7 +390,7 @@ Function::Function(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace,
// We only need a symbol table for a function if the context keeps value names
if (!getContext().shouldDiscardValueNames())
- SymTab = std::make_unique<ValueSymbolTable>();
+ SymTab = std::make_unique<ValueSymbolTable>(NonGlobalValueMaxNameSize);
// If the function has arguments, mark them as lazily built.
if (Ty->getNumParams())
@@ -719,40 +765,47 @@ void Function::recalculateIntrinsicID() {
/// which can't be confused with it's prefix. This ensures we don't have
/// collisions between two unrelated function types. Otherwise, you might
/// parse ffXX as f(fXX) or f(fX)X. (X is a placeholder for any other type.)
-///
-static std::string getMangledTypeStr(Type* Ty) {
+/// The HasUnnamedType boolean is set if an unnamed type was encountered,
+/// indicating that extra care must be taken to ensure a unique name.
+static std::string getMangledTypeStr(Type *Ty, bool &HasUnnamedType) {
std::string Result;
- if (PointerType* PTyp = dyn_cast<PointerType>(Ty)) {
- Result += "p" + utostr(PTyp->getAddressSpace()) +
- getMangledTypeStr(PTyp->getElementType());
- } else if (ArrayType* ATyp = dyn_cast<ArrayType>(Ty)) {
+ if (PointerType *PTyp = dyn_cast<PointerType>(Ty)) {
+ Result += "p" + utostr(PTyp->getAddressSpace());
+ // Opaque pointer doesn't have pointee type information, so we just mangle
+ // address space for opaque pointer.
+ if (!PTyp->isOpaque())
+ Result += getMangledTypeStr(PTyp->getElementType(), HasUnnamedType);
+ } else if (ArrayType *ATyp = dyn_cast<ArrayType>(Ty)) {
Result += "a" + utostr(ATyp->getNumElements()) +
- getMangledTypeStr(ATyp->getElementType());
+ getMangledTypeStr(ATyp->getElementType(), HasUnnamedType);
} else if (StructType *STyp = dyn_cast<StructType>(Ty)) {
if (!STyp->isLiteral()) {
Result += "s_";
- Result += STyp->getName();
+ if (STyp->hasName())
+ Result += STyp->getName();
+ else
+ HasUnnamedType = true;
} else {
Result += "sl_";
for (auto Elem : STyp->elements())
- Result += getMangledTypeStr(Elem);
+ Result += getMangledTypeStr(Elem, HasUnnamedType);
}
// Ensure nested structs are distinguishable.
Result += "s";
} else if (FunctionType *FT = dyn_cast<FunctionType>(Ty)) {
- Result += "f_" + getMangledTypeStr(FT->getReturnType());
+ Result += "f_" + getMangledTypeStr(FT->getReturnType(), HasUnnamedType);
for (size_t i = 0; i < FT->getNumParams(); i++)
- Result += getMangledTypeStr(FT->getParamType(i));
+ Result += getMangledTypeStr(FT->getParamType(i), HasUnnamedType);
if (FT->isVarArg())
Result += "vararg";
// Ensure nested function types are distinguishable.
Result += "f";
- } else if (VectorType* VTy = dyn_cast<VectorType>(Ty)) {
+ } else if (VectorType *VTy = dyn_cast<VectorType>(Ty)) {
ElementCount EC = VTy->getElementCount();
if (EC.isScalable())
Result += "nx";
Result += "v" + utostr(EC.getKnownMinValue()) +
- getMangledTypeStr(VTy->getElementType());
+ getMangledTypeStr(VTy->getElementType(), HasUnnamedType);
} else if (Ty) {
switch (Ty->getTypeID()) {
default: llvm_unreachable("Unhandled type");
@@ -775,24 +828,55 @@ static std::string getMangledTypeStr(Type* Ty) {
return Result;
}
+StringRef Intrinsic::getBaseName(ID id) {
+ assert(id < num_intrinsics && "Invalid intrinsic ID!");
+ return IntrinsicNameTable[id];
+}
+
StringRef Intrinsic::getName(ID id) {
assert(id < num_intrinsics && "Invalid intrinsic ID!");
assert(!Intrinsic::isOverloaded(id) &&
"This version of getName does not support overloading");
- return IntrinsicNameTable[id];
+ return getBaseName(id);
}
-std::string Intrinsic::getName(ID id, ArrayRef<Type*> Tys) {
- assert(id < num_intrinsics && "Invalid intrinsic ID!");
- assert((Tys.empty() || Intrinsic::isOverloaded(id)) &&
+static std::string getIntrinsicNameImpl(Intrinsic::ID Id, ArrayRef<Type *> Tys,
+ Module *M, FunctionType *FT,
+ bool EarlyModuleCheck) {
+
+ assert(Id < Intrinsic::num_intrinsics && "Invalid intrinsic ID!");
+ assert((Tys.empty() || Intrinsic::isOverloaded(Id)) &&
"This version of getName is for overloaded intrinsics only");
- std::string Result(IntrinsicNameTable[id]);
- for (Type *Ty : Tys) {
- Result += "." + getMangledTypeStr(Ty);
+ (void)EarlyModuleCheck;
+ assert((!EarlyModuleCheck || M ||
+ !any_of(Tys, [](Type *T) { return isa<PointerType>(T); })) &&
+ "Intrinsic overloading on pointer types need to provide a Module");
+ bool HasUnnamedType = false;
+ std::string Result(Intrinsic::getBaseName(Id));
+ for (Type *Ty : Tys)
+ Result += "." + getMangledTypeStr(Ty, HasUnnamedType);
+ if (HasUnnamedType) {
+ assert(M && "unnamed types need a module");
+ if (!FT)
+ FT = Intrinsic::getType(M->getContext(), Id, Tys);
+ else
+ assert((FT == Intrinsic::getType(M->getContext(), Id, Tys)) &&
+ "Provided FunctionType must match arguments");
+ return M->getUniqueIntrinsicName(Result, Id, FT);
}
return Result;
}
+std::string Intrinsic::getName(ID Id, ArrayRef<Type *> Tys, Module *M,
+ FunctionType *FT) {
+ assert(M && "We need to have a Module");
+ return getIntrinsicNameImpl(Id, Tys, M, FT, true);
+}
+
+std::string Intrinsic::getNameNoUnnamedTypes(ID Id, ArrayRef<Type *> Tys) {
+ return getIntrinsicNameImpl(Id, Tys, nullptr, nullptr, false);
+}
+
/// IIT_Info - These are enumerators that describe the entries returned by the
/// getIntrinsicInfoTableEntries function.
///
@@ -1252,8 +1336,10 @@ bool Intrinsic::isLeaf(ID id) {
Function *Intrinsic::getDeclaration(Module *M, ID id, ArrayRef<Type*> Tys) {
// There can never be multiple globals with the same name of different types,
// because intrinsics must be a specific type.
+ auto *FT = getType(M->getContext(), id, Tys);
return cast<Function>(
- M->getOrInsertFunction(Tys.empty() ? getName(id) : getName(id, Tys),
+ M->getOrInsertFunction(Tys.empty() ? getName(id)
+ : getName(id, Tys, M, FT),
getType(M->getContext(), id, Tys))
.getCallee());
}
@@ -1312,9 +1398,21 @@ static bool matchIntrinsicType(
}
case IITDescriptor::Pointer: {
PointerType *PT = dyn_cast<PointerType>(Ty);
- return !PT || PT->getAddressSpace() != D.Pointer_AddressSpace ||
- matchIntrinsicType(PT->getElementType(), Infos, ArgTys,
- DeferredChecks, IsDeferredCheck);
+ if (!PT || PT->getAddressSpace() != D.Pointer_AddressSpace)
+ return true;
+ if (!PT->isOpaque())
+ return matchIntrinsicType(PT->getElementType(), Infos, ArgTys,
+ DeferredChecks, IsDeferredCheck);
+ // If typed pointers are supported, do not allow using opaque pointer in
+ // place of fixed pointer type. This would make the intrinsic signature
+ // non-unique.
+ if (Ty->getContext().supportsTypedPointers())
+ return true;
+ // Consume IIT descriptors relating to the pointer element type.
+ while (Infos.front().Kind == IITDescriptor::Pointer)
+ Infos = Infos.slice(1);
+ Infos = Infos.slice(1);
+ return false;
}
case IITDescriptor::Struct: {
@@ -1425,8 +1523,13 @@ static bool matchIntrinsicType(
dyn_cast<VectorType> (ArgTys[D.getArgumentNumber()]);
PointerType *ThisArgType = dyn_cast<PointerType>(Ty);
- return (!ThisArgType || !ReferenceType ||
- ThisArgType->getElementType() != ReferenceType->getElementType());
+ if (!ThisArgType || !ReferenceType)
+ return true;
+ if (!ThisArgType->isOpaque())
+ return ThisArgType->getElementType() != ReferenceType->getElementType();
+ // If typed pointers are supported, do not allow opaque pointer to ensure
+ // uniqueness.
+ return Ty->getContext().supportsTypedPointers();
}
case IITDescriptor::VecOfAnyPtrsToElt: {
unsigned RefArgNumber = D.getRefArgNumber();
@@ -1457,7 +1560,8 @@ static bool matchIntrinsicType(
dyn_cast<PointerType>(ThisArgVecTy->getElementType());
if (!ThisArgEltTy)
return true;
- return ThisArgEltTy->getElementType() != ReferenceType->getElementType();
+ return !ThisArgEltTy->isOpaqueOrPointeeTypeMatches(
+ ReferenceType->getElementType());
}
case IITDescriptor::VecElementArgument: {
if (D.getArgumentNumber() >= ArgTys.size())
@@ -1566,10 +1670,26 @@ Optional<Function *> Intrinsic::remangleIntrinsicFunction(Function *F) {
Intrinsic::ID ID = F->getIntrinsicID();
StringRef Name = F->getName();
- if (Name == Intrinsic::getName(ID, ArgTys))
+ std::string WantedName =
+ Intrinsic::getName(ID, ArgTys, F->getParent(), F->getFunctionType());
+ if (Name == WantedName)
return None;
- auto NewDecl = Intrinsic::getDeclaration(F->getParent(), ID, ArgTys);
+ Function *NewDecl = [&] {
+ if (auto *ExistingGV = F->getParent()->getNamedValue(WantedName)) {
+ if (auto *ExistingF = dyn_cast<Function>(ExistingGV))
+ if (ExistingF->getFunctionType() == F->getFunctionType())
+ return ExistingF;
+
+ // The name already exists, but is not a function or has the wrong
+ // prototype. Make place for the new one by renaming the old version.
+ // Either this old version will be removed later on or the module is
+ // invalid and we'll get an error.
+ ExistingGV->setName(WantedName + ".renamed");
+ }
+ return Intrinsic::getDeclaration(F->getParent(), ID, ArgTys);
+ }();
+
NewDecl->setCallingConv(F->getCallingConv());
assert(NewDecl->getFunctionType() == F->getFunctionType() &&
"Shouldn't change the signature");
@@ -1578,9 +1698,12 @@ Optional<Function *> Intrinsic::remangleIntrinsicFunction(Function *F) {
/// hasAddressTaken - returns true if there are any uses of this function
/// other than direct calls or invokes to it. Optionally ignores callback
-/// uses.
+/// uses, assume like pointer annotation calls, and references in llvm.used
+/// and llvm.compiler.used variables.
bool Function::hasAddressTaken(const User **PutOffender,
- bool IgnoreCallbackUses) const {
+ bool IgnoreCallbackUses,
+ bool IgnoreAssumeLikeCalls,
+ bool IgnoreLLVMUsed) const {
for (const Use &U : uses()) {
const User *FU = U.getUser();
if (isa<BlockAddress>(FU))
@@ -1594,6 +1717,31 @@ bool Function::hasAddressTaken(const User **PutOffender,
const auto *Call = dyn_cast<CallBase>(FU);
if (!Call) {
+ if (IgnoreAssumeLikeCalls) {
+ if (const auto *FI = dyn_cast<Instruction>(FU)) {
+ if (FI->isCast() && !FI->user_empty() &&
+ llvm::all_of(FU->users(), [](const User *U) {
+ if (const auto *I = dyn_cast<IntrinsicInst>(U))
+ return I->isAssumeLikeIntrinsic();
+ return false;
+ }))
+ continue;
+ }
+ }
+ if (IgnoreLLVMUsed && !FU->user_empty()) {
+ const User *FUU = FU;
+ if (isa<BitCastOperator>(FU) && FU->hasOneUse() &&
+ !FU->user_begin()->user_empty())
+ FUU = *FU->user_begin();
+ if (llvm::all_of(FUU->users(), [](const User *U) {
+ if (const auto *GV = dyn_cast<GlobalVariable>(U))
+ return GV->hasName() &&
+ (GV->getName().equals("llvm.compiler.used") ||
+ GV->getName().equals("llvm.used"));
+ return false;
+ }))
+ continue;
+ }
if (PutOffender)
*PutOffender = FU;
return true;