<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Fri, Dec 5, 2014 at 9:13 AM, Shankar Easwaran <span dir="ltr"><<a href="mailto:shankare@codeaurora.org" target="_blank">shankare@codeaurora.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">Hi Rui,<br>
<br>
They key idea was to flatten the graph but also use tags to know about some control flags, that change linker operation(group begins / ends (or) what input files are part of as-needed).<br>
<br>
The LinkingContext would need to know about what happens in the resolver per input element (that would contain a tag and a file locator).<br>
<br>
These two requirements are really needed for the linker Gnu flavor for its operation and the infrastructure needs to be scalable as well.<br></blockquote><div><br></div><div>Yes, these are obvious needs. I have of course no intention to remove --as-needed from the linker.</div><div><br></div><div>As you might have noticed, notifyProgress is not the only way that we can use for the core linker to the LinkingContext. It, for example, doesn't have to be real-time. Instead of telling the progress for each file, we could accumulate that information and pass it to the next pass.</div><div><br></div><div>The breakage caused by the last commit was an accident -- it should have caught by a test but it wasn't. I'm trying to fix it by self-hosting LLD on Linux and Mac.</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
Shankar Easwaran<span class=""><br>
<br>
On 12/4/2014 3:51 PM, Rui Ueyama wrote:<br>
</span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span class="">
Shanker,<br>
<br>
I don't think this patch is that different from what you proposed. The key<br>
idea is as I understand to flatten the Graph to make it easy to handle.<br>
This patch is in aligned with that. This is an incremental patch towards<br>
that direction.<br>
<br>
On Thu, Dec 4, 2014 at 10:54 AM, Shankar Easwaran <<a href="mailto:shankare@codeaurora.org" target="_blank">shankare@codeaurora.org</a>><br>
wrote:<br>
<br>
</span><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span class="">
Hi Rui,<br>
<br>
I try to build clang with lld by just taking the arguments directly from<br>
the usual clang build, without any change.<br>
<br>
You should be able to reproduce it locally, but anyways here are the<br>
arguments to build clang with lld with the Gnu flavor :-<br>
<br></span>
*lld -flavor gnu* -z relro --hash-style=gnu --build-id --eh-frame-hdr -m<div><div class="h5"><br>
elf_x86_64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 -o bin/clang-3.6<br>
/usr/bin/../lib/gcc/x86_64-<u></u>linux-gnu/4.9/../../../x86_64-<u></u>linux-gnu/crt1.o<br>
/usr/bin/../lib/gcc/x86_64-<u></u>linux-gnu/4.9/../../../x86_64-<u></u>linux-gnu/crti.o<br>
/usr/bin/../lib/gcc/x86_64-<u></u>linux-gnu/4.9/crtbegin.o<br>
-L/usr/bin/../lib/gcc/x86_64-<u></u>linux-gnu/4.9<br>
-L/usr/bin/../lib/gcc/x86_64-<u></u>linux-gnu/4.9/../../../x86_64-<u></u>linux-gnu<br>
-L/lib/x86_64-linux-gnu -L/lib/../lib64 -L/usr/lib/x86_64-linux-gnu<br>
-L/usr/bin/../lib/gcc/x86_64-<u></u>linux-gnu/4.9/../../..<br>
-L/usr/lib/llvm-3.5/bin/../lib -L/lib -L/usr/lib -allow-shlib-undefined<br>
--export-dynamic -O3<br>
tools/clang/tools/driver/<u></u>CMakeFiles/clang.dir/driver.<u></u>cpp.o<br>
tools/clang/tools/driver/<u></u>CMakeFiles/clang.dir/cc1_main.<u></u>cpp.o<br>
tools/clang/tools/driver/<u></u>CMakeFiles/clang.dir/cc1as_<u></u>main.cpp.o<br>
lib/libLLVMAArch64CodeGen.a lib/libLLVMAArch64AsmPrinter.a<br>
lib/libLLVMAArch64AsmParser.a lib/libLLVMAArch64Desc.a<br>
lib/libLLVMAArch64Info.a lib/<u></u>libLLVMAArch64Disassembler.a<br>
lib/libLLVMARMCodeGen.a lib/libLLVMARMAsmPrinter.a<br>
lib/libLLVMARMAsmParser.a lib/libLLVMARMDesc.a lib/libLLVMARMInfo.a<br>
lib/libLLVMARMDisassembler.a lib/libLLVMCppBackendCodeGen.a<br>
lib/libLLVMCppBackendInfo.a lib/libLLVMHexagonCodeGen.a<br>
lib/libLLVMHexagonDesc.a lib/libLLVMHexagonInfo.a<br>
lib/<u></u>libLLVMHexagonDisassembler.a lib/libLLVMMipsCodeGen.a<br>
lib/libLLVMMipsAsmPrinter.a lib/libLLVMMipsAsmParser.a<br>
lib/libLLVMMipsDesc.a lib/libLLVMMipsInfo.a lib/libLLVMMipsDisassembler.a<br>
lib/libLLVMMSP430CodeGen.a lib/libLLVMMSP430AsmPrinter.a<br>
lib/libLLVMMSP430Desc.a lib/libLLVMMSP430Info.a lib/libLLVMNVPTXCodeGen.a<br>
lib/libLLVMNVPTXAsmPrinter.a lib/libLLVMNVPTXDesc.a lib/libLLVMNVPTXInfo.a<br>
lib/libLLVMPowerPCCodeGen.a lib/libLLVMPowerPCAsmPrinter.a<br>
lib/libLLVMPowerPCAsmParser.a lib/libLLVMPowerPCDesc.a<br>
lib/libLLVMPowerPCInfo.a lib/<u></u>libLLVMPowerPCDisassembler.a<br>
lib/libLLVMR600CodeGen.a lib/libLLVMR600AsmPrinter.a<br>
lib/libLLVMR600AsmParser.a lib/libLLVMR600Desc.a lib/libLLVMR600Info.a<br>
lib/libLLVMSparcCodeGen.a lib/libLLVMSparcAsmPrinter.a<br>
lib/libLLVMSparcAsmParser.a lib/libLLVMSparcDesc.a lib/libLLVMSparcInfo.a<br>
lib/libLLVMSparcDisassembler.a lib/libLLVMSystemZCodeGen.a<br>
lib/libLLVMSystemZAsmPrinter.a lib/libLLVMSystemZAsmParser.a<br>
lib/libLLVMSystemZDesc.a lib/libLLVMSystemZInfo.a<br>
lib/<u></u>libLLVMSystemZDisassembler.a lib/libLLVMX86CodeGen.a<br>
lib/libLLVMX86AsmPrinter.a lib/libLLVMX86AsmParser.a lib/libLLVMX86Desc.a<br>
lib/libLLVMX86Info.a lib/libLLVMX86Disassembler.a lib/libLLVMXCoreCodeGen.a<br>
lib/libLLVMXCoreAsmPrinter.a lib/libLLVMXCoreDesc.a lib/libLLVMXCoreInfo.a<br>
lib/libLLVMXCoreDisassembler.a lib/libLLVMAnalysis.a lib/libLLVMCodeGen.a<br>
lib/libLLVMCore.a lib/libLLVMipa.a lib/libLLVMipo.a<br>
lib/libLLVMInstCombine.a lib/libLLVMInstrumentation.a lib/libLLVMMC.a<br>
lib/libLLVMMCParser.a lib/libLLVMObjCARCOpts.a lib/libLLVMOption.a<br>
lib/libLLVMScalarOpts.a lib/libLLVMSupport.a lib/libLLVMTransformUtils.a<br>
lib/libLLVMVectorize.a lib/libclangBasic.a lib/libclangDriver.a<br>
lib/libclangFrontend.a lib/libclangFrontendTool.a<br>
lib/libLLVMAArch64AsmPrinter.a lib/libLLVMAArch64Info.a<br>
lib/libLLVMAArch64Utils.a lib/libLLVMARMDesc.a lib/libLLVMARMAsmPrinter.a<br>
lib/libLLVMARMInfo.a lib/libLLVMHexagonDesc.a lib/libLLVMHexagonInfo.a<br>
lib/libLLVMMipsAsmPrinter.a lib/libLLVMMipsInfo.a<br>
lib/libLLVMMSP430AsmPrinter.a lib/libLLVMNVPTXAsmPrinter.a<br>
lib/libLLVMPowerPCAsmPrinter.a lib/libLLVMPowerPCInfo.a<br>
lib/libLLVMR600AsmPrinter.a lib/libLLVMSparcAsmPrinter.a<br>
lib/libLLVMSparcInfo.a lib/libLLVMSystemZDesc.a<br>
lib/libLLVMSystemZAsmPrinter.a lib/libLLVMSystemZInfo.a<br>
lib/libLLVMX86CodeGen.a lib/libLLVMX86Desc.a lib/libLLVMX86AsmPrinter.a<br>
lib/libLLVMX86Utils.a lib/libLLVMX86Info.a lib/libLLVMXCoreAsmPrinter.a<br>
lib/libLLVMAsmPrinter.a lib/libLLVMSelectionDAG.a lib/libLLVMCodeGen.a<br>
lib/libLLVMXCoreInfo.a lib/libLLVMMCDisassembler.a lib/libclangCodeGen.a<br>
lib/libLLVMipo.a lib/libLLVMVectorize.a lib/libLLVMInstrumentation.a<br>
lib/libLLVMObjCARCOpts.a lib/libLLVMScalarOpts.a lib/libLLVMInstCombine.a<br>
lib/libLLVMProfileData.a lib/libLLVMObject.a lib/libLLVMBitWriter.a<br>
lib/libLLVMIRReader.a lib/libLLVMAsmParser.a lib/libLLVMLinker.a<br>
lib/libLLVMTransformUtils.a lib/libLLVMipa.a lib/libLLVMAnalysis.a<br>
lib/libLLVMTarget.a lib/libclangRewriteFrontend.a lib/libclangARCMigrate.a<br>
lib/<u></u>libclangStaticAnalyzerFrontend<u></u>.a lib/libclangFrontend.a<br>
lib/libclangDriver.a lib/libLLVMOption.a lib/libclangParse.a<br>
lib/libLLVMMCParser.a lib/libclangSerialization.a lib/libclangSema.a<br>
lib/libclangEdit.a lib/libLLVMBitReader.a<br>
lib/<u></u>libclangStaticAnalyzerCheckers<u></u>.a lib/<u></u>libclangStaticAnalyzerCore.a<br>
lib/libclangAnalysis.a lib/libclangAST.a lib/libclangRewrite.a<br>
lib/libclangLex.a lib/libclangBasic.a lib/libLLVMCore.a lib/libLLVMMC.a<br>
lib/libLLVMSupport.a -lrt -ldl -ltinfo -latomic -lpthread -lz -lm -rpath<br>
"\$ORIGIN/../lib" -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc<br>
/usr/bin/../lib/gcc/x86_64-<u></u>linux-gnu/4.9/crtend.o<br>
/usr/bin/../lib/gcc/x86_64-<u></u>linux-gnu/4.9/../../../x86_64-<u></u>linux-gnu/crtn.o<br>
<br>
Shankar Easwaran<br>
<br>
On 12/4/2014 12:26 PM, Rui Ueyama wrote:<br>
<br>
Let me roll this back first.<br>
<br>
Jean-Deniel and Shankar, please send me code so that I can reproduce that<br>
issue locally (and I will add the tests).<br>
<br></div></div>
On Thu, Dec 4, 2014 at 9:34 AM, Shankar Easwaran <<a href="mailto:shankare@codeaurora.org" target="_blank">shankare@codeaurora.org</a>> <<a href="mailto:shankare@codeaurora.org" target="_blank">shankare@codeaurora.org</a>><div><div class="h5"><br>
wrote:<br>
<br>
<br>
Hi Ruiu,<br>
<br>
Sorry I missed this review completely.<br>
<br>
We have taken a lot of effort to be able to build clang with lld, and this<br>
change prevents building clang with lld anymore as it fails with unresolved<br>
symbols. Please revert this change.<br>
<br>
*There are two things missing for modeling the Gnu flavor with this model<br>
as part of this change as well when I reviewed :-*<br>
<br>
a) The ELF writer needs to dump the way the linker resolved with<br>
start-group/end-group information.<br>
<br>
b) This model is also difficult to model --as-needed, --no-as-needed. The<br>
shared libraries in the list need to be added, only if the shared libraries<br>
resolved any symbol.<br>
For the above, the resolver has to notify the LinkingContext about how<br>
symbols were resolved for this functionality.<br>
<br>
Finally I would think we thoroughly review the the proposal that<br>
myself/Bigcheese talked about in the developers conference.<br>
<br>
The linkingcontext will be completely responsible for managing the input<br>
graph, which will just be a vector of InputElements that contain a tag in<br>
addition to the FileLocator.<br>
<br>
<br>
<a href="http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20141027/242287.html" target="_blank">http://lists.cs.uiuc.edu/<u></u>pipermail/llvm-commits/Week-<u></u>of-Mon-20141027/242287.html</a><br>
<br>
Shankar Easwaran<br>
<br>
<br>
On 12/3/2014 7:09 PM, Rui Ueyama wrote:<br>
<br>
Author: ruiu<br>
Date: Wed Dec 3 19:09:06 2014<br>
New Revision: 223330<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=223330&view=rev" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project?rev=223330&view=rev</a><br>
Log:<br>
Rewrite InputGraph's Group<br>
<br>
The aim of this patch is to reduce the excessive abstraction from<br>
the InputGraph. We found that even a simple thing, such as sorting<br>
input files (Mach-O) or adding a new file to the input file list<br>
(PE/COFF), is nearly impossible with the InputGraph abstraction,<br>
because it hides too much information behind it. As a result,<br>
we invented complex interactions between components (e.g.<br>
notifyProgress() mechanism) and tricky code to work around that<br>
limitation. There were many occasions that we needed to write<br>
awkward code.<br>
<br>
This patch is a first step to make it cleaner. As a first step,<br>
this removes Group class from the InputGraph. The grouping feature<br>
is now directly handled by the Resolver. notifyProgress is removed<br>
since we no longer need that. I could have cleaned it up even more,<br>
but in order to keep the patch minimum, I focused on Group.<br>
<br>
SimpleFileNode class, a container of File objects, is now limited<br>
to have only one File. We shold have done this earlier.<br>
We used to allow putting multiple File objects to FileNode.<br>
Although SimpleFileNode usually has only one file, the Driver class<br>
actually used that capability. I modified the Driver class a bit,<br>
so that one FileNode is created for each input File.<br>
<br>
We should now probably remove SimpleFileNode and directly store<br>
File objects to the InputGraph in some way, because a container<br>
that can contain only one object is useless. This is a TODO.<br>
<br>
Mach-O input files are now sorted before they are passe to the<br>
Resolver. DarwinInputGraph class is no longer needed, so removed.<br>
<br>
PECOFF still has hacky code to add a new file to the input file list.<br>
This will be cleaned up in another patch.<br>
<br>
Modified:<br>
lld/trunk/include/lld/Core/<u></u>InputGraph.h<br>
lld/trunk/include/lld/Core/<u></u>LinkingContext.h<br>
lld/trunk/include/lld/Core/<u></u>Resolver.h<br>
lld/trunk/include/lld/Driver/<u></u>DarwinInputGraph.h<br>
lld/trunk/include/lld/Driver/<u></u>WinLinkInputGraph.h<br>
lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>MachOLinkingContext.h<br>
lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>PECOFFLinkingContext.h<br>
lld/trunk/lib/Core/InputGraph.<u></u>cpp<br>
lld/trunk/lib/Core/Resolver.<u></u>cpp<br>
lld/trunk/lib/Driver/<u></u>DarwinInputGraph.cpp<br>
lld/trunk/lib/Driver/<u></u>DarwinLdDriver.cpp<br>
lld/trunk/lib/Driver/Driver.<u></u>cpp<br>
lld/trunk/lib/Driver/<u></u>GnuLdDriver.cpp<br>
lld/trunk/lib/Driver/<u></u>GnuLdInputGraph.cpp<br>
lld/trunk/lib/Driver/<u></u>WinLinkDriver.cpp<br>
lld/trunk/lib/ReaderWriter/<u></u>MachO/MachOLinkingContext.cpp<br>
lld/trunk/lib/ReaderWriter/<u></u>PECOFF/PECOFFLinkingContext.<u></u>cpp<br>
lld/trunk/unittests/<u></u>DriverTests/DriverTest.h<br>
lld/trunk/unittests/<u></u>DriverTests/InputGraphTest.cpp<br>
lld/trunk/unittests/<u></u>DriverTests/WinLinkDriverTest.<u></u>cpp<br>
<br>
Modified: lld/trunk/include/lld/Core/<u></u>InputGraph.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/InputGraph.h?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/include/lld/<u></u>Core/InputGraph.h?rev=223330&<u></u>r1=223329&r2=223330&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/include/lld/Core/<u></u>InputGraph.h (original)<br>
+++ lld/trunk/include/lld/Core/<u></u>InputGraph.h Wed Dec 3 19:09:06 2014<br>
@@ -59,12 +59,6 @@ public:<br>
/// assigned in the way files are resolved.<br>
virtual ErrorOr<File &> getNextFile();<br>
<br>
- /// Notifies the current input element of Resolver made some progress on<br>
- /// resolving undefined symbols using the current file. Group (representing<br>
- /// --start-group and --end-group) uses that notification to make a decision<br>
- /// whether it should iterate over again or terminate or not.<br>
- virtual void notifyProgress();<br>
-<br>
/// Adds an observer of getNextFile(). Each time a new file is about to be<br>
/// returned from getNextFile(), registered observers are called with the file<br>
/// being returned.<br>
@@ -76,14 +70,18 @@ public:<br>
/// \brief Adds a node at the beginning of the InputGraph<br>
void addInputElementFront(std::<u></u>unique_ptr<InputElement>);<br>
<br>
- /// Normalize the InputGraph. It calls expand() on each node and then replace<br>
- /// it with getReplacements() results.<br>
+ /// Normalize the InputGraph. It calls getReplacements() on each element.<br>
void normalize();<br>
<br>
- range<InputElementIterT> inputElements() {<br>
- return make_range(_inputArgs.begin(), _inputArgs.end());<br>
+ InputElementVectorT &inputElements() {<br>
+ return _inputArgs;<br>
}<br>
<br>
+ // Returns the current group size if we are at an --end-group.<br>
+ // Otherwise returns 0.<br>
+ int getGroupSize();<br>
+ void skipGroup();<br>
+<br>
// \brief Returns the number of input files.<br>
size_t size() const { return _inputArgs.size(); }<br>
<br>
@@ -108,8 +106,8 @@ class InputElement {<br>
public:<br>
/// Each input element in the graph can be a File or a control<br>
enum class Kind : uint8_t {<br>
- Group, // Represents a type associated with Group<br>
- File // Represents a type associated with File Nodes<br>
+ File, // Represents a type associated with File Nodes<br>
+ GroupEnd,<br>
};<br>
<br>
InputElement(Kind type) : _kind(type) {}<br>
@@ -129,16 +127,9 @@ public:<br>
/// Get the next file to be processed by the resolver<br>
virtual ErrorOr<File &> getNextFile() = 0;<br>
<br>
- /// Refer InputGraph::notifyProgress(). By default, it does nothing. Only<br>
- /// Group is interested in this message.<br>
- virtual void notifyProgress() {};<br>
-<br>
/// \brief Reset the next index<br>
virtual void resetNextIndex() = 0;<br>
<br>
- /// Returns true if we want to replace this node with children.<br>
- virtual void expand() {}<br>
-<br>
/// Get the elements that we want to expand with.<br>
virtual bool getReplacements(InputGraph::<u></u>InputElementVectorT &) {<br>
return false;<br>
@@ -148,73 +139,31 @@ protected:<br>
Kind _kind; // The type of the Element<br>
};<br>
<br>
-/// \brief A Control node which contains a group of InputElements<br>
-/// This affects the resolver so that it resolves undefined symbols<br>
-/// in the group completely before looking at other input files that<br>
-/// follow the group<br>
-class Group : public InputElement {<br>
+// This is a marker for --end-group. getSize() returns the number of<br>
+// files between the corresponding --start-group and this marker.<br>
+class GroupEnd : public InputElement {<br>
public:<br>
- Group()<br>
- : InputElement(InputElement::<u></u>Kind::Group), _currentElementIndex(0),<br>
- _nextElementIndex(0), _madeProgress(false) {}<br>
+ GroupEnd(int size) : InputElement(Kind::GroupEnd), _size(size) {}<br>
<br>
- static inline bool classof(const InputElement *a) {<br>
- return a->kind() == InputElement::Kind::Group;<br>
- }<br>
-<br>
- /// \brief Process input element and add it to the group<br>
- bool addFile(std::unique_ptr<<u></u>InputElement> element) {<br>
- _elements.push_back(std::move(<u></u>element));<br>
- return true;<br>
- }<br>
+ int getSize() const { return _size; }<br>
<br>
- range<InputGraph::<u></u>InputElementIterT> elements() {<br>
- return make_range(_elements.begin(), _elements.end());<br>
- }<br>
-<br>
- void resetNextIndex() override {<br>
- _madeProgress = false;<br>
- _currentElementIndex = 0;<br>
- _nextElementIndex = 0;<br>
- for (std::unique_ptr<InputElement> &elem : _elements)<br>
- elem->resetNextIndex();<br>
+ static inline bool classof(const InputElement *a) {<br>
+ return a->kind() == Kind::GroupEnd;<br>
}<br>
<br>
/// \brief Parse the group members.<br>
std::error_code parse(const LinkingContext &ctx, raw_ostream &diag) override {<br>
- for (std::unique_ptr<InputElement> &ei : _elements)<br>
- if (std::error_code ec = ei->parse(ctx, diag))<br>
- return ec;<br>
return std::error_code();<br>
}<br>
<br>
- /// If Resolver made a progress using the current file, it's ok to revisit<br>
- /// files in this group in future.<br>
- void notifyProgress() override {<br>
- for (std::unique_ptr<InputElement> &elem : _elements)<br>
- elem->notifyProgress();<br>
- _madeProgress = true;<br>
- }<br>
-<br>
- ErrorOr<File &> getNextFile() override;<br>
-<br>
- void expand() override {<br>
- for (std::unique_ptr<InputElement> &elt : _elements)<br>
- elt->expand();<br>
- std::vector<std::unique_ptr<<u></u>InputElement>> result;<br>
- for (std::unique_ptr<InputElement> &elt : _elements) {<br>
- if (elt->getReplacements(result))<br>
- continue;<br>
- result.push_back(std::move(<u></u>elt));<br>
- }<br>
- _elements.swap(result);<br>
+ ErrorOr<File &> getNextFile() override {<br>
+ llvm_unreachable("shouldn't be here.");<br>
}<br>
<br>
-protected:<br>
- InputGraph::<u></u>InputElementVectorT _elements;<br>
- uint32_t _currentElementIndex;<br>
- uint32_t _nextElementIndex;<br>
- bool _madeProgress;<br>
+ void resetNextIndex() override {}<br>
+<br>
+private:<br>
+ int _size;<br>
};<br>
<br>
/// \brief Represents an Input file in the graph<br>
@@ -252,6 +201,8 @@ public:<br>
<br>
/// \brief add a file to the list of files<br>
virtual void addFiles(InputGraph::<u></u>FileVectorT files) {<br>
+ assert(files.size() == 1);<br>
+ assert(_files.empty());<br>
for (std::unique_ptr<File> &ai : files)<br>
_files.push_back(std::move(ai)<u></u>);<br>
}<br>
@@ -260,6 +211,8 @@ public:<br>
/// the node again.<br>
void resetNextIndex() override { _nextFileIndex = 0; }<br>
<br>
+ bool getReplacements(InputGraph::<u></u>InputElementVectorT &result) override;<br>
+<br>
protected:<br>
/// \brief Read the file into _buffer.<br>
std::error_code getBuffer(StringRef filePath);<br>
@@ -276,6 +229,10 @@ protected:<br>
class SimpleFileNode : public FileNode {<br>
public:<br>
SimpleFileNode(StringRef path) : FileNode(path) {}<br>
+ SimpleFileNode(StringRef path, std::unique_ptr<File> f)<br>
+ : FileNode(path) {<br>
+ _files.push_back(std::move(f))<u></u>;<br>
+ }<br>
<br>
virtual ~SimpleFileNode() {}<br>
<br>
<br>
Modified: lld/trunk/include/lld/Core/<u></u>LinkingContext.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/LinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/include/lld/<u></u>Core/LinkingContext.h?rev=<u></u>223330&r1=223329&r2=223330&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/include/lld/Core/<u></u>LinkingContext.h (original)<br>
+++ lld/trunk/include/lld/Core/<u></u>LinkingContext.h Wed Dec 3 19:09:06 2014<br>
@@ -322,6 +322,10 @@ public:<br>
bool runRoundTripPass() const { return _runRoundTripPasses; }<br>
#endif<br>
<br>
+ // This function is called just before the Resolver kicks in.<br>
+ // Derived classes may use that chance to rearrange the input files.<br>
+ virtual void maybeSortInputFiles() {}<br>
+<br>
/// @}<br>
protected:<br>
LinkingContext(); // Must be subclassed<br>
<br>
Modified: lld/trunk/include/lld/Core/<u></u>Resolver.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Core/Resolver.h?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/include/lld/<u></u>Core/Resolver.h?rev=223330&r1=<u></u>223329&r2=223330&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/include/lld/Core/<u></u>Resolver.h (original)<br>
+++ lld/trunk/include/lld/Core/<u></u>Resolver.h Wed Dec 3 19:09:06 2014<br>
@@ -28,7 +28,8 @@ class LinkingContext;<br>
class Resolver {<br>
public:<br>
Resolver(LinkingContext &context)<br>
- : _context(context), _symbolTable(context), _result(new MergedFile()) {}<br>
+ : _context(context), _symbolTable(context), _result(new MergedFile()),<br>
+ _fileIndex(0) {}<br>
<br>
// InputFiles::Handler methods<br>
void doDefinedAtom(const DefinedAtom&);<br>
@@ -38,10 +39,10 @@ public:<br>
<br>
// Handle files, this adds atoms from the current file thats<br>
// being processed by the resolver<br>
- void handleFile(const File &);<br>
+ bool handleFile(const File &);<br>
<br>
// Handle an archive library file.<br>
- void handleArchiveFile(const File &);<br>
+ bool handleArchiveFile(const File &);<br>
<br>
// Handle a shared library file.<br>
void handleSharedLibrary(const File &);<br>
@@ -54,6 +55,9 @@ public:<br>
private:<br>
typedef std::function<void(StringRef, bool)> UndefCallback;<br>
<br>
+ bool undefinesAdded(int count);<br>
+ ErrorOr<File &> nextFile(bool &inGroup);<br>
+<br>
/// \brief Add section group/.gnu.linkonce if it does not exist previously.<br>
void maybeAddSectionGroupOrGnuLinkO<u></u>nce(const DefinedAtom &atom);<br>
<br>
@@ -110,6 +114,11 @@ private:<br>
llvm::DenseSet<const Atom *> _deadAtoms;<br>
std::unique_ptr<MergedFile> _result;<br>
llvm::DenseMap<const Atom *, llvm::DenseSet<const Atom *>> _reverseRef;<br>
+<br>
+ // --start-group and --end-group<br>
+ std::vector<File *> _files;<br>
+ std::map<File *, bool> _newUndefinesAdded;<br>
+ size_t _fileIndex;<br>
};<br>
<br>
} // namespace lld<br>
<br>
Modified: lld/trunk/include/lld/Driver/<u></u>DarwinInputGraph.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/DarwinInputGraph.h?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/include/lld/<u></u>Driver/DarwinInputGraph.h?rev=<u></u>223330&r1=223329&r2=223330&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/include/lld/Driver/<u></u>DarwinInputGraph.h (original)<br>
+++ lld/trunk/include/lld/Driver/<u></u>DarwinInputGraph.h Wed Dec 3 19:09:06 2014<br>
@@ -23,18 +23,6 @@<br>
<br>
namespace lld {<br>
<br>
-<br>
-class DarwinInputGraph : public InputGraph {<br>
-public:<br>
- DarwinInputGraph() : _librariesPhase(false), _repeatLibraries(false) { }<br>
- ErrorOr<File &> getNextFile() override;<br>
- void notifyProgress() override;<br>
-private:<br>
- bool _librariesPhase;<br>
- bool _repeatLibraries;<br>
-};<br>
-<br>
-<br>
/// \brief Represents a MachO File<br>
class MachOFileNode : public FileNode {<br>
public:<br>
<br>
Modified: lld/trunk/include/lld/Driver/<u></u>WinLinkInputGraph.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/Driver/WinLinkInputGraph.h?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/include/lld/<u></u>Driver/WinLinkInputGraph.h?<u></u>rev=223330&r1=223329&r2=<u></u>223330&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/include/lld/Driver/<u></u>WinLinkInputGraph.h (original)<br>
+++ lld/trunk/include/lld/Driver/<u></u>WinLinkInputGraph.h Wed Dec 3 19:09:06 2014<br>
@@ -55,21 +55,6 @@ public:<br>
ErrorOr<StringRef> getPath(const LinkingContext &ctx) const override;<br>
};<br>
<br>
-/// \brief Represents a ELF control node<br>
-class PECOFFGroup : public Group {<br>
-public:<br>
- PECOFFGroup(<u></u>PECOFFLinkingContext &ctx) : Group(), _ctx(ctx) {}<br>
-<br>
- /// \brief Parse the group members.<br>
- std::error_code parse(const LinkingContext &ctx, raw_ostream &diag) override {<br>
- std::lock_guard<std::<u></u>recursive_mutex> lock(_ctx.getMutex());<br>
- return Group::parse(ctx, diag);<br>
- }<br>
-<br>
-private:<br>
- PECOFFLinkingContext &_ctx;<br>
-};<br>
-<br>
} // namespace lld<br>
<br>
#endif<br>
<br>
Modified: lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>MachOLinkingContext.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>MachOLinkingContext.h?rev=<u></u>223330&r1=223329&r2=223330&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>MachOLinkingContext.h (original)<br>
+++ lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>MachOLinkingContext.h Wed Dec 3 19:09:06 2014<br>
@@ -283,6 +283,8 @@ public:<br>
/// bits are xxxx.yy.zz. Largest number is 65535.255.255<br>
static bool parsePackedVersion(StringRef str, uint32_t &result);<br>
<br>
+ void maybeSortInputFiles() override;<br>
+<br>
private:<br>
Writer &writer() const override;<br>
mach_o::MachODylibFile* loadIndirectDylib(StringRef path);<br>
<br>
Modified: lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>PECOFFLinkingContext.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/PECOFFLinkingContext.h?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>PECOFFLinkingContext.h?rev=<u></u>223330&r1=223329&r2=223330&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>PECOFFLinkingContext.h (original)<br>
+++ lld/trunk/include/lld/<u></u>ReaderWriter/<u></u>PECOFFLinkingContext.h Wed Dec 3 19:09:06 2014<br>
@@ -29,7 +29,6 @@ using llvm::COFF::WindowsSubsystem;<br>
static const uint8_t DEFAULT_DOS_STUB[128] = {'M', 'Z'};<br>
<br>
namespace lld {<br>
-class Group;<br>
<br>
class PECOFFLinkingContext : public LinkingContext {<br>
public:<br>
@@ -315,8 +314,7 @@ public:<br>
void setEntryNode(SimpleFileNode *node) { _entryNode = node; }<br>
SimpleFileNode *getEntryNode() const { return _entryNode; }<br>
<br>
- void setLibraryGroup(Group *group) { _libraryGroup = group; }<br>
- Group *getLibraryGroup() const { return _libraryGroup; }<br>
+ void addLibraryFile(std::unique_<u></u>ptr<FileNode> file);<br>
<br>
void setModuleDefinitionFile(const std::string val) {<br>
_moduleDefinitionFile = val;<br>
@@ -438,9 +436,6 @@ private:<br>
// The node containing the entry point file.<br>
SimpleFileNode *_entryNode;<br>
<br>
- // The PECOFFGroup that contains all the .lib files.<br>
- Group *_libraryGroup;<br>
-<br>
// Name of the temporary file for lib.exe subcommand. For debugging<br>
// only.<br>
std::string _moduleDefinitionFile;<br>
<br>
Modified: lld/trunk/lib/Core/InputGraph.<u></u>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/InputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/Core/<u></u>InputGraph.cpp?rev=223330&r1=<u></u>223329&r2=223330&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/Core/InputGraph.<u></u>cpp (original)<br>
+++ lld/trunk/lib/Core/InputGraph.<u></u>cpp Wed Dec 3 19:09:06 2014<br>
@@ -36,8 +36,6 @@ ErrorOr<File &> InputGraph::getNextFile(<br>
}<br>
}<br>
<br>
-void InputGraph::notifyProgress() { _currentInputElement-><u></u>notifyProgress(); }<br>
-<br>
void InputGraph::registerObserver(<u></u>std::function<void(File *)> fn) {<br>
_observers.push_back(fn);<br>
}<br>
@@ -61,12 +59,13 @@ bool InputGraph::dump(raw_ostream &diagn<br>
ErrorOr<InputElement *> InputGraph::<u></u>getNextInputElement() {<br>
if (_nextElementIndex >= _inputArgs.size())<br>
return make_error_code(<u></u>InputGraphError::no_more_<u></u>elements);<br>
- return _inputArgs[_nextElementIndex++<u></u>].get();<br>
+ InputElement *elem = _inputArgs[_nextElementIndex++<u></u>].get();<br>
+ if (isa<GroupEnd>(elem))<br>
+ return getNextInputElement();<br>
+ return elem;<br>
}<br>
<br>
void InputGraph::normalize() {<br>
- for (std::unique_ptr<InputElement> &elt : _inputArgs)<br>
- elt->expand();<br>
std::vector<std::unique_ptr<<u></u>InputElement>> vec;<br>
for (std::unique_ptr<InputElement> &elt : _inputArgs) {<br>
if (elt->getReplacements(vec))<br>
@@ -76,6 +75,25 @@ void InputGraph::normalize() {<br>
_inputArgs = std::move(vec);<br>
}<br>
<br>
+// If we are at the end of a group, return its size (which indicates<br>
+// how many files we need to go back in the command line).<br>
+// Returns 0 if we are not at the end of a group.<br>
+int InputGraph::getGroupSize() {<br>
+ if (_nextElementIndex >= _inputArgs.size())<br>
+ return 0;<br>
+ InputElement *elem = _inputArgs[_nextElementIndex].<u></u>get();<br>
+ if (const GroupEnd *group = dyn_cast<GroupEnd>(elem))<br>
+ return group->getSize();<br>
+ return 0;<br>
+}<br>
+<br>
+void InputGraph::skipGroup() {<br>
+ if (_nextElementIndex >= _inputArgs.size())<br>
+ return;<br>
+ if (isa<GroupEnd>(_inputArgs[_<u></u>nextElementIndex].get()))<br>
+ _nextElementIndex++;<br>
+}<br>
+<br>
/// \brief Read the file into _buffer.<br>
std::error_code FileNode::getBuffer(StringRef filePath) {<br>
// Create a memory buffer<br>
@@ -87,32 +105,10 @@ std::error_code FileNode::getBuffer(Stri<br>
return std::error_code();<br>
}<br>
<br>
-/// \brief Return the next file that need to be processed by the resolver.<br>
-/// This also processes input elements depending on the resolve status<br>
-/// of the input elements contained in the group.<br>
-ErrorOr<File &> Group::getNextFile() {<br>
- // If there are no elements, move on to the next input element<br>
- if (_elements.empty())<br>
- return make_error_code(<u></u>InputGraphError::no_more_<u></u>files);<br>
-<br>
- for (;;) {<br>
- // If we have processed all the elements, and have made no progress on<br>
- // linking, we cannot resolve any symbol from this group. Continue to the<br>
- // next one by returning no_more_files.<br>
- if (_nextElementIndex == _elements.size()) {<br>
- if (!_madeProgress)<br>
- return make_error_code(<u></u>InputGraphError::no_more_<u></u>files);<br>
- resetNextIndex();<br>
- }<br>
-<br>
- _currentElementIndex = _nextElementIndex;<br>
- auto file = _elements[_nextElementIndex]-><u></u>getNextFile();<br>
- // Move on to the next element if we have finished processing all<br>
- // the files in the input element<br>
- if (file.getError() == InputGraphError::no_more_<u></u>files) {<br>
- _nextElementIndex++;<br>
- continue;<br>
- }<br>
- return *file;<br>
- }<br>
+bool FileNode::getReplacements(<u></u>InputGraph::<u></u>InputElementVectorT &result) {<br>
+ if (_files.size() < 2)<br>
+ return false;<br>
+ for (std::unique_ptr<File> &file : _files)<br>
+ result.push_back(llvm::make_<u></u>unique<SimpleFileNode>(_path, std::move(file)));<br>
+ return true;<br>
}<br>
<br>
Modified: lld/trunk/lib/Core/Resolver.<u></u>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Core/Resolver.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/Core/<u></u>Resolver.cpp?rev=223330&r1=<u></u>223329&r2=223330&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/Core/Resolver.<u></u>cpp (original)<br>
+++ lld/trunk/lib/Core/Resolver.<u></u>cpp Wed Dec 3 19:09:06 2014<br>
@@ -27,7 +27,7 @@<br>
<br>
namespace lld {<br>
<br>
-void Resolver::handleFile(const File &file) {<br>
+bool Resolver::handleFile(const File &file) {<br>
bool undefAdded = false;<br>
for (const DefinedAtom *atom : file.defined())<br>
doDefinedAtom(*atom);<br>
@@ -38,13 +38,7 @@ void Resolver::handleFile(const File &fi<br>
doSharedLibraryAtom(*atom);<br>
for (const AbsoluteAtom *atom : file.absolute())<br>
doAbsoluteAtom(*atom);<br>
-<br>
- // Notify the input file manager of the fact that we have made some progress<br>
- // on linking using the current input file. It may want to know the fact for<br>
- // --start-group/--end-group.<br>
- if (undefAdded) {<br>
- _context.getInputGraph().<u></u>notifyProgress();<br>
- }<br>
+ return undefAdded;<br>
}<br>
<br>
void Resolver::forEachUndefines(<u></u>bool searchForOverrides,<br>
@@ -76,17 +70,19 @@ void Resolver::forEachUndefines(<u></u>bool sea<br>
} while (undefineGenCount != _symbolTable.size());<br>
}<br>
<br>
-void Resolver::handleArchiveFile(<u></u>const File &file) {<br>
+bool Resolver::handleArchiveFile(<u></u>const File &file) {<br>
const ArchiveLibraryFile *archiveFile = cast<ArchiveLibraryFile>(&<u></u>file);<br>
bool searchForOverrides =<br>
_context.<u></u>searchArchivesToOverrideTentat<u></u>iveDefinitions();<br>
+ bool undefAdded = false;<br>
forEachUndefines(<u></u>searchForOverrides,<br>
[&](StringRef undefName, bool dataSymbolOnly) {<br>
if (const File *member = archiveFile->find(undefName, dataSymbolOnly)) {<br>
member->setOrdinal(_context.<u></u>getNextOrdinalAndIncrement());<br>
- handleFile(*member);<br>
+ undefAdded = undefAdded || handleFile(*member);<br>
}<br>
});<br>
+ return undefAdded;<br>
}<br>
<br>
void Resolver::handleSharedLibrary(<u></u>const File &file) {<br>
@@ -233,31 +229,66 @@ void Resolver::addAtoms(const std::vecto<br>
doDefinedAtom(*newAtom);<br>
}<br>
<br>
+// Returns true if at least one of N previous files has created an<br>
+// undefined symbol.<br>
+bool Resolver::undefinesAdded(int n) {<br>
+ for (size_t i = _fileIndex - n; i < _fileIndex; ++i)<br>
+ if (_newUndefinesAdded[_files[i]]<u></u>)<br>
+ return true;<br>
+ return false;<br>
+}<br>
+<br>
+ErrorOr<File &> Resolver::nextFile(bool &inGroup) {<br>
+ if (size_t groupSize = _context.getInputGraph().<u></u>getGroupSize()) {<br>
+ // We are at the end of the current group. If one or more new<br>
+ // undefined atom has been added in the last groupSize files, we<br>
+ // reiterate over the files.<br>
+ if (undefinesAdded(groupSize))<br>
+ _fileIndex -= groupSize;<br>
+ _context.getInputGraph().<u></u>skipGroup();<br>
+ return nextFile(inGroup);<br>
+ }<br>
+ if (_fileIndex < _files.size()) {<br>
+ // We are still in the current group.<br>
+ inGroup = true;<br>
+ return *_files[_fileIndex++];<br>
+ }<br>
+ // We are not in a group. Get a new file.<br>
+ ErrorOr<File &> file = _context.getInputGraph().<u></u>getNextFile();<br>
+ if (std::error_code ec = file.getError()) {<br>
+ if (ec != InputGraphError::no_more_<u></u>files)<br>
+ llvm::errs() << "Error occurred in getNextFile: " << ec.message() << "\n";<br>
+ return ec;<br>
+ }<br>
+ _files.push_back(&*file);<br>
+ ++_fileIndex;<br>
+ inGroup = false;<br>
+ return *file;<br>
+}<br>
+<br>
// Keep adding atoms until _context.getNextFile() returns an error. This<br>
// function is where undefined atoms are resolved.<br>
bool Resolver::resolveUndefines() {<br>
ScopedTask task(getDefaultDomain(), "resolveUndefines");<br>
<br>
for (;;) {<br>
- ErrorOr<File &> file = _context.getInputGraph().<u></u>getNextFile();<br>
- std::error_code ec = file.getError();<br>
- if (ec == InputGraphError::no_more_<u></u>files)<br>
- return true;<br>
- if (!file) {<br>
- llvm::errs() << "Error occurred in getNextFile: " << ec.message() << "\n";<br>
- return false;<br>
- }<br>
-<br>
+ bool inGroup = false;<br>
+ bool undefAdded = false;<br>
+ ErrorOr<File &> file = nextFile(inGroup);<br>
+ if (std::error_code ec = file.getError())<br>
+ return ec == InputGraphError::no_more_<u></u>files;<br>
switch (file->kind()) {<br>
case File::kindObject:<br>
+ if (inGroup)<br>
+ break;<br>
assert(!file->hasOrdinal());<br>
file->setOrdinal(_context.<u></u>getNextOrdinalAndIncrement());<br>
- handleFile(*file);<br>
+ undefAdded = handleFile(*file);<br>
break;<br>
case File::kindArchiveLibrary:<br>
if (!file->hasOrdinal())<br>
file->setOrdinal(_context.<u></u>getNextOrdinalAndIncrement());<br>
- handleArchiveFile(*file);<br>
+ undefAdded = handleArchiveFile(*file);<br>
break;<br>
case File::kindSharedLibrary:<br>
if (!file->hasOrdinal())<br>
@@ -265,6 +296,7 @@ bool Resolver::resolveUndefines() {<br>
handleSharedLibrary(*file);<br>
break;<br>
}<br>
+ _newUndefinesAdded[&*file] = undefAdded;<br>
}<br>
}<br>
<br>
<br>
Modified: lld/trunk/lib/Driver/<u></u>DarwinInputGraph.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinInputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/Driver/<u></u>DarwinInputGraph.cpp?rev=<u></u>223330&r1=223329&r2=223330&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/Driver/<u></u>DarwinInputGraph.cpp (original)<br>
+++ lld/trunk/lib/Driver/<u></u>DarwinInputGraph.cpp Wed Dec 3 19:09:06 2014<br>
@@ -18,48 +18,6 @@<br>
namespace lld {<br>
<br>
<br>
-ErrorOr<File &> DarwinInputGraph::getNextFile(<u></u>) {<br>
- // The darwin linker processes input files in two phases. The first phase<br>
- // links in all object (.o) files in command line order. The second phase<br>
- // links in libraries in command line order. If there are still UndefinedAtoms<br>
- // the second phase is repeated until notifyProgress() is not called by<br>
- // resolver.<br>
- for (;;) {<br>
- if (_currentInputElement) {<br>
- for(;;) {<br>
- ErrorOr<File &> next = _currentInputElement-><u></u>getNextFile();<br>
- if (next.getError())<br>
- break;<br>
- File *file = &next.get();<br>
- bool fileIsLibrary = isa<SharedLibraryFile>(file) ||<br>
- isa<ArchiveLibraryFile>(file);<br>
- if (fileIsLibrary == _librariesPhase) {<br>
- // Return library in library phase and object files in non-lib mode.<br>
- return *file;<br>
- }<br>
- }<br>
- }<br>
-<br>
- if (_nextElementIndex >= _inputArgs.size()) {<br>
- // If no more elements, done unless we need to repeat library scan.<br>
- if (_librariesPhase && !_repeatLibraries)<br>
- return make_error_code(<u></u>InputGraphError::no_more_<u></u>files);<br>
- // Clear iterations and only look for libraries.<br>
- _librariesPhase = true;<br>
- _repeatLibraries = false;<br>
- _nextElementIndex = 0;<br>
- for (auto &ie : _inputArgs) {<br>
- ie->resetNextIndex();<br>
- }<br>
- }<br>
- _currentInputElement = _inputArgs[_nextElementIndex++<u></u>].get();<br>
- }<br>
-}<br>
-<br>
-void DarwinInputGraph::<u></u>notifyProgress() {<br>
- _repeatLibraries = true;<br>
-}<br>
-<br>
/// \brief Parse the input file to lld::File.<br>
std::error_code MachOFileNode::parse(const LinkingContext &ctx,<br>
raw_ostream &diagnostics) {<br>
<br>
Modified: lld/trunk/lib/Driver/<u></u>DarwinLdDriver.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/Driver/<u></u>DarwinLdDriver.cpp?rev=223330&<u></u>r1=223329&r2=223330&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/Driver/<u></u>DarwinLdDriver.cpp (original)<br>
+++ lld/trunk/lib/Driver/<u></u>DarwinLdDriver.cpp Wed Dec 3 19:09:06 2014<br>
@@ -83,7 +83,7 @@ static std::string canonicalizePath(Stri<br>
}<br>
}<br>
<br>
-static void addFile(StringRef path, std::unique_ptr<<u></u>DarwinInputGraph> &inputGraph,<br>
+static void addFile(StringRef path, std::unique_ptr<InputGraph> &inputGraph,<br>
MachOLinkingContext &ctx, bool loadWholeArchive,<br>
bool upwardDylib) {<br>
auto node = llvm::make_unique<<u></u>MachOFileNode>(path, ctx);<br>
@@ -185,7 +185,7 @@ static std::error_code parseOrderFile(St<br>
// per line. The <dir> prefix is prepended to each partial path.<br>
//<br>
static std::error_code parseFileList(StringRef fileListPath,<br>
- std::unique_ptr<<u></u>DarwinInputGraph> &inputGraph,<br>
+ std::unique_ptr<InputGraph> &inputGraph,<br>
MachOLinkingContext &ctx, bool forceLoad,<br>
raw_ostream &diagnostics) {<br>
// If there is a comma, split off <dir>.<br>
@@ -521,7 +521,7 @@ bool DarwinLdDriver::parse(int argc, con<br>
}<br>
}<br>
<br>
- std::unique_ptr<<u></u>DarwinInputGraph> inputGraph(new DarwinInputGraph());<br>
+ std::unique_ptr<InputGraph> inputGraph(new InputGraph());<br>
<br>
// Now construct the set of library search directories, following ld64's<br>
// baroque set of accumulated hacks. Mostly, the algorithm constructs<br>
<br>
Modified: lld/trunk/lib/Driver/Driver.<u></u>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/Driver.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/Driver/<u></u>Driver.cpp?rev=223330&r1=<u></u>223329&r2=223330&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/Driver/Driver.<u></u>cpp (original)<br>
+++ lld/trunk/lib/Driver/Driver.<u></u>cpp Wed Dec 3 19:09:06 2014<br>
@@ -62,9 +62,6 @@ bool Driver::link(LinkingContext &contex<br>
if (std::error_code ec = ie->parse(context, stream)) {<br>
if (FileNode *fileNode = dyn_cast<FileNode>(ie.get()))<br>
stream << fileNode->errStr(ec) << "\n";<br>
- else if (dyn_cast<Group>(ie.get()))<br>
- // FIXME: We need a better diagnostics here<br>
- stream << "Cannot parse group input element\n";<br>
else<br>
llvm_unreachable("Unknown type of input element");<br>
fail = true;<br>
@@ -83,21 +80,24 @@ bool Driver::link(LinkingContext &contex<br>
if (fail)<br>
return false;<br>
<br>
- std::unique_ptr<<u></u>SimpleFileNode> fileNode(<br>
- new SimpleFileNode("Internal Files"));<br>
-<br>
InputGraph::FileVectorT internalFiles;<br>
context.createInternalFiles(<u></u>internalFiles);<br>
-<br>
- if (internalFiles.size())<br>
- fileNode->addFiles(std::move(<u></u>internalFiles));<br>
+ for (auto i = internalFiles.rbegin(), e = internalFiles.rend(); i != e; ++i) {<br>
+ context.getInputGraph().<u></u>addInputElementFront(<br>
+ llvm::make_unique<<u></u>SimpleFileNode>("internal", std::move(*i)));<br>
+ }<br>
<br>
// Give target a chance to add files.<br>
InputGraph::FileVectorT implicitFiles;<br>
context.createImplicitFiles(<u></u>implicitFiles);<br>
- if (implicitFiles.size())<br>
- fileNode->addFiles(std::move(<u></u>implicitFiles));<br>
- context.getInputGraph().<u></u>addInputElementFront(std::<u></u>move(fileNode));<br>
+ for (auto i = implicitFiles.rbegin(), e = implicitFiles.rend(); i != e; ++i) {<br>
+ context.getInputGraph().<u></u>addInputElementFront(<br>
+ llvm::make_unique<<u></u>SimpleFileNode>("implicit", std::move(*i)));<br>
+ }<br>
+<br>
+ // Give target a chance to sort the input files.<br>
+ // Mach-O uses this chance to move all object files before library files.<br>
+ context.maybeSortInputFiles();<br>
<br>
// Do core linking.<br>
ScopedTask resolveTask(getDefaultDomain()<u></u>, "Resolve");<br>
<br>
Modified: lld/trunk/lib/Driver/<u></u>GnuLdDriver.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/Driver/<u></u>GnuLdDriver.cpp?rev=223330&r1=<u></u>223329&r2=223330&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/Driver/<u></u>GnuLdDriver.cpp (original)<br>
+++ lld/trunk/lib/Driver/<u></u>GnuLdDriver.cpp Wed Dec 3 19:09:06 2014<br>
@@ -295,7 +295,8 @@ bool GnuLdDriver::parse(int argc, const<br>
}<br>
<br>
std::unique_ptr<InputGraph> inputGraph(new InputGraph());<br>
- std::stack<Group *> groupStack;<br>
+ std::stack<int> groupStack;<br>
+ int numfiles = 0;<br>
<br>
ELFFileNode::Attributes attributes;<br>
<br>
@@ -468,16 +469,21 @@ bool GnuLdDriver::parse(int argc, const<br>
break;<br>
}<br>
<br>
- case OPT_start_group: {<br>
- std::unique_ptr<Group> group(new Group());<br>
- groupStack.push(group.get());<br>
- inputGraph->addInputElement(<u></u>std::move(group));<br>
+ case OPT_start_group:<br>
+ groupStack.push(numfiles);<br>
break;<br>
- }<br>
<br>
- case OPT_end_group:<br>
+ case OPT_end_group: {<br>
+ if (groupStack.empty()) {<br>
+ diagnostics << "stray --end-group\n";<br>
+ return false;<br>
+ }<br>
+ int startGroupPos = groupStack.top();<br>
+ inputGraph->addInputElement(<br>
+ llvm::make_unique<GroupEnd>(<u></u>numfiles - startGroupPos));<br>
groupStack.pop();<br>
break;<br>
+ }<br>
<br>
case OPT_z: {<br>
StringRef extOpt = inputArg->getValue();<br>
@@ -552,11 +558,8 @@ bool GnuLdDriver::parse(int argc, const<br>
}<br>
}<br>
std::unique_ptr<InputElement> inputFile(inputNode);<br>
- if (groupStack.empty()) {<br>
- inputGraph->addInputElement(<u></u>std::move(inputFile));<br>
- } else {<br>
- groupStack.top()->addFile(std:<u></u>:move(inputFile));<br>
- }<br>
+ ++numfiles;<br>
+ inputGraph->addInputElement(<u></u>std::move(inputFile));<br>
break;<br>
}<br>
<br>
<br>
Modified: lld/trunk/lib/Driver/<u></u>GnuLdInputGraph.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/GnuLdInputGraph.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/Driver/<u></u>GnuLdInputGraph.cpp?rev=<u></u>223330&r1=223329&r2=223330&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/Driver/<u></u>GnuLdInputGraph.cpp (original)<br>
+++ lld/trunk/lib/Driver/<u></u>GnuLdInputGraph.cpp Wed Dec 3 19:09:06 2014<br>
@@ -91,7 +91,7 @@ std::error_code ELFGNULdScript::parse(co<br>
auto *group = dyn_cast<script::Group>(c);<br>
if (!group)<br>
continue;<br>
- std::unique_ptr<Group> groupStart(new Group());<br>
+ size_t numfiles = 0;<br>
for (const script::Path &path : group->getPaths()) {<br>
// TODO : Propagate Set WholeArchive/dashlPrefix<br>
attributes.setAsNeeded(path._<u></u>asNeeded);<br>
@@ -100,9 +100,10 @@ std::error_code ELFGNULdScript::parse(co<br>
_elfLinkingContext, _elfLinkingContext.<u></u>allocateString(path._path),<br>
attributes);<br>
std::unique_ptr<InputElement> inputFile(inputNode);<br>
- groupStart.get()->addFile(std:<u></u>:move(inputFile));<br>
+ _expandElements.push_back(std:<u></u>:move(inputFile));<br>
+ ++numfiles;<br>
}<br>
- _expandElements.push_back(std:<u></u>:move(groupStart));<br>
+ _expandElements.push_back(<u></u>llvm::make_unique<GroupEnd>(<u></u>numfiles));<br>
}<br>
return std::error_code();<br>
}<br>
<br>
Modified: lld/trunk/lib/Driver/<u></u>WinLinkDriver.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/WinLinkDriver.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/Driver/<u></u>WinLinkDriver.cpp?rev=223330&<u></u>r1=223329&r2=223330&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/Driver/<u></u>WinLinkDriver.cpp (original)<br>
+++ lld/trunk/lib/Driver/<u></u>WinLinkDriver.cpp Wed Dec 3 19:09:06 2014<br>
@@ -781,7 +781,7 @@ static bool hasLibrary(const PECOFFLinki<br>
ErrorOr<StringRef> path = fileNode->getPath(ctx);<br>
if (!path)<br>
return false;<br>
- for (std::unique_ptr<InputElement> &p : ctx.getLibraryGroup()-><u></u>elements())<br>
+ for (std::unique_ptr<InputElement> &p : ctx.getInputGraph().<u></u>inputElements())<br>
if (auto *f = dyn_cast<FileNode>(p.get()))<br>
if (*path == *f->getPath(ctx))<br>
return true;<br>
@@ -1397,10 +1397,8 @@ bool WinLinkDriver::parse(int argc, cons<br>
ctx.setEntryNode(entry.get());<br>
ctx.getInputGraph().<u></u>addInputElement(std::move(<u></u>entry));<br>
<br>
- // The container for all library files.<br>
- std::unique_ptr<Group> group(new PECOFFGroup(ctx));<br>
- ctx.setLibraryGroup(group.get(<u></u>));<br>
- ctx.getInputGraph().<u></u>addInputElement(std::move(<u></u>group));<br>
+ // Add a group-end marker.<br>
+ ctx.getInputGraph().<u></u>addInputElement(llvm::make_<u></u>unique<GroupEnd>(0));<br>
}<br>
<br>
// Add the library files to the library group.<br>
@@ -1409,7 +1407,7 @@ bool WinLinkDriver::parse(int argc, cons<br>
if (isReadingDirectiveSection)<br>
if (lib->parse(ctx, diag))<br>
return false;<br>
- ctx.getLibraryGroup()-><u></u>addFile(std::move(lib));<br>
+ ctx.addLibraryFile(std::move(<u></u>lib));<br>
}<br>
}<br>
<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/<u></u>MachO/MachOLinkingContext.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/<u></u>ReaderWriter/MachO/<u></u>MachOLinkingContext.cpp?rev=<u></u>223330&r1=223329&r2=223330&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/ReaderWriter/<u></u>MachO/MachOLinkingContext.cpp (original)<br>
+++ lld/trunk/lib/ReaderWriter/<u></u>MachO/MachOLinkingContext.cpp Wed Dec 3 19:09:06 2014<br>
@@ -22,6 +22,7 @@<br>
#include "llvm/ADT/Triple.h"<br>
#include "llvm/Config/config.h"<br>
#include "llvm/Support/Errc.h"<br>
+#include "llvm/Support/Debug.h"<br>
#include "llvm/Support/Host.h"<br>
#include "llvm/Support/MachO.h"<br>
#include "llvm/Support/Path.h"<br>
@@ -923,4 +924,35 @@ bool MachOLinkingContext::<u></u>customAtomOrde<br>
return true;<br>
}<br>
<br>
+static File *getFirstFile(const std::unique_ptr<InputElement> &elem) {<br>
+ FileNode *e = dyn_cast<FileNode>(const_cast<<u></u>InputElement *>(elem.get()));<br>
+ if (!e || e->files().empty())<br>
+ return nullptr;<br>
+ return e->files()[0].get();<br>
+}<br>
+<br>
+static bool isLibrary(const std::unique_ptr<InputElement> &elem) {<br>
+ File *f = getFirstFile(elem);<br>
+ return f && (isa<SharedLibraryFile>(f) || isa<ArchiveLibraryFile>(f));<br>
+}<br>
+<br>
+// The darwin linker processes input files in two phases. The first phase<br>
+// links in all object (.o) files in command line order. The second phase<br>
+// links in libraries in command line order.<br>
+// In this function we reorder the input files so that all the object files<br>
+// comes before any library file. We also make a group for the library files<br>
+// so that the Resolver will reiterate over the libraries as long as we find<br>
+// new undefines from libraries.<br>
+void MachOLinkingContext::<u></u>maybeSortInputFiles() {<br>
+ std::vector<std::unique_ptr<<u></u>InputElement>> &elements<br>
+ = getInputGraph().inputElements(<u></u>);<br>
+ std::stable_sort(elements.<u></u>begin(), elements.end(),<br>
+ [](const std::unique_ptr<InputElement> &a,<br>
+ const std::unique_ptr<InputElement> &b) {<br>
+ return !isLibrary(a) && isLibrary(b);<br>
+ });<br>
+ size_t numLibs = std::count_if(elements.begin()<u></u>, elements.end(), isLibrary);<br>
+ elements.push_back(llvm::make_<u></u>unique<GroupEnd>(numLibs));<br>
+}<br>
+<br>
} // end namespace lld<br>
<br>
Modified: lld/trunk/lib/ReaderWriter/<u></u>PECOFF/PECOFFLinkingContext.<u></u>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/lib/<u></u>ReaderWriter/PECOFF/<u></u>PECOFFLinkingContext.cpp?rev=<u></u>223330&r1=223329&r2=223330&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/lib/ReaderWriter/<u></u>PECOFF/PECOFFLinkingContext.<u></u>cpp (original)<br>
+++ lld/trunk/lib/ReaderWriter/<u></u>PECOFF/PECOFFLinkingContext.<u></u>cpp Wed Dec 3 19:09:06 2014<br>
@@ -87,6 +87,23 @@ std::unique_ptr<File> PECOFFLinkingConte<br>
"<command line option /include>");<br>
}<br>
<br>
+void PECOFFLinkingContext::<u></u>addLibraryFile(std::unique_<u></u>ptr<FileNode> file) {<br>
+ GroupEnd *currentGroupEnd;<br>
+ int pos = -1;<br>
+ std::vector<std::unique_ptr<<u></u>InputElement>> &elements<br>
+ = getInputGraph().inputElements(<u></u>);<br>
+ for (int i = 0, e = elements.size(); i < e; ++i) {<br>
+ if ((currentGroupEnd = dyn_cast<GroupEnd>(elements[i]<u></u>.get()))) {<br>
+ pos = i;<br>
+ break;<br>
+ }<br>
+ }<br>
+ assert(pos >= 0);<br>
+ elements.insert(elements.<u></u>begin() + pos, std::move(file));<br>
+ elements[pos + 1] = llvm::make_unique<GroupEnd>(<br>
+ currentGroupEnd->getSize() + 1);<br>
+}<br>
+<br>
bool PECOFFLinkingContext::<u></u>createImplicitFiles(<br>
std::vector<std::unique_ptr<<u></u>File>> &) {<br>
// Create a file for __ImageBase.<br>
@@ -109,7 +126,7 @@ bool PECOFFLinkingContext::<u></u>createImplici<br>
auto exportNode = llvm::make_unique<<u></u>SimpleFileNode>("<export>");<br>
exportNode->appendInputFile(<br>
llvm::make_unique<pecoff::<u></u>ExportedSymbolRenameFile>(*<u></u>this, syms));<br>
- getLibraryGroup()->addFile(<u></u>std::move(exportNode));<br>
+ addLibraryFile(std::move(<u></u>exportNode));<br>
<br>
// Create a file for the entry point function.<br>
getEntryNode()-><u></u>appendInputFile(<br>
<br>
Modified: lld/trunk/unittests/<u></u>DriverTests/DriverTest.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/DriverTest.h?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/unittests/<u></u>DriverTests/DriverTest.h?rev=<u></u>223330&r1=223329&r2=223330&<u></u>view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/unittests/<u></u>DriverTests/DriverTest.h (original)<br>
+++ lld/trunk/unittests/<u></u>DriverTests/DriverTest.h Wed Dec 3 19:09:06 2014<br>
@@ -37,18 +37,6 @@ protected:<br>
llvm_unreachable("not handling other types of input files");<br>
}<br>
<br>
- // Convenience method for getting i'th input files name.<br>
- std::string inputFile(int index1, int index2) {<br>
- Group *group = dyn_cast<Group>(<br>
- linkingContext()-><u></u>getInputGraph().inputElements(<u></u>)[index1].get());<br>
- if (!group)<br>
- llvm_unreachable("not handling other types of input files");<br>
- FileNode *file = dyn_cast<FileNode>(group-><u></u>elements()[index2].get());<br>
- if (!file)<br>
- llvm_unreachable("not handling other types of input files");<br>
- return *file->getPath(*<u></u>linkingContext());<br>
- }<br>
-<br>
// For unit tests to call driver with various command lines.<br>
bool parse(const char *args, ...) {<br>
// Construct command line options from varargs.<br>
<br>
Modified: lld/trunk/unittests/<u></u>DriverTests/InputGraphTest.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/InputGraphTest.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/unittests/<u></u>DriverTests/InputGraphTest.<u></u>cpp?rev=223330&r1=223329&r2=<u></u>223330&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/unittests/<u></u>DriverTests/InputGraphTest.cpp (original)<br>
+++ lld/trunk/unittests/<u></u>DriverTests/InputGraphTest.cpp Wed Dec 3 19:09:06 2014<br>
@@ -77,7 +77,7 @@ protected:<br>
<br>
} // end anonymous namespace<br>
<br>
-static std::unique_ptr<TestFileNode> createFile1(StringRef name) {<br>
+static std::unique_ptr<TestFileNode> createFile(StringRef name) {<br>
std::vector<std::unique_ptr<<u></u>File>> files;<br>
files.push_back(std::unique_<u></u>ptr<SimpleFile>(new SimpleFile(name)));<br>
std::unique_ptr<TestFileNode> file(new TestFileNode("filenode"));<br>
@@ -85,109 +85,30 @@ static std::unique_ptr<TestFileNode> cre<br>
return file;<br>
}<br>
<br>
-static std::unique_ptr<TestFileNode> createFile2(StringRef name1,<br>
- StringRef name2) {<br>
- std::vector<std::unique_ptr<<u></u>File>> files;<br>
- files.push_back(std::unique_<u></u>ptr<SimpleFile>(new SimpleFile(name1)));<br>
- files.push_back(std::unique_<u></u>ptr<SimpleFile>(new SimpleFile(name2)));<br>
- std::unique_ptr<TestFileNode> file(new TestFileNode("filenode"));<br>
- file->addFiles(std::move(<u></u>files));<br>
- return file;<br>
-}<br>
-<br>
TEST_F(InputGraphTest, Empty) {<br>
expectEnd();<br>
}<br>
<br>
TEST_F(InputGraphTest, File) {<br>
- _graph->addInputElement(<u></u>createFile1("file1"));<br>
- EXPECT_EQ("file1", getNext());<br>
- expectEnd();<br>
-}<br>
-<br>
-TEST_F(InputGraphTest, Files) {<br>
- _graph->addInputElement(<u></u>createFile2("file1", "file2"));<br>
- EXPECT_EQ("file1", getNext());<br>
- EXPECT_EQ("file2", getNext());<br>
- expectEnd();<br>
-}<br>
-<br>
-TEST_F(InputGraphTest, Group) {<br>
- _graph->addInputElement(<u></u>createFile2("file1", "file2"));<br>
-<br>
- std::unique_ptr<Group> group(new Group());<br>
- group->addFile(createFile2("<u></u>file3", "file4"));<br>
- group->addFile(createFile1("<u></u>file5"));<br>
- group->addFile(createFile1("<u></u>file6"));<br>
- _graph->addInputElement(std::<u></u>move(group));<br>
-<br>
+ _graph->addInputElement(<u></u>createFile("file1"));<br>
EXPECT_EQ("file1", getNext());<br>
- EXPECT_EQ("file2", getNext());<br>
- EXPECT_EQ("file3", getNext());<br>
- EXPECT_EQ("file4", getNext());<br>
- EXPECT_EQ("file5", getNext());<br>
- EXPECT_EQ("file6", getNext());<br>
- expectEnd();<br>
-}<br>
-<br>
-// Iterate through the group<br>
-TEST_F(InputGraphTest, GroupIteration) {<br>
- _graph->addInputElement(<u></u>createFile2("file1", "file2"));<br>
-<br>
- std::unique_ptr<Group> group(new Group());<br>
- group->addFile(createFile2("<u></u>file3", "file4"));<br>
- group->addFile(createFile1("<u></u>file5"));<br>
- group->addFile(createFile1("<u></u>file6"));<br>
- _graph->addInputElement(std::<u></u>move(group));<br>
-<br>
- EXPECT_EQ("file1", getNext());<br>
- EXPECT_EQ("file2", getNext());<br>
-<br>
- EXPECT_EQ("file3", getNext());<br>
- EXPECT_EQ("file4", getNext());<br>
- EXPECT_EQ("file5", getNext());<br>
- EXPECT_EQ("file6", getNext());<br>
- _graph->notifyProgress();<br>
-<br>
- EXPECT_EQ("file3", getNext());<br>
- EXPECT_EQ("file4", getNext());<br>
- _graph->notifyProgress();<br>
- EXPECT_EQ("file5", getNext());<br>
- EXPECT_EQ("file6", getNext());<br>
-<br>
- EXPECT_EQ("file3", getNext());<br>
- EXPECT_EQ("file4", getNext());<br>
- EXPECT_EQ("file5", getNext());<br>
- EXPECT_EQ("file6", getNext());<br>
expectEnd();<br>
}<br>
<br>
// Node expansion tests<br>
TEST_F(InputGraphTest, Normalize) {<br>
- _graph->addInputElement(<u></u>createFile2("file1", "file2"));<br>
+ _graph->addInputElement(<u></u>createFile("file1"));<br>
<br>
std::unique_ptr<<u></u>TestExpandFileNode> expandFile(<br>
new TestExpandFileNode("node"));<br>
- expandFile->addElement(<u></u>createFile1("file3"));<br>
- expandFile->addElement(<u></u>createFile1("file4"));<br>
+ expandFile->addElement(<u></u>createFile("file2"));<br>
+ expandFile->addElement(<u></u>createFile("file3"));<br>
_graph->addInputElement(std::<u></u>move(expandFile));<br>
-<br>
- std::unique_ptr<Group> group(new Group());<br>
- std::unique_ptr<<u></u>TestExpandFileNode> expandFile2(<br>
- new TestExpandFileNode("node"));<br>
- expandFile2->addElement(<u></u>createFile1("file5"));<br>
- group->addFile(std::move(<u></u>expandFile2));<br>
- _graph->addInputElement(std::<u></u>move(group));<br>
-<br>
- _graph->addInputElement(<u></u>createFile1("file6"));<br>
_graph->normalize();<br>
<br>
EXPECT_EQ("file1", getNext());<br>
EXPECT_EQ("file2", getNext());<br>
EXPECT_EQ("file3", getNext());<br>
- EXPECT_EQ("file4", getNext());<br>
- EXPECT_EQ("file5", getNext());<br>
- EXPECT_EQ("file6", getNext());<br>
expectEnd();<br>
}<br>
<br>
@@ -195,8 +116,8 @@ TEST_F(InputGraphTest, Observer) {<br>
std::vector<std::string> files;<br>
_graph->registerObserver([&](<u></u>File *file) { files.push_back(file->path()); });<br>
<br>
- _graph->addInputElement(<u></u>createFile1("file1"));<br>
- _graph->addInputElement(<u></u>createFile1("file2"));<br>
+ _graph->addInputElement(<u></u>createFile("file1"));<br>
+ _graph->addInputElement(<u></u>createFile("file2"));<br>
EXPECT_EQ("file1", getNext());<br>
EXPECT_EQ("file2", getNext());<br>
expectEnd();<br>
<br>
Modified: lld/trunk/unittests/<u></u>DriverTests/WinLinkDriverTest.<u></u>cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/WinLinkDriverTest.cpp?rev=223330&r1=223329&r2=223330&view=diff" target="_blank">http://llvm.org/viewvc/llvm-<u></u>project/lld/trunk/unittests/<u></u>DriverTests/WinLinkDriverTest.<u></u>cpp?rev=223330&r1=223329&r2=<u></u>223330&view=diff</a><br>
==============================<u></u>==============================<u></u>==================<br>
--- lld/trunk/unittests/<u></u>DriverTests/WinLinkDriverTest.<u></u>cpp (original)<br>
+++ lld/trunk/unittests/<u></u>DriverTests/WinLinkDriverTest.<u></u>cpp Wed Dec 3 19:09:06 2014<br>
@@ -137,11 +137,11 @@ TEST_F(WinLinkParserTest, Libpath) {<br>
TEST_F(WinLinkParserTest, InputOrder) {<br>
EXPECT_TRUE(parse("link.exe", "a.lib", "b.obj", "c.obj", "a.lib", "d.obj",<br>
nullptr));<br>
- EXPECT_EQ(5, inputFileCount());<br>
+ EXPECT_EQ(6, inputFileCount());<br>
EXPECT_EQ("b.obj", inputFile(0));<br>
EXPECT_EQ("c.obj", inputFile(1));<br>
EXPECT_EQ("d.obj", inputFile(2));<br>
- EXPECT_EQ("a.lib", inputFile(4, 0));<br>
+ EXPECT_EQ("a.lib", inputFile(4));<br>
}<br>
<br>
//<br>
@@ -393,36 +393,36 @@ TEST_F(WinLinkParserTest, SectionMultipl<br>
TEST_F(WinLinkParserTest, DefaultLib) {<br>
EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",<br>
"/defaultlib:kernel32", "a.obj", nullptr));<br>
- EXPECT_EQ(3, inputFileCount());<br>
+ EXPECT_EQ(5, inputFileCount());<br>
EXPECT_EQ("a.obj", inputFile(0));<br>
- EXPECT_EQ("user32.lib", inputFile(2, 0));<br>
- EXPECT_EQ("kernel32.lib", inputFile(2, 1));<br>
+ EXPECT_EQ("user32.lib", inputFile(2));<br>
+ EXPECT_EQ("kernel32.lib", inputFile(3));<br>
}<br>
<br>
TEST_F(WinLinkParserTest, DefaultLibDuplicates) {<br>
EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",<br>
"/defaultlib:user32.lib", "a.obj", nullptr));<br>
- EXPECT_EQ(3, inputFileCount());<br>
+ EXPECT_EQ(4, inputFileCount());<br>
EXPECT_EQ("a.obj", inputFile(0));<br>
- EXPECT_EQ("user32.lib", inputFile(2, 0));<br>
+ EXPECT_EQ("user32.lib", inputFile(2));<br>
}<br>
<br>
TEST_F(WinLinkParserTest, NoDefaultLib) {<br>
EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",<br>
"/defaultlib:kernel32", "/nodefaultlib:user32.lib", "a.obj",<br>
nullptr));<br>
- EXPECT_EQ(3, inputFileCount());<br>
+ EXPECT_EQ(4, inputFileCount());<br>
EXPECT_EQ("a.obj", inputFile(0));<br>
- EXPECT_EQ("kernel32.lib", inputFile(2, 0));<br>
+ EXPECT_EQ("kernel32.lib", inputFile(2));<br>
}<br>
<br>
TEST_F(WinLinkParserTest, NoDefaultLibCase) {<br>
EXPECT_TRUE(parse("link.exe", "/defaultlib:user32",<br>
"/defaultlib:kernel32", "/nodefaultlib:USER32.LIB", "a.obj",<br>
nullptr));<br>
- EXPECT_EQ(3, inputFileCount());<br>
+ EXPECT_EQ(4, inputFileCount());<br>
EXPECT_EQ("a.obj", inputFile(0));<br>
- EXPECT_EQ("kernel32.lib", inputFile(2, 0));<br>
+ EXPECT_EQ("kernel32.lib", inputFile(2));<br>
}<br>
<br>
TEST_F(WinLinkParserTest, NoDefaultLibAll) {<br>
@@ -436,9 +436,9 @@ TEST_F(WinLinkParserTest, DisallowLib) {<br>
EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",<br>
"/defaultlib:kernel32", "/disallowlib:user32.lib", "a.obj",<br>
nullptr));<br>
- EXPECT_EQ(3, inputFileCount());<br>
+ EXPECT_EQ(4, inputFileCount());<br>
EXPECT_EQ("a.obj", inputFile(0));<br>
- EXPECT_EQ("kernel32.lib", inputFile(2, 0));<br>
+ EXPECT_EQ("kernel32.lib", inputFile(2));<br>
}<br>
<br>
//<br>
<br>
<br>
______________________________<br>
_________________<br>
llvm-commits mailing listllvm-commits@cs.uiuc.<u></u>eduhttp://<a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank">lists.cs.uiuc.edu/<u></u>mailman/listinfo/llvm-commits</a><br>
<br>
<br>
<br>
--<br>
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation<br>
<br>
<br>
<br>
<br>
<br>
--<br>
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation<br>
<br>
<br>
</div></div></blockquote></blockquote><div class=""><div class="h5">
<br>
<br>
-- <br>
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by the Linux Foundation<br>
<br>
</div></div></blockquote></div><br></div></div>