[cfe-commits] r69884 - in /cfe/trunk: include/clang/Basic/IdentifierTable.h include/clang/Frontend/PCHBitCodes.h include/clang/Frontend/PCHReader.h include/clang/Frontend/PCHWriter.h lib/Frontend/PCHReader.cpp lib/Frontend/PCHWriter.cpp test/PCH/objc_exprs.h test/PCH/objc_exprs.m

Steve Naroff snaroff at apple.com
Thu Apr 23 03:40:11 PDT 2009


Author: snaroff
Date: Thu Apr 23 05:39:46 2009
New Revision: 69884

URL: http://llvm.org/viewvc/llvm-project?rev=69884&view=rev
Log:
Add PCH read/write support for Objective-C Selectors.

Note: This support is non-lazy. Once we get "Cocoa.h" humming, we can optimize this.

Modified:
    cfe/trunk/include/clang/Basic/IdentifierTable.h
    cfe/trunk/include/clang/Frontend/PCHBitCodes.h
    cfe/trunk/include/clang/Frontend/PCHReader.h
    cfe/trunk/include/clang/Frontend/PCHWriter.h
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/test/PCH/objc_exprs.h
    cfe/trunk/test/PCH/objc_exprs.m

Modified: cfe/trunk/include/clang/Basic/IdentifierTable.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/IdentifierTable.h?rev=69884&r1=69883&r2=69884&view=diff

==============================================================================
--- cfe/trunk/include/clang/Basic/IdentifierTable.h (original)
+++ cfe/trunk/include/clang/Basic/IdentifierTable.h Thu Apr 23 05:39:46 2009
@@ -370,7 +370,6 @@
     InfoPtr = reinterpret_cast<uintptr_t>(SI);
     assert((InfoPtr & ArgFlags) == 0 &&"Insufficiently aligned IdentifierInfo");
   }
