mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
[IntrinsicEmitter] Extend argument overloading with forward references.
Extend the mechanism to overload intrinsic arguments by using either backward or forward references to the overloadable arguments. In for example: def int_something : Intrinsic<[LLVMPointerToElt<0>], [llvm_anyvector_ty], []>; LLVMPointerToElt<0> is a forward reference to the overloadable operand of type 'llvm_anyvector_ty' and would allow intrinsics such as: declare i32* @llvm.something.v4i32(<4 x i32>); declare i64* @llvm.something.v2i64(<2 x i64>); where the result pointer type is deduced from the element type of the first argument. If the returned pointer is not a pointer to the element type, LLVM will give an error: Intrinsic has incorrect return type! i64* (<4 x i32>)* @llvm.something.v4i32 Reviewers: RKSimon, arsenm, rnk, greened Reviewed By: arsenm Differential Revision: https://reviews.llvm.org/D62995 llvm-svn: 363233
This commit is contained in:
parent
13c49f48e7
commit
dfbd44a9f0
@ -116,7 +116,8 @@ namespace Intrinsic {
|
||||
AK_AnyInteger,
|
||||
AK_AnyFloat,
|
||||
AK_AnyVector,
|
||||
AK_AnyPointer
|
||||
AK_AnyPointer,
|
||||
AK_MatchType = 7
|
||||
};
|
||||
|
||||
unsigned getArgumentNumber() const {
|
||||
@ -161,14 +162,21 @@ namespace Intrinsic {
|
||||
/// of IITDescriptors.
|
||||
void getIntrinsicInfoTableEntries(ID id, SmallVectorImpl<IITDescriptor> &T);
|
||||
|
||||
/// Match the specified type (which comes from an intrinsic argument or return
|
||||
/// value) with the type constraints specified by the .td file. If the given
|
||||
/// type is an overloaded type it is pushed to the ArgTys vector.
|
||||
enum MatchIntrinsicTypesResult {
|
||||
MatchIntrinsicTypes_Match = 0,
|
||||
MatchIntrinsicTypes_NoMatchRet = 1,
|
||||
MatchIntrinsicTypes_NoMatchArg = 2,
|
||||
};
|
||||
|
||||
/// Match the specified function type with the type constraints specified by
|
||||
/// the .td file. If the given type is an overloaded type it is pushed to the
|
||||
/// ArgTys vector.
|
||||
///
|
||||
/// Returns false if the given type matches with the constraints, true
|
||||
/// otherwise.
|
||||
bool matchIntrinsicType(Type *Ty, ArrayRef<IITDescriptor> &Infos,
|
||||
SmallVectorImpl<Type*> &ArgTys);
|
||||
MatchIntrinsicTypesResult
|
||||
matchIntrinsicSignature(FunctionType *FTy, ArrayRef<IITDescriptor> &Infos,
|
||||
SmallVectorImpl<Type *> &ArgTys);
|
||||
|
||||
/// Verify if the intrinsic has variable arguments. This method is intended to
|
||||
/// be called after all the fixed arguments have been matched first.
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -4154,14 +4154,14 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
|
||||
getIntrinsicInfoTableEntries(ID, Table);
|
||||
ArrayRef<Intrinsic::IITDescriptor> TableRef = Table;
|
||||
|
||||
// Walk the descriptors to extract overloaded types.
|
||||
SmallVector<Type *, 4> ArgTys;
|
||||
Assert(!Intrinsic::matchIntrinsicType(IFTy->getReturnType(),
|
||||
TableRef, ArgTys),
|
||||
Intrinsic::MatchIntrinsicTypesResult Res =
|
||||
Intrinsic::matchIntrinsicSignature(IFTy, TableRef, ArgTys);
|
||||
Assert(Res != Intrinsic::MatchIntrinsicTypes_NoMatchRet,
|
||||
"Intrinsic has incorrect return type!", IF);
|
||||
for (unsigned i = 0, e = IFTy->getNumParams(); i != e; ++i)
|
||||
Assert(!Intrinsic::matchIntrinsicType(IFTy->getParamType(i),
|
||||
TableRef, ArgTys),
|
||||
"Intrinsic has incorrect argument type!", IF);
|
||||
Assert(Res != Intrinsic::MatchIntrinsicTypes_NoMatchArg,
|
||||
"Intrinsic has incorrect argument type!", IF);
|
||||
|
||||
// Verify if the intrinsic call matches the vararg property.
|
||||
if (IsVarArg)
|
||||
|
@ -1019,13 +1019,12 @@ Value *InstCombiner::simplifyAMDGCNMemoryIntrinsicDemanded(IntrinsicInst *II,
|
||||
getIntrinsicInfoTableEntries(IID, Table);
|
||||
ArrayRef<Intrinsic::IITDescriptor> TableRef = Table;
|
||||
|
||||
// Validate function argument and return types, extracting overloaded types
|
||||
// along the way.
|
||||
FunctionType *FTy = II->getCalledFunction()->getFunctionType();
|
||||
SmallVector<Type *, 6> OverloadTys;
|
||||
Intrinsic::matchIntrinsicType(FTy->getReturnType(), TableRef, OverloadTys);
|
||||
for (unsigned i = 0, e = FTy->getNumParams(); i != e; ++i)
|
||||
Intrinsic::matchIntrinsicType(FTy->getParamType(i), TableRef, OverloadTys);
|
||||
Intrinsic::matchIntrinsicSignature(FTy, TableRef, OverloadTys);
|
||||
|
||||
// Get the new return type overload of the intrinsic.
|
||||
Module *M = II->getParent()->getParent()->getParent();
|
||||
Type *EltTy = II->getType()->getVectorElementType();
|
||||
Type *NewTy = (NewNumElts == 1) ? EltTy : VectorType::get(EltTy, NewNumElts);
|
||||
|
@ -591,9 +591,29 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
|
||||
TargetPrefix + ".'!");
|
||||
}
|
||||
|
||||
// Parse the list of return types.
|
||||
ListInit *RetTypes = R->getValueAsListInit("RetTypes");
|
||||
ListInit *ParamTypes = R->getValueAsListInit("ParamTypes");
|
||||
|
||||
// First collate a list of overloaded types.
|
||||
std::vector<MVT::SimpleValueType> OverloadedVTs;
|
||||
ListInit *TypeList = R->getValueAsListInit("RetTypes");
|
||||
for (ListInit *TypeList : {RetTypes, ParamTypes}) {
|
||||
for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
|
||||
Record *TyEl = TypeList->getElementAsRecord(i);
|
||||
assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
|
||||
|
||||
if (TyEl->isSubClassOf("LLVMMatchType"))
|
||||
continue;
|
||||
|
||||
MVT::SimpleValueType VT = getValueType(TyEl->getValueAsDef("VT"));
|
||||
if (MVT(VT).isOverloaded()) {
|
||||
OverloadedVTs.push_back(VT);
|
||||
isOverloaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Parse the list of return types.
|
||||
ListInit *TypeList = RetTypes;
|
||||
for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
|
||||
Record *TyEl = TypeList->getElementAsRecord(i);
|
||||
assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
|
||||
@ -613,10 +633,6 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
|
||||
} else {
|
||||
VT = getValueType(TyEl->getValueAsDef("VT"));
|
||||
}
|
||||
if (MVT(VT).isOverloaded()) {
|
||||
OverloadedVTs.push_back(VT);
|
||||
isOverloaded = true;
|
||||
}
|
||||
|
||||
// Reject invalid types.
|
||||
if (VT == MVT::isVoid)
|
||||
@ -628,7 +644,7 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
|
||||
}
|
||||
|
||||
// Parse the list of parameter types.
|
||||
TypeList = R->getValueAsListInit("ParamTypes");
|
||||
TypeList = ParamTypes;
|
||||
for (unsigned i = 0, e = TypeList->size(); i != e; ++i) {
|
||||
Record *TyEl = TypeList->getElementAsRecord(i);
|
||||
assert(TyEl->isSubClassOf("LLVMType") && "Expected a type!");
|
||||
@ -654,11 +670,6 @@ CodeGenIntrinsic::CodeGenIntrinsic(Record *R) {
|
||||
} else
|
||||
VT = getValueType(TyEl->getValueAsDef("VT"));
|
||||
|
||||
if (MVT(VT).isOverloaded()) {
|
||||
OverloadedVTs.push_back(VT);
|
||||
isOverloaded = true;
|
||||
}
|
||||
|
||||
// Reject invalid types.
|
||||
if (VT == MVT::isVoid && i != e-1 /*void at end means varargs*/)
|
||||
PrintFatalError(DefLoc, "Intrinsic '" + DefName +
|
||||
|
@ -258,10 +258,12 @@ static void EncodeFixedValueType(MVT::SimpleValueType VT,
|
||||
#endif
|
||||
|
||||
static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
|
||||
std::vector<unsigned char> &Sig) {
|
||||
unsigned &NextArgCode,
|
||||
std::vector<unsigned char> &Sig,
|
||||
ArrayRef<unsigned char> Mapping) {
|
||||
|
||||
if (R->isSubClassOf("LLVMMatchType")) {
|
||||
unsigned Number = R->getValueAsInt("Number");
|
||||
unsigned Number = Mapping[R->getValueAsInt("Number")];
|
||||
assert(Number < ArgCodes.size() && "Invalid matching number!");
|
||||
if (R->isSubClassOf("LLVMExtendedType"))
|
||||
Sig.push_back(IIT_EXTEND_ARG);
|
||||
@ -280,10 +282,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
|
||||
Sig.push_back(IIT_PTR_TO_ARG);
|
||||
else if (R->isSubClassOf("LLVMVectorOfAnyPointersToElt")) {
|
||||
Sig.push_back(IIT_VEC_OF_ANYPTRS_TO_ELT);
|
||||
unsigned ArgNo = ArgCodes.size();
|
||||
ArgCodes.push_back(3 /*vAny*/);
|
||||
// Encode overloaded ArgNo
|
||||
Sig.push_back(ArgNo);
|
||||
Sig.push_back(NextArgCode++);
|
||||
// Encode LLVMMatchType<Number> ArgNo
|
||||
Sig.push_back(Number);
|
||||
return;
|
||||
@ -291,7 +291,7 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
|
||||
Sig.push_back(IIT_PTR_TO_ELT);
|
||||
else
|
||||
Sig.push_back(IIT_ARG);
|
||||
return Sig.push_back((Number << 3) | ArgCodes[Number]);
|
||||
return Sig.push_back((Number << 3) | 7 /*IITDescriptor::AK_MatchType*/);
|
||||
}
|
||||
|
||||
MVT::SimpleValueType VT = getValueType(R->getValueAsDef("VT"));
|
||||
@ -309,8 +309,9 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
|
||||
Sig.push_back(IIT_ARG);
|
||||
|
||||
// Figure out what arg # this is consuming, and remember what kind it was.
|
||||
unsigned ArgNo = ArgCodes.size();
|
||||
ArgCodes.push_back(Tmp);
|
||||
assert(NextArgCode < ArgCodes.size() && ArgCodes[NextArgCode] == Tmp &&
|
||||
"Invalid or no ArgCode associated with overloaded VT!");
|
||||
unsigned ArgNo = NextArgCode++;
|
||||
|
||||
// Encode what sort of argument it must be in the low 3 bits of the ArgNo.
|
||||
return Sig.push_back((ArgNo << 3) | Tmp);
|
||||
@ -328,7 +329,8 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
|
||||
} else {
|
||||
Sig.push_back(IIT_PTR);
|
||||
}
|
||||
return EncodeFixedType(R->getValueAsDef("ElTy"), ArgCodes, Sig);
|
||||
return EncodeFixedType(R->getValueAsDef("ElTy"), ArgCodes, NextArgCode, Sig,
|
||||
Mapping);
|
||||
}
|
||||
}
|
||||
|
||||
@ -353,6 +355,42 @@ static void EncodeFixedType(Record *R, std::vector<unsigned char> &ArgCodes,
|
||||
EncodeFixedValueType(VT, Sig);
|
||||
}
|
||||
|
||||
static void UpdateArgCodes(Record *R, std::vector<unsigned char> &ArgCodes,
|
||||
unsigned int &NumInserted,
|
||||
SmallVectorImpl<unsigned char> &Mapping) {
|
||||
if (R->isSubClassOf("LLVMMatchType")) {
|
||||
if (R->isSubClassOf("LLVMVectorOfAnyPointersToElt")) {
|
||||
ArgCodes.push_back(3 /*vAny*/);
|
||||
++NumInserted;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned Tmp = 0;
|
||||
switch (getValueType(R->getValueAsDef("VT"))) {
|
||||
default: break;
|
||||
case MVT::iPTRAny:
|
||||
++Tmp;
|
||||
LLVM_FALLTHROUGH;
|
||||
case MVT::vAny:
|
||||
++Tmp;
|
||||
LLVM_FALLTHROUGH;
|
||||
case MVT::fAny:
|
||||
++Tmp;
|
||||
LLVM_FALLTHROUGH;
|
||||
case MVT::iAny:
|
||||
++Tmp;
|
||||
LLVM_FALLTHROUGH;
|
||||
case MVT::Any:
|
||||
unsigned OriginalIdx = ArgCodes.size() - NumInserted;
|
||||
assert(OriginalIdx >= Mapping.size());
|
||||
Mapping.resize(OriginalIdx+1);
|
||||
Mapping[OriginalIdx] = ArgCodes.size();
|
||||
ArgCodes.push_back(Tmp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
#pragma optimize("",on)
|
||||
#endif
|
||||
@ -363,6 +401,17 @@ static void ComputeFixedEncoding(const CodeGenIntrinsic &Int,
|
||||
std::vector<unsigned char> &TypeSig) {
|
||||
std::vector<unsigned char> ArgCodes;
|
||||
|
||||
// Add codes for any overloaded result VTs.
|
||||
unsigned int NumInserted = 0;
|
||||
SmallVector<unsigned char, 8> ArgMapping;
|
||||
for (unsigned i = 0, e = Int.IS.RetVTs.size(); i != e; ++i)
|
||||
UpdateArgCodes(Int.IS.RetTypeDefs[i], ArgCodes, NumInserted, ArgMapping);
|
||||
|
||||
// Add codes for any overloaded operand VTs.
|
||||
for (unsigned i = 0, e = Int.IS.ParamTypeDefs.size(); i != e; ++i)
|
||||
UpdateArgCodes(Int.IS.ParamTypeDefs[i], ArgCodes, NumInserted, ArgMapping);
|
||||
|
||||
unsigned NextArgCode = 0;
|
||||
if (Int.IS.RetVTs.empty())
|
||||
TypeSig.push_back(IIT_Done);
|
||||
else if (Int.IS.RetVTs.size() == 1 &&
|
||||
@ -382,11 +431,13 @@ static void ComputeFixedEncoding(const CodeGenIntrinsic &Int,
|
||||
}
|
||||
|
||||
for (unsigned i = 0, e = Int.IS.RetVTs.size(); i != e; ++i)
|
||||
EncodeFixedType(Int.IS.RetTypeDefs[i], ArgCodes, TypeSig);
|
||||
EncodeFixedType(Int.IS.RetTypeDefs[i], ArgCodes, NextArgCode, TypeSig,
|
||||
ArgMapping);
|
||||
}
|
||||
|
||||
for (unsigned i = 0, e = Int.IS.ParamTypeDefs.size(); i != e; ++i)
|
||||
EncodeFixedType(Int.IS.ParamTypeDefs[i], ArgCodes, TypeSig);
|
||||
EncodeFixedType(Int.IS.ParamTypeDefs[i], ArgCodes, NextArgCode, TypeSig,
|
||||
ArgMapping);
|
||||
}
|
||||
|
||||
static void printIITEntry(raw_ostream &OS, unsigned char X) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user