diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 17 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 3 | ||||
-rw-r--r-- | clang/lib/Parse/ParseDecl.cpp | 47 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 33 |
4 files changed, 90 insertions, 10 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 5e8bce974ba..bd4c98e35b1 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -323,6 +323,23 @@ void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD, if (CGM.getCodeGenOpts().EmitOpenCLArgMetadata) GenOpenCLArgMetadata(FD, Fn, CGM, Context, kernelMDArgs); + if (FD->hasAttr<VecTypeHintAttr>()) { + VecTypeHintAttr *attr = FD->getAttr<VecTypeHintAttr>(); + QualType hintQTy = attr->getTypeHint(); + const ExtVectorType *hintEltQTy = hintQTy->getAs<ExtVectorType>(); + bool isSignedInteger = + hintQTy->isSignedIntegerType() || + (hintEltQTy && hintEltQTy->getElementType()->isSignedIntegerType()); + llvm::Value *attrMDArgs[] = { + llvm::MDString::get(Context, "vec_type_hint"), + llvm::UndefValue::get(CGM.getTypes().ConvertType(attr->getTypeHint())), + llvm::ConstantInt::get( + llvm::IntegerType::get(Context, 32), + llvm::APInt(32, (uint64_t)(isSignedInteger ? 1 : 0))) + }; + kernelMDArgs.push_back(llvm::MDNode::get(Context, attrMDArgs)); + } + if (FD->hasAttr<WorkGroupSizeHintAttr>()) { WorkGroupSizeHintAttr *attr = FD->getAttr<WorkGroupSizeHintAttr>(); llvm::Value *attrMDArgs[] = { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 2be8dcc4a65..0155f033e6f 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1214,6 +1214,9 @@ private: /// Add a kernel metadata node to the named metadata node 'opencl.kernels'. /// In the kernel metadata node, reference the kernel function and metadata /// nodes for its optional attribute qualifiers (OpenCL 1.1 6.7.2): + /// - A node for the vec_type_hint(<type>) qualifier contains string + /// "vec_type_hint", an undefined value of the <type> data type, + /// and a Boolean that is true if the <type> is integer and signed. /// - A node for the work_group_size_hint(X,Y,Z) qualifier contains string /// "work_group_size_hint", and three 32-bit integers X, Y and Z. /// - A node for the reqd_work_group_size(X,Y,Z) qualifier contains string diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 6ab1540134a..bf5c078b714 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -214,6 +214,10 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, SourceLocation ParmLoc; bool BuiltinType = false; + TypeResult T; + SourceRange TypeRange; + bool TypeParsed = false; + switch (Tok.getKind()) { case tok::kw_char: case tok::kw_wchar_t: @@ -232,12 +236,17 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, case tok::kw_void: case tok::kw_typeof: // __attribute__(( vec_type_hint(char) )) - // FIXME: Don't just discard the builtin type token. - ConsumeToken(); BuiltinType = true; + T = ParseTypeName(&TypeRange); + TypeParsed = true; break; case tok::identifier: + if (AttrName->isStr("vec_type_hint")) { + T = ParseTypeName(&TypeRange); + TypeParsed = true; + break; + } ParmName = Tok.getIdentifierInfo(); ParmLoc = ConsumeToken(); break; @@ -247,8 +256,10 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, } ExprVector ArgExprs; + bool isInvalid = false; + bool isParmType = false; - if (!BuiltinType && + if (!BuiltinType && !AttrName->isStr("vec_type_hint") && (ParmLoc.isValid() ? Tok.is(tok::comma) : Tok.isNot(tok::r_paren))) { // Eat the comma. if (ParmLoc.isValid()) @@ -283,17 +294,33 @@ void Parser::ParseGNUAttributeArgs(IdentifierInfo *AttrName, Diag(Tok, diag::err_iboutletcollection_with_protocol); SkipUntil(tok::r_paren, false, true); // skip until ')' } + } else if (AttrName->isStr("vec_type_hint")) { + if (T.get() && !T.isInvalid()) + isParmType = true; + else { + if (Tok.is(tok::identifier)) + ConsumeToken(); + if (TypeParsed) + isInvalid = true; + } } SourceLocation RParen = Tok.getLocation(); - if (!ExpectAndConsume(tok::r_paren, diag::err_expected_rparen)) { + if (!ExpectAndConsume(tok::r_paren, diag::err_expected_rparen) && + !isInvalid) { SourceLocation AttrLoc = ScopeLoc.isValid() ? ScopeLoc : AttrNameLoc; - AttributeList *attr = - Attrs.addNew(AttrName, SourceRange(AttrLoc, RParen), - ScopeName, ScopeLoc, ParmName, ParmLoc, - ArgExprs.data(), ArgExprs.size(), Syntax); - if (BuiltinType && attr->getKind() == AttributeList::AT_IBOutletCollection) - Diag(Tok, diag::err_iboutletcollection_builtintype); + if (isParmType) { + QualType ParmType = Sema::GetTypeFromParser(T.get()); + Attrs.addNewTypeAttr(AttrName, SourceRange(AttrLoc, RParen), ScopeName, + ScopeLoc, ParmName, ParmLoc, T.get(), Syntax); + } else { + AttributeList *attr = Attrs.addNew( + AttrName, SourceRange(AttrLoc, RParen), ScopeName, ScopeLoc, ParmName, + ParmLoc, ArgExprs.data(), ArgExprs.size(), Syntax); + if (BuiltinType && + attr->getKind() == AttributeList::AT_IBOutletCollection) + Diag(Tok, diag::err_iboutletcollection_builtintype); + } } } diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 2778d6e6484..c9ccf80191e 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2769,6 +2769,36 @@ static void handleWorkGroupSize(Sema &S, Decl *D, Attr.getAttributeSpellingListIndex())); } +static void handleVecTypeHint(Sema &S, Decl *D, const AttributeList &Attr) { + assert(Attr.getKind() == AttributeList::AT_VecTypeHint); + + // Attribute has 1 argument. + if (!checkAttributeNumArgs(S, Attr, 1)) + return; + + QualType ParmType = S.GetTypeFromParser(Attr.getTypeArg()); + + if (!ParmType->isExtVectorType() && !ParmType->isFloatingType() && + (ParmType->isBooleanType() || + !ParmType->isIntegralType(S.getASTContext()))) { + S.Diag(Attr.getLoc(), diag::err_attribute_argument_vec_type_hint) + << ParmType; + return; + } + + if (Attr.getKind() == AttributeList::AT_VecTypeHint && + D->hasAttr<VecTypeHintAttr>()) { + VecTypeHintAttr *A = D->getAttr<VecTypeHintAttr>(); + if (A->getTypeHint() != ParmType) { + S.Diag(Attr.getLoc(), diag::warn_duplicate_attribute) << Attr.getName(); + return; + } + } + + D->addAttr(::new (S.Context) VecTypeHintAttr(Attr.getLoc(), S.Context, + ParmType, Attr.getLoc())); +} + SectionAttr *Sema::mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name, unsigned AttrSpellingListIndex) { @@ -4750,6 +4780,9 @@ static void ProcessInheritableDeclAttr(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_ReqdWorkGroupSize: handleWorkGroupSize(S, D, Attr); break; + case AttributeList::AT_VecTypeHint: + handleVecTypeHint(S, D, Attr); break; + case AttributeList::AT_InitPriority: handleInitPriorityAttr(S, D, Attr); break; |