Validator pass for image instructions

Includes validation rules for OpImageXXX and ImageOperand.

Doesn't include OpTypeImage and OpImageSparseXXX.

Disabled an invalid test.
This commit is contained in:
Andrey Tuganov 2017-10-26 15:30:23 -04:00 committed by David Neto
parent e28edd458b
commit f407ae2b50
10 changed files with 4532 additions and 2 deletions

View File

@ -41,6 +41,7 @@ SPVTOOLS_SRC_FILES := \
source/validate_datarules.cpp \ source/validate_datarules.cpp \
source/validate_decorations.cpp \ source/validate_decorations.cpp \
source/validate_id.cpp \ source/validate_id.cpp \
source/validate_image.cpp \
source/validate_instruction.cpp \ source/validate_instruction.cpp \
source/validate_layout.cpp \ source/validate_layout.cpp \
source/validate_logicals.cpp \ source/validate_logicals.cpp \

View File

@ -261,6 +261,7 @@ set(SPIRV_SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/validate_datarules.cpp ${CMAKE_CURRENT_SOURCE_DIR}/validate_datarules.cpp
${CMAKE_CURRENT_SOURCE_DIR}/validate_decorations.cpp ${CMAKE_CURRENT_SOURCE_DIR}/validate_decorations.cpp
${CMAKE_CURRENT_SOURCE_DIR}/validate_id.cpp ${CMAKE_CURRENT_SOURCE_DIR}/validate_id.cpp
${CMAKE_CURRENT_SOURCE_DIR}/validate_image.cpp
${CMAKE_CURRENT_SOURCE_DIR}/validate_instruction.cpp ${CMAKE_CURRENT_SOURCE_DIR}/validate_instruction.cpp
${CMAKE_CURRENT_SOURCE_DIR}/validate_layout.cpp ${CMAKE_CURRENT_SOURCE_DIR}/validate_layout.cpp
${CMAKE_CURRENT_SOURCE_DIR}/validate_logicals.cpp ${CMAKE_CURRENT_SOURCE_DIR}/validate_logicals.cpp

View File

@ -438,8 +438,12 @@ bool ValidationState_t::RegisterUniqueTypeDeclaration(
uint32_t ValidationState_t::GetTypeId(uint32_t id) const { uint32_t ValidationState_t::GetTypeId(uint32_t id) const {
const Instruction* inst = FindDef(id); const Instruction* inst = FindDef(id);
assert(inst); return inst ? inst->type_id() : 0;
return inst->type_id(); }
SpvOp ValidationState_t::GetIdOpcode(uint32_t id) const {
const Instruction* inst = FindDef(id);
return inst ? inst->opcode() : SpvOpNop;
} }
uint32_t ValidationState_t::GetComponentType(uint32_t id) const { uint32_t ValidationState_t::GetComponentType(uint32_t id) const {
@ -523,6 +527,21 @@ bool ValidationState_t::IsFloatVectorType(uint32_t id) const {
return false; return false;
} }
bool ValidationState_t::IsFloatScalarOrVectorType(uint32_t id) const {
const Instruction* inst = FindDef(id);
assert(inst);
if (inst->opcode() == SpvOpTypeFloat) {
return true;
}
if (inst->opcode() == SpvOpTypeVector) {
return IsFloatScalarType(GetComponentType(id));
}
return false;
}
bool ValidationState_t::IsIntScalarType(uint32_t id) const { bool ValidationState_t::IsIntScalarType(uint32_t id) const {
const Instruction* inst = FindDef(id); const Instruction* inst = FindDef(id);
assert(inst); assert(inst);
@ -540,6 +559,21 @@ bool ValidationState_t::IsIntVectorType(uint32_t id) const {
return false; return false;
} }
bool ValidationState_t::IsIntScalarOrVectorType(uint32_t id) const {
const Instruction* inst = FindDef(id);
assert(inst);
if (inst->opcode() == SpvOpTypeInt) {
return true;
}
if (inst->opcode() == SpvOpTypeVector) {
return IsIntScalarType(GetComponentType(id));
}
return false;
}
bool ValidationState_t::IsUnsignedIntScalarType(uint32_t id) const { bool ValidationState_t::IsUnsignedIntScalarType(uint32_t id) const {
const Instruction* inst = FindDef(id); const Instruction* inst = FindDef(id);
assert(inst); assert(inst);
@ -591,6 +625,21 @@ bool ValidationState_t::IsBoolVectorType(uint32_t id) const {
return false; return false;
} }
bool ValidationState_t::IsBoolScalarOrVectorType(uint32_t id) const {
const Instruction* inst = FindDef(id);
assert(inst);
if (inst->opcode() == SpvOpTypeBool) {
return true;
}
if (inst->opcode() == SpvOpTypeVector) {
return IsBoolScalarType(GetComponentType(id));
}
return false;
}
bool ValidationState_t::IsFloatMatrixType(uint32_t id) const { bool ValidationState_t::IsFloatMatrixType(uint32_t id) const {
const Instruction* inst = FindDef(id); const Instruction* inst = FindDef(id);
assert(inst); assert(inst);
@ -673,4 +722,27 @@ uint32_t ValidationState_t::GetOperandTypeId(
return GetTypeId(inst->words[operand.offset]); return GetTypeId(inst->words[operand.offset]);
} }
bool ValidationState_t::GetConstantValUint64(uint32_t id, uint64_t* val) const {
const Instruction* inst = FindDef(id);
if (!inst) {
assert(0 && "Instruction not found");
return false;
}
if (inst->opcode() != SpvOpConstant && inst->opcode() != SpvOpSpecConstant)
return false;
if (!IsIntScalarType(inst->type_id()))
return false;
if (inst->words().size() == 4) {
*val = inst->word(3);
} else {
assert(inst->words().size() == 5);
*val = inst->word(3);
*val |= uint64_t(inst->word(4)) << 32;
}
return true;
}
} // namespace libspirv } // namespace libspirv

View File

@ -371,20 +371,31 @@ class ValidationState_t {
// Only works for types not for objects. // Only works for types not for objects.
bool IsFloatScalarType(uint32_t id) const; bool IsFloatScalarType(uint32_t id) const;
bool IsFloatVectorType(uint32_t id) const; bool IsFloatVectorType(uint32_t id) const;
bool IsFloatScalarOrVectorType(uint32_t id) const;
bool IsFloatMatrixType(uint32_t id) const; bool IsFloatMatrixType(uint32_t id) const;
bool IsIntScalarType(uint32_t id) const; bool IsIntScalarType(uint32_t id) const;
bool IsIntVectorType(uint32_t id) const; bool IsIntVectorType(uint32_t id) const;
bool IsIntScalarOrVectorType(uint32_t id) const;
bool IsUnsignedIntScalarType(uint32_t id) const; bool IsUnsignedIntScalarType(uint32_t id) const;
bool IsUnsignedIntVectorType(uint32_t id) const; bool IsUnsignedIntVectorType(uint32_t id) const;
bool IsSignedIntScalarType(uint32_t id) const; bool IsSignedIntScalarType(uint32_t id) const;
bool IsSignedIntVectorType(uint32_t id) const; bool IsSignedIntVectorType(uint32_t id) const;
bool IsBoolScalarType(uint32_t id) const; bool IsBoolScalarType(uint32_t id) const;
bool IsBoolVectorType(uint32_t id) const; bool IsBoolVectorType(uint32_t id) const;
bool IsBoolScalarOrVectorType(uint32_t id) const;
bool IsPointerType(uint32_t id) const; bool IsPointerType(uint32_t id) const;
// Gets value from OpConstant and OpSpecConstant as uint64.
// Returns false on failure (no instruction, wrong instruction, not int).
bool GetConstantValUint64(uint32_t id, uint64_t* val) const;
// Returns type_id if id has type or zero otherwise. // Returns type_id if id has type or zero otherwise.
uint32_t GetTypeId(uint32_t id) const; uint32_t GetTypeId(uint32_t id) const;
// Returns opcode of the instruction which issued the id or OpNop if the
// instruction is not registered.
SpvOp GetIdOpcode(uint32_t id) const;
// Returns type_id for given id operand if it has a type or zero otherwise. // Returns type_id for given id operand if it has a type or zero otherwise.
// |operand_index| is expected to be pointing towards an operand which is an // |operand_index| is expected to be pointing towards an operand which is an
// id. // id.

View File

@ -183,6 +183,7 @@ spv_result_t ProcessInstruction(void* user_data,
if (auto error = ConversionPass(_, inst)) return error; if (auto error = ConversionPass(_, inst)) return error;
if (auto error = LogicalsPass(_, inst)) return error; if (auto error = LogicalsPass(_, inst)) return error;
if (auto error = BitwisePass(_, inst)) return error; if (auto error = BitwisePass(_, inst)) return error;
if (auto error = ImagePass(_, inst)) return error;
return SPV_SUCCESS; return SPV_SUCCESS;
} }

View File

@ -127,6 +127,10 @@ spv_result_t LogicalsPass(ValidationState_t& _,
spv_result_t BitwisePass(ValidationState_t& _, spv_result_t BitwisePass(ValidationState_t& _,
const spv_parsed_instruction_t* inst); const spv_parsed_instruction_t* inst);
/// Validates correctness of image instructions.
spv_result_t ImagePass(ValidationState_t& _,
const spv_parsed_instruction_t* inst);
// Validates that capability declarations use operands allowed in the current // Validates that capability declarations use operands allowed in the current
// context. // context.
spv_result_t CapabilityPass(ValidationState_t& _, spv_result_t CapabilityPass(ValidationState_t& _,

1389
source/validate_image.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -98,6 +98,12 @@ add_spvtools_unittest(TARGET val_bitwise
LIBS ${SPIRV_TOOLS} LIBS ${SPIRV_TOOLS}
) )
add_spvtools_unittest(TARGET val_image
SRCS val_image_test.cpp
${VAL_TEST_COMMON_SRCS}
LIBS ${SPIRV_TOOLS}
)
add_spvtools_unittest(TARGET val_limits add_spvtools_unittest(TARGET val_limits
SRCS val_limits_test.cpp SRCS val_limits_test.cpp
${VAL_TEST_COMMON_SRCS} ${VAL_TEST_COMMON_SRCS}

View File

@ -1402,6 +1402,10 @@ make_pair(string(kOpenCLMemoryModel) +
MatrixDependencies()))),); MatrixDependencies()))),);
// clang-format on // clang-format on
#if 0
// TODO(atgoo@github.com) The following test is not valid as it generates
// invalid combinations of images, instructions and image operands.
//
// Creates assembly containing an OpImageFetch instruction using operands for // Creates assembly containing an OpImageFetch instruction using operands for
// the image-operands part. The assembly defines constants %fzero and %izero // the image-operands part. The assembly defines constants %fzero and %izero
// that can be used for operands where IDs are required. The assembly is valid, // that can be used for operands where IDs are required. The assembly is valid,
@ -1448,6 +1452,7 @@ INSTANTIATE_TEST_CASE_P(
vector<string>{"MinLod"}), vector<string>{"MinLod"}),
make_pair(ImageOperandsTemplate("Lod|Sample %fzero %izero"), make_pair(ImageOperandsTemplate("Lod|Sample %fzero %izero"),
AllCapabilities()))), ); AllCapabilities()))), );
#endif
// TODO(umar): Instruction capability checks // TODO(umar): Instruction capability checks

3040
test/val/val_image_test.cpp Normal file

File diff suppressed because it is too large Load Diff