<commit_before>//===- ScriptParser.cpp ---------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a recursive-descendent parser for linker scripts.
// Parsed results are stored to Config and Script global objects.
//
//===----------------------------------------------------------------------===//

#include "ScriptParser.h"
#include "Config.h"
#include "Driver.h"
#include "InputSection.h"
#include "LinkerScript.h"
#include "OutputSections.h"
#include "ScriptLexer.h"
#include "Symbols.h"
#include "Target.h"
#include "lld/Common/Memory.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include <cassert>
#include <limits>
#include <vector>

using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::support::endian;
using namespace lld;
using namespace lld::elf;

static bool isUnderSysroot(StringRef Path);

namespace {
class ScriptParser final : ScriptLexer {
public:
  ScriptParser(MemoryBufferRef MB)
      : ScriptLexer(MB),
        IsUnderSysroot(isUnderSysroot(MB.getBufferIdentifier())) {}

  void readLinkerScript();
  void readVersionScript();
  void readDynamicList();
  void readDefsym(StringRef Name);

private:
  void addFile(StringRef Path);

  void readAsNeeded();
  void readEntry();
  void readExtern();
  void readGroup();
  void readInclude();
  void readMemory();
  void readOutput();
  void readOutputArch();
  void readOutputFormat();
  void readPhdrs();
  void readRegionAlias();
  void readSearchDir();
  void readSections();
  void readVersion();
  void readVersionScriptCommand();

  SymbolAssignment *readAssignment(StringRef Name);
  ByteCommand *readByteCommand(StringRef Tok);
  uint32_t readFill();
  uint32_t parseFill(StringRef Tok);
  void readSectionAddressType(OutputSection *Cmd);
  OutputSection *readOutputSectionDescription(StringRef OutSec);
  std::vector<StringRef> readOutputSectionPhdrs();
  InputSectionDescription *readInputSectionDescription(StringRef Tok);
  StringMatcher readFilePatterns();
  std::vector<SectionPattern> readInputSectionsList();
  InputSectionDescription *readInputSectionRules(StringRef FilePattern);
  unsigned readPhdrType();
  SortSectionPolicy readSortKind();
  SymbolAssignment *readProvideHidden(bool Provide, bool Hidden);
  SymbolAssignment *readProvideOrAssignment(StringRef Tok);
  void readSort();
  AssertCommand *readAssert();
  Expr readAssertExpr();
  Expr readConstant();
  Expr getPageSize();

  uint64_t readMemoryAssignment(StringRef, StringRef, StringRef);
  std::pair<uint32_t, uint32_t> readMemoryAttributes();

  Expr readExpr();
  Expr readExpr1(Expr Lhs, int MinPrec);
  StringRef readParenLiteral();
  Expr readPrimary();
  Expr readTernary(Expr Cond);
  Expr readParenExpr();

  // For parsing version script.
  std::vector<SymbolVersion> readVersionExtern();
  void readAnonymousDeclaration();
  void readVersionDeclaration(StringRef VerStr);

  std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>>
  readSymbols();

  // True if a script being read is in a subdirectory specified by -sysroot.
  bool IsUnderSysroot;

  // A set to detect an INCLUDE() cycle.
  StringSet<> Seen;
};
} // namespace

static StringRef unquote(StringRef S) {
  if (S.startswith("\""))
    return S.substr(1, S.size() - 2);
  return S;
}

static bool isUnderSysroot(StringRef Path) {
  if (Config->Sysroot == "")
    return false;
  for (; !Path.empty(); Path = sys::path::parent_path(Path))
    if (sys::fs::equivalent(Config->Sysroot, Path))
      return true;
  return false;
}

// Some operations only support one non absolute value. Move the
// absolute one to the right hand side for convenience.
static void moveAbsRight(ExprValue &A, ExprValue &B) {
  if (A.Sec == nullptr || (A.ForceAbsolute && !B.isAbsolute()))
    std::swap(A, B);
  if (!B.isAbsolute())
    error(A.Loc + ": at least one side of the expression must be absolute");
}

static ExprValue add(ExprValue A, ExprValue B) {
  moveAbsRight(A, B);
  return {A.Sec, A.ForceAbsolute, A.getSectionOffset() + B.getValue(), A.Loc};
}

static ExprValue sub(ExprValue A, ExprValue B) {
  if (!A.isAbsolute() && !B.isAbsolute())
    return A.getValue() - B.getValue();
  return {A.Sec, false, A.getSectionOffset() - B.getValue(), A.Loc};
}

static ExprValue mul(ExprValue A, ExprValue B) {
  return A.getValue() * B.getValue();
}<commit_msg>Add a comment about subtracting two non abs symbols. NFC.<commit_after>//===- ScriptParser.cpp ---------------------------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file contains a recursive-descendent parser for linker scripts.
// Parsed results are stored to Config and Script global objects.
//
//===----------------------------------------------------------------------===//

