//===- Action.cpp - Abstract compilation steps ----------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "clang/Driver/Action.h"
#include "llvm/Support/ErrorHandling.h"
#include <cassert>
#include <string>

using namespace clang;
using namespace driver;
using namespace llvm::opt;

Action::~Action() = default;

const char *Action::getClassName(ActionClass AC) {
  switch (AC) {
  case InputClass: return "input";
  case BindArchClass: return "bind-arch";
  case OffloadClass:
    return "offload";
  case PreprocessJobClass: return "preprocessor";
  case PrecompileJobClass: return "precompiler";
  case ExtractAPIJobClass:
    return "api-extractor";
  case AnalyzeJobClass:
    return "analyzer";
  case CompileJobClass: return "compiler";
  case BackendJobClass: return "backend";
  case AssembleJobClass: return "assembler";
  case IfsMergeJobClass: return "interface-stub-merger";
  case LinkJobClass: return "linker";
  case LipoJobClass: return "lipo";
  case DsymutilJobClass: return "dsymutil";
  case VerifyDebugInfoJobClass: return "verify-debug-info";
  case VerifyPCHJobClass: return "verify-pch";
  case OffloadBundlingJobClass:
    return "clang-offload-bundler";
  case OffloadUnbundlingJobClass:
    return "clang-offload-unbundler";
  case OffloadPackagerJobClass:
    return "clang-offload-packager";
  case LinkerWrapperJobClass:
    return "clang-linker-wrapper";
  case StaticLibJobClass:
    return "static-lib-linker";
  case BinaryAnalyzeJobClass:
    return "binary-analyzer";
  case BinaryTranslatorJobClass:
    return "binary-translator";
  }

  llvm_unreachable("invalid class");
}

void Action::propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch,
                                        const ToolChain *OToolChain) {
  // Offload action set its own kinds on their dependences.
  if (Kind == OffloadClass)
    return;
  // Unbundling actions use the host kinds.
  if (Kind == OffloadUnbundlingJobClass)
    return;

  assert((OffloadingDeviceKind == OKind || OffloadingDeviceKind == OFK_None) &&
         "Setting device kind to a different device??");
  assert(!ActiveOffloadKindMask && "Setting a device kind in a host action??");
  OffloadingDeviceKind = OKind;
  OffloadingArch = OArch;
  OffloadingToolChain = OToolChain;

  for (auto *A : Inputs)
    A->propagateDeviceOffloadInfo(OffloadingDeviceKind, OArch, OToolChain);
}

void Action::propagateHostOffloadInfo(unsigned OKinds, const char *OArch) {
  // Offload action set its own kinds on their dependences.
  if (Kind == OffloadClass)
    return;

  assert(OffloadingDeviceKind == OFK_None &&
         "Setting a host kind in a device action.");
  ActiveOffloadKindMask |= OKinds;
  OffloadingArch = OArch;

  for (auto *A : Inputs)
    A->propagateHostOffloadInfo(ActiveOffloadKindMask, OArch);
}

void Action::propagateOffloadInfo(const Action *A) {
  if (unsigned HK = A->getOffloadingHostActiveKinds())
    propagateHostOffloadInfo(HK, A->getOffloadingArch());
  else
    propagateDeviceOffloadInfo(A->getOffloadingDeviceKind(),
                               A->getOffloadingArch(),
                               A->getOffloadingToolChain());
}

std::string Action::getOffloadingKindPrefix() const {
  switch (OffloadingDeviceKind) {
  case OFK_None:
    break;
  case OFK_Host:
    llvm_unreachable("Host kind is not an offloading device kind.");
    break;
  case OFK_Cuda:
    return "device-cuda";
  case OFK_OpenMP:
    return "device-openmp";
  case OFK_HIP:
    return "device-hip";
  case OFK_SYCL:
    return "device-sycl";

    // TODO: Add other programming models here.
  }

  if (!ActiveOffloadKindMask)
    return {};

  std::string Res("host");
  assert(!((ActiveOffloadKindMask & OFK_Cuda) &&
           (ActiveOffloadKindMask & OFK_HIP)) &&
         "Cannot offload CUDA and HIP at the same time");
  if (ActiveOffloadKindMask & OFK_Cuda)
    Res += "-cuda";
  if (ActiveOffloadKindMask & OFK_HIP)
    Res += "-hip";
  if (ActiveOffloadKindMask & OFK_OpenMP)
    Res += "-openmp";
  if (ActiveOffloadKindMask & OFK_SYCL)
    Res += "-sycl";

  // TODO: Add other programming models here.

  return Res;
}

