[lld] [LLD] Improve linker script handing in LLD (PR #106334)
Hongyu Chen via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 29 11:40:15 PDT 2024
https://github.com/yugier updated https://github.com/llvm/llvm-project/pull/106334
>From a0da2721011d4a7054d026a93d567ec87229c3b1 Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Fri, 16 Aug 2024 18:03:58 +0000
Subject: [PATCH 01/16] [ELF] Added ScriptExpr, DynamicExpr, ConstantExpr,
BinaryExpr, and UnaryExpr
The use of `using Expr = std::function<ExprValue()>;` for representing
expressions in linker scritps. This commit plans to replace it by using
syntactic objects since the current way potentially complictaes further
analysis and transformations.
---
lld/ELF/LinkerScript.h | 57 ++++++++++++++++++++++++++++++++++++++++
lld/ELF/ScriptParser.cpp | 18 ++++++-------
2 files changed, 66 insertions(+), 9 deletions(-)
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 90090ce16de547..851a25c258d235 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -74,6 +74,63 @@ struct ExprValue {
// Later, we evaluate the expression by calling the function.
using Expr = std::function<ExprValue()>;
+class ScriptExpr {
+public:
+ enum class ExprKind : uint8_t { Constant, Dynamic, Unary, Binary };
+
+private:
+ ExprKind kind_;
+
+protected:
+ explicit ScriptExpr(ExprKind kind) : kind_(kind) {}
+
+public:
+ ExprKind getKind() const { return kind_; }
+};
+
+class ConstantExpr : public ScriptExpr {
+public:
+ ConstantExpr(ExprValue val) : ScriptExpr(ExprKind::Constant), val_(val) {}
+ ConstantExpr(uint64_t val)
+ : ScriptExpr(ExprKind::Constant), val_(ExprValue(val)) {}
+ ExprValue getVal() const { return val_; }
+
+private:
+ ExprValue val_;
+};
+
+class DynamicExpr : public ScriptExpr {
+public:
+ static DynamicExpr create(std::function<ExprValue()> impl) {
+ return DynamicExpr(impl);
+ }
+ std::function<ExprValue()> getImpl() const { return impl_; }
+
+private:
+ DynamicExpr(std::function<ExprValue()> impl)
+ : ScriptExpr(ExprKind::Dynamic), impl_(impl) {}
+ std::function<ExprValue()> impl_;
+};
+
+class UnaryExpr : public ScriptExpr {
+public:
+ static const UnaryExpr *create();
+
+private:
+ UnaryExpr() : ScriptExpr(ExprKind::Unary) {}
+};
+
+class BinaryExpr : public ScriptExpr {
+public:
+ static const BinaryExpr *create();
+
+private:
+ BinaryExpr(const ExprValue *LHS, const ExprValue *RHS)
+ : ScriptExpr(ExprKind::Binary), LHS(LHS), RHS(RHS) {}
+
+ const ExprValue *LHS, *RHS;
+};
+
// This enum is used to implement linker script SECTIONS command.
// https://sourceware.org/binutils/docs/ld/SECTIONS.html#SECTIONS
enum SectionsCommandKind {
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index bdbce396cba1f8..868ecf89141f38 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -104,8 +104,8 @@ class ScriptParser final : ScriptLexer {
SymbolAssignment *readAssignment(StringRef tok);
void readSort();
Expr readAssert();
- Expr readConstant();
- Expr getPageSize();
+ DynamicExpr readConstant();
+ DynamicExpr getPageSize();
Expr readMemoryAssignment(StringRef, StringRef, StringRef);
void readMemoryAttributes(uint32_t &flags, uint32_t &invFlags,
@@ -1322,24 +1322,24 @@ Expr ScriptParser::readExpr1(Expr lhs, int minPrec) {
return lhs;
}
-Expr ScriptParser::getPageSize() {
+DynamicExpr ScriptParser::getPageSize() {
std::string location = getCurrentLocation();
- return [=]() -> uint64_t {
+ return DynamicExpr::create([=]() -> uint64_t {
if (target)
return config->commonPageSize;
error(location + ": unable to calculate page size");
return 4096; // Return a dummy value.
- };
+ });
}
-Expr ScriptParser::readConstant() {
+DynamicExpr ScriptParser::readConstant() {
StringRef s = readParenName();
if (s == "COMMONPAGESIZE")
return getPageSize();
if (s == "MAXPAGESIZE")
- return [] { return config->maxPageSize; };
+ return DynamicExpr::create([] { return config->maxPageSize; });
setError("unknown constant: " + s);
- return [] { return 0; };
+ return DynamicExpr::create([] { return 0; });
}
// Parses Tok as an integer. It recognizes hexadecimal (prefixed with
@@ -1537,7 +1537,7 @@ Expr ScriptParser::readPrimary() {
if (tok == "ASSERT")
return readAssert();
if (tok == "CONSTANT")
- return readConstant();
+ return readConstant().getImpl();
if (tok == "DATA_SEGMENT_ALIGN") {
expect("(");
Expr e = readExpr();
>From a999c4f51b9dc138d8ecf8dfda84675e3aea9639 Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Sun, 18 Aug 2024 23:53:08 +0000
Subject: [PATCH 02/16] [ELF] Updated ScriptExpr subclasses
---
lld/ELF/LinkerScript.cpp | 11 +++++++++++
lld/ELF/LinkerScript.h | 10 +++++++---
lld/ELF/ScriptParser.cpp | 7 ++++---
3 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 0c4ba1abb4778c..f080c375d33d4a 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -131,6 +131,17 @@ uint64_t ExprValue::getSectionOffset() const {
return getValue() - getSecAddr();
}
+std::function<ExprValue()> ScriptExpr::getExpr() const {
+ switch (kind_) {
+ case ExprKind::Constant:
+ return static_cast<const ConstantExpr *>(this)->getVal();
+ case ExprKind::Dynamic:
+ return static_cast<const DynamicExpr *>(this)->getImpl();
+ default:
+ return [] { return ExprValue(0); };
+ };
+}
+
OutputDesc *LinkerScript::createOutputSection(StringRef name,
StringRef location) {
OutputDesc *&secRef = nameToOutputSection[CachedHashStringRef(name)];
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 851a25c258d235..3c4a5e79b3a3c5 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -86,14 +86,17 @@ class ScriptExpr {
public:
ExprKind getKind() const { return kind_; }
+ std::function<ExprValue()> getExpr() const;
};
class ConstantExpr : public ScriptExpr {
public:
ConstantExpr(ExprValue val) : ScriptExpr(ExprKind::Constant), val_(val) {}
- ConstantExpr(uint64_t val)
- : ScriptExpr(ExprKind::Constant), val_(ExprValue(val)) {}
- ExprValue getVal() const { return val_; }
+ // ConstantExpr(uint64_t val)
+ // : ScriptExpr(ExprKind::Constant), val_(val) {}
+ std::function<ExprValue()> getVal() const {
+ return [=] { return val_; };
+ }
private:
ExprValue val_;
@@ -122,6 +125,7 @@ class UnaryExpr : public ScriptExpr {
class BinaryExpr : public ScriptExpr {
public:
+ enum class Opcode { LNot, Minus, Not, Plus };
static const BinaryExpr *create();
private:
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 868ecf89141f38..7989862786aa05 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -104,7 +104,7 @@ class ScriptParser final : ScriptLexer {
SymbolAssignment *readAssignment(StringRef tok);
void readSort();
Expr readAssert();
- DynamicExpr readConstant();
+ ScriptExpr readConstant();
DynamicExpr getPageSize();
Expr readMemoryAssignment(StringRef, StringRef, StringRef);
@@ -1332,13 +1332,14 @@ DynamicExpr ScriptParser::getPageSize() {
});
}
-DynamicExpr ScriptParser::readConstant() {
+ScriptExpr ScriptParser::readConstant() {
StringRef s = readParenName();
if (s == "COMMONPAGESIZE")
return getPageSize();
if (s == "MAXPAGESIZE")
return DynamicExpr::create([] { return config->maxPageSize; });
setError("unknown constant: " + s);
+ // return ConstantExpr(ExprValue(0));
return DynamicExpr::create([] { return 0; });
}
@@ -1537,7 +1538,7 @@ Expr ScriptParser::readPrimary() {
if (tok == "ASSERT")
return readAssert();
if (tok == "CONSTANT")
- return readConstant().getImpl();
+ return readConstant().getExpr();
if (tok == "DATA_SEGMENT_ALIGN") {
expect("(");
Expr e = readExpr();
>From 4264e8193b0e440b05e269fbe451685ab62259fe Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Wed, 21 Aug 2024 21:37:05 +0000
Subject: [PATCH 03/16] [ELF] Updated function return type from ScriptExpr to
ScriptExpr*
Otherwise, we have error because of type slicing
---
lld/ELF/LinkerScript.cpp | 9 +++++++--
lld/ELF/LinkerScript.h | 16 ++++++++--------
lld/ELF/ScriptParser.cpp | 18 +++++++++---------
3 files changed, 24 insertions(+), 19 deletions(-)
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index f080c375d33d4a..3d8696260af20a 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -132,11 +132,16 @@ uint64_t ExprValue::getSectionOffset() const {
}
std::function<ExprValue()> ScriptExpr::getExpr() const {
+ // llvm::errs() << "getExpr: " << static_cast<int>(kind_) << ", " <<
+ // reinterpret_cast<uintptr_t>(this) << "\n";
switch (kind_) {
case ExprKind::Constant:
return static_cast<const ConstantExpr *>(this)->getVal();
- case ExprKind::Dynamic:
- return static_cast<const DynamicExpr *>(this)->getImpl();
+ case ExprKind::Dynamic: {
+ auto expr = static_cast<const DynamicExpr *>(this);
+ // llvm::errs() << "expr = " <<
+ return expr->getImpl();
+ }
default:
return [] { return ExprValue(0); };
};
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 3c4a5e79b3a3c5..5d2d56663d9b9e 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -13,6 +13,7 @@
#include "InputSection.h"
#include "Writer.h"
#include "lld/Common/LLVM.h"
+#include "lld/Common/Memory.h"
#include "lld/Common/Strings.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
@@ -91,9 +92,8 @@ class ScriptExpr {
class ConstantExpr : public ScriptExpr {
public:
- ConstantExpr(ExprValue val) : ScriptExpr(ExprKind::Constant), val_(val) {}
- // ConstantExpr(uint64_t val)
- // : ScriptExpr(ExprKind::Constant), val_(val) {}
+ // ConstantExpr(ExprValue val) : ScriptExpr(ExprKind::Constant), val_(val) {}
+ ConstantExpr(uint64_t val) : ScriptExpr(ExprKind::Constant), val_(val) {}
std::function<ExprValue()> getVal() const {
return [=] { return val_; };
}
@@ -104,14 +104,14 @@ class ConstantExpr : public ScriptExpr {
class DynamicExpr : public ScriptExpr {
public:
- static DynamicExpr create(std::function<ExprValue()> impl) {
- return DynamicExpr(impl);
- }
+ // static DynamicExpr create(std::function<ExprValue()> impl) {
+ // return DynamicExpr(impl);
+ // }
std::function<ExprValue()> getImpl() const { return impl_; }
-
-private:
DynamicExpr(std::function<ExprValue()> impl)
: ScriptExpr(ExprKind::Dynamic), impl_(impl) {}
+
+private:
std::function<ExprValue()> impl_;
};
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 7989862786aa05..93bcf8c0e8bfd6 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -104,8 +104,8 @@ class ScriptParser final : ScriptLexer {
SymbolAssignment *readAssignment(StringRef tok);
void readSort();
Expr readAssert();
- ScriptExpr readConstant();
- DynamicExpr getPageSize();
+ ScriptExpr *readConstant();
+ DynamicExpr *getPageSize();
Expr readMemoryAssignment(StringRef, StringRef, StringRef);
void readMemoryAttributes(uint32_t &flags, uint32_t &invFlags,
@@ -1322,9 +1322,9 @@ Expr ScriptParser::readExpr1(Expr lhs, int minPrec) {
return lhs;
}
-DynamicExpr ScriptParser::getPageSize() {
+DynamicExpr *ScriptParser::getPageSize() {
std::string location = getCurrentLocation();
- return DynamicExpr::create([=]() -> uint64_t {
+ return make<DynamicExpr>([=]() -> uint64_t {
if (target)
return config->commonPageSize;
error(location + ": unable to calculate page size");
@@ -1332,15 +1332,15 @@ DynamicExpr ScriptParser::getPageSize() {
});
}
-ScriptExpr ScriptParser::readConstant() {
+ScriptExpr *ScriptParser::readConstant() {
StringRef s = readParenName();
if (s == "COMMONPAGESIZE")
return getPageSize();
if (s == "MAXPAGESIZE")
- return DynamicExpr::create([] { return config->maxPageSize; });
+ return make<DynamicExpr>([] { return config->maxPageSize; });
setError("unknown constant: " + s);
- // return ConstantExpr(ExprValue(0));
- return DynamicExpr::create([] { return 0; });
+ return make<ConstantExpr>(0);
+ // return DynamicExpr::create([] {return 0;});
}
// Parses Tok as an integer. It recognizes hexadecimal (prefixed with
@@ -1538,7 +1538,7 @@ Expr ScriptParser::readPrimary() {
if (tok == "ASSERT")
return readAssert();
if (tok == "CONSTANT")
- return readConstant().getExpr();
+ return readConstant()->getExpr();
if (tok == "DATA_SEGMENT_ALIGN") {
expect("(");
Expr e = readExpr();
>From e1e7d3dc0e1823035f9744c15a60d6253b158b75 Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Fri, 23 Aug 2024 05:18:54 +0000
Subject: [PATCH 04/16] [ELF] Replace all Expr to ScriptExpr*
UnaryExpr and BinaryExpr will be added once we can run all with
DynamicExpr successfully. This change contains bugs that do not pass
most LTO tests.
---
lld/ELF/LinkerScript.cpp | 38 +++--
lld/ELF/LinkerScript.h | 35 ++--
lld/ELF/OutputSections.cpp | 3 +-
lld/ELF/OutputSections.h | 8 +-
lld/ELF/ScriptParser.cpp | 317 +++++++++++++++++++++----------------
lld/ELF/Writer.cpp | 17 +-
6 files changed, 247 insertions(+), 171 deletions(-)
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 3d8696260af20a..e7ebf90aa1a0ea 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -136,7 +136,7 @@ std::function<ExprValue()> ScriptExpr::getExpr() const {
// reinterpret_cast<uintptr_t>(this) << "\n";
switch (kind_) {
case ExprKind::Constant:
- return static_cast<const ConstantExpr *>(this)->getVal();
+ return static_cast<const ConstantExpr *>(this)->getExpr();
case ExprKind::Dynamic: {
auto expr = static_cast<const DynamicExpr *>(this);
// llvm::errs() << "expr = " <<
@@ -147,6 +147,22 @@ std::function<ExprValue()> ScriptExpr::getExpr() const {
};
}
+ExprValue ScriptExpr::getExprValue() const {
+ switch (kind_) {
+ case ExprKind::Constant:
+ return static_cast<const ConstantExpr *>(this)->getExprValue();
+ case ExprKind::Dynamic:
+ return static_cast<const DynamicExpr *>(this)->getImpl()();
+ default:
+ return ExprValue(0);
+ }
+}
+
+uint64_t ScriptExpr::getExprValueAlignValue() const {
+ auto e = getExprValue();
+ return e.getValue();
+}
+
OutputDesc *LinkerScript::createOutputSection(StringRef name,
StringRef location) {
OutputDesc *&secRef = nameToOutputSection[CachedHashStringRef(name)];
@@ -189,8 +205,8 @@ void LinkerScript::expandOutputSection(uint64_t size) {
expandMemoryRegions(size);
}
-void LinkerScript::setDot(Expr e, const Twine &loc, bool inSec) {
- uint64_t val = e().getValue();
+void LinkerScript::setDot(ScriptExpr *e, const Twine &loc, bool inSec) {
+ uint64_t val = e->getExprValueAlignValue();
// If val is smaller and we are in an output section, record the error and
// report it if this is the last assignAddresses iteration. dot may be smaller
// if there is another assignAddresses iteration.
@@ -225,7 +241,7 @@ void LinkerScript::addSymbol(SymbolAssignment *cmd) {
return;
// Define a symbol.
- ExprValue value = cmd->expression();
+ ExprValue value = cmd->expression->getExprValue();
SectionBase *sec = value.isAbsolute() ? nullptr : value.sec;
uint8_t visibility = cmd->hidden ? STV_HIDDEN : STV_DEFAULT;
@@ -394,7 +410,7 @@ void LinkerScript::assignSymbol(SymbolAssignment *cmd, bool inSec) {
if (!cmd->sym)
return;
- ExprValue v = cmd->expression();
+ ExprValue v = cmd->expression->getExprValue();
if (v.isAbsolute()) {
cmd->sym->section = nullptr;
cmd->sym->value = v.getValue();
@@ -735,7 +751,7 @@ void LinkerScript::processSectionCommands() {
// is given, input sections are aligned to that value, whether the
// given value is larger or smaller than the original section alignment.
if (osec->subalignExpr) {
- uint32_t subalign = osec->subalignExpr().getValue();
+ uint32_t subalign = osec->subalignExpr->getExprValueAlignValue();
for (InputSectionBase *s : v)
s->addralign = subalign;
}
@@ -1190,7 +1206,7 @@ bool LinkerScript::assignOffsets(OutputSection *sec) {
// heuristics described in
// https://sourceware.org/binutils/docs/ld/Output-Section-LMA.html
if (sec->lmaExpr) {
- state->lmaOffset = sec->lmaExpr().getValue() - dot;
+ state->lmaOffset = sec->lmaExpr->getExprValueAlignValue() - dot;
} else if (MemoryRegion *mr = sec->lmaRegion) {
uint64_t lmaStart = alignToPowerOf2(mr->curPos, sec->addralign);
if (mr->curPos < lmaStart)
@@ -1342,8 +1358,8 @@ void LinkerScript::adjustOutputSections() {
// Handle align (e.g. ".foo : ALIGN(16) { ... }").
if (sec->alignExpr)
- sec->addralign =
- std::max<uint32_t>(sec->addralign, sec->alignExpr().getValue());
+ sec->addralign = std::max<uint32_t>(
+ sec->addralign, sec->alignExpr->getExprValueAlignValue());
bool isEmpty = (getFirstInputSection(sec) == nullptr);
bool discardable = isEmpty && isDiscardable(*sec);
@@ -1489,7 +1505,7 @@ void LinkerScript::allocateHeaders(SmallVector<PhdrEntry *, 0> &phdrs) {
LinkerScript::AddressState::AddressState() {
for (auto &mri : script->memoryRegions) {
MemoryRegion *mr = mri.second;
- mr->curPos = (mr->origin)().getValue();
+ mr->curPos = (mr->origin)->getExprValueAlignValue();
}
}
@@ -1660,7 +1676,7 @@ SmallVector<PhdrEntry *, 0> LinkerScript::createPhdrs() {
phdr->add(ctx.out.programHeaders);
if (cmd.lmaExpr) {
- phdr->p_paddr = cmd.lmaExpr().getValue();
+ phdr->p_paddr = cmd.lmaExpr->getExprValueAlignValue();
phdr->hasLMA = true;
}
ret.push_back(phdr);
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 5d2d56663d9b9e..de4852b7fa168f 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -88,15 +88,18 @@ class ScriptExpr {
public:
ExprKind getKind() const { return kind_; }
std::function<ExprValue()> getExpr() const;
+ ExprValue getExprValue() const;
+ uint64_t getExprValueAlignValue() const;
};
class ConstantExpr : public ScriptExpr {
public:
// ConstantExpr(ExprValue val) : ScriptExpr(ExprKind::Constant), val_(val) {}
ConstantExpr(uint64_t val) : ScriptExpr(ExprKind::Constant), val_(val) {}
- std::function<ExprValue()> getVal() const {
+ std::function<ExprValue()> getExpr() const {
return [=] { return val_; };
}
+ ExprValue getExprValue() const { return val_; }
private:
ExprValue val_;
@@ -152,7 +155,8 @@ struct SectionCommand {
// This represents ". = <expr>" or "<symbol> = <expr>".
struct SymbolAssignment : SectionCommand {
- SymbolAssignment(StringRef name, Expr e, unsigned symOrder, std::string loc)
+ SymbolAssignment(StringRef name, ScriptExpr *e, unsigned symOrder,
+ std::string loc)
: SectionCommand(AssignmentKind), name(name), expression(e),
symOrder(symOrder), location(loc) {}
@@ -165,7 +169,7 @@ struct SymbolAssignment : SectionCommand {
Defined *sym = nullptr;
// The RHS of an expression.
- Expr expression;
+ ScriptExpr *expression;
// Command attributes for PROVIDE, HIDDEN and PROVIDE_HIDDEN.
bool provide = false;
@@ -200,14 +204,15 @@ enum class ConstraintKind { NoConstraint, ReadOnly, ReadWrite };
// target memory. Instances of the struct are created by parsing the
// MEMORY command.
struct MemoryRegion {
- MemoryRegion(StringRef name, Expr origin, Expr length, uint32_t flags,
- uint32_t invFlags, uint32_t negFlags, uint32_t negInvFlags)
+ MemoryRegion(StringRef name, ScriptExpr *origin, ScriptExpr *length,
+ uint32_t flags, uint32_t invFlags, uint32_t negFlags,
+ uint32_t negInvFlags)
: name(std::string(name)), origin(origin), length(length), flags(flags),
invFlags(invFlags), negFlags(negFlags), negInvFlags(negInvFlags) {}
std::string name;
- Expr origin;
- Expr length;
+ ScriptExpr *origin = nullptr;
+ ScriptExpr *length = nullptr;
// A section can be assigned to the region if any of these ELF section flags
// are set...
uint32_t flags;
@@ -222,8 +227,12 @@ struct MemoryRegion {
uint32_t negInvFlags;
uint64_t curPos = 0;
- uint64_t getOrigin() const { return origin().getValue(); }
- uint64_t getLength() const { return length().getValue(); }
+ uint64_t getOrigin() const {
+ return origin ? origin->getExprValueAlignValue() : 0;
+ }
+ uint64_t getLength() const {
+ return length ? length->getExprValueAlignValue() : 0;
+ }
bool compatibleWith(uint32_t secFlags) const {
if ((secFlags & negFlags) || (~secFlags & negInvFlags))
@@ -303,7 +312,7 @@ class InputSectionDescription : public SectionCommand {
// Represents BYTE(), SHORT(), LONG(), or QUAD().
struct ByteCommand : SectionCommand {
- ByteCommand(Expr e, unsigned size, std::string commandString)
+ ByteCommand(ScriptExpr *e, unsigned size, std::string commandString)
: SectionCommand(ByteKind), commandString(commandString), expression(e),
size(size) {}
@@ -312,7 +321,7 @@ struct ByteCommand : SectionCommand {
// Keeps string representing the command. Used for -Map" is perhaps better.
std::string commandString;
- Expr expression;
+ ScriptExpr *expression;
// This is just an offset of this assignment command in the output section.
unsigned offset;
@@ -343,7 +352,7 @@ struct PhdrsCommand {
bool hasFilehdr = false;
bool hasPhdrs = false;
std::optional<unsigned> flags;
- Expr lmaExpr = nullptr;
+ ScriptExpr *lmaExpr = nullptr;
};
class LinkerScript final {
@@ -363,7 +372,7 @@ class LinkerScript final {
void addSymbol(SymbolAssignment *cmd);
void assignSymbol(SymbolAssignment *cmd, bool inSec);
- void setDot(Expr e, const Twine &loc, bool inSec);
+ void setDot(ScriptExpr *e, const Twine &loc, bool inSec);
void expandOutputSection(uint64_t size);
void expandMemoryRegions(uint64_t size);
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index c076f442558fac..bbf8b4f23aaf2f 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -558,7 +558,8 @@ void OutputSection::writeTo(uint8_t *buf, parallel::TaskGroup &tg) {
if (auto *data = dyn_cast<ByteCommand>(cmd)) {
if (!std::exchange(written, true))
fn(0, numSections);
- writeInt(buf + data->offset, data->expression().getValue(), data->size);
+ writeInt(buf + data->offset, data->expression->getExprValueAlignValue(),
+ data->size);
}
if (written || !numSections)
return;
diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h
index 909b284a75a2ef..d308ae1c3cc25f 100644
--- a/lld/ELF/OutputSections.h
+++ b/lld/ELF/OutputSections.h
@@ -80,10 +80,10 @@ class OutputSection final : public SectionBase {
// The following members are normally only used in linker scripts.
MemoryRegion *memRegion = nullptr;
MemoryRegion *lmaRegion = nullptr;
- Expr addrExpr;
- Expr alignExpr;
- Expr lmaExpr;
- Expr subalignExpr;
+ ScriptExpr *addrExpr;
+ ScriptExpr *alignExpr;
+ ScriptExpr *lmaExpr;
+ ScriptExpr *subalignExpr;
// Used by non-alloc SHT_CREL to hold the header and content byte stream.
uint64_t crelHeader = 0;
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 93bcf8c0e8bfd6..b996affa4a28d3 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -103,21 +103,21 @@ class ScriptParser final : ScriptLexer {
SymbolAssignment *readProvideHidden(bool provide, bool hidden);
SymbolAssignment *readAssignment(StringRef tok);
void readSort();
- Expr readAssert();
+ ScriptExpr *readAssert();
ScriptExpr *readConstant();
DynamicExpr *getPageSize();
- Expr readMemoryAssignment(StringRef, StringRef, StringRef);
+ ScriptExpr *readMemoryAssignment(StringRef, StringRef, StringRef);
void readMemoryAttributes(uint32_t &flags, uint32_t &invFlags,
uint32_t &negFlags, uint32_t &negInvFlags);
- Expr combine(StringRef op, Expr l, Expr r);
- Expr readExpr();
- Expr readExpr1(Expr lhs, int minPrec);
+ ScriptExpr *combine(StringRef op, ScriptExpr *l, ScriptExpr *r);
+ ScriptExpr *readExpr();
+ ScriptExpr *readExpr1(ScriptExpr *lhs, int minPrec);
StringRef readParenName();
- Expr readPrimary();
- Expr readTernary(Expr cond);
- Expr readParenExpr();
+ ScriptExpr *readPrimary();
+ ScriptExpr *readTernary(ScriptExpr *cond);
+ ScriptExpr *readParenExpr();
// For parsing version script.
SmallVector<SymbolVersion, 0> readVersionExtern();
@@ -291,7 +291,7 @@ void ScriptParser::readDefsym() {
inExpr = true;
StringRef name = readName();
expect("=");
- Expr e = readExpr();
+ ScriptExpr *e = readExpr();
if (!atEOF())
setError("EOF expected, but got " + next());
auto *cmd = make<SymbolAssignment>(
@@ -524,7 +524,8 @@ void ScriptParser::readPhdrs() {
else if (consume("AT"))
cmd.lmaExpr = readParenExpr();
else if (consume("FLAGS"))
- cmd.flags = readParenExpr()().getValue();
+ // TODO flags
+ cmd.flags = readParenExpr()->getExprValueAlignValue();
else
setError("unexpected header attribute: " + next());
}
@@ -560,17 +561,18 @@ void ScriptParser::readSearchDir() {
// linker's sections sanity check failures.
// https://sourceware.org/binutils/docs/ld/Overlay-Description.html#Overlay-Description
SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
- Expr addrExpr;
+ ScriptExpr *addrExpr;
if (consume(":")) {
- addrExpr = [] { return script->getDot(); };
+ addrExpr = make<DynamicExpr>([] { return script->getDot(); });
} else {
addrExpr = readExpr();
expect(":");
}
// When AT is omitted, LMA should equal VMA. script->getDot() when evaluating
// lmaExpr will ensure this, even if the start address is specified.
- Expr lmaExpr =
- consume("AT") ? readParenExpr() : [] { return script->getDot(); };
+ ScriptExpr *lmaExpr =
+ consume("AT") ? readParenExpr()
+ : make<DynamicExpr>([] { return script->getDot(); });
expect("{");
SmallVector<SectionCommand *, 0> v;
@@ -581,13 +583,15 @@ SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
OutputDesc *osd = readOverlaySectionDescription();
osd->osec.addrExpr = addrExpr;
if (prev) {
- osd->osec.lmaExpr = [=] { return prev->getLMA() + prev->size; };
+ osd->osec.lmaExpr =
+ make<DynamicExpr>([=] { return prev->getLMA() + prev->size; });
} else {
osd->osec.lmaExpr = lmaExpr;
// Use first section address for subsequent sections as initial addrExpr
// can be DOT. Ensure the first section, even if empty, is not discarded.
osd->osec.usedInExpression = true;
- addrExpr = [=]() -> ExprValue { return {&osd->osec, false, 0, ""}; };
+ addrExpr = make<DynamicExpr>(
+ [=]() -> ExprValue { return {&osd->osec, false, 0, ""}; });
}
v.push_back(osd);
prev = &osd->osec;
@@ -597,12 +601,13 @@ SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
// counter should be equal to the overlay base address plus size of the
// largest section seen in the overlay.
// Here we want to create the Dot assignment command to achieve that.
- Expr moveDot = [=] {
+ ScriptExpr *moveDot = make<DynamicExpr>([=] {
uint64_t max = 0;
for (SectionCommand *cmd : v)
max = std::max(max, cast<OutputDesc>(cmd)->osec.size);
- return addrExpr().getValue() + max;
- };
+ // return addrExpr().getValue() + max;
+ return addrExpr->getExprValueAlignValue() + max;
+ });
v.push_back(make<SymbolAssignment>(".", moveDot, 0, getCurrentLocation()));
return v;
}
@@ -884,18 +889,18 @@ void ScriptParser::readSort() {
expect(")");
}
-Expr ScriptParser::readAssert() {
+ScriptExpr *ScriptParser::readAssert() {
expect("(");
- Expr e = readExpr();
+ ScriptExpr *e = readExpr();
expect(",");
StringRef msg = readName();
expect(")");
- return [=] {
- if (!e().getValue())
+ return make<DynamicExpr>([=] {
+ if (!e->getExprValueAlignValue())
errorOrWarn(msg);
return script->getDot();
- };
+ });
}
#define ECase(X) \
@@ -929,7 +934,7 @@ bool ScriptParser::readSectionDirective(OutputSection *cmd, StringRef tok) {
setError("unknown section type " + value);
} else {
// Otherwise, read an expression.
- cmd->type = readExpr()().getValue();
+ cmd->type = readExpr()->getExprValueAlignValue();
}
cmd->typeIsSet = true;
} else {
@@ -971,15 +976,15 @@ void ScriptParser::readSectionAddressType(OutputSection *cmd) {
}
}
-static Expr checkAlignment(Expr e, std::string &loc) {
- return [=] {
- uint64_t alignment = std::max((uint64_t)1, e().getValue());
+static ScriptExpr *checkAlignment(ScriptExpr *e, std::string &loc) {
+ return make<DynamicExpr>([=] {
+ uint64_t alignment = std::max((uint64_t)1, e->getExprValueAlignValue());
if (!isPowerOf2_64(alignment)) {
error(loc + ": alignment must be power of 2");
return (uint64_t)1; // Return a dummy value.
}
return alignment;
- };
+ });
}
OutputDesc *ScriptParser::readOverlaySectionDescription() {
@@ -1111,7 +1116,7 @@ OutputDesc *ScriptParser::readOutputSectionDescription(StringRef outSec) {
// round brackets. We did it to resolve the ambiguity when parsing scripts like:
// SECTIONS { .foo : { ... } =120+3 /DISCARD/ : { ... } }
std::array<uint8_t, 4> ScriptParser::readFill() {
- uint64_t value = readPrimary()().val;
+ uint64_t value = readPrimary()->getExprValue().val;
if (value > UINT32_MAX)
setError("filler expression result does not fit 32-bit: 0x" +
Twine::utohexstr(value));
@@ -1193,37 +1198,37 @@ SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) {
assert(op == "=" || op == "*=" || op == "/=" || op == "+=" || op == "-=" ||
op == "&=" || op == "^=" || op == "|=" || op == "<<=" || op == ">>=");
// Note: GNU ld does not support %=.
- Expr e = readExpr();
+ ScriptExpr *e = readExpr();
if (op != "=") {
std::string loc = getCurrentLocation();
- e = [=, c = op[0]]() -> ExprValue {
+ e = make<DynamicExpr>([=, c = op[0]]() -> ExprValue {
ExprValue lhs = script->getSymbolValue(name, loc);
switch (c) {
case '*':
- return lhs.getValue() * e().getValue();
+ return lhs.getValue() * e->getExprValueAlignValue();
case '/':
- if (uint64_t rv = e().getValue())
+ if (uint64_t rv = e->getExprValueAlignValue())
return lhs.getValue() / rv;
error(loc + ": division by zero");
return 0;
case '+':
- return add(lhs, e());
+ return add(lhs, e->getExprValue());
case '-':
- return sub(lhs, e());
+ return sub(lhs, e->getExprValue());
case '<':
- return lhs.getValue() << e().getValue() % 64;
+ return lhs.getValue() << e->getExprValueAlignValue() % 64;
case '>':
- return lhs.getValue() >> e().getValue() % 64;
+ return lhs.getValue() >> e->getExprValueAlignValue() % 64;
case '&':
- return lhs.getValue() & e().getValue();
+ return lhs.getValue() & e->getExprValueAlignValue();
case '^':
- return lhs.getValue() ^ e().getValue();
+ return lhs.getValue() ^ e->getExprValueAlignValue();
case '|':
- return lhs.getValue() | e().getValue();
+ return lhs.getValue() | e->getExprValueAlignValue();
default:
llvm_unreachable("");
}
- };
+ });
}
return make<SymbolAssignment>(name, e, ctx.scriptSymOrderCounter++,
getCurrentLocation());
@@ -1231,71 +1236,98 @@ SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) {
// This is an operator-precedence parser to parse a linker
// script expression.
-Expr ScriptParser::readExpr() {
+ScriptExpr *ScriptParser::readExpr() {
// Our lexer is context-aware. Set the in-expression bit so that
// they apply different tokenization rules.
SaveAndRestore saved(inExpr, true);
- Expr e = readExpr1(readPrimary(), 0);
+ ScriptExpr *e = readExpr1(readPrimary(), 0);
return e;
}
-Expr ScriptParser::combine(StringRef op, Expr l, Expr r) {
+ScriptExpr *ScriptParser::combine(StringRef op, ScriptExpr *l, ScriptExpr *r) {
if (op == "+")
- return [=] { return add(l(), r()); };
+ return make<DynamicExpr>(
+ [=] { return add(l->getExprValue(), r->getExprValue()); });
if (op == "-")
- return [=] { return sub(l(), r()); };
+ return make<DynamicExpr>(
+ [=] { return sub(l->getExprValue(), r->getExprValue()); });
if (op == "*")
- return [=] { return l().getValue() * r().getValue(); };
+ return make<DynamicExpr>([=] {
+ return l->getExprValueAlignValue() * r->getExprValueAlignValue();
+ });
if (op == "/") {
std::string loc = getCurrentLocation();
- return [=]() -> uint64_t {
- if (uint64_t rv = r().getValue())
- return l().getValue() / rv;
+ return make<DynamicExpr>([=]() -> uint64_t {
+ if (uint64_t rv = r->getExprValueAlignValue())
+ return l->getExprValueAlignValue() / rv;
error(loc + ": division by zero");
return 0;
- };
+ });
}
if (op == "%") {
std::string loc = getCurrentLocation();
- return [=]() -> uint64_t {
- if (uint64_t rv = r().getValue())
- return l().getValue() % rv;
+ return make<DynamicExpr>([=]() -> uint64_t {
+ if (uint64_t rv = r->getExprValueAlignValue())
+ return l->getExprValueAlignValue() % rv;
error(loc + ": modulo by zero");
return 0;
- };
+ });
}
if (op == "<<")
- return [=] { return l().getValue() << r().getValue() % 64; };
+ return make<DynamicExpr>([=] {
+ return l->getExprValueAlignValue() << r->getExprValueAlignValue() % 64;
+ });
if (op == ">>")
- return [=] { return l().getValue() >> r().getValue() % 64; };
+ return make<DynamicExpr>([=] {
+ return l->getExprValueAlignValue() >> r->getExprValueAlignValue() % 64;
+ });
if (op == "<")
- return [=] { return l().getValue() < r().getValue(); };
+ return make<DynamicExpr>([=] {
+ return l->getExprValueAlignValue() < r->getExprValueAlignValue();
+ });
if (op == ">")
- return [=] { return l().getValue() > r().getValue(); };
+ return make<DynamicExpr>([=] {
+ return l->getExprValueAlignValue() > r->getExprValueAlignValue();
+ });
if (op == ">=")
- return [=] { return l().getValue() >= r().getValue(); };
+ return make<DynamicExpr>([=] {
+ return l->getExprValueAlignValue() >= r->getExprValueAlignValue();
+ });
if (op == "<=")
- return [=] { return l().getValue() <= r().getValue(); };
+ return make<DynamicExpr>([=] {
+ return l->getExprValueAlignValue() <= r->getExprValueAlignValue();
+ });
if (op == "==")
- return [=] { return l().getValue() == r().getValue(); };
+ return make<DynamicExpr>([=] {
+ return l->getExprValueAlignValue() == r->getExprValueAlignValue();
+ });
if (op == "!=")
- return [=] { return l().getValue() != r().getValue(); };
+ return make<DynamicExpr>([=] {
+ return l->getExprValueAlignValue() != r->getExprValueAlignValue();
+ });
if (op == "||")
- return [=] { return l().getValue() || r().getValue(); };
+ return make<DynamicExpr>([=] {
+ return l->getExprValueAlignValue() || r->getExprValueAlignValue();
+ });
if (op == "&&")
- return [=] { return l().getValue() && r().getValue(); };
+ return make<DynamicExpr>([=] {
+ return l->getExprValueAlignValue() && r->getExprValueAlignValue();
+ });
if (op == "&")
- return [=] { return bitAnd(l(), r()); };
+ return make<DynamicExpr>(
+ [=] { return bitAnd(l->getExprValue(), r->getExprValue()); });
if (op == "^")
- return [=] { return bitXor(l(), r()); };
+ return make<DynamicExpr>(
+ [=] { return bitXor(l->getExprValue(), r->getExprValue()); });
if (op == "|")
- return [=] { return bitOr(l(), r()); };
+ return make<DynamicExpr>(
+ [=] { return bitOr(l->getExprValue(), r->getExprValue()); });
llvm_unreachable("invalid operator");
}
// This is a part of the operator-precedence parser. This function
// assumes that the remaining token stream starts with an operator.
-Expr ScriptParser::readExpr1(Expr lhs, int minPrec) {
+ScriptExpr *ScriptParser::readExpr1(ScriptExpr *lhs, int minPrec) {
while (!atEOF() && !errorCount()) {
// Read an operator and an expression.
StringRef op1 = peek();
@@ -1304,7 +1336,7 @@ Expr ScriptParser::readExpr1(Expr lhs, int minPrec) {
skip();
if (op1 == "?")
return readTernary(lhs);
- Expr rhs = readPrimary();
+ ScriptExpr *rhs = readPrimary();
// Evaluate the remaining part of the expression first if the
// next operator has greater precedence than the previous one.
@@ -1340,7 +1372,6 @@ ScriptExpr *ScriptParser::readConstant() {
return make<DynamicExpr>([] { return config->maxPageSize; });
setError("unknown constant: " + s);
return make<ConstantExpr>(0);
- // return DynamicExpr::create([] {return 0;});
}
// Parses Tok as an integer. It recognizes hexadecimal (prefixed with
@@ -1387,7 +1418,7 @@ ByteCommand *ScriptParser::readByteCommand(StringRef tok) {
return nullptr;
const char *oldS = prevTok.data();
- Expr e = readParenExpr();
+ ScriptExpr *e = readParenExpr();
std::string commandString = StringRef(oldS, curBuf.s.data() - oldS).str();
squeezeSpaces(commandString);
return make<ByteCommand>(e, size, std::move(commandString));
@@ -1472,21 +1503,22 @@ static bool isValidSymbolName(StringRef s) {
return !s.empty() && !isDigit(s[0]) && llvm::all_of(s, valid);
}
-Expr ScriptParser::readPrimary() {
+ScriptExpr *ScriptParser::readPrimary() {
if (peek() == "(")
return readParenExpr();
if (consume("~")) {
- Expr e = readPrimary();
- return [=] { return ~e().getValue(); };
+ ScriptExpr *e = readPrimary();
+ // return [=] { return ~e().getValue(); };
+ return make<DynamicExpr>([=] { return ~e->getExprValueAlignValue(); });
}
if (consume("!")) {
- Expr e = readPrimary();
- return [=] { return !e().getValue(); };
+ ScriptExpr *e = readPrimary();
+ return make<DynamicExpr>([=] { return !e->getExprValueAlignValue(); });
}
if (consume("-")) {
- Expr e = readPrimary();
- return [=] { return -e().getValue(); };
+ ScriptExpr *e = readPrimary();
+ return make<DynamicExpr>([=] { return -e->getExprValueAlignValue(); });
}
StringRef tok = next();
@@ -1495,67 +1527,69 @@ Expr ScriptParser::readPrimary() {
// Built-in functions are parsed here.
// https://sourceware.org/binutils/docs/ld/Builtin-Functions.html.
if (tok == "ABSOLUTE") {
- Expr inner = readParenExpr();
- return [=] {
- ExprValue i = inner();
+ ScriptExpr *inner = readParenExpr();
+ return make<DynamicExpr>([=] {
+ ExprValue i = inner->getExprValue();
i.forceAbsolute = true;
return i;
- };
+ });
}
if (tok == "ADDR") {
StringRef name = readParenName();
OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
osec->usedInExpression = true;
- return [=]() -> ExprValue {
+ return make<DynamicExpr>([=]() -> ExprValue {
checkIfExists(*osec, location);
return {osec, false, 0, location};
- };
+ });
}
if (tok == "ALIGN") {
expect("(");
- Expr e = readExpr();
+ ScriptExpr *e = readExpr();
if (consume(")")) {
e = checkAlignment(e, location);
- return [=] { return alignToPowerOf2(script->getDot(), e().getValue()); };
+ return make<DynamicExpr>([=] {
+ return alignToPowerOf2(script->getDot(), e->getExprValueAlignValue());
+ });
}
expect(",");
- Expr e2 = checkAlignment(readExpr(), location);
+ ScriptExpr *e2 = checkAlignment(readExpr(), location);
expect(")");
- return [=] {
- ExprValue v = e();
- v.alignment = e2().getValue();
+ return make<DynamicExpr>([=] {
+ ExprValue v = e->getExprValue();
+ v.alignment = e2->getExprValueAlignValue();
return v;
- };
+ });
}
if (tok == "ALIGNOF") {
StringRef name = readParenName();
OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
- return [=] {
+ return make<DynamicExpr>([=] {
checkIfExists(*osec, location);
return osec->addralign;
- };
+ });
}
if (tok == "ASSERT")
return readAssert();
if (tok == "CONSTANT")
- return readConstant()->getExpr();
+ return readConstant();
if (tok == "DATA_SEGMENT_ALIGN") {
expect("(");
- Expr e = readExpr();
+ ScriptExpr *e = readExpr();
expect(",");
readExpr();
expect(")");
script->seenDataAlign = true;
- return [=] {
- uint64_t align = std::max(uint64_t(1), e().getValue());
+ return make<DynamicExpr>([=] {
+ uint64_t align = std::max(uint64_t(1), e->getExprValueAlignValue());
return (script->getDot() + align - 1) & -align;
- };
+ });
}
if (tok == "DATA_SEGMENT_END") {
expect("(");
expect(".");
expect(")");
- return [] { return script->getDot(); };
+ return make<DynamicExpr>([] { return script->getDot(); });
}
if (tok == "DATA_SEGMENT_RELRO_END") {
// GNU linkers implements more complicated logic to handle
@@ -1567,70 +1601,80 @@ Expr ScriptParser::readPrimary() {
readExpr();
expect(")");
script->seenRelroEnd = true;
- return [=] { return alignToPowerOf2(script->getDot(), config->maxPageSize); };
+ return make<DynamicExpr>(
+ [=] { return alignToPowerOf2(script->getDot(), config->maxPageSize); });
}
if (tok == "DEFINED") {
StringRef name = readParenName();
// Return 1 if s is defined. If the definition is only found in a linker
// script, it must happen before this DEFINED.
auto order = ctx.scriptSymOrderCounter++;
- return [=] {
+ return make<DynamicExpr>([=] {
Symbol *s = symtab.find(name);
return s && s->isDefined() && ctx.scriptSymOrder.lookup(s) < order ? 1
: 0;
- };
+ });
}
if (tok == "LENGTH") {
StringRef name = readParenName();
if (script->memoryRegions.count(name) == 0) {
setError("memory region not defined: " + name);
- return [] { return 0; };
+ // return [] { return 0; };
+ return make<ConstantExpr>(0);
}
+ // TODO
return script->memoryRegions[name]->length;
}
if (tok == "LOADADDR") {
StringRef name = readParenName();
OutputSection *osec = &script->getOrCreateOutputSection(name)->osec;
osec->usedInExpression = true;
- return [=] {
+ return make<DynamicExpr>([=] {
checkIfExists(*osec, location);
return osec->getLMA();
- };
+ });
}
if (tok == "LOG2CEIL") {
expect("(");
- Expr a = readExpr();
+ ScriptExpr *a = readExpr();
expect(")");
- return [=] {
+ return make<DynamicExpr>([=] {
// LOG2CEIL(0) is defined to be 0.
- return llvm::Log2_64_Ceil(std::max(a().getValue(), UINT64_C(1)));
- };
+ return llvm::Log2_64_Ceil(
+ std::max(a->getExprValueAlignValue(), UINT64_C(1)));
+ });
}
if (tok == "MAX" || tok == "MIN") {
expect("(");
- Expr a = readExpr();
+ ScriptExpr *a = readExpr();
expect(",");
- Expr b = readExpr();
+ ScriptExpr *b = readExpr();
expect(")");
if (tok == "MIN")
- return [=] { return std::min(a().getValue(), b().getValue()); };
- return [=] { return std::max(a().getValue(), b().getValue()); };
+ return make<DynamicExpr>([=] {
+ return std::min(a->getExprValueAlignValue(),
+ b->getExprValueAlignValue());
+ });
+ return make<DynamicExpr>([=] {
+ return std::max(a->getExprValueAlignValue(), b->getExprValueAlignValue());
+ });
}
if (tok == "ORIGIN") {
StringRef name = readParenName();
if (script->memoryRegions.count(name) == 0) {
setError("memory region not defined: " + name);
- return [] { return 0; };
+ return make<ConstantExpr>(0);
}
+ // TODO
return script->memoryRegions[name]->origin;
}
if (tok == "SEGMENT_START") {
expect("(");
skip();
expect(",");
- Expr e = readExpr();
+ ScriptExpr *e = readExpr();
expect(")");
- return [=] { return e(); };
+ return make<DynamicExpr>([=] { return e->getExprValue(); });
}
if (tok == "SIZEOF") {
StringRef name = readParenName();
@@ -1638,18 +1682,19 @@ Expr ScriptParser::readPrimary() {
// Linker script does not create an output section if its content is empty.
// We want to allow SIZEOF(.foo) where .foo is a section which happened to
// be empty.
- return [=] { return cmd->size; };
+ return make<DynamicExpr>([=] { return cmd->size; });
}
if (tok == "SIZEOF_HEADERS")
- return [=] { return elf::getHeaderSize(); };
+ return make<DynamicExpr>([=] { return elf::getHeaderSize(); });
// Tok is the dot.
if (tok == ".")
- return [=] { return script->getSymbolValue(tok, location); };
+ return make<DynamicExpr>(
+ [=] { return script->getSymbolValue(tok, location); });
// Tok is a literal number.
if (std::optional<uint64_t> val = parseInt(tok))
- return [=] { return *val; };
+ return make<DynamicExpr>([=] { return *val; });
// Tok is a symbol name.
if (tok.starts_with("\""))
@@ -1660,19 +1705,23 @@ Expr ScriptParser::readPrimary() {
script->provideMap[*activeProvideSym].push_back(tok);
else
script->referencedSymbols.push_back(tok);
- return [=] { return script->getSymbolValue(tok, location); };
+ return make<DynamicExpr>(
+ [=] { return script->getSymbolValue(tok, location); });
}
-Expr ScriptParser::readTernary(Expr cond) {
- Expr l = readExpr();
+ScriptExpr *ScriptParser::readTernary(ScriptExpr *cond) {
+ ScriptExpr *l = readExpr();
expect(":");
- Expr r = readExpr();
- return [=] { return cond().getValue() ? l() : r(); };
+ ScriptExpr *r = readExpr();
+ return make<DynamicExpr>([=] {
+ return cond->getExprValueAlignValue() ? l->getExprValue()
+ : r->getExprValue();
+ });
}
-Expr ScriptParser::readParenExpr() {
+ScriptExpr *ScriptParser::readParenExpr() {
expect("(");
- Expr e = readExpr();
+ ScriptExpr *e = readExpr();
expect(")");
return e;
}
@@ -1811,11 +1860,11 @@ SmallVector<SymbolVersion, 0> ScriptParser::readVersionExtern() {
return ret;
}
-Expr ScriptParser::readMemoryAssignment(StringRef s1, StringRef s2,
- StringRef s3) {
+ScriptExpr *ScriptParser::readMemoryAssignment(StringRef s1, StringRef s2,
+ StringRef s3) {
if (!consume(s1) && !consume(s2) && !consume(s3)) {
setError("expected one of: " + s1 + ", " + s2 + ", or " + s3);
- return [] { return 0; };
+ return make<ConstantExpr>(0);
}
expect("=");
return readExpr();
@@ -1843,9 +1892,9 @@ void ScriptParser::readMemory() {
}
expect(":");
- Expr origin = readMemoryAssignment("ORIGIN", "org", "o");
+ ScriptExpr *origin = readMemoryAssignment("ORIGIN", "org", "o");
expect(",");
- Expr length = readMemoryAssignment("LENGTH", "len", "l");
+ ScriptExpr *length = readMemoryAssignment("LENGTH", "len", "l");
// Add the memory region to the region map.
MemoryRegion *mr = make<MemoryRegion>(tok, origin, length, flags, invFlags,
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 4c0b4df5bea170..e925a4cd1b4aab 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1911,7 +1911,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
for (OutputSection *sec : ctx.outputSections) {
auto i = config->sectionStartMap.find(sec->name);
if (i != config->sectionStartMap.end())
- sec->addrExpr = [=] { return i->second; };
+ sec->addrExpr = make<DynamicExpr>([=] { return i->second; });
}
// With the ctx.outputSections available check for GDPLT relocations
@@ -2387,7 +2387,8 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
OutputSection *cmd = p->firstSec;
if (!cmd)
return;
- cmd->alignExpr = [align = cmd->addralign]() { return align; };
+ cmd->alignExpr =
+ make<DynamicExpr>([align = cmd->addralign]() { return align; });
if (!cmd->addrExpr) {
// Prefer advancing to align(dot, maxPageSize) + dot%maxPageSize to avoid
// padding in the file contents.
@@ -2406,9 +2407,9 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
(config->zSeparate == SeparateSegmentKind::Code && prev &&
(prev->p_flags & PF_X) != (p->p_flags & PF_X)) ||
cmd->type == SHT_LLVM_PART_EHDR)
- cmd->addrExpr = [] {
+ cmd->addrExpr = make<DynamicExpr>([] {
return alignToPowerOf2(script->getDot(), config->maxPageSize);
- };
+ });
// PT_TLS is at the start of the first RW PT_LOAD. If `p` includes PT_TLS,
// it must be the RW. Align to p_align(PT_TLS) to make sure
// p_vaddr(PT_LOAD)%p_align(PT_LOAD) = 0. Otherwise, if
@@ -2423,16 +2424,16 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
// bug, musl (TLS Variant 1 architectures) before 1.1.23 handled TLS
// blocks correctly. We need to keep the workaround for a while.
else if (ctx.tlsPhdr && ctx.tlsPhdr->firstSec == p->firstSec)
- cmd->addrExpr = [] {
+ cmd->addrExpr = make<DynamicExpr>([] {
return alignToPowerOf2(script->getDot(), config->maxPageSize) +
alignToPowerOf2(script->getDot() % config->maxPageSize,
ctx.tlsPhdr->p_align);
- };
+ });
else
- cmd->addrExpr = [] {
+ cmd->addrExpr = make<DynamicExpr>([] {
return alignToPowerOf2(script->getDot(), config->maxPageSize) +
script->getDot() % config->maxPageSize;
- };
+ });
}
};
>From 2093066c7ee8c186a71791fa77503517ba79abfd Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Sat, 24 Aug 2024 00:57:37 +0000
Subject: [PATCH 05/16] [ELF] Fixed nullptr bugs for ScriptExpr* variables
This commit still contains tests failure.
---
lld/ELF/LinkerScript.cpp | 7 ++++---
lld/ELF/LinkerScript.h | 9 +++++----
lld/ELF/OutputSections.h | 8 ++++----
3 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index e7ebf90aa1a0ea..33d254a4f15e02 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -136,10 +136,9 @@ std::function<ExprValue()> ScriptExpr::getExpr() const {
// reinterpret_cast<uintptr_t>(this) << "\n";
switch (kind_) {
case ExprKind::Constant:
- return static_cast<const ConstantExpr *>(this)->getExpr();
+ return static_cast<const ConstantExpr *>(this)->getConstantExpr();
case ExprKind::Dynamic: {
auto expr = static_cast<const DynamicExpr *>(this);
- // llvm::errs() << "expr = " <<
return expr->getImpl();
}
default:
@@ -148,9 +147,11 @@ std::function<ExprValue()> ScriptExpr::getExpr() const {
}
ExprValue ScriptExpr::getExprValue() const {
+ // llvm::errs() << "getExprValue: " << static_cast<int>(kind_) << ", " <<
+ // reinterpret_cast<uintptr_t>(this) << "\n";
switch (kind_) {
case ExprKind::Constant:
- return static_cast<const ConstantExpr *>(this)->getExprValue();
+ return static_cast<const ConstantExpr *>(this)->getConstantExprValue();
case ExprKind::Dynamic:
return static_cast<const DynamicExpr *>(this)->getImpl()();
default:
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index de4852b7fa168f..e27ebb0478c326 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -96,13 +96,14 @@ class ConstantExpr : public ScriptExpr {
public:
// ConstantExpr(ExprValue val) : ScriptExpr(ExprKind::Constant), val_(val) {}
ConstantExpr(uint64_t val) : ScriptExpr(ExprKind::Constant), val_(val) {}
- std::function<ExprValue()> getExpr() const {
+ std::function<ExprValue()> getConstantExpr() const {
return [=] { return val_; };
}
- ExprValue getExprValue() const { return val_; }
+ ExprValue getConstantExprValue() const { return ExprValue(val_); }
private:
- ExprValue val_;
+ // ExprValue val_;
+ uint64_t val_;
};
class DynamicExpr : public ScriptExpr {
@@ -321,7 +322,7 @@ struct ByteCommand : SectionCommand {
// Keeps string representing the command. Used for -Map" is perhaps better.
std::string commandString;
- ScriptExpr *expression;
+ ScriptExpr *expression = nullptr;
// This is just an offset of this assignment command in the output section.
unsigned offset;
diff --git a/lld/ELF/OutputSections.h b/lld/ELF/OutputSections.h
index d308ae1c3cc25f..3e52c1920e2f90 100644
--- a/lld/ELF/OutputSections.h
+++ b/lld/ELF/OutputSections.h
@@ -80,10 +80,10 @@ class OutputSection final : public SectionBase {
// The following members are normally only used in linker scripts.
MemoryRegion *memRegion = nullptr;
MemoryRegion *lmaRegion = nullptr;
- ScriptExpr *addrExpr;
- ScriptExpr *alignExpr;
- ScriptExpr *lmaExpr;
- ScriptExpr *subalignExpr;
+ ScriptExpr *addrExpr = nullptr;
+ ScriptExpr *alignExpr = nullptr;
+ ScriptExpr *lmaExpr = nullptr;
+ ScriptExpr *subalignExpr = nullptr;
// Used by non-alloc SHT_CREL to hold the header and content byte stream.
uint64_t crelHeader = 0;
>From d6e9a525b90502b475dc8741477e8351c9d3f686 Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Mon, 26 Aug 2024 00:42:45 +0000
Subject: [PATCH 06/16] [ELF] Binary operation updated
---
lld/ELF/LinkerScript.cpp | 56 ++++++++++++++++++++++++++++++++---
lld/ELF/LinkerScript.h | 21 +++++++++----
lld/ELF/ScriptParser.cpp | 64 +++++++++-------------------------------
3 files changed, 82 insertions(+), 59 deletions(-)
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 33d254a4f15e02..1d718d598171ab 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -132,8 +132,6 @@ uint64_t ExprValue::getSectionOffset() const {
}
std::function<ExprValue()> ScriptExpr::getExpr() const {
- // llvm::errs() << "getExpr: " << static_cast<int>(kind_) << ", " <<
- // reinterpret_cast<uintptr_t>(this) << "\n";
switch (kind_) {
case ExprKind::Constant:
return static_cast<const ConstantExpr *>(this)->getConstantExpr();
@@ -147,8 +145,6 @@ std::function<ExprValue()> ScriptExpr::getExpr() const {
}
ExprValue ScriptExpr::getExprValue() const {
- // llvm::errs() << "getExprValue: " << static_cast<int>(kind_) << ", " <<
- // reinterpret_cast<uintptr_t>(this) << "\n";
switch (kind_) {
case ExprKind::Constant:
return static_cast<const ConstantExpr *>(this)->getConstantExprValue();
@@ -164,6 +160,58 @@ uint64_t ScriptExpr::getExprValueAlignValue() const {
return e.getValue();
}
+uint64_t BinaryExpr::evaluateSymbolAssignment() {
+ switch (op_[0]) {
+ case '*':
+ return LHS.getValue() * RHS.getValue();
+ case '/':
+ if (uint64_t rv = RHS.getValue())
+ return LHS.getValue() / rv;
+ error(loc_ + ": division by zero");
+ return 0;
+ // case '+':
+ }
+ return 0;
+}
+
+void BinaryExpr::moveAbsRight(ExprValue &a, ExprValue &b) {
+ if (a.sec == nullptr || (a.forceAbsolute && !b.isAbsolute()))
+ std::swap(a, b);
+ if (!b.isAbsolute())
+ script->recordError(
+ a.loc + ": at least one side of the expression must be absolute");
+}
+
+ExprValue BinaryExpr::add(ExprValue a, ExprValue b) {
+ moveAbsRight(a, b);
+ return {a.sec, a.forceAbsolute, a.getSectionOffset() + b.getValue(), a.loc};
+}
+
+ExprValue BinaryExpr::sub(ExprValue a, ExprValue b) {
+ // The distance between two symbols in sections is absolute.
+ if (!a.isAbsolute() && !b.isAbsolute())
+ return a.getValue() - b.getValue();
+ return {a.sec, false, a.getSectionOffset() - b.getValue(), a.loc};
+}
+
+ExprValue BinaryExpr::bitAnd(ExprValue a, ExprValue b) {
+ moveAbsRight(a, b);
+ return {a.sec, a.forceAbsolute,
+ (a.getValue() & b.getValue()) - a.getSecAddr(), a.loc};
+}
+
+ExprValue BinaryExpr::bitXor(ExprValue a, ExprValue b) {
+ moveAbsRight(a, b);
+ return {a.sec, a.forceAbsolute,
+ (a.getValue() ^ b.getValue()) - a.getSecAddr(), a.loc};
+}
+
+ExprValue BinaryExpr::bitOr(ExprValue a, ExprValue b) {
+ moveAbsRight(a, b);
+ return {a.sec, a.forceAbsolute,
+ (a.getValue() | b.getValue()) - a.getSecAddr(), a.loc};
+}
+
OutputDesc *LinkerScript::createOutputSection(StringRef name,
StringRef location) {
OutputDesc *&secRef = nameToOutputSection[CachedHashStringRef(name)];
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index e27ebb0478c326..25c25636f77408 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -130,13 +130,24 @@ class UnaryExpr : public ScriptExpr {
class BinaryExpr : public ScriptExpr {
public:
enum class Opcode { LNot, Minus, Not, Plus };
- static const BinaryExpr *create();
+ BinaryExpr(StringRef op, const ExprValue LHS, const ExprValue RHS,
+ const std::string loc)
+ : ScriptExpr(ExprKind::Binary), op_(op), LHS(LHS), RHS(RHS), loc_(loc) {}
+
+ uint64_t evaluateSymbolAssignment();
+ // 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);
+ static ExprValue add(ExprValue a, ExprValue b);
+ static ExprValue sub(ExprValue a, ExprValue b);
+ static ExprValue bitAnd(ExprValue a, ExprValue b);
+ static ExprValue bitXor(ExprValue a, ExprValue b);
+ static ExprValue bitOr(ExprValue a, ExprValue b);
private:
- BinaryExpr(const ExprValue *LHS, const ExprValue *RHS)
- : ScriptExpr(ExprKind::Binary), LHS(LHS), RHS(RHS) {}
-
- const ExprValue *LHS, *RHS;
+ StringRef op_;
+ const ExprValue LHS, RHS;
+ std::string loc_;
};
// This enum is used to implement linker script SECTIONS command.
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index b996affa4a28d3..756f5426971571 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -139,46 +139,6 @@ static StringRef unquote(StringRef s) {
return s;
}
-// 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) {
- if (a.sec == nullptr || (a.forceAbsolute && !b.isAbsolute()))
- std::swap(a, b);
- if (!b.isAbsolute())
- script->recordError(
- a.loc + ": at least one side of the expression must be absolute");
-}
-
-static ExprValue add(ExprValue a, ExprValue b) {
- moveAbsRight(a, b);
- return {a.sec, a.forceAbsolute, a.getSectionOffset() + b.getValue(), a.loc};
-}
-
-static ExprValue sub(ExprValue a, ExprValue b) {
- // The distance between two symbols in sections is absolute.
- if (!a.isAbsolute() && !b.isAbsolute())
- return a.getValue() - b.getValue();
- return {a.sec, false, a.getSectionOffset() - b.getValue(), a.loc};
-}
-
-static ExprValue bitAnd(ExprValue a, ExprValue b) {
- moveAbsRight(a, b);
- return {a.sec, a.forceAbsolute,
- (a.getValue() & b.getValue()) - a.getSecAddr(), a.loc};
-}
-
-static ExprValue bitXor(ExprValue a, ExprValue b) {
- moveAbsRight(a, b);
- return {a.sec, a.forceAbsolute,
- (a.getValue() ^ b.getValue()) - a.getSecAddr(), a.loc};
-}
-
-static ExprValue bitOr(ExprValue a, ExprValue b) {
- moveAbsRight(a, b);
- return {a.sec, a.forceAbsolute,
- (a.getValue() | b.getValue()) - a.getSecAddr(), a.loc};
-}
-
void ScriptParser::readDynamicList() {
expect("{");
SmallVector<SymbolVersion, 0> locals;
@@ -1203,6 +1163,7 @@ SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) {
std::string loc = getCurrentLocation();
e = make<DynamicExpr>([=, c = op[0]]() -> ExprValue {
ExprValue lhs = script->getSymbolValue(name, loc);
+ BinaryExpr *expr = make<BinaryExpr>(op, lhs, e->getExprValue(), loc);
switch (c) {
case '*':
return lhs.getValue() * e->getExprValueAlignValue();
@@ -1212,9 +1173,9 @@ SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) {
error(loc + ": division by zero");
return 0;
case '+':
- return add(lhs, e->getExprValue());
+ return BinaryExpr::add(lhs, e->getExprValue());
case '-':
- return sub(lhs, e->getExprValue());
+ return BinaryExpr::sub(lhs, e->getExprValue());
case '<':
return lhs.getValue() << e->getExprValueAlignValue() % 64;
case '>':
@@ -1247,10 +1208,10 @@ ScriptExpr *ScriptParser::readExpr() {
ScriptExpr *ScriptParser::combine(StringRef op, ScriptExpr *l, ScriptExpr *r) {
if (op == "+")
return make<DynamicExpr>(
- [=] { return add(l->getExprValue(), r->getExprValue()); });
+ [=] { return BinaryExpr::add(l->getExprValue(), r->getExprValue()); });
if (op == "-")
return make<DynamicExpr>(
- [=] { return sub(l->getExprValue(), r->getExprValue()); });
+ [=] { return BinaryExpr::sub(l->getExprValue(), r->getExprValue()); });
if (op == "*")
return make<DynamicExpr>([=] {
return l->getExprValueAlignValue() * r->getExprValueAlignValue();
@@ -1314,14 +1275,17 @@ ScriptExpr *ScriptParser::combine(StringRef op, ScriptExpr *l, ScriptExpr *r) {
return l->getExprValueAlignValue() && r->getExprValueAlignValue();
});
if (op == "&")
- return make<DynamicExpr>(
- [=] { return bitAnd(l->getExprValue(), r->getExprValue()); });
+ return make<DynamicExpr>([=] {
+ return BinaryExpr::bitAnd(l->getExprValue(), r->getExprValue());
+ });
if (op == "^")
- return make<DynamicExpr>(
- [=] { return bitXor(l->getExprValue(), r->getExprValue()); });
+ return make<DynamicExpr>([=] {
+ return BinaryExpr::bitXor(l->getExprValue(), r->getExprValue());
+ });
if (op == "|")
- return make<DynamicExpr>(
- [=] { return bitOr(l->getExprValue(), r->getExprValue()); });
+ return make<DynamicExpr>([=] {
+ return BinaryExpr::bitOr(l->getExprValue(), r->getExprValue());
+ });
llvm_unreachable("invalid operator");
}
>From d47fd4b77de29cd55f77bca4fa56614e7eadeaea Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Mon, 26 Aug 2024 20:37:28 +0000
Subject: [PATCH 07/16] [ELF] Updated BinaryExpr symbol assignmemnt
---
lld/ELF/LinkerScript.cpp | 19 +++++++++++++++++--
lld/ELF/LinkerScript.h | 2 +-
lld/ELF/ScriptParser.cpp | 26 +-------------------------
3 files changed, 19 insertions(+), 28 deletions(-)
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 1d718d598171ab..96817f8b3bd409 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -160,7 +160,7 @@ uint64_t ScriptExpr::getExprValueAlignValue() const {
return e.getValue();
}
-uint64_t BinaryExpr::evaluateSymbolAssignment() {
+ExprValue BinaryExpr::evaluateSymbolAssignment() {
switch (op_[0]) {
case '*':
return LHS.getValue() * RHS.getValue();
@@ -169,7 +169,22 @@ uint64_t BinaryExpr::evaluateSymbolAssignment() {
return LHS.getValue() / rv;
error(loc_ + ": division by zero");
return 0;
- // case '+':
+ case '+':
+ return add(LHS, RHS);
+ case '-':
+ return sub(LHS, RHS);
+ case '<':
+ return LHS.getValue() << RHS.getValue() % 64;
+ case '>':
+ return LHS.getValue() >> RHS.getValue() % 64;
+ case '&':
+ return LHS.getValue() & RHS.getValue();
+ case '^':
+ return LHS.getValue() ^ RHS.getValue();
+ case '|':
+ return LHS.getValue() | RHS.getValue();
+ default:
+ llvm_unreachable("");
}
return 0;
}
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 25c25636f77408..4967f377b037be 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -134,7 +134,7 @@ class BinaryExpr : public ScriptExpr {
const std::string loc)
: ScriptExpr(ExprKind::Binary), op_(op), LHS(LHS), RHS(RHS), loc_(loc) {}
- uint64_t evaluateSymbolAssignment();
+ ExprValue evaluateSymbolAssignment();
// 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);
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 756f5426971571..e99f53d0727fb7 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -1164,31 +1164,7 @@ SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) {
e = make<DynamicExpr>([=, c = op[0]]() -> ExprValue {
ExprValue lhs = script->getSymbolValue(name, loc);
BinaryExpr *expr = make<BinaryExpr>(op, lhs, e->getExprValue(), loc);
- switch (c) {
- case '*':
- return lhs.getValue() * e->getExprValueAlignValue();
- case '/':
- if (uint64_t rv = e->getExprValueAlignValue())
- return lhs.getValue() / rv;
- error(loc + ": division by zero");
- return 0;
- case '+':
- return BinaryExpr::add(lhs, e->getExprValue());
- case '-':
- return BinaryExpr::sub(lhs, e->getExprValue());
- case '<':
- return lhs.getValue() << e->getExprValueAlignValue() % 64;
- case '>':
- return lhs.getValue() >> e->getExprValueAlignValue() % 64;
- case '&':
- return lhs.getValue() & e->getExprValueAlignValue();
- case '^':
- return lhs.getValue() ^ e->getExprValueAlignValue();
- case '|':
- return lhs.getValue() | e->getExprValueAlignValue();
- default:
- llvm_unreachable("");
- }
+ return expr->evaluateSymbolAssignment();
});
}
return make<SymbolAssignment>(name, e, ctx.scriptSymOrderCounter++,
>From 79c6fbea3bce91812bd79fab14633fa2a3445b42 Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Tue, 27 Aug 2024 01:04:02 +0000
Subject: [PATCH 08/16] [ELF] Removed combine and updated BinaryExpr for
evaluate statements
---
lld/ELF/LinkerScript.cpp | 79 +++++++++++++++++++++++-----------
lld/ELF/LinkerScript.h | 9 ++--
lld/ELF/ScriptParser.cpp | 93 +++-------------------------------------
3 files changed, 64 insertions(+), 117 deletions(-)
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 96817f8b3bd409..cb5defd6d73e5a 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -139,6 +139,10 @@ std::function<ExprValue()> ScriptExpr::getExpr() const {
auto expr = static_cast<const DynamicExpr *>(this);
return expr->getImpl();
}
+ case ExprKind::Binary: {
+ auto expr = static_cast<const BinaryExpr *>(this);
+ return [=] { return expr->evaluateBinaryOperands(); };
+ }
default:
return [] { return ExprValue(0); };
};
@@ -150,6 +154,8 @@ ExprValue ScriptExpr::getExprValue() const {
return static_cast<const ConstantExpr *>(this)->getConstantExprValue();
case ExprKind::Dynamic:
return static_cast<const DynamicExpr *>(this)->getImpl()();
+ case ExprKind::Binary:
+ return static_cast<const BinaryExpr *>(this)->evaluateBinaryOperands();
default:
return ExprValue(0);
}
@@ -160,33 +166,58 @@ uint64_t ScriptExpr::getExprValueAlignValue() const {
return e.getValue();
}
-ExprValue BinaryExpr::evaluateSymbolAssignment() {
- switch (op_[0]) {
- case '*':
- return LHS.getValue() * RHS.getValue();
- case '/':
- if (uint64_t rv = RHS.getValue())
- return LHS.getValue() / rv;
+ExprValue BinaryExpr::evaluateBinaryOperands() const {
+ if (op_ == "+" || op_ == "+=")
+ return add(LHS->getExprValue(), RHS->getExprValue());
+ if (op_ == "-" || op_ == "-=")
+ return sub(LHS->getExprValue(), RHS->getExprValue());
+ if (op_ == "*" || op_ == "*=")
+ return LHS->getExprValueAlignValue() * RHS->getExprValueAlignValue();
+ if (op_ == "/" || op_ == "/=") {
+ if (uint64_t rv = RHS->getExprValueAlignValue())
+ return LHS->getExprValueAlignValue() / rv;
error(loc_ + ": division by zero");
return 0;
- case '+':
- return add(LHS, RHS);
- case '-':
- return sub(LHS, RHS);
- case '<':
- return LHS.getValue() << RHS.getValue() % 64;
- case '>':
- return LHS.getValue() >> RHS.getValue() % 64;
- case '&':
- return LHS.getValue() & RHS.getValue();
- case '^':
- return LHS.getValue() ^ RHS.getValue();
- case '|':
- return LHS.getValue() | RHS.getValue();
- default:
- llvm_unreachable("");
}
- return 0;
+ if (op_ == "%") {
+ if (uint64_t rv = RHS->getExprValueAlignValue())
+ return LHS->getExprValueAlignValue() % rv;
+ error(loc_ + ": modulo by zero");
+ return 0;
+ }
+ if (op_ == "<<" || op_ == "<<=")
+ return LHS->getExprValueAlignValue() << RHS->getExprValueAlignValue() % 64;
+ if (op_ == ">>" || op_ == ">>=")
+ return LHS->getExprValueAlignValue() >> RHS->getExprValueAlignValue() % 64;
+ if (op_ == "<")
+ return LHS->getExprValueAlignValue() < RHS->getExprValueAlignValue();
+ if (op_ == ">")
+ return LHS->getExprValueAlignValue() > RHS->getExprValueAlignValue();
+ if (op_ == ">=")
+ return LHS->getExprValueAlignValue() >= RHS->getExprValueAlignValue();
+ if (op_ == "<=")
+ return LHS->getExprValueAlignValue() <= RHS->getExprValueAlignValue();
+ if (op_ == "==")
+ return LHS->getExprValueAlignValue() == RHS->getExprValueAlignValue();
+ if (op_ == "!=")
+ return LHS->getExprValueAlignValue() != RHS->getExprValueAlignValue();
+ if (op_ == "||")
+ return LHS->getExprValueAlignValue() || RHS->getExprValueAlignValue();
+ if (op_ == "&&")
+ return LHS->getExprValueAlignValue() && RHS->getExprValueAlignValue();
+ if (op_ == "&")
+ return bitAnd(LHS->getExprValue(), RHS->getExprValue());
+ if (op_ == "^")
+ return bitXor(LHS->getExprValue(), RHS->getExprValue());
+ if (op_ == "|")
+ return bitOr(LHS->getExprValue(), RHS->getExprValue());
+ if (op_ == "&=")
+ return LHS->getExprValueAlignValue() & RHS->getExprValueAlignValue();
+ if (op_ == "^=")
+ return LHS->getExprValueAlignValue() ^ RHS->getExprValueAlignValue();
+ if (op_ == "|=")
+ return LHS->getExprValueAlignValue() | RHS->getExprValueAlignValue();
+ llvm_unreachable("invalid operator");
}
void BinaryExpr::moveAbsRight(ExprValue &a, ExprValue &b) {
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 4967f377b037be..4eaec397d96a19 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -129,12 +129,10 @@ class UnaryExpr : public ScriptExpr {
class BinaryExpr : public ScriptExpr {
public:
- enum class Opcode { LNot, Minus, Not, Plus };
- BinaryExpr(StringRef op, const ExprValue LHS, const ExprValue RHS,
+ BinaryExpr(StringRef op, ScriptExpr *LHS, ScriptExpr *RHS,
const std::string loc)
: ScriptExpr(ExprKind::Binary), op_(op), LHS(LHS), RHS(RHS), loc_(loc) {}
-
- ExprValue evaluateSymbolAssignment();
+ ExprValue evaluateBinaryOperands() const;
// 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);
@@ -146,7 +144,8 @@ class BinaryExpr : public ScriptExpr {
private:
StringRef op_;
- const ExprValue LHS, RHS;
+ // const ExprValue LHS, RHS;
+ const ScriptExpr *LHS, *RHS;
std::string loc_;
};
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index e99f53d0727fb7..9b1a7e8552b2f2 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -111,7 +111,6 @@ class ScriptParser final : ScriptLexer {
void readMemoryAttributes(uint32_t &flags, uint32_t &invFlags,
uint32_t &negFlags, uint32_t &negInvFlags);
- ScriptExpr *combine(StringRef op, ScriptExpr *l, ScriptExpr *r);
ScriptExpr *readExpr();
ScriptExpr *readExpr1(ScriptExpr *lhs, int minPrec);
StringRef readParenName();
@@ -1163,8 +1162,9 @@ SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) {
std::string loc = getCurrentLocation();
e = make<DynamicExpr>([=, c = op[0]]() -> ExprValue {
ExprValue lhs = script->getSymbolValue(name, loc);
- BinaryExpr *expr = make<BinaryExpr>(op, lhs, e->getExprValue(), loc);
- return expr->evaluateSymbolAssignment();
+ BinaryExpr *expr =
+ make<BinaryExpr>(op, make<DynamicExpr>([=] { return lhs; }), e, loc);
+ return expr->evaluateBinaryOperands();
});
}
return make<SymbolAssignment>(name, e, ctx.scriptSymOrderCounter++,
@@ -1181,90 +1181,6 @@ ScriptExpr *ScriptParser::readExpr() {
return e;
}
-ScriptExpr *ScriptParser::combine(StringRef op, ScriptExpr *l, ScriptExpr *r) {
- if (op == "+")
- return make<DynamicExpr>(
- [=] { return BinaryExpr::add(l->getExprValue(), r->getExprValue()); });
- if (op == "-")
- return make<DynamicExpr>(
- [=] { return BinaryExpr::sub(l->getExprValue(), r->getExprValue()); });
- if (op == "*")
- return make<DynamicExpr>([=] {
- return l->getExprValueAlignValue() * r->getExprValueAlignValue();
- });
- if (op == "/") {
- std::string loc = getCurrentLocation();
- return make<DynamicExpr>([=]() -> uint64_t {
- if (uint64_t rv = r->getExprValueAlignValue())
- return l->getExprValueAlignValue() / rv;
- error(loc + ": division by zero");
- return 0;
- });
- }
- if (op == "%") {
- std::string loc = getCurrentLocation();
- return make<DynamicExpr>([=]() -> uint64_t {
- if (uint64_t rv = r->getExprValueAlignValue())
- return l->getExprValueAlignValue() % rv;
- error(loc + ": modulo by zero");
- return 0;
- });
- }
- if (op == "<<")
- return make<DynamicExpr>([=] {
- return l->getExprValueAlignValue() << r->getExprValueAlignValue() % 64;
- });
- if (op == ">>")
- return make<DynamicExpr>([=] {
- return l->getExprValueAlignValue() >> r->getExprValueAlignValue() % 64;
- });
- if (op == "<")
- return make<DynamicExpr>([=] {
- return l->getExprValueAlignValue() < r->getExprValueAlignValue();
- });
- if (op == ">")
- return make<DynamicExpr>([=] {
- return l->getExprValueAlignValue() > r->getExprValueAlignValue();
- });
- if (op == ">=")
- return make<DynamicExpr>([=] {
- return l->getExprValueAlignValue() >= r->getExprValueAlignValue();
- });
- if (op == "<=")
- return make<DynamicExpr>([=] {
- return l->getExprValueAlignValue() <= r->getExprValueAlignValue();
- });
- if (op == "==")
- return make<DynamicExpr>([=] {
- return l->getExprValueAlignValue() == r->getExprValueAlignValue();
- });
- if (op == "!=")
- return make<DynamicExpr>([=] {
- return l->getExprValueAlignValue() != r->getExprValueAlignValue();
- });
- if (op == "||")
- return make<DynamicExpr>([=] {
- return l->getExprValueAlignValue() || r->getExprValueAlignValue();
- });
- if (op == "&&")
- return make<DynamicExpr>([=] {
- return l->getExprValueAlignValue() && r->getExprValueAlignValue();
- });
- if (op == "&")
- return make<DynamicExpr>([=] {
- return BinaryExpr::bitAnd(l->getExprValue(), r->getExprValue());
- });
- if (op == "^")
- return make<DynamicExpr>([=] {
- return BinaryExpr::bitXor(l->getExprValue(), r->getExprValue());
- });
- if (op == "|")
- return make<DynamicExpr>([=] {
- return BinaryExpr::bitOr(l->getExprValue(), r->getExprValue());
- });
- llvm_unreachable("invalid operator");
-}
-
// This is a part of the operator-precedence parser. This function
// assumes that the remaining token stream starts with an operator.
ScriptExpr *ScriptParser::readExpr1(ScriptExpr *lhs, int minPrec) {
@@ -1289,7 +1205,8 @@ ScriptExpr *ScriptParser::readExpr1(ScriptExpr *lhs, int minPrec) {
rhs = readExpr1(rhs, precedence(op2));
}
- lhs = combine(op1, lhs, rhs);
+ std::string location = getCurrentLocation();
+ lhs = make<BinaryExpr>(op1, lhs, rhs, location);
}
return lhs;
}
>From 76c91f8820838fdd4e366ac81bb9bb39d83972be Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Tue, 27 Aug 2024 20:52:04 +0000
Subject: [PATCH 09/16] [ELF] Updated BinaryExpr
---
lld/ELF/LinkerScript.cpp | 75 +++++++++++++++++++++++++++-------------
lld/ELF/LinkerScript.h | 39 +++++++++++++++++++--
2 files changed, 87 insertions(+), 27 deletions(-)
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index cb5defd6d73e5a..bc873cc7eb33d1 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -166,58 +166,85 @@ uint64_t ScriptExpr::getExprValueAlignValue() const {
return e.getValue();
}
+BinaryExpr::Op BinaryExpr::stringToOp(const StringRef op) {
+ static const std::unordered_map<llvm::StringRef, Op> opMap = {
+ {"+", Op::Add}, {"-", Op::Sub}, {"*", Op::Mul},
+ {"/", Op::Div}, {"%", Op::Mod}, {"<<", Op::Shl},
+ {">>", Op::Shr}, {"&", Op::And}, {"|", Op::Or},
+ {"^", Op::Xor}, {"&&", Op::LAnd}, {"||", Op::LOr},
+ {"==", Op::Eq}, {"!=", Op::Neq}, {"<", Op::Lt},
+ {">", Op::Gt}, {"<=", Op::Leq}, {">=", Op::Geq},
+ {"+=", Op::AddAssign}, {"-=", Op::SubAssign}, {"*=", Op::MulAssign},
+ {"/=", Op::DivAssign}, {"<<=", Op::ShlAssign}, {">>=", Op::ShrAssign},
+ {"&=", Op::AndAssign}, {"|=", Op::OrAssign}, {"^=", Op::XorAssign}};
+
+ auto it = opMap.find(op);
+ if (it != opMap.end()) {
+ return it->second;
+ }
+ return Op::Invalid;
+}
+
ExprValue BinaryExpr::evaluateBinaryOperands() const {
- if (op_ == "+" || op_ == "+=")
+ switch (opcode) {
+ case Op::Add:
+ case Op::AddAssign:
return add(LHS->getExprValue(), RHS->getExprValue());
- if (op_ == "-" || op_ == "-=")
+ case Op::Sub:
+ case Op::SubAssign:
return sub(LHS->getExprValue(), RHS->getExprValue());
- if (op_ == "*" || op_ == "*=")
+ case Op::Mul:
+ case Op::MulAssign:
return LHS->getExprValueAlignValue() * RHS->getExprValueAlignValue();
- if (op_ == "/" || op_ == "/=") {
+ case Op::Div:
+ case Op::DivAssign:
if (uint64_t rv = RHS->getExprValueAlignValue())
return LHS->getExprValueAlignValue() / rv;
error(loc_ + ": division by zero");
return 0;
- }
- if (op_ == "%") {
+ case Op::Mod:
if (uint64_t rv = RHS->getExprValueAlignValue())
return LHS->getExprValueAlignValue() % rv;
error(loc_ + ": modulo by zero");
return 0;
- }
- if (op_ == "<<" || op_ == "<<=")
+ case Op::Shl:
+ case Op::ShlAssign:
return LHS->getExprValueAlignValue() << RHS->getExprValueAlignValue() % 64;
- if (op_ == ">>" || op_ == ">>=")
+ case Op::Shr:
+ case Op::ShrAssign:
return LHS->getExprValueAlignValue() >> RHS->getExprValueAlignValue() % 64;
- if (op_ == "<")
+ case Op::Lt:
return LHS->getExprValueAlignValue() < RHS->getExprValueAlignValue();
- if (op_ == ">")
+ case Op::Gt:
return LHS->getExprValueAlignValue() > RHS->getExprValueAlignValue();
- if (op_ == ">=")
+ case Op::Geq:
return LHS->getExprValueAlignValue() >= RHS->getExprValueAlignValue();
- if (op_ == "<=")
+ case Op::Leq:
return LHS->getExprValueAlignValue() <= RHS->getExprValueAlignValue();
- if (op_ == "==")
+ case Op::Eq:
return LHS->getExprValueAlignValue() == RHS->getExprValueAlignValue();
- if (op_ == "!=")
+ case Op::Neq:
return LHS->getExprValueAlignValue() != RHS->getExprValueAlignValue();
- if (op_ == "||")
+ case Op::LOr:
return LHS->getExprValueAlignValue() || RHS->getExprValueAlignValue();
- if (op_ == "&&")
+ case Op::LAnd:
return LHS->getExprValueAlignValue() && RHS->getExprValueAlignValue();
- if (op_ == "&")
+ case Op::And:
return bitAnd(LHS->getExprValue(), RHS->getExprValue());
- if (op_ == "^")
+ case Op::Xor:
return bitXor(LHS->getExprValue(), RHS->getExprValue());
- if (op_ == "|")
+ case Op::Or:
return bitOr(LHS->getExprValue(), RHS->getExprValue());
- if (op_ == "&=")
+ case Op::AndAssign:
return LHS->getExprValueAlignValue() & RHS->getExprValueAlignValue();
- if (op_ == "^=")
+ case Op::XorAssign:
return LHS->getExprValueAlignValue() ^ RHS->getExprValueAlignValue();
- if (op_ == "|=")
+ case Op::OrAssign:
return LHS->getExprValueAlignValue() | RHS->getExprValueAlignValue();
- llvm_unreachable("invalid operator");
+ case Op::Invalid:
+ default:
+ llvm_unreachable("invalid operator");
+ }
}
void BinaryExpr::moveAbsRight(ExprValue &a, ExprValue &b) {
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 4eaec397d96a19..a413a3b6d96acf 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -129,9 +129,42 @@ class UnaryExpr : public ScriptExpr {
class BinaryExpr : public ScriptExpr {
public:
+ enum class Op {
+ Add,
+ Sub,
+ Mul,
+ Div,
+ Mod,
+ Shl,
+ Shr,
+ And,
+ Or,
+ Xor,
+ LAnd,
+ LOr,
+ Eq,
+ Neq,
+ Lt,
+ Gt,
+ Leq,
+ Geq,
+ AddAssign,
+ SubAssign,
+ MulAssign,
+ DivAssign,
+ ModAssign,
+ ShlAssign,
+ ShrAssign,
+ AndAssign,
+ OrAssign,
+ XorAssign,
+ Invalid
+ };
BinaryExpr(StringRef op, ScriptExpr *LHS, ScriptExpr *RHS,
const std::string loc)
- : ScriptExpr(ExprKind::Binary), op_(op), LHS(LHS), RHS(RHS), loc_(loc) {}
+ : ScriptExpr(ExprKind::Binary), LHS(LHS), RHS(RHS), loc_(loc) {
+ opcode = stringToOp(op);
+ }
ExprValue evaluateBinaryOperands() const;
// Some operations only support one non absolute value. Move the
// absolute one to the right hand side for convenience.
@@ -143,10 +176,10 @@ class BinaryExpr : public ScriptExpr {
static ExprValue bitOr(ExprValue a, ExprValue b);
private:
- StringRef op_;
- // const ExprValue LHS, RHS;
+ Op opcode;
const ScriptExpr *LHS, *RHS;
std::string loc_;
+ static Op stringToOp(const StringRef op);
};
// This enum is used to implement linker script SECTIONS command.
>From 8b73209bdeab3894f2523b66b5ffd91ec55f7e11 Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Tue, 27 Aug 2024 21:54:07 +0000
Subject: [PATCH 10/16] [ELF] Simplified nested ScriptExpr with BinaryExpr
---
lld/ELF/ScriptParser.cpp | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 9b1a7e8552b2f2..ffce80ca70c88d 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -1160,12 +1160,9 @@ SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) {
ScriptExpr *e = readExpr();
if (op != "=") {
std::string loc = getCurrentLocation();
- e = make<DynamicExpr>([=, c = op[0]]() -> ExprValue {
- ExprValue lhs = script->getSymbolValue(name, loc);
- BinaryExpr *expr =
- make<BinaryExpr>(op, make<DynamicExpr>([=] { return lhs; }), e, loc);
- return expr->evaluateBinaryOperands();
- });
+ DynamicExpr *lhs =
+ make<DynamicExpr>([=] { return script->getSymbolValue(name, loc); });
+ e = make<BinaryExpr>(op, lhs, e, loc);
}
return make<SymbolAssignment>(name, e, ctx.scriptSymOrderCounter++,
getCurrentLocation());
>From f6c756d6cd6abc825bb44f1d295072e96f35567d Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Wed, 28 Aug 2024 03:42:00 +0000
Subject: [PATCH 11/16] [ELF] Removed getExprValueAlignValue
---
lld/ELF/LinkerScript.cpp | 55 ++++++++++++++++++--------------------
lld/ELF/LinkerScript.h | 5 ++--
lld/ELF/OutputSections.cpp | 2 +-
lld/ELF/ScriptParser.cpp | 36 ++++++++++++-------------
4 files changed, 47 insertions(+), 51 deletions(-)
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index bc873cc7eb33d1..521bfce3bbaf35 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -161,11 +161,6 @@ ExprValue ScriptExpr::getExprValue() const {
}
}
-uint64_t ScriptExpr::getExprValueAlignValue() const {
- auto e = getExprValue();
- return e.getValue();
-}
-
BinaryExpr::Op BinaryExpr::stringToOp(const StringRef op) {
static const std::unordered_map<llvm::StringRef, Op> opMap = {
{"+", Op::Add}, {"-", Op::Sub}, {"*", Op::Mul},
@@ -195,40 +190,42 @@ ExprValue BinaryExpr::evaluateBinaryOperands() const {
return sub(LHS->getExprValue(), RHS->getExprValue());
case Op::Mul:
case Op::MulAssign:
- return LHS->getExprValueAlignValue() * RHS->getExprValueAlignValue();
+ return LHS->getExprValue().getValue() * RHS->getExprValue().getValue();
case Op::Div:
case Op::DivAssign:
- if (uint64_t rv = RHS->getExprValueAlignValue())
- return LHS->getExprValueAlignValue() / rv;
+ if (uint64_t rv = RHS->getExprValue().getValue())
+ return LHS->getExprValue().getValue() / rv;
error(loc_ + ": division by zero");
return 0;
case Op::Mod:
- if (uint64_t rv = RHS->getExprValueAlignValue())
- return LHS->getExprValueAlignValue() % rv;
+ if (uint64_t rv = RHS->getExprValue().getValue())
+ return LHS->getExprValue().getValue() % rv;
error(loc_ + ": modulo by zero");
return 0;
case Op::Shl:
case Op::ShlAssign:
- return LHS->getExprValueAlignValue() << RHS->getExprValueAlignValue() % 64;
+ return LHS->getExprValue().getValue()
+ << RHS->getExprValue().getValue() % 64;
case Op::Shr:
case Op::ShrAssign:
- return LHS->getExprValueAlignValue() >> RHS->getExprValueAlignValue() % 64;
+ return LHS->getExprValue().getValue() >>
+ RHS->getExprValue().getValue() % 64;
case Op::Lt:
- return LHS->getExprValueAlignValue() < RHS->getExprValueAlignValue();
+ return LHS->getExprValue().getValue() < RHS->getExprValue().getValue();
case Op::Gt:
- return LHS->getExprValueAlignValue() > RHS->getExprValueAlignValue();
+ return LHS->getExprValue().getValue() > RHS->getExprValue().getValue();
case Op::Geq:
- return LHS->getExprValueAlignValue() >= RHS->getExprValueAlignValue();
+ return LHS->getExprValue().getValue() >= RHS->getExprValue().getValue();
case Op::Leq:
- return LHS->getExprValueAlignValue() <= RHS->getExprValueAlignValue();
+ return LHS->getExprValue().getValue() <= RHS->getExprValue().getValue();
case Op::Eq:
- return LHS->getExprValueAlignValue() == RHS->getExprValueAlignValue();
+ return LHS->getExprValue().getValue() == RHS->getExprValue().getValue();
case Op::Neq:
- return LHS->getExprValueAlignValue() != RHS->getExprValueAlignValue();
+ return LHS->getExprValue().getValue() != RHS->getExprValue().getValue();
case Op::LOr:
- return LHS->getExprValueAlignValue() || RHS->getExprValueAlignValue();
+ return LHS->getExprValue().getValue() || RHS->getExprValue().getValue();
case Op::LAnd:
- return LHS->getExprValueAlignValue() && RHS->getExprValueAlignValue();
+ return LHS->getExprValue().getValue() && RHS->getExprValue().getValue();
case Op::And:
return bitAnd(LHS->getExprValue(), RHS->getExprValue());
case Op::Xor:
@@ -236,11 +233,11 @@ ExprValue BinaryExpr::evaluateBinaryOperands() const {
case Op::Or:
return bitOr(LHS->getExprValue(), RHS->getExprValue());
case Op::AndAssign:
- return LHS->getExprValueAlignValue() & RHS->getExprValueAlignValue();
+ return LHS->getExprValue().getValue() & RHS->getExprValue().getValue();
case Op::XorAssign:
- return LHS->getExprValueAlignValue() ^ RHS->getExprValueAlignValue();
+ return LHS->getExprValue().getValue() ^ RHS->getExprValue().getValue();
case Op::OrAssign:
- return LHS->getExprValueAlignValue() | RHS->getExprValueAlignValue();
+ return LHS->getExprValue().getValue() | RHS->getExprValue().getValue();
case Op::Invalid:
default:
llvm_unreachable("invalid operator");
@@ -328,7 +325,7 @@ void LinkerScript::expandOutputSection(uint64_t size) {
}
void LinkerScript::setDot(ScriptExpr *e, const Twine &loc, bool inSec) {
- uint64_t val = e->getExprValueAlignValue();
+ uint64_t val = e->getExprValue().getValue();
// If val is smaller and we are in an output section, record the error and
// report it if this is the last assignAddresses iteration. dot may be smaller
// if there is another assignAddresses iteration.
@@ -873,7 +870,7 @@ void LinkerScript::processSectionCommands() {
// is given, input sections are aligned to that value, whether the
// given value is larger or smaller than the original section alignment.
if (osec->subalignExpr) {
- uint32_t subalign = osec->subalignExpr->getExprValueAlignValue();
+ uint32_t subalign = osec->subalignExpr->getExprValue().getValue();
for (InputSectionBase *s : v)
s->addralign = subalign;
}
@@ -1328,7 +1325,7 @@ bool LinkerScript::assignOffsets(OutputSection *sec) {
// heuristics described in
// https://sourceware.org/binutils/docs/ld/Output-Section-LMA.html
if (sec->lmaExpr) {
- state->lmaOffset = sec->lmaExpr->getExprValueAlignValue() - dot;
+ state->lmaOffset = sec->lmaExpr->getExprValue().getValue() - dot;
} else if (MemoryRegion *mr = sec->lmaRegion) {
uint64_t lmaStart = alignToPowerOf2(mr->curPos, sec->addralign);
if (mr->curPos < lmaStart)
@@ -1481,7 +1478,7 @@ void LinkerScript::adjustOutputSections() {
// Handle align (e.g. ".foo : ALIGN(16) { ... }").
if (sec->alignExpr)
sec->addralign = std::max<uint32_t>(
- sec->addralign, sec->alignExpr->getExprValueAlignValue());
+ sec->addralign, sec->alignExpr->getExprValue().getValue());
bool isEmpty = (getFirstInputSection(sec) == nullptr);
bool discardable = isEmpty && isDiscardable(*sec);
@@ -1627,7 +1624,7 @@ void LinkerScript::allocateHeaders(SmallVector<PhdrEntry *, 0> &phdrs) {
LinkerScript::AddressState::AddressState() {
for (auto &mri : script->memoryRegions) {
MemoryRegion *mr = mri.second;
- mr->curPos = (mr->origin)->getExprValueAlignValue();
+ mr->curPos = (mr->origin)->getExprValue().getValue();
}
}
@@ -1798,7 +1795,7 @@ SmallVector<PhdrEntry *, 0> LinkerScript::createPhdrs() {
phdr->add(ctx.out.programHeaders);
if (cmd.lmaExpr) {
- phdr->p_paddr = cmd.lmaExpr->getExprValueAlignValue();
+ phdr->p_paddr = cmd.lmaExpr->getExprValue().getValue();
phdr->hasLMA = true;
}
ret.push_back(phdr);
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index a413a3b6d96acf..89affd95e7918f 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -89,7 +89,6 @@ class ScriptExpr {
ExprKind getKind() const { return kind_; }
std::function<ExprValue()> getExpr() const;
ExprValue getExprValue() const;
- uint64_t getExprValueAlignValue() const;
};
class ConstantExpr : public ScriptExpr {
@@ -272,10 +271,10 @@ struct MemoryRegion {
uint64_t curPos = 0;
uint64_t getOrigin() const {
- return origin ? origin->getExprValueAlignValue() : 0;
+ return origin ? origin->getExprValue().getValue() : 0;
}
uint64_t getLength() const {
- return length ? length->getExprValueAlignValue() : 0;
+ return length ? length->getExprValue().getValue() : 0;
}
bool compatibleWith(uint32_t secFlags) const {
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index bbf8b4f23aaf2f..53306118d3118d 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -558,7 +558,7 @@ void OutputSection::writeTo(uint8_t *buf, parallel::TaskGroup &tg) {
if (auto *data = dyn_cast<ByteCommand>(cmd)) {
if (!std::exchange(written, true))
fn(0, numSections);
- writeInt(buf + data->offset, data->expression->getExprValueAlignValue(),
+ writeInt(buf + data->offset, data->expression->getExprValue().getValue(),
data->size);
}
if (written || !numSections)
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index ffce80ca70c88d..a705784fa3ec5e 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -483,8 +483,7 @@ void ScriptParser::readPhdrs() {
else if (consume("AT"))
cmd.lmaExpr = readParenExpr();
else if (consume("FLAGS"))
- // TODO flags
- cmd.flags = readParenExpr()->getExprValueAlignValue();
+ cmd.flags = readParenExpr()->getExprValue().getValue();
else
setError("unexpected header attribute: " + next());
}
@@ -565,7 +564,7 @@ SmallVector<SectionCommand *, 0> ScriptParser::readOverlay() {
for (SectionCommand *cmd : v)
max = std::max(max, cast<OutputDesc>(cmd)->osec.size);
// return addrExpr().getValue() + max;
- return addrExpr->getExprValueAlignValue() + max;
+ return addrExpr->getExprValue().getValue() + max;
});
v.push_back(make<SymbolAssignment>(".", moveDot, 0, getCurrentLocation()));
return v;
@@ -856,7 +855,7 @@ ScriptExpr *ScriptParser::readAssert() {
expect(")");
return make<DynamicExpr>([=] {
- if (!e->getExprValueAlignValue())
+ if (!e->getExprValue().getValue())
errorOrWarn(msg);
return script->getDot();
});
@@ -893,7 +892,7 @@ bool ScriptParser::readSectionDirective(OutputSection *cmd, StringRef tok) {
setError("unknown section type " + value);
} else {
// Otherwise, read an expression.
- cmd->type = readExpr()->getExprValueAlignValue();
+ cmd->type = readExpr()->getExprValue().getValue();
}
cmd->typeIsSet = true;
} else {
@@ -937,7 +936,7 @@ void ScriptParser::readSectionAddressType(OutputSection *cmd) {
static ScriptExpr *checkAlignment(ScriptExpr *e, std::string &loc) {
return make<DynamicExpr>([=] {
- uint64_t alignment = std::max((uint64_t)1, e->getExprValueAlignValue());
+ uint64_t alignment = std::max((uint64_t)1, e->getExprValue().getValue());
if (!isPowerOf2_64(alignment)) {
error(loc + ": alignment must be power of 2");
return (uint64_t)1; // Return a dummy value.
@@ -1364,15 +1363,15 @@ ScriptExpr *ScriptParser::readPrimary() {
if (consume("~")) {
ScriptExpr *e = readPrimary();
// return [=] { return ~e().getValue(); };
- return make<DynamicExpr>([=] { return ~e->getExprValueAlignValue(); });
+ return make<DynamicExpr>([=] { return ~e->getExprValue().getValue(); });
}
if (consume("!")) {
ScriptExpr *e = readPrimary();
- return make<DynamicExpr>([=] { return !e->getExprValueAlignValue(); });
+ return make<DynamicExpr>([=] { return !e->getExprValue().getValue(); });
}
if (consume("-")) {
ScriptExpr *e = readPrimary();
- return make<DynamicExpr>([=] { return -e->getExprValueAlignValue(); });
+ return make<DynamicExpr>([=] { return -e->getExprValue().getValue(); });
}
StringRef tok = next();
@@ -1403,7 +1402,7 @@ ScriptExpr *ScriptParser::readPrimary() {
if (consume(")")) {
e = checkAlignment(e, location);
return make<DynamicExpr>([=] {
- return alignToPowerOf2(script->getDot(), e->getExprValueAlignValue());
+ return alignToPowerOf2(script->getDot(), e->getExprValue().getValue());
});
}
expect(",");
@@ -1411,7 +1410,7 @@ ScriptExpr *ScriptParser::readPrimary() {
expect(")");
return make<DynamicExpr>([=] {
ExprValue v = e->getExprValue();
- v.alignment = e2->getExprValueAlignValue();
+ v.alignment = e2->getExprValue().getValue();
return v;
});
}
@@ -1435,7 +1434,7 @@ ScriptExpr *ScriptParser::readPrimary() {
expect(")");
script->seenDataAlign = true;
return make<DynamicExpr>([=] {
- uint64_t align = std::max(uint64_t(1), e->getExprValueAlignValue());
+ uint64_t align = std::max(uint64_t(1), e->getExprValue().getValue());
return (script->getDot() + align - 1) & -align;
});
}
@@ -1495,7 +1494,7 @@ ScriptExpr *ScriptParser::readPrimary() {
return make<DynamicExpr>([=] {
// LOG2CEIL(0) is defined to be 0.
return llvm::Log2_64_Ceil(
- std::max(a->getExprValueAlignValue(), UINT64_C(1)));
+ std::max(a->getExprValue().getValue(), UINT64_C(1)));
});
}
if (tok == "MAX" || tok == "MIN") {
@@ -1506,11 +1505,12 @@ ScriptExpr *ScriptParser::readPrimary() {
expect(")");
if (tok == "MIN")
return make<DynamicExpr>([=] {
- return std::min(a->getExprValueAlignValue(),
- b->getExprValueAlignValue());
+ return std::min(a->getExprValue().getValue(),
+ b->getExprValue().getValue());
});
return make<DynamicExpr>([=] {
- return std::max(a->getExprValueAlignValue(), b->getExprValueAlignValue());
+ return std::max(a->getExprValue().getValue(),
+ b->getExprValue().getValue());
});
}
if (tok == "ORIGIN") {
@@ -1568,8 +1568,8 @@ ScriptExpr *ScriptParser::readTernary(ScriptExpr *cond) {
expect(":");
ScriptExpr *r = readExpr();
return make<DynamicExpr>([=] {
- return cond->getExprValueAlignValue() ? l->getExprValue()
- : r->getExprValue();
+ return cond->getExprValue().getValue() ? l->getExprValue()
+ : r->getExprValue();
});
}
>From 1858942c2692aa92cfb8bdbb99ec265dcebea079 Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Wed, 28 Aug 2024 03:55:40 +0000
Subject: [PATCH 12/16] [ELF] Update llvm_unreachable to error handling
---
lld/ELF/LinkerScript.cpp | 3 +--
lld/ELF/LinkerScript.h | 1 -
2 files changed, 1 insertion(+), 3 deletions(-)
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 521bfce3bbaf35..c05a2e85355c3b 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -239,8 +239,7 @@ ExprValue BinaryExpr::evaluateBinaryOperands() const {
case Op::OrAssign:
return LHS->getExprValue().getValue() | RHS->getExprValue().getValue();
case Op::Invalid:
- default:
- llvm_unreachable("invalid operator");
+ error(loc_ + ": invalid operator");
}
}
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 89affd95e7918f..6006e979ee181c 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -151,7 +151,6 @@ class BinaryExpr : public ScriptExpr {
SubAssign,
MulAssign,
DivAssign,
- ModAssign,
ShlAssign,
ShrAssign,
AndAssign,
>From 0ad69e3bcc2ac36c06ca948738d24ee19a33d323 Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Wed, 28 Aug 2024 18:36:53 +0000
Subject: [PATCH 13/16] [ELF] Delete getExpr and updated getExprValue for all
subclasses of ScriptExpr
---
lld/ELF/LinkerScript.cpp | 25 ++++---------------------
lld/ELF/LinkerScript.h | 19 ++++++++-----------
2 files changed, 12 insertions(+), 32 deletions(-)
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index c05a2e85355c3b..0dbc41b106dbf1 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -131,31 +131,14 @@ uint64_t ExprValue::getSectionOffset() const {
return getValue() - getSecAddr();
}
-std::function<ExprValue()> ScriptExpr::getExpr() const {
- switch (kind_) {
- case ExprKind::Constant:
- return static_cast<const ConstantExpr *>(this)->getConstantExpr();
- case ExprKind::Dynamic: {
- auto expr = static_cast<const DynamicExpr *>(this);
- return expr->getImpl();
- }
- case ExprKind::Binary: {
- auto expr = static_cast<const BinaryExpr *>(this);
- return [=] { return expr->evaluateBinaryOperands(); };
- }
- default:
- return [] { return ExprValue(0); };
- };
-}
-
ExprValue ScriptExpr::getExprValue() const {
switch (kind_) {
case ExprKind::Constant:
- return static_cast<const ConstantExpr *>(this)->getConstantExprValue();
+ return static_cast<const ConstantExpr *>(this)->getExprValue();
case ExprKind::Dynamic:
- return static_cast<const DynamicExpr *>(this)->getImpl()();
+ return static_cast<const DynamicExpr *>(this)->getExprValue();
case ExprKind::Binary:
- return static_cast<const BinaryExpr *>(this)->evaluateBinaryOperands();
+ return static_cast<const BinaryExpr *>(this)->getExprValue();
default:
return ExprValue(0);
}
@@ -180,7 +163,7 @@ BinaryExpr::Op BinaryExpr::stringToOp(const StringRef op) {
return Op::Invalid;
}
-ExprValue BinaryExpr::evaluateBinaryOperands() const {
+ExprValue BinaryExpr::getExprValue() const {
switch (opcode) {
case Op::Add:
case Op::AddAssign:
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 6006e979ee181c..44cbff281b199f 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -93,12 +93,8 @@ class ScriptExpr {
class ConstantExpr : public ScriptExpr {
public:
- // ConstantExpr(ExprValue val) : ScriptExpr(ExprKind::Constant), val_(val) {}
ConstantExpr(uint64_t val) : ScriptExpr(ExprKind::Constant), val_(val) {}
- std::function<ExprValue()> getConstantExpr() const {
- return [=] { return val_; };
- }
- ExprValue getConstantExprValue() const { return ExprValue(val_); }
+ ExprValue getExprValue() const { return ExprValue(val_); }
private:
// ExprValue val_;
@@ -107,12 +103,10 @@ class ConstantExpr : public ScriptExpr {
class DynamicExpr : public ScriptExpr {
public:
- // static DynamicExpr create(std::function<ExprValue()> impl) {
- // return DynamicExpr(impl);
- // }
- std::function<ExprValue()> getImpl() const { return impl_; }
+ // std::function<ExprValue()> getImpl() const { return impl_; }
DynamicExpr(std::function<ExprValue()> impl)
: ScriptExpr(ExprKind::Dynamic), impl_(impl) {}
+ ExprValue getExprValue() const { return impl_(); }
private:
std::function<ExprValue()> impl_;
@@ -123,7 +117,10 @@ class UnaryExpr : public ScriptExpr {
static const UnaryExpr *create();
private:
- UnaryExpr() : ScriptExpr(ExprKind::Unary) {}
+ UnaryExpr(StringRef op, ScriptExpr *operand)
+ : ScriptExpr(ExprKind::Unary), op_(op), operand_(operand) {}
+ StringRef op_;
+ const ScriptExpr *operand_;
};
class BinaryExpr : public ScriptExpr {
@@ -163,7 +160,7 @@ class BinaryExpr : public ScriptExpr {
: ScriptExpr(ExprKind::Binary), LHS(LHS), RHS(RHS), loc_(loc) {
opcode = stringToOp(op);
}
- ExprValue evaluateBinaryOperands() const;
+ ExprValue getExprValue() const;
// 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);
>From 96d34598dcccfdeb432a6161496f4a91255cb6f9 Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Wed, 28 Aug 2024 21:50:23 +0000
Subject: [PATCH 14/16] [ELF] Replcaed std::unordered_map with llvm
StringSwitch in LinkerScript
---
lld/ELF/LinkerScript.cpp | 46 ++++++++++++++++++++++++++--------------
lld/ELF/LinkerScript.h | 2 --
lld/ELF/ScriptParser.cpp | 6 +-----
3 files changed, 31 insertions(+), 23 deletions(-)
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 0dbc41b106dbf1..556ecc5bff1e4c 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -24,6 +24,7 @@
#include "lld/Common/Strings.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Endian.h"
@@ -145,22 +146,35 @@ ExprValue ScriptExpr::getExprValue() const {
}
BinaryExpr::Op BinaryExpr::stringToOp(const StringRef op) {
- static const std::unordered_map<llvm::StringRef, Op> opMap = {
- {"+", Op::Add}, {"-", Op::Sub}, {"*", Op::Mul},
- {"/", Op::Div}, {"%", Op::Mod}, {"<<", Op::Shl},
- {">>", Op::Shr}, {"&", Op::And}, {"|", Op::Or},
- {"^", Op::Xor}, {"&&", Op::LAnd}, {"||", Op::LOr},
- {"==", Op::Eq}, {"!=", Op::Neq}, {"<", Op::Lt},
- {">", Op::Gt}, {"<=", Op::Leq}, {">=", Op::Geq},
- {"+=", Op::AddAssign}, {"-=", Op::SubAssign}, {"*=", Op::MulAssign},
- {"/=", Op::DivAssign}, {"<<=", Op::ShlAssign}, {">>=", Op::ShrAssign},
- {"&=", Op::AndAssign}, {"|=", Op::OrAssign}, {"^=", Op::XorAssign}};
-
- auto it = opMap.find(op);
- if (it != opMap.end()) {
- return it->second;
- }
- return Op::Invalid;
+ return llvm::StringSwitch<Op>(op)
+ .Case("+", Op::Add)
+ .Case("-", Op::Sub)
+ .Case("*", Op::Mul)
+ .Case("/", Op::Div)
+ .Case("%", Op::Mod)
+ .Case("<<", Op::Shl)
+ .Case(">>", Op::Shr)
+ .Case("&", Op::And)
+ .Case("|", Op::Or)
+ .Case("^", Op::Xor)
+ .Case("&&", Op::LAnd)
+ .Case("||", Op::LOr)
+ .Case("==", Op::Eq)
+ .Case("!=", Op::Neq)
+ .Case("<", Op::Lt)
+ .Case(">", Op::Gt)
+ .Case("<=", Op::Leq)
+ .Case(">=", Op::Geq)
+ .Case("+=", Op::AddAssign)
+ .Case("-=", Op::SubAssign)
+ .Case("*=", Op::MulAssign)
+ .Case("/=", Op::DivAssign)
+ .Case("<<=", Op::ShlAssign)
+ .Case(">>=", Op::ShrAssign)
+ .Case("&=", Op::AndAssign)
+ .Case("|=", Op::OrAssign)
+ .Case("^=", Op::XorAssign)
+ .Default(Op::Invalid);
}
ExprValue BinaryExpr::getExprValue() const {
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 44cbff281b199f..28b64a9c47c454 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -97,13 +97,11 @@ class ConstantExpr : public ScriptExpr {
ExprValue getExprValue() const { return ExprValue(val_); }
private:
- // ExprValue val_;
uint64_t val_;
};
class DynamicExpr : public ScriptExpr {
public:
- // std::function<ExprValue()> getImpl() const { return impl_; }
DynamicExpr(std::function<ExprValue()> impl)
: ScriptExpr(ExprKind::Dynamic), impl_(impl) {}
ExprValue getExprValue() const { return impl_(); }
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index a705784fa3ec5e..2a963f2851779f 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -1362,7 +1362,6 @@ ScriptExpr *ScriptParser::readPrimary() {
if (consume("~")) {
ScriptExpr *e = readPrimary();
- // return [=] { return ~e().getValue(); };
return make<DynamicExpr>([=] { return ~e->getExprValue().getValue(); });
}
if (consume("!")) {
@@ -1472,10 +1471,8 @@ ScriptExpr *ScriptParser::readPrimary() {
StringRef name = readParenName();
if (script->memoryRegions.count(name) == 0) {
setError("memory region not defined: " + name);
- // return [] { return 0; };
return make<ConstantExpr>(0);
}
- // TODO
return script->memoryRegions[name]->length;
}
if (tok == "LOADADDR") {
@@ -1519,7 +1516,6 @@ ScriptExpr *ScriptParser::readPrimary() {
setError("memory region not defined: " + name);
return make<ConstantExpr>(0);
}
- // TODO
return script->memoryRegions[name]->origin;
}
if (tok == "SEGMENT_START") {
@@ -1528,7 +1524,7 @@ ScriptExpr *ScriptParser::readPrimary() {
expect(",");
ScriptExpr *e = readExpr();
expect(")");
- return make<DynamicExpr>([=] { return e->getExprValue(); });
+ return e;
}
if (tok == "SIZEOF") {
StringRef name = readParenName();
>From 72c0b91a185e463004239f0458575bc7db179317 Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Wed, 28 Aug 2024 22:52:19 +0000
Subject: [PATCH 15/16] [ELF] Updated some DynamicExpr with ConstantExpr
---
lld/ELF/ScriptParser.cpp | 2 +-
lld/ELF/Writer.cpp | 5 ++---
2 files changed, 3 insertions(+), 4 deletions(-)
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 2a963f2851779f..f32ac215aa6f7b 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -1544,7 +1544,7 @@ ScriptExpr *ScriptParser::readPrimary() {
// Tok is a literal number.
if (std::optional<uint64_t> val = parseInt(tok))
- return make<DynamicExpr>([=] { return *val; });
+ return make<ConstantExpr>(*val);
// Tok is a symbol name.
if (tok.starts_with("\""))
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index e925a4cd1b4aab..50e9c19801c76b 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1911,7 +1911,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
for (OutputSection *sec : ctx.outputSections) {
auto i = config->sectionStartMap.find(sec->name);
if (i != config->sectionStartMap.end())
- sec->addrExpr = make<DynamicExpr>([=] { return i->second; });
+ sec->addrExpr = make<ConstantExpr>(i->second);
}
// With the ctx.outputSections available check for GDPLT relocations
@@ -2387,8 +2387,7 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
OutputSection *cmd = p->firstSec;
if (!cmd)
return;
- cmd->alignExpr =
- make<DynamicExpr>([align = cmd->addralign]() { return align; });
+ cmd->alignExpr = make<ConstantExpr>(cmd->addralign);
if (!cmd->addrExpr) {
// Prefer advancing to align(dot, maxPageSize) + dot%maxPageSize to avoid
// padding in the file contents.
>From 3590180d054a9fa6a789a4ffd1c3c40304b3e3ba Mon Sep 17 00:00:00 2001
From: Hongyu Chen <hongyuchy at google.com>
Date: Thu, 29 Aug 2024 18:39:41 +0000
Subject: [PATCH 16/16] [ELF] Added UnaryExpr
---
lld/ELF/LinkerScript.cpp | 13 +++++++++++++
lld/ELF/LinkerScript.h | 6 +++---
lld/ELF/ScriptParser.cpp | 16 +++-------------
3 files changed, 19 insertions(+), 16 deletions(-)
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 556ecc5bff1e4c..9b19398f39fc3f 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -140,11 +140,24 @@ ExprValue ScriptExpr::getExprValue() const {
return static_cast<const DynamicExpr *>(this)->getExprValue();
case ExprKind::Binary:
return static_cast<const BinaryExpr *>(this)->getExprValue();
+ case ExprKind::Unary:
+ return static_cast<const UnaryExpr *>(this)->getExprValue();
default:
return ExprValue(0);
}
}
+ExprValue UnaryExpr::getExprValue() const {
+ switch (op_[0]) {
+ case '~':
+ return ExprValue(~operand_->getExprValue().getValue());
+ case '!':
+ return ExprValue(!operand_->getExprValue().getValue());
+ case '-':
+ return ExprValue(-operand_->getExprValue().getValue());
+ }
+}
+
BinaryExpr::Op BinaryExpr::stringToOp(const StringRef op) {
return llvm::StringSwitch<Op>(op)
.Case("+", Op::Add)
diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h
index 28b64a9c47c454..d33f46b0ad102e 100644
--- a/lld/ELF/LinkerScript.h
+++ b/lld/ELF/LinkerScript.h
@@ -112,11 +112,11 @@ class DynamicExpr : public ScriptExpr {
class UnaryExpr : public ScriptExpr {
public:
- static const UnaryExpr *create();
-
-private:
UnaryExpr(StringRef op, ScriptExpr *operand)
: ScriptExpr(ExprKind::Unary), op_(op), operand_(operand) {}
+ ExprValue getExprValue() const;
+
+private:
StringRef op_;
const ScriptExpr *operand_;
};
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index f32ac215aa6f7b..0c6795917039f4 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -1360,20 +1360,10 @@ ScriptExpr *ScriptParser::readPrimary() {
if (peek() == "(")
return readParenExpr();
- if (consume("~")) {
- ScriptExpr *e = readPrimary();
- return make<DynamicExpr>([=] { return ~e->getExprValue().getValue(); });
- }
- if (consume("!")) {
- ScriptExpr *e = readPrimary();
- return make<DynamicExpr>([=] { return !e->getExprValue().getValue(); });
- }
- if (consume("-")) {
- ScriptExpr *e = readPrimary();
- return make<DynamicExpr>([=] { return -e->getExprValue().getValue(); });
- }
-
StringRef tok = next();
+ if (tok == "~" || tok == "!" || tok == "-")
+ return make<UnaryExpr>(tok, readPrimary());
+
std::string location = getCurrentLocation();
// Built-in functions are parsed here.
More information about the llvm-commits
mailing list