data_synonym_transformation_test.cpp 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258
  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 "source/fuzz/data_descriptor.h"
  15. #include "gtest/gtest.h"
  16. #include "source/fuzz/fuzzer_util.h"
  17. #include "source/fuzz/id_use_descriptor.h"
  18. #include "source/fuzz/instruction_descriptor.h"
  19. #include "source/fuzz/transformation_composite_extract.h"
  20. #include "source/fuzz/transformation_replace_id_with_synonym.h"
  21. #include "source/fuzz/transformation_vector_shuffle.h"
  22. #include "test/fuzz/fuzz_test_util.h"
  23. namespace spvtools {
  24. namespace fuzz {
  25. namespace {
  26. // This file captures tests that check correctness of the collective use of a
  27. // number of transformations that relate to data synonyms.
  28. protobufs::Fact MakeSynonymFact(uint32_t first_id,
  29. const std::vector<uint32_t>& first_indices,
  30. uint32_t second_id,
  31. const std::vector<uint32_t>& second_indices) {
  32. protobufs::FactDataSynonym data_synonym_fact;
  33. *data_synonym_fact.mutable_data1() =
  34. MakeDataDescriptor(first_id, first_indices);
  35. *data_synonym_fact.mutable_data2() =
  36. MakeDataDescriptor(second_id, second_indices);
  37. protobufs::Fact result;
  38. *result.mutable_data_synonym_fact() = data_synonym_fact;
  39. return result;
  40. }
  41. TEST(DataSynonymTransformationTest, ArrayCompositeSynonyms) {
  42. std::string shader = R"(
  43. OpCapability Shader
  44. %1 = OpExtInstImport "GLSL.std.450"
  45. OpMemoryModel Logical GLSL450
  46. OpEntryPoint Fragment %4 "main"
  47. OpExecutionMode %4 OriginUpperLeft
  48. OpSource ESSL 310
  49. OpName %4 "main"
  50. OpName %11 "A"
  51. OpName %20 "B"
  52. OpName %31 "g"
  53. OpName %35 "h"
  54. OpDecorate %11 RelaxedPrecision
  55. OpDecorate %22 RelaxedPrecision
  56. OpDecorate %27 RelaxedPrecision
  57. OpDecorate %35 RelaxedPrecision
  58. OpDecorate %36 RelaxedPrecision
  59. OpDecorate %40 RelaxedPrecision
  60. OpDecorate %41 RelaxedPrecision
  61. %2 = OpTypeVoid
  62. %3 = OpTypeFunction %2
  63. %6 = OpTypeInt 32 1
  64. %7 = OpTypeInt 32 0
  65. %8 = OpConstant %7 3
  66. %9 = OpTypeArray %6 %8
  67. %10 = OpTypePointer Function %9
  68. %12 = OpConstant %6 0
  69. %13 = OpConstant %6 3
  70. %14 = OpTypePointer Function %6
  71. %16 = OpTypeFloat 32
  72. %17 = OpConstant %7 4
  73. %18 = OpTypeArray %16 %17
  74. %19 = OpTypePointer Function %18
  75. %24 = OpTypePointer Function %16
  76. %28 = OpConstant %16 42
  77. %30 = OpConstant %6 2
  78. %34 = OpConstant %6 1
  79. %38 = OpConstant %6 42
  80. %4 = OpFunction %2 None %3
  81. %5 = OpLabel
  82. %11 = OpVariable %10 Function
  83. %20 = OpVariable %19 Function
  84. %31 = OpVariable %24 Function
  85. %35 = OpVariable %14 Function
  86. %15 = OpAccessChain %14 %11 %12
  87. %21 = OpAccessChain %14 %11 %12
  88. %22 = OpLoad %6 %21
  89. %100 = OpCompositeConstruct %9 %12 %13 %22
  90. OpStore %15 %13
  91. %23 = OpConvertSToF %16 %22
  92. %25 = OpAccessChain %24 %20 %12
  93. OpStore %25 %23
  94. %26 = OpAccessChain %14 %11 %12
  95. %27 = OpLoad %6 %26
  96. %29 = OpAccessChain %24 %20 %27
  97. OpStore %29 %28
  98. %32 = OpLoad %16 %31
  99. %101 = OpCompositeConstruct %18 %28 %23 %32 %23
  100. %50 = OpCopyObject %16 %23
  101. %51 = OpCopyObject %16 %23
  102. %33 = OpAccessChain %24 %20 %30
  103. OpStore %33 %28
  104. OpStore %33 %32
  105. %36 = OpLoad %6 %35
  106. %37 = OpAccessChain %14 %11 %34
  107. OpStore %37 %36
  108. %39 = OpAccessChain %14 %11 %12
  109. %40 = OpLoad %6 %39
  110. %41 = OpIAdd %6 %38 %40
  111. %42 = OpAccessChain %14 %11 %30
  112. OpStore %42 %41
  113. OpReturn
  114. OpFunctionEnd
  115. )";
  116. const auto env = SPV_ENV_UNIVERSAL_1_3;
  117. const auto consumer = nullptr;
  118. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  119. spvtools::ValidatorOptions validator_options;
  120. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  121. kConsoleMessageConsumer));
  122. TransformationContext transformation_context(
  123. MakeUnique<FactManager>(context.get()), validator_options);
  124. transformation_context.GetFactManager()->MaybeAddFact(
  125. MakeSynonymFact(12, {}, 100, {0}));
  126. transformation_context.GetFactManager()->MaybeAddFact(
  127. MakeSynonymFact(13, {}, 100, {1}));
  128. transformation_context.GetFactManager()->MaybeAddFact(
  129. MakeSynonymFact(22, {}, 100, {2}));
  130. transformation_context.GetFactManager()->MaybeAddFact(
  131. MakeSynonymFact(28, {}, 101, {0}));
  132. transformation_context.GetFactManager()->MaybeAddFact(
  133. MakeSynonymFact(23, {}, 101, {1}));
  134. transformation_context.GetFactManager()->MaybeAddFact(
  135. MakeSynonymFact(32, {}, 101, {2}));
  136. transformation_context.GetFactManager()->MaybeAddFact(
  137. MakeSynonymFact(23, {}, 101, {3}));
  138. // Replace %12 with %100[0] in '%25 = OpAccessChain %24 %20 %12'
  139. auto instruction_descriptor_1 =
  140. MakeInstructionDescriptor(25, spv::Op::OpAccessChain, 0);
  141. auto good_extract_1 =
  142. TransformationCompositeExtract(instruction_descriptor_1, 102, 100, {0});
  143. // Bad: id already in use
  144. auto bad_extract_1 = TransformationCompositeExtract(
  145. MakeInstructionDescriptor(25, spv::Op::OpAccessChain, 0), 25, 100, {0});
  146. ASSERT_TRUE(
  147. good_extract_1.IsApplicable(context.get(), transformation_context));
  148. ASSERT_FALSE(
  149. bad_extract_1.IsApplicable(context.get(), transformation_context));
  150. good_extract_1.Apply(context.get(), &transformation_context);
  151. auto replacement_1 = TransformationReplaceIdWithSynonym(
  152. MakeIdUseDescriptor(12, instruction_descriptor_1, 1), 102);
  153. ASSERT_TRUE(
  154. replacement_1.IsApplicable(context.get(), transformation_context));
  155. replacement_1.Apply(context.get(), &transformation_context);
  156. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  157. kConsoleMessageConsumer));
  158. // Replace %13 with %100[1] in 'OpStore %15 %13'
  159. auto instruction_descriptor_2 =
  160. MakeInstructionDescriptor(100, spv::Op::OpStore, 0);
  161. auto good_extract_2 =
  162. TransformationCompositeExtract(instruction_descriptor_2, 103, 100, {1});
  163. // No bad example provided here.
  164. ASSERT_TRUE(
  165. good_extract_2.IsApplicable(context.get(), transformation_context));
  166. good_extract_2.Apply(context.get(), &transformation_context);
  167. auto replacement_2 = TransformationReplaceIdWithSynonym(
  168. MakeIdUseDescriptor(13, instruction_descriptor_2, 1), 103);
  169. ASSERT_TRUE(
  170. replacement_2.IsApplicable(context.get(), transformation_context));
  171. replacement_2.Apply(context.get(), &transformation_context);
  172. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  173. kConsoleMessageConsumer));
  174. // Replace %22 with %100[2] in '%23 = OpConvertSToF %16 %22'
  175. auto instruction_descriptor_3 =
  176. MakeInstructionDescriptor(23, spv::Op::OpConvertSToF, 0);
  177. auto good_extract_3 =
  178. TransformationCompositeExtract(instruction_descriptor_3, 104, 100, {2});
  179. ASSERT_TRUE(
  180. good_extract_3.IsApplicable(context.get(), transformation_context));
  181. good_extract_3.Apply(context.get(), &transformation_context);
  182. auto replacement_3 = TransformationReplaceIdWithSynonym(
  183. MakeIdUseDescriptor(22, instruction_descriptor_3, 0), 104);
  184. // Bad: wrong input operand index
  185. auto bad_replacement_3 = TransformationReplaceIdWithSynonym(
  186. MakeIdUseDescriptor(22, instruction_descriptor_3, 1), 104);
  187. ASSERT_TRUE(
  188. replacement_3.IsApplicable(context.get(), transformation_context));
  189. ASSERT_FALSE(
  190. bad_replacement_3.IsApplicable(context.get(), transformation_context));
  191. replacement_3.Apply(context.get(), &transformation_context);
  192. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  193. kConsoleMessageConsumer));
  194. // Replace %28 with %101[0] in 'OpStore %33 %28'
  195. auto instruction_descriptor_4 =
  196. MakeInstructionDescriptor(33, spv::Op::OpStore, 0);
  197. auto good_extract_4 =
  198. TransformationCompositeExtract(instruction_descriptor_4, 105, 101, {0});
  199. // Bad: instruction descriptor does not identify an appropriate instruction
  200. auto bad_extract_4 = TransformationCompositeExtract(
  201. MakeInstructionDescriptor(33, spv::Op::OpCopyObject, 0), 105, 101, {0});
  202. ASSERT_TRUE(
  203. good_extract_4.IsApplicable(context.get(), transformation_context));
  204. ASSERT_FALSE(
  205. bad_extract_4.IsApplicable(context.get(), transformation_context));
  206. good_extract_4.Apply(context.get(), &transformation_context);
  207. auto replacement_4 = TransformationReplaceIdWithSynonym(
  208. MakeIdUseDescriptor(28, instruction_descriptor_4, 1), 105);
  209. ASSERT_TRUE(
  210. replacement_4.IsApplicable(context.get(), transformation_context));
  211. replacement_4.Apply(context.get(), &transformation_context);
  212. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  213. kConsoleMessageConsumer));
  214. // Replace %23 with %101[1] in '%50 = OpCopyObject %16 %23'
  215. auto instruction_descriptor_5 =
  216. MakeInstructionDescriptor(50, spv::Op::OpCopyObject, 0);
  217. auto good_extract_5 =
  218. TransformationCompositeExtract(instruction_descriptor_5, 106, 101, {1});
  219. ASSERT_TRUE(
  220. good_extract_5.IsApplicable(context.get(), transformation_context));
  221. good_extract_5.Apply(context.get(), &transformation_context);
  222. auto replacement_5 = TransformationReplaceIdWithSynonym(
  223. MakeIdUseDescriptor(23, instruction_descriptor_5, 0), 106);
  224. // Bad: wrong synonym fact being used
  225. auto bad_replacement_5 = TransformationReplaceIdWithSynonym(
  226. MakeIdUseDescriptor(23, instruction_descriptor_5, 0), 105);
  227. ASSERT_TRUE(
  228. replacement_5.IsApplicable(context.get(), transformation_context));
  229. ASSERT_FALSE(
  230. bad_replacement_5.IsApplicable(context.get(), transformation_context));
  231. replacement_5.Apply(context.get(), &transformation_context);
  232. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  233. kConsoleMessageConsumer));
  234. // Replace %32 with %101[2] in 'OpStore %33 %32'
  235. auto instruction_descriptor_6 =
  236. MakeInstructionDescriptor(33, spv::Op::OpStore, 1);
  237. auto good_extract_6 =
  238. TransformationCompositeExtract(instruction_descriptor_6, 107, 101, {2});
  239. // Bad: id 1001 does not exist
  240. auto bad_extract_6 =
  241. TransformationCompositeExtract(instruction_descriptor_6, 107, 1001, {2});
  242. ASSERT_TRUE(
  243. good_extract_6.IsApplicable(context.get(), transformation_context));
  244. ASSERT_FALSE(
  245. bad_extract_6.IsApplicable(context.get(), transformation_context));
  246. good_extract_6.Apply(context.get(), &transformation_context);
  247. auto replacement_6 = TransformationReplaceIdWithSynonym(
  248. MakeIdUseDescriptor(32, instruction_descriptor_6, 1), 107);
  249. ASSERT_TRUE(
  250. replacement_6.IsApplicable(context.get(), transformation_context));
  251. replacement_6.Apply(context.get(), &transformation_context);
  252. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  253. kConsoleMessageConsumer));
  254. // Replace %23 with %101[3] in '%51 = OpCopyObject %16 %23'
  255. auto instruction_descriptor_7 =
  256. MakeInstructionDescriptor(51, spv::Op::OpCopyObject, 0);
  257. auto good_extract_7 =
  258. TransformationCompositeExtract(instruction_descriptor_7, 108, 101, {3});
  259. ASSERT_TRUE(
  260. good_extract_7.IsApplicable(context.get(), transformation_context));
  261. good_extract_7.Apply(context.get(), &transformation_context);
  262. auto replacement_7 = TransformationReplaceIdWithSynonym(
  263. MakeIdUseDescriptor(23, instruction_descriptor_7, 0), 108);
  264. // Bad: use id 0 is invalid
  265. auto bad_replacement_7 = TransformationReplaceIdWithSynonym(
  266. MakeIdUseDescriptor(0, instruction_descriptor_7, 0), 108);
  267. ASSERT_TRUE(
  268. replacement_7.IsApplicable(context.get(), transformation_context));
  269. ASSERT_FALSE(
  270. bad_replacement_7.IsApplicable(context.get(), transformation_context));
  271. replacement_7.Apply(context.get(), &transformation_context);
  272. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  273. kConsoleMessageConsumer));
  274. const std::string after_transformation = R"(
  275. OpCapability Shader
  276. %1 = OpExtInstImport "GLSL.std.450"
  277. OpMemoryModel Logical GLSL450
  278. OpEntryPoint Fragment %4 "main"
  279. OpExecutionMode %4 OriginUpperLeft
  280. OpSource ESSL 310
  281. OpName %4 "main"
  282. OpName %11 "A"
  283. OpName %20 "B"
  284. OpName %31 "g"
  285. OpName %35 "h"
  286. OpDecorate %11 RelaxedPrecision
  287. OpDecorate %22 RelaxedPrecision
  288. OpDecorate %27 RelaxedPrecision
  289. OpDecorate %35 RelaxedPrecision
  290. OpDecorate %36 RelaxedPrecision
  291. OpDecorate %40 RelaxedPrecision
  292. OpDecorate %41 RelaxedPrecision
  293. %2 = OpTypeVoid
  294. %3 = OpTypeFunction %2
  295. %6 = OpTypeInt 32 1
  296. %7 = OpTypeInt 32 0
  297. %8 = OpConstant %7 3
  298. %9 = OpTypeArray %6 %8
  299. %10 = OpTypePointer Function %9
  300. %12 = OpConstant %6 0
  301. %13 = OpConstant %6 3
  302. %14 = OpTypePointer Function %6
  303. %16 = OpTypeFloat 32
  304. %17 = OpConstant %7 4
  305. %18 = OpTypeArray %16 %17
  306. %19 = OpTypePointer Function %18
  307. %24 = OpTypePointer Function %16
  308. %28 = OpConstant %16 42
  309. %30 = OpConstant %6 2
  310. %34 = OpConstant %6 1
  311. %38 = OpConstant %6 42
  312. %4 = OpFunction %2 None %3
  313. %5 = OpLabel
  314. %11 = OpVariable %10 Function
  315. %20 = OpVariable %19 Function
  316. %31 = OpVariable %24 Function
  317. %35 = OpVariable %14 Function
  318. %15 = OpAccessChain %14 %11 %12
  319. %21 = OpAccessChain %14 %11 %12
  320. %22 = OpLoad %6 %21
  321. %100 = OpCompositeConstruct %9 %12 %13 %22
  322. %103 = OpCompositeExtract %6 %100 1
  323. OpStore %15 %103
  324. %104 = OpCompositeExtract %6 %100 2
  325. %23 = OpConvertSToF %16 %104
  326. %102 = OpCompositeExtract %6 %100 0
  327. %25 = OpAccessChain %24 %20 %102
  328. OpStore %25 %23
  329. %26 = OpAccessChain %14 %11 %12
  330. %27 = OpLoad %6 %26
  331. %29 = OpAccessChain %24 %20 %27
  332. OpStore %29 %28
  333. %32 = OpLoad %16 %31
  334. %101 = OpCompositeConstruct %18 %28 %23 %32 %23
  335. %106 = OpCompositeExtract %16 %101 1
  336. %50 = OpCopyObject %16 %106
  337. %108 = OpCompositeExtract %16 %101 3
  338. %51 = OpCopyObject %16 %108
  339. %33 = OpAccessChain %24 %20 %30
  340. %105 = OpCompositeExtract %16 %101 0
  341. OpStore %33 %105
  342. %107 = OpCompositeExtract %16 %101 2
  343. OpStore %33 %107
  344. %36 = OpLoad %6 %35
  345. %37 = OpAccessChain %14 %11 %34
  346. OpStore %37 %36
  347. %39 = OpAccessChain %14 %11 %12
  348. %40 = OpLoad %6 %39
  349. %41 = OpIAdd %6 %38 %40
  350. %42 = OpAccessChain %14 %11 %30
  351. OpStore %42 %41
  352. OpReturn
  353. OpFunctionEnd
  354. )";
  355. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  356. }
  357. TEST(DataSynonymTransformationTest, MatrixCompositeSynonyms) {
  358. std::string shader = R"(
  359. OpCapability Shader
  360. %1 = OpExtInstImport "GLSL.std.450"
  361. OpMemoryModel Logical GLSL450
  362. OpEntryPoint Fragment %4 "main"
  363. OpExecutionMode %4 OriginUpperLeft
  364. OpSource ESSL 310
  365. OpName %4 "main"
  366. OpName %10 "m"
  367. %2 = OpTypeVoid
  368. %3 = OpTypeFunction %2
  369. %6 = OpTypeFloat 32
  370. %7 = OpTypeVector %6 4
  371. %50 = OpUndef %7
  372. %8 = OpTypeMatrix %7 3
  373. %9 = OpTypePointer Function %8
  374. %11 = OpTypeInt 32 1
  375. %12 = OpConstant %11 0
  376. %13 = OpConstant %6 1
  377. %14 = OpConstantComposite %7 %13 %13 %13 %13
  378. %15 = OpTypePointer Function %7
  379. %17 = OpConstant %11 1
  380. %18 = OpConstant %6 2
  381. %19 = OpConstantComposite %7 %18 %18 %18 %18
  382. %21 = OpConstant %11 2
  383. %4 = OpFunction %2 None %3
  384. %5 = OpLabel
  385. %10 = OpVariable %9 Function
  386. %16 = OpAccessChain %15 %10 %12
  387. OpStore %16 %14
  388. %20 = OpAccessChain %15 %10 %17
  389. OpStore %20 %19
  390. %22 = OpAccessChain %15 %10 %12
  391. %23 = OpLoad %7 %22
  392. %24 = OpAccessChain %15 %10 %17
  393. %25 = OpLoad %7 %24
  394. %100 = OpCompositeConstruct %8 %23 %25 %50
  395. %26 = OpFAdd %7 %23 %25
  396. %27 = OpAccessChain %15 %10 %21
  397. OpStore %27 %26
  398. OpReturn
  399. OpFunctionEnd
  400. )";
  401. const auto env = SPV_ENV_UNIVERSAL_1_3;
  402. const auto consumer = nullptr;
  403. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  404. spvtools::ValidatorOptions validator_options;
  405. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  406. kConsoleMessageConsumer));
  407. TransformationContext transformation_context(
  408. MakeUnique<FactManager>(context.get()), validator_options);
  409. transformation_context.GetFactManager()->MaybeAddFact(
  410. MakeSynonymFact(23, {}, 100, {0}));
  411. transformation_context.GetFactManager()->MaybeAddFact(
  412. MakeSynonymFact(25, {}, 100, {1}));
  413. transformation_context.GetFactManager()->MaybeAddFact(
  414. MakeSynonymFact(50, {}, 100, {2}));
  415. // Replace %23 with %100[0] in '%26 = OpFAdd %7 %23 %25'
  416. auto instruction_descriptor_1 =
  417. MakeInstructionDescriptor(26, spv::Op::OpFAdd, 0);
  418. auto extract_1 =
  419. TransformationCompositeExtract(instruction_descriptor_1, 101, 100, {0});
  420. ASSERT_TRUE(extract_1.IsApplicable(context.get(), transformation_context));
  421. extract_1.Apply(context.get(), &transformation_context);
  422. auto replacement_1 = TransformationReplaceIdWithSynonym(
  423. MakeIdUseDescriptor(23, instruction_descriptor_1, 0), 101);
  424. ASSERT_TRUE(
  425. replacement_1.IsApplicable(context.get(), transformation_context));
  426. replacement_1.Apply(context.get(), &transformation_context);
  427. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  428. kConsoleMessageConsumer));
  429. // Replace %25 with %100[1] in '%26 = OpFAdd %7 %23 %25'
  430. auto instruction_descriptor_2 =
  431. MakeInstructionDescriptor(26, spv::Op::OpFAdd, 0);
  432. auto extract_2 =
  433. TransformationCompositeExtract(instruction_descriptor_2, 102, 100, {1});
  434. ASSERT_TRUE(extract_2.IsApplicable(context.get(), transformation_context));
  435. extract_2.Apply(context.get(), &transformation_context);
  436. auto replacement_2 = TransformationReplaceIdWithSynonym(
  437. MakeIdUseDescriptor(25, instruction_descriptor_2, 1), 102);
  438. ASSERT_TRUE(
  439. replacement_2.IsApplicable(context.get(), transformation_context));
  440. replacement_2.Apply(context.get(), &transformation_context);
  441. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  442. kConsoleMessageConsumer));
  443. const std::string after_transformation = R"(
  444. OpCapability Shader
  445. %1 = OpExtInstImport "GLSL.std.450"
  446. OpMemoryModel Logical GLSL450
  447. OpEntryPoint Fragment %4 "main"
  448. OpExecutionMode %4 OriginUpperLeft
  449. OpSource ESSL 310
  450. OpName %4 "main"
  451. OpName %10 "m"
  452. %2 = OpTypeVoid
  453. %3 = OpTypeFunction %2
  454. %6 = OpTypeFloat 32
  455. %7 = OpTypeVector %6 4
  456. %50 = OpUndef %7
  457. %8 = OpTypeMatrix %7 3
  458. %9 = OpTypePointer Function %8
  459. %11 = OpTypeInt 32 1
  460. %12 = OpConstant %11 0
  461. %13 = OpConstant %6 1
  462. %14 = OpConstantComposite %7 %13 %13 %13 %13
  463. %15 = OpTypePointer Function %7
  464. %17 = OpConstant %11 1
  465. %18 = OpConstant %6 2
  466. %19 = OpConstantComposite %7 %18 %18 %18 %18
  467. %21 = OpConstant %11 2
  468. %4 = OpFunction %2 None %3
  469. %5 = OpLabel
  470. %10 = OpVariable %9 Function
  471. %16 = OpAccessChain %15 %10 %12
  472. OpStore %16 %14
  473. %20 = OpAccessChain %15 %10 %17
  474. OpStore %20 %19
  475. %22 = OpAccessChain %15 %10 %12
  476. %23 = OpLoad %7 %22
  477. %24 = OpAccessChain %15 %10 %17
  478. %25 = OpLoad %7 %24
  479. %100 = OpCompositeConstruct %8 %23 %25 %50
  480. %101 = OpCompositeExtract %7 %100 0
  481. %102 = OpCompositeExtract %7 %100 1
  482. %26 = OpFAdd %7 %101 %102
  483. %27 = OpAccessChain %15 %10 %21
  484. OpStore %27 %26
  485. OpReturn
  486. OpFunctionEnd
  487. )";
  488. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  489. }
  490. TEST(DataSynonymTransformationTest, StructCompositeSynonyms) {
  491. std::string shader = R"(
  492. OpCapability Shader
  493. %1 = OpExtInstImport "GLSL.std.450"
  494. OpMemoryModel Logical GLSL450
  495. OpEntryPoint Fragment %4 "main"
  496. OpExecutionMode %4 OriginUpperLeft
  497. OpSource ESSL 310
  498. OpName %4 "main"
  499. OpName %9 "Inner"
  500. OpMemberName %9 0 "a"
  501. OpMemberName %9 1 "b"
  502. OpName %11 "i1"
  503. OpName %17 "i2"
  504. OpName %31 "Point"
  505. OpMemberName %31 0 "x"
  506. OpMemberName %31 1 "y"
  507. OpMemberName %31 2 "z"
  508. OpName %32 "Outer"
  509. OpMemberName %32 0 "c"
  510. OpMemberName %32 1 "d"
  511. OpName %34 "o1"
  512. %2 = OpTypeVoid
  513. %3 = OpTypeFunction %2
  514. %6 = OpTypeInt 32 1
  515. %7 = OpTypeFloat 32
  516. %8 = OpTypeVector %7 2
  517. %9 = OpTypeStruct %6 %8
  518. %10 = OpTypePointer Function %9
  519. %12 = OpConstant %6 1
  520. %13 = OpConstant %7 2
  521. %14 = OpConstant %7 3
  522. %15 = OpConstantComposite %8 %13 %14
  523. %16 = OpConstantComposite %9 %12 %15
  524. %18 = OpConstant %6 0
  525. %19 = OpTypePointer Function %6
  526. %24 = OpTypePointer Function %8
  527. %27 = OpConstant %7 4
  528. %31 = OpTypeStruct %7 %7 %7
  529. %32 = OpTypeStruct %9 %31
  530. %33 = OpTypePointer Function %32
  531. %36 = OpConstant %7 10
  532. %37 = OpTypeInt 32 0
  533. %38 = OpConstant %37 0
  534. %39 = OpTypePointer Function %7
  535. %42 = OpConstant %37 1
  536. %4 = OpFunction %2 None %3
  537. %5 = OpLabel
  538. %11 = OpVariable %10 Function
  539. %17 = OpVariable %10 Function
  540. %34 = OpVariable %33 Function
  541. %101 = OpCompositeConstruct %31 %27 %36 %27
  542. OpStore %11 %16
  543. %20 = OpAccessChain %19 %11 %18
  544. %21 = OpLoad %6 %20
  545. %22 = OpIAdd %6 %21 %12
  546. %102 = OpCompositeConstruct %9 %22 %15
  547. %23 = OpAccessChain %19 %17 %18
  548. OpStore %23 %22
  549. %25 = OpAccessChain %24 %17 %12
  550. %26 = OpLoad %8 %25
  551. %28 = OpCompositeConstruct %8 %27 %27
  552. %29 = OpFAdd %8 %26 %28
  553. %30 = OpAccessChain %24 %17 %12
  554. OpStore %30 %29
  555. %35 = OpLoad %9 %11
  556. %40 = OpAccessChain %39 %11 %12 %38
  557. %41 = OpLoad %7 %40
  558. %43 = OpAccessChain %39 %11 %12 %42
  559. %44 = OpLoad %7 %43
  560. %45 = OpCompositeConstruct %31 %36 %41 %44
  561. %100 = OpCompositeConstruct %32 %16 %45
  562. %46 = OpCompositeConstruct %32 %35 %45
  563. OpStore %34 %46
  564. OpReturn
  565. OpFunctionEnd
  566. )";
  567. const auto env = SPV_ENV_UNIVERSAL_1_3;
  568. const auto consumer = nullptr;
  569. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  570. spvtools::ValidatorOptions validator_options;
  571. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  572. kConsoleMessageConsumer));
  573. TransformationContext transformation_context(
  574. MakeUnique<FactManager>(context.get()), validator_options);
  575. transformation_context.GetFactManager()->MaybeAddFact(
  576. MakeSynonymFact(16, {}, 100, {0}));
  577. transformation_context.GetFactManager()->MaybeAddFact(
  578. MakeSynonymFact(45, {}, 100, {1}));
  579. transformation_context.GetFactManager()->MaybeAddFact(
  580. MakeSynonymFact(27, {}, 101, {0}));
  581. transformation_context.GetFactManager()->MaybeAddFact(
  582. MakeSynonymFact(36, {}, 101, {1}));
  583. transformation_context.GetFactManager()->MaybeAddFact(
  584. MakeSynonymFact(27, {}, 101, {2}));
  585. transformation_context.GetFactManager()->MaybeAddFact(
  586. MakeSynonymFact(22, {}, 102, {0}));
  587. transformation_context.GetFactManager()->MaybeAddFact(
  588. MakeSynonymFact(15, {}, 102, {1}));
  589. // Replace %45 with %100[1] in '%46 = OpCompositeConstruct %32 %35 %45'
  590. auto instruction_descriptor_1 =
  591. MakeInstructionDescriptor(46, spv::Op::OpCompositeConstruct, 0);
  592. auto extract_1 =
  593. TransformationCompositeExtract(instruction_descriptor_1, 201, 100, {1});
  594. ASSERT_TRUE(extract_1.IsApplicable(context.get(), transformation_context));
  595. extract_1.Apply(context.get(), &transformation_context);
  596. auto replacement_1 = TransformationReplaceIdWithSynonym(
  597. MakeIdUseDescriptor(45, instruction_descriptor_1, 1), 201);
  598. ASSERT_TRUE(
  599. replacement_1.IsApplicable(context.get(), transformation_context));
  600. replacement_1.Apply(context.get(), &transformation_context);
  601. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  602. kConsoleMessageConsumer));
  603. // Replace second occurrence of %27 with %101[0] in '%28 =
  604. // OpCompositeConstruct %8 %27 %27'
  605. auto instruction_descriptor_2 =
  606. MakeInstructionDescriptor(28, spv::Op::OpCompositeConstruct, 0);
  607. auto extract_2 =
  608. TransformationCompositeExtract(instruction_descriptor_2, 202, 101, {0});
  609. ASSERT_TRUE(extract_2.IsApplicable(context.get(), transformation_context));
  610. extract_2.Apply(context.get(), &transformation_context);
  611. auto replacement_2 = TransformationReplaceIdWithSynonym(
  612. MakeIdUseDescriptor(27, instruction_descriptor_2, 1), 202);
  613. ASSERT_TRUE(
  614. replacement_2.IsApplicable(context.get(), transformation_context));
  615. replacement_2.Apply(context.get(), &transformation_context);
  616. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  617. kConsoleMessageConsumer));
  618. // Replace %36 with %101[1] in '%45 = OpCompositeConstruct %31 %36 %41 %44'
  619. auto instruction_descriptor_3 =
  620. MakeInstructionDescriptor(45, spv::Op::OpCompositeConstruct, 0);
  621. auto extract_3 =
  622. TransformationCompositeExtract(instruction_descriptor_3, 203, 101, {1});
  623. ASSERT_TRUE(extract_3.IsApplicable(context.get(), transformation_context));
  624. extract_3.Apply(context.get(), &transformation_context);
  625. auto replacement_3 = TransformationReplaceIdWithSynonym(
  626. MakeIdUseDescriptor(36, instruction_descriptor_3, 0), 203);
  627. ASSERT_TRUE(
  628. replacement_3.IsApplicable(context.get(), transformation_context));
  629. replacement_3.Apply(context.get(), &transformation_context);
  630. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  631. kConsoleMessageConsumer));
  632. // Replace first occurrence of %27 with %101[2] in '%28 = OpCompositeConstruct
  633. // %8 %27 %27'
  634. auto instruction_descriptor_4 =
  635. MakeInstructionDescriptor(28, spv::Op::OpCompositeConstruct, 0);
  636. auto extract_4 =
  637. TransformationCompositeExtract(instruction_descriptor_4, 204, 101, {2});
  638. ASSERT_TRUE(extract_4.IsApplicable(context.get(), transformation_context));
  639. extract_4.Apply(context.get(), &transformation_context);
  640. auto replacement_4 = TransformationReplaceIdWithSynonym(
  641. MakeIdUseDescriptor(27, instruction_descriptor_4, 0), 204);
  642. ASSERT_TRUE(
  643. replacement_4.IsApplicable(context.get(), transformation_context));
  644. replacement_4.Apply(context.get(), &transformation_context);
  645. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  646. kConsoleMessageConsumer));
  647. // Replace %22 with %102[0] in 'OpStore %23 %22'
  648. auto instruction_descriptor_5 =
  649. MakeInstructionDescriptor(23, spv::Op::OpStore, 0);
  650. auto extract_5 =
  651. TransformationCompositeExtract(instruction_descriptor_5, 205, 102, {0});
  652. ASSERT_TRUE(extract_5.IsApplicable(context.get(), transformation_context));
  653. extract_5.Apply(context.get(), &transformation_context);
  654. auto replacement_5 = TransformationReplaceIdWithSynonym(
  655. MakeIdUseDescriptor(22, instruction_descriptor_5, 1), 205);
  656. ASSERT_TRUE(
  657. replacement_5.IsApplicable(context.get(), transformation_context));
  658. replacement_5.Apply(context.get(), &transformation_context);
  659. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  660. kConsoleMessageConsumer));
  661. const std::string after_transformation = R"(
  662. OpCapability Shader
  663. %1 = OpExtInstImport "GLSL.std.450"
  664. OpMemoryModel Logical GLSL450
  665. OpEntryPoint Fragment %4 "main"
  666. OpExecutionMode %4 OriginUpperLeft
  667. OpSource ESSL 310
  668. OpName %4 "main"
  669. OpName %9 "Inner"
  670. OpMemberName %9 0 "a"
  671. OpMemberName %9 1 "b"
  672. OpName %11 "i1"
  673. OpName %17 "i2"
  674. OpName %31 "Point"
  675. OpMemberName %31 0 "x"
  676. OpMemberName %31 1 "y"
  677. OpMemberName %31 2 "z"
  678. OpName %32 "Outer"
  679. OpMemberName %32 0 "c"
  680. OpMemberName %32 1 "d"
  681. OpName %34 "o1"
  682. %2 = OpTypeVoid
  683. %3 = OpTypeFunction %2
  684. %6 = OpTypeInt 32 1
  685. %7 = OpTypeFloat 32
  686. %8 = OpTypeVector %7 2
  687. %9 = OpTypeStruct %6 %8
  688. %10 = OpTypePointer Function %9
  689. %12 = OpConstant %6 1
  690. %13 = OpConstant %7 2
  691. %14 = OpConstant %7 3
  692. %15 = OpConstantComposite %8 %13 %14
  693. %16 = OpConstantComposite %9 %12 %15
  694. %18 = OpConstant %6 0
  695. %19 = OpTypePointer Function %6
  696. %24 = OpTypePointer Function %8
  697. %27 = OpConstant %7 4
  698. %31 = OpTypeStruct %7 %7 %7
  699. %32 = OpTypeStruct %9 %31
  700. %33 = OpTypePointer Function %32
  701. %36 = OpConstant %7 10
  702. %37 = OpTypeInt 32 0
  703. %38 = OpConstant %37 0
  704. %39 = OpTypePointer Function %7
  705. %42 = OpConstant %37 1
  706. %4 = OpFunction %2 None %3
  707. %5 = OpLabel
  708. %11 = OpVariable %10 Function
  709. %17 = OpVariable %10 Function
  710. %34 = OpVariable %33 Function
  711. %101 = OpCompositeConstruct %31 %27 %36 %27
  712. OpStore %11 %16
  713. %20 = OpAccessChain %19 %11 %18
  714. %21 = OpLoad %6 %20
  715. %22 = OpIAdd %6 %21 %12
  716. %102 = OpCompositeConstruct %9 %22 %15
  717. %23 = OpAccessChain %19 %17 %18
  718. %205 = OpCompositeExtract %6 %102 0
  719. OpStore %23 %205
  720. %25 = OpAccessChain %24 %17 %12
  721. %26 = OpLoad %8 %25
  722. %202 = OpCompositeExtract %7 %101 0
  723. %204 = OpCompositeExtract %7 %101 2
  724. %28 = OpCompositeConstruct %8 %204 %202
  725. %29 = OpFAdd %8 %26 %28
  726. %30 = OpAccessChain %24 %17 %12
  727. OpStore %30 %29
  728. %35 = OpLoad %9 %11
  729. %40 = OpAccessChain %39 %11 %12 %38
  730. %41 = OpLoad %7 %40
  731. %43 = OpAccessChain %39 %11 %12 %42
  732. %44 = OpLoad %7 %43
  733. %203 = OpCompositeExtract %7 %101 1
  734. %45 = OpCompositeConstruct %31 %203 %41 %44
  735. %100 = OpCompositeConstruct %32 %16 %45
  736. %201 = OpCompositeExtract %31 %100 1
  737. %46 = OpCompositeConstruct %32 %35 %201
  738. OpStore %34 %46
  739. OpReturn
  740. OpFunctionEnd
  741. )";
  742. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  743. }
  744. TEST(DataSynonymTransformationTest, VectorCompositeSynonyms) {
  745. std::string shader = R"(
  746. OpCapability Shader
  747. %1 = OpExtInstImport "GLSL.std.450"
  748. OpMemoryModel Logical GLSL450
  749. OpEntryPoint Fragment %4 "main"
  750. OpExecutionMode %4 OriginUpperLeft
  751. OpSource ESSL 310
  752. OpName %4 "main"
  753. OpName %8 "f"
  754. OpName %12 "v2"
  755. OpName %18 "v3"
  756. OpName %23 "v4"
  757. OpName %32 "b"
  758. OpName %36 "bv2"
  759. OpName %41 "bv3"
  760. OpName %50 "bv4"
  761. %2 = OpTypeVoid
  762. %3 = OpTypeFunction %2
  763. %6 = OpTypeFloat 32
  764. %7 = OpTypePointer Function %6
  765. %9 = OpConstant %6 42
  766. %10 = OpTypeVector %6 2
  767. %11 = OpTypePointer Function %10
  768. %16 = OpTypeVector %6 3
  769. %17 = OpTypePointer Function %16
  770. %21 = OpTypeVector %6 4
  771. %22 = OpTypePointer Function %21
  772. %30 = OpTypeBool
  773. %31 = OpTypePointer Function %30
  774. %33 = OpConstantFalse %30
  775. %34 = OpTypeVector %30 2
  776. %35 = OpTypePointer Function %34
  777. %37 = OpConstantTrue %30
  778. %38 = OpConstantComposite %34 %37 %37
  779. %39 = OpTypeVector %30 3
  780. %40 = OpTypePointer Function %39
  781. %48 = OpTypeVector %30 4
  782. %49 = OpTypePointer Function %48
  783. %51 = OpTypeInt 32 0
  784. %52 = OpConstant %51 2
  785. %55 = OpConstant %6 0
  786. %57 = OpConstant %51 1
  787. %4 = OpFunction %2 None %3
  788. %5 = OpLabel
  789. %8 = OpVariable %7 Function
  790. %12 = OpVariable %11 Function
  791. %18 = OpVariable %17 Function
  792. %23 = OpVariable %22 Function
  793. %32 = OpVariable %31 Function
  794. %36 = OpVariable %35 Function
  795. %41 = OpVariable %40 Function
  796. %50 = OpVariable %49 Function
  797. OpStore %8 %9
  798. %13 = OpLoad %6 %8
  799. %14 = OpLoad %6 %8
  800. %15 = OpCompositeConstruct %10 %13 %14
  801. OpStore %12 %15
  802. %19 = OpLoad %10 %12
  803. %20 = OpVectorShuffle %16 %19 %19 0 0 1
  804. OpStore %18 %20
  805. %24 = OpLoad %16 %18
  806. %25 = OpLoad %6 %8
  807. %26 = OpCompositeExtract %6 %24 0
  808. %27 = OpCompositeExtract %6 %24 1
  809. %28 = OpCompositeExtract %6 %24 2
  810. %29 = OpCompositeConstruct %21 %26 %27 %28 %25
  811. OpStore %23 %29
  812. OpStore %32 %33
  813. OpStore %36 %38
  814. %42 = OpLoad %30 %32
  815. %43 = OpLoad %34 %36
  816. %44 = OpVectorShuffle %34 %43 %43 0 0
  817. %45 = OpCompositeExtract %30 %44 0
  818. %46 = OpCompositeExtract %30 %44 1
  819. %47 = OpCompositeConstruct %39 %42 %45 %46
  820. OpStore %41 %47
  821. %53 = OpAccessChain %7 %23 %52
  822. %54 = OpLoad %6 %53
  823. %100 = OpCompositeConstruct %21 %20 %54
  824. %101 = OpCompositeConstruct %21 %15 %19
  825. %102 = OpCompositeConstruct %16 %27 %15
  826. %103 = OpCompositeConstruct %48 %33 %47
  827. %104 = OpCompositeConstruct %34 %42 %45
  828. %105 = OpCompositeConstruct %39 %38 %46
  829. %86 = OpCopyObject %30 %33
  830. %56 = OpFOrdNotEqual %30 %54 %55
  831. %80 = OpCopyObject %16 %20
  832. %58 = OpAccessChain %7 %18 %57
  833. %59 = OpLoad %6 %58
  834. %60 = OpFOrdNotEqual %30 %59 %55
  835. %61 = OpLoad %34 %36
  836. %62 = OpLogicalAnd %30 %45 %46
  837. %63 = OpLogicalOr %30 %45 %46
  838. %64 = OpCompositeConstruct %48 %56 %60 %62 %63
  839. OpStore %12 %15
  840. %81 = OpVectorShuffle %16 %19 %19 0 0 1
  841. %82 = OpCompositeConstruct %21 %26 %27 %28 %25
  842. %83 = OpCopyObject %10 %15
  843. %84 = OpCopyObject %39 %47
  844. OpStore %50 %64
  845. %85 = OpCopyObject %30 %42
  846. OpStore %36 %38
  847. OpReturn
  848. OpFunctionEnd
  849. )";
  850. const auto env = SPV_ENV_UNIVERSAL_1_3;
  851. const auto consumer = nullptr;
  852. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  853. spvtools::ValidatorOptions validator_options;
  854. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  855. kConsoleMessageConsumer));
  856. TransformationContext transformation_context(
  857. MakeUnique<FactManager>(context.get()), validator_options);
  858. transformation_context.GetFactManager()->MaybeAddFact(
  859. MakeSynonymFact(20, {0}, 100, {0}));
  860. transformation_context.GetFactManager()->MaybeAddFact(
  861. MakeSynonymFact(20, {1}, 100, {1}));
  862. transformation_context.GetFactManager()->MaybeAddFact(
  863. MakeSynonymFact(20, {2}, 100, {2}));
  864. transformation_context.GetFactManager()->MaybeAddFact(
  865. MakeSynonymFact(54, {}, 100, {3}));
  866. transformation_context.GetFactManager()->MaybeAddFact(
  867. MakeSynonymFact(15, {0}, 101, {0}));
  868. transformation_context.GetFactManager()->MaybeAddFact(
  869. MakeSynonymFact(15, {1}, 101, {1}));
  870. transformation_context.GetFactManager()->MaybeAddFact(
  871. MakeSynonymFact(19, {0}, 101, {2}));
  872. transformation_context.GetFactManager()->MaybeAddFact(
  873. MakeSynonymFact(19, {1}, 101, {3}));
  874. transformation_context.GetFactManager()->MaybeAddFact(
  875. MakeSynonymFact(27, {}, 102, {0}));
  876. transformation_context.GetFactManager()->MaybeAddFact(
  877. MakeSynonymFact(15, {0}, 102, {1}));
  878. transformation_context.GetFactManager()->MaybeAddFact(
  879. MakeSynonymFact(15, {1}, 102, {2}));
  880. transformation_context.GetFactManager()->MaybeAddFact(
  881. MakeSynonymFact(33, {}, 103, {0}));
  882. transformation_context.GetFactManager()->MaybeAddFact(
  883. MakeSynonymFact(47, {0}, 103, {1}));
  884. transformation_context.GetFactManager()->MaybeAddFact(
  885. MakeSynonymFact(47, {1}, 103, {2}));
  886. transformation_context.GetFactManager()->MaybeAddFact(
  887. MakeSynonymFact(47, {2}, 103, {3}));
  888. transformation_context.GetFactManager()->MaybeAddFact(
  889. MakeSynonymFact(42, {}, 104, {0}));
  890. transformation_context.GetFactManager()->MaybeAddFact(
  891. MakeSynonymFact(45, {}, 104, {1}));
  892. transformation_context.GetFactManager()->MaybeAddFact(
  893. MakeSynonymFact(38, {0}, 105, {0}));
  894. transformation_context.GetFactManager()->MaybeAddFact(
  895. MakeSynonymFact(38, {1}, 105, {1}));
  896. transformation_context.GetFactManager()->MaybeAddFact(
  897. MakeSynonymFact(46, {}, 105, {2}));
  898. // Replace %20 with %100[0:2] in '%80 = OpCopyObject %16 %20'
  899. auto instruction_descriptor_1 =
  900. MakeInstructionDescriptor(80, spv::Op::OpCopyObject, 0);
  901. auto shuffle_1 = TransformationVectorShuffle(instruction_descriptor_1, 200,
  902. 100, 100, {0, 1, 2});
  903. ASSERT_TRUE(shuffle_1.IsApplicable(context.get(), transformation_context));
  904. shuffle_1.Apply(context.get(), &transformation_context);
  905. transformation_context.GetFactManager()->ComputeClosureOfFacts(100);
  906. auto replacement_1 = TransformationReplaceIdWithSynonym(
  907. MakeIdUseDescriptor(20, instruction_descriptor_1, 0), 200);
  908. ASSERT_TRUE(
  909. replacement_1.IsApplicable(context.get(), transformation_context));
  910. replacement_1.Apply(context.get(), &transformation_context);
  911. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  912. kConsoleMessageConsumer));
  913. // Replace %54 with %100[3] in '%56 = OpFOrdNotEqual %30 %54 %55'
  914. auto instruction_descriptor_2 =
  915. MakeInstructionDescriptor(56, spv::Op::OpFOrdNotEqual, 0);
  916. auto extract_2 =
  917. TransformationCompositeExtract(instruction_descriptor_2, 201, 100, {3});
  918. ASSERT_TRUE(extract_2.IsApplicable(context.get(), transformation_context));
  919. extract_2.Apply(context.get(), &transformation_context);
  920. auto replacement_2 = TransformationReplaceIdWithSynonym(
  921. MakeIdUseDescriptor(54, instruction_descriptor_2, 0), 201);
  922. ASSERT_TRUE(
  923. replacement_2.IsApplicable(context.get(), transformation_context));
  924. replacement_2.Apply(context.get(), &transformation_context);
  925. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  926. kConsoleMessageConsumer));
  927. // Replace %15 with %101[0:1] in 'OpStore %12 %15'
  928. auto instruction_descriptor_3 =
  929. MakeInstructionDescriptor(64, spv::Op::OpStore, 0);
  930. auto shuffle_3 = TransformationVectorShuffle(instruction_descriptor_3, 202,
  931. 101, 101, {0, 1});
  932. ASSERT_TRUE(shuffle_3.IsApplicable(context.get(), transformation_context));
  933. shuffle_3.Apply(context.get(), &transformation_context);
  934. transformation_context.GetFactManager()->ComputeClosureOfFacts(100);
  935. auto replacement_3 = TransformationReplaceIdWithSynonym(
  936. MakeIdUseDescriptor(15, instruction_descriptor_3, 1), 202);
  937. ASSERT_TRUE(
  938. replacement_3.IsApplicable(context.get(), transformation_context));
  939. replacement_3.Apply(context.get(), &transformation_context);
  940. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  941. kConsoleMessageConsumer));
  942. // Replace %19 with %101[2:3] in '%81 = OpVectorShuffle %16 %19 %19 0 0 1'
  943. auto instruction_descriptor_4 =
  944. MakeInstructionDescriptor(81, spv::Op::OpVectorShuffle, 0);
  945. auto shuffle_4 = TransformationVectorShuffle(instruction_descriptor_4, 203,
  946. 101, 101, {2, 3});
  947. ASSERT_TRUE(shuffle_4.IsApplicable(context.get(), transformation_context));
  948. shuffle_4.Apply(context.get(), &transformation_context);
  949. transformation_context.GetFactManager()->ComputeClosureOfFacts(100);
  950. auto replacement_4 = TransformationReplaceIdWithSynonym(
  951. MakeIdUseDescriptor(19, instruction_descriptor_4, 0), 203);
  952. ASSERT_TRUE(
  953. replacement_4.IsApplicable(context.get(), transformation_context));
  954. replacement_4.Apply(context.get(), &transformation_context);
  955. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  956. kConsoleMessageConsumer));
  957. // Replace %27 with %102[0] in '%82 = OpCompositeConstruct %21 %26 %27 %28
  958. // %25'
  959. auto instruction_descriptor_5 =
  960. MakeInstructionDescriptor(82, spv::Op::OpCompositeConstruct, 0);
  961. auto extract_5 =
  962. TransformationCompositeExtract(instruction_descriptor_5, 204, 102, {0});
  963. ASSERT_TRUE(extract_5.IsApplicable(context.get(), transformation_context));
  964. extract_5.Apply(context.get(), &transformation_context);
  965. auto replacement_5 = TransformationReplaceIdWithSynonym(
  966. MakeIdUseDescriptor(27, instruction_descriptor_5, 1), 204);
  967. ASSERT_TRUE(
  968. replacement_5.IsApplicable(context.get(), transformation_context));
  969. replacement_5.Apply(context.get(), &transformation_context);
  970. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  971. kConsoleMessageConsumer));
  972. // Replace %15 with %102[1:2] in '%83 = OpCopyObject %10 %15'
  973. auto instruction_descriptor_6 =
  974. MakeInstructionDescriptor(83, spv::Op::OpCopyObject, 0);
  975. auto shuffle_6 = TransformationVectorShuffle(instruction_descriptor_6, 205,
  976. 102, 102, {1, 2});
  977. ASSERT_TRUE(shuffle_6.IsApplicable(context.get(), transformation_context));
  978. shuffle_6.Apply(context.get(), &transformation_context);
  979. transformation_context.GetFactManager()->ComputeClosureOfFacts(100);
  980. auto replacement_6 = TransformationReplaceIdWithSynonym(
  981. MakeIdUseDescriptor(15, instruction_descriptor_6, 0), 205);
  982. ASSERT_TRUE(
  983. replacement_6.IsApplicable(context.get(), transformation_context));
  984. replacement_6.Apply(context.get(), &transformation_context);
  985. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  986. kConsoleMessageConsumer));
  987. // Replace %33 with %103[0] in '%86 = OpCopyObject %30 %33'
  988. auto instruction_descriptor_7 =
  989. MakeInstructionDescriptor(86, spv::Op::OpCopyObject, 0);
  990. auto extract_7 =
  991. TransformationCompositeExtract(instruction_descriptor_7, 206, 103, {0});
  992. ASSERT_TRUE(extract_7.IsApplicable(context.get(), transformation_context));
  993. extract_7.Apply(context.get(), &transformation_context);
  994. auto replacement_7 = TransformationReplaceIdWithSynonym(
  995. MakeIdUseDescriptor(33, instruction_descriptor_7, 0), 206);
  996. ASSERT_TRUE(
  997. replacement_7.IsApplicable(context.get(), transformation_context));
  998. replacement_7.Apply(context.get(), &transformation_context);
  999. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1000. kConsoleMessageConsumer));
  1001. // Replace %47 with %103[1:3] in '%84 = OpCopyObject %39 %47'
  1002. auto instruction_descriptor_8 =
  1003. MakeInstructionDescriptor(84, spv::Op::OpCopyObject, 0);
  1004. auto shuffle_8 = TransformationVectorShuffle(instruction_descriptor_8, 207,
  1005. 103, 103, {1, 2, 3});
  1006. ASSERT_TRUE(shuffle_8.IsApplicable(context.get(), transformation_context));
  1007. shuffle_8.Apply(context.get(), &transformation_context);
  1008. transformation_context.GetFactManager()->ComputeClosureOfFacts(100);
  1009. auto replacement_8 = TransformationReplaceIdWithSynonym(
  1010. MakeIdUseDescriptor(47, instruction_descriptor_8, 0), 207);
  1011. ASSERT_TRUE(
  1012. replacement_8.IsApplicable(context.get(), transformation_context));
  1013. replacement_8.Apply(context.get(), &transformation_context);
  1014. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1015. kConsoleMessageConsumer));
  1016. // Replace %42 with %104[0] in '%85 = OpCopyObject %30 %42'
  1017. auto instruction_descriptor_9 =
  1018. MakeInstructionDescriptor(85, spv::Op::OpCopyObject, 0);
  1019. auto extract_9 =
  1020. TransformationCompositeExtract(instruction_descriptor_9, 208, 104, {0});
  1021. ASSERT_TRUE(extract_9.IsApplicable(context.get(), transformation_context));
  1022. extract_9.Apply(context.get(), &transformation_context);
  1023. auto replacement_9 = TransformationReplaceIdWithSynonym(
  1024. MakeIdUseDescriptor(42, instruction_descriptor_9, 0), 208);
  1025. ASSERT_TRUE(
  1026. replacement_9.IsApplicable(context.get(), transformation_context));
  1027. replacement_9.Apply(context.get(), &transformation_context);
  1028. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1029. kConsoleMessageConsumer));
  1030. // Replace %45 with %104[1] in '%63 = OpLogicalOr %30 %45 %46'
  1031. auto instruction_descriptor_10 =
  1032. MakeInstructionDescriptor(63, spv::Op::OpLogicalOr, 0);
  1033. auto extract_10 =
  1034. TransformationCompositeExtract(instruction_descriptor_10, 209, 104, {1});
  1035. ASSERT_TRUE(extract_10.IsApplicable(context.get(), transformation_context));
  1036. extract_10.Apply(context.get(), &transformation_context);
  1037. auto replacement_10 = TransformationReplaceIdWithSynonym(
  1038. MakeIdUseDescriptor(45, instruction_descriptor_10, 0), 209);
  1039. ASSERT_TRUE(
  1040. replacement_10.IsApplicable(context.get(), transformation_context));
  1041. replacement_10.Apply(context.get(), &transformation_context);
  1042. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1043. kConsoleMessageConsumer));
  1044. // Replace %38 with %105[0:1] in 'OpStore %36 %38'
  1045. auto instruction_descriptor_11 =
  1046. MakeInstructionDescriptor(85, spv::Op::OpStore, 0);
  1047. auto shuffle_11 = TransformationVectorShuffle(instruction_descriptor_11, 210,
  1048. 105, 105, {0, 1});
  1049. ASSERT_TRUE(shuffle_11.IsApplicable(context.get(), transformation_context));
  1050. shuffle_11.Apply(context.get(), &transformation_context);
  1051. transformation_context.GetFactManager()->ComputeClosureOfFacts(100);
  1052. auto replacement_11 = TransformationReplaceIdWithSynonym(
  1053. MakeIdUseDescriptor(38, instruction_descriptor_11, 1), 210);
  1054. ASSERT_TRUE(
  1055. replacement_11.IsApplicable(context.get(), transformation_context));
  1056. replacement_11.Apply(context.get(), &transformation_context);
  1057. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1058. kConsoleMessageConsumer));
  1059. // Replace %46 with %105[2] in '%62 = OpLogicalAnd %30 %45 %46'
  1060. auto instruction_descriptor_12 =
  1061. MakeInstructionDescriptor(62, spv::Op::OpLogicalAnd, 0);
  1062. auto extract_12 =
  1063. TransformationCompositeExtract(instruction_descriptor_12, 211, 105, {2});
  1064. ASSERT_TRUE(extract_12.IsApplicable(context.get(), transformation_context));
  1065. extract_12.Apply(context.get(), &transformation_context);
  1066. auto replacement_12 = TransformationReplaceIdWithSynonym(
  1067. MakeIdUseDescriptor(46, instruction_descriptor_12, 1), 211);
  1068. ASSERT_TRUE(
  1069. replacement_12.IsApplicable(context.get(), transformation_context));
  1070. replacement_12.Apply(context.get(), &transformation_context);
  1071. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1072. kConsoleMessageConsumer));
  1073. const std::string after_transformation = R"(
  1074. OpCapability Shader
  1075. %1 = OpExtInstImport "GLSL.std.450"
  1076. OpMemoryModel Logical GLSL450
  1077. OpEntryPoint Fragment %4 "main"
  1078. OpExecutionMode %4 OriginUpperLeft
  1079. OpSource ESSL 310
  1080. OpName %4 "main"
  1081. OpName %8 "f"
  1082. OpName %12 "v2"
  1083. OpName %18 "v3"
  1084. OpName %23 "v4"
  1085. OpName %32 "b"
  1086. OpName %36 "bv2"
  1087. OpName %41 "bv3"
  1088. OpName %50 "bv4"
  1089. %2 = OpTypeVoid
  1090. %3 = OpTypeFunction %2
  1091. %6 = OpTypeFloat 32
  1092. %7 = OpTypePointer Function %6
  1093. %9 = OpConstant %6 42
  1094. %10 = OpTypeVector %6 2
  1095. %11 = OpTypePointer Function %10
  1096. %16 = OpTypeVector %6 3
  1097. %17 = OpTypePointer Function %16
  1098. %21 = OpTypeVector %6 4
  1099. %22 = OpTypePointer Function %21
  1100. %30 = OpTypeBool
  1101. %31 = OpTypePointer Function %30
  1102. %33 = OpConstantFalse %30
  1103. %34 = OpTypeVector %30 2
  1104. %35 = OpTypePointer Function %34
  1105. %37 = OpConstantTrue %30
  1106. %38 = OpConstantComposite %34 %37 %37
  1107. %39 = OpTypeVector %30 3
  1108. %40 = OpTypePointer Function %39
  1109. %48 = OpTypeVector %30 4
  1110. %49 = OpTypePointer Function %48
  1111. %51 = OpTypeInt 32 0
  1112. %52 = OpConstant %51 2
  1113. %55 = OpConstant %6 0
  1114. %57 = OpConstant %51 1
  1115. %4 = OpFunction %2 None %3
  1116. %5 = OpLabel
  1117. %8 = OpVariable %7 Function
  1118. %12 = OpVariable %11 Function
  1119. %18 = OpVariable %17 Function
  1120. %23 = OpVariable %22 Function
  1121. %32 = OpVariable %31 Function
  1122. %36 = OpVariable %35 Function
  1123. %41 = OpVariable %40 Function
  1124. %50 = OpVariable %49 Function
  1125. OpStore %8 %9
  1126. %13 = OpLoad %6 %8
  1127. %14 = OpLoad %6 %8
  1128. %15 = OpCompositeConstruct %10 %13 %14
  1129. OpStore %12 %15
  1130. %19 = OpLoad %10 %12
  1131. %20 = OpVectorShuffle %16 %19 %19 0 0 1
  1132. OpStore %18 %20
  1133. %24 = OpLoad %16 %18
  1134. %25 = OpLoad %6 %8
  1135. %26 = OpCompositeExtract %6 %24 0
  1136. %27 = OpCompositeExtract %6 %24 1
  1137. %28 = OpCompositeExtract %6 %24 2
  1138. %29 = OpCompositeConstruct %21 %26 %27 %28 %25
  1139. OpStore %23 %29
  1140. OpStore %32 %33
  1141. OpStore %36 %38
  1142. %42 = OpLoad %30 %32
  1143. %43 = OpLoad %34 %36
  1144. %44 = OpVectorShuffle %34 %43 %43 0 0
  1145. %45 = OpCompositeExtract %30 %44 0
  1146. %46 = OpCompositeExtract %30 %44 1
  1147. %47 = OpCompositeConstruct %39 %42 %45 %46
  1148. OpStore %41 %47
  1149. %53 = OpAccessChain %7 %23 %52
  1150. %54 = OpLoad %6 %53
  1151. %100 = OpCompositeConstruct %21 %20 %54
  1152. %101 = OpCompositeConstruct %21 %15 %19
  1153. %102 = OpCompositeConstruct %16 %27 %15
  1154. %103 = OpCompositeConstruct %48 %33 %47
  1155. %104 = OpCompositeConstruct %34 %42 %45
  1156. %105 = OpCompositeConstruct %39 %38 %46
  1157. %206 = OpCompositeExtract %30 %103 0
  1158. %86 = OpCopyObject %30 %206
  1159. %201 = OpCompositeExtract %6 %100 3
  1160. %56 = OpFOrdNotEqual %30 %201 %55
  1161. %200 = OpVectorShuffle %16 %100 %100 0 1 2
  1162. %80 = OpCopyObject %16 %200
  1163. %58 = OpAccessChain %7 %18 %57
  1164. %59 = OpLoad %6 %58
  1165. %60 = OpFOrdNotEqual %30 %59 %55
  1166. %61 = OpLoad %34 %36
  1167. %211 = OpCompositeExtract %30 %105 2
  1168. %62 = OpLogicalAnd %30 %45 %211
  1169. %209 = OpCompositeExtract %30 %104 1
  1170. %63 = OpLogicalOr %30 %209 %46
  1171. %64 = OpCompositeConstruct %48 %56 %60 %62 %63
  1172. %202 = OpVectorShuffle %10 %101 %101 0 1
  1173. OpStore %12 %202
  1174. %203 = OpVectorShuffle %10 %101 %101 2 3
  1175. %81 = OpVectorShuffle %16 %203 %19 0 0 1
  1176. %204 = OpCompositeExtract %6 %102 0
  1177. %82 = OpCompositeConstruct %21 %26 %204 %28 %25
  1178. %205 = OpVectorShuffle %10 %102 %102 1 2
  1179. %83 = OpCopyObject %10 %205
  1180. %207 = OpVectorShuffle %39 %103 %103 1 2 3
  1181. %84 = OpCopyObject %39 %207
  1182. OpStore %50 %64
  1183. %208 = OpCompositeExtract %30 %104 0
  1184. %85 = OpCopyObject %30 %208
  1185. %210 = OpVectorShuffle %34 %105 %105 0 1
  1186. OpStore %36 %210
  1187. OpReturn
  1188. OpFunctionEnd
  1189. )";
  1190. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  1191. }
  1192. } // namespace
  1193. } // namespace fuzz
  1194. } // namespace spvtools