/// Return a string that can be used as prefix in order to generate unique files
/// for each offloading kind.
std::string
Action::GetOffloadingFileNamePrefix(OffloadKind Kind,
                                    StringRef NormalizedTriple,
                                    bool CreatePrefixForHost) {
  // Don't generate prefix for host actions unless required.
  if (!CreatePrefixForHost && (Kind == OFK_None || Kind == OFK_Host))
    return {};

  std::string Res("-");
  Res += GetOffloadKindName(Kind);
  Res += "-";
  Res += NormalizedTriple;
  return Res;
}

/// Return a string with the offload kind name. If that is not defined, we
/// assume 'host'.
StringRef Action::GetOffloadKindName(OffloadKind Kind) {
  switch (Kind) {
  case OFK_None:
  case OFK_Host:
    return "host";
  case OFK_Cuda:
    return "cuda";
  case OFK_OpenMP:
    return "openmp";
  case OFK_HIP:
    return "hip";
  case OFK_SYCL:
    return "sycl";

    // TODO: Add other programming models here.
  }

  llvm_unreachable("invalid offload kind");
}

void InputAction::anchor() {}

InputAction::InputAction(const Arg &_Input, types::ID _Type, StringRef _Id)
    : Action(InputClass, _Type), Input(_Input), Id(_Id.str()) {}

void BindArchAction::anchor() {}

BindArchAction::BindArchAction(Action *Input, StringRef ArchName)
    : Action(BindArchClass, Input), ArchName(ArchName) {}

void OffloadAction::anchor() {}

OffloadAction::OffloadAction(const HostDependence &HDep)
    : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()) {
  OffloadingArch = HDep.getBoundArch();
  ActiveOffloadKindMask = HDep.getOffloadKinds();
  HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
                                             HDep.getBoundArch());
}

OffloadAction::OffloadAction(const DeviceDependences &DDeps, types::ID Ty)
    : Action(OffloadClass, DDeps.getActions(), Ty),
      DevToolChains(DDeps.getToolChains()) {
  auto &OKinds = DDeps.getOffloadKinds();
  auto &BArchs = DDeps.getBoundArchs();
  auto &OTCs = DDeps.getToolChains();

  // If all inputs agree on the same kind, use it also for this action.
  if (llvm::all_equal(OKinds))
    OffloadingDeviceKind = OKinds.front();

  // If we have a single dependency, inherit the architecture from it.
  if (OKinds.size() == 1)
    OffloadingArch = BArchs.front();

  // Propagate info to the dependencies.
  for (unsigned i = 0, e = getInputs().size(); i != e; ++i)
    getInputs()[i]->propagateDeviceOffloadInfo(OKinds[i], BArchs[i], OTCs[i]);
}

OffloadAction::OffloadAction(const HostDependence &HDep,
                             const DeviceDependences &DDeps)
    : Action(OffloadClass, HDep.getAction()), HostTC(HDep.getToolChain()),
      DevToolChains(DDeps.getToolChains()) {
  // We use the kinds of the host dependence for this action.
  OffloadingArch = HDep.getBoundArch();
  ActiveOffloadKindMask = HDep.getOffloadKinds();
  HDep.getAction()->propagateHostOffloadInfo(HDep.getOffloadKinds(),
                                             HDep.getBoundArch());

  // Add device inputs and propagate info to the device actions. Do work only if
  // we have dependencies.
  for (unsigned i = 0, e = DDeps.getActions().size(); i != e; ++i) {
    if (auto *A = DDeps.getActions()[i]) {
      getInputs().push_back(A);
      A->propagateDeviceOffloadInfo(DDeps.getOffloadKinds()[i],
                                    DDeps.getBoundArchs()[i],
                                    DDeps.getToolChains()[i]);
      // If this action is used to forward single dependency, set the toolchain.
      if (DDeps.getActions().size() == 1)
        OffloadingToolChain = DDeps.getToolChains()[i];
    }
  }
}

