Skip to content

Commit a518a01

Browse files
spirv-val: Add Concrete pointer check
1 parent a8a38c4 commit a518a01

4 files changed

Lines changed: 116 additions & 10 deletions

File tree

source/val/validate_misc.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ spv_result_t ValidateSizeOf(ValidationState_t& _, const Instruction* inst) {
8888
return _.diag(SPV_ERROR_INVALID_DATA, inst)
8989
<< "Expected OpSizeOf Result Type to be a 32-bit int scalar.";
9090
}
91+
92+
uint32_t pointer_id = inst->GetOperandAs<uint32_t>(2);
93+
if (!_.IsConcreteType(pointer_id)) {
94+
return _.diag(SPV_ERROR_INVALID_DATA, inst)
95+
<< "OpSizeOf Pointer operand is not concrete.";
96+
}
97+
9198
return SPV_SUCCESS;
9299
}
93100

source/val/validation_state.cpp

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "source/val/construct.h"
3131
#include "source/val/function.h"
3232
#include "spirv-tools/libspirv.h"
33+
#include "spirv/unified1/spirv.hpp11"
3334

3435
namespace spvtools {
3536
namespace val {
@@ -926,22 +927,16 @@ uint32_t ValidationState_t::GetComponentType(uint32_t id) const {
926927

927928
case spv::Op::OpTypeArray:
928929
case spv::Op::OpTypeRuntimeArray:
929-
return inst->word(2);
930-
931930
case spv::Op::OpTypeVector:
932-
return inst->word(2);
933-
934-
case spv::Op::OpTypeMatrix:
935-
return GetComponentType(inst->word(2));
936-
931+
case spv::Op::OpTypeVectorIdEXT:
937932
case spv::Op::OpTypeCooperativeMatrixNV:
938933
case spv::Op::OpTypeCooperativeMatrixKHR:
939-
case spv::Op::OpTypeVectorIdEXT:
940-
return inst->word(2);
941-
942934
case spv::Op::OpTypeTensorARM:
943935
return inst->word(2);
944936

937+
case spv::Op::OpTypeMatrix:
938+
return GetComponentType(inst->word(2));
939+
945940
default:
946941
break;
947942
}
@@ -1547,6 +1542,57 @@ bool ValidationState_t::IsTensorType(uint32_t id) const {
15471542
return inst && inst->opcode() == spv::Op::OpTypeTensorARM;
15481543
}
15491544

1545+
// From the spec (SPIRV.html#PhysicalPointerType)
1546+
bool ValidationState_t::IsPhysicalPointerType(uint32_t id) const {
1547+
const Instruction* inst = FindDef(id);
1548+
const spv::Op opcode = inst->opcode();
1549+
if (opcode != spv::Op::OpTypePointer &&
1550+
opcode != spv::Op::OpTypeUntypedPointerKHR) {
1551+
return false;
1552+
}
1553+
1554+
const spv::AddressingModel am = addressing_model();
1555+
if (am == spv::AddressingModel::Logical) {
1556+
return false;
1557+
} else if (am == spv::AddressingModel::Physical32 ||
1558+
am == spv::AddressingModel::Physical64) {
1559+
return true;
1560+
} else if (am == spv::AddressingModel::PhysicalStorageBuffer64) {
1561+
const spv::StorageClass storage_class = spv::StorageClass(inst->word(2));
1562+
return storage_class == spv::StorageClass::PhysicalStorageBuffer;
1563+
}
1564+
1565+
assert(0);
1566+
return false;
1567+
}
1568+
1569+
// From the spec (SPIRV.html#Numerical)
1570+
bool ValidationState_t::IsNumericalType(uint32_t id) const {
1571+
const Instruction* inst = FindDef(id);
1572+
const spv::Op opcode = inst->opcode();
1573+
return opcode == spv::Op::OpTypeInt || opcode == spv::Op::OpTypeFloat;
1574+
}
1575+
1576+
// From the spec (SPIRV.html#Concrete)
1577+
bool ValidationState_t::IsConcreteType(uint32_t id) const {
1578+
const Instruction* inst = FindDef(id);
1579+
const spv::Op opcode = inst->opcode();
1580+
1581+
if (opcode == spv::Op::OpTypeStruct) {
1582+
// all elements must be concrete
1583+
for (uint32_t i = 1; i < inst->operands().size(); ++i) {
1584+
if (!IsConcreteType(inst->GetOperandAs<uint32_t>(i))) {
1585+
return false;
1586+
}
1587+
}
1588+
return true;
1589+
}
1590+
1591+
const uint32_t component_type = GetComponentType(id);
1592+
return IsNumericalType(component_type) ||
1593+
IsPhysicalPointerType(component_type);
1594+
}
1595+
15501596
spv_result_t ValidationState_t::CooperativeMatrixShapesMatch(
15511597
const Instruction* inst, uint32_t result_type_id, uint32_t m2,
15521598
bool is_conversion, bool swap_row_col) {

source/val/validation_state.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,9 @@ class ValidationState_t {
708708
bool IsIntCooperativeVectorNVType(uint32_t id) const;
709709
bool IsUnsignedIntCooperativeVectorNVType(uint32_t id) const;
710710
bool IsTensorType(uint32_t id) const;
711+
bool IsPhysicalPointerType(uint32_t id) const;
712+
bool IsNumericalType(uint32_t id) const;
713+
bool IsConcreteType(uint32_t id) const;
711714
// When |length| is not 0, return true only if the array length is equal to
712715
// |length| and the array length is not defined by a specialization constant.
713716
bool IsArrayType(uint32_t id, uint64_t length = 0) const;

test/val/val_misc_test.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,56 @@ TEST_F(ValidateMisc, SizeOfValid) {
105105
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
106106
}
107107

108+
TEST_F(ValidateMisc, SizeOfStructValid) {
109+
const std::string spirv = R"(
110+
OpCapability Addresses
111+
OpCapability Kernel
112+
OpMemoryModel Physical64 OpenCL
113+
OpEntryPoint Kernel %f "f"
114+
%void = OpTypeVoid
115+
%i32 = OpTypeInt 32 0
116+
%ptr = OpTypePointer CrossWorkgroup %i32
117+
%struct_a = OpTypeStruct %ptr %i32
118+
%struct_b = OpTypeStruct %struct_a %ptr
119+
%fnTy = OpTypeFunction %void
120+
%f = OpFunction %void None %fnTy
121+
%entry = OpLabel
122+
%s = OpSizeOf %i32 %struct_b
123+
OpReturn
124+
OpFunctionEnd
125+
)";
126+
127+
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_1);
128+
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
129+
}
130+
131+
TEST_F(ValidateMisc, SizeOfStructWithAbstract) {
132+
const std::string spirv = R"(
133+
OpCapability Addresses
134+
OpCapability Kernel
135+
OpMemoryModel Physical64 OpenCL
136+
OpEntryPoint Kernel %f "f"
137+
%void = OpTypeVoid
138+
%i32 = OpTypeInt 32 0
139+
%bool = OpTypeBool
140+
%ptr = OpTypePointer CrossWorkgroup %i32
141+
%struct_a = OpTypeStruct %ptr %bool
142+
%struct_b = OpTypeStruct %struct_a %ptr
143+
%fnTy = OpTypeFunction %void
144+
%f = OpFunction %void None %fnTy
145+
%entry = OpLabel
146+
%s = OpSizeOf %i32 %struct_b
147+
OpReturn
148+
OpFunctionEnd
149+
)";
150+
151+
CompileSuccessfully(spirv, SPV_ENV_UNIVERSAL_1_1);
152+
EXPECT_EQ(SPV_ERROR_INVALID_DATA,
153+
ValidateInstructions(SPV_ENV_UNIVERSAL_1_1));
154+
EXPECT_THAT(getDiagnosticString(),
155+
HasSubstr("OpSizeOf Pointer operand is not concrete"));
156+
}
157+
108158
TEST_F(ValidateMisc, SizeOfFloat) {
109159
const std::string spirv = R"(
110160
OpCapability Addresses

0 commit comments

Comments
 (0)