mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-10-18 19:20:05 +00:00
Validate decorations from SPV_KHR_no_integer_wrap (#2271)
Validates NoSignedWrap, NoUnsignedWrap. We are permissive by allowing any extended instruction.
This commit is contained in:
parent
df5bd2d05a
commit
6958d11bc2
@ -1180,6 +1180,36 @@ spv_result_t CheckUniformDecoration(ValidationState_t& vstate,
|
||||
return SPV_SUCCESS;
|
||||
}
|
||||
|
||||
// Returns SPV_SUCCESS if validation rules are satisfied for NoSignedWrap or
|
||||
// NoUnsignedWrap decorations. Otherwise emits a diagnostic and returns
|
||||
// something other than SPV_SUCCESS. Assumes each decoration on a group has been
|
||||
// propagated down to the group members.
|
||||
spv_result_t CheckIntegerWrapDecoration(ValidationState_t& vstate,
|
||||
const Instruction& inst,
|
||||
const Decoration& decoration) {
|
||||
switch (inst.opcode()) {
|
||||
case SpvOpIAdd:
|
||||
case SpvOpISub:
|
||||
case SpvOpIMul:
|
||||
case SpvOpShiftLeftLogical:
|
||||
case SpvOpSNegate:
|
||||
return SPV_SUCCESS;
|
||||
case SpvOpExtInst:
|
||||
// TODO(dneto): Only certain extended instructions allow these
|
||||
// decorations. For now allow anything.
|
||||
return SPV_SUCCESS;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return vstate.diag(SPV_ERROR_INVALID_ID, &inst)
|
||||
<< (decoration.dec_type() == SpvDecorationNoSignedWrap
|
||||
? "NoSignedWrap"
|
||||
: "NoUnsignedWrap")
|
||||
<< " decoration may not be applied to "
|
||||
<< spvOpcodeString(inst.opcode());
|
||||
}
|
||||
|
||||
#define PASS_OR_BAIL_AT_LINE(X, LINE) \
|
||||
{ \
|
||||
spv_result_t e##LINE = (X); \
|
||||
@ -1216,6 +1246,10 @@ spv_result_t CheckDecorationsFromDecoration(ValidationState_t& vstate) {
|
||||
case SpvDecorationUniform:
|
||||
PASS_OR_BAIL(CheckUniformDecoration(vstate, *inst, decoration));
|
||||
break;
|
||||
case SpvDecorationNoSignedWrap:
|
||||
case SpvDecorationNoUnsignedWrap:
|
||||
PASS_OR_BAIL(CheckIntegerWrapDecoration(vstate, *inst, decoration));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -4810,6 +4810,282 @@ TEST_F(ValidateDecorations, BlockAndBufferBlockDecorationsOnSameID) {
|
||||
"ID '2' decorated with both BufferBlock and Block is not allowed."));
|
||||
}
|
||||
|
||||
std::string MakeIntegerShader(
|
||||
const std::string& decoration, const std::string& inst,
|
||||
const std::string& extension =
|
||||
"OpExtension \"SPV_KHR_no_integer_wrap_decoration\"") {
|
||||
return R"(
|
||||
OpCapability Shader
|
||||
OpCapability Linkage
|
||||
)" + extension +
|
||||
R"(
|
||||
%glsl = OpExtInstImport "GLSL.std.450"
|
||||
%opencl = OpExtInstImport "OpenCL.std"
|
||||
OpMemoryModel Logical GLSL450
|
||||
OpEntryPoint GLCompute %main "main"
|
||||
OpName %entry "entry"
|
||||
)" + decoration +
|
||||
R"(
|
||||
%void = OpTypeVoid
|
||||
%voidfn = OpTypeFunction %void
|
||||
%int = OpTypeInt 32 1
|
||||
%zero = OpConstantNull %int
|
||||
%float = OpTypeFloat 32
|
||||
%float0 = OpConstantNull %float
|
||||
%main = OpFunction %void None %voidfn
|
||||
%entry = OpLabel
|
||||
)" + inst +
|
||||
R"(
|
||||
OpReturn
|
||||
OpFunctionEnd)";
|
||||
}
|
||||
|
||||
// NoSignedWrap
|
||||
|
||||
TEST_F(ValidateDecorations, NoSignedWrapOnTypeBad) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %void NoSignedWrap", "");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("NoSignedWrap decoration may not be applied to TypeVoid"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoSignedWrapOnLabelBad) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %entry NoSignedWrap", "");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("NoSignedWrap decoration may not be applied to Label"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoSignedWrapRequiresExtensionBad) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
|
||||
"%val = OpIAdd %int %zero %zero", "");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("requires one of these extensions: "
|
||||
"SPV_KHR_no_integer_wrap_decoration"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoSignedWrapIAddGood) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
|
||||
"%val = OpIAdd %int %zero %zero");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoSignedWrapISubGood) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
|
||||
"%val = OpISub %int %zero %zero");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoSignedWrapIMulGood) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
|
||||
"%val = OpIMul %int %zero %zero");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoSignedWrapShiftLeftLogicalGood) {
|
||||
std::string spirv =
|
||||
MakeIntegerShader("OpDecorate %val NoSignedWrap",
|
||||
"%val = OpShiftLeftLogical %int %zero %zero");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoSignedWrapSNegateGood) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
|
||||
"%val = OpSNegate %int %zero");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoSignedWrapSRemBad) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
|
||||
"%val = OpSRem %int %zero %zero");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("NoSignedWrap decoration may not be applied to SRem"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoSignedWrapFAddBad) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %val NoSignedWrap",
|
||||
"%val = OpFAdd %float %float0 %float0");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("NoSignedWrap decoration may not be applied to FAdd"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoSignedWrapExtInstOpenCLGood) {
|
||||
std::string spirv =
|
||||
MakeIntegerShader("OpDecorate %val NoSignedWrap",
|
||||
"%val = OpExtInst %int %opencl s_abs %zero");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoSignedWrapExtInstGLSLGood) {
|
||||
std::string spirv = MakeIntegerShader(
|
||||
"OpDecorate %val NoSignedWrap", "%val = OpExtInst %int %glsl SAbs %zero");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
}
|
||||
|
||||
// TODO(dneto): For NoSignedWrap and NoUnsignedWrap, permit
|
||||
// "OpExtInst for instruction numbers specified in the extended
|
||||
// instruction-set specifications as accepting this decoration."
|
||||
|
||||
// NoUnignedWrap
|
||||
|
||||
TEST_F(ValidateDecorations, NoUnsignedWrapOnTypeBad) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %void NoUnsignedWrap", "");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("NoUnsignedWrap decoration may not be applied to TypeVoid"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoUnsignedWrapOnLabelBad) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %entry NoUnsignedWrap", "");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("NoUnsignedWrap decoration may not be applied to Label"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoUnsignedWrapRequiresExtensionBad) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
|
||||
"%val = OpIAdd %int %zero %zero", "");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_NE(SPV_SUCCESS, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("requires one of these extensions: "
|
||||
"SPV_KHR_no_integer_wrap_decoration"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoUnsignedWrapIAddGood) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
|
||||
"%val = OpIAdd %int %zero %zero");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoUnsignedWrapISubGood) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
|
||||
"%val = OpISub %int %zero %zero");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoUnsignedWrapIMulGood) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
|
||||
"%val = OpIMul %int %zero %zero");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoUnsignedWrapShiftLeftLogicalGood) {
|
||||
std::string spirv =
|
||||
MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
|
||||
"%val = OpShiftLeftLogical %int %zero %zero");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoUnsignedWrapSNegateGood) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
|
||||
"%val = OpSNegate %int %zero");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoUnsignedWrapSRemBad) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
|
||||
"%val = OpSRem %int %zero %zero");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("NoUnsignedWrap decoration may not be applied to SRem"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoUnsignedWrapFAddBad) {
|
||||
std::string spirv = MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
|
||||
"%val = OpFAdd %float %float0 %float0");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr("NoUnsignedWrap decoration may not be applied to FAdd"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoUnsignedWrapExtInstOpenCLGood) {
|
||||
std::string spirv =
|
||||
MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
|
||||
"%val = OpExtInst %int %opencl s_abs %zero");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, NoUnsignedWrapExtInstGLSLGood) {
|
||||
std::string spirv =
|
||||
MakeIntegerShader("OpDecorate %val NoUnsignedWrap",
|
||||
"%val = OpExtInst %int %glsl SAbs %zero");
|
||||
|
||||
CompileSuccessfully(spirv);
|
||||
EXPECT_EQ(SPV_SUCCESS, ValidateInstructions());
|
||||
EXPECT_THAT(getDiagnosticString(), Eq(""));
|
||||
}
|
||||
|
||||
// TODO(dneto): For NoUnsignedWrap and NoUnsignedWrap, permit
|
||||
// "OpExtInst for instruction numbers specified in the extended
|
||||
// instruction-set specifications as accepting this decoration."
|
||||
|
||||
TEST_F(ValidateDecorations, PSBAliasedRestrictPointerSuccess) {
|
||||
const std::string body = R"(
|
||||
OpCapability PhysicalStorageBufferAddressesEXT
|
||||
@ -4952,10 +5228,9 @@ OpFunctionEnd
|
||||
|
||||
CompileSuccessfully(body.c_str());
|
||||
ASSERT_EQ(SPV_ERROR_INVALID_ID, ValidateInstructions());
|
||||
EXPECT_THAT(
|
||||
getDiagnosticString(),
|
||||
HasSubstr(
|
||||
"expected Aliased or Restrict for PhysicalStorageBufferEXT pointer"));
|
||||
EXPECT_THAT(getDiagnosticString(),
|
||||
HasSubstr("expected Aliased or Restrict for "
|
||||
"PhysicalStorageBufferEXT pointer"));
|
||||
}
|
||||
|
||||
TEST_F(ValidateDecorations, PSBAliasedRestrictFunctionParamBoth) {
|
||||
|
Loading…
Reference in New Issue
Block a user