mirror of
https://github.com/RPCSX/SPIRV-Tools.git
synced 2025-03-03 08:47:33 +00:00
Enforce suitable literal number operands to be unsigned integers.
Except for OpConstant and OpSpecConstant, all other literal number operands are indeed unsigned integers. So, * Rename all *LITERAL_NUMBER* operand types to *LITERAL_INTEGER*. * Expect unsigned integers for *LITERAL_INTEGER* operands. * Keep MULITPLE_WORD_LITERAL untouched since it is only used by OpConstant and OpSpecConstant. And we want to provide the capability to specify floating-point numbers after !<integer> in the alternate parsing mode. So, OPTIONAL_LITERAL_NUMBER is reserved for OPTIONAL_CIV.
This commit is contained in:
parent
5d65ea726c
commit
6483bd7132
@ -102,8 +102,8 @@ include_directories(
|
||||
|
||||
set(SPIRV_SOURCES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/libspirv/libspirv.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/util/bitwisecast.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/binary.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/bitwisecast.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/diagnostic.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/ext_inst.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/source/instruction.h
|
||||
|
@ -154,7 +154,7 @@ typedef enum spv_operand_type_t {
|
||||
SPV_OPERAND_TYPE_ID,
|
||||
SPV_OPERAND_TYPE_TYPE_ID,
|
||||
SPV_OPERAND_TYPE_RESULT_ID,
|
||||
SPV_OPERAND_TYPE_LITERAL_NUMBER,
|
||||
SPV_OPERAND_TYPE_LITERAL_INTEGER,
|
||||
// A literal number that can (but is not required to) expand multiple words.
|
||||
SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER,
|
||||
SPV_OPERAND_TYPE_LITERAL_STRING,
|
||||
@ -200,8 +200,8 @@ typedef enum spv_operand_type_t {
|
||||
// An optional image operands mask. A set bit in the mask may
|
||||
// imply that more arguments are required.
|
||||
SPV_OPERAND_TYPE_OPTIONAL_IMAGE,
|
||||
// An optional literal number.
|
||||
SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER,
|
||||
// An optional literal integer.
|
||||
SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER,
|
||||
// An optional literal string.
|
||||
SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING,
|
||||
// An optional memory access qualifier mask, e.g. Volatile, Aligned,
|
||||
@ -213,25 +213,28 @@ typedef enum spv_operand_type_t {
|
||||
// In an instruction definition, this may only appear at the end of the
|
||||
// operand types.
|
||||
SPV_OPERAND_TYPE_VARIABLE_ID,
|
||||
SPV_OPERAND_TYPE_VARIABLE_LITERAL_NUMBER,
|
||||
// A sequence of zero or more pairs of (Literal number, Id)
|
||||
SPV_OPERAND_TYPE_VARIABLE_LITERAL_NUMBER_ID,
|
||||
// A sequence of zero or more pairs of (Id, Literal number)
|
||||
SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_NUMBER,
|
||||
SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER,
|
||||
// A sequence of zero or more pairs of (Literal integer, Id)
|
||||
SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID,
|
||||
// A sequence of zero or more pairs of (Id, Literal integer)
|
||||
SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER,
|
||||
// A sequence of zero or more execution modes
|
||||
SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE,
|
||||
|
||||
// An Id that is second or later in an optional tuple of operands.
|
||||
// This must be present if the first operand in the tuple is present.
|
||||
SPV_OPERAND_TYPE_ID_IN_OPTIONAL_TUPLE,
|
||||
// A Literal number that is second or later in an optional tuple of operands.
|
||||
// A Literal integer that is second or later in an optional tuple of operands.
|
||||
// This must be present if the first operand in the tuple is present.
|
||||
SPV_OPERAND_TYPE_LITERAL_NUMBER_IN_OPTIONAL_TUPLE,
|
||||
SPV_OPERAND_TYPE_LITERAL_INTEGER_IN_OPTIONAL_TUPLE,
|
||||
|
||||
// An optional context-independent value, or CIV. CIVs are tokens that we can
|
||||
// assemble regardless of where they occur -- literals, IDs, immediate
|
||||
// integers, etc.
|
||||
SPV_OPERAND_TYPE_OPTIONAL_CIV,
|
||||
// An optional literal number. This can expand to either a literal integer or
|
||||
// a literal floating-point number.
|
||||
SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER,
|
||||
|
||||
// This is a sentinel value, and does not represent an operand type.
|
||||
// It should come last.
|
||||
|
@ -193,7 +193,7 @@ spv_result_t spvBinaryDecodeOperand(
|
||||
stream.get() << ((color) ? clr::reset() : "");
|
||||
position->index++;
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_LITERAL_NUMBER: {
|
||||
case SPV_OPERAND_TYPE_LITERAL_INTEGER: {
|
||||
// NOTE: Special case for extended instruction use
|
||||
if (OpExtInst == opcode) {
|
||||
spv_ext_inst_desc extInst;
|
||||
@ -211,8 +211,8 @@ spv_result_t spvBinaryDecodeOperand(
|
||||
}
|
||||
} // Fall through for the general case.
|
||||
case SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER:
|
||||
case SPV_OPERAND_TYPE_LITERAL_NUMBER_IN_OPTIONAL_TUPLE: {
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER:
|
||||
case SPV_OPERAND_TYPE_LITERAL_INTEGER_IN_OPTIONAL_TUPLE: {
|
||||
// TODO: Need to support multiple word literals
|
||||
stream.get() << (color ? clr::red() : "");
|
||||
if (numWords > 2) {
|
||||
|
@ -106,11 +106,11 @@ spv_operand_type_t convertOperandClassToType(spv::Op opcode,
|
||||
case OperandOptionalImage: return SPV_OPERAND_TYPE_OPTIONAL_IMAGE;
|
||||
case OperandVariableIds: return SPV_OPERAND_TYPE_VARIABLE_ID;
|
||||
// The spec only uses OptionalLiteral for an optional literal number.
|
||||
case OperandOptionalLiteral: return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER;
|
||||
case OperandOptionalLiteral: return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER;
|
||||
case OperandOptionalLiteralString: return SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING;
|
||||
// This is only used for sequences of literal numbers.
|
||||
case OperandVariableLiterals: return SPV_OPERAND_TYPE_VARIABLE_LITERAL_NUMBER;
|
||||
case OperandLiteralNumber: return SPV_OPERAND_TYPE_LITERAL_NUMBER;
|
||||
case OperandVariableLiterals: return SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER;
|
||||
case OperandLiteralNumber: return SPV_OPERAND_TYPE_LITERAL_INTEGER;
|
||||
case OperandLiteralString: return SPV_OPERAND_TYPE_LITERAL_STRING;
|
||||
case OperandSource: return SPV_OPERAND_TYPE_SOURCE_LANGUAGE;
|
||||
case OperandExecutionModel: return SPV_OPERAND_TYPE_EXECUTION_MODEL;
|
||||
@ -159,10 +159,10 @@ spv_operand_type_t convertOperandClassToType(spv::Op opcode,
|
||||
case OperandCapability: return SPV_OPERAND_TYPE_CAPABILITY;
|
||||
|
||||
// Used by GroupMemberDecorate
|
||||
case OperandVariableIdLiteral: return SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_NUMBER;
|
||||
case OperandVariableIdLiteral: return SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER;
|
||||
|
||||
// Used by Switch
|
||||
case OperandVariableLiteralId: return SPV_OPERAND_TYPE_VARIABLE_LITERAL_NUMBER_ID;
|
||||
case OperandVariableLiteralId: return SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID;
|
||||
|
||||
// These exceptional cases shouldn't occur.
|
||||
case OperandCount:
|
||||
|
@ -118,7 +118,7 @@ static const spv_operand_desc_t memoryModelEntries[] = {
|
||||
// operand.
|
||||
#define ExecMode1(mode, cap) \
|
||||
#mode, ExecutionMode##mode, SPV_CAPABILITY_AS_MASK(Capability##cap), { \
|
||||
SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE \
|
||||
SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE \
|
||||
}
|
||||
static const spv_operand_desc_t executionModeEntries[] = {
|
||||
{ExecMode1(Invocations, Geometry)},
|
||||
@ -140,13 +140,13 @@ static const spv_operand_desc_t executionModeEntries[] = {
|
||||
{"LocalSize",
|
||||
ExecutionModeLocalSize,
|
||||
0,
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_LITERAL_NUMBER,
|
||||
SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER,
|
||||
SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"LocalSizeHint",
|
||||
ExecutionModeLocalSizeHint,
|
||||
SPV_CAPABILITY_AS_MASK(CapabilityKernel),
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_LITERAL_NUMBER,
|
||||
SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_LITERAL_INTEGER,
|
||||
SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{ExecMode0(InputPoints, Geometry)},
|
||||
{ExecMode0(InputLines, Geometry)},
|
||||
{ExecMode0(InputLinesAdjacency, Geometry)},
|
||||
@ -162,7 +162,7 @@ static const spv_operand_desc_t executionModeEntries[] = {
|
||||
ExecutionModeOutputVertices,
|
||||
SPV_CAPABILITY_AS_MASK(CapabilityGeometry) |
|
||||
SPV_CAPABILITY_AS_MASK(CapabilityTessellation),
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{ExecMode0(OutputPoints, Geometry)},
|
||||
{ExecMode0(OutputLineStrip, Geometry)},
|
||||
{ExecMode0(OutputTriangleStrip, Geometry)},
|
||||
@ -542,7 +542,7 @@ static const spv_operand_desc_t decorationEntries[] = {
|
||||
"SpecId",
|
||||
DecorationSpecId,
|
||||
SPV_CAPABILITY_AS_MASK(CapabilityShader),
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER},
|
||||
},
|
||||
{"Block",
|
||||
DecorationBlock,
|
||||
@ -563,11 +563,11 @@ static const spv_operand_desc_t decorationEntries[] = {
|
||||
{"ArrayStride",
|
||||
DecorationArrayStride,
|
||||
SPV_CAPABILITY_AS_MASK(CapabilityShader),
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"MatrixStride",
|
||||
DecorationMatrixStride,
|
||||
SPV_CAPABILITY_AS_MASK(CapabilityShader),
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"GLSLShared",
|
||||
DecorationGLSLShared,
|
||||
SPV_CAPABILITY_AS_MASK(CapabilityShader),
|
||||
@ -651,39 +651,39 @@ static const spv_operand_desc_t decorationEntries[] = {
|
||||
{"Stream",
|
||||
DecorationStream,
|
||||
SPV_CAPABILITY_AS_MASK(CapabilityGeometry),
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Location",
|
||||
DecorationLocation,
|
||||
SPV_CAPABILITY_AS_MASK(CapabilityShader),
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Component",
|
||||
DecorationComponent,
|
||||
SPV_CAPABILITY_AS_MASK(CapabilityShader),
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Index",
|
||||
DecorationIndex,
|
||||
SPV_CAPABILITY_AS_MASK(CapabilityShader),
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Binding",
|
||||
DecorationBinding,
|
||||
SPV_CAPABILITY_AS_MASK(CapabilityShader),
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"DescriptorSet",
|
||||
DecorationDescriptorSet,
|
||||
SPV_CAPABILITY_AS_MASK(CapabilityShader),
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"Offset",
|
||||
DecorationOffset,
|
||||
0,
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"XfbBuffer",
|
||||
DecorationXfbBuffer,
|
||||
SPV_CAPABILITY_AS_MASK(CapabilityTransformFeedback),
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"XfbStride",
|
||||
DecorationXfbStride,
|
||||
SPV_CAPABILITY_AS_MASK(CapabilityTransformFeedback),
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
{"FuncParamAttr",
|
||||
DecorationFuncParamAttr,
|
||||
SPV_CAPABILITY_AS_MASK(CapabilityKernel),
|
||||
@ -714,7 +714,7 @@ static const spv_operand_desc_t decorationEntries[] = {
|
||||
{"Alignment",
|
||||
DecorationAlignment,
|
||||
SPV_CAPABILITY_AS_MASK(CapabilityKernel),
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE}},
|
||||
};
|
||||
|
||||
static const spv_operand_desc_t builtInEntries[] = {
|
||||
@ -1012,7 +1012,7 @@ static const spv_operand_desc_t memoryAccessEntries[] = {
|
||||
"Aligned",
|
||||
MemoryAccessAlignedMask,
|
||||
0,
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SPV_OPERAND_TYPE_NONE},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_NONE},
|
||||
},
|
||||
{"Nontemporal",
|
||||
MemoryAccessNontemporalMask,
|
||||
@ -1314,7 +1314,7 @@ const char* spvOperandTypeStr(spv_operand_type_t type) {
|
||||
return "ID";
|
||||
case SPV_OPERAND_TYPE_RESULT_ID:
|
||||
return "result ID";
|
||||
case SPV_OPERAND_TYPE_LITERAL_NUMBER:
|
||||
case SPV_OPERAND_TYPE_LITERAL_INTEGER:
|
||||
return "literal number";
|
||||
case SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER:
|
||||
return "multiple word literal number";
|
||||
@ -1418,6 +1418,7 @@ bool spvOperandIsOptional(spv_operand_type_t type) {
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_ID:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_IMAGE:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_STRING:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_EXECUTION_MODE:
|
||||
@ -1432,9 +1433,9 @@ bool spvOperandIsOptional(spv_operand_type_t type) {
|
||||
bool spvOperandIsVariable(spv_operand_type_t type) {
|
||||
switch (type) {
|
||||
case SPV_OPERAND_TYPE_VARIABLE_ID:
|
||||
case SPV_OPERAND_TYPE_VARIABLE_LITERAL_NUMBER:
|
||||
case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_NUMBER:
|
||||
case SPV_OPERAND_TYPE_VARIABLE_LITERAL_NUMBER_ID:
|
||||
case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER:
|
||||
case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER:
|
||||
case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID:
|
||||
case SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE:
|
||||
return true;
|
||||
default:
|
||||
@ -1449,22 +1450,22 @@ bool spvExpandOperandSequenceOnce(spv_operand_type_t type,
|
||||
case SPV_OPERAND_TYPE_VARIABLE_ID:
|
||||
pattern->insert(pattern->begin(), {SPV_OPERAND_TYPE_OPTIONAL_ID, type});
|
||||
return true;
|
||||
case SPV_OPERAND_TYPE_VARIABLE_LITERAL_NUMBER:
|
||||
case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER:
|
||||
pattern->insert(pattern->begin(),
|
||||
{SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER, type});
|
||||
{SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER, type});
|
||||
return true;
|
||||
case SPV_OPERAND_TYPE_VARIABLE_LITERAL_NUMBER_ID:
|
||||
case SPV_OPERAND_TYPE_VARIABLE_LITERAL_INTEGER_ID:
|
||||
// Represents Zero or more (Literal number, Id) pairs.
|
||||
pattern->insert(pattern->begin(),
|
||||
{SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER,
|
||||
{SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER,
|
||||
SPV_OPERAND_TYPE_ID_IN_OPTIONAL_TUPLE, type});
|
||||
return true;
|
||||
case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_NUMBER:
|
||||
case SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER:
|
||||
// Represents Zero or more (Id, Literal number) pairs.
|
||||
pattern->insert(
|
||||
pattern->begin(),
|
||||
{SPV_OPERAND_TYPE_OPTIONAL_ID,
|
||||
SPV_OPERAND_TYPE_LITERAL_NUMBER_IN_OPTIONAL_TUPLE, type});
|
||||
SPV_OPERAND_TYPE_LITERAL_INTEGER_IN_OPTIONAL_TUPLE, type});
|
||||
return true;
|
||||
case SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE:
|
||||
pattern->insert(pattern->begin(),
|
||||
|
@ -39,7 +39,6 @@
|
||||
#include <vector>
|
||||
|
||||
#include "binary.h"
|
||||
#include "bitwisecast.h"
|
||||
#include "diagnostic.h"
|
||||
#include "ext_inst.h"
|
||||
#include "instruction.h"
|
||||
@ -47,6 +46,7 @@
|
||||
#include "opcode.h"
|
||||
#include "operand.h"
|
||||
#include "text_handler.h"
|
||||
#include "util/bitwisecast.h"
|
||||
|
||||
bool spvIsValidIDCharacter(const char value) {
|
||||
return value == '_' || 0 != ::isalnum(value);
|
||||
@ -111,7 +111,7 @@ spv_result_t spvTextToLiteral(const char* textValue, spv_literal_t* pLiteral) {
|
||||
return SPV_FAILED_MATCH;
|
||||
bool escaping = false;
|
||||
size_t write_index = 0;
|
||||
for(const char* val = textValue + 1; val != textValue + len - 1; ++val) {
|
||||
for (const char* val = textValue + 1; val != textValue + len - 1; ++val) {
|
||||
if ((*val == '\\') && (!escaping)) {
|
||||
escaping = true;
|
||||
} else {
|
||||
@ -234,7 +234,7 @@ spv_result_t spvTextEncodeOperand(const libspirv::AssemblyGrammar& grammar,
|
||||
if (type == SPV_OPERAND_TYPE_TYPE_ID) pInst->resultTypeId = id;
|
||||
spvInstructionAddWord(pInst, id);
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_LITERAL_NUMBER: {
|
||||
case SPV_OPERAND_TYPE_LITERAL_INTEGER: {
|
||||
// NOTE: Special case for extension instruction lookup
|
||||
if (OpExtInst == pInst->opcode) {
|
||||
spv_ext_inst_desc extInst;
|
||||
@ -251,35 +251,41 @@ spv_result_t spvTextEncodeOperand(const libspirv::AssemblyGrammar& grammar,
|
||||
}
|
||||
} // Fall through for the general case.
|
||||
case SPV_OPERAND_TYPE_MULTIWORD_LITERAL_NUMBER:
|
||||
case SPV_OPERAND_TYPE_LITERAL_NUMBER_IN_OPTIONAL_TUPLE:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER: {
|
||||
case SPV_OPERAND_TYPE_LITERAL_INTEGER_IN_OPTIONAL_TUPLE:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER:
|
||||
case SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER: {
|
||||
libspirv::IdType expected_type = libspirv::kUnknownType;
|
||||
// The encoding for OpConstant, OpSpecConstant and OpSwitch all
|
||||
// depend on either their own result-id or the result-id of
|
||||
// one of their parameters.
|
||||
if (OpConstant == pInst->opcode || OpSpecConstant == pInst->opcode) {
|
||||
// Special cases for encoding possibly non-32-bit literals here.
|
||||
expected_type =
|
||||
context->getTypeOfTypeGeneratingValue(pInst->resultTypeId);
|
||||
if (!libspirv::isScalarFloating(expected_type) &&
|
||||
!libspirv::isScalarIntegral(expected_type)) {
|
||||
spv_opcode_desc d;
|
||||
const char* opcode_name = "opcode";
|
||||
if (SPV_SUCCESS == grammar.lookupOpcode(pInst->opcode, &d)) {
|
||||
opcode_name = d->name;
|
||||
if (type != SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER) {
|
||||
// From now, it's safe to assume that the current operand is an unsigned
|
||||
// integer, apart from the special cases handled below.
|
||||
expected_type = {32, false, libspirv::IdTypeClass::kScalarIntegerType};
|
||||
// The encoding for OpConstant, OpSpecConstant and OpSwitch all
|
||||
// depend on either their own result-id or the result-id of
|
||||
// one of their parameters.
|
||||
if (OpConstant == pInst->opcode || OpSpecConstant == pInst->opcode) {
|
||||
// Special cases for encoding possibly non-32-bit literals here.
|
||||
expected_type =
|
||||
context->getTypeOfTypeGeneratingValue(pInst->resultTypeId);
|
||||
if (!libspirv::isScalarFloating(expected_type) &&
|
||||
!libspirv::isScalarIntegral(expected_type)) {
|
||||
spv_opcode_desc d;
|
||||
const char* opcode_name = "opcode";
|
||||
if (SPV_SUCCESS == grammar.lookupOpcode(pInst->opcode, &d)) {
|
||||
opcode_name = d->name;
|
||||
}
|
||||
return context->diagnostic()
|
||||
<< "Type for " << opcode_name
|
||||
<< " must be a scalar floating point or integer type";
|
||||
}
|
||||
} else if (pInst->opcode == OpSwitch) {
|
||||
// We need to know the type of the selector.
|
||||
expected_type = context->getTypeOfValueInstruction(pInst->words[1]);
|
||||
if (!libspirv::isScalarIntegral(expected_type)) {
|
||||
context->diagnostic()
|
||||
<< "The selector operand for OpSwitch must be the result"
|
||||
" of an instruction that generates an integer scalar";
|
||||
return SPV_ERROR_INVALID_TEXT;
|
||||
}
|
||||
return context->diagnostic()
|
||||
<< "Type for " << opcode_name
|
||||
<< " must be a scalar floating point or integer type";
|
||||
}
|
||||
} else if (pInst->opcode == OpSwitch) {
|
||||
// We need to know the type of the selector.
|
||||
expected_type = context->getTypeOfValueInstruction(pInst->words[1]);
|
||||
if (!libspirv::isScalarIntegral(expected_type)) {
|
||||
context->diagnostic()
|
||||
<< "The selector operand for OpSwitch must be the result"
|
||||
" of an instruction that generates an integer scalar";
|
||||
return SPV_ERROR_INVALID_TEXT;
|
||||
}
|
||||
}
|
||||
|
||||
@ -479,8 +485,7 @@ spv_result_t spvTextEncodeOpcode(const libspirv::AssemblyGrammar& grammar,
|
||||
if (context->advance())
|
||||
return context->diagnostic() << "Expected opcode, found end of stream.";
|
||||
error = context->getWord(opcodeName, &nextPosition);
|
||||
if (error)
|
||||
return context->diagnostic(error) << "Internal Error";
|
||||
if (error) return context->diagnostic(error) << "Internal Error";
|
||||
if (!context->startsWithOp()) {
|
||||
return context->diagnostic() << "Invalid Opcode prefix '" << opcodeName
|
||||
<< "'.";
|
||||
@ -654,7 +659,8 @@ spv_result_t spvTextToBinaryInternal(const libspirv::AssemblyGrammar& grammar,
|
||||
if (!data) return SPV_ERROR_OUT_OF_MEMORY;
|
||||
uint64_t currentIndex = SPV_INDEX_INSTRUCTION;
|
||||
for (auto& inst : instructions) {
|
||||
memcpy(data + currentIndex, inst.words.data(), sizeof(uint32_t) * inst.words.size());
|
||||
memcpy(data + currentIndex, inst.words.data(),
|
||||
sizeof(uint32_t) * inst.words.size());
|
||||
currentIndex += inst.words.size();
|
||||
}
|
||||
|
||||
|
@ -33,11 +33,11 @@
|
||||
#include <tuple>
|
||||
|
||||
#include "binary.h"
|
||||
#include "bitwisecast.h"
|
||||
#include "ext_inst.h"
|
||||
#include "instruction.h"
|
||||
#include "opcode.h"
|
||||
#include "text.h"
|
||||
#include "util/bitwisecast.h"
|
||||
|
||||
namespace {
|
||||
|
||||
|
@ -81,7 +81,7 @@ spv_result_t spvValidateOperandValue(const spv_operand_type_t type,
|
||||
// NOTE: ID's are validated in SPV_VALIDATION_LEVEL_1, this is
|
||||
// SPV_VALIDATION_LEVEL_0
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_LITERAL_NUMBER: {
|
||||
case SPV_OPERAND_TYPE_LITERAL_INTEGER: {
|
||||
// NOTE: Implicitly valid as they are encoded as 32 bit value
|
||||
} break;
|
||||
case SPV_OPERAND_TYPE_SOURCE_LANGUAGE:
|
||||
@ -168,7 +168,7 @@ spv_result_t spvValidateBasic(const spv_instruction_t *pInsts,
|
||||
words + index, wordCount - index, position, pDiagnostic));
|
||||
// NOTE: String literals are always at the end of Opcodes
|
||||
break;
|
||||
} else if (SPV_OPERAND_TYPE_LITERAL_NUMBER == type) {
|
||||
} else if (SPV_OPERAND_TYPE_LITERAL_INTEGER == type) {
|
||||
spvCheckReturn(spvValidateOperandsLiteral(
|
||||
words + index, wordCount - index, 2, position, pDiagnostic));
|
||||
} else {
|
||||
|
@ -31,11 +31,14 @@
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include "TestFixture.h"
|
||||
#include "util/bitwisecast.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using spvtest::Concatenate;
|
||||
using spvtest::MakeInstruction;
|
||||
using spvtest::TextToBinaryTest;
|
||||
using spvutils::BitwiseCast;
|
||||
using ::testing::ElementsAre;
|
||||
using ::testing::Eq;
|
||||
using ::testing::HasSubstr;
|
||||
@ -69,7 +72,7 @@ using ImmediateIntTest = TextToBinaryTest;
|
||||
|
||||
TEST_F(ImmediateIntTest, AnyWordInSimpleStatement) {
|
||||
EXPECT_THAT(CompiledInstructions("!0x00040018 %a %b %123", kCAF),
|
||||
Eq(MakeInstruction(spv::OpTypeMatrix, {1, 2,3 })));
|
||||
Eq(MakeInstruction(spv::OpTypeMatrix, {1, 2, 3})));
|
||||
EXPECT_THAT(CompiledInstructions("OpTypeMatrix !1 %b %123", kCAF),
|
||||
Eq(MakeInstruction(spv::OpTypeMatrix, {1, 1, 2})));
|
||||
EXPECT_THAT(CompiledInstructions("OpTypeMatrix %1 !2 %123", kCAF),
|
||||
@ -117,17 +120,30 @@ TEST_F(ImmediateIntTest, IntegerFollowingImmediate) {
|
||||
EXPECT_EQ(original, CompiledInstructions("!0x00040015 1 8 1", kCAF));
|
||||
EXPECT_EQ(original, CompiledInstructions("OpTypeInt !1 8 1", kCAF));
|
||||
|
||||
// 64-bit integer literal.
|
||||
EXPECT_EQ(CompiledInstructions("OpTypeInt %i64 64 0\n"
|
||||
"OpConstant %i64 %2 5000000000", kCAF),
|
||||
// With !<integer>, we can (and can only) accept 32-bit number literals,
|
||||
// even when we declare the return type is 64-bit.
|
||||
EXPECT_EQ(Concatenate({
|
||||
MakeInstruction(OpTypeInt, {1, 64, 0}),
|
||||
MakeInstruction(OpConstant, {1, 2, 4294967295}),
|
||||
}),
|
||||
CompiledInstructions("OpTypeInt %i64 64 0\n"
|
||||
"OpConstant %i64 !2 5000000000", kCAF));
|
||||
"OpConstant %i64 !2 4294967295",
|
||||
kCAF));
|
||||
// 64-bit integer literal.
|
||||
EXPECT_EQ("Invalid word following !<integer>: 5000000000",
|
||||
CompileFailure("OpConstant !1 %2 5000000000", kCAF));
|
||||
EXPECT_EQ("Invalid word following !<integer>: 5000000000",
|
||||
CompileFailure("OpTypeInt %i64 64 0\n"
|
||||
"OpConstant %i64 !2 5000000000",
|
||||
kCAF));
|
||||
|
||||
// Negative integer.
|
||||
EXPECT_EQ(CompiledInstructions("OpTypeInt %i64 32 1\n"
|
||||
"OpConstant %i64 %2 -123", kCAF),
|
||||
"OpConstant %i64 %2 -123",
|
||||
kCAF),
|
||||
CompiledInstructions("OpTypeInt %i64 32 1\n"
|
||||
"OpConstant %i64 !2 -123", kCAF));
|
||||
"OpConstant %i64 !2 -123",
|
||||
kCAF));
|
||||
|
||||
// TODO(deki): uncomment assertions below and make them pass.
|
||||
// Hex value(s).
|
||||
@ -140,10 +156,28 @@ TEST_F(ImmediateIntTest, IntegerFollowingImmediate) {
|
||||
|
||||
// Literal floats after !<integer> are handled correctly.
|
||||
TEST_F(ImmediateIntTest, FloatFollowingImmediate) {
|
||||
EXPECT_EQ(CompiledInstructions("OpTypeMatrix %10 %2 0.123", kCAF),
|
||||
CompiledInstructions("OpTypeMatrix %10 !2 0.123", kCAF));
|
||||
EXPECT_EQ(CompiledInstructions("OpTypeMatrix %10 %2 -0.5", kCAF),
|
||||
CompiledInstructions("OpTypeMatrix %10 !2 -0.5", kCAF));
|
||||
EXPECT_EQ(
|
||||
CompiledInstructions("OpTypeFloat %1 32\nOpConstant %1 %2 0.123", kCAF),
|
||||
CompiledInstructions("OpTypeFloat %1 32\nOpConstant %1 !2 0.123", kCAF));
|
||||
EXPECT_EQ(
|
||||
CompiledInstructions("OpTypeFloat %1 32\nOpConstant %1 %2 -0.5", kCAF),
|
||||
CompiledInstructions("OpTypeFloat %1 32\nOpConstant %1 !2 -0.5", kCAF));
|
||||
EXPECT_EQ(
|
||||
CompiledInstructions("OpTypeFloat %1 32\nOpConstant %1 %2 0.123", kCAF),
|
||||
CompiledInstructions("OpTypeFloat %1 32\n!0x0004002b %1 %2 0.123", kCAF));
|
||||
EXPECT_EQ(
|
||||
CompiledInstructions("OpTypeFloat %1 32\nOpConstant %1 %2 -0.5", kCAF),
|
||||
CompiledInstructions("OpTypeFloat %1 32\n!0x0004002b %1 %2 -0.5", kCAF));
|
||||
|
||||
EXPECT_EQ(
|
||||
Concatenate({
|
||||
MakeInstruction(OpTypeInt, {1, 64, 0}),
|
||||
MakeInstruction(OpConstant, {1, 2, 0xb, 0xa}),
|
||||
MakeInstruction(OpSwitch, {2, 1234, BitwiseCast<uint32_t>(2.5f), 3}),
|
||||
}),
|
||||
CompiledInstructions("%i64 = OpTypeInt 64 0\n"
|
||||
"%big = OpConstant %i64 0xa0000000b\n"
|
||||
"OpSwitch %big !1234 2.5 %target\n"));
|
||||
}
|
||||
|
||||
// Literal strings after !<integer> are handled correctly.
|
||||
@ -272,12 +306,10 @@ TEST_F(ImmediateIntTest, ForbiddenOperands) {
|
||||
}
|
||||
|
||||
TEST_F(ImmediateIntTest, NotInteger) {
|
||||
EXPECT_THAT(CompileFailure("!abc"),
|
||||
StrEq("Invalid immediate integer: !abc"));
|
||||
EXPECT_THAT(CompileFailure("!abc"), StrEq("Invalid immediate integer: !abc"));
|
||||
EXPECT_THAT(CompileFailure("!12.3"),
|
||||
StrEq("Invalid immediate integer: !12.3"));
|
||||
EXPECT_THAT(CompileFailure("!12K"),
|
||||
StrEq("Invalid immediate integer: !12K"));
|
||||
EXPECT_THAT(CompileFailure("!12K"), StrEq("Invalid immediate integer: !12K"));
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
@ -58,7 +58,7 @@ TEST(OperandPattern, PushFrontsAreOnTheLeft) {
|
||||
}
|
||||
|
||||
TEST(OperandPattern, PopFrontsAreOnTheLeft) {
|
||||
spv_operand_pattern_t pattern{SPV_OPERAND_TYPE_LITERAL_NUMBER,
|
||||
spv_operand_pattern_t pattern{SPV_OPERAND_TYPE_LITERAL_INTEGER,
|
||||
SPV_OPERAND_TYPE_ID};
|
||||
|
||||
pattern.pop_front();
|
||||
@ -112,12 +112,12 @@ INSTANTIATE_TEST_CASE_P(
|
||||
{SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
|
||||
spv::MemoryAccessAlignedMask,
|
||||
{SUFFIX1},
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SUFFIX1}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SUFFIX1}},
|
||||
// Volatile with Aligned still has just one literal number operand.
|
||||
{SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS,
|
||||
spv::MemoryAccessVolatileMask | spv::MemoryAccessAlignedMask,
|
||||
{SUFFIX1},
|
||||
{SPV_OPERAND_TYPE_LITERAL_NUMBER, SUFFIX1}},
|
||||
{SPV_OPERAND_TYPE_LITERAL_INTEGER, SUFFIX1}},
|
||||
}));
|
||||
#undef SUFFIX0
|
||||
#undef SUFFIX1
|
||||
@ -176,7 +176,7 @@ TEST(AlternatePatternFollowingImmediate, Empty) {
|
||||
TEST(AlternatePatternFollowingImmediate, SingleElement) {
|
||||
// Spot-check a random selection of types.
|
||||
EXPECT_THAT(spvAlternatePatternFollowingImmediate(
|
||||
{SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_NUMBER}),
|
||||
{SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER}),
|
||||
Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
|
||||
EXPECT_THAT(
|
||||
spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_CAPABILITY}),
|
||||
@ -185,7 +185,7 @@ TEST(AlternatePatternFollowingImmediate, SingleElement) {
|
||||
spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_LOOP_CONTROL}),
|
||||
Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
|
||||
EXPECT_THAT(spvAlternatePatternFollowingImmediate(
|
||||
{SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER}),
|
||||
{SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER}),
|
||||
Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
|
||||
EXPECT_THAT(spvAlternatePatternFollowingImmediate({SPV_OPERAND_TYPE_ID}),
|
||||
Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
|
||||
@ -204,9 +204,9 @@ TEST(AlternatePatternFollowingImmediate, SingleResultId) {
|
||||
TEST(AlternatePatternFollowingImmediate, MultipleNonResultIds) {
|
||||
EXPECT_THAT(
|
||||
spvAlternatePatternFollowingImmediate(
|
||||
{SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_NUMBER,
|
||||
{SPV_OPERAND_TYPE_VARIABLE_ID_LITERAL_INTEGER,
|
||||
SPV_OPERAND_TYPE_CAPABILITY, SPV_OPERAND_TYPE_LOOP_CONTROL,
|
||||
SPV_OPERAND_TYPE_OPTIONAL_LITERAL_NUMBER, SPV_OPERAND_TYPE_ID,
|
||||
SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER, SPV_OPERAND_TYPE_ID,
|
||||
SPV_OPERAND_TYPE_VARIABLE_EXECUTION_MODE}),
|
||||
Eq(spv_operand_pattern_t{SPV_OPERAND_TYPE_OPTIONAL_CIV}));
|
||||
}
|
||||
|
@ -48,6 +48,27 @@ TEST_F(TextToBinaryTest, LiteralNumberInPlaceOfLiteralString) {
|
||||
CompileFailure("OpSourceExtension 1000"));
|
||||
}
|
||||
|
||||
TEST_F(TextToBinaryTest, LiteralFloatInPlaceOfLiteralInteger) {
|
||||
EXPECT_EQ("Invalid unsigned integer literal: 10.5",
|
||||
CompileFailure("OpSource GLSL 10.5"));
|
||||
|
||||
EXPECT_EQ("Invalid unsigned integer literal: 0.2",
|
||||
CompileFailure(R"(OpMemberName %type 0.2 "member0.2")"));
|
||||
|
||||
EXPECT_EQ("Invalid unsigned integer literal: 32.42",
|
||||
CompileFailure("%int = OpTypeInt 32.42 0"));
|
||||
|
||||
EXPECT_EQ("Invalid unsigned integer literal: 4.5",
|
||||
CompileFailure("%mat = OpTypeMatrix %vec 4.5"));
|
||||
|
||||
EXPECT_EQ("Invalid unsigned integer literal: 1.5",
|
||||
CompileFailure("OpExecutionMode %main LocalSize 1.5 1.6 1.7"));
|
||||
|
||||
EXPECT_EQ("Invalid unsigned integer literal: 0.123",
|
||||
CompileFailure("%i32 = OpTypeInt 32 1\n"
|
||||
"%c = OpConstant %i32 0.123"));
|
||||
}
|
||||
|
||||
TEST_F(TextToBinaryTest, LiteralStringASCIILong) {
|
||||
// SPIR-V allows strings up to 65535 characters.
|
||||
// Test the simple case of UTF-8 code points corresponding
|
||||
|
Loading…
x
Reference in New Issue
Block a user