diff options
Diffstat (limited to 'contrib/llvm-project/llvm/lib/IR/Function.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/IR/Function.cpp | 230 |
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; |