MinGW.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687
  1. //===--- MinGW.cpp - MinGWToolChain Implementation ------------------------===//
  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 "MinGW.h"
  9. #include "CommonArgs.h"
  10. #include "clang/Config/config.h"
  11. #include "clang/Driver/Compilation.h"
  12. #include "clang/Driver/Driver.h"
  13. #include "clang/Driver/DriverDiagnostic.h"
  14. #include "clang/Driver/InputInfo.h"
  15. #include "clang/Driver/Options.h"
  16. #include "clang/Driver/SanitizerArgs.h"
  17. #include "llvm/Option/ArgList.h"
  18. #include "llvm/Support/FileSystem.h"
  19. #include "llvm/Support/Path.h"
  20. #include "llvm/Support/VirtualFileSystem.h"
  21. #include <system_error>
  22. using namespace clang::diag;
  23. using namespace clang::driver;
  24. using namespace clang;
  25. using namespace llvm::opt;
  26. /// MinGW Tools
  27. void tools::MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
  28. const InputInfo &Output,
  29. const InputInfoList &Inputs,
  30. const ArgList &Args,
  31. const char *LinkingOutput) const {
  32. claimNoWarnArgs(Args);
  33. ArgStringList CmdArgs;
  34. if (getToolChain().getArch() == llvm::Triple::x86) {
  35. CmdArgs.push_back("--32");
  36. } else if (getToolChain().getArch() == llvm::Triple::x86_64) {
  37. CmdArgs.push_back("--64");
  38. }
  39. Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
  40. CmdArgs.push_back("-o");
  41. CmdArgs.push_back(Output.getFilename());
  42. for (const auto &II : Inputs)
  43. CmdArgs.push_back(II.getFilename());
  44. const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
  45. C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
  46. Exec, CmdArgs, Inputs, Output));
  47. if (Args.hasArg(options::OPT_gsplit_dwarf))
  48. SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output,
  49. SplitDebugName(JA, Args, Inputs[0], Output));
  50. }
  51. void tools::MinGW::Linker::AddLibGCC(const ArgList &Args,
  52. ArgStringList &CmdArgs) const {
  53. if (Args.hasArg(options::OPT_mthreads))
  54. CmdArgs.push_back("-lmingwthrd");
  55. CmdArgs.push_back("-lmingw32");
  56. // Make use of compiler-rt if --rtlib option is used
  57. ToolChain::RuntimeLibType RLT = getToolChain().GetRuntimeLibType(Args);
  58. if (RLT == ToolChain::RLT_Libgcc) {
  59. bool Static = Args.hasArg(options::OPT_static_libgcc) ||
  60. Args.hasArg(options::OPT_static);
  61. bool Shared = Args.hasArg(options::OPT_shared);
  62. bool CXX = getToolChain().getDriver().CCCIsCXX();
  63. if (Static || (!CXX && !Shared)) {
  64. CmdArgs.push_back("-lgcc");
  65. CmdArgs.push_back("-lgcc_eh");
  66. } else {
  67. CmdArgs.push_back("-lgcc_s");
  68. CmdArgs.push_back("-lgcc");
  69. }
  70. } else {
  71. AddRunTimeLibs(getToolChain(), getToolChain().getDriver(), CmdArgs, Args);
  72. }
  73. CmdArgs.push_back("-lmoldname");
  74. CmdArgs.push_back("-lmingwex");
  75. for (auto Lib : Args.getAllArgValues(options::OPT_l))
  76. if (StringRef(Lib).startswith("msvcr") ||
  77. StringRef(Lib).startswith("ucrt") ||
  78. StringRef(Lib).startswith("crtdll"))
  79. return;
  80. CmdArgs.push_back("-lmsvcrt");
  81. }
  82. void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
  83. const InputInfo &Output,
  84. const InputInfoList &Inputs,
  85. const ArgList &Args,
  86. const char *LinkingOutput) const {
  87. const ToolChain &TC = getToolChain();
  88. const Driver &D = TC.getDriver();
  89. const SanitizerArgs &Sanitize = TC.getSanitizerArgs(Args);
  90. ArgStringList CmdArgs;
  91. // Silence warning for "clang -g foo.o -o foo"
  92. Args.ClaimAllArgs(options::OPT_g_Group);
  93. // and "clang -emit-llvm foo.o -o foo"
  94. Args.ClaimAllArgs(options::OPT_emit_llvm);
  95. // and for "clang -w foo.o -o foo". Other warning options are already
  96. // handled somewhere else.
  97. Args.ClaimAllArgs(options::OPT_w);
  98. if (!D.SysRoot.empty())
  99. CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
  100. if (Args.hasArg(options::OPT_s))
  101. CmdArgs.push_back("-s");
  102. CmdArgs.push_back("-m");
  103. switch (TC.getArch()) {
  104. case llvm::Triple::x86:
  105. CmdArgs.push_back("i386pe");
  106. break;
  107. case llvm::Triple::x86_64:
  108. CmdArgs.push_back("i386pep");
  109. break;
  110. case llvm::Triple::arm:
  111. case llvm::Triple::thumb:
  112. // FIXME: this is incorrect for WinCE
  113. CmdArgs.push_back("thumb2pe");
  114. break;
  115. case llvm::Triple::aarch64:
  116. CmdArgs.push_back("arm64pe");
  117. break;
  118. default:
  119. llvm_unreachable("Unsupported target architecture.");
  120. }
  121. Arg *SubsysArg =
  122. Args.getLastArg(options::OPT_mwindows, options::OPT_mconsole);
  123. if (SubsysArg && SubsysArg->getOption().matches(options::OPT_mwindows)) {
  124. CmdArgs.push_back("--subsystem");
  125. CmdArgs.push_back("windows");
  126. } else if (SubsysArg &&
  127. SubsysArg->getOption().matches(options::OPT_mconsole)) {
  128. CmdArgs.push_back("--subsystem");
  129. CmdArgs.push_back("console");
  130. }
  131. if (Args.hasArg(options::OPT_mdll))
  132. CmdArgs.push_back("--dll");
  133. else if (Args.hasArg(options::OPT_shared))
  134. CmdArgs.push_back("--shared");
  135. if (Args.hasArg(options::OPT_static))
  136. CmdArgs.push_back("-Bstatic");
  137. else
  138. CmdArgs.push_back("-Bdynamic");
  139. if (Args.hasArg(options::OPT_mdll) || Args.hasArg(options::OPT_shared)) {
  140. CmdArgs.push_back("-e");
  141. if (TC.getArch() == llvm::Triple::x86)
  142. CmdArgs.push_back("_DllMainCRTStartup@12");
  143. else
  144. CmdArgs.push_back("DllMainCRTStartup");
  145. CmdArgs.push_back("--enable-auto-image-base");
  146. }
  147. if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle))
  148. CmdArgs.push_back("--no-demangle");
  149. CmdArgs.push_back("-o");
  150. const char *OutputFile = Output.getFilename();
  151. // GCC implicitly adds an .exe extension if it is given an output file name
  152. // that lacks an extension.
  153. // GCC used to do this only when the compiler itself runs on windows, but
  154. // since GCC 8 it does the same when cross compiling as well.
  155. if (!llvm::sys::path::has_extension(OutputFile)) {
  156. CmdArgs.push_back(Args.MakeArgString(Twine(OutputFile) + ".exe"));
  157. OutputFile = CmdArgs.back();
  158. } else
  159. CmdArgs.push_back(OutputFile);
  160. Args.AddAllArgs(CmdArgs, options::OPT_e);
  161. // FIXME: add -N, -n flags
  162. Args.AddLastArg(CmdArgs, options::OPT_r);
  163. Args.AddLastArg(CmdArgs, options::OPT_s);
  164. Args.AddLastArg(CmdArgs, options::OPT_t);
  165. Args.AddAllArgs(CmdArgs, options::OPT_u_Group);
  166. Args.AddLastArg(CmdArgs, options::OPT_Z_Flag);
  167. if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
  168. if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) {
  169. CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o")));
  170. } else {
  171. if (Args.hasArg(options::OPT_municode))
  172. CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2u.o")));
  173. else
  174. CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2.o")));
  175. }
  176. if (Args.hasArg(options::OPT_pg))
  177. CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("gcrt2.o")));
  178. CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o")));
  179. }
  180. Args.AddAllArgs(CmdArgs, options::OPT_L);
  181. TC.AddFilePathLibArgs(Args, CmdArgs);
  182. // Add the compiler-rt library directories if they exist to help
  183. // the linker find the various sanitizer, builtin, and profiling runtimes.
  184. for (const auto &LibPath : TC.getLibraryPaths()) {
  185. if (TC.getVFS().exists(LibPath))
  186. CmdArgs.push_back(Args.MakeArgString("-L" + LibPath));
  187. }
  188. auto CRTPath = TC.getCompilerRTPath();
  189. if (TC.getVFS().exists(CRTPath))
  190. CmdArgs.push_back(Args.MakeArgString("-L" + CRTPath));
  191. AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
  192. // TODO: Add profile stuff here
  193. if (TC.ShouldLinkCXXStdlib(Args)) {
  194. bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) &&
  195. !Args.hasArg(options::OPT_static);
  196. if (OnlyLibstdcxxStatic)
  197. CmdArgs.push_back("-Bstatic");
  198. TC.AddCXXStdlibLibArgs(Args, CmdArgs);
  199. if (OnlyLibstdcxxStatic)
  200. CmdArgs.push_back("-Bdynamic");
  201. }
  202. bool HasWindowsApp = false;
  203. for (auto Lib : Args.getAllArgValues(options::OPT_l)) {
  204. if (Lib == "windowsapp") {
  205. HasWindowsApp = true;
  206. break;
  207. }
  208. }
  209. if (!Args.hasArg(options::OPT_nostdlib)) {
  210. if (!Args.hasArg(options::OPT_nodefaultlibs)) {
  211. if (Args.hasArg(options::OPT_static))
  212. CmdArgs.push_back("--start-group");
  213. if (Args.hasArg(options::OPT_fstack_protector) ||
  214. Args.hasArg(options::OPT_fstack_protector_strong) ||
  215. Args.hasArg(options::OPT_fstack_protector_all)) {
  216. CmdArgs.push_back("-lssp_nonshared");
  217. CmdArgs.push_back("-lssp");
  218. }
  219. if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
  220. options::OPT_fno_openmp, false)) {
  221. switch (TC.getDriver().getOpenMPRuntime(Args)) {
  222. case Driver::OMPRT_OMP:
  223. CmdArgs.push_back("-lomp");
  224. break;
  225. case Driver::OMPRT_IOMP5:
  226. CmdArgs.push_back("-liomp5md");
  227. break;
  228. case Driver::OMPRT_GOMP:
  229. CmdArgs.push_back("-lgomp");
  230. break;
  231. case Driver::OMPRT_Unknown:
  232. // Already diagnosed.
  233. break;
  234. }
  235. }
  236. AddLibGCC(Args, CmdArgs);
  237. if (Args.hasArg(options::OPT_pg))
  238. CmdArgs.push_back("-lgmon");
  239. if (Args.hasArg(options::OPT_pthread))
  240. CmdArgs.push_back("-lpthread");
  241. if (Sanitize.needsAsanRt()) {
  242. // MinGW always links against a shared MSVCRT.
  243. CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dynamic",
  244. ToolChain::FT_Shared));
  245. CmdArgs.push_back(
  246. TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk"));
  247. CmdArgs.push_back("--require-defined");
  248. CmdArgs.push_back(TC.getArch() == llvm::Triple::x86
  249. ? "___asan_seh_interceptor"
  250. : "__asan_seh_interceptor");
  251. // Make sure the linker consider all object files from the dynamic
  252. // runtime thunk.
  253. CmdArgs.push_back("--whole-archive");
  254. CmdArgs.push_back(
  255. TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk"));
  256. CmdArgs.push_back("--no-whole-archive");
  257. }
  258. TC.addProfileRTLibs(Args, CmdArgs);
  259. if (!HasWindowsApp) {
  260. // Add system libraries. If linking to libwindowsapp.a, that import
  261. // library replaces all these and we shouldn't accidentally try to
  262. // link to the normal desktop mode dlls.
  263. if (Args.hasArg(options::OPT_mwindows)) {
  264. CmdArgs.push_back("-lgdi32");
  265. CmdArgs.push_back("-lcomdlg32");
  266. }
  267. CmdArgs.push_back("-ladvapi32");
  268. CmdArgs.push_back("-lshell32");
  269. CmdArgs.push_back("-luser32");
  270. CmdArgs.push_back("-lkernel32");
  271. }
  272. if (Args.hasArg(options::OPT_static)) {
  273. CmdArgs.push_back("--end-group");
  274. } else {
  275. AddLibGCC(Args, CmdArgs);
  276. if (!HasWindowsApp)
  277. CmdArgs.push_back("-lkernel32");
  278. }
  279. }
  280. if (!Args.hasArg(options::OPT_nostartfiles)) {
  281. // Add crtfastmath.o if available and fast math is enabled.
  282. TC.addFastMathRuntimeIfAvailable(Args, CmdArgs);
  283. CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o")));
  284. }
  285. }
  286. const char *Exec = Args.MakeArgString(TC.GetLinkerPath());
  287. C.addCommand(std::make_unique<Command>(JA, *this,
  288. ResponseFileSupport::AtFileUTF8(),
  289. Exec, CmdArgs, Inputs, Output));
  290. }
  291. // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple.
  292. static bool findGccVersion(StringRef LibDir, std::string &GccLibDir,
  293. std::string &Ver) {
  294. auto Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0");
  295. std::error_code EC;
  296. for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE;
  297. LI = LI.increment(EC)) {
  298. StringRef VersionText = llvm::sys::path::filename(LI->path());
  299. auto CandidateVersion =
  300. toolchains::Generic_GCC::GCCVersion::Parse(VersionText);
  301. if (CandidateVersion.Major == -1)
  302. continue;
  303. if (CandidateVersion <= Version)
  304. continue;
  305. Version = CandidateVersion;
  306. Ver = std::string(VersionText);
  307. GccLibDir = LI->path();
  308. }
  309. return Ver.size();
  310. }
  311. void toolchains::MinGW::findGccLibDir() {
  312. llvm::SmallVector<llvm::SmallString<32>, 2> SubdirNames;
  313. SubdirNames.emplace_back(getTriple().getArchName());
  314. SubdirNames[0] += "-w64-mingw32";
  315. SubdirNames.emplace_back("mingw32");
  316. if (SubdirName.empty())
  317. SubdirName = std::string(SubdirNames[0].str());
  318. // lib: Arch Linux, Ubuntu, Windows
  319. // lib64: openSUSE Linux
  320. for (StringRef CandidateLib : {"lib", "lib64"}) {
  321. for (StringRef CandidateSysroot : SubdirNames) {
  322. llvm::SmallString<1024> LibDir(Base);
  323. llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateSysroot);
  324. if (findGccVersion(LibDir, GccLibDir, Ver)) {
  325. SubdirName = std::string(CandidateSysroot);
  326. return;
  327. }
  328. }
  329. }
  330. }
  331. static llvm::ErrorOr<std::string> findGcc(const llvm::Triple &T) {
  332. llvm::SmallVector<llvm::SmallString<32>, 2> Gccs;
  333. Gccs.emplace_back(T.getArchName());
  334. Gccs[0] += "-w64-mingw32-gcc";
  335. Gccs.emplace_back("mingw32-gcc");
  336. // Please do not add "gcc" here
  337. for (StringRef CandidateGcc : Gccs)
  338. if (llvm::ErrorOr<std::string> GPPName = llvm::sys::findProgramByName(CandidateGcc))
  339. return GPPName;
  340. return make_error_code(std::errc::no_such_file_or_directory);
  341. }
  342. static llvm::ErrorOr<std::string>
  343. findClangRelativeSysroot(const Driver &D, const llvm::Triple &T,
  344. std::string &SubdirName) {
  345. llvm::SmallVector<llvm::SmallString<32>, 2> Subdirs;
  346. Subdirs.emplace_back(T.str());
  347. Subdirs.emplace_back(T.getArchName());
  348. Subdirs[1] += "-w64-mingw32";
  349. StringRef ClangRoot = llvm::sys::path::parent_path(D.getInstalledDir());
  350. StringRef Sep = llvm::sys::path::get_separator();
  351. for (StringRef CandidateSubdir : Subdirs) {
  352. if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) {
  353. SubdirName = std::string(CandidateSubdir);
  354. return (ClangRoot + Sep + CandidateSubdir).str();
  355. }
  356. }
  357. return make_error_code(std::errc::no_such_file_or_directory);
  358. }
  359. toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple,
  360. const ArgList &Args)
  361. : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args),
  362. RocmInstallation(D, Triple, Args) {
  363. getProgramPaths().push_back(getDriver().getInstalledDir());
  364. // The sequence for detecting a sysroot here should be kept in sync with
  365. // the testTriple function below.
  366. if (getDriver().SysRoot.size())
  367. Base = getDriver().SysRoot;
  368. // Look for <clang-bin>/../<triplet>; if found, use <clang-bin>/.. as the
  369. // base as it could still be a base for a gcc setup with libgcc.
  370. else if (llvm::ErrorOr<std::string> TargetSubdir =
  371. findClangRelativeSysroot(getDriver(), getTriple(), SubdirName))
  372. Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get()));
  373. else if (llvm::ErrorOr<std::string> GPPName = findGcc(getTriple()))
  374. Base = std::string(llvm::sys::path::parent_path(
  375. llvm::sys::path::parent_path(GPPName.get())));
  376. else
  377. Base = std::string(
  378. llvm::sys::path::parent_path(getDriver().getInstalledDir()));
  379. Base += llvm::sys::path::get_separator();
  380. findGccLibDir();
  381. // GccLibDir must precede Base/lib so that the
  382. // correct crtbegin.o ,cetend.o would be found.
  383. getFilePaths().push_back(GccLibDir);
  384. getFilePaths().push_back(
  385. (Base + SubdirName + llvm::sys::path::get_separator() + "lib").str());
  386. getFilePaths().push_back(Base + "lib");
  387. // openSUSE
  388. getFilePaths().push_back(Base + SubdirName + "/sys-root/mingw/lib");
  389. NativeLLVMSupport =
  390. Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER)
  391. .equals_insensitive("lld");
  392. }
  393. bool toolchains::MinGW::IsIntegratedAssemblerDefault() const { return true; }
  394. Tool *toolchains::MinGW::getTool(Action::ActionClass AC) const {
  395. switch (AC) {
  396. case Action::PreprocessJobClass:
  397. if (!Preprocessor)
  398. Preprocessor.reset(new tools::gcc::Preprocessor(*this));
  399. return Preprocessor.get();
  400. case Action::CompileJobClass:
  401. if (!Compiler)
  402. Compiler.reset(new tools::gcc::Compiler(*this));
  403. return Compiler.get();
  404. default:
  405. return ToolChain::getTool(AC);
  406. }
  407. }
  408. Tool *toolchains::MinGW::buildAssembler() const {
  409. return new tools::MinGW::Assembler(*this);
  410. }
  411. Tool *toolchains::MinGW::buildLinker() const {
  412. return new tools::MinGW::Linker(*this);
  413. }
  414. bool toolchains::MinGW::HasNativeLLVMSupport() const {
  415. return NativeLLVMSupport;
  416. }
  417. bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList &Args) const {
  418. Arg *ExceptionArg = Args.getLastArg(options::OPT_fsjlj_exceptions,
  419. options::OPT_fseh_exceptions,
  420. options::OPT_fdwarf_exceptions);
  421. if (ExceptionArg &&
  422. ExceptionArg->getOption().matches(options::OPT_fseh_exceptions))
  423. return true;
  424. return getArch() == llvm::Triple::x86_64 ||
  425. getArch() == llvm::Triple::aarch64;
  426. }
  427. bool toolchains::MinGW::isPICDefault() const {
  428. return getArch() == llvm::Triple::x86_64 ||
  429. getArch() == llvm::Triple::aarch64;
  430. }
  431. bool toolchains::MinGW::isPIEDefault(const llvm::opt::ArgList &Args) const {
  432. return false;
  433. }
  434. bool toolchains::MinGW::isPICDefaultForced() const { return true; }
  435. llvm::ExceptionHandling
  436. toolchains::MinGW::GetExceptionModel(const ArgList &Args) const {
  437. if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64)
  438. return llvm::ExceptionHandling::WinEH;
  439. return llvm::ExceptionHandling::DwarfCFI;
  440. }
  441. SanitizerMask toolchains::MinGW::getSupportedSanitizers() const {
  442. SanitizerMask Res = ToolChain::getSupportedSanitizers();
  443. Res |= SanitizerKind::Address;
  444. Res |= SanitizerKind::PointerCompare;
  445. Res |= SanitizerKind::PointerSubtract;
  446. Res |= SanitizerKind::Vptr;
  447. return Res;
  448. }
  449. void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs,
  450. ArgStringList &CC1Args) const {
  451. CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args);
  452. }
  453. void toolchains::MinGW::AddHIPIncludeArgs(const ArgList &DriverArgs,
  454. ArgStringList &CC1Args) const {
  455. RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args);
  456. }
  457. void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const {
  458. CudaInstallation.print(OS);
  459. RocmInstallation.print(OS);
  460. }
  461. // Include directories for various hosts:
  462. // Windows, mingw.org
  463. // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++
  464. // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\mingw32
  465. // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\backward
  466. // c:\mingw\include
  467. // c:\mingw\mingw32\include
  468. // Windows, mingw-w64 mingw-builds
  469. // c:\mingw32\i686-w64-mingw32\include
  470. // c:\mingw32\i686-w64-mingw32\include\c++
  471. // c:\mingw32\i686-w64-mingw32\include\c++\i686-w64-mingw32
  472. // c:\mingw32\i686-w64-mingw32\include\c++\backward
  473. // Windows, mingw-w64 msys2
  474. // c:\msys64\mingw32\include
  475. // c:\msys64\mingw32\i686-w64-mingw32\include
  476. // c:\msys64\mingw32\include\c++\4.9.2
  477. // c:\msys64\mingw32\include\c++\4.9.2\i686-w64-mingw32
  478. // c:\msys64\mingw32\include\c++\4.9.2\backward
  479. // openSUSE
  480. // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++
  481. // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32
  482. // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/backward
  483. // /usr/x86_64-w64-mingw32/sys-root/mingw/include
  484. // Arch Linux
  485. // /usr/i686-w64-mingw32/include/c++/5.1.0
  486. // /usr/i686-w64-mingw32/include/c++/5.1.0/i686-w64-mingw32
  487. // /usr/i686-w64-mingw32/include/c++/5.1.0/backward
  488. // /usr/i686-w64-mingw32/include
  489. // Ubuntu
  490. // /usr/include/c++/4.8
  491. // /usr/include/c++/4.8/x86_64-w64-mingw32
  492. // /usr/include/c++/4.8/backward
  493. // /usr/x86_64-w64-mingw32/include
  494. void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
  495. ArgStringList &CC1Args) const {
  496. if (DriverArgs.hasArg(options::OPT_nostdinc))
  497. return;
  498. if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
  499. SmallString<1024> P(getDriver().ResourceDir);
  500. llvm::sys::path::append(P, "include");
  501. addSystemInclude(DriverArgs, CC1Args, P.str());
  502. }
  503. if (DriverArgs.hasArg(options::OPT_nostdlibinc))
  504. return;
  505. if (GetRuntimeLibType(DriverArgs) == ToolChain::RLT_Libgcc) {
  506. // openSUSE
  507. addSystemInclude(DriverArgs, CC1Args,
  508. Base + SubdirName + "/sys-root/mingw/include");
  509. }
  510. addSystemInclude(DriverArgs, CC1Args,
  511. Base + SubdirName + llvm::sys::path::get_separator() +
  512. "include");
  513. addSystemInclude(DriverArgs, CC1Args, Base + "include");
  514. }
  515. void toolchains::MinGW::AddClangCXXStdlibIncludeArgs(
  516. const ArgList &DriverArgs, ArgStringList &CC1Args) const {
  517. if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
  518. DriverArgs.hasArg(options::OPT_nostdincxx))
  519. return;
  520. StringRef Slash = llvm::sys::path::get_separator();
  521. switch (GetCXXStdlibType(DriverArgs)) {
  522. case ToolChain::CST_Libcxx: {
  523. std::string TargetDir = (Base + "include" + Slash + getTripleString() +
  524. Slash + "c++" + Slash + "v1")
  525. .str();
  526. if (getDriver().getVFS().exists(TargetDir))
  527. addSystemInclude(DriverArgs, CC1Args, TargetDir);
  528. addSystemInclude(DriverArgs, CC1Args,
  529. Base + SubdirName + Slash + "include" + Slash + "c++" +
  530. Slash + "v1");
  531. addSystemInclude(DriverArgs, CC1Args,
  532. Base + "include" + Slash + "c++" + Slash + "v1");
  533. break;
  534. }
  535. case ToolChain::CST_Libstdcxx:
  536. llvm::SmallVector<llvm::SmallString<1024>, 4> CppIncludeBases;
  537. CppIncludeBases.emplace_back(Base);
  538. llvm::sys::path::append(CppIncludeBases[0], SubdirName, "include", "c++");
  539. CppIncludeBases.emplace_back(Base);
  540. llvm::sys::path::append(CppIncludeBases[1], SubdirName, "include", "c++",
  541. Ver);
  542. CppIncludeBases.emplace_back(Base);
  543. llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver);
  544. CppIncludeBases.emplace_back(GccLibDir);
  545. llvm::sys::path::append(CppIncludeBases[3], "include", "c++");
  546. for (auto &CppIncludeBase : CppIncludeBases) {
  547. addSystemInclude(DriverArgs, CC1Args, CppIncludeBase);
  548. CppIncludeBase += Slash;
  549. addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + SubdirName);
  550. addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward");
  551. }
  552. break;
  553. }
  554. }
  555. static bool testTriple(const Driver &D, const llvm::Triple &Triple,
  556. const ArgList &Args) {
  557. // If an explicit sysroot is set, that will be used and we shouldn't try to
  558. // detect anything else.
  559. std::string SubdirName;
  560. if (D.SysRoot.size())
  561. return true;
  562. if (llvm::ErrorOr<std::string> TargetSubdir =
  563. findClangRelativeSysroot(D, Triple, SubdirName))
  564. return true;
  565. if (llvm::ErrorOr<std::string> GPPName = findGcc(Triple))
  566. return true;
  567. // If we neither found a colocated sysroot or a matching gcc executable,
  568. // conclude that we can't know if this is the correct spelling of the triple.
  569. return false;
  570. }
  571. static llvm::Triple adjustTriple(const Driver &D, const llvm::Triple &Triple,
  572. const ArgList &Args) {
  573. // First test if the original triple can find a sysroot with the triple
  574. // name.
  575. if (testTriple(D, Triple, Args))
  576. return Triple;
  577. llvm::SmallVector<llvm::StringRef, 3> Archs;
  578. // If not, test a couple other possible arch names that might be what was
  579. // intended.
  580. if (Triple.getArch() == llvm::Triple::x86) {
  581. Archs.emplace_back("i386");
  582. Archs.emplace_back("i586");
  583. Archs.emplace_back("i686");
  584. } else if (Triple.getArch() == llvm::Triple::arm ||
  585. Triple.getArch() == llvm::Triple::thumb) {
  586. Archs.emplace_back("armv7");
  587. }
  588. for (auto A : Archs) {
  589. llvm::Triple TestTriple(Triple);
  590. TestTriple.setArchName(A);
  591. if (testTriple(D, TestTriple, Args))
  592. return TestTriple;
  593. }
  594. // If none was found, just proceed with the original value.
  595. return Triple;
  596. }
  597. void toolchains::MinGW::fixTripleArch(const Driver &D, llvm::Triple &Triple,
  598. const ArgList &Args) {
  599. if (Triple.getArch() == llvm::Triple::x86 ||
  600. Triple.getArch() == llvm::Triple::arm ||
  601. Triple.getArch() == llvm::Triple::thumb)
  602. Triple = adjustTriple(D, Triple, Args);
  603. }