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 9 #include "MSVC.h" 10 #include "CommonArgs.h" 11 #include "Darwin.h" 12 #include "clang/Basic/CharInfo.h" 13 #include "clang/Basic/Version.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/ADT/StringSwitch.h" 21 #include "llvm/Option/Arg.h" 22 #include "llvm/Option/ArgList.h" 23 #include "llvm/Support/ConvertUTF.h" 24 #include "llvm/Support/ErrorHandling.h" 25 #include "llvm/Support/FileSystem.h" 26 #include "llvm/Support/Host.h" 27 #include "llvm/Support/MemoryBuffer.h" 28 #include "llvm/Support/Path.h" 29 #include "llvm/Support/Process.h" 30 #include <cstdio> 31 32 #ifdef _WIN32 33 #define WIN32_LEAN_AND_MEAN 34 #define NOGDI 35 #ifndef NOMINMAX 36 #define NOMINMAX 37 #endif 38 #include <windows.h> 39 #endif 40 41 #ifdef _MSC_VER 42 // Don't support SetupApi on MinGW. 43 #define USE_MSVC_SETUP_API 44 45 // Make sure this comes before MSVCSetupApi.h 46 #include <comdef.h> 47 48 #include "MSVCSetupApi.h" 49 #include "llvm/Support/COM.h" 50 _COM_SMARTPTR_TYPEDEF(ISetupConfiguration, __uuidof(ISetupConfiguration)); 51 _COM_SMARTPTR_TYPEDEF(ISetupConfiguration2, __uuidof(ISetupConfiguration2)); 52 _COM_SMARTPTR_TYPEDEF(ISetupHelper, __uuidof(ISetupHelper)); 53 _COM_SMARTPTR_TYPEDEF(IEnumSetupInstances, __uuidof(IEnumSetupInstances)); 54 _COM_SMARTPTR_TYPEDEF(ISetupInstance, __uuidof(ISetupInstance)); 55 _COM_SMARTPTR_TYPEDEF(ISetupInstance2, __uuidof(ISetupInstance2)); 56 #endif 57 58 using namespace clang::driver; 59 using namespace clang::driver::toolchains; 60 using namespace clang::driver::tools; 61 using namespace clang; 62 using namespace llvm::opt; 63 64 // Defined below. 65 // Forward declare this so there aren't too many things above the constructor. 66 static bool getSystemRegistryString(const char *keyPath, const char *valueName, 67 std::string &value, std::string *phValue); 68 69 static std::string getHighestNumericTupleInDirectory(StringRef Directory) { 70 std::string Highest; 71 llvm::VersionTuple HighestTuple; 72 73 std::error_code EC; 74 for (llvm::sys::fs::directory_iterator DirIt(Directory, EC), DirEnd; 75 !EC && DirIt != DirEnd; DirIt.increment(EC)) { 76 if (!llvm::sys::fs::is_directory(DirIt->path())) 77 continue; 78 StringRef CandidateName = llvm::sys::path::filename(DirIt->path()); 79 llvm::VersionTuple Tuple; 80 if (Tuple.tryParse(CandidateName)) // tryParse() returns true on error. 81 continue; 82 if (Tuple > HighestTuple) { 83 HighestTuple = Tuple; 84 Highest = CandidateName.str(); 85 } 86 } 87 88 return Highest; 89 } 90 91 // Check command line arguments to try and find a toolchain. 92 static bool 93 findVCToolChainViaCommandLine(const ArgList &Args, std::string &Path, 94 MSVCToolChain::ToolsetLayout &VSLayout) { 95 // Don't validate the input; trust the value supplied by the user. 96 // The primary motivation is to prevent unnecessary file and registry access. 97 if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsdir, 98 options::OPT__SLASH_winsysroot)) { 99 if (A->getOption().getID() == options::OPT__SLASH_winsysroot) { 100 llvm::SmallString<128> ToolsPath(A->getValue()); 101 llvm::sys::path::append(ToolsPath, "VC", "Tools", "MSVC"); 102 std::string VCToolsVersion; 103 if (Arg *A = Args.getLastArg(options::OPT__SLASH_vctoolsversion)) 104 VCToolsVersion = A->getValue(); 105 else 106 VCToolsVersion = getHighestNumericTupleInDirectory(ToolsPath); 107 llvm::sys::path::append(ToolsPath, VCToolsVersion); 108 Path = std::string(ToolsPath.str()); 109 } else { 110 Path = A->getValue(); 111 } 112 VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer; 113 return true; 114 } 115 return false; 116 } 117 118 // Check various environment variables to try and find a toolchain. 119 static bool 120 findVCToolChainViaEnvironment(std::string &Path, 121 MSVCToolChain::ToolsetLayout &VSLayout) { 122 // These variables are typically set by vcvarsall.bat 123 // when launching a developer command prompt. 124 if (llvm::Optional<std::string> VCToolsInstallDir = 125 llvm::sys::Process::GetEnv("VCToolsInstallDir")) { 126 // This is only set by newer Visual Studios, and it leads straight to 127 // the toolchain directory. 128 Path = std::move(*VCToolsInstallDir); 129 VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer; 130 return true; 131 } 132 if (llvm::Optional<std::string> VCInstallDir = 133 llvm::sys::Process::GetEnv("VCINSTALLDIR")) { 134 // If the previous variable isn't set but this one is, then we've found 135 // an older Visual Studio. This variable is set by newer Visual Studios too, 136 // so this check has to appear second. 137 // In older Visual Studios, the VC directory is the toolchain. 138 Path = std::move(*VCInstallDir); 139 VSLayout = MSVCToolChain::ToolsetLayout::OlderVS; 140 return true; 141 } 142 143 // We couldn't find any VC environment variables. Let's walk through PATH and 144 // see if it leads us to a VC toolchain bin directory. If it does, pick the 145 // first one that we find. 146 if (llvm::Optional<std::string> PathEnv = 147 llvm::sys::Process::GetEnv("PATH")) { 148 llvm::SmallVector<llvm::StringRef, 8> PathEntries; 149 llvm::StringRef(*PathEnv).split(PathEntries, llvm::sys::EnvPathSeparator); 150 for (llvm::StringRef PathEntry : PathEntries) { 151 if (PathEntry.empty()) 152 continue; 153 154 llvm::SmallString<256> ExeTestPath; 155 156 // If cl.exe doesn't exist, then this definitely isn't a VC toolchain. 157 ExeTestPath = PathEntry; 158 llvm::sys::path::append(ExeTestPath, "cl.exe"); 159 if (!llvm::sys::fs::exists(ExeTestPath)) 160 continue; 161 162 // cl.exe existing isn't a conclusive test for a VC toolchain; clang also 163 // has a cl.exe. So let's check for link.exe too. 164 ExeTestPath = PathEntry; 165 llvm::sys::path::append(ExeTestPath, "link.exe"); 166 if (!llvm::sys::fs::exists(ExeTestPath)) 167 continue; 168 169 // whatever/VC/bin --> old toolchain, VC dir is toolchain dir. 170 llvm::StringRef TestPath = PathEntry; 171 bool IsBin = llvm::sys::path::filename(TestPath).equals_lower("bin"); 172 if (!IsBin) { 173 // Strip any architecture subdir like "amd64". 174 TestPath = llvm::sys::path::parent_path(TestPath); 175 IsBin = llvm::sys::path::filename(TestPath).equals_lower("bin"); 176 } 177 if (IsBin) { 178 llvm::StringRef ParentPath = llvm::sys::path::parent_path(TestPath); 179 llvm::StringRef ParentFilename = llvm::sys::path::filename(ParentPath); 180 if (ParentFilename == "VC") { 181 Path = std::string(ParentPath); 182 VSLayout = MSVCToolChain::ToolsetLayout::OlderVS; 183 return true; 184 } 185 if (ParentFilename == "x86ret" || ParentFilename == "x86chk" 186 || ParentFilename == "amd64ret" || ParentFilename == "amd64chk") { 187 Path = std::string(ParentPath); 188 VSLayout = MSVCToolChain::ToolsetLayout::DevDivInternal; 189 return true; 190 } 191 192 } else { 193 // This could be a new (>=VS2017) toolchain. If it is, we should find 194 // path components with these prefixes when walking backwards through 195 // the path. 196 // Note: empty strings match anything. 197 llvm::StringRef ExpectedPrefixes[] = {"", "Host", "bin", "", 198 "MSVC", "Tools", "VC"}; 199 200 auto It = llvm::sys::path::rbegin(PathEntry); 201 auto End = llvm::sys::path::rend(PathEntry); 202 for (llvm::StringRef Prefix : ExpectedPrefixes) { 203 if (It == End) 204 goto NotAToolChain; 205 if (!It->startswith(Prefix)) 206 goto NotAToolChain; 207 ++It; 208 } 209 210 // We've found a new toolchain! 211 // Back up 3 times (/bin/Host/arch) to get the root path. 212 llvm::StringRef ToolChainPath(PathEntry); 213 for (int i = 0; i < 3; ++i) 214 ToolChainPath = llvm::sys::path::parent_path(ToolChainPath); 215 216 Path = std::string(ToolChainPath); 217 VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer; 218 return true; 219 } 220 221 NotAToolChain: 222 continue; 223 } 224 } 225 return false; 226 } 227 228 // Query the Setup Config server for installs, then pick the newest version 229 // and find its default VC toolchain. 230 // This is the preferred way to discover new Visual Studios, as they're no 231 // longer listed in the registry. 232 static bool findVCToolChainViaSetupConfig(std::string &Path, 233 MSVCToolChain::ToolsetLayout &VSLayout) { 234 #if !defined(USE_MSVC_SETUP_API) 235 return false; 236 #else 237 // FIXME: This really should be done once in the top-level program's main 238 // function, as it may have already been initialized with a different 239 // threading model otherwise. 240 llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::SingleThreaded); 241 HRESULT HR; 242 243 // _com_ptr_t will throw a _com_error if a COM calls fail. 244 // The LLVM coding standards forbid exception handling, so we'll have to 245 // stop them from being thrown in the first place. 246 // The destructor will put the regular error handler back when we leave 247 // this scope. 248 struct SuppressCOMErrorsRAII { 249 static void __stdcall handler(HRESULT hr, IErrorInfo *perrinfo) {} 250 251 SuppressCOMErrorsRAII() { _set_com_error_handler(handler); } 252 253 ~SuppressCOMErrorsRAII() { _set_com_error_handler(_com_raise_error); } 254 255 } COMErrorSuppressor; 256 257 ISetupConfigurationPtr Query; 258 HR = Query.CreateInstance(__uuidof(SetupConfiguration)); 259 if (FAILED(HR)) 260 return false; 261 262 IEnumSetupInstancesPtr EnumInstances; 263 HR = ISetupConfiguration2Ptr(Query)->EnumAllInstances(&EnumInstances); 264 if (FAILED(HR)) 265 return false; 266 267 ISetupInstancePtr Instance; 268 HR = EnumInstances->Next(1, &Instance, nullptr); 269 if (HR != S_OK) 270 return false; 271 272 ISetupInstancePtr NewestInstance; 273 Optional<uint64_t> NewestVersionNum; 274 do { 275 bstr_t VersionString; 276 uint64_t VersionNum; 277 HR = Instance->GetInstallationVersion(VersionString.GetAddress()); 278 if (FAILED(HR)) 279 continue; 280 HR = ISetupHelperPtr(Query)->ParseVersion(VersionString, &VersionNum); 281 if (FAILED(HR)) 282 continue; 283 if (!NewestVersionNum || (VersionNum > NewestVersionNum)) { 284 NewestInstance = Instance; 285 NewestVersionNum = VersionNum; 286 } 287 } while ((HR = EnumInstances->Next(1, &Instance, nullptr)) == S_OK); 288 289 if (!NewestInstance) 290 return false; 291 292 bstr_t VCPathWide; 293 HR = NewestInstance->ResolvePath(L"VC", VCPathWide.GetAddress()); 294 if (FAILED(HR)) 295 return false; 296 297 std::string VCRootPath; 298 llvm::convertWideToUTF8(std::wstring(VCPathWide), VCRootPath); 299 300 llvm::SmallString<256> ToolsVersionFilePath(VCRootPath); 301 llvm::sys::path::append(ToolsVersionFilePath, "Auxiliary", "Build", 302 "Microsoft.VCToolsVersion.default.txt"); 303 304 auto ToolsVersionFile = llvm::MemoryBuffer::getFile(ToolsVersionFilePath); 305 if (!ToolsVersionFile) 306 return false; 307 308 llvm::SmallString<256> ToolchainPath(VCRootPath); 309 llvm::sys::path::append(ToolchainPath, "Tools", "MSVC", 310 ToolsVersionFile->get()->getBuffer().rtrim()); 311 if (!llvm::sys::fs::is_directory(ToolchainPath)) 312 return false; 313 314 Path = std::string(ToolchainPath.str()); 315 VSLayout = MSVCToolChain::ToolsetLayout::VS2017OrNewer; 316 return true; 317 #endif 318 } 319 320 // Look in the registry for Visual Studio installs, and use that to get 321 // a toolchain path. VS2017 and newer don't get added to the registry. 322 // So if we find something here, we know that it's an older version. 323 static bool findVCToolChainViaRegistry(std::string &Path, 324 MSVCToolChain::ToolsetLayout &VSLayout) { 325 std::string VSInstallPath; 326 if (getSystemRegistryString(R"(SOFTWARE\Microsoft\VisualStudio\$VERSION)", 327 "InstallDir", VSInstallPath, nullptr) || 328 getSystemRegistryString(R"(SOFTWARE\Microsoft\VCExpress\$VERSION)", 329 "InstallDir", VSInstallPath, nullptr)) { 330 if (!VSInstallPath.empty()) { 331 llvm::SmallString<256> VCPath(llvm::StringRef( 332 VSInstallPath.c_str(), VSInstallPath.find(R"(\Common7\IDE)"))); 333 llvm::sys::path::append(VCPath, "VC"); 334 335 Path = std::string(VCPath.str()); 336 VSLayout = MSVCToolChain::ToolsetLayout::OlderVS; 337 return true; 338 } 339 } 340 return false; 341 } 342 343 // Try to find Exe from a Visual Studio distribution. This first tries to find 344 // an installed copy of Visual Studio and, failing that, looks in the PATH, 345 // making sure that whatever executable that's found is not a same-named exe 346 // from clang itself to prevent clang from falling back to itself. 347 static std::string FindVisualStudioExecutable(const ToolChain &TC, 348 const char *Exe) { 349 const auto &MSVC = static_cast<const toolchains::MSVCToolChain &>(TC); 350 SmallString<128> FilePath(MSVC.getSubDirectoryPath( 351 toolchains::MSVCToolChain::SubDirectoryType::Bin)); 352 llvm::sys::path::append(FilePath, Exe); 353 return std::string(llvm::sys::fs::can_execute(FilePath) ? FilePath.str() 354 : Exe); 355 } 356 357 void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, 358 const InputInfo &Output, 359 const InputInfoList &Inputs, 360 const ArgList &Args, 361 const char *LinkingOutput) const { 362 ArgStringList CmdArgs; 363 364 auto &TC = static_cast<const toolchains::MSVCToolChain &>(getToolChain()); 365 366 assert((Output.isFilename() || Output.isNothing()) && "invalid output"); 367 if (Output.isFilename()) 368 CmdArgs.push_back( 369 Args.MakeArgString(std::string("-out:") + Output.getFilename())); 370 371 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) && 372 !C.getDriver().IsCLMode()) { 373 CmdArgs.push_back("-defaultlib:libcmt"); 374 CmdArgs.push_back("-defaultlib:oldnames"); 375 } 376 377 // If the VC environment hasn't been configured (perhaps because the user 378 // did not run vcvarsall), try to build a consistent link environment. If 379 // the environment variable is set however, assume the user knows what 380 // they're doing. If the user passes /vctoolsdir or /winsdkdir, trust that 381 // over env vars. 382 if (!llvm::sys::Process::GetEnv("LIB") || 383 Args.getLastArg(options::OPT__SLASH_vctoolsdir, 384 options::OPT__SLASH_winsysroot)) { 385 CmdArgs.push_back(Args.MakeArgString( 386 Twine("-libpath:") + 387 TC.getSubDirectoryPath( 388 toolchains::MSVCToolChain::SubDirectoryType::Lib))); 389 CmdArgs.push_back(Args.MakeArgString( 390 Twine("-libpath:") + 391 TC.getSubDirectoryPath(toolchains::MSVCToolChain::SubDirectoryType::Lib, 392 "atlmfc"))); 393 } 394 if (!llvm::sys::Process::GetEnv("LIB") || 395 Args.getLastArg(options::OPT__SLASH_winsdkdir, 396 options::OPT__SLASH_winsysroot)) { 397 if (TC.useUniversalCRT()) { 398 std::string UniversalCRTLibPath; 399 if (TC.getUniversalCRTLibraryPath(Args, UniversalCRTLibPath)) 400 CmdArgs.push_back( 401 Args.MakeArgString(Twine("-libpath:") + UniversalCRTLibPath)); 402 } 403 std::string WindowsSdkLibPath; 404 if (TC.getWindowsSDKLibraryPath(Args, WindowsSdkLibPath)) 405 CmdArgs.push_back( 406 Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath)); 407 } 408 409 // Add the compiler-rt library directories to libpath if they exist to help 410 // the linker find the various sanitizer, builtin, and profiling runtimes. 411 for (const auto &LibPath : TC.getLibraryPaths()) { 412 if (TC.getVFS().exists(LibPath)) 413 CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath)); 414 } 415 auto CRTPath = TC.getCompilerRTPath(); 416 if (TC.getVFS().exists(CRTPath)) 417 CmdArgs.push_back(Args.MakeArgString("-libpath:" + CRTPath)); 418 419 if (!C.getDriver().IsCLMode() && Args.hasArg(options::OPT_L)) 420 for (const auto &LibPath : Args.getAllArgValues(options::OPT_L)) 421 CmdArgs.push_back(Args.MakeArgString("-libpath:" + LibPath)); 422 423 CmdArgs.push_back("-nologo"); 424 425 if (Args.hasArg(options::OPT_g_Group, options::OPT__SLASH_Z7)) 426 CmdArgs.push_back("-debug"); 427 428 // Pass on /Brepro if it was passed to the compiler. 429 // Note that /Brepro maps to -mno-incremental-linker-compatible. 430 bool DefaultIncrementalLinkerCompatible = 431 C.getDefaultToolChain().getTriple().isWindowsMSVCEnvironment(); 432 if (!Args.hasFlag(options::OPT_mincremental_linker_compatible, 433 options::OPT_mno_incremental_linker_compatible, 434 DefaultIncrementalLinkerCompatible)) 435 CmdArgs.push_back("-Brepro"); 436 437 bool DLL = Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd, 438 options::OPT_shared); 439 if (DLL) { 440 CmdArgs.push_back(Args.MakeArgString("-dll")); 441 442 SmallString<128> ImplibName(Output.getFilename()); 443 llvm::sys::path::replace_extension(ImplibName, "lib"); 444 CmdArgs.push_back(Args.MakeArgString(std::string("-implib:") + ImplibName)); 445 } 446 447 if (TC.getSanitizerArgs().needsFuzzer()) { 448 if (!Args.hasArg(options::OPT_shared)) 449 CmdArgs.push_back( 450 Args.MakeArgString(std::string("-wholearchive:") + 451 TC.getCompilerRTArgString(Args, "fuzzer"))); 452 CmdArgs.push_back(Args.MakeArgString("-debug")); 453 // Prevent the linker from padding sections we use for instrumentation 454 // arrays. 455 CmdArgs.push_back(Args.MakeArgString("-incremental:no")); 456 } 457 458 if (TC.getSanitizerArgs().needsAsanRt()) { 459 CmdArgs.push_back(Args.MakeArgString("-debug")); 460 CmdArgs.push_back(Args.MakeArgString("-incremental:no")); 461 if (TC.getSanitizerArgs().needsSharedRt() || 462 Args.hasArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd)) { 463 for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"}) 464 CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib)); 465 // Make sure the dynamic runtime thunk is not optimized out at link time 466 // to ensure proper SEH handling. 467 CmdArgs.push_back(Args.MakeArgString( 468 TC.getArch() == llvm::Triple::x86 469 ? "-include:___asan_seh_interceptor" 470 : "-include:__asan_seh_interceptor")); 471 // Make sure the linker consider all object files from the dynamic runtime 472 // thunk. 473 CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") + 474 TC.getCompilerRT(Args, "asan_dynamic_runtime_thunk"))); 475 } else if (DLL) { 476 CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk")); 477 } else { 478 for (const auto &Lib : {"asan", "asan_cxx"}) { 479 CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib)); 480 // Make sure the linker consider all object files from the static lib. 481 // This is necessary because instrumented dlls need access to all the 482 // interface exported by the static lib in the main executable. 483 CmdArgs.push_back(Args.MakeArgString(std::string("-wholearchive:") + 484 TC.getCompilerRT(Args, Lib))); 485 } 486 } 487 } 488 489 Args.AddAllArgValues(CmdArgs, options::OPT__SLASH_link); 490 491 // Control Flow Guard checks 492 if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) { 493 StringRef GuardArgs = A->getValue(); 494 if (GuardArgs.equals_lower("cf") || GuardArgs.equals_lower("cf,nochecks")) { 495 // MSVC doesn't yet support the "nochecks" modifier. 496 CmdArgs.push_back("-guard:cf"); 497 } else if (GuardArgs.equals_lower("cf-")) { 498 CmdArgs.push_back("-guard:cf-"); 499 } 500 } 501 502 if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, 503 options::OPT_fno_openmp, false)) { 504 CmdArgs.push_back("-nodefaultlib:vcomp.lib"); 505 CmdArgs.push_back("-nodefaultlib:vcompd.lib"); 506 CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") + 507 TC.getDriver().Dir + "/../lib")); 508 switch (TC.getDriver().getOpenMPRuntime(Args)) { 509 case Driver::OMPRT_OMP: 510 CmdArgs.push_back("-defaultlib:libomp.lib"); 511 break; 512 case Driver::OMPRT_IOMP5: 513 CmdArgs.push_back("-defaultlib:libiomp5md.lib"); 514 break; 515 case Driver::OMPRT_GOMP: 516 break; 517 case Driver::OMPRT_Unknown: 518 // Already diagnosed. 519 break; 520 } 521 } 522 523 // Add compiler-rt lib in case if it was explicitly 524 // specified as an argument for --rtlib option. 525 if (!Args.hasArg(options::OPT_nostdlib)) { 526 AddRunTimeLibs(TC, TC.getDriver(), CmdArgs, Args); 527 } 528 529 // Add filenames, libraries, and other linker inputs. 530 for (const auto &Input : Inputs) { 531 if (Input.isFilename()) { 532 CmdArgs.push_back(Input.getFilename()); 533 continue; 534 } 535 536 const Arg &A = Input.getInputArg(); 537 538 // Render -l options differently for the MSVC linker. 539 if (A.getOption().matches(options::OPT_l)) { 540 StringRef Lib = A.getValue(); 541 const char *LinkLibArg; 542 if (Lib.endswith(".lib")) 543 LinkLibArg = Args.MakeArgString(Lib); 544 else 545 LinkLibArg = Args.MakeArgString(Lib + ".lib"); 546 CmdArgs.push_back(LinkLibArg); 547 continue; 548 } 549 550 // Otherwise, this is some other kind of linker input option like -Wl, -z, 551 // or -L. Render it, even if MSVC doesn't understand it. 552 A.renderAsInput(Args, CmdArgs); 553 } 554 555 TC.addProfileRTLibs(Args, CmdArgs); 556 557 std::vector<const char *> Environment; 558 559 // We need to special case some linker paths. In the case of lld, we need to 560 // translate 'lld' into 'lld-link', and in the case of the regular msvc 561 // linker, we need to use a special search algorithm. 562 llvm::SmallString<128> linkPath; 563 StringRef Linker = Args.getLastArgValue(options::OPT_fuse_ld_EQ, "link"); 564 if (Linker.equals_lower("lld")) 565 Linker = "lld-link"; 566 567 if (Linker.equals_lower("link")) { 568 // If we're using the MSVC linker, it's not sufficient to just use link 569 // from the program PATH, because other environments like GnuWin32 install 570 // their own link.exe which may come first. 571 linkPath = FindVisualStudioExecutable(TC, "link.exe"); 572 573 if (!TC.FoundMSVCInstall() && !llvm::sys::fs::can_execute(linkPath)) { 574 llvm::SmallString<128> ClPath; 575 ClPath = TC.GetProgramPath("cl.exe"); 576 if (llvm::sys::fs::can_execute(ClPath)) { 577 linkPath = llvm::sys::path::parent_path(ClPath); 578 llvm::sys::path::append(linkPath, "link.exe"); 579 if (!llvm::sys::fs::can_execute(linkPath)) 580 C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found); 581 } else { 582 C.getDriver().Diag(clang::diag::warn_drv_msvc_not_found); 583 } 584 } 585 586 #ifdef _WIN32 587 // When cross-compiling with VS2017 or newer, link.exe expects to have 588 // its containing bin directory at the top of PATH, followed by the 589 // native target bin directory. 590 // e.g. when compiling for x86 on an x64 host, PATH should start with: 591 // /bin/Hostx64/x86;/bin/Hostx64/x64 592 // This doesn't attempt to handle ToolsetLayout::DevDivInternal. 593 if (TC.getIsVS2017OrNewer() && 594 llvm::Triple(llvm::sys::getProcessTriple()).getArch() != TC.getArch()) { 595 auto HostArch = llvm::Triple(llvm::sys::getProcessTriple()).getArch(); 596 597 auto EnvBlockWide = 598 std::unique_ptr<wchar_t[], decltype(&FreeEnvironmentStringsW)>( 599 GetEnvironmentStringsW(), FreeEnvironmentStringsW); 600 if (!EnvBlockWide) 601 goto SkipSettingEnvironment; 602 603 size_t EnvCount = 0; 604 size_t EnvBlockLen = 0; 605 while (EnvBlockWide[EnvBlockLen] != L'\0') { 606 ++EnvCount; 607 EnvBlockLen += std::wcslen(&EnvBlockWide[EnvBlockLen]) + 608 1 /*string null-terminator*/; 609 } 610 ++EnvBlockLen; // add the block null-terminator 611 612 std::string EnvBlock; 613 if (!llvm::convertUTF16ToUTF8String( 614 llvm::ArrayRef<char>(reinterpret_cast<char *>(EnvBlockWide.get()), 615 EnvBlockLen * sizeof(EnvBlockWide[0])), 616 EnvBlock)) 617 goto SkipSettingEnvironment; 618 619 Environment.reserve(EnvCount); 620 621 // Now loop over each string in the block and copy them into the 622 // environment vector, adjusting the PATH variable as needed when we 623 // find it. 624 for (const char *Cursor = EnvBlock.data(); *Cursor != '\0';) { 625 llvm::StringRef EnvVar(Cursor); 626 if (EnvVar.startswith_lower("path=")) { 627 using SubDirectoryType = toolchains::MSVCToolChain::SubDirectoryType; 628 constexpr size_t PrefixLen = 5; // strlen("path=") 629 Environment.push_back(Args.MakeArgString( 630 EnvVar.substr(0, PrefixLen) + 631 TC.getSubDirectoryPath(SubDirectoryType::Bin) + 632 llvm::Twine(llvm::sys::EnvPathSeparator) + 633 TC.getSubDirectoryPath(SubDirectoryType::Bin, "", HostArch) + 634 (EnvVar.size() > PrefixLen 635 ? llvm::Twine(llvm::sys::EnvPathSeparator) + 636 EnvVar.substr(PrefixLen) 637 : ""))); 638 } else { 639 Environment.push_back(Args.MakeArgString(EnvVar)); 640 } 641 Cursor += EnvVar.size() + 1 /*null-terminator*/; 642 } 643 } 644 SkipSettingEnvironment:; 645 #endif 646 } else { 647 linkPath = TC.GetProgramPath(Linker.str().c_str()); 648 } 649 650 auto LinkCmd = std::make_unique<Command>( 651 JA, *this, ResponseFileSupport::AtFileUTF16(), 652 Args.MakeArgString(linkPath), CmdArgs, Inputs, Output); 653 if (!Environment.empty()) 654 LinkCmd->setEnvironment(Environment); 655 C.addCommand(std::move(LinkCmd)); 656 } 657 658 void visualstudio::Compiler::ConstructJob(Compilation &C, const JobAction &JA, 659 const InputInfo &Output, 660 const InputInfoList &Inputs, 661 const ArgList &Args, 662 const char *LinkingOutput) const { 663 C.addCommand(GetCommand(C, JA, Output, Inputs, Args, LinkingOutput)); 664 } 665 666 std::unique_ptr<Command> visualstudio::Compiler::GetCommand( 667 Compilation &C, const JobAction &JA, const InputInfo &Output, 668 const InputInfoList &Inputs, const ArgList &Args, 669 const char *LinkingOutput) const { 670 ArgStringList CmdArgs; 671 CmdArgs.push_back("/nologo"); 672 CmdArgs.push_back("/c"); // Compile only. 673 CmdArgs.push_back("/W0"); // No warnings. 674 675 // The goal is to be able to invoke this tool correctly based on 676 // any flag accepted by clang-cl. 677 678 // These are spelled the same way in clang and cl.exe,. 679 Args.AddAllArgs(CmdArgs, {options::OPT_D, options::OPT_U, options::OPT_I}); 680 681 // Optimization level. 682 if (Arg *A = Args.getLastArg(options::OPT_fbuiltin, options::OPT_fno_builtin)) 683 CmdArgs.push_back(A->getOption().getID() == options::OPT_fbuiltin ? "/Oi" 684 : "/Oi-"); 685 if (Arg *A = Args.getLastArg(options::OPT_O, options::OPT_O0)) { 686 if (A->getOption().getID() == options::OPT_O0) { 687 CmdArgs.push_back("/Od"); 688 } else { 689 CmdArgs.push_back("/Og"); 690 691 StringRef OptLevel = A->getValue(); 692 if (OptLevel == "s" || OptLevel == "z") 693 CmdArgs.push_back("/Os"); 694 else 695 CmdArgs.push_back("/Ot"); 696 697 CmdArgs.push_back("/Ob2"); 698 } 699 } 700 if (Arg *A = Args.getLastArg(options::OPT_fomit_frame_pointer, 701 options::OPT_fno_omit_frame_pointer)) 702 CmdArgs.push_back(A->getOption().getID() == options::OPT_fomit_frame_pointer 703 ? "/Oy" 704 : "/Oy-"); 705 if (!Args.hasArg(options::OPT_fwritable_strings)) 706 CmdArgs.push_back("/GF"); 707 708 // Flags for which clang-cl has an alias. 709 // FIXME: How can we ensure this stays in sync with relevant clang-cl options? 710 711 if (Args.hasFlag(options::OPT__SLASH_GR_, options::OPT__SLASH_GR, 712 /*Default=*/false)) 713 CmdArgs.push_back("/GR-"); 714 715 if (Args.hasFlag(options::OPT__SLASH_GS_, options::OPT__SLASH_GS, 716 /*Default=*/false)) 717 CmdArgs.push_back("/GS-"); 718 719 if (Arg *A = Args.getLastArg(options::OPT_ffunction_sections, 720 options::OPT_fno_function_sections)) 721 CmdArgs.push_back(A->getOption().getID() == options::OPT_ffunction_sections 722 ? "/Gy" 723 : "/Gy-"); 724 if (Arg *A = Args.getLastArg(options::OPT_fdata_sections, 725 options::OPT_fno_data_sections)) 726 CmdArgs.push_back( 727 A->getOption().getID() == options::OPT_fdata_sections ? "/Gw" : "/Gw-"); 728 if (Args.hasArg(options::OPT_fsyntax_only)) 729 CmdArgs.push_back("/Zs"); 730 if (Args.hasArg(options::OPT_g_Flag, options::OPT_gline_tables_only, 731 options::OPT__SLASH_Z7)) 732 CmdArgs.push_back("/Z7"); 733 734 std::vector<std::string> Includes = 735 Args.getAllArgValues(options::OPT_include); 736 for (const auto &Include : Includes) 737 CmdArgs.push_back(Args.MakeArgString(std::string("/FI") + Include)); 738 739 // Flags that can simply be passed through. 740 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LD); 741 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_LDd); 742 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX); 743 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_GX_); 744 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_EH); 745 Args.AddAllArgs(CmdArgs, options::OPT__SLASH_Zl); 746 747 // The order of these flags is relevant, so pick the last one. 748 if (Arg *A = Args.getLastArg(options::OPT__SLASH_MD, options::OPT__SLASH_MDd, 749 options::OPT__SLASH_MT, options::OPT__SLASH_MTd)) 750 A->render(Args, CmdArgs); 751 752 // Use MSVC's default threadsafe statics behaviour unless there was a flag. 753 if (Arg *A = Args.getLastArg(options::OPT_fthreadsafe_statics, 754 options::OPT_fno_threadsafe_statics)) { 755 CmdArgs.push_back(A->getOption().getID() == options::OPT_fthreadsafe_statics 756 ? "/Zc:threadSafeInit" 757 : "/Zc:threadSafeInit-"); 758 } 759 760 // Control Flow Guard checks 761 if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) { 762 StringRef GuardArgs = A->getValue(); 763 if (GuardArgs.equals_lower("cf") || GuardArgs.equals_lower("cf,nochecks")) { 764 // MSVC doesn't yet support the "nochecks" modifier. 765 CmdArgs.push_back("/guard:cf"); 766 } else if (GuardArgs.equals_lower("cf-")) { 767 CmdArgs.push_back("/guard:cf-"); 768 } 769 } 770 771 // Pass through all unknown arguments so that the fallback command can see 772 // them too. 773 Args.AddAllArgs(CmdArgs, options::OPT_UNKNOWN); 774 775 // Input filename. 776 assert(Inputs.size() == 1); 777 const InputInfo &II = Inputs[0]; 778 assert(II.getType() == types::TY_C || II.getType() == types::TY_CXX); 779 CmdArgs.push_back(II.getType() == types::TY_C ? "/Tc" : "/Tp"); 780 if (II.isFilename()) 781 CmdArgs.push_back(II.getFilename()); 782 else 783 II.getInputArg().renderAsInput(Args, CmdArgs); 784 785 // Output filename. 786 assert(Output.getType() == types::TY_Object); 787 const char *Fo = 788 Args.MakeArgString(std::string("/Fo") + Output.getFilename()); 789 CmdArgs.push_back(Fo); 790 791 std::string Exec = FindVisualStudioExecutable(getToolChain(), "cl.exe"); 792 return std::make_unique<Command>( 793 JA, *this, ResponseFileSupport::AtFileUTF16(), Args.MakeArgString(Exec), 794 CmdArgs, Inputs, Output); 795 } 796 797 MSVCToolChain::MSVCToolChain(const Driver &D, const llvm::Triple &Triple, 798 const ArgList &Args) 799 : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args), 800 RocmInstallation(D, Triple, Args) { 801 getProgramPaths().push_back(getDriver().getInstalledDir()); 802 if (getDriver().getInstalledDir() != getDriver().Dir) 803 getProgramPaths().push_back(getDriver().Dir); 804 805 // Check the command line first, that's the user explicitly telling us what to 806 // use. Check the environment next, in case we're being invoked from a VS 807 // command prompt. Failing that, just try to find the newest Visual Studio 808 // version we can and use its default VC toolchain. 809 findVCToolChainViaCommandLine(Args, VCToolChainPath, VSLayout) || 810 findVCToolChainViaEnvironment(VCToolChainPath, VSLayout) || 811 findVCToolChainViaSetupConfig(VCToolChainPath, VSLayout) || 812 findVCToolChainViaRegistry(VCToolChainPath, VSLayout); 813 } 814 815 Tool *MSVCToolChain::buildLinker() const { 816 return new tools::visualstudio::Linker(*this); 817 } 818 819 Tool *MSVCToolChain::buildAssembler() const { 820 if (getTriple().isOSBinFormatMachO()) 821 return new tools::darwin::Assembler(*this); 822 getDriver().Diag(clang::diag::err_no_external_assembler); 823 return nullptr; 824 } 825 826 bool MSVCToolChain::IsIntegratedAssemblerDefault() const { 827 return true; 828 } 829 830 bool MSVCToolChain::IsUnwindTablesDefault(const ArgList &Args) const { 831 // Don't emit unwind tables by default for MachO targets. 832 if (getTriple().isOSBinFormatMachO()) 833 return false; 834 835 // All non-x86_32 Windows targets require unwind tables. However, LLVM 836 // doesn't know how to generate them for all targets, so only enable 837 // the ones that are actually implemented. 838 return getArch() == llvm::Triple::x86_64 || 839 getArch() == llvm::Triple::aarch64; 840 } 841 842 bool MSVCToolChain::isPICDefault() const { 843 return getArch() == llvm::Triple::x86_64; 844 } 845 846 bool MSVCToolChain::isPIEDefault() const { 847 return false; 848 } 849 850 bool MSVCToolChain::isPICDefaultForced() const { 851 return getArch() == llvm::Triple::x86_64; 852 } 853 854 void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs, 855 ArgStringList &CC1Args) const { 856 CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); 857 } 858 859 void MSVCToolChain::AddHIPIncludeArgs(const ArgList &DriverArgs, 860 ArgStringList &CC1Args) const { 861 RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args); 862 } 863 864 void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const { 865 CudaInstallation.print(OS); 866 RocmInstallation.print(OS); 867 } 868 869 // Windows SDKs and VC Toolchains group their contents into subdirectories based 870 // on the target architecture. This function converts an llvm::Triple::ArchType 871 // to the corresponding subdirectory name. 872 static const char *llvmArchToWindowsSDKArch(llvm::Triple::ArchType Arch) { 873 using ArchType = llvm::Triple::ArchType; 874 switch (Arch) { 875 case ArchType::x86: 876 return "x86"; 877 case ArchType::x86_64: 878 return "x64"; 879 case ArchType::arm: 880 return "arm"; 881 case ArchType::aarch64: 882 return "arm64"; 883 default: 884 return ""; 885 } 886 } 887 888 // Similar to the above function, but for Visual Studios before VS2017. 889 static const char *llvmArchToLegacyVCArch(llvm::Triple::ArchType Arch) { 890 using ArchType = llvm::Triple::ArchType; 891 switch (Arch) { 892 case ArchType::x86: 893 // x86 is default in legacy VC toolchains. 894 // e.g. x86 libs are directly in /lib as opposed to /lib/x86. 895 return ""; 896 case ArchType::x86_64: 897 return "amd64"; 898 case ArchType::arm: 899 return "arm"; 900 case ArchType::aarch64: 901 return "arm64"; 902 default: 903 return ""; 904 } 905 } 906 907 // Similar to the above function, but for DevDiv internal builds. 908 static const char *llvmArchToDevDivInternalArch(llvm::Triple::ArchType Arch) { 909 using ArchType = llvm::Triple::ArchType; 910 switch (Arch) { 911 case ArchType::x86: 912 return "i386"; 913 case ArchType::x86_64: 914 return "amd64"; 915 case ArchType::arm: 916 return "arm"; 917 case ArchType::aarch64: 918 return "arm64"; 919 default: 920 return ""; 921 } 922 } 923 924 // Get the path to a specific subdirectory in the current toolchain for 925 // a given target architecture. 926 // VS2017 changed the VC toolchain layout, so this should be used instead 927 // of hardcoding paths. 928 std::string 929 MSVCToolChain::getSubDirectoryPath(SubDirectoryType Type, 930 llvm::StringRef SubdirParent, 931 llvm::Triple::ArchType TargetArch) const { 932 const char *SubdirName; 933 const char *IncludeName; 934 switch (VSLayout) { 935 case ToolsetLayout::OlderVS: 936 SubdirName = llvmArchToLegacyVCArch(TargetArch); 937 IncludeName = "include"; 938 break; 939 case ToolsetLayout::VS2017OrNewer: 940 SubdirName = llvmArchToWindowsSDKArch(TargetArch); 941 IncludeName = "include"; 942 break; 943 case ToolsetLayout::DevDivInternal: 944 SubdirName = llvmArchToDevDivInternalArch(TargetArch); 945 IncludeName = "inc"; 946 break; 947 } 948 949 llvm::SmallString<256> Path(VCToolChainPath); 950 if (!SubdirParent.empty()) 951 llvm::sys::path::append(Path, SubdirParent); 952 953 switch (Type) { 954 case SubDirectoryType::Bin: 955 if (VSLayout == ToolsetLayout::VS2017OrNewer) { 956 const bool HostIsX64 = 957 llvm::Triple(llvm::sys::getProcessTriple()).isArch64Bit(); 958 const char *const HostName = HostIsX64 ? "Hostx64" : "Hostx86"; 959 llvm::sys::path::append(Path, "bin", HostName, SubdirName); 960 } else { // OlderVS or DevDivInternal 961 llvm::sys::path::append(Path, "bin", SubdirName); 962 } 963 break; 964 case SubDirectoryType::Include: 965 llvm::sys::path::append(Path, IncludeName); 966 break; 967 case SubDirectoryType::Lib: 968 llvm::sys::path::append(Path, "lib", SubdirName); 969 break; 970 } 971 return std::string(Path.str()); 972 } 973 974 #ifdef _WIN32 975 static bool readFullStringValue(HKEY hkey, const char *valueName, 976 std::string &value) { 977 std::wstring WideValueName; 978 if (!llvm::ConvertUTF8toWide(valueName, WideValueName)) 979 return false; 980 981 DWORD result = 0; 982 DWORD valueSize = 0; 983 DWORD type = 0; 984 // First just query for the required size. 985 result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, &type, NULL, 986 &valueSize); 987 if (result != ERROR_SUCCESS || type != REG_SZ || !valueSize) 988 return false; 989 std::vector<BYTE> buffer(valueSize); 990 result = RegQueryValueExW(hkey, WideValueName.c_str(), NULL, NULL, &buffer[0], 991 &valueSize); 992 if (result == ERROR_SUCCESS) { 993 std::wstring WideValue(reinterpret_cast<const wchar_t *>(buffer.data()), 994 valueSize / sizeof(wchar_t)); 995 if (valueSize && WideValue.back() == L'\0') { 996 WideValue.pop_back(); 997 } 998 // The destination buffer must be empty as an invariant of the conversion 999 // function; but this function is sometimes called in a loop that passes in 1000 // the same buffer, however. Simply clear it out so we can overwrite it. 1001 value.clear(); 1002 return llvm::convertWideToUTF8(WideValue, value); 1003 } 1004 return false; 1005 } 1006 #endif 1007 1008 /// Read registry string. 1009 /// This also supports a means to look for high-versioned keys by use 1010 /// of a $VERSION placeholder in the key path. 1011 /// $VERSION in the key path is a placeholder for the version number, 1012 /// causing the highest value path to be searched for and used. 1013 /// I.e. "SOFTWARE\\Microsoft\\VisualStudio\\$VERSION". 1014 /// There can be additional characters in the component. Only the numeric 1015 /// characters are compared. This function only searches HKLM. 1016 static bool getSystemRegistryString(const char *keyPath, const char *valueName, 1017 std::string &value, std::string *phValue) { 1018 #ifndef _WIN32 1019 return false; 1020 #else 1021 HKEY hRootKey = HKEY_LOCAL_MACHINE; 1022 HKEY hKey = NULL; 1023 long lResult; 1024 bool returnValue = false; 1025 1026 const char *placeHolder = strstr(keyPath, "$VERSION"); 1027 std::string bestName; 1028 // If we have a $VERSION placeholder, do the highest-version search. 1029 if (placeHolder) { 1030 const char *keyEnd = placeHolder - 1; 1031 const char *nextKey = placeHolder; 1032 // Find end of previous key. 1033 while ((keyEnd > keyPath) && (*keyEnd != '\\')) 1034 keyEnd--; 1035 // Find end of key containing $VERSION. 1036 while (*nextKey && (*nextKey != '\\')) 1037 nextKey++; 1038 size_t partialKeyLength = keyEnd - keyPath; 1039 char partialKey[256]; 1040 if (partialKeyLength >= sizeof(partialKey)) 1041 partialKeyLength = sizeof(partialKey) - 1; 1042 strncpy(partialKey, keyPath, partialKeyLength); 1043 partialKey[partialKeyLength] = '\0'; 1044 HKEY hTopKey = NULL; 1045 lResult = RegOpenKeyExA(hRootKey, partialKey, 0, KEY_READ | KEY_WOW64_32KEY, 1046 &hTopKey); 1047 if (lResult == ERROR_SUCCESS) { 1048 char keyName[256]; 1049 double bestValue = 0.0; 1050 DWORD index, size = sizeof(keyName) - 1; 1051 for (index = 0; RegEnumKeyExA(hTopKey, index, keyName, &size, NULL, NULL, 1052 NULL, NULL) == ERROR_SUCCESS; 1053 index++) { 1054 const char *sp = keyName; 1055 while (*sp && !isDigit(*sp)) 1056 sp++; 1057 if (!*sp) 1058 continue; 1059 const char *ep = sp + 1; 1060 while (*ep && (isDigit(*ep) || (*ep == '.'))) 1061 ep++; 1062 char numBuf[32]; 1063 strncpy(numBuf, sp, sizeof(numBuf) - 1); 1064 numBuf[sizeof(numBuf) - 1] = '\0'; 1065 double dvalue = strtod(numBuf, NULL); 1066 if (dvalue > bestValue) { 1067 // Test that InstallDir is indeed there before keeping this index. 1068 // Open the chosen key path remainder. 1069 bestName = keyName; 1070 // Append rest of key. 1071 bestName.append(nextKey); 1072 lResult = RegOpenKeyExA(hTopKey, bestName.c_str(), 0, 1073 KEY_READ | KEY_WOW64_32KEY, &hKey); 1074 if (lResult == ERROR_SUCCESS) { 1075 if (readFullStringValue(hKey, valueName, value)) { 1076 bestValue = dvalue; 1077 if (phValue) 1078 *phValue = bestName; 1079 returnValue = true; 1080 } 1081 RegCloseKey(hKey); 1082 } 1083 } 1084 size = sizeof(keyName) - 1; 1085 } 1086 RegCloseKey(hTopKey); 1087 } 1088 } else { 1089 lResult = 1090 RegOpenKeyExA(hRootKey, keyPath, 0, KEY_READ | KEY_WOW64_32KEY, &hKey); 1091 if (lResult == ERROR_SUCCESS) { 1092 if (readFullStringValue(hKey, valueName, value)) 1093 returnValue = true; 1094 if (phValue) 1095 phValue->clear(); 1096 RegCloseKey(hKey); 1097 } 1098 } 1099 return returnValue; 1100 #endif // _WIN32 1101 } 1102 1103 // Find the most recent version of Universal CRT or Windows 10 SDK. 1104 // vcvarsqueryregistry.bat from Visual Studio 2015 sorts entries in the include 1105 // directory by name and uses the last one of the list. 1106 // So we compare entry names lexicographically to find the greatest one. 1107 static bool getWindows10SDKVersionFromPath(const std::string &SDKPath, 1108 std::string &SDKVersion) { 1109 llvm::SmallString<128> IncludePath(SDKPath); 1110 llvm::sys::path::append(IncludePath, "Include"); 1111 SDKVersion = getHighestNumericTupleInDirectory(IncludePath); 1112 return !SDKVersion.empty(); 1113 } 1114 1115 static bool getWindowsSDKDirViaCommandLine(const ArgList &Args, 1116 std::string &Path, int &Major, 1117 std::string &Version) { 1118 if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkdir, 1119 options::OPT__SLASH_winsysroot)) { 1120 // Don't validate the input; trust the value supplied by the user. 1121 // The motivation is to prevent unnecessary file and registry access. 1122 llvm::VersionTuple SDKVersion; 1123 if (Arg *A = Args.getLastArg(options::OPT__SLASH_winsdkversion)) 1124 SDKVersion.tryParse(A->getValue()); 1125 1126 if (A->getOption().getID() == options::OPT__SLASH_winsysroot) { 1127 llvm::SmallString<128> SDKPath(A->getValue()); 1128 llvm::sys::path::append(SDKPath, "Windows Kits"); 1129 if (!SDKVersion.empty()) 1130 llvm::sys::path::append(SDKPath, Twine(SDKVersion.getMajor())); 1131 else 1132 llvm::sys::path::append(SDKPath, getHighestNumericTupleInDirectory(SDKPath)); 1133 Path = std::string(SDKPath.str()); 1134 } else { 1135 Path = A->getValue(); 1136 } 1137 1138 if (!SDKVersion.empty()) { 1139 Major = SDKVersion.getMajor(); 1140 Version = SDKVersion.getAsString(); 1141 } else if (getWindows10SDKVersionFromPath(Path, Version)) { 1142 Major = 10; 1143 } 1144 return true; 1145 } 1146 return false; 1147 } 1148 1149 /// Get Windows SDK installation directory. 1150 static bool getWindowsSDKDir(const ArgList &Args, std::string &Path, int &Major, 1151 std::string &WindowsSDKIncludeVersion, 1152 std::string &WindowsSDKLibVersion) { 1153 // Trust /winsdkdir and /winsdkversion if present. 1154 if (getWindowsSDKDirViaCommandLine( 1155 Args, Path, Major, WindowsSDKIncludeVersion)) { 1156 WindowsSDKLibVersion = WindowsSDKIncludeVersion; 1157 return true; 1158 } 1159 1160 // FIXME: Try env vars (%WindowsSdkDir%, %UCRTVersion%) before going to registry. 1161 1162 // Try the Windows registry. 1163 std::string RegistrySDKVersion; 1164 if (!getSystemRegistryString( 1165 "SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", 1166 "InstallationFolder", Path, &RegistrySDKVersion)) 1167 return false; 1168 if (Path.empty() || RegistrySDKVersion.empty()) 1169 return false; 1170 1171 WindowsSDKIncludeVersion.clear(); 1172 WindowsSDKLibVersion.clear(); 1173 Major = 0; 1174 std::sscanf(RegistrySDKVersion.c_str(), "v%d.", &Major); 1175 if (Major <= 7) 1176 return true; 1177 if (Major == 8) { 1178 // Windows SDK 8.x installs libraries in a folder whose names depend on the 1179 // version of the OS you're targeting. By default choose the newest, which 1180 // usually corresponds to the version of the OS you've installed the SDK on. 1181 const char *Tests[] = {"winv6.3", "win8", "win7"}; 1182 for (const char *Test : Tests) { 1183 llvm::SmallString<128> TestPath(Path); 1184 llvm::sys::path::append(TestPath, "Lib", Test); 1185 if (llvm::sys::fs::exists(TestPath.c_str())) { 1186 WindowsSDKLibVersion = Test; 1187 break; 1188 } 1189 } 1190 return !WindowsSDKLibVersion.empty(); 1191 } 1192 if (Major == 10) { 1193 if (!getWindows10SDKVersionFromPath(Path, WindowsSDKIncludeVersion)) 1194 return false; 1195 WindowsSDKLibVersion = WindowsSDKIncludeVersion; 1196 return true; 1197 } 1198 // Unsupported SDK version 1199 return false; 1200 } 1201 1202 // Gets the library path required to link against the Windows SDK. 1203 bool MSVCToolChain::getWindowsSDKLibraryPath( 1204 const ArgList &Args, std::string &path) const { 1205 std::string sdkPath; 1206 int sdkMajor = 0; 1207 std::string windowsSDKIncludeVersion; 1208 std::string windowsSDKLibVersion; 1209 1210 path.clear(); 1211 if (!getWindowsSDKDir(Args, sdkPath, sdkMajor, windowsSDKIncludeVersion, 1212 windowsSDKLibVersion)) 1213 return false; 1214 1215 llvm::SmallString<128> libPath(sdkPath); 1216 llvm::sys::path::append(libPath, "Lib"); 1217 if (sdkMajor >= 8) { 1218 llvm::sys::path::append(libPath, windowsSDKLibVersion, "um", 1219 llvmArchToWindowsSDKArch(getArch())); 1220 } else { 1221 switch (getArch()) { 1222 // In Windows SDK 7.x, x86 libraries are directly in the Lib folder. 1223 case llvm::Triple::x86: 1224 break; 1225 case llvm::Triple::x86_64: 1226 llvm::sys::path::append(libPath, "x64"); 1227 break; 1228 case llvm::Triple::arm: 1229 // It is not necessary to link against Windows SDK 7.x when targeting ARM. 1230 return false; 1231 default: 1232 return false; 1233 } 1234 } 1235 1236 path = std::string(libPath.str()); 1237 return true; 1238 } 1239 1240 // Check if the Include path of a specified version of Visual Studio contains 1241 // specific header files. If not, they are probably shipped with Universal CRT. 1242 bool MSVCToolChain::useUniversalCRT() const { 1243 llvm::SmallString<128> TestPath( 1244 getSubDirectoryPath(SubDirectoryType::Include)); 1245 llvm::sys::path::append(TestPath, "stdlib.h"); 1246 return !llvm::sys::fs::exists(TestPath); 1247 } 1248 1249 static bool getUniversalCRTSdkDir(const ArgList &Args, std::string &Path, 1250 std::string &UCRTVersion) { 1251 // If /winsdkdir is passed, use it as location for the UCRT too. 1252 // FIXME: Should there be a dedicated /ucrtdir to override /winsdkdir? 1253 int Major; 1254 if (getWindowsSDKDirViaCommandLine(Args, Path, Major, UCRTVersion)) 1255 return true; 1256 1257 // FIXME: Try env vars (%UniversalCRTSdkDir%, %UCRTVersion%) before going to 1258 // registry. 1259 1260 // vcvarsqueryregistry.bat for Visual Studio 2015 queries the registry 1261 // for the specific key "KitsRoot10". So do we. 1262 if (!getSystemRegistryString( 1263 "SOFTWARE\\Microsoft\\Windows Kits\\Installed Roots", "KitsRoot10", 1264 Path, nullptr)) 1265 return false; 1266 1267 return getWindows10SDKVersionFromPath(Path, UCRTVersion); 1268 } 1269 1270 bool MSVCToolChain::getUniversalCRTLibraryPath(const ArgList &Args, 1271 std::string &Path) const { 1272 std::string UniversalCRTSdkPath; 1273 std::string UCRTVersion; 1274 1275 Path.clear(); 1276 if (!getUniversalCRTSdkDir(Args, UniversalCRTSdkPath, UCRTVersion)) 1277 return false; 1278 1279 StringRef ArchName = llvmArchToWindowsSDKArch(getArch()); 1280 if (ArchName.empty()) 1281 return false; 1282 1283 llvm::SmallString<128> LibPath(UniversalCRTSdkPath); 1284 llvm::sys::path::append(LibPath, "Lib", UCRTVersion, "ucrt", ArchName); 1285 1286 Path = std::string(LibPath.str()); 1287 return true; 1288 } 1289 1290 static VersionTuple getMSVCVersionFromTriple(const llvm::Triple &Triple) { 1291 unsigned Major, Minor, Micro; 1292 Triple.getEnvironmentVersion(Major, Minor, Micro); 1293 if (Major || Minor || Micro) 1294 return VersionTuple(Major, Minor, Micro); 1295 return VersionTuple(); 1296 } 1297 1298 static VersionTuple getMSVCVersionFromExe(const std::string &BinDir) { 1299 VersionTuple Version; 1300 #ifdef _WIN32 1301 SmallString<128> ClExe(BinDir); 1302 llvm::sys::path::append(ClExe, "cl.exe"); 1303 1304 std::wstring ClExeWide; 1305 if (!llvm::ConvertUTF8toWide(ClExe.c_str(), ClExeWide)) 1306 return Version; 1307 1308 const DWORD VersionSize = ::GetFileVersionInfoSizeW(ClExeWide.c_str(), 1309 nullptr); 1310 if (VersionSize == 0) 1311 return Version; 1312 1313 SmallVector<uint8_t, 4 * 1024> VersionBlock(VersionSize); 1314 if (!::GetFileVersionInfoW(ClExeWide.c_str(), 0, VersionSize, 1315 VersionBlock.data())) 1316 return Version; 1317 1318 VS_FIXEDFILEINFO *FileInfo = nullptr; 1319 UINT FileInfoSize = 0; 1320 if (!::VerQueryValueW(VersionBlock.data(), L"\\", 1321 reinterpret_cast<LPVOID *>(&FileInfo), &FileInfoSize) || 1322 FileInfoSize < sizeof(*FileInfo)) 1323 return Version; 1324 1325 const unsigned Major = (FileInfo->dwFileVersionMS >> 16) & 0xFFFF; 1326 const unsigned Minor = (FileInfo->dwFileVersionMS ) & 0xFFFF; 1327 const unsigned Micro = (FileInfo->dwFileVersionLS >> 16) & 0xFFFF; 1328 1329 Version = VersionTuple(Major, Minor, Micro); 1330 #endif 1331 return Version; 1332 } 1333 1334 void MSVCToolChain::AddSystemIncludeWithSubfolder( 1335 const ArgList &DriverArgs, ArgStringList &CC1Args, 1336 const std::string &folder, const Twine &subfolder1, const Twine &subfolder2, 1337 const Twine &subfolder3) const { 1338 llvm::SmallString<128> path(folder); 1339 llvm::sys::path::append(path, subfolder1, subfolder2, subfolder3); 1340 addSystemInclude(DriverArgs, CC1Args, path); 1341 } 1342 1343 void MSVCToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 1344 ArgStringList &CC1Args) const { 1345 if (DriverArgs.hasArg(options::OPT_nostdinc)) 1346 return; 1347 1348 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 1349 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, getDriver().ResourceDir, 1350 "include"); 1351 } 1352 1353 // Add %INCLUDE%-like directories from the -imsvc flag. 1354 for (const auto &Path : DriverArgs.getAllArgValues(options::OPT__SLASH_imsvc)) 1355 addSystemInclude(DriverArgs, CC1Args, Path); 1356 1357 if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 1358 return; 1359 1360 // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat. 1361 // Skip if the user expressly set a vctoolsdir 1362 if (!DriverArgs.getLastArg(options::OPT__SLASH_vctoolsdir, 1363 options::OPT__SLASH_winsysroot)) { 1364 if (llvm::Optional<std::string> cl_include_dir = 1365 llvm::sys::Process::GetEnv("INCLUDE")) { 1366 SmallVector<StringRef, 8> Dirs; 1367 StringRef(*cl_include_dir) 1368 .split(Dirs, ";", /*MaxSplit=*/-1, /*KeepEmpty=*/false); 1369 for (StringRef Dir : Dirs) 1370 addSystemInclude(DriverArgs, CC1Args, Dir); 1371 if (!Dirs.empty()) 1372 return; 1373 } 1374 } 1375 1376 // When built with access to the proper Windows APIs, try to actually find 1377 // the correct include paths first. 1378 if (!VCToolChainPath.empty()) { 1379 addSystemInclude(DriverArgs, CC1Args, 1380 getSubDirectoryPath(SubDirectoryType::Include)); 1381 addSystemInclude(DriverArgs, CC1Args, 1382 getSubDirectoryPath(SubDirectoryType::Include, "atlmfc")); 1383 1384 if (useUniversalCRT()) { 1385 std::string UniversalCRTSdkPath; 1386 std::string UCRTVersion; 1387 if (getUniversalCRTSdkDir(DriverArgs, UniversalCRTSdkPath, UCRTVersion)) { 1388 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, UniversalCRTSdkPath, 1389 "Include", UCRTVersion, "ucrt"); 1390 } 1391 } 1392 1393 std::string WindowsSDKDir; 1394 int major; 1395 std::string windowsSDKIncludeVersion; 1396 std::string windowsSDKLibVersion; 1397 if (getWindowsSDKDir(DriverArgs, WindowsSDKDir, major, 1398 windowsSDKIncludeVersion, windowsSDKLibVersion)) { 1399 if (major >= 8) { 1400 // Note: windowsSDKIncludeVersion is empty for SDKs prior to v10. 1401 // Anyway, llvm::sys::path::append is able to manage it. 1402 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 1403 "Include", windowsSDKIncludeVersion, 1404 "shared"); 1405 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 1406 "Include", windowsSDKIncludeVersion, 1407 "um"); 1408 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 1409 "Include", windowsSDKIncludeVersion, 1410 "winrt"); 1411 } else { 1412 AddSystemIncludeWithSubfolder(DriverArgs, CC1Args, WindowsSDKDir, 1413 "Include"); 1414 } 1415 } 1416 1417 return; 1418 } 1419 1420 #if defined(_WIN32) 1421 // As a fallback, select default install paths. 1422 // FIXME: Don't guess drives and paths like this on Windows. 1423 const StringRef Paths[] = { 1424 "C:/Program Files/Microsoft Visual Studio 10.0/VC/include", 1425 "C:/Program Files/Microsoft Visual Studio 9.0/VC/include", 1426 "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include", 1427 "C:/Program Files/Microsoft Visual Studio 8/VC/include", 1428 "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include" 1429 }; 1430 addSystemIncludes(DriverArgs, CC1Args, Paths); 1431 #endif 1432 } 1433 1434 void MSVCToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, 1435 ArgStringList &CC1Args) const { 1436 // FIXME: There should probably be logic here to find libc++ on Windows. 1437 } 1438 1439 VersionTuple MSVCToolChain::computeMSVCVersion(const Driver *D, 1440 const ArgList &Args) const { 1441 bool IsWindowsMSVC = getTriple().isWindowsMSVCEnvironment(); 1442 VersionTuple MSVT = ToolChain::computeMSVCVersion(D, Args); 1443 if (MSVT.empty()) 1444 MSVT = getMSVCVersionFromTriple(getTriple()); 1445 if (MSVT.empty() && IsWindowsMSVC) 1446 MSVT = getMSVCVersionFromExe(getSubDirectoryPath(SubDirectoryType::Bin)); 1447 if (MSVT.empty() && 1448 Args.hasFlag(options::OPT_fms_extensions, options::OPT_fno_ms_extensions, 1449 IsWindowsMSVC)) { 1450 // -fms-compatibility-version=19.11 is default, aka 2017, 15.3 1451 MSVT = VersionTuple(19, 11); 1452 } 1453 return MSVT; 1454 } 1455 1456 std::string 1457 MSVCToolChain::ComputeEffectiveClangTriple(const ArgList &Args, 1458 types::ID InputType) const { 1459 // The MSVC version doesn't care about the architecture, even though it 1460 // may look at the triple internally. 1461 VersionTuple MSVT = computeMSVCVersion(/*D=*/nullptr, Args); 1462 MSVT = VersionTuple(MSVT.getMajor(), MSVT.getMinor().getValueOr(0), 1463 MSVT.getSubminor().getValueOr(0)); 1464 1465 // For the rest of the triple, however, a computed architecture name may 1466 // be needed. 1467 llvm::Triple Triple(ToolChain::ComputeEffectiveClangTriple(Args, InputType)); 1468 if (Triple.getEnvironment() == llvm::Triple::MSVC) { 1469 StringRef ObjFmt = Triple.getEnvironmentName().split('-').second; 1470 if (ObjFmt.empty()) 1471 Triple.setEnvironmentName((Twine("msvc") + MSVT.getAsString()).str()); 1472 else 1473 Triple.setEnvironmentName( 1474 (Twine("msvc") + MSVT.getAsString() + Twine('-') + ObjFmt).str()); 1475 } 1476 return Triple.getTriple(); 1477 } 1478 1479 SanitizerMask MSVCToolChain::getSupportedSanitizers() const { 1480 SanitizerMask Res = ToolChain::getSupportedSanitizers(); 1481 Res |= SanitizerKind::Address; 1482 Res |= SanitizerKind::PointerCompare; 1483 Res |= SanitizerKind::PointerSubtract; 1484 Res |= SanitizerKind::Fuzzer; 1485 Res |= SanitizerKind::FuzzerNoLink; 1486 Res &= ~SanitizerKind::CFIMFCall; 1487 return Res; 1488 } 1489 1490 static void TranslateOptArg(Arg *A, llvm::opt::DerivedArgList &DAL, 1491 bool SupportsForcingFramePointer, 1492 const char *ExpandChar, const OptTable &Opts) { 1493 assert(A->getOption().matches(options::OPT__SLASH_O)); 1494 1495 StringRef OptStr = A->getValue(); 1496 for (size_t I = 0, E = OptStr.size(); I != E; ++I) { 1497 const char &OptChar = *(OptStr.data() + I); 1498 switch (OptChar) { 1499 default: 1500 break; 1501 case '1': 1502 case '2': 1503 case 'x': 1504 case 'd': 1505 // Ignore /O[12xd] flags that aren't the last one on the command line. 1506 // Only the last one gets expanded. 1507 if (&OptChar != ExpandChar) { 1508 A->claim(); 1509 break; 1510 } 1511 if (OptChar == 'd') { 1512 DAL.AddFlagArg(A, Opts.getOption(options::OPT_O0)); 1513 } else { 1514 if (OptChar == '1') { 1515 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); 1516 } else if (OptChar == '2' || OptChar == 'x') { 1517 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); 1518 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2"); 1519 } 1520 if (SupportsForcingFramePointer && 1521 !DAL.hasArgNoClaim(options::OPT_fno_omit_frame_pointer)) 1522 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fomit_frame_pointer)); 1523 if (OptChar == '1' || OptChar == '2') 1524 DAL.AddFlagArg(A, Opts.getOption(options::OPT_ffunction_sections)); 1525 } 1526 break; 1527 case 'b': 1528 if (I + 1 != E && isdigit(OptStr[I + 1])) { 1529 switch (OptStr[I + 1]) { 1530 case '0': 1531 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_inline)); 1532 break; 1533 case '1': 1534 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_hint_functions)); 1535 break; 1536 case '2': 1537 DAL.AddFlagArg(A, Opts.getOption(options::OPT_finline_functions)); 1538 break; 1539 } 1540 ++I; 1541 } 1542 break; 1543 case 'g': 1544 A->claim(); 1545 break; 1546 case 'i': 1547 if (I + 1 != E && OptStr[I + 1] == '-') { 1548 ++I; 1549 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fno_builtin)); 1550 } else { 1551 DAL.AddFlagArg(A, Opts.getOption(options::OPT_fbuiltin)); 1552 } 1553 break; 1554 case 's': 1555 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "s"); 1556 break; 1557 case 't': 1558 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_O), "2"); 1559 break; 1560 case 'y': { 1561 bool OmitFramePointer = true; 1562 if (I + 1 != E && OptStr[I + 1] == '-') { 1563 OmitFramePointer = false; 1564 ++I; 1565 } 1566 if (SupportsForcingFramePointer) { 1567 if (OmitFramePointer) 1568 DAL.AddFlagArg(A, 1569 Opts.getOption(options::OPT_fomit_frame_pointer)); 1570 else 1571 DAL.AddFlagArg( 1572 A, Opts.getOption(options::OPT_fno_omit_frame_pointer)); 1573 } else { 1574 // Don't warn about /Oy- in x86-64 builds (where 1575 // SupportsForcingFramePointer is false). The flag having no effect 1576 // there is a compiler-internal optimization, and people shouldn't have 1577 // to special-case their build files for x86-64 clang-cl. 1578 A->claim(); 1579 } 1580 break; 1581 } 1582 } 1583 } 1584 } 1585 1586 static void TranslateDArg(Arg *A, llvm::opt::DerivedArgList &DAL, 1587 const OptTable &Opts) { 1588 assert(A->getOption().matches(options::OPT_D)); 1589 1590 StringRef Val = A->getValue(); 1591 size_t Hash = Val.find('#'); 1592 if (Hash == StringRef::npos || Hash > Val.find('=')) { 1593 DAL.append(A); 1594 return; 1595 } 1596 1597 std::string NewVal = std::string(Val); 1598 NewVal[Hash] = '='; 1599 DAL.AddJoinedArg(A, Opts.getOption(options::OPT_D), NewVal); 1600 } 1601 1602 llvm::opt::DerivedArgList * 1603 MSVCToolChain::TranslateArgs(const llvm::opt::DerivedArgList &Args, 1604 StringRef BoundArch, 1605 Action::OffloadKind OFK) const { 1606 DerivedArgList *DAL = new DerivedArgList(Args.getBaseArgs()); 1607 const OptTable &Opts = getDriver().getOpts(); 1608 1609 // /Oy and /Oy- don't have an effect on X86-64 1610 bool SupportsForcingFramePointer = getArch() != llvm::Triple::x86_64; 1611 1612 // The -O[12xd] flag actually expands to several flags. We must desugar the 1613 // flags so that options embedded can be negated. For example, the '-O2' flag 1614 // enables '-Oy'. Expanding '-O2' into its constituent flags allows us to 1615 // correctly handle '-O2 -Oy-' where the trailing '-Oy-' disables a single 1616 // aspect of '-O2'. 1617 // 1618 // Note that this expansion logic only applies to the *last* of '[12xd]'. 1619 1620 // First step is to search for the character we'd like to expand. 1621 const char *ExpandChar = nullptr; 1622 for (Arg *A : Args.filtered(options::OPT__SLASH_O)) { 1623 StringRef OptStr = A->getValue(); 1624 for (size_t I = 0, E = OptStr.size(); I != E; ++I) { 1625 char OptChar = OptStr[I]; 1626 char PrevChar = I > 0 ? OptStr[I - 1] : '0'; 1627 if (PrevChar == 'b') { 1628 // OptChar does not expand; it's an argument to the previous char. 1629 continue; 1630 } 1631 if (OptChar == '1' || OptChar == '2' || OptChar == 'x' || OptChar == 'd') 1632 ExpandChar = OptStr.data() + I; 1633 } 1634 } 1635 1636 for (Arg *A : Args) { 1637 if (A->getOption().matches(options::OPT__SLASH_O)) { 1638 // The -O flag actually takes an amalgam of other options. For example, 1639 // '/Ogyb2' is equivalent to '/Og' '/Oy' '/Ob2'. 1640 TranslateOptArg(A, *DAL, SupportsForcingFramePointer, ExpandChar, Opts); 1641 } else if (A->getOption().matches(options::OPT_D)) { 1642 // Translate -Dfoo#bar into -Dfoo=bar. 1643 TranslateDArg(A, *DAL, Opts); 1644 } else if (OFK != Action::OFK_HIP) { 1645 // HIP Toolchain translates input args by itself. 1646 DAL->append(A); 1647 } 1648 } 1649 1650 return DAL; 1651 } 1652