[cfe-commits] r46691 - in /cfe/trunk: AST/ASTContext.cpp AST/Type.cpp AST/TypeSerialization.cpp CodeGen/CGDecl.cpp CodeGen/CodeGenModule.cpp CodeGen/CodeGenTypes.cpp Sema/Sema.h Sema/SemaDecl.cpp include/clang/AST/ASTContext.h include/clang/AST/Type.h include/clang/Basic/DiagnosticKinds.def test/CodeGen/address-space.c

Christopher Lamb christopher.lamb at gmail.com
Sun Feb 3 18:31:57 PST 2008


Author: clamb
Date: Sun Feb  3 20:31:56 2008
New Revision: 46691

URL: http://llvm.org/viewvc/llvm-project?rev=46691&view=rev
Log:
Add experimental support for address space qualified types. Address space
qualifiers use the __attribute__((address_space(id))) syntax.

Added:
    cfe/trunk/test/CodeGen/address-space.c
Modified:
    cfe/trunk/AST/ASTContext.cpp
    cfe/trunk/AST/Type.cpp
    cfe/trunk/AST/TypeSerialization.cpp
    cfe/trunk/CodeGen/CGDecl.cpp
    cfe/trunk/CodeGen/CodeGenModule.cpp
    cfe/trunk/CodeGen/CodeGenTypes.cpp
    cfe/trunk/Sema/Sema.h
    cfe/trunk/Sema/SemaDecl.cpp
    cfe/trunk/include/clang/AST/ASTContext.h
    cfe/trunk/include/clang/AST/Type.h
    cfe/trunk/include/clang/Basic/DiagnosticKinds.def

Modified: cfe/trunk/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/ASTContext.cpp?rev=46691&r1=46690&r2=46691&view=diff

==============================================================================
--- cfe/trunk/AST/ASTContext.cpp (original)
+++ cfe/trunk/AST/ASTContext.cpp Sun Feb  3 20:31:56 2008
@@ -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;

Modified: cfe/trunk/AST/Type.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/Type.cpp?rev=46691&r1=46690&r2=46691&view=diff

==============================================================================
--- cfe/trunk/AST/Type.cpp (original)
+++ cfe/trunk/AST/Type.cpp Sun Feb  3 20:31:56 2008
@@ -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;
   

Modified: cfe/trunk/AST/TypeSerialization.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/AST/TypeSerialization.cpp?rev=46691&r1=46690&r2=46691&view=diff

==============================================================================
--- cfe/trunk/AST/TypeSerialization.cpp (original)
+++ cfe/trunk/AST/TypeSerialization.cpp Sun Feb  3 20:31:56 2008
@@ -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
 //===----------------------------------------------------------------------===//
 

Modified: cfe/trunk/CodeGen/CGDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CGDecl.cpp?rev=46691&r1=46690&r2=46691&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CGDecl.cpp (original)
+++ cfe/trunk/CodeGen/CGDecl.cpp Sun Feb  3 20:31:56 2008
@@ -84,7 +84,8 @@
   DMEntry = 
     new llvm::GlobalVariable(LTy, false, 
                             llvm::GlobalValue::InternalLinkage,
-                             Init, D.getName(), &CGM.getModule());
+                             Init, D.getName(), &CGM.getModule(), 0,
+                             Ty.getAddressSpace());
   
 }
   

Modified: cfe/trunk/CodeGen/CodeGenModule.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenModule.cpp?rev=46691&r1=46690&r2=46691&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenModule.cpp (original)
+++ cfe/trunk/CodeGen/CodeGenModule.cpp Sun Feb  3 20:31:56 2008
@@ -131,7 +131,8 @@
   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 @@
   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 @@
   // 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.

Modified: cfe/trunk/CodeGen/CodeGenTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/CodeGen/CodeGenTypes.cpp?rev=46691&r1=46690&r2=46691&view=diff

==============================================================================
--- cfe/trunk/CodeGen/CodeGenTypes.cpp (original)
+++ cfe/trunk/CodeGen/CodeGenTypes.cpp Sun Feb  3 20:31:56 2008
@@ -199,7 +199,8 @@
   }
   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 @@
     
     // 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 @@
     
     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 @@
     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)));
 

Modified: cfe/trunk/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/Sema.h?rev=46691&r1=46690&r2=46691&view=diff

==============================================================================
--- cfe/trunk/Sema/Sema.h (original)
+++ cfe/trunk/Sema/Sema.h Sun Feb  3 20:31:56 2008
@@ -245,7 +245,14 @@
   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

Modified: cfe/trunk/Sema/SemaDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Sema/SemaDecl.cpp?rev=46691&r1=46690&r2=46691&view=diff

==============================================================================
--- cfe/trunk/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/Sema/SemaDecl.cpp Sun Feb  3 20:31:56 2008
@@ -1760,6 +1760,19 @@
     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 @@
   }
 }
 
+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();

Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=46691&r1=46690&r2=46691&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Sun Feb  3 20:31:56 2008
@@ -32,6 +32,7 @@
 /// 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 @@
   //                           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);

Modified: cfe/trunk/include/clang/AST/Type.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/Type.h?rev=46691&r1=46690&r2=46691&view=diff

==============================================================================
--- cfe/trunk/include/clang/AST/Type.h (original)
+++ cfe/trunk/include/clang/AST/Type.h Sun Feb  3 20:31:56 2008
@@ -50,6 +50,7 @@
   class FunctionType;
   class OCUVectorType;
   class BuiltinType;
+  class ASQualType;
   class ObjCQualifiedInterfaceType;
   class StmtIteratorBase;
   
@@ -132,9 +133,7 @@
     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 @@
   /// 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 @@
     ConstantArray, VariableArray, 
     Vector, OCUVector,
     FunctionNoProto, FunctionProto,
-    TypeName, Tagged, 
+    TypeName, Tagged, ASQual,
     ObjCInterface, ObjCQualifiedInterface,
     ObjCQualifiedId,
     TypeOfExp, TypeOfTyp // GNU typeof extension.
@@ -229,7 +231,7 @@
   /// 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 @@
   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 @@
   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 @@
   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 @@
   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 @@
                   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 @@
     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)

Modified: cfe/trunk/include/clang/Basic/DiagnosticKinds.def
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticKinds.def?rev=46691&r1=46690&r2=46691&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticKinds.def (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticKinds.def Sun Feb  3 20:31:56 2008
@@ -575,6 +575,8 @@
      "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 @@
      "void function '%0' should not return a value")
 
 
-
 #undef DIAG

Added: cfe/trunk/test/CodeGen/address-space.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGen/address-space.c?rev=46691&view=auto

==============================================================================
--- cfe/trunk/test/CodeGen/address-space.c (added)
+++ cfe/trunk/test/CodeGen/address-space.c Sun Feb  3 20:31:56 2008
@@ -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]; }
\ No newline at end of file





More information about the cfe-commits mailing list