SourceManager.cpp revision 30fc933e5fbbb5f0ea60c47976d435254e378536
1//===--- SourceManager.cpp - Track and cache source files -----------------===//
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 file implements the SourceManager interface.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Basic/SourceManager.h"
15#include "clang/Basic/FileManager.h"
16#include "llvm/Support/Compiler.h"
17#include "llvm/Support/MemoryBuffer.h"
18#include "llvm/System/Path.h"
19#include "llvm/Bitcode/Serialize.h"
20#include "llvm/Bitcode/Deserialize.h"
21#include "llvm/Support/Streams.h"
22#include <algorithm>
23using namespace clang;
24using namespace SrcMgr;
25using llvm::MemoryBuffer;
26
27//===----------------------------------------------------------------------===//
28// SourceManager Helper Classes
29//===----------------------------------------------------------------------===//
30
31ContentCache::~ContentCache() {
32  delete Buffer;
33}
34
35/// 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
50const llvm::MemoryBuffer *ContentCache::getBuffer() const {
51  // 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?
55    Buffer = MemoryBuffer::getFile(Entry->getName(), 0, Entry->getSize());
56  }
57  return Buffer;
58}
59
60//===----------------------------------------------------------------------===//
61// Line Table Implementation
62//===----------------------------------------------------------------------===//
63
64namespace clang {
65struct LineEntry {
66  /// FileOffset - The offset in this file that the line entry occurs at.
67  unsigned FileOffset;
68  /// LineNo - The presumed line number of this line entry: #line 4.
69  unsigned LineNo;
70  /// FilenameID - The ID of the filename identified by this line entry:
71  /// #line 4 "foo.c".  This is -1 if not specified.
72  int FilenameID;
73
74  static LineEntry get(unsigned Offs, unsigned Line, int Filename) {
75    LineEntry E;
76    E.FileOffset = Offs;
77    E.LineNo = Line;
78    E.FilenameID = Filename;
79    return E;
80  }
81};
82
83
84/// LineTableInfo - This class is used to hold and unique data used to
85/// represent #line information.
86class LineTableInfo {
87  /// FilenameIDs - This map is used to assign unique IDs to filenames in
88  /// #line directives.  This allows us to unique the filenames that
89  /// frequently reoccur and reference them with indices.  FilenameIDs holds
90  /// the mapping from string -> ID, and FilenamesByID holds the mapping of ID
91  /// to string.
92  llvm::StringMap<unsigned, llvm::BumpPtrAllocator> FilenameIDs;
93  std::vector<llvm::StringMapEntry<unsigned>*> FilenamesByID;
94
95  /// LineEntries - This is a map from FileIDs to a list of line entries (sorted
96  /// by the offset they occur in the file.
97  std::map<unsigned, std::vector<LineEntry> > LineEntries;
98public:
99  LineTableInfo() {
100  }
101
102  void clear() {
103    FilenameIDs.clear();
104    FilenamesByID.clear();
105  }
106
107  ~LineTableInfo() {}
108
109  unsigned getLineTableFilenameID(const char *Ptr, unsigned Len);
110  void AddLineNote(unsigned FID, unsigned Offset,
111                   unsigned LineNo, int FilenameID);
112};
113} // namespace clang
114
115unsigned LineTableInfo::getLineTableFilenameID(const char *Ptr, unsigned Len) {
116  // Look up the filename in the string table, returning the pre-existing value
117  // if it exists.
118  llvm::StringMapEntry<unsigned> &Entry =
119    FilenameIDs.GetOrCreateValue(Ptr, Ptr+Len, ~0U);
120  if (Entry.getValue() != ~0U)
121    return Entry.getValue();
122
123  // Otherwise, assign this the next available ID.
124  Entry.setValue(FilenamesByID.size());
125  FilenamesByID.push_back(&Entry);
126  return FilenamesByID.size()-1;
127}
128
129/// AddLineNote - Add a line note to the line table that indicates that there
130/// is a #line at the specified FID/Offset location which changes the presumed
131/// location to LineNo/FilenameID.
132void LineTableInfo::AddLineNote(unsigned FID, unsigned Offset,
133                                unsigned LineNo, int FilenameID) {
134  std::vector<LineEntry> &Entries = LineEntries[FID];
135
136  assert((Entries.empty() || Entries.back().FileOffset < Offset) &&
137         "Adding line entries out of order!");
138  Entries.push_back(LineEntry::get(Offset, LineNo, FilenameID));
139}
140
141
142
143/// getLineTableFilenameID - Return the uniqued ID for the specified filename.
144///
145unsigned SourceManager::getLineTableFilenameID(const char *Ptr, unsigned Len) {
146  if (LineTable == 0)
147    LineTable = new LineTableInfo();
148  return LineTable->getLineTableFilenameID(Ptr, Len);
149}
150
151
152/// AddLineNote - Add a line note to the line table for the FileID and offset
153/// specified by Loc.  If FilenameID is -1, it is considered to be
154/// unspecified.
155void SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
156                                int FilenameID) {
157  std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
158
159  const SrcMgr::FileInfo &FileInfo = getSLocEntry(LocInfo.first).getFile();
160
161  // Remember that this file has #line directives now if it doesn't already.
162  const_cast<SrcMgr::FileInfo&>(FileInfo).setHasLineDirectives();
163
164  if (LineTable == 0)
165    LineTable = new LineTableInfo();
166  LineTable->AddLineNote(LocInfo.first.ID, LocInfo.second, LineNo, FilenameID);
167}
168
169
170//===----------------------------------------------------------------------===//
171// Private 'Create' methods.
172//===----------------------------------------------------------------------===//
173
174SourceManager::~SourceManager() {
175  delete LineTable;
176
177  // Delete FileEntry objects corresponding to content caches.  Since the actual
178  // content cache objects are bump pointer allocated, we just have to run the
179  // dtors, but we call the deallocate method for completeness.
180  for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) {
181    MemBufferInfos[i]->~ContentCache();
182    ContentCacheAlloc.Deallocate(MemBufferInfos[i]);
183  }
184  for (llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::iterator
185       I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {
186    I->second->~ContentCache();
187    ContentCacheAlloc.Deallocate(I->second);
188  }
189}
190
191void SourceManager::clearIDTables() {
192  MainFileID = FileID();
193  SLocEntryTable.clear();
194  LastLineNoFileIDQuery = FileID();
195  LastLineNoContentCache = 0;
196  LastFileIDLookup = FileID();
197
198  if (LineTable)
199    LineTable->clear();
200
201  // Use up FileID #0 as an invalid instantiation.
202  NextOffset = 0;
203  createInstantiationLoc(SourceLocation(), SourceLocation(), 1);
204}
205
206/// getOrCreateContentCache - Create or return a cached ContentCache for the
207/// specified file.
208const ContentCache *
209SourceManager::getOrCreateContentCache(const FileEntry *FileEnt) {
210  assert(FileEnt && "Didn't specify a file entry to use?");
211
212  // Do we already have information about this file?
213  ContentCache *&Entry = FileInfos[FileEnt];
214  if (Entry) return Entry;
215
216  // Nope, create a new Cache entry.  Make sure it is at least 8-byte aligned
217  // so that FileInfo can use the low 3 bits of the pointer for its own
218  // nefarious purposes.
219  unsigned EntryAlign = llvm::AlignOf<ContentCache>::Alignment;
220  EntryAlign = std::max(8U, EntryAlign);
221  Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign);
222  new (Entry) ContentCache(FileEnt);
223  return Entry;
224}
225
226
227/// createMemBufferContentCache - Create a new ContentCache for the specified
228///  memory buffer.  This does no caching.
229const ContentCache*
230SourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) {
231  // Add a new ContentCache to the MemBufferInfos list and return it.  Make sure
232  // it is at least 8-byte aligned so that FileInfo can use the low 3 bits of
233  // the pointer for its own nefarious purposes.
234  unsigned EntryAlign = llvm::AlignOf<ContentCache>::Alignment;
235  EntryAlign = std::max(8U, EntryAlign);
236  ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign);
237  new (Entry) ContentCache();
238  MemBufferInfos.push_back(Entry);
239  Entry->setBuffer(Buffer);
240  return Entry;
241}
242
243//===----------------------------------------------------------------------===//
244// Methods to create new FileID's and instantiations.
245//===----------------------------------------------------------------------===//
246
247/// createFileID - Create a new fileID for the specified ContentCache and
248/// include position.  This works regardless of whether the ContentCache
249/// corresponds to a file or some other input source.
250FileID SourceManager::createFileID(const ContentCache *File,
251                                   SourceLocation IncludePos,
252                                   SrcMgr::CharacteristicKind FileCharacter) {
253  SLocEntryTable.push_back(SLocEntry::get(NextOffset,
254                                          FileInfo::get(IncludePos, File,
255                                                        FileCharacter)));
256  unsigned FileSize = File->getSize();
257  assert(NextOffset+FileSize+1 > NextOffset && "Ran out of source locations!");
258  NextOffset += FileSize+1;
259
260  // Set LastFileIDLookup to the newly created file.  The next getFileID call is
261  // almost guaranteed to be from that file.
262  return LastFileIDLookup = FileID::get(SLocEntryTable.size()-1);
263}
264
265/// createInstantiationLoc - Return a new SourceLocation that encodes the fact
266/// that a token from SpellingLoc should actually be referenced from
267/// InstantiationLoc.
268SourceLocation SourceManager::createInstantiationLoc(SourceLocation SpellingLoc,
269                                                     SourceLocation InstantLoc,
270                                                     unsigned TokLength) {
271  SLocEntryTable.push_back(SLocEntry::get(NextOffset,
272                                          InstantiationInfo::get(InstantLoc,
273                                                                 SpellingLoc)));
274  assert(NextOffset+TokLength+1 > NextOffset && "Ran out of source locations!");
275  NextOffset += TokLength+1;
276  return SourceLocation::getMacroLoc(NextOffset-(TokLength+1));
277}
278
279/// getBufferData - Return a pointer to the start and end of the source buffer
280/// data for the specified FileID.
281std::pair<const char*, const char*>
282SourceManager::getBufferData(FileID FID) const {
283  const llvm::MemoryBuffer *Buf = getBuffer(FID);
284  return std::make_pair(Buf->getBufferStart(), Buf->getBufferEnd());
285}
286
287
288//===----------------------------------------------------------------------===//
289// SourceLocation manipulation methods.
290//===----------------------------------------------------------------------===//
291
292/// getFileIDSlow - Return the FileID for a SourceLocation.  This is a very hot
293/// method that is used for all SourceManager queries that start with a
294/// SourceLocation object.  It is responsible for finding the entry in
295/// SLocEntryTable which contains the specified location.
296///
297FileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
298  assert(SLocOffset && "Invalid FileID");
299
300  // After the first and second level caches, I see two common sorts of
301  // behavior: 1) a lot of searched FileID's are "near" the cached file location
302  // or are "near" the cached instantiation location.  2) others are just
303  // completely random and may be a very long way away.
304  //
305  // To handle this, we do a linear search for up to 8 steps to catch #1 quickly
306  // then we fall back to a less cache efficient, but more scalable, binary
307  // search to find the location.
308
309  // See if this is near the file point - worst case we start scanning from the
310  // most newly created FileID.
311  std::vector<SrcMgr::SLocEntry>::const_iterator I;
312
313  if (SLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) {
314    // Neither loc prunes our search.
315    I = SLocEntryTable.end();
316  } else {
317    // Perhaps it is near the file point.
318    I = SLocEntryTable.begin()+LastFileIDLookup.ID;
319  }
320
321  // Find the FileID that contains this.  "I" is an iterator that points to a
322  // FileID whose offset is known to be larger than SLocOffset.
323  unsigned NumProbes = 0;
324  while (1) {
325    --I;
326    if (I->getOffset() <= SLocOffset) {
327#if 0
328      printf("lin %d -> %d [%s] %d %d\n", SLocOffset,
329             I-SLocEntryTable.begin(),
330             I->isInstantiation() ? "inst" : "file",
331             LastFileIDLookup.ID,  int(SLocEntryTable.end()-I));
332#endif
333      FileID Res = FileID::get(I-SLocEntryTable.begin());
334
335      // If this isn't an instantiation, remember it.  We have good locality
336      // across FileID lookups.
337      if (!I->isInstantiation())
338        LastFileIDLookup = Res;
339      NumLinearScans += NumProbes+1;
340      return Res;
341    }
342    if (++NumProbes == 8)
343      break;
344  }
345
346  // Convert "I" back into an index.  We know that it is an entry whose index is
347  // larger than the offset we are looking for.
348  unsigned GreaterIndex = I-SLocEntryTable.begin();
349  // LessIndex - This is the lower bound of the range that we're searching.
350  // We know that the offset corresponding to the FileID is is less than
351  // SLocOffset.
352  unsigned LessIndex = 0;
353  NumProbes = 0;
354  while (1) {
355    unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
356    unsigned MidOffset = SLocEntryTable[MiddleIndex].getOffset();
357
358    ++NumProbes;
359
360    // If the offset of the midpoint is too large, chop the high side of the
361    // range to the midpoint.
362    if (MidOffset > SLocOffset) {
363      GreaterIndex = MiddleIndex;
364      continue;
365    }
366
367    // If the middle index contains the value, succeed and return.
368    if (isOffsetInFileID(FileID::get(MiddleIndex), SLocOffset)) {
369#if 0
370      printf("bin %d -> %d [%s] %d %d\n", SLocOffset,
371             I-SLocEntryTable.begin(),
372             I->isInstantiation() ? "inst" : "file",
373             LastFileIDLookup.ID, int(SLocEntryTable.end()-I));
374#endif
375      FileID Res = FileID::get(MiddleIndex);
376
377      // If this isn't an instantiation, remember it.  We have good locality
378      // across FileID lookups.
379      if (!I->isInstantiation())
380        LastFileIDLookup = Res;
381      NumBinaryProbes += NumProbes;
382      return Res;
383    }
384
385    // Otherwise, move the low-side up to the middle index.
386    LessIndex = MiddleIndex;
387  }
388}
389
390SourceLocation SourceManager::
391getInstantiationLocSlowCase(SourceLocation Loc) const {
392  do {
393    std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
394    Loc =getSLocEntry(LocInfo.first).getInstantiation().getInstantiationLoc();
395    Loc = Loc.getFileLocWithOffset(LocInfo.second);
396  } while (!Loc.isFileID());
397
398  return Loc;
399}
400
401SourceLocation SourceManager::getSpellingLocSlowCase(SourceLocation Loc) const {
402  do {
403    std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
404    Loc = getSLocEntry(LocInfo.first).getInstantiation().getSpellingLoc();
405    Loc = Loc.getFileLocWithOffset(LocInfo.second);
406  } while (!Loc.isFileID());
407  return Loc;
408}
409
410
411std::pair<FileID, unsigned>
412SourceManager::getDecomposedInstantiationLocSlowCase(const SrcMgr::SLocEntry *E,
413                                                     unsigned Offset) const {
414  // If this is an instantiation record, walk through all the instantiation
415  // points.
416  FileID FID;
417  SourceLocation Loc;
418  do {
419    Loc = E->getInstantiation().getInstantiationLoc();
420
421    FID = getFileID(Loc);
422    E = &getSLocEntry(FID);
423    Offset += Loc.getOffset()-E->getOffset();
424  } while (!Loc.isFileID());
425
426  return std::make_pair(FID, Offset);
427}
428
429std::pair<FileID, unsigned>
430SourceManager::getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,
431                                                unsigned Offset) const {
432  // If this is an instantiation record, walk through all the instantiation
433  // points.
434  FileID FID;
435  SourceLocation Loc;
436  do {
437    Loc = E->getInstantiation().getSpellingLoc();
438
439    FID = getFileID(Loc);
440    E = &getSLocEntry(FID);
441    Offset += Loc.getOffset()-E->getOffset();
442  } while (!Loc.isFileID());
443
444  return std::make_pair(FID, Offset);
445}
446
447
448//===----------------------------------------------------------------------===//
449// Queries about the code at a SourceLocation.
450//===----------------------------------------------------------------------===//
451
452/// getCharacterData - Return a pointer to the start of the specified location
453/// in the appropriate MemoryBuffer.
454const char *SourceManager::getCharacterData(SourceLocation SL) const {
455  // Note that this is a hot function in the getSpelling() path, which is
456  // heavily used by -E mode.
457  std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(SL);
458
459  // Note that calling 'getBuffer()' may lazily page in a source file.
460  return getSLocEntry(LocInfo.first).getFile().getContentCache()
461              ->getBuffer()->getBufferStart() + LocInfo.second;
462}
463
464
465/// getColumnNumber - Return the column # for the specified file position.
466/// this is significantly cheaper to compute than the line number.
467unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos) const {
468  const char *Buf = getBuffer(FID)->getBufferStart();
469
470  unsigned LineStart = FilePos;
471  while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
472    --LineStart;
473  return FilePos-LineStart+1;
474}
475
476unsigned SourceManager::getSpellingColumnNumber(SourceLocation Loc) const {
477  if (Loc.isInvalid()) return 0;
478  std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
479  return getColumnNumber(LocInfo.first, LocInfo.second);
480}
481
482unsigned SourceManager::getInstantiationColumnNumber(SourceLocation Loc) const {
483  if (Loc.isInvalid()) return 0;
484  std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
485  return getColumnNumber(LocInfo.first, LocInfo.second);
486}
487
488
489
490static void ComputeLineNumbers(ContentCache* FI,
491                               llvm::BumpPtrAllocator &Alloc) DISABLE_INLINE;
492static void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){
493  // Note that calling 'getBuffer()' may lazily page in the file.
494  const MemoryBuffer *Buffer = FI->getBuffer();
495
496  // Find the file offsets of all of the *physical* source lines.  This does
497  // not look at trigraphs, escaped newlines, or anything else tricky.
498  std::vector<unsigned> LineOffsets;
499
500  // Line #1 starts at char 0.
501  LineOffsets.push_back(0);
502
503  const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart();
504  const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd();
505  unsigned Offs = 0;
506  while (1) {
507    // Skip over the contents of the line.
508    // TODO: Vectorize this?  This is very performance sensitive for programs
509    // with lots of diagnostics and in -E mode.
510    const unsigned char *NextBuf = (const unsigned char *)Buf;
511    while (*NextBuf != '\n' && *NextBuf != '\r' && *NextBuf != '\0')
512      ++NextBuf;
513    Offs += NextBuf-Buf;
514    Buf = NextBuf;
515
516    if (Buf[0] == '\n' || Buf[0] == '\r') {
517      // If this is \n\r or \r\n, skip both characters.
518      if ((Buf[1] == '\n' || Buf[1] == '\r') && Buf[0] != Buf[1])
519        ++Offs, ++Buf;
520      ++Offs, ++Buf;
521      LineOffsets.push_back(Offs);
522    } else {
523      // Otherwise, this is a null.  If end of file, exit.
524      if (Buf == End) break;
525      // Otherwise, skip the null.
526      ++Offs, ++Buf;
527    }
528  }
529
530  // Copy the offsets into the FileInfo structure.
531  FI->NumLines = LineOffsets.size();
532  FI->SourceLineCache = Alloc.Allocate<unsigned>(LineOffsets.size());
533  std::copy(LineOffsets.begin(), LineOffsets.end(), FI->SourceLineCache);
534}
535
536/// getLineNumber - Given a SourceLocation, return the spelling line number
537/// for the position indicated.  This requires building and caching a table of
538/// line offsets for the MemoryBuffer, so this is not cheap: use only when
539/// about to emit a diagnostic.
540unsigned SourceManager::getLineNumber(FileID FID, unsigned FilePos) const {
541  ContentCache *Content;
542  if (LastLineNoFileIDQuery == FID)
543    Content = LastLineNoContentCache;
544  else
545    Content = const_cast<ContentCache*>(getSLocEntry(FID)
546                                        .getFile().getContentCache());
547
548  // If this is the first use of line information for this buffer, compute the
549  /// SourceLineCache for it on demand.
550  if (Content->SourceLineCache == 0)
551    ComputeLineNumbers(Content, ContentCacheAlloc);
552
553  // Okay, we know we have a line number table.  Do a binary search to find the
554  // line number that this character position lands on.
555  unsigned *SourceLineCache = Content->SourceLineCache;
556  unsigned *SourceLineCacheStart = SourceLineCache;
557  unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines;
558
559  unsigned QueriedFilePos = FilePos+1;
560
561  // If the previous query was to the same file, we know both the file pos from
562  // that query and the line number returned.  This allows us to narrow the
563  // search space from the entire file to something near the match.
564  if (LastLineNoFileIDQuery == FID) {
565    if (QueriedFilePos >= LastLineNoFilePos) {
566      SourceLineCache = SourceLineCache+LastLineNoResult-1;
567
568      // The query is likely to be nearby the previous one.  Here we check to
569      // see if it is within 5, 10 or 20 lines.  It can be far away in cases
570      // where big comment blocks and vertical whitespace eat up lines but
571      // contribute no tokens.
572      if (SourceLineCache+5 < SourceLineCacheEnd) {
573        if (SourceLineCache[5] > QueriedFilePos)
574          SourceLineCacheEnd = SourceLineCache+5;
575        else if (SourceLineCache+10 < SourceLineCacheEnd) {
576          if (SourceLineCache[10] > QueriedFilePos)
577            SourceLineCacheEnd = SourceLineCache+10;
578          else if (SourceLineCache+20 < SourceLineCacheEnd) {
579            if (SourceLineCache[20] > QueriedFilePos)
580              SourceLineCacheEnd = SourceLineCache+20;
581          }
582        }
583      }
584    } else {
585      SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
586    }
587  }
588
589  // If the spread is large, do a "radix" test as our initial guess, based on
590  // the assumption that lines average to approximately the same length.
591  // NOTE: This is currently disabled, as it does not appear to be profitable in
592  // initial measurements.
593  if (0 && SourceLineCacheEnd-SourceLineCache > 20) {
594    unsigned FileLen = Content->SourceLineCache[Content->NumLines-1];
595
596    // Take a stab at guessing where it is.
597    unsigned ApproxPos = Content->NumLines*QueriedFilePos / FileLen;
598
599    // Check for -10 and +10 lines.
600    unsigned LowerBound = std::max(int(ApproxPos-10), 0);
601    unsigned UpperBound = std::min(ApproxPos+10, FileLen);
602
603    // If the computed lower bound is less than the query location, move it in.
604    if (SourceLineCache < SourceLineCacheStart+LowerBound &&
605        SourceLineCacheStart[LowerBound] < QueriedFilePos)
606      SourceLineCache = SourceLineCacheStart+LowerBound;
607
608    // If the computed upper bound is greater than the query location, move it.
609    if (SourceLineCacheEnd > SourceLineCacheStart+UpperBound &&
610        SourceLineCacheStart[UpperBound] >= QueriedFilePos)
611      SourceLineCacheEnd = SourceLineCacheStart+UpperBound;
612  }
613
614  unsigned *Pos
615    = std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
616  unsigned LineNo = Pos-SourceLineCacheStart;
617
618  LastLineNoFileIDQuery = FID;
619  LastLineNoContentCache = Content;
620  LastLineNoFilePos = QueriedFilePos;
621  LastLineNoResult = LineNo;
622  return LineNo;
623}
624
625unsigned SourceManager::getInstantiationLineNumber(SourceLocation Loc) const {
626  if (Loc.isInvalid()) return 0;
627  std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
628  return getLineNumber(LocInfo.first, LocInfo.second);
629}
630unsigned SourceManager::getSpellingLineNumber(SourceLocation Loc) const {
631  if (Loc.isInvalid()) return 0;
632  std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(Loc);
633  return getLineNumber(LocInfo.first, LocInfo.second);
634}
635
636
637/// getPresumedLoc - This method returns the "presumed" location of a
638/// SourceLocation specifies.  A "presumed location" can be modified by #line
639/// or GNU line marker directives.  This provides a view on the data that a
640/// user should see in diagnostics, for example.
641///
642/// Note that a presumed location is always given as the instantiation point
643/// of an instantiation location, not at the spelling location.
644PresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const {
645  if (Loc.isInvalid()) return PresumedLoc();
646
647  // Presumed locations are always for instantiation points.
648  std::pair<FileID, unsigned> LocInfo = getDecomposedInstantiationLoc(Loc);
649
650  const SrcMgr::FileInfo &FI = getSLocEntry(LocInfo.first).getFile();
651  const SrcMgr::ContentCache *C = FI.getContentCache();
652
653  // To get the source name, first consult the FileEntry (if one exists) before
654  // the MemBuffer as this will avoid unnecessarily paging in the MemBuffer.
655  const char *Filename =
656    C->Entry ? C->Entry->getName() : C->getBuffer()->getBufferIdentifier();
657
658  return PresumedLoc(Filename,
659                     getLineNumber(LocInfo.first, LocInfo.second),
660                     getColumnNumber(LocInfo.first, LocInfo.second),
661                     FI.getIncludeLoc());
662}
663
664//===----------------------------------------------------------------------===//
665// Other miscellaneous methods.
666//===----------------------------------------------------------------------===//
667
668
669/// PrintStats - Print statistics to stderr.
670///
671void SourceManager::PrintStats() const {
672  llvm::cerr << "\n*** Source Manager Stats:\n";
673  llvm::cerr << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
674             << " mem buffers mapped.\n";
675  llvm::cerr << SLocEntryTable.size() << " SLocEntry's allocated, "
676             << NextOffset << "B of Sloc address space used.\n";
677
678  unsigned NumLineNumsComputed = 0;
679  unsigned NumFileBytesMapped = 0;
680  for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){
681    NumLineNumsComputed += I->second->SourceLineCache != 0;
682    NumFileBytesMapped  += I->second->getSizeBytesMapped();
683  }
684
685  llvm::cerr << NumFileBytesMapped << " bytes of files mapped, "
686             << NumLineNumsComputed << " files with line #'s computed.\n";
687  llvm::cerr << "FileID scans: " << NumLinearScans << " linear, "
688             << NumBinaryProbes << " binary.\n";
689}
690
691//===----------------------------------------------------------------------===//
692// Serialization.
693//===----------------------------------------------------------------------===//
694
695void ContentCache::Emit(llvm::Serializer& S) const {
696  S.FlushRecord();
697  S.EmitPtr(this);
698
699  if (Entry) {
700    llvm::sys::Path Fname(Buffer->getBufferIdentifier());
701
702    if (Fname.isAbsolute())
703      S.EmitCStr(Fname.c_str());
704    else {
705      // Create an absolute path.
706      // FIXME: This will potentially contain ".." and "." in the path.
707      llvm::sys::Path path = llvm::sys::Path::GetCurrentDirectory();
708      path.appendComponent(Fname.c_str());
709      S.EmitCStr(path.c_str());
710    }
711  }
712  else {
713    const char* p = Buffer->getBufferStart();
714    const char* e = Buffer->getBufferEnd();
715
716    S.EmitInt(e-p);
717
718    for ( ; p != e; ++p)
719      S.EmitInt(*p);
720  }
721
722  S.FlushRecord();
723}
724
725void ContentCache::ReadToSourceManager(llvm::Deserializer& D,
726                                       SourceManager& SMgr,
727                                       FileManager* FMgr,
728                                       std::vector<char>& Buf) {
729  if (FMgr) {
730    llvm::SerializedPtrID PtrID = D.ReadPtrID();
731    D.ReadCStr(Buf,false);
732
733    // Create/fetch the FileEntry.
734    const char* start = &Buf[0];
735    const FileEntry* E = FMgr->getFile(start,start+Buf.size());
736
737    // FIXME: Ideally we want a lazy materialization of the ContentCache
738    //  anyway, because we don't want to read in source files unless this
739    //  is absolutely needed.
740    if (!E)
741      D.RegisterPtr(PtrID,NULL);
742    else
743      // Get the ContextCache object and register it with the deserializer.
744      D.RegisterPtr(PtrID, SMgr.getOrCreateContentCache(E));
745    return;
746  }
747
748  // Register the ContextCache object with the deserializer.
749  /* FIXME:
750  ContentCache *Entry
751  SMgr.MemBufferInfos.push_back(ContentCache());
752   = const_cast<ContentCache&>(SMgr.MemBufferInfos.back());
753  D.RegisterPtr(&Entry);
754
755  // Create the buffer.
756  unsigned Size = D.ReadInt();
757  Entry.Buffer = MemoryBuffer::getNewUninitMemBuffer(Size);
758
759  // Read the contents of the buffer.
760  char* p = const_cast<char*>(Entry.Buffer->getBufferStart());
761  for (unsigned i = 0; i < Size ; ++i)
762    p[i] = D.ReadInt();
763   */
764}
765
766void SourceManager::Emit(llvm::Serializer& S) const {
767  S.EnterBlock();
768  S.EmitPtr(this);
769  S.EmitInt(MainFileID.getOpaqueValue());
770
771  // Emit: FileInfos.  Just emit the file name.
772  S.EnterBlock();
773
774  // FIXME: Emit FileInfos.
775  //std::for_each(FileInfos.begin(), FileInfos.end(),
776  //              S.MakeEmitter<ContentCache>());
777
778  S.ExitBlock();
779
780  // Emit: MemBufferInfos
781  S.EnterBlock();
782
783  /* FIXME: EMIT.
784  std::for_each(MemBufferInfos.begin(), MemBufferInfos.end(),
785                S.MakeEmitter<ContentCache>());
786   */
787
788  S.ExitBlock();
789
790  // FIXME: Emit SLocEntryTable.
791
792  S.ExitBlock();
793}
794
795SourceManager*
796SourceManager::CreateAndRegister(llvm::Deserializer &D, FileManager &FMgr) {
797  SourceManager *M = new SourceManager();
798  D.RegisterPtr(M);
799
800  // Read: the FileID of the main source file of the translation unit.
801  M->MainFileID = FileID::get(D.ReadInt());
802
803  std::vector<char> Buf;
804
805  /*{ // FIXME Read: FileInfos.
806    llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();
807    while (!D.FinishedBlock(BLoc))
808    ContentCache::ReadToSourceManager(D,*M,&FMgr,Buf);
809  }*/
810
811  { // Read: MemBufferInfos.
812    llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();
813    while (!D.FinishedBlock(BLoc))
814    ContentCache::ReadToSourceManager(D,*M,NULL,Buf);
815  }
816
817  // FIXME: Read SLocEntryTable.
818
819  return M;
820}
821