//===- DXILPostOptimizationValidation.cpp - Opt DXIL validation ----------===//
//
// 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 "DXILPostOptimizationValidation.h"
#include "DXILRootSignature.h"
#include "DXILShaderFlags.h"
#include "DXILSignatureAnalysis.h"
#include "DirectX.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Analysis/DXILMetadataAnalysis.h"
#include "llvm/Analysis/DXILResource.h"
#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicsDirectX.h"
#include "llvm/IR/Module.h"
#include "llvm/InitializePasses.h"
#include "llvm/Support/DXILABI.h"

#define DEBUG_TYPE "dxil-post-optimization-validation"

using namespace llvm;
using namespace llvm::dxil;

static ResourceClass toResourceClass(dxbc::RootParameterType Type) {
  using namespace dxbc;
  switch (Type) {
  case RootParameterType::Constants32Bit:
    return ResourceClass::CBuffer;
  case RootParameterType::SRV:
    return ResourceClass::SRV;
  case RootParameterType::UAV:
    return ResourceClass::UAV;
  case RootParameterType::CBV:
    return ResourceClass::CBuffer;
  case dxbc::RootParameterType::DescriptorTable:
    llvm_unreachable("DescriptorTable is not convertible to ResourceClass");
  }
  llvm_unreachable("Unknown RootParameterType");
}

static void reportInvalidDirection(Module &M, DXILResourceMap &DRM) {
  for (const auto &UAV : DRM.uavs()) {
    if (UAV.CounterDirection != ResourceCounterDirection::Invalid)
      continue;

    CallInst *ResourceHandle = nullptr;
    for (CallInst *MaybeHandle : DRM.calls()) {
      if (*DRM.find(MaybeHandle) == UAV) {
        ResourceHandle = MaybeHandle;
        break;
      }
    }

    StringRef Message = "RWStructuredBuffers may increment or decrement their "
                        "counters, but not both.";
    for (const auto &U : ResourceHandle->users()) {
      const CallInst *CI = dyn_cast<CallInst>(U);
      if (!CI && CI->getIntrinsicID() != Intrinsic::dx_resource_updatecounter)
        continue;

      M.getContext().diagnose(DiagnosticInfoGenericWithLoc(
          Message, *CI->getFunction(), CI->getDebugLoc()));
    }
  }
}

static void reportOverlappingError(Module &M, ResourceInfo R1,
                                   ResourceInfo R2) {
  SmallString<128> Message;
  raw_svector_ostream OS(Message);
  OS << "resource " << R1.getName() << " at register "
     << R1.getBinding().LowerBound << " overlaps with resource " << R2.getName()
     << " at register " << R2.getBinding().LowerBound << " in space "
     << R2.getBinding().Space;
  M.getContext().diagnose(DiagnosticInfoGeneric(Message));
}

static void reportOverlappingBinding(Module &M, DXILResourceMap &DRM) {
  [[maybe_unused]] bool ErrorFound = false;
  for (const auto &ResList :
       {DRM.srvs(), DRM.uavs(), DRM.cbuffers(), DRM.samplers()}) {
    if (ResList.empty())
      continue;
    const ResourceInfo *PrevRI = &*ResList.begin();
    for (auto *I = ResList.begin() + 1; I != ResList.end(); ++I) {
      const ResourceInfo *CurrentRI = &*I;
      const ResourceInfo *RI = CurrentRI;
      while (RI != ResList.end() &&
             PrevRI->getBinding().overlapsWith(RI->getBinding())) {
        reportOverlappingError(M, *PrevRI, *RI);
        ErrorFound = true;
        RI++;
      }
      PrevRI = CurrentRI;
    }
  }
  assert(ErrorFound && "this function should be called only when if "
                       "DXILResourceBindingInfo::hasOverlapingBinding() is "
                       "true, yet no overlapping binding was found");
}

static void reportInvalidHandleTyError(Module &M, ResourceClass RC,
                                       ResourceInfo::ResourceBinding Binding) {
  SmallString<160> Message;
  raw_svector_ostream OS(Message);
  StringRef RCName = getResourceClassName(RC);
  OS << RCName << " at register " << Binding.LowerBound << " and space "
     << Binding.Space << " is bound to a texture or typed buffer. " << RCName
     << " root descriptors can only be Raw or Structured buffers.";
  M.getContext().diagnose(DiagnosticInfoGeneric(Message));
}

