Add experimental support for address space qualified types. Address space
qualifiers use the __attribute__((address_space(id))) syntax.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46691 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/AST/ASTContext.cpp b/AST/ASTContext.cpp
index 96bf45d..823a20b 100644
--- a/AST/ASTContext.cpp
+++ b/AST/ASTContext.cpp
@@ -256,6 +256,8 @@
}
break;
}
+ case Type::ASQual:
+ return getTypeInfo(cast<ASQualType>(T)->getBaseType(), L);
case Type::ObjCQualifiedId:
Target.getPointerInfo(Size, Align, getFullLoc(L));
break;
@@ -368,6 +370,30 @@
// Type creation/memoization methods
//===----------------------------------------------------------------------===//
+QualType ASTContext::getASQualType(QualType T, unsigned AddressSpace) {
+ // Check if we've already instantiated an address space qual'd type of this type.
+ llvm::FoldingSetNodeID ID;
+ ASQualType::Profile(ID, T, AddressSpace);
+ void *InsertPos = 0;
+ if (ASQualType *ASQy = ASQualTypes.FindNodeOrInsertPos(ID, InsertPos))
+ return QualType(ASQy, 0);
+
+ // If the base 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 = getASQualType(T.getCanonicalType(), AddressSpace);
+
+ // Get the new insert position for the node we care about.
+ ASQualType *NewIP = ASQualTypes.FindNodeOrInsertPos(ID, InsertPos);
+ assert(NewIP == 0 && "Shouldn't be in the map!");
+ }
+ ASQualType *New = new ASQualType(T, Canonical, AddressSpace);
+ ASQualTypes.InsertNode(New, InsertPos);
+ Types.push_back(New);
+ return QualType(New, 0);
+}
+
/// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type.
@@ -817,7 +843,7 @@
return 4;
}
- const BuiltinType *BT = cast<BuiltinType>(t.getCanonicalType());
+ const BuiltinType *BT = t.getCanonicalType()->getAsBuiltinType();
switch (BT->getKind()) {
default:
assert(0 && "getIntegerRank(): not a built-in integer");
@@ -847,10 +873,10 @@
/// This routine will assert if passed a built-in type that isn't a float.
static int getFloatingRank(QualType T) {
T = T.getCanonicalType();
- if (ComplexType *CT = dyn_cast<ComplexType>(T))
+ if (const ComplexType *CT = T->getAsComplexType())
return getFloatingRank(CT->getElementType());
- switch (cast<BuiltinType>(T)->getKind()) {
+ switch (T->getAsBuiltinType()->getKind()) {
default: assert(0 && "getFloatingRank(): not a floating type");
case BuiltinType::Float: return FloatRank;
case BuiltinType::Double: return DoubleRank;
diff --git a/AST/Type.cpp b/AST/Type.cpp
index 6751a23..d3eb003 100644
--- a/AST/Type.cpp
+++ b/AST/Type.cpp
@@ -125,8 +125,12 @@
return BTy;
// If the canonical form of this type isn't a builtin type, reject it.
- if (!isa<BuiltinType>(CanonicalType))
+ if (!isa<BuiltinType>(CanonicalType)) {
+ // Look through type qualifiers
+ if (isa<BuiltinType>(CanonicalType.getUnqualifiedType()))
+ return CanonicalType.getUnqualifiedType()->getAsBuiltinType();
return 0;
+ }
// If this is a typedef for a builtin type, strip the typedef off without
// losing all typedef information.
@@ -137,10 +141,14 @@
// If this is directly a function type, return it.
if (const FunctionType *FTy = dyn_cast<FunctionType>(this))
return FTy;
-
+
// If the canonical form of this type isn't the right kind, reject it.
- if (!isa<FunctionType>(CanonicalType))
+ if (!isa<FunctionType>(CanonicalType)) {
+ // Look through type qualifiers
+ if (isa<FunctionType>(CanonicalType.getUnqualifiedType()))
+ return CanonicalType.getUnqualifiedType()->getAsFunctionType();
return 0;
+ }
// If this is a typedef for a function type, strip the typedef off without
// losing all typedef information.
@@ -153,8 +161,12 @@
return PTy;
// If the canonical form of this type isn't the right kind, reject it.
- if (!isa<PointerType>(CanonicalType))
+ if (!isa<PointerType>(CanonicalType)) {
+ // Look through type qualifiers
+ if (isa<PointerType>(CanonicalType.getUnqualifiedType()))
+ return CanonicalType.getUnqualifiedType()->getAsPointerType();
return 0;
+ }
// If this is a typedef for a pointer type, strip the typedef off without
// losing all typedef information.
@@ -167,8 +179,12 @@
return RTy;
// If the canonical form of this type isn't the right kind, reject it.
- if (!isa<ReferenceType>(CanonicalType))
+ if (!isa<ReferenceType>(CanonicalType)) {
+ // Look through type qualifiers
+ if (isa<ReferenceType>(CanonicalType.getUnqualifiedType()))
+ return CanonicalType.getUnqualifiedType()->getAsReferenceType();
return 0;
+ }
// If this is a typedef for a reference type, strip the typedef off without
// losing all typedef information.
@@ -181,8 +197,12 @@
return ATy;
// If the canonical form of this type isn't the right kind, reject it.
- if (!isa<ArrayType>(CanonicalType))
+ if (!isa<ArrayType>(CanonicalType)) {
+ // Look through type qualifiers
+ if (isa<ArrayType>(CanonicalType.getUnqualifiedType()))
+ return CanonicalType.getUnqualifiedType()->getAsArrayType();
return 0;
+ }
// If this is a typedef for an array type, strip the typedef off without
// losing all typedef information.
@@ -193,10 +213,14 @@
// If this is directly a constant array type, return it.
if (const ConstantArrayType *ATy = dyn_cast<ConstantArrayType>(this))
return ATy;
-
+
// If the canonical form of this type isn't the right kind, reject it.
- if (!isa<ConstantArrayType>(CanonicalType))
+ if (!isa<ConstantArrayType>(CanonicalType)) {
+ // Look through type qualifiers
+ if (isa<ConstantArrayType>(CanonicalType.getUnqualifiedType()))
+ return CanonicalType.getUnqualifiedType()->getAsConstantArrayType();
return 0;
+ }
// If this is a typedef for a constant array type, strip the typedef off
// without losing all typedef information.
@@ -209,8 +233,12 @@
return ATy;
// If the canonical form of this type isn't the right kind, reject it.
- if (!isa<VariableArrayType>(CanonicalType))
+ if (!isa<VariableArrayType>(CanonicalType)) {
+ // Look through type qualifiers
+ if (isa<VariableArrayType>(CanonicalType.getUnqualifiedType()))
+ return CanonicalType.getUnqualifiedType()->getAsVariableArrayType();
return 0;
+ }
// If this is a typedef for a variable array type, strip the typedef off
// without losing all typedef information.
@@ -257,8 +285,12 @@
return RTy;
// If the canonical form of this type isn't the right kind, reject it.
- if (!isa<RecordType>(CanonicalType))
+ if (!isa<RecordType>(CanonicalType)) {
+ // Look through type qualifiers
+ if (isa<RecordType>(CanonicalType.getUnqualifiedType()))
+ return CanonicalType.getUnqualifiedType()->getAsRecordType();
return 0;
+ }
// If this is a typedef for a record type, strip the typedef off without
// losing all typedef information.
@@ -281,6 +313,9 @@
// losing all typedef information.
return getDesugaredType()->getAsStructureType();
}
+ // Look through type qualifiers
+ if (isa<RecordType>(CanonicalType.getUnqualifiedType()))
+ return CanonicalType.getUnqualifiedType()->getAsStructureType();
return 0;
}
@@ -290,6 +325,7 @@
if (RT->getDecl()->getKind() == Decl::Union)
return RT;
}
+
// If the canonical form of this type isn't the right kind, reject it.
if (const RecordType *RT = dyn_cast<RecordType>(CanonicalType)) {
if (RT->getDecl()->getKind() != Decl::Union)
@@ -299,6 +335,10 @@
// losing all typedef information.
return getDesugaredType()->getAsUnionType();
}
+
+ // Look through type qualifiers
+ if (isa<RecordType>(CanonicalType.getUnqualifiedType()))
+ return CanonicalType.getUnqualifiedType()->getAsUnionType();
return 0;
}
@@ -308,8 +348,12 @@
return CTy;
// If the canonical form of this type isn't the right kind, reject it.
- if (!isa<ComplexType>(CanonicalType))
+ if (!isa<ComplexType>(CanonicalType)) {
+ // Look through type qualifiers
+ if (isa<ComplexType>(CanonicalType.getUnqualifiedType()))
+ return CanonicalType.getUnqualifiedType()->getAsComplexType();
return 0;
+ }
// If this is a typedef for a complex type, strip the typedef off without
// losing all typedef information.
@@ -322,8 +366,12 @@
return VTy;
// If the canonical form of this type isn't the right kind, reject it.
- if (!isa<VectorType>(CanonicalType))
+ if (!isa<VectorType>(CanonicalType)) {
+ // Look through type qualifiers
+ if (isa<VectorType>(CanonicalType.getUnqualifiedType()))
+ return CanonicalType.getUnqualifiedType()->getAsVectorType();
return 0;
+ }
// If this is a typedef for a vector type, strip the typedef off without
// losing all typedef information.
@@ -336,8 +384,12 @@
return VTy;
// If the canonical form of this type isn't the right kind, reject it.
- if (!isa<OCUVectorType>(CanonicalType))
+ if (!isa<OCUVectorType>(CanonicalType)) {
+ // Look through type qualifiers
+ if (isa<OCUVectorType>(CanonicalType.getUnqualifiedType()))
+ return CanonicalType.getUnqualifiedType()->getAsOCUVectorType();
return 0;
+ }
// If this is a typedef for an ocuvector type, strip the typedef off without
// losing all typedef information.
@@ -353,6 +405,8 @@
return true;
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isIntegerType();
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isIntegerType();
return false;
}
@@ -363,18 +417,24 @@
if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
if (TT->getDecl()->getKind() == Decl::Enum)
return true;
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isIntegralType();
return false;
}
bool Type::isEnumeralType() const {
if (const TagType *TT = dyn_cast<TagType>(CanonicalType))
return TT->getDecl()->getKind() == Decl::Enum;
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isEnumeralType();
return false;
}
bool Type::isBooleanType() const {
if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType))
return BT->getKind() == BuiltinType::Bool;
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isBooleanType();
return false;
}
@@ -384,6 +444,8 @@
BT->getKind() == BuiltinType::UChar ||
BT->getKind() == BuiltinType::Char_S ||
BT->getKind() == BuiltinType::SChar;
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isCharType();
return false;
}
@@ -403,6 +465,8 @@
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isSignedIntegerType();
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isSignedIntegerType();
return false;
}
@@ -422,6 +486,8 @@
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isUnsignedIntegerType();
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isUnsignedIntegerType();
return false;
}
@@ -433,6 +499,8 @@
return CT->getElementType()->isFloatingType();
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isFloatingType();
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isFloatingType();
return false;
}
@@ -442,6 +510,8 @@
BT->getKind() <= BuiltinType::LongDouble;
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isRealFloatingType();
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isRealFloatingType();
return false;
}
@@ -453,6 +523,8 @@
return TT->getDecl()->getKind() == Decl::Enum;
if (const VectorType *VT = dyn_cast<VectorType>(CanonicalType))
return VT->getElementType()->isRealType();
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isRealType();
return false;
}
@@ -464,6 +536,8 @@
// GCC allows forward declaration of enum types (forbid by C99 6.7.2.3p2).
// If a body isn't seen by the time we get here, return false.
return ED->isDefinition();
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isArithmeticType();
return isa<ComplexType>(CanonicalType) || isa<VectorType>(CanonicalType);
}
@@ -475,6 +549,8 @@
return true;
return false;
}
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isScalarType();
return isa<PointerType>(CanonicalType) || isa<ComplexType>(CanonicalType) ||
isa<ObjCQualifiedIdType>(CanonicalType);
}
@@ -485,6 +561,8 @@
return true;
return false;
}
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isAggregateType();
return CanonicalType->getTypeClass() == ConstantArray ||
CanonicalType->getTypeClass() == VariableArray;
}
@@ -493,6 +571,8 @@
/// according to the rules of C99 6.7.5p3. It is not legal to call this on
/// incomplete types.
bool Type::isConstantSizeType(ASTContext &Ctx) const {
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isConstantSizeType(Ctx);
assert(!isIncompleteType() && "This doesn't make sense for incomplete types");
// The VAT must have a size, as it is known to be complete.
return !isa<VariableArrayType>(CanonicalType);
@@ -504,6 +584,8 @@
bool Type::isIncompleteType() const {
switch (CanonicalType->getTypeClass()) {
default: return false;
+ case ASQual:
+ return cast<ASQualType>(CanonicalType)->getBaseType()->isIncompleteType();
case Builtin:
// Void is the only incomplete builtin type. Per C99 6.2.5p19, it can never
// be completed.
@@ -519,6 +601,8 @@
}
bool Type::isPromotableIntegerType() const {
+ if (const ASQualType *ASQT = dyn_cast<ASQualType>(CanonicalType))
+ return ASQT->getBaseType()->isPromotableIntegerType();
const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType);
if (!BT) return false;
switch (BT->getKind()) {
@@ -685,6 +769,11 @@
S = "_Complex " + S;
}
+void ASQualType::getAsStringInternal(std::string &S) const {
+ S = "__attribute__((address_space("+llvm::utostr_32(AddressSpace)+")))" + S;
+ BaseType->getAsStringInternal(S);
+}
+
void PointerType::getAsStringInternal(std::string &S) const {
S = '*' + S;
diff --git a/AST/TypeSerialization.cpp b/AST/TypeSerialization.cpp
index c6dee4e..7583a07 100644
--- a/AST/TypeSerialization.cpp
+++ b/AST/TypeSerialization.cpp
@@ -71,6 +71,10 @@
D.RegisterPtr(PtrID,Context.getTypes()[i]);
break;
+ case Type::ASQual:
+ D.RegisterPtr(PtrID,ASQualType::CreateImpl(Context,D));
+ break;
+
case Type::Complex:
D.RegisterPtr(PtrID,ComplexType::CreateImpl(Context,D));
break;
@@ -106,6 +110,21 @@
}
//===----------------------------------------------------------------------===//
+// ASQualType
+//===----------------------------------------------------------------------===//
+
+void ASQualType::EmitImpl(Serializer& S) const {
+ S.Emit(getBaseType());
+ S.EmitInt(getAddressSpace());
+}
+
+Type* ASQualType::CreateImpl(ASTContext& Context, Deserializer& D) {
+ QualType BaseTy = QualType::ReadVal(D);
+ unsigned AddressSpace = D.ReadInt();
+ return Context.getASQualType(BaseTy, AddressSpace).getTypePtr();
+}
+
+//===----------------------------------------------------------------------===//
// ComplexType
//===----------------------------------------------------------------------===//