mirror of
https://gitee.com/openharmony/third_party_spirv-tools
synced 2024-11-23 15:30:36 +00:00
Turn all function static non-POD variables into global POD variables
Function static non-POD data causes problems with DLL lifetime. This pull request turns all static info tables into strict POD tables. Specifically, the capabilities/extensions field of opcode/operand/extended-instruction table are turned into two fields, one for the count and the other a pointer to an array of capabilities/extensions. CapabilitySet/EnumSet are not used in the static table anymore, but they are still used for checking inclusion by constructing on the fly, which should be cheap for the majority cases. Also moves all these tables into the global namespace to avoid C++11 function static thread-safe initialization overhead.
This commit is contained in:
parent
90862fe4b1
commit
063dbea0f1
@ -46,6 +46,9 @@ class EnumSet {
|
||||
EnumSet(std::initializer_list<EnumType> cs) {
|
||||
for (auto c : cs) Add(c);
|
||||
}
|
||||
EnumSet(uint32_t count, const EnumType* ptr) {
|
||||
for (uint32_t i = 0; i < count; ++i) Add(ptr[i]);
|
||||
}
|
||||
// Copy constructor.
|
||||
EnumSet(const EnumSet& other) { *this = other; }
|
||||
// Move constructor. The moved-from set is emptied.
|
||||
@ -95,15 +98,12 @@ class EnumSet {
|
||||
bool HasAnyOf(const EnumSet<EnumType>& in_set) const {
|
||||
if (in_set.IsEmpty()) return true;
|
||||
|
||||
if (mask_ & in_set.mask_)
|
||||
return true;
|
||||
if (mask_ & in_set.mask_) return true;
|
||||
|
||||
if (!overflow_ || !in_set.overflow_)
|
||||
return false;
|
||||
if (!overflow_ || !in_set.overflow_) return false;
|
||||
|
||||
for (uint32_t item : *in_set.overflow_) {
|
||||
if (overflow_->find(item) != overflow_->end())
|
||||
return true;
|
||||
if (overflow_->find(item) != overflow_->end()) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -19,9 +19,9 @@
|
||||
|
||||
#include "spirv/1.1/spirv.h"
|
||||
|
||||
namespace libspirv {
|
||||
#include "extensions.h"
|
||||
|
||||
enum class Extension;
|
||||
namespace libspirv {
|
||||
|
||||
// Finds Extension enum corresponding to |str|. Returns false if not found.
|
||||
bool GetExtensionFromString(const std::string& str, Extension* extension);
|
||||
|
@ -23,40 +23,17 @@
|
||||
|
||||
#include "macro.h"
|
||||
|
||||
spv_result_t spvExtInstTableGet(spv_ext_inst_table* pExtInstTable,
|
||||
spv_target_env env) {
|
||||
if (!pExtInstTable) return SPV_ERROR_INVALID_POINTER;
|
||||
#include "glsl.std.450.insts-1.0.inc" // defines glsl_entries
|
||||
#include "opencl.std.insts-1.0.inc" // defines opencl_entries
|
||||
|
||||
static const spv_ext_inst_desc_t glslStd450Entries_1_0[] = {
|
||||
#include "glsl.std.450.insts-1.0.inc"
|
||||
};
|
||||
|
||||
static const spv_ext_inst_desc_t openclEntries_1_0[] = {
|
||||
#include "opencl.std.insts-1.0.inc"
|
||||
};
|
||||
|
||||
static const spv_ext_inst_desc_t
|
||||
spv_amd_shader_explicit_vertex_parameter_entries[] = {
|
||||
#include "spv-amd-shader-explicit-vertex-parameter.insts.inc"
|
||||
};
|
||||
|
||||
static const spv_ext_inst_desc_t spv_amd_shader_trinary_minmax_entries[] = {
|
||||
#include "spv-amd-shader-trinary-minmax.insts.inc"
|
||||
};
|
||||
|
||||
static const spv_ext_inst_desc_t spv_amd_gcn_shader_entries[] = {
|
||||
#include "spv-amd-gcn-shader.insts.inc"
|
||||
};
|
||||
|
||||
static const spv_ext_inst_desc_t spv_amd_shader_ballot_entries[] = {
|
||||
#include "spv-amd-shader-ballot.insts.inc"
|
||||
};
|
||||
#include "spv-amd-shader-explicit-vertex-parameter.insts.inc"
|
||||
#include "spv-amd-shader-trinary-minmax.insts.inc"
|
||||
|
||||
static const spv_ext_inst_group_t groups_1_0[] = {
|
||||
{SPV_EXT_INST_TYPE_GLSL_STD_450, ARRAY_SIZE(glslStd450Entries_1_0),
|
||||
glslStd450Entries_1_0},
|
||||
{SPV_EXT_INST_TYPE_OPENCL_STD, ARRAY_SIZE(openclEntries_1_0),
|
||||
openclEntries_1_0},
|
||||
static const spv_ext_inst_group_t kGroups_1_0[] = {
|
||||
{SPV_EXT_INST_TYPE_GLSL_STD_450, ARRAY_SIZE(glsl_entries), glsl_entries},
|
||||
{SPV_EXT_INST_TYPE_OPENCL_STD, ARRAY_SIZE(opencl_entries), opencl_entries},
|
||||
{SPV_EXT_INST_TYPE_SPV_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER,
|
||||
ARRAY_SIZE(spv_amd_shader_explicit_vertex_parameter_entries),
|
||||
spv_amd_shader_explicit_vertex_parameter_entries},
|
||||
@ -66,12 +43,15 @@ spv_result_t spvExtInstTableGet(spv_ext_inst_table* pExtInstTable,
|
||||
{SPV_EXT_INST_TYPE_SPV_AMD_GCN_SHADER,
|
||||
ARRAY_SIZE(spv_amd_gcn_shader_entries), spv_amd_gcn_shader_entries},
|
||||
{SPV_EXT_INST_TYPE_SPV_AMD_SHADER_BALLOT,
|
||||
ARRAY_SIZE(spv_amd_shader_ballot_entries),
|
||||
spv_amd_shader_ballot_entries},
|
||||
};
|
||||
ARRAY_SIZE(spv_amd_shader_ballot_entries), spv_amd_shader_ballot_entries},
|
||||
};
|
||||
|
||||
static const spv_ext_inst_table_t table_1_0 = {ARRAY_SIZE(groups_1_0),
|
||||
groups_1_0};
|
||||
static const spv_ext_inst_table_t kTable_1_0 = {ARRAY_SIZE(kGroups_1_0),
|
||||
kGroups_1_0};
|
||||
|
||||
spv_result_t spvExtInstTableGet(spv_ext_inst_table* pExtInstTable,
|
||||
spv_target_env env) {
|
||||
if (!pExtInstTable) return SPV_ERROR_INVALID_POINTER;
|
||||
|
||||
switch (env) {
|
||||
// The extended instruction sets are all version 1.0 so far.
|
||||
@ -86,7 +66,7 @@ spv_result_t spvExtInstTableGet(spv_ext_inst_table* pExtInstTable,
|
||||
case SPV_ENV_OPENGL_4_2:
|
||||
case SPV_ENV_OPENGL_4_3:
|
||||
case SPV_ENV_OPENGL_4_5:
|
||||
*pExtInstTable = &table_1_0;
|
||||
*pExtInstTable = &kTable_1_0;
|
||||
return SPV_SUCCESS;
|
||||
default:
|
||||
assert(0 && "Unknown spv_target_env in spvExtInstTableGet()");
|
||||
|
@ -23,7 +23,7 @@
|
||||
namespace libspirv {
|
||||
|
||||
// The known SPIR-V extensions.
|
||||
enum class Extension {
|
||||
enum Extension {
|
||||
#include "extension_enum.inc"
|
||||
};
|
||||
|
||||
|
@ -32,13 +32,16 @@ struct OpcodeDescPtrLen {
|
||||
uint32_t len;
|
||||
};
|
||||
|
||||
OpcodeDescPtrLen getOpcodeTableEntries_1_2() {
|
||||
static const spv_opcode_desc_t opcodeTableEntries_1_2[] = {
|
||||
#include "core.insts-1.2.inc"
|
||||
};
|
||||
#include "core.insts-1.0.inc" // defines kOpcodeTableEntries_1_0
|
||||
#include "core.insts-1.1.inc" // defines kOpcodeTableEntries_1_1
|
||||
#include "core.insts-1.2.inc" // defines kOpcodeTableEntries_1_2
|
||||
|
||||
return {opcodeTableEntries_1_2, ARRAY_SIZE(opcodeTableEntries_1_2)};
|
||||
}
|
||||
static const spv_opcode_table_t kTable_1_0 = {
|
||||
ARRAY_SIZE(kOpcodeTableEntries_1_0), kOpcodeTableEntries_1_0};
|
||||
static const spv_opcode_table_t kTable_1_1 = {
|
||||
ARRAY_SIZE(kOpcodeTableEntries_1_1), kOpcodeTableEntries_1_1};
|
||||
static const spv_opcode_table_t kTable_1_2 = {
|
||||
ARRAY_SIZE(kOpcodeTableEntries_1_2), kOpcodeTableEntries_1_2};
|
||||
|
||||
// Represents a vendor tool entry in the SPIR-V XML Regsitry.
|
||||
struct VendorTool {
|
||||
@ -84,20 +87,6 @@ spv_result_t spvOpcodeTableGet(spv_opcode_table* pInstTable,
|
||||
|
||||
// Descriptions of each opcode. Each entry describes the format of the
|
||||
// instruction that follows a particular opcode.
|
||||
static const spv_opcode_desc_t opcodeTableEntries_1_0[] = {
|
||||
#include "core.insts-1.0.inc"
|
||||
};
|
||||
static const spv_opcode_desc_t opcodeTableEntries_1_1[] = {
|
||||
#include "core.insts-1.1.inc"
|
||||
};
|
||||
|
||||
const auto ptr_len = getOpcodeTableEntries_1_2();
|
||||
|
||||
static const spv_opcode_table_t table_1_0 = {
|
||||
ARRAY_SIZE(opcodeTableEntries_1_0), opcodeTableEntries_1_0};
|
||||
static const spv_opcode_table_t table_1_1 = {
|
||||
ARRAY_SIZE(opcodeTableEntries_1_1), opcodeTableEntries_1_1};
|
||||
static const spv_opcode_table_t table_1_2 = {ptr_len.len, ptr_len.ptr};
|
||||
|
||||
switch (env) {
|
||||
case SPV_ENV_UNIVERSAL_1_0:
|
||||
@ -108,14 +97,14 @@ spv_result_t spvOpcodeTableGet(spv_opcode_table* pInstTable,
|
||||
case SPV_ENV_OPENGL_4_2:
|
||||
case SPV_ENV_OPENGL_4_3:
|
||||
case SPV_ENV_OPENGL_4_5:
|
||||
*pInstTable = &table_1_0;
|
||||
*pInstTable = &kTable_1_0;
|
||||
return SPV_SUCCESS;
|
||||
case SPV_ENV_UNIVERSAL_1_1:
|
||||
*pInstTable = &table_1_1;
|
||||
*pInstTable = &kTable_1_1;
|
||||
return SPV_SUCCESS;
|
||||
case SPV_ENV_UNIVERSAL_1_2:
|
||||
case SPV_ENV_OPENCL_2_2:
|
||||
*pInstTable = &table_1_2;
|
||||
*pInstTable = &kTable_1_2;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
assert(0 && "Unknown spv_target_env in spvOpcodeTableGet()");
|
||||
@ -183,10 +172,9 @@ void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
|
||||
const char* spvOpcodeString(const SpvOp opcode) {
|
||||
// Use the latest SPIR-V version, which should be backward-compatible with all
|
||||
// previous ones.
|
||||
const auto entries = getOpcodeTableEntries_1_2();
|
||||
|
||||
for (uint32_t i = 0; i < entries.len; ++i) {
|
||||
if (entries.ptr[i].opcode == opcode) return entries.ptr[i].name;
|
||||
for (uint32_t i = 0; i < ARRAY_SIZE(kOpcodeTableEntries_1_2); ++i) {
|
||||
if (kOpcodeTableEntries_1_2[i].opcode == opcode)
|
||||
return kOpcodeTableEntries_1_2[i].name;
|
||||
}
|
||||
|
||||
assert(0 && "Unreachable!");
|
||||
|
@ -20,24 +20,24 @@
|
||||
|
||||
#include "macro.h"
|
||||
|
||||
spv_result_t spvOperandTableGet(spv_operand_table* pOperandTable,
|
||||
spv_target_env env) {
|
||||
if (!pOperandTable) return SPV_ERROR_INVALID_POINTER;
|
||||
|
||||
#include "operand.kinds-1.0.inc"
|
||||
#include "operand.kinds-1.1.inc"
|
||||
#include "operand.kinds-1.2.inc"
|
||||
|
||||
static const spv_operand_table_t table_1_0 = {
|
||||
static const spv_operand_table_t kTable_1_0 = {
|
||||
ARRAY_SIZE(pygen_variable_OperandInfoTable_1_0),
|
||||
pygen_variable_OperandInfoTable_1_0};
|
||||
static const spv_operand_table_t table_1_1 = {
|
||||
static const spv_operand_table_t kTable_1_1 = {
|
||||
ARRAY_SIZE(pygen_variable_OperandInfoTable_1_1),
|
||||
pygen_variable_OperandInfoTable_1_1};
|
||||
static const spv_operand_table_t table_1_2 = {
|
||||
static const spv_operand_table_t kTable_1_2 = {
|
||||
ARRAY_SIZE(pygen_variable_OperandInfoTable_1_2),
|
||||
pygen_variable_OperandInfoTable_1_2};
|
||||
|
||||
spv_result_t spvOperandTableGet(spv_operand_table* pOperandTable,
|
||||
spv_target_env env) {
|
||||
if (!pOperandTable) return SPV_ERROR_INVALID_POINTER;
|
||||
|
||||
switch (env) {
|
||||
case SPV_ENV_UNIVERSAL_1_0:
|
||||
case SPV_ENV_VULKAN_1_0:
|
||||
@ -47,14 +47,14 @@ spv_result_t spvOperandTableGet(spv_operand_table* pOperandTable,
|
||||
case SPV_ENV_OPENGL_4_2:
|
||||
case SPV_ENV_OPENGL_4_3:
|
||||
case SPV_ENV_OPENGL_4_5:
|
||||
*pOperandTable = &table_1_0;
|
||||
*pOperandTable = &kTable_1_0;
|
||||
return SPV_SUCCESS;
|
||||
case SPV_ENV_UNIVERSAL_1_1:
|
||||
*pOperandTable = &table_1_1;
|
||||
*pOperandTable = &kTable_1_1;
|
||||
return SPV_SUCCESS;
|
||||
case SPV_ENV_UNIVERSAL_1_2:
|
||||
case SPV_ENV_OPENCL_2_2:
|
||||
*pOperandTable = &table_1_2;
|
||||
*pOperandTable = &kTable_1_2;
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
assert(0 && "Unknown spv_target_env in spvOperandTableGet()");
|
||||
|
@ -24,7 +24,8 @@
|
||||
typedef struct spv_opcode_desc_t {
|
||||
const char* name;
|
||||
const SpvOp opcode;
|
||||
const libspirv::CapabilitySet capabilities;
|
||||
const uint32_t numCapabilities;
|
||||
const SpvCapability* capabilities;
|
||||
// operandTypes[0..numTypes-1] describe logical operands for the instruction.
|
||||
// The operand types include result id and result-type id, followed by
|
||||
// the types of arguments.
|
||||
@ -37,12 +38,14 @@ typedef struct spv_opcode_desc_t {
|
||||
typedef struct spv_operand_desc_t {
|
||||
const char* name;
|
||||
const uint32_t value;
|
||||
const libspirv::CapabilitySet capabilities;
|
||||
const uint32_t numCapabilities;
|
||||
const SpvCapability* capabilities;
|
||||
// A set of extensions that enable this feature. If empty then this operand
|
||||
// value is always enabled, i.e. it's in core. The assembler, binary parser,
|
||||
// and disassembler ignore this rule, so you can freely process invalid
|
||||
// modules.
|
||||
const libspirv::ExtensionSet extensions;
|
||||
const uint32_t numExtensions;
|
||||
const libspirv::Extension* extensions;
|
||||
const spv_operand_type_t operandTypes[16]; // TODO: Smaller/larger?
|
||||
} spv_operand_desc_t;
|
||||
|
||||
@ -55,7 +58,8 @@ typedef struct spv_operand_desc_group_t {
|
||||
typedef struct spv_ext_inst_desc_t {
|
||||
const char* name;
|
||||
const uint32_t ext_inst;
|
||||
const libspirv::CapabilitySet capabilities;
|
||||
const uint32_t numCapabilities;
|
||||
const SpvCapability* capabilities;
|
||||
const spv_operand_type_t operandTypes[16]; // TODO: Smaller/larger?
|
||||
} spv_ext_inst_desc_t;
|
||||
|
||||
|
@ -215,15 +215,13 @@ bool ValidationState_t::IsDefinedId(uint32_t id) const {
|
||||
|
||||
const Instruction* ValidationState_t::FindDef(uint32_t id) const {
|
||||
auto it = all_definitions_.find(id);
|
||||
if (it == all_definitions_.end())
|
||||
return nullptr;
|
||||
if (it == all_definitions_.end()) return nullptr;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
Instruction* ValidationState_t::FindDef(uint32_t id) {
|
||||
auto it = all_definitions_.find(id);
|
||||
if (it == all_definitions_.end())
|
||||
return nullptr;
|
||||
if (it == all_definitions_.end()) return nullptr;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
@ -283,8 +281,8 @@ void ValidationState_t::RegisterCapability(SpvCapability cap) {
|
||||
spv_operand_desc desc;
|
||||
if (SPV_SUCCESS ==
|
||||
grammar_.lookupOperand(SPV_OPERAND_TYPE_CAPABILITY, cap, &desc)) {
|
||||
desc->capabilities.ForEach(
|
||||
[this](SpvCapability c) { RegisterCapability(c); });
|
||||
CapabilitySet(desc->numCapabilities, desc->capabilities)
|
||||
.ForEach([this](SpvCapability c) { RegisterCapability(c); });
|
||||
}
|
||||
|
||||
switch (cap) {
|
||||
@ -464,8 +462,7 @@ uint32_t ValidationState_t::GetComponentType(uint32_t id) const {
|
||||
break;
|
||||
}
|
||||
|
||||
if (inst->type_id())
|
||||
return GetComponentType(inst->type_id());
|
||||
if (inst->type_id()) return GetComponentType(inst->type_id());
|
||||
|
||||
assert(0);
|
||||
return 0;
|
||||
@ -489,8 +486,7 @@ uint32_t ValidationState_t::GetDimension(uint32_t id) const {
|
||||
break;
|
||||
}
|
||||
|
||||
if (inst->type_id())
|
||||
return GetDimension(inst->type_id());
|
||||
if (inst->type_id()) return GetDimension(inst->type_id());
|
||||
|
||||
assert(0);
|
||||
return 0;
|
||||
@ -504,8 +500,7 @@ uint32_t ValidationState_t::GetBitWidth(uint32_t id) const {
|
||||
if (inst->opcode() == SpvOpTypeFloat || inst->opcode() == SpvOpTypeInt)
|
||||
return inst->word(2);
|
||||
|
||||
if (inst->opcode() == SpvOpTypeBool)
|
||||
return 1;
|
||||
if (inst->opcode() == SpvOpTypeBool) return 1;
|
||||
|
||||
assert(0);
|
||||
return 0;
|
||||
@ -607,16 +602,15 @@ bool ValidationState_t::IsFloatMatrixType(uint32_t id) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ValidationState_t::GetMatrixTypeInfo(
|
||||
uint32_t id, uint32_t* num_rows, uint32_t* num_cols,
|
||||
uint32_t* column_type, uint32_t* component_type) const {
|
||||
if (!id)
|
||||
return false;
|
||||
bool ValidationState_t::GetMatrixTypeInfo(uint32_t id, uint32_t* num_rows,
|
||||
uint32_t* num_cols,
|
||||
uint32_t* column_type,
|
||||
uint32_t* component_type) const {
|
||||
if (!id) return false;
|
||||
|
||||
const Instruction* mat_inst = FindDef(id);
|
||||
assert(mat_inst);
|
||||
if (mat_inst->opcode() != SpvOpTypeMatrix)
|
||||
return false;
|
||||
if (mat_inst->opcode() != SpvOpTypeMatrix) return false;
|
||||
|
||||
const uint32_t vec_type = mat_inst->word(2);
|
||||
const Instruction* vec_inst = FindDef(vec_type);
|
||||
@ -638,19 +632,16 @@ bool ValidationState_t::GetMatrixTypeInfo(
|
||||
bool ValidationState_t::GetStructMemberTypes(
|
||||
uint32_t struct_type_id, std::vector<uint32_t>* member_types) const {
|
||||
member_types->clear();
|
||||
if (!struct_type_id)
|
||||
return false;
|
||||
if (!struct_type_id) return false;
|
||||
|
||||
const Instruction* inst = FindDef(struct_type_id);
|
||||
assert(inst);
|
||||
if (inst->opcode() != SpvOpTypeStruct)
|
||||
return false;
|
||||
if (inst->opcode() != SpvOpTypeStruct) return false;
|
||||
|
||||
*member_types = std::vector<uint32_t>(inst->words().cbegin() + 2,
|
||||
inst->words().cend());
|
||||
*member_types =
|
||||
std::vector<uint32_t>(inst->words().cbegin() + 2, inst->words().cend());
|
||||
|
||||
if (member_types->empty())
|
||||
return false;
|
||||
if (member_types->empty()) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -661,15 +652,13 @@ bool ValidationState_t::IsPointerType(uint32_t id) const {
|
||||
return inst->opcode() == SpvOpTypePointer;
|
||||
}
|
||||
|
||||
bool ValidationState_t::GetPointerTypeInfo(
|
||||
uint32_t id, uint32_t* data_type, uint32_t* storage_class) const {
|
||||
if (!id)
|
||||
return false;
|
||||
bool ValidationState_t::GetPointerTypeInfo(uint32_t id, uint32_t* data_type,
|
||||
uint32_t* storage_class) const {
|
||||
if (!id) return false;
|
||||
|
||||
const Instruction* inst = FindDef(id);
|
||||
assert(inst);
|
||||
if (inst->opcode() != SpvOpTypePointer)
|
||||
return false;
|
||||
if (inst->opcode() != SpvOpTypePointer) return false;
|
||||
|
||||
*storage_class = inst->word(2);
|
||||
*data_type = inst->word(3);
|
||||
@ -677,12 +666,11 @@ bool ValidationState_t::GetPointerTypeInfo(
|
||||
}
|
||||
|
||||
uint32_t ValidationState_t::GetOperandTypeId(
|
||||
const spv_parsed_instruction_t* inst,
|
||||
size_t operand_index) const {
|
||||
const spv_parsed_instruction_t* inst, size_t operand_index) const {
|
||||
assert(operand_index < inst->num_operands);
|
||||
const spv_parsed_operand_t& operand = inst->operands[operand_index];
|
||||
assert(operand.num_words == 1);
|
||||
return GetTypeId(inst->words[operand.offset]);
|
||||
}
|
||||
|
||||
} /// namespace libspirv
|
||||
} // namespace libspirv
|
||||
|
@ -80,17 +80,18 @@ bool IsSupportOptionalVulkan_1_0(uint32_t capability) {
|
||||
// Checks if |capability| was enabled by extension.
|
||||
bool IsEnabledByExtension(ValidationState_t& _, uint32_t capability) {
|
||||
spv_operand_desc operand_desc = nullptr;
|
||||
_.grammar().lookupOperand(
|
||||
SPV_OPERAND_TYPE_CAPABILITY, capability, &operand_desc);
|
||||
_.grammar().lookupOperand(SPV_OPERAND_TYPE_CAPABILITY, capability,
|
||||
&operand_desc);
|
||||
|
||||
// operand_desc is expected to be not null, otherwise validator would have
|
||||
// failed at an earlier stage. This 'assert' is 'just in case'.
|
||||
assert(operand_desc);
|
||||
|
||||
if (operand_desc->extensions.IsEmpty())
|
||||
return false;
|
||||
ExtensionSet operand_exts(operand_desc->numExtensions,
|
||||
operand_desc->extensions);
|
||||
if (operand_exts.IsEmpty()) return false;
|
||||
|
||||
return _.HasAnyOfExtensions(operand_desc->extensions);
|
||||
return _.HasAnyOfExtensions(operand_exts);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@ -100,8 +101,7 @@ bool IsEnabledByExtension(ValidationState_t& _, uint32_t capability) {
|
||||
spv_result_t CapabilityPass(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
if (opcode != SpvOpCapability)
|
||||
return SPV_SUCCESS;
|
||||
if (opcode != SpvOpCapability) return SPV_SUCCESS;
|
||||
|
||||
assert(inst->num_operands == 1);
|
||||
|
||||
|
@ -94,7 +94,8 @@ CapabilitySet RequiredCapabilities(const ValidationState_t& state,
|
||||
spv_operand_desc operand_desc;
|
||||
const auto ret = state.grammar().lookupOperand(type, operand, &operand_desc);
|
||||
if (ret == SPV_SUCCESS) {
|
||||
CapabilitySet result = operand_desc->capabilities;
|
||||
CapabilitySet result(operand_desc->numCapabilities,
|
||||
operand_desc->capabilities);
|
||||
|
||||
// Allow FPRoundingMode decoration if requested
|
||||
if (state.features().free_fp_rounding_mode &&
|
||||
@ -115,7 +116,7 @@ ExtensionSet RequiredExtensions(const ValidationState_t& state,
|
||||
if (state.grammar().lookupOperand(type, operand, &operand_desc) ==
|
||||
SPV_SUCCESS) {
|
||||
assert(operand_desc);
|
||||
return operand_desc->extensions;
|
||||
return {operand_desc->numExtensions, operand_desc->extensions};
|
||||
}
|
||||
|
||||
return ExtensionSet();
|
||||
@ -127,14 +128,17 @@ namespace libspirv {
|
||||
|
||||
spv_result_t CapabilityCheck(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
spv_opcode_desc opcode_desc;
|
||||
spv_opcode_desc opcode_desc = {};
|
||||
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
if (SPV_SUCCESS == _.grammar().lookupOpcode(opcode, &opcode_desc) &&
|
||||
!_.HasAnyOfCapabilities(opcode_desc->capabilities))
|
||||
if (SPV_SUCCESS == _.grammar().lookupOpcode(opcode, &opcode_desc)) {
|
||||
CapabilitySet opcode_caps(opcode_desc->numCapabilities,
|
||||
opcode_desc->capabilities);
|
||||
if (!_.HasAnyOfCapabilities(opcode_caps))
|
||||
return _.diag(SPV_ERROR_INVALID_CAPABILITY)
|
||||
<< "Opcode " << spvOpcodeString(opcode)
|
||||
<< " requires one of these capabilities: "
|
||||
<< ToString(opcode_desc->capabilities, _.grammar());
|
||||
<< ToString(opcode_caps, _.grammar());
|
||||
}
|
||||
for (int i = 0; i < inst->num_operands; ++i) {
|
||||
const auto& operand = inst->operands[i];
|
||||
const auto word = inst->words[operand.offset];
|
||||
@ -194,8 +198,8 @@ spv_result_t ReservedCheck(ValidationState_t& _,
|
||||
case SpvOpImageSparseSampleProjExplicitLod:
|
||||
case SpvOpImageSparseSampleProjDrefImplicitLod:
|
||||
case SpvOpImageSparseSampleProjDrefExplicitLod:
|
||||
return _.diag(SPV_ERROR_INVALID_VALUE) << spvOpcodeString(opcode)
|
||||
<< " is reserved for future use.";
|
||||
return _.diag(SPV_ERROR_INVALID_VALUE)
|
||||
<< spvOpcodeString(opcode) << " is reserved for future use.";
|
||||
default:
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
@ -393,8 +397,7 @@ void CheckIfKnownExtension(ValidationState_t& _,
|
||||
spv_result_t InstructionPass(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
if (opcode == SpvOpExtension)
|
||||
CheckIfKnownExtension(_, inst);
|
||||
if (opcode == SpvOpExtension) CheckIfKnownExtension(_, inst);
|
||||
if (opcode == SpvOpCapability) {
|
||||
_.RegisterCapability(
|
||||
static_cast<SpvCapability>(inst->words[inst->operands[0].offset]));
|
||||
|
@ -37,8 +37,9 @@ TEST_P(OpcodeTableCapabilitiesTest, TableEntryMatchesExpectedCapabilities) {
|
||||
spv_opcode_desc entry;
|
||||
ASSERT_EQ(SPV_SUCCESS,
|
||||
spvOpcodeTableValueLookup(opcodeTable, GetParam().opcode, &entry));
|
||||
EXPECT_EQ(ElementsIn(GetParam().capabilities),
|
||||
ElementsIn(entry->capabilities));
|
||||
EXPECT_EQ(
|
||||
ElementsIn(GetParam().capabilities),
|
||||
ElementsIn(CapabilitySet(entry->numCapabilities, entry->capabilities)));
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
|
@ -51,7 +51,8 @@ TEST_P(EnumCapabilityTest, Sample) {
|
||||
ASSERT_EQ(SPV_SUCCESS,
|
||||
spvOperandTableValueLookup(operandTable, get<1>(GetParam()).type,
|
||||
get<1>(GetParam()).value, &entry));
|
||||
EXPECT_THAT(ElementsIn(entry->capabilities),
|
||||
EXPECT_THAT(
|
||||
ElementsIn(CapabilitySet(entry->numCapabilities, entry->capabilities)),
|
||||
Eq(ElementsIn(get<1>(GetParam()).expected_capabilities)))
|
||||
<< " capability value " << get<1>(GetParam()).value;
|
||||
}
|
||||
@ -279,8 +280,7 @@ INSTANTIATE_TEST_CASE_P(
|
||||
// See SPIR-V Section 3.12 Image Channel Order
|
||||
INSTANTIATE_TEST_CASE_P(
|
||||
ImageChannelOrder, EnumCapabilityTest,
|
||||
Combine(
|
||||
Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
|
||||
Combine(Values(SPV_ENV_UNIVERSAL_1_0, SPV_ENV_UNIVERSAL_1_1),
|
||||
ValuesIn(std::vector<EnumCapabilityCase>{
|
||||
CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderR, Kernel),
|
||||
CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderA, Kernel),
|
||||
@ -296,7 +296,8 @@ INSTANTIATE_TEST_CASE_P(
|
||||
CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRGx, Kernel),
|
||||
CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderRGBx, Kernel),
|
||||
CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderDepth, Kernel),
|
||||
CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderDepthStencil, Kernel),
|
||||
CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrderDepthStencil,
|
||||
Kernel),
|
||||
CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrdersRGB, Kernel),
|
||||
CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrdersRGBx, Kernel),
|
||||
CASE1(IMAGE_CHANNEL_ORDER, ImageChannelOrdersRGBA, Kernel),
|
||||
|
@ -24,7 +24,7 @@ import re
|
||||
# Prefix for all C variables generated by this script.
|
||||
PYGEN_VARIABLE_PREFIX = 'pygen_variable'
|
||||
|
||||
# Extensions to recognize, but which don't necessarily come from the SPIRV-V
|
||||
# Extensions to recognize, but which don't necessarily come from the SPIR-V
|
||||
# core grammar. Get this list from the SPIR-V registery web page.
|
||||
EXTENSIONS_FROM_SPIRV_REGISTRY = """
|
||||
SPV_AMD_shader_explicit_vertex_parameter
|
||||
@ -56,7 +56,6 @@ SPV_AMD_shader_fragment_mask
|
||||
"""
|
||||
|
||||
|
||||
|
||||
def make_path_to_file(f):
|
||||
"""Makes all ancestor directories to the given file, if they
|
||||
don't yet exist.
|
||||
@ -86,6 +85,33 @@ def compose_capability_list(caps):
|
||||
return "{" + ", ".join(['SpvCapability{}'.format(c) for c in caps]) + "}"
|
||||
|
||||
|
||||
def get_capability_array_name(caps, version):
|
||||
"""Returns the name of the array containing all the given capabilities.
|
||||
|
||||
Args:
|
||||
- caps: a sequence of capability names
|
||||
"""
|
||||
if not caps:
|
||||
return 'nullptr'
|
||||
else:
|
||||
return '{}_caps_{}_{}'.format(
|
||||
PYGEN_VARIABLE_PREFIX, ''.join(caps), version)
|
||||
|
||||
|
||||
def generate_capability_arrays(caps, version):
|
||||
"""Returns the arrays of capabilities.
|
||||
|
||||
Arguments:
|
||||
- caps: a sequence of sequence of capability names
|
||||
"""
|
||||
caps = sorted(set([tuple(c) for c in caps if c]))
|
||||
arrays = [
|
||||
'static const SpvCapability {}[] = {};'.format(
|
||||
get_capability_array_name(c, version), compose_capability_list(c))
|
||||
for c in caps]
|
||||
return '\n'.join(arrays)
|
||||
|
||||
|
||||
def compose_extension_list(exts):
|
||||
"""Returns a string containing a braced list of extensions as enums.
|
||||
|
||||
@ -99,6 +125,33 @@ def compose_extension_list(exts):
|
||||
['libspirv::Extension::k{}'.format(e) for e in exts]) + "}"
|
||||
|
||||
|
||||
def get_extension_array_name(extensions, version):
|
||||
"""Returns the name of the array containing all the given extensions.
|
||||
|
||||
Args:
|
||||
- extensions: a sequence of extension names
|
||||
"""
|
||||
if not extensions:
|
||||
return 'nullptr'
|
||||
else:
|
||||
return '{}_exts_{}_{}'.format(
|
||||
PYGEN_VARIABLE_PREFIX, ''.join(extensions), version)
|
||||
|
||||
|
||||
def generate_extension_arrays(extensions, version):
|
||||
"""Returns the arrays of extensions.
|
||||
|
||||
Arguments:
|
||||
- caps: a sequence of sequence of extension names
|
||||
"""
|
||||
extensions = sorted(set([tuple(e) for e in extensions if e]))
|
||||
arrays = [
|
||||
'static const libspirv::Extension {}[] = {};'.format(
|
||||
get_extension_array_name(e, version), compose_extension_list(e))
|
||||
for e in extensions]
|
||||
return '\n'.join(arrays)
|
||||
|
||||
|
||||
def convert_operand_kind(operand_tuple):
|
||||
"""Returns the corresponding operand type used in spirv-tools for
|
||||
the given operand kind and quantifier used in the JSON grammar.
|
||||
@ -166,17 +219,19 @@ class InstInitializer(object):
|
||||
"""Instances holds a SPIR-V instruction suitable for printing as
|
||||
the initializer for spv_opcode_desc_t."""
|
||||
|
||||
def __init__(self, opname, caps, operands):
|
||||
def __init__(self, opname, caps, operands, version):
|
||||
"""Initialization.
|
||||
|
||||
Arguments:
|
||||
- opname: opcode name (with the 'Op' prefix)
|
||||
- caps: a sequence of capability names required by this opcode
|
||||
- operands: a sequence of (operand-kind, operand-quantifier) tuples
|
||||
- version: version of the instruction set
|
||||
"""
|
||||
assert opname.startswith('Op')
|
||||
self.opname = opname[2:] # Remove the "Op" prefix.
|
||||
self.caps_mask = compose_capability_list(caps)
|
||||
self.num_caps = len(caps)
|
||||
self.caps_mask = get_capability_array_name(caps, version)
|
||||
self.operands = [convert_operand_kind(o) for o in operands]
|
||||
|
||||
self.fix_syntax()
|
||||
@ -198,11 +253,13 @@ class InstInitializer(object):
|
||||
self.operands.pop()
|
||||
|
||||
def __str__(self):
|
||||
template = ['{{"{opname}"', 'SpvOp{opname}', '{caps_mask}',
|
||||
template = ['{{"{opname}"', 'SpvOp{opname}',
|
||||
'{num_caps}', '{caps_mask}',
|
||||
'{num_operands}', '{{{operands}}}',
|
||||
'{def_result_id}', '{ref_type_id}}}']
|
||||
return ', '.join(template).format(
|
||||
opname=self.opname,
|
||||
num_caps=self.num_caps,
|
||||
caps_mask=self.caps_mask,
|
||||
num_operands=len(self.operands),
|
||||
operands=', '.join(self.operands),
|
||||
@ -214,7 +271,7 @@ class ExtInstInitializer(object):
|
||||
"""Instances holds a SPIR-V extended instruction suitable for printing as
|
||||
the initializer for spv_ext_inst_desc_t."""
|
||||
|
||||
def __init__(self, opname, opcode, caps, operands):
|
||||
def __init__(self, opname, opcode, caps, operands, version):
|
||||
"""Initialization.
|
||||
|
||||
Arguments:
|
||||
@ -222,24 +279,27 @@ class ExtInstInitializer(object):
|
||||
- opcode: enumerant value for this opcode
|
||||
- caps: a sequence of capability names required by this opcode
|
||||
- operands: a sequence of (operand-kind, operand-quantifier) tuples
|
||||
- version: version of the extended instruction set
|
||||
"""
|
||||
self.opname = opname
|
||||
self.opcode = opcode
|
||||
self.caps_mask = compose_capability_list(caps)
|
||||
self.num_caps = len(caps)
|
||||
self.caps_mask = get_capability_array_name(caps, version)
|
||||
self.operands = [convert_operand_kind(o) for o in operands]
|
||||
self.operands.append('SPV_OPERAND_TYPE_NONE')
|
||||
|
||||
def __str__(self):
|
||||
template = ['{{"{opname}"', '{opcode}', '{caps_mask}',
|
||||
template = ['{{"{opname}"', '{opcode}', '{num_caps}', '{caps_mask}',
|
||||
'{{{operands}}}}}']
|
||||
return ', '.join(template).format(
|
||||
opname=self.opname,
|
||||
opcode=self.opcode,
|
||||
num_caps=self.num_caps,
|
||||
caps_mask=self.caps_mask,
|
||||
operands=', '.join(self.operands))
|
||||
|
||||
|
||||
def generate_instruction(inst, is_ext_inst):
|
||||
def generate_instruction(inst, version, is_ext_inst):
|
||||
"""Returns the C initializer for the given SPIR-V instruction.
|
||||
|
||||
Arguments:
|
||||
@ -260,27 +320,49 @@ def generate_instruction(inst, is_ext_inst):
|
||||
assert opname is not None
|
||||
|
||||
if is_ext_inst:
|
||||
return str(ExtInstInitializer(opname, opcode, caps, operands))
|
||||
return str(ExtInstInitializer(opname, opcode, caps, operands, version))
|
||||
else:
|
||||
return str(InstInitializer(opname, caps, operands))
|
||||
return str(InstInitializer(opname, caps, operands, version))
|
||||
|
||||
|
||||
def generate_instruction_table(inst_table, is_ext_inst):
|
||||
"""Returns the info table containing all SPIR-V instructions.
|
||||
def generate_instruction_table(inst_table, version):
|
||||
"""Returns the info table containing all SPIR-V instructions,
|
||||
prefixed by capability arrays.
|
||||
|
||||
Arguments:
|
||||
- inst_table: a dict containing all SPIR-V instructions.
|
||||
- is_ext_inst: a bool indicating whether |inst_table| is for
|
||||
an extended instruction set.
|
||||
- vesion: SPIR-V version.
|
||||
"""
|
||||
return ',\n'.join([generate_instruction(inst, is_ext_inst)
|
||||
for inst in inst_table])
|
||||
caps_arrays = generate_capability_arrays(
|
||||
[inst.get('capabilities', []) for inst in inst_table], version)
|
||||
insts = [generate_instruction(inst, version, False) for inst in inst_table]
|
||||
insts = ['static const spv_opcode_desc_t kOpcodeTableEntries_{}[] = {{\n'
|
||||
' {}\n}};'.format(version, ',\n '.join(insts))]
|
||||
|
||||
return '{}\n\n{}'.format(caps_arrays, '\n'.join(insts))
|
||||
|
||||
|
||||
def generate_extended_instruction_table(inst_table, set_name, version):
|
||||
"""Returns the info table containing all SPIR-V extended instructions,
|
||||
prefixed by capability arrays.
|
||||
|
||||
Arguments:
|
||||
- inst_table: a dict containing all SPIR-V instructions.
|
||||
- set_name: the name of the extended instruction set.
|
||||
"""
|
||||
caps = [inst.get('capabilities', []) for inst in inst_table]
|
||||
caps_arrays = generate_capability_arrays(caps, version)
|
||||
insts = [generate_instruction(inst, version, True) for inst in inst_table]
|
||||
insts = ['static const spv_ext_inst_desc_t {}_entries[] = {{\n'
|
||||
' {}\n}};'.format(set_name, ',\n '.join(insts))]
|
||||
|
||||
return '{}\n\n{}'.format(caps_arrays, '\n'.join(insts))
|
||||
|
||||
|
||||
class EnumerantInitializer(object):
|
||||
"""Prints an enumerant as the initializer for spv_operand_desc_t."""
|
||||
|
||||
def __init__(self, enumerant, value, caps, exts, parameters):
|
||||
def __init__(self, enumerant, value, caps, exts, parameters, version):
|
||||
"""Initialization.
|
||||
|
||||
Arguments:
|
||||
@ -292,22 +374,26 @@ class EnumerantInitializer(object):
|
||||
"""
|
||||
self.enumerant = enumerant
|
||||
self.value = value
|
||||
self.caps = compose_capability_list(caps)
|
||||
self.exts = compose_extension_list(exts)
|
||||
self.num_caps = len(caps)
|
||||
self.caps = get_capability_array_name(caps, version)
|
||||
self.num_exts = len(exts)
|
||||
self.exts = get_extension_array_name(exts, version)
|
||||
self.parameters = [convert_operand_kind(p) for p in parameters]
|
||||
|
||||
def __str__(self):
|
||||
template = ['{{"{enumerant}"', '{value}',
|
||||
'{caps}', '{exts}', '{{{parameters}}}}}']
|
||||
template = ['{{"{enumerant}"', '{value}', '{num_caps}',
|
||||
'{caps}', '{num_exts}', '{exts}', '{{{parameters}}}}}']
|
||||
return ', '.join(template).format(
|
||||
enumerant=self.enumerant,
|
||||
value=self.value,
|
||||
num_caps=self.num_caps,
|
||||
caps=self.caps,
|
||||
num_exts=self.num_exts,
|
||||
exts=self.exts,
|
||||
parameters=', '.join(self.parameters))
|
||||
|
||||
|
||||
def generate_enum_operand_kind_entry(entry):
|
||||
def generate_enum_operand_kind_entry(entry, version):
|
||||
"""Returns the C initializer for the given operand enum entry.
|
||||
|
||||
Arguments:
|
||||
@ -327,7 +413,8 @@ def generate_enum_operand_kind_entry(entry):
|
||||
assert enumerant is not None
|
||||
assert value is not None
|
||||
|
||||
return str(EnumerantInitializer(enumerant, value, caps, exts, params))
|
||||
return str(EnumerantInitializer(
|
||||
enumerant, value, caps, exts, params, version))
|
||||
|
||||
|
||||
def generate_enum_operand_kind(enum, version):
|
||||
@ -336,7 +423,7 @@ def generate_enum_operand_kind(enum, version):
|
||||
assert kind is not None
|
||||
|
||||
name = '{}_{}Entries_{}'.format(PYGEN_VARIABLE_PREFIX, kind, version)
|
||||
entries = [' {}'.format(generate_enum_operand_kind_entry(e))
|
||||
entries = [' {}'.format(generate_enum_operand_kind_entry(e, version))
|
||||
for e in enum.get('enumerants', [])]
|
||||
|
||||
template = ['static const spv_operand_desc_t {name}[] = {{',
|
||||
@ -351,9 +438,19 @@ def generate_enum_operand_kind(enum, version):
|
||||
def generate_operand_kind_table(enums, version):
|
||||
"""Returns the info table containing all SPIR-V operand kinds."""
|
||||
# We only need to output info tables for those operand kinds that are enums.
|
||||
enums = [generate_enum_operand_kind(e, version)
|
||||
for e in enums
|
||||
if e.get('category') in ['ValueEnum', 'BitEnum']]
|
||||
enums = [e for e in enums if e.get('category') in ['ValueEnum', 'BitEnum']]
|
||||
|
||||
caps = [entry.get('capabilities', [])
|
||||
for enum in enums
|
||||
for entry in enum.get('enumerants', [])]
|
||||
caps_arrays = generate_capability_arrays(caps, version)
|
||||
|
||||
exts = [entry.get('extensions', [])
|
||||
for enum in enums
|
||||
for entry in enum.get('enumerants', [])]
|
||||
exts_arrays = generate_extension_arrays(exts, version)
|
||||
|
||||
enums = [generate_enum_operand_kind(e, version) for e in enums]
|
||||
# We have three operand kinds that requires their optional counterpart to
|
||||
# exist in the operand info table.
|
||||
three_optional_enums = ['ImageOperands', 'AccessQualifier', 'MemoryAccess']
|
||||
@ -377,7 +474,7 @@ def generate_operand_kind_table(enums, version):
|
||||
table = '\n'.join(template).format(
|
||||
p=PYGEN_VARIABLE_PREFIX, v=version, enums=',\n'.join(table_entries))
|
||||
|
||||
return '\n\n'.join(enum_entries + (table,))
|
||||
return '\n\n'.join((caps_arrays,) + (exts_arrays,) + enum_entries + (table,))
|
||||
|
||||
|
||||
def get_extension_list(operands):
|
||||
@ -580,11 +677,11 @@ def main():
|
||||
if args.core_insts_output is not None:
|
||||
make_path_to_file(args.core_insts_output)
|
||||
make_path_to_file(args.operand_kinds_output)
|
||||
print(generate_instruction_table(
|
||||
grammar['instructions'], False),
|
||||
file=open(args.core_insts_output, 'w'))
|
||||
version = '{}_{}'.format(grammar['major_version'],
|
||||
grammar['minor_version'])
|
||||
print(generate_instruction_table(
|
||||
grammar['instructions'], version),
|
||||
file=open(args.core_insts_output, 'w'))
|
||||
print(generate_operand_kind_table(
|
||||
grammar['operand_kinds'], version),
|
||||
file=open(args.operand_kinds_output, 'w'))
|
||||
@ -602,21 +699,27 @@ def main():
|
||||
with open(args.extinst_glsl_grammar) as json_file:
|
||||
grammar = json.loads(json_file.read())
|
||||
make_path_to_file(args.glsl_insts_output)
|
||||
print(generate_instruction_table(grammar['instructions'], True),
|
||||
print(generate_extended_instruction_table(
|
||||
grammar['instructions'], "glsl", "1_0"),
|
||||
file=open(args.glsl_insts_output, 'w'))
|
||||
|
||||
if args.extinst_opencl_grammar is not None:
|
||||
with open(args.extinst_opencl_grammar) as json_file:
|
||||
grammar = json.loads(json_file.read())
|
||||
make_path_to_file(args.opencl_insts_output)
|
||||
print(generate_instruction_table(grammar['instructions'], True),
|
||||
print(generate_extended_instruction_table(
|
||||
grammar['instructions'], "opencl", "1_0"),
|
||||
file=open(args.opencl_insts_output, 'w'))
|
||||
|
||||
if args.extinst_vendor_grammar is not None:
|
||||
with open(args.extinst_vendor_grammar) as json_file:
|
||||
grammar = json.loads(json_file.read())
|
||||
make_path_to_file(args.vendor_insts_output)
|
||||
print(generate_instruction_table(grammar['instructions'], True),
|
||||
name = args.extinst_vendor_grammar
|
||||
start = name.find("extinst.") + len("extinst.")
|
||||
name = name[start:-len(".grammar.json")].replace("-", "_")
|
||||
print(generate_extended_instruction_table(
|
||||
grammar['instructions'], name, "1_0"),
|
||||
file=open(args.vendor_insts_output, 'w'))
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user