[lld] [ELF] Added `struct Token` and changed `next()` and `peek()` to return Token (PR #100180)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 23 12:09:30 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld-elf
Author: Hongyu Chen (yugier)
<details>
<summary>Changes</summary>
This change is reflecting [one](https://github.com/llvm/llvm-project/issues/99921) of the [issues](https://github.com/llvm/llvm-project/issues/99920) to replace current linker script lexer with a fully stateful lexer.
This change:
1. added `struct Token{Kind kind, StringRef val}`
2. replace `vector<StringRef> tokens` with `vector<Token> tokens`
3. updated function `peek()` and `next()` to return `Token`
4. updated most of StringRef checks for linker script keywords with switch cases by using token kind
This change does not fully reflect the correct symbol/operator kind since our current Lexer is not stateful enough to support it; most of the symbols/operator checks are using StringRef comparison. The next steps:
- add a consume overload to accept Token. The existing consume(StringRef) is be a special case that expects identifier/quoted_string.
- introduce state to remove some unquote and https://github.com/llvm/llvm-project/pull/84130 hack
should be able to support symbol/operator kind once they are done.
---
Patch is 48.34 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/100180.diff
4 Files Affected:
- (modified) lld/ELF/ScriptLexer.cpp (+230-34)
- (modified) lld/ELF/ScriptLexer.h (+17-3)
- (modified) lld/ELF/ScriptParser.cpp (+195-149)
- (added) lld/ELF/ScriptToken.h (+177)
``````````diff
diff --git a/lld/ELF/ScriptLexer.cpp b/lld/ELF/ScriptLexer.cpp
index c8c02ab0f3e09..d4de18c417d8c 100644
--- a/lld/ELF/ScriptLexer.cpp
+++ b/lld/ELF/ScriptLexer.cpp
@@ -44,7 +44,7 @@ using namespace lld::elf;
// Returns a whole line containing the current token.
StringRef ScriptLexer::getLine() {
StringRef s = getCurrentMB().getBuffer();
- StringRef tok = tokens[pos - 1];
+ StringRef tok = tokens[pos - 1].val;
size_t pos = s.rfind('\n', tok.data() - s.data());
if (pos != StringRef::npos)
@@ -57,7 +57,7 @@ size_t ScriptLexer::getLineNumber() {
if (pos == 0)
return 1;
StringRef s = getCurrentMB().getBuffer();
- StringRef tok = tokens[pos - 1];
+ StringRef tok = tokens[pos - 1].val;
const size_t tokOffset = tok.data() - s.data();
// For the first token, or when going backwards, start from the beginning of
@@ -81,7 +81,7 @@ size_t ScriptLexer::getLineNumber() {
// Returns 0-based column number of the current token.
size_t ScriptLexer::getColumnNumber() {
- StringRef tok = tokens[pos - 1];
+ StringRef tok = tokens[pos - 1].val;
return tok.data() - getLine().data();
}
@@ -90,6 +90,22 @@ std::string ScriptLexer::getCurrentLocation() {
return (filename + ":" + Twine(getLineNumber())).str();
}
+std::string ScriptLexer::joinTokens(size_t begin, size_t end) {
+ auto itBegin = tokens.begin() + begin;
+ auto itEnd = tokens.begin() + end;
+
+ std::string S;
+ if (itBegin == itEnd)
+ return S;
+
+ S += (*itBegin).val;
+ while (++itBegin != itEnd) {
+ S += " ";
+ S += (*itBegin).val;
+ }
+ return S;
+}
+
ScriptLexer::ScriptLexer(MemoryBufferRef mb) { tokenize(mb); }
// We don't want to record cascading errors. Keep only the first one.
@@ -106,7 +122,7 @@ void ScriptLexer::setError(const Twine &msg) {
// Split S into linker script tokens.
void ScriptLexer::tokenize(MemoryBufferRef mb) {
- std::vector<StringRef> vec;
+ std::vector<Token> vec;
mbs.push_back(mb);
StringRef s = mb.getBuffer();
StringRef begin = s;
@@ -129,20 +145,19 @@ void ScriptLexer::tokenize(MemoryBufferRef mb) {
return;
}
- vec.push_back(s.take_front(e + 1));
+ vec.push_back({Kind::Quote, s.take_front(e + 1)});
s = s.substr(e + 1);
continue;
}
-
// Some operators form separate tokens.
if (s.starts_with("<<=") || s.starts_with(">>=")) {
- vec.push_back(s.substr(0, 3));
+ vec.push_back(getOperatorToken(s));
s = s.substr(3);
continue;
}
if (s.size() > 1 && ((s[1] == '=' && strchr("*/+-<>&^|", s[0])) ||
(s[0] == s[1] && strchr("<>&|", s[0])))) {
- vec.push_back(s.substr(0, 2));
+ vec.push_back(getOperatorToken(s));
s = s.substr(2);
continue;
}
@@ -155,15 +170,199 @@ void ScriptLexer::tokenize(MemoryBufferRef mb) {
// A character that cannot start a word (which is usually a
// punctuation) forms a single character token.
- if (pos == 0)
+ if (pos == 0) {
pos = 1;
- vec.push_back(s.substr(0, pos));
+ vec.push_back(getOperatorToken(s));
+ } else {
+ vec.push_back(getKeywordorIdentifier(s.substr(0, pos)));
+ }
s = s.substr(pos);
}
tokens.insert(tokens.begin() + pos, vec.begin(), vec.end());
}
+ScriptLexer::Token ScriptLexer::getOperatorToken(StringRef s) {
+ auto createToken = [&](Kind kind, size_t pos) -> Token {
+ return {kind, s.substr(0, pos)};
+ };
+
+ switch (s.front()) {
+ case EOF:
+ return createToken(Kind::Eof, 0);
+ case '(':
+ return createToken(Kind::BracektBegin, 1);
+ case ')':
+ return createToken(Kind::BracektEnd, 1);
+ case '{':
+ return createToken(Kind::CurlyBegin, 1);
+ case '}':
+ return createToken(Kind::CurlyEnd, 1);
+ case ';':
+ return createToken(Kind::Semicolon, 1);
+ case ',':
+ return createToken(Kind::Comma, 1);
+ case ':':
+ return createToken(Kind::Colon, 1);
+ case '?':
+ return createToken(Kind::Question, 1);
+ case '%':
+ return createToken(Kind::Percent, 1);
+ case '!':
+ if (s.size() > 1 && s[1] == '=')
+ return createToken(Kind::NotEqual, 2);
+ return createToken(Kind::Excalamation, 1);
+ case '*':
+ if (s.size() > 1 && s[1] == '=')
+ return createToken(Kind::MulAssign, 2);
+ return createToken(Kind::Asterisk, 1);
+ case '/':
+ if (s.size() > 1 && s[1] == '=')
+ return createToken(Kind::DivAssign, 2);
+ return createToken(Kind::Slash, 1);
+ case '=':
+ if (s.size() > 1 && s[1] == '=')
+ return createToken(Kind::Equal, 2);
+ return createToken(Kind::Assign, 1);
+ case '+':
+ if (s.size() > 1 && s[1] == '=')
+ return createToken(Kind::PlusAssign, 2);
+ return createToken(Kind::Plus, 1);
+ case '-':
+ if (s.size() > 1 && s[1] == '=')
+ return createToken(Kind::MinusAssign, 2);
+ return createToken(Kind::Minus, 1);
+ case '<':
+ if (s.size() > 2 && s[1] == s[0] && s[2] == '=')
+ return createToken(Kind::LeftShiftAssign, 3);
+ if (s.size() > 1) {
+ if (s[1] == '=')
+ return createToken(Kind::LessEqual, 2);
+ if (s[1] == '<')
+ return createToken(Kind::LeftShift, 2);
+ }
+ return createToken(Kind::Less, 1);
+ case '>':
+ if (s.size() > 2 && s[1] == s[0] && s[2] == '=')
+ return createToken(Kind::RightShiftAssign, 3);
+ if (s.size() > 1) {
+ if (s[1] == '=')
+ return createToken(Kind::GreaterEqual, 2);
+ if (s[1] == '>')
+ return createToken(Kind::RightShift, 2);
+ }
+ return createToken(Kind::Greater, 1);
+ case '&':
+ if (s.size() > 1) {
+ if (s[1] == '=')
+ return createToken(Kind::AndAssign, 2);
+ if (s[1] == '&')
+ return createToken(Kind::AndGate, 2);
+ }
+ return createToken(Kind::Bitwise, 1);
+ case '^':
+ if (s.size() > 1 && s[1] == '=')
+ return createToken(Kind::XorAssign, 2);
+ return createToken(Kind::Xor, 1);
+ case '|':
+ if (s.size() > 1) {
+ if (s[1] == '=')
+ return createToken(Kind::OrAssign, 2);
+ if (s[1] == '|')
+ return createToken(Kind::OrGate, 2);
+ }
+ return createToken(Kind::Or, 1);
+ case '.':
+ return createToken(Kind::Dot, 1);
+ case '_':
+ return createToken(Kind::Underscore, 1);
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return createToken(Kind::Decimal, 1);
+ default:
+ return {Kind::Identifier, s};
+ }
+}
+
+ScriptLexer::Token ScriptLexer::getKeywordorIdentifier(StringRef s) {
+ static const std::unordered_map<std::string, Kind> keywords = {
+ {"ENTRY", Kind::Entry},
+ {"INPUT", Kind::Input},
+ {"GROUP", Kind::Group},
+ {"INCLUDE", Kind::Include},
+ {"MEMORY", Kind::Memory},
+ {"OUTPUT", Kind::Output},
+ {"SEARCH_DIR", Kind::SearchDir},
+ {"STARTUP", Kind::Startup},
+ {"INSERT", Kind::Insert},
+ {"AFTER", Kind::After},
+ {"OUTPUT_FORMAT", Kind::OutputFormat},
+ {"TARGET", Kind::Target},
+ {"ASSERT", Kind::Assert},
+ {"CONSTANT", Kind::Constant},
+ {"EXTERN", Kind::Extern},
+ {"OUTPUT_ARCH", Kind::OutputArch},
+ {"NOCROSSREFS", Kind::Nocrossrefs},
+ {"NOCROSSREFS_TO", Kind::NocrossrefsTo},
+ {"PROVIDE", Kind::Provide},
+ {"HIDDEN", Kind::Hidden},
+ {"PROVIDE_HIDDEN", Kind::ProvideHidden},
+ {"SECTIONS", Kind::Sections},
+ {"BEFORE", Kind::Before},
+ {"EXCLUDE_FILE", Kind::ExcludeFile},
+ {"KEEP", Kind::Keep},
+ {"INPUT_SECTION_FLAGS", Kind::InputSectionFlags},
+ {"OVERLAY", Kind::Overlay},
+ {"NOLOAD", Kind::Noload},
+ {"COPY", Kind::Copy},
+ {"INFO", Kind::Info},
+ {"OVERWRITE_SECTIONS", Kind::OverwriteSections},
+ {"SUBALIGN", Kind::Subalign},
+ {"ONLY_IF_RO", Kind::OnlyIfRO},
+ {"ONLY_IF_RW", Kind::OnlyIfRW},
+ {"FILL", Kind::Fill},
+ {"SORT", Kind::Sort},
+ {"ABSOLUTE", Kind::Absolute},
+ {"ADDR", Kind::Addr},
+ {"ALIGN", Kind::Align},
+ {"ALIGNOF", Kind::Alignof},
+ {"DATA_SEGMENT_ALIGN", Kind::DataSegmentAlign},
+ {"DATA_SEGMENT_END", Kind::DataSegmentEnd},
+ {"DATA_SEGMENT_RELRO_END", Kind::DataSegmentRelroEnd},
+ {"DEFINED", Kind::Defined},
+ {"LENGTH", Kind::Length},
+ {"LOADADDR", Kind::Loadaddr},
+ {"LOG2CEIL", Kind::Log2ceil},
+ {"MAX", Kind::Max},
+ {"MIN", Kind::Min},
+ {"ORIGIN", Kind::Origin},
+ {"SEGMENT_START", Kind::SegmentStart},
+ {"SIZEOF", Kind::Sizeof},
+ {"SIZEOF_HEADERS", Kind::SizeofHeaders},
+ {"FILEHDR", Kind::Filehdr},
+ {"PHDRS", Kind::Phdrs},
+ {"AT", Kind::At},
+ {"FLAGS", Kind::Flags},
+ {"VERSION", Kind::Version},
+ {"REGION_ALIAS", Kind::RegionAlias},
+ {"AS_NEEDED", Kind::AsNeeded},
+ {"CONSTRUCTORS", Kind::Constructors},
+ {"MAXPAGESIZE", Kind::Maxpagesize},
+ {"COMMONPAGESIZE", Kind::Commonpagesize}};
+ auto it = keywords.find(s.str());
+ if (it != keywords.end())
+ return {it->second, s};
+ return {Kind::Identifier, s};
+}
+
// Skip leading whitespace characters or comments.
StringRef ScriptLexer::skipSpace(StringRef s) {
for (;;) {
@@ -195,37 +394,37 @@ bool ScriptLexer::atEOF() { return errorCount() || tokens.size() == pos; }
// Split a given string as an expression.
// This function returns "3", "*" and "5" for "3*5" for example.
-static std::vector<StringRef> tokenizeExpr(StringRef s) {
+std::vector<ScriptLexer::Token> ScriptLexer::tokenizeExpr(StringRef s) {
StringRef ops = "!~*/+-<>?^:="; // List of operators
// Quoted strings are literal strings, so we don't want to split it.
if (s.starts_with("\""))
- return {s};
+ return {{Kind::Quote, s}};
// Split S with operators as separators.
- std::vector<StringRef> ret;
+ std::vector<ScriptLexer::Token> ret;
while (!s.empty()) {
size_t e = s.find_first_of(ops);
// No need to split if there is no operator.
if (e == StringRef::npos) {
- ret.push_back(s);
+ ret.push_back({Kind::Identifier, s});
break;
}
// Get a token before the operator.
if (e != 0)
- ret.push_back(s.substr(0, e));
+ ret.push_back({Kind::Identifier, s.substr(0, e)});
// Get the operator as a token.
// Keep !=, ==, >=, <=, << and >> operators as a single tokens.
if (s.substr(e).starts_with("!=") || s.substr(e).starts_with("==") ||
s.substr(e).starts_with(">=") || s.substr(e).starts_with("<=") ||
s.substr(e).starts_with("<<") || s.substr(e).starts_with(">>")) {
- ret.push_back(s.substr(e, 2));
+ ret.push_back(getOperatorToken(s.substr(e)));
s = s.substr(e + 2);
} else {
- ret.push_back(s.substr(e, 1));
+ ret.push_back(getOperatorToken(s.substr(e, 1)));
s = s.substr(e + 1);
}
}
@@ -242,32 +441,29 @@ static std::vector<StringRef> tokenizeExpr(StringRef s) {
//
// This function may split the current token into multiple tokens.
void ScriptLexer::maybeSplitExpr() {
- if (!inExpr || errorCount() || atEOF())
- return;
-
- std::vector<StringRef> v = tokenizeExpr(tokens[pos]);
+ std::vector<Token> v = tokenizeExpr(tokens[pos].val);
if (v.size() == 1)
return;
tokens.erase(tokens.begin() + pos);
tokens.insert(tokens.begin() + pos, v.begin(), v.end());
}
-StringRef ScriptLexer::next() {
- maybeSplitExpr();
-
+ScriptLexer::Token ScriptLexer::next() {
if (errorCount())
- return "";
+ return {Kind::Error, ""};
if (atEOF()) {
setError("unexpected EOF");
- return "";
+ return {Kind::Eof, ""};
}
+ if (inExpr)
+ maybeSplitExpr();
return tokens[pos++];
}
-StringRef ScriptLexer::peek() {
- StringRef tok = next();
+ScriptLexer::Token ScriptLexer::peek() {
+ Token tok = next();
if (errorCount())
- return "";
+ return {Kind::Error, ""};
pos = pos - 1;
return tok;
}
@@ -283,8 +479,8 @@ bool ScriptLexer::consume(StringRef tok) {
bool ScriptLexer::consumeLabel(StringRef tok) {
if (consume((tok + ":").str()))
return true;
- if (tokens.size() >= pos + 2 && tokens[pos] == tok &&
- tokens[pos + 1] == ":") {
+ if (tokens.size() >= pos + 2 && tokens[pos].val == tok &&
+ tokens[pos + 1].val == ":") {
pos += 2;
return true;
}
@@ -296,9 +492,9 @@ void ScriptLexer::skip() { (void)next(); }
void ScriptLexer::expect(StringRef expect) {
if (errorCount())
return;
- StringRef tok = next();
+ Token tok = next();
if (tok != expect)
- setError(expect + " expected, but got " + tok);
+ setError(expect + " expected, but got " + tok.val);
}
// Returns true if S encloses T.
@@ -312,7 +508,7 @@ MemoryBufferRef ScriptLexer::getCurrentMB() {
if (pos == 0)
return mbs.back();
for (MemoryBufferRef mb : mbs)
- if (encloses(mb.getBuffer(), tokens[pos - 1]))
+ if (encloses(mb.getBuffer(), tokens[pos - 1].val))
return mb;
llvm_unreachable("getCurrentMB: failed to find a token");
}
diff --git a/lld/ELF/ScriptLexer.h b/lld/ELF/ScriptLexer.h
index d5393818ed553..b98635ef0aeb2 100644
--- a/lld/ELF/ScriptLexer.h
+++ b/lld/ELF/ScriptLexer.h
@@ -9,6 +9,7 @@
#ifndef LLD_ELF_SCRIPT_LEXER_H
#define LLD_ELF_SCRIPT_LEXER_H
+#include "ScriptToken.h"
#include "lld/Common/LLVM.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MemoryBufferRef.h"
@@ -18,14 +19,22 @@ namespace lld::elf {
class ScriptLexer {
public:
+ struct Token {
+ Kind kind;
+ StringRef val;
+ inline bool operator==(StringRef other) { return val == other; }
+
+ inline bool operator!=(StringRef other) { return val != other; }
+ };
+
explicit ScriptLexer(MemoryBufferRef mb);
void setError(const Twine &msg);
void tokenize(MemoryBufferRef mb);
StringRef skipSpace(StringRef s);
bool atEOF();
- StringRef next();
- StringRef peek();
+ Token next();
+ Token peek();
void skip();
bool consume(StringRef tok);
void expect(StringRef expect);
@@ -34,7 +43,8 @@ class ScriptLexer {
MemoryBufferRef getCurrentMB();
std::vector<MemoryBufferRef> mbs;
- std::vector<StringRef> tokens;
+ std::vector<Token> tokens;
+ std::string joinTokens(size_t begin, size_t end);
bool inExpr = false;
size_t pos = 0;
@@ -46,6 +56,10 @@ class ScriptLexer {
StringRef getLine();
size_t getLineNumber();
size_t getColumnNumber();
+
+ Token getOperatorToken(StringRef s);
+ Token getKeywordorIdentifier(StringRef s);
+ std::vector<ScriptLexer::Token> tokenizeExpr(StringRef s);
};
} // namespace lld::elf
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 49aa7e6374905..bae5ae3d1e7e7 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -109,7 +109,7 @@ class ScriptParser final : ScriptLexer {
SortSectionPolicy peekSortKind();
SortSectionPolicy readSortKind();
SymbolAssignment *readProvideHidden(bool provide, bool hidden);
- SymbolAssignment *readAssignment(StringRef tok);
+ SymbolAssignment *readAssignment(ScriptLexer::Token tok);
void readSort();
Expr readAssert();
Expr readConstant();
@@ -119,7 +119,7 @@ class ScriptParser final : ScriptLexer {
void readMemoryAttributes(uint32_t &flags, uint32_t &invFlags,
uint32_t &negFlags, uint32_t &negInvFlags);
- Expr combine(StringRef op, Expr l, Expr r);
+ Expr combine(ScriptLexer::Token op, Expr l, Expr r);
Expr readExpr();
Expr readExpr1(Expr lhs, int minPrec);
StringRef readParenLiteral();
@@ -153,6 +153,12 @@ static StringRef unquote(StringRef s) {
return s;
}
+static StringRef unquote(ScriptLexer::Token tok) {
+ if (tok.val.starts_with("\""))
+ return tok.val.substr(1, tok.val.size() - 2);
+ return tok.val;
+}
+
// Some operations only support one non absolute value. Move the
// absolute one to the right hand side for convenience.
static void moveAbsRight(ExprValue &a, ExprValue &b) {
@@ -201,7 +207,7 @@ void ScriptParser::readDynamicList() {
expect(";");
if (!atEOF()) {
- setError("EOF expected, but got " + next());
+ setError("EOF expected, but got " + next().val);
return;
}
if (!locals.empty()) {
@@ -216,7 +222,7 @@ void ScriptParser::readDynamicList() {
void ScriptParser::readVersionScript() {
readVersionScriptCommand();
if (!atEOF())
- setError("EOF expected, but got " + next());
+ setError("EOF expected, but got " + next().val);
}
void ScriptParser::readVersionScriptCommand() {
@@ -226,14 +232,14 @@ void ScriptParser::readVersionScriptCommand() {
}
while (!atEOF() && !errorCount() && peek() != "}") {
- StringRef verStr = next();
- if (verStr == "{") {
+ ScriptLexer::Token verTok = next();
+ if (verTok.kind == Kind::CurlyBegin) {
setError("anonymous version definition is used in "
"combination with other version definitions");
return;
}
expect("{");
- readVersionDeclaration(verStr);
+ readVersionDeclaration(verTok.val);
}
}
@@ -245,50 +251,71 @@ void ScriptParser::readVersion() {
void ScriptParser::readLinkerScript() {
while (!atEOF()) {
- StringRef tok = next();
- if (tok == ";")
+ ScriptLexer::Token tok = next();
+ if (tok.kind == Kind::Semicolon)
continue;
- if (tok == "ENTRY") {
+ switch (tok.kind) {
+ case Kind::Entry:
readEntry();
- } else if (tok == "EXTERN") {
+ break;
+ case Kind::Extern:
readExtern();
- } else if (tok == "GROUP") {
+ break;
+ case Kind::Group:
readGroup();
- } else if (tok == "INCLUDE") {
+ break;
+ case Kind::Include:
readInclude();
- } else if (tok == "INPUT") {
+ break;
+ case Kind::Input:
readInput();
- } else if (tok == "MEMORY") {
+ break;
+ case Kind::Memory:
readMemory();
- } else if (tok == "OUTPUT") {
+ break;
+ case Kind::Output:
readOutput();
- } else if (tok == "OUTPUT_ARCH") {
+ break;
+ case Kind::OutputArch:
readOutputArch();
- } else if (tok == "OUTPUT_FORMAT") {
+ break;
+ case Kind::OutputFormat:
readOutputFormat();
- } else if (tok == "OVERWRITE_SECTIONS") {
+ break;
+ case Kind::OverwriteSections:
readOverwriteSections();
- } else if (tok == "PHDRS") {
+ break;
+ case Kind::Phdrs:
readPhdrs();
- } else if (tok == "REGION_ALIAS") {
+ break;
+ case Kind::RegionAlias:
readRegionAlias();
- } else if (tok == "SEARCH_DIR") {
+ break;
+ case Kind::SearchDir:
readSearchDir();
- } else if (tok == "SECTIONS") {
+ break;
+ case Kind::Sections:
readSections();
- } else if (tok == "TARGET") {
+ break;
+ case Kind::Target:
readTarget();
- } else if (tok == "VERSION") {
+ break;
+ case Kind::Version:
readVersion();
- } else if (tok == "NOCROSSREFS") {
+ break;
+ case Kind::Nocrossrefs:
readNoCrossRefs(/*to=*/false);
- } else if (tok == "NOCROSSREFS_TO") {
+ break;
+ case Kind::NocrossrefsTo:
readNoCrossRefs(/*to=*/true);
- } else if (SymbolAssignment *cmd = readAssignment(tok)) {
- script->sectionCommands.push_back(cmd);
- } else {
- setError("unknown directive: " + tok);
+ break;
+ default:
+ if (SymbolAssignment *cmd = readAssignment(tok)) {
+ script->sectionCommands.push_back(cmd);
+ } else {
+ setError("unknown directive: " + tok.val);
+ }
}
}
}
@@ -298,7 +325,7 @@ void ScriptParser::readDefsym(StringRef name) {
return;
Expr e = readExpr();
if (!atEOF())
- setError("EOF expected, but got " + next());
+ setError("EOF expected, but got " + next().val);
auto *cmd = make<SymbolAssignment>(
name, e, 0, getCurrentMB().getBufferIdentifier().str());
script->sectionCommands.push_back(cmd);
@@ -376,7 +403,7 @@ void ScriptParser::readAsNeeded() {
void ScriptParser::readEntry() {
// -e <symbol> takes predecence over ENTRY(<symbol>).
expect("(");
- StringRef tok = next();
+ StringRef tok = next().val;
if (config->entry.empty())
config->entry = unquote(tok);
expect(")");
@@ -426,7 +453,7 @@ void ScriptParser::readInput() {
void ScriptParser::readOutput() {
// -o <file> takes predecence over OUTPUT(<file>).
expect("(");
- StringRef tok = next();
+ StringRef tok = next().val;
if (config->outputF...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/100180
More information about the llvm-commits
mailing list