blob: eaa0f1a5bb908a40f9cba4dba45211c1f87cef3d [file] [log] [blame]
Chris Lattnerec659fc2006-10-29 22:09:44 +00001//===--- IdentifierTable.cpp - Hash table for identifier lookup -----------===//
Chris Lattner22eb9722006-06-18 05:43:12 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
Chris Lattnerc79f6fb2006-07-04 17:53:21 +000010// This file implements the IdentifierInfo, IdentifierVisitor, and
Chris Lattner91cbf112006-07-03 04:28:52 +000011// IdentifierTable interfaces.
Chris Lattner22eb9722006-06-18 05:43:12 +000012//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Lex/IdentifierTable.h"
16#include "clang/Lex/MacroInfo.h"
Chris Lattner25e0d542006-10-18 06:07:05 +000017#include "clang/Basic/LangOptions.h"
Chris Lattner22eb9722006-06-18 05:43:12 +000018#include <iostream>
19using namespace llvm;
20using namespace clang;
21
22//===----------------------------------------------------------------------===//
Chris Lattnerc79f6fb2006-07-04 17:53:21 +000023// IdentifierInfo Implementation
Chris Lattner22eb9722006-06-18 05:43:12 +000024//===----------------------------------------------------------------------===//
25
Chris Lattner3bc804e2006-10-28 23:46:24 +000026IdentifierInfo::IdentifierInfo() {
27 Macro = 0;
28 TokenID = tok::identifier;
29 PPID = tok::pp_not_keyword;
30 ObjCID = tok::objc_not_keyword;
31 IsExtension = false;
32 IsPoisoned = false;
33 IsOtherTargetMacro = false;
34 FETokenInfo = 0;
35}
36
37IdentifierInfo::~IdentifierInfo() {
Chris Lattner22eb9722006-06-18 05:43:12 +000038 delete Macro;
39}
40
Chris Lattner91cbf112006-07-03 04:28:52 +000041//===----------------------------------------------------------------------===//
Chris Lattner22eb9722006-06-18 05:43:12 +000042// IdentifierTable Implementation
43//===----------------------------------------------------------------------===//
44
Chris Lattner2b9e19b2006-10-29 23:43:13 +000045IdentifierTable::IdentifierTable(const LangOptions &LangOpts)
46 // Start with space for 8K identifiers.
47 : HashTable(8192) {
Chris Lattnerda933aa2006-10-29 23:49:15 +000048
Chris Lattnerf2e3ac32006-10-27 03:59:10 +000049 // Populate the identifier table with info about keywords for the current
50 // language.
Chris Lattner25e0d542006-10-18 06:07:05 +000051 AddKeywords(LangOpts);
Chris Lattner91cbf112006-07-03 04:28:52 +000052}
Chris Lattner22eb9722006-06-18 05:43:12 +000053
Chris Lattner25e0d542006-10-18 06:07:05 +000054//===----------------------------------------------------------------------===//
55// Language Keyword Implementation
56//===----------------------------------------------------------------------===//
57
58/// AddKeyword - This method is used to associate a token ID with specific
59/// identifiers because they are language keywords. This causes the lexer to
60/// automatically map matching identifiers to specialized token codes.
61///
62/// The C90/C99/CPP flags are set to 0 if the token should be enabled in the
63/// specified langauge, set to 1 if it is an extension in the specified
64/// language, and set to 2 if disabled in the specified language.
Chris Lattner2b9e19b2006-10-29 23:43:13 +000065static void AddKeyword(const char *Keyword, unsigned KWLen,
66 tok::TokenKind TokenCode,
Chris Lattnera4271e42006-10-20 06:13:26 +000067 int C90, int C99, int CXX,
Chris Lattner25e0d542006-10-18 06:07:05 +000068 const LangOptions &LangOpts, IdentifierTable &Table) {
Chris Lattnera4271e42006-10-20 06:13:26 +000069 int Flags = LangOpts.CPlusPlus ? CXX : (LangOpts.C99 ? C99 : C90);
Chris Lattner25e0d542006-10-18 06:07:05 +000070
71 // Don't add this keyword if disabled in this language or if an extension
72 // and extensions are disabled.
73 if (Flags + LangOpts.NoExtensions >= 2) return;
74
Chris Lattner2b9e19b2006-10-29 23:43:13 +000075 IdentifierInfo &Info = Table.get(Keyword, Keyword+KWLen);
Chris Lattner25e0d542006-10-18 06:07:05 +000076 Info.setTokenID(TokenCode);
77 Info.setIsExtensionToken(Flags == 1);
78}
79
80/// AddPPKeyword - Register a preprocessor keyword like "define" "undef" or
81/// "elif".
82static void AddPPKeyword(tok::PPKeywordKind PPID,
83 const char *Name, unsigned NameLen,
84 IdentifierTable &Table) {
85 Table.get(Name, Name+NameLen).setPPKeywordID(PPID);
86}
87
88/// AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or
89/// "property".
90static void AddObjCKeyword(tok::ObjCKeywordKind ObjCID,
91 const char *Name, unsigned NameLen,
92 IdentifierTable &Table) {
93 Table.get(Name, Name+NameLen).setObjCKeywordID(ObjCID);
94}
95
96/// AddKeywords - Add all keywords to the symbol table.
97///
98void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
99 enum {
100 C90Shift = 0,
101 EXTC90 = 1 << C90Shift,
102 NOTC90 = 2 << C90Shift,
103 C99Shift = 2,
104 EXTC99 = 1 << C99Shift,
105 NOTC99 = 2 << C99Shift,
106 CPPShift = 4,
107 EXTCPP = 1 << CPPShift,
108 NOTCPP = 2 << CPPShift,
109 Mask = 3
110 };
111
112 // Add keywords and tokens for the current language.
113#define KEYWORD(NAME, FLAGS) \
Chris Lattner2b9e19b2006-10-29 23:43:13 +0000114 AddKeyword(#NAME, strlen(#NAME), tok::kw_ ## NAME, \
Chris Lattner25e0d542006-10-18 06:07:05 +0000115 ((FLAGS) >> C90Shift) & Mask, \
116 ((FLAGS) >> C99Shift) & Mask, \
117 ((FLAGS) >> CPPShift) & Mask, LangOpts, *this);
118#define ALIAS(NAME, TOK) \
Chris Lattner2b9e19b2006-10-29 23:43:13 +0000119 AddKeyword(NAME, strlen(NAME), tok::kw_ ## TOK, 0, 0, 0, LangOpts, *this);
Chris Lattner25e0d542006-10-18 06:07:05 +0000120#define PPKEYWORD(NAME) \
121 AddPPKeyword(tok::pp_##NAME, #NAME, strlen(#NAME), *this);
122#define OBJC1_AT_KEYWORD(NAME) \
123 if (LangOpts.ObjC1) \
124 AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
125#define OBJC2_AT_KEYWORD(NAME) \
126 if (LangOpts.ObjC2) \
127 AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
128#include "clang/Basic/TokenKinds.def"
129}
130
131
132//===----------------------------------------------------------------------===//
133// Stats Implementation
134//===----------------------------------------------------------------------===//
135
Chris Lattner2b9e19b2006-10-29 23:43:13 +0000136class StatsVisitor : public CStringMapVisitor {
137 unsigned &IDLenTotal;
138 unsigned &MaxIDLen;
139public:
140 StatsVisitor(unsigned &idLenTotal, unsigned &maxIDLen)
141 : IDLenTotal(idLenTotal), MaxIDLen(maxIDLen) {}
142 void Visit(const char *Key, void *Value) const {
143 unsigned IdLen = strlen(Key);
144 IDLenTotal += IdLen;
145 if (MaxIDLen < IdLen)
146 MaxIDLen = IdLen;
147 }
148};
149
150
Chris Lattner22eb9722006-06-18 05:43:12 +0000151/// PrintStats - Print statistics about how well the identifier table is doing
152/// at hashing identifiers.
153void IdentifierTable::PrintStats() const {
Chris Lattner2b9e19b2006-10-29 23:43:13 +0000154 unsigned NumBuckets = HashTable.getNumBuckets();
155 unsigned NumIdentifiers = HashTable.getNumItems();
156 unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
Chris Lattner22eb9722006-06-18 05:43:12 +0000157 unsigned AverageIdentifierSize = 0;
158 unsigned MaxIdentifierLength = 0;
159
Chris Lattner2b9e19b2006-10-29 23:43:13 +0000160 // TODO: Figure out maximum times an identifier had to probe for -stats.
161 HashTable.VisitEntries(StatsVisitor(AverageIdentifierSize,
162 MaxIdentifierLength));
Chris Lattner22eb9722006-06-18 05:43:12 +0000163
164 std::cerr << "\n*** Identifier Table Stats:\n";
165 std::cerr << "# Identifiers: " << NumIdentifiers << "\n";
166 std::cerr << "# Empty Buckets: " << NumEmptyBuckets << "\n";
Chris Lattner22eb9722006-06-18 05:43:12 +0000167 std::cerr << "Hash density (#identifiers per bucket): "
Chris Lattner2b9e19b2006-10-29 23:43:13 +0000168 << NumIdentifiers/(double)NumBuckets << "\n";
Chris Lattner22eb9722006-06-18 05:43:12 +0000169 std::cerr << "Ave identifier length: "
170 << (AverageIdentifierSize/(double)NumIdentifiers) << "\n";
171 std::cerr << "Max identifier length: " << MaxIdentifierLength << "\n";
172
173 // Compute statistics about the memory allocated for identifiers.
Chris Lattner2b9e19b2006-10-29 23:43:13 +0000174 HashTable.getAllocator().PrintStats();
Chris Lattner22eb9722006-06-18 05:43:12 +0000175}
176
177