[cfe-commits] r84293 - in /cfe/trunk: include/clang/Frontend/PCHBitCodes.h include/clang/Frontend/PCHWriter.h lib/Frontend/PCHReader.cpp lib/Frontend/PCHWriter.cpp lib/Frontend/PCHWriterDecl.cpp

Douglas Gregor dgregor at apple.com
Fri Oct 16 17:13:20 PDT 2009


Author: dgregor
Date: Fri Oct 16 19:13:19 2009
New Revision: 84293

URL: http://llvm.org/viewvc/llvm-project?rev=84293&view=rev
Log:
Merge the "types" and "declarations" blocks in the precompiled header
format, so that we don't end up with multiple declaration and types
blocks. Also, fix a few obscure bugs with PCH loading and generation:

  - If the DeclIDs DenseMap reallocates while we are writing a
    declaration (due to recursively writing other declarations), we
    could end up writing a bad ID to ExternalDefinitions.
  - When loading an ArrayLoc (part of DeclaratorInfo), we need to set
    the size expression to NULL if no size expression was provided.

PCH -> AST rewriting is still partly broken, unfortunately.

Modified:
    cfe/trunk/include/clang/Frontend/PCHBitCodes.h
    cfe/trunk/include/clang/Frontend/PCHWriter.h
    cfe/trunk/lib/Frontend/PCHReader.cpp
    cfe/trunk/lib/Frontend/PCHWriter.cpp
    cfe/trunk/lib/Frontend/PCHWriterDecl.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHBitCodes.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHBitCodes.h Fri Oct 16 19:13:19 2009
@@ -86,38 +86,33 @@
       PREPROCESSOR_BLOCK_ID,
 
       /// \brief The block containing the definitions of all of the
