blob: b8684753b2ccb639ad88bb6af38f70f2d3dc8021 [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +00001//===--- IdentifierTable.cpp - Hash table for identifier lookup -----------===//
2//
3// The LLVM Compiler Infrastructure
4//
Chris Lattner0bc735f2007-12-29 19:59:25 +00005// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
Reid Spencer5f016e22007-07-11 17:01:13 +00007//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the IdentifierInfo, IdentifierVisitor, and
11// IdentifierTable interfaces.
12//
13//===----------------------------------------------------------------------===//
14
Chris Lattnerc7229c32007-10-07 08:58:51 +000015#include "clang/Basic/IdentifierTable.h"
Reid Spencer5f016e22007-07-11 17:01:13 +000016#include "clang/Basic/LangOptions.h"
Steve Naroff29238a02007-10-05 18:42:47 +000017#include "llvm/ADT/FoldingSet.h"
Chris Lattner85994262007-10-05 20:15:24 +000018#include "llvm/ADT/DenseMap.h"
Ted Kremeneka2bfb912007-10-24 19:06:02 +000019#include "llvm/Bitcode/Serialize.h"
20#include "llvm/Bitcode/Deserialize.h"
Ted Kremenekc637e6b2007-10-23 22:18:37 +000021
Reid Spencer5f016e22007-07-11 17:01:13 +000022using namespace clang;
23
24//===----------------------------------------------------------------------===//
25// IdentifierInfo Implementation
26//===----------------------------------------------------------------------===//
27
28IdentifierInfo::IdentifierInfo() {
Reid Spencer5f016e22007-07-11 17:01:13 +000029 TokenID = tok::identifier;
Douglas Gregor5142af32008-11-06 16:32:23 +000030 ObjCOrBuiltinID = 0;
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +000031 OperatorID = 0;
Chris Lattner4365a7e2007-10-07 07:09:52 +000032 HasMacro = false;
Reid Spencer5f016e22007-07-11 17:01:13 +000033 IsExtension = false;
34 IsPoisoned = false;
Reid Spencer5f016e22007-07-11 17:01:13 +000035 IsCPPOperatorKeyword = false;
36 FETokenInfo = 0;
37}
38
Reid Spencer5f016e22007-07-11 17:01:13 +000039//===----------------------------------------------------------------------===//
40// IdentifierTable Implementation
41//===----------------------------------------------------------------------===//
42
43IdentifierTable::IdentifierTable(const LangOptions &LangOpts)
44 // Start with space for 8K identifiers.
Douglas Gregor7d7e6722008-11-12 23:21:09 +000045 : HashTable(8192),
46 ConstructorId(0), DestructorId(0), ConversionFunctionId(0) {
Reid Spencer5f016e22007-07-11 17:01:13 +000047
48 // Populate the identifier table with info about keywords for the current
49 // language.
50 AddKeywords(LangOpts);
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +000051 AddOverloadedOperators();
Reid Spencer5f016e22007-07-11 17:01:13 +000052}
53
Ted Kremenekc637e6b2007-10-23 22:18:37 +000054// This cstor is intended to be used only for serialization.
Douglas Gregor7d7e6722008-11-12 23:21:09 +000055IdentifierTable::IdentifierTable()
56 : HashTable(8192),
57 ConstructorId(0), DestructorId(0), ConversionFunctionId(0) { }
58
59/// getConstructorId - Return a placeholder identifier for a C++
60/// constructor.
61IdentifierInfo &IdentifierTable::getConstructorId() {
62 if (!ConstructorId)
63 ConstructorId = &get("<constructor>");
64 return *ConstructorId;
65}
66
67/// getDestructorId - Return a placeholder identifier for a C++
68/// destructor.
69IdentifierInfo &IdentifierTable::getDestructorId() {
70 if (!DestructorId)
71 DestructorId = &get("<destructor>");
72 return *DestructorId;
73}
74
75/// getConversionFunctionId - Return a placeholder identifier for a
76/// C++ conversion function.
77IdentifierInfo &IdentifierTable::getConversionFunctionId() {
78 if (!ConversionFunctionId)
79 ConversionFunctionId = &get("<conversion function>");
80 return *ConversionFunctionId;
81}
Ted Kremenekc637e6b2007-10-23 22:18:37 +000082
Reid Spencer5f016e22007-07-11 17:01:13 +000083//===----------------------------------------------------------------------===//
84// Language Keyword Implementation
85//===----------------------------------------------------------------------===//
86
87/// AddKeyword - This method is used to associate a token ID with specific
88/// identifiers because they are language keywords. This causes the lexer to
89/// automatically map matching identifiers to specialized token codes.
90///
Chris Lattnerd4b80f12007-07-16 04:18:29 +000091/// The C90/C99/CPP/CPP0x flags are set to 0 if the token should be
92/// enabled in the specified langauge, set to 1 if it is an extension
93/// in the specified language, and set to 2 if disabled in the
94/// specified language.
Reid Spencer5f016e22007-07-11 17:01:13 +000095static void AddKeyword(const char *Keyword, unsigned KWLen,
96 tok::TokenKind TokenCode,
Nate Begeman8aebcb72007-11-15 07:30:50 +000097 int C90, int C99, int CXX, int CXX0x, int BoolSupport,
Reid Spencer5f016e22007-07-11 17:01:13 +000098 const LangOptions &LangOpts, IdentifierTable &Table) {
Nate Begeman8aebcb72007-11-15 07:30:50 +000099 int Flags = 0;
100 if (BoolSupport != 0) {
Douglas Gregor7de3d792008-09-11 12:06:59 +0000101 Flags = LangOpts.CPlusPlus? 0 : LangOpts.Boolean ? BoolSupport : 2;
Nate Begeman8aebcb72007-11-15 07:30:50 +0000102 } else if (LangOpts.CPlusPlus) {
103 Flags = LangOpts.CPlusPlus0x ? CXX0x : CXX;
104 } else if (LangOpts.C99) {
105 Flags = C99;
106 } else {
107 Flags = C90;
108 }
Reid Spencer5f016e22007-07-11 17:01:13 +0000109
110 // Don't add this keyword if disabled in this language or if an extension
111 // and extensions are disabled.
112 if (Flags + LangOpts.NoExtensions >= 2) return;
113
114 IdentifierInfo &Info = Table.get(Keyword, Keyword+KWLen);
115 Info.setTokenID(TokenCode);
116 Info.setIsExtensionToken(Flags == 1);
117}
118
119static void AddAlias(const char *Keyword, unsigned KWLen,
Chris Lattner49581f42008-02-19 06:46:10 +0000120 tok::TokenKind AliaseeID,
Reid Spencer5f016e22007-07-11 17:01:13 +0000121 const char *AliaseeKeyword, unsigned AliaseeKWLen,
122 const LangOptions &LangOpts, IdentifierTable &Table) {
123 IdentifierInfo &AliasInfo = Table.get(Keyword, Keyword+KWLen);
124 IdentifierInfo &AliaseeInfo = Table.get(AliaseeKeyword,
125 AliaseeKeyword+AliaseeKWLen);
Chris Lattner49581f42008-02-19 06:46:10 +0000126 AliasInfo.setTokenID(AliaseeID);
Reid Spencer5f016e22007-07-11 17:01:13 +0000127 AliasInfo.setIsExtensionToken(AliaseeInfo.isExtensionToken());
128}
129
Reid Spencer5f016e22007-07-11 17:01:13 +0000130/// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
131/// representations.
132static void AddCXXOperatorKeyword(const char *Keyword, unsigned KWLen,
133 tok::TokenKind TokenCode,
134 IdentifierTable &Table) {
135 IdentifierInfo &Info = Table.get(Keyword, Keyword + KWLen);
136 Info.setTokenID(TokenCode);
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000137 Info.setIsCPlusPlusOperatorKeyword();
Reid Spencer5f016e22007-07-11 17:01:13 +0000138}
139
140/// AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or
141/// "property".
142static void AddObjCKeyword(tok::ObjCKeywordKind ObjCID,
143 const char *Name, unsigned NameLen,
144 IdentifierTable &Table) {
145 Table.get(Name, Name+NameLen).setObjCKeywordID(ObjCID);
146}
147
148/// AddKeywords - Add all keywords to the symbol table.
149///
150void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
151 enum {
152 C90Shift = 0,
153 EXTC90 = 1 << C90Shift,
154 NOTC90 = 2 << C90Shift,
155 C99Shift = 2,
156 EXTC99 = 1 << C99Shift,
157 NOTC99 = 2 << C99Shift,
158 CPPShift = 4,
159 EXTCPP = 1 << CPPShift,
160 NOTCPP = 2 << CPPShift,
Chris Lattnerd4b80f12007-07-16 04:18:29 +0000161 CPP0xShift = 6,
162 EXTCPP0x = 1 << CPP0xShift,
163 NOTCPP0x = 2 << CPP0xShift,
Nate Begeman8aebcb72007-11-15 07:30:50 +0000164 BoolShift = 8,
165 BOOLSUPPORT = 1 << BoolShift,
Reid Spencer5f016e22007-07-11 17:01:13 +0000166 Mask = 3
167 };
168
169 // Add keywords and tokens for the current language.
170#define KEYWORD(NAME, FLAGS) \
171 AddKeyword(#NAME, strlen(#NAME), tok::kw_ ## NAME, \
172 ((FLAGS) >> C90Shift) & Mask, \
173 ((FLAGS) >> C99Shift) & Mask, \
Chris Lattnerd4b80f12007-07-16 04:18:29 +0000174 ((FLAGS) >> CPPShift) & Mask, \
Nate Begeman8aebcb72007-11-15 07:30:50 +0000175 ((FLAGS) >> CPP0xShift) & Mask, \
176 ((FLAGS) >> BoolShift) & Mask, LangOpts, *this);
Reid Spencer5f016e22007-07-11 17:01:13 +0000177#define ALIAS(NAME, TOK) \
Chris Lattner49581f42008-02-19 06:46:10 +0000178 AddAlias(NAME, strlen(NAME), tok::kw_ ## TOK, #TOK, strlen(#TOK), \
179 LangOpts, *this);
Reid Spencer5f016e22007-07-11 17:01:13 +0000180#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
181 if (LangOpts.CXXOperatorNames) \
182 AddCXXOperatorKeyword(#NAME, strlen(#NAME), tok::ALIAS, *this);
183#define OBJC1_AT_KEYWORD(NAME) \
184 if (LangOpts.ObjC1) \
185 AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
186#define OBJC2_AT_KEYWORD(NAME) \
187 if (LangOpts.ObjC2) \
188 AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
189#include "clang/Basic/TokenKinds.def"
190}
191
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000192/// AddOverloadedOperators - Register the name of all C++ overloadable
193/// operators ("operator+", "operator[]", etc.)
194void IdentifierTable::AddOverloadedOperators() {
Douglas Gregor02bcd4c2008-11-10 13:38:07 +0000195#define OVERLOADED_OPERATOR(Name,Spelling,Token, Unary, Binary, MemberOnly) \
Douglas Gregor1cd1b1e2008-11-06 22:13:31 +0000196 OverloadedOperators[OO_##Name] = &get(Spelling); \
197 OverloadedOperators[OO_##Name]->setOverloadedOperatorID(OO_##Name);
198#include "clang/Basic/OperatorKinds.def"
199}
200
Chris Lattner387b98d2007-10-07 07:52:34 +0000201tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
202 // We use a perfect hash function here involving the length of the keyword,
203 // the first and third character. For preprocessor ID's there are no
204 // collisions (if there were, the switch below would complain about duplicate
205 // case values). Note that this depends on 'if' being null terminated.
206
207#define HASH(LEN, FIRST, THIRD) \
208 (LEN << 5) + (((FIRST-'a') + (THIRD-'a')) & 31)
209#define CASE(LEN, FIRST, THIRD, NAME) \
210 case HASH(LEN, FIRST, THIRD): \
211 return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
212
213 unsigned Len = getLength();
Chris Lattnera31f0302007-10-10 20:59:57 +0000214 if (Len < 2) return tok::pp_not_keyword;
Chris Lattner387b98d2007-10-07 07:52:34 +0000215 const char *Name = getName();
216 switch (HASH(Len, Name[0], Name[2])) {
217 default: return tok::pp_not_keyword;
218 CASE( 2, 'i', '\0', if);
219 CASE( 4, 'e', 'i', elif);
220 CASE( 4, 'e', 's', else);
221 CASE( 4, 'l', 'n', line);
222 CASE( 4, 's', 'c', sccs);
223 CASE( 5, 'e', 'd', endif);
224 CASE( 5, 'e', 'r', error);
225 CASE( 5, 'i', 'e', ident);
226 CASE( 5, 'i', 'd', ifdef);
227 CASE( 5, 'u', 'd', undef);
228
229 CASE( 6, 'a', 's', assert);
230 CASE( 6, 'd', 'f', define);
231 CASE( 6, 'i', 'n', ifndef);
232 CASE( 6, 'i', 'p', import);
233 CASE( 6, 'p', 'a', pragma);
234
235 CASE( 7, 'd', 'f', defined);
236 CASE( 7, 'i', 'c', include);
237 CASE( 7, 'w', 'r', warning);
238
239 CASE( 8, 'u', 'a', unassert);
240 CASE(12, 'i', 'c', include_next);
Chris Lattner387b98d2007-10-07 07:52:34 +0000241#undef CASE
242#undef HASH
243 }
244}
Reid Spencer5f016e22007-07-11 17:01:13 +0000245
246//===----------------------------------------------------------------------===//
247// Stats Implementation
248//===----------------------------------------------------------------------===//
249
250/// PrintStats - Print statistics about how well the identifier table is doing
251/// at hashing identifiers.
252void IdentifierTable::PrintStats() const {
253 unsigned NumBuckets = HashTable.getNumBuckets();
254 unsigned NumIdentifiers = HashTable.getNumItems();
255 unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
256 unsigned AverageIdentifierSize = 0;
257 unsigned MaxIdentifierLength = 0;
258
259 // TODO: Figure out maximum times an identifier had to probe for -stats.
260 for (llvm::StringMap<IdentifierInfo, llvm::BumpPtrAllocator>::const_iterator
261 I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
262 unsigned IdLen = I->getKeyLength();
263 AverageIdentifierSize += IdLen;
264 if (MaxIdentifierLength < IdLen)
265 MaxIdentifierLength = IdLen;
266 }
267
268 fprintf(stderr, "\n*** Identifier Table Stats:\n");
269 fprintf(stderr, "# Identifiers: %d\n", NumIdentifiers);
270 fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets);
271 fprintf(stderr, "Hash density (#identifiers per bucket): %f\n",
272 NumIdentifiers/(double)NumBuckets);
273 fprintf(stderr, "Ave identifier length: %f\n",
274 (AverageIdentifierSize/(double)NumIdentifiers));
275 fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength);
276
277 // Compute statistics about the memory allocated for identifiers.
278 HashTable.getAllocator().PrintStats();
279}
Steve Naroff68d331a2007-09-27 14:38:14 +0000280
Steve Naroff29238a02007-10-05 18:42:47 +0000281//===----------------------------------------------------------------------===//
282// SelectorTable Implementation
283//===----------------------------------------------------------------------===//
284
Chris Lattner85994262007-10-05 20:15:24 +0000285unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) {
286 return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());
287}
288
289
Steve Naroff29238a02007-10-05 18:42:47 +0000290/// MultiKeywordSelector - One of these variable length records is kept for each
291/// selector containing more than one keyword. We use a folding set
292/// to unique aggregate names (keyword selectors in ObjC parlance). Access to
293/// this class is provided strictly through Selector.
Chris Lattner85994262007-10-05 20:15:24 +0000294namespace clang {
Steve Naroff29238a02007-10-05 18:42:47 +0000295class MultiKeywordSelector : public llvm::FoldingSetNode {
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000296 friend SelectorTable* SelectorTable::CreateAndRegister(llvm::Deserializer&);
297 MultiKeywordSelector(unsigned nKeys) : NumArgs(nKeys) {}
Steve Naroff29238a02007-10-05 18:42:47 +0000298public:
299 unsigned NumArgs;
300
301 // Constructor for keyword selectors.
302 MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV) {
303 assert((nKeys > 1) && "not a multi-keyword selector");
304 NumArgs = nKeys;
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000305
Steve Naroff29238a02007-10-05 18:42:47 +0000306 // Fill in the trailing keyword array.
307 IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(this+1);
308 for (unsigned i = 0; i != nKeys; ++i)
309 KeyInfo[i] = IIV[i];
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000310 }
311
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000312 // getName - Derive the full selector name and return it.
313 std::string getName() const;
314
Steve Naroff29238a02007-10-05 18:42:47 +0000315 unsigned getNumArgs() const { return NumArgs; }
316
317 typedef IdentifierInfo *const *keyword_iterator;
318 keyword_iterator keyword_begin() const {
319 return reinterpret_cast<keyword_iterator>(this+1);
320 }
321 keyword_iterator keyword_end() const {
322 return keyword_begin()+NumArgs;
323 }
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000324 IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const {
325 assert(i < NumArgs && "getIdentifierInfoForSlot(): illegal index");
Steve Naroff29238a02007-10-05 18:42:47 +0000326 return keyword_begin()[i];
327 }
328 static void Profile(llvm::FoldingSetNodeID &ID,
329 keyword_iterator ArgTys, unsigned NumArgs) {
330 ID.AddInteger(NumArgs);
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000331 for (unsigned i = 0; i != NumArgs; ++i)
332 ID.AddPointer(ArgTys[i]);
Steve Naroff29238a02007-10-05 18:42:47 +0000333 }
334 void Profile(llvm::FoldingSetNodeID &ID) {
335 Profile(ID, keyword_begin(), NumArgs);
336 }
337};
Chris Lattner85994262007-10-05 20:15:24 +0000338} // end namespace clang.
Steve Naroff29238a02007-10-05 18:42:47 +0000339
340unsigned Selector::getNumArgs() const {
341 unsigned IIF = getIdentifierInfoFlag();
342 if (IIF == ZeroArg)
343 return 0;
344 if (IIF == OneArg)
345 return 1;
346 // We point to a MultiKeywordSelector (pointer doesn't contain any flags).
347 MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
348 return SI->getNumArgs();
349}
350
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000351IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
352 if (IdentifierInfo *II = getAsIdentifierInfo()) {
353 assert(argIndex == 0 && "illegal keyword index");
Steve Naroff29238a02007-10-05 18:42:47 +0000354 return II;
355 }
356 // We point to a MultiKeywordSelector (pointer doesn't contain any flags).
357 MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
358 return SI->getIdentifierInfoForSlot(argIndex);
359}
360
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000361std::string MultiKeywordSelector::getName() const {
362 std::string Result;
363 unsigned Length = 0;
364 for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
365 if (*I)
366 Length += (*I)->getLength();
367 ++Length; // :
Steve Naroff29238a02007-10-05 18:42:47 +0000368 }
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000369
370 Result.reserve(Length);
371
372 for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
373 if (*I)
374 Result.insert(Result.end(), (*I)->getName(),
375 (*I)->getName()+(*I)->getLength());
376 Result.push_back(':');
377 }
378
379 return Result;
Steve Naroff29238a02007-10-05 18:42:47 +0000380}
381
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000382std::string Selector::getName() const {
383 if (IdentifierInfo *II = getAsIdentifierInfo()) {
384 if (getNumArgs() == 0)
385 return II->getName();
386
387 std::string Res = II->getName();
388 Res += ":";
389 return Res;
Steve Naroff29238a02007-10-05 18:42:47 +0000390 }
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000391
392 // We have a multiple keyword selector (no embedded flags).
393 return reinterpret_cast<MultiKeywordSelector *>(InfoPtr)->getName();
Steve Naroff29238a02007-10-05 18:42:47 +0000394}
395
396
Chris Lattnerff384912007-10-07 02:00:24 +0000397Selector SelectorTable::getSelector(unsigned nKeys, IdentifierInfo **IIV) {
398 if (nKeys < 2)
399 return Selector(IIV[0], nKeys);
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000400
Steve Naroff29238a02007-10-05 18:42:47 +0000401 llvm::FoldingSet<MultiKeywordSelector> *SelTab;
402
403 SelTab = static_cast<llvm::FoldingSet<MultiKeywordSelector> *>(Impl);
404
405 // Unique selector, to guarantee there is one per name.
406 llvm::FoldingSetNodeID ID;
407 MultiKeywordSelector::Profile(ID, IIV, nKeys);
408
409 void *InsertPos = 0;
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000410 if (MultiKeywordSelector *SI = SelTab->FindNodeOrInsertPos(ID, InsertPos))
Steve Naroff29238a02007-10-05 18:42:47 +0000411 return Selector(SI);
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000412
Steve Naroff29238a02007-10-05 18:42:47 +0000413 // MultiKeywordSelector objects are not allocated with new because they have a
414 // variable size array (for parameter types) at the end of them.
415 MultiKeywordSelector *SI =
416 (MultiKeywordSelector*)malloc(sizeof(MultiKeywordSelector) +
417 nKeys*sizeof(IdentifierInfo *));
418 new (SI) MultiKeywordSelector(nKeys, IIV);
419 SelTab->InsertNode(SI, InsertPos);
420 return Selector(SI);
421}
422
Steve Naroff29238a02007-10-05 18:42:47 +0000423SelectorTable::SelectorTable() {
424 Impl = new llvm::FoldingSet<MultiKeywordSelector>;
425}
426
427SelectorTable::~SelectorTable() {
428 delete static_cast<llvm::FoldingSet<MultiKeywordSelector> *>(Impl);
429}
430
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000431//===----------------------------------------------------------------------===//
432// Serialization for IdentifierInfo and IdentifierTable.
433//===----------------------------------------------------------------------===//
434
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000435void IdentifierInfo::Emit(llvm::Serializer& S) const {
436 S.EmitInt(getTokenID());
437 S.EmitInt(getBuiltinID());
438 S.EmitInt(getObjCKeywordID());
439 S.EmitBool(hasMacroDefinition());
440 S.EmitBool(isExtensionToken());
441 S.EmitBool(isPoisoned());
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000442 S.EmitBool(isCPlusPlusOperatorKeyword());
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000443 // FIXME: FETokenInfo
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000444}
445
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000446void IdentifierInfo::Read(llvm::Deserializer& D) {
447 setTokenID((tok::TokenKind) D.ReadInt());
448 setBuiltinID(D.ReadInt());
449 setObjCKeywordID((tok::ObjCKeywordKind) D.ReadInt());
450 setHasMacroDefinition(D.ReadBool());
451 setIsExtensionToken(D.ReadBool());
452 setIsPoisoned(D.ReadBool());
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000453 setIsCPlusPlusOperatorKeyword(D.ReadBool());
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000454 // FIXME: FETokenInfo
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000455}
456
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000457void IdentifierTable::Emit(llvm::Serializer& S) const {
458 S.EnterBlock();
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000459
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000460 S.EmitPtr(this);
461
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000462 for (iterator I=begin(), E=end(); I != E; ++I) {
463 const char* Key = I->getKeyData();
464 const IdentifierInfo* Info = &I->getValue();
465
Ted Kremenekeae5cd02007-11-10 02:11:55 +0000466 bool KeyRegistered = S.isRegistered(Key);
467 bool InfoRegistered = S.isRegistered(Info);
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000468
469 if (KeyRegistered || InfoRegistered) {
470 // These acrobatics are so that we don't incur the cost of registering
471 // a pointer with the backpatcher during deserialization if nobody
472 // references the object.
473 S.EmitPtr(InfoRegistered ? Info : NULL);
474 S.EmitPtr(KeyRegistered ? Key : NULL);
475 S.EmitCStr(Key);
476 S.Emit(*Info);
477 }
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000478 }
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000479
480 S.ExitBlock();
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000481}
482
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000483IdentifierTable* IdentifierTable::CreateAndRegister(llvm::Deserializer& D) {
Ted Kremenek3b0eff82007-11-09 00:43:55 +0000484 llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000485
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000486 std::vector<char> buff;
487 buff.reserve(200);
Ted Kremeneka2bfb912007-10-24 19:06:02 +0000488
Ted Kremeneka2bfb912007-10-24 19:06:02 +0000489 IdentifierTable* t = new IdentifierTable();
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000490 D.RegisterPtr(t);
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000491
492 while (!D.FinishedBlock(BLoc)) {
493 llvm::SerializedPtrID InfoPtrID = D.ReadPtrID();
494 llvm::SerializedPtrID KeyPtrID = D.ReadPtrID();
495
496 D.ReadCStr(buff);
497
498 llvm::StringMapEntry<IdentifierInfo>& Entry =
499 t->HashTable.GetOrCreateValue(&buff[0],&buff[0]+buff.size());
500
501 D.Read(Entry.getValue());
502
503 if (InfoPtrID)
504 D.RegisterRef(InfoPtrID,Entry.getValue());
505
506 if (KeyPtrID)
507 D.RegisterPtr(KeyPtrID,Entry.getKeyData());
508 }
509
Ted Kremeneka2bfb912007-10-24 19:06:02 +0000510 return t;
511}
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000512
513//===----------------------------------------------------------------------===//
514// Serialization for Selector and SelectorTable.
515//===----------------------------------------------------------------------===//
516
517void Selector::Emit(llvm::Serializer& S) const {
518 S.EmitInt(getIdentifierInfoFlag());
519 S.EmitPtr(reinterpret_cast<void*>(InfoPtr & ~ArgFlags));
520}
521
522Selector Selector::ReadVal(llvm::Deserializer& D) {
523 unsigned flag = D.ReadInt();
524
525 uintptr_t ptr;
526 D.ReadUIntPtr(ptr,false); // No backpatching.
527
528 return Selector(ptr | flag);
529}
530
531void SelectorTable::Emit(llvm::Serializer& S) const {
532 typedef llvm::FoldingSet<MultiKeywordSelector>::iterator iterator;
533 llvm::FoldingSet<MultiKeywordSelector> *SelTab;
534 SelTab = static_cast<llvm::FoldingSet<MultiKeywordSelector> *>(Impl);
535
536 S.EnterBlock();
537
538 S.EmitPtr(this);
539
540 for (iterator I=SelTab->begin(), E=SelTab->end(); I != E; ++I) {
Ted Kremenek68072a72007-12-01 04:43:17 +0000541 if (!S.isRegistered(&*I))
542 continue;
543
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000544 S.FlushRecord(); // Start a new record.
Ted Kremenek68072a72007-12-01 04:43:17 +0000545
546 S.EmitPtr(&*I);
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000547 S.EmitInt(I->getNumArgs());
548
549 for (MultiKeywordSelector::keyword_iterator KI = I->keyword_begin(),
550 KE = I->keyword_end(); KI != KE; ++KI)
551 S.EmitPtr(*KI);
552 }
553
554 S.ExitBlock();
555}
556
557SelectorTable* SelectorTable::CreateAndRegister(llvm::Deserializer& D) {
558 llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();
559
560 SelectorTable* t = new SelectorTable();
561 D.RegisterPtr(t);
562
563 llvm::FoldingSet<MultiKeywordSelector>& SelTab =
564 *static_cast<llvm::FoldingSet<MultiKeywordSelector>*>(t->Impl);
565
566 while (!D.FinishedBlock(BLoc)) {
Ted Kremenek68072a72007-12-01 04:43:17 +0000567
568 llvm::SerializedPtrID PtrID = D.ReadPtrID();
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000569 unsigned nKeys = D.ReadInt();
570
571 MultiKeywordSelector *SI =
572 (MultiKeywordSelector*)malloc(sizeof(MultiKeywordSelector) +
573 nKeys*sizeof(IdentifierInfo *));
574
575 new (SI) MultiKeywordSelector(nKeys);
Ted Kremenek68072a72007-12-01 04:43:17 +0000576
577 D.RegisterPtr(PtrID,SI);
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000578
579 IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(SI+1);
580
581 for (unsigned i = 0; i != nKeys; ++i)
582 D.ReadPtr(KeyInfo[i],false);
583
584 SelTab.GetOrInsertNode(SI);
585 }
586
587 return t;
588}