#!/usr/bin/env python3
# Copyright (c) 2016 Google Inc.
#
# 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.
"""Generates compressed grammar tables from SPIR-V JSON grammar."""

import errno
import json
import os.path
import re
import sys
from typing import Dict, List, Tuple, Any

# Find modules relative to the directory containing this script.
# This is needed for hermetic Bazel builds, where the Table files are bundled
# together with this script, while keeping their relative locations.
sys.path.append(os.path.dirname(os.path.abspath(__file__)))

from Table.Context import Context
from Table.IndexRange import IndexRange
from Table.Operand import Operand

class GrammarError(Exception):
    pass

# Extensions to recognize, but which don't necessarily come from the SPIR-V
# core or KHR grammar files.  Get this list from the SPIR-V registry web page.
# NOTE: Only put things on this list if it is not in those grammar files.
EXTENSIONS_FROM_SPIRV_REGISTRY_AND_NOT_FROM_GRAMMARS = """
SPV_AMD_gpu_shader_half_float
SPV_AMD_gpu_shader_int16
SPV_KHR_non_semantic_info
SPV_EXT_relaxed_printf_string_address_space
"""

class ExtInst():
    """
    An extended instruction set.

    Properties:
       prefix: the string prefix for operand enums. Often an empty string.
       file: the location of the JSON grammar file
       name: the name, can be used as an identifier
       enum_name: the enum name, e.g. SPV_EXT_INST_OPENCL_STD
       grammar: the JSON object for the grammar, loaded from the file.
    """
    def __init__(self,spec: str):
        matches = re.fullmatch('^([^,]*),(.*)',spec)
        if matches is None:
            raise Exception("Invalid prefix and path: {}".format(spec))
        self.prefix = matches[1]
        if self.prefix is None:
            self.prefix = ""
        self.file = matches[2]
        matches = re.match('.*extinst\\.(.*)\\.grammar.json', self.file)
        if matches is None:
            raise Exception("Invalid grammar file name: {}".format(self.file))
        self.name = matches[1].replace('-','_').replace('.','_')

        self.enum_name = 'SPV_EXT_INST_TYPE_{}'.format(self.name).upper()
        if self.enum_name == "SPV_EXT_INST_TYPE_OPENCL_STD_100":
            # Live with an old decision, by adjusting this name.
            self.enum_name = "SPV_EXT_INST_TYPE_OPENCL_STD"

        self.load()

    def load(self):
        """
        Populates self.grammar from the file.
        Applies the self.prefix to operand enums
        """
        with open(self.file) as json_file:
            self.grammar = json.loads(json_file.read())
            if len(self.prefix) > 0:
                prefix_operand_kind_names(self.prefix, self.grammar)


def convert_min_required_version(version): # (version: str | None) -> str
    """Converts the minimal required SPIR-V version encoded in the grammar to
    the symbol in SPIRV-Tools."""
    if version is None:
        return 'SPV_SPIRV_VERSION_WORD(1, 0)'
    if version == 'None':
        return '0xffffffffu'
    return 'SPV_SPIRV_VERSION_WORD({})'.format(version.replace('.', ','))


def convert_max_required_version(version): # (version: str | None) -> str
    """Converts the maximum required SPIR-V version encoded in the grammar to
    the symbol in SPIRV-Tools."""
    if version is None:
        return '0xffffffffu'
    return 'SPV_SPIRV_VERSION_WORD({})'.format(version.replace('.', ','))


def c_bool(b: bool) -> str:
    return 'true' if b else 'false'


def ctype(kind: str, quantifier: str) -> str:
    """Returns the corresponding operand type used in spirv-tools for the given
    operand kind and quantifier used in the JSON grammar.

    Arguments:
      - kind, e.g. 'IdRef'
      - quantifier, e.g. '', '?', '*'

    Returns:
      a string of the enumerant name in spv_operand_type_t
    """
    if kind == '':
        raise Error("operand JSON object missing a 'kind' field")
    # The following cases are where we differ between the JSON grammar and
    # spirv-tools.
    if kind == 'IdResultType':
        kind = 'TypeId'
    elif kind == 'IdResult':
        kind = 'ResultId'
    elif kind == 'IdMemorySemantics' or kind == 'MemorySemantics':
        kind = 'MemorySemanticsId'
    elif kind == 'IdScope' or kind == 'Scope':
        kind = 'ScopeId'
    elif kind == 'IdRef':
        kind = 'Id'

    elif kind == 'ImageOperands':
        kind = 'Image'
    elif kind == 'Dim':
        kind = 'Dimensionality'
    elif kind == 'ImageFormat':
        kind = 'SamplerImageFormat'
    elif kind == 'KernelEnqueueFlags':
        kind = 'KernelEnqFlags'

    elif kind == 'LiteralExtInstInteger':
        kind = 'ExtensionInstructionNumber'
    elif kind == 'LiteralSpecConstantOpInteger':
        kind = 'SpecConstantOpNumber'
    elif kind == 'LiteralContextDependentNumber':
        kind = 'TypedLiteralNumber'

    elif kind == 'PairLiteralIntegerIdRef':
        kind = 'LiteralIntegerId'
    elif kind == 'PairIdRefLiteralInteger':
        kind = 'IdLiteralInteger'
    elif kind == 'PairIdRefIdRef':  # Used by OpPhi in the grammar
        kind = 'Id'

    if kind == 'FPRoundingMode':
        kind = 'FpRoundingMode'
    elif kind == 'FPFastMathMode':
        kind = 'FpFastMathMode'

    if quantifier == '?':
        kind = 'Optional{}'.format(kind)
    elif quantifier == '*':
        kind = 'Variable{}'.format(kind)

    return 'SPV_OPERAND_TYPE_{}'.format(
        re.sub(r'([a-z])([A-Z])', r'\1_\2', kind).upper())


