Skip to content

Commit 9328c20

Browse files
committed
[ELF] Track line number precisely
`getLineNumber` is both imprecise (when `INCLUDE` is used) and inefficient (see https://reviews.llvm.org/D104137). Track line number precisely now that we have `struct Buffer` abstraction from #100493.
1 parent ecf125e commit 9328c20

File tree

4 files changed

+16
-35
lines changed

4 files changed

+16
-35
lines changed

lld/ELF/ScriptLexer.cpp

Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -48,40 +48,14 @@ StringRef ScriptLexer::getLine() {
4848
return s.substr(0, s.find_first_of("\r\n"));
4949
}
5050

51-
// Returns 1-based line number of the current token.
52-
size_t ScriptLexer::getLineNumber() {
53-
if (prevTok.empty())
54-
return 1;
55-
StringRef s = getCurrentMB().getBuffer();
56-
const size_t tokOffset = prevTok.data() - s.data();
57-
58-
// For the first token, or when going backwards, start from the beginning of
59-
// the buffer. If this token is after the previous token, start from the
60-
// previous token.
61-
size_t line = 1;
62-
size_t start = 0;
63-
if (lastLineNumberOffset > 0 && tokOffset >= lastLineNumberOffset) {
64-
start = lastLineNumberOffset;
65-
line = lastLineNumber;
66-
}
67-
68-
line += s.substr(start, tokOffset - start).count('\n');
69-
70-
// Store the line number of this token for reuse.
71-
lastLineNumberOffset = tokOffset;
72-
lastLineNumber = line;
73-
74-
return line;
75-
}
76-
7751
// Returns 0-based column number of the current token.
7852
size_t ScriptLexer::getColumnNumber() {
7953
return prevTok.data() - getLine().data();
8054
}
8155

8256
std::string ScriptLexer::getCurrentLocation() {
8357
std::string filename = std::string(getCurrentMB().getBufferIdentifier());
84-
return (filename + ":" + Twine(getLineNumber())).str();
58+
return (filename + ":" + Twine(prevTokLine)).str();
8559
}
8660

8761
// We don't want to record cascading errors. Keep only the first one.
@@ -177,20 +151,25 @@ StringRef ScriptLexer::skipSpace(StringRef s) {
177151
setError("unclosed comment in a linker script");
178152
return "";
179153
}
154+
curBuf.lineNumber += s.substr(0, e).count('\n');
180155
s = s.substr(e + 2);
181156
continue;
182157
}
183158
if (s.starts_with("#")) {
184159
size_t e = s.find('\n', 1);
185160
if (e == StringRef::npos)
186161
e = s.size() - 1;
162+
else
163+
++curBuf.lineNumber;
187164
s = s.substr(e + 1);
188165
continue;
189166
}
190-
size_t size = s.size();
167+
StringRef saved = s;
191168
s = s.ltrim();
192-
if (s.size() == size)
169+
auto len = saved.size() - s.size();
170+
if (len == 0)
193171
return s;
172+
curBuf.lineNumber += saved.substr(0, len).count('\n');
194173
}
195174
}
196175

@@ -199,6 +178,10 @@ bool ScriptLexer::atEOF() { return eof || errorCount(); }
199178

200179
StringRef ScriptLexer::next() {
201180
prevTok = peek();
181+
// `prevTokLine` is not updated for EOF so that the line number in `setError`
182+
// will be more useful.
183+
if (prevTok.size())
184+
prevTokLine = curBuf.lineNumber;
202185
return std::exchange(curTok, StringRef(curBuf.s.data(), 0));
203186
}
204187

lld/ELF/ScriptLexer.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ class ScriptLexer {
2323
// The remaining content to parse and the filename.
2424
StringRef s, filename;
2525
const char *begin = nullptr;
26+
size_t lineNumber = 1;
2627
Buffer() = default;
2728
Buffer(MemoryBufferRef mb)
2829
: s(mb.getBuffer()), filename(mb.getBufferIdentifier()),
@@ -44,6 +45,7 @@ class ScriptLexer {
4445
// curTok holds the cached return value of peek() and is invalid when the
4546
// expression state changes.
4647
StringRef curTok;
48+
size_t prevTokLine = 1;
4749
// The inExpr state when curTok is cached.
4850
bool curTokState = false;
4951
bool eof = false;
@@ -67,12 +69,8 @@ class ScriptLexer {
6769
std::vector<MemoryBufferRef> mbs;
6870
bool inExpr = false;
6971

70-
size_t lastLineNumber = 0;
71-
size_t lastLineNumberOffset = 0;
72-
7372
private:
7473
StringRef getLine();
75-
size_t getLineNumber();
7674
size_t getColumnNumber();
7775
};
7876

lld/test/ELF/linkerscript/overlay.test

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,5 +98,5 @@ SECTIONS {
9898
OVERLAY 0x1000 : AT ( 0x2000 ) {
9999

100100
# RUN: not ld.lld a.o -T unclosed.lds 2>&1 | FileCheck %s --check-prefix=UNCLOSED
101-
# UNCLOSED: error: unclosed.lds:1: unexpected EOF
101+
# UNCLOSED: error: unclosed.lds:2: unexpected EOF
102102
# UNCLOSED-NOT: {{.}}

lld/test/ELF/linkerscript/sections.s

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ SECTIONS {
103103
.text : { *(.text) }
104104

105105
# RUN: not ld.lld -T unclosed.lds a.o 2>&1 | FileCheck --check-prefix=UNCLOSED %s
106-
# UNCLOSED:error: unclosed.lds:1: unexpected EOF
106+
# UNCLOSED:error: unclosed.lds:2: unexpected EOF
107107
# UNCLOSED-NOT:{{.}}
108108

109109
#--- unclosed-out.lds

0 commit comments

Comments
 (0)