Delete the old script parser.
authorRafael Espindola <rafael.espindola@gmail.com>
Sun, 28 Feb 2016 02:14:48 +0000 (02:14 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Sun, 28 Feb 2016 02:14:48 +0000 (02:14 +0000)
It was ELF specific.

llvm-svn: 262163

29 files changed:
lld/lib/ReaderWriter/CMakeLists.txt
lld/lib/ReaderWriter/LinkerScript.cpp [deleted file]
lld/test/CMakeLists.txt
lld/test/LinkerScript/expr-precedence.test [deleted file]
lld/test/LinkerScript/extern-bad-symbol.test [deleted file]
lld/test/LinkerScript/extern-empty.test [deleted file]
lld/test/LinkerScript/extern-valid.test [deleted file]
lld/test/LinkerScript/incomplete-ternary.test [deleted file]
lld/test/LinkerScript/libname-err-1.test [deleted file]
lld/test/LinkerScript/libname-err-2.test [deleted file]
lld/test/LinkerScript/linker-script-outputformat.test [deleted file]
lld/test/LinkerScript/linker-script.test [deleted file]
lld/test/LinkerScript/memory-empty.test [deleted file]
lld/test/LinkerScript/memory-missing-attrs.test [deleted file]
lld/test/LinkerScript/memory-missing-length.test [deleted file]
lld/test/LinkerScript/memory-missing-name.test [deleted file]
lld/test/LinkerScript/memory-missing-origin.test [deleted file]
lld/test/LinkerScript/memory-valid.test [deleted file]
lld/test/LinkerScript/missing-entry-symbol.test [deleted file]
lld/test/LinkerScript/missing-input-file-name.test [deleted file]
lld/test/LinkerScript/missing-input-sections.test [deleted file]
lld/test/LinkerScript/missing-operand.test [deleted file]
lld/test/LinkerScript/missing-output-section-name.test [deleted file]
lld/test/LinkerScript/missing-symbol.test [deleted file]
lld/test/LinkerScript/phdrs-sections.test [deleted file]
lld/test/LinkerScript/sections.test [deleted file]
lld/tools/CMakeLists.txt
lld/tools/linker-script-test/CMakeLists.txt [deleted file]
lld/tools/linker-script-test/linker-script-test.cpp [deleted file]

index 097291f..dc02deb 100644 (file)
@@ -8,7 +8,6 @@ endif()
 add_lld_library(lldReaderWriter
   CoreLinkingContext.cpp
   FileArchive.cpp
-  LinkerScript.cpp
 
   ADDITIONAL_HEADER_DIRS
   ${LLD_INCLUDE_DIR}/lld/ReaderWriter
diff --git a/lld/lib/ReaderWriter/LinkerScript.cpp b/lld/lib/ReaderWriter/LinkerScript.cpp
deleted file mode 100644 (file)
index 67822dc..0000000
+++ /dev/null
@@ -1,2895 +0,0 @@
-//===- ReaderWriter/LinkerScript.cpp ----------------------------*- C++ -*-===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Linker script parser.
-///
-//===----------------------------------------------------------------------===//
-
-#include "lld/ReaderWriter/LinkerScript.h"
-
-#include "llvm/ADT/APInt.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/ELF.h"
-
-namespace lld {
-namespace script {
-void Token::dump(raw_ostream &os) const {
-  switch (_kind) {
-#define CASE(name)                                                             \
-  case Token::name:                                                            \
-    os << #name ": ";                                                          \
-    break;
-    CASE(unknown)
-    CASE(eof)
-    CASE(exclaim)
-    CASE(exclaimequal)
-    CASE(amp)
-    CASE(ampequal)
-    CASE(l_paren)
-    CASE(r_paren)
-    CASE(star)
-    CASE(starequal)
-    CASE(plus)
-    CASE(plusequal)
-    CASE(comma)
-    CASE(minus)
-    CASE(minusequal)
-    CASE(slash)
-    CASE(slashequal)
-    CASE(number)
-    CASE(colon)
-    CASE(semicolon)
-    CASE(less)
-    CASE(lessequal)
-    CASE(lessless)
-    CASE(lesslessequal)
-    CASE(equal)
-    CASE(equalequal)
-    CASE(greater)
-    CASE(greaterequal)
-    CASE(greatergreater)
-    CASE(greatergreaterequal)
-    CASE(question)
-    CASE(identifier)
-    CASE(libname)
-    CASE(kw_align)
-    CASE(kw_align_with_input)
-    CASE(kw_as_needed)
-    CASE(kw_at)
-    CASE(kw_discard)
-    CASE(kw_entry)
-    CASE(kw_exclude_file)
-    CASE(kw_extern)
-    CASE(kw_filehdr)
-    CASE(kw_fill)
-    CASE(kw_flags)
-    CASE(kw_group)
-    CASE(kw_hidden)
-    CASE(kw_input)
-    CASE(kw_keep)
-    CASE(kw_length)
-    CASE(kw_memory)
-    CASE(kw_origin)
-    CASE(kw_phdrs)
-    CASE(kw_provide)
-    CASE(kw_provide_hidden)
-    CASE(kw_only_if_ro)
-    CASE(kw_only_if_rw)
-    CASE(kw_output)
-    CASE(kw_output_arch)
-    CASE(kw_output_format)
-    CASE(kw_overlay)
-    CASE(kw_search_dir)
-    CASE(kw_sections)
-    CASE(kw_sort_by_alignment)
-    CASE(kw_sort_by_init_priority)
-    CASE(kw_sort_by_name)
-    CASE(kw_sort_none)
-    CASE(kw_subalign)
-    CASE(l_brace)
-    CASE(pipe)
-    CASE(pipeequal)
-    CASE(r_brace)
-    CASE(tilde)
-#undef CASE
-  }
-  os << _range << "\n";
-}
-
-static llvm::ErrorOr<uint64_t> parseDecimal(StringRef str) {
-  uint64_t res = 0;
-  for (auto &c : str) {
-    res *= 10;
-    if (c < '0' || c > '9')
-      return llvm::ErrorOr<uint64_t>(make_error_code(llvm::errc::io_error));
-    res += c - '0';
-  }
-  return res;
-}
-
-static llvm::ErrorOr<uint64_t> parseOctal(StringRef str) {
-  uint64_t res = 0;
-  for (auto &c : str) {
-    res <<= 3;
-    if (c < '0' || c > '7')
-      return llvm::ErrorOr<uint64_t>(make_error_code(llvm::errc::io_error));
-    res += c - '0';
-  }
-  return res;
-}
-
-static llvm::ErrorOr<uint64_t> parseBinary(StringRef str) {
-  uint64_t res = 0;
-  for (auto &c : str) {
-    res <<= 1;
-    if (c != '0' && c != '1')
-      return llvm::ErrorOr<uint64_t>(make_error_code(llvm::errc::io_error));
-    res += c - '0';
-  }
-  return res;
-}
-
-static llvm::ErrorOr<uint64_t> parseHex(StringRef str) {
-  uint64_t res = 0;
-  for (auto &c : str) {
-    res <<= 4;
-    if (c >= '0' && c <= '9')
-      res += c - '0';
-    else if (c >= 'a' && c <= 'f')
-      res += c - 'a' + 10;
-    else if (c >= 'A' && c <= 'F')
-      res += c - 'A' + 10;
-    else
-      return llvm::ErrorOr<uint64_t>(make_error_code(llvm::errc::io_error));
-  }
-  return res;
-}
-
-static bool parseHexToByteStream(StringRef str, std::string &buf) {
-  unsigned char byte = 0;
-  bool dumpByte = str.size() % 2;
-  for (auto &c : str) {
-    byte <<= 4;
-    if (c >= '0' && c <= '9')
-      byte += c - '0';
-    else if (c >= 'a' && c <= 'f')
-      byte += c - 'a' + 10;
-    else if (c >= 'A' && c <= 'F')
-      byte += c - 'A' + 10;
-    else
-      return false;
-    if (!dumpByte) {
-      dumpByte = true;
-      continue;
-    }
-    buf.push_back(byte);
-    byte = 0;
-    dumpByte = false;
-  }
-  return !dumpByte;
-}
-
-static void dumpByteStream(raw_ostream &os, StringRef stream) {
-  os << "0x";
-  for (auto &c : stream) {
-    unsigned char firstNibble = c >> 4 & 0xF;
-    if (firstNibble > 9)
-      os << (char) ('A' + firstNibble - 10);
-    else
-      os << (char) ('0' + firstNibble);
-    unsigned char secondNibble = c & 0xF;
-    if (secondNibble > 9)
-      os << (char) ('A' + secondNibble - 10);
-    else
-      os << (char) ('0' + secondNibble);
-  }
-}
-
-static llvm::ErrorOr<uint64_t> parseNum(StringRef str) {
-  unsigned multiplier = 1;
-  enum NumKind { decimal, hex, octal, binary };
-  NumKind kind = llvm::StringSwitch<NumKind>(str)
-                     .StartsWith("0x", hex)
-                     .StartsWith("0X", hex)
-                     .StartsWith("0", octal)
-                     .Default(decimal);
-
-  // Parse scale
-  if (str.endswith("K")) {
-    multiplier = 1 << 10;
-    str = str.drop_back();
-  } else if (str.endswith("M")) {
-    multiplier = 1 << 20;
-    str = str.drop_back();
-  }
-
-  // Parse type
-  if (str.endswith_lower("o")) {
-    kind = octal;
-    str = str.drop_back();
-  } else if (str.endswith_lower("h")) {
-    kind = hex;
-    str = str.drop_back();
-  } else if (str.endswith_lower("d")) {
-    kind = decimal;
-    str = str.drop_back();
-  } else if (str.endswith_lower("b")) {
-    kind = binary;
-    str = str.drop_back();
-  }
-
-  llvm::ErrorOr<uint64_t> res(0);
-  switch (kind) {
-  case hex:
-    if (str.startswith_lower("0x"))
-      str = str.drop_front(2);
-    res = parseHex(str);
-    break;
-  case octal:
-    res = parseOctal(str);
-    break;
-  case decimal:
-    res = parseDecimal(str);
-    break;
-  case binary:
-    res = parseBinary(str);
-    break;
-  }
-  if (res.getError())
-    return res;
-
-  *res = *res * multiplier;
-  return res;
-}
-
-bool Lexer::canStartNumber(char c) const {
-  return '0' <= c && c <= '9';
-}
-
-bool Lexer::canContinueNumber(char c) const {
-  // [xX] = hex marker, [hHoO] = type suffix, [MK] = scale suffix.
-  return strchr("0123456789ABCDEFabcdefxXhHoOMK", c);
-}
-
-bool Lexer::canStartName(char c) const {
-  return strchr(
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_.$/\\*", c);
-}
-
-bool Lexer::canContinueName(char c) const {
-  return strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
-                "0123456789_.$/\\~=+[]*?-:", c);
-}
-
-/// Helper function to split a StringRef in two at the nth character.
-/// The StringRef s is updated, while the function returns the n first
-/// characters.
-static StringRef drop(StringRef &s, int n) {
-  StringRef res = s.substr(0, n);
-  s = s.drop_front(n);
-  return res;
-}
-
-void Lexer::lex(Token &tok) {
-  skipWhitespace();
-  if (_buffer.empty()) {
-    tok = Token(_buffer, Token::eof);
-    return;
-  }
-  switch (_buffer[0]) {
-  case 0:
-    tok = Token(drop(_buffer, 1), Token::eof);
-    return;
-  case '(':
-    tok = Token(drop(_buffer, 1), Token::l_paren);
-    return;
-  case ')':
-    tok = Token(drop(_buffer, 1), Token::r_paren);
-    return;
-  case '{':
-    tok = Token(drop(_buffer, 1), Token::l_brace);
-    return;
-  case '}':
-    tok = Token(drop(_buffer, 1), Token::r_brace);
-    return;
-  case '=':
-    if (_buffer.startswith("==")) {
-      tok = Token(drop(_buffer, 2), Token::equalequal);
-      return;
-    }
-    tok = Token(drop(_buffer, 1), Token::equal);
-    return;
-  case '!':
-    if (_buffer.startswith("!=")) {
-      tok = Token(drop(_buffer, 2), Token::exclaimequal);
-      return;
-    }
-    tok = Token(drop(_buffer, 1), Token::exclaim);
-    return;
-  case ',':
-    tok = Token(drop(_buffer, 1), Token::comma);
-    return;
-  case ';':
-    tok = Token(drop(_buffer, 1), Token::semicolon);
-    return;
-  case ':':
-    tok = Token(drop(_buffer, 1), Token::colon);
-    return;
-  case '&':
-    if (_buffer.startswith("&=")) {
-      tok = Token(drop(_buffer, 2), Token::ampequal);
-      return;
-    }
-    tok = Token(drop(_buffer, 1), Token::amp);
-    return;
-  case '|':
-    if (_buffer.startswith("|=")) {
-      tok = Token(drop(_buffer, 2), Token::pipeequal);
-      return;
-    }
-    tok = Token(drop(_buffer, 1), Token::pipe);
-    return;
-  case '+':
-    if (_buffer.startswith("+=")) {
-      tok = Token(drop(_buffer, 2), Token::plusequal);
-      return;
-    }
-    tok = Token(drop(_buffer, 1), Token::plus);
-    return;
-  case '-': {
-    if (_buffer.startswith("-=")) {
-      tok = Token(drop(_buffer, 2), Token::minusequal);
-      return;
-    }
-    if (!_buffer.startswith("-l")) {
-      tok = Token(drop(_buffer, 1), Token::minus);
-      return;
-    }
-    // -l<lib name>
-    _buffer = _buffer.drop_front(2);
-    StringRef::size_type start = 0;
-    if (_buffer[start] == ':')
-      ++start;
-    if (!canStartName(_buffer[start]))
-      // Create 'unknown' token.
-      break;
-    auto libNameEnd = std::find_if(_buffer.begin() + start + 1, _buffer.end(),
-                                   [=](char c) { return !canContinueName(c); });
-    StringRef::size_type libNameLen =
-        std::distance(_buffer.begin(), libNameEnd);
-    tok = Token(_buffer.substr(0, libNameLen), Token::libname);
-    _buffer = _buffer.drop_front(libNameLen);
-    return;
-  }
-  case '<':
-    if (_buffer.startswith("<<=")) {
-      tok = Token(drop(_buffer, 3), Token::lesslessequal);
-      return;
-    }
-    if (_buffer.startswith("<<")) {
-      tok = Token(drop(_buffer, 2), Token::lessless);
-      return;
-    }
-    if (_buffer.startswith("<=")) {
-      tok = Token(drop(_buffer, 2), Token::lessequal);
-      return;
-    }
-    tok = Token(drop(_buffer, 1), Token::less);
-    return;
-  case '>':
-    if (_buffer.startswith(">>=")) {
-      tok = Token(drop(_buffer, 3), Token::greatergreaterequal);
-      return;
-    }
-    if (_buffer.startswith(">>")) {
-      tok = Token(drop(_buffer, 2), Token::greatergreater);
-      return;
-    }
-    if (_buffer.startswith(">=")) {
-      tok = Token(drop(_buffer, 2), Token::greaterequal);
-      return;
-    }
-    tok = Token(drop(_buffer, 1), Token::greater);
-    return;
-  case '~':
-    tok = Token(drop(_buffer, 1), Token::tilde);
-    return;
-  case '\"': case '\'': {
-    // Handle quoted strings. They are treated as identifiers for
-    // simplicity.
-    char c = _buffer[0];
-    _buffer = _buffer.drop_front();
-    auto quotedStringEnd = _buffer.find(c);
-    if (quotedStringEnd == StringRef::npos || quotedStringEnd == 0)
-      break;
-    StringRef word = _buffer.substr(0, quotedStringEnd);
-    tok = Token(word, Token::identifier);
-    _buffer = _buffer.drop_front(quotedStringEnd + 1);
-    return;
-  }
-  default:
-    // Handle literal numbers
-    if (canStartNumber(_buffer[0])) {
-      auto endIter = std::find_if(_buffer.begin(), _buffer.end(), [=](char c) {
-        return !canContinueNumber(c);
-      });
-      StringRef::size_type end = endIter == _buffer.end()
-                                     ? StringRef::npos
-                                     : std::distance(_buffer.begin(), endIter);
-      if (end == StringRef::npos || end == 0)
-        break;
-      StringRef word = _buffer.substr(0, end);
-      tok = Token(word, Token::number);
-      _buffer = _buffer.drop_front(end);
-      return;
-    }
-    // Handle slashes '/', which can be either an operator inside an expression
-    // or the beginning of an identifier
-    if (_buffer.startswith("/=")) {
-      tok = Token(drop(_buffer, 2), Token::slashequal);
-      return;
-    }
-    if (_buffer[0] == '/' && _buffer.size() > 1 &&
-        !canContinueName(_buffer[1])) {
-      tok = Token(drop(_buffer, 1), Token::slash);
-      return;
-    }
-    // Handle stars '*'
-    if (_buffer.startswith("*=")) {
-      tok = Token(drop(_buffer, 2), Token::starequal);
-      return;
-    }
-    if (_buffer[0] == '*' && _buffer.size() > 1 &&
-        !canContinueName(_buffer[1])) {
-      tok = Token(drop(_buffer, 1), Token::star);
-      return;
-    }
-    // Handle questions '?'
-    if (_buffer[0] == '?' && _buffer.size() > 1 &&
-        !canContinueName(_buffer[1])) {
-      tok = Token(drop(_buffer, 1), Token::question);
-      return;
-    }
-    // keyword or identifier.
-    if (!canStartName(_buffer[0]))
-      break;
-    auto endIter = std::find_if(_buffer.begin() + 1, _buffer.end(),
-                                [=](char c) { return !canContinueName(c); });
-    StringRef::size_type end = endIter == _buffer.end()
-                                   ? StringRef::npos
-                                   : std::distance(_buffer.begin(), endIter);
-    if (end == StringRef::npos || end == 0)
-      break;
-    StringRef word = _buffer.substr(0, end);
-    Token::Kind kind =
-        llvm::StringSwitch<Token::Kind>(word)
-            .Case("ALIGN", Token::kw_align)
-            .Case("ALIGN_WITH_INPUT", Token::kw_align_with_input)
-            .Case("AS_NEEDED", Token::kw_as_needed)
-            .Case("AT", Token::kw_at)
-            .Case("ENTRY", Token::kw_entry)
-            .Case("EXCLUDE_FILE", Token::kw_exclude_file)
-            .Case("EXTERN", Token::kw_extern)
-            .Case("FILEHDR", Token::kw_filehdr)
-            .Case("FILL", Token::kw_fill)
-            .Case("FLAGS", Token::kw_flags)
-            .Case("GROUP", Token::kw_group)
-            .Case("HIDDEN", Token::kw_hidden)
-            .Case("INPUT", Token::kw_input)
-            .Case("KEEP", Token::kw_keep)
-            .Case("LENGTH", Token::kw_length)
-            .Case("l", Token::kw_length)
-            .Case("len", Token::kw_length)
-            .Case("MEMORY", Token::kw_memory)
-            .Case("ONLY_IF_RO", Token::kw_only_if_ro)
-            .Case("ONLY_IF_RW", Token::kw_only_if_rw)
-            .Case("ORIGIN", Token::kw_origin)
-            .Case("o", Token::kw_origin)
-            .Case("org", Token::kw_origin)
-            .Case("OUTPUT", Token::kw_output)
-            .Case("OUTPUT_ARCH", Token::kw_output_arch)
-            .Case("OUTPUT_FORMAT", Token::kw_output_format)
-            .Case("OVERLAY", Token::kw_overlay)
-            .Case("PHDRS", Token::kw_phdrs)
-            .Case("PROVIDE", Token::kw_provide)
-            .Case("PROVIDE_HIDDEN", Token::kw_provide_hidden)
-            .Case("SEARCH_DIR", Token::kw_search_dir)
-            .Case("SECTIONS", Token::kw_sections)
-            .Case("SORT", Token::kw_sort_by_name)
-            .Case("SORT_BY_ALIGNMENT", Token::kw_sort_by_alignment)
-            .Case("SORT_BY_INIT_PRIORITY", Token::kw_sort_by_init_priority)
-            .Case("SORT_BY_NAME", Token::kw_sort_by_name)
-            .Case("SORT_NONE", Token::kw_sort_none)
-            .Case("SUBALIGN", Token::kw_subalign)
-            .Case("/DISCARD/", Token::kw_discard)
-            .Default(Token::identifier);
-    tok = Token(word, kind);
-    _buffer = _buffer.drop_front(end);
-    return;
-  }
-  tok = Token(drop(_buffer, 1), Token::unknown);
-}
-
-void Lexer::skipWhitespace() {
-  while (true) {
-    if (_buffer.empty())
-      return;
-    switch (_buffer[0]) {
-    case ' ':
-    case '\r':
-    case '\n':
-    case '\t':
-      _buffer = _buffer.drop_front();
-      break;
-    // Potential comment.
-    case '/':
-      if (_buffer.size() <= 1 || _buffer[1] != '*')
-        return;
-      // Skip starting /*
-      _buffer = _buffer.drop_front(2);
-      // If the next char is also a /, it's not the end.
-      if (!_buffer.empty() && _buffer[0] == '/')
-        _buffer = _buffer.drop_front();
-
-      // Scan for /'s. We're done if it is preceded by a *.
-      while (true) {
-        if (_buffer.empty())
-          break;
-        _buffer = _buffer.drop_front();
-        if (_buffer.data()[-1] == '/' && _buffer.data()[-2] == '*')
-          break;
-      }
-      break;
-    default:
-      return;
-    }
-  }
-}
-
-// Constant functions
-void Constant::dump(raw_ostream &os) const { os << _num; }
-
-ErrorOr<int64_t> Constant::evalExpr(const SymbolTableTy &symbolTable) const {
-  return _num;
-}
-
-// Symbol functions
-void Symbol::dump(raw_ostream &os) const { os << _name; }
-
-ErrorOr<int64_t> Symbol::evalExpr(const SymbolTableTy &symbolTable) const {
-  auto it = symbolTable.find(_name);
-  if (it == symbolTable.end())
-    return LinkerScriptReaderError::unknown_symbol_in_expr;
-  return it->second;
-}
-
-// FunctionCall functions
-void FunctionCall::dump(raw_ostream &os) const {
-  os << _name << "(";
-  for (unsigned i = 0, e = _args.size(); i != e; ++i) {
-    if (i)
-      os << ", ";
-    _args[i]->dump(os);
-  }
-  os << ")";
-}
-
-ErrorOr<int64_t>
-FunctionCall::evalExpr(const SymbolTableTy &symbolTable) const {
-  return LinkerScriptReaderError::unrecognized_function_in_expr;
-}
-
-// Unary functions
-void Unary::dump(raw_ostream &os) const {
-  os << "(";
-  if (_op == Unary::Minus)
-    os << "-";
-  else
-    os << "~";
-  _child->dump(os);
-  os << ")";
-}
-
-ErrorOr<int64_t> Unary::evalExpr(const SymbolTableTy &symbolTable) const {
-  auto child = _child->evalExpr(symbolTable);
-  if (child.getError())
-    return child.getError();
-
-  int64_t childRes = *child;
-  switch (_op) {
-  case Unary::Minus:
-    return -childRes;
-  case Unary::Not:
-    return ~childRes;
-  }
-
-  llvm_unreachable("");
-}
-
-// BinOp functions
-void BinOp::dump(raw_ostream &os) const {
-  os << "(";
-  _lhs->dump(os);
-  os << " ";
-  switch (_op) {
-  case Sum:
-    os << "+";
-    break;
-  case Sub:
-    os << "-";
-    break;
-  case Mul:
-    os << "*";
-    break;
-  case Div:
-    os << "/";
-    break;
-  case Shl:
-    os << "<<";
-    break;
-  case Shr:
-    os << ">>";
-    break;
-  case And:
-    os << "&";
-    break;
-  case Or:
-    os << "|";
-    break;
-  case CompareEqual:
-    os << "==";
-    break;
-  case CompareDifferent:
-    os << "!=";
-    break;
-  case CompareLess:
-    os << "<";
-    break;
-  case CompareGreater:
-    os << ">";
-    break;
-  case CompareLessEqual:
-    os << "<=";
-    break;
-  case CompareGreaterEqual:
-    os << ">=";
-    break;
-  }
-  os << " ";
-  _rhs->dump(os);
-  os << ")";
-}
-
-ErrorOr<int64_t> BinOp::evalExpr(const SymbolTableTy &symbolTable) const {
-  auto lhs = _lhs->evalExpr(symbolTable);
-  if (lhs.getError())
-    return lhs.getError();
-  auto rhs = _rhs->evalExpr(symbolTable);
-  if (rhs.getError())
-    return rhs.getError();
-
-  int64_t lhsRes = *lhs;
-  int64_t rhsRes = *rhs;
-
-  switch(_op) {
-  case And:                 return lhsRes & rhsRes;
-  case CompareDifferent:    return lhsRes != rhsRes;
-  case CompareEqual:        return lhsRes == rhsRes;
-  case CompareGreater:      return lhsRes > rhsRes;
-  case CompareGreaterEqual: return lhsRes >= rhsRes;
-  case CompareLess:         return lhsRes < rhsRes;
-  case CompareLessEqual:    return lhsRes <= rhsRes;
-  case Div:                 return lhsRes / rhsRes;
-  case Mul:                 return lhsRes * rhsRes;
-  case Or:                  return lhsRes | rhsRes;
-  case Shl:                 return lhsRes << rhsRes;
-  case Shr:                 return lhsRes >> rhsRes;
-  case Sub:                 return lhsRes - rhsRes;
-  case Sum:                 return lhsRes + rhsRes;
-  }
-
-  llvm_unreachable("");
-}
-
-// TernaryConditional functions
-void TernaryConditional::dump(raw_ostream &os) const {
-  _conditional->dump(os);
-  os << " ? ";
-  _trueExpr->dump(os);
-  os << " : ";
-  _falseExpr->dump(os);
-}
-
-ErrorOr<int64_t>
-TernaryConditional::evalExpr(const SymbolTableTy &symbolTable) const {
-  auto conditional = _conditional->evalExpr(symbolTable);
-  if (conditional.getError())
-    return conditional.getError();
-  if (*conditional)
-    return _trueExpr->evalExpr(symbolTable);
-  return _falseExpr->evalExpr(symbolTable);
-}
-
-// SymbolAssignment functions
-void SymbolAssignment::dump(raw_ostream &os) const {
-  int numParen = 0;
-
-  if (_assignmentVisibility != Default) {
-    switch (_assignmentVisibility) {
-    case Hidden:
-      os << "HIDDEN(";
-      break;
-    case Provide:
-      os << "PROVIDE(";
-      break;
-    case ProvideHidden:
-      os << "PROVIDE_HIDDEN(";
-      break;
-    default:
-      llvm_unreachable("Unknown visibility");
-    }
-    ++numParen;
-  }
-
-  os << _symbol << " ";
-  switch (_assignmentKind) {
-  case Simple:
-    os << "=";
-    break;
-  case Sum:
-    os << "+=";
-    break;
-  case Sub:
-    os << "-=";
-    break;
-  case Mul:
-    os << "*=";
-    break;
-  case Div:
-    os << "/=";
-    break;
-  case Shl:
-    os << "<<=";
-    break;
-  case Shr:
-    os << ">>=";
-    break;
-  case And:
-    os << "&=";
-    break;
-  case Or:
-    os << "|=";
-    break;
-  }
-
-  os << " ";
-  _expression->dump(os);
-  if (numParen)
-    os << ")";
-  os << ";";
-}
-
-static int dumpSortDirectives(raw_ostream &os, WildcardSortMode sortMode) {
-  switch (sortMode) {
-  case WildcardSortMode::NA:
-    return 0;
-  case WildcardSortMode::ByName:
-    os << "SORT_BY_NAME(";
-    return 1;
-  case WildcardSortMode::ByAlignment:
-    os << "SORT_BY_ALIGNMENT(";
-    return 1;
-  case WildcardSortMode::ByInitPriority:
-    os << "SORT_BY_INIT_PRIORITY(";
-    return 1;
-  case WildcardSortMode::ByNameAndAlignment:
-    os << "SORT_BY_NAME(SORT_BY_ALIGNMENT(";
-    return 2;
-  case WildcardSortMode::ByAlignmentAndName:
-    os << "SORT_BY_ALIGNMENT(SORT_BY_NAME(";
-    return 2;
-  case WildcardSortMode::None:
-    os << "SORT_NONE(";
-    return 1;
-  }
-  return 0;
-}
-
-// InputSectionName functions
-void InputSectionName::dump(raw_ostream &os) const {
-  os << _name;
-}
-
-// InputSectionSortedGroup functions
-static void dumpInputSections(raw_ostream &os,
-                              llvm::ArrayRef<const InputSection *> secs) {
-  bool excludeFile = false;
-  bool first = true;
-
-  for (auto &secName : secs) {
-    if (!first)
-      os << " ";
-    first = false;
-    // Coalesce multiple input sections marked with EXCLUDE_FILE in the same
-    // EXCLUDE_FILE() group
-    if (auto inputSec = dyn_cast<InputSectionName>(secName)) {
-      if (!excludeFile && inputSec->hasExcludeFile()) {
-        excludeFile = true;
-        os << "EXCLUDE_FILE(";
-      } else if (excludeFile && !inputSec->hasExcludeFile()) {
-        excludeFile = false;
-        os << ") ";
-      }
-    }
-    secName->dump(os);
-  }
-
-  if (excludeFile)
-    os << ")";
-}
-
-void InputSectionSortedGroup::dump(raw_ostream &os) const {
-  int numParen = dumpSortDirectives(os, _sortMode);
-  dumpInputSections(os, _sections);
-  for (int i = 0; i < numParen; ++i)
-    os << ")";
-}
-
-// InputSectionsCmd functions
-void InputSectionsCmd::dump(raw_ostream &os) const {
-  if (_keep)
-    os << "KEEP(";
-
-  int numParen = dumpSortDirectives(os, _fileSortMode);
-  os << _memberName;
-  for (int i = 0; i < numParen; ++i)
-    os << ")";
-
-  if (_archiveName.size() > 0) {
-    os << ":";
-    numParen = dumpSortDirectives(os, _archiveSortMode);
-    os << _archiveName;
-    for (int i = 0; i < numParen; ++i)
-      os << ")";
-  }
-
-  if (_sections.size() > 0) {
-    os << "(";
-    dumpInputSections(os, _sections);
-    os << ")";
-  }
-
-  if (_keep)
-    os << ")";
-}
-
-void FillCmd::dump(raw_ostream &os) const {
-  os << "FILL(";
-  dumpByteStream(os, StringRef((const char *)_bytes.begin(), _bytes.size()));
-  os << ")";
-}
-
-// OutputSectionDescription functions
-void OutputSectionDescription::dump(raw_ostream &os) const {
-  if (_discard)
-    os << "/DISCARD/";
-  else
-    os << _sectionName;
-
-  if (_address) {
-    os << " ";
-    _address->dump(os);
-  }
-  os << " :\n";
-
-  if (_at) {
-    os << "  AT(";
-    _at->dump(os);
-    os << ")\n";
-  }
-
-  if (_align) {
-    os << "  ALIGN(";
-    _align->dump(os);
-    os << ")\n";
-  } else if (_alignWithInput) {
-    os << " ALIGN_WITH_INPUT\n";
-  }
-
-  if (_subAlign) {
-    os << "  SUBALIGN(";
-    _subAlign->dump(os);
-    os << ")\n";
-  }
-
-  switch (_constraint) {
-  case C_None:
-    break;
-  case C_OnlyIfRO:
-    os << "ONLY_IF_RO";
-    break;
-  case C_OnlyIfRW:
-    os << "ONLY_IF_RW";
-    break;
-  }
-
-  os << "  {\n";
-  for (auto &command : _outputSectionCommands) {
-    os << "    ";
-    command->dump(os);
-    os << "\n";
-  }
-  os << "  }";
-
-  for (auto && phdr : _phdrs)
-    os << " : " << phdr;
-
-  if (_fillStream.size() > 0) {
-    os << " =";
-    dumpByteStream(os, _fillStream);
-  } else if (_fillExpr) {
-    os << " =";
-    _fillExpr->dump(os);
-  }
-}
-
-// Special header that discards output sections assigned to it.
-static const PHDR PHDR_NONE("NONE", 0, false, false, nullptr, 0);
-
-bool PHDR::isNone() const {
-  return this == &PHDR_NONE;
-}
-
-void PHDR::dump(raw_ostream &os) const {
-  os << _name << " " << _type;
-  if (_includeFileHdr)
-    os << " FILEHDR";
-  if (_includePHDRs)
-    os << " PHDRS";
-  if (_at) {
-    os << " AT (";
-    _at->dump(os);
-    os << ")";
-  }
-  if (_flags)
-    os << " FLAGS (" << _flags << ")";
-  os << ";\n";
-}
-
-void PHDRS::dump(raw_ostream &os) const {
-  os << "PHDRS\n{\n";
-  for (auto &&phdr : _phdrs) {
-    phdr->dump(os);
-  }
-  os << "}\n";
-}
-
-// Sections functions
-void Sections::dump(raw_ostream &os) const {
-  os << "SECTIONS\n{\n";
-  for (auto &command : _sectionsCommands) {
-    command->dump(os);
-    os << "\n";
-  }
-  os << "}\n";
-}
-
-// Memory functions
-void MemoryBlock::dump(raw_ostream &os) const {
-    os << _name;
-
-    if (!_attr.empty())
-      os << " (" << _attr << ")";
-
-    os << " : ";
-
-    os << "ORIGIN = ";
-    _origin->dump(os);
-    os << ", ";
-
-    os << "LENGTH = ";
-    _length->dump(os);
-}
-
-void Memory::dump(raw_ostream &os) const {
-  os << "MEMORY\n{\n";
-  for (auto &block : _blocks) {
-    block->dump(os);
-    os << "\n";
-  }
-  os << "}\n";
-}
-
-// Extern functions
-void Extern::dump(raw_ostream &os) const {
-  os << "EXTERN(";
-  for (unsigned i = 0, e = _symbols.size(); i != e; ++i) {
-    if (i)
-      os << " ";
-    os << _symbols[i];
-  }
-  os << ")\n";
-}
-
-// Parser functions
-std::error_code Parser::parse() {
-  // Get the first token.
-  _lex.lex(_tok);
-  // Parse top level commands.
-  while (true) {
-    switch (_tok._kind) {
-    case Token::eof:
-      return std::error_code();
-    case Token::semicolon:
-      consumeToken();
-      break;
-    case Token::kw_output: {
-      auto output = parseOutput();
-      if (!output)
-        return LinkerScriptReaderError::parse_error;
-      _script._commands.push_back(output);
-      break;
-    }
-    case Token::kw_output_format: {
-      auto outputFormat = parseOutputFormat();
-      if (!outputFormat)
-        return LinkerScriptReaderError::parse_error;
-      _script._commands.push_back(outputFormat);
-      break;
-    }
-    case Token::kw_output_arch: {
-      auto outputArch = parseOutputArch();
-      if (!outputArch)
-        return LinkerScriptReaderError::parse_error;
-      _script._commands.push_back(outputArch);
-      break;
-    }
-    case Token::kw_input: {
-      Input *input = parsePathList<Input>();
-      if (!input)
-        return LinkerScriptReaderError::parse_error;
-      _script._commands.push_back(input);
-      break;
-    }
-    case Token::kw_group: {
-      Group *group = parsePathList<Group>();
-      if (!group)
-        return LinkerScriptReaderError::parse_error;
-      _script._commands.push_back(group);
-      break;
-    }
-    case Token::kw_as_needed:
-      // Not allowed at top level.
-      error(_tok, "AS_NEEDED not allowed at top level.");
-      return LinkerScriptReaderError::parse_error;
-    case Token::kw_entry: {
-      Entry *entry = parseEntry();
-      if (!entry)
-        return LinkerScriptReaderError::parse_error;
-      _script._commands.push_back(entry);
-      break;
-    }
-    case Token::kw_phdrs: {
-      PHDRS *phdrs = parsePHDRS();
-      if (!phdrs)
-        return LinkerScriptReaderError::parse_error;
-      _script._commands.push_back(phdrs);
-      break;
-    }
-    case Token::kw_search_dir: {
-      SearchDir *searchDir = parseSearchDir();
-      if (!searchDir)
-        return LinkerScriptReaderError::parse_error;
-      _script._commands.push_back(searchDir);
-      break;
-    }
-    case Token::kw_sections: {
-      Sections *sections = parseSections();
-      if (!sections)
-        return LinkerScriptReaderError::parse_error;
-      _script._commands.push_back(sections);
-      break;
-    }
-    case Token::identifier:
-    case Token::kw_hidden:
-    case Token::kw_provide:
-    case Token::kw_provide_hidden: {
-      const Command *cmd = parseSymbolAssignment();
-      if (!cmd)
-        return LinkerScriptReaderError::parse_error;
-      _script._commands.push_back(cmd);
-      break;
-    }
-    case Token::kw_memory: {
-      const Command *cmd = parseMemory();
-      if (!cmd)
-        return LinkerScriptReaderError::parse_error;
-      _script._commands.push_back(cmd);
-      break;
-    }
-    case Token::kw_extern: {
-      const Command *cmd = parseExtern();
-      if (!cmd)
-        return LinkerScriptReaderError::parse_error;
-      _script._commands.push_back(cmd);
-      break;
-    }
-    default:
-      // Unexpected.
-      error(_tok, "expected linker script command");
-      return LinkerScriptReaderError::parse_error;
-    }
-  }
-  return LinkerScriptReaderError::parse_error;
-}
-
-const Expression *Parser::parseFunctionCall() {
-  assert((_tok._kind == Token::identifier || _tok._kind == Token::kw_align) &&
-         "expected function call first tokens");
-  SmallVector<const Expression *, 8> params;
-  StringRef name = _tok._range;
-
-  consumeToken();
-  if (!expectAndConsume(Token::l_paren, "expected ("))
-    return nullptr;
-
-  if (_tok._kind == Token::r_paren) {
-    consumeToken();
-    return new (_alloc) FunctionCall(*this, _tok._range, params);
-  }
-
-  if (const Expression *firstParam = parseExpression())
-    params.push_back(firstParam);
-  else
-    return nullptr;
-
-  while (_tok._kind == Token::comma) {
-    consumeToken();
-    if (const Expression *param = parseExpression())
-      params.push_back(param);
-    else
-      return nullptr;
-  }
-
-  if (!expectAndConsume(Token::r_paren, "expected )"))
-    return nullptr;
-  return new (_alloc) FunctionCall(*this, name, params);
-}
-
-bool Parser::expectExprOperand() {
-  if (!(_tok._kind == Token::identifier || _tok._kind == Token::number ||
-        _tok._kind == Token::kw_align || _tok._kind == Token::l_paren ||
-        _tok._kind == Token::minus || _tok._kind == Token::tilde)) {
-    error(_tok, "expected symbol, number, minus, tilde or left parenthesis.");
-    return false;
-  }
-  return true;
-}
-
-const Expression *Parser::parseExprOperand() {
-  if (!expectExprOperand())
-    return nullptr;
-
-  switch (_tok._kind) {
-  case Token::identifier: {
-    if (peek()._kind== Token::l_paren)
-      return parseFunctionCall();
-    auto *sym = new (_alloc) Symbol(*this, _tok._range);
-    consumeToken();
-    return sym;
-  }
-  case Token::kw_align:
-    return parseFunctionCall();
-  case Token::minus:
-    consumeToken();
-    return new (_alloc) Unary(*this, Unary::Minus, parseExprOperand());
-  case Token::tilde:
-    consumeToken();
-    return new (_alloc) Unary(*this, Unary::Not, parseExprOperand());
-  case Token::number: {
-    auto val = parseNum(_tok._range);
-    if (val.getError()) {
-      error(_tok, "Unrecognized number constant");
-      return nullptr;
-    }
-    auto *c = new (_alloc) Constant(*this, *val);
-    consumeToken();
-    return c;
-  }
-  case Token::l_paren: {
-    consumeToken();
-    const Expression *expr = parseExpression();
-    if (!expectAndConsume(Token::r_paren, "expected )"))
-      return nullptr;
-    return expr;
-  }
-  default:
-    llvm_unreachable("Unknown token");
-  }
-}
-
-static bool TokenToBinOp(const Token &tok, BinOp::Operation &op,
-                         unsigned &precedence) {
-  switch (tok._kind) {
-  case Token::star:
-    op = BinOp::Mul;
-    precedence = 3;
-    return true;
-  case Token::slash:
-    op = BinOp::Div;
-    precedence = 3;
-    return true;
-  case Token::plus:
-    op = BinOp::Sum;
-    precedence = 4;
-    return true;
-  case Token::minus:
-    op = BinOp::Sub;
-    precedence = 4;
-    return true;
-  case Token::lessless:
-    op = BinOp::Shl;
-    precedence = 5;
-    return true;
-  case Token::greatergreater:
-    op = BinOp::Shr;
-    precedence = 5;
-    return true;
-  case Token::less:
-    op = BinOp::CompareLess;
-    precedence = 6;
-    return true;
-  case Token::greater:
-    op = BinOp::CompareGreater;
-    precedence = 6;
-    return true;
-  case Token::lessequal:
-    op = BinOp::CompareLessEqual;
-    precedence = 6;
-    return true;
-  case Token::greaterequal:
-    op = BinOp::CompareGreaterEqual;
-    precedence = 6;
-    return true;
-  case Token::equalequal:
-    op = BinOp::CompareEqual;
-    precedence = 7;
-    return true;
-  case Token::exclaimequal:
-    op = BinOp::CompareDifferent;
-    precedence = 7;
-    return true;
-  case Token::amp:
-    op = BinOp::And;
-    precedence = 8;
-    return true;
-  case Token::pipe:
-    op = BinOp::Or;
-    precedence = 10;
-    return true;
-  default:
-    break;
-  }
-  return false;
-}
-
-static bool isExpressionOperator(Token tok) {
-  switch (tok._kind) {
-  case Token::star:
-  case Token::slash:
-  case Token::plus:
-  case Token::minus:
-  case Token::lessless:
-  case Token::greatergreater:
-  case Token::less:
-  case Token::greater:
-  case Token::lessequal:
-  case Token::greaterequal:
-  case Token::equalequal:
-  case Token::exclaimequal:
-  case Token::amp:
-  case Token::pipe:
-  case Token::question:
-    return true;
-  default:
-    return false;
-  }
-}
-
-const Expression *Parser::parseExpression(unsigned precedence) {
-  assert(precedence <= 13 && "Invalid precedence value");
-  if (!expectExprOperand())
-    return nullptr;
-
-  const Expression *expr = parseExprOperand();
-  if (!expr)
-    return nullptr;
-
-  BinOp::Operation op;
-  unsigned binOpPrecedence = 0;
-  if (TokenToBinOp(_tok, op, binOpPrecedence)) {
-    if (precedence >= binOpPrecedence)
-      return parseOperatorOperandLoop(expr, precedence);
-    return expr;
-  }
-
-  // Non-binary operators
-  if (_tok._kind == Token::question && precedence >= 13)
-    return parseOperatorOperandLoop(expr, precedence);
-  return expr;
-}
-
-const Expression *Parser::parseOperatorOperandLoop(const Expression *lhs,
-                                                   unsigned highestPrecedence) {
-  assert(highestPrecedence <= 13 && "Invalid precedence value");
-  unsigned precedence = 0;
-  const Expression *binOp = nullptr;
-
-  while (1) {
-    BinOp::Operation op;
-    if (!TokenToBinOp(_tok, op, precedence)) {
-      if (_tok._kind == Token::question && highestPrecedence >= 13)
-        return parseTernaryCondOp(lhs);
-      return binOp;
-    }
-
-    if (precedence > highestPrecedence)
-      return binOp;
-
-    consumeToken();
-    const Expression *rhs = parseExpression(precedence - 1);
-    if (!rhs)
-      return nullptr;
-    binOp = new (_alloc) BinOp(*this, lhs, op, rhs);
-    lhs = binOp;
-  }
-}
-
-const Expression *Parser::parseTernaryCondOp(const Expression *lhs) {
-  assert(_tok._kind == Token::question && "Expected question mark");
-
-  consumeToken();
-
-  // The ternary conditional operator has right-to-left associativity.
-  // To implement this, we allow our children to contain ternary conditional
-  // operators themselves (precedence 13).
-  const Expression *trueExpr = parseExpression(13);
-  if (!trueExpr)
-    return nullptr;
-
-  if (!expectAndConsume(Token::colon, "expected :"))
-    return nullptr;
-
-  const Expression *falseExpr = parseExpression(13);
-  if (!falseExpr)
-    return nullptr;
-
-  return new (_alloc) TernaryConditional(*this, lhs, trueExpr, falseExpr);
-}
-
-// Parse OUTPUT(ident)
-Output *Parser::parseOutput() {
-  assert(_tok._kind == Token::kw_output && "Expected OUTPUT");
-  consumeToken();
-  if (!expectAndConsume(Token::l_paren, "expected ("))
-    return nullptr;
-
-  if (_tok._kind != Token::identifier) {
-    error(_tok, "Expected identifier in OUTPUT.");
-    return nullptr;
-  }
-
-  auto ret = new (_alloc) Output(*this, _tok._range);
-  consumeToken();
-
-  if (!expectAndConsume(Token::r_paren, "expected )"))
-    return nullptr;
-
-  return ret;
-}
-
-// Parse OUTPUT_FORMAT(ident)
-OutputFormat *Parser::parseOutputFormat() {
-  assert(_tok._kind == Token::kw_output_format && "Expected OUTPUT_FORMAT!");
-  consumeToken();
-  if (!expectAndConsume(Token::l_paren, "expected ("))
-    return nullptr;
-
-  if (_tok._kind != Token::identifier) {
-    error(_tok, "Expected identifier in OUTPUT_FORMAT.");
-    return nullptr;
-  }
-
-  SmallVector<StringRef, 8> formats;
-  formats.push_back(_tok._range);
-
-  consumeToken();
-
-  do {
-    if (isNextToken(Token::comma))
-      consumeToken();
-    else
-      break;
-    if (_tok._kind != Token::identifier) {
-      error(_tok, "Expected identifier in OUTPUT_FORMAT.");
-      return nullptr;
-    }
-    formats.push_back(_tok._range);
-    consumeToken();
-  } while (isNextToken(Token::comma));
-
-  if (!expectAndConsume(Token::r_paren, "expected )"))
-    return nullptr;
-
-  return new (_alloc) OutputFormat(*this, formats);
-}
-
-// Parse OUTPUT_ARCH(ident)
-OutputArch *Parser::parseOutputArch() {
-  assert(_tok._kind == Token::kw_output_arch && "Expected OUTPUT_ARCH!");
-  consumeToken();
-  if (!expectAndConsume(Token::l_paren, "expected ("))
-    return nullptr;
-
-  if (_tok._kind != Token::identifier) {
-    error(_tok, "Expected identifier in OUTPUT_ARCH.");
-    return nullptr;
-  }
-
-  auto ret = new (_alloc) OutputArch(*this, _tok._range);
-  consumeToken();
-
-  if (!expectAndConsume(Token::r_paren, "expected )"))
-    return nullptr;
-
-  return ret;
-}
-
-// Parse file list for INPUT or GROUP
-template<class T> T *Parser::parsePathList() {
-  consumeToken();
-  if (!expectAndConsume(Token::l_paren, "expected ("))
-    return nullptr;
-
-  SmallVector<Path, 8> paths;
-  while (_tok._kind == Token::identifier || _tok._kind == Token::libname ||
-         _tok._kind == Token::kw_as_needed) {
-    switch (_tok._kind) {
-    case Token::identifier:
-      paths.push_back(Path(_tok._range));
-      consumeToken();
-      break;
-    case Token::libname:
-      paths.push_back(Path(_tok._range, false, true));
-      consumeToken();
-      break;
-    case Token::kw_as_needed:
-      if (!parseAsNeeded(paths))
-        return nullptr;
-      break;
-    default:
-      llvm_unreachable("Invalid token.");
-    }
-  }
-  if (!expectAndConsume(Token::r_paren, "expected )"))
-    return nullptr;
-  return new (_alloc) T(*this, paths);
-}
-
-// Parse AS_NEEDED(file ...)
-bool Parser::parseAsNeeded(SmallVectorImpl<Path> &paths) {
-  assert(_tok._kind == Token::kw_as_needed && "Expected AS_NEEDED!");
-  consumeToken();
-  if (!expectAndConsume(Token::l_paren, "expected ("))
-    return false;
-
-  while (_tok._kind == Token::identifier || _tok._kind == Token::libname) {
-    switch (_tok._kind) {
-    case Token::identifier:
-      paths.push_back(Path(_tok._range, true, false));
-      consumeToken();
-      break;
-    case Token::libname:
-      paths.push_back(Path(_tok._range, true, true));
-      consumeToken();
-      break;
-    default:
-      llvm_unreachable("Invalid token.");
-    }
-  }
-
-  if (!expectAndConsume(Token::r_paren, "expected )"))
-    return false;
-  return true;
-}
-
-// Parse ENTRY(ident)
-Entry *Parser::parseEntry() {
-  assert(_tok._kind == Token::kw_entry && "Expected ENTRY!");
-  consumeToken();
-  if (!expectAndConsume(Token::l_paren, "expected ("))
-    return nullptr;
-  if (_tok._kind != Token::identifier) {
-    error(_tok, "expected identifier in ENTRY");
-    return nullptr;
-  }
-  StringRef entryName(_tok._range);
-  consumeToken();
-  if (!expectAndConsume(Token::r_paren, "expected )"))
-    return nullptr;
-  return new (_alloc) Entry(*this, entryName);
-}
-
-// Parse SEARCH_DIR(ident)
-SearchDir *Parser::parseSearchDir() {
-  assert(_tok._kind == Token::kw_search_dir && "Expected SEARCH_DIR!");
-  consumeToken();
-  if (!expectAndConsume(Token::l_paren, "expected ("))
-    return nullptr;
-  if (_tok._kind != Token::identifier) {
-    error(_tok, "expected identifier in SEARCH_DIR");
-    return nullptr;
-  }
-  StringRef searchPath(_tok._range);
-  consumeToken();
-  if (!expectAndConsume(Token::r_paren, "expected )"))
-    return nullptr;
-  return new (_alloc) SearchDir(*this, searchPath);
-}
-
-const SymbolAssignment *Parser::parseSymbolAssignment() {
-  assert((_tok._kind == Token::identifier || _tok._kind == Token::kw_hidden ||
-          _tok._kind == Token::kw_provide ||
-          _tok._kind == Token::kw_provide_hidden) &&
-         "Expected identifier!");
-  SymbolAssignment::AssignmentVisibility visibility = SymbolAssignment::Default;
-  SymbolAssignment::AssignmentKind kind;
-  int numParen = 0;
-
-  switch (_tok._kind) {
-  case Token::kw_hidden:
-    visibility = SymbolAssignment::Hidden;
-    ++numParen;
-    consumeToken();
-    if (!expectAndConsume(Token::l_paren, "expected ("))
-      return nullptr;
-    break;
-  case Token::kw_provide:
-    visibility = SymbolAssignment::Provide;
-    ++numParen;
-    consumeToken();
-    if (!expectAndConsume(Token::l_paren, "expected ("))
-      return nullptr;
-    break;
-  case Token::kw_provide_hidden:
-    visibility = SymbolAssignment::ProvideHidden;
-    ++numParen;
-    consumeToken();
-    if (!expectAndConsume(Token::l_paren, "expected ("))
-      return nullptr;
-    break;
-  default:
-    break;
-  }
-
-  StringRef name = _tok._range;
-  consumeToken();
-
-  // Parse assignment operator (=, +=, -= etc.)
-  switch (_tok._kind) {
-  case Token::equal:
-    kind = SymbolAssignment::Simple;
-    break;
-  case Token::plusequal:
-    kind = SymbolAssignment::Sum;
-    break;
-  case Token::minusequal:
-    kind = SymbolAssignment::Sub;
-    break;
-  case Token::starequal:
-    kind = SymbolAssignment::Mul;
-    break;
-  case Token::slashequal:
-    kind = SymbolAssignment::Div;
-    break;
-  case Token::ampequal:
-    kind = SymbolAssignment::And;
-    break;
-  case Token::pipeequal:
-    kind = SymbolAssignment::Or;
-    break;
-  case Token::lesslessequal:
-    kind = SymbolAssignment::Shl;
-    break;
-  case Token::greatergreaterequal:
-    kind = SymbolAssignment::Shr;
-    break;
-  default:
-    error(_tok, "unexpected token");
-    return nullptr;
-  }
-
-  consumeToken();
-
-  const Expression *expr = nullptr;
-  switch (_tok._kind) {
-  case Token::number:
-  case Token::kw_align:
-  case Token::identifier:
-  case Token::l_paren:
-    expr = parseExpression();
-    if (!expr)
-      return nullptr;
-    break;
-  default:
-    error(_tok, "unexpected token while parsing assignment value.");
-    return nullptr;
-  }
-
-  for (int i = 0; i < numParen; ++i)
-    if (!expectAndConsume(Token::r_paren, "expected )"))
-      return nullptr;
-
-  return new (_alloc) SymbolAssignment(*this, name, expr, kind, visibility);
-}
-
-llvm::ErrorOr<InputSectionsCmd::VectorTy> Parser::parseExcludeFile() {
-  assert(_tok._kind == Token::kw_exclude_file && "Expected EXCLUDE_FILE!");
-  InputSectionsCmd::VectorTy res;
-  consumeToken();
-
-  if (!expectAndConsume(Token::l_paren, "expected ("))
-    return llvm::ErrorOr<InputSectionsCmd::VectorTy>(
-        make_error_code(llvm::errc::io_error));
-
-  while (_tok._kind == Token::identifier) {
-    res.push_back(new (_alloc) InputSectionName(*this, _tok._range, true));
-    consumeToken();
-  }
-
-  if (!expectAndConsume(Token::r_paren, "expected )"))
-    return llvm::ErrorOr<InputSectionsCmd::VectorTy>(
-        make_error_code(llvm::errc::io_error));
-  return llvm::ErrorOr<InputSectionsCmd::VectorTy>(std::move(res));
-}
-
-int Parser::parseSortDirectives(WildcardSortMode &sortMode) {
-  int numParsedDirectives = 0;
-  sortMode = WildcardSortMode::NA;
-
-  if (_tok._kind == Token::kw_sort_by_name) {
-    consumeToken();
-    if (!expectAndConsume(Token::l_paren, "expected ("))
-      return -1;
-    ++numParsedDirectives;
-    sortMode = WildcardSortMode::ByName;
-  }
-
-  if (_tok._kind == Token::kw_sort_by_init_priority) {
-    consumeToken();
-    if (!expectAndConsume(Token::l_paren, "expected ("))
-      return -1;
-    ++numParsedDirectives;
-    sortMode = WildcardSortMode::ByInitPriority;
-  }
-
-  if (_tok._kind == Token::kw_sort_by_alignment) {
-    consumeToken();
-    if (!expectAndConsume(Token::l_paren, "expected ("))
-      return -1;
-    ++numParsedDirectives;
-    if (sortMode != WildcardSortMode::ByName)
-      sortMode = WildcardSortMode::ByAlignment;
-    else
-      sortMode = WildcardSortMode::ByNameAndAlignment;
-  }
-
-  if (numParsedDirectives < 2 && _tok._kind == Token::kw_sort_by_name) {
-    consumeToken();
-    if (!expectAndConsume(Token::l_paren, "expected ("))
-      return -1;
-    ++numParsedDirectives;
-    if (sortMode == WildcardSortMode::ByAlignment)
-      sortMode = WildcardSortMode::ByAlignmentAndName;
-  }
-
-  if (numParsedDirectives < 2 && _tok._kind == Token::kw_sort_by_alignment) {
-    consumeToken();
-    if (!expectAndConsume(Token::l_paren, "expected ("))
-      return -1;
-    ++numParsedDirectives;
-  }
-
-  if (numParsedDirectives == 0 && _tok._kind == Token::kw_sort_none) {
-    consumeToken();
-    if (!expectAndConsume(Token::l_paren, "expected ("))
-      return -1;
-    ++numParsedDirectives;
-    sortMode = WildcardSortMode::None;
-  }
-
-  return numParsedDirectives;
-}
-
-const InputSection *Parser::parseSortedInputSections() {
-  assert((_tok._kind == Token::kw_sort_by_name ||
-          _tok._kind == Token::kw_sort_by_alignment ||
-          _tok._kind == Token::kw_sort_by_init_priority ||
-          _tok._kind == Token::kw_sort_none) &&
-         "Expected SORT directives!");
-
-  WildcardSortMode sortMode = WildcardSortMode::NA;
-  int numParen = parseSortDirectives(sortMode);
-  if (numParen == -1)
-    return nullptr;
-
-  SmallVector<const InputSection *, 8> inputSections;
-
-  while (_tok._kind == Token::identifier) {
-    inputSections.push_back(new (_alloc)
-                                InputSectionName(*this, _tok._range, false));
-    consumeToken();
-  }
-
-  // Eat "numParen" rparens
-  for (int i = 0, e = numParen; i != e; ++i)
-    if (!expectAndConsume(Token::r_paren, "expected )"))
-      return nullptr;
-
-  return new (_alloc) InputSectionSortedGroup(*this, sortMode, inputSections);
-}
-
-const InputSectionsCmd *Parser::parseInputSectionsCmd() {
-  assert((_tok._kind == Token::identifier || _tok._kind == Token::colon ||
-          _tok._kind == Token::star || _tok._kind == Token::kw_keep ||
-          _tok._kind == Token::kw_sort_by_name ||
-          _tok._kind == Token::kw_sort_by_alignment ||
-          _tok._kind == Token::kw_sort_by_init_priority ||
-          _tok._kind == Token::kw_sort_none) &&
-         "Expected input section first tokens!");
-  int numParen = 1;
-  bool keep = false;
-  WildcardSortMode fileSortMode = WildcardSortMode::NA;
-  WildcardSortMode archiveSortMode = WildcardSortMode::NA;
-  StringRef memberName;
-  StringRef archiveName;
-
-  if (_tok._kind == Token::kw_keep) {
-    consumeToken();
-    if (!expectAndConsume(Token::l_paren, "expected ("))
-      return nullptr;
-    ++numParen;
-    keep = true;
-  }
-
-  // Input name
-  if (_tok._kind != Token::colon) {
-    int numParen = parseSortDirectives(fileSortMode);
-    if (numParen == -1)
-      return nullptr;
-    memberName = _tok._range;
-    consumeToken();
-    if (numParen) {
-      while (numParen--)
-        if (!expectAndConsume(Token::r_paren, "expected )"))
-          return nullptr;
-    }
-  }
-  if (_tok._kind == Token::colon) {
-    consumeToken();
-    if (_tok._kind == Token::identifier ||
-        _tok._kind == Token::kw_sort_by_name ||
-        _tok._kind == Token::kw_sort_by_alignment ||
-        _tok._kind == Token::kw_sort_by_init_priority ||
-        _tok._kind == Token::kw_sort_none) {
-      int numParen = parseSortDirectives(archiveSortMode);
-      if (numParen == -1)
-        return nullptr;
-      archiveName = _tok._range;
-      consumeToken();
-      for (int i = 0; i != numParen; ++i)
-       if (!expectAndConsume(Token::r_paren, "expected )"))
-         return nullptr;
-    }
-  }
-
-  SmallVector<const InputSection *, 8> inputSections;
-
-  if (_tok._kind != Token::l_paren)
-    return new (_alloc)
-        InputSectionsCmd(*this, memberName, archiveName, keep, fileSortMode,
-                         archiveSortMode, inputSections);
-  consumeToken();
-
-  while (_tok._kind == Token::identifier ||
-         _tok._kind == Token::kw_exclude_file ||
-         _tok._kind == Token::kw_sort_by_name ||
-         _tok._kind == Token::kw_sort_by_alignment ||
-         _tok._kind == Token::kw_sort_by_init_priority ||
-         _tok._kind == Token::kw_sort_none) {
-    switch (_tok._kind) {
-    case Token::kw_exclude_file: {
-      auto vec = parseExcludeFile();
-      if (vec.getError())
-        return nullptr;
-      inputSections.insert(inputSections.end(), vec->begin(), vec->end());
-      break;
-    }
-    case Token::star:
-    case Token::identifier: {
-      inputSections.push_back(new (_alloc)
-                                  InputSectionName(*this, _tok._range, false));
-      consumeToken();
-      break;
-    }
-    case Token::kw_sort_by_name:
-    case Token::kw_sort_by_alignment:
-    case Token::kw_sort_by_init_priority:
-    case Token::kw_sort_none: {
-      const InputSection *group = parseSortedInputSections();
-      if (!group)
-        return nullptr;
-      inputSections.push_back(group);
-      break;
-    }
-    default:
-      llvm_unreachable("Unknown token");
-    }
-  }
-
-  for (int i = 0; i < numParen; ++i)
-    if (!expectAndConsume(Token::r_paren, "expected )"))
-      return nullptr;
-  return new (_alloc)
-      InputSectionsCmd(*this, memberName, archiveName, keep, fileSortMode,
-                       archiveSortMode, inputSections);
-}
-
-const FillCmd *Parser::parseFillCmd() {
-  assert(_tok._kind == Token::kw_fill && "Expected FILL!");
-  consumeToken();
-  if (!expectAndConsume(Token::l_paren, "expected ("))
-    return nullptr;
-
-  SmallVector<uint8_t, 8> storage;
-
-  // If the expression is just a number, it's arbitrary length.
-  if (_tok._kind == Token::number && peek()._kind == Token::r_paren) {
-    if (_tok._range.size() > 2 && _tok._range.startswith("0x")) {
-      StringRef num = _tok._range.substr(2);
-      for (char c : num) {
-        unsigned nibble = llvm::hexDigitValue(c);
-        if (nibble == -1u)
-          goto not_simple_hex;
-        storage.push_back(nibble);
-      }
-      
-      if (storage.size() % 2 != 0)
-        storage.insert(storage.begin(), 0);
-
-      // Collapse nibbles.
-      for (std::size_t i = 0, e = storage.size() / 2; i != e; ++i)
-        storage[i] = (storage[i * 2] << 4) + storage[(i * 2) + 1];
-
-      storage.resize(storage.size() / 2);
-    }
-  }
-not_simple_hex:
-
-  const Expression *expr = parseExpression();
-  if (!expr)
-    return nullptr;
-  if (!expectAndConsume(Token::r_paren, "expected )"))
-    return nullptr;
-  
-  return new(getAllocator()) FillCmd(*this, storage);
-}
-
-const OutputSectionDescription *Parser::parseOutputSectionDescription() {
-  assert((_tok._kind == Token::kw_discard || _tok._kind == Token::identifier) &&
-         "Expected /DISCARD/ or identifier!");
-  StringRef sectionName;
-  const Expression *address = nullptr;
-  const Expression *align = nullptr;
-  const Expression *subAlign = nullptr;
-  const Expression *at = nullptr;
-  const Expression *fillExpr = nullptr;
-  StringRef fillStream;
-  bool alignWithInput = false;
-  bool discard = false;
-  OutputSectionDescription::Constraint constraint =
-      OutputSectionDescription::C_None;
-  SmallVector<const Command *, 8> outputSectionCommands;
-
-  if (_tok._kind == Token::kw_discard)
-    discard = true;
-  else
-    sectionName = _tok._range;
-  consumeToken();
-
-  if (_tok._kind == Token::number || _tok._kind == Token::identifier ||
-      _tok._kind == Token::kw_align || _tok._kind == Token::l_paren) {
-    address = parseExpression();
-    if (!address)
-      return nullptr;
-  }
-
-  if (!expectAndConsume(Token::colon, "expected :"))
-    return nullptr;
-
-  if (_tok._kind == Token::kw_at) {
-    consumeToken();
-    at = parseExpression();
-    if (!at)
-      return nullptr;
-  }
-
-  if (_tok._kind == Token::kw_align) {
-    consumeToken();
-    align = parseExpression();
-    if (!align)
-      return nullptr;
-  }
-
-  if (_tok._kind == Token::kw_align_with_input) {
-    consumeToken();
-    alignWithInput = true;
-  }
-
-  if (_tok._kind == Token::kw_subalign) {
-    consumeToken();
-    subAlign = parseExpression();
-    if (!subAlign)
-      return nullptr;
-  }
-
-  if (_tok._kind == Token::kw_only_if_ro) {
-    consumeToken();
-    constraint = OutputSectionDescription::C_OnlyIfRO;
-  } else if (_tok._kind == Token::kw_only_if_rw) {
-    consumeToken();
-    constraint = OutputSectionDescription::C_OnlyIfRW;
-  }
-
-  if (!expectAndConsume(Token::l_brace, "expected {"))
-    return nullptr;
-
-  // Parse zero or more output-section-commands
-  while (_tok._kind != Token::r_brace) {
-    switch (_tok._kind) {
-    case Token::semicolon:
-      consumeToken();
-      break;
-    case Token::identifier:
-      switch (peek()._kind) {
-      case Token::equal:
-      case Token::plusequal:
-      case Token::minusequal:
-      case Token::starequal:
-      case Token::slashequal:
-      case Token::ampequal:
-      case Token::pipeequal:
-      case Token::lesslessequal:
-      case Token::greatergreaterequal:
-        if (const Command *cmd = parseSymbolAssignment())
-          outputSectionCommands.push_back(cmd);
-        else
-          return nullptr;
-        break;
-      default:
-        if (const Command *cmd = parseInputSectionsCmd())
-          outputSectionCommands.push_back(cmd);
-        else
-          return nullptr;
-        break;
-      }
-      break;
-    case Token::kw_fill:
-      if (const Command *cmd = parseFillCmd())
-        outputSectionCommands.push_back(cmd);
-      else
-        return nullptr;
-      break;
-    case Token::kw_keep:
-    case Token::star:
-    case Token::colon:
-    case Token::kw_sort_by_name:
-    case Token::kw_sort_by_alignment:
-    case Token::kw_sort_by_init_priority:
-    case Token::kw_sort_none:
-      if (const Command *cmd = parseInputSectionsCmd())
-        outputSectionCommands.push_back(cmd);
-      else
-        return nullptr;
-      break;
-    case Token::kw_hidden:
-    case Token::kw_provide:
-    case Token::kw_provide_hidden:
-      if (const Command *cmd = parseSymbolAssignment())
-        outputSectionCommands.push_back(cmd);
-      else
-        return nullptr;
-      break;
-    default:
-      error(_tok, "expected symbol assignment or input file name.");
-      return nullptr;
-    }
-  }
-
-  if (!expectAndConsume(Token::r_brace, "expected }"))
-    return nullptr;
-
-  SmallVector<StringRef, 2> phdrs;
-  while (_tok._kind == Token::colon) {
-    consumeToken();
-    if (_tok._kind != Token::identifier) {
-      error(_tok, "expected program header name");
-      return nullptr;
-    }
-    phdrs.push_back(_tok._range);
-    consumeToken();
-  }
-
-  if (_tok._kind == Token::equal) {
-    consumeToken();
-    if (_tok._kind != Token::number || !_tok._range.startswith_lower("0x")) {
-      fillExpr = parseExpression();
-      if (!fillExpr)
-        return nullptr;
-    } else {
-      std::string strBuf;
-      if (isExpressionOperator(peek()) ||
-          !parseHexToByteStream(_tok._range.drop_front(2), strBuf)) {
-        fillExpr = parseExpression();
-        if(!fillExpr)
-          return nullptr;
-      } else {
-        char *rawBuf = (char *) _alloc.Allocate(strBuf.size(), 1);
-        memcpy(rawBuf, strBuf.c_str(), strBuf.size());
-        fillStream = StringRef(rawBuf, strBuf.size());
-        consumeToken();
-      }
-    }
-  }
-
-  return new (_alloc) OutputSectionDescription(
-      *this, sectionName, address, align, subAlign, at, fillExpr, fillStream,
-      alignWithInput, discard, constraint, outputSectionCommands, phdrs);
-}
-
-const Overlay *Parser::parseOverlay() {
-  assert(_tok._kind == Token::kw_overlay && "Expected OVERLAY!");
-  error(_tok, "Overlay description is not yet supported.");
-  return nullptr;
-}
-
-const PHDR *Parser::parsePHDR() {
-  assert(_tok._kind == Token::identifier && "Expected identifier!");
-  
-  StringRef name = _tok._range;
-  consumeToken();
-    
-  uint64_t type;
-
-  switch (_tok._kind) {
-  case Token::identifier:
-  case Token::number:
-  case Token::l_paren: {
-    const Expression *expr = parseExpression();
-    if (!expr)
-      return nullptr;
-    Expression::SymbolTableTy PHDRTypes;
-#define PHDR_INSERT(x) PHDRTypes.insert(std::make_pair(#x, llvm::ELF::x))
-    PHDR_INSERT(PT_NULL);
-    PHDR_INSERT(PT_LOAD);
-    PHDR_INSERT(PT_DYNAMIC);
-    PHDR_INSERT(PT_INTERP);
-    PHDR_INSERT(PT_NOTE);
-    PHDR_INSERT(PT_SHLIB);
-    PHDR_INSERT(PT_PHDR);
-    PHDR_INSERT(PT_TLS);
-    PHDR_INSERT(PT_LOOS);
-    PHDR_INSERT(PT_GNU_EH_FRAME);
-    PHDR_INSERT(PT_GNU_STACK);
-    PHDR_INSERT(PT_GNU_RELRO);
-    PHDR_INSERT(PT_SUNW_EH_FRAME);
-    PHDR_INSERT(PT_SUNW_UNWIND);
-    PHDR_INSERT(PT_HIOS);
-    PHDR_INSERT(PT_LOPROC);
-    PHDR_INSERT(PT_ARM_ARCHEXT);
-    PHDR_INSERT(PT_ARM_EXIDX);
-    PHDR_INSERT(PT_ARM_UNWIND);
-    PHDR_INSERT(PT_MIPS_REGINFO);
-    PHDR_INSERT(PT_MIPS_RTPROC);
-    PHDR_INSERT(PT_MIPS_OPTIONS);
-    PHDR_INSERT(PT_MIPS_ABIFLAGS);
-    PHDR_INSERT(PT_HIPROC);
-#undef PHDR_INSERT
-    auto t = expr->evalExpr(PHDRTypes);
-    if (t == LinkerScriptReaderError::unknown_symbol_in_expr) {
-      error(_tok, "Unknown type");
-      return nullptr;
-    }
-    if (!t)
-      return nullptr;
-    type = *t;
-    break;
-  }
-  default:
-    error(_tok, "expected identifier or expression");
-    return nullptr;
-  }
-
-  uint64_t flags = 0;
-  const Expression *flagsExpr = nullptr;
-  bool includeFileHdr = false;
-  bool includePHDRs = false;
-
-  while (_tok._kind != Token::semicolon) {
-    switch (_tok._kind) {
-    case Token::kw_filehdr:
-      if (includeFileHdr) {
-        error(_tok, "Duplicate FILEHDR attribute");
-        return nullptr;
-      }
-      includeFileHdr = true;
-      consumeToken();
-      break;
-    case Token::kw_phdrs:
-      if (includePHDRs) {
-        error(_tok, "Duplicate PHDRS attribute");
-        return nullptr;
-      }
-      includePHDRs = true;
-      consumeToken();
-      break;
-    case Token::kw_flags: {
-      if (flagsExpr) {
-        error(_tok, "Duplicate FLAGS attribute");
-        return nullptr;
-      }
-      consumeToken();
-      if (!expectAndConsume(Token::l_paren, "Expected ("))
-        return nullptr;
-      flagsExpr = parseExpression();
-      if (!flagsExpr)
-        return nullptr;
-      auto f = flagsExpr->evalExpr();
-      if (!f)
-        return nullptr;
-      flags = *f;
-      if (!expectAndConsume(Token::r_paren, "Expected )"))
-        return nullptr;
-    } break;
-    default:
-      error(_tok, "Unexpected token");
-      return nullptr;
-    }
-  }
-  
-  if (!expectAndConsume(Token::semicolon, "Expected ;"))
-    return nullptr;
-
-  return new (getAllocator())
-      PHDR(name, type, includeFileHdr, includePHDRs, nullptr, flags);
-}
-
-PHDRS *Parser::parsePHDRS() {
-  assert(_tok._kind == Token::kw_phdrs && "Expected PHDRS!");
-  consumeToken();
-  if (!expectAndConsume(Token::l_brace, "expected {"))
-    return nullptr;
-
-  SmallVector<const PHDR *, 8> phdrs;
-
-  while (true) {
-    if (_tok._kind == Token::identifier) {
-      const PHDR *phdr = parsePHDR();
-      if (!phdr)
-        return nullptr;
-      phdrs.push_back(phdr);
-    } else
-      break;
-  }
-
-  if (!expectAndConsume(Token::r_brace, "expected }"))
-    return nullptr;
-
-  return new (getAllocator()) PHDRS(*this, phdrs);
-}
-
-Sections *Parser::parseSections() {
-  assert(_tok._kind == Token::kw_sections && "Expected SECTIONS!");
-  consumeToken();
-  if (!expectAndConsume(Token::l_brace, "expected {"))
-    return nullptr;
-  SmallVector<const Command *, 8> sectionsCommands;
-
-  bool unrecognizedToken = false;
-  // Parse zero or more sections-commands
-  while (!unrecognizedToken) {
-    switch (_tok._kind) {
-    case Token::semicolon:
-      consumeToken();
-      break;
-
-    case Token::identifier:
-      switch (peek()._kind) {
-      case Token::equal:
-      case Token::plusequal:
-      case Token::minusequal:
-      case Token::starequal:
-      case Token::slashequal:
-      case Token::ampequal:
-      case Token::pipeequal:
-      case Token::lesslessequal:
-      case Token::greatergreaterequal:
-        if (const Command *cmd = parseSymbolAssignment())
-          sectionsCommands.push_back(cmd);
-        else
-          return nullptr;
-        break;
-      default:
-        if (const Command *cmd = parseOutputSectionDescription())
-          sectionsCommands.push_back(cmd);
-        else
-          return nullptr;
-        break;
-      }
-      break;
-
-    case Token::kw_discard:
-    case Token::star:
-      if (const Command *cmd = parseOutputSectionDescription())
-        sectionsCommands.push_back(cmd);
-      else
-        return nullptr;
-      break;
-
-    case Token::kw_entry:
-      if (const Command *cmd = parseEntry())
-        sectionsCommands.push_back(cmd);
-      else
-        return nullptr;
-      break;
-
-    case Token::kw_hidden:
-    case Token::kw_provide:
-    case Token::kw_provide_hidden:
-      if (const Command *cmd = parseSymbolAssignment())
-        sectionsCommands.push_back(cmd);
-      else
-        return nullptr;
-      break;
-
-    case Token::kw_overlay:
-      if (const Command *cmd = parseOverlay())
-        sectionsCommands.push_back(cmd);
-      else
-        return nullptr;
-      break;
-
-    default:
-      unrecognizedToken = true;
-      break;
-    }
-  }
-
-  if (!expectAndConsume(
-          Token::r_brace,
-          "expected symbol assignment, entry, overlay or output section name."))
-    return nullptr;
-
-  return new (_alloc) Sections(*this, sectionsCommands);
-}
-
-Memory *Parser::parseMemory() {
-  assert(_tok._kind == Token::kw_memory && "Expected MEMORY!");
-  consumeToken();
-  if (!expectAndConsume(Token::l_brace, "expected {"))
-    return nullptr;
-  SmallVector<const MemoryBlock *, 8> blocks;
-
-  bool unrecognizedToken = false;
-  // Parse zero or more memory block descriptors.
-  while (!unrecognizedToken) {
-    if (_tok._kind == Token::identifier) {
-      StringRef name;
-      StringRef attrs;
-      const Expression *origin = nullptr;
-      const Expression *length = nullptr;
-
-      name = _tok._range;
-      consumeToken();
-
-      // Parse optional memory region attributes.
-      if (_tok._kind == Token::l_paren) {
-        consumeToken();
-
-        if (_tok._kind != Token::identifier) {
-          error(_tok, "Expected memory attribute string.");
-          return nullptr;
-        }
-        attrs = _tok._range;
-        consumeToken();
-
-        if (!expectAndConsume(Token::r_paren, "expected )"))
-          return nullptr;
-      }
-
-      if (!expectAndConsume(Token::colon, "expected :"))
-        return nullptr;
-
-      // Parse the ORIGIN (base address of memory block).
-      if (!expectAndConsume(Token::kw_origin, "expected ORIGIN"))
-        return nullptr;
-
-      if (!expectAndConsume(Token::equal, "expected ="))
-        return nullptr;
-
-      origin = parseExpression();
-      if (!origin)
-        return nullptr;
-
-      if (!expectAndConsume(Token::comma, "expected ,"))
-        return nullptr;
-
-      // Parse the LENGTH (length of memory block).
-      if (!expectAndConsume(Token::kw_length, "expected LENGTH"))
-        return nullptr;
-
-      if (!expectAndConsume(Token::equal, "expected ="))
-        return nullptr;
-
-      length = parseExpression();
-      if (!length)
-        return nullptr;
-
-      auto *block = new (_alloc) MemoryBlock(name, attrs, origin, length);
-      blocks.push_back(block);
-    } else {
-      unrecognizedToken = true;
-    }
-  }
-  if (!expectAndConsume(
-          Token::r_brace,
-          "expected memory block definition."))
-    return nullptr;
-
-  return new (_alloc) Memory(*this, blocks);
-}
-
-Extern *Parser::parseExtern() {
-  assert(_tok._kind == Token::kw_extern && "Expected EXTERN!");
-  consumeToken();
-  if (!expectAndConsume(Token::l_paren, "expected ("))
-    return nullptr;
-
-  // Parse one or more symbols.
-  SmallVector<StringRef, 8> symbols;
-  if (_tok._kind != Token::identifier) {
-    error(_tok, "expected one or more symbols in EXTERN.");
-    return nullptr;
-  }
-  symbols.push_back(_tok._range);
-  consumeToken();
-  while (_tok._kind == Token::identifier) {
-    symbols.push_back(_tok._range);
-    consumeToken();
-  }
-
-  if (!expectAndConsume(Token::r_paren, "expected symbol in EXTERN."))
-    return nullptr;
-
-  return new (_alloc) Extern(*this, symbols);
-}
-
-// Sema member functions
-Sema::Sema() : _programPHDR(nullptr) {}
-
-std::error_code Sema::perform() {
-  llvm::StringMap<const PHDR *> phdrs;
-
-  for (auto &parser : _scripts) {
-    for (const Command *c : parser->get()->_commands) {
-      if (const auto *sec = dyn_cast<Sections>(c)) {
-        linearizeAST(sec);
-      } else if (const auto *ph = dyn_cast<PHDRS>(c)) {
-        if (auto ec = collectPHDRs(ph, phdrs))
-          return ec;
-      }
-    }
-  }
-  return buildSectionToPHDR(phdrs);
-}
-
-bool Sema::less(const SectionKey &lhs, const SectionKey &rhs) const {
-  int a = getLayoutOrder(lhs, true);
-  int b = getLayoutOrder(rhs, true);
-
-  if (a != b) {
-    if (a < 0)
-      return false;
-    if (b < 0)
-      return true;
-    return a < b;
-  }
-
-  // If both sections are not mapped anywhere, they have the same order
-  if (a < 0)
-    return false;
-
-  // If both sections fall into the same layout order, we need to find their
-  // relative position as written in the (InputSectionsCmd).
-  return localCompare(a, lhs, rhs);
-}
-
-StringRef Sema::getOutputSection(const SectionKey &key) const {
-  int layoutOrder = getLayoutOrder(key, true);
-  if (layoutOrder < 0)
-    return StringRef();
-
-  for (int i = layoutOrder - 1; i >= 0; --i) {
-    if (!isa<OutputSectionDescription>(_layoutCommands[i]))
-      continue;
-
-    const OutputSectionDescription *out =
-        dyn_cast<OutputSectionDescription>(_layoutCommands[i]);
-    return out->name();
-  }
-
-  return StringRef();
-}
-
-std::vector<const SymbolAssignment *>
-Sema::getExprs(const SectionKey &key) {
-  int layoutOrder = getLayoutOrder(key, false);
-  auto ans = std::vector<const SymbolAssignment *>();
-
-  if (layoutOrder < 0 || _deliveredExprs.count(layoutOrder) > 0)
-    return ans;
-
-  for (int i = layoutOrder - 1; i >= 0; --i) {
-    if (isa<InputSection>(_layoutCommands[i]))
-      break;
-    if (auto assgn = dyn_cast<SymbolAssignment>(_layoutCommands[i]))
-      ans.push_back(assgn);
-  }
-
-  // Reverse this order so we evaluate the expressions in the original order
-  // of the linker script
-  std::reverse(ans.begin(), ans.end());
-
-  // Mark this layout number as delivered
-  _deliveredExprs.insert(layoutOrder);
-  return ans;
-}
-
-std::error_code Sema::evalExpr(const SymbolAssignment *assgn,
-                               uint64_t &curPos) {
-  _symbolTable[StringRef(".")] = curPos;
-
-  auto ans = assgn->expr()->evalExpr(_symbolTable);
-  if (ans.getError())
-    return ans.getError();
-  uint64_t result = *ans;
-
-  if (assgn->symbol() == ".") {
-    curPos = result;
-    return std::error_code();
-  }
-
-  _symbolTable[assgn->symbol()] = result;
-  return std::error_code();
-}
-
-const llvm::StringSet<> &Sema::getScriptDefinedSymbols() const {
-  // Do we have cached results?
-  if (!_definedSymbols.empty())
-    return _definedSymbols;
-
-  // Populate our defined set and return it
-  for (auto cmd : _layoutCommands)
-    if (auto sa = dyn_cast<SymbolAssignment>(cmd)) {
-      StringRef symbol = sa->symbol();
-      if (!symbol.empty() && symbol != ".")
-        _definedSymbols.insert(symbol);
-    }
-
-  return _definedSymbols;
-}
-
-uint64_t Sema::getLinkerScriptExprValue(StringRef name) const {
-  auto it = _symbolTable.find(name);
-  assert (it != _symbolTable.end() && "Invalid symbol name!");
-  return it->second;
-}
-
-bool Sema::hasPHDRs() const { return !_sectionToPHDR.empty(); }
-
-std::vector<const PHDR *> Sema::getPHDRsForOutputSection(StringRef name) const {
-  auto vec = _sectionToPHDR.lookup(name);
-  return std::vector<const PHDR *>(std::begin(vec), std::end(vec));
-}
-
-const PHDR *Sema::getProgramPHDR() const { return _programPHDR; }
-
-void Sema::dump() const {
-  raw_ostream &os = llvm::outs();
-  os << "Linker script semantics dump\n";
-  int num = 0;
-  for (auto &parser : _scripts) {
-    os << "Dumping script #" << ++num << ":\n";
-    parser->get()->dump(os);
-    os << "\n";
-  }
-  os << "Dumping rule ids:\n";
-  for (unsigned i = 0; i < _layoutCommands.size(); ++i) {
-    os << "LayoutOrder " << i << ":\n";
-    _layoutCommands[i]->dump(os);
-    os << "\n\n";
-  }
-}
-
-/// Given a string "pattern" with wildcard characters, return true if it
-/// matches "name". This function is useful when checking if a given name
-/// pattern written in the linker script, i.e. ".text*", should match
-/// ".text.anytext".
-static bool wildcardMatch(StringRef pattern, StringRef name) {
-  auto i = name.begin();
-
-  // Check if each char in pattern also appears in our input name, handling
-  // special wildcard characters.
-  for (auto j = pattern.begin(), e = pattern.end(); j != e; ++j) {
-    if (i == name.end())
-      return false;
-
-    switch (*j) {
-    case '*':
-      while (!wildcardMatch(pattern.drop_front(j - pattern.begin() + 1),
-                            name.drop_front(i - name.begin()))) {
-        if (i == name.end())
-          return false;
-        ++i;
-      }
-      break;
-    case '?':
-      // Matches any character
-      ++i;
-      break;
-    case '[': {
-      // Matches a range of characters specified between brackets
-      size_t end = pattern.find(']', j - pattern.begin());
-      if (end == pattern.size())
-        return false;
-
-      StringRef chars = pattern.slice(j - pattern.begin(), end);
-      if (chars.find(i) == StringRef::npos)
-        return false;
-
-      j = pattern.begin() + end;
-      ++i;
-      break;
-    }
-    case '\\':
-      ++j;
-      if (*j != *i)
-        return false;
-      ++i;
-      break;
-    default:
-      // No wildcard character means we must match exactly the same char
-      if (*j != *i)
-        return false;
-      ++i;
-      break;
-    }
-  }
-
-  // If our pattern has't consumed the entire string, it is not a match
-  return i == name.end();
-}
-
-int Sema::matchSectionName(int id, const SectionKey &key) const {
-  const InputSectionsCmd *cmd = dyn_cast<InputSectionsCmd>(_layoutCommands[id]);
-
-  if (!cmd || !wildcardMatch(cmd->archiveName(), key.archivePath))
-    return -1;
-
-  while ((size_t)++id < _layoutCommands.size() &&
-         (isa<InputSection>(_layoutCommands[id]))) {
-    if (isa<InputSectionSortedGroup>(_layoutCommands[id]))
-      continue;
-
-    const InputSectionName *in =
-        dyn_cast<InputSectionName>(_layoutCommands[id]);
-    if (wildcardMatch(in->name(), key.sectionName))
-      return id;
-  }
-  return -1;
-}
-
-int Sema::getLayoutOrder(const SectionKey &key, bool coarse) const {
-  // First check if we already answered this layout question
-  if (coarse) {
-    auto entry = _cacheSectionOrder.find(key);
-    if (entry != _cacheSectionOrder.end())
-      return entry->second;
-  } else {
-    auto entry = _cacheExpressionOrder.find(key);
-    if (entry != _cacheExpressionOrder.end())
-      return entry->second;
-  }
-
-  // Try to match exact file name
-  auto range = _memberToLayoutOrder.equal_range(key.memberPath);
-  for (auto I = range.first, E = range.second; I != E; ++I) {
-    int order = I->second;
-    int exprOrder = -1;
-
-    if ((exprOrder = matchSectionName(order, key)) >= 0) {
-      if (coarse) {
-        _cacheSectionOrder.insert(std::make_pair(key, order));
-        return order;
-      }
-      _cacheExpressionOrder.insert(std::make_pair(key, exprOrder));
-      return exprOrder;
-    }
-  }
-
-  // If we still couldn't find a rule for this input section, try to match
-  // wildcards
-  for (const auto &I : _memberNameWildcards) {
-    if (!wildcardMatch(I.first, key.memberPath))
-      continue;
-    int order = I.second;
-    int exprOrder = -1;
-
-    if ((exprOrder = matchSectionName(order, key)) >= 0) {
-      if (coarse) {
-        _cacheSectionOrder.insert(std::make_pair(key, order));
-        return order;
-      }
-      _cacheExpressionOrder.insert(std::make_pair(key, exprOrder));
-      return exprOrder;
-    }
-  }
-
-  _cacheSectionOrder.insert(std::make_pair(key, -1));
-  _cacheExpressionOrder.insert(std::make_pair(key, -1));
-  return -1;
-}
-
-static bool compareSortedNames(WildcardSortMode sortMode, StringRef lhs,
-                               StringRef rhs) {
-  switch (sortMode) {
-  case WildcardSortMode::None:
-  case WildcardSortMode::NA:
-    return false;
-  case WildcardSortMode::ByAlignment:
-  case WildcardSortMode::ByInitPriority:
-  case WildcardSortMode::ByAlignmentAndName:
-    assert(false && "Unimplemented sort order");
-    break;
-  case WildcardSortMode::ByName:
-    return lhs.compare(rhs) < 0;
-  case WildcardSortMode::ByNameAndAlignment:
-    int compare = lhs.compare(rhs);
-    if (compare != 0)
-      return compare < 0;
-    return compareSortedNames(WildcardSortMode::ByAlignment, lhs, rhs);
-  }
-  return false;
-}
-
-static bool sortedGroupContains(const InputSectionSortedGroup *cmd,
-                                const Sema::SectionKey &key) {
-  for (const InputSection *child : *cmd) {
-    if (auto i = dyn_cast<InputSectionName>(child)) {
-      if (wildcardMatch(i->name(), key.sectionName))
-        return true;
-      continue;
-    }
-
-    auto *sortedGroup = dyn_cast<InputSectionSortedGroup>(child);
-    assert(sortedGroup && "Expected InputSectionSortedGroup object");
-
-    if (sortedGroupContains(sortedGroup, key))
-      return true;
-  }
-
-  return false;
-}
-
-bool Sema::localCompare(int order, const SectionKey &lhs,
-                        const SectionKey &rhs) const {
-  const InputSectionsCmd *cmd =
-      dyn_cast<InputSectionsCmd>(_layoutCommands[order]);
-
-  assert(cmd && "Invalid InputSectionsCmd index");
-
-  if (lhs.archivePath != rhs.archivePath)
-    return compareSortedNames(cmd->archiveSortMode(), lhs.archivePath,
-                              rhs.archivePath);
-
-  if (lhs.memberPath != rhs.memberPath)
-    return compareSortedNames(cmd->fileSortMode(), lhs.memberPath,
-                              rhs.memberPath);
-
-  // Both sections come from the same exact same file and rule. Start walking
-  // through input section names as written in the linker script and the
-  // first one to match will have higher priority.
-  for (const InputSection *inputSection : *cmd) {
-    if (auto i = dyn_cast<InputSectionName>(inputSection)) {
-      // If both match, return false (both have equal priority)
-      // If rhs match, return false (rhs has higher priority)
-      if (wildcardMatch(i->name(), rhs.sectionName))
-        return false;
-      //  If lhs matches first, it has priority over rhs
-      if (wildcardMatch(i->name(), lhs.sectionName))
-        return true;
-      continue;
-    }
-
-    // Handle sorted subgroups specially
-    auto *sortedGroup = dyn_cast<InputSectionSortedGroup>(inputSection);
-    assert(sortedGroup && "Expected InputSectionSortedGroup object");
-
-    bool a = sortedGroupContains(sortedGroup, lhs);
-    bool b = sortedGroupContains(sortedGroup, rhs);
-    if (a && !b)
-      return false;
-    if (b && !a)
-      return true;
-    if (!a && !a)
-      continue;
-
-    return compareSortedNames(sortedGroup->sortMode(), lhs.sectionName,
-                              rhs.sectionName);
-  }
-
-  llvm_unreachable("");
-  return false;
-}
-
-std::error_code Sema::collectPHDRs(const PHDRS *ph,
-                                   llvm::StringMap<const PHDR *> &phdrs) {
-  bool loadFound = false;
-  for (auto *p : *ph) {
-    phdrs[p->name()] = p;
-
-    switch (p->type()) {
-    case llvm::ELF::PT_PHDR:
-      if (_programPHDR != nullptr)
-        return LinkerScriptReaderError::extra_program_phdr;
-      if (loadFound)
-        return LinkerScriptReaderError::misplaced_program_phdr;
-      if (!p->hasPHDRs())
-        return LinkerScriptReaderError::program_phdr_wrong_phdrs;
-      _programPHDR = p;
-      break;
-    case llvm::ELF::PT_LOAD:
-      // Program header, if available, should have program header table
-      // mapped in the first loadable segment.
-      if (!loadFound && _programPHDR && !p->hasPHDRs())
-        return LinkerScriptReaderError::program_phdr_wrong_phdrs;
-      loadFound = true;
-      break;
-    }
-  }
-  return std::error_code();
-}
-
-std::error_code Sema::buildSectionToPHDR(llvm::StringMap<const PHDR *> &phdrs) {
-  const bool noPhdrs = phdrs.empty();
-
-  // Add NONE header to the map provided there's no user-defined
-  // header with the same name.
-  if (!phdrs.count(PHDR_NONE.name()))
-    phdrs[PHDR_NONE.name()] = &PHDR_NONE;
-
-  // Match output sections to available headers.
-  llvm::SmallVector<const PHDR *, 2> phdrsCur, phdrsLast { &PHDR_NONE };
-  for (const Command *cmd : _layoutCommands) {
-    auto osd = dyn_cast<OutputSectionDescription>(cmd);
-    if (!osd || osd->isDiscarded())
-      continue;
-
-    phdrsCur.clear();
-    for (StringRef name : osd->PHDRs()) {
-      auto it = phdrs.find(name);
-      if (it == phdrs.end()) {
-        return LinkerScriptReaderError::unknown_phdr_ids;
-      }
-      phdrsCur.push_back(it->second);
-    }
-
-    // If no headers and no errors - insert empty headers set.
-    // If the current set of headers is empty, then use the last non-empty
-    // set. Otherwise mark the current set to be the last non-empty set for
-    // successors.
-    if (noPhdrs)
-      phdrsCur.clear();
-    else if (phdrsCur.empty())
-      phdrsCur = phdrsLast;
-    else
-      phdrsLast = phdrsCur;
-
-    _sectionToPHDR[osd->name()] = phdrsCur;
-  }
-  return std::error_code();
-}
-
-static bool hasWildcard(StringRef name) {
-  for (auto ch : name)
-    if (ch == '*' || ch == '?' || ch == '[' || ch == '\\')
-      return true;
-  return false;
-}
-
-void Sema::linearizeAST(const InputSection *inputSection) {
-  if (isa<InputSectionName>(inputSection)) {
-    _layoutCommands.push_back(inputSection);
-    return;
-  }
-
-  auto *sortedGroup = dyn_cast<InputSectionSortedGroup>(inputSection);
-  assert(sortedGroup && "Expected InputSectionSortedGroup object");
-
-  for (const InputSection *child : *sortedGroup) {
-    linearizeAST(child);
-  }
-}
-
-void Sema::linearizeAST(const InputSectionsCmd *inputSections) {
-  StringRef memberName = inputSections->memberName();
-  // Populate our maps for fast lookup of InputSectionsCmd
-  if (hasWildcard(memberName))
-    _memberNameWildcards.push_back(
-        std::make_pair(memberName, (int)_layoutCommands.size()));
-  else if (!memberName.empty())
-    _memberToLayoutOrder.insert(
-        std::make_pair(memberName.str(), (int)_layoutCommands.size()));
-
-  _layoutCommands.push_back(inputSections);
-  for (const InputSection *inputSection : *inputSections)
-    linearizeAST(inputSection);
-}
-
-void Sema::linearizeAST(const Sections *sections) {
-  for (const Command *sectionCommand : *sections) {
-    if (isa<SymbolAssignment>(sectionCommand)) {
-      _layoutCommands.push_back(sectionCommand);
-      continue;
-    }
-
-    if (!isa<OutputSectionDescription>(sectionCommand))
-      continue;
-
-    _layoutCommands.push_back(sectionCommand);
-    auto *outSection = dyn_cast<OutputSectionDescription>(sectionCommand);
-
-    for (const Command *outSecCommand : *outSection) {
-      if (isa<SymbolAssignment>(outSecCommand)) {
-        _layoutCommands.push_back(outSecCommand);
-        continue;
-      }
-
-      if (!isa<InputSectionsCmd>(outSecCommand))
-        continue;
-
-      linearizeAST(dyn_cast<InputSectionsCmd>(outSecCommand));
-    }
-  }
-}
-
-} // end namespace script
-} // end namespace lld
index b92489e..93ae328 100644 (file)
@@ -22,7 +22,7 @@ configure_lit_site_cfg(
 set(LLD_TEST_DEPS
   FileCheck not llvm-ar llvm-as llvm-nm llc
   lld llvm-config llvm-objdump llvm-readobj yaml2obj obj2yaml
-  linker-script-test llvm-mc llvm-nm llvm-lib
+  llvm-mc llvm-nm llvm-lib
   )
 if (LLVM_INCLUDE_TESTS)
   set(LLD_TEST_DEPS ${LLD_TEST_DEPS} LLDUnitTests)
diff --git a/lld/test/LinkerScript/expr-precedence.test b/lld/test/LinkerScript/expr-precedence.test
deleted file mode 100644 (file)
index 5170e34..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
-  RUN: linker-script-test %s | FileCheck %s
-*/
-SECTIONS {
-    . = foo >= bar + 1 ? bar : 1- - - -1;
-}
-
-/*
-CHECK: kw_sections: SECTIONS
-CHECK: l_brace: {
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: identifier: foo
-CHECK: greaterequal: >=
-CHECK: identifier: bar
-CHECK: plus: +
-CHECK: number: 1
-CHECK: question: ?
-CHECK: identifier: bar
-CHECK: colon: :
-CHECK: number: 1
-CHECK: minus: -
-CHECK: minus: -
-CHECK: minus: -
-CHECK: minus: -
-CHECK: number: 1
-CHECK: semicolon: ;
-CHECK: r_brace: }
-CHECK: eof:
-CHECK: SECTIONS
-CHECK: {
-CHECK: . = (foo >= (bar + 1)) ? bar : (1 - (-(-(-1))))
-CHECK: }
-*/
diff --git a/lld/test/LinkerScript/extern-bad-symbol.test b/lld/test/LinkerScript/extern-bad-symbol.test
deleted file mode 100644 (file)
index 279a7cc..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
-  RUN: linker-script-test %s 2> %t | FileCheck %s
-  RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-
-
-EXTERN(a b 3)
-/*
-CHECK-ERR: [[@LINE-2]]:12: error: expected symbol in EXTERN.
-CHECK-ERR-NEXT: {{^EXTERN\(a b 3\)}}
-CHECK-ERR-NEXT: {{^          \^}}
-*/
-
-/*
-CHECK: kw_extern: EXTERN
-CHECK: l_paren: (
-CHECK: identifier: a
-CHECK: identifier: b
-CHECK: number: 3
-CHECK: r_paren: )
-CHECK: eof:
-*/
diff --git a/lld/test/LinkerScript/extern-empty.test b/lld/test/LinkerScript/extern-empty.test
deleted file mode 100644 (file)
index a5e1ece..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
-  RUN: linker-script-test %s 2> %t | FileCheck %s
-  RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-
-
-EXTERN()
-/*
-CHECK-ERR: [[@LINE-2]]:8: error: expected one or more symbols in EXTERN.
-CHECK-ERR-NEXT: {{^EXTERN()}}
-CHECK-ERR-NEXT: {{^     \^}}
-*/
-
-/*
-CHECK: kw_extern: EXTERN
-CHECK: l_paren: (
-CHECK: r_paren: )
-CHECK: eof:
-*/
diff --git a/lld/test/LinkerScript/extern-valid.test b/lld/test/LinkerScript/extern-valid.test
deleted file mode 100644 (file)
index 764b466..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-  RUN: linker-script-test %s | FileCheck %s
-*/
-
-EXTERN(a)
-EXTERN(a b)
-EXTERN(_foo _bar _baz)
-
-/*
-CHECK: kw_extern: EXTERN
-CHECK: l_paren: (
-CHECK: identifier: a
-CHECK: r_paren: )
-CHECK: kw_extern: EXTERN
-CHECK: l_paren: (
-CHECK: identifier: a
-CHECK: identifier: b
-CHECK: r_paren: )
-CHECK: kw_extern: EXTERN
-CHECK: l_paren: (
-CHECK: identifier: _foo
-CHECK: identifier: _bar
-CHECK: identifier: _baz
-CHECK: r_paren: )
-CHECK: eof:
-CHECK: EXTERN(a)
-CHECK: EXTERN(a b)
-CHECK: EXTERN(_foo _bar _baz)
-*/
diff --git a/lld/test/LinkerScript/incomplete-ternary.test b/lld/test/LinkerScript/incomplete-ternary.test
deleted file mode 100644 (file)
index fae3053..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
-  RUN: linker-script-test %s 2> %t | FileCheck %s
-  RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-SECTIONS {
-    . = foo ? bar;
-/*
-CHECK-ERR: [[@LINE-2]]:18: error: expected :
-CHECK-ERR-NEXT: {{^    \. = foo \? bar;}}
-CHECK-ERR-NEXT: {{^                 \^}}
-*/
-}
-
-/*
-CHECK: kw_sections: SECTIONS
-CHECK: l_brace: {
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: identifier: foo
-CHECK: question: ?
-CHECK: identifier: bar
-CHECK: semicolon: ;
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/lld/test/LinkerScript/libname-err-1.test b/lld/test/LinkerScript/libname-err-1.test
deleted file mode 100644 (file)
index 451a469..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/* RUN: linker-script-test %s 2>&1 | FileCheck %s
-*/
-
-OUTPUT_ARCH(i386:x86_64)
-OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
-GROUP( -l### )
-ENTRY(init)
-
-/*
-CHECK: libname-err-1.test:6:10: error: expected )
-*/
diff --git a/lld/test/LinkerScript/libname-err-2.test b/lld/test/LinkerScript/libname-err-2.test
deleted file mode 100644 (file)
index f1d96d7..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-/* RUN: linker-script-test %s 2>&1 | FileCheck %s
-*/
-
-OUTPUT_ARCH(i386:x86_64)
-OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
-GROUP( -l )
-ENTRY(init)
-
-/*
-CHECK: libname-err-2.test:6:10: error: expected )
-*/
diff --git a/lld/test/LinkerScript/linker-script-outputformat.test b/lld/test/LinkerScript/linker-script-outputformat.test
deleted file mode 100644 (file)
index b47bb38..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-/* RUN: linker-script-test %s | FileCheck %s
-*/
-
-OUTPUT_FORMAT(elf64-x86-64)
-
-/*
-CHECK: kw_output_format: OUTPUT_FORMAT
-CHECK: l_paren: (
-CHECK: identifier: elf64-x86-64
-CHECK: r_paren: )
-CHECK: OUTPUT_FORMAT("elf64-x86-64")
-*/
diff --git a/lld/test/LinkerScript/linker-script.test b/lld/test/LinkerScript/linker-script.test
deleted file mode 100644 (file)
index 4214936..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/* RUN: linker-script-test %s | FileCheck %s
-*/
-
-OUTPUT_ARCH(i386:x86_64)
-OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
-OUTPUT("/out/foo")
-GROUP ( /lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a  AS_NEEDED ( /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 ) -lm -l:libgcc.a )
-ENTRY(init)
-
-/*
-CHECK: kw_output_arch: OUTPUT_ARCH
-CHECK: l_paren: (
-CHECK: identifier: i386:x86_64
-CHECK: r_paren: )
-CHECK: kw_output_format: OUTPUT_FORMAT
-CHECK: l_paren: (
-CHECK: identifier: elf64-x86-64
-CHECK: comma: ,
-CHECK: identifier: elf64-x86-64
-CHECK: comma: ,
-CHECK: identifier: elf64-x86-64
-CHECK: r_paren: )
-CHECK: kw_output: OUTPUT
-CHECK: l_paren: (
-CHECK: identifier: /out/foo
-CHECK: r_paren: )
-CHECK: kw_group: GROUP
-CHECK: l_paren: (
-CHECK: identifier: /lib/x86_64-linux-gnu/libc.so.6
-CHECK: identifier: /usr/lib/x86_64-linux-gnu/libc_nonshared.a
-CHECK: kw_as_needed: AS_NEEDED
-CHECK: l_paren: (
-CHECK: identifier: /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2
-CHECK: r_paren: )
-CHECK: libname: m
-CHECK: libname: :libgcc.a
-CHECK: r_paren: )
-CHECK: kw_entry: ENTRY
-CHECK: l_paren: (
-CHECK: identifier: init
-CHECK: r_paren: )
-CHECK: eof:
-CHECK: OUTPUT_FORMAT("elf64-x86-64","elf64-x86-64","elf64-x86-64")
-CHECK: GROUP(/lib/x86_64-linux-gnu/libc.so.6 /usr/lib/x86_64-linux-gnu/libc_nonshared.a AS_NEEDED(/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2) -lm -l:libgcc.a)
-CHECK: ENTRY(init)
-*/
diff --git a/lld/test/LinkerScript/memory-empty.test b/lld/test/LinkerScript/memory-empty.test
deleted file mode 100644 (file)
index b71022a..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
-  RUN: linker-script-test %s | FileCheck %s
-*/
-
-MEMORY
-{
-}
-
-/*
-CHECK: kw_memory: MEMORY
-CHECK: l_brace: {
-CHECK: r_brace: }
-CHECK: eof:
-CHECK: MEMORY
-CHECK: {
-CHECK: }
-*/
diff --git a/lld/test/LinkerScript/memory-missing-attrs.test b/lld/test/LinkerScript/memory-missing-attrs.test
deleted file mode 100644 (file)
index fbbf38b..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
-  RUN: linker-script-test %s 2> %t | FileCheck %s
-  RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-
-MEMORY
-{
-  ram () : ORIGIN = 0x20000000, LENGTH = 128M
-/*
-CHECK-ERR: [[@LINE-2]]:8: error: Expected memory attribute string.
-CHECK-ERR-NEXT: {{^  ram \(\) : ORIGIN = 0x20000000, LENGTH = 128M}}
-CHECK-ERR-NEXT: {{^        \^}}
-*/
-}
-
-/*
-CHECK: kw_memory: MEMORY
-CHECK: l_brace: {
-CHECK: identifier: ram
-CHECK: l_paren: (
-CHECK: r_paren: )
-CHECK: colon: :
-CHECK: kw_origin: ORIGIN
-CHECK: equal: =
-CHECK: number: 0x20000000
-CHECK: comma: ,
-CHECK: kw_length: LENGTH
-CHECK: equal: =
-CHECK: number: 128M
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/lld/test/LinkerScript/memory-missing-length.test b/lld/test/LinkerScript/memory-missing-length.test
deleted file mode 100644 (file)
index f317c9a..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-  RUN: linker-script-test %s 2> %t | FileCheck %s
-  RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-
-MEMORY
-{
-  ram (rwx) : ORIGIN = 0x20000000,
-}
-/*
-CHECK-ERR: [[@LINE-2]]:1: error: expected LENGTH
-CHECK-ERR-NEXT: {{^}}}
-CHECK-ERR-NEXT: {{^\^}}
-*/
-
-/*
-CHECK: kw_memory: MEMORY
-CHECK: l_brace: {
-CHECK: identifier: ram
-CHECK: l_paren: (
-CHECK: identifier: rwx
-CHECK: r_paren: )
-CHECK: colon: :
-CHECK: kw_origin: ORIGIN
-CHECK: equal: =
-CHECK: number: 0x20000000
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/lld/test/LinkerScript/memory-missing-name.test b/lld/test/LinkerScript/memory-missing-name.test
deleted file mode 100644 (file)
index 46597d4..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
-  RUN: linker-script-test %s 2> %t | FileCheck %s
-  RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-
-MEMORY
-{
-  (rwx) : ORIGIN = 0x20000000, LENGTH = 128M
-/*
-CHECK-ERR: [[@LINE-2]]:3: error: expected memory block definition.
-CHECK-ERR-NEXT: {{^  \(rwx\) : ORIGIN = 0x20000000, LENGTH = 128M}}
-CHECK-ERR-NEXT: {{^  \^}}
-*/
-}
-
-/*
-CHECK: kw_memory: MEMORY
-CHECK: l_brace: {
-CHECK: l_paren: (
-CHECK: r_paren: )
-CHECK: colon: :
-CHECK: kw_origin: ORIGIN
-CHECK: equal: =
-CHECK: number: 0x20000000
-CHECK: comma: ,
-CHECK: kw_length: LENGTH
-CHECK: equal: =
-CHECK: number: 128M
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/lld/test/LinkerScript/memory-missing-origin.test b/lld/test/LinkerScript/memory-missing-origin.test
deleted file mode 100644 (file)
index 50a64d1..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
-  RUN: linker-script-test %s 2> %t | FileCheck %s
-  RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-
-MEMORY
-{
-  ram (rwx) : LENGTH = 128M
-/*
-CHECK-ERR: [[@LINE-2]]:15: error: expected ORIGIN
-CHECK-ERR-NEXT: {{^  ram \(rwx\) : LENGTH = 128M}}
-CHECK-ERR-NEXT: {{^               \^}}
-*/
-
-}
-
-/*
-CHECK: kw_memory: MEMORY
-CHECK: l_brace: {
-CHECK: identifier: ram
-CHECK: l_paren: (
-CHECK: identifier: rwx
-CHECK: r_paren: )
-CHECK: colon: :
-CHECK: kw_length: LENGTH
-CHECK: equal: =
-CHECK: number: 128M
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/lld/test/LinkerScript/memory-valid.test b/lld/test/LinkerScript/memory-valid.test
deleted file mode 100644 (file)
index 7a0e906..0000000
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
-  RUN: linker-script-test %s | FileCheck %s
-*/
-
-MEMORY
-{
-  ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K
-  rom (rx) : org = 0x0, len = 256K
-  boot : o = 0x1000000, l = 0x5f00
-}
-
-/*
-CHECK: kw_memory: MEMORY
-CHECK: l_brace: {
-CHECK: identifier: ram
-CHECK: l_paren: (
-CHECK: identifier: rwx
-CHECK: r_paren: )
-CHECK: colon: :
-CHECK: kw_origin: ORIGIN
-CHECK: equal: =
-CHECK: number: 0x20000000
-CHECK: comma: ,
-CHECK: kw_length: LENGTH
-CHECK: equal: =
-CHECK: number: 96K
-CHECK: identifier: rom
-CHECK: l_paren: (
-CHECK: identifier: rx
-CHECK: r_paren: )
-CHECK: colon: :
-CHECK: kw_origin: org
-CHECK: equal: =
-CHECK: number: 0x0
-CHECK: comma: ,
-CHECK: kw_length: len
-CHECK: equal: =
-CHECK: number: 256K
-CHECK: identifier: boot
-CHECK: colon: :
-CHECK: kw_origin: o
-CHECK: equal: =
-CHECK: number: 0x1000000
-CHECK: comma: ,
-CHECK: kw_length: l
-CHECK: equal: =
-CHECK: number: 0x5f00
-CHECK: r_brace: }
-CHECK: eof:
-CHECK: MEMORY
-CHECK: {
-CHECK: ram (rwx) : ORIGIN = 536870912, LENGTH = 98304
-CHECK: rom (rx) : ORIGIN = 0, LENGTH = 262144
-CHECK: boot : ORIGIN = 16777216, LENGTH = 24320
-CHECK: }
-*/
diff --git a/lld/test/LinkerScript/missing-entry-symbol.test b/lld/test/LinkerScript/missing-entry-symbol.test
deleted file mode 100644 (file)
index 54e8f75..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
-  RUN: linker-script-test %s 2> %t | FileCheck %s
-  RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-SECTIONS {
-    ENTRY()
-/*
-CHECK-ERR: [[@LINE-2]]:11: error: expected identifier in ENTRY
-CHECK-ERR-NEXT: {{^    ENTRY()}}
-CHECK-ERR-NEXT: {{^          \^}}
-*/
-}
-
-/*
-CHECK: l_brace: {
-CHECK: kw_entry: ENTRY
-CHECK: l_paren: (
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/lld/test/LinkerScript/missing-input-file-name.test b/lld/test/LinkerScript/missing-input-file-name.test
deleted file mode 100644 (file)
index c4218cc..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
-  RUN: linker-script-test %s 2> %t | FileCheck %s
-  RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-SECTIONS {
-    .text : { ()}
-/*
-CHECK-ERR: [[@LINE-2]]:15: error: expected symbol assignment or input file name.
-CHECK-ERR-NEXT: {{^    \.text : { \(\)}}}
-CHECK-ERR-NEXT: {{^              \^}}
-*/
-}
-
-/*
-CHECK: kw_sections: SECTIONS
-CHECK: l_brace: {
-CHECK: identifier: .text
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: l_paren: (
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/lld/test/LinkerScript/missing-input-sections.test b/lld/test/LinkerScript/missing-input-sections.test
deleted file mode 100644 (file)
index 5db9344..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
-  RUN: linker-script-test %s 2> %t | FileCheck %s
-  RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-SECTIONS {
-   .text : { *(+)}
-/*
-CHECK-ERR: [[@LINE-2]]:16: error: expected )
-CHECK-ERR-NEXT: {{^   \.text : { \*\(\+\)}}}
-CHECK-ERR-NEXT: {{^                 \^}}
-*/
-}
-
-/*
-CHECK: kw_sections: SECTIONS
-CHECK: l_brace: {
-CHECK: identifier: .text
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: plus: +
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/lld/test/LinkerScript/missing-operand.test b/lld/test/LinkerScript/missing-operand.test
deleted file mode 100644 (file)
index cfa87bf..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-  RUN: linker-script-test %s 2> %t | FileCheck %s
-  RUN: FileCheck -check-prefix=CHECK-ERR -input-file %t %s
-*/
-SECTIONS {
-    . = foo / ;
-/*
-CHECK-ERR: [[@LINE-2]]:15: error: expected symbol, number, minus, tilde or left parenthesis.
-CHECK-ERR-NEXT: {{^ . = foo / ;}}
-CHECK-ERR-NEXT: {{^           \^}}
-*/
-}
-
-/*
-CHECK: kw_sections: SECTIONS
-CHECK: l_brace: {
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: identifier: foo
-CHECK: slash: /
-CHECK: semicolon: ;
-CHECK: r_brace: }
-CHECK: eof:
- */
diff --git a/lld/test/LinkerScript/missing-output-section-name.test b/lld/test/LinkerScript/missing-output-section-name.test
deleted file mode 100644 (file)
index 7979298..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
-  RUN: linker-script-test %s 2> %t | FileCheck %s
-  RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-SECTIONS {
-    : { *()}
-/*
-CHECK-ERR: [[@LINE-2]]:5: error: expected symbol assignment, entry, overlay or output section name
-CHECK-ERR-NEXT: {{^    : { \*\(\)}}}
-CHECK-ERR-NEXT: {{^    \^}}
-*/
-}
-
-/*
-CHECK: kw_sections: SECTIONS
-CHECK: l_brace: {
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/lld/test/LinkerScript/missing-symbol.test b/lld/test/LinkerScript/missing-symbol.test
deleted file mode 100644 (file)
index 4e8777e..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
-  RUN: linker-script-test %s 2> %t | FileCheck %s
-  RUN: FileCheck -input-file %t -check-prefix=CHECK-ERR %s
-*/
-SECTIONS {
-    = foo + bar;
-/*
-CHECK-ERR: [[@LINE-2]]:5: error: expected symbol assignment, entry, overlay or output section name.
-CHECK-ERR-NEXT: {{^ = foo \+ bar;}}
-CHECK-ERR-NEXT: {{^ \^}}
-*/
-}
-
-/*
-CHECK: kw_sections: SECTIONS
-CHECK: l_brace: {
-CHECK: equal: =
-CHECK: identifier: foo
-CHECK: plus: +
-CHECK: identifier: bar
-CHECK: semicolon: ;
-CHECK: r_brace: }
-CHECK: eof:
-*/
diff --git a/lld/test/LinkerScript/phdrs-sections.test b/lld/test/LinkerScript/phdrs-sections.test
deleted file mode 100644 (file)
index 872b799..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
-  Test PHDR parsing and section -> phdr mapping.
-  RUN: linker-script-test %s | FileCheck %s
-*/
-
-PHDRS
-{
-  ph_text PT_LOAD FLAGS (0x1 | 0x4);
-  ph_data PT_LOAD FLAGS (0x2 | 0x4);
-}
-
-SECTIONS 
-{
-  .init : {} : ph_text
-}
-
-/*
-CHECK: PHDRS
-CHECK: {
-CHECK: ph_text 1 FLAGS (5);
-CHECK: ph_data 1 FLAGS (6);
-CHECK: }
-CHECK: SECTIONS
-CHECK: {
-CHECK: .init :
-CHECK:   {
-CHECK:   } : ph_text
-CHECK: }
-*/
diff --git a/lld/test/LinkerScript/sections.test b/lld/test/LinkerScript/sections.test
deleted file mode 100644 (file)
index 67f8288..0000000
+++ /dev/null
@@ -1,624 +0,0 @@
-/*
-  This test exercises parsing typical commands found in GNU ld linker scripts.
-  RUN: linker-script-test %s | FileCheck %s
-*/
-
-SEARCH_DIR("/usr/x86_64-linux-gnu/lib64"); SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu");
-SECTIONS
-{
-  PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
-  .interp         : { *(.interp) }
-  .note.gnu.build-id : { *(.note.gnu.build-id) }
-  .hash           : { *(.hash) }
-  .rela.dyn       :
-    {
-      *(.rela.init)
-      *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
-      *(.rela.fini)
-      *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
-    }
-  .rela.plt       :
-    {
-      *(.rela.plt)
-      PROVIDE_HIDDEN (__rela_iplt_start = .);
-      *(.rela.iplt)
-      PROVIDE_HIDDEN (__rela_iplt_end = .);
-    }
-  .init           :
-  {
-    FILL (0x90909090)
-    KEEP (*(SORT_NONE(.init)))
-  } =0x909090909090909090909090
-  PROVIDE (__etext = .);
-  .eh_frame       : ONLY_IF_RO { KEEP (*(.eh_frame)) }
-  .exception_ranges   : ONLY_IF_RO { *(.exception_ranges
-  .exception_ranges*) }
-  . = ALIGN (CONSTANT (MAXPAGESIZE)) - ((CONSTANT (MAXPAGESIZE) - .) & (CONSTANT (MAXPAGESIZE) - 1)); . = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
-  /* Exception handling  */
-  .eh_frame       : ONLY_IF_RW { KEEP (*(.eh_frame)) }
-  .ctors          :
-  {
-    KEEP (*crtbegin.o(.ctors))
-    KEEP (*crtbegin?.o(.ctors))
-    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
-    KEEP (*(SORT(.ctors.*)))
-    KEEP (*(.ctors))
-  }
-  .dtors          :
-  {
-    KEEP (*crtbegin.o(.dtors))
-    KEEP (*crtbegin?.o(.dtors))
-    KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
-    KEEP (*(SORT(.dtors.*)))
-    KEEP (*(.dtors))
-  }
-  . = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
-  .got.plt        : { *(.got.plt)  *(.igot.plt) }
-  .lrodata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
-  {
-    *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
-  }
-  .ldata   ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
-  {
-    *(.ldata .ldata.* .gnu.linkonce.l.*)
-    . = ALIGN(. != 0 ? 64 / 8 : 1);
-  }
-  . = ALIGN(64 / 8);
-  _end = .; PROVIDE (end = .);
-  . = DATA_SEGMENT_END (.);
-  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
-}
-
-/*
-CHECK: kw_search_dir: SEARCH_DIR
-CHECK: l_paren: (
-CHECK: identifier: /usr/x86_64-linux-gnu/lib64
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: kw_search_dir: SEARCH_DIR
-CHECK: l_paren: (
-CHECK: identifier: =/usr/local/lib/x86_64-linux-gnu
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: kw_sections: SECTIONS
-CHECK: l_brace: {
-CHECK: kw_provide: PROVIDE
-CHECK: l_paren: (
-CHECK: identifier: __executable_start
-CHECK: equal: =
-CHECK: identifier: SEGMENT_START
-CHECK: l_paren: (
-CHECK: identifier: text-segment
-CHECK: comma: ,
-CHECK: number: 0x400000
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: identifier: SEGMENT_START
-CHECK: l_paren: (
-CHECK: identifier: text-segment
-CHECK: comma: ,
-CHECK: number: 0x400000
-CHECK: r_paren: )
-CHECK: plus: +
-CHECK: identifier: SIZEOF_HEADERS
-CHECK: semicolon: ;
-CHECK: identifier: .interp
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .interp
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .note.gnu.build-id
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .note.gnu.build-id
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .hash
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .hash
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .rela.dyn
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .rela.init
-CHECK: r_paren: )
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .rela.text
-CHECK: identifier: .rela.text.*
-CHECK: identifier: .rela.gnu.linkonce.t.*
-CHECK: r_paren: )
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .rela.fini
-CHECK: r_paren: )
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .rela.rodata
-CHECK: identifier: .rela.rodata.*
-CHECK: identifier: .rela.gnu.linkonce.r.*
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .rela.plt
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .rela.plt
-CHECK: r_paren: )
-CHECK: kw_provide_hidden: PROVIDE_HIDDEN
-CHECK: l_paren: (
-CHECK: identifier: __rela_iplt_start
-CHECK: equal: =
-CHECK: identifier: .
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .rela.iplt
-CHECK: r_paren: )
-CHECK: kw_provide_hidden: PROVIDE_HIDDEN
-CHECK: l_paren: (
-CHECK: identifier: __rela_iplt_end
-CHECK: equal: =
-CHECK: identifier: .
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: r_brace: }
-CHECK: identifier: .init
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: kw_fill: FILL
-CHECK: l_paren: (
-CHECK: number: 0x90909090
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: kw_sort_none: SORT_NONE
-CHECK: l_paren: (
-CHECK: identifier: .init
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: kw_provide: PROVIDE
-CHECK: l_paren: (
-CHECK: identifier: __etext
-CHECK: equal: =
-CHECK: identifier: .
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: identifier: .eh_frame
-CHECK: colon: :
-CHECK: kw_only_if_ro: ONLY_IF_RO
-CHECK: l_brace: {
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .eh_frame
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .exception_ranges
-CHECK: colon: :
-CHECK: kw_only_if_ro: ONLY_IF_RO
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .exception_ranges
-CHECK: identifier: .exception_ranges*
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: kw_align: ALIGN
-CHECK: l_paren: (
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: MAXPAGESIZE
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: minus: -
-CHECK: l_paren: (
-CHECK: l_paren: (
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: MAXPAGESIZE
-CHECK: r_paren: )
-CHECK: minus: -
-CHECK: identifier: .
-CHECK: r_paren: )
-CHECK: amp: &
-CHECK: l_paren: (
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: MAXPAGESIZE
-CHECK: r_paren: )
-CHECK: minus: -
-CHECK: number: 1
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: identifier: DATA_SEGMENT_ALIGN
-CHECK: l_paren: (
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: MAXPAGESIZE
-CHECK: r_paren: )
-CHECK: comma: ,
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: COMMONPAGESIZE
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: identifier: .eh_frame
-CHECK: colon: :
-CHECK: kw_only_if_rw: ONLY_IF_RW
-CHECK: l_brace: {
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .eh_frame
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .ctors
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: identifier: *crtbegin.o
-CHECK: l_paren: (
-CHECK: identifier: .ctors
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: identifier: *crtbegin?.o
-CHECK: l_paren: (
-CHECK: identifier: .ctors
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: kw_exclude_file: EXCLUDE_FILE
-CHECK: l_paren: (
-CHECK: identifier: *crtend.o
-CHECK: identifier: *crtend?.o
-CHECK: r_paren: )
-CHECK: identifier: .ctors
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: kw_sort_by_name: SORT
-CHECK: l_paren: (
-CHECK: identifier: .ctors.*
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .ctors
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .dtors
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: identifier: *crtbegin.o
-CHECK: l_paren: (
-CHECK: identifier: .dtors
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: identifier: *crtbegin?.o
-CHECK: l_paren: (
-CHECK: identifier: .dtors
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: kw_exclude_file: EXCLUDE_FILE
-CHECK: l_paren: (
-CHECK: identifier: *crtend.o
-CHECK: identifier: *crtend?.o
-CHECK: r_paren: )
-CHECK: identifier: .dtors
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: kw_sort_by_name: SORT
-CHECK: l_paren: (
-CHECK: identifier: .dtors.*
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: kw_keep: KEEP
-CHECK: l_paren: (
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .dtors
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: identifier: DATA_SEGMENT_RELRO_END
-CHECK: l_paren: (
-CHECK: identifier: SIZEOF
-CHECK: l_paren: (
-CHECK: identifier: .got.plt
-CHECK: r_paren: )
-CHECK: greaterequal: >=
-CHECK: number: 24
-CHECK: question: ?
-CHECK: number: 24
-CHECK: colon: :
-CHECK: number: 0
-CHECK: comma: ,
-CHECK: identifier: .
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: identifier: .got.plt
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .got.plt
-CHECK: r_paren: )
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .igot.plt
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .lrodata
-CHECK: kw_align: ALIGN
-CHECK: l_paren: (
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: MAXPAGESIZE
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: plus: +
-CHECK: l_paren: (
-CHECK: identifier: .
-CHECK: amp: &
-CHECK: l_paren: (
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: MAXPAGESIZE
-CHECK: r_paren: )
-CHECK: minus: -
-CHECK: number: 1
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .lrodata
-CHECK: identifier: .lrodata.*
-CHECK: identifier: .gnu.linkonce.lr.*
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: identifier: .ldata
-CHECK: kw_align: ALIGN
-CHECK: l_paren: (
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: MAXPAGESIZE
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: plus: +
-CHECK: l_paren: (
-CHECK: identifier: .
-CHECK: amp: &
-CHECK: l_paren: (
-CHECK: identifier: CONSTANT
-CHECK: l_paren: (
-CHECK: identifier: MAXPAGESIZE
-CHECK: r_paren: )
-CHECK: minus: -
-CHECK: number: 1
-CHECK: r_paren: )
-CHECK: r_paren: )
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .ldata
-CHECK: identifier: .ldata.*
-CHECK: identifier: .gnu.linkonce.l.*
-CHECK: r_paren: )
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: kw_align: ALIGN
-CHECK: l_paren: (
-CHECK: identifier: .
-CHECK: exclaimequal: !=
-CHECK: number: 0
-CHECK: question: ?
-CHECK: number: 64
-CHECK: slash: /
-CHECK: number: 8
-CHECK: colon: :
-CHECK: number: 1
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: r_brace: }
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: kw_align: ALIGN
-CHECK: l_paren: (
-CHECK: number: 64
-CHECK: slash: /
-CHECK: number: 8
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: identifier: _end
-CHECK: equal: =
-CHECK: identifier: .
-CHECK: semicolon: ;
-CHECK: kw_provide: PROVIDE
-CHECK: l_paren: (
-CHECK: identifier: end
-CHECK: equal: =
-CHECK: identifier: .
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: identifier: .
-CHECK: equal: =
-CHECK: identifier: DATA_SEGMENT_END
-CHECK: l_paren: (
-CHECK: identifier: .
-CHECK: r_paren: )
-CHECK: semicolon: ;
-CHECK: kw_discard: /DISCARD/
-CHECK: colon: :
-CHECK: l_brace: {
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .note.GNU-stack
-CHECK: r_paren: )
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .gnu_debuglink
-CHECK: r_paren: )
-CHECK: star: *
-CHECK: l_paren: (
-CHECK: identifier: .gnu.lto_*
-CHECK: r_paren: )
-CHECK: r_brace: }
-CHECK: r_brace: }
-CHECK: eof:
-CHECK: SEARCH_DIR("/usr/x86_64-linux-gnu/lib64")
-CHECK: SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu")
-CHECK: SECTIONS
-CHECK: {
-CHECK: PROVIDE(__executable_start = SEGMENT_START(text-segment, 4194304))
-CHECK: . = (SEGMENT_START(text-segment, 4194304) + SIZEOF_HEADERS)
-CHECK: .interp :
-CHECK:   {
-CHECK:     *(.interp)
-CHECK:   }
-CHECK: .note.gnu.build-id :
-CHECK:   {
-CHECK:     *(.note.gnu.build-id)
-CHECK:   }
-CHECK: .hash :
-CHECK:   {
-CHECK:     *(.hash)
-CHECK:   }
-CHECK: .rela.dyn :
-CHECK:   {
-CHECK:     *(.rela.init)
-CHECK:     *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
-CHECK:     *(.rela.fini)
-CHECK:     *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
-CHECK:   }
-CHECK: .rela.plt :
-CHECK:   {
-CHECK:     *(.rela.plt)
-CHECK:     PROVIDE_HIDDEN(__rela_iplt_start = .)
-CHECK:     *(.rela.iplt)
-CHECK:     PROVIDE_HIDDEN(__rela_iplt_end = .)
-CHECK:   }
-CHECK: .init :
-CHECK:   {
-CHECK:     FILL(0x90909090)
-CHECK:     KEEP(*(SORT_NONE(.init)))
-CHECK:   } =0x909090909090909090909090
-CHECK: PROVIDE(__etext = .)
-CHECK: .eh_frame :
-CHECK: ONLY_IF_RO  {
-CHECK:     KEEP(*(.eh_frame))
-CHECK:   }
-CHECK: .exception_ranges :
-CHECK: ONLY_IF_RO  {
-CHECK:     *(.exception_ranges .exception_ranges*)
-CHECK:   }
-CHECK: . = (ALIGN(CONSTANT(MAXPAGESIZE)) - ((CONSTANT(MAXPAGESIZE) - .) & (CONSTANT(MAXPAGESIZE) - 1)))
-CHECK: . = DATA_SEGMENT_ALIGN(CONSTANT(MAXPAGESIZE), CONSTANT(COMMONPAGESIZE))
-CHECK: .eh_frame :
-CHECK: ONLY_IF_RW  {
-CHECK:     KEEP(*(.eh_frame))
-CHECK:   }
-CHECK: .ctors :
-CHECK:   {
-CHECK:     KEEP(*crtbegin.o(.ctors))
-CHECK:     KEEP(*crtbegin?.o(.ctors))
-CHECK:     KEEP(*(EXCLUDE_FILE(*crtend.o *crtend?.o ) .ctors))
-CHECK:     KEEP(*(SORT_BY_NAME(.ctors.*)))
-CHECK:     KEEP(*(.ctors))
-CHECK:   }
-CHECK: .dtors :
-CHECK:   {
-CHECK:     KEEP(*crtbegin.o(.dtors))
-CHECK:     KEEP(*crtbegin?.o(.dtors))
-CHECK:     KEEP(*(EXCLUDE_FILE(*crtend.o *crtend?.o ) .dtors))
-CHECK:     KEEP(*(SORT_BY_NAME(.dtors.*)))
-CHECK:     KEEP(*(.dtors))
-CHECK:   }
-CHECK: . = DATA_SEGMENT_RELRO_END((SIZEOF(.got.plt) >= 24) ? 24 : 0, .)
-CHECK: .got.plt :
-CHECK:   {
-CHECK:     *(.got.plt)
-CHECK:     *(.igot.plt)
-CHECK:   }
-CHECK: .lrodata (ALIGN(CONSTANT(MAXPAGESIZE)) + (. & (CONSTANT(MAXPAGESIZE) - 1))) :
-CHECK:   {
-CHECK:     *(.lrodata .lrodata.* .gnu.linkonce.lr.*)
-CHECK:   }
-CHECK: .ldata (ALIGN(CONSTANT(MAXPAGESIZE)) + (. & (CONSTANT(MAXPAGESIZE) - 1))) :
-CHECK:   {
-CHECK:     *(.ldata .ldata.* .gnu.linkonce.l.*)
-CHECK:     . = ALIGN((. != 0) ? (64 / 8) : 1)
-CHECK:   }
-CHECK: . = ALIGN((64 / 8))
-CHECK: _end = .
-CHECK: PROVIDE(end = .)
-CHECK: . = DATA_SEGMENT_END(.)
-CHECK:  :
-CHECK:   {
-CHECK:     *(.note.GNU-stack)
-CHECK:     *(.gnu_debuglink)
-CHECK:     *(.gnu.lto_*)
-CHECK:   }
-CHECK: }
-*/
index 1151404..c4b58cd 100644 (file)
@@ -1,2 +1 @@
-add_subdirectory(linker-script-test)
 add_subdirectory(lld)
