summaryrefslogtreecommitdiffstats
path: root/gnu/llvm/lib/Support/SourceMgr.cpp
diff options
context:
space:
mode:
authorpatrick <patrick@openbsd.org>2019-01-27 16:42:12 +0000
committerpatrick <patrick@openbsd.org>2019-01-27 16:42:12 +0000
commitb773203fb58f3ef282fb69c832d8710cab5bc82d (patch)
treee75913f147570fbd75169647b144df85b88a038c /gnu/llvm/lib/Support/SourceMgr.cpp
parenttweak errno in previous (diff)
downloadwireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.tar.xz
wireguard-openbsd-b773203fb58f3ef282fb69c832d8710cab5bc82d.zip
Import LLVM 7.0.1 release including clang, lld and lldb.
Diffstat (limited to 'gnu/llvm/lib/Support/SourceMgr.cpp')
-rw-r--r--gnu/llvm/lib/Support/SourceMgr.cpp152
1 files changed, 87 insertions, 65 deletions
diff --git a/gnu/llvm/lib/Support/SourceMgr.cpp b/gnu/llvm/lib/Support/SourceMgr.cpp
index a8f6208a558..d8fde7fa899 100644
--- a/gnu/llvm/lib/Support/SourceMgr.cpp
+++ b/gnu/llvm/lib/Support/SourceMgr.cpp
@@ -28,6 +28,7 @@
#include <algorithm>
#include <cassert>
#include <cstddef>
+#include <limits>
#include <memory>
#include <string>
#include <utility>
@@ -36,24 +37,6 @@ using namespace llvm;
static const size_t TabStop = 8;
-namespace {
-
- struct LineNoCacheTy {
- const char *LastQuery;
- unsigned LastQueryBufferID;
- unsigned LineNoOfQuery;
- };
-
-} // end anonymous namespace
-
-static LineNoCacheTy *getCache(void *Ptr) {
- return (LineNoCacheTy*)Ptr;
-}
-
-SourceMgr::~SourceMgr() {
- delete getCache(LineNoCache);
-}
-
unsigned SourceMgr::AddIncludeFile(const std::string &Filename,
SMLoc IncludeLoc,
std::string &IncludedFile) {
@@ -85,46 +68,85 @@ unsigned SourceMgr::FindBufferContainingLoc(SMLoc Loc) const {
return 0;
}
+template <typename T>
+unsigned SourceMgr::SrcBuffer::getLineNumber(const char *Ptr) const {
+
+ // Ensure OffsetCache is allocated and populated with offsets of all the
+ // '\n' bytes.
+ std::vector<T> *Offsets = nullptr;
+ if (OffsetCache.isNull()) {
+ Offsets = new std::vector<T>();
+ OffsetCache = Offsets;
+ size_t Sz = Buffer->getBufferSize();
+ assert(Sz <= std::numeric_limits<T>::max());
+ StringRef S = Buffer->getBuffer();
+ for (size_t N = 0; N < Sz; ++N) {
+ if (S[N] == '\n') {
+ Offsets->push_back(static_cast<T>(N));
+ }
+ }
+ } else {
+ Offsets = OffsetCache.get<std::vector<T> *>();
+ }
+
+ const char *BufStart = Buffer->getBufferStart();
+ assert(Ptr >= BufStart && Ptr <= Buffer->getBufferEnd());
+ ptrdiff_t PtrDiff = Ptr - BufStart;
+ assert(PtrDiff >= 0 && static_cast<size_t>(PtrDiff) <= std::numeric_limits<T>::max());
+ T PtrOffset = static_cast<T>(PtrDiff);
+
+ // std::lower_bound returns the first EOL offset that's not-less-than
+ // PtrOffset, meaning the EOL that _ends the line_ that PtrOffset is on
+ // (including if PtrOffset refers to the EOL itself). If there's no such
+ // EOL, returns end().
+ auto EOL = std::lower_bound(Offsets->begin(), Offsets->end(), PtrOffset);
+
+ // Lines count from 1, so add 1 to the distance from the 0th line.
+ return (1 + (EOL - Offsets->begin()));
+}
+
+SourceMgr::SrcBuffer::SrcBuffer(SourceMgr::SrcBuffer &&Other)
+ : Buffer(std::move(Other.Buffer)),
+ OffsetCache(Other.OffsetCache),
+ IncludeLoc(Other.IncludeLoc) {
+ Other.OffsetCache = nullptr;
+}
+
+SourceMgr::SrcBuffer::~SrcBuffer() {
+ if (!OffsetCache.isNull()) {
+ if (OffsetCache.is<std::vector<uint8_t>*>())
+ delete OffsetCache.get<std::vector<uint8_t>*>();
+ else if (OffsetCache.is<std::vector<uint16_t>*>())
+ delete OffsetCache.get<std::vector<uint16_t>*>();
+ else if (OffsetCache.is<std::vector<uint32_t>*>())
+ delete OffsetCache.get<std::vector<uint32_t>*>();
+ else
+ delete OffsetCache.get<std::vector<uint64_t>*>();
+ OffsetCache = nullptr;
+ }
+}
+
std::pair<unsigned, unsigned>
SourceMgr::getLineAndColumn(SMLoc Loc, unsigned BufferID) const {
if (!BufferID)
BufferID = FindBufferContainingLoc(Loc);
assert(BufferID && "Invalid Location!");
- const MemoryBuffer *Buff = getMemoryBuffer(BufferID);
-
- // Count the number of \n's between the start of the file and the specified
- // location.
- unsigned LineNo = 1;
-
- const char *BufStart = Buff->getBufferStart();
- const char *Ptr = BufStart;
-
- // If we have a line number cache, and if the query is to a later point in the
- // same file, start searching from the last query location. This optimizes
- // for the case when multiple diagnostics come out of one file in order.
- if (LineNoCacheTy *Cache = getCache(LineNoCache))
- if (Cache->LastQueryBufferID == BufferID &&
- Cache->LastQuery <= Loc.getPointer()) {
- Ptr = Cache->LastQuery;
- LineNo = Cache->LineNoOfQuery;
- }
-
- // Scan for the location being queried, keeping track of the number of lines
- // we see.
- for (; SMLoc::getFromPointer(Ptr) != Loc; ++Ptr)
- if (*Ptr == '\n') ++LineNo;
-
- // Allocate the line number cache if it doesn't exist.
- if (!LineNoCache)
- LineNoCache = new LineNoCacheTy();
-
- // Update the line # cache.
- LineNoCacheTy &Cache = *getCache(LineNoCache);
- Cache.LastQueryBufferID = BufferID;
- Cache.LastQuery = Ptr;
- Cache.LineNoOfQuery = LineNo;
-
+ auto &SB = getBufferInfo(BufferID);
+ const char *Ptr = Loc.getPointer();
+
+ size_t Sz = SB.Buffer->getBufferSize();
+ unsigned LineNo;
+ if (Sz <= std::numeric_limits<uint8_t>::max())
+ LineNo = SB.getLineNumber<uint8_t>(Ptr);
+ else if (Sz <= std::numeric_limits<uint16_t>::max())
+ LineNo = SB.getLineNumber<uint16_t>(Ptr);
+ else if (Sz <= std::numeric_limits<uint32_t>::max())
+ LineNo = SB.getLineNumber<uint32_t>(Ptr);
+ else
+ LineNo = SB.getLineNumber<uint64_t>(Ptr);
+
+ const char *BufStart = SB.Buffer->getBufferStart();
size_t NewlineOffs = StringRef(BufStart, Ptr-BufStart).find_last_of("\n\r");
if (NewlineOffs == StringRef::npos) NewlineOffs = ~(size_t)0;
return std::make_pair(LineNo, Ptr-BufStart-NewlineOffs);
@@ -153,14 +175,14 @@ SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
std::pair<unsigned, unsigned> LineAndCol;
StringRef BufferID = "<unknown>";
std::string LineStr;
-
+
if (Loc.isValid()) {
unsigned CurBuf = FindBufferContainingLoc(Loc);
assert(CurBuf && "Invalid or unspecified location!");
const MemoryBuffer *CurMB = getMemoryBuffer(CurBuf);
BufferID = CurMB->getBufferIdentifier();
-
+
// Scan backward to find the start of the line.
const char *LineStart = Loc.getPointer();
const char *BufStart = CurMB->getBufferStart();
@@ -180,17 +202,17 @@ SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
for (unsigned i = 0, e = Ranges.size(); i != e; ++i) {
SMRange R = Ranges[i];
if (!R.isValid()) continue;
-
+
// If the line doesn't contain any part of the range, then ignore it.
if (R.Start.getPointer() > LineEnd || R.End.getPointer() < LineStart)
continue;
-
+
// Ignore pieces of the range that go onto other lines.
if (R.Start.getPointer() < LineStart)
R.Start = SMLoc::getFromPointer(LineStart);
if (R.End.getPointer() > LineEnd)
R.End = SMLoc::getFromPointer(LineEnd);
-
+
// Translate from SMLoc ranges to column ranges.
// FIXME: Handle multibyte characters.
ColRanges.push_back(std::make_pair(R.Start.getPointer()-LineStart,
@@ -199,7 +221,7 @@ SMDiagnostic SourceMgr::GetMessage(SMLoc Loc, SourceMgr::DiagKind Kind,
LineAndCol = getLineAndColumn(Loc, CurBuf);
}
-
+
return SMDiagnostic(*this, Loc, BufferID, LineAndCol.first,
LineAndCol.second-1, Kind, Msg.str(),
LineStr, ColRanges, FixIts);
@@ -247,7 +269,7 @@ SMDiagnostic::SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN,
: SM(&sm), Loc(L), Filename(FN), LineNo(Line), ColumnNo(Col), Kind(Kind),
Message(Msg), LineContents(LineStr), Ranges(Ranges.vec()),
FixIts(Hints.begin(), Hints.end()) {
- std::sort(FixIts.begin(), FixIts.end());
+ llvm::sort(FixIts.begin(), FixIts.end());
}
static void buildFixItLine(std::string &CaretLine, std::string &FixItLine,
@@ -418,7 +440,7 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S, bool ShowColors,
// Build the line with the caret and ranges.
std::string CaretLine(NumColumns+1, ' ');
-
+
// Expand any ranges.
for (unsigned r = 0, e = Ranges.size(); r != e; ++r) {
std::pair<unsigned, unsigned> R = Ranges[r];
@@ -437,14 +459,14 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S, bool ShowColors,
// Finally, plop on the caret.
if (unsigned(ColumnNo) <= NumColumns)
CaretLine[ColumnNo] = '^';
- else
+ else
CaretLine[NumColumns] = '^';
-
+
// ... and remove trailing whitespace so the output doesn't wrap for it. We
// know that the line isn't completely empty because it has the caret in it at
// least.
CaretLine.erase(CaretLine.find_last_not_of(' ')+1);
-
+
printSourceLine(S, LineContents);
if (ShowColors)
@@ -457,7 +479,7 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S, bool ShowColors,
++OutCol;
continue;
}
-
+
// Okay, we have a tab. Insert the appropriate number of characters.
do {
S << CaretLine[i];
@@ -472,7 +494,7 @@ void SMDiagnostic::print(const char *ProgName, raw_ostream &S, bool ShowColors,
// Print out the replacement line, matching tabs in the source line.
if (FixItInsertionLine.empty())
return;
-
+
for (size_t i = 0, e = FixItInsertionLine.size(), OutCol = 0; i < e; ++i) {
if (i >= LineContents.size() || LineContents[i] != '\t') {
S << FixItInsertionLine[i];