Index: llvm/include/llvm/IR/Intrinsics.h =================================================================== --- llvm/include/llvm/IR/Intrinsics.h +++ llvm/include/llvm/IR/Intrinsics.h @@ -53,11 +53,18 @@ StringRef getName(ID id); /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx". - /// Note, this version of getName supports overloads, but is less efficient - /// than the StringRef version of this function. If no overloads are - /// requried, it is safe to use this version, but better to use the StringRef - /// version. - std::string getName(ID id, ArrayRef Tys); + /// Note, this version of getName supports overloads, but no anonymous + /// structs. It is less efficient than the StringRef version of this function. + /// If no overloads are requiered, it is safe to use this version, but better + /// to use the StringRef version. + std::string getName(ID id, ArrayRef Tys); + + /// Return the LLVM name for an intrinsic, such as "llvm.ppc.altivec.lvx". + /// Note, this version of getName supports overloads and anonymous structs, + /// but is less efficient than the StringRef version of this function. If no + /// overloads are requiered, it is safe to use this version, but better to use + /// the StringRef version. + std::string getName(ID id, ArrayRef Tys, Module *M); /// Return the function type for an intrinsic. FunctionType *getType(LLVMContext &Context, ID id, Index: llvm/include/llvm/IR/Module.h =================================================================== --- llvm/include/llvm/IR/Module.h +++ llvm/include/llvm/IR/Module.h @@ -335,6 +335,10 @@ std::vector getIdentifiedStructTypes() const; + /// Return a stable unique id for the anonymous struct type, to be used by + /// intrinsic function name mangling. + unsigned getAnonStructUniqueID(const StructType *S); + /// @} /// @name Function Accessors /// @{ Index: llvm/lib/IR/Function.cpp =================================================================== --- llvm/lib/IR/Function.cpp +++ llvm/lib/IR/Function.cpp @@ -711,29 +711,35 @@ /// 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) { +static std::string getMangledTypeStr(Type *Ty, Module *M) { std::string Result; if (PointerType* PTyp = dyn_cast(Ty)) { Result += "p" + utostr(PTyp->getAddressSpace()) + - getMangledTypeStr(PTyp->getElementType()); + getMangledTypeStr(PTyp->getElementType(), M); } else if (ArrayType* ATyp = dyn_cast(Ty)) { Result += "a" + utostr(ATyp->getNumElements()) + - getMangledTypeStr(ATyp->getElementType()); + getMangledTypeStr(ATyp->getElementType(), M); } else if (StructType *STyp = dyn_cast(Ty)) { if (!STyp->isLiteral()) { - Result += "s_"; - Result += STyp->getName(); + if (STyp->hasName()) { + Result += "s_"; + Result += STyp->getName(); + } else if (M != nullptr) { + Result += "sa_" + utostr(M->getAnonStructUniqueID(STyp)); + } else { + Result += "s_"; + } } else { Result += "sl_"; for (auto Elem : STyp->elements()) - Result += getMangledTypeStr(Elem); + Result += getMangledTypeStr(Elem, M); } // Ensure nested structs are distinguishable. Result += "s"; } else if (FunctionType *FT = dyn_cast(Ty)) { - Result += "f_" + getMangledTypeStr(FT->getReturnType()); + Result += "f_" + getMangledTypeStr(FT->getReturnType(), M); for (size_t i = 0; i < FT->getNumParams(); i++) - Result += getMangledTypeStr(FT->getParamType(i)); + Result += getMangledTypeStr(FT->getParamType(i), M); if (FT->isVarArg()) Result += "vararg"; // Ensure nested function types are distinguishable. @@ -743,7 +749,7 @@ if (EC.isScalable()) Result += "nx"; Result += "v" + utostr(EC.getKnownMinValue()) + - getMangledTypeStr(VTy->getElementType()); + getMangledTypeStr(VTy->getElementType(), M); } else if (Ty) { switch (Ty->getTypeID()) { default: llvm_unreachable("Unhandled type"); @@ -772,15 +778,19 @@ return IntrinsicNameTable[id]; } -std::string Intrinsic::getName(ID id, ArrayRef Tys) { +std::string Intrinsic::getName(ID id, ArrayRef Tys, Module *M) { assert(id < num_intrinsics && "Invalid intrinsic ID!"); std::string Result(IntrinsicNameTable[id]); for (Type *Ty : Tys) { - Result += "." + getMangledTypeStr(Ty); + Result += "." + getMangledTypeStr(Ty, M); } return Result; } +std::string Intrinsic::getName(ID id, ArrayRef Tys) { + return getName(id, Tys, nullptr); +} + /// IIT_Info - These are enumerators that describe the entries returned by the /// getIntrinsicInfoTableEntries function. /// @@ -1236,7 +1246,7 @@ // There can never be multiple globals with the same name of different types, // because intrinsics must be a specific type. return cast( - M->getOrInsertFunction(getName(id, Tys), + M->getOrInsertFunction(getName(id, Tys, M), getType(M->getContext(), id, Tys)) .getCallee()); } Index: llvm/lib/IR/LLVMContextImpl.h =================================================================== --- llvm/lib/IR/LLVMContextImpl.h +++ llvm/lib/IR/LLVMContextImpl.h @@ -1406,6 +1406,7 @@ StructTypeSet AnonStructTypes; StringMap NamedStructTypes; unsigned NamedStructTypesUniqueID = 0; + DenseMap AnonStructIntrinsicNameManglingID; DenseMap, ArrayType*> ArrayTypes; DenseMap, VectorType*> VectorTypes; Index: llvm/lib/IR/Type.cpp =================================================================== --- llvm/lib/IR/Type.cpp +++ llvm/lib/IR/Type.cpp @@ -537,6 +537,13 @@ return getContext().pImpl->NamedStructTypes.lookup(Name); } +unsigned Module::getAnonStructUniqueID(const StructType *S) { + assert(S && !S->hasName() && "S must be an anonymous struct"); + auto &ASIMap = getContext().pImpl->AnonStructIntrinsicNameManglingID; + auto where = ASIMap.insert(std::make_pair(S, ASIMap.size())); + return where.first->second; +} + Type *StructType::getTypeAtIndex(const Value *V) const { unsigned Idx = (unsigned)cast(V)->getUniqueInteger().getZExtValue(); assert(indexValid(Idx) && "Invalid structure index!"); Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -4517,7 +4517,8 @@ // know they are legal for the intrinsic!) get the intrinsic name through the // usual means. This allows us to verify the mangling of argument types into // the name. - const std::string ExpectedName = Intrinsic::getName(ID, ArgTys); + const std::string ExpectedName = + Intrinsic::getName(ID, ArgTys, IF->getParent()); Assert(ExpectedName == IF->getName(), "Intrinsic name not mangled correctly for type arguments! " "Should be: " +