diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2015-11-19 10:13:11 +0000 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2015-11-19 10:13:11 +0000 |
commit | f278eb10b7dad7e081a29ff6d7f0f21fd3f37533 (patch) | |
tree | 3a755373078e8393c1bc8fa2d753cf9e6e1c5c32 /clang/lib/Sema/SemaDeclAttr.cpp | |
parent | 0ecdbe7d6b543256f9225355cc3c315314a2fd57 (diff) | |
download | bcm5719-llvm-f278eb10b7dad7e081a29ff6d7f0f21fd3f37533.tar.gz bcm5719-llvm-f278eb10b7dad7e081a29ff6d7f0f21fd3f37533.zip |
PR10235: support for vector mode attributes + warning, by Dmitry Polukhin.
Add support for vector mode attributes like "attribute((mode(V4SF)))". Also add warning about deprecated vector modes like GCC does.
Differential Revision: http://reviews.llvm.org/D14744
llvm-svn: 253551
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 102 |
1 files changed, 72 insertions, 30 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 433d3ba098e..c00914663aa 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -3234,38 +3234,31 @@ bool Sema::checkMSInheritanceAttrOnDefinition( return true; } -/// handleModeAttr - This attribute modifies the width of a decl with primitive -/// type. -/// -/// Despite what would be logical, the mode attribute is a decl attribute, not a -/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be -/// HImode, not an intermediate pointer. -static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { - // This attribute isn't documented, but glibc uses it. It changes - // the width of an int or unsigned int to the specified size. - if (!Attr.isArgIdent(0)) { - S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName() - << AANT_ArgumentIdentifier; - return; - } - - IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident; - StringRef Str = Name->getName(); - - normalizeName(Str); - - unsigned DestWidth = 0; - bool IntegerMode = true; - bool ComplexMode = false; +/// parseModeAttrArg - Parses attribute mode string and returns parsed type +/// attribute. +static void parseModeAttrArg(Sema &S, StringRef Str, unsigned &DestWidth, + bool &IntegerMode, bool &ComplexMode) { switch (Str.size()) { case 2: switch (Str[0]) { - case 'Q': DestWidth = 8; break; - case 'H': DestWidth = 16; break; - case 'S': DestWidth = 32; break; - case 'D': DestWidth = 64; break; - case 'X': DestWidth = 96; break; - case 'T': DestWidth = 128; break; + case 'Q': + DestWidth = 8; + break; + case 'H': + DestWidth = 16; + break; + case 'S': + DestWidth = 32; + break; + case 'D': + DestWidth = 64; + break; + case 'X': + DestWidth = 96; + break; + case 'T': + DestWidth = 128; + break; } if (Str[1] == 'F') { IntegerMode = false; @@ -3293,6 +3286,52 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { DestWidth = S.Context.getTargetInfo().getUnwindWordWidth(); break; } +} + +/// handleModeAttr - This attribute modifies the width of a decl with primitive +/// type. +/// +/// Despite what would be logical, the mode attribute is a decl attribute, not a +/// type attribute: 'int ** __attribute((mode(HI))) *G;' tries to make 'G' be +/// HImode, not an intermediate pointer. +static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { + // This attribute isn't documented, but glibc uses it. It changes + // the width of an int or unsigned int to the specified size. + if (!Attr.isArgIdent(0)) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName() + << AANT_ArgumentIdentifier; + return; + } + + IdentifierInfo *Name = Attr.getArgAsIdent(0)->Ident; + StringRef Str = Name->getName(); + + normalizeName(Str); + + unsigned DestWidth = 0; + bool IntegerMode = true; + bool ComplexMode = false; + llvm::APInt VectorSize(64, 0); + if (Str.size() >= 4 && Str[0] == 'V') { + // Minimal length of vector mode is 4: 'V' + NUMBER(>=1) + TYPE(>=2). + size_t StrSize = Str.size(); + size_t VectorStringLength = 0; + while ((VectorStringLength + 1) < StrSize && + isdigit(Str[VectorStringLength + 1])) + ++VectorStringLength; + if (VectorStringLength && + !Str.substr(1, VectorStringLength).getAsInteger(10, VectorSize) && + VectorSize.isPowerOf2()) { + parseModeAttrArg(S, Str.substr(VectorStringLength + 1), DestWidth, + IntegerMode, ComplexMode); + S.Diag(Attr.getLoc(), diag::warn_vector_mode_deprecated); + } else { + VectorSize = 0; + } + } + + if (!VectorSize) + parseModeAttrArg(S, Str, DestWidth, IntegerMode, ComplexMode); QualType OldTy; if (TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) @@ -3351,7 +3390,10 @@ static void handleModeAttr(Sema &S, Decl *D, const AttributeList &Attr) { } QualType NewTy = NewElemTy; - if (const VectorType *OldVT = OldTy->getAs<VectorType>()) { + if (VectorSize.getBoolValue()) { + NewTy = S.Context.getVectorType(NewTy, VectorSize.getZExtValue(), + VectorType::GenericVector); + } else if (const VectorType *OldVT = OldTy->getAs<VectorType>()) { // Complex machine mode does not support base vector types. if (ComplexMode) { S.Diag(Attr.getLoc(), diag::err_complex_mode_vector_type); |