1fd4e5da5Sopenharmony_ci// Copyright (c) 2020 Vasyl Teliman 2fd4e5da5Sopenharmony_ci// 3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License"); 4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License. 5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at 6fd4e5da5Sopenharmony_ci// 7fd4e5da5Sopenharmony_ci// http://www.apache.org/licenses/LICENSE-2.0 8fd4e5da5Sopenharmony_ci// 9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software 10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS, 11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and 13fd4e5da5Sopenharmony_ci// limitations under the License. 14fd4e5da5Sopenharmony_ci 15fd4e5da5Sopenharmony_ci#include "gtest/gtest.h" 16fd4e5da5Sopenharmony_ci#include "source/fuzz/fuzzer_pass_add_opphi_synonyms.h" 17fd4e5da5Sopenharmony_ci#include "source/fuzz/fuzzer_util.h" 18fd4e5da5Sopenharmony_ci#include "source/fuzz/pseudo_random_generator.h" 19fd4e5da5Sopenharmony_ci#include "test/fuzz/fuzz_test_util.h" 20fd4e5da5Sopenharmony_ci 21fd4e5da5Sopenharmony_cinamespace spvtools { 22fd4e5da5Sopenharmony_cinamespace fuzz { 23fd4e5da5Sopenharmony_cinamespace { 24fd4e5da5Sopenharmony_ci 25fd4e5da5Sopenharmony_ciclass FuzzerPassMock : public FuzzerPass { 26fd4e5da5Sopenharmony_ci public: 27fd4e5da5Sopenharmony_ci FuzzerPassMock(opt::IRContext* ir_context, 28fd4e5da5Sopenharmony_ci TransformationContext* transformation_context, 29fd4e5da5Sopenharmony_ci FuzzerContext* fuzzer_context, 30fd4e5da5Sopenharmony_ci protobufs::TransformationSequence* transformations) 31fd4e5da5Sopenharmony_ci : FuzzerPass(ir_context, transformation_context, fuzzer_context, 32fd4e5da5Sopenharmony_ci transformations, false) {} 33fd4e5da5Sopenharmony_ci 34fd4e5da5Sopenharmony_ci ~FuzzerPassMock() override = default; 35fd4e5da5Sopenharmony_ci 36fd4e5da5Sopenharmony_ci const std::unordered_set<uint32_t>& GetReachedInstructions() const { 37fd4e5da5Sopenharmony_ci return reached_ids_; 38fd4e5da5Sopenharmony_ci } 39fd4e5da5Sopenharmony_ci 40fd4e5da5Sopenharmony_ci void Apply() override { 41fd4e5da5Sopenharmony_ci ForEachInstructionWithInstructionDescriptor( 42fd4e5da5Sopenharmony_ci [this](opt::Function* /*unused*/, opt::BasicBlock* /*unused*/, 43fd4e5da5Sopenharmony_ci opt::BasicBlock::iterator inst_it, 44fd4e5da5Sopenharmony_ci const protobufs::InstructionDescriptor& /*unused*/) { 45fd4e5da5Sopenharmony_ci if (inst_it->result_id()) { 46fd4e5da5Sopenharmony_ci reached_ids_.insert(inst_it->result_id()); 47fd4e5da5Sopenharmony_ci } 48fd4e5da5Sopenharmony_ci }); 49fd4e5da5Sopenharmony_ci } 50fd4e5da5Sopenharmony_ci 51fd4e5da5Sopenharmony_ci private: 52fd4e5da5Sopenharmony_ci std::unordered_set<uint32_t> reached_ids_; 53fd4e5da5Sopenharmony_ci}; 54fd4e5da5Sopenharmony_ci 55fd4e5da5Sopenharmony_ciTEST(FuzzerPassTest, ForEachInstructionWithInstructionDescriptor) { 56fd4e5da5Sopenharmony_ci std::string shader = R"( 57fd4e5da5Sopenharmony_ci OpCapability Shader 58fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 59fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 60fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %4 "main" 61fd4e5da5Sopenharmony_ci OpExecutionMode %4 OriginUpperLeft 62fd4e5da5Sopenharmony_ci OpSource ESSL 310 63fd4e5da5Sopenharmony_ci %2 = OpTypeVoid 64fd4e5da5Sopenharmony_ci %3 = OpTypeFunction %2 65fd4e5da5Sopenharmony_ci %6 = OpTypeFloat 32 66fd4e5da5Sopenharmony_ci %4 = OpFunction %2 None %3 67fd4e5da5Sopenharmony_ci %5 = OpLabel 68fd4e5da5Sopenharmony_ci %7 = OpUndef %6 69fd4e5da5Sopenharmony_ci OpReturn 70fd4e5da5Sopenharmony_ci %8 = OpLabel 71fd4e5da5Sopenharmony_ci %9 = OpUndef %6 72fd4e5da5Sopenharmony_ci OpReturn 73fd4e5da5Sopenharmony_ci OpFunctionEnd 74fd4e5da5Sopenharmony_ci )"; 75fd4e5da5Sopenharmony_ci 76fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_3; 77fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 78fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 79fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 80fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 81fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 82fd4e5da5Sopenharmony_ci TransformationContext transformation_context( 83fd4e5da5Sopenharmony_ci MakeUnique<FactManager>(context.get()), validator_options); 84fd4e5da5Sopenharmony_ci // Check that %5 is reachable and %8 is unreachable as expected. 85fd4e5da5Sopenharmony_ci const auto* dominator_analysis = 86fd4e5da5Sopenharmony_ci context->GetDominatorAnalysis(context->GetFunction(4)); 87fd4e5da5Sopenharmony_ci ASSERT_TRUE(dominator_analysis->IsReachable(5)); 88fd4e5da5Sopenharmony_ci ASSERT_FALSE(dominator_analysis->IsReachable(8)); 89fd4e5da5Sopenharmony_ci 90fd4e5da5Sopenharmony_ci FuzzerContext fuzzer_context(MakeUnique<PseudoRandomGenerator>(0), 100, 91fd4e5da5Sopenharmony_ci false); 92fd4e5da5Sopenharmony_ci protobufs::TransformationSequence transformations; 93fd4e5da5Sopenharmony_ci FuzzerPassMock fuzzer_pass_mock(context.get(), &transformation_context, 94fd4e5da5Sopenharmony_ci &fuzzer_context, &transformations); 95fd4e5da5Sopenharmony_ci fuzzer_pass_mock.Apply(); 96fd4e5da5Sopenharmony_ci 97fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzer_pass_mock.GetReachedInstructions().count(7)); 98fd4e5da5Sopenharmony_ci ASSERT_FALSE(fuzzer_pass_mock.GetReachedInstructions().count(9)); 99fd4e5da5Sopenharmony_ci} 100fd4e5da5Sopenharmony_ci 101fd4e5da5Sopenharmony_ci} // namespace 102fd4e5da5Sopenharmony_ci} // namespace fuzz 103fd4e5da5Sopenharmony_ci} // namespace spvtools 104