CrossWindows.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. //===-- CrossWindows.cpp - Cross Windows Tool Chain -----------------------===//
  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 "CrossWindows.h"
  9. #include "CommonArgs.h"
  10. #include "clang/Driver/Compilation.h"
  11. #include "clang/Driver/Driver.h"
  12. #include "clang/Driver/Options.h"
  13. #include "clang/Driver/SanitizerArgs.h"
  14. #include "llvm/Option/ArgList.h"
  15. #include "llvm/Support/Path.h"
  16. using namespace clang::driver;
  17. using namespace clang::driver::toolchains;
  18. using llvm::opt::ArgList;
  19. using llvm::opt::ArgStringList;
  20. void tools::CrossWindows::Assembler::ConstructJob(
  21. Compilation &C, const JobAction &JA, const InputInfo &Output,
  22. const InputInfoList &Inputs, const ArgList &Args,
  23. const char *LinkingOutput) const {
  24. claimNoWarnArgs(Args);
  25. const auto &TC =
  26. static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
  27. ArgStringList CmdArgs;
  28. const char *Exec;
  29. switch (TC.getArch()) {
  30. default:
  31. llvm_unreachable("unsupported architecture");
  32. case llvm::Triple::arm:
  33. case llvm::Triple::thumb:
  34. case llvm::Triple::aarch64:
  35. break;
  36. case llvm::Triple::x86:
  37. CmdArgs.push_back("--32");
  38. break;
  39. case llvm::Triple::x86_64:
  40. CmdArgs.push_back("--64");
  41. break;
  42. }
  43. Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
  44. CmdArgs.push_back("-o");
  45. CmdArgs.push_back(Output.getFilename());
  46. for (const auto &Input : Inputs)
  47. CmdArgs.push_back(Input.getFilename());
  48. const std::string Assembler = TC.GetProgramPath("as");
  49. Exec = Args.MakeArgString(Assembler);
  50. C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
  51. }
  52. void tools::CrossWindows::Linker::ConstructJob(
  53. Compilation &C, const JobAction &JA, const InputInfo &Output,
  54. const InputInfoList &Inputs, const ArgList &Args,
  55. const char *LinkingOutput) const {
  56. const auto &TC =
  57. static_cast<const toolchains::CrossWindowsToolChain &>(getToolChain());
  58. const llvm::Triple &T = TC.getTriple();
  59. const Driver &D = TC.getDriver();
  60. SmallString<128> EntryPoint;
  61. ArgStringList CmdArgs;
  62. const char *Exec;
  63. // Silence warning for "clang -g foo.o -o foo"
  64. Args.ClaimAllArgs(options::OPT_g_Group);
  65. // and "clang -emit-llvm foo.o -o foo"
  66. Args.ClaimAllArgs(options::OPT_emit_llvm);
  67. // and for "clang -w foo.o -o foo"
  68. Args.ClaimAllArgs(options::OPT_w);
  69. // Other warning options are already handled somewhere else.
  70. if (!D.SysRoot.empty())
  71. CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot));
  72. if (Args.hasArg(options::OPT_pie))
  73. CmdArgs.push_back("-pie");
  74. if (Args.hasArg(options::OPT_rdynamic))
  75. CmdArgs.push_back("-export-dynamic");
  76. if (Args.hasArg(options::OPT_s))
  77. CmdArgs.push_back("--strip-all");
  78. CmdArgs.push_back("-m");
  79. switch (TC.getArch()) {
  80. default:
  81. llvm_unreachable("unsupported architecture");
  82. case llvm::Triple::arm:
  83. case llvm::Triple::thumb:
  84. // FIXME: this is incorrect for WinCE
  85. CmdArgs.push_back("thumb2pe");
  86. break;
  87. case llvm::Triple::aarch64:
  88. CmdArgs.push_back("arm64pe");
  89. break;
  90. case llvm::Triple::x86:
  91. CmdArgs.push_back("i386pe");
  92. EntryPoint.append("_");
  93. break;
  94. case llvm::Triple::x86_64:
  95. CmdArgs.push_back("i386pep");
  96. break;
  97. }
  98. if (Args.hasArg(options::OPT_shared)) {
  99. switch (T.getArch()) {
  100. default:
  101. llvm_unreachable("unsupported architecture");
  102. case llvm::Triple::aarch64:
  103. case llvm::Triple::arm:
  104. case llvm::Triple::thumb:
  105. case llvm::Triple::x86_64:
  106. EntryPoint.append("_DllMainCRTStartup");
  107. break;
  108. case llvm::Triple::x86:
  109. EntryPoint.append("_DllMainCRTStartup@12");
  110. break;
  111. }
  112. CmdArgs.push_back("-shared");
  113. CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic"
  114. : "-Bdynamic");
  115. CmdArgs.push_back("--enable-auto-image-base");
  116. CmdArgs.push_back("--entry");
  117. CmdArgs.push_back(Args.MakeArgString(EntryPoint));
  118. } else {
  119. EntryPoint.append("mainCRTStartup");
  120. CmdArgs.push_back(Args.hasArg(options::OPT_static) ? "-Bstatic"
  121. : "-Bdynamic");
  122. if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
  123. CmdArgs.push_back("--entry");
  124. CmdArgs.push_back(Args.MakeArgString(EntryPoint));
  125. }
  126. // FIXME: handle subsystem
  127. }
  128. // NOTE: deal with multiple definitions on Windows (e.g. COMDAT)
  129. CmdArgs.push_back("--allow-multiple-definition");
  130. CmdArgs.push_back("-o");
  131. CmdArgs.push_back(Output.getFilename());
  132. if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_rdynamic)) {
  133. SmallString<261> ImpLib(Output.getFilename());
  134. llvm::sys::path::replace_extension(ImpLib, ".lib");
  135. CmdArgs.push_back("--out-implib");
  136. CmdArgs.push_back(Args.MakeArgString(ImpLib));
  137. }
  138. Args.AddAllArgs(CmdArgs, options::OPT_L);
  139. TC.AddFilePathLibArgs(Args, CmdArgs);
  140. AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA);
  141. if (TC.ShouldLinkCXXStdlib(Args)) {
  142. bool StaticCXX = Args.hasArg(options::OPT_static_libstdcxx) &&
  143. !Args.hasArg(options::OPT_static);
  144. if (StaticCXX)
  145. CmdArgs.push_back("-Bstatic");
  146. TC.AddCXXStdlibLibArgs(Args, CmdArgs);
  147. if (StaticCXX)
  148. CmdArgs.push_back("-Bdynamic");
  149. }
  150. if (!Args.hasArg(options::OPT_nostdlib)) {
  151. if (!Args.hasArg(options::OPT_nodefaultlibs)) {
  152. // TODO handle /MT[d] /MD[d]
  153. CmdArgs.push_back("-lmsvcrt");
  154. AddRunTimeLibs(TC, D, CmdArgs, Args);
  155. }
  156. }
  157. if (TC.getSanitizerArgs().needsAsanRt()) {
  158. // TODO handle /MT[d] /MD[d]
  159. if (Args.hasArg(options::OPT_shared)) {
  160. CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dll_thunk"));
  161. } else {
  162. for (const auto &Lib : {"asan_dynamic", "asan_dynamic_runtime_thunk"})
  163. CmdArgs.push_back(TC.getCompilerRTArgString(Args, Lib));
  164. // Make sure the dynamic runtime thunk is not optimized out at link time
  165. // to ensure proper SEH handling.
  166. CmdArgs.push_back(Args.MakeArgString("--undefined"));
  167. CmdArgs.push_back(Args.MakeArgString(TC.getArch() == llvm::Triple::x86
  168. ? "___asan_seh_interceptor"
  169. : "__asan_seh_interceptor"));
  170. }
  171. }
  172. Exec = Args.MakeArgString(TC.GetLinkerPath());
  173. C.addCommand(std::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs));
  174. }
  175. CrossWindowsToolChain::CrossWindowsToolChain(const Driver &D,
  176. const llvm::Triple &T,
  177. const llvm::opt::ArgList &Args)
  178. : Generic_GCC(D, T, Args) {}
  179. bool CrossWindowsToolChain::IsUnwindTablesDefault(const ArgList &Args) const {
  180. // FIXME: all non-x86 targets need unwind tables, however, LLVM currently does
  181. // not know how to emit them.
  182. return getArch() == llvm::Triple::x86_64;
  183. }
  184. bool CrossWindowsToolChain::isPICDefault() const {
  185. return getArch() == llvm::Triple::x86_64;
  186. }
  187. bool CrossWindowsToolChain::isPIEDefault() const {
  188. return getArch() == llvm::Triple::x86_64;
  189. }
  190. bool CrossWindowsToolChain::isPICDefaultForced() const {
  191. return getArch() == llvm::Triple::x86_64;
  192. }
  193. void CrossWindowsToolChain::
  194. AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
  195. llvm::opt::ArgStringList &CC1Args) const {
  196. const Driver &D = getDriver();
  197. const std::string &SysRoot = D.SysRoot;
  198. auto AddSystemAfterIncludes = [&]() {
  199. for (const auto &P : DriverArgs.getAllArgValues(options::OPT_isystem_after))
  200. addSystemInclude(DriverArgs, CC1Args, P);
  201. };
  202. if (DriverArgs.hasArg(options::OPT_nostdinc)) {
  203. AddSystemAfterIncludes();
  204. return;
  205. }
  206. addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
  207. if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
  208. SmallString<128> ResourceDir(D.ResourceDir);
  209. llvm::sys::path::append(ResourceDir, "include");
  210. addSystemInclude(DriverArgs, CC1Args, ResourceDir);
  211. }
  212. AddSystemAfterIncludes();
  213. addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
  214. }
  215. void CrossWindowsToolChain::
  216. AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
  217. llvm::opt::ArgStringList &CC1Args) const {
  218. const std::string &SysRoot = getDriver().SysRoot;
  219. if (DriverArgs.hasArg(options::OPT_nostdinc) ||
  220. DriverArgs.hasArg(options::OPT_nostdincxx))
  221. return;
  222. if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx)
  223. addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include/c++/v1");
  224. }
  225. void CrossWindowsToolChain::
  226. AddCXXStdlibLibArgs(const llvm::opt::ArgList &DriverArgs,
  227. llvm::opt::ArgStringList &CC1Args) const {
  228. if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx)
  229. CC1Args.push_back("-lc++");
  230. }
  231. clang::SanitizerMask CrossWindowsToolChain::getSupportedSanitizers() const {
  232. SanitizerMask Res = ToolChain::getSupportedSanitizers();
  233. Res |= SanitizerKind::Address;
  234. Res |= SanitizerKind::PointerCompare;
  235. Res |= SanitizerKind::PointerSubtract;
  236. return Res;
  237. }
  238. Tool *CrossWindowsToolChain::buildLinker() const {
  239. return new tools::CrossWindows::Linker(*this);
  240. }
  241. Tool *CrossWindowsToolChain::buildAssembler() const {
  242. return new tools::CrossWindows::Assembler(*this);
  243. }