xref: /llvm-project/lld/MinGW/Driver.cpp (revision dd647e3e608ed0b2bac7c588d5859b80ef4a5976)
1894dbbe8SMartell Malone //===- MinGW/Driver.cpp ---------------------------------------------------===//
2894dbbe8SMartell Malone //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6894dbbe8SMartell Malone //
7894dbbe8SMartell Malone //===----------------------------------------------------------------------===//
85abe10acSMartin Storsjo //
95abe10acSMartin Storsjo // MinGW is a GNU development environment for Windows. It consists of GNU
105abe10acSMartin Storsjo // tools such as GCC and GNU ld. Unlike Cygwin, there's no POSIX-compatible
115abe10acSMartin Storsjo // layer, as it aims to be a native development toolchain.
125abe10acSMartin Storsjo //
135abe10acSMartin Storsjo // lld/MinGW is a drop-in replacement for GNU ld/MinGW.
145abe10acSMartin Storsjo //
155abe10acSMartin Storsjo // Being a native development tool, a MinGW linker is not very different from
165abe10acSMartin Storsjo // Microsoft link.exe, so a MinGW linker can be implemented as a thin wrapper
175abe10acSMartin Storsjo // for lld/COFF. This driver takes Unix-ish command line options, translates
185abe10acSMartin Storsjo // them to Windows-ish ones, and then passes them to lld/COFF.
195abe10acSMartin Storsjo //
205abe10acSMartin Storsjo // When this driver calls the lld/COFF driver, it passes a hidden option
215abe10acSMartin Storsjo // "-lldmingw" along with other user-supplied options, to run the lld/COFF
225abe10acSMartin Storsjo // linker in "MinGW mode".
235abe10acSMartin Storsjo //
245abe10acSMartin Storsjo // There are subtle differences between MS link.exe and GNU ld/MinGW, and GNU
255abe10acSMartin Storsjo // ld/MinGW implements a few GNU-specific features. Such features are directly
265abe10acSMartin Storsjo // implemented in lld/COFF and enabled only when the linker is running in MinGW
275abe10acSMartin Storsjo // mode.
285abe10acSMartin Storsjo //
29894dbbe8SMartell Malone //===----------------------------------------------------------------------===//
30894dbbe8SMartell Malone 
316cb7141cSRui Ueyama #include "lld/Common/Driver.h"
326b9a80deSFangrui Song #include "lld/Common/CommonLinkerContext.h"
33338c4b23SRui Ueyama #include "lld/Common/ErrorHandler.h"
34bb12396fSMartin Storsjo #include "lld/Common/Memory.h"
356863dfaaSMartin Storsjo #include "lld/Common/Version.h"
36894dbbe8SMartell Malone #include "llvm/ADT/ArrayRef.h"
37a79762a3SMartin Storsjo #include "llvm/ADT/StringExtras.h"
38894dbbe8SMartell Malone #include "llvm/ADT/StringRef.h"
39894dbbe8SMartell Malone #include "llvm/Option/Arg.h"
40894dbbe8SMartell Malone #include "llvm/Option/ArgList.h"
41894dbbe8SMartell Malone #include "llvm/Option/Option.h"
42894dbbe8SMartell Malone #include "llvm/Support/CommandLine.h"
43894dbbe8SMartell Malone #include "llvm/Support/FileSystem.h"
44894dbbe8SMartell Malone #include "llvm/Support/Path.h"
45d768bf99SArchibald Elliott #include "llvm/TargetParser/Host.h"
4662c7f035SArchibald Elliott #include "llvm/TargetParser/Triple.h"
47b9ef5648SKazu Hirata #include <optional>
48894dbbe8SMartell Malone 
49894dbbe8SMartell Malone using namespace lld;
50dcb6d212SJustin Bogner using namespace llvm::opt;
51894dbbe8SMartell Malone using namespace llvm;
52894dbbe8SMartell Malone 
53894dbbe8SMartell Malone // Create OptTable
54894dbbe8SMartell Malone enum {
55894dbbe8SMartell Malone   OPT_INVALID = 0,
563f092f37SJan Svoboda #define OPTION(...) LLVM_MAKE_OPT_ID(__VA_ARGS__),
57894dbbe8SMartell Malone #include "Options.inc"
58894dbbe8SMartell Malone #undef OPTION
59894dbbe8SMartell Malone };
60894dbbe8SMartell Malone 
61*dd647e3eSChandler Carruth #define OPTTABLE_STR_TABLE_CODE
62894dbbe8SMartell Malone #include "Options.inc"
63*dd647e3eSChandler Carruth #undef OPTTABLE_STR_TABLE_CODE
64*dd647e3eSChandler Carruth 
65*dd647e3eSChandler Carruth #define OPTTABLE_PREFIXES_TABLE_CODE
66*dd647e3eSChandler Carruth #include "Options.inc"
67*dd647e3eSChandler Carruth #undef OPTTABLE_PREFIXES_TABLE_CODE
68894dbbe8SMartell Malone 
69894dbbe8SMartell Malone // Create table mapping all options defined in Options.td
7007d9ab9aSserge-sans-paille static constexpr opt::OptTable::Info infoTable[] = {
71dcb6d212SJustin Bogner #define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS,         \
72aff197ffSDavid Spickett                VISIBILITY, PARAM, HELPTEXT, HELPTEXTSFORVARIANTS, METAVAR,     \
73aff197ffSDavid Spickett                VALUES)                                                         \
74aff197ffSDavid Spickett   {PREFIX,                                                                     \
75aff197ffSDavid Spickett    NAME,                                                                       \
76aff197ffSDavid Spickett    HELPTEXT,                                                                   \
77aff197ffSDavid Spickett    HELPTEXTSFORVARIANTS,                                                       \
78aff197ffSDavid Spickett    METAVAR,                                                                    \
79aff197ffSDavid Spickett    OPT_##ID,                                                                   \
80aff197ffSDavid Spickett    opt::Option::KIND##Class,                                                   \
81aff197ffSDavid Spickett    PARAM,                                                                      \
82aff197ffSDavid Spickett    FLAGS,                                                                      \
83aff197ffSDavid Spickett    VISIBILITY,                                                                 \
84aff197ffSDavid Spickett    OPT_##GROUP,                                                                \
85aff197ffSDavid Spickett    OPT_##ALIAS,                                                                \
86aff197ffSDavid Spickett    ALIASARGS,                                                                  \
87dcb6d212SJustin Bogner    VALUES},
88894dbbe8SMartell Malone #include "Options.inc"
89894dbbe8SMartell Malone #undef OPTION
90894dbbe8SMartell Malone };
91894dbbe8SMartell Malone 
92c16fd25cSRui Ueyama namespace {
9307bb29d8Sserge-sans-paille class MinGWOptTable : public opt::GenericOptTable {
94894dbbe8SMartell Malone public:
95*dd647e3eSChandler Carruth   MinGWOptTable()
96*dd647e3eSChandler Carruth       : opt::GenericOptTable(OptionStrTable, OptionPrefixesTable, infoTable,
97*dd647e3eSChandler Carruth                              false) {}
98136d27abSRui Ueyama   opt::InputArgList parse(ArrayRef<const char *> argv);
99894dbbe8SMartell Malone };
100894dbbe8SMartell Malone } // namespace
101894dbbe8SMartell Malone 
102ddc0eb70SFangrui Song static void printHelp(CommonLinkerContext &ctx, const char *argv0) {
103ddc0eb70SFangrui Song   auto &outs = ctx.e.outs();
104f1e2d585SFangrui Song   MinGWOptTable().printHelp(
105ddc0eb70SFangrui Song       outs, (std::string(argv0) + " [options] file...").c_str(), "lld",
106ddc0eb70SFangrui Song       /*ShowHidden=*/false, /*ShowAllAliases=*/true);
107ddc0eb70SFangrui Song   outs << '\n';
1089ae0d222SMartin Storsjo }
1099ae0d222SMartin Storsjo 
110bb12396fSMartin Storsjo static cl::TokenizerCallback getQuotingStyle() {
111bb12396fSMartin Storsjo   if (Triple(sys::getProcessTriple()).getOS() == Triple::Win32)
112bb12396fSMartin Storsjo     return cl::TokenizeWindowsCommandLine;
113bb12396fSMartin Storsjo   return cl::TokenizeGNUCommandLine;
114bb12396fSMartin Storsjo }
115bb12396fSMartin Storsjo 
116136d27abSRui Ueyama opt::InputArgList MinGWOptTable::parse(ArrayRef<const char *> argv) {
117136d27abSRui Ueyama   unsigned missingIndex;
118136d27abSRui Ueyama   unsigned missingCount;
119d2da71f9SRui Ueyama 
120136d27abSRui Ueyama   SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size());
12183d59e05SAlexandre Ganea   cl::ExpandResponseFiles(saver(), getQuotingStyle(), vec);
122136d27abSRui Ueyama   opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount);
123d2da71f9SRui Ueyama 
124136d27abSRui Ueyama   if (missingCount)
12537bf9bb4SRui Ueyama     error(StringRef(args.getArgString(missingIndex)) + ": missing argument");
126136d27abSRui Ueyama   for (auto *arg : args.filtered(OPT_UNKNOWN))
12737bf9bb4SRui Ueyama     error("unknown argument: " + arg->getAsString(args));
128136d27abSRui Ueyama   return args;
129894dbbe8SMartell Malone }
130894dbbe8SMartell Malone 
131894dbbe8SMartell Malone // Find a file by concatenating given paths.
132b9ef5648SKazu Hirata static std::optional<std::string> findFile(StringRef path1,
133b9ef5648SKazu Hirata                                            const Twine &path2) {
134136d27abSRui Ueyama   SmallString<128> s;
135136d27abSRui Ueyama   sys::path::append(s, path1, path2);
136136d27abSRui Ueyama   if (sys::fs::exists(s))
1373e24242aSJonas Devlieghere     return std::string(s);
138c68af42fSKazu Hirata   return std::nullopt;
139894dbbe8SMartell Malone }
140894dbbe8SMartell Malone 
141894dbbe8SMartell Malone // This is for -lfoo. We'll look for libfoo.dll.a or libfoo.a from search paths.
1425941b0bbSRui Ueyama static std::string
143136d27abSRui Ueyama searchLibrary(StringRef name, ArrayRef<StringRef> searchPaths, bool bStatic) {
1448d85c96eSFangrui Song   if (name.starts_with(":")) {
145136d27abSRui Ueyama     for (StringRef dir : searchPaths)
146b9ef5648SKazu Hirata       if (std::optional<std::string> s = findFile(dir, name.substr(1)))
147136d27abSRui Ueyama         return *s;
1480226c352SMartin Storsjo     error("unable to find library -l" + name);
1490226c352SMartin Storsjo     return "";
150894dbbe8SMartell Malone   }
151894dbbe8SMartell Malone 
152136d27abSRui Ueyama   for (StringRef dir : searchPaths) {
1530226c352SMartin Storsjo     if (!bStatic) {
154b9ef5648SKazu Hirata       if (std::optional<std::string> s = findFile(dir, "lib" + name + ".dll.a"))
155136d27abSRui Ueyama         return *s;
156b9ef5648SKazu Hirata       if (std::optional<std::string> s = findFile(dir, name + ".dll.a"))
157136d27abSRui Ueyama         return *s;
158894dbbe8SMartell Malone     }
159b9ef5648SKazu Hirata     if (std::optional<std::string> s = findFile(dir, "lib" + name + ".a"))
1600226c352SMartin Storsjo       return *s;
161b9ef5648SKazu Hirata     if (std::optional<std::string> s = findFile(dir, name + ".lib"))
1620226c352SMartin Storsjo       return *s;
163e75c87f2SMartin Storsjö     if (!bStatic) {
164b9ef5648SKazu Hirata       if (std::optional<std::string> s = findFile(dir, "lib" + name + ".dll"))
165c09e5e50SMartin Storsjö         return *s;
166b9ef5648SKazu Hirata       if (std::optional<std::string> s = findFile(dir, name + ".dll"))
167c09e5e50SMartin Storsjö         return *s;
1680226c352SMartin Storsjo     }
1690226c352SMartin Storsjo   }
1700226c352SMartin Storsjo   error("unable to find library -l" + name);
1710226c352SMartin Storsjo   return "";
172894dbbe8SMartell Malone }
173894dbbe8SMartell Malone 
1746f2e92c1SAlexandre Ganea namespace lld {
1756f2e92c1SAlexandre Ganea namespace coff {
1766f2e92c1SAlexandre Ganea bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
1776f2e92c1SAlexandre Ganea           llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput);
1786f2e92c1SAlexandre Ganea }
1796f2e92c1SAlexandre Ganea 
1806f2e92c1SAlexandre Ganea namespace mingw {
1815941b0bbSRui Ueyama // Convert Unix-ish command line arguments to Windows-ish ones and
1825941b0bbSRui Ueyama // then call coff::link.
1836f2e92c1SAlexandre Ganea bool link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
1846f2e92c1SAlexandre Ganea           llvm::raw_ostream &stderrOS, bool exitEarly, bool disableOutput) {
18583d59e05SAlexandre Ganea   auto *ctx = new CommonLinkerContext;
18683d59e05SAlexandre Ganea   ctx->e.initialize(stdoutOS, stderrOS, exitEarly, disableOutput);
187d3fec7fbSJames Y Knight 
188136d27abSRui Ueyama   MinGWOptTable parser;
189136d27abSRui Ueyama   opt::InputArgList args = parser.parse(argsArr.slice(1));
190894dbbe8SMartell Malone 
19137bf9bb4SRui Ueyama   if (errorCount())
19237bf9bb4SRui Ueyama     return false;
19337bf9bb4SRui Ueyama 
194136d27abSRui Ueyama   if (args.hasArg(OPT_help)) {
195ddc0eb70SFangrui Song     printHelp(*ctx, argsArr[0]);
1969ae0d222SMartin Storsjo     return true;
1979ae0d222SMartin Storsjo   }
1989ae0d222SMartin Storsjo 
1996863dfaaSMartin Storsjo   // A note about "compatible with GNU linkers" message: this is a hack for
2006863dfaaSMartin Storsjo   // scripts generated by GNU Libtool 2.4.6 (released in February 2014 and
2016863dfaaSMartin Storsjo   // still the newest version in March 2017) or earlier to recognize LLD as
2026863dfaaSMartin Storsjo   // a GNU compatible linker. As long as an output for the -v option
2036863dfaaSMartin Storsjo   // contains "GNU" or "with BFD", they recognize us as GNU-compatible.
204136d27abSRui Ueyama   if (args.hasArg(OPT_v) || args.hasArg(OPT_version))
205b298e2d2SMartin Storsjö     message(getLLDVersion() + " (compatible with GNU linkers)");
2066863dfaaSMartin Storsjo 
2076863dfaaSMartin Storsjo   // The behavior of -v or --version is a bit strange, but this is
2086863dfaaSMartin Storsjo   // needed for compatibility with GNU linkers.
209136d27abSRui Ueyama   if (args.hasArg(OPT_v) && !args.hasArg(OPT_INPUT) && !args.hasArg(OPT_l))
2106863dfaaSMartin Storsjo     return true;
211136d27abSRui Ueyama   if (args.hasArg(OPT_version))
2126863dfaaSMartin Storsjo     return true;
2136863dfaaSMartin Storsjo 
21437bf9bb4SRui Ueyama   if (!args.hasArg(OPT_INPUT) && !args.hasArg(OPT_l)) {
21537bf9bb4SRui Ueyama     error("no input files");
21637bf9bb4SRui Ueyama     return false;
21737bf9bb4SRui Ueyama   }
2189ae0d222SMartin Storsjo 
219136d27abSRui Ueyama   std::vector<std::string> linkArgs;
220136d27abSRui Ueyama   auto add = [&](const Twine &s) { linkArgs.push_back(s.str()); };
221894dbbe8SMartell Malone 
222136d27abSRui Ueyama   add("lld-link");
223136d27abSRui Ueyama   add("-lldmingw");
224894dbbe8SMartell Malone 
225136d27abSRui Ueyama   if (auto *a = args.getLastArg(OPT_entry)) {
226136d27abSRui Ueyama     StringRef s = a->getValue();
2278d85c96eSFangrui Song     if (args.getLastArgValue(OPT_m) == "i386pe" && s.starts_with("_"))
228136d27abSRui Ueyama       add("-entry:" + s.substr(1));
229acf675b6SMartin Storsjö     else if (!s.empty())
230136d27abSRui Ueyama       add("-entry:" + s);
231acf675b6SMartin Storsjö     else
232acf675b6SMartin Storsjö       add("-noentry");
2336d8dace4SMartin Storsjo   }
2346d8dace4SMartin Storsjo 
235136d27abSRui Ueyama   if (args.hasArg(OPT_major_os_version, OPT_minor_os_version,
2366f047ae5SMartin Storsjo                   OPT_major_subsystem_version, OPT_minor_subsystem_version)) {
237bc8f3b42SMartin Storsjö     StringRef majOSVer = args.getLastArgValue(OPT_major_os_version, "6");
238bc8f3b42SMartin Storsjö     StringRef minOSVer = args.getLastArgValue(OPT_minor_os_version, "0");
23961e2f9faSMartin Storsjö     StringRef majSubSysVer = "6";
24061e2f9faSMartin Storsjö     StringRef minSubSysVer = "0";
24161e2f9faSMartin Storsjö     StringRef subSysName = "default";
24261e2f9faSMartin Storsjö     StringRef subSysVer;
24361e2f9faSMartin Storsjö     // Iterate over --{major,minor}-subsystem-version and --subsystem, and pick
24461e2f9faSMartin Storsjö     // the version number components from the last one of them that specifies
24561e2f9faSMartin Storsjö     // a version.
24661e2f9faSMartin Storsjö     for (auto *a : args.filtered(OPT_major_subsystem_version,
24761e2f9faSMartin Storsjö                                  OPT_minor_subsystem_version, OPT_subs)) {
24861e2f9faSMartin Storsjö       switch (a->getOption().getID()) {
24961e2f9faSMartin Storsjö       case OPT_major_subsystem_version:
25061e2f9faSMartin Storsjö         majSubSysVer = a->getValue();
25161e2f9faSMartin Storsjö         break;
25261e2f9faSMartin Storsjö       case OPT_minor_subsystem_version:
25361e2f9faSMartin Storsjö         minSubSysVer = a->getValue();
25461e2f9faSMartin Storsjö         break;
25561e2f9faSMartin Storsjö       case OPT_subs:
25661e2f9faSMartin Storsjö         std::tie(subSysName, subSysVer) = StringRef(a->getValue()).split(':');
25761e2f9faSMartin Storsjö         if (!subSysVer.empty()) {
25861e2f9faSMartin Storsjö           if (subSysVer.contains('.'))
25961e2f9faSMartin Storsjö             std::tie(majSubSysVer, minSubSysVer) = subSysVer.split('.');
26061e2f9faSMartin Storsjö           else
26161e2f9faSMartin Storsjö             majSubSysVer = subSysVer;
26261e2f9faSMartin Storsjö         }
26361e2f9faSMartin Storsjö         break;
26461e2f9faSMartin Storsjö       }
26561e2f9faSMartin Storsjö     }
266bc8f3b42SMartin Storsjö     add("-osversion:" + majOSVer + "." + minOSVer);
26761e2f9faSMartin Storsjö     add("-subsystem:" + subSysName + "," + majSubSysVer + "." + minSubSysVer);
26861e2f9faSMartin Storsjö   } else if (args.hasArg(OPT_subs)) {
26961e2f9faSMartin Storsjö     StringRef subSys = args.getLastArgValue(OPT_subs, "default");
27061e2f9faSMartin Storsjö     StringRef subSysName, subSysVer;
27161e2f9faSMartin Storsjö     std::tie(subSysName, subSysVer) = subSys.split(':');
27261e2f9faSMartin Storsjö     StringRef sep = subSysVer.empty() ? "" : ",";
27361e2f9faSMartin Storsjö     add("-subsystem:" + subSysName + sep + subSysVer);
2746f047ae5SMartin Storsjo   }
2756f047ae5SMartin Storsjo 
276136d27abSRui Ueyama   if (auto *a = args.getLastArg(OPT_out_implib))
277136d27abSRui Ueyama     add("-implib:" + StringRef(a->getValue()));
278136d27abSRui Ueyama   if (auto *a = args.getLastArg(OPT_stack))
279136d27abSRui Ueyama     add("-stack:" + StringRef(a->getValue()));
280136d27abSRui Ueyama   if (auto *a = args.getLastArg(OPT_output_def))
281136d27abSRui Ueyama     add("-output-def:" + StringRef(a->getValue()));
282136d27abSRui Ueyama   if (auto *a = args.getLastArg(OPT_image_base))
283136d27abSRui Ueyama     add("-base:" + StringRef(a->getValue()));
284136d27abSRui Ueyama   if (auto *a = args.getLastArg(OPT_map))
285136d27abSRui Ueyama     add("-lldmap:" + StringRef(a->getValue()));
286e4758a5cSRui Ueyama   if (auto *a = args.getLastArg(OPT_reproduce))
287e4758a5cSRui Ueyama     add("-reproduce:" + StringRef(a->getValue()));
28892f7bd3aSMartin Storsjö   if (auto *a = args.getLastArg(OPT_file_alignment))
28992f7bd3aSMartin Storsjö     add("-filealign:" + StringRef(a->getValue()));
29092f7bd3aSMartin Storsjö   if (auto *a = args.getLastArg(OPT_section_alignment))
29192f7bd3aSMartin Storsjö     add("-align:" + StringRef(a->getValue()));
292460830a9SMateusz Mikuła   if (auto *a = args.getLastArg(OPT_heap))
293460830a9SMateusz Mikuła     add("-heap:" + StringRef(a->getValue()));
2940b51e648SMartin Storsjö   if (auto *a = args.getLastArg(OPT_threads))
2950b51e648SMartin Storsjö     add("-threads:" + StringRef(a->getValue()));
296894dbbe8SMartell Malone 
297136d27abSRui Ueyama   if (auto *a = args.getLastArg(OPT_o))
298136d27abSRui Ueyama     add("-out:" + StringRef(a->getValue()));
299136d27abSRui Ueyama   else if (args.hasArg(OPT_shared))
300136d27abSRui Ueyama     add("-out:a.dll");
301894dbbe8SMartell Malone   else
302136d27abSRui Ueyama     add("-out:a.exe");
303894dbbe8SMartell Malone 
304136d27abSRui Ueyama   if (auto *a = args.getLastArg(OPT_pdb)) {
305136d27abSRui Ueyama     add("-debug");
306136d27abSRui Ueyama     StringRef v = a->getValue();
307136d27abSRui Ueyama     if (!v.empty())
308136d27abSRui Ueyama       add("-pdb:" + v);
3097dcd8ef1SMartin Storsjö     if (args.hasArg(OPT_strip_all)) {
3107dcd8ef1SMartin Storsjö       add("-debug:nodwarf,nosymtab");
3117dcd8ef1SMartin Storsjö     } else if (args.hasArg(OPT_strip_debug)) {
3127dcd8ef1SMartin Storsjö       add("-debug:nodwarf,symtab");
3137dcd8ef1SMartin Storsjö     }
314136d27abSRui Ueyama   } else if (args.hasArg(OPT_strip_debug)) {
315136d27abSRui Ueyama     add("-debug:symtab");
316136d27abSRui Ueyama   } else if (!args.hasArg(OPT_strip_all)) {
317136d27abSRui Ueyama     add("-debug:dwarf");
318b7d50115SMartin Storsjo   }
319aaf3a8deSZequan Wu   if (auto *a = args.getLastArg(OPT_build_id)) {
320aaf3a8deSZequan Wu     StringRef v = a->getValue();
321aaf3a8deSZequan Wu     if (v == "none")
322aaf3a8deSZequan Wu       add("-build-id:no");
323aaf3a8deSZequan Wu     else {
324aaf3a8deSZequan Wu       if (!v.empty())
325aaf3a8deSZequan Wu         warn("unsupported build id hashing: " + v + ", using default hashing.");
326aaf3a8deSZequan Wu       add("-build-id");
327aaf3a8deSZequan Wu     }
328aaf3a8deSZequan Wu   } else {
329aaf3a8deSZequan Wu     if (args.hasArg(OPT_strip_debug) || args.hasArg(OPT_strip_all))
330aaf3a8deSZequan Wu       add("-build-id:no");
331aaf3a8deSZequan Wu     else
332aaf3a8deSZequan Wu       add("-build-id");
333aaf3a8deSZequan Wu   }
334b7d50115SMartin Storsjo 
335696c1087SJacek Caban   if (auto *a = args.getLastArg(OPT_functionpadmin)) {
336696c1087SJacek Caban     StringRef v = a->getValue();
337696c1087SJacek Caban     if (v.empty())
338696c1087SJacek Caban       add("-functionpadmin");
339696c1087SJacek Caban     else
340696c1087SJacek Caban       add("-functionpadmin:" + v);
341696c1087SJacek Caban   }
342696c1087SJacek Caban 
34384306ef9SMateusz Mikuła   if (args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false))
34484306ef9SMateusz Mikuła     add("-WX");
34584306ef9SMateusz Mikuła   else
34684306ef9SMateusz Mikuła     add("-WX:no");
34784306ef9SMateusz Mikuła 
348ce211c50SMartin Storsjö   if (args.hasFlag(OPT_enable_stdcall_fixup, OPT_disable_stdcall_fixup, false))
349ce211c50SMartin Storsjö     add("-stdcall-fixup");
350ce211c50SMartin Storsjö   else if (args.hasArg(OPT_disable_stdcall_fixup))
351ce211c50SMartin Storsjö     add("-stdcall-fixup:no");
352ce211c50SMartin Storsjö 
353136d27abSRui Ueyama   if (args.hasArg(OPT_shared))
354136d27abSRui Ueyama     add("-dll");
355136d27abSRui Ueyama   if (args.hasArg(OPT_verbose))
356136d27abSRui Ueyama     add("-verbose");
357136d27abSRui Ueyama   if (args.hasArg(OPT_exclude_all_symbols))
358136d27abSRui Ueyama     add("-exclude-all-symbols");
359136d27abSRui Ueyama   if (args.hasArg(OPT_export_all_symbols))
360136d27abSRui Ueyama     add("-export-all-symbols");
361136d27abSRui Ueyama   if (args.hasArg(OPT_large_address_aware))
362136d27abSRui Ueyama     add("-largeaddressaware");
363136d27abSRui Ueyama   if (args.hasArg(OPT_kill_at))
364136d27abSRui Ueyama     add("-kill-at");
365136d27abSRui Ueyama   if (args.hasArg(OPT_appcontainer))
366136d27abSRui Ueyama     add("-appcontainer");
367f8340c8cSMartin Storsjö   if (args.hasFlag(OPT_no_seh, OPT_disable_no_seh, false))
368745eb024SMartin Storsjö     add("-noseh");
3695941b0bbSRui Ueyama 
370136d27abSRui Ueyama   if (args.getLastArgValue(OPT_m) != "thumb2pe" &&
371e72403f9SMartin Storsjö       args.getLastArgValue(OPT_m) != "arm64pe" &&
372a9ffdc17SBilly Laws       args.getLastArgValue(OPT_m) != "arm64ecpe" &&
373f8340c8cSMartin Storsjö       args.hasFlag(OPT_disable_dynamicbase, OPT_dynamicbase, false))
374136d27abSRui Ueyama     add("-dynamicbase:no");
375f8340c8cSMartin Storsjö   if (args.hasFlag(OPT_disable_high_entropy_va, OPT_high_entropy_va, false))
376f8340c8cSMartin Storsjö     add("-highentropyva:no");
377f8340c8cSMartin Storsjö   if (args.hasFlag(OPT_disable_nxcompat, OPT_nxcompat, false))
378f8340c8cSMartin Storsjö     add("-nxcompat:no");
379f8340c8cSMartin Storsjö   if (args.hasFlag(OPT_disable_tsaware, OPT_tsaware, false))
380f8340c8cSMartin Storsjö     add("-tsaware:no");
381094d8c09SMartin Storsjo 
382aefa1116SMartin Storsjö   if (args.hasFlag(OPT_disable_reloc_section, OPT_enable_reloc_section, false))
383aefa1116SMartin Storsjö     add("-fixed");
384aefa1116SMartin Storsjö 
385136d27abSRui Ueyama   if (args.hasFlag(OPT_no_insert_timestamp, OPT_insert_timestamp, false))
386136d27abSRui Ueyama     add("-timestamp:0");
387537a718fSMartin Storsjo 
388136d27abSRui Ueyama   if (args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false))
389136d27abSRui Ueyama     add("-opt:ref");
390b190fd2bSMartin Storsjo   else
391136d27abSRui Ueyama     add("-opt:noref");
392b190fd2bSMartin Storsjo 
393248e3450SMartin Storsjö   if (args.hasFlag(OPT_demangle, OPT_no_demangle, true))
394248e3450SMartin Storsjö     add("-demangle");
395248e3450SMartin Storsjö   else
396248e3450SMartin Storsjö     add("-demangle:no");
397248e3450SMartin Storsjö 
3987f0e6c31SMartin Storsjö   if (args.hasFlag(OPT_enable_auto_import, OPT_disable_auto_import, true))
3997f0e6c31SMartin Storsjö     add("-auto-import");
4007f0e6c31SMartin Storsjö   else
4017f0e6c31SMartin Storsjö     add("-auto-import:no");
4027f0e6c31SMartin Storsjö   if (args.hasFlag(OPT_enable_runtime_pseudo_reloc,
4037f0e6c31SMartin Storsjö                    OPT_disable_runtime_pseudo_reloc, true))
4047f0e6c31SMartin Storsjö     add("-runtime-pseudo-reloc");
4057f0e6c31SMartin Storsjö   else
4067f0e6c31SMartin Storsjö     add("-runtime-pseudo-reloc:no");
4077f0e6c31SMartin Storsjö 
408c82078b5SMateusz Mikuła   if (args.hasFlag(OPT_allow_multiple_definition,
409c82078b5SMateusz Mikuła                    OPT_no_allow_multiple_definition, false))
410c82078b5SMateusz Mikuła     add("-force:multiple");
411c82078b5SMateusz Mikuła 
4123d7260b4SMateusz Mikuła   if (auto *a = args.getLastArg(OPT_dependent_load_flag))
4133d7260b4SMateusz Mikuła     add("-dependentloadflag:" + StringRef(a->getValue()));
4143d7260b4SMateusz Mikuła 
415136d27abSRui Ueyama   if (auto *a = args.getLastArg(OPT_icf)) {
416136d27abSRui Ueyama     StringRef s = a->getValue();
417136d27abSRui Ueyama     if (s == "all")
418136d27abSRui Ueyama       add("-opt:icf");
4196d66440cSMartin Storsjö     else if (s == "safe")
4206d66440cSMartin Storsjö       add("-opt:safeicf");
4216d66440cSMartin Storsjö     else if (s == "none")
422136d27abSRui Ueyama       add("-opt:noicf");
423b190fd2bSMartin Storsjo     else
42437bf9bb4SRui Ueyama       error("unknown parameter: --icf=" + s);
425b190fd2bSMartin Storsjo   } else {
426136d27abSRui Ueyama     add("-opt:noicf");
427b190fd2bSMartin Storsjo   }
428b190fd2bSMartin Storsjo 
429136d27abSRui Ueyama   if (auto *a = args.getLastArg(OPT_m)) {
430136d27abSRui Ueyama     StringRef s = a->getValue();
431136d27abSRui Ueyama     if (s == "i386pe")
432136d27abSRui Ueyama       add("-machine:x86");
433136d27abSRui Ueyama     else if (s == "i386pep")
434136d27abSRui Ueyama       add("-machine:x64");
435136d27abSRui Ueyama     else if (s == "thumb2pe")
436136d27abSRui Ueyama       add("-machine:arm");
437136d27abSRui Ueyama     else if (s == "arm64pe")
438136d27abSRui Ueyama       add("-machine:arm64");
439a9ffdc17SBilly Laws     else if (s == "arm64ecpe")
440a9ffdc17SBilly Laws       add("-machine:arm64ec");
4415941b0bbSRui Ueyama     else
44237bf9bb4SRui Ueyama       error("unknown parameter: -m" + s);
4435941b0bbSRui Ueyama   }
4445941b0bbSRui Ueyama 
445bf7c5f1fSAlvin Wong   if (args.hasFlag(OPT_guard_cf, OPT_no_guard_cf, false)) {
446bf7c5f1fSAlvin Wong     if (args.hasFlag(OPT_guard_longjmp, OPT_no_guard_longjmp, true))
447bf7c5f1fSAlvin Wong       add("-guard:cf,longjmp");
448bf7c5f1fSAlvin Wong     else
449bf7c5f1fSAlvin Wong       add("-guard:cf,nolongjmp");
450bf7c5f1fSAlvin Wong   } else if (args.hasFlag(OPT_guard_longjmp, OPT_no_guard_longjmp, false)) {
451bf7c5f1fSAlvin Wong     auto *a = args.getLastArg(OPT_guard_longjmp);
452bf7c5f1fSAlvin Wong     warn("parameter " + a->getSpelling() +
453bf7c5f1fSAlvin Wong          " only takes effect when used with --guard-cf");
454bf7c5f1fSAlvin Wong   }
455bf7c5f1fSAlvin Wong 
456de4364f1SAlvin Wong   if (auto *a = args.getLastArg(OPT_error_limit)) {
457de4364f1SAlvin Wong     int n;
458de4364f1SAlvin Wong     StringRef s = a->getValue();
459de4364f1SAlvin Wong     if (s.getAsInteger(10, n))
460de4364f1SAlvin Wong       error(a->getSpelling() + ": number expected, but got " + s);
461de4364f1SAlvin Wong     else
462de4364f1SAlvin Wong       add("-errorlimit:" + s);
463de4364f1SAlvin Wong   }
464de4364f1SAlvin Wong 
46569f76c78SMartin Storsjö   if (auto *a = args.getLastArg(OPT_rpath))
46669f76c78SMartin Storsjö     warn("parameter " + a->getSpelling() + " has no effect on PE/COFF targets");
46769f76c78SMartin Storsjö 
468136d27abSRui Ueyama   for (auto *a : args.filtered(OPT_mllvm))
469136d27abSRui Ueyama     add("-mllvm:" + StringRef(a->getValue()));
4700d17638bSMartell Malone 
4715c92c9f3SMartin Storsjö   if (auto *arg = args.getLastArg(OPT_plugin_opt_mcpu_eq))
4725c92c9f3SMartin Storsjö     add("-mllvm:-mcpu=" + StringRef(arg->getValue()));
4730b51e648SMartin Storsjö   if (auto *arg = args.getLastArg(OPT_lto_O))
4740b51e648SMartin Storsjö     add("-opt:lldlto=" + StringRef(arg->getValue()));
4750b51e648SMartin Storsjö   if (auto *arg = args.getLastArg(OPT_lto_CGO))
4760b51e648SMartin Storsjö     add("-opt:lldltocgo=" + StringRef(arg->getValue()));
4770b51e648SMartin Storsjö   if (auto *arg = args.getLastArg(OPT_plugin_opt_dwo_dir_eq))
4780b51e648SMartin Storsjö     add("-dwodir:" + StringRef(arg->getValue()));
4790b51e648SMartin Storsjö   if (args.hasArg(OPT_lto_cs_profile_generate))
4800b51e648SMartin Storsjö     add("-lto-cs-profile-generate");
4810b51e648SMartin Storsjö   if (auto *arg = args.getLastArg(OPT_lto_cs_profile_file))
4820b51e648SMartin Storsjö     add("-lto-cs-profile-file:" + StringRef(arg->getValue()));
483d033366bSMartin Storsjö   if (args.hasArg(OPT_plugin_opt_emit_llvm))
484d033366bSMartin Storsjö     add("-lldemit:llvm");
485d033366bSMartin Storsjö   if (args.hasArg(OPT_lto_emit_asm))
486d033366bSMartin Storsjö     add("-lldemit:asm");
487276283d8Schrulski-intel   if (auto *arg = args.getLastArg(OPT_lto_sample_profile))
488276283d8Schrulski-intel     add("-lto-sample-profile:" + StringRef(arg->getValue()));
4895c92c9f3SMartin Storsjö 
490a08506e3SMartin Storsjö   if (auto *a = args.getLastArg(OPT_thinlto_cache_dir))
491a08506e3SMartin Storsjö     add("-lldltocache:" + StringRef(a->getValue()));
492a08506e3SMartin Storsjö   if (auto *a = args.getLastArg(OPT_thinlto_cache_policy))
493a08506e3SMartin Storsjö     add("-lldltocachepolicy:" + StringRef(a->getValue()));
494a08506e3SMartin Storsjö   if (args.hasArg(OPT_thinlto_emit_imports_files))
495a08506e3SMartin Storsjö     add("-thinlto-emit-imports-files");
496a08506e3SMartin Storsjö   if (args.hasArg(OPT_thinlto_index_only))
497a08506e3SMartin Storsjö     add("-thinlto-index-only");
498a08506e3SMartin Storsjö   if (auto *arg = args.getLastArg(OPT_thinlto_index_only_eq))
499a08506e3SMartin Storsjö     add("-thinlto-index-only:" + StringRef(arg->getValue()));
500a08506e3SMartin Storsjö   if (auto *arg = args.getLastArg(OPT_thinlto_jobs_eq))
501a08506e3SMartin Storsjö     add("-opt:lldltojobs=" + StringRef(arg->getValue()));
502a08506e3SMartin Storsjö   if (auto *arg = args.getLastArg(OPT_thinlto_object_suffix_replace_eq))
503a08506e3SMartin Storsjö     add("-thinlto-object-suffix-replace:" + StringRef(arg->getValue()));
504a08506e3SMartin Storsjö   if (auto *arg = args.getLastArg(OPT_thinlto_prefix_replace_eq))
505a08506e3SMartin Storsjö     add("-thinlto-prefix-replace:" + StringRef(arg->getValue()));
506a08506e3SMartin Storsjö 
5075c92c9f3SMartin Storsjö   for (auto *a : args.filtered(OPT_plugin_opt_eq_minus))
5085c92c9f3SMartin Storsjö     add("-mllvm:-" + StringRef(a->getValue()));
5095c92c9f3SMartin Storsjö 
5105c92c9f3SMartin Storsjö   // GCC collect2 passes -plugin-opt=path/to/lto-wrapper with an absolute or
5115c92c9f3SMartin Storsjö   // relative path. Just ignore. If not ended with "lto-wrapper" (or
5125c92c9f3SMartin Storsjö   // "lto-wrapper.exe" for GCC cross-compiled for Windows), consider it an
5135c92c9f3SMartin Storsjö   // unsupported LLVMgold.so option and error.
5145c92c9f3SMartin Storsjö   for (opt::Arg *arg : args.filtered(OPT_plugin_opt_eq)) {
5155c92c9f3SMartin Storsjö     StringRef v(arg->getValue());
5165c92c9f3SMartin Storsjö     if (!v.ends_with("lto-wrapper") && !v.ends_with("lto-wrapper.exe"))
5175c92c9f3SMartin Storsjö       error(arg->getSpelling() + ": unknown plugin option '" + arg->getValue() +
5185c92c9f3SMartin Storsjö             "'");
5195c92c9f3SMartin Storsjö   }
5205c92c9f3SMartin Storsjö 
521136d27abSRui Ueyama   for (auto *a : args.filtered(OPT_Xlink))
522136d27abSRui Ueyama     add(a->getValue());
523107b5483SMartin Storsjo 
524136d27abSRui Ueyama   if (args.getLastArgValue(OPT_m) == "i386pe")
525136d27abSRui Ueyama     add("-alternatename:__image_base__=___ImageBase");
5265941b0bbSRui Ueyama   else
527136d27abSRui Ueyama     add("-alternatename:__image_base__=__ImageBase");
5285941b0bbSRui Ueyama 
529136d27abSRui Ueyama   for (auto *a : args.filtered(OPT_require_defined))
530136d27abSRui Ueyama     add("-include:" + StringRef(a->getValue()));
53199cd4cb1SMiguel A. Arroyo   for (auto *a : args.filtered(OPT_undefined_glob))
53299cd4cb1SMiguel A. Arroyo     add("-includeglob:" + StringRef(a->getValue()));
533136d27abSRui Ueyama   for (auto *a : args.filtered(OPT_undefined))
534136d27abSRui Ueyama     add("-includeoptional:" + StringRef(a->getValue()));
535c92b3563SMartin Storsjo   for (auto *a : args.filtered(OPT_delayload))
536c92b3563SMartin Storsjo     add("-delayload:" + StringRef(a->getValue()));
5373785a413SMartin Storsjö   for (auto *a : args.filtered(OPT_wrap))
5383785a413SMartin Storsjö     add("-wrap:" + StringRef(a->getValue()));
539d1da6469SMartin Storsjö   for (auto *a : args.filtered(OPT_exclude_symbols))
540d1da6469SMartin Storsjö     add("-exclude-symbols:" + StringRef(a->getValue()));
541db62913fSMartin Storsjo 
542136d27abSRui Ueyama   std::vector<StringRef> searchPaths;
543136d27abSRui Ueyama   for (auto *a : args.filtered(OPT_L)) {
544136d27abSRui Ueyama     searchPaths.push_back(a->getValue());
545136d27abSRui Ueyama     add("-libpath:" + StringRef(a->getValue()));
546803b37adSMartin Storsjo   }
5475941b0bbSRui Ueyama 
548136d27abSRui Ueyama   StringRef prefix = "";
549136d27abSRui Ueyama   bool isStatic = false;
550136d27abSRui Ueyama   for (auto *a : args) {
551136d27abSRui Ueyama     switch (a->getOption().getID()) {
55232e1626aSMartin Storsjo     case OPT_INPUT:
553ed1539c6SKazu Hirata       if (StringRef(a->getValue()).ends_with_insensitive(".def"))
554136d27abSRui Ueyama         add("-def:" + StringRef(a->getValue()));
555064b0facSMartin Storsjo       else
556136d27abSRui Ueyama         add(prefix + StringRef(a->getValue()));
55732e1626aSMartin Storsjo       break;
55832e1626aSMartin Storsjo     case OPT_l:
559136d27abSRui Ueyama       add(prefix + searchLibrary(a->getValue(), searchPaths, isStatic));
56032e1626aSMartin Storsjo       break;
56132e1626aSMartin Storsjo     case OPT_whole_archive:
562136d27abSRui Ueyama       prefix = "-wholearchive:";
56332e1626aSMartin Storsjo       break;
56432e1626aSMartin Storsjo     case OPT_no_whole_archive:
565136d27abSRui Ueyama       prefix = "";
56632e1626aSMartin Storsjo       break;
5672ba37d4bSMartin Storsjo     case OPT_Bstatic:
568136d27abSRui Ueyama       isStatic = true;
5692ba37d4bSMartin Storsjo       break;
5702ba37d4bSMartin Storsjo     case OPT_Bdynamic:
571136d27abSRui Ueyama       isStatic = false;
5722ba37d4bSMartin Storsjo       break;
57332e1626aSMartin Storsjo     }
5745941b0bbSRui Ueyama   }
5755941b0bbSRui Ueyama 
5760226c352SMartin Storsjo   if (errorCount())
5770226c352SMartin Storsjo     return false;
5780226c352SMartin Storsjo 
579136d27abSRui Ueyama   if (args.hasArg(OPT_verbose) || args.hasArg(OPT__HASH_HASH_HASH))
580ddc0eb70SFangrui Song     ctx->e.errs() << llvm::join(linkArgs, " ") << "\n";
581a79762a3SMartin Storsjo 
582136d27abSRui Ueyama   if (args.hasArg(OPT__HASH_HASH_HASH))
583a79762a3SMartin Storsjo     return true;
584a79762a3SMartin Storsjo 
5855941b0bbSRui Ueyama   // Repack vector of strings to vector of const char pointers for coff::link.
586136d27abSRui Ueyama   std::vector<const char *> vec;
587136d27abSRui Ueyama   for (const std::string &s : linkArgs)
588136d27abSRui Ueyama     vec.push_back(s.c_str());
5891c8bb625SMartin Storsjö   // Pass the actual binary name, to make error messages be printed with
5901c8bb625SMartin Storsjö   // the right prefix.
5911c8bb625SMartin Storsjö   vec[0] = argsArr[0];
59283d59e05SAlexandre Ganea 
59383d59e05SAlexandre Ganea   // The context will be re-created in the COFF driver.
59483d59e05SAlexandre Ganea   lld::CommonLinkerContext::destroy();
59583d59e05SAlexandre Ganea 
59683d59e05SAlexandre Ganea   return coff::link(vec, stdoutOS, stderrOS, exitEarly, disableOutput);
597894dbbe8SMartell Malone }
5986f2e92c1SAlexandre Ganea } // namespace mingw
5996f2e92c1SAlexandre Ganea } // namespace lld
600