Skip to content

Commit 7779d4d

Browse files
spirv-val: Add Concrete pointer check
1 parent 38e504d commit 7779d4d

4 files changed

Lines changed: 105 additions & 12 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: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -927,22 +927,16 @@ uint32_t ValidationState_t::GetComponentType(uint32_t id) const {
927927

928928
case spv::Op::OpTypeArray:
929929
case spv::Op::OpTypeRuntimeArray:
930-
return inst->word(2);
931-
932930
case spv::Op::OpTypeVector:
933-
return inst->word(2);
934-
935-
case spv::Op::OpTypeMatrix:
936-
return GetComponentType(inst->word(2));
937-
931+
case spv::Op::OpTypeVectorIdEXT:
938932
case spv::Op::OpTypeCooperativeMatrixNV:
939933
case spv::Op::OpTypeCooperativeMatrixKHR:
940-
case spv::Op::OpTypeVectorIdEXT:
941-
return inst->word(2);
942-
943934
case spv::Op::OpTypeTensorARM:
944935
return inst->word(2);
945936

937+
case spv::Op::OpTypeMatrix:
938+
return GetComponentType(inst->word(2));
939+
946940
default:
947941
break;
948942
}
@@ -1548,15 +1542,55 @@ bool ValidationState_t::IsTensorType(uint32_t id) const {
15481542
return inst && inst->opcode() == spv::Op::OpTypeTensorARM;
15491543
}
15501544

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+
15511576
// From the spec (SPIRV.html#Concrete)
15521577
bool ValidationState_t::IsConcreteType(uint32_t id) const {
15531578
const Instruction* inst = FindDef(id);
15541579
const spv::Op opcode = inst->opcode();
15551580

1556-
if (opcode == spv::Op::OpTypeInt || opcode == spv::Op::OpTypeFloat) {
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+
}
15571588
return true;
15581589
}
1559-
return inst && inst->opcode() == spv::Op::OpTypeTensorARM;
1590+
1591+
const uint32_t component_type = GetComponentType(id);
1592+
return IsNumericalType(component_type) ||
1593+
IsPhysicalPointerType(component_type);
15601594
}
15611595

15621596
spv_result_t ValidationState_t::CooperativeMatrixShapesMatch(

source/val/validation_state.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,8 @@ 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;
711713
bool IsConcreteType(uint32_t id) const;
712714
// When |length| is not 0, return true only if the array length is equal to
713715
// |length| and the array length is not defined by a specialization constant.

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)