def convert_operand_kind(obj: Dict[str, str]) -> str:
    """Returns the corresponding operand type used in spirv-tools for the given
    operand kind and quantifier used in the JSON grammar.

    Arguments:
      - obj: an instruction operand, having keys:
          - 'kind', e.g. 'IdRef'
          - optionally, a quantifier: '?' or '*'

    Returns:
      a string of the enumerant name in spv_operand_type_t
    """
    kind = obj.get('kind', '')
    quantifier = obj.get('quantifier', '')
    return ctype(kind, quantifier)


def to_safe_identifier(s: str) -> str:
    """
    Returns a new string with all non-letters converted to underscores,
    and prepending 'k'.
    The result should be safe to use as a C identifier.
    """
    return 'k' + re.sub(r'[^a-zA-Z0-9]', '_', s)


class Grammar():
    """
    Accumulates string and enum tables.
    The extensions and operand kinds lists are fixed at creation time.
    Prints tables for instructions, operand kinds, and underlying string
    and enum tables.
    Assumes an index range is emitted by printing an IndexRange object.
    """
    def __init__(self, extensions: List[str], operand_kinds:List[dict], printing_classes: List[str]) -> None:
        self.context = Context()
        self.extensions = sorted(extensions)
        self.operand_kinds = sorted(operand_kinds, key = lambda ok: convert_operand_kind(ok))
        self.printing_classes = sorted([to_safe_identifier(x) for x in printing_classes])

        # The self.header_ignore_decls are only used to debug the flow.
        # They are copied into the C++ source code where they are more likely
        # to be seen by humans.
        self.header_ignore_decls: List[str] = [self.IndexRangeDecls()]

        # The self.header_decls content goes into core_tables_header.inc to be
        # included in a .h file.
        self.header_decls: List[str] = []
        # The self.body_decls content goes into core_tables_body.inc to be included
        # in a .cpp file.  It includes definitions of static variables and
        # hidden functions.
        self.body_decls: List[str] = []

        if len(self.operand_kinds) == 0:
            raise Exception("operand_kinds should be a non-empty list")
        if len(self.extensions) == 0:
            raise Exception("extensions should be a non-empty list")

        self.ComputePrintingClassDecls()
        self.ComputeExtensionDecls()

        # These operand kinds need to have their optional counterpart to also
        # be represented in the lookup tables, with the same content.
        self.operand_kinds_needing_optional_variant = [
                'ImageOperands',
                'AccessQualifier',
                'MemoryAccess',
                'PackedVectorFormat',
                'CooperativeMatrixOperands',
                'MatrixMultiplyAccumulateOperands',
                'RawAccessChainOperands',
                'FPEncoding',
                'TensorOperands',
                'Capability']

    def dump(self) -> None:
        self.context.dump()

    def IndexRangeDecls(self) -> str:
        return """
struct IndexRange {
  uint32_t first = 0; // index of the first element in the range
  uint32_t count = 0; // number of elements in the range
};
constexpr inline IndexRange IR(uint32_t first, uint32_t count) {
  return {first, count};
}
"""

    def ComputePrintingClassDecls(self) -> str:
        parts: List[str] = []
        parts.append("enum class PrintingClass : uint32_t {");
        parts.extend(["  {},".format(x) for x in self.printing_classes])
        parts.append("};\n")
        self.header_decls.extend(parts)

    def ComputeExtensionDecls(self) -> None:
        parts: List[str] = []
        parts.append("enum Extension : uint32_t {");
        parts.extend(["  {},".format(to_safe_identifier(x)) for x in self.extensions])
        parts.append("};\n")
        self.header_decls.extend(parts)

        parts = []
        parts.append("// Returns the name of an extension, as an index into kStrings")
        parts.append("IndexRange ExtensionToIndexRange(Extension extension) {\n  switch(extension) {")
        for e in self.extensions:
            parts.append('    case Extension::k{}: return {};'.format(e,self.context.AddString(e)))
        parts.append("    default: break;");
        parts.append('  }\n  return {};\n}\n');
        self.body_decls.extend(parts)

        parts = []
        parts.append("""// Extension names and values, ordered by name
// The fields in order are:
//   name, indexing into kStrings
//   enum value""")
        parts.append("static const std::array<NameValue,{}> kExtensionNames{{{{".format(len(self.extensions)))
        for e in self.extensions:
            parts.append('    {{{}, static_cast<uint32_t>({})}},'.format(self.context.AddString(e), to_safe_identifier(e)))
        parts.append("}};\n")
        self.body_decls.extend(parts)

    def ComputeOperandTables(self) -> None:
        """
        Returns the string for the C definitions of the operand kind tables.

        An operand kind such as ImageOperands also has an associated
        operand kind that is an 'optional' variant.
        These are represented as two distinct operand kinds in spv_operand_type_t.
        For example, ImageOperands maps to both SPV_OPERAND_TYPE_IMAGE, and also
        to SPV_OPERAND_TYPE_OPTIONAL_IMAGE.

        The definitions are:
         - kOperandsByValue: a 1-dimensional array of all operand descriptions
           sorted first by operand kind, then by operand value.
           Only non-optional operand kinds are represented here.

         - kOperandsByValueRangeByKind: a function mapping from operand kind to
           the index range into kOperandByValue.
           This has mappings for both concrete and corresponding optional operand kinds.

         - kOperandNames: a 1-dimensional array of all operand NameIndex
           entries, sorted first by operand kinds, then by operand name.
           The name part is represented by an index range into the string table.
           The index part is the index of this name's entry into the by-value array.
           This can have more entries than the by-value array, because names
           can have string aliases. For example,the MemorySemantics value 0
           is named both "Relaxed" and "None".
           Only non-optional operand kinds are represented here.

         - kOperandNamesRangeByKind: a mapping from operand kind to the index
           range into kOperandNames.
           This has mappings for both concrete and corresponding optional operand kinds.
        """

        self.header_ignore_decls.append(
"""
struct NameIndex {
  // Location of the null-terminated name in the global string table.
  IndexRange name;
  // Index of this name's entry in in the associated by-value table.
  uint32_t index;
};
struct NameValue {
  // Location of the null-terminated name in the global string table.
  IndexRange name;
  // Enum value in the binary format.
  uint32_t value;
};
// Describes a SPIR-V operand.
struct OperandDesc {
  uint32_t value;
  IndexRange operands_range;      // Indexes kOperandSpans
  IndexRange name_range;          // Indexes kStrings
  IndexRange aliases_range;       // Indexes kAliasSpans
  IndexRange capabilities_range;  // Indexes kCapabilitySpans
  // A set of extensions that enable this feature. If empty then this operand
  // value is in core and its availability is subject to minVersion. The
  // assembler, binary parser, and disassembler ignore this rule, so you can
  // freely process invalid modules.
  IndexRange extensions_range;  // Indexes kExtensionSpans
  // Minimal core SPIR-V version required for this feature, if without
  // extensions. ~0u means reserved for future use. ~0u and non-empty
  // extension lists means only available in extensions.
  uint32_t minVersion;
  uint32_t lastVersion;
  utils::Span<spv_operand_type_t> operands() const;
  utils::Span<char> name() const;
  utils::Span<IndexRange> aliases() const;
  utils::Span<spv::Capability> capabilities() const;
  utils::Span<spvtools::Extension> extensions() const;
  OperandDesc(const OperandDesc&) = delete;
  OperandDesc(OperandDesc&&) = delete;
};
""")

        def ShouldEmit(operand_kind_json: Dict[str,any]):
            """ Returns true if we should emit a table for the given
            operand kind.
            """
            category = operand_kind_json.get('category')
            return category in ['ValueEnum', 'BitEnum']

        # Populate kOperandsByValue
        operands_by_value: List[str] = []
        operands_by_value_by_kind: Dict[str,IndexRange] = {}
        # Maps the operand kind and value to the index into kOperandsByValue
        index_by_kind_and_value: Dict[Tuple(str,int),int] = {}
        index = 0
        for operand_kind_json in self.operand_kinds:
            kind_key: str = convert_operand_kind(operand_kind_json)
            if ShouldEmit(operand_kind_json):
                operands = [Operand(o) for o in operand_kind_json['enumerants']]
                operand_descs: List[str] = []
                for o in sorted(operands, key = lambda o: o.value):
                    suboperands = [convert_operand_kind(p) for p in o.parameters]
                    desc = [
                        o.value,
                        self.context.AddStringList('operand', suboperands),
                        str(self.context.AddString(o.enumerant)) + '/* {} */'.format(o.enumerant),
                        self.context.AddStringList('alias', o.aliases),
                        self.context.AddStringList('capability', o.capabilities),
                        self.context.AddStringList('extension', o.extensions),
                        convert_min_required_version(o.version),
                        convert_max_required_version(o.lastVersion),
                    ]
                    operand_descs.append('{' + ','.join([str(d) for d in desc]) + '}}, // {}'.format(kind_key))
                    index_by_kind_and_value[(kind_key,o.value)] = index
                    index += 1
                operands_by_value_by_kind[kind_key] = IndexRange(len(operands_by_value), len(operand_descs))
                operands_by_value.extend(operand_descs)
            else:
                pass

        parts = []
        parts.append("""// Operand descriptions, ordered by (operand kind, operand enum value).
// The fields in order are:
//   enum value
//   operands, an IndexRange into kOperandSpans
//   name, a character-counting IndexRange into kStrings
//   aliases, an IndexRange into kAliasSpans
//   capabilities, an IndexRange into kCapabilitySpans
//   extensions, as an IndexRange into kExtensionSpans
//   version, first version of SPIR-V that has it
//   lastVersion, last version of SPIR-V that has it""")
        parts.append("static const std::array<OperandDesc, {}> kOperandsByValue{{{{".format(len(operands_by_value)))
        parts.extend(['  ' + str(x) for x in operands_by_value])
        parts.append("}};\n")
        self.body_decls.extend(parts)

        parts = []
        parts.append("""// 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.
// An optional variant of a kind maps to the details for the corresponding
// concrete operand kind.""")
        parts.append("IndexRange OperandByValueRangeForKind(spv_operand_type_t type) {\n  switch(type) {")
        for kind_key, ir in operands_by_value_by_kind.items():
            parts.append("    case {}: return {};".format(
                kind_key,
                str(operands_by_value_by_kind[kind_key])))
        for kind in self.operand_kinds_needing_optional_variant:
            non_optional_kind = ctype(kind,'')
            if non_optional_kind in operands_by_value_by_kind:
                parts.append("    case {}: return {};".format(
                    ctype(kind, '?'),
                    str(operands_by_value_by_kind[ctype(kind,'')])))
            else:
                raise GrammarError(
                        "error: unknown operand type {}, from JSON grammar operand '{}':".format(non_optional_kind, kind) +
                        " consider updating spv_operand_type_t in spirv-tools/libspirv.h")
            
        parts.append("    default: break;");
        parts.append("  }\n  return IR(0,0);\n}\n")
        self.body_decls.extend(parts)

        # Populate kOperandNames
        operand_names: List[Tuple[IndexRange,int]] = []
        name_range_for_kind: Dict[str,IndexRange] = {}
        for operand_kind_json in self.operand_kinds:
            kind_key: str = convert_operand_kind(operand_kind_json)
            if ShouldEmit(operand_kind_json):
                operands = [Operand(o) for o in operand_kind_json['enumerants']]
                tuples: List[Tuple[str,int,str]] = []
                for o in operands:
                    tuples.append((o.enumerant, o.value, kind_key))
                    for a in o.aliases:
                        tuples.append((a, o.value, kind_key))
                tuples = sorted(tuples, key = lambda t: t[0])
                ir_tuples = [(self.context.AddString(t[0]),t[1],t[2]) for t in tuples]
                name_range_for_kind[kind_key] = IndexRange(len(operand_names), len(ir_tuples))
                operand_names.extend(ir_tuples)
            else:
                pass
        operand_name_strings: List[str] = []
        for i in range(0, len(operand_names)):
            ir, value, kind_key = operand_names[i]
            index = index_by_kind_and_value[(kind_key,value)]
            operand_name_strings.append('{{{}, {}}}, // {} {} in {}'.format(
                str(ir),index,i,self.context.GetString(ir),kind_key))

        parts: List[str] = []
        parts.append("""// Operand names and index into kOperandsByValue, ordered by (operand kind, name)
// The fields in order are:
//   name, either the primary name or an alias, indexing into kStrings
//   index into the kOperandsByValue array""")
        parts.append("static const std::array<NameIndex, {}> kOperandNames{{{{".format(len(operand_name_strings)))
        parts.extend(['  ' + str(x) for x in operand_name_strings])
        parts.append("}};\n")
        self.body_decls.extend(parts)

        parts.append("""// Maps an operand kind to possible names for operands of that kind.
// The result is an IndexRange into kOperandNames, and the names
// are sorted by name within that span.
// An optional variant of a kind maps to the details for the corresponding
// concrete operand kind.""")
        parts = ["IndexRange OperandNameRangeForKind(spv_operand_type_t type) {\n  switch(type) {"]
        for kind_key, ir in name_range_for_kind.items():
            parts.append("    case {}: return {};".format(
                kind_key,
                str(name_range_for_kind[kind_key])))
        for kind in self.operand_kinds_needing_optional_variant:
            parts.append("    case {}: return {};".format(
                ctype(kind, '?'),
                str(name_range_for_kind[ctype(kind,'')])))
        parts.append("    default: break;");
        parts.append("  }\n  return IR(0,0);\n}\n")
        self.body_decls.extend(parts)


    def ComputeInstructionTables(self, insts) -> None:
        """
        Creates declarations for instruction tables.
        Populates self.header_ignore_decls, self.body_decls.

        Params:
            insts: an array of instructions objects using the JSON schema
        """
        self.header_ignore_decls.append("""
// Describes an Instruction
struct InstructionDesc {
  const spv::Op value;
  const bool hasResult;
  const bool hasType;
  const IndexRange operands_range;      // Indexes kOperandSpans
  const IndexRange name_range;          // Indexes kStrings
  const IndexRange aliases_range;       // Indexes kAliasSpans
  const IndexRange capabilities_range;  // Indexes kCapbilitySpans
  // A set of extensions that enable this feature. If empty then this operand
  // value is in core and its availability is subject to minVersion. The
  // assembler, binary parser, and disassembler ignore this rule, so you can
  // freely process invalid modules.
  const IndexRange extensions_range;    // Indexes kExtensionSpans
  // Minimal core SPIR-V version required for this feature, if without
  // extensions. ~0u means reserved for future use. ~0u and non-empty
  // extension lists means only available in extensions.
  uint32_t minVersion;
  uint32_t lastVersion;
  PrintingClass printingClass; // Section of SPIR-V spec. e.g. kComposite, kImage
  utils::Span<spv_operand_type_t> operands() const;
  utils::Span<char> name() const;
  utils::Span<IndexRange> aliases() const;
  utils::Span<spv::Capability> capabilities() const;
  utils::Span<spvtools::Extension> extensions() const;
  OperandDesc(const OperandDesc&) = delete;
  OperandDesc(OperandDesc&&) = delete;
};
""")

        # Create the array of InstructionDesc
        lines: List[str] = []
        # Maps the opcode name (without "Op" prefix) to its index in the table.
        index_by_opcode: Dict[int,int] = {}
        # Sort by opcode, so lookup can use binary search
        for inst in sorted(insts, key = lambda inst: int(inst['opcode'])):
            parts: List[str] = []

            opname: str = inst['opname']

            operand_kinds = [convert_operand_kind(o) for o in inst.get('operands',[])]
            if opname == 'OpExtInst' and operand_kinds[-1] == 'SPV_OPERAND_TYPE_VARIABLE_ID':
                # The published grammar uses 'sequence of ID' at the
                # end of the ExtInst operands. But SPIRV-Tools uses
                # a specific pattern based on the particular opcode.
                # Drop it here.
                # See https://github.com/KhronosGroup/SPIRV-Tools/issues/233
                operand_kinds.pop()

            hasResult = 'SPV_OPERAND_TYPE_RESULT_ID' in operand_kinds
            hasType = 'SPV_OPERAND_TYPE_TYPE_ID' in operand_kinds

            # Remove the "Op" prefix from opcode alias names
            aliases = [name[2:] for name in inst.get('aliases',[])]

            parts.extend([
                'spv::Op::' + opname,
                c_bool(hasResult),
                c_bool(hasType),
                self.context.AddStringList('operand', operand_kinds),
                self.context.AddString(opname[2:]),
                self.context.AddStringList('alias', aliases),
                self.context.AddStringList('capability', inst.get('capabilities',[])),
                self.context.AddStringList('extension', inst.get('extensions',[])),
                convert_min_required_version(inst.get('version', None)),
                convert_max_required_version(inst.get('lastVersion', None)),
                'PrintingClass::' + to_safe_identifier(inst.get('class','@exclude'))
            ])

            index_by_opcode[int(inst['opcode'])] = len(lines)
            lines.append('{{{}}},'.format(', '.join([str(x) for x in parts])))
        parts = []
        parts.append("""// Instruction descriptions, ordered by opcode.
// The fields in order are:
//   opcode
//   a boolean indicating if the instruction produces a result ID
//   a boolean indicating if the instruction result ID has a type
//   operands, an IndexRange into kOperandSpans
//   opcode name (without the 'Op' prefix), a character-counting IndexRange into kStrings
//   aliases, an IndexRange into kAliasSpans
//   capabilities, an IndexRange into kCapabilitySpans
//   extensions, as an IndexRange into kExtensionSpans
//   version, first version of SPIR-V that has it
//   lastVersion, last version of SPIR-V that has it""")
        parts.append("static const std::array<InstructionDesc, {}> kInstructionDesc{{{{".format(len(lines)));
        parts.extend(['  ' + l for l in lines])
        parts.append("}};\n");
        self.body_decls.extend(parts)

        # Create kInstructionNames.
        opcode_name_entries: List[str] = []
        name_value_pairs: List[Tuple[str,int]] = []
        for i in insts:
            name_value_pairs.append((i['opname'][2:], i['opcode']))
            for a in i.get('aliases',[]):
                name_value_pairs.append((a[2:], i['opcode']))
        name_value_pairs = sorted(name_value_pairs)
        inst_name_strings: List[str] = []
        for i in range(0, len(name_value_pairs)):
            name, value = name_value_pairs[i]
            ir = self.context.AddString(name)
            index = index_by_opcode[value]
            inst_name_strings.append('{{{}, {}}}, // {} {}'.format(str(ir),index,i,name))
        parts: List[str] = []
        parts.append("""// Opcode strings (without the 'Op' prefix) and opcode values, ordered by name.
// The fields in order are:
//   name, either the primary name or an alias, indexing into kStrings
//   index into kInstructionDesc""")
        parts.append("static const std::array<NameIndex, {}> kInstructionNames{{{{".format(len(inst_name_strings)))
        parts.extend(['  ' + str(x) for x in inst_name_strings])
        parts.append("}};\n")
        self.body_decls.extend(parts)


    def ComputeExtendedInstructions(self, extinsts) -> None:
        """
        Generates tables for extended instructions

        Args:
            self
            extinsts: a list of extinst objects
        """

        """
            ExtInstDesc {
             value:         uint32_t
             name:          IndexRange
             operands:      IndexRange
             capabilities:  IndexRange
            }

        The definitions are:
         - kExtInstByValue: a 1-dimensional array of all operand descriptions
           sorted first by extended instruction enum, then by operand value.

         - ExtInstByValueRangeForKind: a function mapping from extinst enum to
           the index range into kExtInstByValue.

         - kExtInstNames: a 1-dimensional array of all extinst name-index pairs,
           sorted first by extinst enum, then by operand name.
           The name part is represented by an index range into the string table.
           The index part is the index of this name's entry in the kExtInstByValue
           array.

         - kExtInstNamesRangeByKind: a mapping from operand kind to the index
           range into kOperandNames.
           This has mappings for both concrete and corresponding optional operand kinds.
        """

        # Create kExtInstByValue
        by_value: List[List[Any]] = []
        by_value_by_kind: Dict[str,IndexRange] = {}
        index_by_kind_and_opcode: Dict[Tuple[str,int],int] = {}
        index = 0
        for e in extinsts:
            insts_in_set = []
            for inst in sorted(e.grammar['instructions'], key = lambda inst: inst['opcode']):
                operands = [convert_operand_kind(o) for o in inst.get('operands',[])]
                inst_parts = [
                    inst['opcode'],
                    self.context.AddStringList('operand', operands),
                    self.context.AddString(inst['opname']),
                    self.context.AddStringList('capability', inst.get('capabilities',[])),
                ]
                inst_parts = [str(x) for x in inst_parts]
                insts_in_set.append('    {{{}}}, // {} in {}'.format(
                        ','.join(inst_parts), inst['opname'], e.name))
                index_by_kind_and_opcode[(e.enum_name,int(inst['opcode']))] = index
                index += 1
            by_value_by_kind[e.enum_name] = IndexRange(len(by_value), len(insts_in_set))
            by_value.extend(insts_in_set)

        parts: List[str] = []
        parts.append("""// Extended instruction descriptions, ordered by (extinst enum, opcode value).
// The fields in order are:
//   enum value
//   operands, an IndexRange into kOperandSpans
//   name, a character-counting IndexRange into kStrings
//   capabilities, an IndexRange into kCapabilitySpans""")
        parts.append("static const std::array<ExtInstDesc, {}> kExtInstByValue{{{{".format(len(by_value)))
        parts.extend(by_value)
        parts.append('}};\n')
        self.body_decls.extend(parts)

        # Create kExtInstByValueRangeForKind
        parts = []
        parts.append("""// Maps an extended instruction enum to possible names for operands of that kind.
// The result is an IndexRange into kOperandNames, and the names
// are sorted by name within that span.
// An optional variant of a kind maps to the details for the corresponding
// concrete operand kind.""")
        parts = ["IndexRange ExtInstByValueRangeForKind(spv_ext_inst_type_t type) {\n  switch(type) {"]
        for name, ir in by_value_by_kind.items():
            parts.append("    case {}: return {};".format(name, ir))
        parts.append("    default: break;");
        parts.append("  }\n  return IR(0,0);\n}\n")
        self.body_decls.extend(parts)

        # Create kExtInstNames
        parts = []
        by_name: List[List[Any]] = []
        by_name_by_kind: Dict[str,IndexRange] = {}
        for e in extinsts:
            # Sort by name within a set
            insts_by_name = sorted(e.grammar['instructions'], key = lambda i: i['opname'])
            insts_in_set = []
            for inst in insts_by_name:
                index = index_by_kind_and_opcode[(e.enum_name,int(inst['opcode']))]
                insts_in_set.append(
                        '    {{{}, {}}}, // {} in {}'.format(
                                str(self.context.AddString(inst['opname'])),
                                index,
                                inst['opname'],
                                e.name))
            by_name_by_kind[e.enum_name] = IndexRange(len(by_name), len(insts_in_set))
            by_name.extend(insts_in_set)
        parts.append("""// Extended instruction opcode names sorted by extended instruction kind, then opcode name.
// The fields in order are:
//   name
//   index into kExtInstByValue""")
        parts.append("static const std::array<NameIndex, {}> kExtInstNames{{{{".format(len(by_name)))
        parts.extend(by_name)
        parts.append('}};\n')
        self.body_decls.extend(parts)

        # Create kExtInstNameRangeByKind
        parts = []
        parts.append("""// Maps an extended instruction kind to possible names for instructions of that kind.
// The result is an IndexRange into kExtInstNames, and the names
// are sorted by name within that span.""")
        parts = ["IndexRange ExtInstNameRangeForKind(spv_ext_inst_type_t type) {\n  switch(type) {"]
        for name, ir in by_name_by_kind.items():
            parts.append("    case {}: return {};".format(name, str(ir)))
        parts.append("    default: break;");
        parts.append("  }\n  return IR(0,0);\n}\n")
        self.body_decls.extend(parts)

    def ComputeLeafTables(self) -> None:
        """
        Generates the tables that the instruction and operand tables point to.
        The tables are:
            - the string table
            - the table of sequences of:
               - capabilities
               - extensions
               - operands

        This method must be called after computing instruction and operand tables.
        """

        def c_str(s: str):
            """
            Returns the source for a C string literal or the given string, including
            the explicit null at the end
            """
            return '"{}\\0"'.format(json.dumps(s).strip('"'))

        parts: List[str] = []
        parts.append("// Array of characters, referenced by IndexRanges elsewhere.")
        parts.append("// Each IndexRange denotes a string.")
        parts.append('static const char kStrings[] =');
        parts.extend(['  {} // {}'.format(c_str(s), str(self.context.strings[s])) for s in self.context.string_buffer])
        parts.append(';\n');
        self.body_decls.extend(parts);

        parts: List[str] = []
        parts.append("""// 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.""")
        parts.append('static const IndexRange kAliasSpans[] = {');
        ranges = self.context.range_buffer['alias']
        for i in range(0, len(ranges)):
            ir = ranges[i]
            parts.append('  {}, // {} {}'.format(str(ir), i, self.context.GetString(ir)))
        parts.append('};\n');
        self.body_decls.extend(parts);

        parts = []
        parts.append("// Array of capabilities, referenced by IndexRanges elsewhere.")
        parts.append("// Contains all sequences of capabilities used in the grammar.")
        parts.append('static const spv::Capability kCapabilitySpans[] = {');
        capability_ranges = self.context.range_buffer['capability']
        for i in range(0, len(capability_ranges)):
            ir = capability_ranges[i]
            cap = self.context.GetString(ir)
            parts.append('  spv::Capability::{}, // {}'.format(cap, i))
        parts.append('};\n');
        self.body_decls.extend(parts);

        parts = []
        parts.append("// Array of extensions, referenced by IndexRanges elsewhere.")
        parts.append("// Contains all sequences of extensions used in the grammar.")
        parts.append('static const spvtools::Extension kExtensionSpans[] = {');
        ranges = self.context.range_buffer['extension']
        for i in range(0, len(ranges)):
            ir = ranges[i]
            name = self.context.GetString(ir)
            parts.append('  spvtools::Extension::k{}, // {}'.format(name, i))
        parts.append('};\n');
        self.body_decls.extend(parts);

        parts = []
        parts.append("// Array of operand types, referenced by IndexRanges elsewhere.")
        parts.append("// Contains all sequences of operand types used in the grammar.")
        parts.append('static const spv_operand_type_t kOperandSpans[] = {');
        ranges = self.context.range_buffer['operand']
        for i in range(0, len(ranges)):
            ir = ranges[i]
            name = self.context.GetString(ir)
            parts.append('  {}, // {}'.format(name, i))
        parts.append('};\n');
        self.body_decls.extend(parts)


