[cfe-commits] r139265 - in /cfe/trunk: include/clang/Basic/IdentifierTable.h include/clang/Lex/Preprocessor.h lib/Lex/PPCaching.cpp lib/Lex/PPLexerChange.cpp lib/Lex/Preprocessor.cpp

Douglas Gregor dgregor at apple.com
Wed Sep 7 16:11:55 PDT 2011


Author: dgregor
Date: Wed Sep  7 18:11:54 2011
New Revision: 139265

URL: http://llvm.org/viewvc/llvm-project?rev=139265&view=rev
Log:
Optimize the preprocessor's handling of the __import_module__
keyword. We now handle this keyword in HandleIdentifier, making a note
for ourselves when we've seen the __import_module__ keyword so that
the next lexed token can trigger a module import (if needed). This
greatly simplifies Preprocessor::Lex(), and completely erases the 5.5%
-Eonly slowdown Argiris noted when I originally implemented
__import_module__. Big thanks to Argiris for noting that horrible
regression!


Modified:
    cfe/trunk/include/clang/Basic/IdentifierTable.h
    cfe/trunk/include/clang/Lex/Preprocessor.h
    cfe/trunk/lib/Lex/PPCaching.cpp
    cfe/trunk/lib/Lex/PPLexerChange.cpp
    cfe/trunk/lib/Lex/Preprocessor.cpp

Modified: cfe/trunk/include/clang/Basic/IdentifierTable.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/IdentifierTable.h?rev=139265&r1=139264&r2=139265&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/IdentifierTable.h (original)
+++ cfe/trunk/include/clang/Basic/IdentifierTable.h Wed Sep  7 18:11:54 2011
@@ -252,7 +252,7 @@
   void RecomputeNeedsHandleIdentifier() {
     NeedsHandleIdentifier =
       (isPoisoned() | hasMacroDefinition() | isCPlusPlusOperatorKeyword() |
-       isExtensionToken());
+       isExtensionToken() || (getTokenID() == tok::kw___import_module__));
   }
 };
 

Modified: cfe/trunk/include/clang/Lex/Preprocessor.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Lex/Preprocessor.h?rev=139265&r1=139264&r2=139265&view=diff
==============================================================================
--- cfe/trunk/include/clang/Lex/Preprocessor.h (original)
+++ cfe/trunk/include/clang/Lex/Preprocessor.h Wed Sep  7 18:11:54 2011
@@ -119,9 +119,6 @@
   /// \brief Whether we have already loaded macros from the external source.
   mutable bool ReadMacrosFromExternalSource : 1;
 
-  /// \brief Tracks the depth of Lex() Calls.
-  unsigned LexDepth;
-  
   /// Identifiers - This is mapping/lookup information for all identifiers in
   /// the program, including program keywords.
   mutable IdentifierTable Identifiers;
@@ -164,6 +161,10 @@
   /// for preprocessing.
   SourceLocation CodeCompletionFileLoc;
 
+  /// \brief The source location of the __import_module__ keyword we just
+  /// lexed, if any.
+  SourceLocation ModuleImportLoc;
+  
   /// \brief True if we hit the code-completion point.
   bool CodeCompletionReached;
 
@@ -187,7 +188,7 @@
   ///  if not expanding a macro.  This is an alias for either CurLexer or
   ///  CurPTHLexer.
   PreprocessorLexer *CurPPLexer;
-
+    
   /// CurLookup - The DirectoryLookup structure used to find the current
   /// FileEntry, if CurLexer is non-null and if applicable.  This allows us to
   /// implement #include_next and find directory-specific properties.
@@ -197,20 +198,31 @@
   /// expanding a macro.  One of CurLexer and CurTokenLexer must be null.
   llvm::OwningPtr<TokenLexer> CurTokenLexer;
 
