blob: 6f78ee175c62f29d31a96e7c0532f53e227e4a49 [file] [log] [blame]
Reid Spencer5f016e22007-07-11 17:01:13 +00001//===--- SourceManager.cpp - Track and cache source files -----------------===//
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 SourceManager interface.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Basic/SourceManager.h"
15#include "clang/Basic/FileManager.h"
Chris Lattner5e36a7a2007-07-24 05:57:19 +000016#include "llvm/Support/Compiler.h"
Reid Spencer5f016e22007-07-11 17:01:13 +000017#include "llvm/Support/MemoryBuffer.h"
18#include "llvm/System/Path.h"
Ted Kremenek78d85f52007-10-30 21:08:08 +000019#include "llvm/Bitcode/Serialize.h"
20#include "llvm/Bitcode/Deserialize.h"
Ted Kremenek665dd4a2007-12-05 22:21:13 +000021#include "llvm/Support/Streams.h"
Reid Spencer5f016e22007-07-11 17:01:13 +000022#include <algorithm>
Reid Spencer5f016e22007-07-11 17:01:13 +000023using namespace clang;
24using namespace SrcMgr;
25using llvm::MemoryBuffer;
26
Chris Lattnerde7aeef2009-01-26 00:43:02 +000027//===--------------------------------------------------------------------===//
28// SourceManager Helper Classes
29//===--------------------------------------------------------------------===//
30
Ted Kremenek78d85f52007-10-30 21:08:08 +000031ContentCache::~ContentCache() {
32 delete Buffer;
Reid Spencer5f016e22007-07-11 17:01:13 +000033}
34
Ted Kremenekc16c2082009-01-06 01:55:26 +000035/// getSizeBytesMapped - Returns the number of bytes actually mapped for
36/// this ContentCache. This can be 0 if the MemBuffer was not actually
37/// instantiated.
38unsigned ContentCache::getSizeBytesMapped() const {
39 return Buffer ? Buffer->getBufferSize() : 0;
40}
41
42/// getSize - Returns the size of the content encapsulated by this ContentCache.
43/// This can be the size of the source file or the size of an arbitrary
44/// scratch buffer. If the ContentCache encapsulates a source file, that
45/// file is not lazily brought in from disk to satisfy this query.
46unsigned ContentCache::getSize() const {
47 return Entry ? Entry->getSize() : Buffer->getBufferSize();
48}
49
Chris Lattner987cd3d2009-01-26 07:37:49 +000050const llvm::MemoryBuffer *ContentCache::getBuffer() const {
Ted Kremenek5b034ad2009-01-06 22:43:04 +000051 // Lazily create the Buffer for ContentCaches that wrap files.
52 if (!Buffer && Entry) {
53 // FIXME: Should we support a way to not have to do this check over
54 // and over if we cannot open the file?
Chris Lattner05816592009-01-17 03:54:16 +000055 Buffer = MemoryBuffer::getFile(Entry->getName(), 0, Entry->getSize());
Ted Kremenek5b034ad2009-01-06 22:43:04 +000056 }
Ted Kremenekc16c2082009-01-06 01:55:26 +000057 return Buffer;
58}
59
Chris Lattnerde7aeef2009-01-26 00:43:02 +000060//===--------------------------------------------------------------------===//
Chris Lattner5b9a5042009-01-26 07:57:50 +000061// Line Table Implementation
62//===--------------------------------------------------------------------===//
63
64namespace clang {
65/// LineTableInfo - This class is used to hold and unique data used to
66/// represent #line information.
67class LineTableInfo {
68 /// FilenameIDs - This map is used to assign unique IDs to filenames in
69 /// #line directives. This allows us to unique the filenames that
70 /// frequently reoccur and reference them with indices. FilenameIDs holds
71 /// the mapping from string -> ID, and FilenamesByID holds the mapping of ID
72 /// to string.
73 llvm::StringMap<unsigned, llvm::BumpPtrAllocator> FilenameIDs;
74 std::vector<llvm::StringMapEntry<unsigned>*> FilenamesByID;
75public:
76 LineTableInfo() {
77 }
78
79 void clear() {
80 FilenameIDs.clear();
81 FilenamesByID.clear();
82 }
83
84 ~LineTableInfo() {}
85
86 unsigned getLineTableFilenameID(const char *Ptr, unsigned Len);
87
88};
89} // namespace clang
90
91
92
93
94unsigned LineTableInfo::getLineTableFilenameID(const char *Ptr, unsigned Len) {
95 // Look up the filename in the string table, returning the pre-existing value
96 // if it exists.
97 llvm::StringMapEntry<unsigned> &Entry =
98 FilenameIDs.GetOrCreateValue(Ptr, Ptr+Len, ~0U);
99 if (Entry.getValue() != ~0U)
100 return Entry.getValue();
101
102 // Otherwise, assign this the next available ID.
103 Entry.setValue(FilenamesByID.size());
104 FilenamesByID.push_back(&Entry);
105 return FilenamesByID.size()-1;
106}
107
108/// getLineTableFilenameID - Return the uniqued ID for the specified filename.
109///
110unsigned SourceManager::getLineTableFilenameID(const char *Ptr, unsigned Len) {
111 if (LineTable == 0)
112 LineTable = new LineTableInfo();
113 return LineTable->getLineTableFilenameID(Ptr, Len);
114}
115
116
117//===--------------------------------------------------------------------===//
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000118// Private 'Create' methods.
119//===--------------------------------------------------------------------===//
Ted Kremenekc16c2082009-01-06 01:55:26 +0000120
Chris Lattner5b9a5042009-01-26 07:57:50 +0000121SourceManager::~SourceManager() {
122 delete LineTable;
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000123
124 // Delete FileEntry objects corresponding to content caches. Since the actual
125 // content cache objects are bump pointer allocated, we just have to run the
126 // dtors, but we call the deallocate method for completeness.
127 for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) {
128 MemBufferInfos[i]->~ContentCache();
129 ContentCacheAlloc.Deallocate(MemBufferInfos[i]);
130 }
131 for (llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::iterator
132 I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {
133 I->second->~ContentCache();
134 ContentCacheAlloc.Deallocate(I->second);
135 }
Chris Lattner5b9a5042009-01-26 07:57:50 +0000136}
137
138void SourceManager::clearIDTables() {
139 MainFileID = FileID();
140 SLocEntryTable.clear();
141 LastLineNoFileIDQuery = FileID();
142 LastLineNoContentCache = 0;
143 LastFileIDLookup = FileID();
144
145 if (LineTable)
146 LineTable->clear();
147
148 // Use up FileID #0 as an invalid instantiation.
149 NextOffset = 0;
150 createInstantiationLoc(SourceLocation(), SourceLocation(), 1);
151}
152
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000153/// getOrCreateContentCache - Create or return a cached ContentCache for the
154/// specified file.
155const ContentCache *
156SourceManager::getOrCreateContentCache(const FileEntry *FileEnt) {
Reid Spencer5f016e22007-07-11 17:01:13 +0000157 assert(FileEnt && "Didn't specify a file entry to use?");
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000158
Reid Spencer5f016e22007-07-11 17:01:13 +0000159 // Do we already have information about this file?
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000160 ContentCache *&Entry = FileInfos[FileEnt];
161 if (Entry) return Entry;
Reid Spencer5f016e22007-07-11 17:01:13 +0000162
Chris Lattner00282d62009-02-03 07:41:46 +0000163 // Nope, create a new Cache entry. Make sure it is at least 8-byte aligned
164 // so that FileInfo can use the low 3 bits of the pointer for its own
165 // nefarious purposes.
166 unsigned EntryAlign = llvm::AlignOf<ContentCache>::Alignment;
167 EntryAlign = std::max(8U, EntryAlign);
168 Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign);
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000169 new (Entry) ContentCache(FileEnt);
170 return Entry;
Reid Spencer5f016e22007-07-11 17:01:13 +0000171}
172
173
Ted Kremenekd1c0eee2007-10-31 17:53:38 +0000174/// createMemBufferContentCache - Create a new ContentCache for the specified
175/// memory buffer. This does no caching.
Ted Kremenek78d85f52007-10-30 21:08:08 +0000176const ContentCache*
177SourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) {
Chris Lattner00282d62009-02-03 07:41:46 +0000178 // Add a new ContentCache to the MemBufferInfos list and return it. Make sure
179 // it is at least 8-byte aligned so that FileInfo can use the low 3 bits of
180 // the pointer for its own nefarious purposes.
181 unsigned EntryAlign = llvm::AlignOf<ContentCache>::Alignment;
182 EntryAlign = std::max(8U, EntryAlign);
183 ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign);
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000184 new (Entry) ContentCache();
185 MemBufferInfos.push_back(Entry);
186 Entry->setBuffer(Buffer);
187 return Entry;
Reid Spencer5f016e22007-07-11 17:01:13 +0000188}
189
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000190//===----------------------------------------------------------------------===//
191// Methods to create new FileID's and instantiations.
192//===----------------------------------------------------------------------===//
Reid Spencer5f016e22007-07-11 17:01:13 +0000193
Nico Weber48002c82008-09-29 00:25:48 +0000194/// createFileID - Create a new fileID for the specified ContentCache and
Ted Kremenek0d892d82007-10-30 22:57:35 +0000195/// include position. This works regardless of whether the ContentCache
196/// corresponds to a file or some other input source.
Chris Lattner2b2453a2009-01-17 06:22:33 +0000197FileID SourceManager::createFileID(const ContentCache *File,
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000198 SourceLocation IncludePos,
199 SrcMgr::CharacteristicKind FileCharacter) {
200 SLocEntryTable.push_back(SLocEntry::get(NextOffset,
201 FileInfo::get(IncludePos, File,
202 FileCharacter)));
Ted Kremenekc16c2082009-01-06 01:55:26 +0000203 unsigned FileSize = File->getSize();
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000204 assert(NextOffset+FileSize+1 > NextOffset && "Ran out of source locations!");
205 NextOffset += FileSize+1;
Reid Spencer5f016e22007-07-11 17:01:13 +0000206
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000207 // Set LastFileIDLookup to the newly created file. The next getFileID call is
208 // almost guaranteed to be from that file.
209 return LastFileIDLookup = FileID::get(SLocEntryTable.size()-1);
Reid Spencer5f016e22007-07-11 17:01:13 +0000210}
211
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000212/// createInstantiationLoc - Return a new SourceLocation that encodes the fact
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000213/// that a token from SpellingLoc should actually be referenced from
Reid Spencer5f016e22007-07-11 17:01:13 +0000214/// InstantiationLoc.
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000215SourceLocation SourceManager::createInstantiationLoc(SourceLocation SpellingLoc,
216 SourceLocation InstantLoc,
217 unsigned TokLength) {
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000218 SLocEntryTable.push_back(SLocEntry::get(NextOffset,
219 InstantiationInfo::get(InstantLoc,
220 SpellingLoc)));
221 assert(NextOffset+TokLength+1 > NextOffset && "Ran out of source locations!");
222 NextOffset += TokLength+1;
223 return SourceLocation::getMacroLoc(NextOffset-(TokLength+1));
Reid Spencer5f016e22007-07-11 17:01:13 +0000224}
225
Chris Lattner31530ba2009-01-19 07:32:13 +0000226/// getBufferData - Return a pointer to the start and end of the source buffer
227/// data for the specified FileID.
Chris Lattner2b2453a2009-01-17 06:22:33 +0000228std::pair<const char*, const char*>
229SourceManager::getBufferData(FileID FID) const {
230 const llvm::MemoryBuffer *Buf = getBuffer(FID);
231 return std::make_pair(Buf->getBufferStart(), Buf->getBufferEnd());
232}
233
234
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000235//===--------------------------------------------------------------------===//
236// SourceLocation manipulation methods.
237//===--------------------------------------------------------------------===//
238
239/// getFileIDSlow - Return the FileID for a SourceLocation. This is a very hot
240/// method that is used for all SourceManager queries that start with a
241/// SourceLocation object. It is responsible for finding the entry in
242/// SLocEntryTable which contains the specified location.
243///
244FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
245 assert(SLocOffset && "Invalid FileID");
246
247 // After the first and second level caches, I see two common sorts of
248 // behavior: 1) a lot of searched FileID's are "near" the cached file location
249 // or are "near" the cached instantiation location. 2) others are just
250 // completely random and may be a very long way away.
251 //
252 // To handle this, we do a linear search for up to 8 steps to catch #1 quickly
253 // then we fall back to a less cache efficient, but more scalable, binary
254 // search to find the location.
255
256 // See if this is near the file point - worst case we start scanning from the
257 // most newly created FileID.
258 std::vector<SrcMgr::SLocEntry>::const_iterator I;
259
260 if (SLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) {
261 // Neither loc prunes our search.
262 I = SLocEntryTable.end();
263 } else {
264 // Perhaps it is near the file point.
265 I = SLocEntryTable.begin()+LastFileIDLookup.ID;
266 }
267
268 // Find the FileID that contains this. "I" is an iterator that points to a
269 // FileID whose offset is known to be larger than SLocOffset.
270 unsigned NumProbes = 0;
271 while (1) {
272 --I;
273 if (I->getOffset() <= SLocOffset) {
274#if 0
275 printf("lin %d -> %d [%s] %d %d\n", SLocOffset,
276 I-SLocEntryTable.begin(),
277 I->isInstantiation() ? "inst" : "file",
278 LastFileIDLookup.ID, int(SLocEntryTable.end()-I));
279#endif
280 FileID Res = FileID::get(I-SLocEntryTable.begin());
281
282 // If this isn't an instantiation, remember it. We have good locality
283 // across FileID lookups.
284 if (!I->isInstantiation())
285 LastFileIDLookup = Res;
286 NumLinearScans += NumProbes+1;
287 return Res;
288 }
289 if (++NumProbes == 8)
290 break;
291 }
292
293 // Convert "I" back into an index. We know that it is an entry whose index is
294 // larger than the offset we are looking for.
295 unsigned GreaterIndex = I-SLocEntryTable.begin();
296 // LessIndex - This is the lower bound of the range that we're searching.
297 // We know that the offset corresponding to the FileID is is less than
298 // SLocOffset.
299 unsigned LessIndex = 0;
300 NumProbes = 0;
301 while (1) {
302 unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
303 unsigned MidOffset = SLocEntryTable[MiddleIndex].getOffset();
304
305 ++NumProbes;
306
307 // If the offset of the midpoint is too large, chop the high side of the
308 // range to the midpoint.
309 if (MidOffset > SLocOffset) {
310 GreaterIndex = MiddleIndex;
311 continue;
312 }
313
314 // If the middle index contains the value, succeed and return.
315 if (isOffsetInFileID(FileID::get(MiddleIndex), SLocOffset)) {
316#if 0
317 printf("bin %d -> %d [%s] %d %d\n", SLocOffset,
318 I-SLocEntryTable.begin(),
319 I->isInstantiation() ? "inst" : "file",
320 LastFileIDLookup.ID, int(SLocEntryTable.end()-I));
321#endif
322 FileID Res = FileID::get(MiddleIndex);
323
324 // If this isn't an instantiation, remember it. We have good locality
325 // across FileID lookups.
326 if (!I->isInstantiation())
327 LastFileIDLookup = Res;
328 NumBinaryProbes += NumProbes;
329 return Res;
330 }
331
332 // Otherwise, move the low-side up to the middle index.
333 LessIndex = MiddleIndex;
334 }
335}
336
Chris Lattneraddb7972009-01-26 20:04:19 +0000337SourceLocation SourceManager::
338getInstantiationLocSlowCase(SourceLocation Loc) const {
339 do {
340 std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
341 Loc =getSLocEntry(LocInfo.first).getInstantiation().getInstantiationLoc();
342 Loc = Loc.getFileLocWithOffset(LocInfo.second);
343 } while (!Loc.isFileID());
344
345 return Loc;
346}
347
348SourceLocation SourceManager::getSpellingLocSlowCase(SourceLocation Loc) const {
349 do {
350 std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
351 Loc = getSLocEntry(LocInfo.first).getInstantiation().getSpellingLoc();
352 Loc = Loc.getFileLocWithOffset(LocInfo.second);
353 } while (!Loc.isFileID());
354 return Loc;
355}
356
357
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000358std::pair<FileID, unsigned>
359SourceManager::getDecomposedInstantiationLocSlowCase(const SrcMgr::SLocEntry *E,
360 unsigned Offset) const {
361 // If this is an instantiation record, walk through all the instantiation
362 // points.
363 FileID FID;
364 SourceLocation Loc;
365 do {
366 Loc = E->getInstantiation().getInstantiationLoc();
367
368 FID = getFileID(Loc);
369 E = &getSLocEntry(FID);
370 Offset += Loc.getOffset()-E->getOffset();
Chris Lattnerbcd1a1b2009-01-26 19:41:58 +0000371 } while (!Loc.isFileID());
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000372
373 return std::make_pair(FID, Offset);
374}
375
376std::pair<FileID, unsigned>
377SourceManager::getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,
378 unsigned Offset) const {
Chris Lattnerbcd1a1b2009-01-26 19:41:58 +0000379 // If this is an instantiation record, walk through all the instantiation
380 // points.
381 FileID FID;
382 SourceLocation Loc;
383 do {
384 Loc = E->getInstantiation().getSpellingLoc();
385
386 FID = getFileID(Loc);
387 E = &getSLocEntry(FID);
388 Offset += Loc.getOffset()-E->getOffset();
389 } while (!Loc.isFileID());
390
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000391 return std::make_pair(FID, Offset);
392}
393
394
395//===----------------------------------------------------------------------===//
396// Queries about the code at a SourceLocation.
397//===----------------------------------------------------------------------===//
Reid Spencer5f016e22007-07-11 17:01:13 +0000398
399/// getCharacterData - Return a pointer to the start of the specified location
400/// in the appropriate MemoryBuffer.
401const char *SourceManager::getCharacterData(SourceLocation SL) const {
402 // Note that this is a hot function in the getSpelling() path, which is
403 // heavily used by -E mode.
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000404 std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(SL);
Chris Lattner2b2453a2009-01-17 06:22:33 +0000405
Ted Kremenekc16c2082009-01-06 01:55:26 +0000406 // Note that calling 'getBuffer()' may lazily page in a source file.
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000407 return getSLocEntry(LocInfo.first).getFile().getContentCache()
408 ->getBuffer()->getBufferStart() + LocInfo.second;
Reid Spencer5f016e22007-07-11 17:01:13 +0000409}
410
Reid Spencer5f016e22007-07-11 17:01:13 +0000411
Chris Lattner9dc1f532007-07-20 16:37:10 +0000412/// getColumnNumber - Return the column # for the specified file position.
Reid Spencer5f016e22007-07-11 17:01:13 +0000413/// this is significantly cheaper to compute than the line number. This returns
414/// zero if the column number isn't known.
415unsigned SourceManager::getColumnNumber(SourceLocation Loc) const {
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000416 if (Loc.isInvalid()) return 0;
417 assert(Loc.isFileID() && "Don't know what part of instantiation loc to get");
Reid Spencer5f016e22007-07-11 17:01:13 +0000418
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000419 std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
Chris Lattner2b2453a2009-01-17 06:22:33 +0000420 unsigned FilePos = LocInfo.second;
421
422 const char *Buf = getBuffer(LocInfo.first)->getBufferStart();
Reid Spencer5f016e22007-07-11 17:01:13 +0000423
424 unsigned LineStart = FilePos;
425 while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
426 --LineStart;
427 return FilePos-LineStart+1;
428}
429
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000430static void ComputeLineNumbers(ContentCache* FI,
431 llvm::BumpPtrAllocator &Alloc) DISABLE_INLINE;
432static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){
Ted Kremenekc16c2082009-01-06 01:55:26 +0000433 // Note that calling 'getBuffer()' may lazily page in the file.
434 const MemoryBuffer *Buffer = FI->getBuffer();
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000435
436 // Find the file offsets of all of the *physical* source lines. This does
437 // not look at trigraphs, escaped newlines, or anything else tricky.
438 std::vector<unsigned> LineOffsets;
439
440 // Line #1 starts at char 0.
441 LineOffsets.push_back(0);
442
443 const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart();
444 const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd();
445 unsigned Offs = 0;
446 while (1) {
447 // Skip over the contents of the line.
448 // TODO: Vectorize this? This is very performance sensitive for programs
449 // with lots of diagnostics and in -E mode.
450 const unsigned char *NextBuf = (const unsigned char *)Buf;
451 while (*NextBuf != '\n' && *NextBuf != '\r' && *NextBuf != '\0')
452 ++NextBuf;
453 Offs += NextBuf-Buf;
454 Buf = NextBuf;
455
456 if (Buf[0] == '\n' || Buf[0] == '\r') {
457 // If this is \n\r or \r\n, skip both characters.
458 if ((Buf[1] == '\n' || Buf[1] == '\r') && Buf[0] != Buf[1])
459 ++Offs, ++Buf;
460 ++Offs, ++Buf;
461 LineOffsets.push_back(Offs);
462 } else {
463 // Otherwise, this is a null. If end of file, exit.
464 if (Buf == End) break;
465 // Otherwise, skip the null.
466 ++Offs, ++Buf;
467 }
468 }
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000469
470 // Copy the offsets into the FileInfo structure.
471 FI->NumLines = LineOffsets.size();
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000472 FI->SourceLineCache = Alloc.Allocate<unsigned>(LineOffsets.size());
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000473 std::copy(LineOffsets.begin(), LineOffsets.end(), FI->SourceLineCache);
474}
Reid Spencer5f016e22007-07-11 17:01:13 +0000475
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000476/// getLineNumber - Given a SourceLocation, return the spelling line number
Reid Spencer5f016e22007-07-11 17:01:13 +0000477/// for the position indicated. This requires building and caching a table of
478/// line offsets for the MemoryBuffer, so this is not cheap: use only when
479/// about to emit a diagnostic.
Chris Lattnerf812a452008-11-18 06:51:15 +0000480unsigned SourceManager::getLineNumber(SourceLocation Loc) const {
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000481 if (Loc.isInvalid()) return 0;
482 assert(Loc.isFileID() && "Don't know what part of instantiation loc to get");
Ted Kremenek78d85f52007-10-30 21:08:08 +0000483
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000484 std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
485
Chris Lattner2b2453a2009-01-17 06:22:33 +0000486 ContentCache *Content;
Chris Lattner2b2453a2009-01-17 06:22:33 +0000487 if (LastLineNoFileIDQuery == LocInfo.first)
Ted Kremenek78d85f52007-10-30 21:08:08 +0000488 Content = LastLineNoContentCache;
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000489 else
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000490 Content = const_cast<ContentCache*>(getSLocEntry(LocInfo.first)
491 .getFile().getContentCache());
Reid Spencer5f016e22007-07-11 17:01:13 +0000492
493 // If this is the first use of line information for this buffer, compute the
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000494 /// SourceLineCache for it on demand.
Ted Kremenek78d85f52007-10-30 21:08:08 +0000495 if (Content->SourceLineCache == 0)
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000496 ComputeLineNumbers(Content, ContentCacheAlloc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000497
498 // Okay, we know we have a line number table. Do a binary search to find the
499 // line number that this character position lands on.
Ted Kremenek78d85f52007-10-30 21:08:08 +0000500 unsigned *SourceLineCache = Content->SourceLineCache;
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000501 unsigned *SourceLineCacheStart = SourceLineCache;
Ted Kremenek78d85f52007-10-30 21:08:08 +0000502 unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines;
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000503
Chris Lattner2b2453a2009-01-17 06:22:33 +0000504 unsigned QueriedFilePos = LocInfo.second+1;
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000505
506 // If the previous query was to the same file, we know both the file pos from
507 // that query and the line number returned. This allows us to narrow the
508 // search space from the entire file to something near the match.
Chris Lattner2b2453a2009-01-17 06:22:33 +0000509 if (LastLineNoFileIDQuery == LocInfo.first) {
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000510 if (QueriedFilePos >= LastLineNoFilePos) {
511 SourceLineCache = SourceLineCache+LastLineNoResult-1;
512
513 // The query is likely to be nearby the previous one. Here we check to
514 // see if it is within 5, 10 or 20 lines. It can be far away in cases
515 // where big comment blocks and vertical whitespace eat up lines but
516 // contribute no tokens.
517 if (SourceLineCache+5 < SourceLineCacheEnd) {
518 if (SourceLineCache[5] > QueriedFilePos)
519 SourceLineCacheEnd = SourceLineCache+5;
520 else if (SourceLineCache+10 < SourceLineCacheEnd) {
521 if (SourceLineCache[10] > QueriedFilePos)
522 SourceLineCacheEnd = SourceLineCache+10;
523 else if (SourceLineCache+20 < SourceLineCacheEnd) {
524 if (SourceLineCache[20] > QueriedFilePos)
525 SourceLineCacheEnd = SourceLineCache+20;
526 }
527 }
528 }
529 } else {
530 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
531 }
532 }
533
Chris Lattner1cf12bf2007-07-24 06:43:46 +0000534 // If the spread is large, do a "radix" test as our initial guess, based on
535 // the assumption that lines average to approximately the same length.
536 // NOTE: This is currently disabled, as it does not appear to be profitable in
537 // initial measurements.
538 if (0 && SourceLineCacheEnd-SourceLineCache > 20) {
Ted Kremenek78d85f52007-10-30 21:08:08 +0000539 unsigned FileLen = Content->SourceLineCache[Content->NumLines-1];
Chris Lattner1cf12bf2007-07-24 06:43:46 +0000540
541 // Take a stab at guessing where it is.
Ted Kremenek78d85f52007-10-30 21:08:08 +0000542 unsigned ApproxPos = Content->NumLines*QueriedFilePos / FileLen;
Chris Lattner1cf12bf2007-07-24 06:43:46 +0000543
544 // Check for -10 and +10 lines.
545 unsigned LowerBound = std::max(int(ApproxPos-10), 0);
546 unsigned UpperBound = std::min(ApproxPos+10, FileLen);
547
548 // If the computed lower bound is less than the query location, move it in.
549 if (SourceLineCache < SourceLineCacheStart+LowerBound &&
550 SourceLineCacheStart[LowerBound] < QueriedFilePos)
551 SourceLineCache = SourceLineCacheStart+LowerBound;
552
553 // If the computed upper bound is greater than the query location, move it.
554 if (SourceLineCacheEnd > SourceLineCacheStart+UpperBound &&
555 SourceLineCacheStart[UpperBound] >= QueriedFilePos)
556 SourceLineCacheEnd = SourceLineCacheStart+UpperBound;
557 }
558
559 unsigned *Pos
560 = std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000561 unsigned LineNo = Pos-SourceLineCacheStart;
562
Chris Lattner2b2453a2009-01-17 06:22:33 +0000563 LastLineNoFileIDQuery = LocInfo.first;
Ted Kremenek78d85f52007-10-30 21:08:08 +0000564 LastLineNoContentCache = Content;
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000565 LastLineNoFilePos = QueriedFilePos;
566 LastLineNoResult = LineNo;
567 return LineNo;
Reid Spencer5f016e22007-07-11 17:01:13 +0000568}
569
Chris Lattnerb9c3f962009-01-27 07:57:44 +0000570/// getPresumedLoc - This method returns the "presumed" location of a
571/// SourceLocation specifies. A "presumed location" can be modified by #line
572/// or GNU line marker directives. This provides a view on the data that a
573/// user should see in diagnostics, for example.
574///
575/// Note that a presumed location is always given as the instantiation point
576/// of an instantiation location, not at the spelling location.
577PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const {
578 if (Loc.isInvalid()) return PresumedLoc();
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000579
Chris Lattnerb9c3f962009-01-27 07:57:44 +0000580 // Presumed locations are always for instantiation points.
581 Loc = getInstantiationLoc(Loc);
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000582
Chris Lattnerb9c3f962009-01-27 07:57:44 +0000583 // FIXME: Could just decompose Loc once!
584
585 const SrcMgr::FileInfo &FI = getSLocEntry(getFileID(Loc)).getFile();
586 const SrcMgr::ContentCache *C = FI.getContentCache();
587
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000588 // To get the source name, first consult the FileEntry (if one exists) before
589 // the MemBuffer as this will avoid unnecessarily paging in the MemBuffer.
Chris Lattnerb9c3f962009-01-27 07:57:44 +0000590 const char *Filename =
591 C->Entry ? C->Entry->getName() : C->getBuffer()->getBufferIdentifier();
592
593 return PresumedLoc(Filename, getLineNumber(Loc), getColumnNumber(Loc),
594 FI.getIncludeLoc());
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000595}
596
597//===----------------------------------------------------------------------===//
598// Other miscellaneous methods.
599//===----------------------------------------------------------------------===//
600
601
Reid Spencer5f016e22007-07-11 17:01:13 +0000602/// PrintStats - Print statistics to stderr.
603///
604void SourceManager::PrintStats() const {
Ted Kremenek665dd4a2007-12-05 22:21:13 +0000605 llvm::cerr << "\n*** Source Manager Stats:\n";
606 llvm::cerr << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
Chris Lattner08c375c2009-01-27 05:22:43 +0000607 << " mem buffers mapped.\n";
608 llvm::cerr << SLocEntryTable.size() << " SLocEntry's allocated, "
609 << NextOffset << "B of Sloc address space used.\n";
Reid Spencer5f016e22007-07-11 17:01:13 +0000610
Reid Spencer5f016e22007-07-11 17:01:13 +0000611 unsigned NumLineNumsComputed = 0;
612 unsigned NumFileBytesMapped = 0;
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000613 for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){
614 NumLineNumsComputed += I->second->SourceLineCache != 0;
615 NumFileBytesMapped += I->second->getSizeBytesMapped();
Reid Spencer5f016e22007-07-11 17:01:13 +0000616 }
Ted Kremenek78d85f52007-10-30 21:08:08 +0000617
Ted Kremenek665dd4a2007-12-05 22:21:13 +0000618 llvm::cerr << NumFileBytesMapped << " bytes of files mapped, "
619 << NumLineNumsComputed << " files with line #'s computed.\n";
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000620 llvm::cerr << "FileID scans: " << NumLinearScans << " linear, "
621 << NumBinaryProbes << " binary.\n";
Reid Spencer5f016e22007-07-11 17:01:13 +0000622}
Ted Kremeneke21272f2007-12-04 19:39:02 +0000623
624//===----------------------------------------------------------------------===//
625// Serialization.
626//===----------------------------------------------------------------------===//
Ted Kremenek099b4742007-12-05 00:14:18 +0000627
628void ContentCache::Emit(llvm::Serializer& S) const {
Ted Kremeneke21272f2007-12-04 19:39:02 +0000629 S.FlushRecord();
630 S.EmitPtr(this);
Ted Kremeneke21272f2007-12-04 19:39:02 +0000631
Ted Kremenek82dfaf72007-12-18 22:12:19 +0000632 if (Entry) {
633 llvm::sys::Path Fname(Buffer->getBufferIdentifier());
634
635 if (Fname.isAbsolute())
636 S.EmitCStr(Fname.c_str());
637 else {
638 // Create an absolute path.
639 // FIXME: This will potentially contain ".." and "." in the path.
640 llvm::sys::Path path = llvm::sys::Path::GetCurrentDirectory();
641 path.appendComponent(Fname.c_str());
642 S.EmitCStr(path.c_str());
643 }
644 }
Ted Kremenek099b4742007-12-05 00:14:18 +0000645 else {
Ted Kremeneke21272f2007-12-04 19:39:02 +0000646 const char* p = Buffer->getBufferStart();
647 const char* e = Buffer->getBufferEnd();
648
Ted Kremenek099b4742007-12-05 00:14:18 +0000649 S.EmitInt(e-p);
650
Ted Kremeneke21272f2007-12-04 19:39:02 +0000651 for ( ; p != e; ++p)
Ted Kremenek099b4742007-12-05 00:14:18 +0000652 S.EmitInt(*p);
Ted Kremeneke21272f2007-12-04 19:39:02 +0000653 }
654
Ted Kremenek099b4742007-12-05 00:14:18 +0000655 S.FlushRecord();
Ted Kremeneke21272f2007-12-04 19:39:02 +0000656}
Ted Kremenek099b4742007-12-05 00:14:18 +0000657
658void ContentCache::ReadToSourceManager(llvm::Deserializer& D,
659 SourceManager& SMgr,
660 FileManager* FMgr,
661 std::vector<char>& Buf) {
662 if (FMgr) {
663 llvm::SerializedPtrID PtrID = D.ReadPtrID();
664 D.ReadCStr(Buf,false);
665
666 // Create/fetch the FileEntry.
667 const char* start = &Buf[0];
668 const FileEntry* E = FMgr->getFile(start,start+Buf.size());
669
Ted Kremenekdb9c2292007-12-13 18:12:10 +0000670 // FIXME: Ideally we want a lazy materialization of the ContentCache
671 // anyway, because we don't want to read in source files unless this
672 // is absolutely needed.
673 if (!E)
674 D.RegisterPtr(PtrID,NULL);
Nico Weber48002c82008-09-29 00:25:48 +0000675 else
Ted Kremenekdb9c2292007-12-13 18:12:10 +0000676 // Get the ContextCache object and register it with the deserializer.
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000677 D.RegisterPtr(PtrID, SMgr.getOrCreateContentCache(E));
678 return;
Ted Kremenek099b4742007-12-05 00:14:18 +0000679 }
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000680
681 // Register the ContextCache object with the deserializer.
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000682 /* FIXME:
683 ContentCache *Entry
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000684 SMgr.MemBufferInfos.push_back(ContentCache());
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000685 = const_cast<ContentCache&>(SMgr.MemBufferInfos.back());
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000686 D.RegisterPtr(&Entry);
687
688 // Create the buffer.
689 unsigned Size = D.ReadInt();
690 Entry.Buffer = MemoryBuffer::getNewUninitMemBuffer(Size);
691
692 // Read the contents of the buffer.
693 char* p = const_cast<char*>(Entry.Buffer->getBufferStart());
694 for (unsigned i = 0; i < Size ; ++i)
695 p[i] = D.ReadInt();
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000696 */
Ted Kremenek099b4742007-12-05 00:14:18 +0000697}
698
699void SourceManager::Emit(llvm::Serializer& S) const {
Ted Kremenek1f941002007-12-05 00:19:51 +0000700 S.EnterBlock();
701 S.EmitPtr(this);
Chris Lattner2b2453a2009-01-17 06:22:33 +0000702 S.EmitInt(MainFileID.getOpaqueValue());
Ted Kremenek1f941002007-12-05 00:19:51 +0000703
Ted Kremenek099b4742007-12-05 00:14:18 +0000704 // Emit: FileInfos. Just emit the file name.
705 S.EnterBlock();
706
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000707 // FIXME: Emit FileInfos.
708 //std::for_each(FileInfos.begin(), FileInfos.end(),
709 // S.MakeEmitter<ContentCache>());
Ted Kremenek099b4742007-12-05 00:14:18 +0000710
711 S.ExitBlock();
712
713 // Emit: MemBufferInfos
714 S.EnterBlock();
715
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000716 /* FIXME: EMIT.
Ted Kremenek099b4742007-12-05 00:14:18 +0000717 std::for_each(MemBufferInfos.begin(), MemBufferInfos.end(),
718 S.MakeEmitter<ContentCache>());
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000719 */
Ted Kremenek099b4742007-12-05 00:14:18 +0000720
721 S.ExitBlock();
722
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000723 // FIXME: Emit SLocEntryTable.
Ted Kremenek1f941002007-12-05 00:19:51 +0000724
725 S.ExitBlock();
Ted Kremenek099b4742007-12-05 00:14:18 +0000726}
727
Ted Kremenek1f941002007-12-05 00:19:51 +0000728SourceManager*
729SourceManager::CreateAndRegister(llvm::Deserializer& D, FileManager& FMgr){
730 SourceManager *M = new SourceManager();
731 D.RegisterPtr(M);
732
Ted Kremenek76edd0e2007-12-19 22:29:55 +0000733 // Read: the FileID of the main source file of the translation unit.
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000734 M->MainFileID = FileID::get(D.ReadInt());
Ted Kremenek76edd0e2007-12-19 22:29:55 +0000735
Ted Kremenek099b4742007-12-05 00:14:18 +0000736 std::vector<char> Buf;
737
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000738 /*{ // FIXME Read: FileInfos.
Ted Kremenek099b4742007-12-05 00:14:18 +0000739 llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();
740 while (!D.FinishedBlock(BLoc))
Ted Kremenek1f941002007-12-05 00:19:51 +0000741 ContentCache::ReadToSourceManager(D,*M,&FMgr,Buf);
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000742 }*/
Ted Kremenek099b4742007-12-05 00:14:18 +0000743
744 { // Read: MemBufferInfos.
745 llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();
746 while (!D.FinishedBlock(BLoc))
Ted Kremenek1f941002007-12-05 00:19:51 +0000747 ContentCache::ReadToSourceManager(D,*M,NULL,Buf);
Ted Kremenek099b4742007-12-05 00:14:18 +0000748 }
749
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000750 // FIXME: Read SLocEntryTable.
Ted Kremenek1f941002007-12-05 00:19:51 +0000751
752 return M;
Ted Kremenek1f2c7d12007-12-10 18:01:25 +0000753}