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