mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-02-17 20:52:36 +01:00
Updated spirv-tools.
This commit is contained in:
143
3rdparty/spirv-tools/source/opcode.cpp
vendored
143
3rdparty/spirv-tools/source/opcode.cpp
vendored
@@ -27,18 +27,10 @@
|
||||
#include "source/spirv_constant.h"
|
||||
#include "source/spirv_endian.h"
|
||||
#include "source/spirv_target_env.h"
|
||||
#include "source/table2.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
namespace {
|
||||
struct OpcodeDescPtrLen {
|
||||
const spv_opcode_desc_t* ptr;
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
#include "core.insts-unified1.inc"
|
||||
|
||||
static const spv_opcode_table_t kOpcodeTable = {ARRAY_SIZE(kOpcodeTableEntries),
|
||||
kOpcodeTableEntries};
|
||||
|
||||
// Represents a vendor tool entry in the SPIR-V XML Registry.
|
||||
struct VendorTool {
|
||||
@@ -78,115 +70,6 @@ void spvOpcodeSplit(const uint32_t word, uint16_t* pWordCount,
|
||||
}
|
||||
}
|
||||
|
||||
spv_result_t spvOpcodeTableGet(spv_opcode_table* pInstTable, spv_target_env) {
|
||||
if (!pInstTable) return SPV_ERROR_INVALID_POINTER;
|
||||
|
||||
// Descriptions of each opcode. Each entry describes the format of the
|
||||
// instruction that follows a particular opcode.
|
||||
|
||||
*pInstTable = &kOpcodeTable;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
spv_result_t spvOpcodeTableNameLookup(spv_target_env env,
|
||||
const spv_opcode_table table,
|
||||
const char* name,
|
||||
spv_opcode_desc* pEntry) {
|
||||
if (!name || !pEntry) return SPV_ERROR_INVALID_POINTER;
|
||||
if (!table) return SPV_ERROR_INVALID_TABLE;
|
||||
|
||||
// TODO: This lookup of the Opcode table is suboptimal! Binary sort would be
|
||||
// preferable but the table requires sorting on the Opcode name, but it's
|
||||
// static const initialized and matches the order of the spec.
|
||||
const size_t nameLength = strlen(name);
|
||||
const auto version = spvVersionForTargetEnv(env);
|
||||
for (uint64_t opcodeIndex = 0; opcodeIndex < table->count; ++opcodeIndex) {
|
||||
const spv_opcode_desc_t& entry = table->entries[opcodeIndex];
|
||||
// We consider the current opcode as available as long as
|
||||
// 1. The target environment satisfies the minimal requirement of the
|
||||
// opcode; or
|
||||
// 2. There is at least one extension enabling this opcode.
|
||||
//
|
||||
// Note that the second rule assumes the extension enabling this instruction
|
||||
// is indeed requested in the SPIR-V code; checking that should be
|
||||
// validator's work.
|
||||
if ((version >= entry.minVersion && version <= entry.lastVersion) ||
|
||||
entry.numExtensions > 0u || entry.numCapabilities > 0u) {
|
||||
// Exact match case.
|
||||
if (nameLength == strlen(entry.name) &&
|
||||
!strncmp(name, entry.name, nameLength)) {
|
||||
*pEntry = &entry;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
// Lack of binary search really hurts here. There isn't an easy filter to
|
||||
// apply before checking aliases since we need to handle promotion from
|
||||
// vendor to KHR/EXT and KHR/EXT to core. It would require a sure-fire way
|
||||
// of dropping suffices. Fortunately, most lookup are based on token
|
||||
// value.
|
||||
//
|
||||
// If this was a binary search we could iterate between the lower and
|
||||
// upper bounds.
|
||||
if (entry.numAliases > 0) {
|
||||
for (uint32_t aliasIndex = 0; aliasIndex < entry.numAliases;
|
||||
aliasIndex++) {
|
||||
// Skip Op prefix. Should this be encoded in the table instead?
|
||||
const auto alias = entry.aliases[aliasIndex] + 2;
|
||||
const size_t aliasLength = strlen(alias);
|
||||
if (nameLength == aliasLength && !strncmp(name, alias, nameLength)) {
|
||||
*pEntry = &entry;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_ERROR_INVALID_LOOKUP;
|
||||
}
|
||||
|
||||
spv_result_t spvOpcodeTableValueLookup(spv_target_env env,
|
||||
const spv_opcode_table table,
|
||||
const spv::Op opcode,
|
||||
spv_opcode_desc* pEntry) {
|
||||
if (!table) return SPV_ERROR_INVALID_TABLE;
|
||||
if (!pEntry) return SPV_ERROR_INVALID_POINTER;
|
||||
|
||||
const auto beg = table->entries;
|
||||
const auto end = table->entries + table->count;
|
||||
|
||||
spv_opcode_desc_t needle = {"", opcode, 0, nullptr, 0, {}, 0,
|
||||
{}, false, false, 0, nullptr, ~0u, ~0u};
|
||||
|
||||
auto comp = [](const spv_opcode_desc_t& lhs, const spv_opcode_desc_t& rhs) {
|
||||
return lhs.opcode < rhs.opcode;
|
||||
};
|
||||
|
||||
// We need to loop here because there can exist multiple symbols for the same
|
||||
// opcode value, and they can be introduced in different target environments,
|
||||
// which means they can have different minimal version requirements.
|
||||
// Assumes the underlying table is already sorted ascendingly according to
|
||||
// opcode value.
|
||||
const auto version = spvVersionForTargetEnv(env);
|
||||
for (auto it = std::lower_bound(beg, end, needle, comp);
|
||||
it != end && it->opcode == opcode; ++it) {
|
||||
// We considers the current opcode as available as long as
|
||||
// 1. The target environment satisfies the minimal requirement of the
|
||||
// opcode; or
|
||||
// 2. There is at least one extension enabling this opcode.
|
||||
//
|
||||
// Note that the second rule assumes the extension enabling this instruction
|
||||
// is indeed requested in the SPIR-V code; checking that should be
|
||||
// validator's work.
|
||||
if ((version >= it->minVersion && version <= it->lastVersion) ||
|
||||
it->numExtensions > 0u || it->numCapabilities > 0u) {
|
||||
*pEntry = it;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return SPV_ERROR_INVALID_LOOKUP;
|
||||
}
|
||||
|
||||
void spvInstructionCopy(const uint32_t* words, const spv::Op opcode,
|
||||
const uint16_t wordCount, const spv_endianness_t endian,
|
||||
spv_instruction_t* pInst) {
|
||||
@@ -205,25 +88,13 @@ void spvInstructionCopy(const uint32_t* words, const spv::Op opcode,
|
||||
}
|
||||
|
||||
const char* spvOpcodeString(const uint32_t opcode) {
|
||||
const auto beg = kOpcodeTableEntries;
|
||||
const auto end = kOpcodeTableEntries + ARRAY_SIZE(kOpcodeTableEntries);
|
||||
spv_opcode_desc_t needle = {"", static_cast<spv::Op>(opcode),
|
||||
0, nullptr,
|
||||
0, {},
|
||||
0, {},
|
||||
false, false,
|
||||
0, nullptr,
|
||||
~0u, ~0u};
|
||||
auto comp = [](const spv_opcode_desc_t& lhs, const spv_opcode_desc_t& rhs) {
|
||||
return lhs.opcode < rhs.opcode;
|
||||
};
|
||||
auto it = std::lower_bound(beg, end, needle, comp);
|
||||
if (it != end && it->opcode == spv::Op(opcode)) {
|
||||
return it->name;
|
||||
const spvtools::InstructionDesc* desc = nullptr;
|
||||
if (SPV_SUCCESS !=
|
||||
spvtools::LookupOpcode(static_cast<spv::Op>(opcode), &desc)) {
|
||||
assert(0 && "Unreachable!");
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
assert(0 && "Unreachable!");
|
||||
return "unknown";
|
||||
return desc->name().data();
|
||||
}
|
||||
|
||||
const char* spvOpcodeString(const spv::Op opcode) {
|
||||
|
||||
Reference in New Issue
Block a user