1341825Sdim//===- Action.cpp - Abstract compilation steps ----------------------------===// 2193326Sed// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6193326Sed// 7193326Sed//===----------------------------------------------------------------------===// 8193326Sed 9193326Sed#include "clang/Driver/Action.h" 10226633Sdim#include "llvm/Support/ErrorHandling.h" 11193326Sed#include <cassert> 12341825Sdim#include <string> 13341825Sdim 14341825Sdimusing namespace clang; 15341825Sdimusing namespace driver; 16261991Sdimusing namespace llvm::opt; 17193326Sed 18341825SdimAction::~Action() = default; 19193326Sed 20193326Sedconst char *Action::getClassName(ActionClass AC) { 21193326Sed switch (AC) { 22193326Sed case InputClass: return "input"; 23193326Sed case BindArchClass: return "bind-arch"; 24309124Sdim case OffloadClass: 25309124Sdim return "offload"; 26193326Sed case PreprocessJobClass: return "preprocessor"; 27193326Sed case PrecompileJobClass: return "precompiler"; 28344779Sdim case HeaderModulePrecompileJobClass: return "header-module-precompiler"; 29193326Sed case AnalyzeJobClass: return "analyzer"; 30234353Sdim case MigrateJobClass: return "migrator"; 31193326Sed case CompileJobClass: return "compiler"; 32280031Sdim case BackendJobClass: return "backend"; 33193326Sed case AssembleJobClass: return "assembler"; 34360784Sdim case IfsMergeJobClass: return "interface-stub-merger"; 35193326Sed case LinkJobClass: return "linker"; 36193326Sed case LipoJobClass: return "lipo"; 37210299Sed case DsymutilJobClass: return "dsymutil"; 38276479Sdim case VerifyDebugInfoJobClass: return "verify-debug-info"; 39276479Sdim case VerifyPCHJobClass: return "verify-pch"; 40314564Sdim case OffloadBundlingJobClass: 41314564Sdim return "clang-offload-bundler"; 42314564Sdim case OffloadUnbundlingJobClass: 43314564Sdim return "clang-offload-unbundler"; 44360784Sdim case OffloadWrapperJobClass: 45360784Sdim return "clang-offload-wrapper"; 46193326Sed } 47198092Srdivacky 48226633Sdim llvm_unreachable("invalid class"); 49193326Sed} 50193326Sed 51309124Sdimvoid Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch) { 52309124Sdim // Offload action set its own kinds on their dependences. 53309124Sdim if (Kind == OffloadClass) 54309124Sdim return; 55314564Sdim // Unbundling actions use the host kinds. 56314564Sdim if (Kind == OffloadUnbundlingJobClass) 57314564Sdim return; 58309124Sdim 59309124Sdim assert((OffloadingDeviceKind == OKind || OffloadingDeviceKind == OFK_None) && 60309124Sdim "Setting device kind to a different device??"); 61309124Sdim assert(!ActiveOffloadKindMask && "Setting a device kind in a host action??"); 62309124Sdim OffloadingDeviceKind = OKind; 63309124Sdim OffloadingArch = OArch; 64309124Sdim 65309124Sdim for (auto *A : Inputs) 66309124Sdim A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch); 67309124Sdim} 68309124Sdim 69309124Sdimvoid Action::propagateHostOffloadInfo(unsigned OKinds, const char *OArch) { 70309124Sdim // Offload action set its own kinds on their dependences. 71309124Sdim if (Kind == OffloadClass) 72309124Sdim return; 73309124Sdim 74309124Sdim assert(OffloadingDeviceKind == OFK_None && 75309124Sdim "Setting a host kind in a device action."); 76309124Sdim ActiveOffloadKindMask |= OKinds; 77309124Sdim OffloadingArch = OArch; 78309124Sdim 79309124Sdim for (auto *A : Inputs) 80309124Sdim A->propagateHostOffloadInfo(ActiveOffloadKindMask, OArch); 81309124Sdim} 82309124Sdim 83309124Sdimvoid Action::propagateOffloadInfo(const Action *A) { 84309124Sdim if (unsigned HK = A->getOffloadingHostActiveKinds()) 85309124Sdim propagateHostOffloadInfo(HK, A->getOffloadingArch()); 86309124Sdim else 87309124Sdim propagateDeviceOffloadInfo(A->getOffloadingDeviceKind(), 88309124Sdim A->getOffloadingArch()); 89309124Sdim} 90309124Sdim 91309124Sdimstd::string Action::getOffloadingKindPrefix() const { 92309124Sdim switch (OffloadingDeviceKind) { 93309124Sdim case OFK_None: 94309124Sdim break; 95309124Sdim case OFK_Host: 96309124Sdim llvm_unreachable("Host kind is not an offloading device kind."); 97309124Sdim break; 98309124Sdim case OFK_Cuda: 99309124Sdim return "device-cuda"; 100314564Sdim case OFK_OpenMP: 101314564Sdim return "device-openmp"; 102341825Sdim case OFK_HIP: 103341825Sdim return "device-hip"; 104309124Sdim 105309124Sdim // TODO: Add other programming models here. 106309124Sdim } 107309124Sdim 108309124Sdim if (!ActiveOffloadKindMask) 109341825Sdim return {}; 110309124Sdim 111309124Sdim std::string Res("host"); 112341825Sdim assert(!((ActiveOffloadKindMask & OFK_Cuda) && 113341825Sdim (ActiveOffloadKindMask & OFK_HIP)) && 114341825Sdim "Cannot offload CUDA and HIP at the same time"); 115309124Sdim if (ActiveOffloadKindMask & OFK_Cuda) 116309124Sdim Res += "-cuda"; 117341825Sdim if (ActiveOffloadKindMask & OFK_HIP) 118341825Sdim Res += "-hip"; 119314564Sdim if (ActiveOffloadKindMask & OFK_OpenMP) 120314564Sdim Res += "-openmp"; 121309124Sdim 122309124Sdim // TODO: Add other programming models here. 123309124Sdim 124309124Sdim return Res; 125309124Sdim} 126309124Sdim 127314564Sdim/// Return a string that can be used as prefix in order to generate unique files 128314564Sdim/// for each offloading kind. 129309124Sdimstd::string 130314564SdimAction::GetOffloadingFileNamePrefix(OffloadKind Kind, 131341825Sdim StringRef NormalizedTriple, 132314564Sdim bool CreatePrefixForHost) { 133314564Sdim // Don't generate prefix for host actions unless required. 134314564Sdim if (!CreatePrefixForHost && (Kind == OFK_None || Kind == OFK_Host)) 135341825Sdim return {}; 136309124Sdim 137309124Sdim std::string Res("-"); 138314564Sdim Res += GetOffloadKindName(Kind); 139309124Sdim Res += "-"; 140309124Sdim Res += NormalizedTriple; 141309124Sdim return Res; 142309124Sdim} 143309124Sdim 144314564Sdim/// Return a string with the offload kind name. If that is not defined, we 145314564Sdim/// assume 'host'. 146341825SdimStringRef Action::GetOffloadKindName(OffloadKind Kind) { 147314564Sdim switch (Kind) { 148314564Sdim case OFK_None: 149314564Sdim case OFK_Host: 150314564Sdim return "host"; 151314564Sdim case OFK_Cuda: 152314564Sdim return "cuda"; 153314564Sdim case OFK_OpenMP: 154314564Sdim return "openmp"; 155341825Sdim case OFK_HIP: 156341825Sdim return "hip"; 157314564Sdim 158314564Sdim // TODO: Add other programming models here. 159314564Sdim } 160314564Sdim 161314564Sdim llvm_unreachable("invalid offload kind"); 162314564Sdim} 163314564Sdim 164234353Sdimvoid InputAction::anchor() {} 165234353Sdim 166198092SrdivackyInputAction::InputAction(const Arg &_Input, types::ID _Type) 167341825Sdim : Action(InputClass, _Type), Input(_Input) {} 168193326Sed 169234353Sdimvoid BindArchAction::anchor() {} 170234353Sdim 171341825SdimBindArchAction::BindArchAction(Action *Input, StringRef ArchName) 172314564Sdim : Action(BindArchClass, Input), ArchName(ArchName) {} 173193326Sed 174309124Sdimvoid OffloadAction::anchor() {} 175309124Sdim 176309124SdimOffloadAction::OffloadAction(const HostDependence &HDep) 177309124Sdim : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()) { 178309124Sdim OffloadingArch = HDep.getBoundArch(); 179309124Sdim ActiveOffloadKindMask = HDep.getOffloadKinds(); 180309124Sdim HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(), 181309124Sdim HDep.getBoundArch()); 182296417Sdim} 183296417Sdim 184309124SdimOffloadAction::OffloadAction(const DeviceDependences &DDeps, types::ID Ty) 185309124Sdim : Action(OffloadClass, DDeps.getActions(), Ty), 186309124Sdim DevToolChains(DDeps.getToolChains()) { 187309124Sdim auto &OKinds = DDeps.getOffloadKinds(); 188309124Sdim auto &BArchs = DDeps.getBoundArchs(); 189288943Sdim 190309124Sdim // If all inputs agree on the same kind, use it also for this action. 191309124Sdim if (llvm::all_of(OKinds, [&](OffloadKind K) { return K == OKinds.front(); })) 192309124Sdim OffloadingDeviceKind = OKinds.front(); 193309124Sdim 194309124Sdim // If we have a single dependency, inherit the architecture from it. 195309124Sdim if (OKinds.size() == 1) 196309124Sdim OffloadingArch = BArchs.front(); 197309124Sdim 198309124Sdim // Propagate info to the dependencies. 199309124Sdim for (unsigned i = 0, e = getInputs().size(); i != e; ++i) 200309124Sdim getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i]); 201296417Sdim} 202288943Sdim 203309124SdimOffloadAction::OffloadAction(const HostDependence &HDep, 204309124Sdim const DeviceDependences &DDeps) 205309124Sdim : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()), 206309124Sdim DevToolChains(DDeps.getToolChains()) { 207309124Sdim // We use the kinds of the host dependence for this action. 208309124Sdim OffloadingArch = HDep.getBoundArch(); 209309124Sdim ActiveOffloadKindMask = HDep.getOffloadKinds(); 210309124Sdim HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(), 211309124Sdim HDep.getBoundArch()); 212309124Sdim 213309124Sdim // Add device inputs and propagate info to the device actions. Do work only if 214309124Sdim // we have dependencies. 215309124Sdim for (unsigned i = 0, e = DDeps.getActions().size(); i != e; ++i) 216309124Sdim if (auto *A = DDeps.getActions()[i]) { 217309124Sdim getInputs().push_back(A); 218309124Sdim A->propagateDeviceOffloadInfo(DDeps.getOffloadKinds()[i], 219309124Sdim DDeps.getBoundArchs()[i]); 220309124Sdim } 221296417Sdim} 222296417Sdim 223309124Sdimvoid OffloadAction::doOnHostDependence(const OffloadActionWorkTy &Work) const { 224309124Sdim if (!HostTC) 225309124Sdim return; 226309124Sdim assert(!getInputs().empty() && "No dependencies for offload action??"); 227309124Sdim auto *A = getInputs().front(); 228309124Sdim Work(A, HostTC, A->getOffloadingArch()); 229296417Sdim} 230296417Sdim 231309124Sdimvoid OffloadAction::doOnEachDeviceDependence( 232309124Sdim const OffloadActionWorkTy &Work) const { 233309124Sdim auto I = getInputs().begin(); 234309124Sdim auto E = getInputs().end(); 235309124Sdim if (I == E) 236309124Sdim return; 237288943Sdim 238309124Sdim // We expect to have the same number of input dependences and device tool 239309124Sdim // chains, except if we also have a host dependence. In that case we have one 240309124Sdim // more dependence than we have device tool chains. 241309124Sdim assert(getInputs().size() == DevToolChains.size() + (HostTC ? 1 : 0) && 242309124Sdim "Sizes of action dependences and toolchains are not consistent!"); 243288943Sdim 244309124Sdim // Skip host action 245309124Sdim if (HostTC) 246309124Sdim ++I; 247309124Sdim 248309124Sdim auto TI = DevToolChains.begin(); 249309124Sdim for (; I != E; ++I, ++TI) 250309124Sdim Work(*I, *TI, (*I)->getOffloadingArch()); 251309124Sdim} 252309124Sdim 253309124Sdimvoid OffloadAction::doOnEachDependence(const OffloadActionWorkTy &Work) const { 254309124Sdim doOnHostDependence(Work); 255309124Sdim doOnEachDeviceDependence(Work); 256309124Sdim} 257309124Sdim 258309124Sdimvoid OffloadAction::doOnEachDependence(bool IsHostDependence, 259309124Sdim const OffloadActionWorkTy &Work) const { 260309124Sdim if (IsHostDependence) 261309124Sdim doOnHostDependence(Work); 262309124Sdim else 263309124Sdim doOnEachDeviceDependence(Work); 264309124Sdim} 265309124Sdim 266309124Sdimbool OffloadAction::hasHostDependence() const { return HostTC != nullptr; } 267309124Sdim 268309124SdimAction *OffloadAction::getHostDependence() const { 269309124Sdim assert(hasHostDependence() && "Host dependence does not exist!"); 270309124Sdim assert(!getInputs().empty() && "No dependencies for offload action??"); 271309124Sdim return HostTC ? getInputs().front() : nullptr; 272309124Sdim} 273309124Sdim 274309124Sdimbool OffloadAction::hasSingleDeviceDependence( 275309124Sdim bool DoNotConsiderHostActions) const { 276309124Sdim if (DoNotConsiderHostActions) 277309124Sdim return getInputs().size() == (HostTC ? 2 : 1); 278309124Sdim return !HostTC && getInputs().size() == 1; 279309124Sdim} 280309124Sdim 281309124SdimAction * 282309124SdimOffloadAction::getSingleDeviceDependence(bool DoNotConsiderHostActions) const { 283309124Sdim assert(hasSingleDeviceDependence(DoNotConsiderHostActions) && 284309124Sdim "Single device dependence does not exist!"); 285309124Sdim // The previous assert ensures the number of entries in getInputs() is 286309124Sdim // consistent with what we are doing here. 287309124Sdim return HostTC ? getInputs()[1] : getInputs().front(); 288309124Sdim} 289309124Sdim 290309124Sdimvoid OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC, 291309124Sdim const char *BoundArch, 292309124Sdim OffloadKind OKind) { 293309124Sdim DeviceActions.push_back(&A); 294309124Sdim DeviceToolChains.push_back(&TC); 295309124Sdim DeviceBoundArchs.push_back(BoundArch); 296309124Sdim DeviceOffloadKinds.push_back(OKind); 297309124Sdim} 298309124Sdim 299309124SdimOffloadAction::HostDependence::HostDependence(Action &A, const ToolChain &TC, 300309124Sdim const char *BoundArch, 301309124Sdim const DeviceDependences &DDeps) 302309124Sdim : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch) { 303309124Sdim for (auto K : DDeps.getOffloadKinds()) 304309124Sdim HostOffloadKinds |= K; 305309124Sdim} 306309124Sdim 307234353Sdimvoid JobAction::anchor() {} 308234353Sdim 309296417SdimJobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type) 310296417Sdim : Action(Kind, Input, Type) {} 311193326Sed 312198092SrdivackyJobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type) 313341825Sdim : Action(Kind, Inputs, Type) {} 314193326Sed 315234353Sdimvoid PreprocessJobAction::anchor() {} 316234353Sdim 317296417SdimPreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType) 318296417Sdim : JobAction(PreprocessJobClass, Input, OutputType) {} 319193326Sed 320234353Sdimvoid PrecompileJobAction::anchor() {} 321234353Sdim 322296417SdimPrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType) 323296417Sdim : JobAction(PrecompileJobClass, Input, OutputType) {} 324193326Sed 325344779SdimPrecompileJobAction::PrecompileJobAction(ActionClass Kind, Action *Input, 326344779Sdim types::ID OutputType) 327344779Sdim : JobAction(Kind, Input, OutputType) { 328344779Sdim assert(isa<PrecompileJobAction>((Action*)this) && "invalid action kind"); 329344779Sdim} 330344779Sdim 331344779Sdimvoid HeaderModulePrecompileJobAction::anchor() {} 332344779Sdim 333344779SdimHeaderModulePrecompileJobAction::HeaderModulePrecompileJobAction( 334344779Sdim Action *Input, types::ID OutputType, const char *ModuleName) 335344779Sdim : PrecompileJobAction(HeaderModulePrecompileJobClass, Input, OutputType), 336344779Sdim ModuleName(ModuleName) {} 337344779Sdim 338234353Sdimvoid AnalyzeJobAction::anchor() {} 339234353Sdim 340296417SdimAnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType) 341296417Sdim : JobAction(AnalyzeJobClass, Input, OutputType) {} 342193326Sed 343234353Sdimvoid MigrateJobAction::anchor() {} 344234353Sdim 345296417SdimMigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType) 346296417Sdim : JobAction(MigrateJobClass, Input, OutputType) {} 347234353Sdim 348234353Sdimvoid CompileJobAction::anchor() {} 349234353Sdim 350296417SdimCompileJobAction::CompileJobAction(Action *Input, types::ID OutputType) 351296417Sdim : JobAction(CompileJobClass, Input, OutputType) {} 352193326Sed 353280031Sdimvoid BackendJobAction::anchor() {} 354280031Sdim 355296417SdimBackendJobAction::BackendJobAction(Action *Input, types::ID OutputType) 356296417Sdim : JobAction(BackendJobClass, Input, OutputType) {} 357280031Sdim 358234353Sdimvoid AssembleJobAction::anchor() {} 359234353Sdim 360296417SdimAssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType) 361296417Sdim : JobAction(AssembleJobClass, Input, OutputType) {} 362193326Sed 363360784Sdimvoid IfsMergeJobAction::anchor() {} 364360784Sdim 365360784SdimIfsMergeJobAction::IfsMergeJobAction(ActionList &Inputs, types::ID Type) 366360784Sdim : JobAction(IfsMergeJobClass, Inputs, Type) {} 367360784Sdim 368234353Sdimvoid LinkJobAction::anchor() {} 369234353Sdim 370198092SrdivackyLinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type) 371341825Sdim : JobAction(LinkJobClass, Inputs, Type) {} 372193326Sed 373234353Sdimvoid LipoJobAction::anchor() {} 374234353Sdim 375198092SrdivackyLipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type) 376341825Sdim : JobAction(LipoJobClass, Inputs, Type) {} 377210299Sed 378234353Sdimvoid DsymutilJobAction::anchor() {} 379234353Sdim 380210299SedDsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type) 381341825Sdim : JobAction(DsymutilJobClass, Inputs, Type) {} 382226633Sdim 383234353Sdimvoid VerifyJobAction::anchor() {} 384234353Sdim 385296417SdimVerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input, 386296417Sdim types::ID Type) 387296417Sdim : JobAction(Kind, Input, Type) { 388276479Sdim assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) && 389276479Sdim "ActionClass is not a valid VerifyJobAction"); 390226633Sdim} 391276479Sdim 392276479Sdimvoid VerifyDebugInfoJobAction::anchor() {} 393276479Sdim 394296417SdimVerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input, 395296417Sdim types::ID Type) 396296417Sdim : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {} 397276479Sdim 398276479Sdimvoid VerifyPCHJobAction::anchor() {} 399276479Sdim 400296417SdimVerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type) 401296417Sdim : VerifyJobAction(VerifyPCHJobClass, Input, Type) {} 402314564Sdim 403314564Sdimvoid OffloadBundlingJobAction::anchor() {} 404314564Sdim 405314564SdimOffloadBundlingJobAction::OffloadBundlingJobAction(ActionList &Inputs) 406344779Sdim : JobAction(OffloadBundlingJobClass, Inputs, Inputs.back()->getType()) {} 407314564Sdim 408314564Sdimvoid OffloadUnbundlingJobAction::anchor() {} 409314564Sdim 410314564SdimOffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action *Input) 411314564Sdim : JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {} 412360784Sdim 413360784Sdimvoid OffloadWrapperJobAction::anchor() {} 414360784Sdim 415360784SdimOffloadWrapperJobAction::OffloadWrapperJobAction(ActionList &Inputs, 416360784Sdim types::ID Type) 417360784Sdim : JobAction(OffloadWrapperJobClass, Inputs, Type) {} 418