+  /// \brief The kind of lexer we're currently working with.
+  enum CurLexerKind { 
+    CLK_Lexer, 
+    CLK_PTHLexer, 
+    CLK_TokenLexer, 
+    CLK_CachingLexer,
+    CLK_LexAfterModuleImport
+  } CurLexerKind;
+
   /// IncludeMacroStack - This keeps track of the stack of files currently
   /// #included, and macros currently being expanded from, not counting
   /// CurLexer/CurTokenLexer.
   struct IncludeStackInfo {
+    enum CurLexerKind     CurLexerKind;
     Lexer                 *TheLexer;
     PTHLexer              *ThePTHLexer;
     PreprocessorLexer     *ThePPLexer;
     TokenLexer            *TheTokenLexer;
     const DirectoryLookup *TheDirLookup;
 
-    IncludeStackInfo(Lexer *L, PTHLexer* P, PreprocessorLexer* PPL,
+    IncludeStackInfo(enum CurLexerKind K, Lexer *L, PTHLexer* P, 
+                     PreprocessorLexer* PPL,
                      TokenLexer* TL, const DirectoryLookup *D)
-      : TheLexer(L), ThePTHLexer(P), ThePPLexer(PPL), TheTokenLexer(TL),
-        TheDirLookup(D) {}
+      : CurLexerKind(K), TheLexer(L), ThePTHLexer(P), ThePPLexer(PPL), 
+        TheTokenLexer(TL), TheDirLookup(D) {}
   };
   std::vector<IncludeStackInfo> IncludeMacroStack;
 
@@ -555,22 +567,17 @@
   /// Lex - To lex a token from the preprocessor, just pull a token from the
   /// current lexer or macro object.
   void Lex(Token &Result) {
-    ++LexDepth;
-    if (CurLexer)
-      CurLexer->Lex(Result);
-    else if (CurPTHLexer)
-      CurPTHLexer->Lex(Result);
-    else if (CurTokenLexer)
-      CurTokenLexer->Lex(Result);
-    else
-      CachingLex(Result);
-    --LexDepth;
-    
-    // If we have the __import_module__ keyword, handle the module import now.
-    if (Result.getKind() == tok::kw___import_module__ && LexDepth == 0)
-      HandleModuleImport(Result);
+    switch (CurLexerKind) {
+    case CLK_Lexer: CurLexer->Lex(Result); break;
+    case CLK_PTHLexer: CurPTHLexer->Lex(Result); break;
+    case CLK_TokenLexer: CurTokenLexer->Lex(Result); break;
+    case CLK_CachingLexer: CachingLex(Result); break;
+    case CLK_LexAfterModuleImport: LexAfterModuleImport(Result); break;
+    }
   }
 
+  void LexAfterModuleImport(Token &Result);
+  
   /// LexNonComment - Lex a token.  If it's a comment, keep lexing until we get
   /// something not a comment.  This is useful in -E -C mode where comments
   /// would foul up preprocessor directive handling.
@@ -997,7 +1004,8 @@
 private:
 
   void PushIncludeMacroStack() {
-    IncludeMacroStack.push_back(IncludeStackInfo(CurLexer.take(),
+    IncludeMacroStack.push_back(IncludeStackInfo(CurLexerKind,
+                                                 CurLexer.take(),
                                                  CurPTHLexer.take(),
                                                  CurPPLexer,
                                                  CurTokenLexer.take(),
@@ -1011,6 +1019,7 @@
     CurPPLexer = IncludeMacroStack.back().ThePPLexer;
     CurTokenLexer.reset(IncludeMacroStack.back().TheTokenLexer);
     CurDirLookup  = IncludeMacroStack.back().TheDirLookup;
+    CurLexerKind = IncludeMacroStack.back().CurLexerKind;
     IncludeMacroStack.pop_back();
   }
 
@@ -1065,9 +1074,6 @@
   /// the macro should not be expanded return true, otherwise return false.
   bool HandleMacroExpandedIdentifier(Token &Tok, MacroInfo *MI);
 
-  /// \brief Handle a module import directive.
-  void HandleModuleImport(Token &Import);
-  
   /// \brief Cache macro expanded tokens for TokenLexers.
   //
   /// Works like a stack; a TokenLexer adds the macro expanded tokens that is

Modified: cfe/trunk/lib/Lex/PPCaching.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPCaching.cpp?rev=139265&r1=139264&r2=139265&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPCaching.cpp (original)
+++ cfe/trunk/lib/Lex/PPCaching.cpp Wed Sep  7 18:11:54 2011
@@ -74,6 +74,8 @@
     return;
 
   PushIncludeMacroStack();
+  if (CurLexerKind != CLK_LexAfterModuleImport)
+    CurLexerKind = CLK_CachingLexer;
 }
 
 

Modified: cfe/trunk/lib/Lex/PPLexerChange.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPLexerChange.cpp?rev=139265&r1=139264&r2=139265&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPLexerChange.cpp (original)
+++ cfe/trunk/lib/Lex/PPLexerChange.cpp Wed Sep  7 18:11:54 2011
@@ -113,7 +113,9 @@
   CurLexer.reset(TheLexer);
   CurPPLexer = TheLexer;
   CurDirLookup = CurDir;
-
+  if (CurLexerKind != CLK_LexAfterModuleImport)
+    CurLexerKind = CLK_Lexer;
+  
   // Notify the client, if desired, that we are in a new source file.
   if (Callbacks && !CurLexer->Is_PragmaLexer) {
     SrcMgr::CharacteristicKind FileType =
@@ -135,7 +137,9 @@
   CurDirLookup = CurDir;
   CurPTHLexer.reset(PL);
   CurPPLexer = CurPTHLexer.get();
-
+  if (CurLexerKind != CLK_LexAfterModuleImport)
+    CurLexerKind = CLK_PTHLexer;
+  
   // Notify the client, if desired, that we are in a new source file.
   if (Callbacks) {
     FileID FID = CurPPLexer->getFileID();
@@ -159,6 +163,8 @@
     CurTokenLexer.reset(TokenLexerCache[--NumCachedTokenLexers]);
     CurTokenLexer->Init(Tok, ILEnd, Args);
   }
+  if (CurLexerKind != CLK_LexAfterModuleImport)
+    CurLexerKind = CLK_TokenLexer;
 }
 
 /// EnterTokenStream - Add a "macro" context to the top of the include stack,
@@ -188,6 +194,8 @@
     CurTokenLexer.reset(TokenLexerCache[--NumCachedTokenLexers]);
     CurTokenLexer->Init(Toks, NumToks, DisableMacroExpansion, OwnsTokens);
   }
+  if (CurLexerKind != CLK_LexAfterModuleImport)
+    CurLexerKind = CLK_TokenLexer;
 }
 
 /// HandleEndOfFile - This callback is invoked when the lexer hits the end of

Modified: cfe/trunk/lib/Lex/Preprocessor.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/Preprocessor.cpp?rev=139265&r1=139264&r2=139265&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/Preprocessor.cpp (original)
+++ cfe/trunk/lib/Lex/Preprocessor.cpp Wed Sep  7 18:11:54 2011
@@ -144,8 +144,6 @@
   // We haven't read anything from the external source.
   ReadMacrosFromExternalSource = false;
   
-  LexDepth = 0;
-  
   // "Poison" __VA_ARGS__, which can only appear in the expansion of a macro.
   // This gets unpoisoned where it is allowed.
   (Ident__VA_ARGS__ = getIdentifierInfo("__VA_ARGS__"))->setIsPoisoned();
@@ -524,27 +522,44 @@
   // like "#define TY typeof", "TY(1) x".
   if (II.isExtensionToken() && !DisableMacroExpansion)
     Diag(Identifier, diag::ext_token_used);
+  
+  // If this is the '__import_module__' keyword, note that the next token
+  // indicates a module name.
+  if (II.getTokenID() == tok::kw___import_module__ &&
+      !InMacroArgs && !DisableMacroExpansion) {
+    ModuleImportLoc = Identifier.getLocation();
+    CurLexerKind = CLK_LexAfterModuleImport;
+  }
 }
 
-void Preprocessor::HandleModuleImport(Token &Import) {
+/// \brief Lex a token following the __import_module__ keyword.
+void Preprocessor::LexAfterModuleImport(Token &Result) {
+  // Figure out what kind of lexer we actually have.
+  if (CurLexer)
+    CurLexerKind = CLK_Lexer;
+  else if (CurPTHLexer)
+    CurLexerKind = CLK_PTHLexer;
+  else if (CurTokenLexer)
+    CurLexerKind = CLK_TokenLexer;
+  else 
+    CurLexerKind = CLK_CachingLexer;
+  
+  // Lex the next token.
+  Lex(Result);
+
   // The token sequence 
   //
   //   __import_module__ identifier
   //
-  // indicates a module import directive. We load the module and then 
-  // leave the token sequence for the parser.
-  Token ModuleNameTok = LookAhead(0);
-  if (ModuleNameTok.getKind() != tok::identifier)
+  // indicates a module import directive. We already saw the __import_module__
+  // keyword, so now we're looking for the identifier.
+  if (Result.getKind() != tok::identifier)
     return;
   
-  (void)TheModuleLoader.loadModule(Import.getLocation(),
-                                   *ModuleNameTok.getIdentifierInfo(), 
-                                   ModuleNameTok.getLocation());
-  
-  // FIXME: Transmogrify __import_module__ into some kind of AST-only 
-  // __import_module__ that is not recognized by the preprocessor but is 
-  // recognized by the parser. It would also be useful to stash the ModuleKey
-  // somewhere, so we don't try to load the module twice.
+  // Load the module.
+  (void)TheModuleLoader.loadModule(ModuleImportLoc,
+                                   *Result.getIdentifierInfo(), 
+                                   Result.getLocation());
 }
 
 void Preprocessor::AddCommentHandler(CommentHandler *Handler) {





More information about the cfe-commits mailing list