Path: blob/main/contrib/llvm-project/clang/lib/Driver/Action.cpp
35233 views
//===- Action.cpp - Abstract compilation steps ----------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "clang/Driver/Action.h"9#include "llvm/Support/ErrorHandling.h"10#include <cassert>11#include <string>1213using namespace clang;14using namespace driver;15using namespace llvm::opt;1617Action::~Action() = default;1819const char *Action::getClassName(ActionClass AC) {20switch (AC) {21case InputClass: return "input";22case BindArchClass: return "bind-arch";23case OffloadClass:24return "offload";25case PreprocessJobClass: return "preprocessor";26case PrecompileJobClass: return "precompiler";27case ExtractAPIJobClass:28return "api-extractor";29case AnalyzeJobClass: return "analyzer";30case MigrateJobClass: return "migrator";31case CompileJobClass: return "compiler";32case BackendJobClass: return "backend";33case AssembleJobClass: return "assembler";34case IfsMergeJobClass: return "interface-stub-merger";35case LinkJobClass: return "linker";36case LipoJobClass: return "lipo";37case DsymutilJobClass: return "dsymutil";38case VerifyDebugInfoJobClass: return "verify-debug-info";39case VerifyPCHJobClass: return "verify-pch";40case OffloadBundlingJobClass:41return "clang-offload-bundler";42case OffloadUnbundlingJobClass:43return "clang-offload-unbundler";44case OffloadPackagerJobClass:45return "clang-offload-packager";46case LinkerWrapperJobClass:47return "clang-linker-wrapper";48case StaticLibJobClass:49return "static-lib-linker";50case BinaryAnalyzeJobClass:51return "binary-analyzer";52}5354llvm_unreachable("invalid class");55}5657void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch,58const ToolChain *OToolChain) {59// Offload action set its own kinds on their dependences.60if (Kind == OffloadClass)61return;62// Unbundling actions use the host kinds.63if (Kind == OffloadUnbundlingJobClass)64return;6566assert((OffloadingDeviceKind == OKind || OffloadingDeviceKind == OFK_None) &&67"Setting device kind to a different device??");68assert(!ActiveOffloadKindMask && "Setting a device kind in a host action??");69OffloadingDeviceKind = OKind;70OffloadingArch = OArch;71OffloadingToolChain = OToolChain;7273for (auto *A : Inputs)74A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch, OToolChain);75}7677void Action::propagateHostOffloadInfo(unsigned OKinds, const char *OArch) {78// Offload action set its own kinds on their dependences.79if (Kind == OffloadClass)80return;8182assert(OffloadingDeviceKind == OFK_None &&83"Setting a host kind in a device action.");84ActiveOffloadKindMask |= OKinds;85OffloadingArch = OArch;8687for (auto *A : Inputs)88A->propagateHostOffloadInfo(ActiveOffloadKindMask, OArch);89}9091void Action::propagateOffloadInfo(const Action *A) {92if (unsigned HK = A->getOffloadingHostActiveKinds())93propagateHostOffloadInfo(HK, A->getOffloadingArch());94else95propagateDeviceOffloadInfo(A->getOffloadingDeviceKind(),96A->getOffloadingArch(),97A->getOffloadingToolChain());98}99100std::string Action::getOffloadingKindPrefix() const {101switch (OffloadingDeviceKind) {102case OFK_None:103break;104case OFK_Host:105llvm_unreachable("Host kind is not an offloading device kind.");106break;107case OFK_Cuda:108return "device-cuda";109case OFK_OpenMP:110return "device-openmp";111case OFK_HIP:112return "device-hip";113114// TODO: Add other programming models here.115}116117if (!ActiveOffloadKindMask)118return {};119120std::string Res("host");121assert(!((ActiveOffloadKindMask & OFK_Cuda) &&122(ActiveOffloadKindMask & OFK_HIP)) &&123"Cannot offload CUDA and HIP at the same time");124if (ActiveOffloadKindMask & OFK_Cuda)125Res += "-cuda";126if (ActiveOffloadKindMask & OFK_HIP)127Res += "-hip";128if (ActiveOffloadKindMask & OFK_OpenMP)129Res += "-openmp";130131// TODO: Add other programming models here.132133return Res;134}135136/// Return a string that can be used as prefix in order to generate unique files137/// for each offloading kind.138std::string139Action::GetOffloadingFileNamePrefix(OffloadKind Kind,140StringRef NormalizedTriple,141bool CreatePrefixForHost) {142// Don't generate prefix for host actions unless required.143if (!CreatePrefixForHost && (Kind == OFK_None || Kind == OFK_Host))144return {};145146std::string Res("-");147Res += GetOffloadKindName(Kind);148Res += "-";149Res += NormalizedTriple;150return Res;151}152153/// Return a string with the offload kind name. If that is not defined, we154/// assume 'host'.155StringRef Action::GetOffloadKindName(OffloadKind Kind) {156switch (Kind) {157case OFK_None:158case OFK_Host:159return "host";160case OFK_Cuda:161return "cuda";162case OFK_OpenMP:163return "openmp";164case OFK_HIP:165return "hip";166167// TODO: Add other programming models here.168}169170llvm_unreachable("invalid offload kind");171}172173void InputAction::anchor() {}174175InputAction::InputAction(const Arg &_Input, types::ID _Type, StringRef _Id)176: Action(InputClass, _Type), Input(_Input), Id(_Id.str()) {}177178void BindArchAction::anchor() {}179180BindArchAction::BindArchAction(Action *Input, StringRef ArchName)181: Action(BindArchClass, Input), ArchName(ArchName) {}182183void OffloadAction::anchor() {}184185OffloadAction::OffloadAction(const HostDependence &HDep)186: Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()) {187OffloadingArch = HDep.getBoundArch();188ActiveOffloadKindMask = HDep.getOffloadKinds();189HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),190HDep.getBoundArch());191}192193OffloadAction::OffloadAction(const DeviceDependences &DDeps, types::ID Ty)194: Action(OffloadClass, DDeps.getActions(), Ty),195DevToolChains(DDeps.getToolChains()) {196auto &OKinds = DDeps.getOffloadKinds();197auto &BArchs = DDeps.getBoundArchs();198auto &OTCs = DDeps.getToolChains();199200// If all inputs agree on the same kind, use it also for this action.201if (llvm::all_equal(OKinds))202OffloadingDeviceKind = OKinds.front();203204// If we have a single dependency, inherit the architecture from it.205if (OKinds.size() == 1)206OffloadingArch = BArchs.front();207208// Propagate info to the dependencies.209for (unsigned i = 0, e = getInputs().size(); i != e; ++i)210getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i], OTCs[i]);211}212213OffloadAction::OffloadAction(const HostDependence &HDep,214const DeviceDependences &DDeps)215: Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()),216DevToolChains(DDeps.getToolChains()) {217// We use the kinds of the host dependence for this action.218OffloadingArch = HDep.getBoundArch();219ActiveOffloadKindMask = HDep.getOffloadKinds();220HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),221HDep.getBoundArch());222223// Add device inputs and propagate info to the device actions. Do work only if224// we have dependencies.225for (unsigned i = 0, e = DDeps.getActions().size(); i != e; ++i) {226if (auto *A = DDeps.getActions()[i]) {227getInputs().push_back(A);228A->propagateDeviceOffloadInfo(DDeps.getOffloadKinds()[i],229DDeps.getBoundArchs()[i],230DDeps.getToolChains()[i]);231// If this action is used to forward single dependency, set the toolchain.232if (DDeps.getActions().size() == 1)233OffloadingToolChain = DDeps.getToolChains()[i];234}235}236}237238void OffloadAction::doOnHostDependence(const OffloadActionWorkTy &Work) const {239if (!HostTC)240return;241assert(!getInputs().empty() && "No dependencies for offload action??");242auto *A = getInputs().front();243Work(A, HostTC, A->getOffloadingArch());244}245246void OffloadAction::doOnEachDeviceDependence(247const OffloadActionWorkTy &Work) const {248auto I = getInputs().begin();249auto E = getInputs().end();250if (I == E)251return;252253// We expect to have the same number of input dependences and device tool254// chains, except if we also have a host dependence. In that case we have one255// more dependence than we have device tool chains.256assert(getInputs().size() == DevToolChains.size() + (HostTC ? 1 : 0) &&257"Sizes of action dependences and toolchains are not consistent!");258259// Skip host action260if (HostTC)261++I;262263auto TI = DevToolChains.begin();264for (; I != E; ++I, ++TI)265Work(*I, *TI, (*I)->getOffloadingArch());266}267268void OffloadAction::doOnEachDependence(const OffloadActionWorkTy &Work) const {269doOnHostDependence(Work);270doOnEachDeviceDependence(Work);271}272273void OffloadAction::doOnEachDependence(bool IsHostDependence,274const OffloadActionWorkTy &Work) const {275if (IsHostDependence)276doOnHostDependence(Work);277else278doOnEachDeviceDependence(Work);279}280281bool OffloadAction::hasHostDependence() const { return HostTC != nullptr; }282283Action *OffloadAction::getHostDependence() const {284assert(hasHostDependence() && "Host dependence does not exist!");285assert(!getInputs().empty() && "No dependencies for offload action??");286return HostTC ? getInputs().front() : nullptr;287}288289bool OffloadAction::hasSingleDeviceDependence(290bool DoNotConsiderHostActions) const {291if (DoNotConsiderHostActions)292return getInputs().size() == (HostTC ? 2 : 1);293return !HostTC && getInputs().size() == 1;294}295296Action *297OffloadAction::getSingleDeviceDependence(bool DoNotConsiderHostActions) const {298assert(hasSingleDeviceDependence(DoNotConsiderHostActions) &&299"Single device dependence does not exist!");300// The previous assert ensures the number of entries in getInputs() is301// consistent with what we are doing here.302return HostTC ? getInputs()[1] : getInputs().front();303}304305void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,306const char *BoundArch,307OffloadKind OKind) {308DeviceActions.push_back(&A);309DeviceToolChains.push_back(&TC);310DeviceBoundArchs.push_back(BoundArch);311DeviceOffloadKinds.push_back(OKind);312}313314void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,315const char *BoundArch,316unsigned OffloadKindMask) {317DeviceActions.push_back(&A);318DeviceToolChains.push_back(&TC);319DeviceBoundArchs.push_back(BoundArch);320321// Add each active offloading kind from a mask.322for (OffloadKind OKind : {OFK_OpenMP, OFK_Cuda, OFK_HIP})323if (OKind & OffloadKindMask)324DeviceOffloadKinds.push_back(OKind);325}326327OffloadAction::HostDependence::HostDependence(Action &A, const ToolChain &TC,328const char *BoundArch,329const DeviceDependences &DDeps)330: HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch) {331for (auto K : DDeps.getOffloadKinds())332HostOffloadKinds |= K;333}334335void JobAction::anchor() {}336337JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)338: Action(Kind, Input, Type) {}339340JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)341: Action(Kind, Inputs, Type) {}342343void PreprocessJobAction::anchor() {}344345PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType)346: JobAction(PreprocessJobClass, Input, OutputType) {}347348void PrecompileJobAction::anchor() {}349350PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)351: JobAction(PrecompileJobClass, Input, OutputType) {}352353PrecompileJobAction::PrecompileJobAction(ActionClass Kind, Action *Input,354types::ID OutputType)355: JobAction(Kind, Input, OutputType) {356assert(isa<PrecompileJobAction>((Action*)this) && "invalid action kind");357}358359void ExtractAPIJobAction::anchor() {}360361ExtractAPIJobAction::ExtractAPIJobAction(Action *Inputs, types::ID OutputType)362: JobAction(ExtractAPIJobClass, Inputs, OutputType) {}363364void AnalyzeJobAction::anchor() {}365366AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)367: JobAction(AnalyzeJobClass, Input, OutputType) {}368369void MigrateJobAction::anchor() {}370371MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType)372: JobAction(MigrateJobClass, Input, OutputType) {}373374void CompileJobAction::anchor() {}375376CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)377: JobAction(CompileJobClass, Input, OutputType) {}378379void BackendJobAction::anchor() {}380381BackendJobAction::BackendJobAction(Action *Input, types::ID OutputType)382: JobAction(BackendJobClass, Input, OutputType) {}383384void AssembleJobAction::anchor() {}385386AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)387: JobAction(AssembleJobClass, Input, OutputType) {}388389void IfsMergeJobAction::anchor() {}390391IfsMergeJobAction::IfsMergeJobAction(ActionList &Inputs, types::ID Type)392: JobAction(IfsMergeJobClass, Inputs, Type) {}393394void LinkJobAction::anchor() {}395396LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)397: JobAction(LinkJobClass, Inputs, Type) {}398399void LipoJobAction::anchor() {}400401LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type)402: JobAction(LipoJobClass, Inputs, Type) {}403404void DsymutilJobAction::anchor() {}405406DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type)407: JobAction(DsymutilJobClass, Inputs, Type) {}408409void VerifyJobAction::anchor() {}410411VerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input,412types::ID Type)413: JobAction(Kind, Input, Type) {414assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&415"ActionClass is not a valid VerifyJobAction");416}417418void VerifyDebugInfoJobAction::anchor() {}419420VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input,421types::ID Type)422: VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {}423424void VerifyPCHJobAction::anchor() {}425426VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type)427: VerifyJobAction(VerifyPCHJobClass, Input, Type) {}428429void OffloadBundlingJobAction::anchor() {}430431OffloadBundlingJobAction::OffloadBundlingJobAction(ActionList &Inputs)432: JobAction(OffloadBundlingJobClass, Inputs, Inputs.back()->getType()) {}433434void OffloadUnbundlingJobAction::anchor() {}435436OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action *Input)437: JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {}438439void OffloadPackagerJobAction::anchor() {}440441OffloadPackagerJobAction::OffloadPackagerJobAction(ActionList &Inputs,442types::ID Type)443: JobAction(OffloadPackagerJobClass, Inputs, Type) {}444445void LinkerWrapperJobAction::anchor() {}446447LinkerWrapperJobAction::LinkerWrapperJobAction(ActionList &Inputs,448types::ID Type)449: JobAction(LinkerWrapperJobClass, Inputs, Type) {}450451void StaticLibJobAction::anchor() {}452453StaticLibJobAction::StaticLibJobAction(ActionList &Inputs, types::ID Type)454: JobAction(StaticLibJobClass, Inputs, Type) {}455456void BinaryAnalyzeJobAction::anchor() {}457458BinaryAnalyzeJobAction::BinaryAnalyzeJobAction(Action *Input, types::ID Type)459: JobAction(BinaryAnalyzeJobClass, Input, Type) {}460461462