Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 1 | //===- MinGW/Driver.cpp ---------------------------------------------------===// |
| 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 | [diff] [blame] | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
Martin Storsjo | 5abe10a | 2019-01-05 10:43:59 | [diff] [blame] | 8 | // |
| 9 | // MinGW is a GNU development environment for Windows. It consists of GNU |
| 10 | // tools such as GCC and GNU ld. Unlike Cygwin, there's no POSIX-compatible |
| 11 | // layer, as it aims to be a native development toolchain. |
| 12 | // |
| 13 | // lld/MinGW is a drop-in replacement for GNU ld/MinGW. |
| 14 | // |
| 15 | // Being a native development tool, a MinGW linker is not very different from |
| 16 | // Microsoft link.exe, so a MinGW linker can be implemented as a thin wrapper |
| 17 | // for lld/COFF. This driver takes Unix-ish command line options, translates |
| 18 | // them to Windows-ish ones, and then passes them to lld/COFF. |
| 19 | // |
| 20 | // When this driver calls the lld/COFF driver, it passes a hidden option |
| 21 | // "-lldmingw" along with other user-supplied options, to run the lld/COFF |
| 22 | // linker in "MinGW mode". |
| 23 | // |
| 24 | // There are subtle differences between MS link.exe and GNU ld/MinGW, and GNU |
| 25 | // ld/MinGW implements a few GNU-specific features. Such features are directly |
| 26 | // implemented in lld/COFF and enabled only when the linker is running in MinGW |
| 27 | // mode. |
| 28 | // |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 29 | //===----------------------------------------------------------------------===// |
| 30 | |
Rui Ueyama | 6cb7141 | 2017-10-02 22:05:46 | [diff] [blame] | 31 | #include "lld/Common/Driver.h" |
Rui Ueyama | 338c4b2 | 2017-12-12 20:34:38 | [diff] [blame] | 32 | #include "lld/Common/ErrorHandler.h" |
Martin Storsjo | bb12396 | 2019-06-10 20:10:10 | [diff] [blame] | 33 | #include "lld/Common/Memory.h" |
Martin Storsjo | 6863dfa | 2019-05-17 11:07:42 | [diff] [blame] | 34 | #include "lld/Common/Version.h" |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 35 | #include "llvm/ADT/ArrayRef.h" |
| 36 | #include "llvm/ADT/Optional.h" |
Martin Storsjo | a79762a | 2017-09-11 20:43:39 | [diff] [blame] | 37 | #include "llvm/ADT/StringExtras.h" |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 38 | #include "llvm/ADT/StringRef.h" |
Martin Storsjo | bb12396 | 2019-06-10 20:10:10 | [diff] [blame] | 39 | #include "llvm/ADT/Triple.h" |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 40 | #include "llvm/Option/Arg.h" |
| 41 | #include "llvm/Option/ArgList.h" |
| 42 | #include "llvm/Option/Option.h" |
| 43 | #include "llvm/Support/CommandLine.h" |
| 44 | #include "llvm/Support/FileSystem.h" |
| 45 | #include "llvm/Support/Path.h" |
| 46 | |
| 47 | #if !defined(_MSC_VER) && !defined(__MINGW32__) |
| 48 | #include <unistd.h> |
| 49 | #endif |
| 50 | |
| 51 | using namespace lld; |
| 52 | using namespace llvm; |
| 53 | |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 54 | // Create OptTable |
| 55 | enum { |
| 56 | OPT_INVALID = 0, |
| 57 | #define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11, _12) OPT_##ID, |
| 58 | #include "Options.inc" |
| 59 | #undef OPTION |
| 60 | }; |
| 61 | |
| 62 | // Create prefix string literals used in Options.td |
Rui Ueyama | c16fd25 | 2017-09-11 22:04:13 | [diff] [blame] | 63 | #define PREFIX(NAME, VALUE) static const char *const NAME[] = VALUE; |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 64 | #include "Options.inc" |
| 65 | #undef PREFIX |
| 66 | |
| 67 | // Create table mapping all options defined in Options.td |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 68 | static const opt::OptTable::Info infoTable[] = { |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 69 | #define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \ |
| 70 | {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \ |
| 71 | X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12}, |
| 72 | #include "Options.inc" |
| 73 | #undef OPTION |
| 74 | }; |
| 75 | |
Rui Ueyama | c16fd25 | 2017-09-11 22:04:13 | [diff] [blame] | 76 | namespace { |
Rui Ueyama | 4474796 | 2017-09-11 22:04:25 | [diff] [blame] | 77 | class MinGWOptTable : public opt::OptTable { |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 78 | public: |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 79 | MinGWOptTable() : OptTable(infoTable, false) {} |
| 80 | opt::InputArgList parse(ArrayRef<const char *> argv); |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 81 | }; |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 82 | } // namespace |
| 83 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 84 | static void printHelp(const char *argv0) { |
Martin Storsjo | 9ae0d22 | 2019-05-17 11:07:38 | [diff] [blame] | 85 | MinGWOptTable().PrintHelp( |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 86 | outs(), (std::string(argv0) + " [options] file...").c_str(), "lld", |
Martin Storsjo | 9ae0d22 | 2019-05-17 11:07:38 | [diff] [blame] | 87 | false /*ShowHidden*/, true /*ShowAllAliases*/); |
| 88 | outs() << "\n"; |
| 89 | } |
| 90 | |
Martin Storsjo | bb12396 | 2019-06-10 20:10:10 | [diff] [blame] | 91 | static cl::TokenizerCallback getQuotingStyle() { |
| 92 | if (Triple(sys::getProcessTriple()).getOS() == Triple::Win32) |
| 93 | return cl::TokenizeWindowsCommandLine; |
| 94 | return cl::TokenizeGNUCommandLine; |
| 95 | } |
| 96 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 97 | opt::InputArgList MinGWOptTable::parse(ArrayRef<const char *> argv) { |
| 98 | unsigned missingIndex; |
| 99 | unsigned missingCount; |
Rui Ueyama | d2da71f | 2017-09-11 22:04:37 | [diff] [blame] | 100 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 101 | SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size()); |
| 102 | cl::ExpandResponseFiles(saver, getQuotingStyle(), vec); |
| 103 | opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount); |
Rui Ueyama | d2da71f | 2017-09-11 22:04:37 | [diff] [blame] | 104 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 105 | if (missingCount) |
Rui Ueyama | 37bf9bb | 2019-10-10 09:46:41 | [diff] [blame^] | 106 | error(StringRef(args.getArgString(missingIndex)) + ": missing argument"); |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 107 | for (auto *arg : args.filtered(OPT_UNKNOWN)) |
Rui Ueyama | 37bf9bb | 2019-10-10 09:46:41 | [diff] [blame^] | 108 | error("unknown argument: " + arg->getAsString(args)); |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 109 | return args; |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 110 | } |
| 111 | |
| 112 | // Find a file by concatenating given paths. |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 113 | static Optional<std::string> findFile(StringRef path1, const Twine &path2) { |
| 114 | SmallString<128> s; |
| 115 | sys::path::append(s, path1, path2); |
| 116 | if (sys::fs::exists(s)) |
| 117 | return s.str().str(); |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 118 | return None; |
| 119 | } |
| 120 | |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 121 | // This is for -lfoo. We'll look for libfoo.dll.a or libfoo.a from search paths. |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 122 | static std::string |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 123 | searchLibrary(StringRef name, ArrayRef<StringRef> searchPaths, bool bStatic) { |
| 124 | if (name.startswith(":")) { |
| 125 | for (StringRef dir : searchPaths) |
| 126 | if (Optional<std::string> s = findFile(dir, name.substr(1))) |
| 127 | return *s; |
Martin Storsjo | 0226c35 | 2019-10-10 08:52:39 | [diff] [blame] | 128 | error("unable to find library -l" + name); |
| 129 | return ""; |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 130 | } |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 131 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 132 | for (StringRef dir : searchPaths) { |
Martin Storsjo | 0226c35 | 2019-10-10 08:52:39 | [diff] [blame] | 133 | if (!bStatic) { |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 134 | if (Optional<std::string> s = findFile(dir, "lib" + name + ".dll.a")) |
| 135 | return *s; |
Martin Storsjo | 0226c35 | 2019-10-10 08:52:39 | [diff] [blame] | 136 | if (Optional<std::string> s = findFile(dir, name + ".dll.a")) |
| 137 | return *s; |
| 138 | } |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 139 | if (Optional<std::string> s = findFile(dir, "lib" + name + ".a")) |
| 140 | return *s; |
Martin Storsjo | 0226c35 | 2019-10-10 08:52:39 | [diff] [blame] | 141 | if (!bStatic) { |
| 142 | if (Optional<std::string> s = findFile(dir, name + ".lib")) |
| 143 | return *s; |
| 144 | if (Optional<std::string> s = findFile(dir, "lib" + name + ".dll")) { |
| 145 | error("lld doesn't support linking directly against " + *s + |
| 146 | ", use an import library"); |
| 147 | return ""; |
| 148 | } |
| 149 | if (Optional<std::string> s = findFile(dir, name + ".dll")) { |
| 150 | error("lld doesn't support linking directly against " + *s + |
| 151 | ", use an import library"); |
| 152 | return ""; |
| 153 | } |
| 154 | } |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 155 | } |
Martin Storsjo | 0226c35 | 2019-10-10 08:52:39 | [diff] [blame] | 156 | error("unable to find library -l" + name); |
| 157 | return ""; |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 158 | } |
| 159 | |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 160 | // Convert Unix-ish command line arguments to Windows-ish ones and |
| 161 | // then call coff::link. |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 162 | bool mingw::link(ArrayRef<const char *> argsArr, raw_ostream &diag) { |
Rui Ueyama | 37bf9bb | 2019-10-10 09:46:41 | [diff] [blame^] | 163 | enableColors(diag.has_colors()); |
| 164 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 165 | MinGWOptTable parser; |
| 166 | opt::InputArgList args = parser.parse(argsArr.slice(1)); |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 167 | |
Rui Ueyama | 37bf9bb | 2019-10-10 09:46:41 | [diff] [blame^] | 168 | if (errorCount()) |
| 169 | return false; |
| 170 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 171 | if (args.hasArg(OPT_help)) { |
| 172 | printHelp(argsArr[0]); |
Martin Storsjo | 9ae0d22 | 2019-05-17 11:07:38 | [diff] [blame] | 173 | return true; |
| 174 | } |
| 175 | |
Martin Storsjo | 6863dfa | 2019-05-17 11:07:42 | [diff] [blame] | 176 | // A note about "compatible with GNU linkers" message: this is a hack for |
| 177 | // scripts generated by GNU Libtool 2.4.6 (released in February 2014 and |
| 178 | // still the newest version in March 2017) or earlier to recognize LLD as |
| 179 | // a GNU compatible linker. As long as an output for the -v option |
| 180 | // contains "GNU" or "with BFD", they recognize us as GNU-compatible. |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 181 | if (args.hasArg(OPT_v) || args.hasArg(OPT_version)) |
Martin Storsjo | 6863dfa | 2019-05-17 11:07:42 | [diff] [blame] | 182 | message(getLLDVersion() + " (compatible with GNU linkers)"); |
| 183 | |
| 184 | // The behavior of -v or --version is a bit strange, but this is |
| 185 | // needed for compatibility with GNU linkers. |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 186 | if (args.hasArg(OPT_v) && !args.hasArg(OPT_INPUT) && !args.hasArg(OPT_l)) |
Martin Storsjo | 6863dfa | 2019-05-17 11:07:42 | [diff] [blame] | 187 | return true; |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 188 | if (args.hasArg(OPT_version)) |
Martin Storsjo | 6863dfa | 2019-05-17 11:07:42 | [diff] [blame] | 189 | return true; |
| 190 | |
Rui Ueyama | 37bf9bb | 2019-10-10 09:46:41 | [diff] [blame^] | 191 | if (!args.hasArg(OPT_INPUT) && !args.hasArg(OPT_l)) { |
| 192 | error("no input files"); |
| 193 | return false; |
| 194 | } |
Martin Storsjo | 9ae0d22 | 2019-05-17 11:07:38 | [diff] [blame] | 195 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 196 | std::vector<std::string> linkArgs; |
| 197 | auto add = [&](const Twine &s) { linkArgs.push_back(s.str()); }; |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 198 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 199 | add("lld-link"); |
| 200 | add("-lldmingw"); |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 201 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 202 | if (auto *a = args.getLastArg(OPT_entry)) { |
| 203 | StringRef s = a->getValue(); |
| 204 | if (args.getLastArgValue(OPT_m) == "i386pe" && s.startswith("_")) |
| 205 | add("-entry:" + s.substr(1)); |
Martin Storsjo | 6d8dace | 2017-09-12 19:23:54 | [diff] [blame] | 206 | else |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 207 | add("-entry:" + s); |
Martin Storsjo | 6d8dace | 2017-09-12 19:23:54 | [diff] [blame] | 208 | } |
| 209 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 210 | if (args.hasArg(OPT_major_os_version, OPT_minor_os_version, |
Martin Storsjo | 6f047ae | 2019-06-14 17:50:35 | [diff] [blame] | 211 | OPT_major_subsystem_version, OPT_minor_subsystem_version)) { |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 212 | auto *majOSVer = args.getLastArg(OPT_major_os_version); |
| 213 | auto *minOSVer = args.getLastArg(OPT_minor_os_version); |
| 214 | auto *majSubSysVer = args.getLastArg(OPT_major_subsystem_version); |
| 215 | auto *minSubSysVer = args.getLastArg(OPT_minor_subsystem_version); |
| 216 | if (majOSVer && majSubSysVer && |
| 217 | StringRef(majOSVer->getValue()) != StringRef(majSubSysVer->getValue())) |
Martin Storsjo | 6f047ae | 2019-06-14 17:50:35 | [diff] [blame] | 218 | warn("--major-os-version and --major-subsystem-version set to differing " |
| 219 | "versions, not supported"); |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 220 | if (minOSVer && minSubSysVer && |
| 221 | StringRef(minOSVer->getValue()) != StringRef(minSubSysVer->getValue())) |
Martin Storsjo | 6f047ae | 2019-06-14 17:50:35 | [diff] [blame] | 222 | warn("--minor-os-version and --minor-subsystem-version set to differing " |
| 223 | "versions, not supported"); |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 224 | StringRef subSys = args.getLastArgValue(OPT_subs, "default"); |
| 225 | StringRef major = majOSVer ? majOSVer->getValue() |
| 226 | : majSubSysVer ? majSubSysVer->getValue() : "6"; |
| 227 | StringRef minor = minOSVer ? minOSVer->getValue() |
| 228 | : minSubSysVer ? minSubSysVer->getValue() : ""; |
| 229 | StringRef sep = minor.empty() ? "" : "."; |
| 230 | add("-subsystem:" + subSys + "," + major + sep + minor); |
| 231 | } else if (auto *a = args.getLastArg(OPT_subs)) { |
| 232 | add("-subsystem:" + StringRef(a->getValue())); |
Martin Storsjo | 6f047ae | 2019-06-14 17:50:35 | [diff] [blame] | 233 | } |
| 234 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 235 | if (auto *a = args.getLastArg(OPT_out_implib)) |
| 236 | add("-implib:" + StringRef(a->getValue())); |
| 237 | if (auto *a = args.getLastArg(OPT_stack)) |
| 238 | add("-stack:" + StringRef(a->getValue())); |
| 239 | if (auto *a = args.getLastArg(OPT_output_def)) |
| 240 | add("-output-def:" + StringRef(a->getValue())); |
| 241 | if (auto *a = args.getLastArg(OPT_image_base)) |
| 242 | add("-base:" + StringRef(a->getValue())); |
| 243 | if (auto *a = args.getLastArg(OPT_map)) |
| 244 | add("-lldmap:" + StringRef(a->getValue())); |
Rui Ueyama | e4758a5 | 2019-10-04 07:27:45 | [diff] [blame] | 245 | if (auto *a = args.getLastArg(OPT_reproduce)) |
| 246 | add("-reproduce:" + StringRef(a->getValue())); |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 247 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 248 | if (auto *a = args.getLastArg(OPT_o)) |
| 249 | add("-out:" + StringRef(a->getValue())); |
| 250 | else if (args.hasArg(OPT_shared)) |
| 251 | add("-out:a.dll"); |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 252 | else |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 253 | add("-out:a.exe"); |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 254 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 255 | if (auto *a = args.getLastArg(OPT_pdb)) { |
| 256 | add("-debug"); |
| 257 | StringRef v = a->getValue(); |
| 258 | if (!v.empty()) |
| 259 | add("-pdb:" + v); |
| 260 | } else if (args.hasArg(OPT_strip_debug)) { |
| 261 | add("-debug:symtab"); |
| 262 | } else if (!args.hasArg(OPT_strip_all)) { |
| 263 | add("-debug:dwarf"); |
Martin Storsjo | b7d5011 | 2018-05-15 06:34:18 | [diff] [blame] | 264 | } |
| 265 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 266 | if (args.hasArg(OPT_shared)) |
| 267 | add("-dll"); |
| 268 | if (args.hasArg(OPT_verbose)) |
| 269 | add("-verbose"); |
| 270 | if (args.hasArg(OPT_exclude_all_symbols)) |
| 271 | add("-exclude-all-symbols"); |
| 272 | if (args.hasArg(OPT_export_all_symbols)) |
| 273 | add("-export-all-symbols"); |
| 274 | if (args.hasArg(OPT_large_address_aware)) |
| 275 | add("-largeaddressaware"); |
| 276 | if (args.hasArg(OPT_kill_at)) |
| 277 | add("-kill-at"); |
| 278 | if (args.hasArg(OPT_appcontainer)) |
| 279 | add("-appcontainer"); |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 280 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 281 | if (args.getLastArgValue(OPT_m) != "thumb2pe" && |
| 282 | args.getLastArgValue(OPT_m) != "arm64pe" && !args.hasArg(OPT_dynamicbase)) |
| 283 | add("-dynamicbase:no"); |
Martin Storsjo | 094d8c0 | 2017-11-15 08:18:11 | [diff] [blame] | 284 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 285 | if (args.hasFlag(OPT_no_insert_timestamp, OPT_insert_timestamp, false)) |
| 286 | add("-timestamp:0"); |
Martin Storsjo | 537a718 | 2019-02-05 08:16:06 | [diff] [blame] | 287 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 288 | if (args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false)) |
| 289 | add("-opt:ref"); |
Martin Storsjo | b190fd2 | 2017-11-15 08:18:20 | [diff] [blame] | 290 | else |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 291 | add("-opt:noref"); |
Martin Storsjo | b190fd2 | 2017-11-15 08:18:20 | [diff] [blame] | 292 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 293 | if (auto *a = args.getLastArg(OPT_icf)) { |
| 294 | StringRef s = a->getValue(); |
| 295 | if (s == "all") |
| 296 | add("-opt:icf"); |
| 297 | else if (s == "safe" || s == "none") |
| 298 | add("-opt:noicf"); |
Martin Storsjo | b190fd2 | 2017-11-15 08:18:20 | [diff] [blame] | 299 | else |
Rui Ueyama | 37bf9bb | 2019-10-10 09:46:41 | [diff] [blame^] | 300 | error("unknown parameter: --icf=" + s); |
Martin Storsjo | b190fd2 | 2017-11-15 08:18:20 | [diff] [blame] | 301 | } else { |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 302 | add("-opt:noicf"); |
Martin Storsjo | b190fd2 | 2017-11-15 08:18:20 | [diff] [blame] | 303 | } |
| 304 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 305 | if (auto *a = args.getLastArg(OPT_m)) { |
| 306 | StringRef s = a->getValue(); |
| 307 | if (s == "i386pe") |
| 308 | add("-machine:x86"); |
| 309 | else if (s == "i386pep") |
| 310 | add("-machine:x64"); |
| 311 | else if (s == "thumb2pe") |
| 312 | add("-machine:arm"); |
| 313 | else if (s == "arm64pe") |
| 314 | add("-machine:arm64"); |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 315 | else |
Rui Ueyama | 37bf9bb | 2019-10-10 09:46:41 | [diff] [blame^] | 316 | error("unknown parameter: -m" + s); |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 317 | } |
| 318 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 319 | for (auto *a : args.filtered(OPT_mllvm)) |
| 320 | add("-mllvm:" + StringRef(a->getValue())); |
Martell Malone | 0d17638 | 2017-09-11 21:36:37 | [diff] [blame] | 321 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 322 | for (auto *a : args.filtered(OPT_Xlink)) |
| 323 | add(a->getValue()); |
Martin Storsjo | 107b548 | 2017-11-03 07:18:37 | [diff] [blame] | 324 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 325 | if (args.getLastArgValue(OPT_m) == "i386pe") |
| 326 | add("-alternatename:__image_base__=___ImageBase"); |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 327 | else |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 328 | add("-alternatename:__image_base__=__ImageBase"); |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 329 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 330 | for (auto *a : args.filtered(OPT_require_defined)) |
| 331 | add("-include:" + StringRef(a->getValue())); |
| 332 | for (auto *a : args.filtered(OPT_undefined)) |
| 333 | add("-includeoptional:" + StringRef(a->getValue())); |
Martin Storsjo | c92b356 | 2019-08-05 11:57:06 | [diff] [blame] | 334 | for (auto *a : args.filtered(OPT_delayload)) |
| 335 | add("-delayload:" + StringRef(a->getValue())); |
Martin Storsjo | db62913 | 2018-09-10 17:41:40 | [diff] [blame] | 336 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 337 | std::vector<StringRef> searchPaths; |
| 338 | for (auto *a : args.filtered(OPT_L)) { |
| 339 | searchPaths.push_back(a->getValue()); |
| 340 | add("-libpath:" + StringRef(a->getValue())); |
Martin Storsjo | 803b37a | 2018-10-10 09:00:03 | [diff] [blame] | 341 | } |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 342 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 343 | StringRef prefix = ""; |
| 344 | bool isStatic = false; |
| 345 | for (auto *a : args) { |
| 346 | switch (a->getOption().getID()) { |
Martin Storsjo | 32e1626 | 2017-09-13 07:28:09 | [diff] [blame] | 347 | case OPT_INPUT: |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 348 | if (StringRef(a->getValue()).endswith_lower(".def")) |
| 349 | add("-def:" + StringRef(a->getValue())); |
Martin Storsjo | 064b0fa | 2017-09-13 07:28:13 | [diff] [blame] | 350 | else |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 351 | add(prefix + StringRef(a->getValue())); |
Martin Storsjo | 32e1626 | 2017-09-13 07:28:09 | [diff] [blame] | 352 | break; |
| 353 | case OPT_l: |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 354 | add(prefix + searchLibrary(a->getValue(), searchPaths, isStatic)); |
Martin Storsjo | 32e1626 | 2017-09-13 07:28:09 | [diff] [blame] | 355 | break; |
| 356 | case OPT_whole_archive: |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 357 | prefix = "-wholearchive:"; |
Martin Storsjo | 32e1626 | 2017-09-13 07:28:09 | [diff] [blame] | 358 | break; |
| 359 | case OPT_no_whole_archive: |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 360 | prefix = ""; |
Martin Storsjo | 32e1626 | 2017-09-13 07:28:09 | [diff] [blame] | 361 | break; |
Martin Storsjo | 2ba37d4 | 2017-09-13 19:29:44 | [diff] [blame] | 362 | case OPT_Bstatic: |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 363 | isStatic = true; |
Martin Storsjo | 2ba37d4 | 2017-09-13 19:29:44 | [diff] [blame] | 364 | break; |
| 365 | case OPT_Bdynamic: |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 366 | isStatic = false; |
Martin Storsjo | 2ba37d4 | 2017-09-13 19:29:44 | [diff] [blame] | 367 | break; |
Martin Storsjo | 32e1626 | 2017-09-13 07:28:09 | [diff] [blame] | 368 | } |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 369 | } |
| 370 | |
Martin Storsjo | 0226c35 | 2019-10-10 08:52:39 | [diff] [blame] | 371 | if (errorCount()) |
| 372 | return false; |
| 373 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 374 | if (args.hasArg(OPT_verbose) || args.hasArg(OPT__HASH_HASH_HASH)) |
| 375 | outs() << llvm::join(linkArgs, " ") << "\n"; |
Martin Storsjo | a79762a | 2017-09-11 20:43:39 | [diff] [blame] | 376 | |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 377 | if (args.hasArg(OPT__HASH_HASH_HASH)) |
Martin Storsjo | a79762a | 2017-09-11 20:43:39 | [diff] [blame] | 378 | return true; |
| 379 | |
Rui Ueyama | 5941b0b | 2017-09-11 20:14:47 | [diff] [blame] | 380 | // Repack vector of strings to vector of const char pointers for coff::link. |
Rui Ueyama | 136d27a | 2019-07-11 05:40:30 | [diff] [blame] | 381 | std::vector<const char *> vec; |
| 382 | for (const std::string &s : linkArgs) |
| 383 | vec.push_back(s.c_str()); |
| 384 | return coff::link(vec, true); |
Martell Malone | 894dbbe | 2017-09-11 17:02:59 | [diff] [blame] | 385 | } |