AIX.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. //===--- AIX.cpp - AIX ToolChain Implementations ----------------*- C++ -*-===//
  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 "AIX.h"
  9. #include "Arch/PPC.h"
  10. #include "CommonArgs.h"
  11. #include "clang/Driver/Compilation.h"
  12. #include "clang/Driver/Options.h"
  13. #include "clang/Driver/SanitizerArgs.h"
  14. #include "llvm/Option/ArgList.h"
  15. #include "llvm/ProfileData/InstrProf.h"
  16. #include "llvm/Support/Path.h"
  17. using AIX = clang::driver::toolchains::AIX;
  18. using namespace clang::driver;
  19. using namespace clang::driver::tools;
  20. using namespace clang::driver::toolchains;
  21. using namespace llvm::opt;
  22. using namespace llvm::sys;
  23. void aix::Assembler::ConstructJob(Compilation &C, const JobAction &JA,
  24. const InputInfo &Output,
  25. const InputInfoList &Inputs,
  26. const ArgList &Args,
  27. const char *LinkingOutput) const {
  28. ArgStringList CmdArgs;
  29. const bool IsArch32Bit = getToolChain().getTriple().isArch32Bit();
  30. const bool IsArch64Bit = getToolChain().getTriple().isArch64Bit();
  31. // Only support 32 and 64 bit.
  32. if (!IsArch32Bit && !IsArch64Bit)
  33. llvm_unreachable("Unsupported bit width value.");
  34. // Specify the mode in which the as(1) command operates.
  35. if (IsArch32Bit) {
  36. CmdArgs.push_back("-a32");
  37. } else {
  38. // Must be 64-bit, otherwise asserted already.
  39. CmdArgs.push_back("-a64");
  40. }
  41. // Accept any mixture of instructions.
  42. // On Power for AIX and Linux, this behaviour matches that of GCC for both the
  43. // user-provided assembler source case and the compiler-produced assembler
  44. // source case. Yet XL with user-provided assembler source would not add this.
  45. CmdArgs.push_back("-many");
  46. Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler);
  47. // Specify assembler output file.
  48. assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
  49. if (Output.isFilename()) {
  50. CmdArgs.push_back("-o");
  51. CmdArgs.push_back(Output.getFilename());
  52. }
  53. // Specify assembler input file.
  54. // The system assembler on AIX takes exactly one input file. The driver is
  55. // expected to invoke as(1) separately for each assembler source input file.
  56. if (Inputs.size() != 1)
  57. llvm_unreachable("Invalid number of input files.");
  58. const InputInfo &II = Inputs[0];
  59. assert((II.isFilename() || II.isNothing()) && "Invalid input.");
  60. if (II.isFilename())
  61. CmdArgs.push_back(II.getFilename());
  62. const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as"));
  63. C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
  64. Exec, CmdArgs, Inputs, Output));
  65. }
  66. // Determine whether there are any linker options that supply an export list
  67. // (or equivalent information about what to export) being sent to the linker.
  68. static bool hasExportListLinkerOpts(const ArgStringList &CmdArgs) {
  69. for (size_t i = 0, Size = CmdArgs.size(); i < Size; ++i) {
  70. llvm::StringRef ArgString(CmdArgs[i]);
  71. if (ArgString.startswith("-bE:") || ArgString.startswith("-bexport:") ||
  72. ArgString == "-bexpall" || ArgString == "-bexpfull")
  73. return true;
  74. // If we split -b option, check the next opt.
  75. if (ArgString == "-b" && i + 1 < Size) {
  76. ++i;
  77. llvm::StringRef ArgNextString(CmdArgs[i]);
  78. if (ArgNextString.startswith("E:") ||
  79. ArgNextString.startswith("export:") || ArgNextString == "expall" ||
  80. ArgNextString == "expfull")
  81. return true;
  82. }
  83. }
  84. return false;
  85. }
  86. void aix::Linker::ConstructJob(Compilation &C, const JobAction &JA,
  87. const InputInfo &Output,
  88. const InputInfoList &Inputs, const ArgList &Args,
  89. const char *LinkingOutput) const {
  90. const AIX &ToolChain = static_cast<const AIX &>(getToolChain());
  91. const Driver &D = ToolChain.getDriver();
  92. ArgStringList CmdArgs;
  93. const bool IsArch32Bit = ToolChain.getTriple().isArch32Bit();
  94. const bool IsArch64Bit = ToolChain.getTriple().isArch64Bit();
  95. // Only support 32 and 64 bit.
  96. if (!(IsArch32Bit || IsArch64Bit))
  97. llvm_unreachable("Unsupported bit width value.");
  98. // Force static linking when "-static" is present.
  99. if (Args.hasArg(options::OPT_static))
  100. CmdArgs.push_back("-bnso");
  101. // Add options for shared libraries.
  102. if (Args.hasArg(options::OPT_shared)) {
  103. CmdArgs.push_back("-bM:SRE");
  104. CmdArgs.push_back("-bnoentry");
  105. }
  106. // PGO instrumentation generates symbols belonging to special sections, and
  107. // the linker needs to place all symbols in a particular section together in
  108. // memory; the AIX linker does that under an option.
  109. if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs,
  110. false) ||
  111. Args.hasFlag(options::OPT_fprofile_generate,
  112. options::OPT_fno_profile_generate, false) ||
  113. Args.hasFlag(options::OPT_fprofile_generate_EQ,
  114. options::OPT_fno_profile_generate, false) ||
  115. Args.hasFlag(options::OPT_fprofile_instr_generate,
  116. options::OPT_fno_profile_instr_generate, false) ||
  117. Args.hasFlag(options::OPT_fprofile_instr_generate_EQ,
  118. options::OPT_fno_profile_instr_generate, false) ||
  119. Args.hasFlag(options::OPT_fcs_profile_generate,
  120. options::OPT_fno_profile_generate, false) ||
  121. Args.hasFlag(options::OPT_fcs_profile_generate_EQ,
  122. options::OPT_fno_profile_generate, false) ||
  123. Args.hasArg(options::OPT_fcreate_profile) ||
  124. Args.hasArg(options::OPT_coverage))
  125. CmdArgs.push_back("-bdbg:namedsects:ss");
  126. // Specify linker output file.
  127. assert((Output.isFilename() || Output.isNothing()) && "Invalid output.");
  128. if (Output.isFilename()) {
  129. CmdArgs.push_back("-o");
  130. CmdArgs.push_back(Output.getFilename());
  131. }
  132. // Set linking mode (i.e., 32/64-bit) and the address of
  133. // text and data sections based on arch bit width.
  134. if (IsArch32Bit) {
  135. CmdArgs.push_back("-b32");
  136. CmdArgs.push_back("-bpT:0x10000000");
  137. CmdArgs.push_back("-bpD:0x20000000");
  138. } else {
  139. // Must be 64-bit, otherwise asserted already.
  140. CmdArgs.push_back("-b64");
  141. CmdArgs.push_back("-bpT:0x100000000");
  142. CmdArgs.push_back("-bpD:0x110000000");
  143. }
  144. auto getCrt0Basename = [&Args, IsArch32Bit] {
  145. // Enable gprofiling when "-pg" is specified.
  146. if (Args.hasArg(options::OPT_pg))
  147. return IsArch32Bit ? "gcrt0.o" : "gcrt0_64.o";
  148. // Enable profiling when "-p" is specified.
  149. else if (Args.hasArg(options::OPT_p))
  150. return IsArch32Bit ? "mcrt0.o" : "mcrt0_64.o";
  151. else
  152. return IsArch32Bit ? "crt0.o" : "crt0_64.o";
  153. };
  154. if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles,
  155. options::OPT_shared)) {
  156. CmdArgs.push_back(
  157. Args.MakeArgString(ToolChain.GetFilePath(getCrt0Basename())));
  158. CmdArgs.push_back(Args.MakeArgString(
  159. ToolChain.GetFilePath(IsArch32Bit ? "crti.o" : "crti_64.o")));
  160. }
  161. // Collect all static constructor and destructor functions in both C and CXX
  162. // language link invocations. This has to come before AddLinkerInputs as the
  163. // implied option needs to precede any other '-bcdtors' settings or
  164. // '-bnocdtors' that '-Wl' might forward.
  165. CmdArgs.push_back("-bcdtors:all:0:s");
  166. // Specify linker input file(s).
  167. AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA);
  168. if (D.isUsingLTO()) {
  169. assert(!Inputs.empty() && "Must have at least one input.");
  170. addLTOOptions(ToolChain, Args, CmdArgs, Output, Inputs[0],
  171. D.getLTOMode() == LTOK_Thin);
  172. }
  173. if (Args.hasArg(options::OPT_shared) && !hasExportListLinkerOpts(CmdArgs)) {
  174. const char *CreateExportListExec = Args.MakeArgString(
  175. path::parent_path(ToolChain.getDriver().ClangExecutable) +
  176. "/llvm-nm");
  177. ArgStringList CreateExportCmdArgs;
  178. std::string CreateExportListPath =
  179. C.getDriver().GetTemporaryPath("CreateExportList", "exp");
  180. const char *ExportList =
  181. C.addTempFile(C.getArgs().MakeArgString(CreateExportListPath));
  182. for (const auto &II : Inputs)
  183. if (II.isFilename())
  184. CreateExportCmdArgs.push_back(II.getFilename());
  185. CreateExportCmdArgs.push_back("--export-symbols");
  186. CreateExportCmdArgs.push_back("-X");
  187. if (IsArch32Bit) {
  188. CreateExportCmdArgs.push_back("32");
  189. } else {
  190. // Must be 64-bit, otherwise asserted already.
  191. CreateExportCmdArgs.push_back("64");
  192. }
  193. auto ExpCommand = std::make_unique<Command>(
  194. JA, *this, ResponseFileSupport::None(), CreateExportListExec,
  195. CreateExportCmdArgs, Inputs, Output);
  196. ExpCommand->setRedirectFiles(
  197. {std::nullopt, std::string(ExportList), std::nullopt});
  198. C.addCommand(std::move(ExpCommand));
  199. CmdArgs.push_back(Args.MakeArgString(llvm::Twine("-bE:") + ExportList));
  200. }
  201. // Add directory to library search path.
  202. Args.AddAllArgs(CmdArgs, options::OPT_L);
  203. ToolChain.AddFilePathLibArgs(Args, CmdArgs);
  204. ToolChain.addProfileRTLibs(Args, CmdArgs);
  205. if (getToolChain().ShouldLinkCXXStdlib(Args))
  206. getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs);
  207. if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) {
  208. AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
  209. // Add OpenMP runtime if -fopenmp is specified.
  210. if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
  211. options::OPT_fno_openmp, false)) {
  212. switch (ToolChain.getDriver().getOpenMPRuntime(Args)) {
  213. case Driver::OMPRT_OMP:
  214. CmdArgs.push_back("-lomp");
  215. break;
  216. case Driver::OMPRT_IOMP5:
  217. CmdArgs.push_back("-liomp5");
  218. break;
  219. case Driver::OMPRT_GOMP:
  220. CmdArgs.push_back("-lgomp");
  221. break;
  222. case Driver::OMPRT_Unknown:
  223. // Already diagnosed.
  224. break;
  225. }
  226. }
  227. // Support POSIX threads if "-pthreads" or "-pthread" is present.
  228. if (Args.hasArg(options::OPT_pthreads, options::OPT_pthread))
  229. CmdArgs.push_back("-lpthreads");
  230. if (D.CCCIsCXX())
  231. CmdArgs.push_back("-lm");
  232. CmdArgs.push_back("-lc");
  233. if (Args.hasArg(options::OPT_pg)) {
  234. CmdArgs.push_back(Args.MakeArgString((llvm::Twine("-L") + D.SysRoot) +
  235. "/lib/profiled"));
  236. CmdArgs.push_back(Args.MakeArgString((llvm::Twine("-L") + D.SysRoot) +
  237. "/usr/lib/profiled"));
  238. }
  239. }
  240. const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
  241. C.addCommand(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(),
  242. Exec, CmdArgs, Inputs, Output));
  243. }
  244. /// AIX - AIX tool chain which can call as(1) and ld(1) directly.
  245. AIX::AIX(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
  246. : ToolChain(D, Triple, Args) {
  247. ParseInlineAsmUsingAsmParser = Args.hasFlag(
  248. options::OPT_fintegrated_as, options::OPT_fno_integrated_as, true);
  249. getLibraryPaths().push_back(getDriver().SysRoot + "/usr/lib");
  250. }
  251. // Returns the effective header sysroot path to use.
  252. // This comes from either -isysroot or --sysroot.
  253. llvm::StringRef
  254. AIX::GetHeaderSysroot(const llvm::opt::ArgList &DriverArgs) const {
  255. if (DriverArgs.hasArg(options::OPT_isysroot))
  256. return DriverArgs.getLastArgValue(options::OPT_isysroot);
  257. if (!getDriver().SysRoot.empty())
  258. return getDriver().SysRoot;
  259. return "/";
  260. }
  261. void AIX::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
  262. ArgStringList &CC1Args) const {
  263. // Return if -nostdinc is specified as a driver option.
  264. if (DriverArgs.hasArg(options::OPT_nostdinc))
  265. return;
  266. llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs);
  267. const Driver &D = getDriver();
  268. if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
  269. SmallString<128> P(D.ResourceDir);
  270. // Add the PowerPC intrinsic headers (<resource>/include/ppc_wrappers)
  271. path::append(P, "include", "ppc_wrappers");
  272. addSystemInclude(DriverArgs, CC1Args, P);
  273. // Add the Clang builtin headers (<resource>/include)
  274. addSystemInclude(DriverArgs, CC1Args, path::parent_path(P.str()));
  275. }
  276. // Return if -nostdlibinc is specified as a driver option.
  277. if (DriverArgs.hasArg(options::OPT_nostdlibinc))
  278. return;
  279. // Add <sysroot>/usr/include.
  280. SmallString<128> UP(Sysroot);
  281. path::append(UP, "/usr/include");
  282. addSystemInclude(DriverArgs, CC1Args, UP.str());
  283. }
  284. void AIX::AddClangCXXStdlibIncludeArgs(
  285. const llvm::opt::ArgList &DriverArgs,
  286. llvm::opt::ArgStringList &CC1Args) const {
  287. if (DriverArgs.hasArg(options::OPT_nostdinc) ||
  288. DriverArgs.hasArg(options::OPT_nostdincxx) ||
  289. DriverArgs.hasArg(options::OPT_nostdlibinc))
  290. return;
  291. switch (GetCXXStdlibType(DriverArgs)) {
  292. case ToolChain::CST_Libstdcxx:
  293. llvm::report_fatal_error(
  294. "picking up libstdc++ headers is unimplemented on AIX");
  295. case ToolChain::CST_Libcxx: {
  296. llvm::StringRef Sysroot = GetHeaderSysroot(DriverArgs);
  297. SmallString<128> PathCPP(Sysroot);
  298. llvm::sys::path::append(PathCPP, "opt/IBM/openxlCSDK", "include", "c++",
  299. "v1");
  300. addSystemInclude(DriverArgs, CC1Args, PathCPP.str());
  301. // Required in order to suppress conflicting C++ overloads in the system
  302. // libc headers that were used by XL C++.
  303. CC1Args.push_back("-D__LIBC_NO_CPP_MATH_OVERLOADS__");
  304. return;
  305. }
  306. }
  307. llvm_unreachable("Unexpected C++ library type; only libc++ is supported.");
  308. }
  309. void AIX::AddCXXStdlibLibArgs(const llvm::opt::ArgList &Args,
  310. llvm::opt::ArgStringList &CmdArgs) const {
  311. switch (GetCXXStdlibType(Args)) {
  312. case ToolChain::CST_Libstdcxx:
  313. llvm::report_fatal_error("linking libstdc++ unimplemented on AIX");
  314. case ToolChain::CST_Libcxx:
  315. CmdArgs.push_back("-lc++");
  316. if (Args.hasArg(options::OPT_fexperimental_library))
  317. CmdArgs.push_back("-lc++experimental");
  318. CmdArgs.push_back("-lc++abi");
  319. return;
  320. }
  321. llvm_unreachable("Unexpected C++ library type; only libc++ is supported.");
  322. }
  323. void AIX::addProfileRTLibs(const llvm::opt::ArgList &Args,
  324. llvm::opt::ArgStringList &CmdArgs) const {
  325. // Add linker option -u__llvm_profile_runtime to cause runtime
  326. // initialization to occur.
  327. if (needsProfileRT(Args))
  328. CmdArgs.push_back(Args.MakeArgString(
  329. Twine("-u", llvm::getInstrProfRuntimeHookVarName())));
  330. ToolChain::addProfileRTLibs(Args, CmdArgs);
  331. }
  332. ToolChain::CXXStdlibType AIX::GetDefaultCXXStdlibType() const {
  333. return ToolChain::CST_Libcxx;
  334. }
  335. ToolChain::RuntimeLibType AIX::GetDefaultRuntimeLibType() const {
  336. return ToolChain::RLT_CompilerRT;
  337. }
  338. auto AIX::buildAssembler() const -> Tool * { return new aix::Assembler(*this); }
  339. auto AIX::buildLinker() const -> Tool * { return new aix::Linker(*this); }