[lld] r267255 - Use ScriptParserBase features to parse linker script expressions.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 22 17:04:04 PDT 2016


Author: ruiu
Date: Fri Apr 22 19:04:03 2016
New Revision: 267255

URL: http://llvm.org/viewvc/llvm-project?rev=267255&view=rev
Log:
Use ScriptParserBase features to parse linker script expressions.

Previously, we have re-implemented utility functions such as `expect`
or `next` in LinkerScript.cpp. This patch reuses the existing
implementation that is in ScriptParser.cpp.

Modified:
    lld/trunk/ELF/LinkerScript.cpp
    lld/trunk/ELF/ScriptParser.cpp
    lld/trunk/ELF/ScriptParser.h
    lld/trunk/test/ELF/linkerscript-locationcounter.s

Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=267255&r1=267254&r2=267255&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Fri Apr 22 19:04:03 2016
@@ -37,6 +37,29 @@ ScriptConfiguration *elf::ScriptConfig;
 
 static bool matchStr(StringRef S, StringRef T);
 
+// This is an operator-precedence parser to parse and evaluate
+// a linker script expression. For each linker script arithmetic
+// expression (e.g. ". = . + 0x1000"), a new instance of ExprParser
+// is created and ran.
+namespace {
+class ExprParser : public ScriptParserBase {
+public:
+  ExprParser(std::vector<StringRef> &Tokens, uint64_t Dot)
+      : ScriptParserBase(Tokens), Dot(Dot) {}
+
+  uint64_t run();
+
+private:
+  uint64_t parsePrimary();
+  uint64_t parseTernary(uint64_t Cond);
+  uint64_t apply(StringRef Op, uint64_t L, uint64_t R);
+  uint64_t parseExpr1(uint64_t Lhs, int MinPrec);
+  uint64_t parseExpr();
+
+  uint64_t Dot;
+};
+}
+
 static int precedence(StringRef Op) {
   return StringSwitch<int>(Op)
       .Case("*", 4)
@@ -47,71 +70,51 @@ static int precedence(StringRef Op) {
       .Default(-1);
 }
 
-static StringRef next(ArrayRef<StringRef> &Tokens) {
-  if (Tokens.empty()) {
-    error("no next token");
-    return "";
-  }
-  StringRef Tok = Tokens.front();
-  Tokens = Tokens.slice(1);
-  return Tok;
+static uint64_t evalExpr(std::vector<StringRef> &Tokens, uint64_t Dot) {
+  return ExprParser(Tokens, Dot).run();
 }
 
-static bool expect(ArrayRef<StringRef> &Tokens, StringRef S) {
-  if (Tokens.empty()) {
-    error(S + " expected");
-    return false;
-  }
-  StringRef Tok = Tokens.front();
-  if (Tok != S) {
-    error(S + " expected, but got " + Tok);
-    return false;
-  }
-  Tokens = Tokens.slice(1);
-  return true;
+uint64_t ExprParser::run() {
+  uint64_t V = parseExpr();
+  if (!atEOF() && !Error)
+    setError("stray token: " + peek());
+  return V;
 }
 
 // This is a part of the operator-precedence parser to evaluate
 // arithmetic expressions in SECTIONS command. This function evaluates an
 // integer literal, a parenthesized expression, the ALIGN function,
 // or the special variable ".".
-template <class ELFT>
-uint64_t LinkerScript<ELFT>::parsePrimary(ArrayRef<StringRef> &Tokens) {
-  StringRef Tok = next(Tokens);
+uint64_t ExprParser::parsePrimary() {
+  StringRef Tok = next();
   if (Tok == ".")
     return Dot;
   if (Tok == "(") {
-    uint64_t V = parseExpr(Tokens);
-    if (!expect(Tokens, ")"))
-      return 0;
+    uint64_t V = parseExpr();
+    expect(")");
     return V;
   }
   if (Tok == "ALIGN") {
-    if (!expect(Tokens, "("))
-      return 0;
-    uint64_t V = parseExpr(Tokens);
-    if (!expect(Tokens, ")"))
-      return 0;
+    expect("(");
+    uint64_t V = parseExpr();
+    expect(")");
     return alignTo(Dot, V);
   }
   uint64_t V = 0;
   if (Tok.getAsInteger(0, V))
-    error("malformed number: " + Tok);
+    setError("malformed number: " + Tok);
   return V;
 }
 
-template <class ELFT>
-uint64_t LinkerScript<ELFT>::parseTernary(ArrayRef<StringRef> &Tokens,
-                                          uint64_t Cond) {
-  next(Tokens);
-  uint64_t V = parseExpr(Tokens);
-  if (!expect(Tokens, ":"))
-    return 0;
-  uint64_t W = parseExpr(Tokens);
+uint64_t ExprParser::parseTernary(uint64_t Cond) {
+  next();
+  uint64_t V = parseExpr();
+  expect(":");
+  uint64_t W = parseExpr();
   return Cond ? V : W;
 }
 
-static uint64_t apply(StringRef Op, uint64_t L, uint64_t R) {
+uint64_t ExprParser::apply(StringRef Op, uint64_t L, uint64_t R) {
   if (Op == "+")
     return L + R;
   if (Op == "-")
@@ -131,32 +134,29 @@ static uint64_t apply(StringRef Op, uint
   return 0;
 }
 
-// This is an operator-precedence parser to evaluate
-// arithmetic expressions in SECTIONS command.
-// Tokens should start with an operator.
-template <class ELFT>
-uint64_t LinkerScript<ELFT>::parseExpr1(ArrayRef<StringRef> &Tokens,
-                                        uint64_t Lhs, int MinPrec) {
-  while (!Tokens.empty()) {
+// This is a part of the operator-precedence parser.
+// This function assumes that the remaining token stream starts
+// with an operator.
+uint64_t ExprParser::parseExpr1(uint64_t Lhs, int MinPrec) {
+  while (!atEOF()) {
     // Read an operator and an expression.
-    StringRef Op1 = Tokens.front();
+    StringRef Op1 = peek();
     if (Op1 == "?")
-      return parseTernary(Tokens, Lhs);
-
+      return parseTernary(Lhs);
     if (precedence(Op1) < MinPrec)
       return Lhs;
-    next(Tokens);
-    uint64_t Rhs = parsePrimary(Tokens);
+    next();
+    uint64_t Rhs = parsePrimary();
 
     // Evaluate the remaining part of the expression first if the
     // next operator has greater precedence than the previous one.
     // For example, if we have read "+" and "3", and if the next
     // operator is "*", then we'll evaluate 3 * ... part first.
-    while (!Tokens.empty()) {
-      StringRef Op2 = Tokens.front();
+    while (!atEOF()) {
+      StringRef Op2 = peek();
       if (precedence(Op2) <= precedence(Op1))
         break;
-      Rhs = parseExpr1(Tokens, Rhs, precedence(Op2));
+      Rhs = parseExpr1(Rhs, precedence(Op2));
     }
 
     Lhs = apply(Op1, Lhs, Rhs);
@@ -164,20 +164,8 @@ uint64_t LinkerScript<ELFT>::parseExpr1(
   return Lhs;
 }
 
-template <class ELFT>
-uint64_t LinkerScript<ELFT>::parseExpr(ArrayRef<StringRef> &Tokens) {
-  uint64_t V = parsePrimary(Tokens);
-  return parseExpr1(Tokens, V, 0);
-}
-
-// Evaluates the expression given by list of tokens.
-template <class ELFT>
-uint64_t LinkerScript<ELFT>::evaluate(ArrayRef<StringRef> Tokens) {
-  uint64_t V = parseExpr(Tokens);
-  if (!Tokens.empty())
-    error("stray token: " + Tokens[0]);
-  return V;
-}
+// Reads and evaluates an arithmetic expression.
+uint64_t ExprParser::parseExpr() { return parseExpr1(parsePrimary(), 0); }
 
 template <class ELFT>
 StringRef LinkerScript<ELFT>::getOutputSection(InputSectionBase<ELFT> *S) {
@@ -229,7 +217,7 @@ void LinkerScript<ELFT>::assignAddresses
 
   for (SectionsCommand &Cmd : Opt.Commands) {
     if (Cmd.Kind == ExprKind) {
-      Dot = evaluate(Cmd.Expr);
+      Dot = evalExpr(Cmd.Expr, Dot);
       continue;
     }
 

Modified: lld/trunk/ELF/ScriptParser.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ScriptParser.cpp?rev=267255&r1=267254&r2=267255&view=diff
==============================================================================
--- lld/trunk/ELF/ScriptParser.cpp (original)
+++ lld/trunk/ELF/ScriptParser.cpp Fri Apr 22 19:04:03 2016
@@ -43,8 +43,12 @@ void ScriptParserBase::printErrorPos() {
 void ScriptParserBase::setError(const Twine &Msg) {
   if (Error)
     return;
-  error("line " + Twine(getPos()) + ": " + Msg);
-  printErrorPos();
+  if (Input.empty()) {
+    error(Msg);
+  } else {
+    error("line " + Twine(getPos()) + ": " + Msg);
+    printErrorPos();
+  }
   Error = true;
 }
 

Modified: lld/trunk/ELF/ScriptParser.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ScriptParser.h?rev=267255&r1=267254&r2=267255&view=diff
==============================================================================
--- lld/trunk/ELF/ScriptParser.h (original)
+++ lld/trunk/ELF/ScriptParser.h Fri Apr 22 19:04:03 2016
@@ -20,6 +20,7 @@ namespace elf {
 class ScriptParserBase {
 public:
   ScriptParserBase(StringRef S) : Input(S), Tokens(tokenize(S)) {}
+  ScriptParserBase(std::vector<StringRef> Tokens) : Input(""), Tokens(Tokens) {}
 
 protected:
   void setError(const Twine &Msg);

Modified: lld/trunk/test/ELF/linkerscript-locationcounter.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript-locationcounter.s?rev=267255&r1=267254&r2=267255&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript-locationcounter.s (original)
+++ lld/trunk/test/ELF/linkerscript-locationcounter.s Fri Apr 22 19:04:03 2016
@@ -157,7 +157,7 @@
 # RUN: }" > %t.script
 # RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \
 # RUN:  FileCheck --check-prefix=BRACKETERR %s
-# BRACKETERR: ) expected
+# BRACKETERR: unexpected EOF
 
 ## Missing opening bracket.
 # RUN: echo "SECTIONS { \
@@ -189,7 +189,7 @@
 # RUN: }" > %t.script
 # RUN: not ld.lld %t --script %t.script -o %t2 2>&1 | \
 # RUN:  FileCheck --check-prefix=TERNERR %s
-# TERNERR: : expected
+# TERNERR: unexpected EOF
 
 .globl _start;
 _start:




More information about the llvm-commits mailing list