]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lld/tools/lld/lld.cpp
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lld / tools / lld / lld.cpp
1 //===- tools/lld/lld.cpp - Linker Driver Dispatcher -----------------------===//
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 // This file contains the main function of the lld executable. The main
11 // function is a thin wrapper which dispatches to the platform specific
12 // driver.
13 //
14 // lld is a single executable that contains four different linkers for ELF,
15 // COFF, WebAssembly and Mach-O. The main function dispatches according to
16 // argv[0] (i.e. command name). The most common name for each target is shown
17 // below:
18 //
19 //  - ld.lld:    ELF (Unix)
20 //  - ld64:      Mach-O (macOS)
21 //  - lld-link:  COFF (Windows)
22 //  - ld-wasm:   WebAssembly
23 //
24 // lld can be invoked as "lld" along with "-flavor" option. This is for
25 // backward compatibility and not recommended.
26 //
27 //===----------------------------------------------------------------------===//
28
29 #include "lld/Common/Driver.h"
30 #include "llvm/ADT/STLExtras.h"
31 #include "llvm/ADT/StringSwitch.h"
32 #include "llvm/ADT/Twine.h"
33 #include "llvm/Support/InitLLVM.h"
34 #include "llvm/Support/Path.h"
35 #include <cstdlib>
36
37 using namespace lld;
38 using namespace llvm;
39 using namespace llvm::sys;
40
41 enum Flavor {
42   Invalid,
43   Gnu,     // -flavor gnu
44   WinLink, // -flavor link
45   Darwin,  // -flavor darwin
46   Wasm,    // -flavor wasm
47 };
48
49 LLVM_ATTRIBUTE_NORETURN static void die(const Twine &S) {
50   errs() << S << "\n";
51   exit(1);
52 }
53
54 static Flavor getFlavor(StringRef S) {
55   return StringSwitch<Flavor>(S)
56       .CasesLower("ld", "ld.lld", "gnu", Gnu)
57       .CasesLower("wasm", "ld-wasm", Wasm)
58       .CaseLower("link", WinLink)
59       .CasesLower("ld64", "ld64.lld", "darwin", Darwin)
60       .Default(Invalid);
61 }
62
63 static bool isPETarget(const std::vector<const char *> &V) {
64   for (auto It = V.begin(); It + 1 != V.end(); ++It) {
65     if (StringRef(*It) != "-m")
66       continue;
67     StringRef S = *(It + 1);
68     return S == "i386pe" || S == "i386pep" || S == "thumb2pe" || S == "arm64pe";
69   }
70   return false;
71 }
72
73 static Flavor parseProgname(StringRef Progname) {
74 #if __APPLE__
75   // Use Darwin driver for "ld" on Darwin.
76   if (Progname == "ld")
77     return Darwin;
78 #endif
79
80 #if LLVM_ON_UNIX
81   // Use GNU driver for "ld" on other Unix-like system.
82   if (Progname == "ld")
83     return Gnu;
84 #endif
85
86   // Progname may be something like "lld-gnu". Parse it.
87   SmallVector<StringRef, 3> V;
88   Progname.split(V, "-");
89   for (StringRef S : V)
90     if (Flavor F = getFlavor(S))
91       return F;
92   return Invalid;
93 }
94
95 static Flavor parseFlavor(std::vector<const char *> &V) {
96   // Parse -flavor option.
97   if (V.size() > 1 && V[1] == StringRef("-flavor")) {
98     if (V.size() <= 2)
99       die("missing arg value for '-flavor'");
100     Flavor F = getFlavor(V[2]);
101     if (F == Invalid)
102       die("Unknown flavor: " + StringRef(V[2]));
103     V.erase(V.begin() + 1, V.begin() + 3);
104     return F;
105   }
106
107   // Deduct the flavor from argv[0].
108   StringRef Arg0 = path::filename(V[0]);
109   if (Arg0.endswith_lower(".exe"))
110     Arg0 = Arg0.drop_back(4);
111   return parseProgname(Arg0);
112 }
113
114 // If this function returns true, lld calls _exit() so that it quickly
115 // exits without invoking destructors of globally allocated objects.
116 //
117 // We don't want to do that if we are running tests though, because
118 // doing that breaks leak sanitizer. So, lit sets this environment variable,
119 // and we use it to detect whether we are running tests or not.
120 static bool canExitEarly() { return StringRef(getenv("LLD_IN_TEST")) != "1"; }
121
122 /// Universal linker main(). This linker emulates the gnu, darwin, or
123 /// windows linker based on the argv[0] or -flavor option.
124 int main(int Argc, const char **Argv) {
125   InitLLVM X(Argc, Argv);
126
127   std::vector<const char *> Args(Argv, Argv + Argc);
128 #ifdef __FreeBSD__
129   return !elf::link(Args, true);
130 #else
131   switch (parseFlavor(Args)) {
132   case Gnu:
133     if (isPETarget(Args))
134       return !mingw::link(Args);
135     return !elf::link(Args, canExitEarly());
136   case WinLink:
137     return !coff::link(Args, canExitEarly());
138   case Darwin:
139     return !mach_o::link(Args, canExitEarly());
140   case Wasm:
141     return !wasm::link(Args, canExitEarly());
142   default:
143     die("lld is a generic driver.\n"
144         "Invoke ld.lld (Unix), ld64.lld (macOS), lld-link (Windows), wasm-lld"
145         " (WebAssembly) instead");
146   }
147 #endif
148 }