SourceManager.cpp revision 4c4ea17d7f991516c37a871dfa4bbe5723fa85f0
15f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===--- SourceManager.cpp - Track and cache source files -----------------===//
25f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
35f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//                     The LLVM Compiler Infrastructure
45f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
50bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// This file is distributed under the University of Illinois Open Source
60bc735ffcfb223c0186419547abaa5c84482663eChris Lattner// License. See LICENSE.TXT for details.
75f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
85f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
95f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//  This file implements the SourceManager interface.
115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//
125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer//===----------------------------------------------------------------------===//
135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
145f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Basic/SourceManager.h"
155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "clang/Basic/FileManager.h"
165e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner#include "llvm/Support/Compiler.h"
175f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "llvm/Support/MemoryBuffer.h"
185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include "llvm/System/Path.h"
1978d85f53b093867bbb0123f016956178eea7343eTed Kremenek#include "llvm/Bitcode/Serialize.h"
2078d85f53b093867bbb0123f016956178eea7343eTed Kremenek#include "llvm/Bitcode/Deserialize.h"
21665dd4a40e0e38657f7bf26c2e3490304e5c7510Ted Kremenek#include "llvm/Support/Streams.h"
225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer#include <algorithm>
235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace clang;
245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing namespace SrcMgr;
255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerusing llvm::MemoryBuffer;
265f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
27de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner//===--------------------------------------------------------------------===//
28de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner// SourceManager Helper Classes
29de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner//===--------------------------------------------------------------------===//
30de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
3178d85f53b093867bbb0123f016956178eea7343eTed KremenekContentCache::~ContentCache() {
3278d85f53b093867bbb0123f016956178eea7343eTed Kremenek  delete Buffer;
335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
35c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek/// getSizeBytesMapped - Returns the number of bytes actually mapped for
36c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek///  this ContentCache.  This can be 0 if the MemBuffer was not actually
37c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek///  instantiated.
38c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenekunsigned ContentCache::getSizeBytesMapped() const {
39c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek  return Buffer ? Buffer->getBufferSize() : 0;
40c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek}
41c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek
42c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek/// getSize - Returns the size of the content encapsulated by this ContentCache.
43c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek///  This can be the size of the source file or the size of an arbitrary
44c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek///  scratch buffer.  If the ContentCache encapsulates a source file, that
45c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek///  file is not lazily brought in from disk to satisfy this query.
46c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenekunsigned ContentCache::getSize() const {
47c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek  return Entry ? Entry->getSize() : Buffer->getBufferSize();
48c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek}
49c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek
50987cd3da36e90aa21a9e290f5b383cf010762b83Chris Lattnerconst llvm::MemoryBuffer *ContentCache::getBuffer() const {
515b034ad3ec0aa1ad6bcb3624390f030038670705Ted Kremenek  // Lazily create the Buffer for ContentCaches that wrap files.
525b034ad3ec0aa1ad6bcb3624390f030038670705Ted Kremenek  if (!Buffer && Entry) {
535b034ad3ec0aa1ad6bcb3624390f030038670705Ted Kremenek    // FIXME: Should we support a way to not have to do this check over
545b034ad3ec0aa1ad6bcb3624390f030038670705Ted Kremenek    //   and over if we cannot open the file?
5505816591ec488a933dfecc9ff9f3cbf3c32767c2Chris Lattner    Buffer = MemoryBuffer::getFile(Entry->getName(), 0, Entry->getSize());
565b034ad3ec0aa1ad6bcb3624390f030038670705Ted Kremenek  }
57c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek  return Buffer;
58c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek}
59c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek
60de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner//===--------------------------------------------------------------------===//
615b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner// Line Table Implementation
625b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner//===--------------------------------------------------------------------===//
635b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner
645b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattnernamespace clang {
655b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner/// LineTableInfo - This class is used to hold and unique data used to
665b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner/// represent #line information.
675b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattnerclass LineTableInfo {
685b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  /// FilenameIDs - This map is used to assign unique IDs to filenames in
695b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  /// #line directives.  This allows us to unique the filenames that
705b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  /// frequently reoccur and reference them with indices.  FilenameIDs holds
715b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  /// the mapping from string -> ID, and FilenamesByID holds the mapping of ID
725b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  /// to string.
735b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  llvm::StringMap<unsigned, llvm::BumpPtrAllocator> FilenameIDs;
745b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  std::vector<llvm::StringMapEntry<unsigned>*> FilenamesByID;
755b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattnerpublic:
765b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  LineTableInfo() {
775b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  }
785b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner
795b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  void clear() {
805b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner    FilenameIDs.clear();
815b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner    FilenamesByID.clear();
825b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  }
835b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner
845b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  ~LineTableInfo() {}
855b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner
865b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  unsigned getLineTableFilenameID(const char *Ptr, unsigned Len);
875b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner
885b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner};
895b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner} // namespace clang
905b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner
915b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner
925b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner
935b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner
945b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattnerunsigned LineTableInfo::getLineTableFilenameID(const char *Ptr, unsigned Len) {
955b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  // Look up the filename in the string table, returning the pre-existing value
965b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  // if it exists.
975b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  llvm::StringMapEntry<unsigned> &Entry =
985b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner    FilenameIDs.GetOrCreateValue(Ptr, Ptr+Len, ~0U);
995b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  if (Entry.getValue() != ~0U)
1005b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner    return Entry.getValue();
1015b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner
1025b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  // Otherwise, assign this the next available ID.
1035b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  Entry.setValue(FilenamesByID.size());
1045b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  FilenamesByID.push_back(&Entry);
1055b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  return FilenamesByID.size()-1;
1065b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner}
1075b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner
1085b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner/// getLineTableFilenameID - Return the uniqued ID for the specified filename.
1095b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner///
1105b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattnerunsigned SourceManager::getLineTableFilenameID(const char *Ptr, unsigned Len) {
1115b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  if (LineTable == 0)
1125b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner    LineTable = new LineTableInfo();
1135b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  return LineTable->getLineTableFilenameID(Ptr, Len);
1145b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner}
1155b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner
1165b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner
1174c4ea17d7f991516c37a871dfa4bbe5723fa85f0Chris Lattner/// AddLineNote - Add a line note to the line table for the FileID and offset
1184c4ea17d7f991516c37a871dfa4bbe5723fa85f0Chris Lattner/// specified by Loc.  If FilenameID is -1, it is considered to be
1194c4ea17d7f991516c37a871dfa4bbe5723fa85f0Chris Lattner/// unspecified.
1204c4ea17d7f991516c37a871dfa4bbe5723fa85f0Chris Lattnervoid SourceManager::AddLineNote(SourceLocation Loc, unsigned LineNo,
1214c4ea17d7f991516c37a871dfa4bbe5723fa85f0Chris Lattner                                int FilenameID) {
1224c4ea17d7f991516c37a871dfa4bbe5723fa85f0Chris Lattner
1234c4ea17d7f991516c37a871dfa4bbe5723fa85f0Chris Lattner}
1244c4ea17d7f991516c37a871dfa4bbe5723fa85f0Chris Lattner
1254c4ea17d7f991516c37a871dfa4bbe5723fa85f0Chris Lattner
1265b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner//===--------------------------------------------------------------------===//
127de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner// Private 'Create' methods.
128de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner//===--------------------------------------------------------------------===//
129c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek
1305b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris LattnerSourceManager::~SourceManager() {
1315b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  delete LineTable;
1320d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner
1330d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  // Delete FileEntry objects corresponding to content caches.  Since the actual
1340d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  // content cache objects are bump pointer allocated, we just have to run the
1350d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  // dtors, but we call the deallocate method for completeness.
1360d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) {
1370d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner    MemBufferInfos[i]->~ContentCache();
1380d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner    ContentCacheAlloc.Deallocate(MemBufferInfos[i]);
1390d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  }
1400d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  for (llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::iterator
1410d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner       I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) {
1420d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner    I->second->~ContentCache();
1430d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner    ContentCacheAlloc.Deallocate(I->second);
1440d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  }
1455b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner}
1465b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner
1475b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattnervoid SourceManager::clearIDTables() {
1485b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  MainFileID = FileID();
1495b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  SLocEntryTable.clear();
1505b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  LastLineNoFileIDQuery = FileID();
1515b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  LastLineNoContentCache = 0;
1525b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  LastFileIDLookup = FileID();
1535b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner
1545b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  if (LineTable)
1555b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner    LineTable->clear();
1565b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner
1575b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  // Use up FileID #0 as an invalid instantiation.
1585b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  NextOffset = 0;
1595b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner  createInstantiationLoc(SourceLocation(), SourceLocation(), 1);
1605b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner}
1615b9a504720fb52594ca3686e10eb6c0cfa2e7d62Chris Lattner
162de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner/// getOrCreateContentCache - Create or return a cached ContentCache for the
163de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner/// specified file.
164de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattnerconst ContentCache *
165de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris LattnerSourceManager::getOrCreateContentCache(const FileEntry *FileEnt) {
1665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  assert(FileEnt && "Didn't specify a file entry to use?");
167de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
1685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Do we already have information about this file?
1690d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  ContentCache *&Entry = FileInfos[FileEnt];
1700d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  if (Entry) return Entry;
1715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
17200282d6e1194655a2e89f940bd6fa8484b52e666Chris Lattner  // Nope, create a new Cache entry.  Make sure it is at least 8-byte aligned
17300282d6e1194655a2e89f940bd6fa8484b52e666Chris Lattner  // so that FileInfo can use the low 3 bits of the pointer for its own
17400282d6e1194655a2e89f940bd6fa8484b52e666Chris Lattner  // nefarious purposes.
17500282d6e1194655a2e89f940bd6fa8484b52e666Chris Lattner  unsigned EntryAlign = llvm::AlignOf<ContentCache>::Alignment;
17600282d6e1194655a2e89f940bd6fa8484b52e666Chris Lattner  EntryAlign = std::max(8U, EntryAlign);
17700282d6e1194655a2e89f940bd6fa8484b52e666Chris Lattner  Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign);
1780d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  new (Entry) ContentCache(FileEnt);
1790d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  return Entry;
1805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
1815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
1825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
183d1c0eee9aa30926839184b657b9e21be4a2ebdb8Ted Kremenek/// createMemBufferContentCache - Create a new ContentCache for the specified
184d1c0eee9aa30926839184b657b9e21be4a2ebdb8Ted Kremenek///  memory buffer.  This does no caching.
18578d85f53b093867bbb0123f016956178eea7343eTed Kremenekconst ContentCache*
18678d85f53b093867bbb0123f016956178eea7343eTed KremenekSourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) {
18700282d6e1194655a2e89f940bd6fa8484b52e666Chris Lattner  // Add a new ContentCache to the MemBufferInfos list and return it.  Make sure
18800282d6e1194655a2e89f940bd6fa8484b52e666Chris Lattner  // it is at least 8-byte aligned so that FileInfo can use the low 3 bits of
18900282d6e1194655a2e89f940bd6fa8484b52e666Chris Lattner  // the pointer for its own nefarious purposes.
19000282d6e1194655a2e89f940bd6fa8484b52e666Chris Lattner  unsigned EntryAlign = llvm::AlignOf<ContentCache>::Alignment;
19100282d6e1194655a2e89f940bd6fa8484b52e666Chris Lattner  EntryAlign = std::max(8U, EntryAlign);
19200282d6e1194655a2e89f940bd6fa8484b52e666Chris Lattner  ContentCache *Entry = ContentCacheAlloc.Allocate<ContentCache>(1, EntryAlign);
1930d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  new (Entry) ContentCache();
1940d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  MemBufferInfos.push_back(Entry);
1950d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  Entry->setBuffer(Buffer);
1960d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  return Entry;
1975f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
1985f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
199de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner//===----------------------------------------------------------------------===//
200de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner// Methods to create new FileID's and instantiations.
201de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner//===----------------------------------------------------------------------===//
2025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
20348002c89578eaeb008a0bb5a10d8216e61906459Nico Weber/// createFileID - Create a new fileID for the specified ContentCache and
2040d892d8bfddd4916cc4f3467e1184a623d0716daTed Kremenek/// include position.  This works regardless of whether the ContentCache
2050d892d8bfddd4916cc4f3467e1184a623d0716daTed Kremenek/// corresponds to a file or some other input source.
2062b2453a7d8fe732561795431f39ceb2b2a832d84Chris LattnerFileID SourceManager::createFileID(const ContentCache *File,
207de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner                                   SourceLocation IncludePos,
208de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner                                   SrcMgr::CharacteristicKind FileCharacter) {
209de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  SLocEntryTable.push_back(SLocEntry::get(NextOffset,
210de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner                                          FileInfo::get(IncludePos, File,
211de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner                                                        FileCharacter)));
212c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek  unsigned FileSize = File->getSize();
213de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  assert(NextOffset+FileSize+1 > NextOffset && "Ran out of source locations!");
214de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  NextOffset += FileSize+1;
2155f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
216de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // Set LastFileIDLookup to the newly created file.  The next getFileID call is
217de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // almost guaranteed to be from that file.
218de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  return LastFileIDLookup = FileID::get(SLocEntryTable.size()-1);
2195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
2205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
221de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner/// createInstantiationLoc - Return a new SourceLocation that encodes the fact
222df7c17a8d02fe09a3466786bae3e40fc3252687aChris Lattner/// that a token from SpellingLoc should actually be referenced from
2235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// InstantiationLoc.
224de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris LattnerSourceLocation SourceManager::createInstantiationLoc(SourceLocation SpellingLoc,
225de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner                                                     SourceLocation InstantLoc,
226de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner                                                     unsigned TokLength) {
227de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  SLocEntryTable.push_back(SLocEntry::get(NextOffset,
228de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner                                          InstantiationInfo::get(InstantLoc,
229de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner                                                                 SpellingLoc)));
230de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  assert(NextOffset+TokLength+1 > NextOffset && "Ran out of source locations!");
231de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  NextOffset += TokLength+1;
232de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  return SourceLocation::getMacroLoc(NextOffset-(TokLength+1));
2335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
2345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
23531530bae788dea5c79e72a1f99a56c3f5c6aa36fChris Lattner/// getBufferData - Return a pointer to the start and end of the source buffer
23631530bae788dea5c79e72a1f99a56c3f5c6aa36fChris Lattner/// data for the specified FileID.
2372b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattnerstd::pair<const char*, const char*>
2382b2453a7d8fe732561795431f39ceb2b2a832d84Chris LattnerSourceManager::getBufferData(FileID FID) const {
2392b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  const llvm::MemoryBuffer *Buf = getBuffer(FID);
2402b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  return std::make_pair(Buf->getBufferStart(), Buf->getBufferEnd());
2412b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner}
2422b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner
2432b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner
244de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner//===--------------------------------------------------------------------===//
245de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner// SourceLocation manipulation methods.
246de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner//===--------------------------------------------------------------------===//
247de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
248de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner/// getFileIDSlow - Return the FileID for a SourceLocation.  This is a very hot
249de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner/// method that is used for all SourceManager queries that start with a
250de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner/// SourceLocation object.  It is responsible for finding the entry in
251de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner/// SLocEntryTable which contains the specified location.
252de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner///
253de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris LattnerFileID SourceManager::getFileIDSlow(unsigned SLocOffset) const {
254de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  assert(SLocOffset && "Invalid FileID");
255de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
256de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // After the first and second level caches, I see two common sorts of
257de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // behavior: 1) a lot of searched FileID's are "near" the cached file location
258de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // or are "near" the cached instantiation location.  2) others are just
259de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // completely random and may be a very long way away.
260de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  //
261de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // To handle this, we do a linear search for up to 8 steps to catch #1 quickly
262de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // then we fall back to a less cache efficient, but more scalable, binary
263de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // search to find the location.
264de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
265de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // See if this is near the file point - worst case we start scanning from the
266de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // most newly created FileID.
267de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  std::vector<SrcMgr::SLocEntry>::const_iterator I;
268de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
269de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  if (SLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) {
270de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    // Neither loc prunes our search.
271de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    I = SLocEntryTable.end();
272de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  } else {
273de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    // Perhaps it is near the file point.
274de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    I = SLocEntryTable.begin()+LastFileIDLookup.ID;
275de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  }
276de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
277de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // Find the FileID that contains this.  "I" is an iterator that points to a
278de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // FileID whose offset is known to be larger than SLocOffset.
279de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  unsigned NumProbes = 0;
280de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  while (1) {
281de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    --I;
282de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    if (I->getOffset() <= SLocOffset) {
283de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner#if 0
284de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      printf("lin %d -> %d [%s] %d %d\n", SLocOffset,
285de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner             I-SLocEntryTable.begin(),
286de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner             I->isInstantiation() ? "inst" : "file",
287de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner             LastFileIDLookup.ID,  int(SLocEntryTable.end()-I));
288de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner#endif
289de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      FileID Res = FileID::get(I-SLocEntryTable.begin());
290de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
291de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      // If this isn't an instantiation, remember it.  We have good locality
292de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      // across FileID lookups.
293de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      if (!I->isInstantiation())
294de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner        LastFileIDLookup = Res;
295de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      NumLinearScans += NumProbes+1;
296de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      return Res;
297de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    }
298de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    if (++NumProbes == 8)
299de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      break;
300de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  }
301de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
302de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // Convert "I" back into an index.  We know that it is an entry whose index is
303de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // larger than the offset we are looking for.
304de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  unsigned GreaterIndex = I-SLocEntryTable.begin();
305de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // LessIndex - This is the lower bound of the range that we're searching.
306de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // We know that the offset corresponding to the FileID is is less than
307de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // SLocOffset.
308de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  unsigned LessIndex = 0;
309de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  NumProbes = 0;
310de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  while (1) {
311de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    unsigned MiddleIndex = (GreaterIndex-LessIndex)/2+LessIndex;
312de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    unsigned MidOffset = SLocEntryTable[MiddleIndex].getOffset();
313de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
314de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    ++NumProbes;
315de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
316de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    // If the offset of the midpoint is too large, chop the high side of the
317de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    // range to the midpoint.
318de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    if (MidOffset > SLocOffset) {
319de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      GreaterIndex = MiddleIndex;
320de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      continue;
321de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    }
322de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
323de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    // If the middle index contains the value, succeed and return.
324de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    if (isOffsetInFileID(FileID::get(MiddleIndex), SLocOffset)) {
325de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner#if 0
326de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      printf("bin %d -> %d [%s] %d %d\n", SLocOffset,
327de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner             I-SLocEntryTable.begin(),
328de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner             I->isInstantiation() ? "inst" : "file",
329de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner             LastFileIDLookup.ID, int(SLocEntryTable.end()-I));
330de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner#endif
331de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      FileID Res = FileID::get(MiddleIndex);
332de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
333de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      // If this isn't an instantiation, remember it.  We have good locality
334de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      // across FileID lookups.
335de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      if (!I->isInstantiation())
336de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner        LastFileIDLookup = Res;
337de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      NumBinaryProbes += NumProbes;
338de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      return Res;
339de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    }
340de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
341de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    // Otherwise, move the low-side up to the middle index.
342de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    LessIndex = MiddleIndex;
343de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  }
344de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner}
345de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
346addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris LattnerSourceLocation SourceManager::
347addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris LattnergetInstantiationLocSlowCase(SourceLocation Loc) const {
348addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner  do {
349addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner    std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
350addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner    Loc =getSLocEntry(LocInfo.first).getInstantiation().getInstantiationLoc();
351addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner    Loc = Loc.getFileLocWithOffset(LocInfo.second);
352addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner  } while (!Loc.isFileID());
353addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner
354addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner  return Loc;
355addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner}
356addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner
357addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris LattnerSourceLocation SourceManager::getSpellingLocSlowCase(SourceLocation Loc) const {
358addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner  do {
359addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner    std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
360addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner    Loc = getSLocEntry(LocInfo.first).getInstantiation().getSpellingLoc();
361addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner    Loc = Loc.getFileLocWithOffset(LocInfo.second);
362addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner  } while (!Loc.isFileID());
363addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner  return Loc;
364addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner}
365addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner
366addb797ca2b5afc1a1e82fd8d5d6eb2a592e75a9Chris Lattner
367de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattnerstd::pair<FileID, unsigned>
368de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris LattnerSourceManager::getDecomposedInstantiationLocSlowCase(const SrcMgr::SLocEntry *E,
369de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner                                                     unsigned Offset) const {
370de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // If this is an instantiation record, walk through all the instantiation
371de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // points.
372de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  FileID FID;
373de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  SourceLocation Loc;
374de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  do {
375de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    Loc = E->getInstantiation().getInstantiationLoc();
376de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
377de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    FID = getFileID(Loc);
378de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    E = &getSLocEntry(FID);
379de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    Offset += Loc.getOffset()-E->getOffset();
380bcd1a1b5af0b2d57b20fc393a8c3b0badc58c450Chris Lattner  } while (!Loc.isFileID());
381de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
382de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  return std::make_pair(FID, Offset);
383de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner}
384de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
385de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattnerstd::pair<FileID, unsigned>
386de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris LattnerSourceManager::getDecomposedSpellingLocSlowCase(const SrcMgr::SLocEntry *E,
387de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner                                                unsigned Offset) const {
388bcd1a1b5af0b2d57b20fc393a8c3b0badc58c450Chris Lattner  // If this is an instantiation record, walk through all the instantiation
389bcd1a1b5af0b2d57b20fc393a8c3b0badc58c450Chris Lattner  // points.
390bcd1a1b5af0b2d57b20fc393a8c3b0badc58c450Chris Lattner  FileID FID;
391bcd1a1b5af0b2d57b20fc393a8c3b0badc58c450Chris Lattner  SourceLocation Loc;
392bcd1a1b5af0b2d57b20fc393a8c3b0badc58c450Chris Lattner  do {
393bcd1a1b5af0b2d57b20fc393a8c3b0badc58c450Chris Lattner    Loc = E->getInstantiation().getSpellingLoc();
394bcd1a1b5af0b2d57b20fc393a8c3b0badc58c450Chris Lattner
395bcd1a1b5af0b2d57b20fc393a8c3b0badc58c450Chris Lattner    FID = getFileID(Loc);
396bcd1a1b5af0b2d57b20fc393a8c3b0badc58c450Chris Lattner    E = &getSLocEntry(FID);
397bcd1a1b5af0b2d57b20fc393a8c3b0badc58c450Chris Lattner    Offset += Loc.getOffset()-E->getOffset();
398bcd1a1b5af0b2d57b20fc393a8c3b0badc58c450Chris Lattner  } while (!Loc.isFileID());
399bcd1a1b5af0b2d57b20fc393a8c3b0badc58c450Chris Lattner
400de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  return std::make_pair(FID, Offset);
401de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner}
402de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
403de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
404de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner//===----------------------------------------------------------------------===//
405de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner// Queries about the code at a SourceLocation.
406de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner//===----------------------------------------------------------------------===//
4075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getCharacterData - Return a pointer to the start of the specified location
4095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// in the appropriate MemoryBuffer.
4105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerconst char *SourceManager::getCharacterData(SourceLocation SL) const {
4115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Note that this is a hot function in the getSpelling() path, which is
4125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // heavily used by -E mode.
413de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  std::pair<FileID, unsigned> LocInfo = getDecomposedSpellingLoc(SL);
4142b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner
415c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek  // Note that calling 'getBuffer()' may lazily page in a source file.
416de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  return getSLocEntry(LocInfo.first).getFile().getContentCache()
417de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner              ->getBuffer()->getBufferStart() + LocInfo.second;
4185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
4195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4219dc1f530c086d2c16f8cba758b0f59a5bf41323aChris Lattner/// getColumnNumber - Return the column # for the specified file position.
4225f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// this is significantly cheaper to compute than the line number.  This returns
4235f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// zero if the column number isn't known.
4245f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerunsigned SourceManager::getColumnNumber(SourceLocation Loc) const {
425de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  if (Loc.isInvalid()) return 0;
426de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  assert(Loc.isFileID() && "Don't know what part of instantiation loc to get");
4272b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner
428de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
4292b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  unsigned FilePos = LocInfo.second;
4305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4312b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  const char *Buf = getBuffer(LocInfo.first)->getBufferStart();
4325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  unsigned LineStart = FilePos;
4345f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r')
4355f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer    --LineStart;
4365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  return FilePos-LineStart+1;
4375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
4385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
4390d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattnerstatic void ComputeLineNumbers(ContentCache* FI,
4400d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner                               llvm::BumpPtrAllocator &Alloc) DISABLE_INLINE;
4410d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattnerstatic void ComputeLineNumbers(ContentCache* FI, llvm::BumpPtrAllocator &Alloc){
442c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek  // Note that calling 'getBuffer()' may lazily page in the file.
443c16c208e8519476d838ad11fffc8e0ecea50550dTed Kremenek  const MemoryBuffer *Buffer = FI->getBuffer();
4445e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner
4455e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  // Find the file offsets of all of the *physical* source lines.  This does
4465e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  // not look at trigraphs, escaped newlines, or anything else tricky.
4475e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  std::vector<unsigned> LineOffsets;
4485e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner
4495e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  // Line #1 starts at char 0.
4505e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  LineOffsets.push_back(0);
4515e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner
4525e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart();
4535e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd();
4545e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  unsigned Offs = 0;
4555e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  while (1) {
4565e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner    // Skip over the contents of the line.
4575e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner    // TODO: Vectorize this?  This is very performance sensitive for programs
4585e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner    // with lots of diagnostics and in -E mode.
4595e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner    const unsigned char *NextBuf = (const unsigned char *)Buf;
4605e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner    while (*NextBuf != '\n' && *NextBuf != '\r' && *NextBuf != '\0')
4615e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner      ++NextBuf;
4625e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner    Offs += NextBuf-Buf;
4635e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner    Buf = NextBuf;
4645e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner
4655e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner    if (Buf[0] == '\n' || Buf[0] == '\r') {
4665e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner      // If this is \n\r or \r\n, skip both characters.
4675e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner      if ((Buf[1] == '\n' || Buf[1] == '\r') && Buf[0] != Buf[1])
4685e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner        ++Offs, ++Buf;
4695e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner      ++Offs, ++Buf;
4705e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner      LineOffsets.push_back(Offs);
4715e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner    } else {
4725e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner      // Otherwise, this is a null.  If end of file, exit.
4735e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner      if (Buf == End) break;
4745e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner      // Otherwise, skip the null.
4755e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner      ++Offs, ++Buf;
4765e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner    }
4775e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  }
4785e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner
4795e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  // Copy the offsets into the FileInfo structure.
4805e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  FI->NumLines = LineOffsets.size();
4810d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  FI->SourceLineCache = Alloc.Allocate<unsigned>(LineOffsets.size());
4825e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  std::copy(LineOffsets.begin(), LineOffsets.end(), FI->SourceLineCache);
4835e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner}
4845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
485df7c17a8d02fe09a3466786bae3e40fc3252687aChris Lattner/// getLineNumber - Given a SourceLocation, return the spelling line number
4865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// for the position indicated.  This requires building and caching a table of
4875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// line offsets for the MemoryBuffer, so this is not cheap: use only when
4885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// about to emit a diagnostic.
489f812a45dd93634c9300ed5533bd26b56374714a1Chris Lattnerunsigned SourceManager::getLineNumber(SourceLocation Loc) const {
490de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  if (Loc.isInvalid()) return 0;
491de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  assert(Loc.isFileID() && "Don't know what part of instantiation loc to get");
49278d85f53b093867bbb0123f016956178eea7343eTed Kremenek
493de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(Loc);
4945e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner
495de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  ContentCache *Content;
4962b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  if (LastLineNoFileIDQuery == LocInfo.first)
49778d85f53b093867bbb0123f016956178eea7343eTed Kremenek    Content = LastLineNoContentCache;
4985e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  else
499de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    Content = const_cast<ContentCache*>(getSLocEntry(LocInfo.first)
500de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner                                        .getFile().getContentCache());
5015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
5025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // If this is the first use of line information for this buffer, compute the
5035e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  /// SourceLineCache for it on demand.
50478d85f53b093867bbb0123f016956178eea7343eTed Kremenek  if (Content->SourceLineCache == 0)
5050d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner    ComputeLineNumbers(Content, ContentCacheAlloc);
5065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
5075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // Okay, we know we have a line number table.  Do a binary search to find the
5085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  // line number that this character position lands on.
50978d85f53b093867bbb0123f016956178eea7343eTed Kremenek  unsigned *SourceLineCache = Content->SourceLineCache;
5105e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  unsigned *SourceLineCacheStart = SourceLineCache;
51178d85f53b093867bbb0123f016956178eea7343eTed Kremenek  unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines;
5125e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner
5132b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  unsigned QueriedFilePos = LocInfo.second+1;
5145e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner
5155e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  // If the previous query was to the same file, we know both the file pos from
5165e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  // that query and the line number returned.  This allows us to narrow the
5175e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  // search space from the entire file to something near the match.
5182b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  if (LastLineNoFileIDQuery == LocInfo.first) {
5195e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner    if (QueriedFilePos >= LastLineNoFilePos) {
5205e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner      SourceLineCache = SourceLineCache+LastLineNoResult-1;
5215e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner
5225e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner      // The query is likely to be nearby the previous one.  Here we check to
5235e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner      // see if it is within 5, 10 or 20 lines.  It can be far away in cases
5245e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner      // where big comment blocks and vertical whitespace eat up lines but
5255e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner      // contribute no tokens.
5265e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner      if (SourceLineCache+5 < SourceLineCacheEnd) {
5275e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner        if (SourceLineCache[5] > QueriedFilePos)
5285e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner          SourceLineCacheEnd = SourceLineCache+5;
5295e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner        else if (SourceLineCache+10 < SourceLineCacheEnd) {
5305e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner          if (SourceLineCache[10] > QueriedFilePos)
5315e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner            SourceLineCacheEnd = SourceLineCache+10;
5325e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner          else if (SourceLineCache+20 < SourceLineCacheEnd) {
5335e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner            if (SourceLineCache[20] > QueriedFilePos)
5345e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner              SourceLineCacheEnd = SourceLineCache+20;
5355e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner          }
5365e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner        }
5375e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner      }
5385e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner    } else {
5395e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner      SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1;
5405e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner    }
5415e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  }
5425e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner
5431cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner  // If the spread is large, do a "radix" test as our initial guess, based on
5441cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner  // the assumption that lines average to approximately the same length.
5451cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner  // NOTE: This is currently disabled, as it does not appear to be profitable in
5461cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner  // initial measurements.
5471cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner  if (0 && SourceLineCacheEnd-SourceLineCache > 20) {
54878d85f53b093867bbb0123f016956178eea7343eTed Kremenek    unsigned FileLen = Content->SourceLineCache[Content->NumLines-1];
5491cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner
5501cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner    // Take a stab at guessing where it is.
55178d85f53b093867bbb0123f016956178eea7343eTed Kremenek    unsigned ApproxPos = Content->NumLines*QueriedFilePos / FileLen;
5521cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner
5531cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner    // Check for -10 and +10 lines.
5541cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner    unsigned LowerBound = std::max(int(ApproxPos-10), 0);
5551cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner    unsigned UpperBound = std::min(ApproxPos+10, FileLen);
5561cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner
5571cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner    // If the computed lower bound is less than the query location, move it in.
5581cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner    if (SourceLineCache < SourceLineCacheStart+LowerBound &&
5591cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner        SourceLineCacheStart[LowerBound] < QueriedFilePos)
5601cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner      SourceLineCache = SourceLineCacheStart+LowerBound;
5611cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner
5621cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner    // If the computed upper bound is greater than the query location, move it.
5631cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner    if (SourceLineCacheEnd > SourceLineCacheStart+UpperBound &&
5641cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner        SourceLineCacheStart[UpperBound] >= QueriedFilePos)
5651cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner      SourceLineCacheEnd = SourceLineCacheStart+UpperBound;
5661cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner  }
5671cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner
5681cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner  unsigned *Pos
5691cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner    = std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos);
5705e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  unsigned LineNo = Pos-SourceLineCacheStart;
5715e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner
5722b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  LastLineNoFileIDQuery = LocInfo.first;
57378d85f53b093867bbb0123f016956178eea7343eTed Kremenek  LastLineNoContentCache = Content;
5745e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  LastLineNoFilePos = QueriedFilePos;
5755e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  LastLineNoResult = LineNo;
5765e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner  return LineNo;
5775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
5785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
579b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner/// getPresumedLoc - This method returns the "presumed" location of a
580b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner/// SourceLocation specifies.  A "presumed location" can be modified by #line
581b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner/// or GNU line marker directives.  This provides a view on the data that a
582b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner/// user should see in diagnostics, for example.
583b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner///
584b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner/// Note that a presumed location is always given as the instantiation point
585b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner/// of an instantiation location, not at the spelling location.
586b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris LattnerPresumedLoc SourceManager::getPresumedLoc(SourceLocation Loc) const {
587b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner  if (Loc.isInvalid()) return PresumedLoc();
588b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner
589b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner  // Presumed locations are always for instantiation points.
590b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner  Loc = getInstantiationLoc(Loc);
591de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
592b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner  // FIXME: Could just decompose Loc once!
593de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
594b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner  const SrcMgr::FileInfo &FI = getSLocEntry(getFileID(Loc)).getFile();
595b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner  const SrcMgr::ContentCache *C = FI.getContentCache();
596b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner
597de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // To get the source name, first consult the FileEntry (if one exists) before
598de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // the MemBuffer as this will avoid unnecessarily paging in the MemBuffer.
599b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner  const char *Filename =
600b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner    C->Entry ? C->Entry->getName() : C->getBuffer()->getBufferIdentifier();
601b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner
602b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner  return PresumedLoc(Filename, getLineNumber(Loc), getColumnNumber(Loc),
603b9c3f966b103f7cfe8e5e60007c4c8b38f7298ebChris Lattner                     FI.getIncludeLoc());
604de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner}
605de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
606de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner//===----------------------------------------------------------------------===//
607de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner// Other miscellaneous methods.
608de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner//===----------------------------------------------------------------------===//
609de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
610de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
6115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// PrintStats - Print statistics to stderr.
6125f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer///
6135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid SourceManager::PrintStats() const {
614665dd4a40e0e38657f7bf26c2e3490304e5c7510Ted Kremenek  llvm::cerr << "\n*** Source Manager Stats:\n";
615665dd4a40e0e38657f7bf26c2e3490304e5c7510Ted Kremenek  llvm::cerr << FileInfos.size() << " files mapped, " << MemBufferInfos.size()
61608c375cd52b8f6b6a6915a2007205bc8179f41e9Chris Lattner             << " mem buffers mapped.\n";
61708c375cd52b8f6b6a6915a2007205bc8179f41e9Chris Lattner  llvm::cerr << SLocEntryTable.size() << " SLocEntry's allocated, "
61808c375cd52b8f6b6a6915a2007205bc8179f41e9Chris Lattner             << NextOffset << "B of Sloc address space used.\n";
6195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer
6205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  unsigned NumLineNumsComputed = 0;
6215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  unsigned NumFileBytesMapped = 0;
6220d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  for (fileinfo_iterator I = fileinfo_begin(), E = fileinfo_end(); I != E; ++I){
6230d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner    NumLineNumsComputed += I->second->SourceLineCache != 0;
6240d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner    NumFileBytesMapped  += I->second->getSizeBytesMapped();
6255f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer  }
62678d85f53b093867bbb0123f016956178eea7343eTed Kremenek
627665dd4a40e0e38657f7bf26c2e3490304e5c7510Ted Kremenek  llvm::cerr << NumFileBytesMapped << " bytes of files mapped, "
628665dd4a40e0e38657f7bf26c2e3490304e5c7510Ted Kremenek             << NumLineNumsComputed << " files with line #'s computed.\n";
629de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  llvm::cerr << "FileID scans: " << NumLinearScans << " linear, "
630de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner             << NumBinaryProbes << " binary.\n";
6315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer}
632e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek
633e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek//===----------------------------------------------------------------------===//
634e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek// Serialization.
635e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek//===----------------------------------------------------------------------===//
636099b4747042352f69184481a48508b599a8d3f73Ted Kremenek
637099b4747042352f69184481a48508b599a8d3f73Ted Kremenekvoid ContentCache::Emit(llvm::Serializer& S) const {
638e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek  S.FlushRecord();
639e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek  S.EmitPtr(this);
640e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek
64182dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek  if (Entry) {
64282dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek    llvm::sys::Path Fname(Buffer->getBufferIdentifier());
64382dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek
64482dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek    if (Fname.isAbsolute())
64582dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek      S.EmitCStr(Fname.c_str());
64682dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek    else {
64782dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek      // Create an absolute path.
64882dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek      // FIXME: This will potentially contain ".." and "." in the path.
64982dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek      llvm::sys::Path path = llvm::sys::Path::GetCurrentDirectory();
65082dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek      path.appendComponent(Fname.c_str());
65182dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek      S.EmitCStr(path.c_str());
65282dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek    }
65382dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek  }
654099b4747042352f69184481a48508b599a8d3f73Ted Kremenek  else {
655e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek    const char* p = Buffer->getBufferStart();
656e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek    const char* e = Buffer->getBufferEnd();
657e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek
658099b4747042352f69184481a48508b599a8d3f73Ted Kremenek    S.EmitInt(e-p);
659099b4747042352f69184481a48508b599a8d3f73Ted Kremenek
660e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek    for ( ; p != e; ++p)
661099b4747042352f69184481a48508b599a8d3f73Ted Kremenek      S.EmitInt(*p);
662099b4747042352f69184481a48508b599a8d3f73Ted Kremenek  }
663099b4747042352f69184481a48508b599a8d3f73Ted Kremenek
664099b4747042352f69184481a48508b599a8d3f73Ted Kremenek  S.FlushRecord();
665099b4747042352f69184481a48508b599a8d3f73Ted Kremenek}
666e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek
667099b4747042352f69184481a48508b599a8d3f73Ted Kremenekvoid ContentCache::ReadToSourceManager(llvm::Deserializer& D,
668099b4747042352f69184481a48508b599a8d3f73Ted Kremenek                                       SourceManager& SMgr,
669099b4747042352f69184481a48508b599a8d3f73Ted Kremenek                                       FileManager* FMgr,
670099b4747042352f69184481a48508b599a8d3f73Ted Kremenek                                       std::vector<char>& Buf) {
671099b4747042352f69184481a48508b599a8d3f73Ted Kremenek  if (FMgr) {
672099b4747042352f69184481a48508b599a8d3f73Ted Kremenek    llvm::SerializedPtrID PtrID = D.ReadPtrID();
673099b4747042352f69184481a48508b599a8d3f73Ted Kremenek    D.ReadCStr(Buf,false);
674099b4747042352f69184481a48508b599a8d3f73Ted Kremenek
675099b4747042352f69184481a48508b599a8d3f73Ted Kremenek    // Create/fetch the FileEntry.
676099b4747042352f69184481a48508b599a8d3f73Ted Kremenek    const char* start = &Buf[0];
677099b4747042352f69184481a48508b599a8d3f73Ted Kremenek    const FileEntry* E = FMgr->getFile(start,start+Buf.size());
678099b4747042352f69184481a48508b599a8d3f73Ted Kremenek
679db9c22917e411c924dae593d71e64fd616fd3a12Ted Kremenek    // FIXME: Ideally we want a lazy materialization of the ContentCache
680db9c22917e411c924dae593d71e64fd616fd3a12Ted Kremenek    //  anyway, because we don't want to read in source files unless this
681db9c22917e411c924dae593d71e64fd616fd3a12Ted Kremenek    //  is absolutely needed.
682db9c22917e411c924dae593d71e64fd616fd3a12Ted Kremenek    if (!E)
683db9c22917e411c924dae593d71e64fd616fd3a12Ted Kremenek      D.RegisterPtr(PtrID,NULL);
68448002c89578eaeb008a0bb5a10d8216e61906459Nico Weber    else
685db9c22917e411c924dae593d71e64fd616fd3a12Ted Kremenek      // Get the ContextCache object and register it with the deserializer.
686de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner      D.RegisterPtr(PtrID, SMgr.getOrCreateContentCache(E));
687de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    return;
688e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek  }
689de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
690de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // Register the ContextCache object with the deserializer.
6910d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  /* FIXME:
6920d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  ContentCache *Entry
693de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  SMgr.MemBufferInfos.push_back(ContentCache());
6940d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner   = const_cast<ContentCache&>(SMgr.MemBufferInfos.back());
695de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  D.RegisterPtr(&Entry);
696de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
697de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // Create the buffer.
698de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  unsigned Size = D.ReadInt();
699de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  Entry.Buffer = MemoryBuffer::getNewUninitMemBuffer(Size);
700de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner
701de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // Read the contents of the buffer.
702de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  char* p = const_cast<char*>(Entry.Buffer->getBufferStart());
703de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  for (unsigned i = 0; i < Size ; ++i)
704de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner    p[i] = D.ReadInt();
7050d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner   */
706e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek}
707e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek
708099b4747042352f69184481a48508b599a8d3f73Ted Kremenekvoid SourceManager::Emit(llvm::Serializer& S) const {
7091f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek  S.EnterBlock();
7101f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek  S.EmitPtr(this);
7112b2453a7d8fe732561795431f39ceb2b2a832d84Chris Lattner  S.EmitInt(MainFileID.getOpaqueValue());
7121f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek
713099b4747042352f69184481a48508b599a8d3f73Ted Kremenek  // Emit: FileInfos.  Just emit the file name.
714099b4747042352f69184481a48508b599a8d3f73Ted Kremenek  S.EnterBlock();
715099b4747042352f69184481a48508b599a8d3f73Ted Kremenek
7160d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  // FIXME: Emit FileInfos.
7170d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  //std::for_each(FileInfos.begin(), FileInfos.end(),
7180d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  //              S.MakeEmitter<ContentCache>());
719e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek
720099b4747042352f69184481a48508b599a8d3f73Ted Kremenek  S.ExitBlock();
721e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek
722099b4747042352f69184481a48508b599a8d3f73Ted Kremenek  // Emit: MemBufferInfos
723099b4747042352f69184481a48508b599a8d3f73Ted Kremenek  S.EnterBlock();
724099b4747042352f69184481a48508b599a8d3f73Ted Kremenek
7250d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  /* FIXME: EMIT.
726099b4747042352f69184481a48508b599a8d3f73Ted Kremenek  std::for_each(MemBufferInfos.begin(), MemBufferInfos.end(),
727099b4747042352f69184481a48508b599a8d3f73Ted Kremenek                S.MakeEmitter<ContentCache>());
7280d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner   */
729099b4747042352f69184481a48508b599a8d3f73Ted Kremenek
730099b4747042352f69184481a48508b599a8d3f73Ted Kremenek  S.ExitBlock();
731099b4747042352f69184481a48508b599a8d3f73Ted Kremenek
732de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // FIXME: Emit SLocEntryTable.
7331f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek
7341f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek  S.ExitBlock();
735e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek}
736099b4747042352f69184481a48508b599a8d3f73Ted Kremenek
7371f94100e53a7d45cea706c09ac0f35cf723a8d83Ted KremenekSourceManager*
7381f94100e53a7d45cea706c09ac0f35cf723a8d83Ted KremenekSourceManager::CreateAndRegister(llvm::Deserializer& D, FileManager& FMgr){
7391f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek  SourceManager *M = new SourceManager();
7401f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek  D.RegisterPtr(M);
7411f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek
74276edd0e4ae0592a7225d50d0bad6732ac64dca2aTed Kremenek  // Read: the FileID of the main source file of the translation unit.
743de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  M->MainFileID = FileID::get(D.ReadInt());
74476edd0e4ae0592a7225d50d0bad6732ac64dca2aTed Kremenek
745099b4747042352f69184481a48508b599a8d3f73Ted Kremenek  std::vector<char> Buf;
746099b4747042352f69184481a48508b599a8d3f73Ted Kremenek
7470d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  /*{ // FIXME Read: FileInfos.
748099b4747042352f69184481a48508b599a8d3f73Ted Kremenek    llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();
749099b4747042352f69184481a48508b599a8d3f73Ted Kremenek    while (!D.FinishedBlock(BLoc))
7501f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek    ContentCache::ReadToSourceManager(D,*M,&FMgr,Buf);
7510d0bf8cf58b35302312cc155287fde3e81eb25a7Chris Lattner  }*/
752099b4747042352f69184481a48508b599a8d3f73Ted Kremenek
753099b4747042352f69184481a48508b599a8d3f73Ted Kremenek  { // Read: MemBufferInfos.
754099b4747042352f69184481a48508b599a8d3f73Ted Kremenek    llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation();
755099b4747042352f69184481a48508b599a8d3f73Ted Kremenek    while (!D.FinishedBlock(BLoc))
7561f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek    ContentCache::ReadToSourceManager(D,*M,NULL,Buf);
757099b4747042352f69184481a48508b599a8d3f73Ted Kremenek  }
758099b4747042352f69184481a48508b599a8d3f73Ted Kremenek
759de7aeefc5573d669ed476d7bda7a8940d3bcadb7Chris Lattner  // FIXME: Read SLocEntryTable.
7601f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek
7611f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek  return M;
7621f2c7d110de6d3c568ab3841a31d76b9148393acTed Kremenek}
763