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