def make_path_to_file(f: str) -> None:
    """Makes all ancestor directories to the given file, if they don't yet
    exist.

    Arguments:
        f: The file whose ancestor directories are to be created.
    """
    dir = os.path.dirname(os.path.abspath(f))
    try:
        os.makedirs(dir)
    except OSError as e:
        if e.errno == errno.EEXIST and os.path.isdir(dir):
            pass
        else:
            raise


def get_extension_list(instructions, operand_kinds):
    """Returns extensions as an alphabetically sorted list of strings.

    Args:
      instructions: list of instruction objects, using the JSON grammar file schema
      operand_kinds: list of operand_kind objects, using the JSON grammar file schema
    """

    things_with_an_extensions_field = [item for item in instructions]

    enumerants = sum([item.get('enumerants', [])
                      for item in operand_kinds], [])

    things_with_an_extensions_field.extend(enumerants)

    extensions = sum([item.get('extensions', [])
                      for item in things_with_an_extensions_field
                      if item.get('extensions')], [])

    for item in EXTENSIONS_FROM_SPIRV_REGISTRY_AND_NOT_FROM_GRAMMARS.split():
            # If it's already listed in a grammar, then don't put it in the
            # special exceptions list.
        assert item not in extensions, 'Extension %s is already in a grammar file' % item

    extensions.extend(
        EXTENSIONS_FROM_SPIRV_REGISTRY_AND_NOT_FROM_GRAMMARS.split())

    # Validator would ignore type declaration unique check. Should only be used
    # for legacy autogenerated test files containing multiple instances of the
    # same type declaration, if fixing the test by other methods is too
    # difficult. Shouldn't be used for any other reasons.
    extensions.append('SPV_VALIDATOR_ignore_type_decl_unique')

    return sorted(set(extensions))


