CrossWindows.cpp 9.6 KB

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