blob: e3731c43293a848f74b7cdc5ee37f1959370852d [file] [log] [blame]
// Copyright (c) 2025 The Khronos Group Inc.
// 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.
#ifndef SOURCE_TABLE2_H_
#define SOURCE_TABLE2_H_
#include "source/latest_version_spirv_header.h"
#include "source/util/index_range.h"
#include "spirv-tools/libspirv.hpp"
// Define the objects that describe the grammatical structure of SPIR-V
// instructions and their operands. The objects are owned by static
// tables populated at C++ build time from the grammar files from SPIRV-Headers.
//
// Clients use freestanding methods to lookup an opcode or an operand, either
// by numeric value (in the binary), or by name.
//
// For historical reasons, the opcode lookup can also use a target enviroment
// enum to filter for opcodes supported in that environment.
//
// It should be very fast for the system loader to load (and possibly relocate)
// the static tables. In particular, there should be very few global symbols
// with independent addresses. Prefer a very few large tables of items rather
// than dozens or hundreds of global symbols.
//
// The overall structure among containers (i.e. skipping scalar data members)
// is as follows:
//
// An OperandDesc describes an operand.
// An InstructionDesc desribes an instruction.
// An ExtInstDesc describes an extended intruction.
//
// Both OperandDesc and InstructionDesc have members:
// - a name string
// - array of alias strings
// - array of spv::Capability (as an enum)
// - array of spv_operand_type_t (as an enum)
// - array of spvtools::Extension (as an enum)
// - a minVersion
// - a lastVersion
//
// An OperandDesc also has:
// - a uint32_t value.
//
// An InstructionDesc also has:
// - a spv::Op opcode
// - a bool hasResult
// - a bool hasType
// - a printing class
//
// An ExtInstDesc has:
// - a name
// - array of spv::Capability (as an enum)
// - array of spv_operand_type_t (as an enum)
//
// The arrays are represented by spans into a global static array, with one
// array for each of:
// - null-terminated strings, for names
// - arrays of null-terminated strings, for alias lists
// - spv_operand_type_t
// - spv::Capability
// - spvtools::Extension
//
// Note: Currently alias lists never have more than one element.
// The data structures and code do not assume this.
// TODO(dneto): convert the tables for extended instructions
// Currently (as defined in table.h):
// An spv_ext_inst_group_t has:
// - array of spv_ext_inst_desc_t
//
// An spv_ext_inst_desc_t has:
// - a name string
// - array of spv::Capability
// - array of spv_operand_type_t
namespace spvtools {
#include "core_tables_header.inc"
using IndexRange = utils::IndexRange<uint32_t, uint32_t>;
// Describes a SPIR-V operand.
struct OperandDesc {
const uint32_t value;
const IndexRange operands_range; // Indexes kOperandSpans
const IndexRange name_range; // Indexes kStrings
const IndexRange aliases_range; // Indexes kAliasSpans
const 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.
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.
const uint32_t minVersion = 0xFFFFFFFFu;
const uint32_t lastVersion = 0xFFFFFFFFu;
utils::Span<const spv_operand_type_t> operands() const;
utils::Span<const char> name() const;
utils::Span<const IndexRange> aliases() const;
utils::Span<const spv::Capability> capabilities() const;
utils::Span<const spvtools::Extension> extensions() const;
constexpr OperandDesc(uint32_t v, IndexRange o, IndexRange n, IndexRange a,
IndexRange c, IndexRange e, uint32_t mv, uint32_t lv)
: value(v),
operands_range(o),
name_range(n),
aliases_range(a),
capabilities_range(c),
extensions_range(e),
minVersion(mv),
lastVersion(lv) {}
constexpr OperandDesc(uint32_t v) : value(v) {}
OperandDesc(const OperandDesc&) = delete;
OperandDesc(OperandDesc&&) = delete;
};
// Describes an Instruction
struct InstructionDesc {
const spv::Op opcode;
const bool hasResult = false;
const bool hasType = false;
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.
const uint32_t minVersion = 0xFFFFFFFFu;
const uint32_t lastVersion = 0xFFFFFFFFu;
// The printing class specifies what kind of instruction it is, e.g. what
// section of the SPIR-V spec. E.g. kImage, kComposite
const PrintingClass printingClass = PrintingClass::kReserved;
// Returns the span of elements in the global grammar tables corresponding
// to the privately-stored index ranges
utils::Span<const spv_operand_type_t> operands() const;
utils::Span<const char> name() const;
utils::Span<const IndexRange> aliases() const;
utils::Span<const spv::Capability> capabilities() const;
utils::Span<const spvtools::Extension> extensions() const;
constexpr InstructionDesc(spv::Op oc, bool hr, bool ht, IndexRange o,
IndexRange n, IndexRange a, IndexRange c,
IndexRange e, uint32_t mv, uint32_t lv,
PrintingClass pc)
: opcode(oc),
hasResult(hr),
hasType(ht),
operands_range(o),
name_range(n),
aliases_range(a),
capabilities_range(c),
extensions_range(e),
minVersion(mv),
lastVersion(lv),
printingClass(pc) {}
constexpr InstructionDesc(spv::Op oc) : opcode(oc) {}
InstructionDesc(const InstructionDesc&) = delete;
InstructionDesc(InstructionDesc&&) = delete;
};
// Describes an extended instruction
struct ExtInstDesc {
const uint32_t value;
const IndexRange operands_range; // Indexes kOperandSpans
const IndexRange name_range; // Indexes kStrings
const IndexRange capabilities_range; // Indexes kCapbilitySpans
// Returns the span of elements in the global grammar tables corresponding
// to the privately-stored index ranges
utils::Span<const spv_operand_type_t> operands() const;
utils::Span<const char> name() const;
utils::Span<const spv::Capability> capabilities() const;
constexpr ExtInstDesc(uint32_t v, IndexRange o, IndexRange n, IndexRange c)
: value(v), operands_range(o), name_range(n), capabilities_range(c) {}
constexpr ExtInstDesc(uint32_t v) : value(v) {}
ExtInstDesc(const ExtInstDesc&) = delete;
ExtInstDesc(ExtInstDesc&&) = delete;
};
// Finds the instruction description by opcode name. The name should not
// have the "Op" prefix. On success, returns SPV_SUCCESS and updates *desc.
spv_result_t LookupOpcode(const char* name, const InstructionDesc** desc);
// Finds the instruction description by opcode value.
// On success, returns SPV_SUCCESS and updates *desc.
spv_result_t LookupOpcode(spv::Op opcode, const InstructionDesc** desc);
// Finds the instruction description by opcode name, without the "Op" prefix.
// A lookup will succeed if:
// - The instruction exists, and
// - Either the target environment supports the SPIR-V version of the
// instruction,
// or the instruction is enabled by at least one extension,
// or the instruction is enabled by at least one capability.,
// On success, returns SPV_SUCCESS and updates *desc.
spv_result_t LookupOpcodeForEnv(spv_target_env env, const char* name,
const InstructionDesc** desc);
// Finds the instruction description by opcode value.
// A lookup will succeed if:
// - The instruction exists, and
// - Either the target environment supports the SPIR-V version of the
// instruction,
// or the instruction is enabled by at least one extension,
// or the instruction is enabled by at least one capability.,
// On success, returns SPV_SUCCESS and updates *desc.
spv_result_t LookupOpcodeForEnv(spv_target_env env, spv::Op,
const InstructionDesc** desc);
spv_result_t LookupOperand(spv_operand_type_t type, const char* name,
size_t name_len, const OperandDesc** desc);
spv_result_t LookupOperand(spv_operand_type_t type, uint32_t operand,
const OperandDesc** desc);
// Finds the extended instruction description by opcode name.
// On success, returns SPV_SUCCESS and updates *desc.
spv_result_t LookupExtInst(spv_ext_inst_type_t type, const char* name,
const ExtInstDesc** desc);
// 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);
// Finds Extension enum corresponding to |str|. Returns false if not found.
bool GetExtensionFromString(const char* str, Extension* extension);
// Returns text string corresponding to |extension|.
const char* ExtensionToString(Extension extension);
} // namespace spvtools
#endif // SOURCE_TABLE2_H_