};
Kind getKind() const { return _kind; }
+ inline llvm::BumpPtrAllocator &getAllocator() const;
virtual void dump(raw_ostream &os) const = 0;
virtual ~Command() {}
protected:
- explicit Command(Kind k) : _kind(k) {}
+ explicit Command(class Parser &ctx, Kind k) : _ctx(ctx), _kind(k) {}
private:
+ Parser &_ctx;
Kind _kind;
};
class Output : public Command {
public:
- explicit Output(StringRef outputFileName)
- : Command(Kind::Output), _outputFileName(outputFileName) {}
+ explicit Output(Parser &ctx, StringRef outputFileName)
+ : Command(ctx, Kind::Output), _outputFileName(outputFileName) {}
static bool classof(const Command *c) { return c->getKind() == Kind::Output; }
class OutputFormat : public Command {
public:
- explicit OutputFormat(StringRef format) : Command(Kind::OutputFormat) {
- _formats.push_back(format);
+ explicit OutputFormat(Parser &ctx, const SmallVectorImpl<StringRef> &formats)
+ : Command(ctx, Kind::OutputFormat) {
+ size_t numFormats = formats.size();
+ StringRef *formatsStart = getAllocator().Allocate<StringRef>(numFormats);
+ std::copy(std::begin(formats), std::end(formats), formatsStart);
+ _formats = llvm::makeArrayRef(formatsStart, numFormats);
}
static bool classof(const Command *c) {
os << ")\n";
}
- virtual void addOutputFormat(StringRef format) { _formats.push_back(format); }
-
- range<StringRef *> getFormats() { return _formats; }
+ llvm::ArrayRef<StringRef> getFormats() { return _formats; }
private:
- std::vector<StringRef> _formats;
+ llvm::ArrayRef<StringRef> _formats;
};
class OutputArch : public Command {
public:
- explicit OutputArch(StringRef arch)
- : Command(Kind::OutputArch), _arch(arch) {}
+ explicit OutputArch(Parser &ctx, StringRef arch)
+ : Command(ctx, Kind::OutputArch), _arch(arch) {}
static bool classof(const Command *c) {
return c->getKind() == Kind::OutputArch;
template<Command::Kind K>
class PathList : public Command {
public:
- template <class RangeT> PathList(StringRef name, RangeT range)
- : Command(K), _name(name) {
- std::copy(std::begin(range), std::end(range), std::back_inserter(_paths));
+ PathList(Parser &ctx, StringRef name, const SmallVectorImpl<Path> &paths)
+ : Command(ctx, K), _name(name) {
+ size_t numPaths = paths.size();
+ Path *pathsStart = getAllocator().template Allocate<Path>(numPaths);
+ std::copy(std::begin(paths), std::end(paths), pathsStart);
+ _paths = llvm::makeArrayRef(pathsStart, numPaths);
}
static bool classof(const Command *c) { return c->getKind() == K; }
os << ")\n";
}
- const std::vector<Path> &getPaths() const { return _paths; }
+ llvm::ArrayRef<Path> getPaths() const { return _paths; }
private:
StringRef _name;
- std::vector<Path> _paths;
+ llvm::ArrayRef<Path> _paths;
};
class Group : public PathList<Command::Kind::Group> {
public:
- template <class RangeT> Group(RangeT range)
- : PathList("GROUP", std::move(range)) {}
+ template <class RangeT>
+ Group(Parser &ctx, RangeT range)
+ : PathList(ctx, "GROUP", std::move(range)) {}
};
class Input : public PathList<Command::Kind::Input> {
public:
- template <class RangeT> Input(RangeT range)
- : PathList("INPUT", std::move(range)) {}
+ template <class RangeT>
+ Input(Parser &ctx, RangeT range)
+ : PathList(ctx, "INPUT", std::move(range)) {}
};
class Entry : public Command {
public:
- explicit Entry(StringRef entryName)
- : Command(Kind::Entry), _entryName(entryName) {}
+ explicit Entry(Parser &ctx, StringRef entryName)
+ : Command(ctx, Kind::Entry), _entryName(entryName) {}
static bool classof(const Command *c) { return c->getKind() == Kind::Entry; }
class SearchDir : public Command {
public:
- explicit SearchDir(StringRef searchPath)
- : Command(Kind::SearchDir), _searchPath(searchPath) {}
+ explicit SearchDir(Parser &ctx, StringRef searchPath)
+ : Command(ctx, Kind::SearchDir), _searchPath(searchPath) {}
static bool classof(const Command *c) {
return c->getKind() == Kind::SearchDir;
enum class Kind { Constant, Symbol, FunctionCall, Unary, BinOp,
TernaryConditional };
Kind getKind() const { return _kind; }
+ inline llvm::BumpPtrAllocator &getAllocator() const;
virtual void dump(raw_ostream &os) const = 0;
virtual ~Expression() {}
protected:
- explicit Expression(Kind k) : _kind(k) {}
+ explicit Expression(class Parser &ctx, Kind k) : _ctx(ctx), _kind(k) {}
private:
+ Parser &_ctx;
Kind _kind;
};
/// with a constant.
class Constant : public Expression {
public:
- explicit Constant(uint64_t num) : Expression(Kind::Constant), _num(num) {}
+ explicit Constant(Parser &ctx, uint64_t num)
+ : Expression(ctx, Kind::Constant), _num(num) {}
void dump(raw_ostream &os) const override;
static bool classof(const Expression *c) {
class Symbol : public Expression {
public:
- Symbol(StringRef name) : Expression(Kind::Symbol), _name(name) {}
+ Symbol(Parser &ctx, StringRef name)
+ : Expression(ctx, Kind::Symbol), _name(name) {}
void dump(raw_ostream &os) const override;
static bool classof(const Expression *c) {
class FunctionCall : public Expression {
public:
- template <class RangeT>
- FunctionCall(StringRef name, RangeT range)
- : Expression(Kind::FunctionCall), _name(name) {
- std::copy(std::begin(range), std::end(range), std::back_inserter(_args));
+ FunctionCall(Parser &ctx, StringRef name,
+ const SmallVectorImpl<const Expression *> &args)
+ : Expression(ctx, Kind::FunctionCall), _name(name) {
+ size_t numArgs = args.size();
+ const Expression **argsStart =
+ getAllocator().Allocate<const Expression *>(numArgs);
+ std::copy(std::begin(args), std::end(args), argsStart);
+ _args = llvm::makeArrayRef(argsStart, numArgs);
}
void dump(raw_ostream &os) const override;
private:
StringRef _name;
- std::vector<const Expression *> _args;
+ llvm::ArrayRef<const Expression *> _args;
};
class Unary : public Expression {
Not
};
- Unary(Operation op, const Expression *child) : Expression(Kind::Unary),
- _op(op), _child(child) {}
+ Unary(Parser &ctx, Operation op, const Expression *child)
+ : Expression(ctx, Kind::Unary), _op(op), _child(child) {}
void dump(raw_ostream &os) const override;
static bool classof(const Expression *c) {
Sum
};
- BinOp(const Expression *lhs, Operation op, const Expression *rhs)
- : Expression(Kind::BinOp), _op(op), _lhs(lhs), _rhs(rhs) {}
+ BinOp(Parser &ctx, const Expression *lhs, Operation op, const Expression *rhs)
+ : Expression(ctx, Kind::BinOp), _op(op), _lhs(lhs), _rhs(rhs) {}
void dump(raw_ostream &os) const override;
///
class TernaryConditional : public Expression {
public:
- TernaryConditional(const Expression *conditional, const Expression *trueExpr,
- const Expression *falseExpr)
- : Expression(Kind::TernaryConditional), _conditional(conditional),
+ TernaryConditional(Parser &ctx, const Expression *conditional,
+ const Expression *trueExpr, const Expression *falseExpr)
+ : Expression(ctx, Kind::TernaryConditional), _conditional(conditional),
_trueExpr(trueExpr), _falseExpr(falseExpr) {}
void dump(raw_ostream &os) const override;
enum AssignmentKind { Simple, Sum, Sub, Mul, Div, Shl, Shr, And, Or };
enum AssignmentVisibility { Normal, Hidden, Provide, ProvideHidden };
- SymbolAssignment(StringRef name, const Expression *expr, AssignmentKind kind,
- AssignmentVisibility visibility)
- : Command(Kind::SymbolAssignment), _expression(expr), _symbol(name),
+ SymbolAssignment(Parser &ctx, StringRef name, const Expression *expr,
+ AssignmentKind kind, AssignmentVisibility visibility)
+ : Command(ctx, Kind::SymbolAssignment), _expression(expr), _symbol(name),
_assignmentKind(Simple), _assignmentVisibility(visibility) {}
static bool classof(const Command *c) {
enum class Kind { InputSectionName, SortedGroup };
Kind getKind() const { return _kind; }
+ inline llvm::BumpPtrAllocator &getAllocator() const;
virtual void dump(raw_ostream &os) const = 0;
virtual ~InputSection() {}
protected:
- explicit InputSection(Kind k) : _kind(k) {}
+ explicit InputSection(Parser &ctx, Kind k) : _ctx(ctx), _kind(k) {}
private:
+ Parser &_ctx;
Kind _kind;
};
class InputSectionName : public InputSection {
public:
- InputSectionName(StringRef name, bool excludeFile)
- : InputSection(Kind::InputSectionName), _name(name),
+ InputSectionName(Parser &ctx, StringRef name, bool excludeFile)
+ : InputSection(ctx, Kind::InputSectionName), _name(name),
_excludeFile(excludeFile) {}
void dump(raw_ostream &os) const override;
class InputSectionSortedGroup : public InputSection {
public:
- template <class RangeT>
- InputSectionSortedGroup(WildcardSortMode sort, RangeT range)
- : InputSection(Kind::SortedGroup), _sortMode(sort) {
- std::copy(std::begin(range), std::end(range),
- std::back_inserter(_sections));
+ InputSectionSortedGroup(Parser &ctx, WildcardSortMode sort,
+ const SmallVectorImpl<const InputSection *> §ions)
+ : InputSection(ctx, Kind::SortedGroup), _sortMode(sort) {
+ size_t numSections = sections.size();
+ const InputSection **sectionsStart =
+ getAllocator().Allocate<const InputSection *>(numSections);
+ std::copy(std::begin(sections), std::end(sections), sectionsStart);
+ _sections = llvm::makeArrayRef(sectionsStart, numSections);
}
void dump(raw_ostream &os) const override;
private:
WildcardSortMode _sortMode;
- std::vector<const InputSection *> _sections;
+ llvm::ArrayRef<const InputSection *> _sections;
};
/// An output-section-command that maps a series of sections inside a given
public:
typedef std::vector<const InputSection *> VectorTy;
- template <class RangeT>
- InputSectionsCmd(StringRef fileName, StringRef archiveName, bool keep,
- WildcardSortMode fileSortMode,
- WildcardSortMode archiveSortMode, RangeT range)
- : Command(Kind::InputSectionsCmd), _fileName(fileName),
+ InputSectionsCmd(Parser &ctx, StringRef fileName, StringRef archiveName,
+ bool keep, WildcardSortMode fileSortMode,
+ WildcardSortMode archiveSortMode,
+ const SmallVectorImpl<const InputSection *> §ions)
+ : Command(ctx, Kind::InputSectionsCmd), _fileName(fileName),
_archiveName(archiveName), _keep(keep), _fileSortMode(fileSortMode),
_archiveSortMode(archiveSortMode) {
- std::copy(std::begin(range), std::end(range),
- std::back_inserter(_sections));
+ size_t numSections = sections.size();
+ const InputSection **sectionsStart =
+ getAllocator().Allocate<const InputSection *>(numSections);
+ std::copy(std::begin(sections), std::end(sections), sectionsStart);
+ _sections = llvm::makeArrayRef(sectionsStart, numSections);
}
void dump(raw_ostream &os) const override;
bool _keep;
WildcardSortMode _fileSortMode;
WildcardSortMode _archiveSortMode;
- VectorTy _sections;
+ llvm::ArrayRef<const InputSection *> _sections;
};
/// A sections-command to specify which input sections and symbols compose a
public:
enum Constraint { C_None, C_OnlyIfRO, C_OnlyIfRW };
- template <class RangeT>
- OutputSectionDescription(StringRef sectionName, const Expression *address,
- const Expression *align, const Expression *subAlign,
- const Expression *at, const Expression *fillExpr,
- StringRef fillStream,
- bool alignWithInput, bool discard,
- Constraint constraint, RangeT range)
- : Command(Kind::OutputSectionDescription), _sectionName(sectionName),
+ OutputSectionDescription(
+ Parser &ctx, StringRef sectionName, const Expression *address,
+ const Expression *align, const Expression *subAlign, const Expression *at,
+ const Expression *fillExpr, StringRef fillStream, bool alignWithInput,
+ bool discard, Constraint constraint,
+ const SmallVectorImpl<const Command *> &outputSectionCommands)
+ : Command(ctx, Kind::OutputSectionDescription), _sectionName(sectionName),
_address(address), _align(align), _subAlign(subAlign), _at(at),
_fillExpr(fillExpr), _fillStream(fillStream),
_alignWithInput(alignWithInput), _discard(discard),
_constraint(constraint) {
- std::copy(std::begin(range), std::end(range),
- std::back_inserter(_outputSectionCommands));
+ size_t numCommands = outputSectionCommands.size();
+ const Command **commandsStart =
+ getAllocator().Allocate<const Command *>(numCommands);
+ std::copy(std::begin(outputSectionCommands),
+ std::end(outputSectionCommands), commandsStart);
+ _outputSectionCommands = llvm::makeArrayRef(commandsStart, numCommands);
}
static bool classof(const Command *c) {
bool _alignWithInput;
bool _discard;
Constraint _constraint;
- std::vector<const Command *> _outputSectionCommands;
+ llvm::ArrayRef<const Command *> _outputSectionCommands;
};
/// Represents an Overlay structure as documented in
/// https://sourceware.org/binutils/docs/ld/Overlay-Description.html#Overlay-Description
class Overlay : public Command {
public:
- Overlay() : Command(Kind::Overlay) {}
+ Overlay(Parser &ctx) : Command(ctx, Kind::Overlay) {}
static bool classof(const Command *c) {
return c->getKind() == Kind::Overlay;
/// Represents all the contents of the SECTIONS {} construct.
class Sections : public Command {
public:
- template <class RangeT> Sections(RangeT range) : Command(Kind::Sections) {
- std::copy(std::begin(range), std::end(range),
- std::back_inserter(_sectionsCommands));
+ Sections(Parser &ctx,
+ const SmallVectorImpl<const Command *> §ionsCommands)
+ : Command(ctx, Kind::Sections) {
+ size_t numCommands = sectionsCommands.size();
+ const Command **commandsStart =
+ getAllocator().Allocate<const Command *>(numCommands);
+ std::copy(std::begin(sectionsCommands), std::end(sectionsCommands),
+ commandsStart);
+ _sectionsCommands = llvm::makeArrayRef(commandsStart, numCommands);
}
static bool classof(const Command *c) {
void dump(raw_ostream &os) const override;
private:
- std::vector<const Command *> _sectionsCommands;
+ llvm::ArrayRef<const Command *> _sectionsCommands;
};
/// Stores the parse tree of a linker script.
/// Returns a reference to the top level node of the linker script AST.
LinkerScript *get() { return &_script; }
+ /// Returns a reference to the underlying allocator.
+ llvm::BumpPtrAllocator &getAllocator() { return _alloc; }
+
private:
/// Advances to the next token, either asking the Lexer to lex the next token
/// or obtaining it from the look ahead buffer.
/// -lm -l:libgcc.a )
///
template<class T> T *parsePathList();
- bool parseAsNeeded(std::vector<Path> &paths);
+ bool parseAsNeeded(SmallVectorImpl<Path> &paths);
/// Parse the ENTRY linker script command.
/// Example:
bool _peekAvailable;
Token _bufferedToken;
};
+
+llvm::BumpPtrAllocator &Command::getAllocator() const {
+ return _ctx.getAllocator();
+}
+llvm::BumpPtrAllocator &Expression::getAllocator() const {
+ return _ctx.getAllocator();
+}
+llvm::BumpPtrAllocator &InputSection::getAllocator() const {
+ return _ctx.getAllocator();
+}
} // end namespace script
} // end namespace lld
// InputSectionSortedGroup functions
static void dumpInputSections(raw_ostream &os,
- const std::vector<const InputSection *> &secs) {
+ llvm::ArrayRef<const InputSection *> secs) {
bool excludeFile = false;
bool first = true;
const Expression *Parser::parseFunctionCall() {
assert((_tok._kind == Token::identifier || _tok._kind == Token::kw_align) &&
"expected function call first tokens");
- std::vector<const Expression *> params;
+ SmallVector<const Expression *, 8> params;
StringRef name = _tok._range;
consumeToken();
if (_tok._kind == Token::r_paren) {
consumeToken();
- return new (_alloc) FunctionCall(_tok._range, params);
+ return new (_alloc) FunctionCall(*this, _tok._range, params);
}
if (const Expression *firstParam = parseExpression())
if (!expectAndConsume(Token::r_paren, "expected )"))
return nullptr;
- return new (_alloc) FunctionCall(name, params);
+ return new (_alloc) FunctionCall(*this, name, params);
}
bool Parser::expectExprOperand() {
case Token::identifier: {
if (peek()._kind== Token::l_paren)
return parseFunctionCall();
- Symbol *sym = new (_alloc) Symbol(_tok._range);
+ Symbol *sym = new (_alloc) Symbol(*this, _tok._range);
consumeToken();
return sym;
}
return parseFunctionCall();
case Token::minus:
consumeToken();
- return new (_alloc) Unary(Unary::Minus, parseExprOperand());
+ return new (_alloc) Unary(*this, Unary::Minus, parseExprOperand());
case Token::tilde:
consumeToken();
- return new (_alloc) Unary(Unary::Not, parseExprOperand());
+ 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;
}
- Constant *c = new (_alloc) Constant(*val);
+ Constant *c = new (_alloc) Constant(*this, *val);
consumeToken();
return c;
}
const Expression *rhs = parseExpression(precedence - 1);
if (!rhs)
return nullptr;
- binOp = new (_alloc) BinOp(lhs, op, rhs);
+ binOp = new (_alloc) BinOp(*this, lhs, op, rhs);
lhs = binOp;
}
}
if (!falseExpr)
return nullptr;
- return new (_alloc) TernaryConditional(lhs, trueExpr, falseExpr);
+ return new (_alloc) TernaryConditional(*this, lhs, trueExpr, falseExpr);
}
// Parse OUTPUT(ident)
return nullptr;
}
- auto ret = new (_alloc) Output(_tok._range);
+ auto ret = new (_alloc) Output(*this, _tok._range);
consumeToken();
if (!expectAndConsume(Token::r_paren, "expected )"))
return nullptr;
}
- auto ret = new (_alloc) OutputFormat(_tok._range);
+ SmallVector<StringRef, 8> formats;
+ formats.push_back(_tok._range);
+
consumeToken();
do {
error(_tok, "Expected identifier in OUTPUT_FORMAT.");
return nullptr;
}
- ret->addOutputFormat(_tok._range);
+ formats.push_back(_tok._range);
consumeToken();
} while (isNextToken(Token::comma));
if (!expectAndConsume(Token::r_paren, "expected )"))
return nullptr;
- return ret;
+ return new (_alloc) OutputFormat(*this, formats);
}
// Parse OUTPUT_ARCH(ident)
return nullptr;
}
- auto ret = new (_alloc) OutputArch(_tok._range);
+ auto ret = new (_alloc) OutputArch(*this, _tok._range);
consumeToken();
if (!expectAndConsume(Token::r_paren, "expected )"))
if (!expectAndConsume(Token::l_paren, "expected ("))
return nullptr;
- std::vector<Path> paths;
+ SmallVector<Path, 8> paths;
while (_tok._kind == Token::identifier || _tok._kind == Token::libname ||
_tok._kind == Token::kw_as_needed) {
switch (_tok._kind) {
}
if (!expectAndConsume(Token::r_paren, "expected )"))
return nullptr;
- return new (_alloc) T(paths);
+ return new (_alloc) T(*this, paths);
}
// Parse AS_NEEDED(file ...)
-bool Parser::parseAsNeeded(std::vector<Path> &paths) {
+bool Parser::parseAsNeeded(SmallVectorImpl<Path> &paths) {
assert(_tok._kind == Token::kw_as_needed && "Expected AS_NEEDED!");
consumeToken();
if (!expectAndConsume(Token::l_paren, "expected ("))
consumeToken();
if (!expectAndConsume(Token::r_paren, "expected )"))
return nullptr;
- return new (_alloc) Entry(entryName);
+ return new (_alloc) Entry(*this, entryName);
}
// Parse SEARCH_DIR(ident)
consumeToken();
if (!expectAndConsume(Token::r_paren, "expected )"))
return nullptr;
- return new (_alloc) SearchDir(searchPath);
+ return new (_alloc) SearchDir(*this, searchPath);
}
const SymbolAssignment *Parser::parseSymbolAssignment() {
if (!expectAndConsume(Token::r_paren, "expected )"))
return nullptr;
- return new (_alloc) SymbolAssignment(name, expr, kind, visibility);
+ return new (_alloc) SymbolAssignment(*this, name, expr, kind, visibility);
}
llvm::ErrorOr<InputSectionsCmd::VectorTy> Parser::parseExcludeFile() {
std::make_error_code(std::errc::io_error));
while (_tok._kind == Token::identifier) {
- res.push_back(new (_alloc) InputSectionName(_tok._range, true));
+ res.push_back(new (_alloc) InputSectionName(*this, _tok._range, true));
consumeToken();
}
if (numParen == -1)
return nullptr;
- std::vector<const InputSection *> inputSections;
+ SmallVector<const InputSection *, 8> inputSections;
while (_tok._kind == Token::identifier) {
- inputSections.push_back(new (_alloc) InputSectionName(_tok._range, false));
+ inputSections.push_back(new (_alloc)
+ InputSectionName(*this, _tok._range, false));
consumeToken();
}
if (!expectAndConsume(Token::r_paren, "expected )"))
return nullptr;
- return new (_alloc) InputSectionSortedGroup(sortMode, inputSections);
+ return new (_alloc) InputSectionSortedGroup(*this, sortMode, inputSections);
}
const InputSectionsCmd *Parser::parseInputSectionsCmd() {
}
}
- std::vector<const InputSection *> inputSections;
+ SmallVector<const InputSection *, 8> inputSections;
if (_tok._kind != Token::l_paren)
return new (_alloc)
- InputSectionsCmd(fileName, archiveName, keep, fileSortMode,
+ InputSectionsCmd(*this, fileName, archiveName, keep, fileSortMode,
archiveSortMode, inputSections);
consumeToken();
case Token::star:
case Token::identifier: {
inputSections.push_back(new (_alloc)
- InputSectionName(_tok._range, false));
+ InputSectionName(*this, _tok._range, false));
consumeToken();
break;
}
if (!expectAndConsume(Token::r_paren, "expected )"))
return nullptr;
return new (_alloc)
- InputSectionsCmd(fileName, archiveName, keep, fileSortMode,
+ InputSectionsCmd(*this, fileName, archiveName, keep, fileSortMode,
archiveSortMode, inputSections);
}
bool discard = false;
OutputSectionDescription::Constraint constraint =
OutputSectionDescription::C_None;
- std::vector<const Command *> outputSectionCommands;
+ SmallVector<const Command *, 8> outputSectionCommands;
if (_tok._kind == Token::kw_discard)
discard = true;
}
return new (_alloc) OutputSectionDescription(
- sectionName, address, align, subAlign, at, fillExpr, fillStream,
+ *this, sectionName, address, align, subAlign, at, fillExpr, fillStream,
alignWithInput, discard, constraint, outputSectionCommands);
}
consumeToken();
if (!expectAndConsume(Token::l_brace, "expected {"))
return nullptr;
- std::vector<const Command *> sectionsCommands;
+ SmallVector<const Command *, 8> sectionsCommands;
bool unrecognizedToken = false;
// Parse zero or more sections-commands
"expected symbol assignment, entry, overlay or output section name."))
return nullptr;
- return new (_alloc) Sections(sectionsCommands);
+ return new (_alloc) Sections(*this, sectionsCommands);
}
} // end namespace script