[lld] r223330 - Rewrite InputGraph's Group
Rui Ueyama
ruiu at google.com
Tue Dec 9 14:49:46 PST 2014
Thanks! Confirmed that the patch fixes the issue.
On Wed, Dec 10, 2014 at 1:29 AM, Jean-Daniel Dupas <dev at xenonium.com> wrote:
> I think I got it. There is a bug in Section address computation that
> result in overlapping Section (Exec format error).
>
> I attached a patch that should fix this issue. The 'addr' counter didn’t
> take alignement into account.
>
>
>
> Le 9 déc. 2014 à 01:43, Rui Ueyama <ruiu at google.com> a écrit :
>
> I'm still getting the same error even though I removed -dead_strip from
> the command line. Hmm, what's wrong...? Does it work for you?
>
> On Mon, Dec 8, 2014 at 10:33 PM, Jean-Daniel Dupas <dev at xenonium.com>
> wrote:
>
>> AFAIK, this is a bug that occurs when dead_strip is enabled. Try to
>> remove the -dead_strip argument and try again.
>>
>>
>> Le 8 déc. 2014 à 08:15, Rui Ueyama <ruiu at google.com> a écrit :
>>
>> I'm having trouble to link LLD using LLD on Darwin. Could you help me
>> figure out what's wrong?
>>
>> LLD aborts with the following error message
>>
>> warning: ignoring unknown argument: -search_paths_first
>> warning: ignoring unknown argument: -headerpad_max_install_names
>> Failed to write file 'bin/lld': Exec format error
>>
>> when I try to link LLD with the following command (../ld is stage 1 LLD
>> executable)
>>
>> $ ../ld "-demangle" "-dynamic" "-arch" "x86_64" "-macosx_version_min"
>> "10.10.0" "-o" bin/lld "-search_paths_first" "-headerpad_max_install_names"
>> "-dead_strip" "tools/lld/tools/lld/CMakeFiles/lld.dir/lld.cpp.o"
>> "lib/liblldDriver.a" "lib/liblldPECOFF.a" "lib/liblldDriver.a"
>> "lib/liblldPECOFF.a" "lib/liblldConfig.a" "lib/liblldMachO.a"
>> "lib/liblldELF.a" "lib/liblldHexagonELFTarget.a"
>> "lib/liblldMipsELFTarget.a" "lib/liblldPPCELFTarget.a"
>> "lib/liblldX86ELFTarget.a" "lib/liblldX86_64ELFTarget.a"
>> "lib/liblldAArch64ELFTarget.a" "lib/libLLVMOption.a" "lib/liblldPasses.a"
>> "lib/liblldCore.a" "lib/liblldNative.a" "lib/liblldReaderWriter.a"
>> "lib/liblldYAML.a" "lib/liblldPasses.a" "lib/liblldCore.a"
>> "lib/liblldNative.a" "lib/liblldReaderWriter.a" "lib/liblldYAML.a"
>> "lib/libLLVMObject.a" "lib/libLLVMBitReader.a" "lib/libLLVMCore.a"
>> "lib/libLLVMMCParser.a" "lib/libLLVMMC.a" "lib/libLLVMSupport.a" "-lcurses"
>> "-lpthread" "-lz" "-lm" "-lc++" "-lSystem"
>> "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/6.0/lib/darwin/libclang_rt.osx.a"
>>
>>
>> I got this command line by passing -### to Clang. I'm using the latest
>> version of Xcode. LLVM/LLD is at head with no local patch (including this
>> one).
>>
>> Nick said that the LLD is now able to self-host it on Darwin. Is it still
>> working?
>>
>> On Fri, Dec 5, 2014 at 12:11 AM, Jean-Daniel Dupas <dev at xenonium.com>
>> wrote:
>>
>>> I think that change broke the Darwin linker.
>>>
>>> When trying to link executable using lld, I know have a lot of
>>> ‘undefined symbol’ error for symbols provided by (static) libraries.
>>>
>>> > Le 4 déc. 2014 à 02:09, Rui Ueyama <ruiu at google.com> a écrit :
>>> >
>>> > Author: ruiu
>>> > Date: Wed Dec 3 19:09:06 2014
>>> > New Revision: 223330
>>> >
>>> > URL: http://llvm.org/viewvc/llvm-project?rev=223330&view=rev
>>> > Log:
>>> > Rewrite InputGraph's Group
>>> >
>>> > The aim of this patch is to reduce the excessive abstraction from
>>> > the InputGraph. We found that even a simple thing, such as sorting
>>> > input files (Mach-O) or adding a new file to the input file list
>>> > (PE/COFF), is nearly impossible with the InputGraph abstraction,
>>> > because it hides too much information behind it. As a result,
>>> > we invented complex interactions between components (e.g.
>>> > notifyProgress() mechanism) and tricky code to work around that
>>> > limitation. There were many occasions that we needed to write
>>> > awkward code.
>>> >
>>> > This patch is a first step to make it cleaner. As a first step,
>>> > this removes Group class from the InputGraph. The grouping feature
>>> > is now directly handled by the Resolver. notifyProgress is removed
>>> > since we no longer need that. I could have cleaned it up even more,
>>> > but in order to keep the patch minimum, I focused on Group.
>>> >
>>> > SimpleFileNode class, a container of File objects, is now limited
>>> > to have only one File. We shold have done this earlier.
>>> > We used to allow putting multiple File objects to FileNode.
>>> > Although SimpleFileNode usually has only one file, the Driver class
>>> > actually used that capability. I modified the Driver class a bit,
>>> > so that one FileNode is created for each input File.
>>> >
>>> > We should now probably remove SimpleFileNode and directly store
>>> > File objects to the InputGraph in some way, because a container
>>> > that can contain only one object is useless. This is a TODO.
>>> >
>>> > Mach-O input files are now sorted before they are passe to the
>>> > Resolver. DarwinInputGraph class is no longer needed, so removed.
>>> >
>>> > PECOFF still has hacky code to add a new file to the input file list.
>>> > This will be cleaned up in another patch.
>>> >
>>> > 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/include/lld/Core/InputGraph.h (original)
>>> > +++ lld/trunk/include/lld/Core/InputGraph.h Wed Dec 3 19:09:06 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/include/lld/Core/LinkingContext.h (original)
>>> > +++ lld/trunk/include/lld/Core/LinkingContext.h Wed Dec 3 19:09:06
>>> 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/include/lld/Core/Resolver.h (original)
>>> > +++ lld/trunk/include/lld/Core/Resolver.h Wed Dec 3 19:09:06 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/include/lld/Driver/DarwinInputGraph.h (original)
>>> > +++ lld/trunk/include/lld/Driver/DarwinInputGraph.h Wed Dec 3
>>> 19:09:06 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/include/lld/Driver/WinLinkInputGraph.h (original)
>>> > +++ lld/trunk/include/lld/Driver/WinLinkInputGraph.h Wed Dec 3
>>> 19:09:06 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h (original)
>>> > +++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h Wed Dec
>>> 3 19:09:06 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h
>>> (original)
>>> > +++ lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h Wed Dec
>>> 3 19:09:06 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:
>>> > @@ -315,8 +314,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;
>>> > @@ -438,9 +436,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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/lib/Core/InputGraph.cpp (original)
>>> > +++ lld/trunk/lib/Core/InputGraph.cpp Wed Dec 3 19:09:06 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/lib/Core/Resolver.cpp (original)
>>> > +++ lld/trunk/lib/Core/Resolver.cpp Wed Dec 3 19:09:06 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 = undefAdded || handleFile(*member);
>>> > }
>>> > });
>>> > + 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/lib/Driver/DarwinInputGraph.cpp (original)
>>> > +++ lld/trunk/lib/Driver/DarwinInputGraph.cpp Wed Dec 3 19:09:06 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/lib/Driver/DarwinLdDriver.cpp (original)
>>> > +++ lld/trunk/lib/Driver/DarwinLdDriver.cpp Wed Dec 3 19:09:06 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/lib/Driver/Driver.cpp (original)
>>> > +++ lld/trunk/lib/Driver/Driver.cpp Wed Dec 3 19:09:06 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/lib/Driver/GnuLdDriver.cpp (original)
>>> > +++ lld/trunk/lib/Driver/GnuLdDriver.cpp Wed Dec 3 19:09:06 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/lib/Driver/GnuLdInputGraph.cpp (original)
>>> > +++ lld/trunk/lib/Driver/GnuLdInputGraph.cpp Wed Dec 3 19:09:06 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/lib/Driver/WinLinkDriver.cpp (original)
>>> > +++ lld/trunk/lib/Driver/WinLinkDriver.cpp Wed Dec 3 19:09:06 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)
>>> > +++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Wed Dec
>>> 3 19:09:06 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
>>> (original)
>>> > +++ lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp Wed
>>> Dec 3 19:09:06 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/unittests/DriverTests/DriverTest.h (original)
>>> > +++ lld/trunk/unittests/DriverTests/DriverTest.h Wed Dec 3 19:09:06
>>> 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/unittests/DriverTests/InputGraphTest.cpp (original)
>>> > +++ lld/trunk/unittests/DriverTests/InputGraphTest.cpp Wed Dec 3
>>> 19:09:06 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=223330&r1=223329&r2=223330&view=diff
>>> >
>>> ==============================================================================
>>> > --- lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp (original)
>>> > +++ lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp Wed Dec 3
>>> 19:09:06 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));
>>> > }
>>> >
>>> > //
>>> >
>>> >
>>> > _______________________________________________
>>> > llvm-commits mailing list
>>> > llvm-commits at cs.uiuc.edu
>>> > http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>>
>>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at cs.uiuc.edu
>> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>>
>>
>>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141210/61ac4c27/attachment.html>
More information about the llvm-commits
mailing list