transformation_replace_irrelevant_id_test.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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_replace_irrelevant_id.h"
  15. #include "gtest/gtest.h"
  16. #include "source/fuzz/fuzzer_util.h"
  17. #include "source/fuzz/id_use_descriptor.h"
  18. #include "source/fuzz/instruction_descriptor.h"
  19. #include "test/fuzz/fuzz_test_util.h"
  20. namespace spvtools {
  21. namespace fuzz {
  22. namespace {
  23. const std::string shader = R"(
  24. OpCapability Shader
  25. %1 = OpExtInstImport "GLSL.std.450"
  26. OpMemoryModel Logical GLSL450
  27. OpEntryPoint Fragment %2 "main"
  28. OpExecutionMode %2 OriginUpperLeft
  29. OpSource ESSL 310
  30. OpName %2 "main"
  31. OpName %3 "a"
  32. OpName %4 "b"
  33. %5 = OpTypeVoid
  34. %6 = OpTypeFunction %5
  35. %7 = OpTypeBool
  36. %8 = OpConstantTrue %7
  37. %9 = OpTypeInt 32 1
  38. %10 = OpTypePointer Function %9
  39. %11 = OpConstant %9 2
  40. %12 = OpTypeStruct %9
  41. %13 = OpTypeInt 32 0
  42. %14 = OpConstant %13 3
  43. %15 = OpTypeArray %12 %14
  44. %16 = OpTypePointer Function %15
  45. %17 = OpConstant %9 0
  46. %2 = OpFunction %5 None %6
  47. %18 = OpLabel
  48. %3 = OpVariable %10 Function
  49. %4 = OpVariable %10 Function
  50. %19 = OpVariable %16 Function
  51. OpStore %3 %11
  52. %20 = OpLoad %9 %3
  53. %21 = OpAccessChain %10 %19 %20 %17
  54. %22 = OpLoad %9 %21
  55. OpStore %4 %22
  56. %23 = OpLoad %9 %4
  57. %24 = OpIAdd %9 %20 %23
  58. %25 = OpISub %9 %23 %20
  59. OpReturn
  60. OpFunctionEnd
  61. )";
  62. void SetUpIrrelevantIdFacts(FactManager* fact_manager) {
  63. fact_manager->AddFactIdIsIrrelevant(17);
  64. fact_manager->AddFactIdIsIrrelevant(23);
  65. fact_manager->AddFactIdIsIrrelevant(24);
  66. fact_manager->AddFactIdIsIrrelevant(25);
  67. }
  68. TEST(TransformationReplaceIrrelevantIdTest, Inapplicable) {
  69. const auto env = SPV_ENV_UNIVERSAL_1_5;
  70. const auto consumer = nullptr;
  71. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  72. spvtools::ValidatorOptions validator_options;
  73. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  74. kConsoleMessageConsumer));
  75. TransformationContext transformation_context(
  76. MakeUnique<FactManager>(context.get()), validator_options);
  77. SetUpIrrelevantIdFacts(transformation_context.GetFactManager());
  78. auto instruction_21_descriptor =
  79. MakeInstructionDescriptor(21, spv::Op::OpAccessChain, 0);
  80. auto instruction_24_descriptor =
  81. MakeInstructionDescriptor(24, spv::Op::OpIAdd, 0);
  82. // %20 has not been declared as irrelevant.
  83. ASSERT_FALSE(TransformationReplaceIrrelevantId(
  84. MakeIdUseDescriptor(20, instruction_24_descriptor, 0), 23)
  85. .IsApplicable(context.get(), transformation_context));
  86. // %22 is not used in %24.
  87. ASSERT_FALSE(TransformationReplaceIrrelevantId(
  88. MakeIdUseDescriptor(22, instruction_24_descriptor, 1), 20)
  89. .IsApplicable(context.get(), transformation_context));
  90. // Replacement id %50 does not exist.
  91. ASSERT_FALSE(TransformationReplaceIrrelevantId(
  92. MakeIdUseDescriptor(23, instruction_24_descriptor, 1), 50)
  93. .IsApplicable(context.get(), transformation_context));
  94. // %25 is not available to use at %24.
  95. ASSERT_FALSE(TransformationReplaceIrrelevantId(
  96. MakeIdUseDescriptor(23, instruction_24_descriptor, 1), 25)
  97. .IsApplicable(context.get(), transformation_context));
  98. // %24 is not available to use at %24.
  99. ASSERT_FALSE(TransformationReplaceIrrelevantId(
  100. MakeIdUseDescriptor(23, instruction_24_descriptor, 1), 24)
  101. .IsApplicable(context.get(), transformation_context));
  102. // %8 has not the same type as %23.
  103. ASSERT_FALSE(TransformationReplaceIrrelevantId(
  104. MakeIdUseDescriptor(23, instruction_24_descriptor, 1), 8)
  105. .IsApplicable(context.get(), transformation_context));
  106. // %17 is an index to a struct in an access chain, so it can't be replaced.
  107. ASSERT_FALSE(TransformationReplaceIrrelevantId(
  108. MakeIdUseDescriptor(17, instruction_21_descriptor, 2), 20)
  109. .IsApplicable(context.get(), transformation_context));
  110. }
  111. TEST(TransformationReplaceIrrelevantIdTest, Apply) {
  112. const auto env = SPV_ENV_UNIVERSAL_1_5;
  113. const auto consumer = nullptr;
  114. const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
  115. spvtools::ValidatorOptions validator_options;
  116. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  117. kConsoleMessageConsumer));
  118. TransformationContext transformation_context(
  119. MakeUnique<FactManager>(context.get()), validator_options);
  120. SetUpIrrelevantIdFacts(transformation_context.GetFactManager());
  121. auto instruction_24_descriptor =
  122. MakeInstructionDescriptor(24, spv::Op::OpIAdd, 0);
  123. // Replace the use of %23 in %24 with %22.
  124. auto transformation = TransformationReplaceIrrelevantId(
  125. MakeIdUseDescriptor(23, instruction_24_descriptor, 1), 22);
  126. ASSERT_TRUE(
  127. transformation.IsApplicable(context.get(), transformation_context));
  128. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  129. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  130. kConsoleMessageConsumer));
  131. std::string after_transformation = R"(
  132. OpCapability Shader
  133. %1 = OpExtInstImport "GLSL.std.450"
  134. OpMemoryModel Logical GLSL450
  135. OpEntryPoint Fragment %2 "main"
  136. OpExecutionMode %2 OriginUpperLeft
  137. OpSource ESSL 310
  138. OpName %2 "main"
  139. OpName %3 "a"
  140. OpName %4 "b"
  141. %5 = OpTypeVoid
  142. %6 = OpTypeFunction %5
  143. %7 = OpTypeBool
  144. %8 = OpConstantTrue %7
  145. %9 = OpTypeInt 32 1
  146. %10 = OpTypePointer Function %9
  147. %11 = OpConstant %9 2
  148. %12 = OpTypeStruct %9
  149. %13 = OpTypeInt 32 0
  150. %14 = OpConstant %13 3
  151. %15 = OpTypeArray %12 %14
  152. %16 = OpTypePointer Function %15
  153. %17 = OpConstant %9 0
  154. %2 = OpFunction %5 None %6
  155. %18 = OpLabel
  156. %3 = OpVariable %10 Function
  157. %4 = OpVariable %10 Function
  158. %19 = OpVariable %16 Function
  159. OpStore %3 %11
  160. %20 = OpLoad %9 %3
  161. %21 = OpAccessChain %10 %19 %20 %17
  162. %22 = OpLoad %9 %21
  163. OpStore %4 %22
  164. %23 = OpLoad %9 %4
  165. %24 = OpIAdd %9 %20 %22
  166. %25 = OpISub %9 %23 %20
  167. OpReturn
  168. OpFunctionEnd
  169. )";
  170. ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
  171. }
  172. TEST(TransformationReplaceIrrelevantIdTest,
  173. DoNotReplaceVariableInitializerWithNonConstant) {
  174. // Checks that it is not possible to replace the initializer of a variable
  175. // with a non-constant id (such as a function parameter).
  176. const std::string reference_shader = R"(
  177. OpCapability Shader
  178. %1 = OpExtInstImport "GLSL.std.450"
  179. OpMemoryModel Logical GLSL450
  180. OpEntryPoint Fragment %4 "main"
  181. OpExecutionMode %4 OriginUpperLeft
  182. OpSource ESSL 320
  183. %2 = OpTypeVoid
  184. %3 = OpTypeFunction %2
  185. %6 = OpTypeInt 32 1
  186. %7 = OpTypePointer Function %6
  187. %8 = OpTypeFunction %2 %6
  188. %13 = OpConstant %6 2
  189. %4 = OpFunction %2 None %3
  190. %5 = OpLabel
  191. OpReturn
  192. OpFunctionEnd
  193. %10 = OpFunction %2 None %8
  194. %9 = OpFunctionParameter %6
  195. %11 = OpLabel
  196. %12 = OpVariable %7 Function %13
  197. OpReturn
  198. OpFunctionEnd
  199. )";
  200. const auto env = SPV_ENV_UNIVERSAL_1_5;
  201. const auto consumer = nullptr;
  202. const auto context =
  203. BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
  204. spvtools::ValidatorOptions validator_options;
  205. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  206. kConsoleMessageConsumer));
  207. TransformationContext transformation_context(
  208. MakeUnique<FactManager>(context.get()), validator_options);
  209. transformation_context.GetFactManager()->AddFactIdIsIrrelevant(13);
  210. // We cannot replace the use of %13 in the initializer of %12 with %9 because
  211. // %9 is not a constant.
  212. ASSERT_FALSE(
  213. TransformationReplaceIrrelevantId(
  214. MakeIdUseDescriptor(
  215. 13, MakeInstructionDescriptor(12, spv::Op::OpVariable, 0), 1),
  216. 9)
  217. .IsApplicable(context.get(), transformation_context));
  218. }
  219. TEST(TransformationReplaceIrrelevantIdTest,
  220. DoNotReplaceIrrelevantIdWithOpFunction) {
  221. // Checks that an OpFunction result id is not allowed to be used to replace an
  222. // irrelevant id.
  223. const std::string reference_shader = R"(
  224. OpCapability Shader
  225. %1 = OpExtInstImport "GLSL.std.450"
  226. OpMemoryModel Logical GLSL450
  227. OpEntryPoint Fragment %4 "main"
  228. OpExecutionMode %4 OriginUpperLeft
  229. OpSource ESSL 320
  230. %2 = OpTypeVoid
  231. %3 = OpTypeFunction %2
  232. %6 = OpTypeInt 32 1
  233. %7 = OpTypeFunction %6
  234. %13 = OpConstant %6 2
  235. %4 = OpFunction %2 None %3
  236. %5 = OpLabel
  237. %20 = OpCopyObject %6 %13
  238. %21 = OpCopyObject %6 %20
  239. OpReturn
  240. OpFunctionEnd
  241. %10 = OpFunction %6 None %7
  242. %11 = OpLabel
  243. OpReturnValue %13
  244. OpFunctionEnd
  245. )";
  246. const auto env = SPV_ENV_UNIVERSAL_1_5;
  247. const auto consumer = nullptr;
  248. const auto context =
  249. BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
  250. spvtools::ValidatorOptions validator_options;
  251. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  252. kConsoleMessageConsumer));
  253. TransformationContext transformation_context(
  254. MakeUnique<FactManager>(context.get()), validator_options);
  255. transformation_context.GetFactManager()->AddFactIdIsIrrelevant(20);
  256. // We cannot replace the use of %20 in by %21 with %10 because %10 is an
  257. // OpFunction instruction.
  258. ASSERT_FALSE(
  259. TransformationReplaceIrrelevantId(
  260. MakeIdUseDescriptor(
  261. 20, MakeInstructionDescriptor(21, spv::Op::OpCopyObject, 0), 0),
  262. 10)
  263. .IsApplicable(context.get(), transformation_context));
  264. }
  265. TEST(TransformationReplaceIrrelevantIdTest, OpAccessChainIrrelevantIndex) {
  266. // Checks that we can't replace irrelevant index operands in OpAccessChain.
  267. const std::string reference_shader = R"(
  268. OpCapability Shader
  269. %1 = OpExtInstImport "GLSL.std.450"
  270. OpMemoryModel Logical GLSL450
  271. OpEntryPoint Fragment %4 "main"
  272. OpExecutionMode %4 OriginUpperLeft
  273. OpSource ESSL 320
  274. %2 = OpTypeVoid
  275. %3 = OpTypeFunction %2
  276. %6 = OpTypeInt 32 1
  277. %7 = OpTypeVector %6 2
  278. %8 = OpTypePointer Function %7
  279. %10 = OpConstant %6 0
  280. %11 = OpConstant %6 2
  281. %13 = OpTypePointer Function %6
  282. %4 = OpFunction %2 None %3
  283. %5 = OpLabel
  284. %9 = OpVariable %8 Function
  285. %12 = OpAccessChain %13 %9 %10
  286. OpReturn
  287. OpFunctionEnd
  288. )";
  289. const auto env = SPV_ENV_UNIVERSAL_1_5;
  290. const auto consumer = nullptr;
  291. const auto context =
  292. BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
  293. spvtools::ValidatorOptions validator_options;
  294. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  295. kConsoleMessageConsumer));
  296. TransformationContext transformation_context(
  297. MakeUnique<FactManager>(context.get()), validator_options);
  298. transformation_context.GetFactManager()->AddFactIdIsIrrelevant(10);
  299. // We cannot replace the use of %10 in %12 with %11 because %10 is an
  300. // irrelevant id.
  301. ASSERT_FALSE(
  302. TransformationReplaceIrrelevantId(
  303. MakeIdUseDescriptor(
  304. 10, MakeInstructionDescriptor(12, spv::Op::OpAccessChain, 0), 1),
  305. 11)
  306. .IsApplicable(context.get(), transformation_context));
  307. }
  308. } // namespace
  309. } // namespace fuzz
  310. } // namespace spvtools