brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.9 KiB · 72a42a6 Raw
477 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "clang/Driver/Action.h"10#include "llvm/Support/ErrorHandling.h"11#include <cassert>12#include <string>13 14using namespace clang;15using namespace driver;16using namespace llvm::opt;17 18Action::~Action() = default;19 20const char *Action::getClassName(ActionClass AC) {21  switch (AC) {22  case InputClass: return "input";23  case BindArchClass: return "bind-arch";24  case OffloadClass:25    return "offload";26  case PreprocessJobClass: return "preprocessor";27  case PrecompileJobClass: return "precompiler";28  case ExtractAPIJobClass:29    return "api-extractor";30  case AnalyzeJobClass:31    return "analyzer";32  case CompileJobClass: return "compiler";33  case BackendJobClass: return "backend";34  case AssembleJobClass: return "assembler";35  case IfsMergeJobClass: return "interface-stub-merger";36  case LinkJobClass: return "linker";37  case LipoJobClass: return "lipo";38  case DsymutilJobClass: return "dsymutil";39  case VerifyDebugInfoJobClass: return "verify-debug-info";40  case VerifyPCHJobClass: return "verify-pch";41  case OffloadBundlingJobClass:42    return "clang-offload-bundler";43  case OffloadUnbundlingJobClass:44    return "clang-offload-unbundler";45  case OffloadPackagerJobClass:46    return "llvm-offload-binary";47  case LinkerWrapperJobClass:48    return "clang-linker-wrapper";49  case StaticLibJobClass:50    return "static-lib-linker";51  case BinaryAnalyzeJobClass:52    return "binary-analyzer";53  case BinaryTranslatorJobClass:54    return "binary-translator";55  case ObjcopyJobClass:56    return "objcopy";57  }58 59  llvm_unreachable("invalid class");60}61 62void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch,63                                        const ToolChain *OToolChain) {64  // Offload action set its own kinds on their dependences.65  if (Kind == OffloadClass)66    return;67  // Unbundling actions use the host kinds.68  if (Kind == OffloadUnbundlingJobClass)69    return;70 71  assert((OffloadingDeviceKind == OKind || OffloadingDeviceKind == OFK_None) &&72         "Setting device kind to a different device??");73  assert(!ActiveOffloadKindMask && "Setting a device kind in a host action??");74  OffloadingDeviceKind = OKind;75  OffloadingArch = OArch;76  OffloadingToolChain = OToolChain;77 78  for (auto *A : Inputs)79    A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch, OToolChain);80}81 82void Action::propagateHostOffloadInfo(unsigned OKinds, const char *OArch) {83  // Offload action set its own kinds on their dependences.84  if (Kind == OffloadClass)85    return;86 87  assert(OffloadingDeviceKind == OFK_None &&88         "Setting a host kind in a device action.");89  ActiveOffloadKindMask |= OKinds;90  OffloadingArch = OArch;91 92  for (auto *A : Inputs)93    A->propagateHostOffloadInfo(ActiveOffloadKindMask, OArch);94}95 96void Action::propagateOffloadInfo(const Action *A) {97  if (unsigned HK = A->getOffloadingHostActiveKinds())98    propagateHostOffloadInfo(HK, A->getOffloadingArch());99  else100    propagateDeviceOffloadInfo(A->getOffloadingDeviceKind(),101                               A->getOffloadingArch(),102                               A->getOffloadingToolChain());103}104 105std::string Action::getOffloadingKindPrefix() const {106  switch (OffloadingDeviceKind) {107  case OFK_None:108    break;109  case OFK_Host:110    llvm_unreachable("Host kind is not an offloading device kind.");111    break;112  case OFK_Cuda:113    return "device-cuda";114  case OFK_OpenMP:115    return "device-openmp";116  case OFK_HIP:117    return "device-hip";118  case OFK_SYCL:119    return "device-sycl";120 121    // TODO: Add other programming models here.122  }123 124  if (!ActiveOffloadKindMask)125    return {};126 127  std::string Res("host");128  assert(!((ActiveOffloadKindMask & OFK_Cuda) &&129           (ActiveOffloadKindMask & OFK_HIP)) &&130         "Cannot offload CUDA and HIP at the same time");131  if (ActiveOffloadKindMask & OFK_Cuda)132    Res += "-cuda";133  if (ActiveOffloadKindMask & OFK_HIP)134    Res += "-hip";135  if (ActiveOffloadKindMask & OFK_OpenMP)136    Res += "-openmp";137  if (ActiveOffloadKindMask & OFK_SYCL)138    Res += "-sycl";139 140  // TODO: Add other programming models here.141 142  return Res;143}144 145/// Return a string that can be used as prefix in order to generate unique files146/// for each offloading kind.147std::string148Action::GetOffloadingFileNamePrefix(OffloadKind Kind,149                                    StringRef NormalizedTriple,150                                    bool CreatePrefixForHost) {151  // Don't generate prefix for host actions unless required.152  if (!CreatePrefixForHost && (Kind == OFK_None || Kind == OFK_Host))153    return {};154 155  std::string Res("-");156  Res += GetOffloadKindName(Kind);157  Res += "-";158  Res += NormalizedTriple;159  return Res;160}161 162/// Return a string with the offload kind name. If that is not defined, we163/// assume 'host'.164StringRef Action::GetOffloadKindName(OffloadKind Kind) {165  switch (Kind) {166  case OFK_None:167  case OFK_Host:168    return "host";169  case OFK_Cuda:170    return "cuda";171  case OFK_OpenMP:172    return "openmp";173  case OFK_HIP:174    return "hip";175  case OFK_SYCL:176    return "sycl";177 178    // TODO: Add other programming models here.179  }180 181  llvm_unreachable("invalid offload kind");182}183 184void InputAction::anchor() {}185 186InputAction::InputAction(const Arg &_Input, types::ID _Type, StringRef _Id)187    : Action(InputClass, _Type), Input(_Input), Id(_Id.str()) {}188 189void BindArchAction::anchor() {}190 191BindArchAction::BindArchAction(Action *Input, StringRef ArchName)192    : Action(BindArchClass, Input), ArchName(ArchName) {}193 194void OffloadAction::anchor() {}195 196OffloadAction::OffloadAction(const HostDependence &HDep)197    : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()) {198  OffloadingArch = HDep.getBoundArch();199  ActiveOffloadKindMask = HDep.getOffloadKinds();200  HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),201                                             HDep.getBoundArch());202}203 204OffloadAction::OffloadAction(const DeviceDependences &DDeps, types::ID Ty)205    : Action(OffloadClass, DDeps.getActions(), Ty),206      DevToolChains(DDeps.getToolChains()) {207  auto &OKinds = DDeps.getOffloadKinds();208  auto &BArchs = DDeps.getBoundArchs();209  auto &OTCs = DDeps.getToolChains();210 211  // If all inputs agree on the same kind, use it also for this action.212  if (llvm::all_equal(OKinds))213    OffloadingDeviceKind = OKinds.front();214 215  // If we have a single dependency, inherit the architecture from it.216  if (OKinds.size() == 1)217    OffloadingArch = BArchs.front();218 219  // Propagate info to the dependencies.220  for (unsigned i = 0, e = getInputs().size(); i != e; ++i)221    getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i], OTCs[i]);222}223 224OffloadAction::OffloadAction(const HostDependence &HDep,225                             const DeviceDependences &DDeps)226    : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()),227      DevToolChains(DDeps.getToolChains()) {228  // We use the kinds of the host dependence for this action.229  OffloadingArch = HDep.getBoundArch();230  ActiveOffloadKindMask = HDep.getOffloadKinds();231  HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),232                                             HDep.getBoundArch());233 234  // Add device inputs and propagate info to the device actions. Do work only if235  // we have dependencies.236  for (unsigned i = 0, e = DDeps.getActions().size(); i != e; ++i) {237    if (auto *A = DDeps.getActions()[i]) {238      getInputs().push_back(A);239      A->propagateDeviceOffloadInfo(DDeps.getOffloadKinds()[i],240                                    DDeps.getBoundArchs()[i],241                                    DDeps.getToolChains()[i]);242      // If this action is used to forward single dependency, set the toolchain.243      if (DDeps.getActions().size() == 1)244        OffloadingToolChain = DDeps.getToolChains()[i];245    }246  }247}248 249void OffloadAction::doOnHostDependence(const OffloadActionWorkTy &Work) const {250  if (!HostTC)251    return;252  assert(!getInputs().empty() && "No dependencies for offload action??");253  auto *A = getInputs().front();254  Work(A, HostTC, A->getOffloadingArch());255}256 257void OffloadAction::doOnEachDeviceDependence(258    const OffloadActionWorkTy &Work) const {259  auto I = getInputs().begin();260  auto E = getInputs().end();261  if (I == E)262    return;263 264  // We expect to have the same number of input dependences and device tool265  // chains, except if we also have a host dependence. In that case we have one266  // more dependence than we have device tool chains.267  assert(getInputs().size() == DevToolChains.size() + (HostTC ? 1 : 0) &&268         "Sizes of action dependences and toolchains are not consistent!");269 270  // Skip host action271  if (HostTC)272    ++I;273 274  auto TI = DevToolChains.begin();275  for (; I != E; ++I, ++TI)276    Work(*I, *TI, (*I)->getOffloadingArch());277}278 279void OffloadAction::doOnEachDependence(const OffloadActionWorkTy &Work) const {280  doOnHostDependence(Work);281  doOnEachDeviceDependence(Work);282}283 284void OffloadAction::doOnEachDependence(bool IsHostDependence,285                                       const OffloadActionWorkTy &Work) const {286  if (IsHostDependence)287    doOnHostDependence(Work);288  else289    doOnEachDeviceDependence(Work);290}291 292bool OffloadAction::hasHostDependence() const { return HostTC != nullptr; }293 294Action *OffloadAction::getHostDependence() const {295  assert(hasHostDependence() && "Host dependence does not exist!");296  assert(!getInputs().empty() && "No dependencies for offload action??");297  return HostTC ? getInputs().front() : nullptr;298}299 300bool OffloadAction::hasSingleDeviceDependence(301    bool DoNotConsiderHostActions) const {302  if (DoNotConsiderHostActions)303    return getInputs().size() == (HostTC ? 2 : 1);304  return !HostTC && getInputs().size() == 1;305}306 307Action *308OffloadAction::getSingleDeviceDependence(bool DoNotConsiderHostActions) const {309  assert(hasSingleDeviceDependence(DoNotConsiderHostActions) &&310         "Single device dependence does not exist!");311  // The previous assert ensures the number of entries in getInputs() is312  // consistent with what we are doing here.313  return HostTC ? getInputs()[1] : getInputs().front();314}315 316void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,317                                           const char *BoundArch,318                                           OffloadKind OKind) {319  DeviceActions.push_back(&A);320  DeviceToolChains.push_back(&TC);321  DeviceBoundArchs.push_back(BoundArch);322  DeviceOffloadKinds.push_back(OKind);323}324 325void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,326                                           const char *BoundArch,327                                           unsigned OffloadKindMask) {328  DeviceActions.push_back(&A);329  DeviceToolChains.push_back(&TC);330  DeviceBoundArchs.push_back(BoundArch);331 332  // Add each active offloading kind from a mask.333  for (OffloadKind OKind : {OFK_OpenMP, OFK_Cuda, OFK_HIP, OFK_SYCL})334    if (OKind & OffloadKindMask)335      DeviceOffloadKinds.push_back(OKind);336}337 338OffloadAction::HostDependence::HostDependence(Action &A, const ToolChain &TC,339                                              const char *BoundArch,340                                              const DeviceDependences &DDeps)341    : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch) {342  for (auto K : DDeps.getOffloadKinds())343    HostOffloadKinds |= K;344}345 346void JobAction::anchor() {}347 348JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)349    : Action(Kind, Input, Type) {}350 351JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)352    : Action(Kind, Inputs, Type) {}353 354void PreprocessJobAction::anchor() {}355 356PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType)357    : JobAction(PreprocessJobClass, Input, OutputType) {}358 359void PrecompileJobAction::anchor() {}360 361PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)362    : JobAction(PrecompileJobClass, Input, OutputType) {}363 364PrecompileJobAction::PrecompileJobAction(ActionClass Kind, Action *Input,365                                         types::ID OutputType)366    : JobAction(Kind, Input, OutputType) {367  assert(isa<PrecompileJobAction>((Action*)this) && "invalid action kind");368}369 370void ExtractAPIJobAction::anchor() {}371 372ExtractAPIJobAction::ExtractAPIJobAction(Action *Inputs, types::ID OutputType)373    : JobAction(ExtractAPIJobClass, Inputs, OutputType) {}374 375void AnalyzeJobAction::anchor() {}376 377AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)378    : JobAction(AnalyzeJobClass, Input, OutputType) {}379 380void CompileJobAction::anchor() {}381 382CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)383    : JobAction(CompileJobClass, Input, OutputType) {}384 385void BackendJobAction::anchor() {}386 387BackendJobAction::BackendJobAction(Action *Input, types::ID OutputType)388    : JobAction(BackendJobClass, Input, OutputType) {}389 390void AssembleJobAction::anchor() {}391 392AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)393    : JobAction(AssembleJobClass, Input, OutputType) {}394 395void IfsMergeJobAction::anchor() {}396 397IfsMergeJobAction::IfsMergeJobAction(ActionList &Inputs, types::ID Type)398    : JobAction(IfsMergeJobClass, Inputs, Type) {}399 400void LinkJobAction::anchor() {}401 402LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)403    : JobAction(LinkJobClass, Inputs, Type) {}404 405void LipoJobAction::anchor() {}406 407LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type)408    : JobAction(LipoJobClass, Inputs, Type) {}409 410void DsymutilJobAction::anchor() {}411 412DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type)413    : JobAction(DsymutilJobClass, Inputs, Type) {}414 415void VerifyJobAction::anchor() {}416 417VerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input,418                                 types::ID Type)419    : JobAction(Kind, Input, Type) {420  assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&421         "ActionClass is not a valid VerifyJobAction");422}423 424void VerifyDebugInfoJobAction::anchor() {}425 426VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input,427                                                   types::ID Type)428    : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {}429 430void VerifyPCHJobAction::anchor() {}431 432VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type)433    : VerifyJobAction(VerifyPCHJobClass, Input, Type) {}434 435void OffloadBundlingJobAction::anchor() {}436 437OffloadBundlingJobAction::OffloadBundlingJobAction(ActionList &Inputs)438    : JobAction(OffloadBundlingJobClass, Inputs, Inputs.back()->getType()) {}439 440void OffloadUnbundlingJobAction::anchor() {}441 442OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action *Input)443    : JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {}444 445void OffloadPackagerJobAction::anchor() {}446 447OffloadPackagerJobAction::OffloadPackagerJobAction(ActionList &Inputs,448                                                   types::ID Type)449    : JobAction(OffloadPackagerJobClass, Inputs, Type) {}450 451void LinkerWrapperJobAction::anchor() {}452 453LinkerWrapperJobAction::LinkerWrapperJobAction(ActionList &Inputs,454                                               types::ID Type)455    : JobAction(LinkerWrapperJobClass, Inputs, Type) {}456 457void StaticLibJobAction::anchor() {}458 459StaticLibJobAction::StaticLibJobAction(ActionList &Inputs, types::ID Type)460    : JobAction(StaticLibJobClass, Inputs, Type) {}461 462void BinaryAnalyzeJobAction::anchor() {}463 464BinaryAnalyzeJobAction::BinaryAnalyzeJobAction(Action *Input, types::ID Type)465    : JobAction(BinaryAnalyzeJobClass, Input, Type) {}466 467void BinaryTranslatorJobAction::anchor() {}468 469BinaryTranslatorJobAction::BinaryTranslatorJobAction(Action *Input,470                                                     types::ID Type)471    : JobAction(BinaryTranslatorJobClass, Input, Type) {}472 473void ObjcopyJobAction::anchor() {}474 475ObjcopyJobAction::ObjcopyJobAction(Action *Input, types::ID Type)476    : JobAction(ObjcopyJobClass, Input, Type) {}477