blob: d76bbdd31d4e81cc828d0164d2cd3e9d3d5fd353 [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.
Rui Ueyama0ca149f2013-08-06 22:31:59 +000032bool Driver::link(const LinkingContext &context, raw_ostream &diagnostics) {
Nick Kledzikc314b462013-04-04 18:59:24 +000033 // Honor -mllvm
Rui Ueyama0ca149f2013-08-06 22:31:59 +000034 if (!context.llvmOptions().empty()) {
35 unsigned numArgs = context.llvmOptions().size();
36 const char **args = new const char *[numArgs + 2];
Nick Kledzikc314b462013-04-04 18:59:24 +000037 args[0] = "lld (LLVM option parsing)";
38 for (unsigned i = 0; i != numArgs; ++i)
Rui Ueyama0ca149f2013-08-06 22:31:59 +000039 args[i + 1] = context.llvmOptions()[i];
Nick Kledzikc314b462013-04-04 18:59:24 +000040 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");
Rui Ueyama0ca149f2013-08-06 22:31:59 +000046 std::vector<std::vector<std::unique_ptr<File>> > files(
47 context.inputFiles().size());
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000048 size_t index = 0;
49 std::atomic<bool> fail(false);
50 TaskGroup tg;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000051 for (const auto &input : context.inputFiles()) {
52 if (context.logInputFiles())
Nick Kledzikc314b462013-04-04 18:59:24 +000053 llvm::outs() << input.getPath() << "\n";
Michael J. Spencere5b8fe12013-05-28 18:37:39 +000054
Rui Ueyama0ca149f2013-08-06 22:31:59 +000055 tg.spawn([ &, index]{
56 if (error_code ec = context.readFile(input.getPath(), files[index])) {
57 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.
Rui Ueyama0ca149f2013-08-06 22:31:59 +000076 context.addImplicitFiles(inputs);
Nick Kledzikc314b462013-04-04 18:59:24 +000077
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");
Rui Ueyama0ca149f2013-08-06 22:31:59 +000083 Resolver resolver(context, inputs);
Nick Kledzikc314b462013-04-04 18:59:24 +000084 if (resolver.resolve()) {
Rui Ueyama0ca149f2013-08-06 22:31:59 +000085 if (!context.allowRemainingUndefines())
Nick Kledzikc314b462013-04-04 18:59:24 +000086 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;
Rui Ueyama0ca149f2013-08-06 22:31:59 +000094 context.addPasses(pm);
Nick Kledzikc314b462013-04-04 18:59:24 +000095 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");
Rui Ueyama0ca149f2013-08-06 22:31:59 +0000100 if (error_code ec = context.writeFile(merged)) {
101 diagnostics << "Failed to write file '" << context.outputPath()
Rafael Espindola66c0a652013-07-15 23:55:07 +0000102 << "': " << ec.message() << "\n";
Nick Kledzikc314b462013-04-04 18:59:24 +0000103 return true;
104 }
105
106 return false;
107}
108
Nick Kledzikc314b462013-04-04 18:59:24 +0000109} // namespace