transformation_add_constant_scalar_test.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366
  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_add_constant_scalar.h"
  15. #include "gtest/gtest.h"
  16. #include "source/fuzz/fuzzer_util.h"
  17. #include "test/fuzz/fuzz_test_util.h"
  18. namespace spvtools {
  19. namespace fuzz {
  20. namespace {
  21. TEST(TransformationAddConstantScalarTest, IsApplicable) {
  22. std::string reference_shader = R"(
  23. OpCapability Shader
  24. OpCapability Int64
  25. OpCapability Float64
  26. %1 = OpExtInstImport "GLSL.std.450"
  27. OpMemoryModel Logical GLSL450
  28. OpEntryPoint Vertex %17 "main"
  29. ; Types
  30. ; 32-bit types
  31. %2 = OpTypeInt 32 0
  32. %3 = OpTypeInt 32 1
  33. %4 = OpTypeFloat 32
  34. ; 64-bit types
  35. %5 = OpTypeInt 64 0
  36. %6 = OpTypeInt 64 1
  37. %7 = OpTypeFloat 64
  38. %8 = OpTypePointer Private %2
  39. %9 = OpTypeVoid
  40. %10 = OpTypeFunction %9
  41. ; Constants
  42. ; 32-bit constants
  43. %11 = OpConstant %2 1
  44. %12 = OpConstant %3 2
  45. %13 = OpConstant %4 3
  46. ; 64-bit constants
  47. %14 = OpConstant %5 1
  48. %15 = OpConstant %6 2
  49. %16 = OpConstant %7 3
  50. ; main function
  51. %17 = OpFunction %9 None %10
  52. %18 = OpLabel
  53. OpReturn
  54. OpFunctionEnd
  55. )";
  56. const auto env = SPV_ENV_UNIVERSAL_1_3;
  57. const auto consumer = nullptr;
  58. const auto context =
  59. BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
  60. spvtools::ValidatorOptions validator_options;
  61. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  62. kConsoleMessageConsumer));
  63. TransformationContext transformation_context(
  64. MakeUnique<FactManager>(context.get()), validator_options);
  65. // Tests |fresh_id| being non-fresh.
  66. auto transformation = TransformationAddConstantScalar(18, 2, {0}, false);
  67. ASSERT_FALSE(
  68. transformation.IsApplicable(context.get(), transformation_context));
  69. // Tests undefined |type_id|.
  70. transformation = TransformationAddConstantScalar(19, 20, {0}, false);
  71. ASSERT_FALSE(
  72. transformation.IsApplicable(context.get(), transformation_context));
  73. // Tests |type_id| not representing a type instruction.
  74. transformation = TransformationAddConstantScalar(19, 11, {0}, false);
  75. ASSERT_FALSE(
  76. transformation.IsApplicable(context.get(), transformation_context));
  77. // Tests |type_id| representing an OpTypePointer instruction.
  78. transformation = TransformationAddConstantScalar(19, 8, {0}, false);
  79. ASSERT_FALSE(
  80. transformation.IsApplicable(context.get(), transformation_context));
  81. // Tests |type_id| representing an OpTypeVoid instruction.
  82. transformation = TransformationAddConstantScalar(19, 9, {0}, false);
  83. ASSERT_FALSE(
  84. transformation.IsApplicable(context.get(), transformation_context));
  85. // Tests |words| having no words.
  86. transformation = TransformationAddConstantScalar(19, 2, {}, false);
  87. ASSERT_FALSE(
  88. transformation.IsApplicable(context.get(), transformation_context));
  89. // Tests |words| having 2 words for a 32-bit type.
  90. transformation = TransformationAddConstantScalar(19, 2, {0, 1}, false);
  91. ASSERT_FALSE(
  92. transformation.IsApplicable(context.get(), transformation_context));
  93. // Tests |words| having 3 words for a 64-bit type.
  94. transformation = TransformationAddConstantScalar(19, 5, {0, 1, 2}, false);
  95. ASSERT_FALSE(
  96. transformation.IsApplicable(context.get(), transformation_context));
  97. // Tests |words| having 2 words for a 32-bit float type.
  98. transformation = TransformationAddConstantScalar(19, 4, {0, 1}, false);
  99. ASSERT_FALSE(
  100. transformation.IsApplicable(context.get(), transformation_context));
  101. }
  102. TEST(TransformationAddConstantScalarTest, Apply) {
  103. std::string reference_shader = R"(
  104. OpCapability Shader
  105. OpCapability Int64
  106. OpCapability Float64
  107. %1 = OpExtInstImport "GLSL.std.450"
  108. OpMemoryModel Logical GLSL450
  109. OpEntryPoint Vertex %17 "main"
  110. ; Types
  111. ; 32-bit types
  112. %2 = OpTypeInt 32 0
  113. %3 = OpTypeInt 32 1
  114. %4 = OpTypeFloat 32
  115. ; 64-bit types
  116. %5 = OpTypeInt 64 0
  117. %6 = OpTypeInt 64 1
  118. %7 = OpTypeFloat 64
  119. %8 = OpTypePointer Private %2
  120. %9 = OpTypeVoid
  121. %10 = OpTypeFunction %9
  122. ; Constants
  123. ; 32-bit constants
  124. %11 = OpConstant %2 1
  125. %12 = OpConstant %3 2
  126. %13 = OpConstant %4 3
  127. ; 64-bit constants
  128. %14 = OpConstant %5 1
  129. %15 = OpConstant %6 2
  130. %16 = OpConstant %7 3
  131. ; main function
  132. %17 = OpFunction %9 None %10
  133. %18 = OpLabel
  134. OpReturn
  135. OpFunctionEnd
  136. )";
  137. const auto env = SPV_ENV_UNIVERSAL_1_3;
  138. const auto consumer = nullptr;
  139. const auto context =
  140. BuildModule(env, consumer, reference_shader, kFuzzAssembleOption);
  141. spvtools::ValidatorOptions validator_options;
  142. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  143. kConsoleMessageConsumer));
  144. TransformationContext transformation_context(
  145. MakeUnique<FactManager>(context.get()), validator_options);
  146. // Adds 32-bit unsigned integer (1 logical operand with 1 word).
  147. auto transformation = TransformationAddConstantScalar(19, 2, {4}, false);
  148. ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(19));
  149. ASSERT_EQ(nullptr, context->get_constant_mgr()->FindDeclaredConstant(19));
  150. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  151. ASSERT_EQ(spv::Op::OpConstant,
  152. context->get_def_use_mgr()->GetDef(19)->opcode());
  153. ASSERT_EQ(4, context->get_constant_mgr()->FindDeclaredConstant(19)->GetU32());
  154. auto* constant_instruction = context->get_def_use_mgr()->GetDef(19);
  155. EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  156. EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
  157. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  158. kConsoleMessageConsumer));
  159. // Adds 32-bit signed integer (1 logical operand with 1 word).
  160. transformation = TransformationAddConstantScalar(20, 3, {5}, false);
  161. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  162. constant_instruction = context->get_def_use_mgr()->GetDef(20);
  163. EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  164. EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
  165. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  166. kConsoleMessageConsumer));
  167. // Adds 32-bit float (1 logical operand with 1 word).
  168. transformation = TransformationAddConstantScalar(
  169. 21, 4, {0b01000000110000000000000000000000}, false);
  170. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  171. constant_instruction = context->get_def_use_mgr()->GetDef(21);
  172. EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  173. EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
  174. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  175. kConsoleMessageConsumer));
  176. // Adds 64-bit unsigned integer (1 logical operand with 2 words).
  177. transformation = TransformationAddConstantScalar(22, 5, {7, 0}, false);
  178. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  179. constant_instruction = context->get_def_use_mgr()->GetDef(22);
  180. EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  181. EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
  182. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  183. kConsoleMessageConsumer));
  184. // Adds 64-bit signed integer (1 logical operand with 2 words).
  185. transformation = TransformationAddConstantScalar(23, 6, {8, 0}, false);
  186. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  187. constant_instruction = context->get_def_use_mgr()->GetDef(23);
  188. EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  189. EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
  190. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  191. kConsoleMessageConsumer));
  192. // Adds 64-bit float (1 logical operand with 2 words).
  193. transformation = TransformationAddConstantScalar(
  194. 24, 7, {0, 0b01000000001000100000000000000000}, false);
  195. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  196. constant_instruction = context->get_def_use_mgr()->GetDef(24);
  197. EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  198. EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
  199. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  200. kConsoleMessageConsumer));
  201. // Adds irrelevant 32-bit unsigned integer (1 logical operand with 1 word).
  202. transformation = TransformationAddConstantScalar(25, 2, {10}, true);
  203. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  204. constant_instruction = context->get_def_use_mgr()->GetDef(25);
  205. EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  206. EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
  207. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  208. kConsoleMessageConsumer));
  209. // Adds irrelevant 32-bit signed integer (1 logical operand with 1 word).
  210. transformation = TransformationAddConstantScalar(26, 3, {11}, true);
  211. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  212. constant_instruction = context->get_def_use_mgr()->GetDef(26);
  213. EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  214. EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
  215. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  216. kConsoleMessageConsumer));
  217. // Adds irrelevant 32-bit float (1 logical operand with 1 word).
  218. transformation = TransformationAddConstantScalar(
  219. 27, 4, {0b01000001010000000000000000000000}, true);
  220. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  221. constant_instruction = context->get_def_use_mgr()->GetDef(27);
  222. EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  223. EXPECT_EQ(constant_instruction->NumInOperandWords(), 1);
  224. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  225. kConsoleMessageConsumer));
  226. // Adds irrelevant 64-bit unsigned integer (1 logical operand with 2 words).
  227. transformation = TransformationAddConstantScalar(28, 5, {13, 0}, true);
  228. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  229. constant_instruction = context->get_def_use_mgr()->GetDef(28);
  230. EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  231. EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
  232. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  233. kConsoleMessageConsumer));
  234. // Adds irrelevant 64-bit signed integer (1 logical operand with 2 words).
  235. transformation = TransformationAddConstantScalar(29, 6, {14, 0}, true);
  236. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  237. constant_instruction = context->get_def_use_mgr()->GetDef(29);
  238. EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  239. EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
  240. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  241. kConsoleMessageConsumer));
  242. // Adds irrelevant 64-bit float (1 logical operand with 2 words).
  243. transformation = TransformationAddConstantScalar(
  244. 30, 7, {0, 0b01000000001011100000000000000000}, true);
  245. ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
  246. constant_instruction = context->get_def_use_mgr()->GetDef(30);
  247. EXPECT_EQ(constant_instruction->NumInOperands(), 1);
  248. EXPECT_EQ(constant_instruction->NumInOperandWords(), 2);
  249. ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
  250. kConsoleMessageConsumer));
  251. for (uint32_t result_id = 19; result_id <= 24; ++result_id) {
  252. ASSERT_FALSE(
  253. transformation_context.GetFactManager()->IdIsIrrelevant(result_id));
  254. }
  255. for (uint32_t result_id = 25; result_id <= 30; ++result_id) {
  256. ASSERT_TRUE(
  257. transformation_context.GetFactManager()->IdIsIrrelevant(result_id));
  258. }
  259. std::string variant_shader = R"(
  260. OpCapability Shader
  261. OpCapability Int64
  262. OpCapability Float64
  263. %1 = OpExtInstImport "GLSL.std.450"
  264. OpMemoryModel Logical GLSL450
  265. OpEntryPoint Vertex %17 "main"
  266. ; Types
  267. ; 32-bit types
  268. %2 = OpTypeInt 32 0
  269. %3 = OpTypeInt 32 1
  270. %4 = OpTypeFloat 32
  271. ; 64-bit types
  272. %5 = OpTypeInt 64 0
  273. %6 = OpTypeInt 64 1
  274. %7 = OpTypeFloat 64
  275. %8 = OpTypePointer Private %2
  276. %9 = OpTypeVoid
  277. %10 = OpTypeFunction %9
  278. ; Constants
  279. ; 32-bit constants
  280. %11 = OpConstant %2 1
  281. %12 = OpConstant %3 2
  282. %13 = OpConstant %4 3
  283. ; 64-bit constants
  284. %14 = OpConstant %5 1
  285. %15 = OpConstant %6 2
  286. %16 = OpConstant %7 3
  287. ; added constants
  288. %19 = OpConstant %2 4
  289. %20 = OpConstant %3 5
  290. %21 = OpConstant %4 6
  291. %22 = OpConstant %5 7
  292. %23 = OpConstant %6 8
  293. %24 = OpConstant %7 9
  294. %25 = OpConstant %2 10
  295. %26 = OpConstant %3 11
  296. %27 = OpConstant %4 12
  297. %28 = OpConstant %5 13
  298. %29 = OpConstant %6 14
  299. %30 = OpConstant %7 15
  300. ; main function
  301. %17 = OpFunction %9 None %10
  302. %18 = OpLabel
  303. OpReturn
  304. OpFunctionEnd
  305. )";
  306. ASSERT_TRUE(IsEqual(env, variant_shader, context.get()));
  307. }
  308. } // namespace
  309. } // namespace fuzz
  310. } // namespace spvtools