mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-29 03:01:08 +00:00
c853a91144
Fixes #4294 by achieving full coverage of this transformation.
1124 lines
43 KiB
C++
1124 lines
43 KiB
C++
// Copyright (c) 2020 Vasyl Teliman
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "source/fuzz/transformation_add_parameter.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
#include "source/fuzz/fuzzer_util.h"
|
|
#include "test/fuzz/fuzz_test_util.h"
|
|
|
|
namespace spvtools {
|
|
namespace fuzz {
|
|
namespace {
|
|
|
|
TEST(TransformationAddParameterTest, NonPointerBasicTest) {
|
|
std::string shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
OpName %4 "main"
|
|
%2 = OpTypeVoid
|
|
%7 = OpTypeBool
|
|
%11 = OpTypeInt 32 1
|
|
%16 = OpTypeFloat 32
|
|
%51 = OpConstant %11 2
|
|
%52 = OpTypeArray %16 %51
|
|
%53 = OpConstant %16 7
|
|
%54 = OpConstantComposite %52 %53 %53
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeFunction %7 %7
|
|
%8 = OpConstant %11 23
|
|
%12 = OpConstantTrue %7
|
|
%15 = OpTypeFunction %2 %16
|
|
%24 = OpTypeFunction %2 %16 %7
|
|
%31 = OpTypeStruct %7 %11
|
|
%32 = OpConstant %16 23
|
|
%33 = OpConstantComposite %31 %12 %8
|
|
%41 = OpTypeStruct %11 %16
|
|
%42 = OpConstantComposite %41 %8 %32
|
|
%43 = OpTypeFunction %2 %41
|
|
%44 = OpTypeFunction %2 %41 %7
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%13 = OpFunctionCall %7 %9 %12
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
; adjust type of the function in-place
|
|
%9 = OpFunction %7 None %6
|
|
%14 = OpFunctionParameter %7
|
|
%10 = OpLabel
|
|
OpReturnValue %12
|
|
OpFunctionEnd
|
|
|
|
; reuse an existing function type
|
|
%17 = OpFunction %2 None %15
|
|
%18 = OpFunctionParameter %16
|
|
%19 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%20 = OpFunction %2 None %15
|
|
%21 = OpFunctionParameter %16
|
|
%22 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%25 = OpFunction %2 None %24
|
|
%26 = OpFunctionParameter %16
|
|
%27 = OpFunctionParameter %7
|
|
%28 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
; create a new function type
|
|
%29 = OpFunction %2 None %3
|
|
%30 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
; don't adjust the type of the function if it creates a duplicate
|
|
%34 = OpFunction %2 None %43
|
|
%35 = OpFunctionParameter %41
|
|
%36 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%37 = OpFunction %2 None %44
|
|
%38 = OpFunctionParameter %41
|
|
%39 = OpFunctionParameter %7
|
|
%40 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
|
|
spvtools::ValidatorOptions validator_options;
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(context.get()), validator_options);
|
|
// Can't modify entry point function.
|
|
ASSERT_FALSE(TransformationAddParameter(4, 60, 7, {{}}, 61)
|
|
.IsApplicable(context.get(), transformation_context));
|
|
|
|
// There is no function with result id 60.
|
|
ASSERT_FALSE(TransformationAddParameter(60, 60, 11, {{}}, 61)
|
|
.IsApplicable(context.get(), transformation_context));
|
|
|
|
// Parameter id is not fresh.
|
|
ASSERT_FALSE(TransformationAddParameter(9, 14, 11, {{{13, 8}}}, 61)
|
|
.IsApplicable(context.get(), transformation_context));
|
|
|
|
// Function type id is not fresh.
|
|
ASSERT_FALSE(TransformationAddParameter(9, 60, 11, {{{13, 8}}}, 14)
|
|
.IsApplicable(context.get(), transformation_context));
|
|
|
|
// Function type id and parameter type id are equal.
|
|
ASSERT_FALSE(TransformationAddParameter(9, 60, 11, {{{13, 8}}}, 60)
|
|
.IsApplicable(context.get(), transformation_context));
|
|
|
|
// Parameter's initializer doesn't exist.
|
|
ASSERT_FALSE(TransformationAddParameter(9, 60, 11, {{{13, 60}}}, 61)
|
|
.IsApplicable(context.get(), transformation_context));
|
|
|
|
// Correct transformations.
|
|
{
|
|
TransformationAddParameter correct(9, 60, 11, {{{13, 8}}}, 61);
|
|
ASSERT_TRUE(correct.IsApplicable(context.get(), transformation_context));
|
|
ApplyAndCheckFreshIds(correct, context.get(), &transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
context.get(), validator_options, kConsoleMessageConsumer));
|
|
ASSERT_TRUE(transformation_context.GetFactManager()->IdIsIrrelevant(60));
|
|
}
|
|
{
|
|
TransformationAddParameter correct(9, 68, 52, {{{13, 54}}}, 69);
|
|
ASSERT_TRUE(correct.IsApplicable(context.get(), transformation_context));
|
|
ApplyAndCheckFreshIds(correct, context.get(), &transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
context.get(), validator_options, kConsoleMessageConsumer));
|
|
ASSERT_TRUE(transformation_context.GetFactManager()->IdIsIrrelevant(68));
|
|
}
|
|
{
|
|
TransformationAddParameter correct(17, 62, 7, {{}}, 63);
|
|
ASSERT_TRUE(correct.IsApplicable(context.get(), transformation_context));
|
|
ApplyAndCheckFreshIds(correct, context.get(), &transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
context.get(), validator_options, kConsoleMessageConsumer));
|
|
ASSERT_TRUE(transformation_context.GetFactManager()->IdIsIrrelevant(62));
|
|
}
|
|
{
|
|
TransformationAddParameter correct(29, 64, 31, {{}}, 65);
|
|
ASSERT_TRUE(correct.IsApplicable(context.get(), transformation_context));
|
|
ApplyAndCheckFreshIds(correct, context.get(), &transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
context.get(), validator_options, kConsoleMessageConsumer));
|
|
ASSERT_TRUE(transformation_context.GetFactManager()->IdIsIrrelevant(64));
|
|
}
|
|
{
|
|
TransformationAddParameter correct(34, 66, 7, {{}}, 67);
|
|
ASSERT_TRUE(correct.IsApplicable(context.get(), transformation_context));
|
|
ApplyAndCheckFreshIds(correct, context.get(), &transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
|
|
context.get(), validator_options, kConsoleMessageConsumer));
|
|
ASSERT_TRUE(transformation_context.GetFactManager()->IdIsIrrelevant(66));
|
|
}
|
|
|
|
std::string expected_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
OpName %4 "main"
|
|
%2 = OpTypeVoid
|
|
%7 = OpTypeBool
|
|
%11 = OpTypeInt 32 1
|
|
%16 = OpTypeFloat 32
|
|
%51 = OpConstant %11 2
|
|
%52 = OpTypeArray %16 %51
|
|
%53 = OpConstant %16 7
|
|
%54 = OpConstantComposite %52 %53 %53
|
|
%3 = OpTypeFunction %2
|
|
%8 = OpConstant %11 23
|
|
%12 = OpConstantTrue %7
|
|
%15 = OpTypeFunction %2 %16
|
|
%24 = OpTypeFunction %2 %16 %7
|
|
%31 = OpTypeStruct %7 %11
|
|
%32 = OpConstant %16 23
|
|
%33 = OpConstantComposite %31 %12 %8
|
|
%41 = OpTypeStruct %11 %16
|
|
%42 = OpConstantComposite %41 %8 %32
|
|
%44 = OpTypeFunction %2 %41 %7
|
|
%6 = OpTypeFunction %7 %7 %11 %52
|
|
%65 = OpTypeFunction %2 %31
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%13 = OpFunctionCall %7 %9 %12 %8 %54
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
; adjust type of the function in-place
|
|
%9 = OpFunction %7 None %6
|
|
%14 = OpFunctionParameter %7
|
|
%60 = OpFunctionParameter %11
|
|
%68 = OpFunctionParameter %52
|
|
%10 = OpLabel
|
|
OpReturnValue %12
|
|
OpFunctionEnd
|
|
|
|
; reuse an existing function type
|
|
%17 = OpFunction %2 None %24
|
|
%18 = OpFunctionParameter %16
|
|
%62 = OpFunctionParameter %7
|
|
%19 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%20 = OpFunction %2 None %15
|
|
%21 = OpFunctionParameter %16
|
|
%22 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%25 = OpFunction %2 None %24
|
|
%26 = OpFunctionParameter %16
|
|
%27 = OpFunctionParameter %7
|
|
%28 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
; create a new function type
|
|
%29 = OpFunction %2 None %65
|
|
%64 = OpFunctionParameter %31
|
|
%30 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
|
|
; don't adjust the type of the function if it creates a duplicate
|
|
%34 = OpFunction %2 None %44
|
|
%35 = OpFunctionParameter %41
|
|
%66 = OpFunctionParameter %7
|
|
%36 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%37 = OpFunction %2 None %44
|
|
%38 = OpFunctionParameter %41
|
|
%39 = OpFunctionParameter %7
|
|
%40 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
|
|
}
|
|
|
|
TEST(TransformationAddParameterTest, NonPointerNotApplicableTest) {
|
|
// This types handles case of adding a new parameter of a non-pointer type
|
|
// where the transformation is not applicable.
|
|
std::string shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
OpName %4 "main"
|
|
OpName %6 "fun1("
|
|
OpName %12 "fun2(i1;"
|
|
OpName %11 "a"
|
|
OpName %14 "fun3("
|
|
OpName %24 "f1"
|
|
OpName %27 "f2"
|
|
OpName %30 "i1"
|
|
OpName %31 "i2"
|
|
OpName %32 "param"
|
|
OpName %35 "i3"
|
|
OpName %36 "param"
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%8 = OpTypeInt 32 1
|
|
%9 = OpTypePointer Function %8
|
|
%10 = OpTypeFunction %8 %9
|
|
%18 = OpConstant %8 2
|
|
%22 = OpTypeFloat 32
|
|
%23 = OpTypePointer Private %22
|
|
%24 = OpVariable %23 Private
|
|
%25 = OpConstant %22 1
|
|
%26 = OpTypePointer Function %22
|
|
%28 = OpConstant %22 2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%27 = OpVariable %26 Function
|
|
%30 = OpVariable %9 Function
|
|
%31 = OpVariable %9 Function
|
|
%32 = OpVariable %9 Function
|
|
%35 = OpVariable %9 Function
|
|
%36 = OpVariable %9 Function
|
|
OpStore %24 %25
|
|
OpStore %27 %28
|
|
%29 = OpFunctionCall %2 %6
|
|
OpStore %30 %18
|
|
%33 = OpLoad %8 %30
|
|
OpStore %32 %33
|
|
%34 = OpFunctionCall %8 %12 %32
|
|
OpStore %31 %34
|
|
%37 = OpLoad %8 %31
|
|
OpStore %36 %37
|
|
%38 = OpFunctionCall %8 %12 %36
|
|
OpStore %35 %38
|
|
; %39 = OpFunctionCall %2 %14
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%6 = OpFunction %2 None %3
|
|
%7 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%12 = OpFunction %8 None %10
|
|
%11 = OpFunctionParameter %9
|
|
%13 = OpLabel
|
|
%17 = OpLoad %8 %11
|
|
%19 = OpIAdd %8 %17 %18
|
|
OpReturnValue %19
|
|
OpFunctionEnd
|
|
%14 = OpFunction %2 None %3
|
|
%15 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
|
|
spvtools::ValidatorOptions validator_options;
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(context.get()), validator_options);
|
|
// Bad: Id 19 is not available in the caller that has id 34.
|
|
TransformationAddParameter transformation_bad_1(12, 50, 8,
|
|
{{{34, 19}, {38, 19}}}, 51);
|
|
|
|
ASSERT_FALSE(
|
|
transformation_bad_1.IsApplicable(context.get(), transformation_context));
|
|
|
|
// Bad: Id 8 does not have a type.
|
|
TransformationAddParameter transformation_bad_2(12, 50, 8,
|
|
{{{34, 8}, {38, 8}}}, 51);
|
|
|
|
ASSERT_FALSE(
|
|
transformation_bad_2.IsApplicable(context.get(), transformation_context));
|
|
|
|
// Bad: Types of id 25 and id 18 are different.
|
|
TransformationAddParameter transformation_bad_3(12, 50, 22,
|
|
{{{34, 25}, {38, 18}}}, 51);
|
|
ASSERT_FALSE(
|
|
transformation_bad_3.IsApplicable(context.get(), transformation_context));
|
|
|
|
// Function with id 14 does not have any callers.
|
|
// Bad: Id 18 is not a vaild type.
|
|
TransformationAddParameter transformation_bad_4(14, 50, 18, {{}}, 51);
|
|
ASSERT_FALSE(
|
|
transformation_bad_4.IsApplicable(context.get(), transformation_context));
|
|
|
|
// Function with id 14 does not have any callers.
|
|
// Bad: Id 3 refers to OpTypeVoid, which is not supported.
|
|
TransformationAddParameter transformation_bad_6(14, 50, 3, {{}}, 51);
|
|
ASSERT_FALSE(
|
|
transformation_bad_6.IsApplicable(context.get(), transformation_context));
|
|
}
|
|
|
|
TEST(TransformationAddParameterTest, PointerFunctionTest) {
|
|
// This types handles case of adding a new parameter of a pointer type with
|
|
// storage class Function.
|
|
std::string shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
OpName %4 "main"
|
|
OpName %6 "fun1("
|
|
OpName %12 "fun2(i1;"
|
|
OpName %11 "a"
|
|
OpName %14 "fun3("
|
|
OpName %17 "s"
|
|
OpName %24 "s"
|
|
OpName %28 "f1"
|
|
OpName %31 "f2"
|
|
OpName %34 "i1"
|
|
OpName %35 "i2"
|
|
OpName %36 "param"
|
|
OpName %39 "i3"
|
|
OpName %40 "param"
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%8 = OpTypeInt 32 1
|
|
%9 = OpTypePointer Function %8
|
|
%10 = OpTypeFunction %8 %9
|
|
%20 = OpConstant %8 2
|
|
%25 = OpConstant %8 0
|
|
%26 = OpTypeFloat 32
|
|
%27 = OpTypePointer Private %26
|
|
%28 = OpVariable %27 Private
|
|
%60 = OpTypePointer Output %26
|
|
%61 = OpVariable %60 Output
|
|
%29 = OpConstant %26 1
|
|
%30 = OpTypePointer Function %26
|
|
%32 = OpConstant %26 2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%31 = OpVariable %30 Function
|
|
%34 = OpVariable %9 Function
|
|
%35 = OpVariable %9 Function
|
|
%36 = OpVariable %9 Function
|
|
%39 = OpVariable %9 Function
|
|
%40 = OpVariable %9 Function
|
|
OpStore %28 %29
|
|
OpStore %31 %32
|
|
%33 = OpFunctionCall %2 %6
|
|
OpStore %34 %20
|
|
%37 = OpLoad %8 %34
|
|
OpStore %36 %37
|
|
%38 = OpFunctionCall %8 %12 %36
|
|
OpStore %35 %38
|
|
%41 = OpLoad %8 %35
|
|
OpStore %40 %41
|
|
%42 = OpFunctionCall %8 %12 %40
|
|
OpStore %39 %42
|
|
%43 = OpFunctionCall %2 %14
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%6 = OpFunction %2 None %3
|
|
%7 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%12 = OpFunction %8 None %10
|
|
%11 = OpFunctionParameter %9
|
|
%13 = OpLabel
|
|
%17 = OpVariable %9 Function
|
|
%18 = OpLoad %8 %11
|
|
OpStore %17 %18
|
|
%19 = OpLoad %8 %17
|
|
%21 = OpIAdd %8 %19 %20
|
|
OpReturnValue %21
|
|
OpFunctionEnd
|
|
%14 = OpFunction %2 None %3
|
|
%15 = OpLabel
|
|
%24 = OpVariable %9 Function
|
|
OpStore %24 %25
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
|
|
spvtools::ValidatorOptions validator_options;
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(context.get()), validator_options);
|
|
// Bad: Pointer of id 61 has storage class Output, which is not supported.
|
|
TransformationAddParameter transformation_bad_1(12, 50, 60,
|
|
{{{38, 61}, {42, 61}}}, 51);
|
|
|
|
ASSERT_FALSE(
|
|
transformation_bad_1.IsApplicable(context.get(), transformation_context));
|
|
|
|
// Good: Local variable of id 31 is defined in the caller (main).
|
|
TransformationAddParameter transformation_good_1(12, 50, 30,
|
|
{{{38, 31}, {42, 31}}}, 51);
|
|
ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
|
|
transformation_context));
|
|
ApplyAndCheckFreshIds(transformation_good_1, context.get(),
|
|
&transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
|
|
// Good: Local variable of id 34 is defined in the caller (main).
|
|
TransformationAddParameter transformation_good_2(14, 52, 9, {{{43, 34}}}, 53);
|
|
ASSERT_TRUE(transformation_good_2.IsApplicable(context.get(),
|
|
transformation_context));
|
|
ApplyAndCheckFreshIds(transformation_good_2, context.get(),
|
|
&transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
|
|
// Good: Local variable of id 39 is defined in the caller (main).
|
|
TransformationAddParameter transformation_good_3(6, 54, 9, {{{33, 39}}}, 55);
|
|
ASSERT_TRUE(transformation_good_3.IsApplicable(context.get(),
|
|
transformation_context));
|
|
ApplyAndCheckFreshIds(transformation_good_3, context.get(),
|
|
&transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
|
|
// Good: This adds another pointer parameter to the function of id 6.
|
|
TransformationAddParameter transformation_good_4(6, 56, 30, {{{33, 31}}}, 57);
|
|
ASSERT_TRUE(transformation_good_4.IsApplicable(context.get(),
|
|
transformation_context));
|
|
ApplyAndCheckFreshIds(transformation_good_4, context.get(),
|
|
&transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
|
|
std::string expected_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
OpName %4 "main"
|
|
OpName %6 "fun1("
|
|
OpName %12 "fun2(i1;"
|
|
OpName %11 "a"
|
|
OpName %14 "fun3("
|
|
OpName %17 "s"
|
|
OpName %24 "s"
|
|
OpName %28 "f1"
|
|
OpName %31 "f2"
|
|
OpName %34 "i1"
|
|
OpName %35 "i2"
|
|
OpName %36 "param"
|
|
OpName %39 "i3"
|
|
OpName %40 "param"
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%8 = OpTypeInt 32 1
|
|
%9 = OpTypePointer Function %8
|
|
%20 = OpConstant %8 2
|
|
%25 = OpConstant %8 0
|
|
%26 = OpTypeFloat 32
|
|
%27 = OpTypePointer Private %26
|
|
%28 = OpVariable %27 Private
|
|
%60 = OpTypePointer Output %26
|
|
%61 = OpVariable %60 Output
|
|
%29 = OpConstant %26 1
|
|
%30 = OpTypePointer Function %26
|
|
%32 = OpConstant %26 2
|
|
%10 = OpTypeFunction %8 %9 %30
|
|
%53 = OpTypeFunction %2 %9
|
|
%57 = OpTypeFunction %2 %9 %30
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%31 = OpVariable %30 Function
|
|
%34 = OpVariable %9 Function
|
|
%35 = OpVariable %9 Function
|
|
%36 = OpVariable %9 Function
|
|
%39 = OpVariable %9 Function
|
|
%40 = OpVariable %9 Function
|
|
OpStore %28 %29
|
|
OpStore %31 %32
|
|
%33 = OpFunctionCall %2 %6 %39 %31
|
|
OpStore %34 %20
|
|
%37 = OpLoad %8 %34
|
|
OpStore %36 %37
|
|
%38 = OpFunctionCall %8 %12 %36 %31
|
|
OpStore %35 %38
|
|
%41 = OpLoad %8 %35
|
|
OpStore %40 %41
|
|
%42 = OpFunctionCall %8 %12 %40 %31
|
|
OpStore %39 %42
|
|
%43 = OpFunctionCall %2 %14 %34
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%6 = OpFunction %2 None %57
|
|
%54 = OpFunctionParameter %9
|
|
%56 = OpFunctionParameter %30
|
|
%7 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%12 = OpFunction %8 None %10
|
|
%11 = OpFunctionParameter %9
|
|
%50 = OpFunctionParameter %30
|
|
%13 = OpLabel
|
|
%17 = OpVariable %9 Function
|
|
%18 = OpLoad %8 %11
|
|
OpStore %17 %18
|
|
%19 = OpLoad %8 %17
|
|
%21 = OpIAdd %8 %19 %20
|
|
OpReturnValue %21
|
|
OpFunctionEnd
|
|
%14 = OpFunction %2 None %53
|
|
%52 = OpFunctionParameter %9
|
|
%15 = OpLabel
|
|
%24 = OpVariable %9 Function
|
|
OpStore %24 %25
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
|
|
}
|
|
|
|
TEST(TransformationAddParameterTest, PointerPrivateWorkgroupTest) {
|
|
// This types handles case of adding a new parameter of a pointer type with
|
|
// storage class Private or Workgroup.
|
|
std::string shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
OpName %4 "main"
|
|
OpName %6 "fun1("
|
|
OpName %12 "fun2(i1;"
|
|
OpName %11 "a"
|
|
OpName %14 "fun3("
|
|
OpName %17 "s"
|
|
OpName %24 "s"
|
|
OpName %28 "f1"
|
|
OpName %31 "f2"
|
|
OpName %34 "i1"
|
|
OpName %35 "i2"
|
|
OpName %36 "param"
|
|
OpName %39 "i3"
|
|
OpName %40 "param"
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%8 = OpTypeInt 32 1
|
|
%9 = OpTypePointer Function %8
|
|
%10 = OpTypeFunction %8 %9
|
|
%20 = OpConstant %8 2
|
|
%25 = OpConstant %8 0
|
|
%26 = OpTypeFloat 32
|
|
%27 = OpTypePointer Private %26
|
|
%28 = OpVariable %27 Private
|
|
%60 = OpTypePointer Workgroup %26
|
|
%61 = OpVariable %60 Workgroup
|
|
%29 = OpConstant %26 1
|
|
%30 = OpTypePointer Function %26
|
|
%32 = OpConstant %26 2
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%31 = OpVariable %30 Function
|
|
%34 = OpVariable %9 Function
|
|
%35 = OpVariable %9 Function
|
|
%36 = OpVariable %9 Function
|
|
%39 = OpVariable %9 Function
|
|
%40 = OpVariable %9 Function
|
|
OpStore %28 %29
|
|
OpStore %31 %32
|
|
%33 = OpFunctionCall %2 %6
|
|
OpStore %34 %20
|
|
%37 = OpLoad %8 %34
|
|
OpStore %36 %37
|
|
%38 = OpFunctionCall %8 %12 %36
|
|
OpStore %35 %38
|
|
%41 = OpLoad %8 %35
|
|
OpStore %40 %41
|
|
%42 = OpFunctionCall %8 %12 %40
|
|
OpStore %39 %42
|
|
%43 = OpFunctionCall %2 %14
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%6 = OpFunction %2 None %3
|
|
%7 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%12 = OpFunction %8 None %10
|
|
%11 = OpFunctionParameter %9
|
|
%13 = OpLabel
|
|
%17 = OpVariable %9 Function
|
|
%18 = OpLoad %8 %11
|
|
OpStore %17 %18
|
|
%19 = OpLoad %8 %17
|
|
%21 = OpIAdd %8 %19 %20
|
|
OpReturnValue %21
|
|
OpFunctionEnd
|
|
%14 = OpFunction %2 None %3
|
|
%15 = OpLabel
|
|
%24 = OpVariable %9 Function
|
|
OpStore %24 %25
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
|
|
spvtools::ValidatorOptions validator_options;
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(context.get()), validator_options);
|
|
// Good: Global variable of id 28 (storage class Private) is defined in the
|
|
// caller (main).
|
|
TransformationAddParameter transformation_good_1(12, 70, 27,
|
|
{{{38, 28}, {42, 28}}}, 71);
|
|
ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
|
|
transformation_context));
|
|
ApplyAndCheckFreshIds(transformation_good_1, context.get(),
|
|
&transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
|
|
// Good: Global variable of id 61 is (storage class Workgroup) is defined in
|
|
// the caller (main).
|
|
TransformationAddParameter transformation_good_2(12, 72, 27,
|
|
{{{38, 28}, {42, 28}}}, 73);
|
|
ASSERT_TRUE(transformation_good_2.IsApplicable(context.get(),
|
|
transformation_context));
|
|
ApplyAndCheckFreshIds(transformation_good_2, context.get(),
|
|
&transformation_context);
|
|
|
|
// Good: Global variable of id 28 (storage class Private) is defined in the
|
|
// caller (main).
|
|
TransformationAddParameter transformation_good_3(6, 74, 27, {{{33, 28}}}, 75);
|
|
ASSERT_TRUE(transformation_good_3.IsApplicable(context.get(),
|
|
transformation_context));
|
|
ApplyAndCheckFreshIds(transformation_good_3, context.get(),
|
|
&transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
|
|
// Good: Global variable of id 61 is (storage class Workgroup) is defined in
|
|
// the caller (main).
|
|
TransformationAddParameter transformation_good_4(6, 76, 60, {{{33, 61}}}, 77);
|
|
ASSERT_TRUE(transformation_good_4.IsApplicable(context.get(),
|
|
transformation_context));
|
|
ApplyAndCheckFreshIds(transformation_good_4, context.get(),
|
|
&transformation_context);
|
|
|
|
// Good: Global variable of id 28 (storage class Private) is defined in the
|
|
// caller (main).
|
|
TransformationAddParameter transformation_good_5(14, 78, 27, {{{43, 28}}},
|
|
79);
|
|
ASSERT_TRUE(transformation_good_5.IsApplicable(context.get(),
|
|
transformation_context));
|
|
ApplyAndCheckFreshIds(transformation_good_5, context.get(),
|
|
&transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
|
|
// Good: Global variable of id 61 is (storage class Workgroup) is defined in
|
|
// the caller (main).
|
|
TransformationAddParameter transformation_good_6(14, 80, 60, {{{43, 61}}},
|
|
81);
|
|
ASSERT_TRUE(transformation_good_6.IsApplicable(context.get(),
|
|
transformation_context));
|
|
ApplyAndCheckFreshIds(transformation_good_6, context.get(),
|
|
&transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
|
|
std::string expected_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
OpName %4 "main"
|
|
OpName %6 "fun1("
|
|
OpName %12 "fun2(i1;"
|
|
OpName %11 "a"
|
|
OpName %14 "fun3("
|
|
OpName %17 "s"
|
|
OpName %24 "s"
|
|
OpName %28 "f1"
|
|
OpName %31 "f2"
|
|
OpName %34 "i1"
|
|
OpName %35 "i2"
|
|
OpName %36 "param"
|
|
OpName %39 "i3"
|
|
OpName %40 "param"
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%8 = OpTypeInt 32 1
|
|
%9 = OpTypePointer Function %8
|
|
%20 = OpConstant %8 2
|
|
%25 = OpConstant %8 0
|
|
%26 = OpTypeFloat 32
|
|
%27 = OpTypePointer Private %26
|
|
%28 = OpVariable %27 Private
|
|
%60 = OpTypePointer Workgroup %26
|
|
%61 = OpVariable %60 Workgroup
|
|
%29 = OpConstant %26 1
|
|
%30 = OpTypePointer Function %26
|
|
%32 = OpConstant %26 2
|
|
%10 = OpTypeFunction %8 %9 %27 %27
|
|
%75 = OpTypeFunction %2 %27 %60
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%31 = OpVariable %30 Function
|
|
%34 = OpVariable %9 Function
|
|
%35 = OpVariable %9 Function
|
|
%36 = OpVariable %9 Function
|
|
%39 = OpVariable %9 Function
|
|
%40 = OpVariable %9 Function
|
|
OpStore %28 %29
|
|
OpStore %31 %32
|
|
%33 = OpFunctionCall %2 %6 %28 %61
|
|
OpStore %34 %20
|
|
%37 = OpLoad %8 %34
|
|
OpStore %36 %37
|
|
%38 = OpFunctionCall %8 %12 %36 %28 %28
|
|
OpStore %35 %38
|
|
%41 = OpLoad %8 %35
|
|
OpStore %40 %41
|
|
%42 = OpFunctionCall %8 %12 %40 %28 %28
|
|
OpStore %39 %42
|
|
%43 = OpFunctionCall %2 %14 %28 %61
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%6 = OpFunction %2 None %75
|
|
%74 = OpFunctionParameter %27
|
|
%76 = OpFunctionParameter %60
|
|
%7 = OpLabel
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%12 = OpFunction %8 None %10
|
|
%11 = OpFunctionParameter %9
|
|
%70 = OpFunctionParameter %27
|
|
%72 = OpFunctionParameter %27
|
|
%13 = OpLabel
|
|
%17 = OpVariable %9 Function
|
|
%18 = OpLoad %8 %11
|
|
OpStore %17 %18
|
|
%19 = OpLoad %8 %17
|
|
%21 = OpIAdd %8 %19 %20
|
|
OpReturnValue %21
|
|
OpFunctionEnd
|
|
%14 = OpFunction %2 None %75
|
|
%78 = OpFunctionParameter %27
|
|
%80 = OpFunctionParameter %60
|
|
%15 = OpLabel
|
|
%24 = OpVariable %9 Function
|
|
OpStore %24 %25
|
|
OpReturn
|
|
OpFunctionEnd
|
|
)";
|
|
ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
|
|
}
|
|
|
|
TEST(TransformationAddParameterTest, PointerMoreEntriesInMapTest) {
|
|
// This types handles case where call_parameter_id has an entry for at least
|
|
// every caller (there are more entries than it is necessary).
|
|
std::string shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
OpName %4 "main"
|
|
OpName %10 "fun(i1;"
|
|
OpName %9 "a"
|
|
OpName %12 "s"
|
|
OpName %19 "i1"
|
|
OpName %21 "i2"
|
|
OpName %22 "i3"
|
|
OpName %24 "i4"
|
|
OpName %25 "param"
|
|
OpName %28 "i5"
|
|
OpName %29 "param"
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeInt 32 1
|
|
%7 = OpTypePointer Function %6
|
|
%8 = OpTypeFunction %6 %7
|
|
%15 = OpConstant %6 2
|
|
%20 = OpConstant %6 1
|
|
%23 = OpConstant %6 3
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%19 = OpVariable %7 Function
|
|
%21 = OpVariable %7 Function
|
|
%22 = OpVariable %7 Function
|
|
%24 = OpVariable %7 Function
|
|
%25 = OpVariable %7 Function
|
|
%28 = OpVariable %7 Function
|
|
%29 = OpVariable %7 Function
|
|
OpStore %19 %20
|
|
OpStore %21 %15
|
|
OpStore %22 %23
|
|
%26 = OpLoad %6 %19
|
|
OpStore %25 %26
|
|
%27 = OpFunctionCall %6 %10 %25
|
|
OpStore %24 %27
|
|
%30 = OpLoad %6 %21
|
|
OpStore %29 %30
|
|
%31 = OpFunctionCall %6 %10 %29
|
|
OpStore %28 %31
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%10 = OpFunction %6 None %8
|
|
%9 = OpFunctionParameter %7
|
|
%11 = OpLabel
|
|
%12 = OpVariable %7 Function
|
|
%13 = OpLoad %6 %9
|
|
OpStore %12 %13
|
|
%14 = OpLoad %6 %12
|
|
%16 = OpIAdd %6 %14 %15
|
|
OpReturnValue %16
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
|
|
spvtools::ValidatorOptions validator_options;
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(context.get()), validator_options);
|
|
// Good: Local variable of id 21 is defined in every caller (id 27 and id 31).
|
|
TransformationAddParameter transformation_good_1(
|
|
10, 70, 7, {{{27, 21}, {31, 21}, {30, 21}}}, 71);
|
|
ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
|
|
transformation_context));
|
|
ApplyAndCheckFreshIds(transformation_good_1, context.get(),
|
|
&transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
|
|
// Good: Local variable of id 28 is defined in every caller (id 27 and id 31).
|
|
TransformationAddParameter transformation_good_2(
|
|
10, 72, 7, {{{27, 28}, {31, 28}, {14, 21}, {16, 14}}}, 73);
|
|
ASSERT_TRUE(transformation_good_2.IsApplicable(context.get(),
|
|
transformation_context));
|
|
ApplyAndCheckFreshIds(transformation_good_2, context.get(),
|
|
&transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
|
|
std::string expected_shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
OpName %4 "main"
|
|
OpName %10 "fun(i1;"
|
|
OpName %9 "a"
|
|
OpName %12 "s"
|
|
OpName %19 "i1"
|
|
OpName %21 "i2"
|
|
OpName %22 "i3"
|
|
OpName %24 "i4"
|
|
OpName %25 "param"
|
|
OpName %28 "i5"
|
|
OpName %29 "param"
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeInt 32 1
|
|
%7 = OpTypePointer Function %6
|
|
%15 = OpConstant %6 2
|
|
%20 = OpConstant %6 1
|
|
%23 = OpConstant %6 3
|
|
%8 = OpTypeFunction %6 %7 %7 %7
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%19 = OpVariable %7 Function
|
|
%21 = OpVariable %7 Function
|
|
%22 = OpVariable %7 Function
|
|
%24 = OpVariable %7 Function
|
|
%25 = OpVariable %7 Function
|
|
%28 = OpVariable %7 Function
|
|
%29 = OpVariable %7 Function
|
|
OpStore %19 %20
|
|
OpStore %21 %15
|
|
OpStore %22 %23
|
|
%26 = OpLoad %6 %19
|
|
OpStore %25 %26
|
|
%27 = OpFunctionCall %6 %10 %25 %21 %28
|
|
OpStore %24 %27
|
|
%30 = OpLoad %6 %21
|
|
OpStore %29 %30
|
|
%31 = OpFunctionCall %6 %10 %29 %21 %28
|
|
OpStore %28 %31
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%10 = OpFunction %6 None %8
|
|
%9 = OpFunctionParameter %7
|
|
%70 = OpFunctionParameter %7
|
|
%72 = OpFunctionParameter %7
|
|
%11 = OpLabel
|
|
%12 = OpVariable %7 Function
|
|
%13 = OpLoad %6 %9
|
|
OpStore %12 %13
|
|
%14 = OpLoad %6 %12
|
|
%16 = OpIAdd %6 %14 %15
|
|
OpReturnValue %16
|
|
OpFunctionEnd
|
|
)";
|
|
ASSERT_TRUE(IsEqual(env, expected_shader, context.get()));
|
|
}
|
|
|
|
TEST(TransformationAddParameterTest, PointeeValueIsIrrelevantTest) {
|
|
// This test checks if the transformation has correctly applied the
|
|
// PointeeValueIsIrrelevant fact for new pointer parameters.
|
|
std::string shader = R"(
|
|
OpCapability Shader
|
|
%1 = OpExtInstImport "GLSL.std.450"
|
|
OpMemoryModel Logical GLSL450
|
|
OpEntryPoint Fragment %4 "main"
|
|
OpExecutionMode %4 OriginUpperLeft
|
|
OpSource ESSL 310
|
|
OpName %4 "main"
|
|
OpName %10 "fun(i1;"
|
|
OpName %9 "a"
|
|
OpName %12 "s"
|
|
OpName %20 "b"
|
|
OpName %22 "i1"
|
|
OpName %24 "i2"
|
|
OpName %25 "i3"
|
|
OpName %26 "param"
|
|
OpName %29 "i4"
|
|
OpName %30 "param"
|
|
%2 = OpTypeVoid
|
|
%3 = OpTypeFunction %2
|
|
%6 = OpTypeInt 32 1
|
|
%7 = OpTypePointer Function %6
|
|
%50 = OpTypePointer Workgroup %6
|
|
%51 = OpVariable %50 Workgroup
|
|
%8 = OpTypeFunction %6 %7
|
|
%15 = OpConstant %6 2
|
|
%19 = OpTypePointer Private %6
|
|
%20 = OpVariable %19 Private
|
|
%21 = OpConstant %6 0
|
|
%23 = OpConstant %6 1
|
|
%4 = OpFunction %2 None %3
|
|
%5 = OpLabel
|
|
%22 = OpVariable %7 Function
|
|
%24 = OpVariable %7 Function
|
|
%25 = OpVariable %7 Function
|
|
%26 = OpVariable %7 Function
|
|
%29 = OpVariable %7 Function
|
|
%30 = OpVariable %7 Function
|
|
OpStore %20 %21
|
|
OpStore %22 %23
|
|
OpStore %24 %15
|
|
%27 = OpLoad %6 %22
|
|
OpStore %26 %27
|
|
%28 = OpFunctionCall %6 %10 %26
|
|
OpStore %25 %28
|
|
%31 = OpLoad %6 %24
|
|
OpStore %30 %31
|
|
%32 = OpFunctionCall %6 %10 %30
|
|
OpStore %29 %32
|
|
OpReturn
|
|
OpFunctionEnd
|
|
%10 = OpFunction %6 None %8
|
|
%9 = OpFunctionParameter %7
|
|
%11 = OpLabel
|
|
%12 = OpVariable %7 Function
|
|
%13 = OpLoad %6 %9
|
|
OpStore %12 %13
|
|
%14 = OpLoad %6 %12
|
|
%16 = OpIAdd %6 %14 %15
|
|
OpReturnValue %16
|
|
OpFunctionEnd
|
|
)";
|
|
|
|
const auto env = SPV_ENV_UNIVERSAL_1_3;
|
|
const auto consumer = nullptr;
|
|
const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
|
|
spvtools::ValidatorOptions validator_options;
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
TransformationContext transformation_context(
|
|
MakeUnique<FactManager>(context.get()), validator_options);
|
|
TransformationAddParameter transformation_good_1(10, 70, 7,
|
|
{{{28, 22}, {32, 22}}}, 71);
|
|
ASSERT_TRUE(transformation_good_1.IsApplicable(context.get(),
|
|
transformation_context));
|
|
ApplyAndCheckFreshIds(transformation_good_1, context.get(),
|
|
&transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
|
|
// Check if the fact PointeeValueIsIrrelevant is set for the new parameter
|
|
// (storage class Function).
|
|
ASSERT_TRUE(
|
|
transformation_context.GetFactManager()->PointeeValueIsIrrelevant(70));
|
|
|
|
TransformationAddParameter transformation_good_2(10, 72, 19,
|
|
{{{28, 20}, {32, 20}}}, 73);
|
|
ASSERT_TRUE(transformation_good_2.IsApplicable(context.get(),
|
|
transformation_context));
|
|
ApplyAndCheckFreshIds(transformation_good_2, context.get(),
|
|
&transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
|
|
// Check if the fact PointeeValueIsIrrelevant is set for the new parameter
|
|
// (storage class Private).
|
|
ASSERT_TRUE(
|
|
transformation_context.GetFactManager()->PointeeValueIsIrrelevant(72));
|
|
|
|
TransformationAddParameter transformation_good_3(10, 74, 50,
|
|
{{{28, 51}, {32, 51}}}, 75);
|
|
ASSERT_TRUE(transformation_good_3.IsApplicable(context.get(),
|
|
transformation_context));
|
|
ApplyAndCheckFreshIds(transformation_good_3, context.get(),
|
|
&transformation_context);
|
|
ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
|
|
kConsoleMessageConsumer));
|
|
|
|
// Check if the fact PointeeValueIsIrrelevant is set for the new parameter
|
|
// (storage class Workgroup).
|
|
ASSERT_TRUE(
|
|
transformation_context.GetFactManager()->PointeeValueIsIrrelevant(74));
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace fuzz
|
|
} // namespace spvtools
|