mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-22 11:40:05 +00:00
Remove dependency on SPIR-V headers in libspirv.h.
For fulfilling this purpose, the |opcode| field in the |spv_parsed_instruction_t| struct is changed to of type uint16_t. Also add functions to query the information of a given SPIR-V target environment.
This commit is contained in:
parent
d03c0a1153
commit
6fa3f8aad9
@ -159,9 +159,3 @@ add_subdirectory(test)
|
||||
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/spirv-tools/libspirv.h
|
||||
DESTINATION include/spirv-tools/)
|
||||
# The installation is broken without these header files from the SPIR-V Registry.
|
||||
# The libspirv.h header includes them.
|
||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/include/spirv/spirv.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/spirv/GLSL.std.450.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/spirv/OpenCL.std.h
|
||||
DESTINATION include/spirv/)
|
||||
|
@ -27,10 +27,6 @@
|
||||
#ifndef SPIRV_TOOLS_LIBSPIRV_H_
|
||||
#define SPIRV_TOOLS_LIBSPIRV_H_
|
||||
|
||||
#include "spirv/GLSL.std.450.h"
|
||||
#include "spirv/OpenCL.std.h"
|
||||
#include "spirv/spirv.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#else
|
||||
@ -40,18 +36,8 @@ extern "C" {
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
// Versions
|
||||
// This library is based on SPIR-V 1.0 Rev2
|
||||
// TODO(dneto): Use the values from the SPIR-V header, when it's updated for
|
||||
// SPIR-V 1.0 public release.
|
||||
#define SPV_SPIRV_VERSION_MAJOR (SPV_VERSION >> 16)
|
||||
#define SPV_SPIRV_VERSION_MINOR (SPV_VERSION & 0xffff)
|
||||
#define SPV_SPIRV_VERSION_REVISION (SPV_REVISION)
|
||||
|
||||
// Helpers
|
||||
|
||||
#define spvIsInBitfield(value, bitfield) ((value) == ((value)&bitfield))
|
||||
|
||||
#define SPV_BIT(shift) (1 << (shift))
|
||||
|
||||
#define SPV_FORCE_16_BIT_ENUM(name) _##name = 0x7fff
|
||||
@ -287,7 +273,7 @@ typedef struct spv_parsed_instruction_t {
|
||||
const uint32_t* words;
|
||||
// The number of words in this instruction.
|
||||
uint16_t num_words;
|
||||
SpvOp opcode;
|
||||
uint16_t opcode;
|
||||
// The extended instruction type, if opcode is OpExtInst. Otherwise
|
||||
// this is the "none" value.
|
||||
spv_ext_inst_type_t ext_inst_type;
|
||||
@ -353,6 +339,9 @@ typedef enum {
|
||||
SPV_ENV_VULKAN_1_0_7 // Vulkan 1.0 revision 7.
|
||||
} spv_target_env;
|
||||
|
||||
// Returns a string describing the given SPIR-V target environment.
|
||||
const char* spvTargetEnvDescription(spv_target_env env);
|
||||
|
||||
// Creates a context object. Returns null if env is invalid.
|
||||
spv_context spvContextCreate(spv_target_env env);
|
||||
|
||||
|
@ -29,6 +29,7 @@ set(SPIRV_SOURCES
|
||||
${spirv-tools_SOURCE_DIR}/include/spirv/spirv.h
|
||||
${spirv-tools_SOURCE_DIR}/include/spirv/GLSL.std.450.h
|
||||
${spirv-tools_SOURCE_DIR}/include/spirv/OpenCL.std.h
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/bitutils.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/util/hex_float.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/assembly_grammar.h
|
||||
@ -46,16 +47,18 @@ set(SPIRV_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/text.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/text_handler.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/validate.h
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/assembly_grammar.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/binary.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/disassemble.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/diagnostic.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/disassemble.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ext_inst.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/instruction.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/opcode.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/operand.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/print.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_endian.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/spirv_target_env.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/table.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/text.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/text_handler.cpp
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include "operand.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "spirv/spirv.h"
|
||||
#include "table.h"
|
||||
|
||||
namespace libspirv {
|
||||
@ -38,13 +39,17 @@ namespace libspirv {
|
||||
class AssemblyGrammar {
|
||||
public:
|
||||
explicit AssemblyGrammar(const spv_const_context context)
|
||||
: operandTable_(context->operand_table),
|
||||
: target_env_(context->target_env),
|
||||
operandTable_(context->operand_table),
|
||||
opcodeTable_(context->opcode_table),
|
||||
extInstTable_(context->ext_inst_table) {}
|
||||
|
||||
// Returns true if the internal tables have been initialized with valid data.
|
||||
bool isValid() const;
|
||||
|
||||
// Returns the SPIR-V target environment.
|
||||
spv_target_env target_env() const { return target_env_; }
|
||||
|
||||
// Fills in the desc parameter with the information about the opcode
|
||||
// of the given name. Returns SPV_SUCCESS if the opcode was found, and
|
||||
// SPV_ERROR_INVALID_LOOKUP if the opcode does not exist.
|
||||
@ -115,6 +120,7 @@ class AssemblyGrammar {
|
||||
spv_operand_pattern_t* pattern) const;
|
||||
|
||||
private:
|
||||
const spv_target_env target_env_;
|
||||
const spv_operand_table operandTable_;
|
||||
const spv_opcode_table opcodeTable_;
|
||||
const spv_ext_inst_table extInstTable_;
|
||||
|
@ -300,8 +300,8 @@ spv_result_t Parser::parseInstruction() {
|
||||
<< inst_word_count;
|
||||
}
|
||||
spv_opcode_desc opcode_desc;
|
||||
if (grammar_.lookupOpcode(inst.opcode, &opcode_desc))
|
||||
return diagnostic() << "Invalid opcode: " << int(inst.opcode);
|
||||
if (grammar_.lookupOpcode(static_cast<SpvOp>(inst.opcode), &opcode_desc))
|
||||
return diagnostic() << "Invalid opcode: " << inst.opcode;
|
||||
|
||||
// Advance past the opcode word. But remember the of the start
|
||||
// of the instruction.
|
||||
@ -397,6 +397,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
std::vector<uint32_t>* words,
|
||||
std::vector<spv_parsed_operand_t>* operands,
|
||||
spv_operand_pattern_t* expected_operands) {
|
||||
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
// We'll fill in this result as we go along.
|
||||
spv_parsed_operand_t parsed_operand;
|
||||
parsed_operand.offset = uint16_t(_.word_index - inst_offset);
|
||||
@ -414,7 +415,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
parsed_operand.number_bit_width = 0;
|
||||
|
||||
if (_.word_index >= _.num_words)
|
||||
return exhaustedInputDiagnostic(inst_offset, inst->opcode, type);
|
||||
return exhaustedInputDiagnostic(inst_offset, opcode, type);
|
||||
|
||||
const uint32_t word = peek();
|
||||
|
||||
@ -442,9 +443,8 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
// A regular value maps to its type. Some instructions (e.g. OpLabel)
|
||||
// have no type Id, and will map to 0. The result Id for a
|
||||
// type-generating instruction (e.g. OpTypeInt) maps to itself.
|
||||
_.id_to_type_id[inst->result_id] = spvOpcodeGeneratesType(inst->opcode)
|
||||
? inst->result_id
|
||||
: inst->type_id;
|
||||
_.id_to_type_id[inst->result_id] =
|
||||
spvOpcodeGeneratesType(opcode) ? inst->result_id : inst->type_id;
|
||||
break;
|
||||
|
||||
case SPV_OPERAND_TYPE_ID:
|
||||
@ -452,7 +452,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
if (!word) return diagnostic(SPV_ERROR_INVALID_ID) << "Id is 0";
|
||||
parsed_operand.type = SPV_OPERAND_TYPE_ID;
|
||||
|
||||
if (inst->opcode == SpvOpExtInst && parsed_operand.offset == 3) {
|
||||
if (opcode == SpvOpExtInst && parsed_operand.offset == 3) {
|
||||
// The current word is the extended instruction set Id.
|
||||
// Set the extended instruction set type for the current instruction.
|
||||
auto ext_inst_type_iter = _.import_id_to_ext_inst_type.find(word);
|
||||
@ -473,7 +473,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
break;
|
||||
|
||||
case SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER: {
|
||||
assert(SpvOpExtInst == inst->opcode);
|
||||
assert(SpvOpExtInst == opcode);
|
||||
assert(inst->ext_inst_type != SPV_EXT_INST_TYPE_NONE);
|
||||
spv_ext_inst_desc ext_inst;
|
||||
if (grammar_.lookupExtInst(inst->ext_inst_type, word, &ext_inst))
|
||||
@ -482,7 +482,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
} break;
|
||||
|
||||
case SPV_OPERAND_TYPE_SPEC_CONSTANT_OP_NUMBER: {
|
||||
assert(SpvOpSpecConstantOp == inst->opcode);
|
||||
assert(SpvOpSpecConstantOp == opcode);
|
||||
if (grammar_.lookupSpecConstantOpcode(SpvOp(word))) {
|
||||
return diagnostic() << "Invalid " << spvOperandTypeStr(type) << ": "
|
||||
<< word;
|
||||
@ -514,7 +514,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
case SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_TYPED_LITERAL_INTEGER:
|
||||
parsed_operand.type = SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER;
|
||||
if (inst->opcode == SpvOpSwitch) {
|
||||
if (opcode == SpvOpSwitch) {
|
||||
// The literal operands have the same type as the value
|
||||
// referenced by the selector Id.
|
||||
const uint32_t selector_id = peekAt(inst_offset + 1);
|
||||
@ -540,8 +540,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
<< " is not a scalar integer";
|
||||
}
|
||||
} else {
|
||||
assert(inst->opcode == SpvOpConstant ||
|
||||
inst->opcode == SpvOpSpecConstant);
|
||||
assert(opcode == SpvOpConstant || opcode == SpvOpSpecConstant);
|
||||
// The literal number type is determined by the type Id for the
|
||||
// constant.
|
||||
assert(inst->type_id);
|
||||
@ -565,7 +564,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
// If there was no terminating null byte, then that's an end-of-input
|
||||
// error.
|
||||
if (string_num_content_bytes == remaining_input_bytes)
|
||||
return exhaustedInputDiagnostic(inst_offset, inst->opcode, type);
|
||||
return exhaustedInputDiagnostic(inst_offset, opcode, type);
|
||||
// Account for null in the word length, so add 1 for null, then add 3 to
|
||||
// make sure we round up. The following is equivalent to:
|
||||
// (string_num_content_bytes + 1 + 3) / 4
|
||||
@ -582,7 +581,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
parsed_operand.num_words = uint16_t(string_num_words);
|
||||
parsed_operand.type = SPV_OPERAND_TYPE_LITERAL_STRING;
|
||||
|
||||
if (SpvOpExtInstImport == inst->opcode) {
|
||||
if (SpvOpExtInstImport == opcode) {
|
||||
// Record the extended instruction type for the ID for this import.
|
||||
// There is only one string literal argument to OpExtInstImport,
|
||||
// so it's sufficient to guard this just on the opcode.
|
||||
@ -696,7 +695,7 @@ spv_result_t Parser::parseOperand(size_t inst_offset,
|
||||
// handled earlier.) For example, this error can occur for a multi-word
|
||||
// argument to OpConstant, or a multi-word case literal operand for OpSwitch.
|
||||
if (_.num_words < index_after_operand)
|
||||
return exhaustedInputDiagnostic(inst_offset, inst->opcode, type);
|
||||
return exhaustedInputDiagnostic(inst_offset, opcode, type);
|
||||
|
||||
if (_.requires_endian_conversion) {
|
||||
// Copy instruction words. Translate to native endianness as needed.
|
||||
@ -742,13 +741,14 @@ spv_result_t Parser::setNumericTypeInfoForType(
|
||||
|
||||
void Parser::recordNumberType(size_t inst_offset,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
if (spvOpcodeGeneratesType(inst->opcode)) {
|
||||
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
if (spvOpcodeGeneratesType(opcode)) {
|
||||
NumberType info = {SPV_NUMBER_NONE, 0};
|
||||
if (SpvOpTypeInt == inst->opcode) {
|
||||
if (SpvOpTypeInt == opcode) {
|
||||
const bool is_signed = peekAt(inst_offset + 3) != 0;
|
||||
info.type = is_signed ? SPV_NUMBER_SIGNED_INT : SPV_NUMBER_UNSIGNED_INT;
|
||||
info.bit_width = peekAt(inst_offset + 2);
|
||||
} else if (SpvOpTypeFloat == inst->opcode) {
|
||||
} else if (SpvOpTypeFloat == opcode) {
|
||||
info.type = SPV_NUMBER_FLOATING;
|
||||
info.bit_width = peekAt(inst_offset + 2);
|
||||
}
|
||||
|
@ -182,7 +182,7 @@ spv_result_t Disassembler::HandleInstruction(
|
||||
stream_ << std::string(indent_, ' ');
|
||||
}
|
||||
|
||||
stream_ << "Op" << spvOpcodeString(inst.opcode);
|
||||
stream_ << "Op" << spvOpcodeString(static_cast<SpvOp>(inst.opcode));
|
||||
|
||||
for (uint16_t i = 0; i < inst.num_operands; i++) {
|
||||
const spv_operand_type_t type = inst.operands[i].type;
|
||||
|
@ -28,16 +28,18 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "spirv/GLSL.std.450.h"
|
||||
#include "spirv/OpenCL.std.h"
|
||||
#include "spirv_definition.h"
|
||||
|
||||
/// Generate a spv_ext_inst_desc_t literal for a GLSL std450 extended
|
||||
/// instruction with one/two/three <id> parameter(s).
|
||||
#define GLSL450Inst1(name) \
|
||||
#name, GLSLstd450::GLSLstd450##name, 0, { SPV_OPERAND_TYPE_ID }
|
||||
#define GLSL450Inst1Cap(name, cap) \
|
||||
#name, GLSLstd450::GLSLstd450##name, \
|
||||
SPV_CAPABILITY_AS_MASK(SpvCapability##cap), { \
|
||||
SPV_OPERAND_TYPE_ID \
|
||||
#define GLSL450Inst1Cap(name, cap) \
|
||||
#name, GLSLstd450::GLSLstd450##name, \
|
||||
SPV_CAPABILITY_AS_MASK(SpvCapability##cap), { \
|
||||
SPV_OPERAND_TYPE_ID \
|
||||
}
|
||||
#define GLSL450Inst2(name) \
|
||||
#name, GLSLstd450::GLSLstd450##name, 0, { \
|
||||
@ -138,9 +140,7 @@ static const spv_ext_inst_desc_t glslStd450Entries[] = {
|
||||
};
|
||||
|
||||
static const spv_ext_inst_desc_t openclEntries[] = {
|
||||
#define ExtInst(Name, Opcode, OperandList) \
|
||||
{ #Name, Opcode, 0, OperandList } \
|
||||
,
|
||||
#define ExtInst(Name, Opcode, OperandList) {#Name, Opcode, 0, OperandList},
|
||||
#define EmptyList \
|
||||
{}
|
||||
#define List(...) \
|
||||
|
@ -82,12 +82,13 @@ uint32_t spvOpcodeMake(uint16_t wordCount, SpvOp opcode) {
|
||||
return ((uint32_t)opcode) | (((uint32_t)wordCount) << 16);
|
||||
}
|
||||
|
||||
void spvOpcodeSplit(const uint32_t word, uint16_t* pWordCount, SpvOp* pOpcode) {
|
||||
void spvOpcodeSplit(const uint32_t word, uint16_t* pWordCount,
|
||||
uint16_t* pOpcode) {
|
||||
if (pWordCount) {
|
||||
*pWordCount = (uint16_t)((0xffff0000 & word) >> 16);
|
||||
}
|
||||
if (pOpcode) {
|
||||
*pOpcode = (SpvOp)(0x0000ffff & word);
|
||||
*pOpcode = 0x0000ffff & word;
|
||||
}
|
||||
}
|
||||
|
||||
@ -162,10 +163,10 @@ void spvInstructionCopy(const uint32_t* words, const SpvOp opcode,
|
||||
pInst->words[wordIndex] = spvFixWord(words[wordIndex], endian);
|
||||
if (!wordIndex) {
|
||||
uint16_t thisWordCount;
|
||||
SpvOp thisOpcode;
|
||||
uint16_t thisOpcode;
|
||||
spvOpcodeSplit(pInst->words[wordIndex], &thisWordCount, &thisOpcode);
|
||||
assert(opcode == thisOpcode && wordCount == thisWordCount &&
|
||||
"Endianness failed!");
|
||||
assert(opcode == static_cast<SpvOp>(thisOpcode) &&
|
||||
wordCount == thisWordCount && "Endianness failed!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include "instruction.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "spirv/spirv.h"
|
||||
#include "table.h"
|
||||
|
||||
// Returns the name of a registered SPIR-V generator as a null-terminated
|
||||
@ -43,7 +44,8 @@ const char* spvGeneratorStr(uint32_t generator);
|
||||
uint32_t spvOpcodeMake(uint16_t word_count, SpvOp opcode);
|
||||
|
||||
// Splits word into into two constituent parts: word_count and opcode.
|
||||
void spvOpcodeSplit(const uint32_t word, uint16_t* word_count, SpvOp* opcode);
|
||||
void spvOpcodeSplit(const uint32_t word, uint16_t* word_count,
|
||||
uint16_t* opcode);
|
||||
|
||||
// Finds the named opcode in the given opcode table. On success, returns
|
||||
// SPV_SUCCESS and writes a handle of the table entry into *entry.
|
||||
|
@ -28,6 +28,7 @@
|
||||
#define LIBSPIRV_SPIRV_CONSTANT_H_
|
||||
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "spirv/spirv.h"
|
||||
|
||||
// Version number macros.
|
||||
|
||||
@ -40,6 +41,9 @@
|
||||
// Returns the minor version extracted from a version header word.
|
||||
#define SPV_SPIRV_VERSION_MINOR_PART(WORD) ((uint32_t(WORD) >> 8) & 0xff)
|
||||
|
||||
// Returns the version number for the given SPIR-V target environment.
|
||||
uint32_t spvVersionForTargetEnv(spv_target_env env);
|
||||
|
||||
// Header indices
|
||||
|
||||
#define SPV_INDEX_MAGIC_NUMBER 0u
|
||||
|
@ -31,6 +31,8 @@
|
||||
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
#define spvIsInBitfield(value, bitfield) ((value) == ((value)&bitfield))
|
||||
|
||||
// A bit mask representing a set of capabilities.
|
||||
// Currently there are 57 distinct capabilities, so 64 bits
|
||||
// should be enough.
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2016 Google Inc. All Rights Reserved.
|
||||
// Copyright (c) 2015-2016 The Khronos Group Inc.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a
|
||||
// copy of this software and/or associated documentation files (the
|
||||
@ -24,16 +24,38 @@
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include <assert.h>
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "spirv_constant.h"
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(LibspirvMacros, Version) {
|
||||
EXPECT_EQ(1, SPV_SPIRV_VERSION_MAJOR);
|
||||
EXPECT_EQ(0, SPV_SPIRV_VERSION_MINOR);
|
||||
EXPECT_EQ(3, SPV_SPIRV_VERSION_REVISION);
|
||||
const char* spvTargetEnvDescription(spv_target_env env) {
|
||||
switch (env) {
|
||||
case SPV_ENV_UNIVERSAL_1_0:
|
||||
return "SPIR-V 1.0";
|
||||
case SPV_ENV_UNIVERSAL_1_0_4:
|
||||
return "SPIR-V 1.0 rev 4";
|
||||
case SPV_ENV_VULKAN_1_0:
|
||||
return "SPIR-V 1.0 (under Vulkan 1.0 semantics)";
|
||||
case SPV_ENV_VULKAN_1_0_7:
|
||||
return "SPIR-V 1.0 (under Vulkan 1.0.7 semantics)";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
assert(0 && "Unhandled SPIR-V target environment");
|
||||
return "";
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
uint32_t spvVersionForTargetEnv(spv_target_env env) {
|
||||
switch (env) {
|
||||
case SPV_ENV_UNIVERSAL_1_0:
|
||||
case SPV_ENV_UNIVERSAL_1_0_4:
|
||||
case SPV_ENV_VULKAN_1_0:
|
||||
case SPV_ENV_VULKAN_1_0_7:
|
||||
return SPV_SPIRV_VERSION_WORD(1, 0);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
assert(0 && "Unhandled SPIR-V target environment");
|
||||
return SPV_SPIRV_VERSION_WORD(0, 0);
|
||||
}
|
@ -47,7 +47,7 @@ spv_context spvContextCreate(spv_target_env env) {
|
||||
spvOperandTableGet(&operand_table);
|
||||
spvExtInstTableGet(&ext_inst_table);
|
||||
|
||||
return new spv_context_t{opcode_table, operand_table, ext_inst_table};
|
||||
return new spv_context_t{env, opcode_table, operand_table, ext_inst_table};
|
||||
}
|
||||
|
||||
void spvContextDestroy(spv_context context) { delete context; }
|
||||
|
@ -28,6 +28,7 @@
|
||||
#define LIBSPIRV_TABLE_H_
|
||||
|
||||
#include "spirv-tools/libspirv.h"
|
||||
#include "spirv/spirv.h"
|
||||
#include "spirv_definition.h"
|
||||
|
||||
typedef struct spv_opcode_desc_t {
|
||||
@ -96,6 +97,7 @@ typedef const spv_operand_table_t* spv_operand_table;
|
||||
typedef const spv_ext_inst_table_t* spv_ext_inst_table;
|
||||
|
||||
struct spv_context_t {
|
||||
const spv_target_env target_env;
|
||||
const spv_opcode_table opcode_table;
|
||||
const spv_operand_table operand_table;
|
||||
const spv_ext_inst_table ext_inst_table;
|
||||
|
@ -653,22 +653,18 @@ spv_result_t spvTextEncodeOpcode(const libspirv::AssemblyGrammar& grammar,
|
||||
|
||||
enum { kAssemblerVersion = 0 };
|
||||
|
||||
/// @brief Populate a binary stream's words with this generator's header.
|
||||
///
|
||||
/// @param[in,out] words the array of words
|
||||
/// @param[in] bound the upper ID bound
|
||||
///
|
||||
/// @return result code
|
||||
spv_result_t SetHeader(uint32_t* words, const uint32_t bound) {
|
||||
if (!words) return SPV_ERROR_INVALID_BINARY;
|
||||
// Populates a binary stream's |header|. The target environment is specified via
|
||||
// |env| and Id bound is via |bound|.
|
||||
spv_result_t SetHeader(spv_target_env env, const uint32_t bound,
|
||||
uint32_t* header) {
|
||||
if (!header) return SPV_ERROR_INVALID_BINARY;
|
||||
|
||||
words[SPV_INDEX_MAGIC_NUMBER] = SpvMagicNumber;
|
||||
words[SPV_INDEX_VERSION_NUMBER] =
|
||||
SPV_SPIRV_VERSION_WORD(SPV_SPIRV_VERSION_MAJOR, SPV_SPIRV_VERSION_MINOR);
|
||||
words[SPV_INDEX_GENERATOR_NUMBER] =
|
||||
header[SPV_INDEX_MAGIC_NUMBER] = SpvMagicNumber;
|
||||
header[SPV_INDEX_VERSION_NUMBER] = spvVersionForTargetEnv(env);
|
||||
header[SPV_INDEX_GENERATOR_NUMBER] =
|
||||
SPV_GENERATOR_WORD(SPV_GENERATOR_KHRONOS_ASSEMBLER, kAssemblerVersion);
|
||||
words[SPV_INDEX_BOUND] = bound;
|
||||
words[SPV_INDEX_SCHEMA] = 0; // NOTE: Reserved
|
||||
header[SPV_INDEX_BOUND] = bound;
|
||||
header[SPV_INDEX_SCHEMA] = 0; // NOTE: Reserved
|
||||
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
@ -721,7 +717,8 @@ spv_result_t spvTextToBinaryInternal(const libspirv::AssemblyGrammar& grammar,
|
||||
currentIndex += inst.words.size();
|
||||
}
|
||||
|
||||
if (auto error = SetHeader(data, context.getBound())) return error;
|
||||
if (auto error = SetHeader(grammar.target_env(), context.getBound(), data))
|
||||
return error;
|
||||
|
||||
spv_binary binary = new spv_binary_t();
|
||||
if (!binary) {
|
||||
|
@ -128,7 +128,7 @@ void DebugInstructionPass(ValidationState_t& _,
|
||||
void ProcessIds(ValidationState_t& _, const spv_parsed_instruction_t& inst) {
|
||||
if (inst.result_id) {
|
||||
_.usedefs().AddDef(
|
||||
{inst.result_id, inst.type_id, inst.opcode,
|
||||
{inst.result_id, inst.type_id, static_cast<SpvOp>(inst.opcode),
|
||||
std::vector<uint32_t>(inst.words, inst.words + inst.num_words)});
|
||||
}
|
||||
for (auto op = inst.operands; op != inst.operands + inst.num_operands; ++op) {
|
||||
@ -140,7 +140,7 @@ spv_result_t ProcessInstruction(void* user_data,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
ValidationState_t& _ = *(reinterpret_cast<ValidationState_t*>(user_data));
|
||||
_.incrementInstructionCount();
|
||||
if (inst->opcode == SpvOpEntryPoint)
|
||||
if (static_cast<SpvOp>(inst->opcode) == SpvOpEntryPoint)
|
||||
_.entry_points().push_back(inst->words[2]);
|
||||
|
||||
DebugInstructionPass(_, inst);
|
||||
@ -203,11 +203,12 @@ spv_result_t spvValidate(const spv_const_context context,
|
||||
uint64_t index = SPV_INDEX_INSTRUCTION;
|
||||
while (index < binary->wordCount) {
|
||||
uint16_t wordCount;
|
||||
SpvOp opcode;
|
||||
uint16_t opcode;
|
||||
spvOpcodeSplit(spvFixWord(binary->code[index], endian), &wordCount,
|
||||
&opcode);
|
||||
spv_instruction_t inst;
|
||||
spvInstructionCopy(&binary->code[index], opcode, wordCount, endian, &inst);
|
||||
spvInstructionCopy(&binary->code[index], static_cast<SpvOp>(opcode),
|
||||
wordCount, endian, &inst);
|
||||
instructions.push_back(inst);
|
||||
index += wordCount;
|
||||
}
|
||||
|
@ -33,25 +33,24 @@ namespace libspirv {
|
||||
spv_result_t CfgPass(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
if (_.getLayoutSection() == kLayoutFunctionDefinitions) {
|
||||
SpvOp opcode = inst->opcode;
|
||||
SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
switch (opcode) {
|
||||
case SpvOpLabel:
|
||||
spvCheckReturn(_.get_functions().RegisterBlock(inst->result_id));
|
||||
break;
|
||||
case SpvOpBranch:
|
||||
case SpvOpBranchConditional:
|
||||
case SpvOpSwitch:
|
||||
case SpvOpKill:
|
||||
case SpvOpReturn:
|
||||
case SpvOpReturnValue:
|
||||
case SpvOpUnreachable:
|
||||
spvCheckReturn(_.get_functions().RegisterBlockEnd());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
case SpvOpLabel:
|
||||
spvCheckReturn(_.get_functions().RegisterBlock(inst->result_id));
|
||||
break;
|
||||
case SpvOpBranch:
|
||||
case SpvOpBranchConditional:
|
||||
case SpvOpSwitch:
|
||||
case SpvOpKill:
|
||||
case SpvOpReturn:
|
||||
case SpvOpReturnValue:
|
||||
case SpvOpUnreachable:
|
||||
spvCheckReturn(_.get_functions().RegisterBlockEnd());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -618,10 +618,10 @@ bool idUsage::isValid<SpvOpConstantSampler>(const spv_instruction_t* inst,
|
||||
// nullability transitively.
|
||||
bool IsTypeNullable(const std::vector<uint32_t>& instruction,
|
||||
const UseDefTracker& usedefs) {
|
||||
SpvOp opcode;
|
||||
uint16_t opcode;
|
||||
uint16_t word_count;
|
||||
spvOpcodeSplit(instruction[0], &word_count, &opcode);
|
||||
switch (opcode) {
|
||||
switch (static_cast<SpvOp>(opcode)) {
|
||||
case SpvOpTypeBool:
|
||||
case SpvOpTypeInt:
|
||||
case SpvOpTypeFloat:
|
||||
|
@ -83,10 +83,11 @@ namespace libspirv {
|
||||
spv_result_t CapCheck(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
spv_opcode_desc opcode_desc;
|
||||
if (SPV_SUCCESS == _.grammar().lookupOpcode(inst->opcode, &opcode_desc) &&
|
||||
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
if (SPV_SUCCESS == _.grammar().lookupOpcode(opcode, &opcode_desc) &&
|
||||
!_.HasAnyOf(opcode_desc->capabilities))
|
||||
return _.diag(SPV_ERROR_INVALID_CAPABILITY)
|
||||
<< "Opcode " << spvOpcodeString(inst->opcode)
|
||||
<< "Opcode " << spvOpcodeString(opcode)
|
||||
<< " requires one of these capabilities: "
|
||||
<< ToString(opcode_desc->capabilities, _.grammar());
|
||||
for (int i = 0; i < inst->num_operands; ++i) {
|
||||
@ -99,7 +100,7 @@ spv_result_t CapCheck(ValidationState_t& _,
|
||||
const auto caps =
|
||||
RequiredCapabilities(_.grammar(), operand.type, mask_bit);
|
||||
if (!_.HasAnyOf(caps)) {
|
||||
return CapabilityError(_, i + 1, inst->opcode,
|
||||
return CapabilityError(_, i + 1, opcode,
|
||||
ToString(caps, _.grammar()));
|
||||
}
|
||||
}
|
||||
@ -108,8 +109,7 @@ spv_result_t CapCheck(ValidationState_t& _,
|
||||
// Check the operand word as a whole.
|
||||
const auto caps = RequiredCapabilities(_.grammar(), operand.type, word);
|
||||
if (!_.HasAnyOf(caps)) {
|
||||
return CapabilityError(_, i + 1, inst->opcode,
|
||||
ToString(caps, _.grammar()));
|
||||
return CapabilityError(_, i + 1, opcode, ToString(caps, _.grammar()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -118,10 +118,11 @@ spv_result_t CapCheck(ValidationState_t& _,
|
||||
|
||||
spv_result_t InstructionPass(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
if (inst->opcode == SpvOpCapability)
|
||||
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
if (opcode == SpvOpCapability)
|
||||
_.registerCapability(
|
||||
static_cast<SpvCapability>(inst->words[inst->operands[0].offset]));
|
||||
if (inst->opcode == SpvOpVariable) {
|
||||
if (opcode == SpvOpVariable) {
|
||||
const auto storage_class =
|
||||
static_cast<SpvStorageClass>(inst->words[inst->operands[2].offset]);
|
||||
if (storage_class == SpvStorageClassGeneric)
|
||||
|
@ -182,7 +182,7 @@ namespace libspirv {
|
||||
// Performs logical layout validation. See Section 2.4
|
||||
spv_result_t ModuleLayoutPass(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
SpvOp opcode = inst->opcode;
|
||||
const SpvOp opcode = static_cast<SpvOp>(inst->opcode);
|
||||
|
||||
switch (_.getLayoutSection()) {
|
||||
case kLayoutCapabilities:
|
||||
|
@ -99,7 +99,7 @@ namespace libspirv {
|
||||
spv_result_t SsaPass(ValidationState_t& _,
|
||||
const spv_parsed_instruction_t* inst) {
|
||||
auto can_have_forward_declared_ids =
|
||||
getCanBeForwardDeclaredFunction(inst->opcode);
|
||||
getCanBeForwardDeclaredFunction(static_cast<SpvOp>(inst->opcode));
|
||||
|
||||
for (unsigned i = 0; i < inst->num_operands; i++) {
|
||||
const spv_parsed_operand_t& operand = inst->operands[i];
|
||||
|
@ -28,10 +28,10 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
|
||||
#include "TestFixture.h"
|
||||
#include "UnitSPIRV.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "spirv/OpenCL.std.h"
|
||||
|
||||
// Returns true if two spv_parsed_operand_t values are equal.
|
||||
// To use this operator, this definition must appear in the same namespace
|
||||
@ -60,7 +60,7 @@ using ::testing::_;
|
||||
struct ParsedInstruction {
|
||||
explicit ParsedInstruction(const spv_parsed_instruction_t& inst)
|
||||
: words(inst.words, inst.words + inst.num_words),
|
||||
opcode(inst.opcode),
|
||||
opcode(static_cast<SpvOp>(inst.opcode)),
|
||||
ext_inst_type(inst.ext_inst_type),
|
||||
type_id(inst.type_id),
|
||||
result_id(inst.result_id),
|
||||
@ -463,7 +463,7 @@ INSTANTIATE_TEST_CASE_P(
|
||||
"Module has incomplete header: only 3 words instead of 5"},
|
||||
{kHeaderForBound1, 4,
|
||||
"Module has incomplete header: only 4 words instead of 5"},
|
||||
}),);
|
||||
}), );
|
||||
|
||||
// A binary parser diagnostic test case where a vector of words is
|
||||
// provided. We'll use this to express cases that can't be created
|
||||
@ -696,7 +696,7 @@ INSTANTIATE_TEST_CASE_P(
|
||||
MakeInstruction(SpvOpConstant, {1, 2, 42}),
|
||||
}),
|
||||
"Type Id 1 is not a scalar numeric type"},
|
||||
}),);
|
||||
}), );
|
||||
|
||||
// A binary parser diagnostic case generated from an assembly text input.
|
||||
struct AssemblyDiagnosticCase {
|
||||
@ -766,6 +766,6 @@ INSTANTIATE_TEST_CASE_P(
|
||||
"Invalid image operand: 511 has invalid mask component 256"},
|
||||
{"OpSelectionMerge %1 !7",
|
||||
"Invalid selection control operand: 7 has invalid mask component 4"},
|
||||
}),);
|
||||
}), );
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -421,8 +421,6 @@ TEST_F(TextToBinaryTest, VersionString) {
|
||||
Eq(SPV_SUCCESS));
|
||||
EXPECT_EQ(nullptr, diagnostic);
|
||||
|
||||
EXPECT_EQ(1, SPV_SPIRV_VERSION_MAJOR);
|
||||
EXPECT_EQ(0, SPV_SPIRV_VERSION_MINOR);
|
||||
EXPECT_THAT(decoded_text->str, HasSubstr("Version: 1.0\n"))
|
||||
<< EncodeAndDecodeSuccessfully("");
|
||||
spvTextDestroy(decoded_text);
|
||||
|
@ -88,7 +88,6 @@ if (NOT ${SPIRV_SKIP_EXECUTABLES})
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Validate.SSA.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ValidateID.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/ValidationState.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Version.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/main.cpp)
|
||||
|
||||
add_executable(UnitSPIRV ${TEST_SOURCES})
|
||||
|
@ -28,6 +28,7 @@
|
||||
|
||||
#include <gmock/gmock.h>
|
||||
#include "TestFixture.h"
|
||||
#include "spirv/OpenCL.std.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "UnitSPIRV.h"
|
||||
#include "spirv/GLSL.std.450.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -31,7 +31,7 @@ namespace {
|
||||
TEST(OpcodeSplit, Default) {
|
||||
uint32_t word = spvOpcodeMake(42, (SpvOp)23);
|
||||
uint16_t wordCount = 0;
|
||||
SpvOp opcode;
|
||||
uint16_t opcode;
|
||||
spvOpcodeSplit(word, &wordCount, &opcode);
|
||||
ASSERT_EQ(42, wordCount);
|
||||
ASSERT_EQ(23, opcode);
|
||||
|
@ -31,6 +31,8 @@
|
||||
|
||||
#include "TestFixture.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "spirv/GLSL.std.450.h"
|
||||
#include "spirv/OpenCL.std.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -54,7 +54,7 @@ Options:
|
||||
|
||||
const char kBuildVersion[] =
|
||||
#include "build-version.inc"
|
||||
;
|
||||
;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
const char* inFile = nullptr;
|
||||
@ -88,8 +88,8 @@ int main(int argc, char** argv) {
|
||||
// Long options
|
||||
if (0 == strcmp(argv[argi], "--version")) {
|
||||
printf("%s\n", kBuildVersion);
|
||||
printf("Target: SPIR-V %d.%d rev %d\n", SPV_SPIRV_VERSION_MAJOR,
|
||||
SPV_SPIRV_VERSION_MINOR, SPV_SPIRV_VERSION_REVISION);
|
||||
printf("Target: %s\n",
|
||||
spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_0_4));
|
||||
return 0;
|
||||
}
|
||||
if (0 == strcmp(argv[argi], "--help")) {
|
||||
|
@ -61,7 +61,7 @@ Options:
|
||||
|
||||
const char kBuildVersion[] =
|
||||
#include "build-version.inc"
|
||||
;
|
||||
;
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
const char* inFile = nullptr;
|
||||
@ -101,8 +101,8 @@ int main(int argc, char** argv) {
|
||||
return 0;
|
||||
} else if (0 == strcmp(argv[argi], "--version")) {
|
||||
printf("%s\n", kBuildVersion);
|
||||
printf("Target: SPIR-V %d.%d rev %d\n", SPV_SPIRV_VERSION_MAJOR,
|
||||
SPV_SPIRV_VERSION_MINOR, SPV_SPIRV_VERSION_REVISION);
|
||||
printf("Target: %s\n",
|
||||
spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_0_4));
|
||||
return 0;
|
||||
} else {
|
||||
print_usage(argv[0]);
|
||||
@ -174,8 +174,7 @@ int main(int argc, char** argv) {
|
||||
// into the output stream.
|
||||
// If the printing option is off, then save the text in memory, so
|
||||
// it can be emitted later in this function.
|
||||
const bool print_to_stdout =
|
||||
spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_PRINT, options);
|
||||
const bool print_to_stdout = SPV_BINARY_TO_TEXT_OPTION_PRINT & options;
|
||||
spv_text text;
|
||||
spv_text* textOrNull = print_to_stdout ? nullptr : &text;
|
||||
spv_diagnostic diagnostic = nullptr;
|
||||
|
@ -63,8 +63,9 @@ int main(int argc, char** argv) {
|
||||
if ('-' == cur_arg[0]) {
|
||||
if (0 == strcmp(cur_arg, "--version")) {
|
||||
printf("%s\n", kBuildVersion);
|
||||
printf("Target: SPIR-V %d.%d rev %d\n", SPV_SPIRV_VERSION_MAJOR,
|
||||
SPV_SPIRV_VERSION_MINOR, SPV_SPIRV_VERSION_REVISION);
|
||||
printf("Targets:\n %s\n %s\n",
|
||||
spvTargetEnvDescription(SPV_ENV_UNIVERSAL_1_0_4),
|
||||
spvTargetEnvDescription(SPV_ENV_VULKAN_1_0_7));
|
||||
return 0;
|
||||
} else if (0 == strcmp(cur_arg, "--help") || 0 == strcmp(cur_arg, "-h")) {
|
||||
print_usage(argv[0]);
|
||||
|
Loading…
Reference in New Issue
Block a user