transformation_equation_instruction_test.cpp 69 KB

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