transformation_copy_object_test.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593
  1. // Copyright (c) 2019 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <algorithm>
  15. #include <set>
  16. #include <unordered_set>
  17. #include "source/fuzz/data_descriptor.h"
  18. #include "source/fuzz/instruction_descriptor.h"
  19. #include "source/fuzz/transformation_copy_object.h"
  20. #include "test/fuzz/fuzz_test_util.h"
  21. namespace spvtools {
  22. namespace fuzz {
  23. namespace {
  24. TEST(TransformationCopyObjectTest, CopyBooleanConstants) {
  25. std::string shader = R"(
  26. OpCapability Shader
  27. %1 = OpExtInstImport "GLSL.std.450"
  28. OpMemoryModel Logical GLSL450
  29. OpEntryPoint Fragment %4 "main"
  30. OpExecutionMode %4 OriginUpperLeft
  31. OpSource ESSL 310
  32. OpName %4 "main"
  33. %2 = OpTypeVoid
  34. %6 = OpTypeBool
  35. %7 = OpConstantTrue %6
  36. %8 = OpConstantFalse %6
  37. %3 = OpTypeFunction %2
  38. %4 = OpFunction %2 None %3
  39. %5 = OpLabel
  40. OpReturn
  41. OpFunctionEnd
  42. )";
  43. const auto env = SPV_ENV_UNIVERSAL_1_3;
  44. const auto consumer = nullptr;
  45. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  46. ASSERT_TRUE(IsValid(env, context.get()));
  47. FactManager fact_manager;
  48. ASSERT_EQ(0,
  49. fact_manager.GetIdsForWhichSynonymsAreKnown(context.get()).size());
  50. {
  51. TransformationCopyObject copy_true(
  52. 7, MakeInstructionDescriptor(5, SpvOpReturn, 0), 100);
  53. ASSERT_TRUE(copy_true.IsApplicable(context.get(), fact_manager));
  54. copy_true.Apply(context.get(), &fact_manager);
  55. std::vector<uint32_t> ids_for_which_synonyms_are_known =
  56. fact_manager.GetIdsForWhichSynonymsAreKnown(context.get());
  57. ASSERT_EQ(2, ids_for_which_synonyms_are_known.size());
  58. ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(),
  59. ids_for_which_synonyms_are_known.end(),
  60. 7) != ids_for_which_synonyms_are_known.end());
  61. ASSERT_EQ(2, fact_manager.GetSynonymsForId(7, context.get()).size());
  62. protobufs::DataDescriptor descriptor_100 = MakeDataDescriptor(100, {});
  63. ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(7, {}),
  64. descriptor_100, context.get()));
  65. }
  66. {
  67. TransformationCopyObject copy_false(
  68. 8, MakeInstructionDescriptor(100, SpvOpReturn, 0), 101);
  69. ASSERT_TRUE(copy_false.IsApplicable(context.get(), fact_manager));
  70. copy_false.Apply(context.get(), &fact_manager);
  71. std::vector<uint32_t> ids_for_which_synonyms_are_known =
  72. fact_manager.GetIdsForWhichSynonymsAreKnown(context.get());
  73. ASSERT_EQ(4, ids_for_which_synonyms_are_known.size());
  74. ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(),
  75. ids_for_which_synonyms_are_known.end(),
  76. 8) != ids_for_which_synonyms_are_known.end());
  77. ASSERT_EQ(2, fact_manager.GetSynonymsForId(8, context.get()).size());
  78. protobufs::DataDescriptor descriptor_101 = MakeDataDescriptor(101, {});
  79. ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(8, {}),
  80. descriptor_101, context.get()));
  81. }
  82. {
  83. TransformationCopyObject copy_false_again(
  84. 101, MakeInstructionDescriptor(5, SpvOpReturn, 0), 102);
  85. ASSERT_TRUE(copy_false_again.IsApplicable(context.get(), fact_manager));
  86. copy_false_again.Apply(context.get(), &fact_manager);
  87. std::vector<uint32_t> ids_for_which_synonyms_are_known =
  88. fact_manager.GetIdsForWhichSynonymsAreKnown(context.get());
  89. ASSERT_EQ(5, ids_for_which_synonyms_are_known.size());
  90. ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(),
  91. ids_for_which_synonyms_are_known.end(),
  92. 101) != ids_for_which_synonyms_are_known.end());
  93. ASSERT_EQ(3, fact_manager.GetSynonymsForId(101, context.get()).size());
  94. protobufs::DataDescriptor descriptor_102 = MakeDataDescriptor(102, {});
  95. ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(101, {}),
  96. descriptor_102, context.get()));
  97. }
  98. {
  99. TransformationCopyObject copy_true_again(
  100. 7, MakeInstructionDescriptor(102, SpvOpReturn, 0), 103);
  101. ASSERT_TRUE(copy_true_again.IsApplicable(context.get(), fact_manager));
  102. copy_true_again.Apply(context.get(), &fact_manager);
  103. std::vector<uint32_t> ids_for_which_synonyms_are_known =
  104. fact_manager.GetIdsForWhichSynonymsAreKnown(context.get());
  105. ASSERT_EQ(6, ids_for_which_synonyms_are_known.size());
  106. ASSERT_TRUE(std::find(ids_for_which_synonyms_are_known.begin(),
  107. ids_for_which_synonyms_are_known.end(),
  108. 7) != ids_for_which_synonyms_are_known.end());
  109. ASSERT_EQ(3, fact_manager.GetSynonymsForId(7, context.get()).size());
  110. protobufs::DataDescriptor descriptor_103 = MakeDataDescriptor(103, {});
  111. ASSERT_TRUE(fact_manager.IsSynonymous(MakeDataDescriptor(7, {}),
  112. descriptor_103, context.get()));
  113. }
  114. std::string after_transformation = R"(
  115. OpCapability Shader
  116. %1 = OpExtInstImport "GLSL.std.450"
  117. OpMemoryModel Logical GLSL450
  118. OpEntryPoint Fragment %4 "main"
  119. OpExecutionMode %4 OriginUpperLeft
  120. OpSource ESSL 310
  121. OpName %4 "main"
  122. %2 = OpTypeVoid
  123. %6 = OpTypeBool
  124. %7 = OpConstantTrue %6
  125. %8 = OpConstantFalse %6
  126. %3 = OpTypeFunction %2
  127. %4 = OpFunction %2 None %3
  128. %5 = OpLabel
  129. %100 = OpCopyObject %6 %7
  130. %101 = OpCopyObject %6 %8
  131. %102 = OpCopyObject %6 %101
  132. %103 = OpCopyObject %6 %7
  133. OpReturn
  134. OpFunctionEnd
  135. )";
  136. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  137. }
  138. TEST(TransformationCopyObjectTest, CheckIllegalCases) {
  139. // The following SPIR-V comes from this GLSL, pushed through spirv-opt
  140. // and then doctored a bit.
  141. //
  142. // #version 310 es
  143. //
  144. // precision highp float;
  145. //
  146. // struct S {
  147. // int a;
  148. // float b;
  149. // };
  150. //
  151. // layout(set = 0, binding = 2) uniform block {
  152. // S s;
  153. // lowp float f;
  154. // int ii;
  155. // } ubuf;
  156. //
  157. // layout(location = 0) out vec4 color;
  158. //
  159. // void main() {
  160. // float c = 0.0;
  161. // lowp float d = 0.0;
  162. // S localS = ubuf.s;
  163. // for (int i = 0; i < ubuf.s.a; i++) {
  164. // switch (ubuf.ii) {
  165. // case 0:
  166. // c += 0.1;
  167. // d += 0.2;
  168. // case 1:
  169. // c += 0.1;
  170. // if (c > d) {
  171. // d += 0.2;
  172. // } else {
  173. // d += c;
  174. // }
  175. // break;
  176. // default:
  177. // i += 1;
  178. // localS.b += d;
  179. // }
  180. // }
  181. // color = vec4(c, d, localS.b, 1.0);
  182. // }
  183. std::string shader = R"(
  184. OpCapability Shader
  185. %1 = OpExtInstImport "GLSL.std.450"
  186. OpMemoryModel Logical GLSL450
  187. OpEntryPoint Fragment %4 "main" %80
  188. OpExecutionMode %4 OriginUpperLeft
  189. OpSource ESSL 310
  190. OpName %4 "main"
  191. OpName %12 "S"
  192. OpMemberName %12 0 "a"
  193. OpMemberName %12 1 "b"
  194. OpName %15 "S"
  195. OpMemberName %15 0 "a"
  196. OpMemberName %15 1 "b"
  197. OpName %16 "block"
  198. OpMemberName %16 0 "s"
  199. OpMemberName %16 1 "f"
  200. OpMemberName %16 2 "ii"
  201. OpName %18 "ubuf"
  202. OpName %80 "color"
  203. OpMemberDecorate %12 0 RelaxedPrecision
  204. OpMemberDecorate %15 0 RelaxedPrecision
  205. OpMemberDecorate %15 0 Offset 0
  206. OpMemberDecorate %15 1 Offset 4
  207. OpMemberDecorate %16 0 Offset 0
  208. OpMemberDecorate %16 1 RelaxedPrecision
  209. OpMemberDecorate %16 1 Offset 16
  210. OpMemberDecorate %16 2 RelaxedPrecision
  211. OpMemberDecorate %16 2 Offset 20
  212. OpDecorate %16 Block
  213. OpDecorate %18 DescriptorSet 0
  214. OpDecorate %18 Binding 2
  215. OpDecorate %38 RelaxedPrecision
  216. OpDecorate %43 RelaxedPrecision
  217. OpDecorate %53 RelaxedPrecision
  218. OpDecorate %62 RelaxedPrecision
  219. OpDecorate %69 RelaxedPrecision
  220. OpDecorate %77 RelaxedPrecision
  221. OpDecorate %80 Location 0
  222. OpDecorate %101 RelaxedPrecision
  223. OpDecorate %102 RelaxedPrecision
  224. OpDecorate %96 RelaxedPrecision
  225. OpDecorate %108 RelaxedPrecision
  226. OpDecorate %107 RelaxedPrecision
  227. OpDecorate %98 RelaxedPrecision
  228. %2 = OpTypeVoid
  229. %3 = OpTypeFunction %2
  230. %6 = OpTypeFloat 32
  231. %9 = OpConstant %6 0
  232. %11 = OpTypeInt 32 1
  233. %12 = OpTypeStruct %11 %6
  234. %15 = OpTypeStruct %11 %6
  235. %16 = OpTypeStruct %15 %6 %11
  236. %17 = OpTypePointer Uniform %16
  237. %18 = OpVariable %17 Uniform
  238. %19 = OpConstant %11 0
  239. %20 = OpTypePointer Uniform %15
  240. %27 = OpConstant %11 1
  241. %36 = OpTypePointer Uniform %11
  242. %39 = OpTypeBool
  243. %41 = OpConstant %11 2
  244. %48 = OpConstant %6 0.100000001
  245. %51 = OpConstant %6 0.200000003
  246. %78 = OpTypeVector %6 4
  247. %79 = OpTypePointer Output %78
  248. %80 = OpVariable %79 Output
  249. %85 = OpConstant %6 1
  250. %95 = OpUndef %12
  251. %112 = OpTypePointer Uniform %6
  252. %113 = OpTypeInt 32 0
  253. %114 = OpConstant %113 1
  254. %179 = OpTypePointer Function %39
  255. %4 = OpFunction %2 None %3
  256. %5 = OpLabel
  257. %180 = OpVariable %179 Function
  258. %181 = OpVariable %179 Function
  259. %182 = OpVariable %179 Function
  260. %21 = OpAccessChain %20 %18 %19
  261. %115 = OpAccessChain %112 %21 %114
  262. %116 = OpLoad %6 %115
  263. %90 = OpCompositeInsert %12 %116 %95 1
  264. OpBranch %30
  265. %30 = OpLabel
  266. %99 = OpPhi %12 %90 %5 %109 %47
  267. %98 = OpPhi %6 %9 %5 %107 %47
  268. %97 = OpPhi %6 %9 %5 %105 %47
  269. %96 = OpPhi %11 %19 %5 %77 %47
  270. %37 = OpAccessChain %36 %18 %19 %19
  271. %38 = OpLoad %11 %37
  272. %40 = OpSLessThan %39 %96 %38
  273. OpLoopMerge %32 %47 None
  274. OpBranchConditional %40 %31 %32
  275. %31 = OpLabel
  276. %42 = OpAccessChain %36 %18 %41
  277. %43 = OpLoad %11 %42
  278. OpSelectionMerge %47 None
  279. OpSwitch %43 %46 0 %44 1 %45
  280. %46 = OpLabel
  281. %69 = OpIAdd %11 %96 %27
  282. %72 = OpCompositeExtract %6 %99 1
  283. %73 = OpFAdd %6 %72 %98
  284. %93 = OpCompositeInsert %12 %73 %99 1
  285. OpBranch %47
  286. %44 = OpLabel
  287. %50 = OpFAdd %6 %97 %48
  288. %53 = OpFAdd %6 %98 %51
  289. OpBranch %45
  290. %45 = OpLabel
  291. %101 = OpPhi %6 %98 %31 %53 %44
  292. %100 = OpPhi %6 %97 %31 %50 %44
  293. %55 = OpFAdd %6 %100 %48
  294. %58 = OpFOrdGreaterThan %39 %55 %101
  295. OpSelectionMerge %60 None
  296. OpBranchConditional %58 %59 %63
  297. %59 = OpLabel
  298. %62 = OpFAdd %6 %101 %51
  299. OpBranch %60
  300. %63 = OpLabel
  301. %66 = OpFAdd %6 %101 %55
  302. OpBranch %60
  303. %60 = OpLabel
  304. %108 = OpPhi %6 %62 %59 %66 %63
  305. OpBranch %47
  306. %47 = OpLabel
  307. %109 = OpPhi %12 %93 %46 %99 %60
  308. %107 = OpPhi %6 %98 %46 %108 %60
  309. %105 = OpPhi %6 %97 %46 %55 %60
  310. %102 = OpPhi %11 %69 %46 %96 %60
  311. %77 = OpIAdd %11 %102 %27
  312. OpBranch %30
  313. %32 = OpLabel
  314. %84 = OpCompositeExtract %6 %99 1
  315. %86 = OpCompositeConstruct %78 %97 %98 %84 %85
  316. OpStore %80 %86
  317. OpReturn
  318. OpFunctionEnd
  319. )";
  320. const auto env = SPV_ENV_UNIVERSAL_1_3;
  321. const auto consumer = nullptr;
  322. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  323. ASSERT_TRUE(IsValid(env, context.get()));
  324. FactManager fact_manager;
  325. // Inapplicable because %18 is decorated.
  326. ASSERT_FALSE(TransformationCopyObject(
  327. 18, MakeInstructionDescriptor(21, SpvOpAccessChain, 0), 200)
  328. .IsApplicable(context.get(), fact_manager));
  329. // Inapplicable because %77 is decorated.
  330. ASSERT_FALSE(TransformationCopyObject(
  331. 77, MakeInstructionDescriptor(77, SpvOpBranch, 0), 200)
  332. .IsApplicable(context.get(), fact_manager));
  333. // Inapplicable because %80 is decorated.
  334. ASSERT_FALSE(TransformationCopyObject(
  335. 80, MakeInstructionDescriptor(77, SpvOpIAdd, 0), 200)
  336. .IsApplicable(context.get(), fact_manager));
  337. // Inapplicable because %84 is not available at the requested point
  338. ASSERT_FALSE(
  339. TransformationCopyObject(
  340. 84, MakeInstructionDescriptor(32, SpvOpCompositeExtract, 0), 200)
  341. .IsApplicable(context.get(), fact_manager));
  342. // Fine because %84 is available at the requested point
  343. ASSERT_TRUE(
  344. TransformationCopyObject(
  345. 84, MakeInstructionDescriptor(32, SpvOpCompositeConstruct, 0), 200)
  346. .IsApplicable(context.get(), fact_manager));
  347. // Inapplicable because id %9 is already in use
  348. ASSERT_FALSE(
  349. TransformationCopyObject(
  350. 84, MakeInstructionDescriptor(32, SpvOpCompositeConstruct, 0), 9)
  351. .IsApplicable(context.get(), fact_manager));
  352. // Inapplicable because the requested point does not exist
  353. ASSERT_FALSE(TransformationCopyObject(
  354. 84, MakeInstructionDescriptor(86, SpvOpReturn, 2), 200)
  355. .IsApplicable(context.get(), fact_manager));
  356. // Inapplicable because %9 is not in a function
  357. ASSERT_FALSE(TransformationCopyObject(
  358. 9, MakeInstructionDescriptor(9, SpvOpTypeInt, 0), 200)
  359. .IsApplicable(context.get(), fact_manager));
  360. // Inapplicable because the insert point is right before, or inside, a chunk
  361. // of OpPhis
  362. ASSERT_FALSE(TransformationCopyObject(
  363. 9, MakeInstructionDescriptor(30, SpvOpPhi, 0), 200)
  364. .IsApplicable(context.get(), fact_manager));
  365. ASSERT_FALSE(TransformationCopyObject(
  366. 9, MakeInstructionDescriptor(99, SpvOpPhi, 1), 200)
  367. .IsApplicable(context.get(), fact_manager));
  368. // OK, because the insert point is just after a chunk of OpPhis.
  369. ASSERT_TRUE(TransformationCopyObject(
  370. 9, MakeInstructionDescriptor(96, SpvOpAccessChain, 0), 200)
  371. .IsApplicable(context.get(), fact_manager));
  372. // Inapplicable because the insert point is right after an OpSelectionMerge
  373. ASSERT_FALSE(
  374. TransformationCopyObject(
  375. 9, MakeInstructionDescriptor(58, SpvOpBranchConditional, 0), 200)
  376. .IsApplicable(context.get(), fact_manager));
  377. // OK, because the insert point is right before the OpSelectionMerge
  378. ASSERT_TRUE(TransformationCopyObject(
  379. 9, MakeInstructionDescriptor(58, SpvOpSelectionMerge, 0), 200)
  380. .IsApplicable(context.get(), fact_manager));
  381. // Inapplicable because the insert point is right after an OpSelectionMerge
  382. ASSERT_FALSE(TransformationCopyObject(
  383. 9, MakeInstructionDescriptor(43, SpvOpSwitch, 0), 200)
  384. .IsApplicable(context.get(), fact_manager));
  385. // OK, because the insert point is right before the OpSelectionMerge
  386. ASSERT_TRUE(TransformationCopyObject(
  387. 9, MakeInstructionDescriptor(43, SpvOpSelectionMerge, 0), 200)
  388. .IsApplicable(context.get(), fact_manager));
  389. // Inapplicable because the insert point is right after an OpLoopMerge
  390. ASSERT_FALSE(
  391. TransformationCopyObject(
  392. 9, MakeInstructionDescriptor(40, SpvOpBranchConditional, 0), 200)
  393. .IsApplicable(context.get(), fact_manager));
  394. // OK, because the insert point is right before the OpLoopMerge
  395. ASSERT_TRUE(TransformationCopyObject(
  396. 9, MakeInstructionDescriptor(40, SpvOpLoopMerge, 0), 200)
  397. .IsApplicable(context.get(), fact_manager));
  398. // Inapplicable because id %300 does not exist
  399. ASSERT_FALSE(TransformationCopyObject(
  400. 300, MakeInstructionDescriptor(40, SpvOpLoopMerge, 0), 200)
  401. .IsApplicable(context.get(), fact_manager));
  402. // Inapplicable because the following instruction is OpVariable
  403. ASSERT_FALSE(TransformationCopyObject(
  404. 9, MakeInstructionDescriptor(180, SpvOpVariable, 0), 200)
  405. .IsApplicable(context.get(), fact_manager));
  406. ASSERT_FALSE(TransformationCopyObject(
  407. 9, MakeInstructionDescriptor(181, SpvOpVariable, 0), 200)
  408. .IsApplicable(context.get(), fact_manager));
  409. ASSERT_FALSE(TransformationCopyObject(
  410. 9, MakeInstructionDescriptor(182, SpvOpVariable, 0), 200)
  411. .IsApplicable(context.get(), fact_manager));
  412. // OK, because this is just past the group of OpVariable instructions.
  413. ASSERT_TRUE(TransformationCopyObject(
  414. 9, MakeInstructionDescriptor(182, SpvOpAccessChain, 0), 200)
  415. .IsApplicable(context.get(), fact_manager));
  416. }
  417. TEST(TransformationCopyObjectTest, MiscellaneousCopies) {
  418. // The following SPIR-V comes from this GLSL:
  419. //
  420. // #version 310 es
  421. //
  422. // precision highp float;
  423. //
  424. // float g;
  425. //
  426. // vec4 h;
  427. //
  428. // void main() {
  429. // int a;
  430. // int b;
  431. // b = int(g);
  432. // h.x = float(a);
  433. // }
  434. std::string shader = R"(
  435. OpCapability Shader
  436. %1 = OpExtInstImport "GLSL.std.450"
  437. OpMemoryModel Logical GLSL450
  438. OpEntryPoint Fragment %4 "main"
  439. OpExecutionMode %4 OriginUpperLeft
  440. OpSource ESSL 310
  441. OpName %4 "main"
  442. OpName %8 "b"
  443. OpName %11 "g"
  444. OpName %16 "h"
  445. OpName %17 "a"
  446. %2 = OpTypeVoid
  447. %3 = OpTypeFunction %2
  448. %6 = OpTypeInt 32 1
  449. %7 = OpTypePointer Function %6
  450. %9 = OpTypeFloat 32
  451. %10 = OpTypePointer Private %9
  452. %11 = OpVariable %10 Private
  453. %14 = OpTypeVector %9 4
  454. %15 = OpTypePointer Private %14
  455. %16 = OpVariable %15 Private
  456. %20 = OpTypeInt 32 0
  457. %21 = OpConstant %20 0
  458. %4 = OpFunction %2 None %3
  459. %5 = OpLabel
  460. %8 = OpVariable %7 Function
  461. %17 = OpVariable %7 Function
  462. %12 = OpLoad %9 %11
  463. %13 = OpConvertFToS %6 %12
  464. OpStore %8 %13
  465. %18 = OpLoad %6 %17
  466. %19 = OpConvertSToF %9 %18
  467. %22 = OpAccessChain %10 %16 %21
  468. OpStore %22 %19
  469. OpReturn
  470. OpFunctionEnd
  471. )";
  472. const auto env = SPV_ENV_UNIVERSAL_1_3;
  473. const auto consumer = nullptr;
  474. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  475. ASSERT_TRUE(IsValid(env, context.get()));
  476. FactManager fact_manager;
  477. std::vector<TransformationCopyObject> transformations = {
  478. TransformationCopyObject(19, MakeInstructionDescriptor(22, SpvOpStore, 0),
  479. 100),
  480. TransformationCopyObject(
  481. 22, MakeInstructionDescriptor(22, SpvOpCopyObject, 0), 101),
  482. TransformationCopyObject(
  483. 12, MakeInstructionDescriptor(22, SpvOpCopyObject, 0), 102),
  484. TransformationCopyObject(
  485. 11, MakeInstructionDescriptor(22, SpvOpCopyObject, 0), 103),
  486. TransformationCopyObject(
  487. 16, MakeInstructionDescriptor(22, SpvOpCopyObject, 0), 104),
  488. TransformationCopyObject(
  489. 8, MakeInstructionDescriptor(22, SpvOpCopyObject, 0), 105),
  490. TransformationCopyObject(
  491. 17, MakeInstructionDescriptor(22, SpvOpCopyObject, 0), 106)};
  492. for (auto& transformation : transformations) {
  493. ASSERT_TRUE(transformation.IsApplicable(context.get(), fact_manager));
  494. transformation.Apply(context.get(), &fact_manager);
  495. }
  496. ASSERT_TRUE(IsValid(env, context.get()));
  497. std::string after_transformation = R"(
  498. OpCapability Shader
  499. %1 = OpExtInstImport "GLSL.std.450"
  500. OpMemoryModel Logical GLSL450
  501. OpEntryPoint Fragment %4 "main"
  502. OpExecutionMode %4 OriginUpperLeft
  503. OpSource ESSL 310
  504. OpName %4 "main"
  505. OpName %8 "b"
  506. OpName %11 "g"
  507. OpName %16 "h"
  508. OpName %17 "a"
  509. %2 = OpTypeVoid
  510. %3 = OpTypeFunction %2
  511. %6 = OpTypeInt 32 1
  512. %7 = OpTypePointer Function %6
  513. %9 = OpTypeFloat 32
  514. %10 = OpTypePointer Private %9
  515. %11 = OpVariable %10 Private
  516. %14 = OpTypeVector %9 4
  517. %15 = OpTypePointer Private %14
  518. %16 = OpVariable %15 Private
  519. %20 = OpTypeInt 32 0
  520. %21 = OpConstant %20 0
  521. %4 = OpFunction %2 None %3
  522. %5 = OpLabel
  523. %8 = OpVariable %7 Function
  524. %17 = OpVariable %7 Function
  525. %12 = OpLoad %9 %11
  526. %13 = OpConvertFToS %6 %12
  527. OpStore %8 %13
  528. %18 = OpLoad %6 %17
  529. %19 = OpConvertSToF %9 %18
  530. %22 = OpAccessChain %10 %16 %21
  531. %106 = OpCopyObject %7 %17
  532. %105 = OpCopyObject %7 %8
  533. %104 = OpCopyObject %15 %16
  534. %103 = OpCopyObject %10 %11
  535. %102 = OpCopyObject %9 %12
  536. %101 = OpCopyObject %10 %22
  537. %100 = OpCopyObject %9 %19
  538. OpStore %22 %19
  539. OpReturn
  540. OpFunctionEnd
  541. )";
  542. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  543. }
  544. } // namespace
  545. } // namespace fuzz
  546. } // namespace spvtools