// Copyright 2020 The IREE Authors
//
// Licensed 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 "compiler/plugins/target/MetalSPIRV/SPIRVToMSL.h"

#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"

// Disable exception handling in favor of assertions.
#define SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS
#include "third_party/spirv_cross/spirv_msl.hpp"

#define DEBUG_TYPE "spirv-to-msl"

/// The [[buffer(N)]] index for push constants.
/// Note that this MUST be kept consistent with the Metal HAL driver.
#define IREE_HAL_METAL_PUSH_CONSTANT_BUFFER_INDEX 3

namespace mlir::iree_compiler {

namespace {
class SPIRVToMSLCompiler : public SPIRV_CROSS_NAMESPACE::CompilerMSL {
public:
  using CompilerMSL::CompilerMSL;

  MetalShader::ThreadGroupSize
  getWorkgroupSizeForEntryPoint(StringRef entryName) {
    const auto &entryPoint = get_entry_point(
        entryName.str(), spv::ExecutionModel::ExecutionModelGLCompute);
    const auto &workgroupSize = entryPoint.workgroup_size;
    // TODO(antiagainst): support specialization constant.
    if (workgroupSize.constant != 0)
      return {0, 0, 0};
    return {workgroupSize.x, workgroupSize.y, workgroupSize.z};
  }

  // A struct containing a resource descriptor's information.
  struct Descriptor {
    uint32_t set;
    uint32_t binding;

    Descriptor(uint32_t s, uint32_t b) : set(s), binding(b) {}

    friend bool operator<(const Descriptor &l, const Descriptor &r) {
      return std::tie(l.set, l.binding) < std::tie(r.set, r.binding);
    }
  };

  // Updates `descriptors` with resource set and binding number pairs in
  // increasing order, and `hasPushConstant` if with push constants.
  // Returns true if no unsupported cases are encountered.
  bool getResources(SmallVectorImpl<Descriptor> *descriptors,
                    bool *hasPushConstant) {
    descriptors->clear();
    *hasPushConstant = false;

    // Iterate over all variables in the SPIR-V blob.
    bool hasUnknownCase = false;
    ir.for_each_typed_id<SPIRV_CROSS_NAMESPACE::SPIRVariable>(
        [&](uint32_t id, SPIRV_CROSS_NAMESPACE::SPIRVariable &var) {
          auto storage = var.storage;
          switch (storage) {
            // Non-interface variables. We don't care.
          case spv::StorageClassFunction:
          case spv::StorageClassPrivate:
          case spv::StorageClassWorkgroup:
            // Builtin variables. We don't care either.
          case spv::StorageClassInput:
            return;
          case spv::StorageClassPushConstant:
            *hasPushConstant = true;
            return;
          case spv::StorageClassUniform:
          case spv::StorageClassStorageBuffer: {
            uint32_t setNo = get_decoration(id, spv::DecorationDescriptorSet);
            uint32_t bindingNo = get_decoration(id, spv::DecorationBinding);
            descriptors->emplace_back(setNo, bindingNo);
            return;
          }
          default:
            break;
          }
          hasUnknownCase = true;
        });

    llvm::sort(*descriptors);
    return !hasUnknownCase;
  }

  Options getCompilationOptions(IREE::HAL::MetalTargetPlatform platform) {
    // TODO(antiagainst): fill out the following according to the Metal GPU
    // family.
    SPIRVToMSLCompiler::Options spvCrossOptions;
    switch (platform) {
    case IREE::HAL::MetalTargetPlatform::macOS:
      spvCrossOptions.platform = SPIRVToMSLCompiler::Options::Platform::macOS;
      break;
    case IREE::HAL::MetalTargetPlatform::iOS:
    case IREE::HAL::MetalTargetPlatform::iOSSimulator:
      spvCrossOptions.platform = SPIRVToMSLCompiler::Options::Platform::iOS;
      break;
    }
    spvCrossOptions.msl_version =
        SPIRVToMSLCompiler::Options::make_msl_version(3, 0);
    // Eanble using Metal argument buffers. It is more akin to Vulkan descriptor
    // sets, which is how IREE HAL models resource bindings and mappings.
    spvCrossOptions.argument_buffers = true;
    return spvCrossOptions;
  }
};
} // namespace

std::optional<std::pair<MetalShader, std::string>>
crossCompileSPIRVToMSL(IREE::HAL::MetalTargetPlatform targetPlatform,
                       llvm::ArrayRef<uint32_t> spvBinary,
                       StringRef entryPoint) {
  SPIRVToMSLCompiler spvCrossCompiler(spvBinary.data(), spvBinary.size());

  // All spirv-cross operations work on the current entry point. It should be
  // set right after the cross compiler construction.
  spvCrossCompiler.set_entry_point(
      entryPoint.str(), spv::ExecutionModel::ExecutionModelGLCompute);

  SmallVector<SPIRVToMSLCompiler::Descriptor> descriptors;
  bool hasPushConstant = false;
  if (!spvCrossCompiler.getResources(&descriptors, &hasPushConstant))
    return std::nullopt;

  // Explicitly set the argument buffer [[id(N)]] location for each SPIR-V
  // resource variable.
  for (const auto &descriptor : descriptors) {
    SPIRV_CROSS_NAMESPACE::MSLResourceBinding binding = {};
    binding.stage = spv::ExecutionModelGLCompute;
    binding.desc_set = descriptor.set;
    binding.binding = descriptor.binding;
    // We only interact with buffers in IREE.
    binding.msl_buffer = descriptor.binding;

    spvCrossCompiler.add_msl_resource_binding(binding);
  }
  // If push constants are used, explicitly set its [[buffer(N)]] location too.
  if (hasPushConstant) {
    SPIRV_CROSS_NAMESPACE::MSLResourceBinding binding = {};
    binding.stage = spv::ExecutionModelGLCompute;
    binding.desc_set =
        SPIRV_CROSS_NAMESPACE::ResourceBindingPushConstantDescriptorSet;
    binding.binding = SPIRV_CROSS_NAMESPACE::ResourceBindingPushConstantBinding;
    binding.msl_buffer = IREE_HAL_METAL_PUSH_CONSTANT_BUFFER_INDEX;

    spvCrossCompiler.add_msl_resource_binding(binding);
  }

  auto spvCrossOptions = spvCrossCompiler.getCompilationOptions(targetPlatform);
  spvCrossCompiler.set_msl_options(spvCrossOptions);

  std::string mslSource = spvCrossCompiler.compile();
  // Get the revised entry point name. Cross compiling to MSL generates source
  // code, where we may run into the case that we are using reserved keyword for
  // the entry point name, e.g., `abs`. Under such circumstances, it will be
  // revised to avoid collision.
  const auto &spirvEntryPoint = spvCrossCompiler.get_entry_point(
      entryPoint.str(), spv::ExecutionModel::ExecutionModelGLCompute);
  LLVM_DEBUG({
    llvm::dbgs() << "Original entry point name: '" << spirvEntryPoint.orig_name
                 << "'\n";
    llvm::dbgs() << "Revised entry point name: '" << spirvEntryPoint.name
                 << "'\n";
    llvm::dbgs() << "Generated MSL:\n-----\n" << mslSource << "\n-----\n";
  });

  auto workgroupSize =
      spvCrossCompiler.getWorkgroupSizeForEntryPoint(entryPoint);
  if (!workgroupSize.x || !workgroupSize.y || !workgroupSize.z) {
    return std::nullopt;
  }
  return std::make_pair(MetalShader{std::move(mslSource), workgroupSize},
                        spirvEntryPoint.name);
}

} // namespace mlir::iree_compiler
