Action.cpp 14 KB

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