diff options
Diffstat (limited to 'tools/lld/lld.cpp')
| -rw-r--r-- | tools/lld/lld.cpp | 107 |
1 files changed, 64 insertions, 43 deletions
diff --git a/tools/lld/lld.cpp b/tools/lld/lld.cpp index c749d458a992..37ef260495e9 100644 --- a/tools/lld/lld.cpp +++ b/tools/lld/lld.cpp @@ -1,9 +1,8 @@ //===- tools/lld/lld.cpp - Linker Driver Dispatcher -----------------------===// // -// The LLVM Linker -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // @@ -27,9 +26,13 @@ //===----------------------------------------------------------------------===// #include "lld/Common/Driver.h" +#include "lld/Common/Memory.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" #include "llvm/ADT/Twine.h" +#include "llvm/Support/CommandLine.h" #include "llvm/Support/InitLLVM.h" #include "llvm/Support/Path.h" #include <cstdlib> @@ -46,13 +49,13 @@ enum Flavor { Wasm, // -flavor wasm }; -LLVM_ATTRIBUTE_NORETURN static void die(const Twine &S) { - errs() << S << "\n"; +LLVM_ATTRIBUTE_NORETURN static void die(const Twine &s) { + errs() << s << "\n"; exit(1); } -static Flavor getFlavor(StringRef S) { - return StringSwitch<Flavor>(S) +static Flavor getFlavor(StringRef s) { + return StringSwitch<Flavor>(s) .CasesLower("ld", "ld.lld", "gnu", Gnu) .CasesLower("wasm", "ld-wasm", Wasm) .CaseLower("link", WinLink) @@ -60,55 +63,73 @@ static Flavor getFlavor(StringRef S) { .Default(Invalid); } -static bool isPETarget(const std::vector<const char *> &V) { - for (auto It = V.begin(); It + 1 != V.end(); ++It) { - if (StringRef(*It) != "-m") +static cl::TokenizerCallback getDefaultQuotingStyle() { + if (Triple(sys::getProcessTriple()).getOS() == Triple::Win32) + return cl::TokenizeWindowsCommandLine; + return cl::TokenizeGNUCommandLine; +} + +static bool isPETargetName(StringRef s) { + return s == "i386pe" || s == "i386pep" || s == "thumb2pe" || s == "arm64pe"; +} + +static bool isPETarget(std::vector<const char *> &v) { + for (auto it = v.begin(); it + 1 != v.end(); ++it) { + if (StringRef(*it) != "-m") + continue; + return isPETargetName(*(it + 1)); + } + // Expand response files (arguments in the form of @<filename>) + // to allow detecting the -m argument from arguments in them. + SmallVector<const char *, 256> expandedArgs(v.data(), v.data() + v.size()); + cl::ExpandResponseFiles(saver, getDefaultQuotingStyle(), expandedArgs); + for (auto it = expandedArgs.begin(); it + 1 != expandedArgs.end(); ++it) { + if (StringRef(*it) != "-m") continue; - StringRef S = *(It + 1); - return S == "i386pe" || S == "i386pep" || S == "thumb2pe" || S == "arm64pe"; + return isPETargetName(*(it + 1)); } return false; } -static Flavor parseProgname(StringRef Progname) { +static Flavor parseProgname(StringRef progname) { #if __APPLE__ // Use Darwin driver for "ld" on Darwin. - if (Progname == "ld") + if (progname == "ld") return Darwin; #endif #if LLVM_ON_UNIX // Use GNU driver for "ld" on other Unix-like system. - if (Progname == "ld") + if (progname == "ld") return Gnu; #endif // Progname may be something like "lld-gnu". Parse it. - SmallVector<StringRef, 3> V; - Progname.split(V, "-"); - for (StringRef S : V) - if (Flavor F = getFlavor(S)) - return F; + SmallVector<StringRef, 3> v; + progname.split(v, "-"); + for (StringRef s : v) + if (Flavor f = getFlavor(s)) + return f; return Invalid; } -static Flavor parseFlavor(std::vector<const char *> &V) { +static Flavor parseFlavor(std::vector<const char *> &v) { // Parse -flavor option. - if (V.size() > 1 && V[1] == StringRef("-flavor")) { - if (V.size() <= 2) + if (v.size() > 1 && v[1] == StringRef("-flavor")) { + if (v.size() <= 2) die("missing arg value for '-flavor'"); - Flavor F = getFlavor(V[2]); - if (F == Invalid) - die("Unknown flavor: " + StringRef(V[2])); - V.erase(V.begin() + 1, V.begin() + 3); - return F; + Flavor f = getFlavor(v[2]); + if (f == Invalid) + die("Unknown flavor: " + StringRef(v[2])); + v.erase(v.begin() + 1, v.begin() + 3); + return f; } // Deduct the flavor from argv[0]. - StringRef Arg0 = path::filename(V[0]); - if (Arg0.endswith_lower(".exe")) - Arg0 = Arg0.drop_back(4); - return parseProgname(Arg0); + StringRef arg0 = path::filename(v[0]); + if (arg0.endswith_lower(".exe")) + arg0 = arg0.drop_back(4); + return parseProgname(arg0); } // If this function returns true, lld calls _exit() so that it quickly @@ -121,21 +142,21 @@ static bool canExitEarly() { return StringRef(getenv("LLD_IN_TEST")) != "1"; } /// Universal linker main(). This linker emulates the gnu, darwin, or /// windows linker based on the argv[0] or -flavor option. -int main(int Argc, const char **Argv) { - InitLLVM X(Argc, Argv); +int main(int argc, const char **argv) { + InitLLVM x(argc, argv); - std::vector<const char *> Args(Argv, Argv + Argc); - switch (parseFlavor(Args)) { + std::vector<const char *> args(argv, argv + argc); + switch (parseFlavor(args)) { case Gnu: - if (isPETarget(Args)) - return !mingw::link(Args); - return !elf::link(Args, canExitEarly()); + if (isPETarget(args)) + return !mingw::link(args); + return !elf::link(args, canExitEarly()); case WinLink: - return !coff::link(Args, canExitEarly()); + return !coff::link(args, canExitEarly()); case Darwin: - return !mach_o::link(Args, canExitEarly()); + return !mach_o::link(args, canExitEarly()); case Wasm: - return !wasm::link(Args, canExitEarly()); + return !wasm::link(args, canExitEarly()); default: die("lld is a generic driver.\n" "Invoke ld.lld (Unix), ld64.lld (macOS), lld-link (Windows), wasm-ld" |
