blob: 6fdb34399fe669b17ded1b20b65d0f046a807d63 [file] [log] [blame]
Michael J. Spencer9ff4be22012-12-08 00:47:36 +00001//===- lib/Driver/Driver.cpp - Linker Driver Emulator ---------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "lld/Driver/Driver.h"
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000011
Nick Kledzikc314b462013-04-04 18:59:24 +000012#include "lld/Core/LLVM.h"
Michael J. Spencerbd66d042013-05-28 18:55:39 +000013#include "lld/Core/Instrumentation.h"
Nick Kledzikc314b462013-04-04 18:59:24 +000014#include "lld/Core/PassManager.h"
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000015#include "lld/Core/Parallel.h"
16#include "lld/Core/Resolver.h"
Nick Kledzikc314b462013-04-04 18:59:24 +000017#include "lld/ReaderWriter/Reader.h"
18#include "lld/ReaderWriter/Writer.h"
Michael J. Spencer9ff4be22012-12-08 00:47:36 +000019
Nick Kledzikc314b462013-04-04 18:59:24 +000020#include "llvm/ADT/StringExtras.h"
21#include "llvm/ADT/StringSwitch.h"
22#include "llvm/Option/Arg.h"
23#include "llvm/Support/CommandLine.h"
24#include "llvm/Support/FileSystem.h"
25#include "llvm/Support/Path.h"
26#include "llvm/Support/raw_ostream.h"
Michael J. Spencer9ff4be22012-12-08 00:47:36 +000027
Rui Ueyama74cc8e12013-10-08 23:01:52 +000028#include <mutex>
29
Nick Kledzikc314b462013-04-04 18:59:24 +000030namespace lld {
31
32/// This is where the link is actually performed.
Shankar Easwaran7f1146c2013-10-08 15:43:48 +000033bool Driver::link(LinkingContext &context, raw_ostream &diagnostics) {
Nick Kledzikc314b462013-04-04 18:59:24 +000034 // Honor -mllvm
Rui Ueyama0ca149f2013-08-06 22:31:59 +000035 if (!context.llvmOptions().empty()) {
36 unsigned numArgs = context.llvmOptions().size();
37 const char **args = new const char *[numArgs + 2];
Nick Kledzikc314b462013-04-04 18:59:24 +000038 args[0] = "lld (LLVM option parsing)";
39 for (unsigned i = 0; i != numArgs; ++i)
Rui Ueyama0ca149f2013-08-06 22:31:59 +000040 args[i + 1] = context.llvmOptions()[i];
Nick Kledzikc314b462013-04-04 18:59:24 +000041 args[numArgs + 1] = 0;
42 llvm::cl::ParseCommandLineOptions(numArgs + 1, args);
43 }
Shankar Easwarane44104b2013-08-21 22:57:10 +000044 InputGraph &inputGraph = context.inputGraph();
Shankar Easwarana96f3a32013-10-07 02:47:09 +000045 if (!inputGraph.size())
Rui Ueyama8db1edd2013-09-24 23:26:34 +000046 return false;
Nick Kledzikc314b462013-04-04 18:59:24 +000047
Shankar Easwarana96f3a32013-10-07 02:47:09 +000048 bool fail = false;
49
Nick Kledzikc314b462013-04-04 18:59:24 +000050 // Read inputs
Michael J. Spencerbd66d042013-05-28 18:55:39 +000051 ScopedTask readTask(getDefaultDomain(), "Read Args");
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000052 TaskGroup tg;
Shankar Easwarana96f3a32013-10-07 02:47:09 +000053 int index = 0;
Rui Ueyama74cc8e12013-10-08 23:01:52 +000054 std::mutex diagnosticsMutex;
Shankar Easwarand26c8e32013-08-31 05:27:38 +000055 for (auto &ie : inputGraph.inputElements()) {
Shankar Easwarana96f3a32013-10-07 02:47:09 +000056 tg.spawn([&, index] {
Rui Ueyama74cc8e12013-10-08 23:01:52 +000057 // Writes to the same output stream is not guaranteed to be thread-safe.
58 // We buffer the diagnostics output to a separate string-backed output
59 // stream, acquire the lock, and then print it out.
60 std::string buf;
61 llvm::raw_string_ostream stream(buf);
62
63 if (error_code ec = ie->parse(context, stream)) {
64 FileNode *fileNode = llvm::dyn_cast<FileNode>(ie.get());
65 stream << fileNode->errStr(ec) << "\n";
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000066 fail = true;
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000067 }
Rui Ueyama74cc8e12013-10-08 23:01:52 +000068
69 stream.flush();
70 if (!buf.empty()) {
71 std::lock_guard<std::mutex> lock(diagnosticsMutex);
72 diagnostics << buf;
73 }
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000074 });
75 ++index;
Nick Kledzikc314b462013-04-04 18:59:24 +000076 }
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000077 tg.sync();
Michael J. Spencerbd66d042013-05-28 18:55:39 +000078 readTask.end();
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000079
80 if (fail)
Rui Ueyama8db1edd2013-09-24 23:26:34 +000081 return false;
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000082
Shankar Easwarana96f3a32013-10-07 02:47:09 +000083 std::unique_ptr<SimpleFileNode> fileNode(
84 new SimpleFileNode("Internal Files"));
Shankar Easwarand26c8e32013-08-31 05:27:38 +000085
Shankar Easwarana96f3a32013-10-07 02:47:09 +000086 InputGraph::FileVectorT internalFiles;
87 context.createInternalFiles(internalFiles);
Shankar Easwarand26c8e32013-08-31 05:27:38 +000088
Shankar Easwarana96f3a32013-10-07 02:47:09 +000089 if (internalFiles.size()) {
90 fileNode->appendInputFiles(std::move(internalFiles));
91 }
Nick Kledzikc314b462013-04-04 18:59:24 +000092
93 // Give target a chance to add files.
Shankar Easwarana96f3a32013-10-07 02:47:09 +000094 InputGraph::FileVectorT implicitFiles;
95 context.createImplicitFiles(implicitFiles);
96 if (implicitFiles.size()) {
97 fileNode->appendInputFiles(std::move(implicitFiles));
98 }
Nick Kledzikc314b462013-04-04 18:59:24 +000099
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000100 context.inputGraph().insertOneElementAt(std::move(fileNode),
101 InputGraph::Position::BEGIN);
102
103 context.inputGraph().assignOrdinals();
104
105 context.inputGraph().doPostProcess();
106
Nick Kledzikc314b462013-04-04 18:59:24 +0000107 // Do core linking.
Michael J. Spencerbd66d042013-05-28 18:55:39 +0000108 ScopedTask resolveTask(getDefaultDomain(), "Resolve");
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000109 Resolver resolver(context);
Rui Ueyamaee366042013-10-11 06:16:33 +0000110 if (!resolver.resolve()) {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000111 if (!context.allowRemainingUndefines())
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000112 return false;
Nick Kledzikc314b462013-04-04 18:59:24 +0000113 }
114 MutableFile &merged = resolver.resultFile();
Michael J. Spencerbd66d042013-05-28 18:55:39 +0000115 resolveTask.end();
Nick Kledzikc314b462013-04-04 18:59:24 +0000116
117 // Run passes on linked atoms.
Michael J. Spencerbd66d042013-05-28 18:55:39 +0000118 ScopedTask passTask(getDefaultDomain(), "Passes");
Nick Kledzikc314b462013-04-04 18:59:24 +0000119 PassManager pm;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000120 context.addPasses(pm);
Nick Kledzikc314b462013-04-04 18:59:24 +0000121 pm.runOnFile(merged);
Michael J. Spencerbd66d042013-05-28 18:55:39 +0000122 passTask.end();
Nick Kledzikc314b462013-04-04 18:59:24 +0000123
124 // Give linked atoms to Writer to generate output file.
Michael J. Spencerbd66d042013-05-28 18:55:39 +0000125 ScopedTask writeTask(getDefaultDomain(), "Write");
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000126 if (error_code ec = context.writeFile(merged)) {
127 diagnostics << "Failed to write file '" << context.outputPath()
Rafael Espindola66c0a652013-07-15 23:55:07 +0000128 << "': " << ec.message() << "\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000129 return false;
Nick Kledzikc314b462013-04-04 18:59:24 +0000130 }
131
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000132 return true;
Nick Kledzikc314b462013-04-04 18:59:24 +0000133}
134
Nick Kledzikc314b462013-04-04 18:59:24 +0000135} // namespace