-      /// types used within the PCH file.
-      TYPES_BLOCK_ID,
-
-      /// \brief The block containing the definitions of all of the
-      /// declarations stored in the PCH file.
-      DECLS_BLOCK_ID
+      /// types and decls used within the PCH file.
+      DECLTYPES_BLOCK_ID
     };
 
     /// \brief Record types that occur within the PCH block itself.
     enum PCHRecordTypes {
-      /// \brief Offset of each type within the types block.
+      /// \brief Record code for the offsets of each type.
       ///
       /// The TYPE_OFFSET constant describes the record that occurs
-      /// within the block identified by TYPE_OFFSETS_BLOCK_ID within
-      /// the PCH file. The record itself is an array of offsets that
-      /// point into the types block (identified by TYPES_BLOCK_ID in
-      /// the PCH file). The index into the array is based on the ID
+      /// within the PCH block. The record itself is an array of offsets that
+      /// point into the declarations and types block (identified by 
+      /// DECLTYPES_BLOCK_ID). The index into the array is based on the ID
       /// of a type. For a given type ID @c T, the lower three bits of
       /// @c T are its qualifiers (const, volatile, restrict), as in
       /// the QualType class. The upper bits, after being shifted and
       /// subtracting NUM_PREDEF_TYPE_IDS, are used to index into the
       /// TYPE_OFFSET block to determine the offset of that type's
-      /// corresponding record within the TYPES_BLOCK_ID block.
+      /// corresponding record within the DECLTYPES_BLOCK_ID block.
       TYPE_OFFSET = 1,
 
       /// \brief Record code for the offsets of each decl.
       ///
       /// The DECL_OFFSET constant describes the record that occurs
-      /// within the block identifier by DECL_OFFSETS_BLOCK_ID within
-      /// the PCH file. The record itself is an array of offsets that
-      /// point into the declarations block (identified by
-      /// DECLS_BLOCK_ID). The declaration ID is an index into this
+      /// within the block identified by DECL_OFFSETS_BLOCK_ID within
+      /// the PCH block. The record itself is an array of offsets that
+      /// point into the declarations and types block (identified by
+      /// DECLTYPES_BLOCK_ID). The declaration ID is an index into this
       /// record, after subtracting one to account for the use of
       /// declaration ID 0 for a NULL declaration pointer. Index 0 is
       /// reserved for the translation unit declaration.
@@ -353,8 +348,8 @@
 
     /// \brief Record codes for each kind of type.
     ///
-    /// These constants describe the records that can occur within a
-    /// block identified by TYPES_BLOCK_ID in the PCH file. Each
+    /// These constants describe the type records that can occur within a
+    /// block identified by DECLTYPES_BLOCK_ID in the PCH file. Each
     /// constant describes a record for a specific type class in the
     /// AST.
     enum TypeCode {
@@ -444,13 +439,13 @@
 
     /// \brief Record codes for each kind of declaration.
     ///
-    /// These constants describe the records that can occur within a
-    /// declarations block (identified by DECLS_BLOCK_ID). Each
+    /// These constants describe the declaration records that can occur within
+    /// a declarations block (identified by DECLS_BLOCK_ID). Each
     /// constant describes a record for a specific declaration class
     /// in the AST.
     enum DeclCode {
       /// \brief Attributes attached to a declaration.
-      DECL_ATTR = 1,
+      DECL_ATTR = 50,
       /// \brief A TranslationUnitDecl record.
       DECL_TRANSLATION_UNIT,
       /// \brief A TypedefDecl record.
@@ -525,14 +520,14 @@
     /// \brief Record codes for each kind of statement or expression.
     ///
     /// These constants describe the records that describe statements
-    /// or expressions. These records can occur within either the type
-    /// or declaration blocks, so they begin with record values of
-    /// 50.  Each constant describes a record for a specific
-    /// statement or expression class in the AST.
+    /// or expressions. These records  occur within type and declarations
+    /// block, so they begin with record values of 100.  Each constant 
+    /// describes a record for a specific statement or expression class in the
+    /// AST.
     enum StmtCode {
       /// \brief A marker record that indicates that we are at the end
       /// of an expression.
-      STMT_STOP = 50,
+      STMT_STOP = 100,
       /// \brief A NULL expression.
       STMT_NULL_PTR,
       /// \brief A NullStmt record.

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

==============================================================================
--- cfe/trunk/include/clang/Frontend/PCHWriter.h (original)
+++ cfe/trunk/include/clang/Frontend/PCHWriter.h Fri Oct 16 19:13:19 2009
@@ -73,6 +73,33 @@
   /// \brief The bitstream writer used to emit this precompiled header.
   llvm::BitstreamWriter &Stream;
 
+  /// \brief Stores a declaration or a type to be written to the PCH file.
+  class DeclOrType {
+  public:
+    DeclOrType(Decl *D) : Stored(D), IsType(false) { }
+    DeclOrType(QualType T) : Stored(T.getAsOpaquePtr()), IsType(true) { }
+    
+    bool isType() const { return IsType; }
+    bool isDecl() const { return !IsType; }
+    
+    QualType getType() const {
+      assert(isType() && "Not a type!");
+      return QualType::getFromOpaquePtr(Stored);
+    }
+    
+    Decl *getDecl() const {
+      assert(isDecl() && "Not a decl!");
+      return static_cast<Decl *>(Stored);
+    }
+    
+  private:
+    void *Stored;
+    bool IsType;
+  };
+  
+  /// \brief The declarations and types to emit.
+  std::queue<DeclOrType> DeclTypesToEmit;
+  
   /// \brief Map that provides the ID numbers of each declaration within
   /// the output stream.
   ///
@@ -85,10 +112,6 @@
   /// the declaration's ID.
   std::vector<uint32_t> DeclOffsets;
 
-  /// \brief Queue containing the declarations that we still need to
-  /// emit.
-  std::queue<Decl *> DeclsToEmit;
-
   /// \brief Map that provides the ID numbers of each type within the
   /// output stream.
   ///
@@ -107,10 +130,6 @@
   /// \brief The type ID that will be assigned to the next new type.
   pch::TypeID NextTypeID;
 
-  /// \brief Queue containing the types that we still need to
-  /// emit.
-  std::queue<QualType> TypesToEmit;
-
   /// \brief Map that provides the ID numbers of each identifier in
   /// the output stream.
   ///
@@ -189,18 +208,17 @@
   void WritePreprocessor(const Preprocessor &PP);
   void WriteComments(ASTContext &Context);
   void WriteType(QualType T);
-  void WriteTypesBlock(ASTContext &Context);
   uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC);
   uint64_t WriteDeclContextVisibleBlock(ASTContext &Context, DeclContext *DC);
 
-  void WriteDeclsBlock(ASTContext &Context);
   void WriteMethodPool(Sema &SemaRef);
   void WriteIdentifierTable(Preprocessor &PP);
   void WriteAttributeRecord(const Attr *Attr);
 
   unsigned ParmVarDeclAbbrev;
   void WriteDeclsBlockAbbrevs();
-
+  void WriteDecl(ASTContext &Context, Decl *D);
+  
 public:
   /// \brief Create a new precompiled header writer that outputs to
   /// the given bitstream.

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

==============================================================================
--- cfe/trunk/lib/Frontend/PCHReader.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHReader.cpp Fri Oct 16 19:13:19 2009
@@ -382,7 +382,7 @@
 }
 
 Expr *PCHReader::ReadTypeExpr() {
-  return dyn_cast_or_null<Expr>(ReadStmt(Stream));
+  return dyn_cast_or_null<Expr>(ReadStmt(DeclsCursor));
 }
 
 
@@ -1157,15 +1157,7 @@
 
     if (Code == llvm::bitc::ENTER_SUBBLOCK) {
       switch (Stream.ReadSubBlockID()) {
-      case pch::TYPES_BLOCK_ID: // Skip types block (lazily loaded)
-      default:  // Skip unknown content.
-        if (Stream.SkipBlock()) {
-          Error("malformed block record in PCH file");
-          return Failure;
-        }
-        break;
-
-      case pch::DECLS_BLOCK_ID:
+      case pch::DECLTYPES_BLOCK_ID:
         // We lazily load the decls block, but we want to set up the
         // DeclsCursor cursor to point into it.  Clone our current bitcode
         // cursor to it, enter the block and read the abbrevs in that block.
@@ -1173,7 +1165,7 @@
         DeclsCursor = Stream;
         if (Stream.SkipBlock() ||  // Skip with the main cursor.
             // Read the abbrevs.
-            ReadBlockAbbrevs(DeclsCursor, pch::DECLS_BLOCK_ID)) {
+            ReadBlockAbbrevs(DeclsCursor, pch::DECLTYPES_BLOCK_ID)) {
           Error("malformed block record in PCH file");
           return Failure;
         }
@@ -1773,15 +1765,15 @@
 QualType PCHReader::ReadTypeRecord(uint64_t Offset) {
   // Keep track of where we are in the stream, then jump back there
   // after reading this type.
-  SavedStreamPosition SavedPosition(Stream);
+  SavedStreamPosition SavedPosition(DeclsCursor);
 
   // Note that we are loading a type record.
   LoadingTypeOrDecl Loading(*this);
 
-  Stream.JumpToBit(Offset);
+  DeclsCursor.JumpToBit(Offset);
   RecordData Record;
-  unsigned Code = Stream.ReadCode();
-  switch ((pch::TypeCode)Stream.ReadRecord(Code, Record)) {
+  unsigned Code = DeclsCursor.ReadCode();
+  switch ((pch::TypeCode)DeclsCursor.ReadRecord(Code, Record)) {
   case pch::TYPE_EXT_QUAL: {
     assert(Record.size() == 2 &&
            "Incorrect encoding of extended qualifier type");
@@ -2045,6 +2037,8 @@
   TyLoc.setRBracketLoc(SourceLocation::getFromRawEncoding(Record[Idx++]));
   if (Record[Idx++])
     TyLoc.setSizeExpr(Reader.ReadDeclExpr());
+  else
+    TyLoc.setSizeExpr(0);
 }
 
 DeclaratorInfo *PCHReader::GetDeclaratorInfo(const RecordData &Record,

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

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriter.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriter.cpp Fri Oct 16 19:13:19 2009
@@ -461,8 +461,8 @@
   RECORD(PP_MACRO_FUNCTION_LIKE);
   RECORD(PP_TOKEN);
 
-  // Types block.
-  BLOCK(TYPES_BLOCK);
+  // Decls and Types block.
+  BLOCK(DECLTYPES_BLOCK);
   RECORD(TYPE_EXT_QUAL);
   RECORD(TYPE_FIXED_WIDTH_INT);
   RECORD(TYPE_COMPLEX);
@@ -486,11 +486,6 @@
   RECORD(TYPE_OBJC_INTERFACE);
   RECORD(TYPE_OBJC_OBJECT_POINTER);
   RECORD(TYPE_OBJC_PROTOCOL_LIST);
-  // Statements and Exprs can occur in the Types block.
-  AddStmtsExprs(Stream, Record);
-
-  // Decls block.
-  BLOCK(DECLS_BLOCK);
   RECORD(DECL_ATTR);
   RECORD(DECL_TRANSLATION_UNIT);
   RECORD(DECL_TYPEDEF);
@@ -520,7 +515,7 @@
   RECORD(DECL_BLOCK);
   RECORD(DECL_CONTEXT_LEXICAL);
   RECORD(DECL_CONTEXT_VISIBLE);
-  // Statements and Exprs can occur in the Decls block.
+  // Statements and Exprs can occur in the Decls and Types block.
   AddStmtsExprs(Stream, Record);
 #undef RECORD
 #undef BLOCK
@@ -1201,22 +1196,6 @@
   FlushStmts();
 }
 
-/// \brief Write a block containing all of the types.
-void PCHWriter::WriteTypesBlock(ASTContext &Context) {
-  // Enter the types block.
-  Stream.EnterSubblock(pch::TYPES_BLOCK_ID, 2);
-
-  // Emit all of the types that need to be emitted (so far).
-  while (!TypesToEmit.empty()) {
-    QualType T = TypesToEmit.front();
-    TypesToEmit.pop();
-    WriteType(T);
-  }
-
-  // Exit the types block
-  Stream.ExitBlock();
-}
-
 //===----------------------------------------------------------------------===//
 // Declaration Serialization
 //===----------------------------------------------------------------------===//
@@ -1859,7 +1838,7 @@
 
   // The translation unit is the first declaration we'll emit.
   DeclIDs[Context.getTranslationUnitDecl()] = 1;
-  DeclsToEmit.push(Context.getTranslationUnitDecl());
+  DeclTypesToEmit.push(Context.getTranslationUnitDecl());
 
   // Make sure that we emit IdentifierInfos (and any attached
   // declarations) for builtins.
@@ -1928,13 +1907,18 @@
 
   // Keep writing types and declarations until all types and
   // declarations have been written.
-  do {
-    if (!DeclsToEmit.empty())
-      WriteDeclsBlock(Context);
-    if (!TypesToEmit.empty())
-      WriteTypesBlock(Context);
-  } while (!(DeclsToEmit.empty() && TypesToEmit.empty()));
-
+  Stream.EnterSubblock(pch::DECLTYPES_BLOCK_ID, 3);
+  WriteDeclsBlockAbbrevs();
+  while (!DeclTypesToEmit.empty()) {
+    DeclOrType DOT = DeclTypesToEmit.front();
+    DeclTypesToEmit.pop();
+    if (DOT.isType())
+      WriteType(DOT.getType());
+    else
+      WriteDecl(Context, DOT.getDecl());
+  }
+  Stream.ExitBlock();
+  
   WriteMethodPool(SemaRef);
   WriteIdentifierTable(PP);
 
@@ -2068,7 +2052,7 @@
       // Assign it a new ID.  This is the only time we enqueue a
       // qualified type, and it has no CV qualifiers.
       ID = NextTypeID++;
-      TypesToEmit.push(T);
+      DeclTypesToEmit.push(T);
     }
     
     // Encode the type qualifiers in the type reference.
@@ -2122,7 +2106,7 @@
     // We haven't seen this type before. Assign it a new ID and put it
     // into the queue of types to emit.
     ID = NextTypeID++;
-    TypesToEmit.push(T);
+    DeclTypesToEmit.push(T);
   }
 
   // Encode the type qualifiers in the type reference.
@@ -2140,7 +2124,7 @@
     // We haven't seen this declaration before. Give it a new ID and
     // enqueue it in the list of declarations to emit.
     ID = DeclIDs.size();
-    DeclsToEmit.push(const_cast<Decl *>(D));
+    DeclTypesToEmit.push(const_cast<Decl *>(D));
   }
 
   Record.push_back(ID);

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

==============================================================================
--- cfe/trunk/lib/Frontend/PCHWriterDecl.cpp (original)
+++ cfe/trunk/lib/Frontend/PCHWriterDecl.cpp Fri Oct 16 19:13:19 2009
@@ -535,80 +535,64 @@
   }
 }
 
-/// \brief Write a block containing all of the declarations.
-void PCHWriter::WriteDeclsBlock(ASTContext &Context) {
-  // Enter the declarations block.
-  Stream.EnterSubblock(pch::DECLS_BLOCK_ID, 3);
-
-  // Output the abbreviations that we will use in this block.
-  WriteDeclsBlockAbbrevs();
-
-  // Emit all of the declarations.
+void PCHWriter::WriteDecl(ASTContext &Context, Decl *D) {
   RecordData Record;
   PCHDeclWriter W(*this, Context, Record);
-  while (!DeclsToEmit.empty()) {
-    // Pull the next declaration off the queue
-    Decl *D = DeclsToEmit.front();
-    DeclsToEmit.pop();
-
-    // If this declaration is also a DeclContext, write blocks for the
-    // declarations that lexically stored inside its context and those
-    // declarations that are visible from its context. These blocks
-    // are written before the declaration itself so that we can put
-    // their offsets into the record for the declaration.
-    uint64_t LexicalOffset = 0;
-    uint64_t VisibleOffset = 0;
-    DeclContext *DC = dyn_cast<DeclContext>(D);
-    if (DC) {
-      LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
-      VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
-    }
-
-    // Determine the ID for this declaration
-    pch::DeclID &ID = DeclIDs[D];
-    if (ID == 0)
-      ID = DeclIDs.size();
-
-    unsigned Index = ID - 1;
-
-    // Record the offset for this declaration
-    if (DeclOffsets.size() == Index)
-      DeclOffsets.push_back(Stream.GetCurrentBitNo());
-    else if (DeclOffsets.size() < Index) {
-      DeclOffsets.resize(Index+1);
-      DeclOffsets[Index] = Stream.GetCurrentBitNo();
-    }
-
-    // Build and emit a record for this declaration
-    Record.clear();
-    W.Code = (pch::DeclCode)0;
-    W.AbbrevToUse = 0;
-    W.Visit(D);
-    if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
-
-    if (!W.Code) {
-      fprintf(stderr, "Cannot serialize declaration of kind %s\n",
-              D->getDeclKindName());
-      assert(false && "Unhandled declaration kind while generating PCH");
-      exit(-1);
-    }
-    Stream.EmitRecord(W.Code, Record, W.AbbrevToUse);
-
-    // If the declaration had any attributes, write them now.
-    if (D->hasAttrs())
-      WriteAttributeRecord(D->getAttrs());
-
-    // Flush any expressions that were written as part of this declaration.
-    FlushStmts();
-
-    // Note "external" declarations so that we can add them to a record in the
-    // PCH file later.
-    //
-    // FIXME: This should be renamed, the predicate is much more complicated.
-    if (isRequiredDecl(D, Context))
-      ExternalDefinitions.push_back(ID);
+
+  // If this declaration is also a DeclContext, write blocks for the
+  // declarations that lexically stored inside its context and those
+  // declarations that are visible from its context. These blocks
+  // are written before the declaration itself so that we can put
+  // their offsets into the record for the declaration.
+  uint64_t LexicalOffset = 0;
+  uint64_t VisibleOffset = 0;
+  DeclContext *DC = dyn_cast<DeclContext>(D);
+  if (DC) {
+    LexicalOffset = WriteDeclContextLexicalBlock(Context, DC);
+    VisibleOffset = WriteDeclContextVisibleBlock(Context, DC);
+  }
+
+  // Determine the ID for this declaration
+  pch::DeclID &ID = DeclIDs[D];
+  if (ID == 0)
+    ID = DeclIDs.size();
+
+  unsigned Index = ID - 1;
+
+  // Record the offset for this declaration
+  if (DeclOffsets.size() == Index)
+    DeclOffsets.push_back(Stream.GetCurrentBitNo());
+  else if (DeclOffsets.size() < Index) {
+    DeclOffsets.resize(Index+1);
+    DeclOffsets[Index] = Stream.GetCurrentBitNo();
+  }
+
+  // Build and emit a record for this declaration
+  Record.clear();
+  W.Code = (pch::DeclCode)0;
+  W.AbbrevToUse = 0;
+  W.Visit(D);
+  if (DC) W.VisitDeclContext(DC, LexicalOffset, VisibleOffset);
+
+  if (!W.Code) {
+    fprintf(stderr, "Cannot serialize declaration of kind %s\n",
+            D->getDeclKindName());
+    assert(false && "Unhandled declaration kind while generating PCH");
+    exit(-1);
   }
+  Stream.EmitRecord(W.Code, Record, W.AbbrevToUse);
 
-  // Exit the declarations block
-  Stream.ExitBlock();
+  // If the declaration had any attributes, write them now.
+  if (D->hasAttrs())
+    WriteAttributeRecord(D->getAttrs());
+
+  // Flush any expressions that were written as part of this declaration.
+  FlushStmts();
+
+  // Note "external" declarations so that we can add them to a record in the
+  // PCH file later.
+  //
+  // FIXME: This should be renamed, the predicate is much more complicated.
+  if (isRequiredDecl(D, Context))
+    ExternalDefinitions.push_back(Index + 1);
 }





More information about the cfe-commits mailing list