2013-11-14 08:51:33 +08:00
|
|
|
//===- lib/Core/InputGraph.cpp --------------------------------------------===//
|
2013-08-22 06:57:10 +08:00
|
|
|
//
|
|
|
|
// The LLVM Linker
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
2013-11-14 08:51:33 +08:00
|
|
|
|
|
|
|
#include "lld/Core/InputGraph.h"
|
|
|
|
|
2013-10-07 10:47:09 +08:00
|
|
|
#include "lld/Core/Resolver.h"
|
2014-03-14 00:20:38 +08:00
|
|
|
|
|
|
|
#include <memory>
|
2013-08-22 06:57:10 +08:00
|
|
|
|
|
|
|
using namespace lld;
|
|
|
|
|
2014-04-04 08:14:04 +08:00
|
|
|
ErrorOr<File &> InputGraph::getNextFile() {
|
|
|
|
// When getNextFile() is called for the first time, _currentInputElement is
|
|
|
|
// not initialized. Initialize it with the first element of the input graph.
|
2014-04-02 13:03:40 +08:00
|
|
|
if (_currentInputElement == nullptr) {
|
|
|
|
ErrorOr<InputElement *> elem = getNextInputElement();
|
|
|
|
if (elem.getError() == InputGraphError::no_more_elements)
|
|
|
|
return make_error_code(InputGraphError::no_more_files);
|
|
|
|
_currentInputElement = *elem;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Otherwise, try to get the next file of _currentInputElement. If the current
|
|
|
|
// input element points to an archive file, and there's a file left in the
|
|
|
|
// archive, it will succeed. If not, try to get the next file in the input
|
|
|
|
// graph.
|
|
|
|
for (;;) {
|
|
|
|
ErrorOr<File &> nextFile = _currentInputElement->getNextFile();
|
|
|
|
if (nextFile.getError() != InputGraphError::no_more_files)
|
|
|
|
return std::move(nextFile);
|
|
|
|
|
|
|
|
ErrorOr<InputElement *> elem = getNextInputElement();
|
|
|
|
if (elem.getError() == InputGraphError::no_more_elements ||
|
|
|
|
*elem == nullptr)
|
|
|
|
return make_error_code(InputGraphError::no_more_files);
|
|
|
|
_currentInputElement = *elem;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-03 05:02:44 +08:00
|
|
|
void InputGraph::notifyProgress() { _currentInputElement->notifyProgress(); }
|
2014-04-02 13:03:40 +08:00
|
|
|
|
2014-05-07 01:33:14 +08:00
|
|
|
void InputGraph::addInputElement(std::unique_ptr<InputElement> ie) {
|
2013-08-22 06:57:10 +08:00
|
|
|
_inputArgs.push_back(std::move(ie));
|
|
|
|
}
|
|
|
|
|
|
|
|
bool InputGraph::dump(raw_ostream &diagnostics) {
|
2014-04-04 04:47:50 +08:00
|
|
|
for (std::unique_ptr<InputElement> &ie : _inputArgs)
|
2013-08-22 06:57:10 +08:00
|
|
|
if (!ie->dump(diagnostics))
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
2013-09-08 01:55:28 +08:00
|
|
|
|
2013-10-09 11:40:29 +08:00
|
|
|
/// \brief Insert element at position
|
2014-04-02 07:17:28 +08:00
|
|
|
void InputGraph::insertElementAt(std::unique_ptr<InputElement> element,
|
2014-04-02 07:58:17 +08:00
|
|
|
Position position) {
|
|
|
|
if (position == InputGraph::Position::BEGIN) {
|
|
|
|
_inputArgs.insert(_inputArgs.begin(), std::move(element));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
assert(position == InputGraph::Position::END);
|
|
|
|
_inputArgs.push_back(std::move(element));
|
2013-10-07 10:47:09 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Helper functions for the resolver
|
|
|
|
ErrorOr<InputElement *> InputGraph::getNextInputElement() {
|
|
|
|
if (_nextElementIndex >= _inputArgs.size())
|
2013-10-09 08:57:22 +08:00
|
|
|
return make_error_code(InputGraphError::no_more_elements);
|
2014-04-02 05:55:36 +08:00
|
|
|
return _inputArgs[_nextElementIndex++].get();
|
2013-10-07 10:47:09 +08:00
|
|
|
}
|
|
|
|
|
2013-11-23 07:08:24 +08:00
|
|
|
void InputGraph::normalize() {
|
2014-04-04 08:59:50 +08:00
|
|
|
std::vector<std::unique_ptr<InputElement>> vec;
|
|
|
|
for (std::unique_ptr<InputElement> &ie : _inputArgs) {
|
|
|
|
if (!ie->shouldExpand()) {
|
|
|
|
vec.push_back(std::move(ie));
|
|
|
|
continue;
|
2014-04-02 05:55:36 +08:00
|
|
|
}
|
2014-04-04 08:59:50 +08:00
|
|
|
range<InputElementIterT> expanded = ie->expandElements();
|
|
|
|
vec.insert(vec.end(), std::make_move_iterator(expanded.begin()),
|
|
|
|
std::make_move_iterator(expanded.end()));
|
2013-11-23 07:08:24 +08:00
|
|
|
}
|
2014-04-04 08:59:50 +08:00
|
|
|
_inputArgs = std::move(vec);
|
2013-11-23 07:08:24 +08:00
|
|
|
}
|
|
|
|
|
2013-10-08 13:52:01 +08:00
|
|
|
/// \brief Read the file into _buffer.
|
2013-11-11 10:13:30 +08:00
|
|
|
error_code FileNode::getBuffer(StringRef filePath) {
|
2013-10-08 13:52:01 +08:00
|
|
|
// Create a memory buffer
|
2014-03-14 00:20:38 +08:00
|
|
|
std::unique_ptr<MemoryBuffer> mb;
|
|
|
|
if (error_code ec = MemoryBuffer::getFileOrSTDIN(filePath, mb))
|
2013-10-08 13:52:01 +08:00
|
|
|
return ec;
|
|
|
|
_buffer = std::move(mb);
|
|
|
|
return error_code::success();
|
|
|
|
}
|
|
|
|
|
2013-10-09 11:40:29 +08:00
|
|
|
/// \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.
|
|
|
|
ErrorOr<File &> Group::getNextFile() {
|
|
|
|
// If there are no elements, move on to the next input element
|
2013-11-13 13:19:47 +08:00
|
|
|
if (_elements.empty())
|
2013-10-09 11:40:29 +08:00
|
|
|
return make_error_code(InputGraphError::no_more_files);
|
2013-10-11 12:20:29 +08:00
|
|
|
|
|
|
|
for (;;) {
|
2014-04-03 05:02:44 +08:00
|
|
|
// If we have processed all the elements, and have made no progress on
|
|
|
|
// linking, we cannot resolve any symbol from this group. Continue to the
|
|
|
|
// next one by returning no_more_files.
|
2013-10-11 12:20:29 +08:00
|
|
|
if (_nextElementIndex == _elements.size()) {
|
2014-04-03 05:02:44 +08:00
|
|
|
if (!_madeProgress)
|
2013-10-11 12:20:29 +08:00
|
|
|
return make_error_code(InputGraphError::no_more_files);
|
|
|
|
resetNextIndex();
|
|
|
|
}
|
2014-04-03 05:02:44 +08:00
|
|
|
|
2013-10-11 12:20:29 +08:00
|
|
|
_currentElementIndex = _nextElementIndex;
|
|
|
|
auto file = _elements[_nextElementIndex]->getNextFile();
|
|
|
|
// Move on to the next element if we have finished processing all
|
|
|
|
// the files in the input element
|
2014-01-09 06:00:09 +08:00
|
|
|
if (file.getError() == InputGraphError::no_more_files) {
|
2013-10-11 12:20:29 +08:00
|
|
|
_nextElementIndex++;
|
|
|
|
continue;
|
|
|
|
}
|
2013-10-09 11:40:29 +08:00
|
|
|
return *file;
|
2013-10-11 12:20:29 +08:00
|
|
|
}
|
2013-10-09 11:40:29 +08:00
|
|
|
}
|