summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.cpp17
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h3
-rw-r--r--clang/lib/Parse/ParseDecl.cpp47
-rw-r--r--clang/lib/Sema/SemaDeclAttr.cpp33
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;
OpenPOWER on IntegriCloud