MSVC.cpp 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991
  1. //===-- MSVC.cpp - MSVC ToolChain Implementations -------------------------===//
  2. //
  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
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "MSVC.h"
  9. #include "CommonArgs.h"
  10. #include "Darwin.h"
  11. #include "clang/Basic/CharInfo.h"
  12. #include "clang/Basic/Version.h"
  13. #include "clang/Config/config.h"
  14. #include "clang/Driver/Compilation.h"
  15. #include "clang/Driver/Driver.h"
  16. #include "clang/Driver/DriverDiagnostic.h"
  17. #include "clang/Driver/Options.h"
  18. #include "clang/Driver/SanitizerArgs.h"
  19. #include "llvm/ADT/StringExtras.h"
  20. #include "llvm/Option/Arg.h"
  21. #include "llvm/Option/ArgList.h"
  22. #include "llvm/Support/ConvertUTF.h"
  23. #include "llvm/Support/ErrorHandling.h"
  24. #include "llvm/Support/FileSystem.h"
  25. #include "llvm/Support/Host.h"
  26. #include "llvm/Support/MemoryBuffer.h"
  27. #include "llvm/Support/Path.h"
  28. #include "llvm/Support/Process.h"
  29. #include "llvm/Support/VirtualFileSystem.h"
  30. #include <cstdio>
  31. #ifdef _WIN32
  32. #define WIN32_LEAN_AND_MEAN
  33. #define NOGDI
  34. #ifndef NOMINMAX
  35. #define NOMINMAX
  36. #endif
  37. #include <windows.h>
  38. #endif
  39. using namespace clang::driver;
  40. using namespace clang::driver::toolchains;
  41. using namespace clang::driver::tools;
  42. using namespace clang;
  43. using namespace llvm::opt;
  44. static bool canExecute(llvm::vfs::FileSystem &VFS, StringRef Path) {
  45. auto Status = VFS.status(Path);
  46. if (!Status)
  47. return false;
  48. return (Status->getPermissions() & llvm::sys::fs::perms::all_exe) != 0;
  49. }
  50. // Try to find Exe from a Visual Studio distribution. This first tries to find
  51. // an installed copy of Visual Studio and, failing that, looks in the PATH,
  52. // making sure that whatever executable that's found is not a same-named exe
  53. // from clang itself to prevent clang from falling back to itself.
  54. static std::string FindVisualStudioExecutable(const ToolChain &TC,
  55. const char *Exe) {
  56. const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC);
  57. SmallString<128> FilePath(
  58. MSVC.getSubDirectoryPath(llvm::SubDirectoryType::Bin));
  59. llvm::sys::path::append(FilePath, Exe);
  60. return std::string(canExecute(TC.getVFS(), FilePath) ? FilePath.str() : Exe);
  61. }
  62. void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
  63. const InputInfo &Output,
  64. const InputInfoList &Inputs,
  65. const ArgList &Args,
  66. const char *LinkingOutput) const {
  67. ArgStringList CmdArgs;
  68. auto &TC = static_cast<const toolchains::MSVCToolChain &>(getToolChain());
  69. assert((Output.isFilename() || Output.isNothing()) && "invalid output");
  70. if (Output.isFilename())
  71. CmdArgs.push_back(
  72. Args.MakeArgString(std::string("-out:") + Output.getFilename()));
  73. if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
  74. !C.getDriver().IsCLMode() && !C.getDriver().IsFlangMode()) {
  75. CmdArgs.push_back("-defaultlib:libcmt");
  76. CmdArgs.push_back("-defaultlib:oldnames");
  77. }
  78. // If the VC environment hasn't been configured (perhaps because the user
  79. // did not run vcvarsall), try to build a consistent link environment. If
  80. // the environment variable is set however, assume the user knows what
  81. // they're doing. If the user passes /vctoolsdir or /winsdkdir, trust that
  82. // over env vars.
  83. if (const Arg *A = Args.getLastArg(options::OPT__SLASH_diasdkdir,
  84. options::OPT__SLASH_winsysroot)) {
  85. // cl.exe doesn't find the DIA SDK automatically, so this too requires
  86. // explicit flags and doesn't automatically look in "DIA SDK" relative
  87. // to the path we found for VCToolChainPath.
  88. llvm::SmallString<128> DIAPath(A->getValue());
  89. if (A->getOption().getID() == options::OPT__SLASH_winsysroot)
  90. llvm::sys::path::append(DIAPath, "DIA SDK");
  91. // The DIA SDK always uses the legacy vc arch, even in new MSVC versions.
  92. llvm::sys::path::append(DIAPath, "lib",
  93. llvm::archToLegacyVCArch(TC.getArch()));
  94. CmdArgs.push_back(Args.MakeArgString(Twine("-libpath:") + DIAPath));
  95. }
  96. if (!llvm::sys::Process::GetEnv("LIB") ||
  97. Args.getLastArg(options::OPT__SLASH_vctoolsdir,
  98. options::OPT__SLASH_winsysroot)) {
  99. CmdArgs.push_back(Args.MakeArgString(
  100. Twine("-libpath:") +
  101. TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib)));
  102. CmdArgs.push_back(Args.MakeArgString(
  103. Twine("-libpath:") +
  104. TC.getSubDirectoryPath(llvm::SubDirectoryType::Lib, "atlmfc")));
  105. }
  106. if (!llvm::sys::Process::GetEnv("LIB") ||
  107. Args.getLastArg(options::OPT__SLASH_winsdkdir,
  108. options::OPT__SLASH_winsysroot)) {
  109. if (TC.useUniversalCRT()) {
  110. std::string UniversalCRTLibPath;
  111. if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath))
  112. CmdArgs.push_back(
  113. Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath));
  114. }
  115. std::string WindowsSdkLibPath;
  116. if (TC.getWindowsSDKLibraryPath(Args, WindowsSdkLibPath))
  117. CmdArgs.push_back(
  118. Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath));
  119. }
  120. if (C.getDriver().IsFlangMode()) {
  121. addFortranRuntimeLibraryPath(TC, Args, CmdArgs);
  122. addFortranRuntimeLibs(TC, CmdArgs);
  123. // Inform the MSVC linker that we're generating a console application, i.e.
  124. // one with `main` as the "user-defined" entry point. The `main` function is
  125. // defined in flang's runtime libraries.
  126. CmdArgs.push_back("/subsystem:console");
  127. }
  128. // Add the compiler-rt library directories to libpath if they exist to help
  129. // the linker find the various sanitizer, builtin, and profiling runtimes.
  130. for (const auto &LibPath : TC.getLibraryPaths()) {
  131. if (TC.getVFS().exists(LibPath))
  132. CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
  133. }
  134. auto CRTPath = TC.getCompilerRTPath();
  135. if (TC.getVFS().exists(CRTPath))
  136. CmdArgs.push_back(Args.MakeArgString("-libpath:" + CRTPath));
  137. if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L))
  138. for (const auto &LibPath : Args.getAllArgValues(options::OPT_L))
  139. CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath));
  140. CmdArgs.push_back("-nologo");
  141. if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7))
  142. CmdArgs.push_back("-debug");
  143. // If we specify /hotpatch, let the linker add padding in front of each
  144. // function, like MSVC does.
  145. if (Args.hasArg(options::OPT_fms_hotpatch, options::OPT__SLASH_hotpatch))
  146. CmdArgs.push_back("-functionpadmin");
  147. // Pass on /Brepro if it was passed to the compiler.
  148. // Note that /Brepro maps to -mno-incremental-linker-compatible.
  149. bool DefaultIncrementalLinkerCompatible =
  150. C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment();
  151. if (!Args.hasFlag(options::OPT_mincremental_linker_compatible,
  152. options::OPT_mno_incremental_linker_compatible,
  153. DefaultIncrementalLinkerCompatible))
  154. CmdArgs.push_back("-Brepro");
  155. bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd,
  156. options::OPT_shared);
  157. if (DLL) {
  158. CmdArgs.push_back(Args.MakeArgString("-dll"));
  159. SmallString<128> ImplibName(Output.getFilename());
  160. llvm::sys::path::replace_extension(ImplibName, "lib");
  161. CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName));
  162. }
  163. if (TC.getSanitizerArgs(Args).needsFuzzer()) {
  164. if (!Args.hasArg(options::OPT_shared))
  165. CmdArgs.push_back(
  166. Args.MakeArgString(std::string("-wholearchive:") +
  167. TC.getCompilerRTArgString(Args, "fuzzer")));
  168. CmdArgs.push_back(Args.MakeArgString("-debug"));
  169. // Prevent the linker from padding sections we use for instrumentation
  170. // arrays.
  171. CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
  172. }
  173. if (TC.getSanitizerArgs(Args).needsAsanRt()) {
  174. CmdArgs.push_back(Args.MakeArgString("-debug"));
  175. CmdArgs.push_back(Args.MakeArgString("-incremental:no"));
  176. if (TC.getSanitizerArgs(Args).needsSharedRt() ||
  177. Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) {
  178. for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
  179. CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
  180. // Make sure the dynamic runtime thunk is not optimized out at link time
  181. // to ensure proper SEH handling.
  182. CmdArgs.push_back(Args.MakeArgString(
  183. TC.getArch() == llvm::Triple::x86
  184. ? "-include:___asan_seh_interceptor"
  185. : "-include:__asan_seh_interceptor"));
  186. // Make sure the linker consider all object files from the dynamic runtime
  187. // thunk.
  188. CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
  189. TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk")));
  190. } else if (DLL) {
  191. CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
  192. } else {
  193. for (const auto &Lib : {"asan", "asan_cxx"}) {
  194. CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
  195. // Make sure the linker consider all object files from the static lib.
  196. // This is necessary because instrumented dlls need access to all the
  197. // interface exported by the static lib in the main executable.
  198. CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") +
  199. TC.getCompilerRT(Args, Lib)));
  200. }
  201. }
  202. }
  203. Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link);
  204. // Control Flow Guard checks
  205. if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
  206. StringRef GuardArgs = A->getValue();
  207. if (GuardArgs.equals_insensitive("cf") ||
  208. GuardArgs.equals_insensitive("cf,nochecks")) {
  209. // MSVC doesn't yet support the "nochecks" modifier.
  210. CmdArgs.push_back("-guard:cf");
  211. } else if (GuardArgs.equals_insensitive("cf-")) {
  212. CmdArgs.push_back("-guard:cf-");
  213. } else if (GuardArgs.equals_insensitive("ehcont")) {
  214. CmdArgs.push_back("-guard:ehcont");
  215. } else if (GuardArgs.equals_insensitive("ehcont-")) {
  216. CmdArgs.push_back("-guard:ehcont-");
  217. }
  218. }
  219. if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
  220. options::OPT_fno_openmp, false)) {
  221. CmdArgs.push_back("-nodefaultlib:vcomp.lib");
  222. CmdArgs.push_back("-nodefaultlib:vcompd.lib");
  223. CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") +
  224. TC.getDriver().Dir + "/../lib"));
  225. switch (TC.getDriver().getOpenMPRuntime(Args)) {
  226. case Driver::OMPRT_OMP:
  227. CmdArgs.push_back("-defaultlib:libomp.lib");
  228. break;
  229. case Driver::OMPRT_IOMP5:
  230. CmdArgs.push_back("-defaultlib:libiomp5md.lib");
  231. break;
  232. case Driver::OMPRT_GOMP:
  233. break;
  234. case Driver::OMPRT_Unknown:
  235. // Already diagnosed.
  236. break;
  237. }
  238. }
  239. // Add compiler-rt lib in case if it was explicitly
  240. // specified as an argument for --rtlib option.
  241. if (!Args.hasArg(options::OPT_nostdlib)) {
  242. AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args);
  243. }
  244. // Add filenames, libraries, and other linker inputs.
  245. for (const auto &Input : Inputs) {
  246. if (Input.isFilename()) {
  247. CmdArgs.push_back(Input.getFilename());
  248. continue;
  249. }
  250. const Arg &A = Input.getInputArg();
  251. // Render -l options differently for the MSVC linker.
  252. if (A.getOption().matches(options::OPT_l)) {
  253. StringRef Lib = A.getValue();
  254. const char *LinkLibArg;
  255. if (Lib.endswith(".lib"))
  256. LinkLibArg = Args.MakeArgString(Lib);
  257. else
  258. LinkLibArg = Args.MakeArgString(Lib + ".lib");
  259. CmdArgs.push_back(LinkLibArg);
  260. continue;
  261. }
  262. // Otherwise, this is some other kind of linker input option like -Wl, -z,
  263. // or -L. Render it, even if MSVC doesn't understand it.
  264. A.renderAsInput(Args, CmdArgs);
  265. }
  266. addHIPRuntimeLibArgs(TC, Args, CmdArgs);
  267. TC.addProfileRTLibs(Args, CmdArgs);
  268. std::vector<const char *> Environment;
  269. // We need to special case some linker paths. In the case of lld, we need to
  270. // translate 'lld' into 'lld-link', and in the case of the regular msvc
  271. // linker, we need to use a special search algorithm.
  272. llvm::SmallString<128> linkPath;
  273. StringRef Linker
  274. = Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER);
  275. if (Linker.empty())
  276. Linker = "link";
  277. if (Linker.equals_insensitive("lld"))
  278. Linker = "lld-link";
  279. if (Linker.equals_insensitive("link")) {
  280. // If we're using the MSVC linker, it's not sufficient to just use link
  281. // from the program PATH, because other environments like GnuWin32 install
  282. // their own link.exe which may come first.
  283. linkPath = FindVisualStudioExecutable(TC, "link.exe");
  284. if (!TC.FoundMSVCInstall() && !canExecute(TC.getVFS(), linkPath)) {
  285. llvm::SmallString<128> ClPath;
  286. ClPath = TC.GetProgramPath("cl.exe");
  287. if (canExecute(TC.getVFS(), ClPath)) {
  288. linkPath = llvm::sys::path::parent_path(ClPath);
  289. llvm::sys::path::append(linkPath, "link.exe");
  290. if (!canExecute(TC.getVFS(), linkPath))
  291. C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
  292. } else {
  293. C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found);
  294. }
  295. }
  296. #ifdef _WIN32
  297. // When cross-compiling with VS2017 or newer, link.exe expects to have
  298. // its containing bin directory at the top of PATH, followed by the
  299. // native target bin directory.
  300. // e.g. when compiling for x86 on an x64 host, PATH should start with:
  301. // /bin/Hostx64/x86;/bin/Hostx64/x64
  302. // This doesn't attempt to handle llvm::ToolsetLayout::DevDivInternal.
  303. if (TC.getIsVS2017OrNewer() &&
  304. llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) {
  305. auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch();
  306. auto EnvBlockWide =
  307. std::unique_ptr<wchar_t[], decltype(&FreeEnvironmentStringsW)>(
  308. GetEnvironmentStringsW(), FreeEnvironmentStringsW);
  309. if (!EnvBlockWide)
  310. goto SkipSettingEnvironment;
  311. size_t EnvCount = 0;
  312. size_t EnvBlockLen = 0;
  313. while (EnvBlockWide[EnvBlockLen] != L'\0') {
  314. ++EnvCount;
  315. EnvBlockLen += std::wcslen(&EnvBlockWide[EnvBlockLen]) +
  316. 1 /*string null-terminator*/;
  317. }
  318. ++EnvBlockLen; // add the block null-terminator
  319. std::string EnvBlock;
  320. if (!llvm::convertUTF16ToUTF8String(
  321. llvm::ArrayRef<char>(reinterpret_cast<char *>(EnvBlockWide.get()),
  322. EnvBlockLen * sizeof(EnvBlockWide[0])),
  323. EnvBlock))
  324. goto SkipSettingEnvironment;
  325. Environment.reserve(EnvCount);
  326. // Now loop over each string in the block and copy them into the
  327. // environment vector, adjusting the PATH variable as needed when we
  328. // find it.
  329. for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) {
  330. llvm::StringRef EnvVar(Cursor);
  331. if (EnvVar.startswith_insensitive("path=")) {
  332. constexpr size_t PrefixLen = 5; // strlen("path=")
  333. Environment.push_back(Args.MakeArgString(
  334. EnvVar.substr(0, PrefixLen) +
  335. TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin) +
  336. llvm::Twine(llvm::sys::EnvPathSeparator) +
  337. TC.getSubDirectoryPath(llvm::SubDirectoryType::Bin, HostArch) +
  338. (EnvVar.size() > PrefixLen
  339. ? llvm::Twine(llvm::sys::EnvPathSeparator) +
  340. EnvVar.substr(PrefixLen)
  341. : "")));
  342. } else {
  343. Environment.push_back(Args.MakeArgString(EnvVar));
  344. }
  345. Cursor += EnvVar.size() + 1 /*null-terminator*/;
  346. }
  347. }
  348. SkipSettingEnvironment:;
  349. #endif
  350. } else {
  351. linkPath = TC.GetProgramPath(Linker.str().c_str());
  352. }
  353. auto LinkCmd = std::make_unique<Command>(
  354. JA, *this, ResponseFileSupport::AtFileUTF16(),
  355. Args.MakeArgString(linkPath), CmdArgs, Inputs, Output);
  356. if (!Environment.empty())
  357. LinkCmd->setEnvironment(Environment);
  358. C.addCommand(std::move(LinkCmd));
  359. }
  360. MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple,
  361. const ArgList &Args)
  362. : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
  363. RocmInstallation(D, Triple, Args) {
  364. getProgramPaths().push_back(getDriver().getInstalledDir());
  365. if (getDriver().getInstalledDir() != getDriver().Dir)
  366. getProgramPaths().push_back(getDriver().Dir);
  367. std::optional<llvm::StringRef> VCToolsDir, VCToolsVersion;
  368. if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir))
  369. VCToolsDir = A->getValue();
  370. if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsversion))
  371. VCToolsVersion = A->getValue();
  372. if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir))
  373. WinSdkDir = A->getValue();
  374. if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion))
  375. WinSdkVersion = A->getValue();
  376. if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsysroot))
  377. WinSysRoot = A->getValue();
  378. // Check the command line first, that's the user explicitly telling us what to
  379. // use. Check the environment next, in case we're being invoked from a VS
  380. // command prompt. Failing that, just try to find the newest Visual Studio
  381. // version we can and use its default VC toolchain.
  382. llvm::findVCToolChainViaCommandLine(getVFS(), VCToolsDir, VCToolsVersion,
  383. WinSysRoot, VCToolChainPath, VSLayout) ||
  384. llvm::findVCToolChainViaEnvironment(getVFS(), VCToolChainPath,
  385. VSLayout) ||
  386. llvm::findVCToolChainViaSetupConfig(getVFS(), VCToolChainPath,
  387. VSLayout) ||
  388. llvm::findVCToolChainViaRegistry(VCToolChainPath, VSLayout);
  389. }
  390. Tool *MSVCToolChain::buildLinker() const {
  391. return new tools::visualstudio::Linker(*this);
  392. }
  393. Tool *MSVCToolChain::buildAssembler() const {
  394. if (getTriple().isOSBinFormatMachO())
  395. return new tools::darwin::Assembler(*this);
  396. getDriver().Diag(clang::diag::err_no_external_assembler);
  397. return nullptr;
  398. }
  399. bool MSVCToolChain::IsIntegratedAssemblerDefault() const {
  400. return true;
  401. }
  402. ToolChain::UnwindTableLevel
  403. MSVCToolChain::getDefaultUnwindTableLevel(const ArgList &Args) const {
  404. // Don't emit unwind tables by default for MachO targets.
  405. if (getTriple().isOSBinFormatMachO())
  406. return UnwindTableLevel::None;
  407. // All non-x86_32 Windows targets require unwind tables. However, LLVM
  408. // doesn't know how to generate them for all targets, so only enable
  409. // the ones that are actually implemented.
  410. if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm ||
  411. getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64)
  412. return UnwindTableLevel::Asynchronous;
  413. return UnwindTableLevel::None;
  414. }
  415. bool MSVCToolChain::isPICDefault() const {
  416. return getArch() == llvm::Triple::x86_64 ||
  417. getArch() == llvm::Triple::aarch64;
  418. }
  419. bool MSVCToolChain::isPIEDefault(const llvm::opt::ArgList &Args) const {
  420. return false;
  421. }
  422. bool MSVCToolChain::isPICDefaultForced() const {
  423. return getArch() == llvm::Triple::x86_64 ||
  424. getArch() == llvm::Triple::aarch64;
  425. }
  426. void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs,
  427. ArgStringList &CC1Args) const {
  428. CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
  429. }
  430. void MSVCToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs,
  431. ArgStringList &CC1Args) const {
  432. RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
  433. }
  434. void MSVCToolChain::AddHIPRuntimeLibArgs(const ArgList &Args,
  435. ArgStringList &CmdArgs) const {
  436. CmdArgs.append({Args.MakeArgString(StringRef("-libpath:") +
  437. RocmInstallation.getLibPath()),
  438. "amdhip64.lib"});
  439. }
  440. void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const {
  441. CudaInstallation.print(OS);
  442. RocmInstallation.print(OS);
  443. }
  444. std::string
  445. MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type,
  446. llvm::StringRef SubdirParent) const {
  447. return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, getArch(),
  448. SubdirParent);
  449. }
  450. std::string
  451. MSVCToolChain::getSubDirectoryPath(llvm::SubDirectoryType Type,
  452. llvm::Triple::ArchType TargetArch) const {
  453. return llvm::getSubDirectoryPath(Type, VSLayout, VCToolChainPath, TargetArch,
  454. "");
  455. }
  456. // Find the most recent version of Universal CRT or Windows 10 SDK.
  457. // vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include
  458. // directory by name and uses the last one of the list.
  459. // So we compare entry names lexicographically to find the greatest one.
  460. // Gets the library path required to link against the Windows SDK.
  461. bool MSVCToolChain::getWindowsSDKLibraryPath(const ArgList &Args,
  462. std::string &path) const {
  463. std::string sdkPath;
  464. int sdkMajor = 0;
  465. std::string windowsSDKIncludeVersion;
  466. std::string windowsSDKLibVersion;
  467. path.clear();
  468. if (!llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot,
  469. sdkPath, sdkMajor, windowsSDKIncludeVersion,
  470. windowsSDKLibVersion))
  471. return false;
  472. llvm::SmallString<128> libPath(sdkPath);
  473. llvm::sys::path::append(libPath, "Lib");
  474. if (sdkMajor >= 8)
  475. llvm::sys::path::append(libPath, windowsSDKLibVersion, "um");
  476. return llvm::appendArchToWindowsSDKLibPath(sdkMajor, libPath, getArch(),
  477. path);
  478. }
  479. bool MSVCToolChain::useUniversalCRT() const {
  480. return llvm::useUniversalCRT(VSLayout, VCToolChainPath, getArch(), getVFS());
  481. }
  482. bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args,
  483. std::string &Path) const {
  484. std::string UniversalCRTSdkPath;
  485. std::string UCRTVersion;
  486. Path.clear();
  487. if (!llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion,
  488. WinSysRoot, UniversalCRTSdkPath,
  489. UCRTVersion))
  490. return false;
  491. StringRef ArchName = llvm::archToWindowsSDKArch(getArch());
  492. if (ArchName.empty())
  493. return false;
  494. llvm::SmallString<128> LibPath(UniversalCRTSdkPath);
  495. llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName);
  496. Path = std::string(LibPath.str());
  497. return true;
  498. }
  499. static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) {
  500. VersionTuple Version;
  501. #ifdef _WIN32
  502. SmallString<128> ClExe(BinDir);
  503. llvm::sys::path::append(ClExe, "cl.exe");
  504. std::wstring ClExeWide;
  505. if (!llvm::ConvertUTF8toWide(ClExe.c_str(), ClExeWide))
  506. return Version;
  507. const DWORD VersionSize = ::GetFileVersionInfoSizeW(ClExeWide.c_str(),
  508. nullptr);
  509. if (VersionSize == 0)
  510. return Version;
  511. SmallVector<uint8_t, 4 * 1024> VersionBlock(VersionSize);
  512. if (!::GetFileVersionInfoW(ClExeWide.c_str(), 0, VersionSize,
  513. VersionBlock.data()))
  514. return Version;
  515. VS_FIXEDFILEINFO *FileInfo = nullptr;
  516. UINT FileInfoSize = 0;
  517. if (!::VerQueryValueW(VersionBlock.data(), L"\\",
  518. reinterpret_cast<LPVOID *>(&FileInfo), &FileInfoSize) ||
  519. FileInfoSize < sizeof(*FileInfo))
  520. return Version;
  521. const unsigned Major = (FileInfo->dwFileVersionMS >> 16) & 0xFFFF;
  522. const unsigned Minor = (FileInfo->dwFileVersionMS ) & 0xFFFF;
  523. const unsigned Micro = (FileInfo->dwFileVersionLS >> 16) & 0xFFFF;
  524. Version = VersionTuple(Major, Minor, Micro);
  525. #endif
  526. return Version;
  527. }
  528. void MSVCToolChain::AddSystemIncludeWithSubfolder(
  529. const ArgList &DriverArgs, ArgStringList &CC1Args,
  530. const std::string &folder, const Twine &subfolder1, const Twine &subfolder2,
  531. const Twine &subfolder3) const {
  532. llvm::SmallString<128> path(folder);
  533. llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3);
  534. addSystemInclude(DriverArgs, CC1Args, path);
  535. }
  536. void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
  537. ArgStringList &CC1Args) const {
  538. if (DriverArgs.hasArg(options::OPT_nostdinc))
  539. return;
  540. if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
  541. AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir,
  542. "include");
  543. }
  544. // Add %INCLUDE%-like directories from the -imsvc flag.
  545. for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc))
  546. addSystemInclude(DriverArgs, CC1Args, Path);
  547. auto AddSystemIncludesFromEnv = [&](StringRef Var) -> bool {
  548. if (auto Val = llvm::sys::Process::GetEnv(Var)) {
  549. SmallVector<StringRef, 8> Dirs;
  550. StringRef(*Val).split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false);
  551. if (!Dirs.empty()) {
  552. addSystemIncludes(DriverArgs, CC1Args, Dirs);
  553. return true;
  554. }
  555. }
  556. return false;
  557. };
  558. // Add %INCLUDE%-like dirs via /external:env: flags.
  559. for (const auto &Var :
  560. DriverArgs.getAllArgValues(options::OPT__SLASH_external_env)) {
  561. AddSystemIncludesFromEnv(Var);
  562. }
  563. // Add DIA SDK include if requested.
  564. if (const Arg *A = DriverArgs.getLastArg(options::OPT__SLASH_diasdkdir,
  565. options::OPT__SLASH_winsysroot)) {
  566. // cl.exe doesn't find the DIA SDK automatically, so this too requires
  567. // explicit flags and doesn't automatically look in "DIA SDK" relative
  568. // to the path we found for VCToolChainPath.
  569. llvm::SmallString<128> DIASDKPath(A->getValue());
  570. if (A->getOption().getID() == options::OPT__SLASH_winsysroot)
  571. llvm::sys::path::append(DIASDKPath, "DIA SDK");
  572. AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, std::string(DIASDKPath),
  573. "include");
  574. }
  575. if (DriverArgs.hasArg(options::OPT_nostdlibinc))
  576. return;
  577. // Honor %INCLUDE% and %EXTERNAL_INCLUDE%. It should have essential search
  578. // paths set by vcvarsall.bat. Skip if the user expressly set a vctoolsdir.
  579. if (!DriverArgs.getLastArg(options::OPT__SLASH_vctoolsdir,
  580. options::OPT__SLASH_winsysroot)) {
  581. bool Found = AddSystemIncludesFromEnv("INCLUDE");
  582. Found |= AddSystemIncludesFromEnv("EXTERNAL_INCLUDE");
  583. if (Found)
  584. return;
  585. }
  586. // When built with access to the proper Windows APIs, try to actually find
  587. // the correct include paths first.
  588. if (!VCToolChainPath.empty()) {
  589. addSystemInclude(DriverArgs, CC1Args,
  590. getSubDirectoryPath(llvm::SubDirectoryType::Include));
  591. addSystemInclude(
  592. DriverArgs, CC1Args,
  593. getSubDirectoryPath(llvm::SubDirectoryType::Include, "atlmfc"));
  594. if (useUniversalCRT()) {
  595. std::string UniversalCRTSdkPath;
  596. std::string UCRTVersion;
  597. if (llvm::getUniversalCRTSdkDir(getVFS(), WinSdkDir, WinSdkVersion,
  598. WinSysRoot, UniversalCRTSdkPath,
  599. UCRTVersion)) {
  600. AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath,
  601. "Include", UCRTVersion, "ucrt");
  602. }
  603. }
  604. std::string WindowsSDKDir;
  605. int major = 0;
  606. std::string windowsSDKIncludeVersion;
  607. std::string windowsSDKLibVersion;
  608. if (llvm::getWindowsSDKDir(getVFS(), WinSdkDir, WinSdkVersion, WinSysRoot,
  609. WindowsSDKDir, major, windowsSDKIncludeVersion,
  610. windowsSDKLibVersion)) {
  611. if (major >= 8) {
  612. // Note: windowsSDKIncludeVersion is empty for SDKs prior to v10.
  613. // Anyway, llvm::sys::path::append is able to manage it.
  614. AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
  615. "Include", windowsSDKIncludeVersion,
  616. "shared");
  617. AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
  618. "Include", windowsSDKIncludeVersion,
  619. "um");
  620. AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
  621. "Include", windowsSDKIncludeVersion,
  622. "winrt");
  623. if (major >= 10) {
  624. llvm::VersionTuple Tuple;
  625. if (!Tuple.tryParse(windowsSDKIncludeVersion) &&
  626. Tuple.getSubminor().value_or(0) >= 17134) {
  627. AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
  628. "Include", windowsSDKIncludeVersion,
  629. "cppwinrt");
  630. }
  631. }
  632. } else {
  633. AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir,
  634. "Include");
  635. }
  636. }
  637. return;
  638. }
  639. #if defined(_WIN32)
  640. // As a fallback, select default install paths.
  641. // FIXME: Don't guess drives and paths like this on Windows.
  642. const StringRef Paths[] = {
  643. "C:/Program Files/Microsoft Visual Studio 10.0/VC/include",
  644. "C:/Program Files/Microsoft Visual Studio 9.0/VC/include",
  645. "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include",
  646. "C:/Program Files/Microsoft Visual Studio 8/VC/include",
  647. "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include"
  648. };
  649. addSystemIncludes(DriverArgs, CC1Args, Paths);
  650. #endif
  651. }
  652. void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
  653. ArgStringList &CC1Args) const {
  654. // FIXME: There should probably be logic here to find libc++ on Windows.
  655. }
  656. VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D,
  657. const ArgList &Args) const {
  658. bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment();
  659. VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args);
  660. if (MSVT.empty())
  661. MSVT = getTriple().getEnvironmentVersion();
  662. if (MSVT.empty() && IsWindowsMSVC)
  663. MSVT =
  664. getMSVCVersionFromExe(getSubDirectoryPath(llvm::SubDirectoryType::Bin));
  665. if (MSVT.empty() &&
  666. Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions,
  667. IsWindowsMSVC)) {
  668. // -fms-compatibility-version=19.20 is default, aka 2019, 16.x
  669. MSVT = VersionTuple(19, 20);
  670. }
  671. return MSVT;
  672. }
  673. std::string
  674. MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args,
  675. types::ID InputType) const {
  676. // The MSVC version doesn't care about the architecture, even though it
  677. // may look at the triple internally.
  678. VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args);
  679. MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().value_or(0),
  680. MSVT.getSubminor().value_or(0));
  681. // For the rest of the triple, however, a computed architecture name may
  682. // be needed.
  683. llvm::Triple Triple(ToolChain::ComputeEffectiveClangTriple(Args, InputType));
  684. if (Triple.getEnvironment() == llvm::Triple::MSVC) {
  685. StringRef ObjFmt = Triple.getEnvironmentName().split('-').second;
  686. if (ObjFmt.empty())
  687. Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str());
  688. else
  689. Triple.setEnvironmentName(
  690. (Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str());
  691. }
  692. return Triple.getTriple();
  693. }
  694. SanitizerMask MSVCToolChain::getSupportedSanitizers() const {
  695. SanitizerMask Res = ToolChain::getSupportedSanitizers();
  696. Res |= SanitizerKind::Address;
  697. Res |= SanitizerKind::PointerCompare;
  698. Res |= SanitizerKind::PointerSubtract;
  699. Res |= SanitizerKind::Fuzzer;
  700. Res |= SanitizerKind::FuzzerNoLink;
  701. Res &= ~SanitizerKind::CFIMFCall;
  702. return Res;
  703. }
  704. static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL,
  705. bool SupportsForcingFramePointer,
  706. const char *ExpandChar, const OptTable &Opts) {
  707. assert(A->getOption().matches(options::OPT__SLASH_O));
  708. StringRef OptStr = A->getValue();
  709. for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
  710. const char &OptChar = *(OptStr.data() + I);
  711. switch (OptChar) {
  712. default:
  713. break;
  714. case '1':
  715. case '2':
  716. case 'x':
  717. case 'd':
  718. // Ignore /O[12xd] flags that aren't the last one on the command line.
  719. // Only the last one gets expanded.
  720. if (&OptChar != ExpandChar) {
  721. A->claim();
  722. break;
  723. }
  724. if (OptChar == 'd') {
  725. DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0));
  726. } else {
  727. if (OptChar == '1') {
  728. DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
  729. } else if (OptChar == '2' || OptChar == 'x') {
  730. DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
  731. DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
  732. }
  733. if (SupportsForcingFramePointer &&
  734. !DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer))
  735. DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer));
  736. if (OptChar == '1' || OptChar == '2')
  737. DAL.AddFlagArg(A, Opts.getOption(options::OPT_ffunction_sections));
  738. }
  739. break;
  740. case 'b':
  741. if (I + 1 != E && isdigit(OptStr[I + 1])) {
  742. switch (OptStr[I + 1]) {
  743. case '0':
  744. DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline));
  745. break;
  746. case '1':
  747. DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions));
  748. break;
  749. case '2':
  750. DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions));
  751. break;
  752. }
  753. ++I;
  754. }
  755. break;
  756. case 'g':
  757. A->claim();
  758. break;
  759. case 'i':
  760. if (I + 1 != E && OptStr[I + 1] == '-') {
  761. ++I;
  762. DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin));
  763. } else {
  764. DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin));
  765. }
  766. break;
  767. case 's':
  768. DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s");
  769. break;
  770. case 't':
  771. DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2");
  772. break;
  773. case 'y': {
  774. bool OmitFramePointer = true;
  775. if (I + 1 != E && OptStr[I + 1] == '-') {
  776. OmitFramePointer = false;
  777. ++I;
  778. }
  779. if (SupportsForcingFramePointer) {
  780. if (OmitFramePointer)
  781. DAL.AddFlagArg(A,
  782. Opts.getOption(options::OPT_fomit_frame_pointer));
  783. else
  784. DAL.AddFlagArg(
  785. A, Opts.getOption(options::OPT_fno_omit_frame_pointer));
  786. } else {
  787. // Don't warn about /Oy- in x86-64 builds (where
  788. // SupportsForcingFramePointer is false). The flag having no effect
  789. // there is a compiler-internal optimization, and people shouldn't have
  790. // to special-case their build files for x86-64 clang-cl.
  791. A->claim();
  792. }
  793. break;
  794. }
  795. }
  796. }
  797. }
  798. static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL,
  799. const OptTable &Opts) {
  800. assert(A->getOption().matches(options::OPT_D));
  801. StringRef Val = A->getValue();
  802. size_t Hash = Val.find('#');
  803. if (Hash == StringRef::npos || Hash > Val.find('=')) {
  804. DAL.append(A);
  805. return;
  806. }
  807. std::string NewVal = std::string(Val);
  808. NewVal[Hash] = '=';
  809. DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal);
  810. }
  811. static void TranslatePermissive(Arg *A, llvm::opt::DerivedArgList &DAL,
  812. const OptTable &Opts) {
  813. DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase_));
  814. DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_operator_names));
  815. }
  816. static void TranslatePermissiveMinus(Arg *A, llvm::opt::DerivedArgList &DAL,
  817. const OptTable &Opts) {
  818. DAL.AddFlagArg(A, Opts.getOption(options::OPT__SLASH_Zc_twoPhase));
  819. DAL.AddFlagArg(A, Opts.getOption(options::OPT_foperator_names));
  820. }
  821. llvm::opt::DerivedArgList *
  822. MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args,
  823. StringRef BoundArch,
  824. Action::OffloadKind OFK) const {
  825. DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs());
  826. const OptTable &Opts = getDriver().getOpts();
  827. // /Oy and /Oy- don't have an effect on X86-64
  828. bool SupportsForcingFramePointer = getArch() != llvm::Triple::x86_64;
  829. // The -O[12xd] flag actually expands to several flags. We must desugar the
  830. // flags so that options embedded can be negated. For example, the '-O2' flag
  831. // enables '-Oy'. Expanding '-O2' into its constituent flags allows us to
  832. // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single
  833. // aspect of '-O2'.
  834. //
  835. // Note that this expansion logic only applies to the *last* of '[12xd]'.
  836. // First step is to search for the character we'd like to expand.
  837. const char *ExpandChar = nullptr;
  838. for (Arg *A : Args.filtered(options::OPT__SLASH_O)) {
  839. StringRef OptStr = A->getValue();
  840. for (size_t I = 0, E = OptStr.size(); I != E; ++I) {
  841. char OptChar = OptStr[I];
  842. char PrevChar = I > 0 ? OptStr[I - 1] : '0';
  843. if (PrevChar == 'b') {
  844. // OptChar does not expand; it's an argument to the previous char.
  845. continue;
  846. }
  847. if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd')
  848. ExpandChar = OptStr.data() + I;
  849. }
  850. }
  851. for (Arg *A : Args) {
  852. if (A->getOption().matches(options::OPT__SLASH_O)) {
  853. // The -O flag actually takes an amalgam of other options. For example,
  854. // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'.
  855. TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts);
  856. } else if (A->getOption().matches(options::OPT_D)) {
  857. // Translate -Dfoo#bar into -Dfoo=bar.
  858. TranslateDArg(A, *DAL, Opts);
  859. } else if (A->getOption().matches(options::OPT__SLASH_permissive)) {
  860. // Expand /permissive
  861. TranslatePermissive(A, *DAL, Opts);
  862. } else if (A->getOption().matches(options::OPT__SLASH_permissive_)) {
  863. // Expand /permissive-
  864. TranslatePermissiveMinus(A, *DAL, Opts);
  865. } else if (OFK != Action::OFK_HIP) {
  866. // HIP Toolchain translates input args by itself.
  867. DAL->append(A);
  868. }
  869. }
  870. return DAL;
  871. }
  872. void MSVCToolChain::addClangTargetOptions(
  873. const ArgList &DriverArgs, ArgStringList &CC1Args,
  874. Action::OffloadKind DeviceOffloadKind) const {
  875. // MSVC STL kindly allows removing all usages of typeid by defining
  876. // _HAS_STATIC_RTTI to 0. Do so, when compiling with -fno-rtti
  877. if (DriverArgs.hasFlag(options::OPT_fno_rtti, options::OPT_frtti,
  878. /*Default=*/false))
  879. CC1Args.push_back("-D_HAS_STATIC_RTTI=0");
  880. }