Add experimental support for address space qualified types. Address space

qualifiers use the __attribute__((address_space(id))) syntax.

llvm-svn: 46691
This commit is contained in:
Christopher Lamb 2008-02-04 02:31:56 +00:00
parent e5b8b7db4a
commit 025b5fb883
12 changed files with 299 additions and 41 deletions

View File

@ -256,6 +256,8 @@ ASTContext::getTypeInfo(QualType T, SourceLocation L) {
}
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 @@ const ASTRecordLayout &ASTContext::getASTRecordLayout(const RecordDecl *D,
// 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 @@ static int getIntegerRank(QualType t) {
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 @@ static int getIntegerRank(QualType t) {
/// 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;

View File

@ -125,8 +125,12 @@ const BuiltinType *Type::getAsBuiltinType() const {
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 @@ const FunctionType *Type::getAsFunctionType() const {
// 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 @@ const PointerType *Type::getAsPointerType() const {
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 @@ const ReferenceType *Type::getAsReferenceType() const {
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 @@ const ArrayType *Type::getAsArrayType() const {
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 @@ const ConstantArrayType *Type::getAsConstantArrayType() const {
// 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 @@ const VariableArrayType *Type::getAsVariableArrayType() const {
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 @@ const RecordType *Type::getAsRecordType() const {
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 @@ const RecordType *Type::getAsStructureType() const {
// 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 @@ const RecordType *Type::getAsUnionType() const {
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 @@ const RecordType *Type::getAsUnionType() const {
// 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 @@ const ComplexType *Type::getAsComplexType() const {
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 @@ const VectorType *Type::getAsVectorType() const {
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 @@ const OCUVectorType *Type::getAsOCUVectorType() const {
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 @@ bool Type::isIntegerType() const {
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 @@ bool Type::isIntegralType() const {
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 @@ bool Type::isCharType() const {
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 @@ bool Type::isSignedIntegerType() const {
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 @@ bool Type::isUnsignedIntegerType() const {
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 @@ bool Type::isFloatingType() const {
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 @@ bool Type::isRealFloatingType() const {
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 @@ bool Type::isRealType() const {
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 @@ bool Type::isArithmeticType() const {
// 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 @@ bool Type::isScalarType() const {
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 @@ bool Type::isAggregateType() const {
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 @@ bool Type::isAggregateType() const {
/// 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::isConstantSizeType(ASTContext &Ctx) const {
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::isIncompleteType() const {
}
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 @@ void ComplexType::getAsStringInternal(std::string &S) const {
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;

View File

@ -71,6 +71,10 @@ void Type::Create(ASTContext& Context, unsigned i, Deserializer& D) {
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;
@ -105,6 +109,21 @@ void Type::Create(ASTContext& Context, unsigned i, Deserializer& D) {
}
}
//===----------------------------------------------------------------------===//
// 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
//===----------------------------------------------------------------------===//

View File

@ -84,7 +84,8 @@ void CodeGenFunction::EmitStaticBlockVarDecl(const BlockVarDecl &D) {
DMEntry =
new llvm::GlobalVariable(LTy, false,
llvm::GlobalValue::InternalLinkage,
Init, D.getName(), &CGM.getModule());
Init, D.getName(), &CGM.getModule(), 0,
Ty.getAddressSpace());
}

View File

@ -131,7 +131,8 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
llvm::Constant *&Entry = GlobalDeclMap[D];
if (Entry) return Entry;
const llvm::Type *Ty = getTypes().ConvertTypeForMem(D->getType());
QualType ASTTy = D->getType();
const llvm::Type *Ty = getTypes().ConvertTypeForMem(ASTTy);
// Check to see if the global already exists.
llvm::GlobalVariable *GV = getModule().getGlobalVariable(D->getName(), true);
@ -140,7 +141,8 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
if (GV == 0) {
return Entry = new llvm::GlobalVariable(Ty, false,
llvm::GlobalValue::ExternalLinkage,
0, D->getName(), &getModule());
0, D->getName(), &getModule(), 0,
ASTTy.getAddressSpace());
}
// If the pointer type matches, just return it.
@ -162,7 +164,8 @@ llvm::Constant *CodeGenModule::GetAddrOfGlobalVar(const VarDecl *D,
// making a new global of the correct type, RAUW, then steal the name.
llvm::GlobalVariable *NewGV =
new llvm::GlobalVariable(Ty, false, llvm::GlobalValue::ExternalLinkage,
0, D->getName(), &getModule());
0, D->getName(), &getModule(), 0,
ASTTy.getAddressSpace());
NewGV->takeName(GV);
// Replace uses of GV with the globalvalue we will endow with a body.

View File

@ -199,7 +199,8 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
}
case Type::Pointer: {
const PointerType &P = cast<PointerType>(Ty);
return llvm::PointerType::getUnqual(ConvertType(P.getPointeeType()));
QualType ETy = P.getPointeeType();
return llvm::PointerType::get(ConvertType(ETy), ETy.getAddressSpace());
}
case Type::Reference: {
const ReferenceType &R = cast<ReferenceType>(Ty);
@ -245,7 +246,8 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
// Struct return passes the struct byref.
if (!ResultType->isFirstClassType() && ResultType != llvm::Type::VoidTy) {
const llvm::Type *RType = llvm::PointerType::getUnqual(ResultType);
const llvm::Type *RType = llvm::PointerType::get(ResultType,
FP.getResultType().getAddressSpace());
QualType RTy = Context.getPointerType(FP.getResultType());
TypeHolderMap.insert(std::make_pair(RTy.getTypePtr(),
llvm::PATypeHolder(RType)));
@ -263,6 +265,10 @@ const llvm::Type *CodeGenTypes::ConvertNewType(QualType T) {
return llvm::FunctionType::get(ResultType, ArgTys, isVarArg);
}
case Type::ASQual:
return ConvertType(cast<ASQualType>(Ty).getBaseType());
break;
case Type::ObjCInterface:
assert(0 && "FIXME: add missing functionality here");
@ -386,8 +392,10 @@ void CodeGenTypes::DecodeArgumentTypes(const FunctionTypeProto &FTP,
if (Ty->isFirstClassType())
ArgTys.push_back(Ty);
else {
QualType PTy = Context.getPointerType(FTP.getArgType(i));
const llvm::Type *PtrTy = llvm::PointerType::getUnqual(Ty);
QualType ATy = FTP.getArgType(i);
QualType PTy = Context.getPointerType(ATy);
unsigned AS = ATy.getAddressSpace();
const llvm::Type *PtrTy = llvm::PointerType::get(Ty, AS);
TypeHolderMap.insert(std::make_pair(PTy.getTypePtr(),
llvm::PATypeHolder(PtrTy)));

View File

@ -245,7 +245,14 @@ private:
void HandleDeclAttributes(Decl *New, AttributeList *declspec_prefix,
AttributeList *declarator_postfix);
void HandleDeclAttribute(Decl *New, AttributeList *rawAttr);
/// HandleAddressSpaceTypeAttribute - this attribute is only applicable to
/// objects without automatic storage duration.
/// The raw attribute contains 1 argument, the id of the address space
/// for the type.
QualType HandleAddressSpaceTypeAttribute(QualType curType,
AttributeList *rawAttr);
// HandleVectorTypeAttribute - this attribute is only applicable to
// integral and float scalars, although arrays, pointers, and function
// return values are allowed in conjunction with this construct. Aggregates

View File

@ -1760,6 +1760,19 @@ void Sema::HandleDeclAttribute(Decl *New, AttributeList *rawAttr) {
else
Diag(rawAttr->getAttributeLoc(),
diag::err_typecheck_ocu_vector_not_typedef);
} else if (attrLen == 13 && !memcmp(attrName, "address_space", 13)) {
if (TypedefDecl *tDecl = dyn_cast<TypedefDecl>(New)) {
QualType newType = HandleAddressSpaceTypeAttribute(
tDecl->getUnderlyingType(),
rawAttr);
if (!newType.isNull()) // install the new addr spaced type into the decl
tDecl->setUnderlyingType(newType);
} else if (ValueDecl *vDecl = dyn_cast<ValueDecl>(New)) {
QualType newType = HandleAddressSpaceTypeAttribute(vDecl->getType(),
rawAttr);
if (!newType.isNull()) // install the new addr spaced type into the decl
vDecl->setType(newType);
}
} else if (attrLen == 7 && !memcmp(attrName, "aligned", 7)) {
HandleAlignedAttribute(New, rawAttr);
}
@ -1779,6 +1792,34 @@ void Sema::HandleDeclAttributes(Decl *New, AttributeList *declspec_prefix,
}
}
QualType Sema::HandleAddressSpaceTypeAttribute(QualType curType,
AttributeList *rawAttr) {
// check the attribute arugments.
if (rawAttr->getNumArgs() != 1) {
Diag(rawAttr->getAttributeLoc(), diag::err_attribute_wrong_number_arguments,
std::string("1"));
return QualType();
}
Expr *addrSpaceExpr = static_cast<Expr *>(rawAttr->getArg(0));
llvm::APSInt addrSpace(32);
if (!addrSpaceExpr->isIntegerConstantExpr(addrSpace, Context)) {
Diag(rawAttr->getAttributeLoc(), diag::err_attribute_address_space_not_int,
addrSpaceExpr->getSourceRange());
return QualType();
}
unsigned addressSpace = static_cast<unsigned>(addrSpace.getZExtValue());
// Zero is the default memory space, so no qualification is needed
if (addressSpace == 0)
return curType;
// TODO: Should we convert contained types of address space
// qualified types here or or where they directly participate in conversions
// (i.e. elsewhere)
return Context.getASQualType(curType, addressSpace);
}
void Sema::HandleOCUVectorTypeAttribute(TypedefDecl *tDecl,
AttributeList *rawAttr) {
QualType curType = tDecl->getUnderlyingType();

View File

@ -32,6 +32,7 @@ namespace clang {
/// decls) that can be referred to throughout the semantic analysis of a file.
class ASTContext {
std::vector<Type*> Types;
llvm::FoldingSet<ASQualType> ASQualTypes;
llvm::FoldingSet<ComplexType> ComplexTypes;
llvm::FoldingSet<PointerType> PointerTypes;
llvm::FoldingSet<ReferenceType> ReferenceTypes;
@ -120,6 +121,10 @@ public:
// Type Constructors
//===--------------------------------------------------------------------===//
/// getAddrSpaceQualType - Return the uniqued reference to the type for an
/// address space qualified type with the specified type and address space.
QualType getASQualType(QualType T, unsigned AddressSpace);
/// getComplexType - Return the uniqued reference to the type for a complex
/// number with the specified element type.
QualType getComplexType(QualType T);

View File

@ -50,6 +50,7 @@ namespace clang {
class FunctionType;
class OCUVectorType;
class BuiltinType;
class ASQualType;
class ObjCQualifiedInterfaceType;
class StmtIteratorBase;
@ -132,9 +133,7 @@ public:
return QualType(getTypePtr(), TQs);
}
QualType getUnqualifiedType() const {
return QualType(getTypePtr(), 0);
}
inline QualType getUnqualifiedType() const;
/// operator==/!= - Indicate whether the specified types and qualifiers are
/// identical.
@ -157,6 +156,9 @@ public:
/// appropriate type qualifiers on it.
inline QualType getCanonicalType() const;
/// getAddressSpace - Return the address space of this type.
inline unsigned getAddressSpace() const;
/// Emit - Serialize a QualType to Bitcode.
void Emit(llvm::Serializer& S) const;
@ -218,7 +220,7 @@ public:
ConstantArray, VariableArray,
Vector, OCUVector,
FunctionNoProto, FunctionProto,
TypeName, Tagged,
TypeName, Tagged, ASQual,
ObjCInterface, ObjCQualifiedInterface,
ObjCQualifiedId,
TypeOfExp, TypeOfTyp // GNU typeof extension.
@ -229,7 +231,7 @@ private:
/// TypeClass bitfield - Enum that specifies what subclass this belongs to.
/// Note that this should stay at the end of the ivars for Type so that
/// subclasses can pack their bitfields into the same word.
unsigned TC : 4;
unsigned TC : 5;
protected:
// silence VC++ warning C4355: 'this' : used in base member initializer list
Type *this_() { return this; }
@ -268,7 +270,7 @@ public:
bool isIncompleteArrayType() const;
/// Helper methods to distinguish type categories. All type predicates
/// operate on the canonical type, ignoring typedefs.
/// operate on the canonical type, ignoring typedefs and qualifiers.
/// isIntegerType() does *not* include complex integers (a GCC extension).
/// isComplexIntegerType() can be used to test for complex integers.
@ -292,7 +294,7 @@ public:
bool isAggregateType() const; // C99 6.2.5p21 (arrays, structures)
// Type Predicates: Check to see if this type is structurally the specified
// type, ignoring typedefs.
// type, ignoring typedefs and qualifiers.
bool isFunctionType() const;
bool isPointerType() const;
bool isFunctionPointerType() const;
@ -308,7 +310,7 @@ public:
bool isObjCQualifiedIdType() const; // id includes conforming protocol type
// Type Checking Functions: Check to see if this type is structurally the
// specified type, ignoring typedefs, and return a pointer to the best type
// specified type, ignoring typedefs and qualifiers, and return a pointer to the best type
// we can.
const BuiltinType *getAsBuiltinType() const;
const FunctionType *getAsFunctionType() const;
@ -373,6 +375,42 @@ protected:
virtual void EmitImpl(llvm::Serializer& S) const;
};
/// ASQualType - TR18037 (C embedded extensions) 6.2.5p26
/// This supports address space qualified types.
///
class ASQualType : public Type, public llvm::FoldingSetNode {
QualType BaseType;
/// Address Space ID - The address space ID this type is qualified with.
unsigned AddressSpace;
ASQualType(QualType Base, QualType CanonicalPtr, unsigned AddrSpace) :
Type(ASQual, CanonicalPtr), BaseType(Base), AddressSpace(AddrSpace) {
}
friend class ASTContext; // ASTContext creates these.
public:
QualType getBaseType() const { return BaseType; }
unsigned getAddressSpace() const { return AddressSpace; }
virtual void getAsStringInternal(std::string &InnerString) const;
void Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getBaseType(), AddressSpace);
}
static void Profile(llvm::FoldingSetNodeID &ID, QualType Base,
unsigned AddrSpace) {
ID.AddPointer(Base.getAsOpaquePtr());
ID.AddInteger(AddrSpace);
}
static bool classof(const Type *T) { return T->getTypeClass() == ASQual; }
static bool classof(const ASQualType *) { return true; }
protected:
virtual void EmitImpl(llvm::Serializer& S) const;
static Type* CreateImpl(ASTContext& Context,llvm::Deserializer& D);
friend class Type;
};
/// BuiltinType - This class is used for builtin types like 'int'. Builtin
/// types are always canonical and have a literal name field.
class BuiltinType : public Type {
@ -1036,12 +1074,25 @@ inline QualType QualType::getCanonicalType() const {
getTypePtr()->getCanonicalTypeInternal().getQualifiers());
}
/// getUnqualifiedType - Return the type without any qualifiers.
inline QualType QualType::getUnqualifiedType() const {
if (const ASQualType *ASQT = dyn_cast<ASQualType>(getTypePtr()))
return ASQT->getBaseType().getUnqualifiedType();
return QualType(getTypePtr(), 0);
}
/// getAddressSpace - Return the address space of this type.
inline unsigned QualType::getAddressSpace() const {
if (const ASQualType *ASQT = dyn_cast<ASQualType>(getTypePtr()))
return ASQT->getAddressSpace();
return 0;
}
inline bool Type::isFunctionType() const {
return isa<FunctionType>(CanonicalType);
return isa<FunctionType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isPointerType() const {
return isa<PointerType>(CanonicalType);
return isa<PointerType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isFunctionPointerType() const {
if (const PointerType* T = getAsPointerType())
@ -1050,19 +1101,19 @@ inline bool Type::isFunctionPointerType() const {
return false;
}
inline bool Type::isReferenceType() const {
return isa<ReferenceType>(CanonicalType);
return isa<ReferenceType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isArrayType() const {
return isa<ArrayType>(CanonicalType);
return isa<ArrayType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isRecordType() const {
return isa<RecordType>(CanonicalType);
return isa<RecordType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isVectorType() const {
return isa<VectorType>(CanonicalType);
return isa<VectorType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isOCUVectorType() const {
return isa<OCUVectorType>(CanonicalType);
return isa<OCUVectorType>(CanonicalType.getUnqualifiedType());
}
inline bool Type::isObjCInterfaceType() const {
return isa<ObjCInterfaceType>(CanonicalType)

View File

@ -575,6 +575,8 @@ DIAG(err_ocuvector_component_name_illegal, ERROR,
"illegal vector component name '%0'")
DIAG(err_ocuvector_component_access, ERROR,
"vector component access limited to variables")
DIAG(err_attribute_address_space_not_int, ERROR,
"address space attribute requires an integer constant")
// Function Parameter Semantic Analysis.
DIAG(err_param_with_void_type, ERROR,
@ -953,5 +955,4 @@ DIAG(ext_return_has_expr, EXTENSION,
"void function '%0' should not return a value")
#undef DIAG

View File

@ -0,0 +1,7 @@
// RUN: clang -emit-llvm < %s 2>&1 | grep 'addrspace(1)' | count 5
int foo __attribute__((address_space(1)));
int ban[10] __attribute__((address_space(1)));
int bar() { return foo; }
int baz(int i) { return ban[i]; }