mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-01-10 10:01:42 +00:00
[OpenCL] Refactor read_only/write_only pipes.
This adds the access qualifier to the Pipe Type, rather than using a class hierarchy. It also fixes mergeTypes for Pipes, by disallowing merges. Only identical pipe types can be merged. The test case in invalid-pipes-cl2.0.cl is added to check that. llvm-svn: 288332
This commit is contained in:
parent
bbd6f7af33
commit
e3c85de6df
@ -135,8 +135,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
|
||||
mutable llvm::FoldingSet<AutoType> AutoTypes;
|
||||
mutable llvm::FoldingSet<AtomicType> AtomicTypes;
|
||||
llvm::FoldingSet<AttributedType> AttributedTypes;
|
||||
mutable llvm::FoldingSet<ReadPipeType> ReadPipeTypes;
|
||||
mutable llvm::FoldingSet<WritePipeType> WritePipeTypes;
|
||||
mutable llvm::FoldingSet<PipeType> PipeTypes;
|
||||
|
||||
mutable llvm::FoldingSet<QualifiedTemplateName> QualifiedTemplateNames;
|
||||
mutable llvm::FoldingSet<DependentTemplateName> DependentTemplateNames;
|
||||
@ -1012,6 +1011,8 @@ private:
|
||||
|
||||
QualType getTypeDeclTypeSlow(const TypeDecl *Decl) const;
|
||||
|
||||
QualType getPipeType(QualType T, bool ReadOnly) const;
|
||||
|
||||
public:
|
||||
/// \brief Return the uniqued reference to the type for an address space
|
||||
/// qualified type with the specified type and address space.
|
||||
|
@ -5285,7 +5285,6 @@ class AtomicType : public Type, public llvm::FoldingSetNode {
|
||||
|
||||
/// PipeType - OpenCL20.
|
||||
class PipeType : public Type, public llvm::FoldingSetNode {
|
||||
protected:
|
||||
QualType ElementType;
|
||||
bool isRead;
|
||||
|
||||
@ -5295,6 +5294,7 @@ protected:
|
||||
elemType->isVariablyModifiedType(),
|
||||
elemType->containsUnexpandedParameterPack()),
|
||||
ElementType(elemType), isRead(isRead) {}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
|
||||
public:
|
||||
QualType getElementType() const { return ElementType; }
|
||||
@ -5304,11 +5304,12 @@ public:
|
||||
QualType desugar() const { return QualType(this, 0); }
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID &ID) {
|
||||
Profile(ID, getElementType());
|
||||
Profile(ID, getElementType(), isReadOnly());
|
||||
}
|
||||
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, QualType T) {
|
||||
static void Profile(llvm::FoldingSetNodeID &ID, QualType T, bool isRead) {
|
||||
ID.AddPointer(T.getAsOpaquePtr());
|
||||
ID.AddBoolean(isRead);
|
||||
}
|
||||
|
||||
static bool classof(const Type *T) {
|
||||
@ -5318,18 +5319,6 @@ public:
|
||||
bool isReadOnly() const { return isRead; }
|
||||
};
|
||||
|
||||
class ReadPipeType : public PipeType {
|
||||
ReadPipeType(QualType elemType, QualType CanonicalPtr) :
|
||||
PipeType(elemType, CanonicalPtr, true) {}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
};
|
||||
|
||||
class WritePipeType : public PipeType {
|
||||
WritePipeType(QualType elemType, QualType CanonicalPtr) :
|
||||
PipeType(elemType, CanonicalPtr, false) {}
|
||||
friend class ASTContext; // ASTContext creates these.
|
||||
};
|
||||
|
||||
/// A qualifier set is used to build a set of qualifiers.
|
||||
class QualifierCollector : public Qualifiers {
|
||||
public:
|
||||
|
@ -905,12 +905,10 @@ namespace clang {
|
||||
TYPE_DECAYED = 41,
|
||||
/// \brief An AdjustedType record.
|
||||
TYPE_ADJUSTED = 42,
|
||||
/// \brief A ReadPipeType record.
|
||||
TYPE_READ_PIPE = 43,
|
||||
/// \brief A PipeType record.
|
||||
TYPE_PIPE = 43,
|
||||
/// \brief An ObjCTypeParamType record.
|
||||
TYPE_OBJC_TYPE_PARAM = 44,
|
||||
/// \brief A WritePipeType record.
|
||||
TYPE_WRITE_PIPE = 45,
|
||||
TYPE_OBJC_TYPE_PARAM = 44
|
||||
};
|
||||
|
||||
/// \brief The type IDs for special types constructed by semantic
|
||||
|
@ -3338,54 +3338,37 @@ QualType ASTContext::getFunctionTypeInternal(
|
||||
return QualType(FTP, 0);
|
||||
}
|
||||
|
||||
QualType ASTContext::getReadPipeType(QualType T) const {
|
||||
QualType ASTContext::getPipeType(QualType T, bool ReadOnly) const {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
ReadPipeType::Profile(ID, T);
|
||||
PipeType::Profile(ID, T, ReadOnly);
|
||||
|
||||
void *InsertPos = 0;
|
||||
if (ReadPipeType *PT = ReadPipeTypes.FindNodeOrInsertPos(ID, InsertPos))
|
||||
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 = getReadPipeType(getCanonicalType(T));
|
||||
Canonical = getPipeType(getCanonicalType(T), ReadOnly);
|
||||
|
||||
// Get the new insert position for the node we care about.
|
||||
ReadPipeType *NewIP = ReadPipeTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
PipeType *NewIP = PipeTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
assert(!NewIP && "Shouldn't be in the map!");
|
||||
(void)NewIP;
|
||||
}
|
||||
ReadPipeType *New = new (*this, TypeAlignment) ReadPipeType(T, Canonical);
|
||||
PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical, ReadOnly);
|
||||
Types.push_back(New);
|
||||
ReadPipeTypes.InsertNode(New, InsertPos);
|
||||
PipeTypes.InsertNode(New, InsertPos);
|
||||
return QualType(New, 0);
|
||||
}
|
||||
|
||||
QualType ASTContext::getReadPipeType(QualType T) const {
|
||||
return getPipeType(T, true);
|
||||
}
|
||||
|
||||
QualType ASTContext::getWritePipeType(QualType T) const {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
WritePipeType::Profile(ID, T);
|
||||
|
||||
void *InsertPos = 0;
|
||||
if (WritePipeType *PT = WritePipeTypes.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 = getWritePipeType(getCanonicalType(T));
|
||||
|
||||
// Get the new insert position for the node we care about.
|
||||
WritePipeType *NewIP = WritePipeTypes.FindNodeOrInsertPos(ID, InsertPos);
|
||||
assert(!NewIP && "Shouldn't be in the map!");
|
||||
(void)NewIP;
|
||||
}
|
||||
WritePipeType *New = new (*this, TypeAlignment) WritePipeType(T, Canonical);
|
||||
Types.push_back(New);
|
||||
WritePipeTypes.InsertNode(New, InsertPos);
|
||||
return QualType(New, 0);
|
||||
return getPipeType(T, false);
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
@ -8260,22 +8243,9 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS,
|
||||
}
|
||||
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 isa<ReadPipeType>(LHS) ? getReadPipeType(ResultType)
|
||||
: getWritePipeType(ResultType);
|
||||
assert(LHS != RHS &&
|
||||
"Equivalent pipe types should have already been handled!");
|
||||
return QualType();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5793,27 +5793,18 @@ QualType ASTReader::readTypeRecord(unsigned Index) {
|
||||
return Context.getAtomicType(ValueType);
|
||||
}
|
||||
|
||||
case TYPE_READ_PIPE: {
|
||||
if (Record.size() != 1) {
|
||||
case TYPE_PIPE: {
|
||||
if (Record.size() != 2) {
|
||||
Error("Incorrect encoding of pipe type");
|
||||
return QualType();
|
||||
}
|
||||
|
||||
// Reading the pipe element type.
|
||||
QualType ElementType = readType(*Loc.F, Record, Idx);
|
||||
return Context.getReadPipeType(ElementType);
|
||||
unsigned ReadOnly = Record[1];
|
||||
return Context.getPipeType(ElementType, ReadOnly);
|
||||
}
|
||||
|
||||
case TYPE_WRITE_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.getWritePipeType(ElementType);
|
||||
}
|
||||
}
|
||||
llvm_unreachable("Invalid TypeCode!");
|
||||
}
|
||||
|
@ -516,10 +516,8 @@ ASTTypeWriter::VisitAtomicType(const AtomicType *T) {
|
||||
void
|
||||
ASTTypeWriter::VisitPipeType(const PipeType *T) {
|
||||
Record.AddTypeRef(T->getElementType());
|
||||
if (T->isReadOnly())
|
||||
Code = TYPE_READ_PIPE;
|
||||
else
|
||||
Code = TYPE_WRITE_PIPE;
|
||||
Record.push_back(T->isReadOnly());
|
||||
Code = TYPE_PIPE;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
@ -28,3 +28,12 @@ bool test_id_comprision(void) {
|
||||
reserve_id_t id1, id2;
|
||||
return (id1 == id2); // expected-error {{invalid operands to binary expression ('reserve_id_t' and 'reserve_id_t')}}
|
||||
}
|
||||
|
||||
// Tests ASTContext::mergeTypes rejects this.
|
||||
int f(pipe int x, int y); // expected-note {{previous declaration is here}}
|
||||
int f(x, y) // expected-error {{conflicting types for 'f}}
|
||||
pipe short x;
|
||||
int y;
|
||||
{
|
||||
return y;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user