mirror of https://github.com/microsoft/clang.git
[OpenCL] Pipe type support
Summary: Support for OpenCL 2.0 pipe type. This is a bug-fix version for bader's patch reviews.llvm.org/D14441 Reviewers: pekka.jaaskelainen, Anastasia Subscribers: bader, Anastasia, cfe-commits Differential Revision: http://reviews.llvm.org/D15603 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@257254 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
1539947508
commit
97f9428a0d
|
@ -131,6 +131,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
|||
mutable llvm::FoldingSet<AutoType> AutoTypes;
|
||||
mutable llvm::FoldingSet<AtomicType> AtomicTypes;
|
||||
llvm::FoldingSet<AttributedType> AttributedTypes;
|
||||
mutable llvm::FoldingSet<PipeType> PipeTypes;
|
||||
|
||||
mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
|
||||
mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
|
||||
|
@ -1079,6 +1080,9 @@ public:
|
|||
/// blocks.
|
||||
QualType getBlockDescriptorType() const;
|
||||
|
||||
/// \brief Return pipe type for the specified type.
|
||||
QualType getPipeType(QualType T) const;
|
||||
|
||||
/// Gets the struct used to keep track of the extended descriptor for
|
||||
/// pointer to blocks.
|
||||
QualType getBlockDescriptorExtendedType() const;
|
||||
|
|
|
@ -978,6 +978,8 @@ DEF_TRAVERSE_TYPE(ObjCObjectPointerType,
|
|||
|
||||
DEF_TRAVERSE_TYPE(AtomicType, { TRY_TO(TraverseType(T->getValueType())); })
|
||||
|
||||
DEF_TRAVERSE_TYPE(PipeType, { TRY_TO(TraverseType(T->getElementType())); })
|
||||
|
||||
#undef DEF_TRAVERSE_TYPE
|
||||
|
||||
// ----------------- TypeLoc traversal -----------------
|
||||
|
@ -1206,6 +1208,8 @@ DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType,
|
|||
|
||||
DEF_TRAVERSE_TYPELOC(AtomicType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
|
||||
|
||||
DEF_TRAVERSE_TYPELOC(PipeType, { TRY_TO(TraverseTypeLoc(TL.getValueLoc())); })
|
||||
|
||||
#undef DEF_TRAVERSE_TYPELOC
|
||||
|
||||
// ----------------- Decl traversal -----------------
|
||||
|
|
|
@ -1721,6 +1721,7 @@ public:
|
|||
bool isNDRangeT() const; // OpenCL ndrange_t
|
||||
bool isReserveIDT() const; // OpenCL reserve_id_t
|
||||
|
||||
bool isPipeType() const; // OpenCL pipe type
|
||||
bool isOpenCLSpecificType() const; // Any OpenCL specific type
|
||||
|
||||
/// Determines if this type, which must satisfy
|
||||
|
@ -5015,6 +5016,41 @@ class AtomicType : public Type, public llvm::FoldingSetNode {
|
|||
}
|
||||
};
|
||||
|
||||
/// PipeType - OpenCL20.
|
||||
class PipeType : public Type, public llvm::FoldingSetNode {
|
||||
QualType ElementType;
|
||||
|
||||
PipeType(QualType elemType, QualType CanonicalPtr) :
|
||||
Type(Pipe, CanonicalPtr, elemType->isDependentType(),
|
||||
elemType->isInstantiationDependentType(),
|
||||
elemType->isVariablyModifiedType(),
|
||||
elemType->containsUnexpandedParameterPack()),
|
||||
ElementType(elemType) {}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
|
||||
public:
|
||||
|
||||
QualType getElementType() const { return ElementType; }
|
||||
|
||||
bool isSugared() const { return false; }
|
||||
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getElementType());
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, QualType T) {
|
||||
ID.AddPointer(T.getAsOpaquePtr());
|
||||
}
|
||||
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
return T->getTypeClass() == Pipe;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/// A qualifier set is used to build a set of qualifiers.
|
||||
class QualifierCollector : public Qualifiers {
|
||||
public:
|
||||
|
@ -5461,9 +5497,13 @@ inline bool Type::isImageType() const {
|
|||
isImage1dBufferT();
|
||||
}
|
||||
|
||||
inline bool Type::isPipeType() const {
|
||||
return isa<PipeType>(CanonicalType);
|
||||
}
|
||||
|
||||
inline bool Type::isOpenCLSpecificType() const {
|
||||
return isSamplerT() || isEventT() || isImageType() || isClkEventT() ||
|
||||
isQueueT() || isNDRangeT() || isReserveIDT();
|
||||
isQueueT() || isNDRangeT() || isReserveIDT() || isPipeType();
|
||||
}
|
||||
|
||||
inline bool Type::isTemplateTypeParmType() const {
|
||||
|
|
|
@ -2033,7 +2033,26 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
struct PipeTypeLocInfo {
|
||||
SourceLocation KWLoc;
|
||||
};
|
||||
|
||||
class PipeTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, PipeTypeLoc, PipeType,
|
||||
PipeTypeLocInfo> {
|
||||
public:
|
||||
TypeLoc getValueLoc() const { return this->getInnerTypeLoc(); }
|
||||
|
||||
SourceRange getLocalSourceRange() const { return SourceRange(getKWLoc()); }
|
||||
|
||||
SourceLocation getKWLoc() const { return this->getLocalData()->KWLoc; }
|
||||
void setKWLoc(SourceLocation Loc) { this->getLocalData()->KWLoc = Loc; }
|
||||
|
||||
void initializeLocal(ASTContext &Context, SourceLocation Loc) {
|
||||
setKWLoc(Loc);
|
||||
}
|
||||
|
||||
QualType getInnerType() const { return this->getTypePtr()->getElementType(); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -104,6 +104,7 @@ NON_CANONICAL_UNLESS_DEPENDENT_TYPE(PackExpansion, Type)
|
|||
TYPE(ObjCObject, Type)
|
||||
TYPE(ObjCInterface, ObjCObjectType)
|
||||
TYPE(ObjCObjectPointer, Type)
|
||||
TYPE(Pipe, Type)
|
||||
TYPE(Atomic, Type)
|
||||
|
||||
#ifdef LAST_TYPE
|
||||
|
|
|
@ -7642,6 +7642,10 @@ def err_wrong_sampler_addressspace: Error<
|
|||
"sampler type cannot be used with the __local and __global address space qualifiers">;
|
||||
def err_opencl_global_invalid_addr_space : Error<
|
||||
"program scope variable must reside in %0 address space">;
|
||||
def err_missing_actual_pipe_type : Error<
|
||||
"missing actual type specifier for pipe">;
|
||||
def err_reference_pipe_type : Error <
|
||||
"pipes packet types cannot be of reference type">;
|
||||
def err_opencl_no_main : Error<"%select{function|kernel}0 cannot be called 'main'">;
|
||||
def err_opencl_kernel_attr :
|
||||
Error<"attribute %0 can only be applied to a kernel function">;
|
||||
|
|
|
@ -36,6 +36,11 @@ namespace clang {
|
|||
TSS_unsigned
|
||||
};
|
||||
|
||||
enum TypeSpecifiersPipe {
|
||||
TSP_unspecified,
|
||||
TSP_pipe
|
||||
};
|
||||
|
||||
/// \brief Specifies the kind of type.
|
||||
enum TypeSpecifierType {
|
||||
TST_unspecified,
|
||||
|
|
|
@ -519,6 +519,8 @@ KEYWORD(vec_step , KEYOPENCL|KEYALTIVEC|KEYZVECTOR)
|
|||
// OpenMP Type Traits
|
||||
KEYWORD(__builtin_omp_required_simd_align, KEYALL)
|
||||
|
||||
KEYWORD(pipe , KEYOPENCL)
|
||||
|
||||
// Borland Extensions.
|
||||
KEYWORD(__pascal , KEYALL)
|
||||
|
||||
|
|
|
@ -337,6 +337,7 @@ private:
|
|||
unsigned TypeAltiVecPixel : 1;
|
||||
unsigned TypeAltiVecBool : 1;
|
||||
unsigned TypeSpecOwned : 1;
|
||||
unsigned TypeSpecPipe : 1;
|
||||
|
||||
// type-qualifiers
|
||||
unsigned TypeQualifiers : 4; // Bitwise OR of TQ.
|
||||
|
@ -385,6 +386,7 @@ private:
|
|||
SourceLocation FS_inlineLoc, FS_virtualLoc, FS_explicitLoc, FS_noreturnLoc;
|
||||
SourceLocation FS_forceinlineLoc;
|
||||
SourceLocation FriendLoc, ModulePrivateLoc, ConstexprLoc, ConceptLoc;
|
||||
SourceLocation TQ_pipeLoc;
|
||||
|
||||
WrittenBuiltinSpecs writtenBS;
|
||||
void SaveWrittenBuiltinSpecs();
|
||||
|
@ -420,6 +422,7 @@ public:
|
|||
TypeAltiVecPixel(false),
|
||||
TypeAltiVecBool(false),
|
||||
TypeSpecOwned(false),
|
||||
TypeSpecPipe(false),
|
||||
TypeQualifiers(TQ_unspecified),
|
||||
FS_inline_specified(false),
|
||||
FS_forceinline_specified(false),
|
||||
|
@ -473,6 +476,7 @@ public:
|
|||
bool isTypeAltiVecBool() const { return TypeAltiVecBool; }
|
||||
bool isTypeSpecOwned() const { return TypeSpecOwned; }
|
||||
bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); }
|
||||
bool isTypeSpecPipe() const { return TypeSpecPipe; }
|
||||
|
||||
ParsedType getRepAsType() const {
|
||||
assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type");
|
||||
|
@ -532,6 +536,7 @@ public:
|
|||
SourceLocation getRestrictSpecLoc() const { return TQ_restrictLoc; }
|
||||
SourceLocation getVolatileSpecLoc() const { return TQ_volatileLoc; }
|
||||
SourceLocation getAtomicSpecLoc() const { return TQ_atomicLoc; }
|
||||
SourceLocation getPipeLoc() const { return TQ_pipeLoc; }
|
||||
|
||||
/// \brief Clear out all of the type qualifiers.
|
||||
void ClearTypeQualifiers() {
|
||||
|
@ -540,6 +545,7 @@ public:
|
|||
TQ_restrictLoc = SourceLocation();
|
||||
TQ_volatileLoc = SourceLocation();
|
||||
TQ_atomicLoc = SourceLocation();
|
||||
TQ_pipeLoc = SourceLocation();
|
||||
}
|
||||
|
||||
// function-specifier
|
||||
|
@ -643,6 +649,9 @@ public:
|
|||
bool SetTypeAltiVecBool(bool isAltiVecBool, SourceLocation Loc,
|
||||
const char *&PrevSpec, unsigned &DiagID,
|
||||
const PrintingPolicy &Policy);
|
||||
bool SetTypePipe(bool isPipe, SourceLocation Loc,
|
||||
const char *&PrevSpec, unsigned &DiagID,
|
||||
const PrintingPolicy &Policy);
|
||||
bool SetTypeSpecError();
|
||||
void UpdateDeclRep(Decl *Rep) {
|
||||
assert(isDeclRep((TST) TypeSpecType));
|
||||
|
@ -1081,7 +1090,7 @@ typedef SmallVector<Token, 4> CachedTokens;
|
|||
/// This is intended to be a small value object.
|
||||
struct DeclaratorChunk {
|
||||
enum {
|
||||
Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren
|
||||
Pointer, Reference, Array, Function, BlockPointer, MemberPointer, Paren, Pipe
|
||||
} Kind;
|
||||
|
||||
/// Loc - The place where this type was defined.
|
||||
|
@ -1409,6 +1418,13 @@ struct DeclaratorChunk {
|
|||
}
|
||||
};
|
||||
|
||||
struct PipeTypeInfo : TypeInfoCommon {
|
||||
/// The access writes.
|
||||
unsigned AccessWrites : 3;
|
||||
|
||||
void destroy() {}
|
||||
};
|
||||
|
||||
union {
|
||||
TypeInfoCommon Common;
|
||||
PointerTypeInfo Ptr;
|
||||
|
@ -1417,6 +1433,7 @@ struct DeclaratorChunk {
|
|||
FunctionTypeInfo Fun;
|
||||
BlockPointerTypeInfo Cls;
|
||||
MemberPointerTypeInfo Mem;
|
||||
PipeTypeInfo PipeInfo;
|
||||
};
|
||||
|
||||
void destroy() {
|
||||
|
@ -1428,6 +1445,7 @@ struct DeclaratorChunk {
|
|||
case DeclaratorChunk::Array: return Arr.destroy();
|
||||
case DeclaratorChunk::MemberPointer: return Mem.destroy();
|
||||
case DeclaratorChunk::Paren: return;
|
||||
case DeclaratorChunk::Pipe: return PipeInfo.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1526,6 +1544,17 @@ struct DeclaratorChunk {
|
|||
return I;
|
||||
}
|
||||
|
||||
/// \brief Return a DeclaratorChunk for a block.
|
||||
static DeclaratorChunk getPipe(unsigned TypeQuals,
|
||||
SourceLocation Loc) {
|
||||
DeclaratorChunk I;
|
||||
I.Kind = Pipe;
|
||||
I.Loc = Loc;
|
||||
I.Cls.TypeQuals = TypeQuals;
|
||||
I.Cls.AttrList = 0;
|
||||
return I;
|
||||
}
|
||||
|
||||
static DeclaratorChunk getMemberPointer(const CXXScopeSpec &SS,
|
||||
unsigned TypeQuals,
|
||||
SourceLocation Loc) {
|
||||
|
@ -2026,6 +2055,7 @@ public:
|
|||
case DeclaratorChunk::Array:
|
||||
case DeclaratorChunk::BlockPointer:
|
||||
case DeclaratorChunk::MemberPointer:
|
||||
case DeclaratorChunk::Pipe:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("Invalid type chunk");
|
||||
|
|
|
@ -1269,6 +1269,8 @@ public:
|
|||
SourceLocation Loc, DeclarationName Entity);
|
||||
QualType BuildParenType(QualType T);
|
||||
QualType BuildAtomicType(QualType T, SourceLocation Loc);
|
||||
QualType BuildPipeType(QualType T,
|
||||
SourceLocation Loc);
|
||||
|
||||
TypeSourceInfo *GetTypeForDeclarator(Declarator &D, Scope *S);
|
||||
TypeSourceInfo *GetTypeForDeclaratorCast(Declarator &D, QualType FromTy);
|
||||
|
|
|
@ -907,7 +907,9 @@ namespace clang {
|
|||
/// \brief A DecayedType record.
|
||||
TYPE_DECAYED = 41,
|
||||
/// \brief An AdjustedType record.
|
||||
TYPE_ADJUSTED = 42
|
||||
TYPE_ADJUSTED = 42,
|
||||
/// \brief A PipeType record.
|
||||
TYPE_PIPE = 43
|
||||
};
|
||||
|
||||
/// \brief The type IDs for special types constructed by semantic
|
||||
|
|
|
@ -1836,6 +1836,13 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const {
|
|||
Align = static_cast<unsigned>(Width);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Type::Pipe: {
|
||||
TypeInfo Info = getTypeInfo(cast<PipeType>(T)->getElementType());
|
||||
Width = Info.Width;
|
||||
Align = Info.Align;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -2663,6 +2670,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const {
|
|||
case Type::FunctionProto:
|
||||
case Type::BlockPointer:
|
||||
case Type::MemberPointer:
|
||||
case Type::Pipe:
|
||||
return type;
|
||||
|
||||
// These types can be variably-modified. All these modifications
|
||||
|
@ -3117,6 +3125,32 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray,
|
|||
return QualType(FTP, 0);
|
||||
}
|
||||
|
||||
/// Return pipe type for the specified type.
|
||||
QualType ASTContext::getPipeType(QualType T) const {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
PipeType::Profile(ID, T);
|
||||
|
||||
void *InsertPos = 0;
|
||||
if (PipeType *PT = PipeTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
return QualType(PT, 0);
|
||||
|
||||
// If the pipe element type isn't canonical, this won't be a canonical type
|
||||
// either, so fill in the canonical type field.
|
||||
QualType Canonical;
|
||||
if (!T.isCanonical()) {
|
||||
Canonical = getPipeType(getCanonicalType(T));
|
||||
|
||||
// Get the new insert position for the node we care about.
|
||||
PipeType *NewIP = PipeTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
assert(!NewIP && "Shouldn't be in the map!");
|
||||
(void)NewIP;
|
||||
}
|
||||
PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical);
|
||||
Types.push_back(New);
|
||||
PipeTypes.InsertNode(New, InsertPos);
|
||||
return QualType(New, 0);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
static bool NeedsInjectedClassNameType(const RecordDecl *D) {
|
||||
if (!isa<CXXRecordDecl>(D)) return false;
|
||||
|
@ -5857,6 +5891,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S,
|
|||
case Type::Auto:
|
||||
return;
|
||||
|
||||
case Type::Pipe:
|
||||
#define ABSTRACT_TYPE(KIND, BASE)
|
||||
#define TYPE(KIND, BASE)
|
||||
#define DEPENDENT_TYPE(KIND, BASE) \
|
||||
|
@ -7792,6 +7827,24 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
|
|||
|
||||
return QualType();
|
||||
}
|
||||
case Type::Pipe:
|
||||
{
|
||||
// Merge two pointer types, while trying to preserve typedef info
|
||||
QualType LHSValue = LHS->getAs<PipeType>()->getElementType();
|
||||
QualType RHSValue = RHS->getAs<PipeType>()->getElementType();
|
||||
if (Unqualified) {
|
||||
LHSValue = LHSValue.getUnqualifiedType();
|
||||
RHSValue = RHSValue.getUnqualifiedType();
|
||||
}
|
||||
QualType ResultType = mergeTypes(LHSValue, RHSValue, false,
|
||||
Unqualified);
|
||||
if (ResultType.isNull()) return QualType();
|
||||
if (getCanonicalType(LHSValue) == getCanonicalType(ResultType))
|
||||
return LHS;
|
||||
if (getCanonicalType(RHSValue) == getCanonicalType(ResultType))
|
||||
return RHS;
|
||||
return getPipeType(ResultType);
|
||||
}
|
||||
}
|
||||
|
||||
llvm_unreachable("Invalid Type::Class!");
|
||||
|
|
|
@ -878,6 +878,14 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context,
|
|||
break;
|
||||
}
|
||||
|
||||
case Type::Pipe: {
|
||||
if (!IsStructurallyEquivalent(Context,
|
||||
cast<PipeType>(T1)->getElementType(),
|
||||
cast<PipeType>(T2)->getElementType()))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
} // end switch
|
||||
|
||||
return true;
|
||||
|
|
|
@ -1509,6 +1509,7 @@ bool CXXNameMangler::mangleUnresolvedTypeOrSimpleId(QualType Ty,
|
|||
case Type::ObjCInterface:
|
||||
case Type::ObjCObjectPointer:
|
||||
case Type::Atomic:
|
||||
case Type::Pipe:
|
||||
llvm_unreachable("type is illegal as a nested name specifier");
|
||||
|
||||
case Type::SubstTemplateTypeParmPack:
|
||||
|
@ -2682,6 +2683,13 @@ void CXXNameMangler::mangleType(const AtomicType *T) {
|
|||
mangleType(T->getValueType());
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleType(const PipeType *T) {
|
||||
// Pipe type mangling rules are described in SPIR 2.0 specification
|
||||
// A.1 Data types and A.3 Summary of changes
|
||||
// <type> ::= 8ocl_pipe
|
||||
Out << "8ocl_pipe";
|
||||
}
|
||||
|
||||
void CXXNameMangler::mangleIntegerLiteral(QualType T,
|
||||
const llvm::APSInt &Value) {
|
||||
// <expr-primary> ::= L <type> <value number> E # integer literal
|
||||
|
|
|
@ -2428,6 +2428,15 @@ void MicrosoftCXXNameMangler::mangleType(const AtomicType *T, Qualifiers,
|
|||
mangleArtificalTagType(TTK_Struct, TemplateMangling, {"__clang"});
|
||||
}
|
||||
|
||||
void MicrosoftCXXNameMangler::mangleType(const PipeType *T, Qualifiers,
|
||||
SourceRange Range) {
|
||||
DiagnosticsEngine &Diags = Context.getDiags();
|
||||
unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Error,
|
||||
"cannot mangle this OpenCL pipe type yet");
|
||||
Diags.Report(Range.getBegin(), DiagID)
|
||||
<< Range;
|
||||
}
|
||||
|
||||
void MicrosoftMangleContextImpl::mangleCXXName(const NamedDecl *D,
|
||||
raw_ostream &Out) {
|
||||
assert((isa<FunctionDecl>(D) || isa<VarDecl>(D)) &&
|
||||
|
|
|
@ -3361,6 +3361,8 @@ static CachedProperties computeCachedProperties(const Type *T) {
|
|||
return Cache::get(cast<ObjCObjectPointerType>(T)->getPointeeType());
|
||||
case Type::Atomic:
|
||||
return Cache::get(cast<AtomicType>(T)->getValueType());
|
||||
case Type::Pipe:
|
||||
return Cache::get(cast<PipeType>(T)->getElementType());
|
||||
}
|
||||
|
||||
llvm_unreachable("unhandled type class");
|
||||
|
@ -3443,6 +3445,8 @@ static LinkageInfo computeLinkageInfo(const Type *T) {
|
|||
return computeLinkageInfo(cast<ObjCObjectPointerType>(T)->getPointeeType());
|
||||
case Type::Atomic:
|
||||
return computeLinkageInfo(cast<AtomicType>(T)->getValueType());
|
||||
case Type::Pipe:
|
||||
return computeLinkageInfo(cast<PipeType>(T)->getElementType());
|
||||
}
|
||||
|
||||
llvm_unreachable("unhandled type class");
|
||||
|
@ -3601,6 +3605,7 @@ bool Type::canHaveNullability() const {
|
|||
case Type::ObjCObject:
|
||||
case Type::ObjCInterface:
|
||||
case Type::Atomic:
|
||||
case Type::Pipe:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("bad type kind!");
|
||||
|
|
|
@ -193,6 +193,7 @@ bool TypePrinter::canPrefixQualifiers(const Type *T,
|
|||
case Type::ObjCObject:
|
||||
case Type::ObjCInterface:
|
||||
case Type::Atomic:
|
||||
case Type::Pipe:
|
||||
CanPrefixQualifiers = true;
|
||||
break;
|
||||
|
||||
|
@ -859,6 +860,15 @@ void TypePrinter::printAtomicBefore(const AtomicType *T, raw_ostream &OS) {
|
|||
}
|
||||
void TypePrinter::printAtomicAfter(const AtomicType *T, raw_ostream &OS) { }
|
||||
|
||||
void TypePrinter::printPipeBefore(const PipeType *T, raw_ostream &OS) {
|
||||
IncludeStrongLifetimeRAII Strong(Policy);
|
||||
|
||||
OS << "pipe";
|
||||
spaceBeforePlaceHolder(OS);
|
||||
}
|
||||
|
||||
void TypePrinter::printPipeAfter(const PipeType *T, raw_ostream &OS) {
|
||||
}
|
||||
/// Appends the given scope to the end of a string.
|
||||
void TypePrinter::AppendScope(DeclContext *DC, raw_ostream &OS) {
|
||||
if (DC->isTranslationUnit()) return;
|
||||
|
|
|
@ -2025,6 +2025,11 @@ llvm::DIType *CGDebugInfo::CreateType(const AtomicType *Ty, llvm::DIFile *U) {
|
|||
return getOrCreateType(Ty->getValueType(), U);
|
||||
}
|
||||
|
||||
llvm::DIType* CGDebugInfo::CreateType(const PipeType *Ty,
|
||||
llvm::DIFile *U) {
|
||||
return getOrCreateType(Ty->getElementType(), U);
|
||||
}
|
||||
|
||||
llvm::DIType *CGDebugInfo::CreateEnumType(const EnumType *Ty) {
|
||||
const EnumDecl *ED = Ty->getDecl();
|
||||
|
||||
|
@ -2284,6 +2289,9 @@ llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
|
|||
case Type::Atomic:
|
||||
return CreateType(cast<AtomicType>(Ty), Unit);
|
||||
|
||||
case Type::Pipe:
|
||||
return CreateType(cast<PipeType>(Ty), Unit);
|
||||
|
||||
case Type::TemplateSpecialization:
|
||||
return CreateType(cast<TemplateSpecializationType>(Ty), Unit);
|
||||
|
||||
|
|
|
@ -168,6 +168,7 @@ class CGDebugInfo {
|
|||
llvm::DIType *CreateType(const RValueReferenceType *Ty, llvm::DIFile *Unit);
|
||||
llvm::DIType *CreateType(const MemberPointerType *Ty, llvm::DIFile *F);
|
||||
llvm::DIType *CreateType(const AtomicType *Ty, llvm::DIFile *F);
|
||||
llvm::DIType *CreateType(const PipeType *Ty, llvm::DIFile *F);
|
||||
/// Get enumeration type.
|
||||
llvm::DIType *CreateEnumType(const EnumType *Ty);
|
||||
llvm::DIType *CreateTypeDefinition(const EnumType *Ty);
|
||||
|
|
|
@ -99,3 +99,14 @@ llvm::Type *CGOpenCLRuntime::convertOpenCLSpecificType(const Type *T) {
|
|||
llvm::StructType::create(Ctx, "opencl.reserve_id_t"), 0);
|
||||
}
|
||||
}
|
||||
|
||||
llvm::Type *CGOpenCLRuntime::getPipeType() {
|
||||
if (!PipeTy){
|
||||
uint32_t PipeAddrSpc =
|
||||
CGM.getContext().getTargetAddressSpace(LangAS::opencl_global);
|
||||
PipeTy = llvm::PointerType::get(llvm::StructType::create(
|
||||
CGM.getLLVMContext(), "opencl.pipe_t"), PipeAddrSpc);
|
||||
}
|
||||
|
||||
return PipeTy;
|
||||
}
|
||||
|
|
|
@ -32,9 +32,10 @@ class CodeGenModule;
|
|||
class CGOpenCLRuntime {
|
||||
protected:
|
||||
CodeGenModule &CGM;
|
||||
llvm::Type *PipeTy;
|
||||
|
||||
public:
|
||||
CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM) {}
|
||||
CGOpenCLRuntime(CodeGenModule &CGM) : CGM(CGM), PipeTy(nullptr) {}
|
||||
virtual ~CGOpenCLRuntime();
|
||||
|
||||
/// Emit the IR required for a work-group-local variable declaration, and add
|
||||
|
@ -44,6 +45,8 @@ public:
|
|||
const VarDecl &D);
|
||||
|
||||
virtual llvm::Type *convertOpenCLSpecificType(const Type *T);
|
||||
|
||||
virtual llvm::Type *getPipeType();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -195,6 +195,7 @@ TypeEvaluationKind CodeGenFunction::getEvaluationKind(QualType type) {
|
|||
case Type::FunctionNoProto:
|
||||
case Type::Enum:
|
||||
case Type::ObjCObjectPointer:
|
||||
case Type::Pipe:
|
||||
return TEK_Scalar;
|
||||
|
||||
// Complexes.
|
||||
|
@ -511,7 +512,8 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
|
|||
typeQuals += typeQuals.empty() ? "volatile" : " volatile";
|
||||
} else {
|
||||
uint32_t AddrSpc = 0;
|
||||
if (ty->isImageType())
|
||||
bool isPipe = ty->isPipeType();
|
||||
if (ty->isImageType() || isPipe)
|
||||
AddrSpc =
|
||||
CGM.getContext().getTargetAddressSpace(LangAS::opencl_global);
|
||||
|
||||
|
@ -519,7 +521,11 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
|
|||
llvm::ConstantAsMetadata::get(Builder.getInt32(AddrSpc)));
|
||||
|
||||
// Get argument type name.
|
||||
std::string typeName = ty.getUnqualifiedType().getAsString(Policy);
|
||||
std::string typeName;
|
||||
if (isPipe)
|
||||
typeName = cast<PipeType>(ty)->getElementType().getAsString(Policy);
|
||||
else
|
||||
typeName = ty.getUnqualifiedType().getAsString(Policy);
|
||||
|
||||
// Turn "unsigned type" to "utype"
|
||||
std::string::size_type pos = typeName.find("unsigned");
|
||||
|
@ -528,7 +534,12 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
|
|||
|
||||
argTypeNames.push_back(llvm::MDString::get(Context, typeName));
|
||||
|
||||
std::string baseTypeName =
|
||||
std::string baseTypeName;
|
||||
if (isPipe)
|
||||
baseTypeName =
|
||||
cast<PipeType>(ty)->getElementType().getCanonicalType().getAsString(Policy);
|
||||
else
|
||||
baseTypeName =
|
||||
ty.getUnqualifiedType().getCanonicalType().getAsString(Policy);
|
||||
|
||||
// Turn "unsigned type" to "utype"
|
||||
|
@ -543,12 +554,16 @@ static void GenOpenCLArgMetadata(const FunctionDecl *FD, llvm::Function *Fn,
|
|||
typeQuals = "const";
|
||||
if (ty.isVolatileQualified())
|
||||
typeQuals += typeQuals.empty() ? "volatile" : " volatile";
|
||||
if (isPipe)
|
||||
typeQuals = "pipe";
|
||||
}
|
||||
|
||||
argTypeQuals.push_back(llvm::MDString::get(Context, typeQuals));
|
||||
|
||||
// Get image access qualifier:
|
||||
if (ty->isImageType()) {
|
||||
// Get image and pipe access qualifier:
|
||||
// FIXME: now image and pipe share the same access qualifier maybe we can
|
||||
// refine it to OpenCL access qualifier and also handle write_read
|
||||
if (ty->isImageType()|| ty->isPipeType()) {
|
||||
const OpenCLImageAccessAttr *A = parm->getAttr<OpenCLImageAccessAttr>();
|
||||
if (A && A->isWriteOnly())
|
||||
accessQuals.push_back(llvm::MDString::get(Context, "write_only"));
|
||||
|
@ -1727,6 +1742,10 @@ void CodeGenFunction::EmitVariablyModifiedType(QualType type) {
|
|||
case Type::Atomic:
|
||||
type = cast<AtomicType>(ty)->getValueType();
|
||||
break;
|
||||
|
||||
case Type::Pipe:
|
||||
type = cast<PipeType>(ty)->getElementType();
|
||||
break;
|
||||
}
|
||||
} while (type->isVariablyModifiedType());
|
||||
}
|
||||
|
|
|
@ -628,6 +628,10 @@ llvm::Type *CodeGenTypes::ConvertType(QualType T) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case Type::Pipe: {
|
||||
ResultType = CGM.getOpenCLRuntime().getPipeType();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(ResultType && "Didn't convert a type?");
|
||||
|
|
|
@ -2715,6 +2715,9 @@ void ItaniumRTTIBuilder::BuildVTablePointer(const Type *Ty) {
|
|||
case Type::Auto:
|
||||
llvm_unreachable("Undeduced auto type shouldn't get here");
|
||||
|
||||
case Type::Pipe:
|
||||
llvm_unreachable("Pipe types shouldn't get here");
|
||||
|
||||
case Type::Builtin:
|
||||
// GCC treats vector and complex types as fundamental types.
|
||||
case Type::Vector:
|
||||
|
@ -2939,6 +2942,9 @@ llvm::Constant *ItaniumRTTIBuilder::BuildTypeInfo(QualType Ty, bool Force) {
|
|||
case Type::Auto:
|
||||
llvm_unreachable("Undeduced auto type shouldn't get here");
|
||||
|
||||
case Type::Pipe:
|
||||
llvm_unreachable("Pipe type shouldn't get here");
|
||||
|
||||
case Type::ConstantArray:
|
||||
case Type::IncompleteArray:
|
||||
case Type::VariableArray:
|
||||
|
|
|
@ -3326,6 +3326,15 @@ void Parser::ParseDeclarationSpecifiers(DeclSpec &DS,
|
|||
case tok::kw___bool:
|
||||
isInvalid = DS.SetTypeAltiVecBool(true, Loc, PrevSpec, DiagID, Policy);
|
||||
break;
|
||||
case tok::kw_pipe:
|
||||
if (!getLangOpts().OpenCL || (getLangOpts().OpenCLVersion < 200)) {
|
||||
// OpenCL 2.0 defined this keyword. OpenCL 1.2 and earlier should
|
||||
// support the "pipe" word as identifier.
|
||||
Tok.getIdentifierInfo()->revertTokenIDToIdentifier();
|
||||
goto DoneWithDeclSpec;
|
||||
}
|
||||
isInvalid = DS.SetTypePipe(true, Loc, PrevSpec, DiagID, Policy);
|
||||
break;
|
||||
case tok::kw___unknown_anytype:
|
||||
isInvalid = DS.SetTypeSpecType(TST_unknown_anytype, Loc,
|
||||
PrevSpec, DiagID, Policy);
|
||||
|
@ -4401,6 +4410,9 @@ bool Parser::isDeclarationSpecifier(bool DisambiguatingWithExpression) {
|
|||
switch (Tok.getKind()) {
|
||||
default: return false;
|
||||
|
||||
case tok::kw_pipe:
|
||||
return getLangOpts().OpenCL && (getLangOpts().OpenCLVersion >= 200);
|
||||
|
||||
case tok::identifier: // foo::bar
|
||||
// Unfortunate hack to support "Class.factoryMethod" notation.
|
||||
if (getLangOpts().ObjC1 && NextToken().is(tok::period))
|
||||
|
@ -4847,6 +4859,9 @@ static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,
|
|||
if (Kind == tok::star || Kind == tok::caret)
|
||||
return true;
|
||||
|
||||
if ((Kind == tok::kw_pipe) && Lang.OpenCL && (Lang.OpenCLVersion >= 200))
|
||||
return true;
|
||||
|
||||
if (!Lang.CPlusPlus)
|
||||
return false;
|
||||
|
||||
|
@ -4865,6 +4880,17 @@ static bool isPtrOperatorToken(tok::TokenKind Kind, const LangOptions &Lang,
|
|||
return false;
|
||||
}
|
||||
|
||||
// Indicates whether the given declarator is a pipe declarator.
|
||||
static bool isPipeDeclerator(const Declarator &D) {
|
||||
const unsigned NumTypes = D.getNumTypeObjects();
|
||||
|
||||
for (unsigned Idx = 0; Idx != NumTypes; ++Idx)
|
||||
if (DeclaratorChunk::Pipe == D.getTypeObject(Idx).Kind)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ParseDeclaratorInternal - Parse a C or C++ declarator. The direct-declarator
|
||||
/// is parsed by the function passed to it. Pass null, and the direct-declarator
|
||||
/// isn't parsed at all, making this function effectively parse the C++
|
||||
|
@ -4941,6 +4967,15 @@ void Parser::ParseDeclaratorInternal(Declarator &D,
|
|||
}
|
||||
|
||||
tok::TokenKind Kind = Tok.getKind();
|
||||
|
||||
if (D.getDeclSpec().isTypeSpecPipe() && !isPipeDeclerator(D)) {
|
||||
DeclSpec &DS = D.getMutableDeclSpec();
|
||||
|
||||
D.AddTypeInfo(
|
||||
DeclaratorChunk::getPipe(DS.getTypeQualifiers(), DS.getPipeLoc()),
|
||||
DS.getAttributes(), SourceLocation());
|
||||
}
|
||||
|
||||
// Not a pointer, C++ reference, or block.
|
||||
if (!isPtrOperatorToken(Kind, getLangOpts(), D.getContext())) {
|
||||
if (DirectDeclParser)
|
||||
|
@ -6092,6 +6127,7 @@ void Parser::ParseMisplacedBracketDeclarator(Declarator &D) {
|
|||
case DeclaratorChunk::Reference:
|
||||
case DeclaratorChunk::BlockPointer:
|
||||
case DeclaratorChunk::MemberPointer:
|
||||
case DeclaratorChunk::Pipe:
|
||||
NeedParens = true;
|
||||
break;
|
||||
case DeclaratorChunk::Array:
|
||||
|
|
|
@ -270,6 +270,7 @@ bool Declarator::isDeclarationOfFunction() const {
|
|||
case DeclaratorChunk::Array:
|
||||
case DeclaratorChunk::BlockPointer:
|
||||
case DeclaratorChunk::MemberPointer:
|
||||
case DeclaratorChunk::Pipe:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("Invalid type chunk");
|
||||
|
@ -713,6 +714,22 @@ bool DeclSpec::SetTypeAltiVecVector(bool isAltiVecVector, SourceLocation Loc,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool DeclSpec::SetTypePipe(bool isPipe, SourceLocation Loc,
|
||||
const char *&PrevSpec, unsigned &DiagID,
|
||||
const PrintingPolicy &Policy) {
|
||||
|
||||
if (TypeSpecType != TST_unspecified) {
|
||||
PrevSpec = DeclSpec::getSpecifierName((TST)TypeSpecType, Policy);
|
||||
DiagID = diag::err_invalid_decl_spec_combination;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isPipe) {
|
||||
TypeSpecPipe = TSP_pipe;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DeclSpec::SetTypeAltiVecPixel(bool isAltiVecPixel, SourceLocation Loc,
|
||||
const char *&PrevSpec, unsigned &DiagID,
|
||||
const PrintingPolicy &Policy) {
|
||||
|
|
|
@ -8256,6 +8256,23 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
|||
for (auto Param : NewFD->params())
|
||||
checkIsValidOpenCLKernelParameter(*this, D, Param, ValidTypes);
|
||||
}
|
||||
for (FunctionDecl::param_iterator PI = NewFD->param_begin(),
|
||||
PE = NewFD->param_end(); PI != PE; ++PI) {
|
||||
ParmVarDecl *Param = *PI;
|
||||
QualType PT = Param->getType();
|
||||
|
||||
// OpenCL 2.0 pipe restrictions forbids pipe packet types to be non-value
|
||||
// types.
|
||||
if (getLangOpts().OpenCLVersion >= 200) {
|
||||
if(const PipeType *PipeTy = PT->getAs<PipeType>()) {
|
||||
QualType ElemTy = PipeTy->getElementType();
|
||||
if (ElemTy->isReferenceType() || ElemTy->isPointerType()) {
|
||||
Diag(Param->getTypeSpecStartLoc(), diag::err_reference_pipe_type );
|
||||
D.setInvalidType();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MarkUnusedFileScopedDecl(NewFD);
|
||||
|
||||
|
|
|
@ -7000,6 +7000,7 @@ void Sema::CheckConversionDeclarator(Declarator &D, QualType &R,
|
|||
case DeclaratorChunk::BlockPointer:
|
||||
case DeclaratorChunk::Reference:
|
||||
case DeclaratorChunk::MemberPointer:
|
||||
case DeclaratorChunk::Pipe:
|
||||
extendLeft(Before, Chunk.getSourceRange());
|
||||
break;
|
||||
|
||||
|
|
|
@ -13140,6 +13140,7 @@ bool Sema::tryCaptureVariable(
|
|||
case Type::ObjCObject:
|
||||
case Type::ObjCInterface:
|
||||
case Type::ObjCObjectPointer:
|
||||
case Type::Pipe:
|
||||
llvm_unreachable("type class is never variably-modified!");
|
||||
case Type::Adjusted:
|
||||
QTy = cast<AdjustedType>(Ty)->getOriginalType();
|
||||
|
|
|
@ -2616,6 +2616,9 @@ addAssociatedClassesAndNamespaces(AssociatedLookup &Result, QualType Ty) {
|
|||
case Type::Atomic:
|
||||
T = cast<AtomicType>(T)->getValueType().getTypePtr();
|
||||
continue;
|
||||
case Type::Pipe:
|
||||
T = cast<PipeType>(T)->getElementType().getTypePtr();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Queue.empty())
|
||||
|
|
|
@ -4184,6 +4184,10 @@ bool UnnamedLocalNoLinkageFinder::VisitAtomicType(const AtomicType* T) {
|
|||
return Visit(T->getValueType());
|
||||
}
|
||||
|
||||
bool UnnamedLocalNoLinkageFinder::VisitPipeType(const PipeType* T) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnnamedLocalNoLinkageFinder::VisitTagDecl(const TagDecl *Tag) {
|
||||
if (Tag->getDeclContext()->isFunctionOrMethod()) {
|
||||
S.Diag(SR.getBegin(),
|
||||
|
|
|
@ -1652,6 +1652,7 @@ DeduceTemplateArgumentsByTypeMatch(Sema &S,
|
|||
case Type::Auto:
|
||||
case Type::DependentTemplateSpecialization:
|
||||
case Type::PackExpansion:
|
||||
case Type::Pipe:
|
||||
// No template argument deduction for these types
|
||||
return Sema::TDK_Success;
|
||||
}
|
||||
|
@ -4964,6 +4965,7 @@ MarkUsedTemplateParameters(ASTContext &Ctx, QualType T,
|
|||
case Type::ObjCObject:
|
||||
case Type::ObjCObjectPointer:
|
||||
case Type::UnresolvedUsing:
|
||||
case Type::Pipe:
|
||||
#define TYPE(Class, Base)
|
||||
#define ABSTRACT_TYPE(Class, Base)
|
||||
#define DEPENDENT_TYPE(Class, Base)
|
||||
|
|
|
@ -750,6 +750,7 @@ bool Sema::containsUnexpandedParameterPacks(Declarator &D) {
|
|||
case DeclaratorChunk::Pointer:
|
||||
case DeclaratorChunk::Reference:
|
||||
case DeclaratorChunk::Paren:
|
||||
case DeclaratorChunk::Pipe:
|
||||
case DeclaratorChunk::BlockPointer:
|
||||
// These declarator chunks cannot contain any parameter packs.
|
||||
break;
|
||||
|
|
|
@ -335,6 +335,7 @@ static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator,
|
|||
case DeclaratorChunk::Array:
|
||||
case DeclaratorChunk::Reference:
|
||||
case DeclaratorChunk::MemberPointer:
|
||||
case DeclaratorChunk::Pipe:
|
||||
return result;
|
||||
|
||||
// If we do find a function declarator, scan inwards from that,
|
||||
|
@ -347,6 +348,7 @@ static DeclaratorChunk *maybeMovePastReturnType(Declarator &declarator,
|
|||
case DeclaratorChunk::Array:
|
||||
case DeclaratorChunk::Function:
|
||||
case DeclaratorChunk::Reference:
|
||||
case DeclaratorChunk::Pipe:
|
||||
continue;
|
||||
|
||||
case DeclaratorChunk::MemberPointer:
|
||||
|
@ -427,6 +429,7 @@ static void distributeObjCPointerTypeAttr(TypeProcessingState &state,
|
|||
// Don't walk through these.
|
||||
case DeclaratorChunk::Reference:
|
||||
case DeclaratorChunk::MemberPointer:
|
||||
case DeclaratorChunk::Pipe:
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
@ -459,6 +462,7 @@ distributeObjCPointerTypeAttrFromDeclarator(TypeProcessingState &state,
|
|||
case DeclaratorChunk::MemberPointer:
|
||||
case DeclaratorChunk::Paren:
|
||||
case DeclaratorChunk::Array:
|
||||
case DeclaratorChunk::Pipe:
|
||||
continue;
|
||||
|
||||
case DeclaratorChunk::Function:
|
||||
|
@ -520,6 +524,7 @@ static void distributeFunctionTypeAttr(TypeProcessingState &state,
|
|||
case DeclaratorChunk::Array:
|
||||
case DeclaratorChunk::Reference:
|
||||
case DeclaratorChunk::MemberPointer:
|
||||
case DeclaratorChunk::Pipe:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -1272,6 +1277,10 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
|
|||
// value being declared, poison it as invalid so we don't get chains of
|
||||
// errors.
|
||||
declarator.setInvalidType(true);
|
||||
} else if (S.getLangOpts().OpenCLVersion >= 200 && DS.isTypeSpecPipe()){
|
||||
S.Diag(DeclLoc, diag::err_missing_actual_pipe_type)
|
||||
<< DS.getSourceRange();
|
||||
declarator.setInvalidType(true);
|
||||
} else {
|
||||
S.Diag(DeclLoc, diag::ext_missing_type_specifier)
|
||||
<< DS.getSourceRange();
|
||||
|
@ -1564,7 +1573,9 @@ static QualType ConvertDeclSpecToType(TypeProcessingState &state) {
|
|||
// Apply any type attributes from the decl spec. This may cause the
|
||||
// list of type attributes to be temporarily saved while the type
|
||||
// attributes are pushed around.
|
||||
processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes().getList());
|
||||
// pipe attributes will be handled later ( at GetFullTypeForDeclarator )
|
||||
if (!DS.isTypeSpecPipe())
|
||||
processTypeAttrs(state, Result, TAL_DeclSpec, DS.getAttributes().getList());
|
||||
|
||||
// Apply const/volatile/restrict qualifiers to T.
|
||||
if (unsigned TypeQuals = DS.getTypeQualifiers()) {
|
||||
|
@ -1924,6 +1935,21 @@ QualType Sema::BuildReferenceType(QualType T, bool SpelledAsLValue,
|
|||
return Context.getRValueReferenceType(T);
|
||||
}
|
||||
|
||||
/// \brief Build a Pipe type.
|
||||
///
|
||||
/// \param T The type to which we'll be building a Pipe.
|
||||
///
|
||||
/// \param Loc We do not use it for now.
|
||||
///
|
||||
/// \returns A suitable pipe type, if there are no errors. Otherwise, returns a
|
||||
/// NULL type.
|
||||
QualType Sema::BuildPipeType(QualType T, SourceLocation Loc) {
|
||||
assert(!T->isObjCObjectType() && "Should build ObjCObjectPointerType");
|
||||
|
||||
// Build the pipe type.
|
||||
return Context.getPipeType(T);
|
||||
}
|
||||
|
||||
/// Check whether the specified array size makes the array type a VLA. If so,
|
||||
/// return true, if not, return the size of the array in SizeVal.
|
||||
static bool isArraySizeVLA(Sema &S, Expr *ArraySize, llvm::APSInt &SizeVal) {
|
||||
|
@ -2393,6 +2419,7 @@ static void inferARCWriteback(TypeProcessingState &state,
|
|||
case DeclaratorChunk::Array: // suppress if written (id[])?
|
||||
case DeclaratorChunk::Function:
|
||||
case DeclaratorChunk::MemberPointer:
|
||||
case DeclaratorChunk::Pipe:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -2532,6 +2559,7 @@ static void diagnoseRedundantReturnTypeQualifiers(Sema &S, QualType RetTy,
|
|||
case DeclaratorChunk::Reference:
|
||||
case DeclaratorChunk::Array:
|
||||
case DeclaratorChunk::MemberPointer:
|
||||
case DeclaratorChunk::Pipe:
|
||||
// FIXME: We can't currently provide an accurate source location and a
|
||||
// fix-it hint for these.
|
||||
unsigned AtomicQual = RetTy->isAtomicType() ? DeclSpec::TQ_atomic : 0;
|
||||
|
@ -3057,6 +3085,7 @@ static PointerDeclaratorKind classifyPointerDeclarator(Sema &S,
|
|||
switch (chunk.Kind) {
|
||||
case DeclaratorChunk::Array:
|
||||
case DeclaratorChunk::Function:
|
||||
case DeclaratorChunk::Pipe:
|
||||
break;
|
||||
|
||||
case DeclaratorChunk::BlockPointer:
|
||||
|
@ -3305,6 +3334,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|||
case DeclaratorChunk::Array:
|
||||
DiagKind = 2;
|
||||
break;
|
||||
case DeclaratorChunk::Pipe:
|
||||
break;
|
||||
}
|
||||
|
||||
S.Diag(DeclChunk.Loc, DiagId) << DiagKind;
|
||||
|
@ -3370,6 +3401,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|||
switch (chunk.Kind) {
|
||||
case DeclaratorChunk::Array:
|
||||
case DeclaratorChunk::Function:
|
||||
case DeclaratorChunk::Pipe:
|
||||
break;
|
||||
|
||||
case DeclaratorChunk::BlockPointer:
|
||||
|
@ -3689,6 +3721,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|||
break;
|
||||
case DeclaratorChunk::Function:
|
||||
case DeclaratorChunk::BlockPointer:
|
||||
case DeclaratorChunk::Pipe:
|
||||
// These are invalid anyway, so just ignore.
|
||||
break;
|
||||
}
|
||||
|
@ -4038,7 +4071,7 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|||
|
||||
break;
|
||||
}
|
||||
case DeclaratorChunk::MemberPointer:
|
||||
case DeclaratorChunk::MemberPointer: {
|
||||
// The scope spec must refer to a class, or be dependent.
|
||||
CXXScopeSpec &SS = DeclType.Mem.Scope();
|
||||
QualType ClsType;
|
||||
|
@ -4098,6 +4131,12 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
|
|||
break;
|
||||
}
|
||||
|
||||
case DeclaratorChunk::Pipe: {
|
||||
T = S.BuildPipeType(T, DeclType.Loc );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (T.isNull()) {
|
||||
D.setInvalidType(true);
|
||||
T = Context.IntTy;
|
||||
|
@ -4392,6 +4431,7 @@ static void transferARCOwnership(TypeProcessingState &state,
|
|||
|
||||
case DeclaratorChunk::Function:
|
||||
case DeclaratorChunk::MemberPointer:
|
||||
case DeclaratorChunk::Pipe:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -4682,6 +4722,14 @@ namespace {
|
|||
}
|
||||
}
|
||||
|
||||
void VisitPipeTypeLoc(PipeTypeLoc TL) {
|
||||
TL.setKWLoc(DS.getTypeSpecTypeLoc());
|
||||
|
||||
TypeSourceInfo *TInfo = 0;
|
||||
Sema::GetTypeFromParser(DS.getRepAsType(), &TInfo);
|
||||
TL.getValueLoc().initializeFullCopy(TInfo->getTypeLoc());
|
||||
}
|
||||
|
||||
void VisitTypeLoc(TypeLoc TL) {
|
||||
// FIXME: add other typespec types and change this to an assert.
|
||||
TL.initialize(Context, DS.getTypeSpecTypeLoc());
|
||||
|
@ -4802,6 +4850,10 @@ namespace {
|
|||
TL.setLParenLoc(Chunk.Loc);
|
||||
TL.setRParenLoc(Chunk.EndLoc);
|
||||
}
|
||||
void VisitPipeTypeLoc(PipeTypeLoc TL) {
|
||||
assert(Chunk.Kind == DeclaratorChunk::Pipe);
|
||||
TL.setKWLoc(Chunk.Loc);
|
||||
}
|
||||
|
||||
void VisitTypeLoc(TypeLoc TL) {
|
||||
llvm_unreachable("unsupported TypeLoc kind in declarator!");
|
||||
|
@ -4815,6 +4867,7 @@ static void fillAtomicQualLoc(AtomicTypeLoc ATL, const DeclaratorChunk &Chunk) {
|
|||
case DeclaratorChunk::Function:
|
||||
case DeclaratorChunk::Array:
|
||||
case DeclaratorChunk::Paren:
|
||||
case DeclaratorChunk::Pipe:
|
||||
llvm_unreachable("cannot be _Atomic qualified");
|
||||
|
||||
case DeclaratorChunk::Pointer:
|
||||
|
@ -5738,6 +5791,7 @@ static bool distributeNullabilityTypeAttr(TypeProcessingState &state,
|
|||
|
||||
// Don't walk through these.
|
||||
case DeclaratorChunk::Reference:
|
||||
case DeclaratorChunk::Pipe:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1046,6 +1046,9 @@ public:
|
|||
/// Subclasses may override this routine to provide different behavior.
|
||||
QualType RebuildAtomicType(QualType ValueType, SourceLocation KWLoc);
|
||||
|
||||
/// \brief Build a new pipe type given its value type.
|
||||
QualType RebuildPipeType(QualType ValueType, SourceLocation KWLoc);
|
||||
|
||||
/// \brief Build a new template name given a nested name specifier, a flag
|
||||
/// indicating whether the "template" keyword was provided, and the template
|
||||
/// that the template name refers to.
|
||||
|
@ -5324,6 +5327,26 @@ QualType TreeTransform<Derived>::TransformAtomicType(TypeLocBuilder &TLB,
|
|||
return Result;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
QualType TreeTransform<Derived>::TransformPipeType(TypeLocBuilder &TLB,
|
||||
PipeTypeLoc TL) {
|
||||
QualType ValueType = getDerived().TransformType(TLB, TL.getValueLoc());
|
||||
if (ValueType.isNull())
|
||||
return QualType();
|
||||
|
||||
QualType Result = TL.getType();
|
||||
if (getDerived().AlwaysRebuild() || ValueType != TL.getValueLoc().getType()) {
|
||||
Result = getDerived().RebuildPipeType(ValueType, TL.getKWLoc());
|
||||
if (Result.isNull())
|
||||
return QualType();
|
||||
}
|
||||
|
||||
PipeTypeLoc NewTL = TLB.push<PipeTypeLoc>(Result);
|
||||
NewTL.setKWLoc(TL.getKWLoc());
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
/// \brief Simple iterator that traverses the template arguments in a
|
||||
/// container that provides a \c getArgLoc() member function.
|
||||
///
|
||||
|
@ -11349,6 +11372,12 @@ QualType TreeTransform<Derived>::RebuildAtomicType(QualType ValueType,
|
|||
return SemaRef.BuildAtomicType(ValueType, KWLoc);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
QualType TreeTransform<Derived>::RebuildPipeType(QualType ValueType,
|
||||
SourceLocation KWLoc) {
|
||||
return SemaRef.BuildPipeType(ValueType, KWLoc);
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
TemplateName
|
||||
TreeTransform<Derived>::RebuildTemplateName(CXXScopeSpec &SS,
|
||||
|
|
|
@ -5640,6 +5640,17 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
|
|||
QualType ValueType = readType(*Loc.F, Record, Idx);
|
||||
return Context.getAtomicType(ValueType);
|
||||
}
|
||||
|
||||
case TYPE_PIPE: {
|
||||
if (Record.size() != 1) {
|
||||
Error("Incorrect encoding of pipe type");
|
||||
return QualType();
|
||||
}
|
||||
|
||||
// Reading the pipe element type.
|
||||
QualType ElementType = readType(*Loc.F, Record, Idx);
|
||||
return Context.getPipeType(ElementType);
|
||||
}
|
||||
}
|
||||
llvm_unreachable("Invalid TypeCode!");
|
||||
}
|
||||
|
@ -5911,6 +5922,9 @@ void TypeLocReader::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
|
|||
TL.setLParenLoc(ReadSourceLocation(Record, Idx));
|
||||
TL.setRParenLoc(ReadSourceLocation(Record, Idx));
|
||||
}
|
||||
void TypeLocReader::VisitPipeTypeLoc(PipeTypeLoc TL) {
|
||||
TL.setKWLoc(ReadSourceLocation(Record, Idx));
|
||||
}
|
||||
|
||||
TypeSourceInfo *ASTReader::GetTypeSourceInfo(ModuleFile &F,
|
||||
const RecordData &Record,
|
||||
|
|
|
@ -446,6 +446,12 @@ ASTTypeWriter::VisitAtomicType(const AtomicType *T) {
|
|||
Code = TYPE_ATOMIC;
|
||||
}
|
||||
|
||||
void
|
||||
ASTTypeWriter::VisitPipeType(const PipeType *T) {
|
||||
Writer.AddTypeRef(T->getElementType(), Record);
|
||||
Code = TYPE_PIPE;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class TypeLocWriter : public TypeLocVisitor<TypeLocWriter> {
|
||||
|
@ -672,6 +678,9 @@ void TypeLocWriter::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
|
|||
Writer.AddSourceLocation(TL.getLParenLoc(), Record);
|
||||
Writer.AddSourceLocation(TL.getRParenLoc(), Record);
|
||||
}
|
||||
void TypeLocWriter::VisitPipeTypeLoc(PipeTypeLoc TL) {
|
||||
Writer.AddSourceLocation(TL.getKWLoc(), Record);
|
||||
}
|
||||
|
||||
void ASTWriter::WriteTypeAbbrevs() {
|
||||
using namespace llvm;
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
// RUN: %clang_cc1 -emit-llvm -O0 -cl-std=CL2.0 -o - %s | FileCheck %s
|
||||
|
||||
// CHECK: %opencl.pipe_t = type opaque
|
||||
typedef unsigned char __attribute__((ext_vector_type(3))) uchar3;
|
||||
typedef int __attribute__((ext_vector_type(4))) int4;
|
||||
|
||||
void test1(read_only pipe int p) {
|
||||
// CHECK: define void @test1(%opencl.pipe_t* %p)
|
||||
reserve_id_t rid;
|
||||
// CHECK: %rid = alloca %opencl.reserve_id_t
|
||||
}
|
||||
|
||||
void test2(write_only pipe float p) {
|
||||
// CHECK: define void @test2(%opencl.pipe_t* %p)
|
||||
}
|
||||
|
||||
void test3(read_only pipe const int p) {
|
||||
// CHECK: define void @test3(%opencl.pipe_t* %p)
|
||||
}
|
||||
|
||||
void test4(read_only pipe uchar3 p) {
|
||||
// CHECK: define void @test4(%opencl.pipe_t* %p)
|
||||
}
|
||||
|
||||
void test5(read_only pipe int4 p) {
|
||||
// CHECK: define void @test5(%opencl.pipe_t* %p)
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
// Test this without pch.
|
||||
// RUN: %clang_cc1 -include %S/ocl_types.h -fsyntax-only %s
|
||||
// RUN: %clang_cc1 -include %S/ocl_types.h -fsyntax-only %s -cl-std=CL2.0 -D__OPENCL_VERSION__=200
|
||||
|
||||
// Test with pch.
|
||||
// RUN: %clang_cc1 -x cl -emit-pch -o %t %S/ocl_types.h
|
||||
// RUN: %clang_cc1 -include-pch %t -fsyntax-only %s -ast-print
|
||||
// RUN: %clang_cc1 -x cl -emit-pch -o %t %S/ocl_types.h -cl-std=CL2.0 -D__OPENCL_VERSION__=200
|
||||
// RUN: %clang_cc1 -include-pch %t -fsyntax-only %s -ast-print -cl-std=CL2.0 -D__OPENCL_VERSION__=200
|
||||
|
||||
void foo1(img1d_t img);
|
||||
|
||||
|
@ -24,3 +24,15 @@ void foo7(smp_t smp) {
|
|||
void foo8(evt_t evt) {
|
||||
evt_t loc_evt;
|
||||
}
|
||||
|
||||
#if __OPENCL_VERSION__ >= 200
|
||||
|
||||
void foo9(pipe int P) {
|
||||
int_pipe_function(P);
|
||||
}
|
||||
|
||||
void foo10(pipe Person P) {
|
||||
person_pipe_function(P);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -44,6 +44,7 @@ typedef image2d_depth_t img2ddep_t;
|
|||
// image2d_array_depth_t
|
||||
typedef image2d_array_depth_t img2darr_dep_t;
|
||||
|
||||
#pragma OPENCL EXTENSION cl_khr_gl_msaa_sharing : enable
|
||||
// image2d_msaa_t
|
||||
typedef image2d_msaa_t img2dmsaa_t;
|
||||
|
||||
|
@ -56,4 +57,14 @@ typedef image2d_msaa_depth_t img2dmsaadep_t;
|
|||
// image2d_array_msaa_depth_t
|
||||
typedef image2d_array_msaa_depth_t img2darrmsaadep_t;
|
||||
|
||||
// pipe specifier
|
||||
|
||||
typedef struct _person {
|
||||
int id;
|
||||
const char *name;
|
||||
} Person;
|
||||
|
||||
void int_pipe_function(pipe int);
|
||||
|
||||
void person_pipe_function(pipe Person);
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL2.0
|
||||
|
||||
void test1(pipe int *p){// expected-error {{pipes packet types cannot be of reference type}}
|
||||
}
|
||||
void test2(pipe p){// expected-error {{missing actual type specifier for pipe}}
|
||||
}
|
||||
void test3(int pipe p){// expected-error {{cannot combine with previous 'int' declaration specifier}}
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
// RUN: %clang_cc1 %s -verify -pedantic -fsyntax-only -cl-std=CL1.2
|
||||
|
||||
void foo(read_only pipe int p); // expected-error {{expected parameter declarator}} expected-error {{expected ')'}} expected-note {{to match this '('}}
|
|
@ -1686,6 +1686,10 @@ bool CursorVisitor::VisitAtomicTypeLoc(AtomicTypeLoc TL) {
|
|||
return Visit(TL.getValueLoc());
|
||||
}
|
||||
|
||||
bool CursorVisitor::VisitPipeTypeLoc(PipeTypeLoc TL) {
|
||||
return Visit(TL.getValueLoc());
|
||||
}
|
||||
|
||||
#define DEFAULT_TYPELOC_IMPL(CLASS, PARENT) \
|
||||
bool CursorVisitor::Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { \
|
||||
return Visit##PARENT##Loc(TL); \
|
||||
|
|
Loading…
Reference in New Issue