diff --git a/lld/tools/linker-script-test/CMakeLists.txt b/lld/tools/linker-script-test/CMakeLists.txt
deleted file mode 100644 (file)
index 2492f10..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-add_llvm_executable(linker-script-test
-  linker-script-test.cpp
-  )
-
-target_link_libraries(linker-script-test
-  LLVMSupport
-  lldReaderWriter
-  )
diff --git a/lld/tools/linker-script-test/linker-script-test.cpp b/lld/tools/linker-script-test/linker-script-test.cpp
deleted file mode 100644 (file)
index 027ecb3..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-//===- utils/linker-script-test/linker-script-test.cpp --------------------===//
-//
-//                             The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Tool for testing linker script parsing.
-///
-//===----------------------------------------------------------------------===//
-
-#include "lld/ReaderWriter/LinkerScript.h"
-
-#include "llvm/Support/PrettyStackTrace.h"
-#include "llvm/Support/Signals.h"
-
-using namespace llvm;
-using namespace lld;
-using namespace script;
-
-int main(int argc, const char **argv) {
-  llvm::sys::PrintStackTraceOnErrorSignal();
-  llvm::PrettyStackTraceProgram X(argc, argv);
-
-  {
-    ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
-        MemoryBuffer::getFileOrSTDIN(argv[1]);
-    if (std::error_code ec = mb.getError()) {
-      llvm::errs() << ec.message() << "\n";
-      return 1;
-    }
-    Lexer l(std::move(mb.get()));
-    Token tok;
-    while (true) {
-      l.lex(tok);
-      tok.dump(llvm::outs());
-      if (tok._kind == Token::eof || tok._kind == Token::unknown)
-        break;
-    }
-  }
-  {
-    ErrorOr<std::unique_ptr<MemoryBuffer>> mb =
-        MemoryBuffer::getFileOrSTDIN(argv[1]);
-    if (std::error_code ec = mb.getError()) {
-      llvm::errs() << ec.message() << "\n";
-      return 1;
-    }
-    Parser p(std::move(mb.get()));
-    if (!p.parse()) {
-      LinkerScript *ls = p.get();
-      ls->dump(llvm::outs());
-    }
-  }
-}