[lld] [ELF] Added `struct Token` and changed `next()` and `peek()` to return Token (PR #100180)
Hongyu Chen via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 23 15:15:10 PDT 2024
https://github.com/yugier updated https://github.com/llvm/llvm-project/pull/100180
>From 649be3cc6b5463f840af4bef9e1476b98fc41bf4 Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Sat, 20 Jul 2024 06:31:44 +0000
Subject: [PATCH 1/6] [ELF] Created linker script token and strcut Token
---
lld/ELF/ScriptLexer.cpp | 223 +++++++++++++++++++++++++++++++++++----
lld/ELF/ScriptLexer.h | 13 ++-
lld/ELF/ScriptParser.cpp | 8 +-
lld/ELF/ScriptToken.h | 175 ++++++++++++++++++++++++++++++
4 files changed, 391 insertions(+), 28 deletions(-)
create mode 100644 lld/ELF/ScriptToken.h
diff --git a/lld/ELF/ScriptLexer.cpp b/lld/ELF/ScriptLexer.cpp
index 14f39ed10e17c..5367dab222ce7 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({Kind::LeftShiftAssign, s.substr(0, 3)});
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({Kind::Assign, s.substr(0, 2)});
s = s.substr(2);
continue;
}
@@ -157,13 +172,179 @@ void ScriptLexer::tokenize(MemoryBufferRef mb) {
// punctuation) forms a single character token.
if (pos == 0)
pos = 1;
- vec.push_back(s.substr(0, pos));
+ vec.push_back({Kind::Identifier, 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, 1);
+ 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 '!':
+ 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);
+ else
+ 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 '.':
+ case '_':
+ // TODO
+ default:
+ return createToken(Kind::Error, 1);
+ }
+}
+
+ScriptLexer::Token ScriptLexer::getKeywordorIdentifier(StringRef s) {
+ static const std::unordered_map<std::string, Kind> keywords = {
+ {"ENTRY", Kind::Entry},
+ {"INPUT", Kind::Input},
+ {"GROUP", Kind::Group},
+ {"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},
+ {"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 +376,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({Kind::GreaterEqual, s.substr(e, 2)});
s = s.substr(e + 2);
} else {
- ret.push_back(s.substr(e, 1));
+ ret.push_back({Kind::Identifier, s.substr(e, 1)});
s = s.substr(e + 1);
}
}
@@ -245,7 +426,7 @@ 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);
@@ -261,7 +442,7 @@ StringRef ScriptLexer::next() {
setError("unexpected EOF");
return "";
}
- return tokens[pos++];
+ return tokens[pos++].val;
}
StringRef ScriptLexer::peek() {
@@ -293,8 +474,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;
}
@@ -322,7 +503,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 7919e493fa28b..a96e9bee23ad6 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,6 +19,11 @@ namespace lld::elf {
class ScriptLexer {
public:
+ struct Token {
+ Kind kind;
+ StringRef val;
+ };
+
explicit ScriptLexer(MemoryBufferRef mb);
void setError(const Twine &msg);
@@ -35,7 +41,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;
@@ -47,6 +54,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 db46263115242..c7d38e13edb9b 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -1100,9 +1100,7 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
if (cmd) {
cmd->dataSegmentRelroEnd = !savedSeenRelroEnd && script->seenRelroEnd;
- cmd->commandString =
- tok.str() + " " +
- llvm::join(tokens.begin() + oldPos, tokens.begin() + pos, " ");
+ cmd->commandString = tok.str() + " " + joinTokens(oldPos, pos);
expect(";");
}
return cmd;
@@ -1310,9 +1308,7 @@ ByteCommand *ScriptParser::readByteCommand(StringRef tok) {
size_t oldPos = pos;
Expr e = readParenExpr();
- std::string commandString =
- tok.str() + " " +
- llvm::join(tokens.begin() + oldPos, tokens.begin() + pos, " ");
+ std::string commandString = tok.str() + " " + joinTokens(oldPos, pos);
return make<ByteCommand>(e, size, commandString);
}
diff --git a/lld/ELF/ScriptToken.h b/lld/ELF/ScriptToken.h
new file mode 100644
index 0000000000000..01b38413cad29
--- /dev/null
+++ b/lld/ELF/ScriptToken.h
@@ -0,0 +1,175 @@
+//===- ScriptLexer.h --------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the nums for LinkerScript lexer
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_SCRIPT_TOKENIZER_H
+#define LLD_ELF_SCRIPT_TOKENIZER_H
+
+namespace lld {
+namespace elf {
+enum class Kind {
+ Entry,
+
+ // Commands Files
+ Include,
+ Input,
+ Group,
+ Memory,
+ Output,
+ SearchDir,
+ Startup,
+
+ Insert,
+ After,
+
+ // Commands for object file formats
+ OutputFormat,
+ Target,
+
+ // Other linker script commands
+ Assert,
+ Constant,
+ Extern,
+ // FORCE_COMMON_ALLOCATION
+ // INHIBIT_COMMON_ALLOCATION
+ OutputArch,
+ Nocrossrefs,
+ NocrossrefsTo,
+
+ // Assignment
+ Provide,
+ Hidden,
+ ProvideHidden,
+
+ Sections,
+ Before,
+
+ // Input Section
+ ExcludeFile,
+ Keep,
+ InputSectionFlags,
+
+ // Read section
+ Overlay,
+ Noload,
+ Copy,
+ Info,
+
+ // Output Section
+ OverwriteSections,
+ Subalign,
+ OnlyIfRO,
+ OnlyIfRW,
+ Fill,
+ Sort,
+
+ // Builtin Functions
+ Absolute,
+ Addr,
+ Align,
+ Alignof,
+ // BLOCK, // synonym for ALIGN for compatibility with older linker script
+ DataSegmentAlign,
+ DataSegmentEnd,
+ Defined,
+ Length,
+ Loadaddr,
+
+ Log2ceil,
+ Max,
+ Min,
+ Origin,
+ SegmentStart,
+ // NEXT, // This function is closely related to ALIGN(exp); unless you use the
+ // MEMORY command to define discontinuous memory for the output file, the two
+ // functions are equivalent.
+ Sizeof,
+ SizeofHeaders,
+
+ // PHDRS Command
+ Filehdr,
+ Phdrs,
+ At,
+ Flags,
+
+ // Version Command
+ Version,
+
+ RegionAlias,
+ AsNeeded,
+ Constructors,
+
+ // Symbolic Constants
+ Maxpagesize,
+ Commonpagesize,
+
+ Error,
+ Eof,
+
+ Identifier,
+ Hexdecimal, // 0x
+ HexdecimalH, // end with H/h
+ Decimal,
+ DecimalK, // end with K/k
+ DecimalM, // end with M/m
+
+ // Symbol tokens
+ CurlyBegin, // {
+ CurlyEnd, // }
+ BracektBegin, // (
+ BracektEnd, // )
+ Comma, // ,
+ Semicolon, // ;
+ Colon, // :
+ Asterisk, // *
+ Question, // ?
+ Excalamation, // !
+ Backslash, // "\"
+ Slash, // /
+ Greater, // >
+ Less, // <
+ Minus, // -
+ Plus, // +
+ Bitwise, // &
+ Xor, // ^
+ Or, // |
+ Underscore, // _
+ Dot, // .
+ Quote, // Quoted token. Note that double-quote characters are parts of a token
+ // because, in a glob match context, only unquoted tokens are interpreted as
+ // glob patterns. Double-quoted tokens are literal patterns in that context.
+
+ // Assignmemnt
+ Assign, // =
+ PlusAssign, // +=
+ MinusAssign, // -=
+ MulAssign, // *=
+ DivAssign, // /=
+ LeftShiftAssign, // <<=
+ RightShiftAssign, // >>=
+ AndAssign, // &=
+ OrAssign, // |=
+ XorAssign, // ^=
+
+ // operator token
+ NotEqual, // !=
+ Equal, // ==
+ GreaterEqual, // >=
+ LessEqual, // <=
+ LeftShift, // <<
+ RightShift, // >>
+ AndGate, // &&
+ OrGate // ||
+};
+} // namespace elf
+} // namespace lld
+
+#endif // LLD_ELF_SCRIPT_TOKENIZER_H
>From 0c7fe7bbfa40d4c9ebd5d0fb1a666ed2bf2ad534 Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Sat, 20 Jul 2024 21:34:05 +0000
Subject: [PATCH 2/6] [ELF] update token kind
---
lld/ELF/ScriptLexer.cpp | 33 ++++++++++++++++++++++++---------
1 file changed, 24 insertions(+), 9 deletions(-)
diff --git a/lld/ELF/ScriptLexer.cpp b/lld/ELF/ScriptLexer.cpp
index 028dcc3ee8c00..e78d8d9712662 100644
--- a/lld/ELF/ScriptLexer.cpp
+++ b/lld/ELF/ScriptLexer.cpp
@@ -151,13 +151,13 @@ void ScriptLexer::tokenize(MemoryBufferRef mb) {
}
// Some operators form separate tokens.
if (s.starts_with("<<=") || s.starts_with(">>=")) {
- vec.push_back({Kind::LeftShiftAssign, 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({Kind::Assign, s.substr(0, 2)});
+ vec.push_back(getOperatorToken(s));
s = s.substr(2);
continue;
}
@@ -170,9 +170,12 @@ 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({Kind::Identifier, s.substr(0, pos)});
+ vec.push_back(getOperatorToken(s));
+ } else {
+ vec.push_back(getKeywordorIdentifier(s.substr(0, pos)));
+ }
s = s.substr(pos);
}
@@ -186,7 +189,7 @@ ScriptLexer::Token ScriptLexer::getOperatorToken(StringRef s) {
switch (s.front()) {
case EOF:
- return createToken(Kind::Eof, 1);
+ return createToken(Kind::Eof, 0);
case '(':
return createToken(Kind::BracektBegin, 1);
case ')':
@@ -269,10 +272,22 @@ ScriptLexer::Token ScriptLexer::getOperatorToken(StringRef s) {
}
return createToken(Kind::Or, 1);
case '.':
+ return createToken(Kind::Dot, 1);
case '_':
- // TODO
+ 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 createToken(Kind::Error, 1);
+ return createToken(Kind::Identifier, 1);
}
}
@@ -403,10 +418,10 @@ std::vector<ScriptLexer::Token> ScriptLexer::tokenizeExpr(StringRef s) {
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({Kind::GreaterEqual, s.substr(e, 2)});
+ ret.push_back(getOperatorToken(s));
s = s.substr(e + 2);
} else {
- ret.push_back({Kind::Identifier, s.substr(e, 1)});
+ ret.push_back(getKeywordorIdentifier(s.substr(e, 1)));
s = s.substr(e + 1);
}
}
>From 2b33a714c4bc56ddd9c240803f22cfb634965f66 Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Sun, 21 Jul 2024 21:15:05 +0000
Subject: [PATCH 3/6] [ELF] Changed next and peek to return Token
---
lld/ELF/ScriptLexer.cpp | 21 ++---
lld/ELF/ScriptLexer.h | 7 +-
lld/ELF/ScriptParser.cpp | 181 +++++++++++++++++++++++----------------
3 files changed, 121 insertions(+), 88 deletions(-)
diff --git a/lld/ELF/ScriptLexer.cpp b/lld/ELF/ScriptLexer.cpp
index e78d8d9712662..9d9d74e016a9e 100644
--- a/lld/ELF/ScriptLexer.cpp
+++ b/lld/ELF/ScriptLexer.cpp
@@ -296,6 +296,7 @@ ScriptLexer::Token ScriptLexer::getKeywordorIdentifier(StringRef s) {
{"ENTRY", Kind::Entry},
{"INPUT", Kind::Input},
{"GROUP", Kind::Group},
+ {"INCLUDE", Kind::Include},
{"MEMORY", Kind::Memory},
{"OUTPUT", Kind::Output},
{"SEARCH_DIR", Kind::SearchDir},
@@ -319,7 +320,7 @@ ScriptLexer::Token ScriptLexer::getKeywordorIdentifier(StringRef s) {
{"KEEP", Kind::Keep},
{"INPUT_SECTION_FLAGS", Kind::InputSectionFlags},
{"OVERLAY", Kind::Overlay},
- {"Noload", Kind::Noload},
+ {"NOLOAD", Kind::Noload},
{"COPY", Kind::Copy},
{"INFO", Kind::Info},
{"OVERWRITE_SECTIONS", Kind::OverwriteSections},
@@ -448,22 +449,22 @@ void ScriptLexer::maybeSplitExpr() {
tokens.insert(tokens.begin() + pos, v.begin(), v.end());
}
-StringRef ScriptLexer::next() {
+ScriptLexer::Token ScriptLexer::next() {
maybeSplitExpr();
if (errorCount())
- return "";
+ return {Kind::Error, ""};
if (atEOF()) {
setError("unexpected EOF");
- return "";
+ return {Kind::Eof, ""};
}
- return tokens[pos++].val;
+ 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;
}
@@ -492,9 +493,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.
diff --git a/lld/ELF/ScriptLexer.h b/lld/ELF/ScriptLexer.h
index 9b99c6ade386c..b98635ef0aeb2 100644
--- a/lld/ELF/ScriptLexer.h
+++ b/lld/ELF/ScriptLexer.h
@@ -22,6 +22,9 @@ class ScriptLexer {
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);
@@ -30,8 +33,8 @@ class ScriptLexer {
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);
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 562e33308226e..995989159e3ae 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -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,7 +232,7 @@ void ScriptParser::readVersionScriptCommand() {
}
while (!atEOF() && !errorCount() && peek() != "}") {
- StringRef verStr = next();
+ StringRef verStr = next().val;
if (verStr == "{") {
setError("anonymous version definition is used in "
"combination with other version definitions");
@@ -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.val)) {
+ 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->outputFile.empty())
config->outputFile = unquote(tok);
expect(")");
@@ -517,7 +544,7 @@ void ScriptParser::readPhdrs() {
while (!errorCount() && !consume("}")) {
PhdrsCommand cmd;
- cmd.name = next();
+ cmd.name = next().val;
cmd.type = readPhdrType();
while (!errorCount() && !consume(";")) {
@@ -530,7 +557,7 @@ void ScriptParser::readPhdrs() {
else if (consume("FLAGS"))
cmd.flags = readParenExpr()().getValue();
else
- setError("unexpected header attribute: " + next());
+ setError("unexpected header attribute: " + next().val);
}
script->phdrsCommands.push_back(cmd);
@@ -541,7 +568,7 @@ void ScriptParser::readRegionAlias() {
expect("(");
StringRef alias = unquote(next());
expect(",");
- StringRef name = next();
+ StringRef name = next().val;
expect(")");
if (script->memoryRegions.count(alias))
@@ -553,7 +580,7 @@ void ScriptParser::readRegionAlias() {
void ScriptParser::readSearchDir() {
expect("(");
- StringRef tok = next();
+ StringRef tok = next().val;
if (!config->nostdlib)
config->searchPaths.push_back(unquote(tok));
expect(")");
@@ -614,27 +641,28 @@ SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
void ScriptParser::readOverwriteSections() {
expect("{");
while (!errorCount() && !consume("}"))
- script->overwriteSections.push_back(readOutputSectionDescription(next()));
+ script->overwriteSections.push_back(
+ readOutputSectionDescription(next().val));
}
void ScriptParser::readSections() {
expect("{");
SmallVector<SectionCommand *, 0> v;
while (!errorCount() && !consume("}")) {
- StringRef tok = next();
- if (tok == "OVERLAY") {
+ ScriptLexer::Token tok = next();
+ if (tok.kind == Kind::Overlay) {
for (SectionCommand *cmd : readOverlay())
v.push_back(cmd);
continue;
- } else if (tok == "INCLUDE") {
+ } else if (tok.kind == Kind::Include) {
readInclude();
continue;
}
- if (SectionCommand *cmd = readAssignment(tok))
+ if (SectionCommand *cmd = readAssignment(tok.val))
v.push_back(cmd);
else
- v.push_back(readOutputSectionDescription(tok));
+ v.push_back(readOutputSectionDescription(tok.val));
}
// If DATA_SEGMENT_RELRO_END is absent, for sections after DATA_SEGMENT_ALIGN,
@@ -656,8 +684,8 @@ void ScriptParser::readSections() {
if (consume("AFTER"))
isAfter = true;
else if (!consume("BEFORE"))
- setError("expected AFTER/BEFORE, but got '" + next() + "'");
- StringRef where = next();
+ setError("expected AFTER/BEFORE, but got '" + next().val + "'");
+ StringRef where = next().val;
SmallVector<StringRef, 0> names;
for (SectionCommand *cmd : v)
if (auto *os = dyn_cast<OutputDesc>(cmd))
@@ -703,12 +731,12 @@ StringMatcher ScriptParser::readFilePatterns() {
StringMatcher Matcher;
while (!errorCount() && !consume(")"))
- Matcher.addPattern(SingleStringMatcher(next()));
+ Matcher.addPattern(SingleStringMatcher(next().val));
return Matcher;
}
SortSectionPolicy ScriptParser::peekSortKind() {
- return StringSwitch<SortSectionPolicy>(peek())
+ return StringSwitch<SortSectionPolicy>(peek().val)
.Case("REVERSE", SortSectionPolicy::Reverse)
.Cases("SORT", "SORT_BY_NAME", SortSectionPolicy::Name)
.Case("SORT_BY_ALIGNMENT", SortSectionPolicy::Alignment)
@@ -749,7 +777,7 @@ SmallVector<SectionPattern, 0> ScriptParser::readInputSectionsList() {
StringMatcher SectionMatcher;
// Break if the next token is ), EXCLUDE_FILE, or SORT*.
while (!errorCount() && peekSortKind() == SortSectionPolicy::Default) {
- StringRef s = peek();
+ StringRef s = peek().val;
if (s == ")" || s == "EXCLUDE_FILE")
break;
// Detect common mistakes when certain non-wildcard meta characters are
@@ -759,7 +787,7 @@ SmallVector<SectionPattern, 0> ScriptParser::readInputSectionsList() {
setError("section pattern is expected");
break;
}
- SectionMatcher.addPattern(unquote(next()));
+ SectionMatcher.addPattern(unquote(next().val));
}
if (!SectionMatcher.empty())
@@ -830,14 +858,14 @@ ScriptParser::readInputSectionDescription(StringRef tok) {
if (consume("INPUT_SECTION_FLAGS"))
std::tie(withFlags, withoutFlags) = readInputSectionFlags();
InputSectionDescription *cmd =
- readInputSectionRules(next(), withFlags, withoutFlags);
+ readInputSectionRules(next().val, withFlags, withoutFlags);
expect(")");
script->keptSections.push_back(cmd);
return cmd;
}
if (tok == "INPUT_SECTION_FLAGS") {
std::tie(withFlags, withoutFlags) = readInputSectionFlags();
- tok = next();
+ tok = next().val;
}
return readInputSectionRules(tok, withFlags, withoutFlags);
}
@@ -883,7 +911,7 @@ bool ScriptParser::readSectionDirective(OutputSection *cmd, StringRef tok) {
cmd->typeIsSet = true;
} else if (consume("TYPE")) {
expect("=");
- StringRef value = peek();
+ StringRef value = peek().val;
auto it = llvm::find_if(typeMap, [=](auto e) { return e.first == value; });
if (it != std::end(typeMap)) {
// The value is a recognized literal SHT_*.
@@ -919,7 +947,7 @@ void ScriptParser::readSectionAddressType(OutputSection *cmd) {
if (consume("(")) {
// Temporarily set inExpr to support TYPE=<value> without spaces.
SaveAndRestore saved(inExpr, true);
- if (readSectionDirective(cmd, peek()))
+ if (readSectionDirective(cmd, peek().val))
return;
cmd->addrExpr = readExpr();
expect(")");
@@ -929,7 +957,7 @@ void ScriptParser::readSectionAddressType(OutputSection *cmd) {
if (consume("(")) {
SaveAndRestore saved(inExpr, true);
- StringRef tok = peek();
+ StringRef tok = peek().val;
if (!readSectionDirective(cmd, tok))
setError("unknown section directive: " + tok);
}
@@ -947,7 +975,8 @@ static Expr checkAlignment(Expr e, std::string &loc) {
}
OutputDesc *ScriptParser::readOverlaySectionDescription() {
- OutputDesc *osd = script->createOutputSection(next(), getCurrentLocation());
+ OutputDesc *osd =
+ script->createOutputSection(next().val, getCurrentLocation());
osd->osec.inOverlay = true;
expect("{");
while (!errorCount() && !consume("}")) {
@@ -956,7 +985,7 @@ OutputDesc *ScriptParser::readOverlaySectionDescription() {
if (consume("INPUT_SECTION_FLAGS"))
std::tie(withFlags, withoutFlags) = readInputSectionFlags();
osd->osec.commands.push_back(
- readInputSectionRules(next(), withFlags, withoutFlags));
+ readInputSectionRules(next().val, withFlags, withoutFlags));
}
osd->osec.phdrs = readOutputSectionPhdrs();
return osd;
@@ -991,7 +1020,7 @@ OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
expect("{");
while (!errorCount() && !consume("}")) {
- StringRef tok = next();
+ StringRef tok = next().val;
if (tok == ";") {
// Empty commands are allowed. Do nothing here.
} else if (SymbolAssignment *assign = readAssignment(tok)) {
@@ -1007,7 +1036,7 @@ OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
// which is different from what GNU linkers do.
// https://sourceware.org/binutils/docs/ld/Output-Section-Data.html
if (peek() != "(")
- setError("( expected, but got " + peek());
+ setError("( expected, but got " + peek().val);
osec->filler = readFill();
} else if (tok == "SORT") {
readSort();
@@ -1031,11 +1060,11 @@ OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
}
if (consume(">"))
- osec->memoryRegionName = std::string(next());
+ osec->memoryRegionName = std::string(next().val);
if (consume("AT")) {
expect(">");
- osec->lmaRegionName = std::string(next());
+ osec->lmaRegionName = std::string(next().val);
}
if (osec->lmaExpr && !osec->lmaRegionName.empty())
@@ -1043,7 +1072,7 @@ OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
osec->phdrs = readOutputSectionPhdrs();
- if (peek() == "=" || peek().starts_with("=")) {
+ if (peek().val == "=" || peek().val.starts_with("=")) {
inExpr = true;
consume("=");
osec->filler = readFill();
@@ -1081,9 +1110,9 @@ std::array<uint8_t, 4> ScriptParser::readFill() {
SymbolAssignment *ScriptParser::readProvideHidden(bool provide, bool hidden) {
expect("(");
- StringRef name = next(), eq = peek();
+ StringRef name = next().val, eq = peek().val;
if (eq != "=") {
- setError("= expected, but got " + next());
+ setError("= expected, but got " + next().val);
while (!atEOF() && next() != ")")
;
return nullptr;
@@ -1106,7 +1135,7 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
size_t oldPos = pos;
SymbolAssignment *cmd = nullptr;
bool savedSeenRelroEnd = script->seenRelroEnd;
- const StringRef op = peek();
+ const StringRef op = peek().val;
if (op.starts_with("=")) {
// Support = followed by an expression without whitespace.
SaveAndRestore saved(inExpr, true);
@@ -1135,7 +1164,7 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) {
name = unquote(name);
- StringRef op = next();
+ StringRef op = next().val;
assert(op == "=" || op == "*=" || op == "/=" || op == "+=" || op == "-=" ||
op == "&=" || op == "^=" || op == "|=" || op == "<<=" || op == ">>=");
// Note: GNU ld does not support %=.
@@ -1244,7 +1273,7 @@ Expr ScriptParser::combine(StringRef op, Expr l, Expr r) {
Expr ScriptParser::readExpr1(Expr lhs, int minPrec) {
while (!atEOF() && !errorCount()) {
// Read an operator and an expression.
- StringRef op1 = peek();
+ StringRef op1 = peek().val;
if (precedence(op1) < minPrec)
break;
skip();
@@ -1257,7 +1286,7 @@ Expr ScriptParser::readExpr1(Expr lhs, int minPrec) {
// For example, if we have read "+" and "3", and if the next
// operator is "*", then we'll evaluate 3 * ... part first.
while (!atEOF()) {
- StringRef op2 = peek();
+ StringRef op2 = peek().val;
if (precedence(op2) <= precedence(op1))
break;
rhs = readExpr1(rhs, precedence(op2));
@@ -1398,7 +1427,7 @@ StringRef ScriptParser::readParenLiteral() {
expect("(");
bool orig = inExpr;
inExpr = false;
- StringRef tok = next();
+ StringRef tok = next().val;
inExpr = orig;
expect(")");
return tok;
@@ -1433,7 +1462,7 @@ Expr ScriptParser::readPrimary() {
return [=] { return -e().getValue(); };
}
- StringRef tok = next();
+ StringRef tok = next().val;
std::string location = getCurrentLocation();
// Built-in functions are parsed here.
@@ -1623,9 +1652,9 @@ Expr ScriptParser::readParenExpr() {
SmallVector<StringRef, 0> ScriptParser::readOutputSectionPhdrs() {
SmallVector<StringRef, 0> phdrs;
- while (!errorCount() && peek().starts_with(":")) {
- StringRef tok = next();
- phdrs.push_back((tok.size() == 1) ? next() : tok.substr(1));
+ while (!errorCount() && peek().val.starts_with(":")) {
+ StringRef tok = next().val;
+ phdrs.push_back((tok.size() == 1) ? next().val : tok.substr(1));
}
return phdrs;
}
@@ -1633,7 +1662,7 @@ SmallVector<StringRef, 0> ScriptParser::readOutputSectionPhdrs() {
// Read a program header type name. The next token must be a
// name of a program header type or a constant (e.g. "0x3").
unsigned ScriptParser::readPhdrType() {
- StringRef tok = next();
+ StringRef tok = next().val;
if (std::optional<uint64_t> val = parseInt(tok))
return *val;
@@ -1697,7 +1726,7 @@ void ScriptParser::readVersionDeclaration(StringRef verStr) {
// as a parent. This version hierarchy is, probably against your
// instinct, purely for hint; the runtime doesn't care about it
// at all. In LLD, we simply ignore it.
- if (next() != ";")
+ if (next().val != ";")
expect(";");
}
@@ -1728,7 +1757,7 @@ ScriptParser::readSymbols() {
SmallVector<SymbolVersion, 0> ext = readVersionExtern();
v->insert(v->end(), ext.begin(), ext.end());
} else {
- StringRef tok = next();
+ StringRef tok = next().val;
v->push_back({unquote(tok), false, hasWildcard(tok)});
}
expect(";");
@@ -1742,7 +1771,7 @@ ScriptParser::readSymbols() {
// The last semicolon is optional. E.g. this is OK:
// "extern "C++" { ns::*; "f(int, double)" };"
SmallVector<SymbolVersion, 0> ScriptParser::readVersionExtern() {
- StringRef tok = next();
+ StringRef tok = next().val;
bool isCXX = tok == "\"C++\"";
if (!isCXX && tok != "\"C\"")
setError("Unknown language");
@@ -1750,7 +1779,7 @@ SmallVector<SymbolVersion, 0> ScriptParser::readVersionExtern() {
SmallVector<SymbolVersion, 0> ret;
while (!errorCount() && peek() != "}") {
- StringRef tok = next();
+ StringRef tok = next().val;
ret.push_back(
{unquote(tok), isCXX, !tok.starts_with("\"") && hasWildcard(tok)});
if (consume("}"))
@@ -1779,7 +1808,7 @@ Expr ScriptParser::readMemoryAssignment(StringRef s1, StringRef s2,
void ScriptParser::readMemory() {
expect("{");
while (!errorCount() && !consume("}")) {
- StringRef tok = next();
+ StringRef tok = next().val;
if (tok == "INCLUDE") {
readInclude();
continue;
@@ -1815,7 +1844,7 @@ void ScriptParser::readMemoryAttributes(uint32_t &flags, uint32_t &invFlags,
uint32_t &negInvFlags) {
bool invert = false;
- for (char c : next().lower()) {
+ for (char c : next().val.lower()) {
if (c == '!') {
invert = !invert;
std::swap(flags, negFlags);
>From 2375d3d49eae2a3d35f965279814c77dec7fd754 Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Mon, 22 Jul 2024 18:14:47 +0000
Subject: [PATCH 4/6] [ELF] Update Keyword comparision in Parser with Switch
cases
---
lld/ELF/ScriptLexer.cpp | 13 ++-
lld/ELF/ScriptParser.cpp | 179 ++++++++++++++++++++++-----------------
lld/ELF/ScriptToken.h | 2 +
3 files changed, 111 insertions(+), 83 deletions(-)
diff --git a/lld/ELF/ScriptLexer.cpp b/lld/ELF/ScriptLexer.cpp
index 9d9d74e016a9e..8e44f38462c96 100644
--- a/lld/ELF/ScriptLexer.cpp
+++ b/lld/ELF/ScriptLexer.cpp
@@ -206,6 +206,8 @@ ScriptLexer::Token ScriptLexer::getOperatorToken(StringRef s) {
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);
@@ -225,8 +227,7 @@ ScriptLexer::Token ScriptLexer::getOperatorToken(StringRef s) {
case '+':
if (s.size() > 1 && s[1] == '=')
return createToken(Kind::PlusAssign, 2);
- else
- return createToken(Kind::Plus, 1);
+ return createToken(Kind::Plus, 1);
case '-':
if (s.size() > 1 && s[1] == '=')
return createToken(Kind::MinusAssign, 2);
@@ -335,6 +336,7 @@ ScriptLexer::Token ScriptLexer::getKeywordorIdentifier(StringRef s) {
{"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},
@@ -419,10 +421,13 @@ std::vector<ScriptLexer::Token> ScriptLexer::tokenizeExpr(StringRef s) {
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(getOperatorToken(s));
+ ret.push_back(getOperatorToken(s.substr(e)));
s = s.substr(e + 2);
} else {
- ret.push_back(getKeywordorIdentifier(s.substr(e, 1)));
+ llvm::errs() << "s.substr(e) is " << s.substr(e, 1);
+ ret.push_back(getOperatorToken(s.substr(e, 1)));
+ llvm::errs() << ", token.kind == "
+ << static_cast<unsigned int>(ret.back().kind) << "\n";
s = s.substr(e + 1);
}
}
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 995989159e3ae..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();
@@ -232,14 +232,14 @@ void ScriptParser::readVersionScriptCommand() {
}
while (!atEOF() && !errorCount() && peek() != "}") {
- StringRef verStr = next().val;
- 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);
}
}
@@ -311,7 +311,7 @@ void ScriptParser::readLinkerScript() {
readNoCrossRefs(/*to=*/true);
break;
default:
- if (SymbolAssignment *cmd = readAssignment(tok.val)) {
+ if (SymbolAssignment *cmd = readAssignment(tok)) {
script->sectionCommands.push_back(cmd);
} else {
setError("unknown directive: " + tok.val);
@@ -548,16 +548,24 @@ void ScriptParser::readPhdrs() {
cmd.type = readPhdrType();
while (!errorCount() && !consume(";")) {
- if (consume("FILEHDR"))
+ ScriptLexer::Token tok = next();
+ switch (tok.kind) {
+ case Kind::Filehdr:
cmd.hasFilehdr = true;
- else if (consume("PHDRS"))
+ break;
+ case Kind::Phdrs:
cmd.hasPhdrs = true;
- else if (consume("AT"))
+ break;
+ case Kind::At:
cmd.lmaExpr = readParenExpr();
- else if (consume("FLAGS"))
+ break;
+ case Kind::Flags:
cmd.flags = readParenExpr()().getValue();
- else
- setError("unexpected header attribute: " + next().val);
+ break;
+ default:
+ setError("unexpected header attribute: " + tok.val);
+ break;
+ }
}
script->phdrsCommands.push_back(cmd);
@@ -659,7 +667,7 @@ void ScriptParser::readSections() {
continue;
}
- if (SectionCommand *cmd = readAssignment(tok.val))
+ if (SectionCommand *cmd = readAssignment(tok))
v.push_back(cmd);
else
v.push_back(readOutputSectionDescription(tok.val));
@@ -777,12 +785,13 @@ SmallVector<SectionPattern, 0> ScriptParser::readInputSectionsList() {
StringMatcher SectionMatcher;
// Break if the next token is ), EXCLUDE_FILE, or SORT*.
while (!errorCount() && peekSortKind() == SortSectionPolicy::Default) {
- StringRef s = peek().val;
- if (s == ")" || s == "EXCLUDE_FILE")
+ ScriptLexer::Token tok = peek();
+ if (tok.kind == Kind::BracektEnd || tok.kind == Kind::ExcludeFile)
break;
// Detect common mistakes when certain non-wildcard meta characters are
// used without a closing ')'.
- if (!s.empty() && strchr("(){}", s[0])) {
+ if (tok.kind == Kind::CurlyBegin || tok.kind == Kind::CurlyEnd ||
+ tok.kind == Kind::BracektBegin || tok.kind == Kind::BracektEnd) {
skip();
setError("section pattern is expected");
break;
@@ -1020,12 +1029,13 @@ OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
expect("{");
while (!errorCount() && !consume("}")) {
- StringRef tok = next().val;
+ // StringRef tok = next().val;
+ ScriptLexer::Token tok = next();
if (tok == ";") {
// Empty commands are allowed. Do nothing here.
} else if (SymbolAssignment *assign = readAssignment(tok)) {
osec->commands.push_back(assign);
- } else if (ByteCommand *data = readByteCommand(tok)) {
+ } else if (ByteCommand *data = readByteCommand(tok.val)) {
osec->commands.push_back(data);
} else if (tok == "CONSTRUCTORS") {
// CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors
@@ -1045,7 +1055,7 @@ OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
} else if (tok == "(" || tok == ")") {
setError("expected filename pattern");
} else if (peek() == "(") {
- osec->commands.push_back(readInputSectionDescription(tok));
+ osec->commands.push_back(readInputSectionDescription(tok.val));
} else {
// We have a file name and no input sections description. It is not a
// commonly used syntax, but still acceptable. In that case, all sections
@@ -1053,7 +1063,7 @@ OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
// FIXME: GNU ld permits INPUT_SECTION_FLAGS to be used here. We do not
// handle this case here as it will already have been matched by the
// case above.
- auto *isd = make<InputSectionDescription>(tok);
+ auto *isd = make<InputSectionDescription>(tok.val);
isd->sectionPatterns.push_back({{}, StringMatcher("*")});
osec->commands.push_back(isd);
}
@@ -1127,7 +1137,7 @@ SymbolAssignment *ScriptParser::readProvideHidden(bool provide, bool hidden) {
return cmd;
}
-SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
+SymbolAssignment *ScriptParser::readAssignment(ScriptLexer::Token tok) {
// Assert expression returns Dot, so this is equal to ".=."
if (tok == "ASSERT")
return make<SymbolAssignment>(".", readAssert(), 0, getCurrentLocation());
@@ -1135,28 +1145,32 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
size_t oldPos = pos;
SymbolAssignment *cmd = nullptr;
bool savedSeenRelroEnd = script->seenRelroEnd;
- const StringRef op = peek().val;
- if (op.starts_with("=")) {
- // Support = followed by an expression without whitespace.
+ ScriptLexer::Token opTok = peek();
+ if (opTok.kind == Kind::Assign || opTok.val.starts_with("=")) {
SaveAndRestore saved(inExpr, true);
- cmd = readSymbolAssignment(tok);
- } else if ((op.size() == 2 && op[1] == '=' && strchr("*/+-&^|", op[0])) ||
- op == "<<=" || op == ">>=") {
- cmd = readSymbolAssignment(tok);
- } else if (tok == "PROVIDE") {
+ cmd = readSymbolAssignment(tok.val);
+ } else if (opTok.kind == Kind::PlusAssign ||
+ opTok.kind == Kind::MinusAssign || opTok.kind == Kind::MulAssign ||
+ opTok.kind == Kind::DivAssign ||
+ opTok.kind == Kind::LeftShiftAssign ||
+ opTok.kind == Kind::RightShiftAssign ||
+ opTok.kind == Kind::AndAssign || opTok.kind == Kind::OrAssign ||
+ opTok.kind == Kind::XorAssign) {
+ cmd = readSymbolAssignment(tok.val);
+ } else if (tok.kind == Kind::Provide) {
SaveAndRestore saved(inExpr, true);
cmd = readProvideHidden(true, false);
- } else if (tok == "HIDDEN") {
+ } else if (tok.kind == Kind::Hidden) {
SaveAndRestore saved(inExpr, true);
cmd = readProvideHidden(false, true);
- } else if (tok == "PROVIDE_HIDDEN") {
+ } else if (tok.kind == Kind::ProvideHidden) {
SaveAndRestore saved(inExpr, true);
cmd = readProvideHidden(true, true);
}
if (cmd) {
cmd->dataSegmentRelroEnd = !savedSeenRelroEnd && script->seenRelroEnd;
- cmd->commandString = tok.str() + " " + joinTokens(oldPos, pos);
+ cmd->commandString = tok.val.str() + " " + joinTokens(oldPos, pos);
expect(";");
}
return cmd;
@@ -1214,7 +1228,7 @@ Expr ScriptParser::readExpr() {
return e;
}
-Expr ScriptParser::combine(StringRef op, Expr l, Expr r) {
+Expr ScriptParser::combine(ScriptLexer::Token op, Expr l, Expr r) {
if (op == "+")
return [=] { return add(l(), r()); };
if (op == "-")
@@ -1273,11 +1287,11 @@ Expr ScriptParser::combine(StringRef op, Expr l, Expr r) {
Expr ScriptParser::readExpr1(Expr lhs, int minPrec) {
while (!atEOF() && !errorCount()) {
// Read an operator and an expression.
- StringRef op1 = peek().val;
- if (precedence(op1) < minPrec)
+ ScriptLexer::Token op1Tok = peek();
+ if (precedence(op1Tok.val) < minPrec)
break;
skip();
- if (op1 == "?")
+ if (op1Tok == "?")
return readTernary(lhs);
Expr rhs = readPrimary();
@@ -1286,13 +1300,13 @@ Expr ScriptParser::readExpr1(Expr lhs, int minPrec) {
// For example, if we have read "+" and "3", and if the next
// operator is "*", then we'll evaluate 3 * ... part first.
while (!atEOF()) {
- StringRef op2 = peek().val;
- if (precedence(op2) <= precedence(op1))
+ ScriptLexer::Token op2Tok = peek();
+ if (precedence(op2Tok.val) <= precedence(op1Tok.val))
break;
- rhs = readExpr1(rhs, precedence(op2));
+ rhs = readExpr1(rhs, precedence(op2Tok.val));
}
- lhs = combine(op1, lhs, rhs);
+ lhs = combine(op1Tok, lhs, rhs);
}
return lhs;
}
@@ -1462,12 +1476,13 @@ Expr ScriptParser::readPrimary() {
return [=] { return -e().getValue(); };
}
- StringRef tok = next().val;
+ ScriptLexer::Token tok = next();
std::string location = getCurrentLocation();
// Built-in functions are parsed here.
// https://sourceware.org/binutils/docs/ld/Builtin-Functions.html.
- if (tok == "ABSOLUTE") {
+ switch (tok.kind) {
+ case Kind::Absolute: {
Expr inner = readParenExpr();
return [=] {
ExprValue i = inner();
@@ -1475,7 +1490,7 @@ Expr ScriptParser::readPrimary() {
return i;
};
}
- if (tok == "ADDR") {
+ case Kind::Addr: {
StringRef name = unquote(readParenLiteral());
OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
osec->usedInExpression = true;
@@ -1484,7 +1499,7 @@ Expr ScriptParser::readPrimary() {
return {osec, false, 0, location};
};
}
- if (tok == "ALIGN") {
+ case Kind::Align: {
expect("(");
Expr e = readExpr();
if (consume(")")) {
@@ -1500,7 +1515,7 @@ Expr ScriptParser::readPrimary() {
return v;
};
}
- if (tok == "ALIGNOF") {
+ case Kind::Alignof: {
StringRef name = unquote(readParenLiteral());
OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
return [=] {
@@ -1508,11 +1523,11 @@ Expr ScriptParser::readPrimary() {
return osec->addralign;
};
}
- if (tok == "ASSERT")
+ case Kind::Assert:
return readAssert();
- if (tok == "CONSTANT")
+ case Kind::Constant:
return readConstant();
- if (tok == "DATA_SEGMENT_ALIGN") {
+ case Kind::DataSegmentAlign: {
expect("(");
Expr e = readExpr();
expect(",");
@@ -1524,13 +1539,13 @@ Expr ScriptParser::readPrimary() {
return (script->getDot() + align - 1) & -align;
};
}
- if (tok == "DATA_SEGMENT_END") {
+ case Kind::DataSegmentEnd: {
expect("(");
expect(".");
expect(")");
return [] { return script->getDot(); };
}
- if (tok == "DATA_SEGMENT_RELRO_END") {
+ case Kind::DataSegmentRelroEnd: {
// GNU linkers implements more complicated logic to handle
// DATA_SEGMENT_RELRO_END. We instead ignore the arguments and
// just align to the next page boundary for simplicity.
@@ -1540,9 +1555,10 @@ Expr ScriptParser::readPrimary() {
readExpr();
expect(")");
script->seenRelroEnd = true;
- return [=] { return alignToPowerOf2(script->getDot(), config->maxPageSize); };
+ return
+ [=] { return alignToPowerOf2(script->getDot(), config->maxPageSize); };
}
- if (tok == "DEFINED") {
+ case Kind::Defined: {
StringRef name = unquote(readParenLiteral());
// Return 1 if s is defined. If the definition is only found in a linker
// script, it must happen before this DEFINED.
@@ -1553,7 +1569,7 @@ Expr ScriptParser::readPrimary() {
: 0;
};
}
- if (tok == "LENGTH") {
+ case Kind::Length: {
StringRef name = readParenLiteral();
if (script->memoryRegions.count(name) == 0) {
setError("memory region not defined: " + name);
@@ -1561,7 +1577,7 @@ Expr ScriptParser::readPrimary() {
}
return script->memoryRegions[name]->length;
}
- if (tok == "LOADADDR") {
+ case Kind::Loadaddr: {
StringRef name = unquote(readParenLiteral());
OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
osec->usedInExpression = true;
@@ -1570,7 +1586,7 @@ Expr ScriptParser::readPrimary() {
return osec->getLMA();
};
}
- if (tok == "LOG2CEIL") {
+ case Kind::Log2ceil: {
expect("(");
Expr a = readExpr();
expect(")");
@@ -1579,17 +1595,18 @@ Expr ScriptParser::readPrimary() {
return llvm::Log2_64_Ceil(std::max(a().getValue(), UINT64_C(1)));
};
}
- if (tok == "MAX" || tok == "MIN") {
+ case Kind::Max:
+ case Kind::Min: {
expect("(");
Expr a = readExpr();
expect(",");
Expr b = readExpr();
expect(")");
- if (tok == "MIN")
+ if (tok.kind == Kind::Min)
return [=] { return std::min(a().getValue(), b().getValue()); };
return [=] { return std::max(a().getValue(), b().getValue()); };
}
- if (tok == "ORIGIN") {
+ case Kind::Origin: {
StringRef name = readParenLiteral();
if (script->memoryRegions.count(name) == 0) {
setError("memory region not defined: " + name);
@@ -1597,7 +1614,7 @@ Expr ScriptParser::readPrimary() {
}
return script->memoryRegions[name]->origin;
}
- if (tok == "SEGMENT_START") {
+ case Kind::SegmentStart: {
expect("(");
skip();
expect(",");
@@ -1605,7 +1622,7 @@ Expr ScriptParser::readPrimary() {
expect(")");
return [=] { return e(); };
}
- if (tok == "SIZEOF") {
+ case Kind::Sizeof: {
StringRef name = unquote(readParenLiteral());
OutputSection *cmd = &script->getOrCreateOutputSection(name)->osec;
// Linker script does not create an output section if its content is empty.
@@ -1613,27 +1630,31 @@ Expr ScriptParser::readPrimary() {
// be empty.
return [=] { return cmd->size; };
}
- if (tok == "SIZEOF_HEADERS")
+ case Kind::SizeofHeaders:
return [=] { return elf::getHeaderSize(); };
- // Tok is the dot.
- if (tok == ".")
- return [=] { return script->getSymbolValue(tok, location); };
-
- // Tok is a literal number.
- if (std::optional<uint64_t> val = parseInt(tok))
- return [=] { return *val; };
-
- // Tok is a symbol name.
- if (tok.starts_with("\""))
- tok = unquote(tok);
- else if (!isValidSymbolName(tok))
- setError("malformed number: " + tok);
- if (activeProvideSym)
- script->provideMap[*activeProvideSym].push_back(tok);
- else
- script->referencedSymbols.push_back(tok);
- return [=] { return script->getSymbolValue(tok, location); };
+ default: {
+ // Tok is the dot.
+ if (tok == ".")
+ return [=] { return script->getSymbolValue(tok.val, location); };
+
+ // Tok is a literal number.
+ if (std::optional<uint64_t> val = parseInt(tok.val))
+ return [=] { return *val; };
+
+ // Tok is a symbol name.
+ StringRef tokVal = tok.val;
+ if (tokVal.starts_with("\""))
+ tokVal = unquote(tok);
+ else if (!isValidSymbolName(tokVal))
+ setError("malformed number: " + tokVal);
+ if (activeProvideSym)
+ script->provideMap[*activeProvideSym].push_back(tokVal);
+ else
+ script->referencedSymbols.push_back(tokVal);
+ return [=] { return script->getSymbolValue(tokVal, location); };
+ }
+ }
}
Expr ScriptParser::readTernary(Expr cond) {
diff --git a/lld/ELF/ScriptToken.h b/lld/ELF/ScriptToken.h
index 01b38413cad29..3ebc1032e498e 100644
--- a/lld/ELF/ScriptToken.h
+++ b/lld/ELF/ScriptToken.h
@@ -79,6 +79,7 @@ enum class Kind {
// BLOCK, // synonym for ALIGN for compatibility with older linker script
DataSegmentAlign,
DataSegmentEnd,
+ DataSegmentRelroEnd,
Defined,
Length,
Loadaddr,
@@ -134,6 +135,7 @@ enum class Kind {
Excalamation, // !
Backslash, // "\"
Slash, // /
+ Percent, // %
Greater, // >
Less, // <
Minus, // -
>From e74cfa4f9d03654c73fa2ed5e53fadb117acb8a4 Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Tue, 23 Jul 2024 17:14:04 +0000
Subject: [PATCH 5/6] [ELF] Update Lexer
---
lld/ELF/ScriptLexer.cpp | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/lld/ELF/ScriptLexer.cpp b/lld/ELF/ScriptLexer.cpp
index 8e44f38462c96..d4de18c417d8c 100644
--- a/lld/ELF/ScriptLexer.cpp
+++ b/lld/ELF/ScriptLexer.cpp
@@ -288,7 +288,7 @@ ScriptLexer::Token ScriptLexer::getOperatorToken(StringRef s) {
case '9':
return createToken(Kind::Decimal, 1);
default:
- return createToken(Kind::Identifier, 1);
+ return {Kind::Identifier, s};
}
}
@@ -424,10 +424,7 @@ std::vector<ScriptLexer::Token> ScriptLexer::tokenizeExpr(StringRef s) {
ret.push_back(getOperatorToken(s.substr(e)));
s = s.substr(e + 2);
} else {
- llvm::errs() << "s.substr(e) is " << s.substr(e, 1);
ret.push_back(getOperatorToken(s.substr(e, 1)));
- llvm::errs() << ", token.kind == "
- << static_cast<unsigned int>(ret.back().kind) << "\n";
s = s.substr(e + 1);
}
}
@@ -444,9 +441,6 @@ std::vector<ScriptLexer::Token> ScriptLexer::tokenizeExpr(StringRef s) {
//
// This function may split the current token into multiple tokens.
void ScriptLexer::maybeSplitExpr() {
- if (!inExpr || errorCount() || atEOF())
- return;
-
std::vector<Token> v = tokenizeExpr(tokens[pos].val);
if (v.size() == 1)
return;
@@ -455,14 +449,14 @@ void ScriptLexer::maybeSplitExpr() {
}
ScriptLexer::Token ScriptLexer::next() {
- maybeSplitExpr();
-
if (errorCount())
return {Kind::Error, ""};
if (atEOF()) {
setError("unexpected EOF");
return {Kind::Eof, ""};
}
+ if (inExpr)
+ maybeSplitExpr();
return tokens[pos++];
}
>From 2ad728669c382087f657632fa498c985582a71ae Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Tue, 23 Jul 2024 22:12:31 +0000
Subject: [PATCH 6/6] [ELF] Updated Kind to Tok and replaced map with
`llvm::StringMap`
---
lld/ELF/ScriptLexer.cpp | 240 ++++++++++++++++++++-------------------
lld/ELF/ScriptLexer.h | 6 +-
lld/ELF/ScriptParser.cpp | 122 ++++++++++----------
lld/ELF/ScriptToken.h | 2 +-
4 files changed, 186 insertions(+), 184 deletions(-)
diff --git a/lld/ELF/ScriptLexer.cpp b/lld/ELF/ScriptLexer.cpp
index d4de18c417d8c..ab97d54841f8c 100644
--- a/lld/ELF/ScriptLexer.cpp
+++ b/lld/ELF/ScriptLexer.cpp
@@ -33,6 +33,7 @@
#include "ScriptLexer.h"
#include "lld/Common/ErrorHandler.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
@@ -98,10 +99,10 @@ std::string ScriptLexer::joinTokens(size_t begin, size_t end) {
if (itBegin == itEnd)
return S;
- S += (*itBegin).val;
+ S += itBegin->val;
while (++itBegin != itEnd) {
S += " ";
- S += (*itBegin).val;
+ S += itBegin->val;
}
return S;
}
@@ -145,7 +146,7 @@ void ScriptLexer::tokenize(MemoryBufferRef mb) {
return;
}
- vec.push_back({Kind::Quote, s.take_front(e + 1)});
+ vec.push_back({Tok::Quote, s.take_front(e + 1)});
s = s.substr(e + 1);
continue;
}
@@ -183,99 +184,99 @@ void ScriptLexer::tokenize(MemoryBufferRef mb) {
}
ScriptLexer::Token ScriptLexer::getOperatorToken(StringRef s) {
- auto createToken = [&](Kind kind, size_t pos) -> Token {
+ auto createToken = [&](Tok kind, size_t pos) -> Token {
return {kind, s.substr(0, pos)};
};
switch (s.front()) {
case EOF:
- return createToken(Kind::Eof, 0);
+ return createToken(Tok::Eof, 0);
case '(':
- return createToken(Kind::BracektBegin, 1);
+ return createToken(Tok::BracektBegin, 1);
case ')':
- return createToken(Kind::BracektEnd, 1);
+ return createToken(Tok::BracektEnd, 1);
case '{':
- return createToken(Kind::CurlyBegin, 1);
+ return createToken(Tok::CurlyBegin, 1);
case '}':
- return createToken(Kind::CurlyEnd, 1);
+ return createToken(Tok::CurlyEnd, 1);
case ';':
- return createToken(Kind::Semicolon, 1);
+ return createToken(Tok::Semicolon, 1);
case ',':
- return createToken(Kind::Comma, 1);
+ return createToken(Tok::Comma, 1);
case ':':
- return createToken(Kind::Colon, 1);
+ return createToken(Tok::Colon, 1);
case '?':
- return createToken(Kind::Question, 1);
+ return createToken(Tok::Question, 1);
case '%':
- return createToken(Kind::Percent, 1);
+ return createToken(Tok::Percent, 1);
case '!':
if (s.size() > 1 && s[1] == '=')
- return createToken(Kind::NotEqual, 2);
- return createToken(Kind::Excalamation, 1);
+ return createToken(Tok::NotEqual, 2);
+ return createToken(Tok::Excalamation, 1);
case '*':
if (s.size() > 1 && s[1] == '=')
- return createToken(Kind::MulAssign, 2);
- return createToken(Kind::Asterisk, 1);
+ return createToken(Tok::MulAssign, 2);
+ return createToken(Tok::Asterisk, 1);
case '/':
if (s.size() > 1 && s[1] == '=')
- return createToken(Kind::DivAssign, 2);
- return createToken(Kind::Slash, 1);
+ return createToken(Tok::DivAssign, 2);
+ return createToken(Tok::Slash, 1);
case '=':
if (s.size() > 1 && s[1] == '=')
- return createToken(Kind::Equal, 2);
- return createToken(Kind::Assign, 1);
+ return createToken(Tok::Equal, 2);
+ return createToken(Tok::Assign, 1);
case '+':
if (s.size() > 1 && s[1] == '=')
- return createToken(Kind::PlusAssign, 2);
- return createToken(Kind::Plus, 1);
+ return createToken(Tok::PlusAssign, 2);
+ return createToken(Tok::Plus, 1);
case '-':
if (s.size() > 1 && s[1] == '=')
- return createToken(Kind::MinusAssign, 2);
- return createToken(Kind::Minus, 1);
+ return createToken(Tok::MinusAssign, 2);
+ return createToken(Tok::Minus, 1);
case '<':
if (s.size() > 2 && s[1] == s[0] && s[2] == '=')
- return createToken(Kind::LeftShiftAssign, 3);
+ return createToken(Tok::LeftShiftAssign, 3);
if (s.size() > 1) {
if (s[1] == '=')
- return createToken(Kind::LessEqual, 2);
+ return createToken(Tok::LessEqual, 2);
if (s[1] == '<')
- return createToken(Kind::LeftShift, 2);
+ return createToken(Tok::LeftShift, 2);
}
- return createToken(Kind::Less, 1);
+ return createToken(Tok::Less, 1);
case '>':
if (s.size() > 2 && s[1] == s[0] && s[2] == '=')
- return createToken(Kind::RightShiftAssign, 3);
+ return createToken(Tok::RightShiftAssign, 3);
if (s.size() > 1) {
if (s[1] == '=')
- return createToken(Kind::GreaterEqual, 2);
+ return createToken(Tok::GreaterEqual, 2);
if (s[1] == '>')
- return createToken(Kind::RightShift, 2);
+ return createToken(Tok::RightShift, 2);
}
- return createToken(Kind::Greater, 1);
+ return createToken(Tok::Greater, 1);
case '&':
if (s.size() > 1) {
if (s[1] == '=')
- return createToken(Kind::AndAssign, 2);
+ return createToken(Tok::AndAssign, 2);
if (s[1] == '&')
- return createToken(Kind::AndGate, 2);
+ return createToken(Tok::AndGate, 2);
}
- return createToken(Kind::Bitwise, 1);
+ return createToken(Tok::Bitwise, 1);
case '^':
if (s.size() > 1 && s[1] == '=')
- return createToken(Kind::XorAssign, 2);
- return createToken(Kind::Xor, 1);
+ return createToken(Tok::XorAssign, 2);
+ return createToken(Tok::Xor, 1);
case '|':
if (s.size() > 1) {
if (s[1] == '=')
- return createToken(Kind::OrAssign, 2);
+ return createToken(Tok::OrAssign, 2);
if (s[1] == '|')
- return createToken(Kind::OrGate, 2);
+ return createToken(Tok::OrGate, 2);
}
- return createToken(Kind::Or, 1);
+ return createToken(Tok::Or, 1);
case '.':
- return createToken(Kind::Dot, 1);
+ return createToken(Tok::Dot, 1);
case '_':
- return createToken(Kind::Underscore, 1);
+ return createToken(Tok::Underscore, 1);
case '0':
case '1':
case '2':
@@ -286,81 +287,82 @@ ScriptLexer::Token ScriptLexer::getOperatorToken(StringRef s) {
case '7':
case '8':
case '9':
- return createToken(Kind::Decimal, 1);
+ return createToken(Tok::Decimal, 1);
default:
- return {Kind::Identifier, s};
+ return {Tok::Identifier, s};
}
}
+const llvm::StringMap<Tok> ScriptLexer::keywordTokMap = {
+ {"ENTRY", Tok::Entry},
+ {"INPUT", Tok::Input},
+ {"GROUP", Tok::Group},
+ {"INCLUDE", Tok::Include},
+ {"MEMORY", Tok::Memory},
+ {"OUTPUT", Tok::Output},
+ {"SEARCH_DIR", Tok::SearchDir},
+ {"STARTUP", Tok::Startup},
+ {"INSERT", Tok::Insert},
+ {"AFTER", Tok::After},
+ {"OUTPUT_FORMAT", Tok::OutputFormat},
+ {"TARGET", Tok::Target},
+ {"ASSERT", Tok::Assert},
+ {"CONSTANT", Tok::Constant},
+ {"EXTERN", Tok::Extern},
+ {"OUTPUT_ARCH", Tok::OutputArch},
+ {"NOCROSSREFS", Tok::Nocrossrefs},
+ {"NOCROSSREFS_TO", Tok::NocrossrefsTo},
+ {"PROVIDE", Tok::Provide},
+ {"HIDDEN", Tok::Hidden},
+ {"PROVIDE_HIDDEN", Tok::ProvideHidden},
+ {"SECTIONS", Tok::Sections},
+ {"BEFORE", Tok::Before},
+ {"EXCLUDE_FILE", Tok::ExcludeFile},
+ {"KEEP", Tok::Keep},
+ {"INPUT_SECTION_FLAGS", Tok::InputSectionFlags},
+ {"OVERLAY", Tok::Overlay},
+ {"NOLOAD", Tok::Noload},
+ {"COPY", Tok::Copy},
+ {"INFO", Tok::Info},
+ {"OVERWRITE_SECTIONS", Tok::OverwriteSections},
+ {"SUBALIGN", Tok::Subalign},
+ {"ONLY_IF_RO", Tok::OnlyIfRO},
+ {"ONLY_IF_RW", Tok::OnlyIfRW},
+ {"FILL", Tok::Fill},
+ {"SORT", Tok::Sort},
+ {"ABSOLUTE", Tok::Absolute},
+ {"ADDR", Tok::Addr},
+ {"ALIGN", Tok::Align},
+ {"ALIGNOF", Tok::Alignof},
+ {"DATA_SEGMENT_ALIGN", Tok::DataSegmentAlign},
+ {"DATA_SEGMENT_END", Tok::DataSegmentEnd},
+ {"DATA_SEGMENT_RELRO_END", Tok::DataSegmentRelroEnd},
+ {"DEFINED", Tok::Defined},
+ {"LENGTH", Tok::Length},
+ {"LOADADDR", Tok::Loadaddr},
+ {"LOG2CEIL", Tok::Log2ceil},
+ {"MAX", Tok::Max},
+ {"MIN", Tok::Min},
+ {"ORIGIN", Tok::Origin},
+ {"SEGMENT_START", Tok::SegmentStart},
+ {"SIZEOF", Tok::Sizeof},
+ {"SIZEOF_HEADERS", Tok::SizeofHeaders},
+ {"FILEHDR", Tok::Filehdr},
+ {"PHDRS", Tok::Phdrs},
+ {"AT", Tok::At},
+ {"FLAGS", Tok::Flags},
+ {"VERSION", Tok::Version},
+ {"REGION_ALIAS", Tok::RegionAlias},
+ {"AS_NEEDED", Tok::AsNeeded},
+ {"CONSTRUCTORS", Tok::Constructors},
+ {"MAXPAGESIZE", Tok::Maxpagesize},
+ {"COMMONPAGESIZE", Tok::Commonpagesize}};
+
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())
+ auto it = keywordTokMap.find(s.str());
+ if (it != keywordTokMap.end())
return {it->second, s};
- return {Kind::Identifier, s};
+ return {Tok::Identifier, s};
}
// Skip leading whitespace characters or comments.
@@ -399,7 +401,7 @@ std::vector<ScriptLexer::Token> ScriptLexer::tokenizeExpr(StringRef s) {
// Quoted strings are literal strings, so we don't want to split it.
if (s.starts_with("\""))
- return {{Kind::Quote, s}};
+ return {{Tok::Quote, s}};
// Split S with operators as separators.
std::vector<ScriptLexer::Token> ret;
@@ -408,13 +410,13 @@ std::vector<ScriptLexer::Token> ScriptLexer::tokenizeExpr(StringRef s) {
// No need to split if there is no operator.
if (e == StringRef::npos) {
- ret.push_back({Kind::Identifier, s});
+ ret.push_back({Tok::Identifier, s});
break;
}
// Get a token before the operator.
if (e != 0)
- ret.push_back({Kind::Identifier, s.substr(0, e)});
+ ret.push_back({Tok::Identifier, s.substr(0, e)});
// Get the operator as a token.
// Keep !=, ==, >=, <=, << and >> operators as a single tokens.
@@ -450,10 +452,10 @@ void ScriptLexer::maybeSplitExpr() {
ScriptLexer::Token ScriptLexer::next() {
if (errorCount())
- return {Kind::Error, ""};
+ return {Tok::Error, ""};
if (atEOF()) {
setError("unexpected EOF");
- return {Kind::Eof, ""};
+ return {Tok::Eof, ""};
}
if (inExpr)
maybeSplitExpr();
@@ -463,7 +465,7 @@ ScriptLexer::Token ScriptLexer::next() {
ScriptLexer::Token ScriptLexer::peek() {
Token tok = next();
if (errorCount())
- return {Kind::Error, ""};
+ return {Tok::Error, ""};
pos = pos - 1;
return tok;
}
diff --git a/lld/ELF/ScriptLexer.h b/lld/ELF/ScriptLexer.h
index b98635ef0aeb2..3accb0cfd8129 100644
--- a/lld/ELF/ScriptLexer.h
+++ b/lld/ELF/ScriptLexer.h
@@ -11,16 +11,17 @@
#include "ScriptToken.h"
#include "lld/Common/LLVM.h"
+#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MemoryBufferRef.h"
#include <vector>
namespace lld::elf {
-
class ScriptLexer {
public:
+ static const llvm::StringMap<Tok> keywordTokMap;
struct Token {
- Kind kind;
+ Tok kind;
StringRef val;
inline bool operator==(StringRef other) { return val == other; }
@@ -44,6 +45,7 @@ class ScriptLexer {
std::vector<MemoryBufferRef> mbs;
std::vector<Token> tokens;
+ static const llvm::StringMap<Tok> keywordToMap;
std::string joinTokens(size_t begin, size_t end);
bool inExpr = false;
size_t pos = 0;
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index bae5ae3d1e7e7..86c304c291c4b 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -233,7 +233,7 @@ void ScriptParser::readVersionScriptCommand() {
while (!atEOF() && !errorCount() && peek() != "}") {
ScriptLexer::Token verTok = next();
- if (verTok.kind == Kind::CurlyBegin) {
+ if (verTok.kind == Tok::CurlyBegin) {
setError("anonymous version definition is used in "
"combination with other version definitions");
return;
@@ -252,62 +252,62 @@ void ScriptParser::readVersion() {
void ScriptParser::readLinkerScript() {
while (!atEOF()) {
ScriptLexer::Token tok = next();
- if (tok.kind == Kind::Semicolon)
+ if (tok.kind == Tok::Semicolon)
continue;
switch (tok.kind) {
- case Kind::Entry:
+ case Tok::Entry:
readEntry();
break;
- case Kind::Extern:
+ case Tok::Extern:
readExtern();
break;
- case Kind::Group:
+ case Tok::Group:
readGroup();
break;
- case Kind::Include:
+ case Tok::Include:
readInclude();
break;
- case Kind::Input:
+ case Tok::Input:
readInput();
break;
- case Kind::Memory:
+ case Tok::Memory:
readMemory();
break;
- case Kind::Output:
+ case Tok::Output:
readOutput();
break;
- case Kind::OutputArch:
+ case Tok::OutputArch:
readOutputArch();
break;
- case Kind::OutputFormat:
+ case Tok::OutputFormat:
readOutputFormat();
break;
- case Kind::OverwriteSections:
+ case Tok::OverwriteSections:
readOverwriteSections();
break;
- case Kind::Phdrs:
+ case Tok::Phdrs:
readPhdrs();
break;
- case Kind::RegionAlias:
+ case Tok::RegionAlias:
readRegionAlias();
break;
- case Kind::SearchDir:
+ case Tok::SearchDir:
readSearchDir();
break;
- case Kind::Sections:
+ case Tok::Sections:
readSections();
break;
- case Kind::Target:
+ case Tok::Target:
readTarget();
break;
- case Kind::Version:
+ case Tok::Version:
readVersion();
break;
- case Kind::Nocrossrefs:
+ case Tok::Nocrossrefs:
readNoCrossRefs(/*to=*/false);
break;
- case Kind::NocrossrefsTo:
+ case Tok::NocrossrefsTo:
readNoCrossRefs(/*to=*/true);
break;
default:
@@ -550,16 +550,16 @@ void ScriptParser::readPhdrs() {
while (!errorCount() && !consume(";")) {
ScriptLexer::Token tok = next();
switch (tok.kind) {
- case Kind::Filehdr:
+ case Tok::Filehdr:
cmd.hasFilehdr = true;
break;
- case Kind::Phdrs:
+ case Tok::Phdrs:
cmd.hasPhdrs = true;
break;
- case Kind::At:
+ case Tok::At:
cmd.lmaExpr = readParenExpr();
break;
- case Kind::Flags:
+ case Tok::Flags:
cmd.flags = readParenExpr()().getValue();
break;
default:
@@ -658,11 +658,11 @@ void ScriptParser::readSections() {
SmallVector<SectionCommand *, 0> v;
while (!errorCount() && !consume("}")) {
ScriptLexer::Token tok = next();
- if (tok.kind == Kind::Overlay) {
+ if (tok.kind == Tok::Overlay) {
for (SectionCommand *cmd : readOverlay())
v.push_back(cmd);
continue;
- } else if (tok.kind == Kind::Include) {
+ } else if (tok.kind == Tok::Include) {
readInclude();
continue;
}
@@ -786,12 +786,12 @@ SmallVector<SectionPattern, 0> ScriptParser::readInputSectionsList() {
// Break if the next token is ), EXCLUDE_FILE, or SORT*.
while (!errorCount() && peekSortKind() == SortSectionPolicy::Default) {
ScriptLexer::Token tok = peek();
- if (tok.kind == Kind::BracektEnd || tok.kind == Kind::ExcludeFile)
+ if (tok.kind == Tok::BracektEnd || tok.kind == Tok::ExcludeFile)
break;
// Detect common mistakes when certain non-wildcard meta characters are
// used without a closing ')'.
- if (tok.kind == Kind::CurlyBegin || tok.kind == Kind::CurlyEnd ||
- tok.kind == Kind::BracektBegin || tok.kind == Kind::BracektEnd) {
+ if (tok.kind == Tok::CurlyBegin || tok.kind == Tok::CurlyEnd ||
+ tok.kind == Tok::BracektBegin || tok.kind == Tok::BracektEnd) {
skip();
setError("section pattern is expected");
break;
@@ -1029,7 +1029,6 @@ OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
expect("{");
while (!errorCount() && !consume("}")) {
- // StringRef tok = next().val;
ScriptLexer::Token tok = next();
if (tok == ";") {
// Empty commands are allowed. Do nothing here.
@@ -1139,31 +1138,30 @@ SymbolAssignment *ScriptParser::readProvideHidden(bool provide, bool hidden) {
SymbolAssignment *ScriptParser::readAssignment(ScriptLexer::Token tok) {
// Assert expression returns Dot, so this is equal to ".=."
- if (tok == "ASSERT")
+ if (tok.kind == Tok::Assert)
return make<SymbolAssignment>(".", readAssert(), 0, getCurrentLocation());
size_t oldPos = pos;
SymbolAssignment *cmd = nullptr;
bool savedSeenRelroEnd = script->seenRelroEnd;
ScriptLexer::Token opTok = peek();
- if (opTok.kind == Kind::Assign || opTok.val.starts_with("=")) {
+ if (opTok.val.starts_with("=")) {
SaveAndRestore saved(inExpr, true);
cmd = readSymbolAssignment(tok.val);
- } else if (opTok.kind == Kind::PlusAssign ||
- opTok.kind == Kind::MinusAssign || opTok.kind == Kind::MulAssign ||
- opTok.kind == Kind::DivAssign ||
- opTok.kind == Kind::LeftShiftAssign ||
- opTok.kind == Kind::RightShiftAssign ||
- opTok.kind == Kind::AndAssign || opTok.kind == Kind::OrAssign ||
- opTok.kind == Kind::XorAssign) {
+ } else if (opTok.kind == Tok::PlusAssign || opTok.kind == Tok::MinusAssign ||
+ opTok.kind == Tok::MulAssign || opTok.kind == Tok::DivAssign ||
+ opTok.kind == Tok::LeftShiftAssign ||
+ opTok.kind == Tok::RightShiftAssign ||
+ opTok.kind == Tok::AndAssign || opTok.kind == Tok::OrAssign ||
+ opTok.kind == Tok::XorAssign) {
cmd = readSymbolAssignment(tok.val);
- } else if (tok.kind == Kind::Provide) {
+ } else if (tok.kind == Tok::Provide) {
SaveAndRestore saved(inExpr, true);
cmd = readProvideHidden(true, false);
- } else if (tok.kind == Kind::Hidden) {
+ } else if (tok.kind == Tok::Hidden) {
SaveAndRestore saved(inExpr, true);
cmd = readProvideHidden(false, true);
- } else if (tok.kind == Kind::ProvideHidden) {
+ } else if (tok.kind == Tok::ProvideHidden) {
SaveAndRestore saved(inExpr, true);
cmd = readProvideHidden(true, true);
}
@@ -1482,7 +1480,7 @@ Expr ScriptParser::readPrimary() {
// Built-in functions are parsed here.
// https://sourceware.org/binutils/docs/ld/Builtin-Functions.html.
switch (tok.kind) {
- case Kind::Absolute: {
+ case Tok::Absolute: {
Expr inner = readParenExpr();
return [=] {
ExprValue i = inner();
@@ -1490,7 +1488,7 @@ Expr ScriptParser::readPrimary() {
return i;
};
}
- case Kind::Addr: {
+ case Tok::Addr: {
StringRef name = unquote(readParenLiteral());
OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
osec->usedInExpression = true;
@@ -1499,7 +1497,7 @@ Expr ScriptParser::readPrimary() {
return {osec, false, 0, location};
};
}
- case Kind::Align: {
+ case Tok::Align: {
expect("(");
Expr e = readExpr();
if (consume(")")) {
@@ -1515,7 +1513,7 @@ Expr ScriptParser::readPrimary() {
return v;
};
}
- case Kind::Alignof: {
+ case Tok::Alignof: {
StringRef name = unquote(readParenLiteral());
OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
return [=] {
@@ -1523,11 +1521,11 @@ Expr ScriptParser::readPrimary() {
return osec->addralign;
};
}
- case Kind::Assert:
+ case Tok::Assert:
return readAssert();
- case Kind::Constant:
+ case Tok::Constant:
return readConstant();
- case Kind::DataSegmentAlign: {
+ case Tok::DataSegmentAlign: {
expect("(");
Expr e = readExpr();
expect(",");
@@ -1539,13 +1537,13 @@ Expr ScriptParser::readPrimary() {
return (script->getDot() + align - 1) & -align;
};
}
- case Kind::DataSegmentEnd: {
+ case Tok::DataSegmentEnd: {
expect("(");
expect(".");
expect(")");
return [] { return script->getDot(); };
}
- case Kind::DataSegmentRelroEnd: {
+ case Tok::DataSegmentRelroEnd: {
// GNU linkers implements more complicated logic to handle
// DATA_SEGMENT_RELRO_END. We instead ignore the arguments and
// just align to the next page boundary for simplicity.
@@ -1558,7 +1556,7 @@ Expr ScriptParser::readPrimary() {
return
[=] { return alignToPowerOf2(script->getDot(), config->maxPageSize); };
}
- case Kind::Defined: {
+ case Tok::Defined: {
StringRef name = unquote(readParenLiteral());
// Return 1 if s is defined. If the definition is only found in a linker
// script, it must happen before this DEFINED.
@@ -1569,7 +1567,7 @@ Expr ScriptParser::readPrimary() {
: 0;
};
}
- case Kind::Length: {
+ case Tok::Length: {
StringRef name = readParenLiteral();
if (script->memoryRegions.count(name) == 0) {
setError("memory region not defined: " + name);
@@ -1577,7 +1575,7 @@ Expr ScriptParser::readPrimary() {
}
return script->memoryRegions[name]->length;
}
- case Kind::Loadaddr: {
+ case Tok::Loadaddr: {
StringRef name = unquote(readParenLiteral());
OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
osec->usedInExpression = true;
@@ -1586,7 +1584,7 @@ Expr ScriptParser::readPrimary() {
return osec->getLMA();
};
}
- case Kind::Log2ceil: {
+ case Tok::Log2ceil: {
expect("(");
Expr a = readExpr();
expect(")");
@@ -1595,18 +1593,18 @@ Expr ScriptParser::readPrimary() {
return llvm::Log2_64_Ceil(std::max(a().getValue(), UINT64_C(1)));
};
}
- case Kind::Max:
- case Kind::Min: {
+ case Tok::Max:
+ case Tok::Min: {
expect("(");
Expr a = readExpr();
expect(",");
Expr b = readExpr();
expect(")");
- if (tok.kind == Kind::Min)
+ if (tok.kind == Tok::Min)
return [=] { return std::min(a().getValue(), b().getValue()); };
return [=] { return std::max(a().getValue(), b().getValue()); };
}
- case Kind::Origin: {
+ case Tok::Origin: {
StringRef name = readParenLiteral();
if (script->memoryRegions.count(name) == 0) {
setError("memory region not defined: " + name);
@@ -1614,7 +1612,7 @@ Expr ScriptParser::readPrimary() {
}
return script->memoryRegions[name]->origin;
}
- case Kind::SegmentStart: {
+ case Tok::SegmentStart: {
expect("(");
skip();
expect(",");
@@ -1622,7 +1620,7 @@ Expr ScriptParser::readPrimary() {
expect(")");
return [=] { return e(); };
}
- case Kind::Sizeof: {
+ case Tok::Sizeof: {
StringRef name = unquote(readParenLiteral());
OutputSection *cmd = &script->getOrCreateOutputSection(name)->osec;
// Linker script does not create an output section if its content is empty.
@@ -1630,7 +1628,7 @@ Expr ScriptParser::readPrimary() {
// be empty.
return [=] { return cmd->size; };
}
- case Kind::SizeofHeaders:
+ case Tok::SizeofHeaders:
return [=] { return elf::getHeaderSize(); };
default: {
diff --git a/lld/ELF/ScriptToken.h b/lld/ELF/ScriptToken.h
index 3ebc1032e498e..3d7470b625277 100644
--- a/lld/ELF/ScriptToken.h
+++ b/lld/ELF/ScriptToken.h
@@ -15,7 +15,7 @@
namespace lld {
namespace elf {
-enum class Kind {
+enum class Tok {
Entry,
// Commands Files
More information about the llvm-commits
mailing list