SourceManager.cpp revision 48002c89578eaeb008a0bb5a10d8216e61906459
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 2778d85f53b093867bbb0123f016956178eea7343eTed KremenekContentCache::~ContentCache() { 2878d85f53b093867bbb0123f016956178eea7343eTed Kremenek delete Buffer; 2978d85f53b093867bbb0123f016956178eea7343eTed Kremenek delete [] SourceLineCache; 305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 325f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getFileInfo - Create or return a cached FileInfo for the specified file. 335f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 3478d85f53b093867bbb0123f016956178eea7343eTed Kremenekconst ContentCache* SourceManager::getContentCache(const FileEntry *FileEnt) { 3578d85f53b093867bbb0123f016956178eea7343eTed Kremenek 365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer assert(FileEnt && "Didn't specify a file entry to use?"); 375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Do we already have information about this file? 3878d85f53b093867bbb0123f016956178eea7343eTed Kremenek std::set<ContentCache>::iterator I = 3978d85f53b093867bbb0123f016956178eea7343eTed Kremenek FileInfos.lower_bound(ContentCache(FileEnt)); 4078d85f53b093867bbb0123f016956178eea7343eTed Kremenek 4178d85f53b093867bbb0123f016956178eea7343eTed Kremenek if (I != FileInfos.end() && I->Entry == FileEnt) 425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &*I; 435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Nope, get information. 453c1f7b615c03e55f8aaee14a5793c917c050b373Chris Lattner const MemoryBuffer *File = 4635de512b9cb22a234a771b417507f71a2bbb5a94Chris Lattner MemoryBuffer::getFile(FileEnt->getName(), 0, FileEnt->getSize()); 475f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (File == 0) 485f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return 0; 495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 5078d85f53b093867bbb0123f016956178eea7343eTed Kremenek ContentCache& Entry = const_cast<ContentCache&>(*FileInfos.insert(I,FileEnt)); 515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 5278d85f53b093867bbb0123f016956178eea7343eTed Kremenek Entry.Buffer = File; 5378d85f53b093867bbb0123f016956178eea7343eTed Kremenek Entry.SourceLineCache = 0; 5478d85f53b093867bbb0123f016956178eea7343eTed Kremenek Entry.NumLines = 0; 555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return &Entry; 565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 59d1c0eee9aa30926839184b657b9e21be4a2ebdb8Ted Kremenek/// createMemBufferContentCache - Create a new ContentCache for the specified 60d1c0eee9aa30926839184b657b9e21be4a2ebdb8Ted Kremenek/// memory buffer. This does no caching. 6178d85f53b093867bbb0123f016956178eea7343eTed Kremenekconst ContentCache* 6278d85f53b093867bbb0123f016956178eea7343eTed KremenekSourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) { 630d892d8bfddd4916cc4f3467e1184a623d0716daTed Kremenek // Add a new ContentCache to the MemBufferInfos list and return it. We 640d892d8bfddd4916cc4f3467e1184a623d0716daTed Kremenek // must default construct the object first that the instance actually 650d892d8bfddd4916cc4f3467e1184a623d0716daTed Kremenek // stored within MemBufferInfos actually owns the Buffer, and not any 660d892d8bfddd4916cc4f3467e1184a623d0716daTed Kremenek // temporary we would use in the call to "push_back". 6778d85f53b093867bbb0123f016956178eea7343eTed Kremenek MemBufferInfos.push_back(ContentCache()); 6878d85f53b093867bbb0123f016956178eea7343eTed Kremenek ContentCache& Entry = const_cast<ContentCache&>(MemBufferInfos.back()); 6978d85f53b093867bbb0123f016956178eea7343eTed Kremenek Entry.Buffer = Buffer; 7078d85f53b093867bbb0123f016956178eea7343eTed Kremenek return &Entry; 715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 7448002c89578eaeb008a0bb5a10d8216e61906459Nico Weber/// createFileID - Create a new fileID for the specified ContentCache and 750d892d8bfddd4916cc4f3467e1184a623d0716daTed Kremenek/// include position. This works regardless of whether the ContentCache 760d892d8bfddd4916cc4f3467e1184a623d0716daTed Kremenek/// corresponds to a file or some other input source. 7778d85f53b093867bbb0123f016956178eea7343eTed Kremenekunsigned SourceManager::createFileID(const ContentCache *File, 787bfaaaecb3113f955db31e8d8a51acffd1bc0c27Nico Weber SourceLocation IncludePos, 790b9e736308af5397f558ffc8e780c438c2fdb563Chris Lattner SrcMgr::Characteristic_t FileCharacter) { 805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If FileEnt is really large (e.g. it's a large .i file), we may not be able 815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // to fit an arbitrary position in the file in the FilePos field. To handle 825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // this, we create one FileID for each chunk of the file that fits in a 835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // FilePos field. 8478d85f53b093867bbb0123f016956178eea7343eTed Kremenek unsigned FileSize = File->Buffer->getBufferSize(); 855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FileSize+1 < (1 << SourceLocation::FilePosBits)) { 860b9e736308af5397f558ffc8e780c438c2fdb563Chris Lattner FileIDs.push_back(FileIDInfo::get(IncludePos, 0, File, FileCharacter)); 875f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer assert(FileIDs.size() < (1 << SourceLocation::FileIDBits) && 885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer "Ran out of file ID's!"); 895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return FileIDs.size(); 905f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Create one FileID for each chunk of the file. 935f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unsigned Result = FileIDs.size()+1; 945f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 955f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unsigned ChunkNo = 0; 965f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer while (1) { 977bfaaaecb3113f955db31e8d8a51acffd1bc0c27Nico Weber FileIDs.push_back(FileIDInfo::get(IncludePos, ChunkNo++, File, 980b9e736308af5397f558ffc8e780c438c2fdb563Chris Lattner FileCharacter)); 995f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1005f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FileSize+1 < (1 << SourceLocation::FilePosBits)) break; 1015f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FileSize -= (1 << SourceLocation::FilePosBits); 1025f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 1035f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1045f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer assert(FileIDs.size() < (1 << SourceLocation::FileIDBits) && 1055f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer "Ran out of file ID's!"); 1065f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return Result; 1075f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1085f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1095f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getInstantiationLoc - Return a new SourceLocation that encodes the fact 1105f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// that a token from physloc PhysLoc should actually be referenced from 1115f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// InstantiationLoc. 11231bb8be680ee2facf7fbb3c6c87b9bbd20248328Chris LattnerSourceLocation SourceManager::getInstantiationLoc(SourceLocation PhysLoc, 1135f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer SourceLocation InstantLoc) { 114abca2bba54197256f2830f757218cfbea2ed9cd1Chris Lattner // The specified source location may be a mapped location, due to a macro 115abca2bba54197256f2830f757218cfbea2ed9cd1Chris Lattner // instantiation or #line directive. Strip off this information to find out 116abca2bba54197256f2830f757218cfbea2ed9cd1Chris Lattner // where the characters are actually located. 11731bb8be680ee2facf7fbb3c6c87b9bbd20248328Chris Lattner PhysLoc = getPhysicalLoc(PhysLoc); 1185f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1195f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Resolve InstantLoc down to a real logical location. 1205f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer InstantLoc = getLogicalLoc(InstantLoc); 1215f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 12231bb8be680ee2facf7fbb3c6c87b9bbd20248328Chris Lattner 12331bb8be680ee2facf7fbb3c6c87b9bbd20248328Chris Lattner // If the last macro id is close to the currently requested location, try to 124991ae518e915bbdef5710b2965adee032a04f5a5Chris Lattner // reuse it. This implements a small cache. 125991ae518e915bbdef5710b2965adee032a04f5a5Chris Lattner for (int i = MacroIDs.size()-1, e = MacroIDs.size()-6; i >= 0 && i != e; --i){ 126991ae518e915bbdef5710b2965adee032a04f5a5Chris Lattner MacroIDInfo &LastOne = MacroIDs[i]; 127d1623a81992a24abbfcd5520b32a0dd90857b8a8Chris Lattner 128991ae518e915bbdef5710b2965adee032a04f5a5Chris Lattner // The instanitation point and source physloc have to exactly match to reuse 129991ae518e915bbdef5710b2965adee032a04f5a5Chris Lattner // (for now). We could allow "nearby" instantiations in the future. 13018807d2bfb9282a35b921b4feeda09ffaa110e6bChris Lattner if (LastOne.getVirtualLoc() != InstantLoc || 131991ae518e915bbdef5710b2965adee032a04f5a5Chris Lattner LastOne.getPhysicalLoc().getFileID() != PhysLoc.getFileID()) 132991ae518e915bbdef5710b2965adee032a04f5a5Chris Lattner continue; 133991ae518e915bbdef5710b2965adee032a04f5a5Chris Lattner 134991ae518e915bbdef5710b2965adee032a04f5a5Chris Lattner // Check to see if the physloc of the token came from near enough to reuse. 135991ae518e915bbdef5710b2965adee032a04f5a5Chris Lattner int PhysDelta = PhysLoc.getRawFilePos() - 136991ae518e915bbdef5710b2965adee032a04f5a5Chris Lattner LastOne.getPhysicalLoc().getRawFilePos(); 137991ae518e915bbdef5710b2965adee032a04f5a5Chris Lattner if (SourceLocation::isValidMacroPhysOffs(PhysDelta)) 138f8484542bbd9f3445b22fe8d240a1eac790cd8caChris Lattner return SourceLocation::getMacroLoc(i, PhysDelta); 13931bb8be680ee2facf7fbb3c6c87b9bbd20248328Chris Lattner } 14031bb8be680ee2facf7fbb3c6c87b9bbd20248328Chris Lattner 14145011cf25e756477766231373111aa80b607ebedChris Lattner 1429dc1f530c086d2c16f8cba758b0f59a5bf41323aChris Lattner MacroIDs.push_back(MacroIDInfo::get(InstantLoc, PhysLoc)); 143f8484542bbd9f3445b22fe8d240a1eac790cd8caChris Lattner return SourceLocation::getMacroLoc(MacroIDs.size()-1, 0); 1445f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1468a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner/// getBufferData - Return a pointer to the start and end of the character 1478a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner/// data for the specified FileID. 1488a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattnerstd::pair<const char*, const char*> 1498a12c2777cccdf629b89745b6ecc89a8c1641e4eChris LattnerSourceManager::getBufferData(unsigned FileID) const { 1508a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner const llvm::MemoryBuffer *Buf = getBuffer(FileID); 1518a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner return std::make_pair(Buf->getBufferStart(), Buf->getBufferEnd()); 1528a12c2777cccdf629b89745b6ecc89a8c1641e4eChris Lattner} 1535f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1545f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1555f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getCharacterData - Return a pointer to the start of the specified location 1565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// in the appropriate MemoryBuffer. 1575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerconst char *SourceManager::getCharacterData(SourceLocation SL) const { 1585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Note that this is a hot function in the getSpelling() path, which is 1595f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // heavily used by -E mode. 1609dc1f530c086d2c16f8cba758b0f59a5bf41323aChris Lattner SL = getPhysicalLoc(SL); 1615f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 16278d85f53b093867bbb0123f016956178eea7343eTed Kremenek return getContentCache(SL.getFileID())->Buffer->getBufferStart() + 1639dc1f530c086d2c16f8cba758b0f59a5bf41323aChris Lattner getFullFilePos(SL); 1645f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1655f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1665f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1679dc1f530c086d2c16f8cba758b0f59a5bf41323aChris Lattner/// getColumnNumber - Return the column # for the specified file position. 1685f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// this is significantly cheaper to compute than the line number. This returns 1695f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// zero if the column number isn't known. 1705f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerunsigned SourceManager::getColumnNumber(SourceLocation Loc) const { 1715f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unsigned FileID = Loc.getFileID(); 1725f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FileID == 0) return 0; 1735f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1749dc1f530c086d2c16f8cba758b0f59a5bf41323aChris Lattner unsigned FilePos = getFullFilePos(Loc); 1755f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const MemoryBuffer *Buffer = getBuffer(FileID); 1765f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer const char *Buf = Buffer->getBufferStart(); 1775f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1785f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unsigned LineStart = FilePos; 1795f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r') 1805f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer --LineStart; 1815f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer return FilePos-LineStart+1; 1825f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1835f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 1845f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getSourceName - This method returns the name of the file or buffer that 1855f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// the SourceLocation specifies. This can be modified with #line directives, 1865f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// etc. 1878b6ca8866f09fd8e018a329a0749d2dcf11b146aChris Lattnerconst char *SourceManager::getSourceName(SourceLocation Loc) const { 1885f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unsigned FileID = Loc.getFileID(); 1895f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FileID == 0) return ""; 19078d85f53b093867bbb0123f016956178eea7343eTed Kremenek return getContentCache(FileID)->Buffer->getBufferIdentifier(); 1915f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 1925f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 19378d85f53b093867bbb0123f016956178eea7343eTed Kremenekstatic void ComputeLineNumbers(ContentCache* FI) DISABLE_INLINE; 19478d85f53b093867bbb0123f016956178eea7343eTed Kremenekstatic void ComputeLineNumbers(ContentCache* FI) { 1955e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner const MemoryBuffer *Buffer = FI->Buffer; 1965e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner 1975e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner // Find the file offsets of all of the *physical* source lines. This does 1985e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner // not look at trigraphs, escaped newlines, or anything else tricky. 1995e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner std::vector<unsigned> LineOffsets; 2005e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner 2015e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner // Line #1 starts at char 0. 2025e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner LineOffsets.push_back(0); 2035e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner 2045e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner const unsigned char *Buf = (const unsigned char *)Buffer->getBufferStart(); 2055e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner const unsigned char *End = (const unsigned char *)Buffer->getBufferEnd(); 2065e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner unsigned Offs = 0; 2075e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner while (1) { 2085e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner // Skip over the contents of the line. 2095e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner // TODO: Vectorize this? This is very performance sensitive for programs 2105e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner // with lots of diagnostics and in -E mode. 2115e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner const unsigned char *NextBuf = (const unsigned char *)Buf; 2125e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner while (*NextBuf != '\n' && *NextBuf != '\r' && *NextBuf != '\0') 2135e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner ++NextBuf; 2145e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner Offs += NextBuf-Buf; 2155e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner Buf = NextBuf; 2165e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner 2175e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner if (Buf[0] == '\n' || Buf[0] == '\r') { 2185e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner // If this is \n\r or \r\n, skip both characters. 2195e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner if ((Buf[1] == '\n' || Buf[1] == '\r') && Buf[0] != Buf[1]) 2205e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner ++Offs, ++Buf; 2215e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner ++Offs, ++Buf; 2225e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner LineOffsets.push_back(Offs); 2235e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner } else { 2245e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner // Otherwise, this is a null. If end of file, exit. 2255e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner if (Buf == End) break; 2265e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner // Otherwise, skip the null. 2275e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner ++Offs, ++Buf; 2285e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner } 2295e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner } 2305e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner 2315e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner // Copy the offsets into the FileInfo structure. 2325e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner FI->NumLines = LineOffsets.size(); 2335e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner FI->SourceLineCache = new unsigned[LineOffsets.size()]; 2345e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner std::copy(LineOffsets.begin(), LineOffsets.end(), FI->SourceLineCache); 2355e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner} 2365f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2375f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// getLineNumber - Given a SourceLocation, return the physical line number 2385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// for the position indicated. This requires building and caching a table of 2395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// line offsets for the MemoryBuffer, so this is not cheap: use only when 2405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// about to emit a diagnostic. 2415f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencerunsigned SourceManager::getLineNumber(SourceLocation Loc) { 2425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unsigned FileID = Loc.getFileID(); 2435f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer if (FileID == 0) return 0; 24478d85f53b093867bbb0123f016956178eea7343eTed Kremenek 24578d85f53b093867bbb0123f016956178eea7343eTed Kremenek ContentCache* Content; 2465e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner 2475e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner if (LastLineNoFileIDQuery == FileID) 24878d85f53b093867bbb0123f016956178eea7343eTed Kremenek Content = LastLineNoContentCache; 2495e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner else 25078d85f53b093867bbb0123f016956178eea7343eTed Kremenek Content = const_cast<ContentCache*>(getContentCache(FileID)); 2515f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2525f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // If this is the first use of line information for this buffer, compute the 2535e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner /// SourceLineCache for it on demand. 25478d85f53b093867bbb0123f016956178eea7343eTed Kremenek if (Content->SourceLineCache == 0) 25578d85f53b093867bbb0123f016956178eea7343eTed Kremenek ComputeLineNumbers(Content); 2565f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 2575f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // Okay, we know we have a line number table. Do a binary search to find the 2585f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer // line number that this character position lands on. 25978d85f53b093867bbb0123f016956178eea7343eTed Kremenek unsigned *SourceLineCache = Content->SourceLineCache; 2605e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner unsigned *SourceLineCacheStart = SourceLineCache; 26178d85f53b093867bbb0123f016956178eea7343eTed Kremenek unsigned *SourceLineCacheEnd = SourceLineCache + Content->NumLines; 2625e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner 2635e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner unsigned QueriedFilePos = getFullFilePos(Loc)+1; 2645e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner 2655e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner // If the previous query was to the same file, we know both the file pos from 2665e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner // that query and the line number returned. This allows us to narrow the 2675e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner // search space from the entire file to something near the match. 2685e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner if (LastLineNoFileIDQuery == FileID) { 2695e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner if (QueriedFilePos >= LastLineNoFilePos) { 2705e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner SourceLineCache = SourceLineCache+LastLineNoResult-1; 2715e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner 2725e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner // The query is likely to be nearby the previous one. Here we check to 2735e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner // see if it is within 5, 10 or 20 lines. It can be far away in cases 2745e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner // where big comment blocks and vertical whitespace eat up lines but 2755e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner // contribute no tokens. 2765e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner if (SourceLineCache+5 < SourceLineCacheEnd) { 2775e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner if (SourceLineCache[5] > QueriedFilePos) 2785e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner SourceLineCacheEnd = SourceLineCache+5; 2795e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner else if (SourceLineCache+10 < SourceLineCacheEnd) { 2805e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner if (SourceLineCache[10] > QueriedFilePos) 2815e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner SourceLineCacheEnd = SourceLineCache+10; 2825e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner else if (SourceLineCache+20 < SourceLineCacheEnd) { 2835e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner if (SourceLineCache[20] > QueriedFilePos) 2845e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner SourceLineCacheEnd = SourceLineCache+20; 2855e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner } 2865e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner } 2875e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner } 2885e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner } else { 2895e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner SourceLineCacheEnd = SourceLineCache+LastLineNoResult+1; 2905e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner } 2915e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner } 2925e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner 2931cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner // If the spread is large, do a "radix" test as our initial guess, based on 2941cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner // the assumption that lines average to approximately the same length. 2951cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner // NOTE: This is currently disabled, as it does not appear to be profitable in 2961cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner // initial measurements. 2971cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner if (0 && SourceLineCacheEnd-SourceLineCache > 20) { 29878d85f53b093867bbb0123f016956178eea7343eTed Kremenek unsigned FileLen = Content->SourceLineCache[Content->NumLines-1]; 2991cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner 3001cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner // Take a stab at guessing where it is. 30178d85f53b093867bbb0123f016956178eea7343eTed Kremenek unsigned ApproxPos = Content->NumLines*QueriedFilePos / FileLen; 3021cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner 3031cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner // Check for -10 and +10 lines. 3041cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner unsigned LowerBound = std::max(int(ApproxPos-10), 0); 3051cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner unsigned UpperBound = std::min(ApproxPos+10, FileLen); 3061cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner 3071cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner // If the computed lower bound is less than the query location, move it in. 3081cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner if (SourceLineCache < SourceLineCacheStart+LowerBound && 3091cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner SourceLineCacheStart[LowerBound] < QueriedFilePos) 3101cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner SourceLineCache = SourceLineCacheStart+LowerBound; 3111cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner 3121cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner // If the computed upper bound is greater than the query location, move it. 3131cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner if (SourceLineCacheEnd > SourceLineCacheStart+UpperBound && 3141cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner SourceLineCacheStart[UpperBound] >= QueriedFilePos) 3151cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner SourceLineCacheEnd = SourceLineCacheStart+UpperBound; 3161cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner } 3171cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner 3181cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner unsigned *Pos 3191cf12bfa80825cce46be35a0a2b54f281b0b51dbChris Lattner = std::lower_bound(SourceLineCache, SourceLineCacheEnd, QueriedFilePos); 3205e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner unsigned LineNo = Pos-SourceLineCacheStart; 3215e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner 3225e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner LastLineNoFileIDQuery = FileID; 32378d85f53b093867bbb0123f016956178eea7343eTed Kremenek LastLineNoContentCache = Content; 3245e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner LastLineNoFilePos = QueriedFilePos; 3255e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner LastLineNoResult = LineNo; 3265e36a7a89da5d69ece23fc8228624a053f75c645Chris Lattner return LineNo; 3275f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 3285f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3295f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// PrintStats - Print statistics to stderr. 3305f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer/// 3315f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencervoid SourceManager::PrintStats() const { 332665dd4a40e0e38657f7bf26c2e3490304e5c7510Ted Kremenek llvm::cerr << "\n*** Source Manager Stats:\n"; 333665dd4a40e0e38657f7bf26c2e3490304e5c7510Ted Kremenek llvm::cerr << FileInfos.size() << " files mapped, " << MemBufferInfos.size() 334665dd4a40e0e38657f7bf26c2e3490304e5c7510Ted Kremenek << " mem buffers mapped, " << FileIDs.size() 335665dd4a40e0e38657f7bf26c2e3490304e5c7510Ted Kremenek << " file ID's allocated.\n"; 336665dd4a40e0e38657f7bf26c2e3490304e5c7510Ted Kremenek llvm::cerr << " " << FileIDs.size() << " normal buffer FileID's, " 337665dd4a40e0e38657f7bf26c2e3490304e5c7510Ted Kremenek << MacroIDs.size() << " macro expansion FileID's.\n"; 3385f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer 3395f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unsigned NumLineNumsComputed = 0; 3405f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer unsigned NumFileBytesMapped = 0; 34178d85f53b093867bbb0123f016956178eea7343eTed Kremenek for (std::set<ContentCache>::const_iterator I = 3425f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer FileInfos.begin(), E = FileInfos.end(); I != E; ++I) { 34378d85f53b093867bbb0123f016956178eea7343eTed Kremenek NumLineNumsComputed += I->SourceLineCache != 0; 34478d85f53b093867bbb0123f016956178eea7343eTed Kremenek NumFileBytesMapped += I->Buffer->getBufferSize(); 3455f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer } 34678d85f53b093867bbb0123f016956178eea7343eTed Kremenek 347665dd4a40e0e38657f7bf26c2e3490304e5c7510Ted Kremenek llvm::cerr << NumFileBytesMapped << " bytes of files mapped, " 348665dd4a40e0e38657f7bf26c2e3490304e5c7510Ted Kremenek << NumLineNumsComputed << " files with line #'s computed.\n"; 3495f016e2cb5d11daeb237544de1c5d59f20fe1a6eReid Spencer} 350e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek 351e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek//===----------------------------------------------------------------------===// 352e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek// Serialization. 353e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek//===----------------------------------------------------------------------===// 354099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 355099b4747042352f69184481a48508b599a8d3f73Ted Kremenekvoid ContentCache::Emit(llvm::Serializer& S) const { 356e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek S.FlushRecord(); 357e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek S.EmitPtr(this); 358e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek 35982dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek if (Entry) { 36082dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek llvm::sys::Path Fname(Buffer->getBufferIdentifier()); 36182dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek 36282dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek if (Fname.isAbsolute()) 36382dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek S.EmitCStr(Fname.c_str()); 36482dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek else { 36582dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek // Create an absolute path. 36682dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek // FIXME: This will potentially contain ".." and "." in the path. 36782dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek llvm::sys::Path path = llvm::sys::Path::GetCurrentDirectory(); 36882dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek path.appendComponent(Fname.c_str()); 36982dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek S.EmitCStr(path.c_str()); 37082dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek } 37182dfaf7c0ccbbde43f701b12367dbf22265dcb4eTed Kremenek } 372099b4747042352f69184481a48508b599a8d3f73Ted Kremenek else { 373e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek const char* p = Buffer->getBufferStart(); 374e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek const char* e = Buffer->getBufferEnd(); 375e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek 376099b4747042352f69184481a48508b599a8d3f73Ted Kremenek S.EmitInt(e-p); 377099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 378e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek for ( ; p != e; ++p) 379099b4747042352f69184481a48508b599a8d3f73Ted Kremenek S.EmitInt(*p); 380099b4747042352f69184481a48508b599a8d3f73Ted Kremenek } 381099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 382099b4747042352f69184481a48508b599a8d3f73Ted Kremenek S.FlushRecord(); 383099b4747042352f69184481a48508b599a8d3f73Ted Kremenek} 384e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek 385099b4747042352f69184481a48508b599a8d3f73Ted Kremenekvoid ContentCache::ReadToSourceManager(llvm::Deserializer& D, 386099b4747042352f69184481a48508b599a8d3f73Ted Kremenek SourceManager& SMgr, 387099b4747042352f69184481a48508b599a8d3f73Ted Kremenek FileManager* FMgr, 388099b4747042352f69184481a48508b599a8d3f73Ted Kremenek std::vector<char>& Buf) { 389099b4747042352f69184481a48508b599a8d3f73Ted Kremenek if (FMgr) { 390099b4747042352f69184481a48508b599a8d3f73Ted Kremenek llvm::SerializedPtrID PtrID = D.ReadPtrID(); 391099b4747042352f69184481a48508b599a8d3f73Ted Kremenek D.ReadCStr(Buf,false); 392099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 393099b4747042352f69184481a48508b599a8d3f73Ted Kremenek // Create/fetch the FileEntry. 394099b4747042352f69184481a48508b599a8d3f73Ted Kremenek const char* start = &Buf[0]; 395099b4747042352f69184481a48508b599a8d3f73Ted Kremenek const FileEntry* E = FMgr->getFile(start,start+Buf.size()); 396099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 397db9c22917e411c924dae593d71e64fd616fd3a12Ted Kremenek // FIXME: Ideally we want a lazy materialization of the ContentCache 398db9c22917e411c924dae593d71e64fd616fd3a12Ted Kremenek // anyway, because we don't want to read in source files unless this 399db9c22917e411c924dae593d71e64fd616fd3a12Ted Kremenek // is absolutely needed. 400db9c22917e411c924dae593d71e64fd616fd3a12Ted Kremenek if (!E) 401db9c22917e411c924dae593d71e64fd616fd3a12Ted Kremenek D.RegisterPtr(PtrID,NULL); 40248002c89578eaeb008a0bb5a10d8216e61906459Nico Weber else 403db9c22917e411c924dae593d71e64fd616fd3a12Ted Kremenek // Get the ContextCache object and register it with the deserializer. 404db9c22917e411c924dae593d71e64fd616fd3a12Ted Kremenek D.RegisterPtr(PtrID,SMgr.getContentCache(E)); 405e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek } 406099b4747042352f69184481a48508b599a8d3f73Ted Kremenek else { 407099b4747042352f69184481a48508b599a8d3f73Ted Kremenek // Register the ContextCache object with the deserializer. 408099b4747042352f69184481a48508b599a8d3f73Ted Kremenek SMgr.MemBufferInfos.push_back(ContentCache()); 40948002c89578eaeb008a0bb5a10d8216e61906459Nico Weber ContentCache& Entry = const_cast<ContentCache&>(SMgr.MemBufferInfos.back()); 410099b4747042352f69184481a48508b599a8d3f73Ted Kremenek D.RegisterPtr(&Entry); 411099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 412099b4747042352f69184481a48508b599a8d3f73Ted Kremenek // Create the buffer. 413099b4747042352f69184481a48508b599a8d3f73Ted Kremenek unsigned Size = D.ReadInt(); 414099b4747042352f69184481a48508b599a8d3f73Ted Kremenek Entry.Buffer = MemoryBuffer::getNewUninitMemBuffer(Size); 415099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 416099b4747042352f69184481a48508b599a8d3f73Ted Kremenek // Read the contents of the buffer. 417099b4747042352f69184481a48508b599a8d3f73Ted Kremenek char* p = const_cast<char*>(Entry.Buffer->getBufferStart()); 418099b4747042352f69184481a48508b599a8d3f73Ted Kremenek for (unsigned i = 0; i < Size ; ++i) 419099b4747042352f69184481a48508b599a8d3f73Ted Kremenek p[i] = D.ReadInt(); 420099b4747042352f69184481a48508b599a8d3f73Ted Kremenek } 421099b4747042352f69184481a48508b599a8d3f73Ted Kremenek} 422099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 423099b4747042352f69184481a48508b599a8d3f73Ted Kremenekvoid FileIDInfo::Emit(llvm::Serializer& S) const { 424099b4747042352f69184481a48508b599a8d3f73Ted Kremenek S.Emit(IncludeLoc); 425099b4747042352f69184481a48508b599a8d3f73Ted Kremenek S.EmitInt(ChunkNo); 426099b4747042352f69184481a48508b599a8d3f73Ted Kremenek S.EmitPtr(Content); 427099b4747042352f69184481a48508b599a8d3f73Ted Kremenek} 428099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 429099b4747042352f69184481a48508b599a8d3f73Ted KremenekFileIDInfo FileIDInfo::ReadVal(llvm::Deserializer& D) { 430099b4747042352f69184481a48508b599a8d3f73Ted Kremenek FileIDInfo I; 431099b4747042352f69184481a48508b599a8d3f73Ted Kremenek I.IncludeLoc = SourceLocation::ReadVal(D); 432099b4747042352f69184481a48508b599a8d3f73Ted Kremenek I.ChunkNo = D.ReadInt(); 433099b4747042352f69184481a48508b599a8d3f73Ted Kremenek D.ReadPtr(I.Content,false); 434099b4747042352f69184481a48508b599a8d3f73Ted Kremenek return I; 435099b4747042352f69184481a48508b599a8d3f73Ted Kremenek} 436099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 437099b4747042352f69184481a48508b599a8d3f73Ted Kremenekvoid MacroIDInfo::Emit(llvm::Serializer& S) const { 438099b4747042352f69184481a48508b599a8d3f73Ted Kremenek S.Emit(VirtualLoc); 439099b4747042352f69184481a48508b599a8d3f73Ted Kremenek S.Emit(PhysicalLoc); 440099b4747042352f69184481a48508b599a8d3f73Ted Kremenek} 441099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 442099b4747042352f69184481a48508b599a8d3f73Ted KremenekMacroIDInfo MacroIDInfo::ReadVal(llvm::Deserializer& D) { 443099b4747042352f69184481a48508b599a8d3f73Ted Kremenek MacroIDInfo I; 444099b4747042352f69184481a48508b599a8d3f73Ted Kremenek I.VirtualLoc = SourceLocation::ReadVal(D); 445099b4747042352f69184481a48508b599a8d3f73Ted Kremenek I.PhysicalLoc = SourceLocation::ReadVal(D); 446099b4747042352f69184481a48508b599a8d3f73Ted Kremenek return I; 447e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek} 448e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek 449099b4747042352f69184481a48508b599a8d3f73Ted Kremenekvoid SourceManager::Emit(llvm::Serializer& S) const { 4501f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek S.EnterBlock(); 4511f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek S.EmitPtr(this); 45276edd0e4ae0592a7225d50d0bad6732ac64dca2aTed Kremenek S.EmitInt(MainFileID); 4531f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek 454099b4747042352f69184481a48508b599a8d3f73Ted Kremenek // Emit: FileInfos. Just emit the file name. 455099b4747042352f69184481a48508b599a8d3f73Ted Kremenek S.EnterBlock(); 456099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 457099b4747042352f69184481a48508b599a8d3f73Ted Kremenek std::for_each(FileInfos.begin(),FileInfos.end(), 458099b4747042352f69184481a48508b599a8d3f73Ted Kremenek S.MakeEmitter<ContentCache>()); 459e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek 460099b4747042352f69184481a48508b599a8d3f73Ted Kremenek S.ExitBlock(); 461e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek 462099b4747042352f69184481a48508b599a8d3f73Ted Kremenek // Emit: MemBufferInfos 463099b4747042352f69184481a48508b599a8d3f73Ted Kremenek S.EnterBlock(); 464099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 465099b4747042352f69184481a48508b599a8d3f73Ted Kremenek std::for_each(MemBufferInfos.begin(), MemBufferInfos.end(), 466099b4747042352f69184481a48508b599a8d3f73Ted Kremenek S.MakeEmitter<ContentCache>()); 467099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 468099b4747042352f69184481a48508b599a8d3f73Ted Kremenek S.ExitBlock(); 469099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 47048002c89578eaeb008a0bb5a10d8216e61906459Nico Weber // Emit: FileIDs 471099b4747042352f69184481a48508b599a8d3f73Ted Kremenek S.EmitInt(FileIDs.size()); 472099b4747042352f69184481a48508b599a8d3f73Ted Kremenek std::for_each(FileIDs.begin(), FileIDs.end(), S.MakeEmitter<FileIDInfo>()); 473099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 474099b4747042352f69184481a48508b599a8d3f73Ted Kremenek // Emit: MacroIDs 475099b4747042352f69184481a48508b599a8d3f73Ted Kremenek S.EmitInt(MacroIDs.size()); 476099b4747042352f69184481a48508b599a8d3f73Ted Kremenek std::for_each(MacroIDs.begin(), MacroIDs.end(), S.MakeEmitter<MacroIDInfo>()); 4771f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek 4781f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek S.ExitBlock(); 479e21272fbdbfbf5bf3461d3e9b42279f4d47caa42Ted Kremenek} 480099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 4811f94100e53a7d45cea706c09ac0f35cf723a8d83Ted KremenekSourceManager* 4821f94100e53a7d45cea706c09ac0f35cf723a8d83Ted KremenekSourceManager::CreateAndRegister(llvm::Deserializer& D, FileManager& FMgr){ 4831f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek SourceManager *M = new SourceManager(); 4841f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek D.RegisterPtr(M); 4851f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek 48676edd0e4ae0592a7225d50d0bad6732ac64dca2aTed Kremenek // Read: the FileID of the main source file of the translation unit. 48776edd0e4ae0592a7225d50d0bad6732ac64dca2aTed Kremenek M->MainFileID = D.ReadInt(); 48876edd0e4ae0592a7225d50d0bad6732ac64dca2aTed Kremenek 489099b4747042352f69184481a48508b599a8d3f73Ted Kremenek std::vector<char> Buf; 490099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 491099b4747042352f69184481a48508b599a8d3f73Ted Kremenek { // Read: FileInfos. 492099b4747042352f69184481a48508b599a8d3f73Ted Kremenek llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation(); 493099b4747042352f69184481a48508b599a8d3f73Ted Kremenek while (!D.FinishedBlock(BLoc)) 4941f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek ContentCache::ReadToSourceManager(D,*M,&FMgr,Buf); 495099b4747042352f69184481a48508b599a8d3f73Ted Kremenek } 496099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 497099b4747042352f69184481a48508b599a8d3f73Ted Kremenek { // Read: MemBufferInfos. 498099b4747042352f69184481a48508b599a8d3f73Ted Kremenek llvm::Deserializer::Location BLoc = D.getCurrentBlockLocation(); 499099b4747042352f69184481a48508b599a8d3f73Ted Kremenek while (!D.FinishedBlock(BLoc)) 5001f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek ContentCache::ReadToSourceManager(D,*M,NULL,Buf); 501099b4747042352f69184481a48508b599a8d3f73Ted Kremenek } 502099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 503099b4747042352f69184481a48508b599a8d3f73Ted Kremenek // Read: FileIDs. 504099b4747042352f69184481a48508b599a8d3f73Ted Kremenek unsigned Size = D.ReadInt(); 5051f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek M->FileIDs.reserve(Size); 506099b4747042352f69184481a48508b599a8d3f73Ted Kremenek for (; Size > 0 ; --Size) 5071f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek M->FileIDs.push_back(FileIDInfo::ReadVal(D)); 508099b4747042352f69184481a48508b599a8d3f73Ted Kremenek 509099b4747042352f69184481a48508b599a8d3f73Ted Kremenek // Read: MacroIDs. 510099b4747042352f69184481a48508b599a8d3f73Ted Kremenek Size = D.ReadInt(); 5111f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek M->MacroIDs.reserve(Size); 512099b4747042352f69184481a48508b599a8d3f73Ted Kremenek for (; Size > 0 ; --Size) 5131f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek M->MacroIDs.push_back(MacroIDInfo::ReadVal(D)); 5141f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek 5151f94100e53a7d45cea706c09ac0f35cf723a8d83Ted Kremenek return M; 5161f2c7d110de6d3c568ab3841a31d76b9148393acTed Kremenek} 517