forked from OSchip/llvm-project
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:
parent
e5b8b7db4a
commit
025b5fb883
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -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());
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)));
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]; }
|
Loading…
Reference in New Issue