#include "ScriptParser.h"
#include "Config.h"
#include "Driver.h"
#include "InputSection.h"
#include "LinkerScript.h"
#include "OutputSections.h"
#include "ScriptLexer.h"
#include "Symbols.h"
#include "Target.h"
#include "lld/Common/Memory.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/BinaryFormat/ELF.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include <cassert>
#include <limits>
#include <vector>

using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::support::endian;
using namespace lld;
using namespace lld::elf;

static bool isUnderSysroot(StringRef Path);

namespace {
class ScriptParser final : ScriptLexer {
public:
  ScriptParser(MemoryBufferRef MB)
      : ScriptLexer(MB),
        IsUnderSysroot(isUnderSysroot(MB.getBufferIdentifier())) {}

  void readLinkerScript();
  void readVersionScript();
  void readDynamicList();
  void readDefsym(StringRef Name);

private:
  void addFile(StringRef Path);

  void readAsNeeded();
  void readEntry();
  void readExtern();
  void readGroup();
  void readInclude();
  void readMemory();
  void readOutput();
  void readOutputArch();
  void readOutputFormat();
  void readPhdrs();
  void readRegionAlias();
  void readSearchDir();
  void readSections();
  void readVersion();
  void readVersionScriptCommand();

  SymbolAssignment *readAssignment(StringRef Name);
  ByteCommand *readByteCommand(StringRef Tok);
  uint32_t readFill();
  uint32_t parseFill(StringRef Tok);
  void readSectionAddressType(OutputSection *Cmd);
  OutputSection *readOutputSectionDescription(StringRef OutSec);
  std::vector<StringRef> readOutputSectionPhdrs();
  InputSectionDescription *readInputSectionDescription(StringRef Tok);
  StringMatcher readFilePatterns();
  std::vector<SectionPattern> readInputSectionsList();
  InputSectionDescription *readInputSectionRules(StringRef FilePattern);
  unsigned readPhdrType();
  SortSectionPolicy readSortKind();
  SymbolAssignment *readProvideHidden(bool Provide, bool Hidden);
  SymbolAssignment *readProvideOrAssignment(StringRef Tok);
  void readSort();
  AssertCommand *readAssert();
  Expr readAssertExpr();
  Expr readConstant();
  Expr getPageSize();

  uint64_t readMemoryAssignment(StringRef, StringRef, StringRef);
  std::pair<uint32_t, uint32_t> readMemoryAttributes();

  Expr readExpr();
  Expr readExpr1(Expr Lhs, int MinPrec);
  StringRef readParenLiteral();
  Expr readPrimary();
  Expr readTernary(Expr Cond);
  Expr readParenExpr();

  // For parsing version script.
  std::vector<SymbolVersion> readVersionExtern();
  void readAnonymousDeclaration();
  void readVersionDeclaration(StringRef VerStr);

  std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>>
  readSymbols();

  // True if a script being read is in a subdirectory specified by -sysroot.
  bool IsUnderSysroot;

  // A set to detect an INCLUDE() cycle.
  StringSet<> Seen;
};
} // namespace

static StringRef unquote(StringRef S) {
  if (S.startswith("\""))
    return S.substr(1, S.size() - 2);
  return S;
}

static bool isUnderSysroot(StringRef Path) {
  if (Config->Sysroot == "")
    return false;
  for (; !Path.empty(); Path = sys::path::parent_path(Path))
    if (sys::fs::equivalent(Config->Sysroot, Path))
      return true;
  return false;
}

// Some operations only support one non absolute value. Move the
// absolute one to the right hand side for convenience.
static void moveAbsRight(ExprValue &A, ExprValue &B) {
  if (A.Sec == nullptr || (A.ForceAbsolute && !B.isAbsolute()))
    std::swap(A, B);
  if (!B.isAbsolute())
    error(A.Loc + ": at least one side of the expression must be absolute");
}

static ExprValue add(ExprValue A, ExprValue B) {
  moveAbsRight(A, B);
  return {A.Sec, A.ForceAbsolute, A.getSectionOffset() + B.getValue(), A.Loc};
}

static ExprValue sub(ExprValue A, ExprValue B) {
  // The distance between two symbols in sections is absolute.
  if (!A.isAbsolute() && !B.isAbsolute())
    return A.getValue() - B.getValue();
  return {A.Sec, false, A.getSectionOffset() - B.getValue(), A.Loc};
}

static ExprValue mul(ExprValue A, ExprValue B) {
  return A.getValue() * B.getValue();
}
{'fraction_non_alphanumeric': 0.16467585502807555, 'fraction_numerical': 0.0026544155181214904, 'mean_word_length': 3.876057740169238, 'pattern_counts': {'":': 2, '<': 25, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1959337', 'n_tokens_mistral': 2971, 'n_tokens_neox': 2914, 'n_words': 790}