blob: a0233fef74d485ec0d7c79d2bc94b31a92c3393b [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"
13#include "lld/Core/InputFiles.h"
Michael J. Spencerbd66d042013-05-28 18:55:39 +000014#include "lld/Core/Instrumentation.h"
Nick Kledzikc314b462013-04-04 18:59:24 +000015#include "lld/Core/PassManager.h"
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000016#include "lld/Core/Parallel.h"
17#include "lld/Core/Resolver.h"
Nick Kledzikc314b462013-04-04 18:59:24 +000018#include "lld/ReaderWriter/Reader.h"
19#include "lld/ReaderWriter/Writer.h"
Michael J. Spencer9ff4be22012-12-08 00:47:36 +000020
Nick Kledzikc314b462013-04-04 18:59:24 +000021#include "llvm/ADT/StringExtras.h"
22#include "llvm/ADT/StringSwitch.h"
23#include "llvm/Option/Arg.h"
24#include "llvm/Support/CommandLine.h"
25#include "llvm/Support/FileSystem.h"
26#include "llvm/Support/Path.h"
27#include "llvm/Support/raw_ostream.h"
Michael J. Spencer9ff4be22012-12-08 00:47:36 +000028
Nick Kledzikc314b462013-04-04 18:59:24 +000029namespace lld {
30
31/// This is where the link is actually performed.
Rafael Espindola66c0a652013-07-15 23:55:07 +000032bool Driver::link(const TargetInfo &targetInfo, raw_ostream &diagnostics) {
Nick Kledzikc314b462013-04-04 18:59:24 +000033 // Honor -mllvm
34 if (!targetInfo.llvmOptions().empty()) {
35 unsigned numArgs = targetInfo.llvmOptions().size();
36 const char **args = new const char*[numArgs + 2];
37 args[0] = "lld (LLVM option parsing)";
38 for (unsigned i = 0; i != numArgs; ++i)
39 args[i + 1] = targetInfo.llvmOptions()[i];
40 args[numArgs + 1] = 0;
41 llvm::cl::ParseCommandLineOptions(numArgs + 1, args);
42 }
43
44 // Read inputs
Michael J. Spencerbd66d042013-05-28 18:55:39 +000045 ScopedTask readTask(getDefaultDomain(), "Read Args");
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000046 std::vector<std::vector<std::unique_ptr<File>>> files(
47 targetInfo.inputFiles().size());
48 size_t index = 0;
49 std::atomic<bool> fail(false);
50 TaskGroup tg;
Nick Kledzikc314b462013-04-04 18:59:24 +000051 for (const auto &input : targetInfo.inputFiles()) {
Nick Kledzikc314b462013-04-04 18:59:24 +000052 if (targetInfo.logInputFiles())
53 llvm::outs() << input.getPath() << "\n";
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000054
Rafael Espindola66c0a652013-07-15 23:55:07 +000055 tg.spawn([&, index] {
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000056 if (error_code ec = targetInfo.readFile(input.getPath(), files[index])) {
Rafael Espindola66c0a652013-07-15 23:55:07 +000057 diagnostics << "Failed to read file: " << input.getPath()
58 << ": " << ec.message() << "\n";
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000059 fail = true;
60 return;
61 }
62 });
63 ++index;
Nick Kledzikc314b462013-04-04 18:59:24 +000064 }
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000065 tg.sync();
Michael J. Spencerbd66d042013-05-28 18:55:39 +000066 readTask.end();
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000067
68 if (fail)
69 return true;
70
71 InputFiles inputs;
72 for (auto &f : files)
73 inputs.appendFiles(f);
Nick Kledzikc314b462013-04-04 18:59:24 +000074
75 // Give target a chance to add files.
76 targetInfo.addImplicitFiles(inputs);
77
78 // assign an ordinal to each file so sort() can preserve command line order
79 inputs.assignFileOrdinals();
80
81 // Do core linking.
Michael J. Spencerbd66d042013-05-28 18:55:39 +000082 ScopedTask resolveTask(getDefaultDomain(), "Resolve");
Nick Kledzikc314b462013-04-04 18:59:24 +000083 Resolver resolver(targetInfo, inputs);
84 if (resolver.resolve()) {
85 if (!targetInfo.allowRemainingUndefines())
86 return true;
87 }
88 MutableFile &merged = resolver.resultFile();
Michael J. Spencerbd66d042013-05-28 18:55:39 +000089 resolveTask.end();
Nick Kledzikc314b462013-04-04 18:59:24 +000090
91 // Run passes on linked atoms.
Michael J. Spencerbd66d042013-05-28 18:55:39 +000092 ScopedTask passTask(getDefaultDomain(), "Passes");
Nick Kledzikc314b462013-04-04 18:59:24 +000093 PassManager pm;
94 targetInfo.addPasses(pm);
95 pm.runOnFile(merged);
Michael J. Spencerbd66d042013-05-28 18:55:39 +000096 passTask.end();
Nick Kledzikc314b462013-04-04 18:59:24 +000097
98 // Give linked atoms to Writer to generate output file.
Michael J. Spencerbd66d042013-05-28 18:55:39 +000099 ScopedTask writeTask(getDefaultDomain(), "Write");
Nick Kledzikc314b462013-04-04 18:59:24 +0000100 if (error_code ec = targetInfo.writeFile(merged)) {
Rafael Espindola66c0a652013-07-15 23:55:07 +0000101 diagnostics << "Failed to write file '" << targetInfo.outputPath()
102 << "': " << ec.message() << "\n";
Nick Kledzikc314b462013-04-04 18:59:24 +0000103 return true;
104 }
105
106 return false;
107}
108
109
110} // namespace
111