| // 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_ |