static void reportOverlappingRegisters(Module &M, const llvm::hlsl::Binding &R1,
                                       const llvm::hlsl::Binding &R2) {
  SmallString<128> Message;

  raw_svector_ostream OS(Message);
  OS << "resource " << getResourceClassName(R1.RC) << " (space=" << R1.Space
     << ", registers=[" << R1.LowerBound << ", " << R1.UpperBound
     << "]) overlaps with resource " << getResourceClassName(R2.RC)
     << " (space=" << R2.Space << ", registers=[" << R2.LowerBound << ", "
     << R2.UpperBound << "])";
  M.getContext().diagnose(DiagnosticInfoGeneric(Message));
}

static void
reportRegNotBound(Module &M, ResourceClass Class,
                  const llvm::dxil::ResourceInfo::ResourceBinding &Unbound) {
  SmallString<128> Message;
  raw_svector_ostream OS(Message);
  OS << getResourceClassName(Class) << " register " << Unbound.LowerBound
     << " in space " << Unbound.Space
     << " does not have a binding in the Root Signature";
  M.getContext().diagnose(DiagnosticInfoGeneric(Message));
}

static dxbc::ShaderVisibility
tripleToVisibility(llvm::Triple::EnvironmentType ET) {
  switch (ET) {
  case Triple::Pixel:
    return dxbc::ShaderVisibility::Pixel;
  case Triple::Vertex:
    return dxbc::ShaderVisibility::Vertex;
  case Triple::Geometry:
    return dxbc::ShaderVisibility::Geometry;
  case Triple::Hull:
    return dxbc::ShaderVisibility::Hull;
  case Triple::Domain:
    return dxbc::ShaderVisibility::Domain;
  case Triple::Mesh:
    return dxbc::ShaderVisibility::Mesh;
  case Triple::Compute:
    return dxbc::ShaderVisibility::All;
  default:
    llvm_unreachable("Invalid triple to shader stage conversion");
  }
}

static void reportIfDeniedShaderStageAccess(Module &M,
                                            const dxbc::RootFlags &Flags,
                                            const dxbc::RootFlags &Mask) {
  if ((Flags & Mask) != Mask)
    return;

  SmallString<128> Message;
  raw_svector_ostream OS(Message);
  OS << "Shader has root bindings but root signature uses a DENY flag to "
        "disallow root binding access to the shader stage.";
  M.getContext().diagnose(DiagnosticInfoGeneric(Message));
}

static std::optional<dxbc::RootFlags>
getEnvironmentDenyFlagMask(Triple::EnvironmentType ShaderProfile) {
  switch (ShaderProfile) {
  case Triple::Pixel:
    return dxbc::RootFlags::DenyPixelShaderRootAccess;
  case Triple::Vertex:
    return dxbc::RootFlags::DenyVertexShaderRootAccess;
  case Triple::Geometry:
    return dxbc::RootFlags::DenyGeometryShaderRootAccess;
  case Triple::Hull:
    return dxbc::RootFlags::DenyHullShaderRootAccess;
  case Triple::Domain:
    return dxbc::RootFlags::DenyDomainShaderRootAccess;
  case Triple::Mesh:
    return dxbc::RootFlags::DenyMeshShaderRootAccess;
  case Triple::Amplification:
    return dxbc::RootFlags::DenyAmplificationShaderRootAccess;
  default:
    return std::nullopt;
  }
}

