|
@@ -1047,12 +1047,26 @@ Function *Intrinsic::getDeclaration(Module *M, ID id, ArrayRef<Type*> Tys) {
|
|
|
#include "llvm/IR/IntrinsicImpl.inc"
|
|
|
#undef GET_LLVM_INTRINSIC_FOR_MS_BUILTIN
|
|
|
|
|
|
-bool Intrinsic::matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor> &Infos,
|
|
|
- SmallVectorImpl<Type*> &ArgTys) {
|
|
|
+using DeferredIntrinsicMatchPair =
|
|
|
+ std::pair<Type *, ArrayRef<Intrinsic::IITDescriptor>>;
|
|
|
+
|
|
|
+static bool matchIntrinsicType(
|
|
|
+ Type *Ty, ArrayRef<Intrinsic::IITDescriptor> &Infos,
|
|
|
+ SmallVectorImpl<Type *> &ArgTys,
|
|
|
+ SmallVectorImpl<DeferredIntrinsicMatchPair> &DeferredChecks,
|
|
|
+ bool IsDeferredCheck) {
|
|
|
using namespace Intrinsic;
|
|
|
|
|
|
// If we ran out of descriptors, there are too many arguments.
|
|
|
if (Infos.empty()) return true;
|
|
|
+
|
|
|
+ // Do this before slicing off the 'front' part
|
|
|
+ auto InfosRef = Infos;
|
|
|
+ auto DeferCheck = [&DeferredChecks, &InfosRef](Type *T) {
|
|
|
+ DeferredChecks.emplace_back(T, InfosRef);
|
|
|
+ return false;
|
|
|
+ };
|
|
|
+
|
|
|
IITDescriptor D = Infos.front();
|
|
|
Infos = Infos.slice(1);
|
|
|
|
|
@@ -1070,12 +1084,14 @@ bool Intrinsic::matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor>
|
|
|
case IITDescriptor::Vector: {
|
|
|
VectorType *VT = dyn_cast<VectorType>(Ty);
|
|
|
return !VT || VT->getNumElements() != D.Vector_Width ||
|
|
|
- matchIntrinsicType(VT->getElementType(), Infos, ArgTys);
|
|
|
+ matchIntrinsicType(VT->getElementType(), Infos, ArgTys,
|
|
|
+ DeferredChecks, IsDeferredCheck);
|
|
|
}
|
|
|
case IITDescriptor::Pointer: {
|
|
|
PointerType *PT = dyn_cast<PointerType>(Ty);
|
|
|
return !PT || PT->getAddressSpace() != D.Pointer_AddressSpace ||
|
|
|
- matchIntrinsicType(PT->getElementType(), Infos, ArgTys);
|
|
|
+ matchIntrinsicType(PT->getElementType(), Infos, ArgTys,
|
|
|
+ DeferredChecks, IsDeferredCheck);
|
|
|
}
|
|
|
|
|
|
case IITDescriptor::Struct: {
|
|
@@ -1084,20 +1100,24 @@ bool Intrinsic::matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor>
|
|
|
return true;
|
|
|
|
|
|
for (unsigned i = 0, e = D.Struct_NumElements; i != e; ++i)
|
|
|
- if (matchIntrinsicType(ST->getElementType(i), Infos, ArgTys))
|
|
|
+ if (matchIntrinsicType(ST->getElementType(i), Infos, ArgTys,
|
|
|
+ DeferredChecks, IsDeferredCheck))
|
|
|
return true;
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
case IITDescriptor::Argument:
|
|
|
- // Two cases here - If this is the second occurrence of an argument, verify
|
|
|
- // that the later instance matches the previous instance.
|
|
|
+ // If this is the second occurrence of an argument,
|
|
|
+ // verify that the later instance matches the previous instance.
|
|
|
if (D.getArgumentNumber() < ArgTys.size())
|
|
|
return Ty != ArgTys[D.getArgumentNumber()];
|
|
|
|
|
|
- // Otherwise, if this is the first instance of an argument, record it and
|
|
|
- // verify the "Any" kind.
|
|
|
- assert(D.getArgumentNumber() == ArgTys.size() && "Table consistency error");
|
|
|
+ if (D.getArgumentNumber() > ArgTys.size() ||
|
|
|
+ D.getArgumentKind() == IITDescriptor::AK_MatchType)
|
|
|
+ return IsDeferredCheck || DeferCheck(Ty);
|
|
|
+
|
|
|
+ assert(D.getArgumentNumber() == ArgTys.size() && !IsDeferredCheck &&
|
|
|
+ "Table consistency error");
|
|
|
ArgTys.push_back(Ty);
|
|
|
|
|
|
switch (D.getArgumentKind()) {
|
|
@@ -1106,13 +1126,14 @@ bool Intrinsic::matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor>
|
|
|
case IITDescriptor::AK_AnyFloat: return !Ty->isFPOrFPVectorTy();
|
|
|
case IITDescriptor::AK_AnyVector: return !isa<VectorType>(Ty);
|
|
|
case IITDescriptor::AK_AnyPointer: return !isa<PointerType>(Ty);
|
|
|
+ default: break;
|
|
|
}
|
|
|
llvm_unreachable("all argument kinds not covered");
|
|
|
|
|
|
case IITDescriptor::ExtendArgument: {
|
|
|
- // This may only be used when referring to a previous vector argument.
|
|
|
+ // If this is a forward reference, defer the check for later.
|
|
|
if (D.getArgumentNumber() >= ArgTys.size())
|
|
|
- return true;
|
|
|
+ return IsDeferredCheck || DeferCheck(Ty);
|
|
|
|
|
|
Type *NewTy = ArgTys[D.getArgumentNumber()];
|
|
|
if (VectorType *VTy = dyn_cast<VectorType>(NewTy))
|
|
@@ -1125,9 +1146,9 @@ bool Intrinsic::matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor>
|
|
|
return Ty != NewTy;
|
|
|
}
|
|
|
case IITDescriptor::TruncArgument: {
|
|
|
- // This may only be used when referring to a previous vector argument.
|
|
|
+ // If this is a forward reference, defer the check for later.
|
|
|
if (D.getArgumentNumber() >= ArgTys.size())
|
|
|
- return true;
|
|
|
+ return IsDeferredCheck || DeferCheck(Ty);
|
|
|
|
|
|
Type *NewTy = ArgTys[D.getArgumentNumber()];
|
|
|
if (VectorType *VTy = dyn_cast<VectorType>(NewTy))
|
|
@@ -1140,14 +1161,17 @@ bool Intrinsic::matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor>
|
|
|
return Ty != NewTy;
|
|
|
}
|
|
|
case IITDescriptor::HalfVecArgument:
|
|
|
- // This may only be used when referring to a previous vector argument.
|
|
|
+ // If this is a forward reference, defer the check for later.
|
|
|
return D.getArgumentNumber() >= ArgTys.size() ||
|
|
|
!isa<VectorType>(ArgTys[D.getArgumentNumber()]) ||
|
|
|
VectorType::getHalfElementsVectorType(
|
|
|
cast<VectorType>(ArgTys[D.getArgumentNumber()])) != Ty;
|
|
|
case IITDescriptor::SameVecWidthArgument: {
|
|
|
- if (D.getArgumentNumber() >= ArgTys.size())
|
|
|
- return true;
|
|
|
+ if (D.getArgumentNumber() >= ArgTys.size()) {
|
|
|
+ // Defer check and subsequent check for the vector element type.
|
|
|
+ Infos = Infos.slice(1);
|
|
|
+ return IsDeferredCheck || DeferCheck(Ty);
|
|
|
+ }
|
|
|
auto *ReferenceType = dyn_cast<VectorType>(ArgTys[D.getArgumentNumber()]);
|
|
|
auto *ThisArgType = dyn_cast<VectorType>(Ty);
|
|
|
// Both must be vectors of the same number of elements or neither.
|
|
@@ -1160,18 +1184,19 @@ bool Intrinsic::matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor>
|
|
|
return true;
|
|
|
EltTy = ThisArgType->getVectorElementType();
|
|
|
}
|
|
|
- return matchIntrinsicType(EltTy, Infos, ArgTys);
|
|
|
+ return matchIntrinsicType(EltTy, Infos, ArgTys, DeferredChecks,
|
|
|
+ IsDeferredCheck);
|
|
|
}
|
|
|
case IITDescriptor::PtrToArgument: {
|
|
|
if (D.getArgumentNumber() >= ArgTys.size())
|
|
|
- return true;
|
|
|
+ return IsDeferredCheck || DeferCheck(Ty);
|
|
|
Type * ReferenceType = ArgTys[D.getArgumentNumber()];
|
|
|
PointerType *ThisArgType = dyn_cast<PointerType>(Ty);
|
|
|
return (!ThisArgType || ThisArgType->getElementType() != ReferenceType);
|
|
|
}
|
|
|
case IITDescriptor::PtrToElt: {
|
|
|
if (D.getArgumentNumber() >= ArgTys.size())
|
|
|
- return true;
|
|
|
+ return IsDeferredCheck || DeferCheck(Ty);
|
|
|
VectorType * ReferenceType =
|
|
|
dyn_cast<VectorType> (ArgTys[D.getArgumentNumber()]);
|
|
|
PointerType *ThisArgType = dyn_cast<PointerType>(Ty);
|
|
@@ -1181,15 +1206,20 @@ bool Intrinsic::matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor>
|
|
|
}
|
|
|
case IITDescriptor::VecOfAnyPtrsToElt: {
|
|
|
unsigned RefArgNumber = D.getRefArgNumber();
|
|
|
+ if (RefArgNumber >= ArgTys.size()) {
|
|
|
+ if (IsDeferredCheck)
|
|
|
+ return true;
|
|
|
+ // If forward referencing, already add the pointer-vector type and
|
|
|
+ // defer the checks for later.
|
|
|
+ ArgTys.push_back(Ty);
|
|
|
+ return DeferCheck(Ty);
|
|
|
+ }
|
|
|
|
|
|
- // This may only be used when referring to a previous argument.
|
|
|
- if (RefArgNumber >= ArgTys.size())
|
|
|
- return true;
|
|
|
-
|
|
|
- // Record the overloaded type
|
|
|
- assert(D.getOverloadArgNumber() == ArgTys.size() &&
|
|
|
- "Table consistency error");
|
|
|
- ArgTys.push_back(Ty);
|
|
|
+ if (!IsDeferredCheck){
|
|
|
+ assert(D.getOverloadArgNumber() == ArgTys.size() &&
|
|
|
+ "Table consistency error");
|
|
|
+ ArgTys.push_back(Ty);
|
|
|
+ }
|
|
|
|
|
|
// Verify the overloaded type "matches" the Ref type.
|
|
|
// i.e. Ty is a vector with the same width as Ref.
|
|
@@ -1211,6 +1241,32 @@ bool Intrinsic::matchIntrinsicType(Type *Ty, ArrayRef<Intrinsic::IITDescriptor>
|
|
|
llvm_unreachable("unhandled");
|
|
|
}
|
|
|
|
|
|
+Intrinsic::MatchIntrinsicTypesResult
|
|
|
+Intrinsic::matchIntrinsicSignature(FunctionType *FTy,
|
|
|
+ ArrayRef<Intrinsic::IITDescriptor> &Infos,
|
|
|
+ SmallVectorImpl<Type *> &ArgTys) {
|
|
|
+ SmallVector<DeferredIntrinsicMatchPair, 2> DeferredChecks;
|
|
|
+ if (matchIntrinsicType(FTy->getReturnType(), Infos, ArgTys, DeferredChecks,
|
|
|
+ false))
|
|
|
+ return MatchIntrinsicTypes_NoMatchRet;
|
|
|
+
|
|
|
+ unsigned NumDeferredReturnChecks = DeferredChecks.size();
|
|
|
+
|
|
|
+ for (auto Ty : FTy->params())
|
|
|
+ if (matchIntrinsicType(Ty, Infos, ArgTys, DeferredChecks, false))
|
|
|
+ return MatchIntrinsicTypes_NoMatchArg;
|
|
|
+
|
|
|
+ for (unsigned I = 0, E = DeferredChecks.size(); I != E; ++I) {
|
|
|
+ DeferredIntrinsicMatchPair &Check = DeferredChecks[I];
|
|
|
+ if (matchIntrinsicType(Check.first, Check.second, ArgTys, DeferredChecks,
|
|
|
+ true))
|
|
|
+ return I < NumDeferredReturnChecks ? MatchIntrinsicTypes_NoMatchRet
|
|
|
+ : MatchIntrinsicTypes_NoMatchArg;
|
|
|
+ }
|
|
|
+
|
|
|
+ return MatchIntrinsicTypes_Match;
|
|
|
+}
|
|
|
+
|
|
|
bool
|
|
|
Intrinsic::matchIntrinsicVarArg(bool isVarArg,
|
|
|
ArrayRef<Intrinsic::IITDescriptor> &Infos) {
|
|
@@ -1244,13 +1300,8 @@ Optional<Function*> Intrinsic::remangleIntrinsicFunction(Function *F) {
|
|
|
getIntrinsicInfoTableEntries(ID, Table);
|
|
|
ArrayRef<Intrinsic::IITDescriptor> TableRef = Table;
|
|
|
|
|
|
- // If we encounter any problems matching the signature with the descriptor
|
|
|
- // just give up remangling. It's up to verifier to report the discrepancy.
|
|
|
- if (Intrinsic::matchIntrinsicType(FTy->getReturnType(), TableRef, ArgTys))
|
|
|
+ if (Intrinsic::matchIntrinsicSignature(FTy, TableRef, ArgTys))
|
|
|
return None;
|
|
|
- for (auto Ty : FTy->params())
|
|
|
- if (Intrinsic::matchIntrinsicType(Ty, TableRef, ArgTys))
|
|
|
- return None;
|
|
|
if (Intrinsic::matchIntrinsicVarArg(FTy->isVarArg(), TableRef))
|
|
|
return None;
|
|
|
}
|