diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp | 144 |
1 files changed, 124 insertions, 20 deletions
diff --git a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp index 364663e..cef091c 100644 --- a/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp +++ b/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp @@ -71,7 +71,11 @@ unsigned ContentCache::getSize() const { void ContentCache::replaceBuffer(const llvm::MemoryBuffer *B, bool DoNotFree) { - assert(B != Buffer.getPointer()); + if (B == Buffer.getPointer()) { + assert(0 && "Replacing with the same buffer"); + Buffer.setInt(DoNotFree? DoNotFreeFlag : 0); + return; + } if (shouldFreeBuffer()) delete Buffer.getPointer(); @@ -366,7 +370,8 @@ LineTableInfo &SourceManager::getLineTable() { SourceManager::SourceManager(DiagnosticsEngine &Diag, FileManager &FileMgr) : Diag(Diag), FileMgr(FileMgr), OverridenFilesKeepOriginalName(true), ExternalSLocEntries(0), LineTable(0), NumLinearScans(0), - NumBinaryProbes(0), FakeBufferForRecovery(0) { + NumBinaryProbes(0), FakeBufferForRecovery(0), + FakeContentCacheForRecovery(0) { clearIDTables(); Diag.setSourceManager(this); } @@ -378,16 +383,21 @@ SourceManager::~SourceManager() { // content cache objects are bump pointer allocated, we just have to run the // dtors, but we call the deallocate method for completeness. for (unsigned i = 0, e = MemBufferInfos.size(); i != e; ++i) { - MemBufferInfos[i]->~ContentCache(); - ContentCacheAlloc.Deallocate(MemBufferInfos[i]); + if (MemBufferInfos[i]) { + MemBufferInfos[i]->~ContentCache(); + ContentCacheAlloc.Deallocate(MemBufferInfos[i]); + } } for (llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*>::iterator I = FileInfos.begin(), E = FileInfos.end(); I != E; ++I) { - I->second->~ContentCache(); - ContentCacheAlloc.Deallocate(I->second); + if (I->second) { + I->second->~ContentCache(); + ContentCacheAlloc.Deallocate(I->second); + } } delete FakeBufferForRecovery; + delete FakeContentCacheForRecovery; for (llvm::DenseMap<FileID, MacroArgsMap *>::iterator I = MacroArgsCacheMap.begin(),E = MacroArgsCacheMap.end(); I!=E; ++I) { @@ -461,6 +471,25 @@ SourceManager::createMemBufferContentCache(const MemoryBuffer *Buffer) { return Entry; } +const SrcMgr::SLocEntry &SourceManager::loadSLocEntry(unsigned Index, + bool *Invalid) const { + assert(!SLocEntryLoaded[Index]); + if (ExternalSLocEntries->ReadSLocEntry(-(static_cast<int>(Index) + 2))) { + if (Invalid) + *Invalid = true; + // If the file of the SLocEntry changed we could still have loaded it. + if (!SLocEntryLoaded[Index]) { + // Try to recover; create a SLocEntry so the rest of clang can handle it. + LoadedSLocEntryTable[Index] = SLocEntry::get(0, + FileInfo::get(SourceLocation(), + getFakeContentCacheForRecovery(), + SrcMgr::C_User)); + } + } + + return LoadedSLocEntryTable[Index]; +} + std::pair<int, unsigned> SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries, unsigned TotalSize) { @@ -483,6 +512,18 @@ const llvm::MemoryBuffer *SourceManager::getFakeBufferForRecovery() const { return FakeBufferForRecovery; } +/// \brief As part of recovering from missing or changed content, produce a +/// fake content cache. +const SrcMgr::ContentCache * +SourceManager::getFakeContentCacheForRecovery() const { + if (!FakeContentCacheForRecovery) { + FakeContentCacheForRecovery = new ContentCache(); + FakeContentCacheForRecovery->replaceBuffer(getFakeBufferForRecovery(), + /*DoNotFree=*/true); + } + return FakeContentCacheForRecovery; +} + //===----------------------------------------------------------------------===// // Methods to create new FileID's and macro expansions. //===----------------------------------------------------------------------===// @@ -580,6 +621,7 @@ void SourceManager::overrideFileContents(const FileEntry *SourceFile, assert(IR && "getOrCreateContentCache() cannot return NULL"); const_cast<SrcMgr::ContentCache *>(IR)->replaceBuffer(Buffer, DoNotFree); + const_cast<SrcMgr::ContentCache *>(IR)->BufferOverridden = true; } void SourceManager::overrideFileContents(const FileEntry *SourceFile, @@ -730,11 +772,11 @@ FileID SourceManager::getFileIDLocal(unsigned SLocOffset) const { /// This function knows that the SourceLocation is in a loaded buffer, not a /// local one. FileID SourceManager::getFileIDLoaded(unsigned SLocOffset) const { - assert(SLocOffset >= CurrentLoadedOffset && "Bad function choice"); - // Sanity checking, otherwise a bug may lead to hanging in release build. - if (SLocOffset < CurrentLoadedOffset) + if (SLocOffset < CurrentLoadedOffset) { + assert(0 && "Invalid SLocOffset or bad function choice"); return FileID(); + } // Essentially the same as the local case, but the loaded array is sorted // in the other direction. @@ -946,13 +988,20 @@ const char *SourceManager::getCharacterData(SourceLocation SL, unsigned SourceManager::getColumnNumber(FileID FID, unsigned FilePos, bool *Invalid) const { bool MyInvalid = false; - const char *Buf = getBuffer(FID, &MyInvalid)->getBufferStart(); + const llvm::MemoryBuffer *MemBuf = getBuffer(FID, &MyInvalid); if (Invalid) *Invalid = MyInvalid; if (MyInvalid) return 1; + if (FilePos >= MemBuf->getBufferSize()) { + if (Invalid) + *Invalid = MyInvalid; + return 1; + } + + const char *Buf = MemBuf->getBufferStart(); unsigned LineStart = FilePos; while (LineStart && Buf[LineStart-1] != '\n' && Buf[LineStart-1] != '\r') --LineStart; @@ -988,6 +1037,10 @@ unsigned SourceManager::getPresumedColumnNumber(SourceLocation Loc, return getPresumedLoc(Loc).getColumn(); } +#ifdef __SSE2__ +#include <emmintrin.h> +#endif + static LLVM_ATTRIBUTE_NOINLINE void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, llvm::BumpPtrAllocator &Alloc, @@ -1013,11 +1066,44 @@ static void ComputeLineNumbers(DiagnosticsEngine &Diag, ContentCache *FI, unsigned Offs = 0; while (1) { // Skip over the contents of the line. - // TODO: Vectorize this? This is very performance sensitive for programs - // with lots of diagnostics and in -E mode. const unsigned char *NextBuf = (const unsigned char *)Buf; + +#ifdef __SSE2__ + // Try to skip to the next newline using SSE instructions. This is very + // performance sensitive for programs with lots of diagnostics and in -E + // mode. + __m128i CRs = _mm_set1_epi8('\r'); + __m128i LFs = _mm_set1_epi8('\n'); + + // First fix up the alignment to 16 bytes. + while (((uintptr_t)NextBuf & 0xF) != 0) { + if (*NextBuf == '\n' || *NextBuf == '\r' || *NextBuf == '\0') + goto FoundSpecialChar; + ++NextBuf; + } + + // Scan 16 byte chunks for '\r' and '\n'. Ignore '\0'. + while (NextBuf+16 <= End) { + __m128i Chunk = *(__m128i*)NextBuf; + __m128i Cmp = _mm_or_si128(_mm_cmpeq_epi8(Chunk, CRs), + _mm_cmpeq_epi8(Chunk, LFs)); + unsigned Mask = _mm_movemask_epi8(Cmp); + + // If we found a newline, adjust the pointer and jump to the handling code. + if (Mask != 0) { + NextBuf += llvm::CountTrailingZeros_32(Mask); + goto FoundSpecialChar; + } + NextBuf += 16; + } +#endif + while (*NextBuf != '\n' && *NextBuf != '\r' && *NextBuf != '\0') ++NextBuf; + +#ifdef __SSE2__ +FoundSpecialChar: +#endif Offs += NextBuf-Buf; Buf = NextBuf; @@ -1508,9 +1594,10 @@ SourceLocation SourceManager::translateLineCol(FileID FID, return FileLoc.getLocWithOffset(Size); } + const llvm::MemoryBuffer *Buffer = Content->getBuffer(Diag, *this); unsigned FilePos = Content->SourceLineCache[Line - 1]; - const char *Buf = Content->getBuffer(Diag, *this)->getBufferStart() + FilePos; - unsigned BufLength = Content->getBuffer(Diag, *this)->getBufferEnd() - Buf; + const char *Buf = Buffer->getBufferStart() + FilePos; + unsigned BufLength = Buffer->getBufferSize() - FilePos; if (BufLength == 0) return FileLoc.getLocWithOffset(FilePos); @@ -1568,14 +1655,31 @@ void SourceManager::computeMacroArgsCache(MacroArgsMap *&CachePtr, continue; } - if (!Entry.getExpansion().isMacroArgExpansion()) + const ExpansionInfo &ExpInfo = Entry.getExpansion(); + + if (ExpInfo.getExpansionLocStart().isFileID()) { + if (!isInFileID(ExpInfo.getExpansionLocStart(), FID)) + return; // No more files/macros that may be "contained" in this file. + } + + if (!ExpInfo.isMacroArgExpansion()) + continue; + + SourceLocation SpellLoc = ExpInfo.getSpellingLoc(); + while (!SpellLoc.isFileID()) { + std::pair<FileID, unsigned> LocInfo = getDecomposedLoc(SpellLoc); + const ExpansionInfo &Info = getSLocEntry(LocInfo.first).getExpansion(); + if (!Info.isMacroArgExpansion()) + break; + SpellLoc = Info.getSpellingLoc().getLocWithOffset(LocInfo.second); + } + if (!SpellLoc.isFileID()) continue; - - SourceLocation SpellLoc = - getSpellingLoc(Entry.getExpansion().getSpellingLoc()); + unsigned BeginOffs; if (!isInFileID(SpellLoc, FID, &BeginOffs)) - return; // No more files/macros that may be "contained" in this file. + continue; + unsigned EndOffs = BeginOffs + getFileIDSize(FileID::get(ID)); // Add a new chunk for this macro argument. A previous macro argument chunk @@ -1648,7 +1752,7 @@ static bool MoveUpIncludeHierarchy(std::pair<FileID, unsigned> &Loc, SourceLocation UpperLoc; const SrcMgr::SLocEntry &Entry = SM.getSLocEntry(Loc.first); if (Entry.isExpansion()) - UpperLoc = Entry.getExpansion().getExpansionLocEnd(); + UpperLoc = Entry.getExpansion().getExpansionLocStart(); else UpperLoc = Entry.getFile().getIncludeLoc(); |