static void validateRootSignature(Module &M,
                                  const mcdxbc::RootSignatureDesc &RSD,
                                  dxil::ModuleMetadataInfo &MMI,
                                  DXILResourceMap &DRM,
                                  DXILResourceTypeMap &DRTM) {

  hlsl::BindingInfoBuilder Builder;
  dxbc::ShaderVisibility Visibility = tripleToVisibility(MMI.ShaderProfile);

  for (const mcdxbc::RootParameterInfo &ParamInfo : RSD.ParametersContainer) {
    dxbc::ShaderVisibility ParamVisibility =
        dxbc::ShaderVisibility(ParamInfo.Visibility);
    if (ParamVisibility != dxbc::ShaderVisibility::All &&
        ParamVisibility != Visibility)
      continue;
    dxbc::RootParameterType ParamType = dxbc::RootParameterType(ParamInfo.Type);
    switch (ParamType) {
    case dxbc::RootParameterType::Constants32Bit: {
      mcdxbc::RootConstants Const =
          RSD.ParametersContainer.getConstant(ParamInfo.Location);
      Builder.trackBinding(dxil::ResourceClass::CBuffer, Const.RegisterSpace,
                           Const.ShaderRegister, Const.ShaderRegister,
                           &ParamInfo);
      break;
    }

    case dxbc::RootParameterType::SRV:
    case dxbc::RootParameterType::UAV:
    case dxbc::RootParameterType::CBV: {
      mcdxbc::RootDescriptor Desc =
          RSD.ParametersContainer.getRootDescriptor(ParamInfo.Location);
      Builder.trackBinding(toResourceClass(ParamInfo.Type), Desc.RegisterSpace,
                           Desc.ShaderRegister, Desc.ShaderRegister,
                           &ParamInfo);

      break;
    }
    case dxbc::RootParameterType::DescriptorTable: {
      const mcdxbc::DescriptorTable &Table =
          RSD.ParametersContainer.getDescriptorTable(ParamInfo.Location);

      for (const mcdxbc::DescriptorRange &Range : Table.Ranges) {
        uint32_t UpperBound =
            Range.NumDescriptors == ~0U
                ? Range.BaseShaderRegister
                : Range.BaseShaderRegister + Range.NumDescriptors - 1;
        Builder.trackBinding(Range.RangeType, Range.RegisterSpace,
                             Range.BaseShaderRegister, UpperBound, &ParamInfo);
      }
      break;
    }
    }
  }

  for (const mcdxbc::StaticSampler &S : RSD.StaticSamplers)
    Builder.trackBinding(dxil::ResourceClass::Sampler, S.RegisterSpace,
                         S.ShaderRegister, S.ShaderRegister, &S);

  Builder.calculateBindingInfo(
      [&M](const llvm::hlsl::BindingInfoBuilder &Builder,
           const llvm::hlsl::Binding &ReportedBinding) {
        const llvm::hlsl::Binding &Overlaping =
            Builder.findOverlapping(ReportedBinding);
        reportOverlappingRegisters(M, ReportedBinding, Overlaping);
      });

  const hlsl::BoundRegs &BoundRegs = Builder.takeBoundRegs();
  bool HasBindings = false;
  for (const ResourceInfo &RI : DRM) {
    const ResourceInfo::ResourceBinding &Binding = RI.getBinding();
    const dxil::ResourceTypeInfo &RTI = DRTM[RI.getHandleTy()];
    dxil::ResourceClass RC = RTI.getResourceClass();
    dxil::ResourceKind RK = RTI.getResourceKind();

    const llvm::hlsl::Binding *Reg =
        BoundRegs.findBoundReg(RC, Binding.Space, Binding.LowerBound,
                               Binding.LowerBound + Binding.Size - 1);

    if (!Reg) {
      reportRegNotBound(M, RC, Binding);
      continue;
    }

    const auto *ParamInfo =
        static_cast<const mcdxbc::RootParameterInfo *>(Reg->Cookie);

    bool IsSRVOrUAV = RC == ResourceClass::SRV || RC == ResourceClass::UAV;
    bool IsDescriptorTable =
        ParamInfo->Type == dxbc::RootParameterType::DescriptorTable;
    bool IsRawOrStructuredBuffer =
        RK != ResourceKind::RawBuffer && RK != ResourceKind::StructuredBuffer;
    if (IsSRVOrUAV && !IsDescriptorTable && IsRawOrStructuredBuffer) {
      reportInvalidHandleTyError(M, RC, Binding);
      continue;
    }

    HasBindings = true;
  }

  if (!HasBindings)
    return;

  if (std::optional<dxbc::RootFlags> Mask =
          getEnvironmentDenyFlagMask(MMI.ShaderProfile))
    reportIfDeniedShaderStageAccess(M, dxbc::RootFlags(RSD.Flags), *Mask);
}

static mcdxbc::RootSignatureDesc *
getRootSignature(RootSignatureBindingInfo &RSBI,
                 dxil::ModuleMetadataInfo &MMI) {
  if (MMI.EntryPropertyVec.size() == 0)
    return nullptr;
  return RSBI.getDescForFunction(MMI.EntryPropertyVec[0].Entry);
}

