]> granicus.if.org Git - clang/commitdiff
Remove the PPID bitfield from IdentifierInfo, shrinking it by a word
authorChris Lattner <sabre@nondot.org>
Sun, 7 Oct 2007 07:52:34 +0000 (07:52 +0000)
committerChris Lattner <sabre@nondot.org>
Sun, 7 Oct 2007 07:52:34 +0000 (07:52 +0000)
(because all bitfields now fit in 32 bits).  This shrinks the identifier
table for carbon.h from 1634428 to 1451424 bytes (12%) and has no impact
on compile time.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42723 91177308-0d34-0410-b5e6-96231b3b80d8

Lex/IdentifierTable.cpp
include/clang/Basic/TokenKinds.def
include/clang/Lex/IdentifierTable.h

index b1c2c63f233fe6e756b85cfe2a3553039fe74c64..865356c7f3d89d68c2a2a39d7c600a046f3c7975 100644 (file)
@@ -59,7 +59,6 @@ tok::ObjCKeywordKind Token::getObjCKeywordID() const {
 
 IdentifierInfo::IdentifierInfo() {
   TokenID = tok::identifier;
-  PPID = tok::pp_not_keyword;
   ObjCID = tok::objc_not_keyword;
   BuiltinID = 0;
   HasMacro = false;
@@ -127,14 +126,6 @@ static void AddAlias(const char *Keyword, unsigned KWLen,
   AliasInfo.setIsExtensionToken(AliaseeInfo.isExtensionToken());
 }  
 
-/// AddPPKeyword - Register a preprocessor keyword like "define" "undef" or 
-/// "elif".
-static void AddPPKeyword(tok::PPKeywordKind PPID, 
-                         const char *Name, unsigned NameLen,
-                         IdentifierTable &Table) {
-  Table.get(Name, Name+NameLen).setPPKeywordID(PPID);
-}
-
 /// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
 /// representations.
 static void AddCXXOperatorKeyword(const char *Keyword, unsigned KWLen,
@@ -181,8 +172,6 @@ void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
              ((FLAGS) >> CPP0xShift) & Mask, LangOpts, *this);
 #define ALIAS(NAME, TOK) \
   AddAlias(NAME, strlen(NAME), #TOK, strlen(#TOK), LangOpts, *this);
-#define PPKEYWORD(NAME) \
-  AddPPKeyword(tok::pp_##NAME, #NAME, strlen(#NAME), *this);
 #define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
   if (LangOpts.CXXOperatorNames)          \
     AddCXXOperatorKeyword(#NAME, strlen(#NAME), tok::ALIAS, *this);
@@ -195,6 +184,51 @@ void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
 #include "clang/Basic/TokenKinds.def"
 }
 
+tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
+  // We use a perfect hash function here involving the length of the keyword,
+  // the first and third character.  For preprocessor ID's there are no
+  // collisions (if there were, the switch below would complain about duplicate
+  // case values).  Note that this depends on 'if' being null terminated.
+  
+#define HASH(LEN, FIRST, THIRD) \
+  (LEN << 5) + (((FIRST-'a') + (THIRD-'a')) & 31)
+#define CASE(LEN, FIRST, THIRD, NAME) \
+  case HASH(LEN, FIRST, THIRD): \
+    return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
+    
+  unsigned Len = getLength();
+  const char *Name = getName();
+  switch (HASH(Len, Name[0], Name[2])) {
+  default: return tok::pp_not_keyword;
+  CASE( 2, 'i', '\0', if);
+  CASE( 4, 'e', 'i', elif);
+  CASE( 4, 'e', 's', else);
+  CASE( 4, 'l', 'n', line);
+  CASE( 4, 's', 'c', sccs);
+  CASE( 5, 'e', 'd', endif);
+  CASE( 5, 'e', 'r', error);
+  CASE( 5, 'i', 'e', ident);
+  CASE( 5, 'i', 'd', ifdef);
+  CASE( 5, 'u', 'd', undef);
+
+  CASE( 6, 'a', 's', assert);
+  CASE( 6, 'd', 'f', define);
+  CASE( 6, 'i', 'n', ifndef);
+  CASE( 6, 'i', 'p', import);
+  CASE( 6, 'p', 'a', pragma);
+
+  CASE( 7, 'd', 'f', defined);
+  CASE( 7, 'i', 'c', include);
+  CASE( 7, 'w', 'r', warning);
+
+  CASE( 8, 'u', 'a', unassert);
+  CASE(12, 'i', 'c', include_next);
+  CASE(13, 'd', 'f', define_target);
+  CASE(19, 'd', 'f', define_other_target);
+#undef CASE
+#undef HASH
+  }
+}
 
 //===----------------------------------------------------------------------===//
 // Stats Implementation
index bd0b2fb32efdbab40a47da6bc3d75d5224332a99..d0eeada4740aafcec1ec9db22a90d6392298b9a9 100644 (file)
@@ -41,7 +41,8 @@
 //===----------------------------------------------------------------------===//
 
 // These have meaning after a '#' at the start of a line. These define enums in
-// the tok::pp_* namespace.
+// the tok::pp_* namespace.  Note that IdentifierInfo::getPPKeywordID must be
+// manually updated if something is added here.
 PPKEYWORD(not_keyword)
 
 // C99 6.10.1 - Conditional Inclusion.
index ed9f971f45339d9fde3d3a31cb29a6a5c6490f45..d987285df4d22527c1d0423c920f1209be402d24 100644 (file)
@@ -39,7 +39,6 @@ namespace clang {
 class IdentifierInfo {
   tok::TokenKind TokenID      : 8; // Front-end token ID or tok::identifier.
   unsigned BuiltinID          : 9; // ID if this is a builtin (__builtin_inf).
-  tok::PPKeywordKind PPID     : 5; // ID for preprocessor command like #'ifdef'.
   tok::ObjCKeywordKind ObjCID : 5; // ID for objc @ keyword like @'protocol'.
   bool HasMacro               : 1; // True if there is a #define for this.
   bool IsExtension            : 1; // True if identifier is a lang extension.
@@ -86,8 +85,7 @@ public:
   
   /// getPPKeywordID - Return the preprocessor keyword ID for this identifier.
   /// For example, define will return tok::pp_define.
-  tok::PPKeywordKind getPPKeywordID() const { return PPID; }
-  void setPPKeywordID(tok::PPKeywordKind ID) { PPID = ID; }
+  tok::PPKeywordKind getPPKeywordID() const;
   
   /// getObjCKeywordID - Return the Objective-C keyword ID for the this
   /// identifier.  For example, 'class' will return tok::objc_class if ObjC is