blob: 8f0387e99e61d536463f748611d34b3a120cd7fb [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;
Chris Lattner4365a7e2007-10-07 07:09:52 +000031 HasMacro = false;
Reid Spencer5f016e22007-07-11 17:01:13 +000032 IsExtension = false;
33 IsPoisoned = false;
Reid Spencer5f016e22007-07-11 17:01:13 +000034 IsCPPOperatorKeyword = false;
35 FETokenInfo = 0;
36}
37
Reid Spencer5f016e22007-07-11 17:01:13 +000038//===----------------------------------------------------------------------===//
39// IdentifierTable Implementation
40//===----------------------------------------------------------------------===//
41
42IdentifierTable::IdentifierTable(const LangOptions &LangOpts)
43 // Start with space for 8K identifiers.
44 : HashTable(8192) {
45
46 // Populate the identifier table with info about keywords for the current
47 // language.
48 AddKeywords(LangOpts);
49}
50
Ted Kremenekc637e6b2007-10-23 22:18:37 +000051// This cstor is intended to be used only for serialization.
52IdentifierTable::IdentifierTable() : HashTable(8192) {}
53
Reid Spencer5f016e22007-07-11 17:01:13 +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///
Chris Lattnerd4b80f12007-07-16 04:18:29 +000062/// The C90/C99/CPP/CPP0x flags are set to 0 if the token should be
63/// enabled in the specified langauge, set to 1 if it is an extension
64/// in the specified language, and set to 2 if disabled in the
65/// specified language.
Reid Spencer5f016e22007-07-11 17:01:13 +000066static void AddKeyword(const char *Keyword, unsigned KWLen,
67 tok::TokenKind TokenCode,
Nate Begeman8aebcb72007-11-15 07:30:50 +000068 int C90, int C99, int CXX, int CXX0x, int BoolSupport,
Reid Spencer5f016e22007-07-11 17:01:13 +000069 const LangOptions &LangOpts, IdentifierTable &Table) {
Nate Begeman8aebcb72007-11-15 07:30:50 +000070 int Flags = 0;
71 if (BoolSupport != 0) {
Douglas Gregor7de3d792008-09-11 12:06:59 +000072 Flags = LangOpts.CPlusPlus? 0 : LangOpts.Boolean ? BoolSupport : 2;
Nate Begeman8aebcb72007-11-15 07:30:50 +000073 } else if (LangOpts.CPlusPlus) {
74 Flags = LangOpts.CPlusPlus0x ? CXX0x : CXX;
75 } else if (LangOpts.C99) {
76 Flags = C99;
77 } else {
78 Flags = C90;
79 }
Reid Spencer5f016e22007-07-11 17:01:13 +000080
81 // Don't add this keyword if disabled in this language or if an extension
82 // and extensions are disabled.
83 if (Flags + LangOpts.NoExtensions >= 2) return;
84
85 IdentifierInfo &Info = Table.get(Keyword, Keyword+KWLen);
86 Info.setTokenID(TokenCode);
87 Info.setIsExtensionToken(Flags == 1);
88}
89
90static void AddAlias(const char *Keyword, unsigned KWLen,
Chris Lattner49581f42008-02-19 06:46:10 +000091 tok::TokenKind AliaseeID,
Reid Spencer5f016e22007-07-11 17:01:13 +000092 const char *AliaseeKeyword, unsigned AliaseeKWLen,
93 const LangOptions &LangOpts, IdentifierTable &Table) {
94 IdentifierInfo &AliasInfo = Table.get(Keyword, Keyword+KWLen);
95 IdentifierInfo &AliaseeInfo = Table.get(AliaseeKeyword,
96 AliaseeKeyword+AliaseeKWLen);
Chris Lattner49581f42008-02-19 06:46:10 +000097 AliasInfo.setTokenID(AliaseeID);
Reid Spencer5f016e22007-07-11 17:01:13 +000098 AliasInfo.setIsExtensionToken(AliaseeInfo.isExtensionToken());
99}
100
Reid Spencer5f016e22007-07-11 17:01:13 +0000101/// AddCXXOperatorKeyword - Register a C++ operator keyword alternative
102/// representations.
103static void AddCXXOperatorKeyword(const char *Keyword, unsigned KWLen,
104 tok::TokenKind TokenCode,
105 IdentifierTable &Table) {
106 IdentifierInfo &Info = Table.get(Keyword, Keyword + KWLen);
107 Info.setTokenID(TokenCode);
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000108 Info.setIsCPlusPlusOperatorKeyword();
Reid Spencer5f016e22007-07-11 17:01:13 +0000109}
110
111/// AddObjCKeyword - Register an Objective-C @keyword like "class" "selector" or
112/// "property".
113static void AddObjCKeyword(tok::ObjCKeywordKind ObjCID,
114 const char *Name, unsigned NameLen,
115 IdentifierTable &Table) {
116 Table.get(Name, Name+NameLen).setObjCKeywordID(ObjCID);
117}
118
119/// AddKeywords - Add all keywords to the symbol table.
120///
121void IdentifierTable::AddKeywords(const LangOptions &LangOpts) {
122 enum {
123 C90Shift = 0,
124 EXTC90 = 1 << C90Shift,
125 NOTC90 = 2 << C90Shift,
126 C99Shift = 2,
127 EXTC99 = 1 << C99Shift,
128 NOTC99 = 2 << C99Shift,
129 CPPShift = 4,
130 EXTCPP = 1 << CPPShift,
131 NOTCPP = 2 << CPPShift,
Chris Lattnerd4b80f12007-07-16 04:18:29 +0000132 CPP0xShift = 6,
133 EXTCPP0x = 1 << CPP0xShift,
134 NOTCPP0x = 2 << CPP0xShift,
Nate Begeman8aebcb72007-11-15 07:30:50 +0000135 BoolShift = 8,
136 BOOLSUPPORT = 1 << BoolShift,
Reid Spencer5f016e22007-07-11 17:01:13 +0000137 Mask = 3
138 };
139
140 // Add keywords and tokens for the current language.
141#define KEYWORD(NAME, FLAGS) \
142 AddKeyword(#NAME, strlen(#NAME), tok::kw_ ## NAME, \
143 ((FLAGS) >> C90Shift) & Mask, \
144 ((FLAGS) >> C99Shift) & Mask, \
Chris Lattnerd4b80f12007-07-16 04:18:29 +0000145 ((FLAGS) >> CPPShift) & Mask, \
Nate Begeman8aebcb72007-11-15 07:30:50 +0000146 ((FLAGS) >> CPP0xShift) & Mask, \
147 ((FLAGS) >> BoolShift) & Mask, LangOpts, *this);
Reid Spencer5f016e22007-07-11 17:01:13 +0000148#define ALIAS(NAME, TOK) \
Chris Lattner49581f42008-02-19 06:46:10 +0000149 AddAlias(NAME, strlen(NAME), tok::kw_ ## TOK, #TOK, strlen(#TOK), \
150 LangOpts, *this);
Reid Spencer5f016e22007-07-11 17:01:13 +0000151#define CXX_KEYWORD_OPERATOR(NAME, ALIAS) \
152 if (LangOpts.CXXOperatorNames) \
153 AddCXXOperatorKeyword(#NAME, strlen(#NAME), tok::ALIAS, *this);
154#define OBJC1_AT_KEYWORD(NAME) \
155 if (LangOpts.ObjC1) \
156 AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
157#define OBJC2_AT_KEYWORD(NAME) \
158 if (LangOpts.ObjC2) \
159 AddObjCKeyword(tok::objc_##NAME, #NAME, strlen(#NAME), *this);
160#include "clang/Basic/TokenKinds.def"
161}
162
Chris Lattner387b98d2007-10-07 07:52:34 +0000163tok::PPKeywordKind IdentifierInfo::getPPKeywordID() const {
164 // We use a perfect hash function here involving the length of the keyword,
165 // the first and third character. For preprocessor ID's there are no
166 // collisions (if there were, the switch below would complain about duplicate
167 // case values). Note that this depends on 'if' being null terminated.
168
169#define HASH(LEN, FIRST, THIRD) \
170 (LEN << 5) + (((FIRST-'a') + (THIRD-'a')) & 31)
171#define CASE(LEN, FIRST, THIRD, NAME) \
172 case HASH(LEN, FIRST, THIRD): \
173 return memcmp(Name, #NAME, LEN) ? tok::pp_not_keyword : tok::pp_ ## NAME
174
175 unsigned Len = getLength();
Chris Lattnera31f0302007-10-10 20:59:57 +0000176 if (Len < 2) return tok::pp_not_keyword;
Chris Lattner387b98d2007-10-07 07:52:34 +0000177 const char *Name = getName();
178 switch (HASH(Len, Name[0], Name[2])) {
179 default: return tok::pp_not_keyword;
180 CASE( 2, 'i', '\0', if);
181 CASE( 4, 'e', 'i', elif);
182 CASE( 4, 'e', 's', else);
183 CASE( 4, 'l', 'n', line);
184 CASE( 4, 's', 'c', sccs);
185 CASE( 5, 'e', 'd', endif);
186 CASE( 5, 'e', 'r', error);
187 CASE( 5, 'i', 'e', ident);
188 CASE( 5, 'i', 'd', ifdef);
189 CASE( 5, 'u', 'd', undef);
190
191 CASE( 6, 'a', 's', assert);
192 CASE( 6, 'd', 'f', define);
193 CASE( 6, 'i', 'n', ifndef);
194 CASE( 6, 'i', 'p', import);
195 CASE( 6, 'p', 'a', pragma);
196
197 CASE( 7, 'd', 'f', defined);
198 CASE( 7, 'i', 'c', include);
199 CASE( 7, 'w', 'r', warning);
200
201 CASE( 8, 'u', 'a', unassert);
202 CASE(12, 'i', 'c', include_next);
Chris Lattner387b98d2007-10-07 07:52:34 +0000203#undef CASE
204#undef HASH
205 }
206}
Reid Spencer5f016e22007-07-11 17:01:13 +0000207
208//===----------------------------------------------------------------------===//
209// Stats Implementation
210//===----------------------------------------------------------------------===//
211
212/// PrintStats - Print statistics about how well the identifier table is doing
213/// at hashing identifiers.
214void IdentifierTable::PrintStats() const {
215 unsigned NumBuckets = HashTable.getNumBuckets();
216 unsigned NumIdentifiers = HashTable.getNumItems();
217 unsigned NumEmptyBuckets = NumBuckets-NumIdentifiers;
218 unsigned AverageIdentifierSize = 0;
219 unsigned MaxIdentifierLength = 0;
220
221 // TODO: Figure out maximum times an identifier had to probe for -stats.
222 for (llvm::StringMap<IdentifierInfo, llvm::BumpPtrAllocator>::const_iterator
223 I = HashTable.begin(), E = HashTable.end(); I != E; ++I) {
224 unsigned IdLen = I->getKeyLength();
225 AverageIdentifierSize += IdLen;
226 if (MaxIdentifierLength < IdLen)
227 MaxIdentifierLength = IdLen;
228 }
229
230 fprintf(stderr, "\n*** Identifier Table Stats:\n");
231 fprintf(stderr, "# Identifiers: %d\n", NumIdentifiers);
232 fprintf(stderr, "# Empty Buckets: %d\n", NumEmptyBuckets);
233 fprintf(stderr, "Hash density (#identifiers per bucket): %f\n",
234 NumIdentifiers/(double)NumBuckets);
235 fprintf(stderr, "Ave identifier length: %f\n",
236 (AverageIdentifierSize/(double)NumIdentifiers));
237 fprintf(stderr, "Max identifier length: %d\n", MaxIdentifierLength);
238
239 // Compute statistics about the memory allocated for identifiers.
240 HashTable.getAllocator().PrintStats();
241}
Steve Naroff68d331a2007-09-27 14:38:14 +0000242
Steve Naroff29238a02007-10-05 18:42:47 +0000243//===----------------------------------------------------------------------===//
244// SelectorTable Implementation
245//===----------------------------------------------------------------------===//
246
Chris Lattner85994262007-10-05 20:15:24 +0000247unsigned llvm::DenseMapInfo<clang::Selector>::getHashValue(clang::Selector S) {
248 return DenseMapInfo<void*>::getHashValue(S.getAsOpaquePtr());
249}
250
251
Steve Naroff29238a02007-10-05 18:42:47 +0000252/// MultiKeywordSelector - One of these variable length records is kept for each
253/// selector containing more than one keyword. We use a folding set
254/// to unique aggregate names (keyword selectors in ObjC parlance). Access to
255/// this class is provided strictly through Selector.
Chris Lattner85994262007-10-05 20:15:24 +0000256namespace clang {
Steve Naroff29238a02007-10-05 18:42:47 +0000257class MultiKeywordSelector : public llvm::FoldingSetNode {
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000258 friend SelectorTable* SelectorTable::CreateAndRegister(llvm::Deserializer&);
259 MultiKeywordSelector(unsigned nKeys) : NumArgs(nKeys) {}
Steve Naroff29238a02007-10-05 18:42:47 +0000260public:
261 unsigned NumArgs;
262
263 // Constructor for keyword selectors.
264 MultiKeywordSelector(unsigned nKeys, IdentifierInfo **IIV) {
265 assert((nKeys > 1) && "not a multi-keyword selector");
266 NumArgs = nKeys;
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000267
Steve Naroff29238a02007-10-05 18:42:47 +0000268 // Fill in the trailing keyword array.
269 IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(this+1);
270 for (unsigned i = 0; i != nKeys; ++i)
271 KeyInfo[i] = IIV[i];
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000272 }
273
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000274 // getName - Derive the full selector name and return it.
275 std::string getName() const;
276
Steve Naroff29238a02007-10-05 18:42:47 +0000277 unsigned getNumArgs() const { return NumArgs; }
278
279 typedef IdentifierInfo *const *keyword_iterator;
280 keyword_iterator keyword_begin() const {
281 return reinterpret_cast<keyword_iterator>(this+1);
282 }
283 keyword_iterator keyword_end() const {
284 return keyword_begin()+NumArgs;
285 }
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000286 IdentifierInfo *getIdentifierInfoForSlot(unsigned i) const {
287 assert(i < NumArgs && "getIdentifierInfoForSlot(): illegal index");
Steve Naroff29238a02007-10-05 18:42:47 +0000288 return keyword_begin()[i];
289 }
290 static void Profile(llvm::FoldingSetNodeID &ID,
291 keyword_iterator ArgTys, unsigned NumArgs) {
292 ID.AddInteger(NumArgs);
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000293 for (unsigned i = 0; i != NumArgs; ++i)
294 ID.AddPointer(ArgTys[i]);
Steve Naroff29238a02007-10-05 18:42:47 +0000295 }
296 void Profile(llvm::FoldingSetNodeID &ID) {
297 Profile(ID, keyword_begin(), NumArgs);
298 }
299};
Chris Lattner85994262007-10-05 20:15:24 +0000300} // end namespace clang.
Steve Naroff29238a02007-10-05 18:42:47 +0000301
302unsigned Selector::getNumArgs() const {
303 unsigned IIF = getIdentifierInfoFlag();
304 if (IIF == ZeroArg)
305 return 0;
306 if (IIF == OneArg)
307 return 1;
308 // We point to a MultiKeywordSelector (pointer doesn't contain any flags).
309 MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
310 return SI->getNumArgs();
311}
312
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000313IdentifierInfo *Selector::getIdentifierInfoForSlot(unsigned argIndex) const {
314 if (IdentifierInfo *II = getAsIdentifierInfo()) {
315 assert(argIndex == 0 && "illegal keyword index");
Steve Naroff29238a02007-10-05 18:42:47 +0000316 return II;
317 }
318 // We point to a MultiKeywordSelector (pointer doesn't contain any flags).
319 MultiKeywordSelector *SI = reinterpret_cast<MultiKeywordSelector *>(InfoPtr);
320 return SI->getIdentifierInfoForSlot(argIndex);
321}
322
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000323std::string MultiKeywordSelector::getName() const {
324 std::string Result;
325 unsigned Length = 0;
326 for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
327 if (*I)
328 Length += (*I)->getLength();
329 ++Length; // :
Steve Naroff29238a02007-10-05 18:42:47 +0000330 }
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000331
332 Result.reserve(Length);
333
334 for (keyword_iterator I = keyword_begin(), E = keyword_end(); I != E; ++I) {
335 if (*I)
336 Result.insert(Result.end(), (*I)->getName(),
337 (*I)->getName()+(*I)->getLength());
338 Result.push_back(':');
339 }
340
341 return Result;
Steve Naroff29238a02007-10-05 18:42:47 +0000342}
343
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000344std::string Selector::getName() const {
345 if (IdentifierInfo *II = getAsIdentifierInfo()) {
346 if (getNumArgs() == 0)
347 return II->getName();
348
349 std::string Res = II->getName();
350 Res += ":";
351 return Res;
Steve Naroff29238a02007-10-05 18:42:47 +0000352 }
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000353
354 // We have a multiple keyword selector (no embedded flags).
355 return reinterpret_cast<MultiKeywordSelector *>(InfoPtr)->getName();
Steve Naroff29238a02007-10-05 18:42:47 +0000356}
357
358
Chris Lattnerff384912007-10-07 02:00:24 +0000359Selector SelectorTable::getSelector(unsigned nKeys, IdentifierInfo **IIV) {
360 if (nKeys < 2)
361 return Selector(IIV[0], nKeys);
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000362
Steve Naroff29238a02007-10-05 18:42:47 +0000363 llvm::FoldingSet<MultiKeywordSelector> *SelTab;
364
365 SelTab = static_cast<llvm::FoldingSet<MultiKeywordSelector> *>(Impl);
366
367 // Unique selector, to guarantee there is one per name.
368 llvm::FoldingSetNodeID ID;
369 MultiKeywordSelector::Profile(ID, IIV, nKeys);
370
371 void *InsertPos = 0;
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000372 if (MultiKeywordSelector *SI = SelTab->FindNodeOrInsertPos(ID, InsertPos))
Steve Naroff29238a02007-10-05 18:42:47 +0000373 return Selector(SI);
Chris Lattnerf836e3f2007-10-07 01:33:16 +0000374
Steve Naroff29238a02007-10-05 18:42:47 +0000375 // MultiKeywordSelector objects are not allocated with new because they have a
376 // variable size array (for parameter types) at the end of them.
377 MultiKeywordSelector *SI =
378 (MultiKeywordSelector*)malloc(sizeof(MultiKeywordSelector) +
379 nKeys*sizeof(IdentifierInfo *));
380 new (SI) MultiKeywordSelector(nKeys, IIV);
381 SelTab->InsertNode(SI, InsertPos);
382 return Selector(SI);
383}
384
Steve Naroff29238a02007-10-05 18:42:47 +0000385SelectorTable::SelectorTable() {
386 Impl = new llvm::FoldingSet<MultiKeywordSelector>;
387}
388
389SelectorTable::~SelectorTable() {
390 delete static_cast<llvm::FoldingSet<MultiKeywordSelector> *>(Impl);
391}
392
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000393//===----------------------------------------------------------------------===//
394// Serialization for IdentifierInfo and IdentifierTable.
395//===----------------------------------------------------------------------===//
396
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000397void IdentifierInfo::Emit(llvm::Serializer& S) const {
398 S.EmitInt(getTokenID());
399 S.EmitInt(getBuiltinID());
400 S.EmitInt(getObjCKeywordID());
401 S.EmitBool(hasMacroDefinition());
402 S.EmitBool(isExtensionToken());
403 S.EmitBool(isPoisoned());
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000404 S.EmitBool(isCPlusPlusOperatorKeyword());
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000405 // FIXME: FETokenInfo
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000406}
407
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000408void IdentifierInfo::Read(llvm::Deserializer& D) {
409 setTokenID((tok::TokenKind) D.ReadInt());
410 setBuiltinID(D.ReadInt());
411 setObjCKeywordID((tok::ObjCKeywordKind) D.ReadInt());
412 setHasMacroDefinition(D.ReadBool());
413 setIsExtensionToken(D.ReadBool());
414 setIsPoisoned(D.ReadBool());
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000415 setIsCPlusPlusOperatorKeyword(D.ReadBool());
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000416 // FIXME: FETokenInfo
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000417}
418
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000419void IdentifierTable::Emit(llvm::Serializer& S) const {
420 S.EnterBlock();
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000421
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000422 S.EmitPtr(this);
423
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000424 for (iterator I=begin(), E=end(); I != E; ++I) {
425 const char* Key = I->getKeyData();
426 const IdentifierInfo* Info = &I->getValue();
427
Ted Kremenekeae5cd02007-11-10 02:11:55 +0000428 bool KeyRegistered = S.isRegistered(Key);
429 bool InfoRegistered = S.isRegistered(Info);
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000430
431 if (KeyRegistered || InfoRegistered) {
432 // These acrobatics are so that we don't incur the cost of registering
433 // a pointer with the backpatcher during deserialization if nobody
434 // references the object.
435 S.EmitPtr(InfoRegistered ? Info : NULL);
436 S.EmitPtr(KeyRegistered ? Key : NULL);
437 S.EmitCStr(Key);
438 S.Emit(*Info);
439 }
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000440 }
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000441
442 S.ExitBlock();
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000443}
444
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000445IdentifierTable* IdentifierTable::CreateAndRegister(llvm::Deserializer& D) {
Ted Kremenek3b0eff82007-11-09 00:43:55 +0000446 llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000447
Ted Kremenekc637e6b2007-10-23 22:18:37 +0000448 std::vector<char> buff;
449 buff.reserve(200);
Ted Kremeneka2bfb912007-10-24 19:06:02 +0000450
Ted Kremeneka2bfb912007-10-24 19:06:02 +0000451 IdentifierTable* t = new IdentifierTable();
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000452 D.RegisterPtr(t);
Ted Kremenek93a9ab42007-11-08 19:52:41 +0000453
454 while (!D.FinishedBlock(BLoc)) {
455 llvm::SerializedPtrID InfoPtrID = D.ReadPtrID();
456 llvm::SerializedPtrID KeyPtrID = D.ReadPtrID();
457
458 D.ReadCStr(buff);
459
460 llvm::StringMapEntry<IdentifierInfo>& Entry =
461 t->HashTable.GetOrCreateValue(&buff[0],&buff[0]+buff.size());
462
463 D.Read(Entry.getValue());
464
465 if (InfoPtrID)
466 D.RegisterRef(InfoPtrID,Entry.getValue());
467
468 if (KeyPtrID)
469 D.RegisterPtr(KeyPtrID,Entry.getKeyData());
470 }
471
Ted Kremeneka2bfb912007-10-24 19:06:02 +0000472 return t;
473}
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000474
475//===----------------------------------------------------------------------===//
476// Serialization for Selector and SelectorTable.
477//===----------------------------------------------------------------------===//
478
479void Selector::Emit(llvm::Serializer& S) const {
480 S.EmitInt(getIdentifierInfoFlag());
481 S.EmitPtr(reinterpret_cast<void*>(InfoPtr & ~ArgFlags));
482}
483
484Selector Selector::ReadVal(llvm::Deserializer& D) {
485 unsigned flag = D.ReadInt();
486
487 uintptr_t ptr;
488 D.ReadUIntPtr(ptr,false); // No backpatching.
489
490 return Selector(ptr | flag);
491}
492
493void SelectorTable::Emit(llvm::Serializer& S) const {
494 typedef llvm::FoldingSet<MultiKeywordSelector>::iterator iterator;
495 llvm::FoldingSet<MultiKeywordSelector> *SelTab;
496 SelTab = static_cast<llvm::FoldingSet<MultiKeywordSelector> *>(Impl);
497
498 S.EnterBlock();
499
500 S.EmitPtr(this);
501
502 for (iterator I=SelTab->begin(), E=SelTab->end(); I != E; ++I) {
Ted Kremenek68072a72007-12-01 04:43:17 +0000503 if (!S.isRegistered(&*I))
504 continue;
505
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000506 S.FlushRecord(); // Start a new record.
Ted Kremenek68072a72007-12-01 04:43:17 +0000507
508 S.EmitPtr(&*I);
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000509 S.EmitInt(I->getNumArgs());
510
511 for (MultiKeywordSelector::keyword_iterator KI = I->keyword_begin(),
512 KE = I->keyword_end(); KI != KE; ++KI)
513 S.EmitPtr(*KI);
514 }
515
516 S.ExitBlock();
517}
518
519SelectorTable* SelectorTable::CreateAndRegister(llvm::Deserializer& D) {
520 llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();
521
522 SelectorTable* t = new SelectorTable();
523 D.RegisterPtr(t);
524
525 llvm::FoldingSet<MultiKeywordSelector>& SelTab =
526 *static_cast<llvm::FoldingSet<MultiKeywordSelector>*>(t->Impl);
527
528 while (!D.FinishedBlock(BLoc)) {
Ted Kremenek68072a72007-12-01 04:43:17 +0000529
530 llvm::SerializedPtrID PtrID = D.ReadPtrID();
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000531 unsigned nKeys = D.ReadInt();
532
533 MultiKeywordSelector *SI =
534 (MultiKeywordSelector*)malloc(sizeof(MultiKeywordSelector) +
535 nKeys*sizeof(IdentifierInfo *));
536
537 new (SI) MultiKeywordSelector(nKeys);
Ted Kremenek68072a72007-12-01 04:43:17 +0000538
539 D.RegisterPtr(PtrID,SI);
Ted Kremenekbdbb2852007-11-30 22:46:56 +0000540
541 IdentifierInfo **KeyInfo = reinterpret_cast<IdentifierInfo **>(SI+1);
542
543 for (unsigned i = 0; i != nKeys; ++i)
544 D.ReadPtr(KeyInfo[i],false);
545
546 SelTab.GetOrInsertNode(SI);
547 }
548
549 return t;
550}