summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Basic/SourceManager.cpp144
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();
OpenPOWER on IntegriCloud