зеркало из https://github.com/microsoft/clang-1.git
Add support for the OpenCL attribute 'vec_type_hint'.
Patch by Murat Bolat! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@176686 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Родитель
ee2d5fd7a3
Коммит
37453b9580
|
@ -720,8 +720,9 @@ def VectorSize : Attr {
|
|||
let ASTNode = 0;
|
||||
}
|
||||
|
||||
def VecTypeHint : IgnoredAttr {
|
||||
def VecTypeHint : InheritableAttr {
|
||||
let Spellings = [GNU<"vec_type_hint">];
|
||||
let Args = [TypeArgument<"TypeHint">, SourceLocArgument<"TypeLoc">];
|
||||
}
|
||||
|
||||
def Visibility : InheritableAttr {
|
||||
|
|
|
@ -1644,6 +1644,8 @@ def err_attribute_too_few_arguments : Error<
|
|||
"attribute takes at least %0 argument%s0">;
|
||||
def err_attribute_missing_parameter_name : Error<
|
||||
"attribute requires unquoted parameter">;
|
||||
def err_attribute_requires_type_parameter : Error<
|
||||
"%0 attribute requires type parameter">;
|
||||
def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">;
|
||||
def err_attribute_bad_neon_vector_size : Error<
|
||||
"Neon vector size must be 64 or 128 bits">;
|
||||
|
@ -1672,6 +1674,8 @@ def err_attribute_argument_outof_range : Error<
|
|||
def err_init_priority_object_attr : Error<
|
||||
"can only use 'init_priority' attribute on file-scope definitions "
|
||||
"of objects of class type">;
|
||||
def err_attribute_argument_vec_type_hint : Error<
|
||||
"invalid attribute argument %0 - expecting a vector or vectorizable scalar type">;
|
||||
def err_attribute_argument_n_not_int : Error<
|
||||
"'%0' attribute requires parameter %1 to be an integer constant">;
|
||||
def err_attribute_argument_n_not_string : Error<
|
||||
|
|
|
@ -144,6 +144,14 @@ private:
|
|||
return *reinterpret_cast<const TypeTagForDatatypeData *>(this + 1);
|
||||
}
|
||||
|
||||
ParsedType &getTypeBuffer() {
|
||||
return *reinterpret_cast<ParsedType *>(this + 1);
|
||||
}
|
||||
|
||||
const ParsedType &getTypeBuffer() const {
|
||||
return *reinterpret_cast<const ParsedType *>(this + 1);
|
||||
}
|
||||
|
||||
AttributeList(const AttributeList &) LLVM_DELETED_FUNCTION;
|
||||
void operator=(const AttributeList &) LLVM_DELETED_FUNCTION;
|
||||
void operator delete(void *) LLVM_DELETED_FUNCTION;
|
||||
|
@ -208,6 +216,20 @@ private:
|
|||
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
|
||||
}
|
||||
|
||||
/// Constructor for attributes with a single type argument.
|
||||
AttributeList(IdentifierInfo *attrName, SourceRange attrRange,
|
||||
IdentifierInfo *scopeName, SourceLocation scopeLoc,
|
||||
IdentifierInfo *parmName, SourceLocation parmLoc,
|
||||
ParsedType typeArg, Syntax syntaxUsed)
|
||||
: AttrName(attrName), ScopeName(scopeName), ParmName(parmName),
|
||||
AttrRange(attrRange), ScopeLoc(scopeLoc), ParmLoc(parmLoc),
|
||||
EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false),
|
||||
UsedAsTypeAttr(false), IsAvailability(false),
|
||||
IsTypeTagForDatatype(false), NextInPosition(0), NextInPool(0) {
|
||||
new (&getTypeBuffer()) ParsedType(typeArg);
|
||||
AttrKind = getKind(getName(), getScopeName(), syntaxUsed);
|
||||
}
|
||||
|
||||
friend class AttributePool;
|
||||
friend class AttributeFactory;
|
||||
|
||||
|
@ -352,6 +374,11 @@ public:
|
|||
return getTypeTagForDatatypeDataSlot().MustBeNull;
|
||||
}
|
||||
|
||||
const ParsedType &getTypeArg() const {
|
||||
assert(getKind() == AT_VecTypeHint && "Not a type attribute");
|
||||
return getTypeBuffer();
|
||||
}
|
||||
|
||||
/// \brief Get an index into the attribute spelling list
|
||||
/// defined in Attr.td. This index is used by an attribute
|
||||
/// to pretty print itself.
|
||||
|
@ -509,6 +536,18 @@ public:
|
|||
matchingCType, layoutCompatible,
|
||||
mustBeNull, syntax));
|
||||
}
|
||||
|
||||
AttributeList *createTypeAttribute(
|
||||
IdentifierInfo *attrName, SourceRange attrRange,
|
||||
IdentifierInfo *scopeName, SourceLocation scopeLoc,
|
||||
IdentifierInfo *parmName, SourceLocation parmLoc,
|
||||
ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
|
||||
void *memory = allocate(sizeof(AttributeList) + sizeof(void *));
|
||||
return add(new (memory) AttributeList(attrName, attrRange,
|
||||
scopeName, scopeLoc,
|
||||
parmName, parmLoc,
|
||||
typeArg, syntaxUsed));
|
||||
}
|
||||
};
|
||||
|
||||
/// addAttributeLists - Add two AttributeLists together
|
||||
|
@ -651,6 +690,19 @@ public:
|
|||
return attr;
|
||||
}
|
||||
|
||||
/// Add an attribute with a single type argument.
|
||||
AttributeList *
|
||||
addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange,
|
||||
IdentifierInfo *scopeName, SourceLocation scopeLoc,
|
||||
IdentifierInfo *parmName, SourceLocation parmLoc,
|
||||
ParsedType typeArg, AttributeList::Syntax syntaxUsed) {
|
||||
AttributeList *attr =
|
||||
pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc,
|
||||
parmName, parmLoc, typeArg, syntaxUsed);
|
||||
add(attr);
|
||||
return attr;
|
||||
}
|
||||
|
||||
AttributeList *addNewInteger(ASTContext &C, IdentifierInfo *name,
|
||||
SourceLocation loc, int arg) {
|
||||
AttributeList *attr =
|
||||
|
|
|
@ -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[] = {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
// RUN: %clang_cc1 -emit-llvm -O0 -o - %s | FileCheck %s
|
||||
|
||||
kernel __attribute__((reqd_work_group_size(1,2,4))) void kernel1(int a) {}
|
||||
typedef unsigned int uint4 __attribute__((ext_vector_type(4)));
|
||||
|
||||
kernel __attribute__((work_group_size_hint(8,16,32))) void kernel2(int a) {}
|
||||
kernel __attribute__((vec_type_hint(int))) __attribute__((reqd_work_group_size(1,2,4))) void kernel1(int a) {}
|
||||
|
||||
kernel __attribute__((vec_type_hint(uint4))) __attribute__((work_group_size_hint(8,16,32))) void kernel2(int a) {}
|
||||
|
||||
// CHECK: opencl.kernels = !{[[MDNODE0:![0-9]+]], [[MDNODE3:![0-9]+]]}
|
||||
|
||||
// CHECK: [[MDNODE0]] = metadata !{void (i32)* @kernel1, metadata [[MDNODE2:![0-9]+]]}
|
||||
// CHECK: [[MDNODE0]] = metadata !{void (i32)* @kernel1, metadata [[MDNODE1:![0-9]+]], metadata [[MDNODE2:![0-9]+]]}
|
||||
// CHECK: [[MDNODE1]] = metadata !{metadata !"vec_type_hint", i32 undef, i32 1}
|
||||
// CHECK: [[MDNODE2]] = metadata !{metadata !"reqd_work_group_size", i32 1, i32 2, i32 4}
|
||||
// CHECK: [[MDNODE3]] = metadata !{void (i32)* @kernel2, metadata [[MDNODE5:![0-9]+]]}
|
||||
// CHECK: [[MDNODE3]] = metadata !{void (i32)* @kernel2, metadata [[MDNODE4:![0-9]+]], metadata [[MDNODE5:![0-9]+]]}
|
||||
// CHECK: [[MDNODE4]] = metadata !{metadata !"vec_type_hint", <4 x i32> undef, i32 0}
|
||||
// CHECK: [[MDNODE5]] = metadata !{metadata !"work_group_size_hint", i32 8, i32 16, i32 32}
|
||||
|
|
Загрузка…
Ссылка в новой задаче