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