void OffloadAction::doOnHostDependence(const OffloadActionWorkTy &Work) const {
  if (!HostTC)
    return;
  assert(!getInputs().empty() && "No dependencies for offload action??");
  auto *A = getInputs().front();
  Work(A, HostTC, A->getOffloadingArch());
}

void OffloadAction::doOnEachDeviceDependence(
    const OffloadActionWorkTy &Work) const {
  auto I = getInputs().begin();
  auto E = getInputs().end();
  if (I == E)
    return;

  // We expect to have the same number of input dependences and device tool
  // chains, except if we also have a host dependence. In that case we have one
  // more dependence than we have device tool chains.
  assert(getInputs().size() == DevToolChains.size() + (HostTC ? 1 : 0) &&
         "Sizes of action dependences and toolchains are not consistent!");

  // Skip host action
  if (HostTC)
    ++I;

  auto TI = DevToolChains.begin();
  for (; I != E; ++I, ++TI)
    Work(*I, *TI, (*I)->getOffloadingArch());
}

void OffloadAction::doOnEachDependence(const OffloadActionWorkTy &Work) const {
  doOnHostDependence(Work);
  doOnEachDeviceDependence(Work);
}

void OffloadAction::doOnEachDependence(bool IsHostDependence,
                                       const OffloadActionWorkTy &Work) const {
  if (IsHostDependence)
    doOnHostDependence(Work);
  else
    doOnEachDeviceDependence(Work);
}

bool OffloadAction::hasHostDependence() const { return HostTC != nullptr; }

Action *OffloadAction::getHostDependence() const {
  assert(hasHostDependence() && "Host dependence does not exist!");
  assert(!getInputs().empty() && "No dependencies for offload action??");
  return HostTC ? getInputs().front() : nullptr;
}

bool OffloadAction::hasSingleDeviceDependence(
    bool DoNotConsiderHostActions) const {
  if (DoNotConsiderHostActions)
    return getInputs().size() == (HostTC ? 2 : 1);
  return !HostTC && getInputs().size() == 1;
}

Action *
OffloadAction::getSingleDeviceDependence(bool DoNotConsiderHostActions) const {
  assert(hasSingleDeviceDependence(DoNotConsiderHostActions) &&
         "Single device dependence does not exist!");
  // The previous assert ensures the number of entries in getInputs() is
  // consistent with what we are doing here.
  return HostTC ? getInputs()[1] : getInputs().front();
}

void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,
                                           const char *BoundArch,
                                           OffloadKind OKind) {
  DeviceActions.push_back(&A);
  DeviceToolChains.push_back(&TC);
  DeviceBoundArchs.push_back(BoundArch);
  DeviceOffloadKinds.push_back(OKind);
}

void OffloadAction::DeviceDependences::add(Action &A, const ToolChain &TC,
                                           const char *BoundArch,
                                           unsigned OffloadKindMask) {
  DeviceActions.push_back(&A);
  DeviceToolChains.push_back(&TC);
  DeviceBoundArchs.push_back(BoundArch);

  // Add each active offloading kind from a mask.
  for (OffloadKind OKind : {OFK_OpenMP, OFK_Cuda, OFK_HIP, OFK_SYCL})
    if (OKind & OffloadKindMask)
      DeviceOffloadKinds.push_back(OKind);
}

OffloadAction::HostDependence::HostDependence(Action &A, const ToolChain &TC,
                                              const char *BoundArch,
                                              const DeviceDependences &DDeps)
    : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch) {
  for (auto K : DDeps.getOffloadKinds())
    HostOffloadKinds |= K;
}

void JobAction::anchor() {}

JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type)
    : Action(Kind, Input, Type) {}

JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type)
    : Action(Kind, Inputs, Type) {}

