transformation_composite_construct_test.cpp 72 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741
  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/transformation_composite_construct.h"
  15. #include "gtest/gtest.h"
  16. #include "source/fuzz/data_descriptor.h"
  17. #include "source/fuzz/fuzzer_util.h"
  18. #include "source/fuzz/instruction_descriptor.h"
  19. #include "test/fuzz/fuzz_test_util.h"
  20. namespace spvtools {
  21. namespace fuzz {
  22. namespace {
  23. TEST(TransformationCompositeConstructTest, ConstructArrays) {
  24. std::string shader = R"(
  25. OpCapability Shader
  26. %1 = OpExtInstImport "GLSL.std.450"
  27. OpMemoryModel Logical GLSL450
  28. OpEntryPoint Fragment %4 "main"
  29. OpExecutionMode %4 OriginUpperLeft
  30. OpSource ESSL 310
  31. OpName %4 "main"
  32. OpName %11 "floats"
  33. OpName %22 "x"
  34. OpName %39 "vecs"
  35. OpName %49 "bools"
  36. OpName %60 "many_uvec3s"
  37. OpDecorate %60 RelaxedPrecision
  38. %2 = OpTypeVoid
  39. %3 = OpTypeFunction %2
  40. %6 = OpTypeFloat 32
  41. %7 = OpTypeInt 32 0
  42. %8 = OpConstant %7 2
  43. %9 = OpTypeArray %6 %8
  44. %10 = OpTypePointer Function %9
  45. %12 = OpTypeInt 32 1
  46. %13 = OpConstant %12 0
  47. %14 = OpConstant %6 1
  48. %15 = OpTypePointer Function %6
  49. %17 = OpConstant %12 1
  50. %18 = OpConstant %6 2
  51. %20 = OpTypeVector %6 2
  52. %21 = OpTypePointer Function %20
  53. %32 = OpTypeBool
  54. %36 = OpConstant %7 3
  55. %37 = OpTypeArray %20 %36
  56. %38 = OpTypePointer Private %37
  57. %39 = OpVariable %38 Private
  58. %40 = OpConstant %6 3
  59. %41 = OpConstantComposite %20 %40 %40
  60. %42 = OpTypePointer Private %20
  61. %44 = OpConstant %12 2
  62. %47 = OpTypeArray %32 %36
  63. %48 = OpTypePointer Function %47
  64. %50 = OpConstantTrue %32
  65. %51 = OpTypePointer Function %32
  66. %56 = OpTypeVector %7 3
  67. %57 = OpTypeArray %56 %8
  68. %58 = OpTypeArray %57 %8
  69. %59 = OpTypePointer Function %58
  70. %61 = OpConstant %7 4
  71. %62 = OpConstantComposite %56 %61 %61 %61
  72. %63 = OpTypePointer Function %56
  73. %65 = OpConstant %7 5
  74. %66 = OpConstantComposite %56 %65 %65 %65
  75. %67 = OpConstant %7 6
  76. %68 = OpConstantComposite %56 %67 %67 %67
  77. %69 = OpConstantComposite %57 %66 %68
  78. %100 = OpUndef %57
  79. %70 = OpTypePointer Function %57
  80. %4 = OpFunction %2 None %3
  81. %5 = OpLabel
  82. %11 = OpVariable %10 Function
  83. %22 = OpVariable %21 Function
  84. %49 = OpVariable %48 Function
  85. %60 = OpVariable %59 Function
  86. %16 = OpAccessChain %15 %11 %13
  87. OpStore %16 %14
  88. %19 = OpAccessChain %15 %11 %17
  89. OpStore %19 %18
  90. %23 = OpAccessChain %15 %11 %13
  91. %24 = OpLoad %6 %23
  92. %25 = OpAccessChain %15 %11 %17
  93. %26 = OpLoad %6 %25
  94. %27 = OpCompositeConstruct %20 %24 %26
  95. OpStore %22 %27
  96. %28 = OpAccessChain %15 %11 %13
  97. %29 = OpLoad %6 %28
  98. %30 = OpAccessChain %15 %11 %17
  99. %31 = OpLoad %6 %30
  100. %33 = OpFOrdGreaterThan %32 %29 %31
  101. OpSelectionMerge %35 None
  102. OpBranchConditional %33 %34 %35
  103. %34 = OpLabel
  104. %43 = OpAccessChain %42 %39 %17
  105. OpStore %43 %41
  106. %45 = OpLoad %20 %22
  107. %46 = OpAccessChain %42 %39 %44
  108. OpStore %46 %45
  109. OpBranch %35
  110. %35 = OpLabel
  111. %52 = OpAccessChain %51 %49 %13
  112. OpStore %52 %50
  113. %53 = OpAccessChain %51 %49 %13
  114. %54 = OpLoad %32 %53
  115. %55 = OpAccessChain %51 %49 %17
  116. OpStore %55 %54
  117. %64 = OpAccessChain %63 %60 %13 %13
  118. OpStore %64 %62
  119. %71 = OpAccessChain %70 %60 %17
  120. OpStore %71 %69
  121. OpReturn
  122. OpFunctionEnd
  123. )";
  124. const auto env = SPV_ENV_UNIVERSAL_1_3;
  125. const auto consumer = nullptr;
  126. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  127. spvtools::ValidatorOptions validator_options;
  128. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  129. kConsoleMessageConsumer));
  130. TransformationContext transformation_context(
  131. MakeUnique<FactManager>(context.get()), validator_options);
  132. // Make a vec2[3]
  133. TransformationCompositeConstruct make_vec2_array_length_3(
  134. 37, {41, 45, 27},
  135. MakeInstructionDescriptor(46, spv::Op::OpAccessChain, 0), 200);
  136. // Bad: there are too many components
  137. TransformationCompositeConstruct make_vec2_array_length_3_bad(
  138. 37, {41, 45, 27, 27},
  139. MakeInstructionDescriptor(46, spv::Op::OpAccessChain, 0), 200);
  140. // The first component does not correspond to an instruction with a result
  141. // type so this check should return false.
  142. TransformationCompositeConstruct make_vec2_array_length_3_nores(
  143. 37, {2, 45, 27}, MakeInstructionDescriptor(46, spv::Op::OpAccessChain, 0),
  144. 200);
  145. ASSERT_TRUE(make_vec2_array_length_3.IsApplicable(context.get(),
  146. transformation_context));
  147. ASSERT_FALSE(make_vec2_array_length_3_bad.IsApplicable(
  148. context.get(), transformation_context));
  149. ASSERT_FALSE(make_vec2_array_length_3_nores.IsApplicable(
  150. context.get(), transformation_context));
  151. ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(200));
  152. ASSERT_EQ(nullptr, context->get_instr_block(200));
  153. uint32_t num_uses_of_41_before = context->get_def_use_mgr()->NumUses(41);
  154. uint32_t num_uses_of_45_before = context->get_def_use_mgr()->NumUses(45);
  155. uint32_t num_uses_of_27_before = context->get_def_use_mgr()->NumUses(27);
  156. ApplyAndCheckFreshIds(make_vec2_array_length_3, context.get(),
  157. &transformation_context);
  158. ASSERT_EQ(spv::Op::OpCompositeConstruct,
  159. context->get_def_use_mgr()->GetDef(200)->opcode());
  160. ASSERT_EQ(34, context->get_instr_block(200)->id());
  161. ASSERT_EQ(num_uses_of_41_before + 1, context->get_def_use_mgr()->NumUses(41));
  162. ASSERT_EQ(num_uses_of_45_before + 1, context->get_def_use_mgr()->NumUses(45));
  163. ASSERT_EQ(num_uses_of_27_before + 1, context->get_def_use_mgr()->NumUses(27));
  164. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  165. kConsoleMessageConsumer));
  166. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  167. MakeDataDescriptor(41, {}), MakeDataDescriptor(200, {0})));
  168. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  169. MakeDataDescriptor(45, {}), MakeDataDescriptor(200, {1})));
  170. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  171. MakeDataDescriptor(27, {}), MakeDataDescriptor(200, {2})));
  172. // Make a float[2]
  173. TransformationCompositeConstruct make_float_array_length_2(
  174. 9, {24, 40}, MakeInstructionDescriptor(71, spv::Op::OpStore, 0), 201);
  175. // Bad: %41 does not have type float
  176. TransformationCompositeConstruct make_float_array_length_2_bad(
  177. 9, {41, 40}, MakeInstructionDescriptor(71, spv::Op::OpStore, 0), 201);
  178. ASSERT_TRUE(make_float_array_length_2.IsApplicable(context.get(),
  179. transformation_context));
  180. ASSERT_FALSE(make_float_array_length_2_bad.IsApplicable(
  181. context.get(), transformation_context));
  182. ApplyAndCheckFreshIds(make_float_array_length_2, context.get(),
  183. &transformation_context);
  184. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  185. kConsoleMessageConsumer));
  186. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  187. MakeDataDescriptor(24, {}), MakeDataDescriptor(201, {0})));
  188. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  189. MakeDataDescriptor(40, {}), MakeDataDescriptor(201, {1})));
  190. // Make a bool[3]
  191. TransformationCompositeConstruct make_bool_array_length_3(
  192. 47, {33, 50, 50},
  193. MakeInstructionDescriptor(33, spv::Op::OpSelectionMerge, 0), 202);
  194. // Bad: %54 is not available at the desired program point.
  195. TransformationCompositeConstruct make_bool_array_length_3_bad(
  196. 47, {33, 54, 50},
  197. MakeInstructionDescriptor(33, spv::Op::OpSelectionMerge, 0), 202);
  198. ASSERT_TRUE(make_bool_array_length_3.IsApplicable(context.get(),
  199. transformation_context));
  200. ASSERT_FALSE(make_bool_array_length_3_bad.IsApplicable(
  201. context.get(), transformation_context));
  202. ApplyAndCheckFreshIds(make_bool_array_length_3, context.get(),
  203. &transformation_context);
  204. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  205. kConsoleMessageConsumer));
  206. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  207. MakeDataDescriptor(33, {}), MakeDataDescriptor(202, {0})));
  208. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  209. MakeDataDescriptor(50, {}), MakeDataDescriptor(202, {1})));
  210. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  211. MakeDataDescriptor(50, {}), MakeDataDescriptor(202, {2})));
  212. // make a uvec3[2][2]
  213. TransformationCompositeConstruct make_uvec3_array_length_2_2(
  214. 58, {69, 100}, MakeInstructionDescriptor(64, spv::Op::OpStore, 0), 203);
  215. // Bad: Skip count 100 is too large.
  216. TransformationCompositeConstruct make_uvec3_array_length_2_2_bad(
  217. 58, {33, 54}, MakeInstructionDescriptor(64, spv::Op::OpStore, 100), 203);
  218. ASSERT_TRUE(make_uvec3_array_length_2_2.IsApplicable(context.get(),
  219. transformation_context));
  220. ASSERT_FALSE(make_uvec3_array_length_2_2_bad.IsApplicable(
  221. context.get(), transformation_context));
  222. ApplyAndCheckFreshIds(make_uvec3_array_length_2_2, context.get(),
  223. &transformation_context);
  224. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  225. kConsoleMessageConsumer));
  226. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  227. MakeDataDescriptor(69, {}), MakeDataDescriptor(203, {0})));
  228. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  229. MakeDataDescriptor(100, {}), MakeDataDescriptor(203, {1})));
  230. std::string after_transformation = R"(
  231. OpCapability Shader
  232. %1 = OpExtInstImport "GLSL.std.450"
  233. OpMemoryModel Logical GLSL450
  234. OpEntryPoint Fragment %4 "main"
  235. OpExecutionMode %4 OriginUpperLeft
  236. OpSource ESSL 310
  237. OpName %4 "main"
  238. OpName %11 "floats"
  239. OpName %22 "x"
  240. OpName %39 "vecs"
  241. OpName %49 "bools"
  242. OpName %60 "many_uvec3s"
  243. OpDecorate %60 RelaxedPrecision
  244. %2 = OpTypeVoid
  245. %3 = OpTypeFunction %2
  246. %6 = OpTypeFloat 32
  247. %7 = OpTypeInt 32 0
  248. %8 = OpConstant %7 2
  249. %9 = OpTypeArray %6 %8
  250. %10 = OpTypePointer Function %9
  251. %12 = OpTypeInt 32 1
  252. %13 = OpConstant %12 0
  253. %14 = OpConstant %6 1
  254. %15 = OpTypePointer Function %6
  255. %17 = OpConstant %12 1
  256. %18 = OpConstant %6 2
  257. %20 = OpTypeVector %6 2
  258. %21 = OpTypePointer Function %20
  259. %32 = OpTypeBool
  260. %36 = OpConstant %7 3
  261. %37 = OpTypeArray %20 %36
  262. %38 = OpTypePointer Private %37
  263. %39 = OpVariable %38 Private
  264. %40 = OpConstant %6 3
  265. %41 = OpConstantComposite %20 %40 %40
  266. %42 = OpTypePointer Private %20
  267. %44 = OpConstant %12 2
  268. %47 = OpTypeArray %32 %36
  269. %48 = OpTypePointer Function %47
  270. %50 = OpConstantTrue %32
  271. %51 = OpTypePointer Function %32
  272. %56 = OpTypeVector %7 3
  273. %57 = OpTypeArray %56 %8
  274. %58 = OpTypeArray %57 %8
  275. %59 = OpTypePointer Function %58
  276. %61 = OpConstant %7 4
  277. %62 = OpConstantComposite %56 %61 %61 %61
  278. %63 = OpTypePointer Function %56
  279. %65 = OpConstant %7 5
  280. %66 = OpConstantComposite %56 %65 %65 %65
  281. %67 = OpConstant %7 6
  282. %68 = OpConstantComposite %56 %67 %67 %67
  283. %69 = OpConstantComposite %57 %66 %68
  284. %100 = OpUndef %57
  285. %70 = OpTypePointer Function %57
  286. %4 = OpFunction %2 None %3
  287. %5 = OpLabel
  288. %11 = OpVariable %10 Function
  289. %22 = OpVariable %21 Function
  290. %49 = OpVariable %48 Function
  291. %60 = OpVariable %59 Function
  292. %16 = OpAccessChain %15 %11 %13
  293. OpStore %16 %14
  294. %19 = OpAccessChain %15 %11 %17
  295. OpStore %19 %18
  296. %23 = OpAccessChain %15 %11 %13
  297. %24 = OpLoad %6 %23
  298. %25 = OpAccessChain %15 %11 %17
  299. %26 = OpLoad %6 %25
  300. %27 = OpCompositeConstruct %20 %24 %26
  301. OpStore %22 %27
  302. %28 = OpAccessChain %15 %11 %13
  303. %29 = OpLoad %6 %28
  304. %30 = OpAccessChain %15 %11 %17
  305. %31 = OpLoad %6 %30
  306. %33 = OpFOrdGreaterThan %32 %29 %31
  307. %202 = OpCompositeConstruct %47 %33 %50 %50
  308. OpSelectionMerge %35 None
  309. OpBranchConditional %33 %34 %35
  310. %34 = OpLabel
  311. %43 = OpAccessChain %42 %39 %17
  312. OpStore %43 %41
  313. %45 = OpLoad %20 %22
  314. %200 = OpCompositeConstruct %37 %41 %45 %27
  315. %46 = OpAccessChain %42 %39 %44
  316. OpStore %46 %45
  317. OpBranch %35
  318. %35 = OpLabel
  319. %52 = OpAccessChain %51 %49 %13
  320. OpStore %52 %50
  321. %53 = OpAccessChain %51 %49 %13
  322. %54 = OpLoad %32 %53
  323. %55 = OpAccessChain %51 %49 %17
  324. OpStore %55 %54
  325. %64 = OpAccessChain %63 %60 %13 %13
  326. %203 = OpCompositeConstruct %58 %69 %100
  327. OpStore %64 %62
  328. %71 = OpAccessChain %70 %60 %17
  329. %201 = OpCompositeConstruct %9 %24 %40
  330. OpStore %71 %69
  331. OpReturn
  332. OpFunctionEnd
  333. )";
  334. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  335. }
  336. TEST(TransformationCompositeConstructTest, ConstructMatrices) {
  337. std::string shader = R"(
  338. OpCapability Shader
  339. %1 = OpExtInstImport "GLSL.std.450"
  340. OpMemoryModel Logical GLSL450
  341. OpEntryPoint Fragment %4 "main"
  342. OpExecutionMode %4 OriginUpperLeft
  343. OpSource ESSL 310
  344. OpName %4 "main"
  345. OpName %9 "v1"
  346. OpName %12 "v2"
  347. OpName %14 "v3"
  348. OpName %19 "v4"
  349. OpName %26 "v5"
  350. OpName %29 "v6"
  351. OpName %34 "m34"
  352. OpName %37 "m43"
  353. OpName %43 "vecs"
  354. %2 = OpTypeVoid
  355. %3 = OpTypeFunction %2
  356. %6 = OpTypeFloat 32
  357. %7 = OpTypeVector %6 3
  358. %8 = OpTypePointer Function %7
  359. %10 = OpConstant %6 1
  360. %11 = OpConstantComposite %7 %10 %10 %10
  361. %17 = OpTypeVector %6 4
  362. %18 = OpTypePointer Function %17
  363. %21 = OpConstant %6 2
  364. %32 = OpTypeMatrix %17 3
  365. %33 = OpTypePointer Private %32
  366. %34 = OpVariable %33 Private
  367. %35 = OpTypeMatrix %7 4
  368. %36 = OpTypePointer Private %35
  369. %37 = OpVariable %36 Private
  370. %38 = OpTypeVector %6 2
  371. %39 = OpTypeInt 32 0
  372. %40 = OpConstant %39 3
  373. %41 = OpTypeArray %38 %40
  374. %42 = OpTypePointer Private %41
  375. %43 = OpVariable %42 Private
  376. %100 = OpUndef %7
  377. %101 = OpUndef %17
  378. %4 = OpFunction %2 None %3
  379. %5 = OpLabel
  380. %9 = OpVariable %8 Function
  381. %12 = OpVariable %8 Function
  382. %14 = OpVariable %8 Function
  383. %19 = OpVariable %18 Function
  384. %26 = OpVariable %18 Function
  385. %29 = OpVariable %18 Function
  386. OpStore %9 %11
  387. %13 = OpLoad %7 %9
  388. OpStore %12 %13
  389. %15 = OpLoad %7 %12
  390. %16 = OpVectorShuffle %7 %15 %15 2 1 0
  391. OpStore %14 %16
  392. %20 = OpLoad %7 %14
  393. %22 = OpCompositeExtract %6 %20 0
  394. %23 = OpCompositeExtract %6 %20 1
  395. %24 = OpCompositeExtract %6 %20 2
  396. %25 = OpCompositeConstruct %17 %22 %23 %24 %21
  397. OpStore %19 %25
  398. %27 = OpLoad %17 %19
  399. %28 = OpVectorShuffle %17 %27 %27 3 2 1 0
  400. OpStore %26 %28
  401. %30 = OpLoad %7 %9
  402. %31 = OpVectorShuffle %17 %30 %30 0 0 1 1
  403. OpStore %29 %31
  404. OpReturn
  405. OpFunctionEnd
  406. )";
  407. const auto env = SPV_ENV_UNIVERSAL_1_3;
  408. const auto consumer = nullptr;
  409. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  410. spvtools::ValidatorOptions validator_options;
  411. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  412. kConsoleMessageConsumer));
  413. TransformationContext transformation_context(
  414. MakeUnique<FactManager>(context.get()), validator_options);
  415. // make a mat3x4
  416. TransformationCompositeConstruct make_mat34(
  417. 32, {25, 28, 31}, MakeInstructionDescriptor(31, spv::Op::OpReturn, 0),
  418. 200);
  419. // Bad: %35 is mat4x3, not mat3x4.
  420. TransformationCompositeConstruct make_mat34_bad(
  421. 35, {25, 28, 31}, MakeInstructionDescriptor(31, spv::Op::OpReturn, 0),
  422. 200);
  423. // The first component does not correspond to an instruction with a result
  424. // type so this check should return false.
  425. TransformationCompositeConstruct make_mat34_nores(
  426. 32, {2, 28, 31}, MakeInstructionDescriptor(31, spv::Op::OpReturn, 0),
  427. 200);
  428. ASSERT_TRUE(make_mat34.IsApplicable(context.get(), transformation_context));
  429. ASSERT_FALSE(
  430. make_mat34_bad.IsApplicable(context.get(), transformation_context));
  431. ASSERT_FALSE(
  432. make_mat34_nores.IsApplicable(context.get(), transformation_context));
  433. ApplyAndCheckFreshIds(make_mat34, context.get(), &transformation_context);
  434. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  435. kConsoleMessageConsumer));
  436. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  437. MakeDataDescriptor(25, {}), MakeDataDescriptor(200, {0})));
  438. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  439. MakeDataDescriptor(28, {}), MakeDataDescriptor(200, {1})));
  440. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  441. MakeDataDescriptor(31, {}), MakeDataDescriptor(200, {2})));
  442. // make a mat4x3
  443. TransformationCompositeConstruct make_mat43(
  444. 35, {11, 13, 16, 100}, MakeInstructionDescriptor(31, spv::Op::OpStore, 0),
  445. 201);
  446. // Bad: %25 does not match the matrix's column type.
  447. TransformationCompositeConstruct make_mat43_bad(
  448. 35, {25, 13, 16, 100}, MakeInstructionDescriptor(31, spv::Op::OpStore, 0),
  449. 201);
  450. ASSERT_TRUE(make_mat43.IsApplicable(context.get(), transformation_context));
  451. ASSERT_FALSE(
  452. make_mat43_bad.IsApplicable(context.get(), transformation_context));
  453. ApplyAndCheckFreshIds(make_mat43, context.get(), &transformation_context);
  454. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  455. kConsoleMessageConsumer));
  456. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  457. MakeDataDescriptor(11, {}), MakeDataDescriptor(201, {0})));
  458. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  459. MakeDataDescriptor(13, {}), MakeDataDescriptor(201, {1})));
  460. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  461. MakeDataDescriptor(16, {}), MakeDataDescriptor(201, {2})));
  462. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  463. MakeDataDescriptor(100, {}), MakeDataDescriptor(201, {3})));
  464. std::string after_transformation = R"(
  465. OpCapability Shader
  466. %1 = OpExtInstImport "GLSL.std.450"
  467. OpMemoryModel Logical GLSL450
  468. OpEntryPoint Fragment %4 "main"
  469. OpExecutionMode %4 OriginUpperLeft
  470. OpSource ESSL 310
  471. OpName %4 "main"
  472. OpName %9 "v1"
  473. OpName %12 "v2"
  474. OpName %14 "v3"
  475. OpName %19 "v4"
  476. OpName %26 "v5"
  477. OpName %29 "v6"
  478. OpName %34 "m34"
  479. OpName %37 "m43"
  480. OpName %43 "vecs"
  481. %2 = OpTypeVoid
  482. %3 = OpTypeFunction %2
  483. %6 = OpTypeFloat 32
  484. %7 = OpTypeVector %6 3
  485. %8 = OpTypePointer Function %7
  486. %10 = OpConstant %6 1
  487. %11 = OpConstantComposite %7 %10 %10 %10
  488. %17 = OpTypeVector %6 4
  489. %18 = OpTypePointer Function %17
  490. %21 = OpConstant %6 2
  491. %32 = OpTypeMatrix %17 3
  492. %33 = OpTypePointer Private %32
  493. %34 = OpVariable %33 Private
  494. %35 = OpTypeMatrix %7 4
  495. %36 = OpTypePointer Private %35
  496. %37 = OpVariable %36 Private
  497. %38 = OpTypeVector %6 2
  498. %39 = OpTypeInt 32 0
  499. %40 = OpConstant %39 3
  500. %41 = OpTypeArray %38 %40
  501. %42 = OpTypePointer Private %41
  502. %43 = OpVariable %42 Private
  503. %100 = OpUndef %7
  504. %101 = OpUndef %17
  505. %4 = OpFunction %2 None %3
  506. %5 = OpLabel
  507. %9 = OpVariable %8 Function
  508. %12 = OpVariable %8 Function
  509. %14 = OpVariable %8 Function
  510. %19 = OpVariable %18 Function
  511. %26 = OpVariable %18 Function
  512. %29 = OpVariable %18 Function
  513. OpStore %9 %11
  514. %13 = OpLoad %7 %9
  515. OpStore %12 %13
  516. %15 = OpLoad %7 %12
  517. %16 = OpVectorShuffle %7 %15 %15 2 1 0
  518. OpStore %14 %16
  519. %20 = OpLoad %7 %14
  520. %22 = OpCompositeExtract %6 %20 0
  521. %23 = OpCompositeExtract %6 %20 1
  522. %24 = OpCompositeExtract %6 %20 2
  523. %25 = OpCompositeConstruct %17 %22 %23 %24 %21
  524. OpStore %19 %25
  525. %27 = OpLoad %17 %19
  526. %28 = OpVectorShuffle %17 %27 %27 3 2 1 0
  527. OpStore %26 %28
  528. %30 = OpLoad %7 %9
  529. %31 = OpVectorShuffle %17 %30 %30 0 0 1 1
  530. %201 = OpCompositeConstruct %35 %11 %13 %16 %100
  531. OpStore %29 %31
  532. %200 = OpCompositeConstruct %32 %25 %28 %31
  533. OpReturn
  534. OpFunctionEnd
  535. )";
  536. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  537. }
  538. TEST(TransformationCompositeConstructTest, ConstructStructs) {
  539. std::string shader = R"(
  540. OpCapability Shader
  541. %1 = OpExtInstImport "GLSL.std.450"
  542. OpMemoryModel Logical GLSL450
  543. OpEntryPoint Fragment %4 "main"
  544. OpExecutionMode %4 OriginUpperLeft
  545. OpSource ESSL 310
  546. OpName %4 "main"
  547. OpName %9 "Inner"
  548. OpMemberName %9 0 "a"
  549. OpMemberName %9 1 "b"
  550. OpName %11 "i1"
  551. OpName %22 "i2"
  552. OpName %33 "Outer"
  553. OpMemberName %33 0 "c"
  554. OpMemberName %33 1 "d"
  555. OpMemberName %33 2 "e"
  556. OpName %35 "o"
  557. %2 = OpTypeVoid
  558. %3 = OpTypeFunction %2
  559. %6 = OpTypeFloat 32
  560. %7 = OpTypeVector %6 2
  561. %8 = OpTypeInt 32 1
  562. %9 = OpTypeStruct %7 %8
  563. %10 = OpTypePointer Function %9
  564. %12 = OpConstant %8 0
  565. %13 = OpConstant %6 2
  566. %14 = OpTypeInt 32 0
  567. %15 = OpConstant %14 0
  568. %16 = OpTypePointer Function %6
  569. %18 = OpConstant %8 1
  570. %19 = OpConstant %8 3
  571. %20 = OpTypePointer Function %8
  572. %23 = OpTypePointer Function %7
  573. %31 = OpConstant %14 2
  574. %32 = OpTypeArray %9 %31
  575. %33 = OpTypeStruct %32 %9 %6
  576. %34 = OpTypePointer Function %33
  577. %36 = OpConstant %6 1
  578. %37 = OpConstantComposite %7 %36 %13
  579. %38 = OpConstant %8 2
  580. %39 = OpConstantComposite %9 %37 %38
  581. %40 = OpConstant %6 3
  582. %41 = OpConstant %6 4
  583. %42 = OpConstantComposite %7 %40 %41
  584. %56 = OpConstant %6 5
  585. %100 = OpUndef %9
  586. %4 = OpFunction %2 None %3
  587. %5 = OpLabel
  588. %11 = OpVariable %10 Function
  589. %22 = OpVariable %10 Function
  590. %35 = OpVariable %34 Function
  591. %17 = OpAccessChain %16 %11 %12 %15
  592. OpStore %17 %13
  593. %21 = OpAccessChain %20 %11 %18
  594. OpStore %21 %19
  595. %24 = OpAccessChain %23 %11 %12
  596. %25 = OpLoad %7 %24
  597. %26 = OpAccessChain %23 %22 %12
  598. OpStore %26 %25
  599. %27 = OpAccessChain %20 %11 %18
  600. %28 = OpLoad %8 %27
  601. %29 = OpIAdd %8 %28 %18
  602. %30 = OpAccessChain %20 %22 %18
  603. OpStore %30 %29
  604. %43 = OpAccessChain %20 %11 %18
  605. %44 = OpLoad %8 %43
  606. %45 = OpCompositeConstruct %9 %42 %44
  607. %46 = OpCompositeConstruct %32 %39 %45
  608. %47 = OpLoad %9 %22
  609. %48 = OpCompositeConstruct %33 %46 %47 %40
  610. OpStore %35 %48
  611. %49 = OpLoad %9 %11
  612. %50 = OpAccessChain %10 %35 %12 %12
  613. OpStore %50 %49
  614. %51 = OpLoad %9 %22
  615. %52 = OpAccessChain %10 %35 %12 %18
  616. OpStore %52 %51
  617. %53 = OpAccessChain %10 %35 %12 %12
  618. %54 = OpLoad %9 %53
  619. %55 = OpAccessChain %10 %35 %18
  620. OpStore %55 %54
  621. %57 = OpAccessChain %16 %35 %38
  622. OpStore %57 %56
  623. OpReturn
  624. OpFunctionEnd
  625. )";
  626. const auto env = SPV_ENV_UNIVERSAL_1_3;
  627. const auto consumer = nullptr;
  628. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  629. spvtools::ValidatorOptions validator_options;
  630. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  631. kConsoleMessageConsumer));
  632. TransformationContext transformation_context(
  633. MakeUnique<FactManager>(context.get()), validator_options);
  634. // make an Inner
  635. TransformationCompositeConstruct make_inner(
  636. 9, {25, 19}, MakeInstructionDescriptor(57, spv::Op::OpAccessChain, 0),
  637. 200);
  638. // Bad: Too few fields to make the struct.
  639. TransformationCompositeConstruct make_inner_bad(
  640. 9, {25}, MakeInstructionDescriptor(57, spv::Op::OpAccessChain, 0), 200);
  641. // The first component does not correspond to an instruction with a result
  642. // type so this check should return false.
  643. TransformationCompositeConstruct make_inner_nores(
  644. 9, {2, 19}, MakeInstructionDescriptor(57, spv::Op::OpAccessChain, 0),
  645. 200);
  646. ASSERT_TRUE(make_inner.IsApplicable(context.get(), transformation_context));
  647. ASSERT_FALSE(
  648. make_inner_bad.IsApplicable(context.get(), transformation_context));
  649. ASSERT_FALSE(
  650. make_inner_nores.IsApplicable(context.get(), transformation_context));
  651. ApplyAndCheckFreshIds(make_inner, context.get(), &transformation_context);
  652. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  653. kConsoleMessageConsumer));
  654. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  655. MakeDataDescriptor(25, {}), MakeDataDescriptor(200, {0})));
  656. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  657. MakeDataDescriptor(19, {}), MakeDataDescriptor(200, {1})));
  658. // make an Outer
  659. TransformationCompositeConstruct make_outer(
  660. 33, {46, 200, 56},
  661. MakeInstructionDescriptor(200, spv::Op::OpAccessChain, 0), 201);
  662. // Bad: %200 is not available at the desired program point.
  663. TransformationCompositeConstruct make_outer_bad(
  664. 33, {46, 200, 56},
  665. MakeInstructionDescriptor(200, spv::Op::OpCompositeConstruct, 0), 201);
  666. ASSERT_TRUE(make_outer.IsApplicable(context.get(), transformation_context));
  667. ASSERT_FALSE(
  668. make_outer_bad.IsApplicable(context.get(), transformation_context));
  669. ApplyAndCheckFreshIds(make_outer, context.get(), &transformation_context);
  670. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  671. kConsoleMessageConsumer));
  672. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  673. MakeDataDescriptor(46, {}), MakeDataDescriptor(201, {0})));
  674. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  675. MakeDataDescriptor(200, {}), MakeDataDescriptor(201, {1})));
  676. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  677. MakeDataDescriptor(56, {}), MakeDataDescriptor(201, {2})));
  678. std::string after_transformation = R"(
  679. OpCapability Shader
  680. %1 = OpExtInstImport "GLSL.std.450"
  681. OpMemoryModel Logical GLSL450
  682. OpEntryPoint Fragment %4 "main"
  683. OpExecutionMode %4 OriginUpperLeft
  684. OpSource ESSL 310
  685. OpName %4 "main"
  686. OpName %9 "Inner"
  687. OpMemberName %9 0 "a"
  688. OpMemberName %9 1 "b"
  689. OpName %11 "i1"
  690. OpName %22 "i2"
  691. OpName %33 "Outer"
  692. OpMemberName %33 0 "c"
  693. OpMemberName %33 1 "d"
  694. OpMemberName %33 2 "e"
  695. OpName %35 "o"
  696. %2 = OpTypeVoid
  697. %3 = OpTypeFunction %2
  698. %6 = OpTypeFloat 32
  699. %7 = OpTypeVector %6 2
  700. %8 = OpTypeInt 32 1
  701. %9 = OpTypeStruct %7 %8
  702. %10 = OpTypePointer Function %9
  703. %12 = OpConstant %8 0
  704. %13 = OpConstant %6 2
  705. %14 = OpTypeInt 32 0
  706. %15 = OpConstant %14 0
  707. %16 = OpTypePointer Function %6
  708. %18 = OpConstant %8 1
  709. %19 = OpConstant %8 3
  710. %20 = OpTypePointer Function %8
  711. %23 = OpTypePointer Function %7
  712. %31 = OpConstant %14 2
  713. %32 = OpTypeArray %9 %31
  714. %33 = OpTypeStruct %32 %9 %6
  715. %34 = OpTypePointer Function %33
  716. %36 = OpConstant %6 1
  717. %37 = OpConstantComposite %7 %36 %13
  718. %38 = OpConstant %8 2
  719. %39 = OpConstantComposite %9 %37 %38
  720. %40 = OpConstant %6 3
  721. %41 = OpConstant %6 4
  722. %42 = OpConstantComposite %7 %40 %41
  723. %56 = OpConstant %6 5
  724. %100 = OpUndef %9
  725. %4 = OpFunction %2 None %3
  726. %5 = OpLabel
  727. %11 = OpVariable %10 Function
  728. %22 = OpVariable %10 Function
  729. %35 = OpVariable %34 Function
  730. %17 = OpAccessChain %16 %11 %12 %15
  731. OpStore %17 %13
  732. %21 = OpAccessChain %20 %11 %18
  733. OpStore %21 %19
  734. %24 = OpAccessChain %23 %11 %12
  735. %25 = OpLoad %7 %24
  736. %26 = OpAccessChain %23 %22 %12
  737. OpStore %26 %25
  738. %27 = OpAccessChain %20 %11 %18
  739. %28 = OpLoad %8 %27
  740. %29 = OpIAdd %8 %28 %18
  741. %30 = OpAccessChain %20 %22 %18
  742. OpStore %30 %29
  743. %43 = OpAccessChain %20 %11 %18
  744. %44 = OpLoad %8 %43
  745. %45 = OpCompositeConstruct %9 %42 %44
  746. %46 = OpCompositeConstruct %32 %39 %45
  747. %47 = OpLoad %9 %22
  748. %48 = OpCompositeConstruct %33 %46 %47 %40
  749. OpStore %35 %48
  750. %49 = OpLoad %9 %11
  751. %50 = OpAccessChain %10 %35 %12 %12
  752. OpStore %50 %49
  753. %51 = OpLoad %9 %22
  754. %52 = OpAccessChain %10 %35 %12 %18
  755. OpStore %52 %51
  756. %53 = OpAccessChain %10 %35 %12 %12
  757. %54 = OpLoad %9 %53
  758. %55 = OpAccessChain %10 %35 %18
  759. OpStore %55 %54
  760. %200 = OpCompositeConstruct %9 %25 %19
  761. %201 = OpCompositeConstruct %33 %46 %200 %56
  762. %57 = OpAccessChain %16 %35 %38
  763. OpStore %57 %56
  764. OpReturn
  765. OpFunctionEnd
  766. )";
  767. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  768. }
  769. TEST(TransformationCompositeConstructTest, ConstructVectors) {
  770. std::string shader = R"(
  771. OpCapability Shader
  772. %1 = OpExtInstImport "GLSL.std.450"
  773. OpMemoryModel Logical GLSL450
  774. OpEntryPoint Fragment %4 "main"
  775. OpExecutionMode %4 OriginUpperLeft
  776. OpSource ESSL 310
  777. OpName %4 "main"
  778. OpName %9 "v2"
  779. OpName %27 "v3"
  780. OpName %46 "v4"
  781. OpName %53 "iv2"
  782. OpName %61 "uv3"
  783. OpName %72 "bv4"
  784. OpName %88 "uv2"
  785. OpName %95 "bv3"
  786. OpName %104 "bv2"
  787. OpName %116 "iv3"
  788. OpName %124 "iv4"
  789. OpName %133 "uv4"
  790. %2 = OpTypeVoid
  791. %3 = OpTypeFunction %2
  792. %6 = OpTypeFloat 32
  793. %7 = OpTypeVector %6 2
  794. %8 = OpTypePointer Function %7
  795. %10 = OpConstant %6 1
  796. %11 = OpConstant %6 2
  797. %12 = OpConstantComposite %7 %10 %11
  798. %13 = OpTypeInt 32 0
  799. %14 = OpConstant %13 0
  800. %15 = OpTypePointer Function %6
  801. %18 = OpConstant %13 1
  802. %21 = OpTypeBool
  803. %25 = OpTypeVector %6 3
  804. %26 = OpTypePointer Function %25
  805. %33 = OpConstant %6 3
  806. %34 = OpConstant %6 -0.756802499
  807. %38 = OpConstant %13 2
  808. %44 = OpTypeVector %6 4
  809. %45 = OpTypePointer Function %44
  810. %50 = OpTypeInt 32 1
  811. %51 = OpTypeVector %50 2
  812. %52 = OpTypePointer Function %51
  813. %57 = OpTypePointer Function %50
  814. %59 = OpTypeVector %13 3
  815. %60 = OpTypePointer Function %59
  816. %65 = OpConstant %13 3
  817. %67 = OpTypePointer Function %13
  818. %70 = OpTypeVector %21 4
  819. %71 = OpTypePointer Function %70
  820. %73 = OpConstantTrue %21
  821. %74 = OpTypePointer Function %21
  822. %86 = OpTypeVector %13 2
  823. %87 = OpTypePointer Function %86
  824. %93 = OpTypeVector %21 3
  825. %94 = OpTypePointer Function %93
  826. %102 = OpTypeVector %21 2
  827. %103 = OpTypePointer Function %102
  828. %111 = OpConstantFalse %21
  829. %114 = OpTypeVector %50 3
  830. %115 = OpTypePointer Function %114
  831. %117 = OpConstant %50 3
  832. %122 = OpTypeVector %50 4
  833. %123 = OpTypePointer Function %122
  834. %131 = OpTypeVector %13 4
  835. %132 = OpTypePointer Function %131
  836. %4 = OpFunction %2 None %3
  837. %5 = OpLabel
  838. %9 = OpVariable %8 Function
  839. %27 = OpVariable %26 Function
  840. %46 = OpVariable %45 Function
  841. %53 = OpVariable %52 Function
  842. %61 = OpVariable %60 Function
  843. %72 = OpVariable %71 Function
  844. %88 = OpVariable %87 Function
  845. %95 = OpVariable %94 Function
  846. %104 = OpVariable %103 Function
  847. %116 = OpVariable %115 Function
  848. %124 = OpVariable %123 Function
  849. %133 = OpVariable %132 Function
  850. OpStore %9 %12
  851. %16 = OpAccessChain %15 %9 %14
  852. %17 = OpLoad %6 %16
  853. %19 = OpAccessChain %15 %9 %18
  854. %20 = OpLoad %6 %19
  855. %22 = OpFOrdGreaterThan %21 %17 %20
  856. OpSelectionMerge %24 None
  857. OpBranchConditional %22 %23 %101
  858. %23 = OpLabel
  859. %28 = OpAccessChain %15 %9 %14
  860. %29 = OpLoad %6 %28
  861. %30 = OpAccessChain %15 %9 %18
  862. %31 = OpLoad %6 %30
  863. %32 = OpFAdd %6 %29 %31
  864. %35 = OpCompositeConstruct %25 %32 %33 %34
  865. OpStore %27 %35
  866. %36 = OpAccessChain %15 %27 %14
  867. %37 = OpLoad %6 %36
  868. %39 = OpAccessChain %15 %27 %38
  869. %40 = OpLoad %6 %39
  870. %41 = OpFOrdLessThan %21 %37 %40
  871. OpSelectionMerge %43 None
  872. OpBranchConditional %41 %42 %69
  873. %42 = OpLabel
  874. %47 = OpAccessChain %15 %9 %18
  875. %48 = OpLoad %6 %47
  876. %49 = OpAccessChain %15 %46 %14
  877. OpStore %49 %48
  878. %54 = OpAccessChain %15 %27 %38
  879. %55 = OpLoad %6 %54
  880. %56 = OpConvertFToS %50 %55
  881. %58 = OpAccessChain %57 %53 %14
  882. OpStore %58 %56
  883. %62 = OpAccessChain %15 %46 %14
  884. %63 = OpLoad %6 %62
  885. %64 = OpConvertFToU %13 %63
  886. %66 = OpIAdd %13 %64 %65
  887. %68 = OpAccessChain %67 %61 %14
  888. OpStore %68 %66
  889. OpBranch %43
  890. %69 = OpLabel
  891. %75 = OpAccessChain %74 %72 %14
  892. OpStore %75 %73
  893. %76 = OpAccessChain %74 %72 %14
  894. %77 = OpLoad %21 %76
  895. %78 = OpLogicalNot %21 %77
  896. %79 = OpAccessChain %74 %72 %18
  897. OpStore %79 %78
  898. %80 = OpAccessChain %74 %72 %14
  899. %81 = OpLoad %21 %80
  900. %82 = OpAccessChain %74 %72 %18
  901. %83 = OpLoad %21 %82
  902. %84 = OpLogicalAnd %21 %81 %83
  903. %85 = OpAccessChain %74 %72 %38
  904. OpStore %85 %84
  905. %89 = OpAccessChain %67 %88 %14
  906. %90 = OpLoad %13 %89
  907. %91 = OpINotEqual %21 %90 %14
  908. %92 = OpAccessChain %74 %72 %65
  909. OpStore %92 %91
  910. OpBranch %43
  911. %43 = OpLabel
  912. %96 = OpLoad %70 %72
  913. %97 = OpCompositeExtract %21 %96 0
  914. %98 = OpCompositeExtract %21 %96 1
  915. %99 = OpCompositeExtract %21 %96 2
  916. %100 = OpCompositeConstruct %93 %97 %98 %99
  917. OpStore %95 %100
  918. OpBranch %24
  919. %101 = OpLabel
  920. %105 = OpAccessChain %67 %88 %14
  921. %106 = OpLoad %13 %105
  922. %107 = OpINotEqual %21 %106 %14
  923. %108 = OpCompositeConstruct %102 %107 %107
  924. OpStore %104 %108
  925. OpBranch %24
  926. %24 = OpLabel
  927. %109 = OpAccessChain %74 %104 %18
  928. %110 = OpLoad %21 %109
  929. %112 = OpLogicalOr %21 %110 %111
  930. %113 = OpAccessChain %74 %104 %14
  931. OpStore %113 %112
  932. %118 = OpAccessChain %57 %116 %14
  933. OpStore %118 %117
  934. %119 = OpAccessChain %57 %116 %14
  935. %120 = OpLoad %50 %119
  936. %121 = OpAccessChain %57 %53 %18
  937. OpStore %121 %120
  938. %125 = OpAccessChain %57 %116 %14
  939. %126 = OpLoad %50 %125
  940. %127 = OpAccessChain %57 %53 %18
  941. %128 = OpLoad %50 %127
  942. %129 = OpIAdd %50 %126 %128
  943. %130 = OpAccessChain %57 %124 %65
  944. OpStore %130 %129
  945. %134 = OpAccessChain %57 %116 %14
  946. %135 = OpLoad %50 %134
  947. %136 = OpBitcast %13 %135
  948. %137 = OpAccessChain %67 %133 %14
  949. OpStore %137 %136
  950. OpReturn
  951. OpFunctionEnd
  952. )";
  953. const auto env = SPV_ENV_UNIVERSAL_1_3;
  954. const auto consumer = nullptr;
  955. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  956. spvtools::ValidatorOptions validator_options;
  957. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  958. kConsoleMessageConsumer));
  959. TransformationContext transformation_context(
  960. MakeUnique<FactManager>(context.get()), validator_options);
  961. TransformationCompositeConstruct make_vec2(
  962. 7, {17, 11}, MakeInstructionDescriptor(100, spv::Op::OpStore, 0), 200);
  963. // Bad: not enough data for a vec2
  964. TransformationCompositeConstruct make_vec2_bad(
  965. 7, {11}, MakeInstructionDescriptor(100, spv::Op::OpStore, 0), 200);
  966. ASSERT_TRUE(make_vec2.IsApplicable(context.get(), transformation_context));
  967. ASSERT_FALSE(
  968. make_vec2_bad.IsApplicable(context.get(), transformation_context));
  969. ApplyAndCheckFreshIds(make_vec2, context.get(), &transformation_context);
  970. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  971. kConsoleMessageConsumer));
  972. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  973. MakeDataDescriptor(17, {}), MakeDataDescriptor(200, {0})));
  974. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  975. MakeDataDescriptor(11, {}), MakeDataDescriptor(200, {1})));
  976. TransformationCompositeConstruct make_vec3(
  977. 25, {12, 32},
  978. MakeInstructionDescriptor(35, spv::Op::OpCompositeConstruct, 0), 201);
  979. // Bad: too much data for a vec3
  980. TransformationCompositeConstruct make_vec3_bad(
  981. 25, {12, 32, 32},
  982. MakeInstructionDescriptor(35, spv::Op::OpCompositeConstruct, 0), 201);
  983. ASSERT_TRUE(make_vec3.IsApplicable(context.get(), transformation_context));
  984. ASSERT_FALSE(
  985. make_vec3_bad.IsApplicable(context.get(), transformation_context));
  986. ApplyAndCheckFreshIds(make_vec3, context.get(), &transformation_context);
  987. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  988. kConsoleMessageConsumer));
  989. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  990. MakeDataDescriptor(12, {0}), MakeDataDescriptor(201, {0})));
  991. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  992. MakeDataDescriptor(12, {1}), MakeDataDescriptor(201, {1})));
  993. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  994. MakeDataDescriptor(32, {}), MakeDataDescriptor(201, {2})));
  995. TransformationCompositeConstruct make_vec4(
  996. 44, {32, 32, 10, 11},
  997. MakeInstructionDescriptor(75, spv::Op::OpAccessChain, 0), 202);
  998. // Bad: id 48 is not available at the insertion points
  999. TransformationCompositeConstruct make_vec4_bad(
  1000. 44, {48, 32, 10, 11},
  1001. MakeInstructionDescriptor(75, spv::Op::OpAccessChain, 0), 202);
  1002. ASSERT_TRUE(make_vec4.IsApplicable(context.get(), transformation_context));
  1003. ASSERT_FALSE(
  1004. make_vec4_bad.IsApplicable(context.get(), transformation_context));
  1005. ApplyAndCheckFreshIds(make_vec4, context.get(), &transformation_context);
  1006. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1007. kConsoleMessageConsumer));
  1008. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1009. MakeDataDescriptor(32, {}), MakeDataDescriptor(202, {0})));
  1010. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1011. MakeDataDescriptor(32, {}), MakeDataDescriptor(202, {1})));
  1012. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1013. MakeDataDescriptor(10, {}), MakeDataDescriptor(202, {2})));
  1014. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1015. MakeDataDescriptor(11, {}), MakeDataDescriptor(202, {3})));
  1016. TransformationCompositeConstruct make_ivec2(
  1017. 51, {126, 120}, MakeInstructionDescriptor(128, spv::Op::OpLoad, 0), 203);
  1018. // Bad: if 128 is not available at the instruction that defines 128
  1019. TransformationCompositeConstruct make_ivec2_bad(
  1020. 51, {128, 120}, MakeInstructionDescriptor(128, spv::Op::OpLoad, 0), 203);
  1021. ASSERT_TRUE(make_ivec2.IsApplicable(context.get(), transformation_context));
  1022. ASSERT_FALSE(
  1023. make_ivec2_bad.IsApplicable(context.get(), transformation_context));
  1024. ApplyAndCheckFreshIds(make_ivec2, context.get(), &transformation_context);
  1025. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1026. kConsoleMessageConsumer));
  1027. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1028. MakeDataDescriptor(126, {}), MakeDataDescriptor(203, {0})));
  1029. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1030. MakeDataDescriptor(120, {}), MakeDataDescriptor(203, {1})));
  1031. TransformationCompositeConstruct make_ivec3(
  1032. 114, {56, 117, 56},
  1033. MakeInstructionDescriptor(66, spv::Op::OpAccessChain, 0), 204);
  1034. // Bad because 1300 is not an id
  1035. TransformationCompositeConstruct make_ivec3_bad(
  1036. 114, {56, 117, 1300},
  1037. MakeInstructionDescriptor(66, spv::Op::OpAccessChain, 0), 204);
  1038. ASSERT_TRUE(make_ivec3.IsApplicable(context.get(), transformation_context));
  1039. ASSERT_FALSE(
  1040. make_ivec3_bad.IsApplicable(context.get(), transformation_context));
  1041. ApplyAndCheckFreshIds(make_ivec3, context.get(), &transformation_context);
  1042. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1043. kConsoleMessageConsumer));
  1044. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1045. MakeDataDescriptor(56, {}), MakeDataDescriptor(204, {0})));
  1046. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1047. MakeDataDescriptor(117, {}), MakeDataDescriptor(204, {1})));
  1048. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1049. MakeDataDescriptor(56, {}), MakeDataDescriptor(204, {2})));
  1050. TransformationCompositeConstruct make_ivec4(
  1051. 122, {56, 117, 117, 117},
  1052. MakeInstructionDescriptor(66, spv::Op::OpIAdd, 0), 205);
  1053. // Bad because 86 is the wrong type.
  1054. TransformationCompositeConstruct make_ivec4_bad(
  1055. 86, {56, 117, 117, 117},
  1056. MakeInstructionDescriptor(66, spv::Op::OpIAdd, 0), 205);
  1057. ASSERT_TRUE(make_ivec4.IsApplicable(context.get(), transformation_context));
  1058. ASSERT_FALSE(
  1059. make_ivec4_bad.IsApplicable(context.get(), transformation_context));
  1060. ApplyAndCheckFreshIds(make_ivec4, context.get(), &transformation_context);
  1061. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1062. kConsoleMessageConsumer));
  1063. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1064. MakeDataDescriptor(56, {}), MakeDataDescriptor(205, {0})));
  1065. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1066. MakeDataDescriptor(117, {}), MakeDataDescriptor(205, {1})));
  1067. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1068. MakeDataDescriptor(117, {}), MakeDataDescriptor(205, {2})));
  1069. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1070. MakeDataDescriptor(117, {}), MakeDataDescriptor(205, {3})));
  1071. TransformationCompositeConstruct make_uvec2(
  1072. 86, {18, 38}, MakeInstructionDescriptor(133, spv::Op::OpAccessChain, 0),
  1073. 206);
  1074. TransformationCompositeConstruct make_uvec2_bad(
  1075. 86, {18, 38}, MakeInstructionDescriptor(133, spv::Op::OpAccessChain, 200),
  1076. 206);
  1077. ASSERT_TRUE(make_uvec2.IsApplicable(context.get(), transformation_context));
  1078. ASSERT_FALSE(
  1079. make_uvec2_bad.IsApplicable(context.get(), transformation_context));
  1080. ApplyAndCheckFreshIds(make_uvec2, context.get(), &transformation_context);
  1081. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1082. kConsoleMessageConsumer));
  1083. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1084. MakeDataDescriptor(18, {}), MakeDataDescriptor(206, {0})));
  1085. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1086. MakeDataDescriptor(38, {}), MakeDataDescriptor(206, {1})));
  1087. TransformationCompositeConstruct make_uvec3(
  1088. 59, {14, 18, 136}, MakeInstructionDescriptor(137, spv::Op::OpReturn, 0),
  1089. 207);
  1090. // Bad because 1300 is not an id
  1091. TransformationCompositeConstruct make_uvec3_bad(
  1092. 59, {14, 18, 1300}, MakeInstructionDescriptor(137, spv::Op::OpReturn, 0),
  1093. 207);
  1094. ASSERT_TRUE(make_uvec3.IsApplicable(context.get(), transformation_context));
  1095. ASSERT_FALSE(
  1096. make_uvec3_bad.IsApplicable(context.get(), transformation_context));
  1097. ApplyAndCheckFreshIds(make_uvec3, context.get(), &transformation_context);
  1098. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1099. kConsoleMessageConsumer));
  1100. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1101. MakeDataDescriptor(14, {}), MakeDataDescriptor(207, {0})));
  1102. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1103. MakeDataDescriptor(18, {}), MakeDataDescriptor(207, {1})));
  1104. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1105. MakeDataDescriptor(136, {}), MakeDataDescriptor(207, {2})));
  1106. TransformationCompositeConstruct make_uvec4(
  1107. 131, {14, 18, 136, 136},
  1108. MakeInstructionDescriptor(137, spv::Op::OpAccessChain, 0), 208);
  1109. // Bad because 86 is the wrong type.
  1110. TransformationCompositeConstruct make_uvec4_bad(
  1111. 86, {14, 18, 136, 136},
  1112. MakeInstructionDescriptor(137, spv::Op::OpAccessChain, 0), 208);
  1113. ASSERT_TRUE(make_uvec4.IsApplicable(context.get(), transformation_context));
  1114. ASSERT_FALSE(
  1115. make_uvec4_bad.IsApplicable(context.get(), transformation_context));
  1116. ApplyAndCheckFreshIds(make_uvec4, context.get(), &transformation_context);
  1117. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1118. kConsoleMessageConsumer));
  1119. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1120. MakeDataDescriptor(14, {}), MakeDataDescriptor(208, {0})));
  1121. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1122. MakeDataDescriptor(18, {}), MakeDataDescriptor(208, {1})));
  1123. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1124. MakeDataDescriptor(136, {}), MakeDataDescriptor(208, {2})));
  1125. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1126. MakeDataDescriptor(136, {}), MakeDataDescriptor(208, {3})));
  1127. TransformationCompositeConstruct make_bvec2(
  1128. 102,
  1129. {
  1130. 111,
  1131. 41,
  1132. },
  1133. MakeInstructionDescriptor(75, spv::Op::OpAccessChain, 0), 209);
  1134. // Bad because 0 is not a valid base instruction id
  1135. TransformationCompositeConstruct make_bvec2_bad(
  1136. 102,
  1137. {
  1138. 111,
  1139. 41,
  1140. },
  1141. MakeInstructionDescriptor(0, spv::Op::OpExtInstImport, 0), 209);
  1142. ASSERT_TRUE(make_bvec2.IsApplicable(context.get(), transformation_context));
  1143. ASSERT_FALSE(
  1144. make_bvec2_bad.IsApplicable(context.get(), transformation_context));
  1145. ApplyAndCheckFreshIds(make_bvec2, context.get(), &transformation_context);
  1146. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1147. kConsoleMessageConsumer));
  1148. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1149. MakeDataDescriptor(111, {}), MakeDataDescriptor(209, {0})));
  1150. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1151. MakeDataDescriptor(41, {}), MakeDataDescriptor(209, {1})));
  1152. TransformationCompositeConstruct make_bvec3(
  1153. 93, {108, 73}, MakeInstructionDescriptor(108, spv::Op::OpStore, 0), 210);
  1154. // Bad because there are too many components for a bvec3
  1155. TransformationCompositeConstruct make_bvec3_bad(
  1156. 93, {108, 108}, MakeInstructionDescriptor(108, spv::Op::OpStore, 0), 210);
  1157. ASSERT_TRUE(make_bvec3.IsApplicable(context.get(), transformation_context));
  1158. ASSERT_FALSE(
  1159. make_bvec3_bad.IsApplicable(context.get(), transformation_context));
  1160. ApplyAndCheckFreshIds(make_bvec3, context.get(), &transformation_context);
  1161. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1162. kConsoleMessageConsumer));
  1163. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1164. MakeDataDescriptor(108, {0}), MakeDataDescriptor(210, {0})));
  1165. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1166. MakeDataDescriptor(108, {1}), MakeDataDescriptor(210, {1})));
  1167. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1168. MakeDataDescriptor(73, {}), MakeDataDescriptor(210, {2})));
  1169. TransformationCompositeConstruct make_bvec4(
  1170. 70, {108, 108}, MakeInstructionDescriptor(108, spv::Op::OpBranch, 0),
  1171. 211);
  1172. // Bad because 21 is a type, not a result id
  1173. TransformationCompositeConstruct make_bvec4_bad(
  1174. 70, {21, 108}, MakeInstructionDescriptor(108, spv::Op::OpBranch, 0), 211);
  1175. ASSERT_TRUE(make_bvec4.IsApplicable(context.get(), transformation_context));
  1176. ASSERT_FALSE(
  1177. make_bvec4_bad.IsApplicable(context.get(), transformation_context));
  1178. ApplyAndCheckFreshIds(make_bvec4, context.get(), &transformation_context);
  1179. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1180. kConsoleMessageConsumer));
  1181. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1182. MakeDataDescriptor(108, {0}), MakeDataDescriptor(211, {0})));
  1183. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1184. MakeDataDescriptor(108, {1}), MakeDataDescriptor(211, {1})));
  1185. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1186. MakeDataDescriptor(108, {0}), MakeDataDescriptor(211, {2})));
  1187. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1188. MakeDataDescriptor(108, {1}), MakeDataDescriptor(211, {3})));
  1189. std::string after_transformation = R"(
  1190. OpCapability Shader
  1191. %1 = OpExtInstImport "GLSL.std.450"
  1192. OpMemoryModel Logical GLSL450
  1193. OpEntryPoint Fragment %4 "main"
  1194. OpExecutionMode %4 OriginUpperLeft
  1195. OpSource ESSL 310
  1196. OpName %4 "main"
  1197. OpName %9 "v2"
  1198. OpName %27 "v3"
  1199. OpName %46 "v4"
  1200. OpName %53 "iv2"
  1201. OpName %61 "uv3"
  1202. OpName %72 "bv4"
  1203. OpName %88 "uv2"
  1204. OpName %95 "bv3"
  1205. OpName %104 "bv2"
  1206. OpName %116 "iv3"
  1207. OpName %124 "iv4"
  1208. OpName %133 "uv4"
  1209. %2 = OpTypeVoid
  1210. %3 = OpTypeFunction %2
  1211. %6 = OpTypeFloat 32
  1212. %7 = OpTypeVector %6 2
  1213. %8 = OpTypePointer Function %7
  1214. %10 = OpConstant %6 1
  1215. %11 = OpConstant %6 2
  1216. %12 = OpConstantComposite %7 %10 %11
  1217. %13 = OpTypeInt 32 0
  1218. %14 = OpConstant %13 0
  1219. %15 = OpTypePointer Function %6
  1220. %18 = OpConstant %13 1
  1221. %21 = OpTypeBool
  1222. %25 = OpTypeVector %6 3
  1223. %26 = OpTypePointer Function %25
  1224. %33 = OpConstant %6 3
  1225. %34 = OpConstant %6 -0.756802499
  1226. %38 = OpConstant %13 2
  1227. %44 = OpTypeVector %6 4
  1228. %45 = OpTypePointer Function %44
  1229. %50 = OpTypeInt 32 1
  1230. %51 = OpTypeVector %50 2
  1231. %52 = OpTypePointer Function %51
  1232. %57 = OpTypePointer Function %50
  1233. %59 = OpTypeVector %13 3
  1234. %60 = OpTypePointer Function %59
  1235. %65 = OpConstant %13 3
  1236. %67 = OpTypePointer Function %13
  1237. %70 = OpTypeVector %21 4
  1238. %71 = OpTypePointer Function %70
  1239. %73 = OpConstantTrue %21
  1240. %74 = OpTypePointer Function %21
  1241. %86 = OpTypeVector %13 2
  1242. %87 = OpTypePointer Function %86
  1243. %93 = OpTypeVector %21 3
  1244. %94 = OpTypePointer Function %93
  1245. %102 = OpTypeVector %21 2
  1246. %103 = OpTypePointer Function %102
  1247. %111 = OpConstantFalse %21
  1248. %114 = OpTypeVector %50 3
  1249. %115 = OpTypePointer Function %114
  1250. %117 = OpConstant %50 3
  1251. %122 = OpTypeVector %50 4
  1252. %123 = OpTypePointer Function %122
  1253. %131 = OpTypeVector %13 4
  1254. %132 = OpTypePointer Function %131
  1255. %4 = OpFunction %2 None %3
  1256. %5 = OpLabel
  1257. %9 = OpVariable %8 Function
  1258. %27 = OpVariable %26 Function
  1259. %46 = OpVariable %45 Function
  1260. %53 = OpVariable %52 Function
  1261. %61 = OpVariable %60 Function
  1262. %72 = OpVariable %71 Function
  1263. %88 = OpVariable %87 Function
  1264. %95 = OpVariable %94 Function
  1265. %104 = OpVariable %103 Function
  1266. %116 = OpVariable %115 Function
  1267. %124 = OpVariable %123 Function
  1268. %133 = OpVariable %132 Function
  1269. OpStore %9 %12
  1270. %206 = OpCompositeConstruct %86 %18 %38
  1271. %16 = OpAccessChain %15 %9 %14
  1272. %17 = OpLoad %6 %16
  1273. %19 = OpAccessChain %15 %9 %18
  1274. %20 = OpLoad %6 %19
  1275. %22 = OpFOrdGreaterThan %21 %17 %20
  1276. OpSelectionMerge %24 None
  1277. OpBranchConditional %22 %23 %101
  1278. %23 = OpLabel
  1279. %28 = OpAccessChain %15 %9 %14
  1280. %29 = OpLoad %6 %28
  1281. %30 = OpAccessChain %15 %9 %18
  1282. %31 = OpLoad %6 %30
  1283. %32 = OpFAdd %6 %29 %31
  1284. %201 = OpCompositeConstruct %25 %12 %32
  1285. %35 = OpCompositeConstruct %25 %32 %33 %34
  1286. OpStore %27 %35
  1287. %36 = OpAccessChain %15 %27 %14
  1288. %37 = OpLoad %6 %36
  1289. %39 = OpAccessChain %15 %27 %38
  1290. %40 = OpLoad %6 %39
  1291. %41 = OpFOrdLessThan %21 %37 %40
  1292. OpSelectionMerge %43 None
  1293. OpBranchConditional %41 %42 %69
  1294. %42 = OpLabel
  1295. %47 = OpAccessChain %15 %9 %18
  1296. %48 = OpLoad %6 %47
  1297. %49 = OpAccessChain %15 %46 %14
  1298. OpStore %49 %48
  1299. %54 = OpAccessChain %15 %27 %38
  1300. %55 = OpLoad %6 %54
  1301. %56 = OpConvertFToS %50 %55
  1302. %58 = OpAccessChain %57 %53 %14
  1303. OpStore %58 %56
  1304. %62 = OpAccessChain %15 %46 %14
  1305. %63 = OpLoad %6 %62
  1306. %64 = OpConvertFToU %13 %63
  1307. %205 = OpCompositeConstruct %122 %56 %117 %117 %117
  1308. %66 = OpIAdd %13 %64 %65
  1309. %204 = OpCompositeConstruct %114 %56 %117 %56
  1310. %68 = OpAccessChain %67 %61 %14
  1311. OpStore %68 %66
  1312. OpBranch %43
  1313. %69 = OpLabel
  1314. %202 = OpCompositeConstruct %44 %32 %32 %10 %11
  1315. %209 = OpCompositeConstruct %102 %111 %41
  1316. %75 = OpAccessChain %74 %72 %14
  1317. OpStore %75 %73
  1318. %76 = OpAccessChain %74 %72 %14
  1319. %77 = OpLoad %21 %76
  1320. %78 = OpLogicalNot %21 %77
  1321. %79 = OpAccessChain %74 %72 %18
  1322. OpStore %79 %78
  1323. %80 = OpAccessChain %74 %72 %14
  1324. %81 = OpLoad %21 %80
  1325. %82 = OpAccessChain %74 %72 %18
  1326. %83 = OpLoad %21 %82
  1327. %84 = OpLogicalAnd %21 %81 %83
  1328. %85 = OpAccessChain %74 %72 %38
  1329. OpStore %85 %84
  1330. %89 = OpAccessChain %67 %88 %14
  1331. %90 = OpLoad %13 %89
  1332. %91 = OpINotEqual %21 %90 %14
  1333. %92 = OpAccessChain %74 %72 %65
  1334. OpStore %92 %91
  1335. OpBranch %43
  1336. %43 = OpLabel
  1337. %96 = OpLoad %70 %72
  1338. %97 = OpCompositeExtract %21 %96 0
  1339. %98 = OpCompositeExtract %21 %96 1
  1340. %99 = OpCompositeExtract %21 %96 2
  1341. %100 = OpCompositeConstruct %93 %97 %98 %99
  1342. %200 = OpCompositeConstruct %7 %17 %11
  1343. OpStore %95 %100
  1344. OpBranch %24
  1345. %101 = OpLabel
  1346. %105 = OpAccessChain %67 %88 %14
  1347. %106 = OpLoad %13 %105
  1348. %107 = OpINotEqual %21 %106 %14
  1349. %108 = OpCompositeConstruct %102 %107 %107
  1350. %210 = OpCompositeConstruct %93 %108 %73
  1351. OpStore %104 %108
  1352. %211 = OpCompositeConstruct %70 %108 %108
  1353. OpBranch %24
  1354. %24 = OpLabel
  1355. %109 = OpAccessChain %74 %104 %18
  1356. %110 = OpLoad %21 %109
  1357. %112 = OpLogicalOr %21 %110 %111
  1358. %113 = OpAccessChain %74 %104 %14
  1359. OpStore %113 %112
  1360. %118 = OpAccessChain %57 %116 %14
  1361. OpStore %118 %117
  1362. %119 = OpAccessChain %57 %116 %14
  1363. %120 = OpLoad %50 %119
  1364. %121 = OpAccessChain %57 %53 %18
  1365. OpStore %121 %120
  1366. %125 = OpAccessChain %57 %116 %14
  1367. %126 = OpLoad %50 %125
  1368. %127 = OpAccessChain %57 %53 %18
  1369. %203 = OpCompositeConstruct %51 %126 %120
  1370. %128 = OpLoad %50 %127
  1371. %129 = OpIAdd %50 %126 %128
  1372. %130 = OpAccessChain %57 %124 %65
  1373. OpStore %130 %129
  1374. %134 = OpAccessChain %57 %116 %14
  1375. %135 = OpLoad %50 %134
  1376. %136 = OpBitcast %13 %135
  1377. %208 = OpCompositeConstruct %131 %14 %18 %136 %136
  1378. %137 = OpAccessChain %67 %133 %14
  1379. OpStore %137 %136
  1380. %207 = OpCompositeConstruct %59 %14 %18 %136
  1381. OpReturn
  1382. OpFunctionEnd
  1383. )";
  1384. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  1385. }
  1386. TEST(TransformationCompositeConstructTest, AddSynonymsForRelevantIds) {
  1387. std::string shader = R"(
  1388. OpCapability Shader
  1389. %1 = OpExtInstImport "GLSL.std.450"
  1390. OpMemoryModel Logical GLSL450
  1391. OpEntryPoint Fragment %4 "main"
  1392. OpExecutionMode %4 OriginUpperLeft
  1393. OpSource ESSL 310
  1394. %2 = OpTypeVoid
  1395. %3 = OpTypeFunction %2
  1396. %6 = OpTypeFloat 32
  1397. %7 = OpTypeVector %6 3
  1398. %8 = OpTypePointer Function %7
  1399. %10 = OpConstant %6 1
  1400. %11 = OpConstantComposite %7 %10 %10 %10
  1401. %17 = OpTypeVector %6 4
  1402. %18 = OpTypePointer Function %17
  1403. %21 = OpConstant %6 2
  1404. %32 = OpTypeMatrix %17 3
  1405. %33 = OpTypePointer Private %32
  1406. %34 = OpVariable %33 Private
  1407. %35 = OpTypeMatrix %7 4
  1408. %36 = OpTypePointer Private %35
  1409. %37 = OpVariable %36 Private
  1410. %38 = OpTypeVector %6 2
  1411. %39 = OpTypeInt 32 0
  1412. %40 = OpConstant %39 3
  1413. %41 = OpTypeArray %38 %40
  1414. %42 = OpTypePointer Private %41
  1415. %43 = OpVariable %42 Private
  1416. %100 = OpUndef %7
  1417. %101 = OpUndef %17
  1418. %4 = OpFunction %2 None %3
  1419. %5 = OpLabel
  1420. %9 = OpVariable %8 Function
  1421. %12 = OpVariable %8 Function
  1422. %14 = OpVariable %8 Function
  1423. %19 = OpVariable %18 Function
  1424. %26 = OpVariable %18 Function
  1425. %29 = OpVariable %18 Function
  1426. OpStore %9 %11
  1427. %13 = OpLoad %7 %9
  1428. OpStore %12 %13
  1429. %15 = OpLoad %7 %12
  1430. %16 = OpVectorShuffle %7 %15 %15 2 1 0
  1431. OpStore %14 %16
  1432. %20 = OpLoad %7 %14
  1433. %22 = OpCompositeExtract %6 %20 0
  1434. %23 = OpCompositeExtract %6 %20 1
  1435. %24 = OpCompositeExtract %6 %20 2
  1436. %25 = OpCompositeConstruct %17 %22 %23 %24 %21
  1437. OpStore %19 %25
  1438. %27 = OpLoad %17 %19
  1439. %28 = OpVectorShuffle %17 %27 %27 3 2 1 0
  1440. OpStore %26 %28
  1441. %30 = OpLoad %7 %9
  1442. %31 = OpVectorShuffle %17 %30 %30 0 0 1 1
  1443. OpStore %29 %31
  1444. OpReturn
  1445. OpFunctionEnd
  1446. )";
  1447. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1448. const auto consumer = nullptr;
  1449. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1450. spvtools::ValidatorOptions validator_options;
  1451. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1452. kConsoleMessageConsumer));
  1453. TransformationContext transformation_context(
  1454. MakeUnique<FactManager>(context.get()), validator_options);
  1455. TransformationCompositeConstruct transformation(
  1456. 32, {25, 28, 31}, MakeInstructionDescriptor(31, spv::Op::OpReturn, 0),
  1457. 200);
  1458. ASSERT_TRUE(
  1459. transformation.IsApplicable(context.get(), transformation_context));
  1460. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  1461. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1462. kConsoleMessageConsumer));
  1463. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1464. MakeDataDescriptor(25, {}), MakeDataDescriptor(200, {0})));
  1465. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1466. MakeDataDescriptor(28, {}), MakeDataDescriptor(200, {1})));
  1467. }
  1468. TEST(TransformationCompositeConstructTest, DontAddSynonymsForIrrelevantIds) {
  1469. std::string shader = R"(
  1470. OpCapability Shader
  1471. %1 = OpExtInstImport "GLSL.std.450"
  1472. OpMemoryModel Logical GLSL450
  1473. OpEntryPoint Fragment %4 "main"
  1474. OpExecutionMode %4 OriginUpperLeft
  1475. OpSource ESSL 310
  1476. %2 = OpTypeVoid
  1477. %3 = OpTypeFunction %2
  1478. %6 = OpTypeFloat 32
  1479. %7 = OpTypeVector %6 3
  1480. %8 = OpTypePointer Function %7
  1481. %10 = OpConstant %6 1
  1482. %11 = OpConstantComposite %7 %10 %10 %10
  1483. %17 = OpTypeVector %6 4
  1484. %18 = OpTypePointer Function %17
  1485. %21 = OpConstant %6 2
  1486. %32 = OpTypeMatrix %17 3
  1487. %33 = OpTypePointer Private %32
  1488. %34 = OpVariable %33 Private
  1489. %35 = OpTypeMatrix %7 4
  1490. %36 = OpTypePointer Private %35
  1491. %37 = OpVariable %36 Private
  1492. %38 = OpTypeVector %6 2
  1493. %39 = OpTypeInt 32 0
  1494. %40 = OpConstant %39 3
  1495. %41 = OpTypeArray %38 %40
  1496. %42 = OpTypePointer Private %41
  1497. %43 = OpVariable %42 Private
  1498. %100 = OpUndef %7
  1499. %101 = OpUndef %17
  1500. %4 = OpFunction %2 None %3
  1501. %5 = OpLabel
  1502. %9 = OpVariable %8 Function
  1503. %12 = OpVariable %8 Function
  1504. %14 = OpVariable %8 Function
  1505. %19 = OpVariable %18 Function
  1506. %26 = OpVariable %18 Function
  1507. %29 = OpVariable %18 Function
  1508. OpStore %9 %11
  1509. %13 = OpLoad %7 %9
  1510. OpStore %12 %13
  1511. %15 = OpLoad %7 %12
  1512. %16 = OpVectorShuffle %7 %15 %15 2 1 0
  1513. OpStore %14 %16
  1514. %20 = OpLoad %7 %14
  1515. %22 = OpCompositeExtract %6 %20 0
  1516. %23 = OpCompositeExtract %6 %20 1
  1517. %24 = OpCompositeExtract %6 %20 2
  1518. %25 = OpCompositeConstruct %17 %22 %23 %24 %21
  1519. OpStore %19 %25
  1520. %27 = OpLoad %17 %19
  1521. %28 = OpVectorShuffle %17 %27 %27 3 2 1 0
  1522. OpStore %26 %28
  1523. %30 = OpLoad %7 %9
  1524. %31 = OpVectorShuffle %17 %30 %30 0 0 1 1
  1525. OpStore %29 %31
  1526. OpReturn
  1527. OpFunctionEnd
  1528. )";
  1529. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1530. const auto consumer = nullptr;
  1531. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1532. spvtools::ValidatorOptions validator_options;
  1533. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1534. kConsoleMessageConsumer));
  1535. TransformationContext transformation_context(
  1536. MakeUnique<FactManager>(context.get()), validator_options);
  1537. transformation_context.GetFactManager()->AddFactIdIsIrrelevant(25);
  1538. TransformationCompositeConstruct transformation(
  1539. 32, {25, 28, 31}, MakeInstructionDescriptor(31, spv::Op::OpReturn, 0),
  1540. 200);
  1541. ASSERT_TRUE(
  1542. transformation.IsApplicable(context.get(), transformation_context));
  1543. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  1544. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1545. kConsoleMessageConsumer));
  1546. ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
  1547. MakeDataDescriptor(25, {}), MakeDataDescriptor(200, {0})));
  1548. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1549. MakeDataDescriptor(28, {}), MakeDataDescriptor(200, {1})));
  1550. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1551. MakeDataDescriptor(31, {}), MakeDataDescriptor(200, {2})));
  1552. }
  1553. TEST(TransformationCompositeConstructTest, DontAddSynonymsInDeadBlock) {
  1554. std::string shader = R"(
  1555. OpCapability Shader
  1556. %1 = OpExtInstImport "GLSL.std.450"
  1557. OpMemoryModel Logical GLSL450
  1558. OpEntryPoint Fragment %4 "main"
  1559. OpExecutionMode %4 OriginUpperLeft
  1560. OpSource ESSL 320
  1561. %2 = OpTypeVoid
  1562. %3 = OpTypeFunction %2
  1563. %6 = OpTypeInt 32 1
  1564. %7 = OpTypeVector %6 2
  1565. %8 = OpTypePointer Function %7
  1566. %10 = OpConstant %6 0
  1567. %11 = OpConstant %6 1
  1568. %12 = OpConstantComposite %7 %10 %11
  1569. %13 = OpTypeBool
  1570. %14 = OpConstantFalse %13
  1571. %4 = OpFunction %2 None %3
  1572. %5 = OpLabel
  1573. %9 = OpVariable %8 Function
  1574. OpStore %9 %12
  1575. OpSelectionMerge %16 None
  1576. OpBranchConditional %14 %15 %16
  1577. %15 = OpLabel
  1578. OpBranch %16
  1579. %16 = OpLabel
  1580. OpReturn
  1581. OpFunctionEnd
  1582. )";
  1583. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1584. const auto consumer = nullptr;
  1585. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1586. spvtools::ValidatorOptions validator_options;
  1587. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1588. kConsoleMessageConsumer));
  1589. TransformationContext transformation_context(
  1590. MakeUnique<FactManager>(context.get()), validator_options);
  1591. transformation_context.GetFactManager()->AddFactBlockIsDead(15);
  1592. TransformationCompositeConstruct transformation(
  1593. 7, {10, 11}, MakeInstructionDescriptor(15, spv::Op::OpBranch, 0), 100);
  1594. ASSERT_TRUE(
  1595. transformation.IsApplicable(context.get(), transformation_context));
  1596. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  1597. ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
  1598. MakeDataDescriptor(100, {0}), MakeDataDescriptor(10, {})));
  1599. ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
  1600. MakeDataDescriptor(100, {1}), MakeDataDescriptor(11, {})));
  1601. }
  1602. TEST(TransformationCompositeConstructTest, OneIrrelevantComponent) {
  1603. std::string shader = R"(
  1604. OpCapability Shader
  1605. %1 = OpExtInstImport "GLSL.std.450"
  1606. OpMemoryModel Logical GLSL450
  1607. OpEntryPoint Fragment %4 "main"
  1608. OpExecutionMode %4 OriginUpperLeft
  1609. OpSource ESSL 320
  1610. %2 = OpTypeVoid
  1611. %3 = OpTypeFunction %2
  1612. %6 = OpTypeInt 32 1
  1613. %7 = OpTypeStruct %6 %6 %6
  1614. %8 = OpConstant %6 42
  1615. %9 = OpConstant %6 50
  1616. %10 = OpConstant %6 51
  1617. %4 = OpFunction %2 None %3
  1618. %5 = OpLabel
  1619. OpReturn
  1620. OpFunctionEnd
  1621. )";
  1622. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1623. const auto consumer = nullptr;
  1624. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1625. spvtools::ValidatorOptions validator_options;
  1626. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1627. kConsoleMessageConsumer));
  1628. TransformationContext transformation_context(
  1629. MakeUnique<FactManager>(context.get()), validator_options);
  1630. transformation_context.GetFactManager()->AddFactIdIsIrrelevant(8);
  1631. TransformationCompositeConstruct transformation(
  1632. 7, {8, 9, 10}, MakeInstructionDescriptor(5, spv::Op::OpReturn, 0), 100);
  1633. ASSERT_TRUE(
  1634. transformation.IsApplicable(context.get(), transformation_context));
  1635. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  1636. ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
  1637. MakeDataDescriptor(100, {0}), MakeDataDescriptor(8, {})));
  1638. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1639. MakeDataDescriptor(100, {1}), MakeDataDescriptor(9, {})));
  1640. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1641. MakeDataDescriptor(100, {2}), MakeDataDescriptor(10, {})));
  1642. }
  1643. TEST(TransformationCompositeConstructTest, IrrelevantVec2ThenFloat) {
  1644. std::string shader = R"(
  1645. OpCapability Shader
  1646. %1 = OpExtInstImport "GLSL.std.450"
  1647. OpMemoryModel Logical GLSL450
  1648. OpEntryPoint Fragment %4 "main"
  1649. OpExecutionMode %4 OriginUpperLeft
  1650. OpSource ESSL 320
  1651. %2 = OpTypeVoid
  1652. %3 = OpTypeFunction %2
  1653. %6 = OpTypeFloat 32
  1654. %7 = OpTypeVector %6 2
  1655. %8 = OpTypeVector %6 3
  1656. %9 = OpConstant %6 0
  1657. %11 = OpConstant %6 1
  1658. %12 = OpConstant %6 2
  1659. %10 = OpConstantComposite %7 %11 %12
  1660. %4 = OpFunction %2 None %3
  1661. %5 = OpLabel
  1662. OpReturn
  1663. OpFunctionEnd
  1664. )";
  1665. const auto env = SPV_ENV_UNIVERSAL_1_3;
  1666. const auto consumer = nullptr;
  1667. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  1668. spvtools::ValidatorOptions validator_options;
  1669. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  1670. kConsoleMessageConsumer));
  1671. TransformationContext transformation_context(
  1672. MakeUnique<FactManager>(context.get()), validator_options);
  1673. transformation_context.GetFactManager()->AddFactIdIsIrrelevant(10);
  1674. TransformationCompositeConstruct transformation(
  1675. 8, {10, 9}, MakeInstructionDescriptor(5, spv::Op::OpReturn, 0), 100);
  1676. ASSERT_TRUE(
  1677. transformation.IsApplicable(context.get(), transformation_context));
  1678. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  1679. ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
  1680. MakeDataDescriptor(100, {0}), MakeDataDescriptor(10, {0})));
  1681. ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
  1682. MakeDataDescriptor(100, {1}), MakeDataDescriptor(10, {1})));
  1683. ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
  1684. MakeDataDescriptor(100, {2}), MakeDataDescriptor(9, {})));
  1685. ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
  1686. MakeDataDescriptor(100, {1}), MakeDataDescriptor(9, {})));
  1687. }
  1688. } // namespace
  1689. } // namespace fuzz
  1690. } // namespace spvtools