// Copyright (c) 2021 Shiyu Liu // // 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_swap_two_functions.h" #include "gtest/gtest.h" #include "source/fuzz/fuzzer_util.h" #include "test/fuzz/fuzz_test_util.h" namespace spvtools { namespace fuzz { namespace { TEST(TransformationSwapTwoFunctionsTest, SimpleTest) { // float multiplyBy2(in float value) { // return value*2.0; // } // float multiplyBy4(in float value) { // return multiplyBy2(value)*2.0; // } // float multiplyBy8(in float value) { // return multiplyBy2(value)*multiplyBy4(value); // } // layout(location=0) in float value; // void main() { //4 // multiplyBy2(3.7); //10 // multiplyBy4(3.9); //13 // multiplyBy8(5.0); //16 // } std::string shader = R"( OpCapability Shader %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 OpEntryPoint Fragment %4 "main" %48 OpExecutionMode %4 OriginUpperLeft OpSource ESSL 310 OpName %4 "main" OpName %10 "multiplyBy2(f1;" OpName %9 "value" OpName %13 "multiplyBy4(f1;" OpName %12 "value" OpName %16 "multiplyBy8(f1;" OpName %15 "value" OpName %23 "param" OpName %29 "param" OpName %32 "param" OpName %39 "param" OpName %42 "param" OpName %45 "param" OpName %48 "value" OpDecorate %48 Location 0 %2 = OpTypeVoid %3 = OpTypeFunction %2 %6 = OpTypeFloat 32 %7 = OpTypePointer Function %6 %8 = OpTypeFunction %6 %7 %19 = OpConstant %6 2 %38 = OpConstant %6 3.70000005 %41 = OpConstant %6 3.9000001 %44 = OpConstant %6 5 %47 = OpTypePointer Input %6 %48 = OpVariable %47 Input %4 = OpFunction %2 None %3 %5 = OpLabel %39 = OpVariable %7 Function %42 = OpVariable %7 Function %45 = OpVariable %7 Function OpStore %39 %38 %40 = OpFunctionCall %6 %10 %39 OpStore %42 %41 %43 = OpFunctionCall %6 %13 %42 OpStore %45 %44 %46 = OpFunctionCall %6 %16 %45 OpReturn OpFunctionEnd %10 = OpFunction %6 None %8 %9 = OpFunctionParameter %7 %11 = OpLabel %18 = OpLoad %6 %9 %20 = OpFMul %6 %18 %19 OpReturnValue %20 OpFunctionEnd %13 = OpFunction %6 None %8 %12 = OpFunctionParameter %7 %14 = OpLabel %23 = OpVariable %7 Function %24 = OpLoad %6 %12 OpStore %23 %24 %25 = OpFunctionCall %6 %10 %23 %26 = OpFMul %6 %25 %19 OpReturnValue %26 OpFunctionEnd %16 = OpFunction %6 None %8 %15 = OpFunctionParameter %7 %17 = OpLabel %29 = OpVariable %7 Function %32 = OpVariable %7 Function %30 = OpLoad %6 %15 OpStore %29 %30 %31 = OpFunctionCall %6 %10 %29 %33 = OpLoad %6 %15 OpStore %32 %33 %34 = OpFunctionCall %6 %13 %32 %35 = OpFMul %6 %31 %34 OpReturnValue %35 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; // Check context validity. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, kConsoleMessageConsumer)); TransformationContext transformation_context( MakeUnique(context.get()), validator_options); #ifndef NDEBUG // Function should not swap with itself. ASSERT_DEATH(TransformationSwapTwoFunctions(4, 4).IsApplicable( context.get(), transformation_context), "The two function ids cannot be the same."); #endif // Function with id 29 does not exist. ASSERT_FALSE(TransformationSwapTwoFunctions(10, 29).IsApplicable( context.get(), transformation_context)); // Function with id 30 does not exist. ASSERT_FALSE(TransformationSwapTwoFunctions(30, 13).IsApplicable( context.get(), transformation_context)); // Both functions with id 5 and 6 do not exist. ASSERT_FALSE(TransformationSwapTwoFunctions(5, 6).IsApplicable( context.get(), transformation_context)); // Function with result_id 10 and 13 should swap successfully. auto swap_test5 = TransformationSwapTwoFunctions(10, 13); ASSERT_TRUE(swap_test5.IsApplicable(context.get(), transformation_context)); // Get the definitions of functions 10 and 13, as recorded by the def-use // manager. auto def_use_manager = context->get_def_use_mgr(); auto function_10_inst = def_use_manager->GetDef(10); auto function_13_inst = def_use_manager->GetDef(13); ApplyAndCheckFreshIds(swap_test5, context.get(), &transformation_context); // Check that def-use information for functions 10 and 13 has been preserved // by the transformation. ASSERT_EQ(function_10_inst, def_use_manager->GetDef(10)); ASSERT_EQ(function_13_inst, def_use_manager->GetDef(13)); ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, kConsoleMessageConsumer)); std::string after_transformation = R"( OpCapability Shader %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 OpEntryPoint Fragment %4 "main" %48 OpExecutionMode %4 OriginUpperLeft OpSource ESSL 310 OpName %4 "main" OpName %10 "multiplyBy2(f1;" OpName %9 "value" OpName %13 "multiplyBy4(f1;" OpName %12 "value" OpName %16 "multiplyBy8(f1;" OpName %15 "value" OpName %23 "param" OpName %29 "param" OpName %32 "param" OpName %39 "param" OpName %42 "param" OpName %45 "param" OpName %48 "value" OpDecorate %48 Location 0 %2 = OpTypeVoid %3 = OpTypeFunction %2 %6 = OpTypeFloat 32 %7 = OpTypePointer Function %6 %8 = OpTypeFunction %6 %7 %19 = OpConstant %6 2 %38 = OpConstant %6 3.70000005 %41 = OpConstant %6 3.9000001 %44 = OpConstant %6 5 %47 = OpTypePointer Input %6 %48 = OpVariable %47 Input %4 = OpFunction %2 None %3 %5 = OpLabel %39 = OpVariable %7 Function %42 = OpVariable %7 Function %45 = OpVariable %7 Function OpStore %39 %38 %40 = OpFunctionCall %6 %10 %39 OpStore %42 %41 %43 = OpFunctionCall %6 %13 %42 OpStore %45 %44 %46 = OpFunctionCall %6 %16 %45 OpReturn OpFunctionEnd %13 = OpFunction %6 None %8 %12 = OpFunctionParameter %7 %14 = OpLabel %23 = OpVariable %7 Function %24 = OpLoad %6 %12 OpStore %23 %24 %25 = OpFunctionCall %6 %10 %23 %26 = OpFMul %6 %25 %19 OpReturnValue %26 OpFunctionEnd %10 = OpFunction %6 None %8 %9 = OpFunctionParameter %7 %11 = OpLabel %18 = OpLoad %6 %9 %20 = OpFMul %6 %18 %19 OpReturnValue %20 OpFunctionEnd %16 = OpFunction %6 None %8 %15 = OpFunctionParameter %7 %17 = OpLabel %29 = OpVariable %7 Function %32 = OpVariable %7 Function %30 = OpLoad %6 %15 OpStore %29 %30 %31 = OpFunctionCall %6 %10 %29 %33 = OpLoad %6 %15 OpStore %32 %33 %34 = OpFunctionCall %6 %13 %32 %35 = OpFMul %6 %31 %34 OpReturnValue %35 OpFunctionEnd )"; ASSERT_TRUE(IsEqual(env, after_transformation, context.get())); } } // namespace } // namespace fuzz } // namespace spvtools