Action.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. //===- Action.cpp - Abstract compilation steps ----------------------------===//
  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 "clang/Driver/Action.h"
  9. #include "llvm/Support/ErrorHandling.h"
  10. #include <cassert>
  11. #include <string>
  12. using namespace clang;
  13. using namespace driver;
  14. using namespace llvm::opt;
  15. Action::~Action() = default;
  16. const char *Action::getClassName(ActionClass AC) {
  17. switch (AC) {
  18. case InputClass: return "input";
  19. case BindArchClass: return "bind-arch";
  20. case OffloadClass:
  21. return "offload";
  22. case PreprocessJobClass: return "preprocessor";
  23. case PrecompileJobClass: return "precompiler";
  24. case HeaderModulePrecompileJobClass: return "header-module-precompiler";
  25. case AnalyzeJobClass: return "analyzer";
  26. case MigrateJobClass: return "migrator";
  27. case CompileJobClass: return "compiler";
  28. case BackendJobClass: return "backend";
  29. case AssembleJobClass: return "assembler";
  30. case IfsMergeJobClass: return "interface-stub-merger";
  31. case LinkJobClass: return "linker";
  32. case LipoJobClass: return "lipo";
  33. case DsymutilJobClass: return "dsymutil";
  34. case VerifyDebugInfoJobClass: return "verify-debug-info";
  35. case VerifyPCHJobClass: return "verify-pch";
  36. case OffloadBundlingJobClass:
  37. return "clang-offload-bundler";
  38. case OffloadUnbundlingJobClass:
  39. return "clang-offload-unbundler";
  40. case OffloadWrapperJobClass:
  41. return "clang-offload-wrapper";
  42. case LinkerWrapperJobClass:
  43. return "clang-linker-wrapper";
  44. case StaticLibJobClass:
  45. return "static-lib-linker";
  46. }
  47. llvm_unreachable("invalid class");
  48. }
  49. void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch) {
  50. // Offload action set its own kinds on their dependences.
  51. if (Kind == OffloadClass)
  52. return;
  53. // Unbundling actions use the host kinds.
  54. if (Kind == OffloadUnbundlingJobClass)
  55. return;
  56. assert((OffloadingDeviceKind == OKind || OffloadingDeviceKind == OFK_None) &&
  57. "Setting device kind to a different device??");
  58. assert(!ActiveOffloadKindMask && "Setting a device kind in a host action??");
  59. OffloadingDeviceKind = OKind;
  60. OffloadingArch = OArch;
  61. for (auto *A : Inputs)
  62. A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch);
  63. }
  64. void Action::propagateHostOffloadInfo(unsigned OKinds, const char *OArch) {
  65. // Offload action set its own kinds on their dependences.
  66. if (Kind == OffloadClass)
  67. return;
  68. assert(OffloadingDeviceKind == OFK_None &&
  69. "Setting a host kind in a device action.");
  70. ActiveOffloadKindMask |= OKinds;
  71. OffloadingArch = OArch;
  72. for (auto *A : Inputs)
  73. A->propagateHostOffloadInfo(ActiveOffloadKindMask, OArch);
  74. }
  75. void Action::propagateOffloadInfo(const Action *A) {
  76. if (unsigned HK = A->getOffloadingHostActiveKinds())
  77. propagateHostOffloadInfo(HK, A->getOffloadingArch());
  78. else
  79. propagateDeviceOffloadInfo(A->getOffloadingDeviceKind(),
  80. A->getOffloadingArch());
  81. }
  82. std::string Action::getOffloadingKindPrefix() const {
  83. switch (OffloadingDeviceKind) {
  84. case OFK_None:
  85. break;
  86. case OFK_Host:
  87. llvm_unreachable("Host kind is not an offloading device kind.");
  88. break;
  89. case OFK_Cuda:
  90. return "device-cuda";
  91. case OFK_OpenMP:
  92. return "device-openmp";
  93. case OFK_HIP:
  94. return "device-hip";
  95. // TODO: Add other programming models here.
  96. }
  97. if (!ActiveOffloadKindMask)
  98. return {};
  99. std::string Res("host");
  100. assert(!((ActiveOffloadKindMask & OFK_Cuda) &&
  101. (ActiveOffloadKindMask & OFK_HIP)) &&
  102. "Cannot offload CUDA and HIP at the same time");
  103. if (ActiveOffloadKindMask & OFK_Cuda)
  104. Res += "-cuda";
  105. if (ActiveOffloadKindMask & OFK_HIP)
  106. Res += "-hip";
  107. if (ActiveOffloadKindMask & OFK_OpenMP)
  108. Res += "-openmp";
  109. // TODO: Add other programming models here.
  110. return Res;
  111. }
  112. /// Return a string that can be used as prefix in order to generate unique files
  113. /// for each offloading kind.
  114. std::string
  115. Action::GetOffloadingFileNamePrefix(OffloadKind Kind,
  116. StringRef NormalizedTriple,
  117. bool CreatePrefixForHost) {
  118. // Don't generate prefix for host actions unless required.
  119. if (!CreatePrefixForHost && (Kind == OFK_None || Kind == OFK_Host))
  120. return {};
  121. std::string Res("-");
  122. Res += GetOffloadKindName(Kind);
  123. Res += "-";
  124. Res += NormalizedTriple;
  125. return Res;
  126. }
  127. /// Return a string with the offload kind name. If that is not defined, we
  128. /// assume 'host'.
  129. StringRef Action::GetOffloadKindName(OffloadKind Kind) {
  130. switch (Kind) {
  131. case OFK_None:
  132. case OFK_Host:
  133. return "host";
  134. case OFK_Cuda:
  135. return "cuda";
  136. case OFK_OpenMP:
  137. return "openmp";
  138. case OFK_HIP:
  139. return "hip";
  140. // TODO: Add other programming models here.
  141. }
  142. llvm_unreachable("invalid offload kind");
  143. }
  144. void InputAction::anchor() {}
  145. InputAction::InputAction(const Arg &_Input, types::ID _Type, StringRef _Id)
  146. : Action(InputClass, _Type), Input(_Input), Id(_Id.str()) {}
  147. void BindArchAction::anchor() {}
  148. BindArchAction::BindArchAction(Action *Input, StringRef ArchName)
  149. : Action(BindArchClass, Input), ArchName(ArchName) {}
  150. void OffloadAction::anchor() {}
  151. OffloadAction::OffloadAction(const HostDependence &HDep)
  152. : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()) {
  153. OffloadingArch = HDep.getBoundArch();
  154. ActiveOffloadKindMask = HDep.getOffloadKinds();
  155. HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
  156. HDep.getBoundArch());
  157. }
  158. OffloadAction::OffloadAction(const DeviceDependences &DDeps, types::ID Ty)
  159. : Action(OffloadClass, DDeps.getActions(), Ty),
  160. DevToolChains(DDeps.getToolChains()) {
  161. auto &OKinds = DDeps.getOffloadKinds();
  162. auto &BArchs = DDeps.getBoundArchs();
  163. // If all inputs agree on the same kind, use it also for this action.
  164. if (llvm::all_of(OKinds, [&](OffloadKind K) { return K == OKinds.front(); }))
  165. OffloadingDeviceKind = OKinds.front();
  166. // If we have a single dependency, inherit the architecture from it.
  167. if (OKinds.size() == 1)
  168. OffloadingArch = BArchs.front();
  169. // Propagate info to the dependencies.
  170. for (unsigned i = 0, e = getInputs().size(); i != e; ++i)
  171. getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i]);
  172. }
  173. OffloadAction::OffloadAction(const HostDependence &HDep,
  174. const DeviceDependences &DDeps)
  175. : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()),
  176. DevToolChains(DDeps.getToolChains()) {
  177. // We use the kinds of the host dependence for this action.
  178. OffloadingArch = HDep.getBoundArch();
  179. ActiveOffloadKindMask = HDep.getOffloadKinds();
  180. HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
  181. HDep.getBoundArch());
  182. // Add device inputs and propagate info to the device actions. Do work only if
  183. // we have dependencies.
  184. for (unsigned i = 0, e = DDeps.getActions().size(); i != e; ++i)
  185. if (auto *A = DDeps.getActions()[i]) {
  186. getInputs().push_back(A);
  187. A->propagateDeviceOffloadInfo(DDeps.getOffloadKinds()[i],
  188. DDeps.getBoundArchs()[i]);
  189. }
  190. }
  191. void OffloadAction::doOnHostDependence(const OffloadActionWorkTy &Work) const {
  192. if (!HostTC)
  193. return;
  194. assert(!getInputs().empty() && "No dependencies for offload action??");
  195. auto *A = getInputs().front();
  196. Work(A, HostTC, A->getOffloadingArch());
  197. }
  198. void OffloadAction::doOnEachDeviceDependence(
  199. const OffloadActionWorkTy &Work) const {
  200. auto I = getInputs().begin();
  201. auto E = getInputs().end();
  202. if (I == E)
  203. return;
  204. // We expect to have the same number of input dependences and device tool
  205. // chains, except if we also have a host dependence. In that case we have one
  206. // more dependence than we have device tool chains.
  207. assert(getInputs().size() == DevToolChains.size() + (HostTC ? 1 : 0) &&
  208. "Sizes of action dependences and toolchains are not consistent!");
  209. // Skip host action
  210. if (HostTC)
  211. ++I;
  212. auto TI = DevToolChains.begin();
  213. for (; I != E; ++I, ++TI)
  214. Work(*I, *TI, (*I)->getOffloadingArch());
  215. }
  216. void OffloadAction::doOnEachDependence(const OffloadActionWorkTy &Work) const {
  217. doOnHostDependence(Work);
  218. doOnEachDeviceDependence(Work);
  219. }
  220. void OffloadAction::doOnEachDependence(bool IsHostDependence,
  221. const OffloadActionWorkTy &Work) const {
  222. if (IsHostDependence)
  223. doOnHostDependence(Work);
  224. else
  225. doOnEachDeviceDependence(Work);
  226. }
  227. bool OffloadAction::hasHostDependence() const { return HostTC != nullptr; }
  228. Action *OffloadAction::getHostDependence() const {
  229. assert(hasHostDependence() && "Host dependence does not exist!");
  230. assert(!getInputs().empty() && "No dependencies for offload action??");
  231. return HostTC ? getInputs().front() : nullptr;
  232. }
  233. bool OffloadAction::hasSingleDeviceDependence(
  234. bool DoNotConsiderHostActions) const {
  235. if (DoNotConsiderHostActions)
  236. return getInputs().size() == (HostTC ? 2 : 1);
  237. return !HostTC && getInputs().size() == 1;
  238. }
  239. Action *
  240. OffloadAction::getSingleDeviceDependence(bool DoNotConsiderHostActions) const {
  241. assert(hasSingleDeviceDependence(DoNotConsiderHostActions) &&
  242. "Single device dependence does not exist!");
  243. // The previous assert ensures the number of entries in getInputs() is
  244. // consistent with what we are doing here.
  245. return HostTC ? getInputs()[1] : getInputs().front();
  246. }
  247. void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,
  248. const char *BoundArch,
  249. OffloadKind OKind) {
  250. DeviceActions.push_back(&A);
  251. DeviceToolChains.push_back(&TC);
  252. DeviceBoundArchs.push_back(BoundArch);
  253. DeviceOffloadKinds.push_back(OKind);
  254. }
  255. OffloadAction::HostDependence::HostDependence(Action &A, const ToolChain &TC,
  256. const char *BoundArch,
  257. const DeviceDependences &DDeps)
  258. : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch) {
  259. for (auto K : DDeps.getOffloadKinds())
  260. HostOffloadKinds |= K;
  261. }
  262. void JobAction::anchor() {}
  263. JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)
  264. : Action(Kind, Input, Type) {}
  265. JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
  266. : Action(Kind, Inputs, Type) {}
  267. void PreprocessJobAction::anchor() {}
  268. PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType)
  269. : JobAction(PreprocessJobClass, Input, OutputType) {}
  270. void PrecompileJobAction::anchor() {}
  271. PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)
  272. : JobAction(PrecompileJobClass, Input, OutputType) {}
  273. PrecompileJobAction::PrecompileJobAction(ActionClass Kind, Action *Input,
  274. types::ID OutputType)
  275. : JobAction(Kind, Input, OutputType) {
  276. assert(isa<PrecompileJobAction>((Action*)this) && "invalid action kind");
  277. }
  278. void HeaderModulePrecompileJobAction::anchor() {}
  279. HeaderModulePrecompileJobAction::HeaderModulePrecompileJobAction(
  280. Action *Input, types::ID OutputType, const char *ModuleName)
  281. : PrecompileJobAction(HeaderModulePrecompileJobClass, Input, OutputType),
  282. ModuleName(ModuleName) {}
  283. void AnalyzeJobAction::anchor() {}
  284. AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
  285. : JobAction(AnalyzeJobClass, Input, OutputType) {}
  286. void MigrateJobAction::anchor() {}
  287. MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType)
  288. : JobAction(MigrateJobClass, Input, OutputType) {}
  289. void CompileJobAction::anchor() {}
  290. CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)
  291. : JobAction(CompileJobClass, Input, OutputType) {}
  292. void BackendJobAction::anchor() {}
  293. BackendJobAction::BackendJobAction(Action *Input, types::ID OutputType)
  294. : JobAction(BackendJobClass, Input, OutputType) {}
  295. void AssembleJobAction::anchor() {}
  296. AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
  297. : JobAction(AssembleJobClass, Input, OutputType) {}
  298. void IfsMergeJobAction::anchor() {}
  299. IfsMergeJobAction::IfsMergeJobAction(ActionList &Inputs, types::ID Type)
  300. : JobAction(IfsMergeJobClass, Inputs, Type) {}
  301. void LinkJobAction::anchor() {}
  302. LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
  303. : JobAction(LinkJobClass, Inputs, Type) {}
  304. void LipoJobAction::anchor() {}
  305. LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type)
  306. : JobAction(LipoJobClass, Inputs, Type) {}
  307. void DsymutilJobAction::anchor() {}
  308. DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type)
  309. : JobAction(DsymutilJobClass, Inputs, Type) {}
  310. void VerifyJobAction::anchor() {}
  311. VerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input,
  312. types::ID Type)
  313. : JobAction(Kind, Input, Type) {
  314. assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&
  315. "ActionClass is not a valid VerifyJobAction");
  316. }
  317. void VerifyDebugInfoJobAction::anchor() {}
  318. VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input,
  319. types::ID Type)
  320. : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {}
  321. void VerifyPCHJobAction::anchor() {}
  322. VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type)
  323. : VerifyJobAction(VerifyPCHJobClass, Input, Type) {}
  324. void OffloadBundlingJobAction::anchor() {}
  325. OffloadBundlingJobAction::OffloadBundlingJobAction(ActionList &Inputs)
  326. : JobAction(OffloadBundlingJobClass, Inputs, Inputs.back()->getType()) {}
  327. void OffloadUnbundlingJobAction::anchor() {}
  328. OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action *Input)
  329. : JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {}
  330. void OffloadWrapperJobAction::anchor() {}
  331. OffloadWrapperJobAction::OffloadWrapperJobAction(ActionList &Inputs,
  332. types::ID Type)
  333. : JobAction(OffloadWrapperJobClass, Inputs, Type) {}
  334. void LinkerWrapperJobAction::anchor() {}
  335. LinkerWrapperJobAction::LinkerWrapperJobAction(ActionList &Inputs,
  336. types::ID Type)
  337. : JobAction(LinkerWrapperJobClass, Inputs, Type) {}
  338. void StaticLibJobAction::anchor() {}
  339. StaticLibJobAction::StaticLibJobAction(ActionList &Inputs, types::ID Type)
  340. : JobAction(StaticLibJobClass, Inputs, Type) {}