blob: 4d0fe6ed0e8e7ee55ac290052188ad323d090e8b [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"
Rui Ueyamaa5f28162015-01-06 23:06:49 +000011#include "lld/Core/ArchiveLibraryFile.h"
12#include "lld/Core/File.h"
Michael J. Spencerbd66d042013-05-28 18:55:39 +000013#include "lld/Core/Instrumentation.h"
Shankar Easwaran2b67fca2014-10-18 05:33:55 +000014#include "lld/Core/LLVM.h"
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000015#include "lld/Core/Parallel.h"
Shankar Easwaran2b67fca2014-10-18 05:33:55 +000016#include "lld/Core/PassManager.h"
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000017#include "lld/Core/Resolver.h"
Shankar Easwaran2bc24922013-10-29 05:12:14 +000018#include "lld/Passes/RoundTripNativePass.h"
19#include "lld/Passes/RoundTripYAMLPass.h"
Shankar Easwaran2b67fca2014-10-18 05:33:55 +000020#include "lld/ReaderWriter/Reader.h"
21#include "lld/ReaderWriter/Writer.h"
Nick Kledzikc314b462013-04-04 18:59:24 +000022#include "llvm/ADT/StringExtras.h"
23#include "llvm/ADT/StringSwitch.h"
24#include "llvm/Option/Arg.h"
25#include "llvm/Support/CommandLine.h"
26#include "llvm/Support/FileSystem.h"
27#include "llvm/Support/Path.h"
28#include "llvm/Support/raw_ostream.h"
Rui Ueyama74cc8e12013-10-08 23:01:52 +000029#include <mutex>
30
Nick Kledzikc314b462013-04-04 18:59:24 +000031namespace lld {
32
Rui Ueyamaa5f28162015-01-06 23:06:49 +000033FileVector makeErrorFile(StringRef path, std::error_code ec) {
34 std::vector<std::unique_ptr<File>> result;
35 result.push_back(llvm::make_unique<ErrorFile>(path, ec));
36 return result;
37}
38
39FileVector parseMemberFiles(FileVector &files) {
40 std::vector<std::unique_ptr<File>> members;
41 for (std::unique_ptr<File> &file : files) {
42 if (auto *archive = dyn_cast<ArchiveLibraryFile>(file.get())) {
43 if (std::error_code ec = archive->parseAllMembers(members))
44 return makeErrorFile(file->path(), ec);
45 } else {
46 members.push_back(std::move(file));
47 }
48 }
49 return members;
50}
51
Rui Ueyamadf230b22015-01-15 04:34:31 +000052FileVector loadFile(LinkingContext &ctx, StringRef path, bool wholeArchive) {
Rui Ueyamaa5f28162015-01-06 23:06:49 +000053 ErrorOr<std::unique_ptr<MemoryBuffer>> mb
54 = MemoryBuffer::getFileOrSTDIN(path);
55 if (std::error_code ec = mb.getError())
56 return makeErrorFile(path, ec);
57 std::vector<std::unique_ptr<File>> files;
Rui Ueyamadf230b22015-01-15 04:34:31 +000058 if (std::error_code ec = ctx.registry().loadFile(std::move(mb.get()), files))
Rui Ueyamaa5f28162015-01-06 23:06:49 +000059 return makeErrorFile(path, ec);
60 if (wholeArchive)
61 return parseMemberFiles(files);
62 return files;
63}
64
Nick Kledzikc314b462013-04-04 18:59:24 +000065/// This is where the link is actually performed.
Shankar Easwaran7f1146c2013-10-08 15:43:48 +000066bool Driver::link(LinkingContext &context, raw_ostream &diagnostics) {
Nick Kledzikc314b462013-04-04 18:59:24 +000067 // Honor -mllvm
Rui Ueyama0ca149f2013-08-06 22:31:59 +000068 if (!context.llvmOptions().empty()) {
69 unsigned numArgs = context.llvmOptions().size();
70 const char **args = new const char *[numArgs + 2];
Nick Kledzikc314b462013-04-04 18:59:24 +000071 args[0] = "lld (LLVM option parsing)";
72 for (unsigned i = 0; i != numArgs; ++i)
Rui Ueyama0ca149f2013-08-06 22:31:59 +000073 args[i + 1] = context.llvmOptions()[i];
Nick Kledzikc314b462013-04-04 18:59:24 +000074 args[numArgs + 1] = 0;
75 llvm::cl::ParseCommandLineOptions(numArgs + 1, args);
76 }
Rui Ueyama8bd093b2014-04-04 00:14:04 +000077 InputGraph &inputGraph = context.getInputGraph();
Shankar Easwarana96f3a32013-10-07 02:47:09 +000078 if (!inputGraph.size())
Rui Ueyama8db1edd2013-09-24 23:26:34 +000079 return false;
Rui Ueyamacfb25342015-01-14 00:21:34 +000080 inputGraph.normalize();
Nick Kledzikc314b462013-04-04 18:59:24 +000081
Shankar Easwarana96f3a32013-10-07 02:47:09 +000082 bool fail = false;
83
Nick Kledzikc314b462013-04-04 18:59:24 +000084 // Read inputs
Michael J. Spencerbd66d042013-05-28 18:55:39 +000085 ScopedTask readTask(getDefaultDomain(), "Read Args");
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000086 TaskGroup tg;
Rui Ueyama74cc8e12013-10-08 23:01:52 +000087 std::mutex diagnosticsMutex;
Rui Ueyama69fcde82014-04-03 20:47:50 +000088 for (std::unique_ptr<InputElement> &ie : inputGraph.inputElements()) {
Rui Ueyamaa1490d62013-10-11 22:02:58 +000089 tg.spawn([&] {
Rui Ueyama74cc8e12013-10-08 23:01:52 +000090 // Writes to the same output stream is not guaranteed to be thread-safe.
91 // We buffer the diagnostics output to a separate string-backed output
92 // stream, acquire the lock, and then print it out.
93 std::string buf;
94 llvm::raw_string_ostream stream(buf);
95
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +000096 if (std::error_code ec = ie->parse(context, stream)) {
Simon Atanasyana64f34b2014-04-30 19:04:01 +000097 if (FileNode *fileNode = dyn_cast<FileNode>(ie.get()))
98 stream << fileNode->errStr(ec) << "\n";
Simon Atanasyana64f34b2014-04-30 19:04:01 +000099 else
100 llvm_unreachable("Unknown type of input element");
Michael J. Spencere5b8fe12013-05-28 18:37:39 +0000101 fail = true;
Michael J. Spencere5b8fe12013-05-28 18:37:39 +0000102 }
Rui Ueyama74cc8e12013-10-08 23:01:52 +0000103
104 stream.flush();
105 if (!buf.empty()) {
106 std::lock_guard<std::mutex> lock(diagnosticsMutex);
107 diagnostics << buf;
108 }
Michael J. Spencere5b8fe12013-05-28 18:37:39 +0000109 });
Nick Kledzikc314b462013-04-04 18:59:24 +0000110 }
Michael J. Spencere5b8fe12013-05-28 18:37:39 +0000111 tg.sync();
Michael J. Spencerbd66d042013-05-28 18:55:39 +0000112 readTask.end();
Michael J. Spencere5b8fe12013-05-28 18:37:39 +0000113
114 if (fail)
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000115 return false;
Michael J. Spencere5b8fe12013-05-28 18:37:39 +0000116
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000117 InputGraph::FileVectorT internalFiles;
118 context.createInternalFiles(internalFiles);
Rui Ueyama00eb2572014-12-10 00:33:00 +0000119 for (auto i = internalFiles.rbegin(), e = internalFiles.rend(); i != e; ++i) {
120 context.getInputGraph().addInputElementFront(
121 llvm::make_unique<SimpleFileNode>("internal", std::move(*i)));
122 }
Nick Kledzikc314b462013-04-04 18:59:24 +0000123
124 // Give target a chance to add files.
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000125 InputGraph::FileVectorT implicitFiles;
126 context.createImplicitFiles(implicitFiles);
Rui Ueyama00eb2572014-12-10 00:33:00 +0000127 for (auto i = implicitFiles.rbegin(), e = implicitFiles.rend(); i != e; ++i) {
128 context.getInputGraph().addInputElementFront(
129 llvm::make_unique<SimpleFileNode>("implicit", std::move(*i)));
130 }
131
132 // Give target a chance to sort the input files.
133 // Mach-O uses this chance to move all object files before library files.
134 context.maybeSortInputFiles();
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000135
Nick Kledzikc314b462013-04-04 18:59:24 +0000136 // Do core linking.
Michael J. Spencerbd66d042013-05-28 18:55:39 +0000137 ScopedTask resolveTask(getDefaultDomain(), "Resolve");
Shankar Easwarana96f3a32013-10-07 02:47:09 +0000138 Resolver resolver(context);
Rui Ueyamaf1e26682013-10-11 06:16:35 +0000139 if (!resolver.resolve())
140 return false;
Shankar Easwaran2bc24922013-10-29 05:12:14 +0000141 std::unique_ptr<MutableFile> merged = resolver.resultFile();
Michael J. Spencerbd66d042013-05-28 18:55:39 +0000142 resolveTask.end();
Nick Kledzikc314b462013-04-04 18:59:24 +0000143
144 // Run passes on linked atoms.
Michael J. Spencerbd66d042013-05-28 18:55:39 +0000145 ScopedTask passTask(getDefaultDomain(), "Passes");
Nick Kledzikc314b462013-04-04 18:59:24 +0000146 PassManager pm;
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000147 context.addPasses(pm);
Shankar Easwaran2bc24922013-10-29 05:12:14 +0000148
Rui Ueyamaaa5b4dc2013-11-01 21:05:42 +0000149#ifndef NDEBUG
Shankar Easwaran28955272014-12-01 01:04:11 +0000150 if (context.runRoundTripPass()) {
Rui Ueyamabc6b52e2014-03-20 02:49:33 +0000151 pm.add(std::unique_ptr<Pass>(new RoundTripYAMLPass(context)));
152 pm.add(std::unique_ptr<Pass>(new RoundTripNativePass(context)));
153 }
Shankar Easwaran2bc24922013-10-29 05:12:14 +0000154#endif
155
Nick Kledzikc314b462013-04-04 18:59:24 +0000156 pm.runOnFile(merged);
Michael J. Spencerbd66d042013-05-28 18:55:39 +0000157 passTask.end();
Nick Kledzikc314b462013-04-04 18:59:24 +0000158
159 // Give linked atoms to Writer to generate output file.
Michael J. Spencerbd66d042013-05-28 18:55:39 +0000160 ScopedTask writeTask(getDefaultDomain(), "Write");
Rafael Espindolab1a4d3a2014-06-12 14:53:47 +0000161 if (std::error_code ec = context.writeFile(*merged)) {
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000162 diagnostics << "Failed to write file '" << context.outputPath()
Rafael Espindola66c0a652013-07-15 23:55:07 +0000163 << "': " << ec.message() << "\n";
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000164 return false;
Nick Kledzikc314b462013-04-04 18:59:24 +0000165 }
166
Rui Ueyama8db1edd2013-09-24 23:26:34 +0000167 return true;
Nick Kledzikc314b462013-04-04 18:59:24 +0000168}
169
Nick Kledzikc314b462013-04-04 18:59:24 +0000170} // namespace