// Copyright (c) 2025 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Compressed grammar tables.

#include "source/table2.h"

#include <algorithm>
#include <array>
#include <cstring>

#include "source/extensions.h"
#include "source/latest_version_spirv_header.h"
#include "source/spirv_constant.h"
#include "source/spirv_target_env.h"
#include "spirv-tools/libspirv.hpp"

namespace spvtools {
namespace {

// This is used in the source for the generated tables.
constexpr inline IndexRange IR(uint32_t first, uint32_t count) {
  return IndexRange{first, count};
}

struct NameIndex {
  // Location of the null-terminated name in the global string table kStrings.
  IndexRange name;
  // Index of this name's entry in the corresponding by-value table.
  uint32_t index;
};

struct NameValue {
  // Location of the null-terminated name in the global string table kStrings.
  IndexRange name;
  // Enum value in the binary format.
  uint32_t value;
};

// The generated include file contains variables:
//
//   std::array<NameIndex,...> kOperandNames:
//      Operand names and index, ordered by (operand kind, name)
//      The index part is the named entry's index in kOperandsByValue array.
//      Aliases are included as their own entries.
//
//   std::array<OperandDesc, ...> kOperandsByValue:
//      Operand descriptions, ordered by (operand kind, operand enum value).
//
//   std::array<NameIndex,...> kInstructionNames:
//      Instruction names and index, ordered by (name, value)
//      The index part is the named entry's index in kInstructionDesc array.
//      Aliases are included as their own entries.
//
//   std::array<InstructionDesc, ...> kInstructionDesc
//      Instruction descriptions, ordered by opcode.
//
//   const char kStrings[]
//      Array of characters, referenced by IndexRanges elsewhere.
//      Each IndexRange denotes a string.
//
//   const IndexRange kAliasSpans[]
//      Array of IndexRanges, where each represents a string by referencing
//      the kStrings table.
//      This array contains all sequences of alias strings used in the grammar.
//      This table is referenced by an IndexRange elsewhere, i.e. by the
//      'aliases' field of an instruction or operand description.
//
//   const spv::Capability kCapabilitySpans[]
//      Array of capabilities, referenced by IndexRanges elsewhere.
//      Contains all sequences of capabilities used in the grammar.
//
//   const spvtools::Extension kExtensionSpans[] = {
//      Array of extensions, referenced by IndexRanges elsewhere.
//      Contains all sequences of extensions used in the grammar.
//
//   const spv_operand_type_t kOperandSpans[] = {
//      Array of operand types, referenced by IndexRanges elsewhere.
//      Contains all sequences of operand types used in the grammar.

// Maps an operand kind to NameValue entries for that kind.
// The result is an IndexRange into kOperandNames, and are sorted
// by string name within that span.
IndexRange OperandNameRangeForKind(spv_operand_type_t type);

// Maps an operand kind to possible operands for that kind.
// The result is an IndexRange into kOperandsByValue, and the operands
// are sorted by value within that span.
IndexRange OperandByValueRangeForKind(spv_operand_type_t type);

// Maps an extended instruction set kind to NameValue entries for that kind.
// The result is an IndexRange into kExtIntNames, and are sorted
// by string name within that span.
IndexRange ExtInstNameRangeForKind(spv_ext_inst_type_t type);

// Maps an extended instruction set kind to possible operands for that kind.
// The result is an IndexRange into kExtInstByValue, and the instructions
// are sorted by opcode value within that span.
IndexRange ExtInstByValueRangeForKind(spv_ext_inst_type_t type);

// Returns the name of an extension, as an index into kStrings
IndexRange ExtensionToIndexRange(Extension extension);

#include "core_tables_body.inc"

// Returns a pointer to the null-terminated C-style string in the global
// strings table, as referenced by 'ir'.  Assumes the given range is valid.
const char* getChars(IndexRange ir) {
  assert(ir.first() < sizeof(kStrings));
  return ir.apply(kStrings).data();
}

}  // anonymous namespace

utils::Span<const spv_operand_type_t> OperandDesc::operands() const {
  return operands_range.apply(kOperandSpans);
}
utils::Span<const char> OperandDesc::name() const {
  return name_range.apply(kStrings);
}
utils::Span<const IndexRange> OperandDesc::aliases() const {
  return name_range.apply(kAliasSpans);
}
utils::Span<const spv::Capability> OperandDesc::capabilities() const {
  return capabilities_range.apply(kCapabilitySpans);
}
utils::Span<const spvtools::Extension> OperandDesc::extensions() const {
  return extensions_range.apply(kExtensionSpans);
}

utils::Span<const spv_operand_type_t> InstructionDesc::operands() const {
  return operands_range.apply(kOperandSpans);
}
utils::Span<const char> InstructionDesc::name() const {
  return name_range.apply(kStrings);
}
utils::Span<const IndexRange> InstructionDesc::aliases() const {
  return name_range.apply(kAliasSpans);
}
utils::Span<const spv::Capability> InstructionDesc::capabilities() const {
  return capabilities_range.apply(kCapabilitySpans);
}
utils::Span<const spvtools::Extension> InstructionDesc::extensions() const {
  return extensions_range.apply(kExtensionSpans);
}

utils::Span<const spv_operand_type_t> ExtInstDesc::operands() const {
  return operands_range.apply(kOperandSpans);
}
utils::Span<const char> ExtInstDesc::name() const {
  return name_range.apply(kStrings);
}
utils::Span<const spv::Capability> ExtInstDesc::capabilities() const {
  return capabilities_range.apply(kCapabilitySpans);
}

spv_result_t LookupOpcode(spv::Op opcode, const InstructionDesc** desc) {
  // Metaphor: Look for the needle in the haystack.
  const InstructionDesc needle(opcode);
  auto where = std::lower_bound(
      kInstructionDesc.begin(), kInstructionDesc.end(), needle,
      [&](const InstructionDesc& lhs, const InstructionDesc& rhs) {
        return uint32_t(lhs.opcode) < uint32_t(rhs.opcode);
      });
  if (where != kInstructionDesc.end() && where->opcode == opcode) {
    *desc = &*where;
    return SPV_SUCCESS;
  }
  return SPV_ERROR_INVALID_LOOKUP;
}

spv_result_t LookupOpcode(const char* name, const InstructionDesc** desc) {
  // The comparison function knows to use 'name' string to compare against
  // when the value is kSentinel.
  const auto kSentinel = uint32_t(-1);
  const NameIndex needle{{}, kSentinel};
  auto less = [&](const NameIndex& lhs, const NameIndex& rhs) {
    const char* lhs_chars = lhs.index == kSentinel ? name : getChars(lhs.name);
    const char* rhs_chars = rhs.index == kSentinel ? name : getChars(rhs.name);
    return std::strcmp(lhs_chars, rhs_chars) < 0;
  };

  auto where = std::lower_bound(kInstructionNames.begin(),
                                kInstructionNames.end(), needle, less);
  if (where != kInstructionNames.end() &&
      std::strcmp(getChars(where->name), name) == 0) {
    *desc = &kInstructionDesc[where->index];
    return SPV_SUCCESS;
  }
  return SPV_ERROR_INVALID_LOOKUP;
}

namespace {
template <typename KEY_TYPE>
spv_result_t LookupOpcodeForEnvInternal(spv_target_env env, KEY_TYPE key,
                                        const InstructionDesc** desc) {
  const InstructionDesc* desc_proxy;
  auto status = LookupOpcode(key, &desc_proxy);
  if (status != SPV_SUCCESS) {
    return status;
  }
  const auto& entry = *desc_proxy;
  const auto version = spvVersionForTargetEnv(env);
  if ((version >= entry.minVersion && version <= entry.lastVersion) ||
      entry.extensions_range.count() > 0 ||
      entry.capabilities_range.count() > 0) {
    *desc = desc_proxy;
    return SPV_SUCCESS;
  }
  return SPV_ERROR_INVALID_LOOKUP;
}
}  // namespace

spv_result_t LookupOpcodeForEnv(spv_target_env env, const char* name,
                                const InstructionDesc** desc) {
  return LookupOpcodeForEnvInternal(env, name, desc);
}

spv_result_t LookupOpcodeForEnv(spv_target_env env, spv::Op opcode,
                                const InstructionDesc** desc) {
  return LookupOpcodeForEnvInternal(env, opcode, desc);
}

spv_result_t LookupOperand(spv_operand_type_t type, uint32_t value,
                           const OperandDesc** desc) {
  auto ir = OperandByValueRangeForKind(type);
  if (ir.empty()) {
    return SPV_ERROR_INVALID_LOOKUP;
  }

  auto span = ir.apply(kOperandsByValue.data());

  // Metaphor: Look for the needle in the haystack.
  // The operand value is the first member.
  const OperandDesc needle{value};
  auto where =
      std::lower_bound(span.begin(), span.end(), needle,
                       [&](const OperandDesc& lhs, const OperandDesc& rhs) {
                         return lhs.value < rhs.value;
                       });
  if (where != span.end() && where->value == value) {
    *desc = &*where;
    return SPV_SUCCESS;
  }
  return SPV_ERROR_INVALID_LOOKUP;
}

spv_result_t LookupOperand(spv_operand_type_t type, const char* name,
                           size_t name_len, const OperandDesc** desc) {
  auto ir = OperandNameRangeForKind(type);
  if (ir.empty()) {
    return SPV_ERROR_INVALID_LOOKUP;
  }

  auto span = ir.apply(kOperandNames.data());

  // The comparison function knows to use (name, name_len) as the
  // string to compare against when the value is kSentinel.
  const auto kSentinel = uint32_t(-1);
  const NameIndex needle{{}, kSentinel};
  // The strings in the global string table are null-terminated, and the count
  // reflects that.  So always deduct 1 from its length.
  auto less = [&](const NameIndex& lhs, const NameIndex& rhs) {
    const char* lhs_chars = lhs.index == kSentinel ? name : getChars(lhs.name);
    const char* rhs_chars = rhs.index == kSentinel ? name : getChars(rhs.name);
    const auto content_cmp = std::strncmp(lhs_chars, rhs_chars, name_len);
    if (content_cmp != 0) {
      return content_cmp < 0;
    }
    const auto lhs_len =
        lhs.index == kSentinel ? name_len : lhs.name.count() - 1;
    const auto rhs_len =
        rhs.index == kSentinel ? name_len : rhs.name.count() - 1;
    return lhs_len < rhs_len;
  };

  auto where = std::lower_bound(span.begin(), span.end(), needle, less);
  if (where != span.end() && where->name.count() - 1 == name_len &&
      std::strncmp(getChars(where->name), name, name_len) == 0) {
    *desc = &kOperandsByValue[where->index];
    return SPV_SUCCESS;
  }
  return SPV_ERROR_INVALID_LOOKUP;
}

spv_result_t LookupExtInst(spv_ext_inst_type_t type, const char* name,
                           const ExtInstDesc** desc) {
  auto ir = ExtInstNameRangeForKind(type);
  if (ir.empty()) {
    return SPV_ERROR_INVALID_LOOKUP;
  }

  auto span = ir.apply(kExtInstNames.data());

  // The comparison function knows to use 'name' string to compare against
  // when the value is kSentinel.
  const auto kSentinel = uint32_t(-1);
  const NameIndex needle{{}, kSentinel};
  auto less = [&](const NameIndex& lhs, const NameIndex& rhs) {
    const char* lhs_chars = lhs.index == kSentinel ? name : getChars(lhs.name);
    const char* rhs_chars = rhs.index == kSentinel ? name : getChars(rhs.name);
    return std::strcmp(lhs_chars, rhs_chars) < 0;
  };

  auto where = std::lower_bound(span.begin(), span.end(), needle, less);
  if (where != span.end() && std::strcmp(getChars(where->name), name) == 0) {
    *desc = &kExtInstByValue[where->index];
    return SPV_SUCCESS;
  }
  return SPV_ERROR_INVALID_LOOKUP;
}

// Finds the extended instruction description by opcode value.
// On success, returns SPV_SUCCESS and updates *desc.
spv_result_t LookupExtInst(spv_ext_inst_type_t type, uint32_t value,
                           const ExtInstDesc** desc) {
  auto ir = ExtInstByValueRangeForKind(type);
  if (ir.empty()) {
    return SPV_ERROR_INVALID_LOOKUP;
  }

  auto span = ir.apply(kExtInstByValue.data());

  // Metaphor: Look for the needle in the haystack.
  // The operand value is the first member.
  const ExtInstDesc needle(value);
  auto where =
      std::lower_bound(span.begin(), span.end(), needle,
                       [&](const ExtInstDesc& lhs, const ExtInstDesc& rhs) {
                         return lhs.value < rhs.value;
                       });
  if (where != span.end() && where->value == value) {
    *desc = &*where;
    return SPV_SUCCESS;
  }
  return SPV_ERROR_INVALID_LOOKUP;
}

const char* ExtensionToString(Extension extension) {
  return getChars(ExtensionToIndexRange(extension));
}

bool GetExtensionFromString(const char* name, Extension* extension) {
  // The comparison function knows to use 'name' string to compare against
  // when the value is kSentinel.
  const auto kSentinel = uint32_t(-1);
  const NameValue needle{{}, kSentinel};
  auto less = [&](const NameValue& lhs, const NameValue& rhs) {
    const char* lhs_chars = lhs.value == kSentinel ? name : getChars(lhs.name);
    const char* rhs_chars = rhs.value == kSentinel ? name : getChars(rhs.name);
    return std::strcmp(lhs_chars, rhs_chars) < 0;
  };

  auto where = std::lower_bound(kExtensionNames.begin(), kExtensionNames.end(),
                                needle, less);
  if (where != kExtensionNames.end() &&
      std::strcmp(getChars(where->name), name) == 0) {
    *extension = static_cast<Extension>(where->value);
    return true;
  }
  return false;
}

}  // namespace spvtools
