PR15730/PR16986 Allow dependently typed vector_size types.
As listed in the above PRs, vector_size doesn't allow dependent types/values. This patch introduces a new DependentVectorType to handle a VectorType that has a dependent size or type. In the future, ALL the vector-types should be able to create one of these to handle dependent types/sizes as well. For example, DependentSizedExtVectorType could likely be switched to just use this instead, though that is left as an exercise for the future. Differential Revision: https://reviews.llvm.org/D49045 llvm-svn: 337036
This commit is contained in:
parent
393fe62e33
commit
f702b029f4
|
@ -168,6 +168,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||
mutable llvm::FoldingSet<DependentAddressSpaceType>
|
||||
DependentAddressSpaceTypes;
|
||||
mutable llvm::FoldingSet<VectorType> VectorTypes;
|
||||
mutable llvm::FoldingSet<DependentVectorType> DependentVectorTypes;
|
||||
mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes;
|
||||
mutable llvm::ContextualFoldingSet<FunctionProtoType, ASTContext&>
|
||||
FunctionProtoTypes;
|
||||
|
@ -1321,6 +1322,11 @@ public:
|
|||
/// \pre \p VectorType must be a built-in type.
|
||||
QualType getVectorType(QualType VectorType, unsigned NumElts,
|
||||
VectorType::VectorKind VecKind) const;
|
||||
/// Return the unique reference to the type for a dependently sized vector of
|
||||
/// the specified element type.
|
||||
QualType getDependentVectorType(QualType VectorType, Expr *SizeExpr,
|
||||
SourceLocation AttrLoc,
|
||||
VectorType::VectorKind VecKind) const;
|
||||
|
||||
/// Return the unique reference to an extended vector type
|
||||
/// of the specified element type and size.
|
||||
|
|
|
@ -993,6 +993,12 @@ DEF_TRAVERSE_TYPE(DependentAddressSpaceType, {
|
|||
TRY_TO(TraverseType(T->getPointeeType()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPE(DependentVectorType, {
|
||||
if (T->getSizeExpr())
|
||||
TRY_TO(TraverseStmt(T->getSizeExpr()));
|
||||
TRY_TO(TraverseType(T->getElementType()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, {
|
||||
if (T->getSizeExpr())
|
||||
TRY_TO(TraverseStmt(T->getSizeExpr()));
|
||||
|
@ -1221,6 +1227,12 @@ DEF_TRAVERSE_TYPELOC(VectorType, {
|
|||
TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
|
||||
})
|
||||
|
||||
DEF_TRAVERSE_TYPELOC(DependentVectorType, {
|
||||
if (TL.getTypePtr()->getSizeExpr())
|
||||
TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
|
||||
TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
|
||||
})
|
||||
|
||||
// FIXME: size and attributes
|
||||
// FIXME: base VectorTypeLoc is unfinished
|
||||
DEF_TRAVERSE_TYPELOC(ExtVectorType, {
|
||||
|
|
|
@ -1590,6 +1590,7 @@ protected:
|
|||
|
||||
class VectorTypeBitfields {
|
||||
friend class VectorType;
|
||||
friend class DependentVectorType;
|
||||
|
||||
unsigned : NumTypeBits;
|
||||
|
||||
|
@ -3079,6 +3080,51 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/// Represents a vector type where either the type or size is dependent.
|
||||
////
|
||||
/// For example:
|
||||
/// \code
|
||||
/// template<typename T, int Size>
|
||||
/// class vector {
|
||||
/// typedef T __attribute__((vector_size(Size))) type;
|
||||
/// }
|
||||
/// \endcode
|
||||
class DependentVectorType : public Type, public llvm::FoldingSetNode {
|
||||
friend class ASTContext;
|
||||
|
||||
const ASTContext &Context;
|
||||
QualType ElementType;
|
||||
Expr *SizeExpr;
|
||||
SourceLocation Loc;
|
||||
|
||||
DependentVectorType(const ASTContext &Context, QualType ElementType,
|
||||
QualType CanonType, Expr *SizeExpr,
|
||||
SourceLocation Loc, VectorType::VectorKind vecKind);
|
||||
|
||||
public:
|
||||
Expr *getSizeExpr() const { return SizeExpr; }
|
||||
QualType getElementType() const { return ElementType; }
|
||||
SourceLocation getAttributeLoc() const { return Loc; }
|
||||
VectorType::VectorKind getVectorKind() const {
|
||||
return VectorType::VectorKind(VectorTypeBits.VecKind);
|
||||
}
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == DependentVector;
|
||||
}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, Context, getElementType(), getSizeExpr(), getVectorKind());
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
|
||||
QualType ElementType, const Expr *SizeExpr,
|
||||
VectorType::VectorKind VecKind);
|
||||
};
|
||||
|
||||
/// ExtVectorType - Extended vector type. This type is created using
|
||||
/// __attribute__((ext_vector_type(n)), where "n" is the number of elements.
|
||||
/// Unlike vector_size, ext_vector_type is only allowed on typedef's. This
|
||||
|
|
|
@ -1798,6 +1798,13 @@ class VectorTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
|||
VectorType> {
|
||||
};
|
||||
|
||||
// FIXME: size expression and attribute locations (or keyword if we
|
||||
// ever fully support altivec syntax).
|
||||
class DependentVectorTypeLoc
|
||||
: public InheritingConcreteTypeLoc<TypeSpecTypeLoc,
|
||||
DependentVectorTypeLoc,
|
||||
DependentVectorType> {};
|
||||
|
||||
// FIXME: size expression and attribute locations.
|
||||
class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc,
|
||||
ExtVectorTypeLoc,
|
||||
|
|
|
@ -75,6 +75,7 @@ DEPENDENT_TYPE(DependentSizedArray, ArrayType)
|
|||
DEPENDENT_TYPE(DependentSizedExtVector, Type)
|
||||
DEPENDENT_TYPE(DependentAddressSpace, Type)
|
||||
TYPE(Vector, Type)
|
||||
DEPENDENT_TYPE(DependentVector, Type)
|
||||
TYPE(ExtVector, VectorType)
|
||||
ABSTRACT_TYPE(Function, Type)
|
||||
TYPE(FunctionProto, FunctionType)
|
||||
|
|
|
@ -1377,6 +1377,7 @@ public:
|
|||
QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
|
||||
Expr *ArraySize, unsigned Quals,
|
||||
SourceRange Brackets, DeclarationName Entity);
|
||||
QualType BuildVectorType(QualType T, Expr *VecSize, SourceLocation AttrLoc);
|
||||
QualType BuildExtVectorType(QualType T, Expr *ArraySize,
|
||||
SourceLocation AttrLoc);
|
||||
QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace,
|
||||
|
|
|
@ -1167,7 +1167,10 @@ namespace serialization {
|
|||
TYPE_DEPENDENT_SIZED_EXT_VECTOR = 46,
|
||||
|
||||
/// A DependentAddressSpaceType record.
|
||||
TYPE_DEPENDENT_ADDRESS_SPACE = 47
|
||||
TYPE_DEPENDENT_ADDRESS_SPACE = 47,
|
||||
|
||||
/// A dependentSizedVectorType record.
|
||||
TYPE_DEPENDENT_SIZED_VECTOR = 48
|
||||
};
|
||||
|
||||
/// The type IDs for special types constructed by semantic
|
||||
|
|
|
@ -3035,6 +3035,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
|
|||
case Type::Builtin:
|
||||
case Type::Complex:
|
||||
case Type::Vector:
|
||||
case Type::DependentVector:
|
||||
case Type::ExtVector:
|
||||
case Type::DependentSizedExtVector:
|
||||
case Type::DependentAddressSpace:
|
||||
|
@ -3313,6 +3314,45 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts,
|
|||
return QualType(New, 0);
|
||||
}
|
||||
|
||||
QualType
|
||||
ASTContext::getDependentVectorType(QualType VecType, Expr *SizeExpr,
|
||||
SourceLocation AttrLoc,
|
||||
VectorType::VectorKind VecKind) const {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
DependentVectorType::Profile(ID, *this, getCanonicalType(VecType), SizeExpr,
|
||||
VecKind);
|
||||
void *InsertPos = nullptr;
|
||||
DependentVectorType *Canon =
|
||||
DependentVectorTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
DependentVectorType *New;
|
||||
|
||||
if (Canon) {
|
||||
New = new (*this, TypeAlignment) DependentVectorType(
|
||||
*this, VecType, QualType(Canon, 0), SizeExpr, AttrLoc, VecKind);
|
||||
} else {
|
||||
QualType CanonVecTy = getCanonicalType(VecType);
|
||||
if (CanonVecTy == VecType) {
|
||||
New = new (*this, TypeAlignment) DependentVectorType(
|
||||
*this, VecType, QualType(), SizeExpr, AttrLoc, VecKind);
|
||||
|
||||
DependentVectorType *CanonCheck =
|
||||
DependentVectorTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
assert(!CanonCheck &&
|
||||
"Dependent-sized vector_size canonical type broken");
|
||||
(void)CanonCheck;
|
||||
DependentVectorTypes.InsertNode(New, InsertPos);
|
||||
} else {
|
||||
QualType Canon = getDependentSizedExtVectorType(CanonVecTy, SizeExpr,
|
||||
SourceLocation());
|
||||
New = new (*this, TypeAlignment) DependentVectorType(
|
||||
*this, VecType, Canon, SizeExpr, AttrLoc, VecKind);
|
||||
}
|
||||
}
|
||||
|
||||
Types.push_back(New);
|
||||
return QualType(New, 0);
|
||||
}
|
||||
|
||||
/// getExtVectorType - Return the unique reference to an extended vector type of
|
||||
/// the specified element type and size. VectorType must be a built-in type.
|
||||
QualType
|
||||
|
|
|
@ -51,7 +51,7 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
|||
|
||||
/// Determine structural equivalence of two expressions.
|
||||
static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
||||
Expr *E1, Expr *E2) {
|
||||
const Expr *E1, const Expr *E2) {
|
||||
if (!E1 || !E2)
|
||||
return E1 == E2;
|
||||
|
||||
|
@ -408,6 +408,20 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
|||
break;
|
||||
}
|
||||
|
||||
case Type::DependentVector: {
|
||||
const auto *Vec1 = cast<DependentVectorType>(T1);
|
||||
const auto *Vec2 = cast<DependentVectorType>(T2);
|
||||
if (Vec1->getVectorKind() != Vec2->getVectorKind())
|
||||
return false;
|
||||
if (!IsStructurallyEquivalent(Context, Vec1->getSizeExpr(),
|
||||
Vec2->getSizeExpr()))
|
||||
return false;
|
||||
if (!IsStructurallyEquivalent(Context, Vec1->getElementType(),
|
||||
Vec2->getElementType()))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
case Type::Vector:
|
||||
case Type::ExtVector: {
|
||||
const auto *Vec1 = cast<VectorType>(T1);
|
||||
|
|
|
@ -539,7 +539,9 @@ private:
|
|||
void mangleBareFunctionType(const FunctionProtoType *T, bool MangleReturnType,
|
||||
const FunctionDecl *FD = nullptr);
|
||||
void mangleNeonVectorType(const VectorType *T);
|
||||
void mangleNeonVectorType(const DependentVectorType *T);
|
||||
void mangleAArch64NeonVectorType(const VectorType *T);
|
||||
void mangleAArch64NeonVectorType(const DependentVectorType *T);
|
||||
|
||||
void mangleIntegerLiteral(QualType T, const llvm::APSInt &Value);
|
||||
void mangleMemberExprBase(const Expr *base, bool isArrow);
|
||||
|
@ -1930,6 +1932,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
|
|||
case Type::VariableArray:
|
||||
case Type::DependentSizedArray:
|
||||
case Type::DependentAddressSpace:
|
||||
case Type::DependentVector:
|
||||
case Type::DependentSizedExtVector:
|
||||
case Type::Vector:
|
||||
case Type::ExtVector:
|
||||
|
@ -3000,6 +3003,14 @@ void CXXNameMangler::mangleNeonVectorType(const VectorType *T) {
|
|||
Out << BaseName << EltName;
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleNeonVectorType(const DependentVectorType *T) {
|
||||
DiagnosticsEngine &Diags = Context.getDiags();
|
||||
unsigned DiagID = Diags.getCustomDiagID(
|
||||
DiagnosticsEngine::Error,
|
||||
"cannot mangle this dependent neon vector type yet");
|
||||
Diags.Report(T->getAttributeLoc(), DiagID);
|
||||
}
|
||||
|
||||
static StringRef mangleAArch64VectorBase(const BuiltinType *EltType) {
|
||||
switch (EltType->getKind()) {
|
||||
case BuiltinType::SChar:
|
||||
|
@ -3067,6 +3078,13 @@ void CXXNameMangler::mangleAArch64NeonVectorType(const VectorType *T) {
|
|||
("__" + EltName + "x" + Twine(T->getNumElements()) + "_t").str();
|
||||
Out << TypeName.length() << TypeName;
|
||||
}
|
||||
void CXXNameMangler::mangleAArch64NeonVectorType(const DependentVectorType *T) {
|
||||
DiagnosticsEngine &Diags = Context.getDiags();
|
||||
unsigned DiagID = Diags.getCustomDiagID(
|
||||
DiagnosticsEngine::Error,
|
||||
"cannot mangle this dependent neon vector type yet");
|
||||
Diags.Report(T->getAttributeLoc(), DiagID);
|
||||
}
|
||||
|
||||
// GNU extension: vector types
|
||||
// <type> ::= <vector-type>
|
||||
|
@ -3097,6 +3115,32 @@ void CXXNameMangler::mangleType(const VectorType *T) {
|
|||
else
|
||||
mangleType(T->getElementType());
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleType(const DependentVectorType *T) {
|
||||
if ((T->getVectorKind() == VectorType::NeonVector ||
|
||||
T->getVectorKind() == VectorType::NeonPolyVector)) {
|
||||
llvm::Triple Target = getASTContext().getTargetInfo().getTriple();
|
||||
llvm::Triple::ArchType Arch =
|
||||
getASTContext().getTargetInfo().getTriple().getArch();
|
||||
if ((Arch == llvm::Triple::aarch64 || Arch == llvm::Triple::aarch64_be) &&
|
||||
!Target.isOSDarwin())
|
||||
mangleAArch64NeonVectorType(T);
|
||||
else
|
||||
mangleNeonVectorType(T);
|
||||
return;
|
||||
}
|
||||
|
||||
Out << "Dv";
|
||||
mangleExpression(T->getSizeExpr());
|
||||
Out << '_';
|
||||
if (T->getVectorKind() == VectorType::AltiVecPixel)
|
||||
Out << 'p';
|
||||
else if (T->getVectorKind() == VectorType::AltiVecBool)
|
||||
Out << 'b';
|
||||
else
|
||||
mangleType(T->getElementType());
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleType(const ExtVectorType *T) {
|
||||
mangleType(static_cast<const VectorType*>(T));
|
||||
}
|
||||
|
|
|
@ -2514,6 +2514,16 @@ void MicrosoftCXXNameMangler::mangleType(const ExtVectorType *T,
|
|||
Qualifiers Quals, SourceRange Range) {
|
||||
mangleType(static_cast<const VectorType *>(T), Quals, Range);
|
||||
}
|
||||
|
||||
void MicrosoftCXXNameMangler::mangleType(const DependentVectorType *T,
|
||||
Qualifiers, SourceRange Range) {
|
||||
DiagnosticsEngine &Diags = Context.getDiags();
|
||||
unsigned DiagID = Diags.getCustomDiagID(
|
||||
DiagnosticsEngine::Error,
|
||||
"cannot mangle this dependent-sized vector type yet");
|
||||
Diags.Report(Range.getBegin(), DiagID) << Range;
|
||||
}
|
||||
|
||||
void MicrosoftCXXNameMangler::mangleType(const DependentSizedExtVectorType *T,
|
||||
Qualifiers, SourceRange Range) {
|
||||
DiagnosticsEngine &Diags = Context.getDiags();
|
||||
|
|
|
@ -177,6 +177,27 @@ void DependentSizedArrayType::Profile(llvm::FoldingSetNodeID &ID,
|
|||
E->Profile(ID, Context, true);
|
||||
}
|
||||
|
||||
DependentVectorType::DependentVectorType(
|
||||
const ASTContext &Context, QualType ElementType, QualType CanonType,
|
||||
Expr *SizeExpr, SourceLocation Loc, VectorType::VectorKind VecKind)
|
||||
: Type(DependentVector, CanonType, /*Dependent=*/true,
|
||||
/*InstantiationDependent=*/true,
|
||||
ElementType->isVariablyModifiedType(),
|
||||
ElementType->containsUnexpandedParameterPack() ||
|
||||
(SizeExpr && SizeExpr->containsUnexpandedParameterPack())),
|
||||
Context(Context), ElementType(ElementType), SizeExpr(SizeExpr), Loc(Loc) {
|
||||
VectorTypeBits.VecKind = VecKind;
|
||||
}
|
||||
|
||||
void DependentVectorType::Profile(llvm::FoldingSetNodeID &ID,
|
||||
const ASTContext &Context,
|
||||
QualType ElementType, const Expr *SizeExpr,
|
||||
VectorType::VectorKind VecKind) {
|
||||
ID.AddPointer(ElementType.getAsOpaquePtr());
|
||||
ID.AddInteger(VecKind);
|
||||
SizeExpr->Profile(ID, Context, true);
|
||||
}
|
||||
|
||||
DependentSizedExtVectorType::DependentSizedExtVectorType(const
|
||||
ASTContext &Context,
|
||||
QualType ElementType,
|
||||
|
@ -3783,6 +3804,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
|
|||
case Type::IncompleteArray:
|
||||
case Type::VariableArray:
|
||||
case Type::DependentSizedArray:
|
||||
case Type::DependentVector:
|
||||
case Type::DependentSizedExtVector:
|
||||
case Type::Vector:
|
||||
case Type::ExtVector:
|
||||
|
|
|
@ -242,6 +242,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
|
|||
case Type::RValueReference:
|
||||
case Type::MemberPointer:
|
||||
case Type::DependentAddressSpace:
|
||||
case Type::DependentVector:
|
||||
case Type::DependentSizedExtVector:
|
||||
case Type::Vector:
|
||||
case Type::ExtVector:
|
||||
|
@ -642,6 +643,54 @@ void TypePrinter::printVectorAfter(const VectorType *T, raw_ostream &OS) {
|
|||
printAfter(T->getElementType(), OS);
|
||||
}
|
||||
|
||||
void TypePrinter::printDependentVectorBefore(
|
||||
const DependentVectorType *T, raw_ostream &OS) {
|
||||
switch (T->getVectorKind()) {
|
||||
case VectorType::AltiVecPixel:
|
||||
OS << "__vector __pixel ";
|
||||
break;
|
||||
case VectorType::AltiVecBool:
|
||||
OS << "__vector __bool ";
|
||||
printBefore(T->getElementType(), OS);
|
||||
break;
|
||||
case VectorType::AltiVecVector:
|
||||
OS << "__vector ";
|
||||
printBefore(T->getElementType(), OS);
|
||||
break;
|
||||
case VectorType::NeonVector:
|
||||
OS << "__attribute__((neon_vector_type(";
|
||||
if (T->getSizeExpr())
|
||||
T->getSizeExpr()->printPretty(OS, nullptr, Policy);
|
||||
OS << "))) ";
|
||||
printBefore(T->getElementType(), OS);
|
||||
break;
|
||||
case VectorType::NeonPolyVector:
|
||||
OS << "__attribute__((neon_polyvector_type(";
|
||||
if (T->getSizeExpr())
|
||||
T->getSizeExpr()->printPretty(OS, nullptr, Policy);
|
||||
OS << "))) ";
|
||||
printBefore(T->getElementType(), OS);
|
||||
break;
|
||||
case VectorType::GenericVector: {
|
||||
// FIXME: We prefer to print the size directly here, but have no way
|
||||
// to get the size of the type.
|
||||
OS << "__attribute__((__vector_size__(";
|
||||
if (T->getSizeExpr())
|
||||
T->getSizeExpr()->printPretty(OS, nullptr, Policy);
|
||||
OS << " * sizeof(";
|
||||
print(T->getElementType(), OS, StringRef());
|
||||
OS << ")))) ";
|
||||
printBefore(T->getElementType(), OS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TypePrinter::printDependentVectorAfter(
|
||||
const DependentVectorType *T, raw_ostream &OS) {
|
||||
printAfter(T->getElementType(), OS);
|
||||
}
|
||||
|
||||
void TypePrinter::printExtVectorBefore(const ExtVectorType *T,
|
||||
raw_ostream &OS) {
|
||||
printBefore(T->getElementType(), OS);
|
||||
|
|
|
@ -734,7 +734,7 @@ NumericLiteralParser::NumericLiteralParser(StringRef TokSpelling,
|
|||
|
||||
if (!hadError && saw_fixed_point_suffix) {
|
||||
assert(isFract || isAccum);
|
||||
assert(radix == 16 || radix == 10);
|
||||
//assert(radix == 16 || radix == 10);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5341,6 +5341,11 @@ bool UnnamedLocalNoLinkageFinder::VisitVectorType(const VectorType* T) {
|
|||
return Visit(T->getElementType());
|
||||
}
|
||||
|
||||
bool UnnamedLocalNoLinkageFinder::VisitDependentVectorType(
|
||||
const DependentVectorType *T) {
|
||||
return Visit(T->getElementType());
|
||||
}
|
||||
|
||||
bool UnnamedLocalNoLinkageFinder::VisitExtVectorType(const ExtVectorType* T) {
|
||||
return Visit(T->getElementType());
|
||||
}
|
||||
|
|
|
@ -1870,6 +1870,54 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
|
|||
return Sema::TDK_NonDeducedMismatch;
|
||||
}
|
||||
|
||||
case Type::DependentVector: {
|
||||
const auto *VectorParam = cast<DependentVectorType>(Param);
|
||||
|
||||
if (const auto *VectorArg = dyn_cast<VectorType>(Arg)) {
|
||||
// Perform deduction on the element types.
|
||||
if (Sema::TemplateDeductionResult Result =
|
||||
DeduceTemplateArgumentsByTypeMatch(
|
||||
S, TemplateParams, VectorParam->getElementType(),
|
||||
VectorArg->getElementType(), Info, Deduced, TDF))
|
||||
return Result;
|
||||
|
||||
// Perform deduction on the vector size, if we can.
|
||||
NonTypeTemplateParmDecl *NTTP =
|
||||
getDeducedParameterFromExpr(Info, VectorParam->getSizeExpr());
|
||||
if (!NTTP)
|
||||
return Sema::TDK_Success;
|
||||
|
||||
llvm::APSInt ArgSize(S.Context.getTypeSize(S.Context.IntTy), false);
|
||||
ArgSize = VectorArg->getNumElements();
|
||||
// Note that we use the "array bound" rules here; just like in that
|
||||
// case, we don't have any particular type for the vector size, but
|
||||
// we can provide one if necessary.
|
||||
return DeduceNonTypeTemplateArgument(S, TemplateParams, NTTP, ArgSize,
|
||||
S.Context.UnsignedIntTy, true,
|
||||
Info, Deduced);
|
||||
}
|
||||
|
||||
if (const auto *VectorArg = dyn_cast<DependentVectorType>(Arg)) {
|
||||
// Perform deduction on the element types.
|
||||
if (Sema::TemplateDeductionResult Result =
|
||||
DeduceTemplateArgumentsByTypeMatch(
|
||||
S, TemplateParams, VectorParam->getElementType(),
|
||||
VectorArg->getElementType(), Info, Deduced, TDF))
|
||||
return Result;
|
||||
|
||||
// Perform deduction on the vector size, if we can.
|
||||
NonTypeTemplateParmDecl *NTTP = getDeducedParameterFromExpr(
|
||||
Info, VectorParam->getSizeExpr());
|
||||
if (!NTTP)
|
||||
return Sema::TDK_Success;
|
||||
|
||||
return DeduceNonTypeTemplateArgument(
|
||||
S, TemplateParams, NTTP, VectorArg->getSizeExpr(), Info, Deduced);
|
||||
}
|
||||
|
||||
return Sema::TDK_NonDeducedMismatch;
|
||||
}
|
||||
|
||||
// (clang extension)
|
||||
//
|
||||
// T __attribute__(((ext_vector_type(N))))
|
||||
|
@ -5264,6 +5312,14 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
|
|||
OnlyDeduced, Depth, Used);
|
||||
break;
|
||||
|
||||
case Type::DependentVector: {
|
||||
const auto *VecType = cast<DependentVectorType>(T);
|
||||
MarkUsedTemplateParameters(Ctx, VecType->getElementType(), OnlyDeduced,
|
||||
Depth, Used);
|
||||
MarkUsedTemplateParameters(Ctx, VecType->getSizeExpr(), OnlyDeduced, Depth,
|
||||
Used);
|
||||
break;
|
||||
}
|
||||
case Type::DependentSizedExtVector: {
|
||||
const DependentSizedExtVectorType *VecType
|
||||
= cast<DependentSizedExtVectorType>(T);
|
||||
|
|
|
@ -2243,6 +2243,58 @@ QualType Sema::BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM,
|
|||
return T;
|
||||
}
|
||||
|
||||
QualType Sema::BuildVectorType(QualType CurType, Expr *SizeExpr,
|
||||
SourceLocation AttrLoc) {
|
||||
// The base type must be integer (not Boolean or enumeration) or float, and
|
||||
// can't already be a vector.
|
||||
if (!CurType->isDependentType() &&
|
||||
(!CurType->isBuiltinType() || CurType->isBooleanType() ||
|
||||
(!CurType->isIntegerType() && !CurType->isRealFloatingType()))) {
|
||||
Diag(AttrLoc, diag::err_attribute_invalid_vector_type) << CurType;
|
||||
return QualType();
|
||||
}
|
||||
|
||||
if (SizeExpr->isTypeDependent() || SizeExpr->isValueDependent())
|
||||
return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc,
|
||||
VectorType::GenericVector);
|
||||
|
||||
llvm::APSInt VecSize(32);
|
||||
if (!SizeExpr->isIntegerConstantExpr(VecSize, Context)) {
|
||||
Diag(AttrLoc, diag::err_attribute_argument_type)
|
||||
<< "vector_size" << AANT_ArgumentIntegerConstant
|
||||
<< SizeExpr->getSourceRange();
|
||||
return QualType();
|
||||
}
|
||||
|
||||
if (CurType->isDependentType())
|
||||
return Context.getDependentVectorType(CurType, SizeExpr, AttrLoc,
|
||||
VectorType::GenericVector);
|
||||
|
||||
unsigned VectorSize = static_cast<unsigned>(VecSize.getZExtValue() * 8);
|
||||
unsigned TypeSize = static_cast<unsigned>(Context.getTypeSize(CurType));
|
||||
|
||||
if (VectorSize == 0) {
|
||||
Diag(AttrLoc, diag::err_attribute_zero_size) << SizeExpr->getSourceRange();
|
||||
return QualType();
|
||||
}
|
||||
|
||||
// vecSize is specified in bytes - convert to bits.
|
||||
if (VectorSize % TypeSize) {
|
||||
Diag(AttrLoc, diag::err_attribute_invalid_size)
|
||||
<< SizeExpr->getSourceRange();
|
||||
return QualType();
|
||||
}
|
||||
|
||||
if (VectorType::isVectorSizeTooLarge(VectorSize / TypeSize)) {
|
||||
Diag(AttrLoc, diag::err_attribute_size_too_large)
|
||||
<< SizeExpr->getSourceRange();
|
||||
return QualType();
|
||||
}
|
||||
|
||||
return Context.getVectorType(CurType, VectorSize / TypeSize,
|
||||
VectorType::GenericVector);
|
||||
}
|
||||
|
||||
/// Build an ext-vector type.
|
||||
///
|
||||
/// Run the required checks for the extended vector type.
|
||||
|
@ -6857,52 +6909,30 @@ static void HandleVectorSizeAttr(QualType &CurType, const ParsedAttr &Attr,
|
|||
Attr.setInvalid();
|
||||
return;
|
||||
}
|
||||
Expr *sizeExpr = static_cast<Expr *>(Attr.getArgAsExpr(0));
|
||||
llvm::APSInt vecSize(32);
|
||||
if (sizeExpr->isTypeDependent() || sizeExpr->isValueDependent() ||
|
||||
!sizeExpr->isIntegerConstantExpr(vecSize, S.Context)) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_argument_type)
|
||||
<< Attr.getName() << AANT_ArgumentIntegerConstant
|
||||
<< sizeExpr->getSourceRange();
|
||||
Attr.setInvalid();
|
||||
return;
|
||||
}
|
||||
// The base type must be integer (not Boolean or enumeration) or float, and
|
||||
// can't already be a vector.
|
||||
if (!CurType->isBuiltinType() || CurType->isBooleanType() ||
|
||||
(!CurType->isIntegerType() && !CurType->isRealFloatingType())) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
|
||||
Attr.setInvalid();
|
||||
return;
|
||||
}
|
||||
unsigned typeSize = static_cast<unsigned>(S.Context.getTypeSize(CurType));
|
||||
// vecSize is specified in bytes - convert to bits.
|
||||
unsigned vectorSize = static_cast<unsigned>(vecSize.getZExtValue() * 8);
|
||||
|
||||
// the vector size needs to be an integral multiple of the type size.
|
||||
if (vectorSize % typeSize) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_invalid_size)
|
||||
<< sizeExpr->getSourceRange();
|
||||
Attr.setInvalid();
|
||||
return;
|
||||
}
|
||||
if (VectorType::isVectorSizeTooLarge(vectorSize / typeSize)) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_size_too_large)
|
||||
<< sizeExpr->getSourceRange();
|
||||
Attr.setInvalid();
|
||||
return;
|
||||
}
|
||||
if (vectorSize == 0) {
|
||||
S.Diag(Attr.getLoc(), diag::err_attribute_zero_size)
|
||||
<< sizeExpr->getSourceRange();
|
||||
Attr.setInvalid();
|
||||
Expr *SizeExpr;
|
||||
// Special case where the argument is a template id.
|
||||
if (Attr.isArgIdent(0)) {
|
||||
CXXScopeSpec SS;
|
||||
SourceLocation TemplateKWLoc;
|
||||
UnqualifiedId Id;
|
||||
Id.setIdentifier(Attr.getArgAsIdent(0)->Ident, Attr.getLoc());
|
||||
|
||||
ExprResult Size = S.ActOnIdExpression(S.getCurScope(), SS, TemplateKWLoc,
|
||||
Id, false, false);
|
||||
|
||||
if (Size.isInvalid())
|
||||
return;
|
||||
SizeExpr = Size.get();
|
||||
} else {
|
||||
SizeExpr = Attr.getArgAsExpr(0);
|
||||
}
|
||||
|
||||
// Success! Instantiate the vector type, the number of elements is > 0, and
|
||||
// not required to be a power of 2, unlike GCC.
|
||||
CurType = S.Context.getVectorType(CurType, vectorSize/typeSize,
|
||||
VectorType::GenericVector);
|
||||
QualType T = S.BuildVectorType(CurType, SizeExpr, Attr.getLoc());
|
||||
if (!T.isNull())
|
||||
CurType = T;
|
||||
else
|
||||
Attr.setInvalid();
|
||||
}
|
||||
|
||||
/// Process the OpenCL-like ext_vector_type attribute when it occurs on
|
||||
|
|
|
@ -818,6 +818,15 @@ public:
|
|||
QualType RebuildVectorType(QualType ElementType, unsigned NumElements,
|
||||
VectorType::VectorKind VecKind);
|
||||
|
||||
/// Build a new potentially dependently-sized extended vector type
|
||||
/// given the element type and number of elements.
|
||||
///
|
||||
/// By default, performs semantic analysis when building the vector type.
|
||||
/// Subclasses may override this routine to provide different behavior.
|
||||
QualType RebuildDependentVectorType(QualType ElementType, Expr *SizeExpr,
|
||||
SourceLocation AttributeLoc,
|
||||
VectorType::VectorKind);
|
||||
|
||||
/// Build a new extended vector type given the element type and
|
||||
/// number of elements.
|
||||
///
|
||||
|
@ -4750,6 +4759,44 @@ TreeTransform<Derived>::TransformDependentSizedArrayType(TypeLocBuilder &TLB,
|
|||
return Result;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
QualType TreeTransform<Derived>::TransformDependentVectorType(
|
||||
TypeLocBuilder &TLB, DependentVectorTypeLoc TL) {
|
||||
const DependentVectorType *T = TL.getTypePtr();
|
||||
QualType ElementType = getDerived().TransformType(T->getElementType());
|
||||
if (ElementType.isNull())
|
||||
return QualType();
|
||||
|
||||
EnterExpressionEvaluationContext Unevaluated(
|
||||
SemaRef, Sema::ExpressionEvaluationContext::ConstantEvaluated);
|
||||
|
||||
ExprResult Size = getDerived().TransformExpr(T->getSizeExpr());
|
||||
Size = SemaRef.ActOnConstantExpression(Size);
|
||||
if (Size.isInvalid())
|
||||
return QualType();
|
||||
|
||||
QualType Result = TL.getType();
|
||||
if (getDerived().AlwaysRebuild() || ElementType != T->getElementType() ||
|
||||
Size.get() != T->getSizeExpr()) {
|
||||
Result = getDerived().RebuildDependentVectorType(
|
||||
ElementType, Size.get(), T->getAttributeLoc(), T->getVectorKind());
|
||||
if (Result.isNull())
|
||||
return QualType();
|
||||
}
|
||||
|
||||
// Result might be dependent or not.
|
||||
if (isa<DependentVectorType>(Result)) {
|
||||
DependentVectorTypeLoc NewTL =
|
||||
TLB.push<DependentVectorTypeLoc>(Result);
|
||||
NewTL.setNameLoc(TL.getNameLoc());
|
||||
} else {
|
||||
VectorTypeLoc NewTL = TLB.push<VectorTypeLoc>(Result);
|
||||
NewTL.setNameLoc(TL.getNameLoc());
|
||||
}
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
QualType TreeTransform<Derived>::TransformDependentSizedExtVectorType(
|
||||
TypeLocBuilder &TLB,
|
||||
|
@ -12381,6 +12428,13 @@ TreeTransform<Derived>::RebuildVectorType(QualType ElementType,
|
|||
return SemaRef.Context.getVectorType(ElementType, NumElements, VecKind);
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
QualType TreeTransform<Derived>::RebuildDependentVectorType(
|
||||
QualType ElementType, Expr *SizeExpr, SourceLocation AttributeLoc,
|
||||
VectorType::VectorKind VecKind) {
|
||||
return SemaRef.BuildVectorType(ElementType, SizeExpr, AttributeLoc);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
QualType TreeTransform<Derived>::RebuildExtVectorType(QualType ElementType,
|
||||
unsigned NumElements,
|
||||
|
|
|
@ -6369,6 +6369,17 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
|
|||
return Context.getPipeType(ElementType, ReadOnly);
|
||||
}
|
||||
|
||||
case TYPE_DEPENDENT_SIZED_VECTOR: {
|
||||
unsigned Idx = 0;
|
||||
QualType ElementType = readType(*Loc.F, Record, Idx);
|
||||
Expr *SizeExpr = ReadExpr(*Loc.F);
|
||||
SourceLocation AttrLoc = ReadSourceLocation(*Loc.F, Record, Idx);
|
||||
unsigned VecKind = Record[Idx];
|
||||
|
||||
return Context.getDependentVectorType(ElementType, SizeExpr, AttrLoc,
|
||||
(VectorType::VectorKind)VecKind);
|
||||
}
|
||||
|
||||
case TYPE_DEPENDENT_SIZED_EXT_VECTOR: {
|
||||
unsigned Idx = 0;
|
||||
|
||||
|
@ -6549,6 +6560,11 @@ void TypeLocReader::VisitVectorTypeLoc(VectorTypeLoc TL) {
|
|||
TL.setNameLoc(ReadSourceLocation());
|
||||
}
|
||||
|
||||
void TypeLocReader::VisitDependentVectorTypeLoc(
|
||||
DependentVectorTypeLoc TL) {
|
||||
TL.setNameLoc(ReadSourceLocation());
|
||||
}
|
||||
|
||||
void TypeLocReader::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
|
||||
TL.setNameLoc(ReadSourceLocation());
|
||||
}
|
||||
|
|
|
@ -455,6 +455,14 @@ ASTTypeWriter::VisitDependentSizedExtVectorType(
|
|||
Code = TYPE_DEPENDENT_SIZED_EXT_VECTOR;
|
||||
}
|
||||
|
||||
void ASTTypeWriter::VisitDependentVectorType(const DependentVectorType *T) {
|
||||
Record.AddTypeRef(T->getElementType());
|
||||
Record.AddStmt(const_cast<Expr*>(T->getSizeExpr()));
|
||||
Record.AddSourceLocation(T->getAttributeLoc());
|
||||
Record.push_back(T->getVectorKind());
|
||||
Code = TYPE_DEPENDENT_SIZED_VECTOR;
|
||||
}
|
||||
|
||||
void
|
||||
ASTTypeWriter::VisitDependentAddressSpaceType(
|
||||
const DependentAddressSpaceType *T) {
|
||||
|
@ -676,6 +684,11 @@ void TypeLocWriter::VisitVectorTypeLoc(VectorTypeLoc TL) {
|
|||
Record.AddSourceLocation(TL.getNameLoc());
|
||||
}
|
||||
|
||||
void TypeLocWriter::VisitDependentVectorTypeLoc(
|
||||
DependentVectorTypeLoc TL) {
|
||||
Record.AddSourceLocation(TL.getNameLoc());
|
||||
}
|
||||
|
||||
void TypeLocWriter::VisitExtVectorTypeLoc(ExtVectorTypeLoc TL) {
|
||||
Record.AddSourceLocation(TL.getNameLoc());
|
||||
}
|
||||
|
|
|
@ -291,3 +291,46 @@ const int &reference_to_vec_element = vi4(1).x;
|
|||
|
||||
// PR12649
|
||||
typedef bool bad __attribute__((__vector_size__(16))); // expected-error {{invalid vector element type 'bool'}}
|
||||
|
||||
namespace Templates {
|
||||
template <typename Elt, unsigned Size>
|
||||
struct TemplateVectorType {
|
||||
typedef Elt __attribute__((__vector_size__(Size))) type;
|
||||
};
|
||||
|
||||
template <int N, typename T>
|
||||
struct PR15730 {
|
||||
typedef T __attribute__((vector_size(N * sizeof(T)))) type;
|
||||
typedef T __attribute__((vector_size(8192))) type2;
|
||||
typedef T __attribute__((vector_size(3))) type3;
|
||||
};
|
||||
|
||||
void Init() {
|
||||
const TemplateVectorType<float, 32>::type Works = {};
|
||||
const TemplateVectorType<int, 32>::type Works2 = {};
|
||||
// expected-error@298 {{invalid vector element type 'bool'}}
|
||||
// expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType<bool, 32>' requested here}}
|
||||
const TemplateVectorType<bool, 32>::type NoBool;
|
||||
// expected-error@298 {{invalid vector element type 'int __attribute__((ext_vector_type(4)))' (vector of 4 'int' values)}}
|
||||
// expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType<int __attribute__((ext_vector_type(4))), 32>' requested here}}
|
||||
const TemplateVectorType<vi4, 32>::type NoComplex;
|
||||
// expected-error@298 {{vector size not an integral multiple of component size}}
|
||||
// expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType<int, 33>' requested here}}
|
||||
const TemplateVectorType<int, 33>::type BadSize;
|
||||
// expected-error@298 {{vector size too large}}
|
||||
// expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType<int, 8192>' requested here}}
|
||||
const TemplateVectorType<int, 8192>::type TooLarge;
|
||||
// expected-error@298 {{zero vector size}}
|
||||
// expected-note@+1 {{in instantiation of template class 'Templates::TemplateVectorType<int, 0>' requested here}}
|
||||
const TemplateVectorType<int, 0>::type Zero;
|
||||
|
||||
// expected-error@304 {{vector size too large}}
|
||||
// expected-error@305 {{vector size not an integral multiple of component size}}
|
||||
// expected-note@+1 {{in instantiation of template class 'Templates::PR15730<8, int>' requested here}}
|
||||
const PR15730<8, int>::type PR15730_1 = {};
|
||||
// expected-error@304 {{vector size too large}}
|
||||
// expected-note@+1 {{in instantiation of template class 'Templates::PR15730<8, char>' requested here}}
|
||||
const PR15730<8, char>::type2 PR15730_2 = {};
|
||||
}
|
||||
|
||||
} // namespace Templates
|
||||
|
|
|
@ -1772,6 +1772,7 @@ DEFAULT_TYPELOC_IMPL(IncompleteArray, ArrayType)
|
|||
DEFAULT_TYPELOC_IMPL(VariableArray, ArrayType)
|
||||
DEFAULT_TYPELOC_IMPL(DependentSizedArray, ArrayType)
|
||||
DEFAULT_TYPELOC_IMPL(DependentAddressSpace, Type)
|
||||
DEFAULT_TYPELOC_IMPL(DependentVector, Type)
|
||||
DEFAULT_TYPELOC_IMPL(DependentSizedExtVector, Type)
|
||||
DEFAULT_TYPELOC_IMPL(Vector, Type)
|
||||
DEFAULT_TYPELOC_IMPL(ExtVector, VectorType)
|
||||
|
|
Loading…
Reference in New Issue