blob: 2548d3d7ddff8f236b11eaaf107046c8598378a6 [file] [log] [blame]
Ted Kremenek71c6cc62008-10-21 00:54:44 +00001//===--- CacheTokens.cpp - Caching of lexer tokens for PCH support --------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This provides a possible implementation of PCH support for Clang that is
11// based on caching lexed tokens and identifiers.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang.h"
16#include "clang/Basic/FileManager.h"
17#include "clang/Basic/SourceManager.h"
18#include "clang/Basic/IdentifierTable.h"
19#include "clang/Basic/Diagnostic.h"
20#include "clang/Lex/Lexer.h"
21#include "clang/Lex/Preprocessor.h"
Ted Kremenek2e395562009-01-08 02:44:06 +000022#include "llvm/ADT/StringMap.h"
Ted Kremenek71c6cc62008-10-21 00:54:44 +000023#include "llvm/Support/MemoryBuffer.h"
24#include "llvm/Support/raw_ostream.h"
Ted Kremenek62739d62008-12-02 19:44:08 +000025#include "llvm/System/Path.h"
Ted Kremenek40291882009-01-08 01:17:37 +000026#include "llvm/Support/Compiler.h"
Ted Kremenek71c6cc62008-10-21 00:54:44 +000027
28using namespace clang;
29
Ted Kremenek62739d62008-12-02 19:44:08 +000030typedef uint32_t Offset;
31
Ted Kremeneke98da522009-01-09 00:37:37 +000032typedef std::vector<std::pair<Offset, llvm::StringMapEntry<Offset>*> >
Ted Kremenek2e395562009-01-08 02:44:06 +000033 SpellMapTy;
34
35namespace {
36class VISIBILITY_HIDDEN PCHEntry {
37 Offset TokenData, PPCondData;
38 union { Offset SpellingOff; SpellMapTy* Spellings; };
39
40public:
41 PCHEntry() {}
42
43 PCHEntry(Offset td, Offset ppcd, SpellMapTy* sp)
44 : TokenData(td), PPCondData(ppcd), Spellings(sp) {}
45
46 Offset getTokenOffset() const { return TokenData; }
47 Offset getPPCondTableOffset() const { return PPCondData; }
48 SpellMapTy& getSpellings() const { return *Spellings; }
49
50 void setSpellingTableOffset(Offset off) { SpellingOff = off; }
51 Offset getSpellingTableOffset() const { return SpellingOff; }
52
53};
54} // end anonymous namespace
55
56typedef llvm::DenseMap<const FileEntry*, PCHEntry> PCHMap;
Ted Kremenek62739d62008-12-02 19:44:08 +000057typedef llvm::DenseMap<const IdentifierInfo*,uint32_t> IDMap;
Ted Kremeneke98da522009-01-09 00:37:37 +000058typedef llvm::StringMap<Offset, llvm::BumpPtrAllocator> CachedStrsTy;
Ted Kremenek71c6cc62008-10-21 00:54:44 +000059
Ted Kremenek40291882009-01-08 01:17:37 +000060namespace {
61class VISIBILITY_HIDDEN PTHWriter {
62 IDMap IM;
63 llvm::raw_fd_ostream& Out;
64 Preprocessor& PP;
65 uint32_t idcount;
66 PCHMap PM;
Ted Kremenek2e395562009-01-08 02:44:06 +000067 CachedStrsTy CachedStrs;
68
69 SpellMapTy* CurSpellMap;
Ted Kremenekd2c4abb2008-12-23 02:52:12 +000070
Ted Kremenek40291882009-01-08 01:17:37 +000071 //// Get the persistent id for the given IdentifierInfo*.
72 uint32_t ResolveID(const IdentifierInfo* II);
Ted Kremenek62739d62008-12-02 19:44:08 +000073
Ted Kremenek40291882009-01-08 01:17:37 +000074 /// Emit a token to the PTH file.
75 void EmitToken(const Token& T);
76
77 void Emit8(uint32_t V) {
78 Out << (unsigned char)(V);
79 }
80
81 void Emit16(uint32_t V) {
82 Out << (unsigned char)(V);
83 Out << (unsigned char)(V >> 8);
84 assert((V >> 16) == 0);
85 }
86
87 void Emit24(uint32_t V) {
88 Out << (unsigned char)(V);
89 Out << (unsigned char)(V >> 8);
90 Out << (unsigned char)(V >> 16);
91 assert((V >> 24) == 0);
92 }
93
94 void Emit32(uint32_t V) {
95 Out << (unsigned char)(V);
96 Out << (unsigned char)(V >> 8);
97 Out << (unsigned char)(V >> 16);
98 Out << (unsigned char)(V >> 24);
99 }
100
101 void EmitBuf(const char* I, const char* E) {
102 for ( ; I != E ; ++I) Out << *I;
103 }
104
Ted Kremenekd4d6d222009-01-15 01:26:25 +0000105 std::pair<Offset,std::pair<Offset, Offset> > EmitIdentifierTable();
Ted Kremenek40291882009-01-08 01:17:37 +0000106 Offset EmitFileTable();
Ted Kremenek2e395562009-01-08 02:44:06 +0000107 PCHEntry LexTokens(Lexer& L);
108 void EmitCachedSpellings();
109
Ted Kremenek40291882009-01-08 01:17:37 +0000110public:
111 PTHWriter(llvm::raw_fd_ostream& out, Preprocessor& pp)
112 : Out(out), PP(pp), idcount(0) {}
113
114 void GeneratePTH();
115};
116} // end anonymous namespace
117
118uint32_t PTHWriter::ResolveID(const IdentifierInfo* II) {
Ted Kremenek62739d62008-12-02 19:44:08 +0000119 // Null IdentifierInfo's map to the persistent ID 0.
120 if (!II)
121 return 0;
122
Ted Kremenek71c6cc62008-10-21 00:54:44 +0000123 IDMap::iterator I = IM.find(II);
124
125 if (I == IM.end()) {
Ted Kremenek40291882009-01-08 01:17:37 +0000126 IM[II] = ++idcount; // Pre-increment since '0' is reserved for NULL.
127 return idcount;
Ted Kremenek71c6cc62008-10-21 00:54:44 +0000128 }
129
Ted Kremenek62739d62008-12-02 19:44:08 +0000130 return I->second; // We've already added 1.
Ted Kremenek71c6cc62008-10-21 00:54:44 +0000131}
132
Ted Kremenek40291882009-01-08 01:17:37 +0000133void PTHWriter::EmitToken(const Token& T) {
134 uint32_t fpos = PP.getSourceManager().getFullFilePos(T.getLocation());
135 Emit8(T.getKind());
136 Emit8(T.getFlags());
137 Emit24(ResolveID(T.getIdentifierInfo()));
138 Emit32(fpos);
139 Emit16(T.getLength());
140
Ted Kremenek40291882009-01-08 01:17:37 +0000141 // For specific tokens we cache their spelling.
142 if (T.getIdentifierInfo())
143 return;
144
145 switch (T.getKind()) {
Ted Kremeneke98da522009-01-09 00:37:37 +0000146 default:
147 break;
148 case tok::string_literal:
Ted Kremenek40291882009-01-08 01:17:37 +0000149 case tok::wide_string_literal:
150 case tok::angle_string_literal:
Ted Kremeneke98da522009-01-09 00:37:37 +0000151 case tok::numeric_constant:
Ted Kremenek2e395562009-01-08 02:44:06 +0000152 case tok::char_constant: {
153 // FIXME: This uses the slow getSpelling(). Perhaps we do better
154 // in the future? This only slows down PTH generation.
Ted Kremeneke98da522009-01-09 00:37:37 +0000155 const std::string& spelling = PP.getSpelling(T);
Ted Kremenek2e395562009-01-08 02:44:06 +0000156 const char* s = spelling.c_str();
157
158 // Get the string entry.
Ted Kremeneke98da522009-01-09 00:37:37 +0000159 llvm::StringMapEntry<Offset> *E =
160 &CachedStrs.GetOrCreateValue(s, s+spelling.size());
Ted Kremenek2e395562009-01-08 02:44:06 +0000161
162 // Store the address of the string entry in our spelling map.
163 (*CurSpellMap).push_back(std::make_pair(fpos, E));
164
Ted Kremenek40291882009-01-08 01:17:37 +0000165 break;
Ted Kremenek2e395562009-01-08 02:44:06 +0000166 }
Ted Kremenek40291882009-01-08 01:17:37 +0000167 }
Ted Kremenek71c6cc62008-10-21 00:54:44 +0000168}
169
Ted Kremenek40291882009-01-08 01:17:37 +0000170namespace {
171struct VISIBILITY_HIDDEN IDData {
Ted Kremenek3e0bb5b2008-11-26 23:58:26 +0000172 const IdentifierInfo* II;
173 uint32_t FileOffset;
Ted Kremenekd4d6d222009-01-15 01:26:25 +0000174};
175
176class VISIBILITY_HIDDEN CompareIDDataIndex {
177 IDData* Table;
178public:
179 CompareIDDataIndex(IDData* table) : Table(table) {}
180
181 bool operator()(unsigned i, unsigned j) const {
182 // Assume that IdentifierInfo::getName() returns a '\0' terminated string.
183 return strcmp(Table[i].II->getName(), Table[j].II->getName()) < 0;
184 }
Ted Kremenek3e0bb5b2008-11-26 23:58:26 +0000185};
Ted Kremenek40291882009-01-08 01:17:37 +0000186}
Ted Kremenekd330ec12008-11-26 03:36:26 +0000187
Ted Kremenekd4d6d222009-01-15 01:26:25 +0000188std::pair<Offset,std::pair<Offset,Offset> >
189PTHWriter::EmitIdentifierTable() {
190 llvm::BumpPtrAllocator Alloc;
Ted Kremenek3e0bb5b2008-11-26 23:58:26 +0000191
192 // Build an inverse map from persistent IDs -> IdentifierInfo*.
Ted Kremenekd4d6d222009-01-15 01:26:25 +0000193 IDData* IIDMap = Alloc.Allocate<IDData>(idcount);
Ted Kremenek71c6cc62008-10-21 00:54:44 +0000194
Ted Kremenek3e0bb5b2008-11-26 23:58:26 +0000195 // Generate mapping from persistent IDs -> IdentifierInfo*.
Ted Kremenek40291882009-01-08 01:17:37 +0000196 for (IDMap::iterator I=IM.begin(), E=IM.end(); I!=E; ++I) {
Ted Kremenek62739d62008-12-02 19:44:08 +0000197 // Decrement by 1 because we are using a vector for the lookup and
198 // 0 is reserved for NULL.
199 assert(I->second > 0);
Ted Kremenekd4d6d222009-01-15 01:26:25 +0000200 assert(I->second-1 < idcount);
201 unsigned idx = I->second-1;
202 IIDMap[idx].II = I->first;
203 }
Ted Kremenek3e0bb5b2008-11-26 23:58:26 +0000204
Ted Kremenekd4d6d222009-01-15 01:26:25 +0000205 // We want to write out the strings in lexical order to support binary
206 // search of strings to identifiers. Create such a table.
207 unsigned *LexicalOrder = Alloc.Allocate<unsigned>(idcount);
208 for (unsigned i = 0; i < idcount ; ++i ) LexicalOrder[i] = i;
209 std::sort(LexicalOrder, LexicalOrder+idcount, CompareIDDataIndex(IIDMap));
210
211 // Write out the lexically-sorted table of persistent ids.
212 Offset LexicalOff = Out.tell();
213 for (unsigned i = 0; i < idcount ; ++i) Emit32(LexicalOrder[i]);
214
215 // Write out the string data itself.
Ted Kremenek62739d62008-12-02 19:44:08 +0000216 Offset DataOff = Out.tell();
Ted Kremenekdb4c8e82008-12-03 01:16:39 +0000217
Ted Kremenekd4d6d222009-01-15 01:26:25 +0000218 for (unsigned i = 0; i < idcount; ++i) {
219 IDData& d = IIDMap[i];
220 d.FileOffset = Out.tell(); // Record the location for this data.
221 unsigned len = d.II->getLength(); // Write out the string length.
Ted Kremenek40291882009-01-08 01:17:37 +0000222 Emit32(len);
Ted Kremenekd4d6d222009-01-15 01:26:25 +0000223 const char* buf = d.II->getName(); // Write out the string data.
Ted Kremenek40291882009-01-08 01:17:37 +0000224 EmitBuf(buf, buf+len);
Ted Kremenek71c6cc62008-10-21 00:54:44 +0000225 }
Ted Kremenekd330ec12008-11-26 03:36:26 +0000226
Ted Kremenek3e0bb5b2008-11-26 23:58:26 +0000227 // Now emit the table mapping from persistent IDs to PTH file offsets.
Ted Kremenek62739d62008-12-02 19:44:08 +0000228 Offset IDOff = Out.tell();
Ted Kremenekd4d6d222009-01-15 01:26:25 +0000229 Emit32(idcount); // Emit the number of identifiers.
230 for (unsigned i = 0 ; i < idcount; ++i) Emit32(IIDMap[i].FileOffset);
Ted Kremenekdb4c8e82008-12-03 01:16:39 +0000231
Ted Kremenek62739d62008-12-02 19:44:08 +0000232
Ted Kremenekd4d6d222009-01-15 01:26:25 +0000233 return std::make_pair(DataOff, std::make_pair(IDOff, LexicalOff));
Ted Kremenek71c6cc62008-10-21 00:54:44 +0000234}
235
Ted Kremenek40291882009-01-08 01:17:37 +0000236Offset PTHWriter::EmitFileTable() {
237 // Determine the offset where this table appears in the PTH file.
Ted Kremenek62739d62008-12-02 19:44:08 +0000238 Offset off = (Offset) Out.tell();
Ted Kremenek40291882009-01-08 01:17:37 +0000239
Ted Kremenek3e0bb5b2008-11-26 23:58:26 +0000240 // Output the size of the table.
Ted Kremenek40291882009-01-08 01:17:37 +0000241 Emit32(PM.size());
Ted Kremenek3e0bb5b2008-11-26 23:58:26 +0000242
243 for (PCHMap::iterator I=PM.begin(), E=PM.end(); I!=E; ++I) {
Ted Kremenek3e0bb5b2008-11-26 23:58:26 +0000244 const FileEntry* FE = I->first;
Ted Kremenek11090552008-12-04 22:36:44 +0000245 const char* Name = FE->getName();
246 unsigned size = strlen(Name);
Ted Kremenek40291882009-01-08 01:17:37 +0000247 Emit32(size);
248 EmitBuf(Name, Name+size);
Ted Kremenek2e395562009-01-08 02:44:06 +0000249 Emit32(I->second.getTokenOffset());
250 Emit32(I->second.getPPCondTableOffset());
251 Emit32(I->second.getSpellingTableOffset());
Ted Kremenek3e0bb5b2008-11-26 23:58:26 +0000252 }
253
Ted Kremenekd330ec12008-11-26 03:36:26 +0000254 return off;
255}
256
Ted Kremenek2e395562009-01-08 02:44:06 +0000257PCHEntry PTHWriter::LexTokens(Lexer& L) {
Ted Kremenek40291882009-01-08 01:17:37 +0000258
Ted Kremenekd330ec12008-11-26 03:36:26 +0000259 // Record the location within the token file.
Ted Kremenek62739d62008-12-02 19:44:08 +0000260 Offset off = (Offset) Out.tell();
Ted Kremenek8309c922008-12-11 23:36:38 +0000261
262 // Keep track of matching '#if' ... '#endif'.
263 typedef std::vector<std::pair<Offset, unsigned> > PPCondTable;
264 PPCondTable PPCond;
Ted Kremenek0b5038d2008-12-12 18:31:09 +0000265 std::vector<unsigned> PPStartCond;
Ted Kremenek9ab79bf2008-12-23 01:30:52 +0000266 bool ParsingPreprocessorDirective = false;
Ted Kremenekd330ec12008-11-26 03:36:26 +0000267
Ted Kremenek2e395562009-01-08 02:44:06 +0000268 // Allocate a spelling map for this source file.
269 llvm::OwningPtr<SpellMapTy> Spellings(new SpellMapTy());
270 CurSpellMap = Spellings.get();
271
Ted Kremenekd330ec12008-11-26 03:36:26 +0000272 Token Tok;
273
274 do {
275 L.LexFromRawLexer(Tok);
276
Ted Kremenek9ab79bf2008-12-23 01:30:52 +0000277 if ((Tok.isAtStartOfLine() || Tok.is(tok::eof)) &&
278 ParsingPreprocessorDirective) {
279 // Insert an eom token into the token cache. It has the same
280 // position as the next token that is not on the same line as the
281 // preprocessor directive. Observe that we continue processing
282 // 'Tok' when we exit this branch.
283 Token Tmp = Tok;
284 Tmp.setKind(tok::eom);
285 Tmp.clearFlag(Token::StartOfLine);
286 Tmp.setIdentifierInfo(0);
Ted Kremenek40291882009-01-08 01:17:37 +0000287 EmitToken(Tmp);
Ted Kremenek9ab79bf2008-12-23 01:30:52 +0000288 ParsingPreprocessorDirective = false;
289 }
290
Ted Kremenekd330ec12008-11-26 03:36:26 +0000291 if (Tok.is(tok::identifier)) {
292 Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
Ted Kremenek9ab79bf2008-12-23 01:30:52 +0000293 continue;
Ted Kremenekd330ec12008-11-26 03:36:26 +0000294 }
Ted Kremenek9ab79bf2008-12-23 01:30:52 +0000295
296 if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
Ted Kremenekd330ec12008-11-26 03:36:26 +0000297 // Special processing for #include. Store the '#' token and lex
298 // the next token.
Ted Kremenek9ab79bf2008-12-23 01:30:52 +0000299 assert(!ParsingPreprocessorDirective);
Ted Kremenek8309c922008-12-11 23:36:38 +0000300 Offset HashOff = (Offset) Out.tell();
Ted Kremenek40291882009-01-08 01:17:37 +0000301 EmitToken(Tok);
Ted Kremenek0b5038d2008-12-12 18:31:09 +0000302
303 // Get the next token.
Ted Kremenekd330ec12008-11-26 03:36:26 +0000304 L.LexFromRawLexer(Tok);
Ted Kremenek9ab79bf2008-12-23 01:30:52 +0000305
306 assert(!Tok.isAtStartOfLine());
Ted Kremenekd330ec12008-11-26 03:36:26 +0000307
308 // Did we see 'include'/'import'/'include_next'?
309 if (!Tok.is(tok::identifier))
310 continue;
311
312 IdentifierInfo* II = PP.LookUpIdentifierInfo(Tok);
313 Tok.setIdentifierInfo(II);
314 tok::PPKeywordKind K = II->getPPKeywordID();
315
Ted Kremenek9ab79bf2008-12-23 01:30:52 +0000316 assert(K != tok::pp_not_keyword);
317 ParsingPreprocessorDirective = true;
318
319 switch (K) {
320 default:
321 break;
322 case tok::pp_include:
323 case tok::pp_import:
324 case tok::pp_include_next: {
Ted Kremenekd330ec12008-11-26 03:36:26 +0000325 // Save the 'include' token.
Ted Kremenek40291882009-01-08 01:17:37 +0000326 EmitToken(Tok);
Ted Kremenekd330ec12008-11-26 03:36:26 +0000327 // Lex the next token as an include string.
328 L.setParsingPreprocessorDirective(true);
329 L.LexIncludeFilename(Tok);
330 L.setParsingPreprocessorDirective(false);
Ted Kremenek9ab79bf2008-12-23 01:30:52 +0000331 assert(!Tok.isAtStartOfLine());
Ted Kremenekd330ec12008-11-26 03:36:26 +0000332 if (Tok.is(tok::identifier))
333 Tok.setIdentifierInfo(PP.LookUpIdentifierInfo(Tok));
Ted Kremenek9ab79bf2008-12-23 01:30:52 +0000334
335 break;
Ted Kremenekd330ec12008-11-26 03:36:26 +0000336 }
Ted Kremenek9ab79bf2008-12-23 01:30:52 +0000337 case tok::pp_if:
338 case tok::pp_ifdef:
339 case tok::pp_ifndef: {
Ted Kremenek8309c922008-12-11 23:36:38 +0000340 // Ad an entry for '#if' and friends. We initially set the target index
341 // to 0. This will get backpatched when we hit #endif.
342 PPStartCond.push_back(PPCond.size());
Ted Kremenek0b5038d2008-12-12 18:31:09 +0000343 PPCond.push_back(std::make_pair(HashOff, 0U));
Ted Kremenek9ab79bf2008-12-23 01:30:52 +0000344 break;
Ted Kremenek8309c922008-12-11 23:36:38 +0000345 }
Ted Kremenek9ab79bf2008-12-23 01:30:52 +0000346 case tok::pp_endif: {
Ted Kremenek8309c922008-12-11 23:36:38 +0000347 // Add an entry for '#endif'. We set the target table index to itself.
Ted Kremenek0b5038d2008-12-12 18:31:09 +0000348 // This will later be set to zero when emitting to the PTH file. We
349 // use 0 for uninitialized indices because that is easier to debug.
Ted Kremenek8309c922008-12-11 23:36:38 +0000350 unsigned index = PPCond.size();
Ted Kremenek8309c922008-12-11 23:36:38 +0000351 // Backpatch the opening '#if' entry.
Ted Kremenek0b5038d2008-12-12 18:31:09 +0000352 assert(!PPStartCond.empty());
353 assert(PPCond.size() > PPStartCond.back());
Ted Kremenek8309c922008-12-11 23:36:38 +0000354 assert(PPCond[PPStartCond.back()].second == 0);
355 PPCond[PPStartCond.back()].second = index;
356 PPStartCond.pop_back();
Ted Kremenek0b5038d2008-12-12 18:31:09 +0000357 // Add the new entry to PPCond.
358 PPCond.push_back(std::make_pair(HashOff, index));
Ted Kremenek9ab79bf2008-12-23 01:30:52 +0000359 break;
Ted Kremenek8309c922008-12-11 23:36:38 +0000360 }
Ted Kremenek9ab79bf2008-12-23 01:30:52 +0000361 case tok::pp_elif:
362 case tok::pp_else: {
363 // Add an entry for #elif or #else.
Ted Kremenek0b5038d2008-12-12 18:31:09 +0000364 // This serves as both a closing and opening of a conditional block.
365 // This means that its entry will get backpatched later.
Ted Kremenek8309c922008-12-11 23:36:38 +0000366 unsigned index = PPCond.size();
Ted Kremenek8309c922008-12-11 23:36:38 +0000367 // Backpatch the previous '#if' entry.
Ted Kremenek0b5038d2008-12-12 18:31:09 +0000368 assert(!PPStartCond.empty());
369 assert(PPCond.size() > PPStartCond.back());
Ted Kremenek8309c922008-12-11 23:36:38 +0000370 assert(PPCond[PPStartCond.back()].second == 0);
371 PPCond[PPStartCond.back()].second = index;
372 PPStartCond.pop_back();
373 // Now add '#elif' as a new block opening.
Ted Kremenek0b5038d2008-12-12 18:31:09 +0000374 PPCond.push_back(std::make_pair(HashOff, 0U));
375 PPStartCond.push_back(index);
Ted Kremenek9ab79bf2008-12-23 01:30:52 +0000376 break;
377 }
Ted Kremenek8309c922008-12-11 23:36:38 +0000378 }
Ted Kremenekd330ec12008-11-26 03:36:26 +0000379 }
380 }
Ted Kremenek40291882009-01-08 01:17:37 +0000381 while (EmitToken(Tok), Tok.isNot(tok::eof));
382
Ted Kremenek0b5038d2008-12-12 18:31:09 +0000383 assert(PPStartCond.empty() && "Error: imblanced preprocessor conditionals.");
Ted Kremenek40291882009-01-08 01:17:37 +0000384
Ted Kremenek8309c922008-12-11 23:36:38 +0000385 // Next write out PPCond.
386 Offset PPCondOff = (Offset) Out.tell();
Ted Kremenek0b5038d2008-12-12 18:31:09 +0000387
388 // Write out the size of PPCond so that clients can identifer empty tables.
Ted Kremenek40291882009-01-08 01:17:37 +0000389 Emit32(PPCond.size());
Ted Kremenek62739d62008-12-02 19:44:08 +0000390
Ted Kremenek0b5038d2008-12-12 18:31:09 +0000391 for (unsigned i = 0, e = PPCond.size(); i!=e; ++i) {
Ted Kremenek40291882009-01-08 01:17:37 +0000392 Emit32(PPCond[i].first - off);
Ted Kremenek0b5038d2008-12-12 18:31:09 +0000393 uint32_t x = PPCond[i].second;
394 assert(x != 0 && "PPCond entry not backpatched.");
395 // Emit zero for #endifs. This allows us to do checking when
396 // we read the PTH file back in.
Ted Kremenek40291882009-01-08 01:17:37 +0000397 Emit32(x == i ? 0 : x);
Ted Kremenek8309c922008-12-11 23:36:38 +0000398 }
399
Ted Kremenek2e395562009-01-08 02:44:06 +0000400 return PCHEntry(off, PPCondOff, Spellings.take());
401}
402
403void PTHWriter::EmitCachedSpellings() {
404 // Write each cached string to the PTH file and update the
405 // the string map entry to contain the relevant offset.
406 //
407 // FIXME: We can write the strings out in order of their frequency. This
408 // may result in better locality.
409 //
410 for (CachedStrsTy::iterator I = CachedStrs.begin(), E = CachedStrs.end();
411 I!=E; ++I) {
412
413 Offset off = Out.tell();
414
415 // Write out the length of the string before the string itself.
416 unsigned len = I->getKeyLength();
Ted Kremeneke98da522009-01-09 00:37:37 +0000417 Emit16(len);
Ted Kremenek2e395562009-01-08 02:44:06 +0000418
419 // Write out the string data.
420 const char* data = I->getKeyData();
421 EmitBuf(data, data+len);
422
Ted Kremeneke98da522009-01-09 00:37:37 +0000423 // Write out a single blank character.
424 Emit8(' ');
425
Ted Kremenek2e395562009-01-08 02:44:06 +0000426 // Now patch the offset of the string in the PTH file into the string map.
Ted Kremeneke98da522009-01-09 00:37:37 +0000427 I->setValue(off);
Ted Kremenek2e395562009-01-08 02:44:06 +0000428 }
429
430 // Now emit the spelling tables.
431 for (PCHMap::iterator I=PM.begin(), E=PM.end(); I!=E; ++I) {
432 SpellMapTy& spellings = I->second.getSpellings();
433 I->second.setSpellingTableOffset(Out.tell());
434
435 // Write out the number of spellings.
436 unsigned n = spellings.size();
437 Emit32(n);
438
439 for (unsigned i = 0; i < n; ++i) {
Ted Kremenek2e395562009-01-08 02:44:06 +0000440 // Write out the offset of the token within the source file.
441 Emit32(spellings[i].first);
442
443 // Write out the offset of the spelling data within the PTH file.
Ted Kremeneke98da522009-01-09 00:37:37 +0000444 Emit32(spellings[i].second->getValue());
Ted Kremenek2e395562009-01-08 02:44:06 +0000445 }
446
447 // Delete the spelling map for this source file.
448 delete &spellings;
449 }
Ted Kremenekd330ec12008-11-26 03:36:26 +0000450}
Ted Kremenek71c6cc62008-10-21 00:54:44 +0000451
Ted Kremenek40291882009-01-08 01:17:37 +0000452void PTHWriter::GeneratePTH() {
Ted Kremenek71c6cc62008-10-21 00:54:44 +0000453 // Iterate over all the files in SourceManager. Create a lexer
454 // for each file and cache the tokens.
455 SourceManager& SM = PP.getSourceManager();
456 const LangOptions& LOpts = PP.getLangOptions();
Ted Kremenek71c6cc62008-10-21 00:54:44 +0000457
458 for (SourceManager::fileid_iterator I=SM.fileid_begin(), E=SM.fileid_end();
459 I!=E; ++I) {
460
461 const SrcMgr::ContentCache* C = I.getFileIDInfo().getContentCache();
Ted Kremenekd330ec12008-11-26 03:36:26 +0000462 if (!C) continue;
Ted Kremenek71c6cc62008-10-21 00:54:44 +0000463
Ted Kremenekd330ec12008-11-26 03:36:26 +0000464 const FileEntry* FE = C->Entry; // Does this entry correspond to a file?
465 if (!FE) continue;
Ted Kremenek62739d62008-12-02 19:44:08 +0000466
467 // FIXME: Handle files with non-absolute paths.
468 llvm::sys::Path P(FE->getName());
469 if (!P.isAbsolute())
470 continue;
Ted Kremenek71c6cc62008-10-21 00:54:44 +0000471
Ted Kremenekd330ec12008-11-26 03:36:26 +0000472 PCHMap::iterator PI = PM.find(FE); // Have we already processed this file?
473 if (PI != PM.end()) continue;
474
Chris Lattner5331d912009-01-06 04:47:20 +0000475 const llvm::MemoryBuffer* B = C->getBuffer();
Ted Kremenekd330ec12008-11-26 03:36:26 +0000476 if (!B) continue;
477
Ted Kremenek71c6cc62008-10-21 00:54:44 +0000478 Lexer L(SourceLocation::getFileLoc(I.getFileID(), 0), LOpts,
479 B->getBufferStart(), B->getBufferEnd(), B);
Ted Kremenek8309c922008-12-11 23:36:38 +0000480
Ted Kremenek40291882009-01-08 01:17:37 +0000481 PM[FE] = LexTokens(L);
Daniel Dunbareee6d102008-11-26 02:18:33 +0000482 }
Ted Kremenekd330ec12008-11-26 03:36:26 +0000483
484 // Write out the identifier table.
Ted Kremenekd4d6d222009-01-15 01:26:25 +0000485 const std::pair<Offset, std::pair<Offset,Offset> >& IdTableOff
486 = EmitIdentifierTable();
Ted Kremenek71c6cc62008-10-21 00:54:44 +0000487
Ted Kremenek2e395562009-01-08 02:44:06 +0000488 // Write out the cached strings table.
489 EmitCachedSpellings();
490
Ted Kremenekd330ec12008-11-26 03:36:26 +0000491 // Write out the file table.
Ted Kremenek40291882009-01-08 01:17:37 +0000492 Offset FileTableOff = EmitFileTable();
Ted Kremenekd330ec12008-11-26 03:36:26 +0000493
494 // Finally, write out the offset table at the end.
Ted Kremenek40291882009-01-08 01:17:37 +0000495 Emit32(IdTableOff.first);
Ted Kremenekd4d6d222009-01-15 01:26:25 +0000496 Emit32(IdTableOff.second.first);
497 Emit32(IdTableOff.second.second);
Ted Kremenek40291882009-01-08 01:17:37 +0000498 Emit32(FileTableOff);
499}
500
501void clang::CacheTokens(Preprocessor& PP, const std::string& OutFile) {
502 // Lex through the entire file. This will populate SourceManager with
503 // all of the header information.
504 Token Tok;
505 PP.EnterMainSourceFile();
506 do { PP.Lex(Tok); } while (Tok.isNot(tok::eof));
507
508 // Open up the PTH file.
509 std::string ErrMsg;
510 llvm::raw_fd_ostream Out(OutFile.c_str(), true, ErrMsg);
511
512 if (!ErrMsg.empty()) {
513 llvm::errs() << "PTH error: " << ErrMsg << "\n";
514 return;
515 }
516
517 // Create the PTHWriter and generate the PTH file.
518 PTHWriter PW(Out, PP);
519 PW.GeneratePTH();
Ted Kremenek71c6cc62008-10-21 00:54:44 +0000520}