-  Selector(uintptr_t V) : InfoPtr(V) {}
   
   IdentifierInfo *getAsIdentifierInfo() const {
     if (getIdentifierInfoFlag())
@@ -388,6 +387,7 @@
   /// The default ctor should only be used when creating data structures that
   ///  will contain selectors.
   Selector() : InfoPtr(0) {}
+  Selector(uintptr_t V) : InfoPtr(V) {}
 
   /// operator==/!= - Indicate whether the specified selectors are identical.
   bool operator==(Selector RHS) const {

Modified: cfe/trunk/include/clang/Frontend/PCHBitCodes.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHBitCodes.h?rev=69884&r1=69883&r2=69884&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Thu Apr 23 05:39:46 2009
@@ -45,6 +45,8 @@
     /// file.
     typedef uint32_t IdentID;
 
+    typedef uint32_t SelectorID;
+    
     /// \brief Describes the various kinds of blocks that occur within
     /// a PCH file.
     enum BlockIDs {
@@ -66,7 +68,10 @@
 
       /// \brief The block containing the definitions of all of the
       /// declarations stored in the PCH file.
-      DECLS_BLOCK_ID
+      DECLS_BLOCK_ID,
+
+      /// \brief The block containing ObjC selectors stored in the PCH file.   
+      SELECTOR_BLOCK_ID
     };
 
     /// \brief Record types that occur within the PCH block itself.
@@ -160,7 +165,10 @@
 
       /// \brief Record code for the array of locally-scoped external
       /// declarations.
-      LOCALLY_SCOPED_EXTERNAL_DECLS = 11
+      LOCALLY_SCOPED_EXTERNAL_DECLS = 11,
+      
+      /// \brief Record code for the Objective-C Selector Table.
+      SELECTOR_TABLE = 12
     };
 
     /// \brief Record types used within a source manager block.

Modified: cfe/trunk/include/clang/Frontend/PCHReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHReader.h?rev=69884&r1=69883&r2=69884&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHReader.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHReader.h Thu Apr 23 05:39:46 2009
@@ -145,6 +145,9 @@
   /// an IdentifierInfo* that has already been resolved.
   llvm::SmallVector<uint64_t, 16> IdentifierData;
 
+  /// \brief SelectorData, indexed by the selector ID minus one.
+  llvm::SmallVector<Selector, 16> SelectorData;
+
   /// \brief The set of external definitions stored in the the PCH
   /// file.
   llvm::SmallVector<uint64_t, 16> ExternalDefinitions;
@@ -198,13 +201,15 @@
   /// \brief FIXME: document!
   llvm::SmallVector<uint64_t, 4> SpecialTypes;
 
-  PCHReadResult ReadPCHBlock(uint64_t &PreprocessorBlockOffset);
+  PCHReadResult ReadPCHBlock(uint64_t &PreprocessorBlockOffset,
+                             uint64_t &SelectorBlockOffset);
   bool CheckPredefinesBuffer(const char *PCHPredef, 
                              unsigned PCHPredefLen,
                              FileID PCHBufferID);
   PCHReadResult ReadSourceManagerBlock();
   bool ReadPreprocessorBlock();
-
+  bool ReadSelectorBlock();
+  
   bool ParseLanguageOptions(const llvm::SmallVectorImpl<uint64_t> &Record);
   QualType ReadTypeRecord(uint64_t Offset);
   void LoadedDecl(unsigned Index, Decl *D);
@@ -313,6 +318,12 @@
   IdentifierInfo *GetIdentifierInfo(const RecordData &Record, unsigned &Idx) {
     return DecodeIdentifierInfo(Record[Idx++]);
   }
+  
+  Selector DecodeSelector(unsigned Idx);
+  
+  Selector GetSelector(const RecordData &Record, unsigned &Idx) {
+    return DecodeSelector(Record[Idx++]);
+  }
   DeclarationName ReadDeclarationName(const RecordData &Record, unsigned &Idx);
 
   /// \brief Read an integral value

Modified: cfe/trunk/include/clang/Frontend/PCHWriter.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Frontend/PCHWriter.h?rev=69884&r1=69883&r2=69884&view=diff

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHWriter.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHWriter.h Thu Apr 23 05:39:46 2009
@@ -93,11 +93,17 @@
   /// discovery), starting at 1. An ID of zero refers to a NULL
   /// IdentifierInfo.
   llvm::DenseMap<const IdentifierInfo *, pch::IdentID> IdentifierIDs;
-
+  
   /// \brief Offsets of each of the identifier IDs into the identifier
   /// table, shifted left by one bit with the low bit set.
   llvm::SmallVector<uint64_t, 16> IdentifierOffsets;
 
+  /// \brief Map that provides the ID numbers of each Selector.
+  llvm::DenseMap<Selector, pch::SelectorID> SelectorIDs;
+  
+  /// \brief A vector of all Selectors (ordered by ID).
+  llvm::SmallVector<Selector, 16> SelVector;
+  
   /// \brief Offsets of each of the macro identifiers into the
   /// bitstream.
   ///
@@ -154,6 +160,7 @@
   uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
   void WriteDeclsBlock(ASTContext &Context);
   void WriteIdentifierTable(Preprocessor &PP);
+  void WriteSelectorTable();
   void WriteAttributeRecord(const Attr *Attr);
 
 public:
@@ -179,6 +186,9 @@
   /// \brief Emit a reference to an identifier
   void AddIdentifierRef(const IdentifierInfo *II, RecordData &Record);
 
+  /// \brief Emit a Selector (which is a smart pointer reference)
+  void AddSelectorRef(const Selector, RecordData &Record);
+  
   /// \brief Get the unique number used to refer to the given
   /// identifier.
   pch::IdentID getIdentifierRef(const IdentifierInfo *II);

Modified: cfe/trunk/lib/Frontend/PCHReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHReader.cpp?rev=69884&r1=69883&r2=69884&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Thu Apr 23 05:39:46 2009
@@ -1063,7 +1063,7 @@
 
 unsigned PCHStmtReader::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
   VisitExpr(E);
-  // FIXME: Selectors.
+  E->setSelector(Reader.GetSelector(Record, Idx));
   E->setAtLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
   E->setRParenLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
   return 0;
@@ -1586,8 +1586,69 @@
   }
 }
 
+bool PCHReader::ReadSelectorBlock() {
+  if (Stream.EnterSubBlock(pch::SELECTOR_BLOCK_ID))
+    return Error("Malformed selector block record");
+  
+  RecordData Record;
+  while (true) {
+    unsigned Code = Stream.ReadCode();
+    switch (Code) {
+    case llvm::bitc::END_BLOCK:
+      if (Stream.ReadBlockEnd())
+        return Error("Error at end of preprocessor block");
+      return false;
+    
+    case llvm::bitc::ENTER_SUBBLOCK:
+      // No known subblocks, always skip them.
+      Stream.ReadSubBlockID();
+      if (Stream.SkipBlock())
+        return Error("Malformed block record");
+      continue;
+    
+    case llvm::bitc::DEFINE_ABBREV:
+      Stream.ReadAbbrevRecord();
+      continue;
+    default: break;
+    }
+    
+    // Read a record.
+    Record.clear();
+    pch::PCHRecordTypes RecType =
+      (pch::PCHRecordTypes)Stream.ReadRecord(Code, Record);
+    switch (RecType) {
+    default:  // Default behavior: ignore unknown records.
+      break;
+    case pch::SELECTOR_TABLE:
+      unsigned Idx = 1; // Record[0] == pch::SELECTOR_TABLE.
+      unsigned NumSels = Record[Idx++];
+      
+      llvm::SmallVector<IdentifierInfo *, 8> KeyIdents;
+      for (unsigned SelIdx = 0; SelIdx < NumSels; SelIdx++) {
+        unsigned NumArgs = Record[Idx++];
+        KeyIdents.clear();
+        if (NumArgs <= 1) {
+          IdentifierInfo *II = DecodeIdentifierInfo(Record[Idx++]);
+          assert(II && "DecodeIdentifierInfo returned 0");
+          KeyIdents.push_back(II);
+        } else {
+          for (unsigned ArgIdx = 0; ArgIdx < NumArgs; ++ArgIdx) {
+            IdentifierInfo *II = DecodeIdentifierInfo(Record[Idx++]);
+            assert(II && "DecodeIdentifierInfo returned 0");
+            KeyIdents.push_back(II);
+          }
+        }
+        Selector Sel = PP.getSelectorTable().getSelector(NumArgs,&KeyIdents[0]);
+        SelectorData.push_back(Sel);
+      }
+    }
+  }
+  return false;
+}
+
 PCHReader::PCHReadResult 
-PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset) {
+PCHReader::ReadPCHBlock(uint64_t &PreprocessorBlockOffset,
+                        uint64_t &SelectorBlockOffset) {
   if (Stream.EnterSubBlock(pch::PCH_BLOCK_ID)) {
     Error("Malformed block record");
     return Failure;
@@ -1630,6 +1691,20 @@
           return Failure;
         }
         break;
+
+      case pch::SELECTOR_BLOCK_ID:
+        // Skip the selector block for now, but remember where it is.  We
+        // want to read it in after the identifier table.
+        if (SelectorBlockOffset) {
+          Error("Multiple selector blocks found.");
+          return Failure;
+        }
+        SelectorBlockOffset = Stream.GetCurrentBitNo();
+        if (Stream.SkipBlock()) {
+          Error("Malformed block record");
+          return Failure;
+        }
+        break;
           
       case pch::SOURCE_MANAGER_BLOCK_ID:
         switch (ReadSourceManagerBlock()) {
@@ -1740,7 +1815,6 @@
       TotalLexicalDeclContexts = Record[2];
       TotalVisibleDeclContexts = Record[3];
       break;
-
     case pch::TENTATIVE_DEFINITIONS:
       if (!TentativeDefinitions.empty()) {
         Error("Duplicate TENTATIVE_DEFINITIONS record in PCH file");
@@ -1758,7 +1832,6 @@
       break;
     }
   }
-
   Error("Premature end of bitstream");
   return Failure;
 }
@@ -1791,6 +1864,8 @@
   // We expect a number of well-defined blocks, though we don't necessarily
   // need to understand them all.
   uint64_t PreprocessorBlockOffset = 0;
+  uint64_t SelectorBlockOffset = 0;
+  
   while (!Stream.AtEndOfStream()) {
     unsigned Code = Stream.ReadCode();
     
@@ -1810,7 +1885,7 @@
       }
       break;
     case pch::PCH_BLOCK_ID:
-      switch (ReadPCHBlock(PreprocessorBlockOffset)) {
+      switch (ReadPCHBlock(PreprocessorBlockOffset, SelectorBlockOffset)) {
       case Success:
         break;
 
@@ -1882,6 +1957,14 @@
       return Failure;
     }
   }
+  if (SelectorBlockOffset) {
+    SavedStreamPosition SavedPos(Stream);
+    Stream.JumpToBit(SelectorBlockOffset);
+    if (ReadSelectorBlock()) {
+      Error("Malformed preprocessor block");
+      return Failure;
+    }
+  }
 
   return Success;
 }
@@ -2633,6 +2716,22 @@
   return reinterpret_cast<IdentifierInfo *>(IdentifierData[ID - 1]);
 }
 