def prefix_operand_kind_names(prefix, json_dict):
    """Modifies json_dict, by prefixing all the operand kind names
    with the given prefix.  Also modifies their uses in the instructions
    to match.
    """

    old_to_new = {}
    for operand_kind in json_dict["operand_kinds"]:
        old_name = operand_kind["kind"]
        new_name = prefix + old_name
        operand_kind["kind"] = new_name
        old_to_new[old_name] = new_name

    for instruction in json_dict["instructions"]:
        for operand in instruction.get("operands", []):
            replacement = old_to_new.get(operand["kind"])
            if replacement is not None:
                operand["kind"] = replacement


def main():
    import argparse
    parser = argparse.ArgumentParser(description='Generate SPIR-V info tables')

    parser.add_argument('--spirv-core-grammar', metavar='<path>',
                        type=str, required=False,
                        help='input JSON grammar file for core SPIR-V '
                        'instructions')
    parser.add_argument('--extinst', metavar='<path>',
                        type=str, action='append', required=False, default=None,
                        help='extended instruction info: an enum prefix, then a comma, then'
                        ' the file location of the JSON grammar')

    parser.add_argument('--core-tables-body-output', metavar='<path>',
                        type=str, required=False, default=None,
                        help='output file for core SPIR-V grammar tables to be included in .cpp')
    parser.add_argument('--core-tables-header-output', metavar='<path>',
                        type=str, required=False, default=None,
                        help='output file for core SPIR-V grammar tables to be included in .h')

    args = parser.parse_args()

    if args.spirv_core_grammar is None:
        print('error: missing --spirv-core-grammar ')
        sys.exit(1)
    if (args.core_tables_body_output is None) and (args.core_tables_header_output is None):
        print('error: need at least one of --core-tables-body-output --core-tables-header-output ')
        sys.exit(1)
    if len(args.extinst) < 1:
        print('error: missing --extinst ')
        sys.exit(1)

    # Load the JSON grammar files.
    extinsts = sorted([ExtInst(e) for e in args.extinst], key = lambda e: e.name)
    with open(args.spirv_core_grammar) as json_file:
        core_grammar = json.loads(json_file.read())
        printing_class: List[str] = [e['tag'] for e in core_grammar['instruction_printing_class']]

    # Collect all operand kinds and instructions, so we can generate
    # extension lists, capability lists, and alias lists.
    # Make a copy to avoid polluting the instruction list.
    instructions = [x for x in core_grammar['instructions']]
    operand_kinds = [x for x in core_grammar['operand_kinds']]
    for e in extinsts:
        instructions.extend(e.grammar.get('instructions',[]))
        operand_kinds.extend(e.grammar.get('operand_kinds',[]))

    extensions = get_extension_list(instructions, operand_kinds)

    g = Grammar(extensions, operand_kinds, printing_class)
    g.ComputeOperandTables()
    g.ComputeInstructionTables(core_grammar['instructions'])
    g.ComputeExtendedInstructions(extinsts)
    g.ComputeLeafTables()

    if args.core_tables_body_output is not None:
        make_path_to_file(args.core_tables_body_output)
        with open(args.core_tables_body_output, 'w') as f:
            f.write('\n'.join(g.body_decls))
    if args.core_tables_header_output is not None:
        make_path_to_file(args.core_tables_header_output)
        with open(args.core_tables_header_output, 'w') as f:
            f.write('\n'.join(g.header_decls))
    sys.exit(0)


if __name__ == '__main__':
  try:
    main()
  except GrammarError as ge:
    print(ge)
    sys.exit(1)
