[lld] r223867 - Re-commit r223330: Rewrite InputGraph's Group
Rui Ueyama
ruiu at google.com
Tue Dec 9 16:33:00 PST 2014
Author: ruiu
Date: Tue Dec 9 18:33:00 2014
New Revision: 223867
URL: http://llvm.org/viewvc/llvm-project?rev=223867&view=rev
Log:
Re-commit r223330: Rewrite InputGraph's Group
Modified:
lld/trunk/include/lld/Core/InputGraph.h
lld/trunk/include/lld/Core/LinkingContext.h
lld/trunk/include/lld/Core/Resolver.h
lld/trunk/include/lld/Driver/DarwinInputGraph.h
lld/trunk/include/lld/Driver/WinLinkInputGraph.h
lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
lld/trunk/lib/Core/InputGraph.cpp
lld/trunk/lib/Core/Resolver.cpp
lld/trunk/lib/Driver/DarwinInputGraph.cpp
lld/trunk/lib/Driver/DarwinLdDriver.cpp
lld/trunk/lib/Driver/Driver.cpp
lld/trunk/lib/Driver/GnuLdDriver.cpp
lld/trunk/lib/Driver/GnuLdInputGraph.cpp
lld/trunk/lib/Driver/WinLinkDriver.cpp
lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
lld/trunk/unittests/DriverTests/DriverTest.h
lld/trunk/unittests/DriverTests/InputGraphTest.cpp
lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp
Modified: lld/trunk/include/lld/Core/InputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/InputGraph.h?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/InputGraph.h (original)
+++ lld/trunk/include/lld/Core/InputGraph.h Tue Dec 9 18:33:00 2014
@@ -59,12 +59,6 @@ public:
/// assigned in the way files are resolved.
virtual ErrorOr<File &> getNextFile();
- /// Notifies the current input element of Resolver made some progress on
- /// resolving undefined symbols using the current file. Group (representing
- /// --start-group and --end-group) uses that notification to make a decision
- /// whether it should iterate over again or terminate or not.
- virtual void notifyProgress();
-
/// Adds an observer of getNextFile(). Each time a new file is about to be
/// returned from getNextFile(), registered observers are called with the file
/// being returned.
@@ -76,14 +70,18 @@ public:
/// \brief Adds a node at the beginning of the InputGraph
void addInputElementFront(std::unique_ptr<InputElement>);
- /// Normalize the InputGraph. It calls expand() on each node and then replace
- /// it with getReplacements() results.
+ /// Normalize the InputGraph. It calls getReplacements() on each element.
void normalize();
- range<InputElementIterT> inputElements() {
- return make_range(_inputArgs.begin(), _inputArgs.end());
+ InputElementVectorT &inputElements() {
+ return _inputArgs;
}
+ // Returns the current group size if we are at an --end-group.
+ // Otherwise returns 0.
+ int getGroupSize();
+ void skipGroup();
+
// \brief Returns the number of input files.
size_t size() const { return _inputArgs.size(); }
@@ -108,8 +106,8 @@ class InputElement {
public:
/// Each input element in the graph can be a File or a control
enum class Kind : uint8_t {
- Group, // Represents a type associated with Group
- File // Represents a type associated with File Nodes
+ File, // Represents a type associated with File Nodes
+ GroupEnd,
};
InputElement(Kind type) : _kind(type) {}
@@ -129,16 +127,9 @@ public:
/// Get the next file to be processed by the resolver
virtual ErrorOr<File &> getNextFile() = 0;
- /// Refer InputGraph::notifyProgress(). By default, it does nothing. Only
- /// Group is interested in this message.
- virtual void notifyProgress() {};
-
/// \brief Reset the next index
virtual void resetNextIndex() = 0;
- /// Returns true if we want to replace this node with children.
- virtual void expand() {}
-
/// Get the elements that we want to expand with.
virtual bool getReplacements(InputGraph::InputElementVectorT &) {
return false;
@@ -148,73 +139,31 @@ protected:
Kind _kind; // The type of the Element
};
-/// \brief A Control node which contains a group of InputElements
-/// This affects the resolver so that it resolves undefined symbols
-/// in the group completely before looking at other input files that
-/// follow the group
-class Group : public InputElement {
+// This is a marker for --end-group. getSize() returns the number of
+// files between the corresponding --start-group and this marker.
+class GroupEnd : public InputElement {
public:
- Group()
- : InputElement(InputElement::Kind::Group), _currentElementIndex(0),
- _nextElementIndex(0), _madeProgress(false) {}
+ GroupEnd(int size) : InputElement(Kind::GroupEnd), _size(size) {}
- static inline bool classof(const InputElement *a) {
- return a->kind() == InputElement::Kind::Group;
- }
-
- /// \brief Process input element and add it to the group
- bool addFile(std::unique_ptr<InputElement> element) {
- _elements.push_back(std::move(element));
- return true;
- }
+ int getSize() const { return _size; }
- range<InputGraph::InputElementIterT> elements() {
- return make_range(_elements.begin(), _elements.end());
- }
-
- void resetNextIndex() override {
- _madeProgress = false;
- _currentElementIndex = 0;
- _nextElementIndex = 0;
- for (std::unique_ptr<InputElement> &elem : _elements)
- elem->resetNextIndex();
+ static inline bool classof(const InputElement *a) {
+ return a->kind() == Kind::GroupEnd;
}
/// \brief Parse the group members.
std::error_code parse(const LinkingContext &ctx, raw_ostream &diag) override {
- for (std::unique_ptr<InputElement> &ei : _elements)
- if (std::error_code ec = ei->parse(ctx, diag))
- return ec;
return std::error_code();
}
- /// If Resolver made a progress using the current file, it's ok to revisit
- /// files in this group in future.
- void notifyProgress() override {
- for (std::unique_ptr<InputElement> &elem : _elements)
- elem->notifyProgress();
- _madeProgress = true;
- }
-
- ErrorOr<File &> getNextFile() override;
-
- void expand() override {
- for (std::unique_ptr<InputElement> &elt : _elements)
- elt->expand();
- std::vector<std::unique_ptr<InputElement>> result;
- for (std::unique_ptr<InputElement> &elt : _elements) {
- if (elt->getReplacements(result))
- continue;
- result.push_back(std::move(elt));
- }
- _elements.swap(result);
+ ErrorOr<File &> getNextFile() override {
+ llvm_unreachable("shouldn't be here.");
}
-protected:
- InputGraph::InputElementVectorT _elements;
- uint32_t _currentElementIndex;
- uint32_t _nextElementIndex;
- bool _madeProgress;
+ void resetNextIndex() override {}
+
+private:
+ int _size;
};
/// \brief Represents an Input file in the graph
@@ -252,6 +201,8 @@ public:
/// \brief add a file to the list of files
virtual void addFiles(InputGraph::FileVectorT files) {
+ assert(files.size() == 1);
+ assert(_files.empty());
for (std::unique_ptr<File> &ai : files)
_files.push_back(std::move(ai));
}
@@ -260,6 +211,8 @@ public:
/// the node again.
void resetNextIndex() override { _nextFileIndex = 0; }
+ bool getReplacements(InputGraph::InputElementVectorT &result) override;
+
protected:
/// \brief Read the file into _buffer.
std::error_code getBuffer(StringRef filePath);
@@ -276,6 +229,10 @@ protected:
class SimpleFileNode : public FileNode {
public:
SimpleFileNode(StringRef path) : FileNode(path) {}
+ SimpleFileNode(StringRef path, std::unique_ptr<File> f)
+ : FileNode(path) {
+ _files.push_back(std::move(f));
+ }
virtual ~SimpleFileNode() {}
Modified: lld/trunk/include/lld/Core/LinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/LinkingContext.h?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/LinkingContext.h (original)
+++ lld/trunk/include/lld/Core/LinkingContext.h Tue Dec 9 18:33:00 2014
@@ -322,6 +322,10 @@ public:
bool runRoundTripPass() const { return _runRoundTripPasses; }
#endif
+ // This function is called just before the Resolver kicks in.
+ // Derived classes may use that chance to rearrange the input files.
+ virtual void maybeSortInputFiles() {}
+
/// @}
protected:
LinkingContext(); // Must be subclassed
Modified: lld/trunk/include/lld/Core/Resolver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/include/lld/Core/Resolver.h (original)
+++ lld/trunk/include/lld/Core/Resolver.h Tue Dec 9 18:33:00 2014
@@ -28,7 +28,8 @@ class LinkingContext;
class Resolver {
public:
Resolver(LinkingContext &context)
- : _context(context), _symbolTable(context), _result(new MergedFile()) {}
+ : _context(context), _symbolTable(context), _result(new MergedFile()),
+ _fileIndex(0) {}
// InputFiles::Handler methods
void doDefinedAtom(const DefinedAtom&);
@@ -38,10 +39,10 @@ public:
// Handle files, this adds atoms from the current file thats
// being processed by the resolver
- void handleFile(const File &);
+ bool handleFile(const File &);
// Handle an archive library file.
- void handleArchiveFile(const File &);
+ bool handleArchiveFile(const File &);
// Handle a shared library file.
void handleSharedLibrary(const File &);
@@ -54,6 +55,9 @@ public:
private:
typedef std::function<void(StringRef, bool)> UndefCallback;
+ bool undefinesAdded(int count);
+ ErrorOr<File &> nextFile(bool &inGroup);
+
/// \brief Add section group/.gnu.linkonce if it does not exist previously.
void maybeAddSectionGroupOrGnuLinkOnce(const DefinedAtom &atom);
@@ -110,6 +114,11 @@ private:
llvm::DenseSet<const Atom *> _deadAtoms;
std::unique_ptr<MergedFile> _result;
llvm::DenseMap<const Atom *, llvm::DenseSet<const Atom *>> _reverseRef;
+
+ // --start-group and --end-group
+ std::vector<File *> _files;
+ std::map<File *, bool> _newUndefinesAdded;
+ size_t _fileIndex;
};
} // namespace lld
Modified: lld/trunk/include/lld/Driver/DarwinInputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/DarwinInputGraph.h?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/include/lld/Driver/DarwinInputGraph.h (original)
+++ lld/trunk/include/lld/Driver/DarwinInputGraph.h Tue Dec 9 18:33:00 2014
@@ -23,18 +23,6 @@
namespace lld {
-
-class DarwinInputGraph : public InputGraph {
-public:
- DarwinInputGraph() : _librariesPhase(false), _repeatLibraries(false) { }
- ErrorOr<File &> getNextFile() override;
- void notifyProgress() override;
-private:
- bool _librariesPhase;
- bool _repeatLibraries;
-};
-
-
/// \brief Represents a MachO File
class MachOFileNode : public FileNode {
public:
Modified: lld/trunk/include/lld/Driver/WinLinkInputGraph.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/WinLinkInputGraph.h?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/include/lld/Driver/WinLinkInputGraph.h (original)
+++ lld/trunk/include/lld/Driver/WinLinkInputGraph.h Tue Dec 9 18:33:00 2014
@@ -55,21 +55,6 @@ public:
ErrorOr<StringRef> getPath(const LinkingContext &ctx) const override;
};
-/// \brief Represents a ELF control node
-class PECOFFGroup : public Group {
-public:
- PECOFFGroup(PECOFFLinkingContext &ctx) : Group(), _ctx(ctx) {}
-
- /// \brief Parse the group members.
- std::error_code parse(const LinkingContext &ctx, raw_ostream &diag) override {
- std::lock_guard<std::recursive_mutex> lock(_ctx.getMutex());
- return Group::parse(ctx, diag);
- }
-
-private:
- PECOFFLinkingContext &_ctx;
-};
-
} // namespace lld
#endif
Modified: lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h Tue Dec 9 18:33:00 2014
@@ -283,6 +283,8 @@ public:
/// bits are xxxx.yy.zz. Largest number is 65535.255.255
static bool parsePackedVersion(StringRef str, uint32_t &result);
+ void maybeSortInputFiles() override;
+
private:
Writer &writer() const override;
mach_o::MachODylibFile* loadIndirectDylib(StringRef path);
Modified: lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h Tue Dec 9 18:33:00 2014
@@ -29,7 +29,6 @@ using llvm::COFF::WindowsSubsystem;
static const uint8_t DEFAULT_DOS_STUB[128] = {'M', 'Z'};
namespace lld {
-class Group;
class PECOFFLinkingContext : public LinkingContext {
public:
@@ -318,8 +317,7 @@ public:
void setEntryNode(SimpleFileNode *node) { _entryNode = node; }
SimpleFileNode *getEntryNode() const { return _entryNode; }
- void setLibraryGroup(Group *group) { _libraryGroup = group; }
- Group *getLibraryGroup() const { return _libraryGroup; }
+ void addLibraryFile(std::unique_ptr<FileNode> file);
void setModuleDefinitionFile(const std::string val) {
_moduleDefinitionFile = val;
@@ -441,9 +439,6 @@ private:
// The node containing the entry point file.
SimpleFileNode *_entryNode;
- // The PECOFFGroup that contains all the .lib files.
- Group *_libraryGroup;
-
// Name of the temporary file for lib.exe subcommand. For debugging
// only.
std::string _moduleDefinitionFile;
Modified: lld/trunk/lib/Core/InputGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/InputGraph.cpp?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/lib/Core/InputGraph.cpp (original)
+++ lld/trunk/lib/Core/InputGraph.cpp Tue Dec 9 18:33:00 2014
@@ -36,8 +36,6 @@ ErrorOr<File &> InputGraph::getNextFile(
}
}
-void InputGraph::notifyProgress() { _currentInputElement->notifyProgress(); }
-
void InputGraph::registerObserver(std::function<void(File *)> fn) {
_observers.push_back(fn);
}
@@ -61,12 +59,13 @@ bool InputGraph::dump(raw_ostream &diagn
ErrorOr<InputElement *> InputGraph::getNextInputElement() {
if (_nextElementIndex >= _inputArgs.size())
return make_error_code(InputGraphError::no_more_elements);
- return _inputArgs[_nextElementIndex++].get();
+ InputElement *elem = _inputArgs[_nextElementIndex++].get();
+ if (isa<GroupEnd>(elem))
+ return getNextInputElement();
+ return elem;
}
void InputGraph::normalize() {
- for (std::unique_ptr<InputElement> &elt : _inputArgs)
- elt->expand();
std::vector<std::unique_ptr<InputElement>> vec;
for (std::unique_ptr<InputElement> &elt : _inputArgs) {
if (elt->getReplacements(vec))
@@ -76,6 +75,25 @@ void InputGraph::normalize() {
_inputArgs = std::move(vec);
}
+// If we are at the end of a group, return its size (which indicates
+// how many files we need to go back in the command line).
+// Returns 0 if we are not at the end of a group.
+int InputGraph::getGroupSize() {
+ if (_nextElementIndex >= _inputArgs.size())
+ return 0;
+ InputElement *elem = _inputArgs[_nextElementIndex].get();
+ if (const GroupEnd *group = dyn_cast<GroupEnd>(elem))
+ return group->getSize();
+ return 0;
+}
+
+void InputGraph::skipGroup() {
+ if (_nextElementIndex >= _inputArgs.size())
+ return;
+ if (isa<GroupEnd>(_inputArgs[_nextElementIndex].get()))
+ _nextElementIndex++;
+}
+
/// \brief Read the file into _buffer.
std::error_code FileNode::getBuffer(StringRef filePath) {
// Create a memory buffer
@@ -87,32 +105,10 @@ std::error_code FileNode::getBuffer(Stri
return std::error_code();
}
-/// \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
- if (_elements.empty())
- return make_error_code(InputGraphError::no_more_files);
-
- for (;;) {
- // 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.
- if (_nextElementIndex == _elements.size()) {
- if (!_madeProgress)
- return make_error_code(InputGraphError::no_more_files);
- resetNextIndex();
- }
-
- _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
- if (file.getError() == InputGraphError::no_more_files) {
- _nextElementIndex++;
- continue;
- }
- return *file;
- }
+bool FileNode::getReplacements(InputGraph::InputElementVectorT &result) {
+ if (_files.size() < 2)
+ return false;
+ for (std::unique_ptr<File> &file : _files)
+ result.push_back(llvm::make_unique<SimpleFileNode>(_path, std::move(file)));
+ return true;
}
Modified: lld/trunk/lib/Core/Resolver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/lib/Core/Resolver.cpp (original)
+++ lld/trunk/lib/Core/Resolver.cpp Tue Dec 9 18:33:00 2014
@@ -27,7 +27,7 @@
namespace lld {
-void Resolver::handleFile(const File &file) {
+bool Resolver::handleFile(const File &file) {
bool undefAdded = false;
for (const DefinedAtom *atom : file.defined())
doDefinedAtom(*atom);
@@ -38,13 +38,7 @@ void Resolver::handleFile(const File &fi
doSharedLibraryAtom(*atom);
for (const AbsoluteAtom *atom : file.absolute())
doAbsoluteAtom(*atom);
-
- // Notify the input file manager of the fact that we have made some progress
- // on linking using the current input file. It may want to know the fact for
- // --start-group/--end-group.
- if (undefAdded) {
- _context.getInputGraph().notifyProgress();
- }
+ return undefAdded;
}
void Resolver::forEachUndefines(bool searchForOverrides,
@@ -76,17 +70,19 @@ void Resolver::forEachUndefines(bool sea
} while (undefineGenCount != _symbolTable.size());
}
-void Resolver::handleArchiveFile(const File &file) {
+bool Resolver::handleArchiveFile(const File &file) {
const ArchiveLibraryFile *archiveFile = cast<ArchiveLibraryFile>(&file);
bool searchForOverrides =
_context.searchArchivesToOverrideTentativeDefinitions();
+ bool undefAdded = false;
forEachUndefines(searchForOverrides,
[&](StringRef undefName, bool dataSymbolOnly) {
if (const File *member = archiveFile->find(undefName, dataSymbolOnly)) {
member->setOrdinal(_context.getNextOrdinalAndIncrement());
- handleFile(*member);
+ undefAdded = handleFile(*member) || undefAdded;
}
});
+ return undefAdded;
}
void Resolver::handleSharedLibrary(const File &file) {
@@ -233,31 +229,66 @@ void Resolver::addAtoms(const std::vecto
doDefinedAtom(*newAtom);
}
+// Returns true if at least one of N previous files has created an
+// undefined symbol.
+bool Resolver::undefinesAdded(int n) {
+ for (size_t i = _fileIndex - n; i < _fileIndex; ++i)
+ if (_newUndefinesAdded[_files[i]])
+ return true;
+ return false;
+}
+
+ErrorOr<File &> Resolver::nextFile(bool &inGroup) {
+ if (size_t groupSize = _context.getInputGraph().getGroupSize()) {
+ // We are at the end of the current group. If one or more new
+ // undefined atom has been added in the last groupSize files, we
+ // reiterate over the files.
+ if (undefinesAdded(groupSize))
+ _fileIndex -= groupSize;
+ _context.getInputGraph().skipGroup();
+ return nextFile(inGroup);
+ }
+ if (_fileIndex < _files.size()) {
+ // We are still in the current group.
+ inGroup = true;
+ return *_files[_fileIndex++];
+ }
+ // We are not in a group. Get a new file.
+ ErrorOr<File &> file = _context.getInputGraph().getNextFile();
+ if (std::error_code ec = file.getError()) {
+ if (ec != InputGraphError::no_more_files)
+ llvm::errs() << "Error occurred in getNextFile: " << ec.message() << "\n";
+ return ec;
+ }
+ _files.push_back(&*file);
+ ++_fileIndex;
+ inGroup = false;
+ return *file;
+}
+
// Keep adding atoms until _context.getNextFile() returns an error. This
// function is where undefined atoms are resolved.
bool Resolver::resolveUndefines() {
ScopedTask task(getDefaultDomain(), "resolveUndefines");
for (;;) {
- ErrorOr<File &> file = _context.getInputGraph().getNextFile();
- std::error_code ec = file.getError();
- if (ec == InputGraphError::no_more_files)
- return true;
- if (!file) {
- llvm::errs() << "Error occurred in getNextFile: " << ec.message() << "\n";
- return false;
- }
-
+ bool inGroup = false;
+ bool undefAdded = false;
+ ErrorOr<File &> file = nextFile(inGroup);
+ if (std::error_code ec = file.getError())
+ return ec == InputGraphError::no_more_files;
switch (file->kind()) {
case File::kindObject:
+ if (inGroup)
+ break;
assert(!file->hasOrdinal());
file->setOrdinal(_context.getNextOrdinalAndIncrement());
- handleFile(*file);
+ undefAdded = handleFile(*file);
break;
case File::kindArchiveLibrary:
if (!file->hasOrdinal())
file->setOrdinal(_context.getNextOrdinalAndIncrement());
- handleArchiveFile(*file);
+ undefAdded = handleArchiveFile(*file);
break;
case File::kindSharedLibrary:
if (!file->hasOrdinal())
@@ -265,6 +296,7 @@ bool Resolver::resolveUndefines() {
handleSharedLibrary(*file);
break;
}
+ _newUndefinesAdded[&*file] = undefAdded;
}
}
Modified: lld/trunk/lib/Driver/DarwinInputGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinInputGraph.cpp?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/lib/Driver/DarwinInputGraph.cpp (original)
+++ lld/trunk/lib/Driver/DarwinInputGraph.cpp Tue Dec 9 18:33:00 2014
@@ -18,48 +18,6 @@
namespace lld {
-ErrorOr<File &> DarwinInputGraph::getNextFile() {
- // The darwin linker processes input files in two phases. The first phase
- // links in all object (.o) files in command line order. The second phase
- // links in libraries in command line order. If there are still UndefinedAtoms
- // the second phase is repeated until notifyProgress() is not called by
- // resolver.
- for (;;) {
- if (_currentInputElement) {
- for(;;) {
- ErrorOr<File &> next = _currentInputElement->getNextFile();
- if (next.getError())
- break;
- File *file = &next.get();
- bool fileIsLibrary = isa<SharedLibraryFile>(file) ||
- isa<ArchiveLibraryFile>(file);
- if (fileIsLibrary == _librariesPhase) {
- // Return library in library phase and object files in non-lib mode.
- return *file;
- }
- }
- }
-
- if (_nextElementIndex >= _inputArgs.size()) {
- // If no more elements, done unless we need to repeat library scan.
- if (_librariesPhase && !_repeatLibraries)
- return make_error_code(InputGraphError::no_more_files);
- // Clear iterations and only look for libraries.
- _librariesPhase = true;
- _repeatLibraries = false;
- _nextElementIndex = 0;
- for (auto &ie : _inputArgs) {
- ie->resetNextIndex();
- }
- }
- _currentInputElement = _inputArgs[_nextElementIndex++].get();
- }
-}
-
-void DarwinInputGraph::notifyProgress() {
- _repeatLibraries = true;
-}
-
/// \brief Parse the input file to lld::File.
std::error_code MachOFileNode::parse(const LinkingContext &ctx,
raw_ostream &diagnostics) {
Modified: lld/trunk/lib/Driver/DarwinLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdDriver.cpp?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/lib/Driver/DarwinLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/DarwinLdDriver.cpp Tue Dec 9 18:33:00 2014
@@ -83,7 +83,7 @@ static std::string canonicalizePath(Stri
}
}
-static void addFile(StringRef path, std::unique_ptr<DarwinInputGraph> &inputGraph,
+static void addFile(StringRef path, std::unique_ptr<InputGraph> &inputGraph,
MachOLinkingContext &ctx, bool loadWholeArchive,
bool upwardDylib) {
auto node = llvm::make_unique<MachOFileNode>(path, ctx);
@@ -185,7 +185,7 @@ static std::error_code parseOrderFile(St
// per line. The <dir> prefix is prepended to each partial path.
//
static std::error_code parseFileList(StringRef fileListPath,
- std::unique_ptr<DarwinInputGraph> &inputGraph,
+ std::unique_ptr<InputGraph> &inputGraph,
MachOLinkingContext &ctx, bool forceLoad,
raw_ostream &diagnostics) {
// If there is a comma, split off <dir>.
@@ -521,7 +521,7 @@ bool DarwinLdDriver::parse(int argc, con
}
}
- std::unique_ptr<DarwinInputGraph> inputGraph(new DarwinInputGraph());
+ std::unique_ptr<InputGraph> inputGraph(new InputGraph());
// Now construct the set of library search directories, following ld64's
// baroque set of accumulated hacks. Mostly, the algorithm constructs
Modified: lld/trunk/lib/Driver/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/Driver.cpp?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/lib/Driver/Driver.cpp (original)
+++ lld/trunk/lib/Driver/Driver.cpp Tue Dec 9 18:33:00 2014
@@ -62,9 +62,6 @@ bool Driver::link(LinkingContext &contex
if (std::error_code ec = ie->parse(context, stream)) {
if (FileNode *fileNode = dyn_cast<FileNode>(ie.get()))
stream << fileNode->errStr(ec) << "\n";
- else if (dyn_cast<Group>(ie.get()))
- // FIXME: We need a better diagnostics here
- stream << "Cannot parse group input element\n";
else
llvm_unreachable("Unknown type of input element");
fail = true;
@@ -83,21 +80,24 @@ bool Driver::link(LinkingContext &contex
if (fail)
return false;
- std::unique_ptr<SimpleFileNode> fileNode(
- new SimpleFileNode("Internal Files"));
-
InputGraph::FileVectorT internalFiles;
context.createInternalFiles(internalFiles);
-
- if (internalFiles.size())
- fileNode->addFiles(std::move(internalFiles));
+ for (auto i = internalFiles.rbegin(), e = internalFiles.rend(); i != e; ++i) {
+ context.getInputGraph().addInputElementFront(
+ llvm::make_unique<SimpleFileNode>("internal", std::move(*i)));
+ }
// Give target a chance to add files.
InputGraph::FileVectorT implicitFiles;
context.createImplicitFiles(implicitFiles);
- if (implicitFiles.size())
- fileNode->addFiles(std::move(implicitFiles));
- context.getInputGraph().addInputElementFront(std::move(fileNode));
+ for (auto i = implicitFiles.rbegin(), e = implicitFiles.rend(); i != e; ++i) {
+ context.getInputGraph().addInputElementFront(
+ llvm::make_unique<SimpleFileNode>("implicit", std::move(*i)));
+ }
+
+ // Give target a chance to sort the input files.
+ // Mach-O uses this chance to move all object files before library files.
+ context.maybeSortInputFiles();
// Do core linking.
ScopedTask resolveTask(getDefaultDomain(), "Resolve");
Modified: lld/trunk/lib/Driver/GnuLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/lib/Driver/GnuLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/GnuLdDriver.cpp Tue Dec 9 18:33:00 2014
@@ -295,7 +295,8 @@ bool GnuLdDriver::parse(int argc, const
}
std::unique_ptr<InputGraph> inputGraph(new InputGraph());
- std::stack<Group *> groupStack;
+ std::stack<int> groupStack;
+ int numfiles = 0;
ELFFileNode::Attributes attributes;
@@ -468,16 +469,21 @@ bool GnuLdDriver::parse(int argc, const
break;
}
- case OPT_start_group: {
- std::unique_ptr<Group> group(new Group());
- groupStack.push(group.get());
- inputGraph->addInputElement(std::move(group));
+ case OPT_start_group:
+ groupStack.push(numfiles);
break;
- }
- case OPT_end_group:
+ case OPT_end_group: {
+ if (groupStack.empty()) {
+ diagnostics << "stray --end-group\n";
+ return false;
+ }
+ int startGroupPos = groupStack.top();
+ inputGraph->addInputElement(
+ llvm::make_unique<GroupEnd>(numfiles - startGroupPos));
groupStack.pop();
break;
+ }
case OPT_z: {
StringRef extOpt = inputArg->getValue();
@@ -552,11 +558,8 @@ bool GnuLdDriver::parse(int argc, const
}
}
std::unique_ptr<InputElement> inputFile(inputNode);
- if (groupStack.empty()) {
- inputGraph->addInputElement(std::move(inputFile));
- } else {
- groupStack.top()->addFile(std::move(inputFile));
- }
+ ++numfiles;
+ inputGraph->addInputElement(std::move(inputFile));
break;
}
Modified: lld/trunk/lib/Driver/GnuLdInputGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdInputGraph.cpp?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/lib/Driver/GnuLdInputGraph.cpp (original)
+++ lld/trunk/lib/Driver/GnuLdInputGraph.cpp Tue Dec 9 18:33:00 2014
@@ -91,7 +91,7 @@ std::error_code ELFGNULdScript::parse(co
auto *group = dyn_cast<script::Group>(c);
if (!group)
continue;
- std::unique_ptr<Group> groupStart(new Group());
+ size_t numfiles = 0;
for (const script::Path &path : group->getPaths()) {
// TODO : Propagate Set WholeArchive/dashlPrefix
attributes.setAsNeeded(path._asNeeded);
@@ -100,9 +100,10 @@ std::error_code ELFGNULdScript::parse(co
_elfLinkingContext, _elfLinkingContext.allocateString(path._path),
attributes);
std::unique_ptr<InputElement> inputFile(inputNode);
- groupStart.get()->addFile(std::move(inputFile));
+ _expandElements.push_back(std::move(inputFile));
+ ++numfiles;
}
- _expandElements.push_back(std::move(groupStart));
+ _expandElements.push_back(llvm::make_unique<GroupEnd>(numfiles));
}
return std::error_code();
}
Modified: lld/trunk/lib/Driver/WinLinkDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/lib/Driver/WinLinkDriver.cpp (original)
+++ lld/trunk/lib/Driver/WinLinkDriver.cpp Tue Dec 9 18:33:00 2014
@@ -781,7 +781,7 @@ static bool hasLibrary(const PECOFFLinki
ErrorOr<StringRef> path = fileNode->getPath(ctx);
if (!path)
return false;
- for (std::unique_ptr<InputElement> &p : ctx.getLibraryGroup()->elements())
+ for (std::unique_ptr<InputElement> &p : ctx.getInputGraph().inputElements())
if (auto *f = dyn_cast<FileNode>(p.get()))
if (*path == *f->getPath(ctx))
return true;
@@ -1397,10 +1397,8 @@ bool WinLinkDriver::parse(int argc, cons
ctx.setEntryNode(entry.get());
ctx.getInputGraph().addInputElement(std::move(entry));
- // The container for all library files.
- std::unique_ptr<Group> group(new PECOFFGroup(ctx));
- ctx.setLibraryGroup(group.get());
- ctx.getInputGraph().addInputElement(std::move(group));
+ // Add a group-end marker.
+ ctx.getInputGraph().addInputElement(llvm::make_unique<GroupEnd>(0));
}
// Add the library files to the library group.
@@ -1409,7 +1407,7 @@ bool WinLinkDriver::parse(int argc, cons
if (isReadingDirectiveSection)
if (lib->parse(ctx, diag))
return false;
- ctx.getLibraryGroup()->addFile(std::move(lib));
+ ctx.addLibraryFile(std::move(lib));
}
}
Modified: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Tue Dec 9 18:33:00 2014
@@ -22,6 +22,7 @@
#include "llvm/ADT/Triple.h"
#include "llvm/Config/config.h"
#include "llvm/Support/Errc.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/Host.h"
#include "llvm/Support/MachO.h"
#include "llvm/Support/Path.h"
@@ -923,4 +924,35 @@ bool MachOLinkingContext::customAtomOrde
return true;
}
+static File *getFirstFile(const std::unique_ptr<InputElement> &elem) {
+ FileNode *e = dyn_cast<FileNode>(const_cast<InputElement *>(elem.get()));
+ if (!e || e->files().empty())
+ return nullptr;
+ return e->files()[0].get();
+}
+
+static bool isLibrary(const std::unique_ptr<InputElement> &elem) {
+ File *f = getFirstFile(elem);
+ return f && (isa<SharedLibraryFile>(f) || isa<ArchiveLibraryFile>(f));
+}
+
+// The darwin linker processes input files in two phases. The first phase
+// links in all object (.o) files in command line order. The second phase
+// links in libraries in command line order.
+// In this function we reorder the input files so that all the object files
+// comes before any library file. We also make a group for the library files
+// so that the Resolver will reiterate over the libraries as long as we find
+// new undefines from libraries.
+void MachOLinkingContext::maybeSortInputFiles() {
+ std::vector<std::unique_ptr<InputElement>> &elements
+ = getInputGraph().inputElements();
+ std::stable_sort(elements.begin(), elements.end(),
+ [](const std::unique_ptr<InputElement> &a,
+ const std::unique_ptr<InputElement> &b) {
+ return !isLibrary(a) && isLibrary(b);
+ });
+ size_t numLibs = std::count_if(elements.begin(), elements.end(), isLibrary);
+ elements.push_back(llvm::make_unique<GroupEnd>(numLibs));
+}
+
} // end namespace lld
Modified: lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp Tue Dec 9 18:33:00 2014
@@ -87,6 +87,23 @@ std::unique_ptr<File> PECOFFLinkingConte
"<command line option /include>");
}
+void PECOFFLinkingContext::addLibraryFile(std::unique_ptr<FileNode> file) {
+ GroupEnd *currentGroupEnd;
+ int pos = -1;
+ std::vector<std::unique_ptr<InputElement>> &elements
+ = getInputGraph().inputElements();
+ for (int i = 0, e = elements.size(); i < e; ++i) {
+ if ((currentGroupEnd = dyn_cast<GroupEnd>(elements[i].get()))) {
+ pos = i;
+ break;
+ }
+ }
+ assert(pos >= 0);
+ elements.insert(elements.begin() + pos, std::move(file));
+ elements[pos + 1] = llvm::make_unique<GroupEnd>(
+ currentGroupEnd->getSize() + 1);
+}
+
bool PECOFFLinkingContext::createImplicitFiles(
std::vector<std::unique_ptr<File>> &) {
// Create a file for __ImageBase.
@@ -109,7 +126,7 @@ bool PECOFFLinkingContext::createImplici
auto exportNode = llvm::make_unique<SimpleFileNode>("<export>");
exportNode->appendInputFile(
llvm::make_unique<pecoff::ExportedSymbolRenameFile>(*this, syms));
- getLibraryGroup()->addFile(std::move(exportNode));
+ addLibraryFile(std::move(exportNode));
// Create a file for the entry point function.
getEntryNode()->appendInputFile(
Modified: lld/trunk/unittests/DriverTests/DriverTest.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/DriverTest.h?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/DriverTest.h (original)
+++ lld/trunk/unittests/DriverTests/DriverTest.h Tue Dec 9 18:33:00 2014
@@ -37,18 +37,6 @@ protected:
llvm_unreachable("not handling other types of input files");
}
- // Convenience method for getting i'th input files name.
- std::string inputFile(int index1, int index2) {
- Group *group = dyn_cast<Group>(
- linkingContext()->getInputGraph().inputElements()[index1].get());
- if (!group)
- llvm_unreachable("not handling other types of input files");
- FileNode *file = dyn_cast<FileNode>(group->elements()[index2].get());
- if (!file)
- llvm_unreachable("not handling other types of input files");
- return *file->getPath(*linkingContext());
- }
-
// For unit tests to call driver with various command lines.
bool parse(const char *args, ...) {
// Construct command line options from varargs.
Modified: lld/trunk/unittests/DriverTests/InputGraphTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/InputGraphTest.cpp?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/InputGraphTest.cpp (original)
+++ lld/trunk/unittests/DriverTests/InputGraphTest.cpp Tue Dec 9 18:33:00 2014
@@ -77,7 +77,7 @@ protected:
} // end anonymous namespace
-static std::unique_ptr<TestFileNode> createFile1(StringRef name) {
+static std::unique_ptr<TestFileNode> createFile(StringRef name) {
std::vector<std::unique_ptr<File>> files;
files.push_back(std::unique_ptr<SimpleFile>(new SimpleFile(name)));
std::unique_ptr<TestFileNode> file(new TestFileNode("filenode"));
@@ -85,109 +85,30 @@ static std::unique_ptr<TestFileNode> cre
return file;
}
-static std::unique_ptr<TestFileNode> createFile2(StringRef name1,
- StringRef name2) {
- std::vector<std::unique_ptr<File>> files;
- files.push_back(std::unique_ptr<SimpleFile>(new SimpleFile(name1)));
- files.push_back(std::unique_ptr<SimpleFile>(new SimpleFile(name2)));
- std::unique_ptr<TestFileNode> file(new TestFileNode("filenode"));
- file->addFiles(std::move(files));
- return file;
-}
-
TEST_F(InputGraphTest, Empty) {
expectEnd();
}
TEST_F(InputGraphTest, File) {
- _graph->addInputElement(createFile1("file1"));
- EXPECT_EQ("file1", getNext());
- expectEnd();
-}
-
-TEST_F(InputGraphTest, Files) {
- _graph->addInputElement(createFile2("file1", "file2"));
- EXPECT_EQ("file1", getNext());
- EXPECT_EQ("file2", getNext());
- expectEnd();
-}
-
-TEST_F(InputGraphTest, Group) {
- _graph->addInputElement(createFile2("file1", "file2"));
-
- std::unique_ptr<Group> group(new Group());
- group->addFile(createFile2("file3", "file4"));
- group->addFile(createFile1("file5"));
- group->addFile(createFile1("file6"));
- _graph->addInputElement(std::move(group));
-
+ _graph->addInputElement(createFile("file1"));
EXPECT_EQ("file1", getNext());
- EXPECT_EQ("file2", getNext());
- EXPECT_EQ("file3", getNext());
- EXPECT_EQ("file4", getNext());
- EXPECT_EQ("file5", getNext());
- EXPECT_EQ("file6", getNext());
- expectEnd();
-}
-
-// Iterate through the group
-TEST_F(InputGraphTest, GroupIteration) {
- _graph->addInputElement(createFile2("file1", "file2"));
-
- std::unique_ptr<Group> group(new Group());
- group->addFile(createFile2("file3", "file4"));
- group->addFile(createFile1("file5"));
- group->addFile(createFile1("file6"));
- _graph->addInputElement(std::move(group));
-
- EXPECT_EQ("file1", getNext());
- EXPECT_EQ("file2", getNext());
-
- EXPECT_EQ("file3", getNext());
- EXPECT_EQ("file4", getNext());
- EXPECT_EQ("file5", getNext());
- EXPECT_EQ("file6", getNext());
- _graph->notifyProgress();
-
- EXPECT_EQ("file3", getNext());
- EXPECT_EQ("file4", getNext());
- _graph->notifyProgress();
- EXPECT_EQ("file5", getNext());
- EXPECT_EQ("file6", getNext());
-
- EXPECT_EQ("file3", getNext());
- EXPECT_EQ("file4", getNext());
- EXPECT_EQ("file5", getNext());
- EXPECT_EQ("file6", getNext());
expectEnd();
}
// Node expansion tests
TEST_F(InputGraphTest, Normalize) {
- _graph->addInputElement(createFile2("file1", "file2"));
+ _graph->addInputElement(createFile("file1"));
std::unique_ptr<TestExpandFileNode> expandFile(
new TestExpandFileNode("node"));
- expandFile->addElement(createFile1("file3"));
- expandFile->addElement(createFile1("file4"));
+ expandFile->addElement(createFile("file2"));
+ expandFile->addElement(createFile("file3"));
_graph->addInputElement(std::move(expandFile));
-
- std::unique_ptr<Group> group(new Group());
- std::unique_ptr<TestExpandFileNode> expandFile2(
- new TestExpandFileNode("node"));
- expandFile2->addElement(createFile1("file5"));
- group->addFile(std::move(expandFile2));
- _graph->addInputElement(std::move(group));
-
- _graph->addInputElement(createFile1("file6"));
_graph->normalize();
EXPECT_EQ("file1", getNext());
EXPECT_EQ("file2", getNext());
EXPECT_EQ("file3", getNext());
- EXPECT_EQ("file4", getNext());
- EXPECT_EQ("file5", getNext());
- EXPECT_EQ("file6", getNext());
expectEnd();
}
@@ -195,8 +116,8 @@ TEST_F(InputGraphTest, Observer) {
std::vector<std::string> files;
_graph->registerObserver([&](File *file) { files.push_back(file->path()); });
- _graph->addInputElement(createFile1("file1"));
- _graph->addInputElement(createFile1("file2"));
+ _graph->addInputElement(createFile("file1"));
+ _graph->addInputElement(createFile("file2"));
EXPECT_EQ("file1", getNext());
EXPECT_EQ("file2", getNext());
expectEnd();
Modified: lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp?rev=223867&r1=223866&r2=223867&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp (original)
+++ lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp Tue Dec 9 18:33:00 2014
@@ -137,11 +137,11 @@ TEST_F(WinLinkParserTest, Libpath) {
TEST_F(WinLinkParserTest, InputOrder) {
EXPECT_TRUE(parse("link.exe", "a.lib", "b.obj", "c.obj", "a.lib", "d.obj",
nullptr));
- EXPECT_EQ(5, inputFileCount());
+ EXPECT_EQ(6, inputFileCount());
EXPECT_EQ("b.obj", inputFile(0));
EXPECT_EQ("c.obj", inputFile(1));
EXPECT_EQ("d.obj", inputFile(2));
- EXPECT_EQ("a.lib", inputFile(4, 0));
+ EXPECT_EQ("a.lib", inputFile(4));
}
//
@@ -393,36 +393,36 @@ TEST_F(WinLinkParserTest, SectionMultipl
TEST_F(WinLinkParserTest, DefaultLib) {
EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
"/defaultlib:kernel32", "a.obj", nullptr));
- EXPECT_EQ(3, inputFileCount());
+ EXPECT_EQ(5, inputFileCount());
EXPECT_EQ("a.obj", inputFile(0));
- EXPECT_EQ("user32.lib", inputFile(2, 0));
- EXPECT_EQ("kernel32.lib", inputFile(2, 1));
+ EXPECT_EQ("user32.lib", inputFile(2));
+ EXPECT_EQ("kernel32.lib", inputFile(3));
}
TEST_F(WinLinkParserTest, DefaultLibDuplicates) {
EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
"/defaultlib:user32.lib", "a.obj", nullptr));
- EXPECT_EQ(3, inputFileCount());
+ EXPECT_EQ(4, inputFileCount());
EXPECT_EQ("a.obj", inputFile(0));
- EXPECT_EQ("user32.lib", inputFile(2, 0));
+ EXPECT_EQ("user32.lib", inputFile(2));
}
TEST_F(WinLinkParserTest, NoDefaultLib) {
EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
"/defaultlib:kernel32", "/nodefaultlib:user32.lib", "a.obj",
nullptr));
- EXPECT_EQ(3, inputFileCount());
+ EXPECT_EQ(4, inputFileCount());
EXPECT_EQ("a.obj", inputFile(0));
- EXPECT_EQ("kernel32.lib", inputFile(2, 0));
+ EXPECT_EQ("kernel32.lib", inputFile(2));
}
TEST_F(WinLinkParserTest, NoDefaultLibCase) {
EXPECT_TRUE(parse("link.exe", "/defaultlib:user32",
"/defaultlib:kernel32", "/nodefaultlib:USER32.LIB", "a.obj",
nullptr));
- EXPECT_EQ(3, inputFileCount());
+ EXPECT_EQ(4, inputFileCount());
EXPECT_EQ("a.obj", inputFile(0));
- EXPECT_EQ("kernel32.lib", inputFile(2, 0));
+ EXPECT_EQ("kernel32.lib", inputFile(2));
}
TEST_F(WinLinkParserTest, NoDefaultLibAll) {
@@ -436,9 +436,9 @@ TEST_F(WinLinkParserTest, DisallowLib) {
EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
"/defaultlib:kernel32", "/disallowlib:user32.lib", "a.obj",
nullptr));
- EXPECT_EQ(3, inputFileCount());
+ EXPECT_EQ(4, inputFileCount());
EXPECT_EQ("a.obj", inputFile(0));
- EXPECT_EQ("kernel32.lib", inputFile(2, 0));
+ EXPECT_EQ("kernel32.lib", inputFile(2));
}
//
More information about the llvm-commits
mailing list