Action.cpp 14 KB

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