enum Position : uint8_t { BEGIN, END };
/// \brief Initialize the inputgraph
- InputGraph()
- : _ordinal(0), _nextElementIndex(0), _currentInputElement(nullptr) {}
+ InputGraph() : _nextElementIndex(0), _currentInputElement(nullptr) {}
/// nextFile returns the next file that needs to be processed by the resolver.
/// When there are no more files to be processed, an appropriate
/// \brief Adds a node into the InputGraph
bool addInputElement(std::unique_ptr<InputElement>);
- /// \brief Set Ordinals for all the InputElements that form the InputGraph
- bool assignOrdinals();
-
/// Normalize the InputGraph. It visits all nodes in the tree to replace a
/// node with its children if it's shouldExpand() returnst true.
void normalize();
- /// \brief Do postprocessing of the InputGraph if there is a need for the
- /// to provide additional information to the user, also rearranges
- /// InputElements by their ordinals. If a user wants to place an input file
- /// at the desired position, the user can do that.
- void doPostProcess();
-
range<InputElementIterT> inputElements() {
return make_range(_inputArgs.begin(), _inputArgs.end());
}
protected:
// Input arguments
InputElementVectorT _inputArgs;
- // Ordinals
- int64_t _ordinal;
// Index of the next element to be processed
uint32_t _nextElementIndex;
InputElement *_currentInputElement;
File // Represents a type associated with File Nodes
};
- /// \brief Initialize the Input Element, The ordinal value of an input Element
- /// is initially set to -1, if the user wants to override its ordinal,
- /// let the user do it
- InputElement(Kind type, int64_t ordinal = -1);
-
+ InputElement(Kind type) : _kind(type) {}
virtual ~InputElement() {}
/// Return the Element Type for an Input Element
virtual Kind kind() const { return _kind; }
- void setOrdinal(int64_t ordinal) {
- if (_ordinal != -1)
- _ordinal = ordinal;
- }
-
- int64_t getOrdinal() const { return _ordinal; }
-
/// \brief Dump the Input Element
virtual bool dump(raw_ostream &diagnostics) { return true; }
}
protected:
- Kind _kind; // The type of the Element
- int64_t _ordinal; // The ordinal value
+ Kind _kind; // The type of the Element
};
/// \brief A Control node which contains a group of InputElements
/// follow the group
class Group : public InputElement {
public:
- Group(int64_t ordinal)
- : InputElement(InputElement::Kind::Group, ordinal),
- _currentElementIndex(0), _nextElementIndex(0), _madeProgress(false) {}
+ Group()
+ : InputElement(InputElement::Kind::Group), _currentElementIndex(0),
+ _nextElementIndex(0), _madeProgress(false) {}
static inline bool classof(const InputElement *a) {
return a->kind() == InputElement::Kind::Group;
/// directly.
class FileNode : public InputElement {
public:
- FileNode(StringRef path, int64_t ordinal = -1);
+ FileNode(StringRef path)
+ : InputElement(InputElement::Kind::File), _path(path), _nextFileIndex(0) {
+ }
virtual ErrorOr<StringRef> getPath(const LinkingContext &) const {
return _path;
/// \brief Represents Internal Input files
class SimpleFileNode : public FileNode {
public:
- SimpleFileNode(StringRef path, int64_t ordinal = -1)
- : FileNode(path, ordinal) {}
+ SimpleFileNode(StringRef path) : FileNode(path) {}
virtual ~SimpleFileNode() {}
bool _isDashlPrefix;
};
- ELFFileNode(ELFLinkingContext &ctx, StringRef path, int64_t ordinal,
- Attributes &attributes)
- : FileNode(path, ordinal), _elfLinkingContext(ctx),
- _attributes(attributes) {}
+ ELFFileNode(ELFLinkingContext &ctx, StringRef path, Attributes &attributes)
+ : FileNode(path), _elfLinkingContext(ctx), _attributes(attributes) {}
ErrorOr<StringRef> getPath(const LinkingContext &ctx) const override;
bool dump(raw_ostream &diagnostics) override {
diagnostics << "Name : " << *getPath(_elfLinkingContext) << "\n"
<< "Type : ELF File\n"
- << "Ordinal : " << getOrdinal() << "\n"
<< "Attributes :\n"
<< " - wholeArchive : "
<< ((_attributes._isWholeArchive) ? "true" : "false") << "\n"
/// \brief Parse GNU Linker scripts.
class GNULdScript : public FileNode {
public:
- GNULdScript(ELFLinkingContext &ctx, StringRef userPath, int64_t ordinal)
- : FileNode(userPath, ordinal), _elfLinkingContext(ctx),
- _linkerScript(nullptr) {}
+ GNULdScript(ELFLinkingContext &ctx, StringRef userPath)
+ : FileNode(userPath), _elfLinkingContext(ctx), _linkerScript(nullptr) {}
/// \brief Parse the linker script.
error_code parse(const LinkingContext &, raw_ostream &) override;
/// \brief Handle ELF style with GNU Linker scripts.
class ELFGNULdScript : public GNULdScript {
public:
- ELFGNULdScript(ELFLinkingContext &ctx, StringRef userPath, int64_t ordinal)
- : GNULdScript(ctx, userPath, ordinal) {}
+ ELFGNULdScript(ELFLinkingContext &ctx, StringRef userPath)
+ : GNULdScript(ctx, userPath) {}
error_code parse(const LinkingContext &ctx, raw_ostream &diagnostics) override;
/// \brief Represents a ELF control node
class PECOFFGroup : public Group {
public:
- PECOFFGroup(PECOFFLinkingContext &ctx) : Group(0), _ctx(ctx) {}
+ PECOFFGroup(PECOFFLinkingContext &ctx) : Group(), _ctx(ctx) {}
/// \brief Parse the group members.
error_code parse(const LinkingContext &ctx, raw_ostream &diag) override {
using namespace lld;
-static bool sortInputElements(const std::unique_ptr<InputElement> &a,
- const std::unique_ptr<InputElement> &b) {
- return a->getOrdinal() < b->getOrdinal();
-}
-
ErrorOr<File &> InputGraph::nextFile() {
// When nextFile() is called for the first time, _currentInputElement is not
// initialized. Initialize it with the first element of the input graph.
return true;
}
-bool InputGraph::assignOrdinals() {
- for (auto &ie : _inputArgs)
- ie->setOrdinal(++_ordinal);
- return true;
-}
-
-void InputGraph::doPostProcess() {
- std::stable_sort(_inputArgs.begin(), _inputArgs.end(), sortInputElements);
-}
-
bool InputGraph::dump(raw_ostream &diagnostics) {
for (auto &ie : _inputArgs)
if (!ie->dump(diagnostics))
_inputArgs = std::move(_workInputArgs);
}
-/// InputElement
-
-/// \brief Initialize the Input Element, The ordinal value of an input Element
-/// is initially set to -1, if the user wants to override its ordinal,
-/// let the user do it
-InputElement::InputElement(Kind type, int64_t ordinal)
- : _kind(type), _ordinal(ordinal) {}
-
-/// FileNode
-FileNode::FileNode(StringRef path, int64_t ordinal)
- : InputElement(InputElement::Kind::File, ordinal), _path(path),
- _nextFileIndex(0) {}
-
/// \brief Read the file into _buffer.
error_code FileNode::getBuffer(StringRef filePath) {
// Create a memory buffer
return error_code::success();
}
-/// Group
-
/// \brief Return the next file that need to be processed by the resolver.
/// This also processes input elements depending on the resolve status
/// of the input elements contained in the group.
context.createImplicitFiles(implicitFiles);
if (implicitFiles.size())
fileNode->addFiles(std::move(implicitFiles));
-
context.inputGraph().insertElementAt(std::move(fileNode),
InputGraph::Position::BEGIN);
- context.inputGraph().assignOrdinals();
-
- context.inputGraph().doPostProcess();
-
// Do core linking.
ScopedTask resolveTask(getDefaultDomain(), "Resolve");
Resolver resolver(context);
ELFFileNode::Attributes attributes;
- int index = 0;
bool _outputOptionSet = false;
// Ignore unknown arguments.
}
case OPT_start_group: {
- std::unique_ptr<Group> group(new Group(index++));
+ std::unique_ptr<Group> group(new Group());
groupStack.push(group.get());
inputGraph->addInputElement(std::move(group));
break;
magic == llvm::sys::fs::file_magic::unknown)
isELFFileNode = false;
FileNode *inputNode = nullptr;
- if (isELFFileNode)
- inputNode = new ELFFileNode(*ctx, userPath, index++, attributes);
- else {
- inputNode = new ELFGNULdScript(*ctx, resolvedInputPath, index++);
+ if (isELFFileNode) {
+ inputNode = new ELFFileNode(*ctx, userPath, attributes);
+ } else {
+ inputNode = new ELFGNULdScript(*ctx, resolvedInputPath);
ec = inputNode->parse(*ctx, diagnostics);
if (ec) {
diagnostics << userPath << ": Error parsing linker script\n";
/// \brief Handle GnuLD script for ELF.
error_code ELFGNULdScript::parse(const LinkingContext &ctx,
raw_ostream &diagnostics) {
- int64_t index = 0;
ELFFileNode::Attributes attributes;
if (error_code ec = GNULdScript::parse(ctx, diagnostics))
return ec;
for (const auto &c : _linkerScript->_commands) {
if (auto group = dyn_cast<script::Group>(c)) {
- std::unique_ptr<Group> groupStart(new Group(index++));
+ std::unique_ptr<Group> groupStart(new Group());
for (auto &path : group->getPaths()) {
// TODO : Propagate Set WholeArchive/dashlPrefix
attributes.setAsNeeded(path._asNeeded);
auto inputNode = new ELFFileNode(
_elfLinkingContext, _elfLinkingContext.allocateString(path._path),
- index++, attributes);
+ attributes);
std::unique_ptr<InputElement> inputFile(inputNode);
cast<Group>(groupStart.get())->addFile(
std::move(inputFile));
CHECK: Name : {{[^ ]+}}elf/Inputs{{[\\/]}}libfnarchive.a
CHECK: Type : ELF File
-CHECK: Ordinal : 0
CHECK: Attributes :
CHECK: - wholeArchive : false
CHECK: - asNeeded : false
WHOLEARCHIVE: Name : {{[^ ]+}}elf/Inputs{{[\\/]}}libfnarchive.a
WHOLEARCHIVE: Type : ELF File
-WHOLEARCHIVE: Ordinal : 0
WHOLEARCHIVE: Attributes :
WHOLEARCHIVE: - wholeArchive : true
WHOLEARCHIVE: - asNeeded : false
ASNEEDED: Name : {{[^ ]+}}elf/Inputs{{[\\/]}}libfnarchive.a
ASNEEDED: Type : ELF File
-ASNEEDED: Ordinal : 0
ASNEEDED: Attributes :
ASNEEDED: - wholeArchive : true
ASNEEDED: - asNeeded : true
SYSROOT: Name : {{[^ ]+}}elf/Inputs{{[\\/]}}libfnarchive.a
SYSROOT: Type : ELF File
-SYSROOT: Ordinal : 0
SYSROOT: Attributes :
SYSROOT: - wholeArchive : false
SYSROOT: - asNeeded : false
class MyFileNode : public SimpleFileNode {
public:
- MyFileNode(StringRef path, int64_t ordinal) : SimpleFileNode(path, ordinal) {}
+ MyFileNode(StringRef path) : SimpleFileNode(path) {}
void resetNextIndex() override { FileNode::resetNextIndex(); }
};
class MyExpandFileNode : public SimpleFileNode {
public:
- MyExpandFileNode(StringRef path, int64_t ordinal)
- : SimpleFileNode(path, ordinal) {}
+ MyExpandFileNode(StringRef path) : SimpleFileNode(path) {}
/// \brief How do we want to expand the current node ?
bool shouldExpand() const override { return true; }
}
TEST_F(InputGraphTest, AddAFile) {
- std::unique_ptr<MyFileNode> myfile(new MyFileNode("file1", 0));
+ std::unique_ptr<MyFileNode> myfile(new MyFileNode("file1"));
EXPECT_EQ(true, inputGraph().addInputElement(std::move(myfile)));
EXPECT_EQ(1, inputFileCount());
ErrorOr<InputElement *> nextElement = inputGraph().getNextInputElement();
}
TEST_F(InputGraphTest, AddAFileWithLLDFiles) {
- std::unique_ptr<MyFileNode> myfile(new MyFileNode("multi_files", 0));
- std::vector<std::unique_ptr<File> > objfiles;
+ std::unique_ptr<MyFileNode> myfile(new MyFileNode("multi_files"));
+ std::vector<std::unique_ptr<File>> objfiles;
std::unique_ptr<SimpleFile> obj1(new SimpleFile("objfile1"));
std::unique_ptr<SimpleFile> obj2(new SimpleFile("objfile2"));
objfiles.push_back(std::move(obj1));
}
TEST_F(InputGraphTest, AddNodeWithFilesAndGroup) {
- std::unique_ptr<MyFileNode> myfile(new MyFileNode("multi_files1", 0));
- std::vector<std::unique_ptr<File> > objfiles;
+ std::unique_ptr<MyFileNode> myfile(new MyFileNode("multi_files1"));
+ std::vector<std::unique_ptr<File>> objfiles;
std::unique_ptr<SimpleFile> obj1(new SimpleFile("objfile1"));
std::unique_ptr<SimpleFile> obj2(new SimpleFile("objfile2"));
objfiles.push_back(std::move(obj1));
// Create a group node with two elements
// an file node which looks like an archive and
// two file nodes
- std::unique_ptr<Group> mygroup(new Group(1));
- std::unique_ptr<MyFileNode> myarchive(new MyFileNode("archive_file", 2));
- std::vector<std::unique_ptr<File> > objfiles_group;
+ std::unique_ptr<Group> mygroup(new Group());
+ std::unique_ptr<MyFileNode> myarchive(new MyFileNode("archive_file"));
+ std::vector<std::unique_ptr<File>> objfiles_group;
std::unique_ptr<SimpleFile> obj_1(new SimpleFile("objfile_1"));
std::unique_ptr<SimpleFile> obj_2(new SimpleFile("objfile_2"));
objfiles_group.push_back(std::move(obj_1));
EXPECT_EQ(true, mygroup->addFile(std::move(myarchive)));
std::unique_ptr<MyFileNode> mygroupobjfile_1(
- new MyFileNode("group_objfile1", 3));
- std::vector<std::unique_ptr<File> > objfiles_group1;
- std::unique_ptr<SimpleFile> mygroupobj1(
- new SimpleFile("group_objfile1"));
+ new MyFileNode("group_objfile1"));
+ std::vector<std::unique_ptr<File>> objfiles_group1;
+ std::unique_ptr<SimpleFile> mygroupobj1(new SimpleFile("group_objfile1"));
objfiles_group1.push_back(std::move(mygroupobj1));
mygroupobjfile_1->addFiles(std::move(objfiles_group1));
EXPECT_EQ(true, mygroup->addFile(std::move(mygroupobjfile_1)));
std::unique_ptr<MyFileNode> mygroupobjfile_2(
- new MyFileNode("group_objfile2", 4));
- std::vector<std::unique_ptr<File> > objfiles_group2;
- std::unique_ptr<SimpleFile> mygroupobj2(
- new SimpleFile("group_objfile2"));
+ new MyFileNode("group_objfile2"));
+ std::vector<std::unique_ptr<File>> objfiles_group2;
+ std::unique_ptr<SimpleFile> mygroupobj2(new SimpleFile("group_objfile2"));
objfiles_group2.push_back(std::move(mygroupobj2));
mygroupobjfile_2->addFiles(std::move(objfiles_group2));
EXPECT_EQ(true, mygroup->addFile(std::move(mygroupobjfile_2)));
// Iterate through the group
TEST_F(InputGraphTest, AddNodeWithGroupIteration) {
- std::unique_ptr<MyFileNode> myfile(new MyFileNode("multi_files1", 0));
- std::vector<std::unique_ptr<File> > objfiles;
+ std::unique_ptr<MyFileNode> myfile(new MyFileNode("multi_files1"));
+ std::vector<std::unique_ptr<File>> objfiles;
std::unique_ptr<SimpleFile> obj1(new SimpleFile("objfile1"));
std::unique_ptr<SimpleFile> obj2(new SimpleFile("objfile2"));
objfiles.push_back(std::move(obj1));
// Create a group node with two elements
// an file node which looks like an archive and
// two file nodes
- std::unique_ptr<Group> mygroup(new Group(1));
- std::unique_ptr<MyFileNode> myarchive(new MyFileNode("archive_file", 2));
- std::vector<std::unique_ptr<File> > objfiles_group;
+ std::unique_ptr<Group> mygroup(new Group());
+ std::unique_ptr<MyFileNode> myarchive(new MyFileNode("archive_file"));
+ std::vector<std::unique_ptr<File>> objfiles_group;
std::unique_ptr<SimpleFile> obj_1(new SimpleFile("objfile_1"));
std::unique_ptr<SimpleFile> obj_2(new SimpleFile("objfile_2"));
objfiles_group.push_back(std::move(obj_1));
EXPECT_EQ(true, mygroup->addFile(std::move(myarchive)));
std::unique_ptr<MyFileNode> mygroupobjfile_1(
- new MyFileNode("group_objfile1", 3));
- std::vector<std::unique_ptr<File> > objfiles_group1;
- std::unique_ptr<SimpleFile> mygroupobj1(
- new SimpleFile("group_objfile1"));
+ new MyFileNode("group_objfile1"));
+ std::vector<std::unique_ptr<File>> objfiles_group1;
+ std::unique_ptr<SimpleFile> mygroupobj1(new SimpleFile("group_objfile1"));
objfiles_group1.push_back(std::move(mygroupobj1));
mygroupobjfile_1->addFiles(std::move(objfiles_group1));
EXPECT_EQ(true, mygroup->addFile(std::move(mygroupobjfile_1)));
std::unique_ptr<MyFileNode> mygroupobjfile_2(
- new MyFileNode("group_objfile2", 4));
- std::vector<std::unique_ptr<File> > objfiles_group2;
- std::unique_ptr<SimpleFile> mygroupobj2(
- new SimpleFile("group_objfile2"));
+ new MyFileNode("group_objfile2"));
+ std::vector<std::unique_ptr<File>> objfiles_group2;
+ std::unique_ptr<SimpleFile> mygroupobj2(new SimpleFile("group_objfile2"));
objfiles_group2.push_back(std::move(mygroupobj2));
mygroupobjfile_2->addFiles(std::move(objfiles_group2));
EXPECT_EQ(true, mygroup->addFile(std::move(mygroupobjfile_2)));
// Node expansion tests.
TEST_F(InputGraphTest, ExpandAndReplaceInputGraphNode) {
- std::unique_ptr<MyFileNode> myfile(new MyFileNode("multi_files1", 0));
- std::vector<std::unique_ptr<File> > objfiles;
+ std::unique_ptr<MyFileNode> myfile(new MyFileNode("multi_files1"));
+ std::vector<std::unique_ptr<File>> objfiles;
std::unique_ptr<SimpleFile> obj1(new SimpleFile("objfile1"));
std::unique_ptr<SimpleFile> obj2(new SimpleFile("objfile2"));
objfiles.push_back(std::move(obj1));
EXPECT_EQ(true, inputGraph().addInputElement(std::move(myfile)));
objfiles.clear();
- std::unique_ptr<MyExpandFileNode> expandFile(new MyExpandFileNode(
- "expand_node", 1));
+ std::unique_ptr<MyExpandFileNode> expandFile(
+ new MyExpandFileNode("expand_node"));
- std::unique_ptr<MyFileNode> filenode1(new MyFileNode("expand_file1", 2));
+ std::unique_ptr<MyFileNode> filenode1(new MyFileNode("expand_file1"));
std::unique_ptr<SimpleFile> obj3(new SimpleFile("objfile3"));
objfiles.push_back(std::move(obj3));
filenode1->addFiles(std::move(objfiles));
expandFile->addElement(std::move(filenode1));
objfiles.clear();
- std::unique_ptr<MyFileNode> filenode2(new MyFileNode("expand_file2", 3));
+ std::unique_ptr<MyFileNode> filenode2(new MyFileNode("expand_file2"));
std::unique_ptr<SimpleFile> obj4(new SimpleFile("objfile4"));
objfiles.push_back(std::move(obj4));
filenode2->addFiles(std::move(objfiles));
// Add expand file to InputGraph
EXPECT_EQ(true, inputGraph().addInputElement(std::move(expandFile)));
- std::unique_ptr<MyFileNode> filenode3(new MyFileNode("obj_after_expand", 4));
+ std::unique_ptr<MyFileNode> filenode3(new MyFileNode("obj_after_expand"));
std::unique_ptr<SimpleFile> obj5(new SimpleFile("objfile5"));
std::unique_ptr<SimpleFile> obj6(new SimpleFile("objfile6"));
objfiles.push_back(std::move(obj5));