blob: 191b6155f0954e280ab39d148f36fc93fb548632 [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 Lattner987cd3d2009-01-26 07:37:49 +0000163 // Nope, create a new Cache entry.
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000164 Entry = ContentCacheAlloc.Allocate<ContentCache>();
165 new (Entry) ContentCache(FileEnt);
166 return Entry;
Reid Spencer5f016e22007-07-11 17:01:13 +0000167}
168
169
Ted Kremenekd1c0eee2007-10-31 17:53:38 +0000170/// createMemBufferContentCache - Create a new ContentCache for the specified
171/// memory buffer. This does no caching.
Ted Kremenek78d85f52007-10-30 21:08:08 +0000172const ContentCache*
173SourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) {
Ted Kremenek0d892d82007-10-30 22:57:35 +0000174 // Add a new ContentCache to the MemBufferInfos list and return it. We
175 // must default construct the object first that the instance actually
176 // stored within MemBufferInfos actually owns the Buffer, and not any
177 // temporary we would use in the call to "push_back".
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000178 ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>();
179 new (Entry) ContentCache();
180 MemBufferInfos.push_back(Entry);
181 Entry->setBuffer(Buffer);
182 return Entry;
Reid Spencer5f016e22007-07-11 17:01:13 +0000183}
184
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000185//===----------------------------------------------------------------------===//
186// Methods to create new FileID's and instantiations.
187//===----------------------------------------------------------------------===//
Reid Spencer5f016e22007-07-11 17:01:13 +0000188
Nico Weber48002c82008-09-29 00:25:48 +0000189/// createFileID - Create a new fileID for the specified ContentCache and
Ted Kremenek0d892d82007-10-30 22:57:35 +0000190/// include position. This works regardless of whether the ContentCache
191/// corresponds to a file or some other input source.
Chris Lattner2b2453a2009-01-17 06:22:33 +0000192FileID SourceManager::createFileID(const ContentCache *File,
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000193 SourceLocation IncludePos,
194 SrcMgr::CharacteristicKind FileCharacter) {
195 SLocEntryTable.push_back(SLocEntry::get(NextOffset,
196 FileInfo::get(IncludePos, File,
197 FileCharacter)));
Ted Kremenekc16c2082009-01-06 01:55:26 +0000198 unsigned FileSize = File->getSize();
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000199 assert(NextOffset+FileSize+1 > NextOffset && "Ran out of source locations!");
200 NextOffset += FileSize+1;
Reid Spencer5f016e22007-07-11 17:01:13 +0000201
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000202 // Set LastFileIDLookup to the newly created file. The next getFileID call is
203 // almost guaranteed to be from that file.
204 return LastFileIDLookup = FileID::get(SLocEntryTable.size()-1);
Reid Spencer5f016e22007-07-11 17:01:13 +0000205}
206
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000207/// createInstantiationLoc - Return a new SourceLocation that encodes the fact
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000208/// that a token from SpellingLoc should actually be referenced from
Reid Spencer5f016e22007-07-11 17:01:13 +0000209/// InstantiationLoc.
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000210SourceLocation SourceManager::createInstantiationLoc(SourceLocation SpellingLoc,
211 SourceLocation InstantLoc,
212 unsigned TokLength) {
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000213 SLocEntryTable.push_back(SLocEntry::get(NextOffset,
214 InstantiationInfo::get(InstantLoc,
215 SpellingLoc)));
216 assert(NextOffset+TokLength+1 > NextOffset && "Ran out of source locations!");
217 NextOffset += TokLength+1;
218 return SourceLocation::getMacroLoc(NextOffset-(TokLength+1));
Reid Spencer5f016e22007-07-11 17:01:13 +0000219}
220
Chris Lattner31530ba2009-01-19 07:32:13 +0000221/// getBufferData - Return a pointer to the start and end of the source buffer
222/// data for the specified FileID.
Chris Lattner2b2453a2009-01-17 06:22:33 +0000223std::pair<const char*, const char*>
224SourceManager::getBufferData(FileID FID) const {
225 const llvm::MemoryBuffer *Buf = getBuffer(FID);
226 return std::make_pair(Buf->getBufferStart(), Buf->getBufferEnd());
227}
228
229
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000230//===--------------------------------------------------------------------===//
231// SourceLocation manipulation methods.
232//===--------------------------------------------------------------------===//
233
234/// getFileIDSlow - Return the FileID for a SourceLocation. This is a very hot
235/// method that is used for all SourceManager queries that start with a
236/// SourceLocation object. It is responsible for finding the entry in
237/// SLocEntryTable which contains the specified location.
238///
239FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
240 assert(SLocOffset && "Invalid FileID");
241
242 // After the first and second level caches, I see two common sorts of
243 // behavior: 1) a lot of searched FileID's are "near" the cached file location
244 // or are "near" the cached instantiation location. 2) others are just
245 // completely random and may be a very long way away.
246 //
247 // To handle this, we do a linear search for up to 8 steps to catch #1 quickly
248 // then we fall back to a less cache efficient, but more scalable, binary
249 // search to find the location.
250
251 // See if this is near the file point - worst case we start scanning from the
252 // most newly created FileID.
253 std::vector<SrcMgr::SLocEntry>::const_iterator I;
254
255 if (SLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) {
256 // Neither loc prunes our search.
257 I = SLocEntryTable.end();
258 } else {
259 // Perhaps it is near the file point.
260 I = SLocEntryTable.begin()+LastFileIDLookup.ID;
261 }
262
263 // Find the FileID that contains this. "I" is an iterator that points to a
264 // FileID whose offset is known to be larger than SLocOffset.
265 unsigned NumProbes = 0;
266 while (1) {
267 --I;
268 if (I->getOffset() <= SLocOffset) {
269#if 0
270 printf("lin %d -> %d [%s] %d %d\n", SLocOffset,
271 I-SLocEntryTable.begin(),
272 I->isInstantiation() ? "inst" : "file",
273 LastFileIDLookup.ID, int(SLocEntryTable.end()-I));
274#endif
275 FileID Res = FileID::get(I-SLocEntryTable.begin());
276
277 // If this isn't an instantiation, remember it. We have good locality
278 // across FileID lookups.
279 if (!I->isInstantiation())
280 LastFileIDLookup = Res;
281 NumLinearScans += NumProbes+1;
282 return Res;
283 }
284 if (++NumProbes == 8)
285 break;
286 }
287
288 // Convert "I" back into an index. We know that it is an entry whose index is
289 // larger than the offset we are looking for.
290 unsigned GreaterIndex = I-SLocEntryTable.begin();
291 // LessIndex - This is the lower bound of the range that we're searching.
292 // We know that the offset corresponding to the FileID is is less than
293 // SLocOffset.
294 unsigned LessIndex = 0;
295 NumProbes = 0;
296 while (1) {
297 unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
298 unsigned MidOffset = SLocEntryTable[MiddleIndex].getOffset();
299
300 ++NumProbes;
301
302 // If the offset of the midpoint is too large, chop the high side of the
303 // range to the midpoint.
304 if (MidOffset > SLocOffset) {
305 GreaterIndex = MiddleIndex;
306 continue;
307 }
308
309 // If the middle index contains the value, succeed and return.
310 if (isOffsetInFileID(FileID::get(MiddleIndex), SLocOffset)) {
311#if 0
312 printf("bin %d -> %d [%s] %d %d\n", SLocOffset,
313 I-SLocEntryTable.begin(),
314 I->isInstantiation() ? "inst" : "file",
315 LastFileIDLookup.ID, int(SLocEntryTable.end()-I));
316#endif
317 FileID Res = FileID::get(MiddleIndex);
318
319 // If this isn't an instantiation, remember it. We have good locality
320 // across FileID lookups.
321 if (!I->isInstantiation())
322 LastFileIDLookup = Res;
323 NumBinaryProbes += NumProbes;
324 return Res;
325 }
326
327 // Otherwise, move the low-side up to the middle index.
328 LessIndex = MiddleIndex;
329 }
330}
331
Chris Lattneraddb7972009-01-26 20:04:19 +0000332SourceLocation SourceManager::
333getInstantiationLocSlowCase(SourceLocation Loc) const {
334 do {
335 std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
336 Loc =getSLocEntry(LocInfo.first).getInstantiation().getInstantiationLoc();
337 Loc = Loc.getFileLocWithOffset(LocInfo.second);
338 } while (!Loc.isFileID());
339
340 return Loc;
341}
342
343SourceLocation SourceManager::getSpellingLocSlowCase(SourceLocation Loc) const {
344 do {
345 std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
346 Loc = getSLocEntry(LocInfo.first).getInstantiation().getSpellingLoc();
347 Loc = Loc.getFileLocWithOffset(LocInfo.second);
348 } while (!Loc.isFileID());
349 return Loc;
350}
351
352
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000353std::pair<FileID, unsigned>
354SourceManager::getDecomposedInstantiationLocSlowCase(const SrcMgr::SLocEntry *E,
355 unsigned Offset) const {
356 // If this is an instantiation record, walk through all the instantiation
357 // points.
358 FileID FID;
359 SourceLocation Loc;
360 do {
361 Loc = E->getInstantiation().getInstantiationLoc();
362
363 FID = getFileID(Loc);
364 E = &getSLocEntry(FID);
365 Offset += Loc.getOffset()-E->getOffset();
Chris Lattnerbcd1a1b2009-01-26 19:41:58 +0000366 } while (!Loc.isFileID());
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000367
368 return std::make_pair(FID, Offset);
369}
370
371std::pair<FileID, unsigned>
372SourceManager::getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,
373 unsigned Offset) const {
Chris Lattnerbcd1a1b2009-01-26 19:41:58 +0000374 // If this is an instantiation record, walk through all the instantiation
375 // points.
376 FileID FID;
377 SourceLocation Loc;
378 do {
379 Loc = E->getInstantiation().getSpellingLoc();
380
381 FID = getFileID(Loc);
382 E = &getSLocEntry(FID);
383 Offset += Loc.getOffset()-E->getOffset();
384 } while (!Loc.isFileID());
385
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000386 return std::make_pair(FID, Offset);
387}
388
389
390//===----------------------------------------------------------------------===//
391// Queries about the code at a SourceLocation.
392//===----------------------------------------------------------------------===//
Reid Spencer5f016e22007-07-11 17:01:13 +0000393
394/// getCharacterData - Return a pointer to the start of the specified location
395/// in the appropriate MemoryBuffer.
396const char *SourceManager::getCharacterData(SourceLocation SL) const {
397 // Note that this is a hot function in the getSpelling() path, which is
398 // heavily used by -E mode.
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000399 std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(SL);
Chris Lattner2b2453a2009-01-17 06:22:33 +0000400
Ted Kremenekc16c2082009-01-06 01:55:26 +0000401 // Note that calling 'getBuffer()' may lazily page in a source file.
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000402 return getSLocEntry(LocInfo.first).getFile().getContentCache()
403 ->getBuffer()->getBufferStart() + LocInfo.second;
Reid Spencer5f016e22007-07-11 17:01:13 +0000404}
405
Reid Spencer5f016e22007-07-11 17:01:13 +0000406
Chris Lattner9dc1f532007-07-20 16:37:10 +0000407/// getColumnNumber - Return the column # for the specified file position.
Reid Spencer5f016e22007-07-11 17:01:13 +0000408/// this is significantly cheaper to compute than the line number. This returns
409/// zero if the column number isn't known.
410unsigned SourceManager::getColumnNumber(SourceLocation Loc) const {
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000411 if (Loc.isInvalid()) return 0;
412 assert(Loc.isFileID() && "Don't know what part of instantiation loc to get");
Reid Spencer5f016e22007-07-11 17:01:13 +0000413
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000414 std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
Chris Lattner2b2453a2009-01-17 06:22:33 +0000415 unsigned FilePos = LocInfo.second;
416
417 const char *Buf = getBuffer(LocInfo.first)->getBufferStart();
Reid Spencer5f016e22007-07-11 17:01:13 +0000418
419 unsigned LineStart = FilePos;
420 while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
421 --LineStart;
422 return FilePos-LineStart+1;
423}
424
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000425static void ComputeLineNumbers(ContentCache* FI,
426 llvm::BumpPtrAllocator &Alloc) DISABLE_INLINE;
427static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){
Ted Kremenekc16c2082009-01-06 01:55:26 +0000428 // Note that calling 'getBuffer()' may lazily page in the file.
429 const MemoryBuffer *Buffer = FI->getBuffer();
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000430
431 // Find the file offsets of all of the *physical* source lines. This does
432 // not look at trigraphs, escaped newlines, or anything else tricky.
433 std::vector<unsigned> LineOffsets;
434
435 // Line #1 starts at char 0.
436 LineOffsets.push_back(0);
437
438 const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart();
439 const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd();
440 unsigned Offs = 0;
441 while (1) {
442 // Skip over the contents of the line.
443 // TODO: Vectorize this? This is very performance sensitive for programs
444 // with lots of diagnostics and in -E mode.
445 const unsigned char *NextBuf = (const unsigned char *)Buf;
446 while (*NextBuf != '\n' && *NextBuf != '\r' && *NextBuf != '\0')
447 ++NextBuf;
448 Offs += NextBuf-Buf;
449 Buf = NextBuf;
450
451 if (Buf[0] == '\n' || Buf[0] == '\r') {
452 // If this is \n\r or \r\n, skip both characters.
453 if ((Buf[1] == '\n' || Buf[1] == '\r') && Buf[0] != Buf[1])
454 ++Offs, ++Buf;
455 ++Offs, ++Buf;
456 LineOffsets.push_back(Offs);
457 } else {
458 // Otherwise, this is a null. If end of file, exit.
459 if (Buf == End) break;
460 // Otherwise, skip the null.
461 ++Offs, ++Buf;
462 }
463 }
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000464
465 // Copy the offsets into the FileInfo structure.
466 FI->NumLines = LineOffsets.size();
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000467 FI->SourceLineCache = Alloc.Allocate<unsigned>(LineOffsets.size());
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000468 std::copy(LineOffsets.begin(), LineOffsets.end(), FI->SourceLineCache);
469}
Reid Spencer5f016e22007-07-11 17:01:13 +0000470
Chris Lattnerdf7c17a2009-01-16 07:00:02 +0000471/// getLineNumber - Given a SourceLocation, return the spelling line number
Reid Spencer5f016e22007-07-11 17:01:13 +0000472/// for the position indicated. This requires building and caching a table of
473/// line offsets for the MemoryBuffer, so this is not cheap: use only when
474/// about to emit a diagnostic.
Chris Lattnerf812a452008-11-18 06:51:15 +0000475unsigned SourceManager::getLineNumber(SourceLocation Loc) const {
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000476 if (Loc.isInvalid()) return 0;
477 assert(Loc.isFileID() && "Don't know what part of instantiation loc to get");
Ted Kremenek78d85f52007-10-30 21:08:08 +0000478
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000479 std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
480
Chris Lattner2b2453a2009-01-17 06:22:33 +0000481 ContentCache *Content;
Chris Lattner2b2453a2009-01-17 06:22:33 +0000482 if (LastLineNoFileIDQuery == LocInfo.first)
Ted Kremenek78d85f52007-10-30 21:08:08 +0000483 Content = LastLineNoContentCache;
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000484 else
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000485 Content = const_cast<ContentCache*>(getSLocEntry(LocInfo.first)
486 .getFile().getContentCache());
Reid Spencer5f016e22007-07-11 17:01:13 +0000487
488 // If this is the first use of line information for this buffer, compute the
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000489 /// SourceLineCache for it on demand.
Ted Kremenek78d85f52007-10-30 21:08:08 +0000490 if (Content->SourceLineCache == 0)
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000491 ComputeLineNumbers(Content, ContentCacheAlloc);
Reid Spencer5f016e22007-07-11 17:01:13 +0000492
493 // Okay, we know we have a line number table. Do a binary search to find the
494 // line number that this character position lands on.
Ted Kremenek78d85f52007-10-30 21:08:08 +0000495 unsigned *SourceLineCache = Content->SourceLineCache;
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000496 unsigned *SourceLineCacheStart = SourceLineCache;
Ted Kremenek78d85f52007-10-30 21:08:08 +0000497 unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines;
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000498
Chris Lattner2b2453a2009-01-17 06:22:33 +0000499 unsigned QueriedFilePos = LocInfo.second+1;
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000500
501 // If the previous query was to the same file, we know both the file pos from
502 // that query and the line number returned. This allows us to narrow the
503 // search space from the entire file to something near the match.
Chris Lattner2b2453a2009-01-17 06:22:33 +0000504 if (LastLineNoFileIDQuery == LocInfo.first) {
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000505 if (QueriedFilePos >= LastLineNoFilePos) {
506 SourceLineCache = SourceLineCache+LastLineNoResult-1;
507
508 // The query is likely to be nearby the previous one. Here we check to
509 // see if it is within 5, 10 or 20 lines. It can be far away in cases
510 // where big comment blocks and vertical whitespace eat up lines but
511 // contribute no tokens.
512 if (SourceLineCache+5 < SourceLineCacheEnd) {
513 if (SourceLineCache[5] > QueriedFilePos)
514 SourceLineCacheEnd = SourceLineCache+5;
515 else if (SourceLineCache+10 < SourceLineCacheEnd) {
516 if (SourceLineCache[10] > QueriedFilePos)
517 SourceLineCacheEnd = SourceLineCache+10;
518 else if (SourceLineCache+20 < SourceLineCacheEnd) {
519 if (SourceLineCache[20] > QueriedFilePos)
520 SourceLineCacheEnd = SourceLineCache+20;
521 }
522 }
523 }
524 } else {
525 SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
526 }
527 }
528
Chris Lattner1cf12bf2007-07-24 06:43:46 +0000529 // If the spread is large, do a "radix" test as our initial guess, based on
530 // the assumption that lines average to approximately the same length.
531 // NOTE: This is currently disabled, as it does not appear to be profitable in
532 // initial measurements.
533 if (0 && SourceLineCacheEnd-SourceLineCache > 20) {
Ted Kremenek78d85f52007-10-30 21:08:08 +0000534 unsigned FileLen = Content->SourceLineCache[Content->NumLines-1];
Chris Lattner1cf12bf2007-07-24 06:43:46 +0000535
536 // Take a stab at guessing where it is.
Ted Kremenek78d85f52007-10-30 21:08:08 +0000537 unsigned ApproxPos = Content->NumLines*QueriedFilePos / FileLen;
Chris Lattner1cf12bf2007-07-24 06:43:46 +0000538
539 // Check for -10 and +10 lines.
540 unsigned LowerBound = std::max(int(ApproxPos-10), 0);
541 unsigned UpperBound = std::min(ApproxPos+10, FileLen);
542
543 // If the computed lower bound is less than the query location, move it in.
544 if (SourceLineCache < SourceLineCacheStart+LowerBound &&
545 SourceLineCacheStart[LowerBound] < QueriedFilePos)
546 SourceLineCache = SourceLineCacheStart+LowerBound;
547
548 // If the computed upper bound is greater than the query location, move it.
549 if (SourceLineCacheEnd > SourceLineCacheStart+UpperBound &&
550 SourceLineCacheStart[UpperBound] >= QueriedFilePos)
551 SourceLineCacheEnd = SourceLineCacheStart+UpperBound;
552 }
553
554 unsigned *Pos
555 = std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000556 unsigned LineNo = Pos-SourceLineCacheStart;
557
Chris Lattner2b2453a2009-01-17 06:22:33 +0000558 LastLineNoFileIDQuery = LocInfo.first;
Ted Kremenek78d85f52007-10-30 21:08:08 +0000559 LastLineNoContentCache = Content;
Chris Lattner5e36a7a2007-07-24 05:57:19 +0000560 LastLineNoFilePos = QueriedFilePos;
561 LastLineNoResult = LineNo;
562 return LineNo;
Reid Spencer5f016e22007-07-11 17:01:13 +0000563}
564
Chris Lattnerb9c3f962009-01-27 07:57:44 +0000565/// getPresumedLoc - This method returns the "presumed" location of a
566/// SourceLocation specifies. A "presumed location" can be modified by #line
567/// or GNU line marker directives. This provides a view on the data that a
568/// user should see in diagnostics, for example.
569///
570/// Note that a presumed location is always given as the instantiation point
571/// of an instantiation location, not at the spelling location.
572PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const {
573 if (Loc.isInvalid()) return PresumedLoc();
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000574
Chris Lattnerb9c3f962009-01-27 07:57:44 +0000575 // Presumed locations are always for instantiation points.
576 Loc = getInstantiationLoc(Loc);
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000577
Chris Lattnerb9c3f962009-01-27 07:57:44 +0000578 // FIXME: Could just decompose Loc once!
579
580 const SrcMgr::FileInfo &FI = getSLocEntry(getFileID(Loc)).getFile();
581 const SrcMgr::ContentCache *C = FI.getContentCache();
582
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000583 // To get the source name, first consult the FileEntry (if one exists) before
584 // the MemBuffer as this will avoid unnecessarily paging in the MemBuffer.
Chris Lattnerb9c3f962009-01-27 07:57:44 +0000585 const char *Filename =
586 C->Entry ? C->Entry->getName() : C->getBuffer()->getBufferIdentifier();
587
588 return PresumedLoc(Filename, getLineNumber(Loc), getColumnNumber(Loc),
589 FI.getIncludeLoc());
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000590}
591
592//===----------------------------------------------------------------------===//
593// Other miscellaneous methods.
594//===----------------------------------------------------------------------===//
595
596
Reid Spencer5f016e22007-07-11 17:01:13 +0000597/// PrintStats - Print statistics to stderr.
598///
599void SourceManager::PrintStats() const {
Ted Kremenek665dd4a2007-12-05 22:21:13 +0000600 llvm::cerr << "\n*** Source Manager Stats:\n";
601 llvm::cerr << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
Chris Lattner08c375c2009-01-27 05:22:43 +0000602 << " mem buffers mapped.\n";
603 llvm::cerr << SLocEntryTable.size() << " SLocEntry's allocated, "
604 << NextOffset << "B of Sloc address space used.\n";
Reid Spencer5f016e22007-07-11 17:01:13 +0000605
Reid Spencer5f016e22007-07-11 17:01:13 +0000606 unsigned NumLineNumsComputed = 0;
607 unsigned NumFileBytesMapped = 0;
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000608 for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){
609 NumLineNumsComputed += I->second->SourceLineCache != 0;
610 NumFileBytesMapped += I->second->getSizeBytesMapped();
Reid Spencer5f016e22007-07-11 17:01:13 +0000611 }
Ted Kremenek78d85f52007-10-30 21:08:08 +0000612
Ted Kremenek665dd4a2007-12-05 22:21:13 +0000613 llvm::cerr << NumFileBytesMapped << " bytes of files mapped, "
614 << NumLineNumsComputed << " files with line #'s computed.\n";
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000615 llvm::cerr << "FileID scans: " << NumLinearScans << " linear, "
616 << NumBinaryProbes << " binary.\n";
Reid Spencer5f016e22007-07-11 17:01:13 +0000617}
Ted Kremeneke21272f2007-12-04 19:39:02 +0000618
619//===----------------------------------------------------------------------===//
620// Serialization.
621//===----------------------------------------------------------------------===//
Ted Kremenek099b4742007-12-05 00:14:18 +0000622
623void ContentCache::Emit(llvm::Serializer& S) const {
Ted Kremeneke21272f2007-12-04 19:39:02 +0000624 S.FlushRecord();
625 S.EmitPtr(this);
Ted Kremeneke21272f2007-12-04 19:39:02 +0000626
Ted Kremenek82dfaf72007-12-18 22:12:19 +0000627 if (Entry) {
628 llvm::sys::Path Fname(Buffer->getBufferIdentifier());
629
630 if (Fname.isAbsolute())
631 S.EmitCStr(Fname.c_str());
632 else {
633 // Create an absolute path.
634 // FIXME: This will potentially contain ".." and "." in the path.
635 llvm::sys::Path path = llvm::sys::Path::GetCurrentDirectory();
636 path.appendComponent(Fname.c_str());
637 S.EmitCStr(path.c_str());
638 }
639 }
Ted Kremenek099b4742007-12-05 00:14:18 +0000640 else {
Ted Kremeneke21272f2007-12-04 19:39:02 +0000641 const char* p = Buffer->getBufferStart();
642 const char* e = Buffer->getBufferEnd();
643
Ted Kremenek099b4742007-12-05 00:14:18 +0000644 S.EmitInt(e-p);
645
Ted Kremeneke21272f2007-12-04 19:39:02 +0000646 for ( ; p != e; ++p)
Ted Kremenek099b4742007-12-05 00:14:18 +0000647 S.EmitInt(*p);
Ted Kremeneke21272f2007-12-04 19:39:02 +0000648 }
649
Ted Kremenek099b4742007-12-05 00:14:18 +0000650 S.FlushRecord();
Ted Kremeneke21272f2007-12-04 19:39:02 +0000651}
Ted Kremenek099b4742007-12-05 00:14:18 +0000652
653void ContentCache::ReadToSourceManager(llvm::Deserializer& D,
654 SourceManager& SMgr,
655 FileManager* FMgr,
656 std::vector<char>& Buf) {
657 if (FMgr) {
658 llvm::SerializedPtrID PtrID = D.ReadPtrID();
659 D.ReadCStr(Buf,false);
660
661 // Create/fetch the FileEntry.
662 const char* start = &Buf[0];
663 const FileEntry* E = FMgr->getFile(start,start+Buf.size());
664
Ted Kremenekdb9c2292007-12-13 18:12:10 +0000665 // FIXME: Ideally we want a lazy materialization of the ContentCache
666 // anyway, because we don't want to read in source files unless this
667 // is absolutely needed.
668 if (!E)
669 D.RegisterPtr(PtrID,NULL);
Nico Weber48002c82008-09-29 00:25:48 +0000670 else
Ted Kremenekdb9c2292007-12-13 18:12:10 +0000671 // Get the ContextCache object and register it with the deserializer.
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000672 D.RegisterPtr(PtrID, SMgr.getOrCreateContentCache(E));
673 return;
Ted Kremenek099b4742007-12-05 00:14:18 +0000674 }
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000675
676 // Register the ContextCache object with the deserializer.
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000677 /* FIXME:
678 ContentCache *Entry
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000679 SMgr.MemBufferInfos.push_back(ContentCache());
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000680 = const_cast<ContentCache&>(SMgr.MemBufferInfos.back());
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000681 D.RegisterPtr(&Entry);
682
683 // Create the buffer.
684 unsigned Size = D.ReadInt();
685 Entry.Buffer = MemoryBuffer::getNewUninitMemBuffer(Size);
686
687 // Read the contents of the buffer.
688 char* p = const_cast<char*>(Entry.Buffer->getBufferStart());
689 for (unsigned i = 0; i < Size ; ++i)
690 p[i] = D.ReadInt();
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000691 */
Ted Kremenek099b4742007-12-05 00:14:18 +0000692}
693
694void SourceManager::Emit(llvm::Serializer& S) const {
Ted Kremenek1f941002007-12-05 00:19:51 +0000695 S.EnterBlock();
696 S.EmitPtr(this);
Chris Lattner2b2453a2009-01-17 06:22:33 +0000697 S.EmitInt(MainFileID.getOpaqueValue());
Ted Kremenek1f941002007-12-05 00:19:51 +0000698
Ted Kremenek099b4742007-12-05 00:14:18 +0000699 // Emit: FileInfos. Just emit the file name.
700 S.EnterBlock();
701
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000702 // FIXME: Emit FileInfos.
703 //std::for_each(FileInfos.begin(), FileInfos.end(),
704 // S.MakeEmitter<ContentCache>());
Ted Kremenek099b4742007-12-05 00:14:18 +0000705
706 S.ExitBlock();
707
708 // Emit: MemBufferInfos
709 S.EnterBlock();
710
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000711 /* FIXME: EMIT.
Ted Kremenek099b4742007-12-05 00:14:18 +0000712 std::for_each(MemBufferInfos.begin(), MemBufferInfos.end(),
713 S.MakeEmitter<ContentCache>());
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000714 */
Ted Kremenek099b4742007-12-05 00:14:18 +0000715
716 S.ExitBlock();
717
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000718 // FIXME: Emit SLocEntryTable.
Ted Kremenek1f941002007-12-05 00:19:51 +0000719
720 S.ExitBlock();
Ted Kremenek099b4742007-12-05 00:14:18 +0000721}
722
Ted Kremenek1f941002007-12-05 00:19:51 +0000723SourceManager*
724SourceManager::CreateAndRegister(llvm::Deserializer& D, FileManager& FMgr){
725 SourceManager *M = new SourceManager();
726 D.RegisterPtr(M);
727
Ted Kremenek76edd0e2007-12-19 22:29:55 +0000728 // Read: the FileID of the main source file of the translation unit.
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000729 M->MainFileID = FileID::get(D.ReadInt());
Ted Kremenek76edd0e2007-12-19 22:29:55 +0000730
Ted Kremenek099b4742007-12-05 00:14:18 +0000731 std::vector<char> Buf;
732
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000733 /*{ // FIXME Read: FileInfos.
Ted Kremenek099b4742007-12-05 00:14:18 +0000734 llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();
735 while (!D.FinishedBlock(BLoc))
Ted Kremenek1f941002007-12-05 00:19:51 +0000736 ContentCache::ReadToSourceManager(D,*M,&FMgr,Buf);
Chris Lattner0d0bf8c2009-02-03 07:30:45 +0000737 }*/
Ted Kremenek099b4742007-12-05 00:14:18 +0000738
739 { // Read: MemBufferInfos.
740 llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();
741 while (!D.FinishedBlock(BLoc))
Ted Kremenek1f941002007-12-05 00:19:51 +0000742 ContentCache::ReadToSourceManager(D,*M,NULL,Buf);
Ted Kremenek099b4742007-12-05 00:14:18 +0000743 }
744
Chris Lattnerde7aeef2009-01-26 00:43:02 +0000745 // FIXME: Read SLocEntryTable.
Ted Kremenek1f941002007-12-05 00:19:51 +0000746
747 return M;
Ted Kremenek1f2c7d12007-12-10 18:01:25 +0000748}