1fd4e5da5Sopenharmony_ci// Copyright (c) 2020 Google LLC 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 "source/fuzz/call_graph.h" 16fd4e5da5Sopenharmony_ci 17fd4e5da5Sopenharmony_ci#include "gtest/gtest.h" 18fd4e5da5Sopenharmony_ci#include "source/fuzz/fuzzer_util.h" 19fd4e5da5Sopenharmony_ci#include "test/fuzz/fuzz_test_util.h" 20fd4e5da5Sopenharmony_ci 21fd4e5da5Sopenharmony_cinamespace spvtools { 22fd4e5da5Sopenharmony_cinamespace fuzz { 23fd4e5da5Sopenharmony_cinamespace { 24fd4e5da5Sopenharmony_ci 25fd4e5da5Sopenharmony_ci// The SPIR-V came from this GLSL, slightly modified 26fd4e5da5Sopenharmony_ci// (main is %2, A is %35, B is %48, C is %50, D is %61): 27fd4e5da5Sopenharmony_ci// 28fd4e5da5Sopenharmony_ci// #version 310 es 29fd4e5da5Sopenharmony_ci// 30fd4e5da5Sopenharmony_ci// int A (int x) { 31fd4e5da5Sopenharmony_ci// return x + 1; 32fd4e5da5Sopenharmony_ci// } 33fd4e5da5Sopenharmony_ci// 34fd4e5da5Sopenharmony_ci// void D() { 35fd4e5da5Sopenharmony_ci// } 36fd4e5da5Sopenharmony_ci// 37fd4e5da5Sopenharmony_ci// void C() { 38fd4e5da5Sopenharmony_ci// int x = 0; 39fd4e5da5Sopenharmony_ci// int y = 0; 40fd4e5da5Sopenharmony_ci// 41fd4e5da5Sopenharmony_ci// while (x < 10) { 42fd4e5da5Sopenharmony_ci// while (y < 10) { 43fd4e5da5Sopenharmony_ci// y = A(y); 44fd4e5da5Sopenharmony_ci// } 45fd4e5da5Sopenharmony_ci// x = A(x); 46fd4e5da5Sopenharmony_ci// } 47fd4e5da5Sopenharmony_ci// } 48fd4e5da5Sopenharmony_ci// 49fd4e5da5Sopenharmony_ci// void B () { 50fd4e5da5Sopenharmony_ci// int x = 0; 51fd4e5da5Sopenharmony_ci// int y = 0; 52fd4e5da5Sopenharmony_ci// 53fd4e5da5Sopenharmony_ci// while (x < 10) { 54fd4e5da5Sopenharmony_ci// D(); 55fd4e5da5Sopenharmony_ci// while (y < 10) { 56fd4e5da5Sopenharmony_ci// y = A(y); 57fd4e5da5Sopenharmony_ci// C(); 58fd4e5da5Sopenharmony_ci// } 59fd4e5da5Sopenharmony_ci// x++; 60fd4e5da5Sopenharmony_ci// } 61fd4e5da5Sopenharmony_ci// 62fd4e5da5Sopenharmony_ci// } 63fd4e5da5Sopenharmony_ci// 64fd4e5da5Sopenharmony_ci// void main() 65fd4e5da5Sopenharmony_ci// { 66fd4e5da5Sopenharmony_ci// int x = 0; 67fd4e5da5Sopenharmony_ci// int y = 0; 68fd4e5da5Sopenharmony_ci// int z = 0; 69fd4e5da5Sopenharmony_ci// 70fd4e5da5Sopenharmony_ci// while (x < 10) { 71fd4e5da5Sopenharmony_ci// while(y < 10) { 72fd4e5da5Sopenharmony_ci// y = A(x); 73fd4e5da5Sopenharmony_ci// while (z < 10) { 74fd4e5da5Sopenharmony_ci// z = A(z); 75fd4e5da5Sopenharmony_ci// } 76fd4e5da5Sopenharmony_ci// } 77fd4e5da5Sopenharmony_ci// x += 2; 78fd4e5da5Sopenharmony_ci// } 79fd4e5da5Sopenharmony_ci// 80fd4e5da5Sopenharmony_ci// B(); 81fd4e5da5Sopenharmony_ci// C(); 82fd4e5da5Sopenharmony_ci// } 83fd4e5da5Sopenharmony_cistd::string shader = R"( 84fd4e5da5Sopenharmony_ci OpCapability Shader 85fd4e5da5Sopenharmony_ci %1 = OpExtInstImport "GLSL.std.450" 86fd4e5da5Sopenharmony_ci OpMemoryModel Logical GLSL450 87fd4e5da5Sopenharmony_ci OpEntryPoint Fragment %2 "main" 88fd4e5da5Sopenharmony_ci OpExecutionMode %2 OriginUpperLeft 89fd4e5da5Sopenharmony_ci OpSource ESSL 310 90fd4e5da5Sopenharmony_ci %3 = OpTypeVoid 91fd4e5da5Sopenharmony_ci %4 = OpTypeFunction %3 92fd4e5da5Sopenharmony_ci %5 = OpTypeInt 32 1 93fd4e5da5Sopenharmony_ci %6 = OpTypePointer Function %5 94fd4e5da5Sopenharmony_ci %7 = OpTypeFunction %5 %6 95fd4e5da5Sopenharmony_ci %8 = OpConstant %5 1 96fd4e5da5Sopenharmony_ci %9 = OpConstant %5 0 97fd4e5da5Sopenharmony_ci %10 = OpConstant %5 10 98fd4e5da5Sopenharmony_ci %11 = OpTypeBool 99fd4e5da5Sopenharmony_ci %12 = OpConstant %5 2 100fd4e5da5Sopenharmony_ci %2 = OpFunction %3 None %4 101fd4e5da5Sopenharmony_ci %13 = OpLabel 102fd4e5da5Sopenharmony_ci %14 = OpVariable %6 Function 103fd4e5da5Sopenharmony_ci %15 = OpVariable %6 Function 104fd4e5da5Sopenharmony_ci %16 = OpVariable %6 Function 105fd4e5da5Sopenharmony_ci %17 = OpVariable %6 Function 106fd4e5da5Sopenharmony_ci %18 = OpVariable %6 Function 107fd4e5da5Sopenharmony_ci OpStore %14 %9 108fd4e5da5Sopenharmony_ci OpStore %15 %9 109fd4e5da5Sopenharmony_ci OpStore %16 %9 110fd4e5da5Sopenharmony_ci OpBranch %19 111fd4e5da5Sopenharmony_ci %19 = OpLabel 112fd4e5da5Sopenharmony_ci OpLoopMerge %20 %21 None 113fd4e5da5Sopenharmony_ci OpBranch %22 114fd4e5da5Sopenharmony_ci %22 = OpLabel 115fd4e5da5Sopenharmony_ci %23 = OpLoad %5 %14 116fd4e5da5Sopenharmony_ci %24 = OpSLessThan %11 %23 %10 117fd4e5da5Sopenharmony_ci OpBranchConditional %24 %25 %20 118fd4e5da5Sopenharmony_ci %25 = OpLabel 119fd4e5da5Sopenharmony_ci OpBranch %26 120fd4e5da5Sopenharmony_ci %26 = OpLabel 121fd4e5da5Sopenharmony_ci OpLoopMerge %27 %28 None 122fd4e5da5Sopenharmony_ci OpBranch %29 123fd4e5da5Sopenharmony_ci %29 = OpLabel 124fd4e5da5Sopenharmony_ci %30 = OpLoad %5 %15 125fd4e5da5Sopenharmony_ci %31 = OpSLessThan %11 %30 %10 126fd4e5da5Sopenharmony_ci OpBranchConditional %31 %32 %27 127fd4e5da5Sopenharmony_ci %32 = OpLabel 128fd4e5da5Sopenharmony_ci %33 = OpLoad %5 %14 129fd4e5da5Sopenharmony_ci OpStore %17 %33 130fd4e5da5Sopenharmony_ci %34 = OpFunctionCall %5 %35 %17 131fd4e5da5Sopenharmony_ci OpStore %15 %34 132fd4e5da5Sopenharmony_ci OpBranch %36 133fd4e5da5Sopenharmony_ci %36 = OpLabel 134fd4e5da5Sopenharmony_ci OpLoopMerge %37 %38 None 135fd4e5da5Sopenharmony_ci OpBranch %39 136fd4e5da5Sopenharmony_ci %39 = OpLabel 137fd4e5da5Sopenharmony_ci %40 = OpLoad %5 %16 138fd4e5da5Sopenharmony_ci %41 = OpSLessThan %11 %40 %10 139fd4e5da5Sopenharmony_ci OpBranchConditional %41 %42 %37 140fd4e5da5Sopenharmony_ci %42 = OpLabel 141fd4e5da5Sopenharmony_ci %43 = OpLoad %5 %16 142fd4e5da5Sopenharmony_ci OpStore %18 %43 143fd4e5da5Sopenharmony_ci %44 = OpFunctionCall %5 %35 %18 144fd4e5da5Sopenharmony_ci OpStore %16 %44 145fd4e5da5Sopenharmony_ci OpBranch %38 146fd4e5da5Sopenharmony_ci %38 = OpLabel 147fd4e5da5Sopenharmony_ci OpBranch %36 148fd4e5da5Sopenharmony_ci %37 = OpLabel 149fd4e5da5Sopenharmony_ci OpBranch %28 150fd4e5da5Sopenharmony_ci %28 = OpLabel 151fd4e5da5Sopenharmony_ci OpBranch %26 152fd4e5da5Sopenharmony_ci %27 = OpLabel 153fd4e5da5Sopenharmony_ci %45 = OpLoad %5 %14 154fd4e5da5Sopenharmony_ci %46 = OpIAdd %5 %45 %12 155fd4e5da5Sopenharmony_ci OpStore %14 %46 156fd4e5da5Sopenharmony_ci OpBranch %21 157fd4e5da5Sopenharmony_ci %21 = OpLabel 158fd4e5da5Sopenharmony_ci OpBranch %19 159fd4e5da5Sopenharmony_ci %20 = OpLabel 160fd4e5da5Sopenharmony_ci %47 = OpFunctionCall %3 %48 161fd4e5da5Sopenharmony_ci %49 = OpFunctionCall %3 %50 162fd4e5da5Sopenharmony_ci OpReturn 163fd4e5da5Sopenharmony_ci OpFunctionEnd 164fd4e5da5Sopenharmony_ci %35 = OpFunction %5 None %7 165fd4e5da5Sopenharmony_ci %51 = OpFunctionParameter %6 166fd4e5da5Sopenharmony_ci %52 = OpLabel 167fd4e5da5Sopenharmony_ci %53 = OpLoad %5 %51 168fd4e5da5Sopenharmony_ci %54 = OpIAdd %5 %53 %8 169fd4e5da5Sopenharmony_ci OpReturnValue %54 170fd4e5da5Sopenharmony_ci OpFunctionEnd 171fd4e5da5Sopenharmony_ci %48 = OpFunction %3 None %4 172fd4e5da5Sopenharmony_ci %55 = OpLabel 173fd4e5da5Sopenharmony_ci %56 = OpVariable %6 Function 174fd4e5da5Sopenharmony_ci %57 = OpVariable %6 Function 175fd4e5da5Sopenharmony_ci %58 = OpVariable %6 Function 176fd4e5da5Sopenharmony_ci OpStore %56 %9 177fd4e5da5Sopenharmony_ci OpStore %57 %9 178fd4e5da5Sopenharmony_ci OpBranch %59 179fd4e5da5Sopenharmony_ci %59 = OpLabel 180fd4e5da5Sopenharmony_ci %60 = OpFunctionCall %3 %61 181fd4e5da5Sopenharmony_ci OpLoopMerge %62 %63 None 182fd4e5da5Sopenharmony_ci OpBranch %64 183fd4e5da5Sopenharmony_ci %64 = OpLabel 184fd4e5da5Sopenharmony_ci OpLoopMerge %65 %66 None 185fd4e5da5Sopenharmony_ci OpBranch %67 186fd4e5da5Sopenharmony_ci %67 = OpLabel 187fd4e5da5Sopenharmony_ci %68 = OpLoad %5 %57 188fd4e5da5Sopenharmony_ci %69 = OpSLessThan %11 %68 %10 189fd4e5da5Sopenharmony_ci OpBranchConditional %69 %70 %65 190fd4e5da5Sopenharmony_ci %70 = OpLabel 191fd4e5da5Sopenharmony_ci %71 = OpLoad %5 %57 192fd4e5da5Sopenharmony_ci OpStore %58 %71 193fd4e5da5Sopenharmony_ci %72 = OpFunctionCall %5 %35 %58 194fd4e5da5Sopenharmony_ci OpStore %57 %72 195fd4e5da5Sopenharmony_ci %73 = OpFunctionCall %3 %50 196fd4e5da5Sopenharmony_ci OpBranch %66 197fd4e5da5Sopenharmony_ci %66 = OpLabel 198fd4e5da5Sopenharmony_ci OpBranch %64 199fd4e5da5Sopenharmony_ci %65 = OpLabel 200fd4e5da5Sopenharmony_ci %74 = OpLoad %5 %56 201fd4e5da5Sopenharmony_ci %75 = OpIAdd %5 %74 %8 202fd4e5da5Sopenharmony_ci OpStore %56 %75 203fd4e5da5Sopenharmony_ci OpBranch %63 204fd4e5da5Sopenharmony_ci %63 = OpLabel 205fd4e5da5Sopenharmony_ci %76 = OpLoad %5 %56 206fd4e5da5Sopenharmony_ci %77 = OpSLessThan %11 %76 %10 207fd4e5da5Sopenharmony_ci OpBranchConditional %77 %59 %62 208fd4e5da5Sopenharmony_ci %62 = OpLabel 209fd4e5da5Sopenharmony_ci OpReturn 210fd4e5da5Sopenharmony_ci OpFunctionEnd 211fd4e5da5Sopenharmony_ci %50 = OpFunction %3 None %4 212fd4e5da5Sopenharmony_ci %78 = OpLabel 213fd4e5da5Sopenharmony_ci %79 = OpVariable %6 Function 214fd4e5da5Sopenharmony_ci %80 = OpVariable %6 Function 215fd4e5da5Sopenharmony_ci %81 = OpVariable %6 Function 216fd4e5da5Sopenharmony_ci %82 = OpVariable %6 Function 217fd4e5da5Sopenharmony_ci OpStore %79 %9 218fd4e5da5Sopenharmony_ci OpStore %80 %9 219fd4e5da5Sopenharmony_ci OpBranch %83 220fd4e5da5Sopenharmony_ci %83 = OpLabel 221fd4e5da5Sopenharmony_ci OpLoopMerge %84 %85 None 222fd4e5da5Sopenharmony_ci OpBranch %86 223fd4e5da5Sopenharmony_ci %86 = OpLabel 224fd4e5da5Sopenharmony_ci %87 = OpLoad %5 %79 225fd4e5da5Sopenharmony_ci %88 = OpSLessThan %11 %87 %10 226fd4e5da5Sopenharmony_ci OpBranchConditional %88 %89 %84 227fd4e5da5Sopenharmony_ci %89 = OpLabel 228fd4e5da5Sopenharmony_ci OpBranch %90 229fd4e5da5Sopenharmony_ci %90 = OpLabel 230fd4e5da5Sopenharmony_ci OpLoopMerge %91 %92 None 231fd4e5da5Sopenharmony_ci OpBranch %93 232fd4e5da5Sopenharmony_ci %93 = OpLabel 233fd4e5da5Sopenharmony_ci %94 = OpLoad %5 %80 234fd4e5da5Sopenharmony_ci %95 = OpSLessThan %11 %94 %10 235fd4e5da5Sopenharmony_ci OpBranchConditional %95 %96 %91 236fd4e5da5Sopenharmony_ci %96 = OpLabel 237fd4e5da5Sopenharmony_ci %97 = OpLoad %5 %80 238fd4e5da5Sopenharmony_ci OpStore %81 %97 239fd4e5da5Sopenharmony_ci %98 = OpFunctionCall %5 %35 %81 240fd4e5da5Sopenharmony_ci OpStore %80 %98 241fd4e5da5Sopenharmony_ci OpBranch %92 242fd4e5da5Sopenharmony_ci %92 = OpLabel 243fd4e5da5Sopenharmony_ci OpBranch %90 244fd4e5da5Sopenharmony_ci %91 = OpLabel 245fd4e5da5Sopenharmony_ci %99 = OpLoad %5 %79 246fd4e5da5Sopenharmony_ci OpStore %82 %99 247fd4e5da5Sopenharmony_ci %100 = OpFunctionCall %5 %35 %82 248fd4e5da5Sopenharmony_ci OpStore %79 %100 249fd4e5da5Sopenharmony_ci OpBranch %85 250fd4e5da5Sopenharmony_ci %85 = OpLabel 251fd4e5da5Sopenharmony_ci OpBranch %83 252fd4e5da5Sopenharmony_ci %84 = OpLabel 253fd4e5da5Sopenharmony_ci OpReturn 254fd4e5da5Sopenharmony_ci OpFunctionEnd 255fd4e5da5Sopenharmony_ci %61 = OpFunction %3 None %4 256fd4e5da5Sopenharmony_ci %101 = OpLabel 257fd4e5da5Sopenharmony_ci OpReturn 258fd4e5da5Sopenharmony_ci OpFunctionEnd 259fd4e5da5Sopenharmony_ci)"; 260fd4e5da5Sopenharmony_ci 261fd4e5da5Sopenharmony_ci// We have that: 262fd4e5da5Sopenharmony_ci// main calls: 263fd4e5da5Sopenharmony_ci// - A (maximum loop nesting depth of function call: 3) 264fd4e5da5Sopenharmony_ci// - B (0) 265fd4e5da5Sopenharmony_ci// - C (0) 266fd4e5da5Sopenharmony_ci// A calls nothing. 267fd4e5da5Sopenharmony_ci// B calls: 268fd4e5da5Sopenharmony_ci// - A (2) 269fd4e5da5Sopenharmony_ci// - C (2) 270fd4e5da5Sopenharmony_ci// - D (1) 271fd4e5da5Sopenharmony_ci// C calls: 272fd4e5da5Sopenharmony_ci// - A (2) 273fd4e5da5Sopenharmony_ci// D calls nothing. 274fd4e5da5Sopenharmony_ci 275fd4e5da5Sopenharmony_ciTEST(CallGraphTest, FunctionInDegree) { 276fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 277fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 278fd4e5da5Sopenharmony_ci 279fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 280fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 281fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 282fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 283fd4e5da5Sopenharmony_ci 284fd4e5da5Sopenharmony_ci const auto graph = CallGraph(context.get()); 285fd4e5da5Sopenharmony_ci 286fd4e5da5Sopenharmony_ci const auto& function_in_degree = graph.GetFunctionInDegree(); 287fd4e5da5Sopenharmony_ci // Check the in-degrees of, in order: main, A, B, C, D. 288fd4e5da5Sopenharmony_ci ASSERT_EQ(function_in_degree.at(2), 0); 289fd4e5da5Sopenharmony_ci ASSERT_EQ(function_in_degree.at(35), 3); 290fd4e5da5Sopenharmony_ci ASSERT_EQ(function_in_degree.at(48), 1); 291fd4e5da5Sopenharmony_ci ASSERT_EQ(function_in_degree.at(50), 2); 292fd4e5da5Sopenharmony_ci ASSERT_EQ(function_in_degree.at(61), 1); 293fd4e5da5Sopenharmony_ci} 294fd4e5da5Sopenharmony_ci 295fd4e5da5Sopenharmony_ciTEST(CallGraphTest, DirectCallees) { 296fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 297fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 298fd4e5da5Sopenharmony_ci 299fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 300fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 301fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 302fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 303fd4e5da5Sopenharmony_ci 304fd4e5da5Sopenharmony_ci const auto graph = CallGraph(context.get()); 305fd4e5da5Sopenharmony_ci 306fd4e5da5Sopenharmony_ci // Check the callee sets of, in order: main, A, B, C, D. 307fd4e5da5Sopenharmony_ci ASSERT_EQ(graph.GetDirectCallees(2), std::set<uint32_t>({35, 48, 50})); 308fd4e5da5Sopenharmony_ci ASSERT_EQ(graph.GetDirectCallees(35), std::set<uint32_t>({})); 309fd4e5da5Sopenharmony_ci ASSERT_EQ(graph.GetDirectCallees(48), std::set<uint32_t>({35, 50, 61})); 310fd4e5da5Sopenharmony_ci ASSERT_EQ(graph.GetDirectCallees(50), std::set<uint32_t>({35})); 311fd4e5da5Sopenharmony_ci ASSERT_EQ(graph.GetDirectCallees(61), std::set<uint32_t>({})); 312fd4e5da5Sopenharmony_ci} 313fd4e5da5Sopenharmony_ci 314fd4e5da5Sopenharmony_ciTEST(CallGraphTest, IndirectCallees) { 315fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 316fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 317fd4e5da5Sopenharmony_ci 318fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 319fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 320fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 321fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 322fd4e5da5Sopenharmony_ci 323fd4e5da5Sopenharmony_ci const auto graph = CallGraph(context.get()); 324fd4e5da5Sopenharmony_ci 325fd4e5da5Sopenharmony_ci // Check the callee sets of, in order: main, A, B, C, D. 326fd4e5da5Sopenharmony_ci ASSERT_EQ(graph.GetIndirectCallees(2), std::set<uint32_t>({35, 48, 50, 61})); 327fd4e5da5Sopenharmony_ci ASSERT_EQ(graph.GetDirectCallees(35), std::set<uint32_t>({})); 328fd4e5da5Sopenharmony_ci ASSERT_EQ(graph.GetDirectCallees(48), std::set<uint32_t>({35, 50, 61})); 329fd4e5da5Sopenharmony_ci ASSERT_EQ(graph.GetDirectCallees(50), std::set<uint32_t>({35})); 330fd4e5da5Sopenharmony_ci ASSERT_EQ(graph.GetDirectCallees(61), std::set<uint32_t>({})); 331fd4e5da5Sopenharmony_ci} 332fd4e5da5Sopenharmony_ci 333fd4e5da5Sopenharmony_ciTEST(CallGraphTest, TopologicalOrder) { 334fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 335fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 336fd4e5da5Sopenharmony_ci 337fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 338fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 339fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 340fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 341fd4e5da5Sopenharmony_ci 342fd4e5da5Sopenharmony_ci const auto graph = CallGraph(context.get()); 343fd4e5da5Sopenharmony_ci 344fd4e5da5Sopenharmony_ci const auto& topological_ordering = graph.GetFunctionsInTopologicalOrder(); 345fd4e5da5Sopenharmony_ci 346fd4e5da5Sopenharmony_ci // The possible topological orderings are: 347fd4e5da5Sopenharmony_ci // - main, B, D, C, A 348fd4e5da5Sopenharmony_ci // - main, B, C, D, A 349fd4e5da5Sopenharmony_ci // - main, B, C, A, D 350fd4e5da5Sopenharmony_ci ASSERT_TRUE( 351fd4e5da5Sopenharmony_ci topological_ordering == std::vector<uint32_t>({2, 48, 61, 50, 35}) || 352fd4e5da5Sopenharmony_ci topological_ordering == std::vector<uint32_t>({2, 48, 50, 61, 35}) || 353fd4e5da5Sopenharmony_ci topological_ordering == std::vector<uint32_t>({2, 48, 50, 35, 61})); 354fd4e5da5Sopenharmony_ci} 355fd4e5da5Sopenharmony_ci 356fd4e5da5Sopenharmony_ciTEST(CallGraphTest, LoopNestingDepth) { 357fd4e5da5Sopenharmony_ci const auto env = SPV_ENV_UNIVERSAL_1_5; 358fd4e5da5Sopenharmony_ci const auto consumer = nullptr; 359fd4e5da5Sopenharmony_ci 360fd4e5da5Sopenharmony_ci const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption); 361fd4e5da5Sopenharmony_ci spvtools::ValidatorOptions validator_options; 362fd4e5da5Sopenharmony_ci ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options, 363fd4e5da5Sopenharmony_ci kConsoleMessageConsumer)); 364fd4e5da5Sopenharmony_ci 365fd4e5da5Sopenharmony_ci const auto graph = CallGraph(context.get()); 366fd4e5da5Sopenharmony_ci 367fd4e5da5Sopenharmony_ci // Check the maximum loop nesting depth for function calls to, in order: 368fd4e5da5Sopenharmony_ci // main, A, B, C, D 369fd4e5da5Sopenharmony_ci ASSERT_EQ(graph.GetMaxCallNestingDepth(2), 0); 370fd4e5da5Sopenharmony_ci ASSERT_EQ(graph.GetMaxCallNestingDepth(35), 4); 371fd4e5da5Sopenharmony_ci ASSERT_EQ(graph.GetMaxCallNestingDepth(48), 0); 372fd4e5da5Sopenharmony_ci ASSERT_EQ(graph.GetMaxCallNestingDepth(50), 2); 373fd4e5da5Sopenharmony_ci ASSERT_EQ(graph.GetMaxCallNestingDepth(61), 1); 374fd4e5da5Sopenharmony_ci} 375fd4e5da5Sopenharmony_ci 376fd4e5da5Sopenharmony_ci} // namespace 377fd4e5da5Sopenharmony_ci} // namespace fuzz 378fd4e5da5Sopenharmony_ci} // namespace spvtools 379