Updated spirv-tools.

This commit is contained in:
Бранимир Караџић
2025-05-10 19:57:06 -07:00
parent 486853494e
commit 3ef67d3eb0
84 changed files with 12022 additions and 4075 deletions

View File

@@ -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) {