+Selector PCHReader::DecodeSelector(unsigned ID) {
+  if (ID == 0)
+    return Selector();
+  
+  if (SelectorData.empty()) {
+    Error("No selector table in PCH file");
+    return Selector();
+  }
+  
+  if (ID > SelectorData.size()) {
+    Error("Selector ID out of range");
+    return Selector();
+  }
+  return SelectorData[ID-1];
+}
+
 DeclarationName 
 PCHReader::ReadDeclarationName(const RecordData &Record, unsigned &Idx) {
   DeclarationName::NameKind Kind = (DeclarationName::NameKind)Record[Idx++];

Modified: cfe/trunk/lib/Frontend/PCHWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/PCHWriter.cpp?rev=69884&r1=69883&r2=69884&view=diff

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Thu Apr 23 05:39:46 2009
@@ -1182,9 +1182,7 @@
 
 void PCHStmtWriter::VisitObjCSelectorExpr(ObjCSelectorExpr *E) {
   VisitExpr(E);
-  assert(0 && "Can't write a selector yet!");
-  // FIXME!  Write selectors.
-  //Writer.WriteSubStmt(E->getSelector());
+  Writer.AddSelectorRef(E->getSelector(), Record);
   Writer.AddSourceLocation(E->getAtLoc(), Record);
   Writer.AddSourceLocation(E->getRParenLoc(), Record);
   Code = pch::EXPR_OBJC_SELECTOR_EXPR;
@@ -1888,6 +1886,26 @@
   Stream.EmitRecord(pch::IDENTIFIER_OFFSET, IdentifierOffsets);
 }
 
+void PCHWriter::WriteSelectorTable() {
+  Stream.EnterSubblock(pch::SELECTOR_BLOCK_ID, 3);
+  RecordData Record;
+  Record.push_back(pch::SELECTOR_TABLE);
+  Record.push_back(SelectorIDs.size());
+  
+  // Create the on-disk representation.
+  for (unsigned selIdx = 0; selIdx < SelVector.size(); selIdx++) {
+    assert(SelVector[selIdx].getAsOpaquePtr() && "NULL Selector found");
+    Record.push_back(SelVector[selIdx].getNumArgs());
+    if (SelVector[selIdx].getNumArgs())
+      for (unsigned i = 0; i < SelVector[selIdx].getNumArgs(); i++)
+        AddIdentifierRef(SelVector[selIdx].getIdentifierInfoForSlot(i), Record);
+    else
+      AddIdentifierRef(SelVector[selIdx].getIdentifierInfoForSlot(0), Record);
+  }
+  Stream.EmitRecord(pch::SELECTOR_TABLE, Record);
+  Stream.ExitBlock();
+}
+
 /// \brief Write a record containing the given attributes.
 void PCHWriter::WriteAttributeRecord(const Attr *Attr) {
   RecordData Record;
@@ -2078,6 +2096,7 @@
   WritePreprocessor(PP);
   WriteTypesBlock(Context);
   WriteDeclsBlock(Context);
+  WriteSelectorTable();
   WriteIdentifierTable(PP);
   Stream.EmitRecord(pch::TYPE_OFFSET, TypeOffsets);
   Stream.EmitRecord(pch::DECL_OFFSET, DeclOffsets);
@@ -2145,6 +2164,20 @@
   return ID;
 }
 
+void PCHWriter::AddSelectorRef(const Selector SelRef, RecordData &Record) {
+  if (SelRef.getAsOpaquePtr() == 0) {
+    Record.push_back(0);
+    return;
+  }
+
+  pch::SelectorID &SID = SelectorIDs[SelRef];
+  if (SID == 0) {
+    SID = SelectorIDs.size();
+    SelVector.push_back(SelRef);
+  }
+  Record.push_back(SID);
+}
+
 void PCHWriter::AddTypeRef(QualType T, RecordData &Record) {
   if (T.isNull()) {
     Record.push_back(pch::PREDEF_TYPE_NULL_ID);
@@ -2223,7 +2256,7 @@
   case DeclarationName::ObjCZeroArgSelector:
   case DeclarationName::ObjCOneArgSelector:
   case DeclarationName::ObjCMultiArgSelector:
-    assert(false && "Serialization of Objective-C selectors unavailable");
+    AddSelectorRef(Name.getObjCSelector(), Record);
     break;
 
   case DeclarationName::CXXConstructorName:

Modified: cfe/trunk/test/PCH/objc_exprs.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/objc_exprs.h?rev=69884&r1=69883&r2=69884&view=diff

==============================================================================
--- cfe/trunk/test/PCH/objc_exprs.h (original)
+++ cfe/trunk/test/PCH/objc_exprs.h Thu Apr 23 05:39:46 2009
@@ -6,6 +6,9 @@
 typedef typeof(@"foo" "bar") objc_string;
 typedef typeof(@encode(int)) objc_encode;
 typedef typeof(@protocol(foo)) objc_protocol;
+typedef typeof(@selector(noArgs)) objc_selector_noArgs;
+typedef typeof(@selector(oneArg:)) objc_selector_oneArg;
+typedef typeof(@selector(foo:bar:)) objc_selector_twoArg;
 
 
 // Types.

Modified: cfe/trunk/test/PCH/objc_exprs.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/PCH/objc_exprs.m?rev=69884&r1=69883&r2=69884&view=diff

==============================================================================
--- cfe/trunk/test/PCH/objc_exprs.m (original)
+++ cfe/trunk/test/PCH/objc_exprs.m Thu Apr 23 05:39:46 2009
@@ -21,3 +21,8 @@
 int *T1 = (objc_interface_ty)0; // expected-warning {{aka 'itf *'}}
 int *T2 = (objc_qual_interface_ty)0; // expected-warning {{aka 'itf<foo> *'}}
 
+objc_selector_noArgs s1;
+objc_selector_oneArg s2;
+objc_selector_twoArg s3;
+
+





More information about the cfe-commits mailing list