static void reportErrors(Module &M, DXILResourceMap &DRM,
                         DXILResourceBindingInfo &DRBI,
                         RootSignatureBindingInfo &RSBI,
                         dxil::ModuleMetadataInfo &MMI,
                         DXILResourceTypeMap &DRTM) {
  if (DRM.hasInvalidCounterDirection())
    reportInvalidDirection(M, DRM);

  if (DRBI.hasOverlappingBinding())
    reportOverlappingBinding(M, DRM);

  assert(!DRBI.hasImplicitBinding() && "implicit bindings should be handled in "
                                       "DXILResourceImplicitBinding pass");

  if (mcdxbc::RootSignatureDesc *RSD = getRootSignature(RSBI, MMI))
    validateRootSignature(M, *RSD, MMI, DRM, DRTM);
}

PreservedAnalyses
DXILPostOptimizationValidation::run(Module &M, ModuleAnalysisManager &MAM) {
  DXILResourceMap &DRM = MAM.getResult<DXILResourceAnalysis>(M);
  DXILResourceBindingInfo &DRBI = MAM.getResult<DXILResourceBindingAnalysis>(M);
  RootSignatureBindingInfo &RSBI = MAM.getResult<RootSignatureAnalysis>(M);
  ModuleMetadataInfo &MMI = MAM.getResult<DXILMetadataAnalysis>(M);
  DXILResourceTypeMap &DRTM = MAM.getResult<DXILResourceTypeAnalysis>(M);

  reportErrors(M, DRM, DRBI, RSBI, MMI, DRTM);
  return PreservedAnalyses::all();
}

namespace {
class DXILPostOptimizationValidationLegacy : public ModulePass {
public:
  bool runOnModule(Module &M) override {
    DXILResourceMap &DRM =
        getAnalysis<DXILResourceWrapperPass>().getResourceMap();
    DXILResourceBindingInfo &DRBI =
        getAnalysis<DXILResourceBindingWrapperPass>().getBindingInfo();
    RootSignatureBindingInfo &RSBI =
        getAnalysis<RootSignatureAnalysisWrapper>().getRSInfo();
    dxil::ModuleMetadataInfo &MMI =
        getAnalysis<DXILMetadataAnalysisWrapperPass>().getModuleMetadata();
    DXILResourceTypeMap &DRTM =
        getAnalysis<DXILResourceTypeWrapperPass>().getResourceTypeMap();

    reportErrors(M, DRM, DRBI, RSBI, MMI, DRTM);
    return false;
  }
  StringRef getPassName() const override {
    return "DXIL Post Optimization Validation";
  }
  DXILPostOptimizationValidationLegacy() : ModulePass(ID) {}

  static char ID; // Pass identification.
  void getAnalysisUsage(llvm::AnalysisUsage &AU) const override {
    AU.addRequired<DXILResourceWrapperPass>();
    AU.addRequired<DXILResourceBindingWrapperPass>();
    AU.addRequired<DXILMetadataAnalysisWrapperPass>();
    AU.addRequired<RootSignatureAnalysisWrapper>();
    AU.addRequired<DXILResourceTypeWrapperPass>();
    AU.addPreserved<DXILResourceWrapperPass>();
    AU.addPreserved<DXILResourceBindingWrapperPass>();
    AU.addPreserved<DXILMetadataAnalysisWrapperPass>();
    AU.addPreserved<ShaderFlagsAnalysisWrapper>();
    AU.addPreserved<RootSignatureAnalysisWrapper>();
    AU.addPreserved<SignatureAnalysisWrapper>();
  }
};
char DXILPostOptimizationValidationLegacy::ID = 0;
} // end anonymous namespace

INITIALIZE_PASS_BEGIN(DXILPostOptimizationValidationLegacy, DEBUG_TYPE,
                      "DXIL Post Optimization Validation", false, false)
INITIALIZE_PASS_DEPENDENCY(DXILResourceBindingWrapperPass)
INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass)
INITIALIZE_PASS_DEPENDENCY(DXILResourceWrapperPass)
INITIALIZE_PASS_DEPENDENCY(DXILMetadataAnalysisWrapperPass)
INITIALIZE_PASS_DEPENDENCY(RootSignatureAnalysisWrapper)
INITIALIZE_PASS_DEPENDENCY(DXILResourceTypeWrapperPass)
INITIALIZE_PASS_END(DXILPostOptimizationValidationLegacy, DEBUG_TYPE,
                    "DXIL Post Optimization Validation", false, false)

ModulePass *llvm::createDXILPostOptimizationValidationLegacyPass() {
  return new DXILPostOptimizationValidationLegacy();
}
