transformation_store_test.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625
  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_store.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(TransformationStoreTest, BasicTest) {
  23. std::string shader = R"(
  24. OpCapability Shader
  25. OpCapability VariablePointers
  26. %1 = OpExtInstImport "GLSL.std.450"
  27. OpMemoryModel Logical GLSL450
  28. OpEntryPoint Fragment %4 "main" %92 %52 %53
  29. OpExecutionMode %4 OriginUpperLeft
  30. OpSource ESSL 310
  31. OpDecorate %92 BuiltIn FragCoord
  32. %2 = OpTypeVoid
  33. %3 = OpTypeFunction %2
  34. %6 = OpTypeInt 32 1
  35. %7 = OpTypeFloat 32
  36. %8 = OpTypeStruct %6 %7
  37. %9 = OpTypePointer Function %8
  38. %10 = OpTypeFunction %6 %9
  39. %14 = OpConstant %6 0
  40. %15 = OpTypePointer Function %6
  41. %51 = OpTypePointer Private %6
  42. %21 = OpConstant %6 2
  43. %23 = OpConstant %6 1
  44. %24 = OpConstant %7 1
  45. %25 = OpTypePointer Function %7
  46. %50 = OpTypePointer Private %7
  47. %34 = OpTypeBool
  48. %35 = OpConstantFalse %34
  49. %60 = OpConstantNull %50
  50. %52 = OpVariable %50 Private
  51. %53 = OpVariable %51 Private
  52. %80 = OpConstantComposite %8 %21 %24
  53. %90 = OpTypeVector %7 4
  54. %91 = OpTypePointer Input %90
  55. %92 = OpVariable %91 Input
  56. %93 = OpConstantComposite %90 %24 %24 %24 %24
  57. %4 = OpFunction %2 None %3
  58. %5 = OpLabel
  59. %20 = OpVariable %9 Function
  60. %27 = OpVariable %9 Function ; irrelevant
  61. %22 = OpAccessChain %15 %20 %14
  62. %44 = OpCopyObject %9 %20
  63. %26 = OpAccessChain %25 %20 %23
  64. %29 = OpFunctionCall %6 %12 %27
  65. %30 = OpAccessChain %15 %20 %14
  66. %45 = OpCopyObject %15 %30
  67. %81 = OpCopyObject %9 %27 ; irrelevant
  68. %33 = OpAccessChain %15 %20 %14
  69. OpSelectionMerge %37 None
  70. OpBranchConditional %35 %36 %37
  71. %36 = OpLabel
  72. %38 = OpAccessChain %15 %20 %14
  73. %40 = OpAccessChain %15 %20 %14
  74. %43 = OpAccessChain %15 %20 %14
  75. %82 = OpCopyObject %9 %27 ; irrelevant
  76. OpBranch %37
  77. %37 = OpLabel
  78. OpReturn
  79. OpFunctionEnd
  80. %12 = OpFunction %6 None %10
  81. %11 = OpFunctionParameter %9 ; irrelevant
  82. %13 = OpLabel
  83. %46 = OpCopyObject %9 %11 ; irrelevant
  84. %16 = OpAccessChain %15 %11 %14 ; irrelevant
  85. %95 = OpCopyObject %8 %80
  86. OpReturnValue %21
  87. OpFunctionEnd
  88. )";
  89. const auto env = SPV_ENV_UNIVERSAL_1_4;
  90. const auto consumer = nullptr;
  91. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  92. spvtools::ValidatorOptions validator_options;
  93. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  94. kConsoleMessageConsumer));
  95. TransformationContext transformation_context(
  96. MakeUnique<FactManager>(context.get()), validator_options);
  97. transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
  98. 27);
  99. transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
  100. 11);
  101. transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
  102. 46);
  103. transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
  104. 16);
  105. transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
  106. 52);
  107. transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
  108. 81);
  109. transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
  110. 82);
  111. transformation_context.GetFactManager()->AddFactBlockIsDead(36);
  112. // Variables with pointee types:
  113. // 52 - ptr_to(7)
  114. // 53 - ptr_to(6)
  115. // 20 - ptr_to(8)
  116. // 27 - ptr_to(8) - irrelevant
  117. // 92 - ptr_to(90) - read only
  118. // Access chains with pointee type:
  119. // 22 - ptr_to(6)
  120. // 26 - ptr_to(6)
  121. // 30 - ptr_to(6)
  122. // 33 - ptr_to(6)
  123. // 38 - ptr_to(6)
  124. // 40 - ptr_to(6)
  125. // 43 - ptr_to(6)
  126. // 16 - ptr_to(6) - irrelevant
  127. // Copied object with pointee type:
  128. // 44 - ptr_to(8)
  129. // 45 - ptr_to(6)
  130. // 46 - ptr_to(8) - irrelevant
  131. // 81 - ptr_to(8) - irrelevant
  132. // 82 - ptr_to(8) - irrelevant
  133. // Function parameters with pointee type:
  134. // 11 - ptr_to(8) - irrelevant
  135. // Pointers that cannot be used:
  136. // 60 - null
  137. // 61 - undefined
  138. // Bad: attempt to store to 11 from outside its function
  139. ASSERT_FALSE(TransformationStore(
  140. 11, false, 0, 0, 80,
  141. MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
  142. .IsApplicable(context.get(), transformation_context));
  143. // Bad: pointer is not available
  144. ASSERT_FALSE(TransformationStore(
  145. 81, false, 0, 0, 80,
  146. MakeInstructionDescriptor(45, spv::Op::OpCopyObject, 0))
  147. .IsApplicable(context.get(), transformation_context));
  148. // Bad: attempt to insert before OpVariable
  149. ASSERT_FALSE(
  150. TransformationStore(52, false, 0, 0, 24,
  151. MakeInstructionDescriptor(27, spv::Op::OpVariable, 0))
  152. .IsApplicable(context.get(), transformation_context));
  153. // Bad: pointer id does not exist
  154. ASSERT_FALSE(TransformationStore(
  155. 1000, false, 0, 0, 24,
  156. MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
  157. .IsApplicable(context.get(), transformation_context));
  158. // Bad: pointer id exists but does not have a type
  159. ASSERT_FALSE(TransformationStore(
  160. 5, false, 0, 0, 24,
  161. MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
  162. .IsApplicable(context.get(), transformation_context));
  163. // Bad: pointer id exists and has a type, but is not a pointer
  164. ASSERT_FALSE(TransformationStore(
  165. 24, false, 0, 0, 24,
  166. MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
  167. .IsApplicable(context.get(), transformation_context));
  168. // Bad: attempt to store to a null pointer
  169. ASSERT_FALSE(TransformationStore(
  170. 60, false, 0, 0, 24,
  171. MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
  172. .IsApplicable(context.get(), transformation_context));
  173. // Bad: attempt to store to an undefined pointer
  174. ASSERT_FALSE(TransformationStore(
  175. 61, false, 0, 0, 21,
  176. MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
  177. .IsApplicable(context.get(), transformation_context));
  178. // Bad: %82 is not available at the program point
  179. ASSERT_FALSE(
  180. TransformationStore(82, false, 0, 0, 80,
  181. MakeInstructionDescriptor(37, spv::Op::OpReturn, 0))
  182. .IsApplicable(context.get(), transformation_context));
  183. // Bad: value id does not exist
  184. ASSERT_FALSE(TransformationStore(
  185. 27, false, 0, 0, 1000,
  186. MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
  187. .IsApplicable(context.get(), transformation_context));
  188. // Bad: value id exists but does not have a type
  189. ASSERT_FALSE(TransformationStore(
  190. 27, false, 0, 0, 15,
  191. MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
  192. .IsApplicable(context.get(), transformation_context));
  193. // Bad: value id exists but has the wrong type
  194. ASSERT_FALSE(TransformationStore(
  195. 27, false, 0, 0, 14,
  196. MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0))
  197. .IsApplicable(context.get(), transformation_context));
  198. // Bad: attempt to store to read-only variable
  199. ASSERT_FALSE(TransformationStore(
  200. 92, false, 0, 0, 93,
  201. MakeInstructionDescriptor(40, spv::Op::OpAccessChain, 0))
  202. .IsApplicable(context.get(), transformation_context));
  203. // Bad: value is not available
  204. ASSERT_FALSE(TransformationStore(
  205. 27, false, 0, 0, 95,
  206. MakeInstructionDescriptor(40, spv::Op::OpAccessChain, 0))
  207. .IsApplicable(context.get(), transformation_context));
  208. // Bad: variable being stored to does not have an irrelevant pointee value,
  209. // and the store is not in a dead block.
  210. ASSERT_FALSE(TransformationStore(
  211. 20, false, 0, 0, 95,
  212. MakeInstructionDescriptor(45, spv::Op::OpCopyObject, 0))
  213. .IsApplicable(context.get(), transformation_context));
  214. // The described instruction does not exist.
  215. ASSERT_FALSE(TransformationStore(
  216. 27, false, 0, 0, 80,
  217. MakeInstructionDescriptor(1000, spv::Op::OpAccessChain, 0))
  218. .IsApplicable(context.get(), transformation_context));
  219. {
  220. // Store to irrelevant variable from dead block.
  221. TransformationStore transformation(
  222. 27, false, 0, 0, 80,
  223. MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0));
  224. ASSERT_TRUE(
  225. transformation.IsApplicable(context.get(), transformation_context));
  226. ApplyAndCheckFreshIds(transformation, context.get(),
  227. &transformation_context);
  228. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
  229. context.get(), validator_options, kConsoleMessageConsumer));
  230. }
  231. {
  232. // Store to irrelevant variable from live block.
  233. TransformationStore transformation(
  234. 11, false, 0, 0, 95,
  235. MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0));
  236. ASSERT_TRUE(
  237. transformation.IsApplicable(context.get(), transformation_context));
  238. ApplyAndCheckFreshIds(transformation, context.get(),
  239. &transformation_context);
  240. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
  241. context.get(), validator_options, kConsoleMessageConsumer));
  242. }
  243. {
  244. // Store to irrelevant variable from live block.
  245. TransformationStore transformation(
  246. 46, false, 0, 0, 80,
  247. MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0));
  248. ASSERT_TRUE(
  249. transformation.IsApplicable(context.get(), transformation_context));
  250. ApplyAndCheckFreshIds(transformation, context.get(),
  251. &transformation_context);
  252. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
  253. context.get(), validator_options, kConsoleMessageConsumer));
  254. }
  255. {
  256. // Store to irrelevant variable from live block.
  257. TransformationStore transformation(
  258. 16, false, 0, 0, 21,
  259. MakeInstructionDescriptor(95, spv::Op::OpReturnValue, 0));
  260. ASSERT_TRUE(
  261. transformation.IsApplicable(context.get(), transformation_context));
  262. ApplyAndCheckFreshIds(transformation, context.get(),
  263. &transformation_context);
  264. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
  265. context.get(), validator_options, kConsoleMessageConsumer));
  266. }
  267. {
  268. // Store to non-irrelevant variable from dead block.
  269. TransformationStore transformation(
  270. 53, false, 0, 0, 21,
  271. MakeInstructionDescriptor(38, spv::Op::OpAccessChain, 0));
  272. ASSERT_TRUE(
  273. transformation.IsApplicable(context.get(), transformation_context));
  274. ApplyAndCheckFreshIds(transformation, context.get(),
  275. &transformation_context);
  276. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
  277. context.get(), validator_options, kConsoleMessageConsumer));
  278. }
  279. std::string after_transformation = R"(
  280. OpCapability Shader
  281. OpCapability VariablePointers
  282. %1 = OpExtInstImport "GLSL.std.450"
  283. OpMemoryModel Logical GLSL450
  284. OpEntryPoint Fragment %4 "main" %92 %52 %53
  285. OpExecutionMode %4 OriginUpperLeft
  286. OpSource ESSL 310
  287. OpDecorate %92 BuiltIn FragCoord
  288. %2 = OpTypeVoid
  289. %3 = OpTypeFunction %2
  290. %6 = OpTypeInt 32 1
  291. %7 = OpTypeFloat 32
  292. %8 = OpTypeStruct %6 %7
  293. %9 = OpTypePointer Function %8
  294. %10 = OpTypeFunction %6 %9
  295. %14 = OpConstant %6 0
  296. %15 = OpTypePointer Function %6
  297. %51 = OpTypePointer Private %6
  298. %21 = OpConstant %6 2
  299. %23 = OpConstant %6 1
  300. %24 = OpConstant %7 1
  301. %25 = OpTypePointer Function %7
  302. %50 = OpTypePointer Private %7
  303. %34 = OpTypeBool
  304. %35 = OpConstantFalse %34
  305. %60 = OpConstantNull %50
  306. %52 = OpVariable %50 Private
  307. %53 = OpVariable %51 Private
  308. %80 = OpConstantComposite %8 %21 %24
  309. %90 = OpTypeVector %7 4
  310. %91 = OpTypePointer Input %90
  311. %92 = OpVariable %91 Input
  312. %93 = OpConstantComposite %90 %24 %24 %24 %24
  313. %4 = OpFunction %2 None %3
  314. %5 = OpLabel
  315. %20 = OpVariable %9 Function
  316. %27 = OpVariable %9 Function ; irrelevant
  317. %22 = OpAccessChain %15 %20 %14
  318. %44 = OpCopyObject %9 %20
  319. %26 = OpAccessChain %25 %20 %23
  320. %29 = OpFunctionCall %6 %12 %27
  321. %30 = OpAccessChain %15 %20 %14
  322. %45 = OpCopyObject %15 %30
  323. %81 = OpCopyObject %9 %27 ; irrelevant
  324. %33 = OpAccessChain %15 %20 %14
  325. OpSelectionMerge %37 None
  326. OpBranchConditional %35 %36 %37
  327. %36 = OpLabel
  328. OpStore %27 %80
  329. OpStore %53 %21
  330. %38 = OpAccessChain %15 %20 %14
  331. %40 = OpAccessChain %15 %20 %14
  332. %43 = OpAccessChain %15 %20 %14
  333. %82 = OpCopyObject %9 %27 ; irrelevant
  334. OpBranch %37
  335. %37 = OpLabel
  336. OpReturn
  337. OpFunctionEnd
  338. %12 = OpFunction %6 None %10
  339. %11 = OpFunctionParameter %9 ; irrelevant
  340. %13 = OpLabel
  341. %46 = OpCopyObject %9 %11 ; irrelevant
  342. %16 = OpAccessChain %15 %11 %14 ; irrelevant
  343. %95 = OpCopyObject %8 %80
  344. OpStore %11 %95
  345. OpStore %46 %80
  346. OpStore %16 %21
  347. OpReturnValue %21
  348. OpFunctionEnd
  349. )";
  350. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  351. }
  352. TEST(TransformationStoreTest, DoNotAllowStoresToReadOnlyMemory) {
  353. std::string shader = R"(
  354. OpCapability Shader
  355. %1 = OpExtInstImport "GLSL.std.450"
  356. OpMemoryModel Logical GLSL450
  357. OpEntryPoint Fragment %4 "main"
  358. OpExecutionMode %4 OriginUpperLeft
  359. OpSource ESSL 320
  360. OpMemberDecorate %10 0 Offset 0
  361. OpMemberDecorate %10 1 Offset 4
  362. OpDecorate %10 Block
  363. OpMemberDecorate %23 0 Offset 0
  364. OpDecorate %23 Block
  365. OpDecorate %25 DescriptorSet 0
  366. OpDecorate %25 Binding 0
  367. %2 = OpTypeVoid
  368. %3 = OpTypeFunction %2
  369. %6 = OpTypeInt 32 1
  370. %7 = OpTypePointer Function %6
  371. %9 = OpTypeFloat 32
  372. %10 = OpTypeStruct %6 %9
  373. %11 = OpTypePointer PushConstant %10
  374. %12 = OpVariable %11 PushConstant
  375. %13 = OpConstant %6 0
  376. %14 = OpTypePointer PushConstant %6
  377. %17 = OpConstant %6 1
  378. %18 = OpTypePointer PushConstant %9
  379. %23 = OpTypeStruct %9
  380. %24 = OpTypePointer UniformConstant %23
  381. %25 = OpVariable %24 UniformConstant
  382. %26 = OpTypePointer UniformConstant %9
  383. %50 = OpConstant %9 0
  384. %4 = OpFunction %2 None %3
  385. %5 = OpLabel
  386. %15 = OpAccessChain %14 %12 %13
  387. %19 = OpAccessChain %18 %12 %17
  388. %27 = OpAccessChain %26 %25 %13
  389. OpReturn
  390. OpFunctionEnd
  391. )";
  392. const auto env = SPV_ENV_UNIVERSAL_1_3;
  393. const auto consumer = nullptr;
  394. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  395. spvtools::ValidatorOptions validator_options;
  396. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  397. kConsoleMessageConsumer));
  398. TransformationContext transformation_context(
  399. MakeUnique<FactManager>(context.get()), validator_options);
  400. transformation_context.GetFactManager()->AddFactBlockIsDead(5);
  401. ASSERT_FALSE(
  402. TransformationStore(15, false, 0, 0, 13,
  403. MakeInstructionDescriptor(27, spv::Op::OpReturn, 0))
  404. .IsApplicable(context.get(), transformation_context));
  405. ASSERT_FALSE(
  406. TransformationStore(19, false, 0, 0, 50,
  407. MakeInstructionDescriptor(27, spv::Op::OpReturn, 0))
  408. .IsApplicable(context.get(), transformation_context));
  409. ASSERT_FALSE(
  410. TransformationStore(27, false, 0, 0, 50,
  411. MakeInstructionDescriptor(27, spv::Op::OpReturn, 0))
  412. .IsApplicable(context.get(), transformation_context));
  413. }
  414. TEST(TransformationStoreTest, SupportAtomicStore) {
  415. const std::string shader = R"(
  416. OpCapability Shader
  417. OpCapability Int8
  418. %1 = OpExtInstImport "GLSL.std.450"
  419. OpMemoryModel Logical GLSL450
  420. OpEntryPoint Fragment %4 "main"
  421. OpExecutionMode %4 OriginUpperLeft
  422. OpSource ESSL 320
  423. %2 = OpTypeVoid
  424. %3 = OpTypeFunction %2
  425. %6 = OpTypeInt 32 1
  426. %7 = OpTypeInt 8 1
  427. %9 = OpTypeInt 32 0
  428. %26 = OpTypeFloat 32
  429. %8 = OpTypeStruct %6
  430. %10 = OpTypePointer StorageBuffer %8
  431. %11 = OpVariable %10 StorageBuffer
  432. %19 = OpConstant %26 0
  433. %18 = OpConstant %9 1
  434. %12 = OpConstant %6 0
  435. %13 = OpTypePointer StorageBuffer %6
  436. %15 = OpConstant %6 4
  437. %16 = OpConstant %6 7
  438. %17 = OpConstant %7 4
  439. %20 = OpConstant %9 64
  440. %21 = OpConstant %6 15
  441. %4 = OpFunction %2 None %3
  442. %5 = OpLabel
  443. %14 = OpAccessChain %13 %11 %12
  444. %24 = OpAccessChain %13 %11 %12
  445. OpReturn
  446. OpFunctionEnd
  447. )";
  448. const auto env = SPV_ENV_UNIVERSAL_1_3;
  449. const auto consumer = nullptr;
  450. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  451. spvtools::ValidatorOptions validator_options;
  452. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  453. kConsoleMessageConsumer));
  454. TransformationContext transformation_context(
  455. MakeUnique<FactManager>(context.get()), validator_options);
  456. transformation_context.GetFactManager()->AddFactValueOfPointeeIsIrrelevant(
  457. 14);
  458. // Bad: id 100 of memory scope instruction does not exist.
  459. ASSERT_FALSE(TransformationStore(
  460. 14, true, 100, 20, 21,
  461. MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
  462. .IsApplicable(context.get(), transformation_context));
  463. // Bad: id 100 of memory semantics instruction does not exist.
  464. ASSERT_FALSE(TransformationStore(
  465. 14, true, 15, 100, 21,
  466. MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
  467. .IsApplicable(context.get(), transformation_context));
  468. // Bad: memory scope should be |OpConstant| opcode.
  469. ASSERT_FALSE(TransformationStore(
  470. 14, true, 5, 20, 21,
  471. MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
  472. .IsApplicable(context.get(), transformation_context));
  473. // Bad: memory semantics should be |OpConstant| opcode.
  474. ASSERT_FALSE(TransformationStore(
  475. 14, true, 15, 5, 21,
  476. MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
  477. .IsApplicable(context.get(), transformation_context));
  478. // Bad: The memory scope instruction must have an Integer operand.
  479. ASSERT_FALSE(TransformationStore(
  480. 14, true, 15, 19, 21,
  481. MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
  482. .IsApplicable(context.get(), transformation_context));
  483. // Bad: The memory memory semantics instruction must have an Integer operand.
  484. ASSERT_FALSE(TransformationStore(
  485. 14, true, 19, 20, 21,
  486. MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
  487. .IsApplicable(context.get(), transformation_context));
  488. // Bad: Integer size of the memory scope must be equal to 32 bits.
  489. ASSERT_FALSE(TransformationStore(
  490. 14, true, 17, 20, 21,
  491. MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
  492. .IsApplicable(context.get(), transformation_context));
  493. // Bad: Integer size of memory semantics must be equal to 32 bits.
  494. ASSERT_FALSE(TransformationStore(
  495. 14, true, 15, 17, 21,
  496. MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
  497. .IsApplicable(context.get(), transformation_context));
  498. // Bad: memory scope value must be 4 (spv::Scope::Invocation).
  499. ASSERT_FALSE(TransformationStore(
  500. 14, true, 16, 20, 21,
  501. MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
  502. .IsApplicable(context.get(), transformation_context));
  503. // Bad: memory semantics value must be either:
  504. // 64 (SpvMemorySemanticsUniformMemoryMask)
  505. // 256 (SpvMemorySemanticsWorkgroupMemoryMask)
  506. ASSERT_FALSE(TransformationStore(
  507. 14, true, 15, 16, 21,
  508. MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0))
  509. .IsApplicable(context.get(), transformation_context));
  510. // Bad: The described instruction does not exist
  511. ASSERT_FALSE(TransformationStore(
  512. 14, true, 15, 20, 21,
  513. MakeInstructionDescriptor(150, spv::Op::OpAccessChain, 0))
  514. .IsApplicable(context.get(), transformation_context));
  515. // Bad: Can't insert OpAccessChain before the id 15 of memory scope.
  516. ASSERT_FALSE(TransformationStore(
  517. 14, true, 15, 20, 21,
  518. MakeInstructionDescriptor(15, spv::Op::OpAccessChain, 0))
  519. .IsApplicable(context.get(), transformation_context));
  520. // Bad: Can't insert OpAccessChain before the id 20 of memory semantics.
  521. ASSERT_FALSE(TransformationStore(
  522. 14, true, 15, 20, 21,
  523. MakeInstructionDescriptor(20, spv::Op::OpAccessChain, 0))
  524. .IsApplicable(context.get(), transformation_context));
  525. // Successful transformations.
  526. {
  527. TransformationStore transformation(
  528. 14, true, 15, 20, 21,
  529. MakeInstructionDescriptor(24, spv::Op::OpReturn, 0));
  530. ASSERT_TRUE(
  531. transformation.IsApplicable(context.get(), transformation_context));
  532. ApplyAndCheckFreshIds(transformation, context.get(),
  533. &transformation_context);
  534. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(
  535. context.get(), validator_options, kConsoleMessageConsumer));
  536. }
  537. const std::string after_transformation = R"(
  538. OpCapability Shader
  539. OpCapability Int8
  540. %1 = OpExtInstImport "GLSL.std.450"
  541. OpMemoryModel Logical GLSL450
  542. OpEntryPoint Fragment %4 "main"
  543. OpExecutionMode %4 OriginUpperLeft
  544. OpSource ESSL 320
  545. %2 = OpTypeVoid
  546. %3 = OpTypeFunction %2
  547. %6 = OpTypeInt 32 1
  548. %7 = OpTypeInt 8 1
  549. %9 = OpTypeInt 32 0
  550. %26 = OpTypeFloat 32
  551. %8 = OpTypeStruct %6
  552. %10 = OpTypePointer StorageBuffer %8
  553. %11 = OpVariable %10 StorageBuffer
  554. %19 = OpConstant %26 0
  555. %18 = OpConstant %9 1
  556. %12 = OpConstant %6 0
  557. %13 = OpTypePointer StorageBuffer %6
  558. %15 = OpConstant %6 4
  559. %16 = OpConstant %6 7
  560. %17 = OpConstant %7 4
  561. %20 = OpConstant %9 64
  562. %21 = OpConstant %6 15
  563. %4 = OpFunction %2 None %3
  564. %5 = OpLabel
  565. %14 = OpAccessChain %13 %11 %12
  566. %24 = OpAccessChain %13 %11 %12
  567. OpAtomicStore %14 %15 %20 %21
  568. OpReturn
  569. OpFunctionEnd
  570. )";
  571. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  572. }
  573. } // namespace
  574. } // namespace fuzz
  575. } // namespace spvtools