Action.cpp 15 KB

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