[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