void PreprocessJobAction::anchor() {}

PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType)
    : JobAction(PreprocessJobClass, Input, OutputType) {}

void PrecompileJobAction::anchor() {}

PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType)
    : JobAction(PrecompileJobClass, Input, OutputType) {}

PrecompileJobAction::PrecompileJobAction(ActionClass Kind, Action *Input,
                                         types::ID OutputType)
    : JobAction(Kind, Input, OutputType) {
  assert(isa<PrecompileJobAction>((Action*)this) && "invalid action kind");
}

void ExtractAPIJobAction::anchor() {}

ExtractAPIJobAction::ExtractAPIJobAction(Action *Inputs, types::ID OutputType)
    : JobAction(ExtractAPIJobClass, Inputs, OutputType) {}

void AnalyzeJobAction::anchor() {}

AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType)
    : JobAction(AnalyzeJobClass, Input, OutputType) {}

void CompileJobAction::anchor() {}

CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType)
    : JobAction(CompileJobClass, Input, OutputType) {}

void BackendJobAction::anchor() {}

BackendJobAction::BackendJobAction(Action *Input, types::ID OutputType)
    : JobAction(BackendJobClass, Input, OutputType) {}

void AssembleJobAction::anchor() {}

AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType)
    : JobAction(AssembleJobClass, Input, OutputType) {}

void IfsMergeJobAction::anchor() {}

IfsMergeJobAction::IfsMergeJobAction(ActionList &Inputs, types::ID Type)
    : JobAction(IfsMergeJobClass, Inputs, Type) {}

void LinkJobAction::anchor() {}

LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type)
    : JobAction(LinkJobClass, Inputs, Type) {}

void LipoJobAction::anchor() {}

LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type)
    : JobAction(LipoJobClass, Inputs, Type) {}

void DsymutilJobAction::anchor() {}

DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type)
    : JobAction(DsymutilJobClass, Inputs, Type) {}

void VerifyJobAction::anchor() {}

VerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input,
                                 types::ID Type)
    : JobAction(Kind, Input, Type) {
  assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&
         "ActionClass is not a valid VerifyJobAction");
}

void VerifyDebugInfoJobAction::anchor() {}

VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input,
                                                   types::ID Type)
    : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {}

void VerifyPCHJobAction::anchor() {}

VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type)
    : VerifyJobAction(VerifyPCHJobClass, Input, Type) {}

void OffloadBundlingJobAction::anchor() {}

OffloadBundlingJobAction::OffloadBundlingJobAction(ActionList &Inputs)
    : JobAction(OffloadBundlingJobClass, Inputs, Inputs.back()->getType()) {}

void OffloadUnbundlingJobAction::anchor() {}

OffloadUnbundlingJobAction::OffloadUnbundlingJobAction(Action *Input)
    : JobAction(OffloadUnbundlingJobClass, Input, Input->getType()) {}

void OffloadPackagerJobAction::anchor() {}

OffloadPackagerJobAction::OffloadPackagerJobAction(ActionList &Inputs,
                                                   types::ID Type)
    : JobAction(OffloadPackagerJobClass, Inputs, Type) {}

void LinkerWrapperJobAction::anchor() {}

LinkerWrapperJobAction::LinkerWrapperJobAction(ActionList &Inputs,
                                               types::ID Type)
    : JobAction(LinkerWrapperJobClass, Inputs, Type) {}

void StaticLibJobAction::anchor() {}

StaticLibJobAction::StaticLibJobAction(ActionList &Inputs, types::ID Type)
    : JobAction(StaticLibJobClass, Inputs, Type) {}

void BinaryAnalyzeJobAction::anchor() {}

BinaryAnalyzeJobAction::BinaryAnalyzeJobAction(Action *Input, types::ID Type)
    : JobAction(BinaryAnalyzeJobClass, Input, Type) {}

void BinaryTranslatorJobAction::anchor() {}

BinaryTranslatorJobAction::BinaryTranslatorJobAction(Action *Input,
                                                     types::ID Type)
    : JobAction(BinaryTranslatorJobClass, Input, Type) {}
