val_validation_state_test.cpp 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. // Copyright (c) 2016 Google Inc.
  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. // Basic tests for the ValidationState_t datastructure.
  15. #include <string>
  16. #include "gmock/gmock.h"
  17. #include "source/spirv_validator_options.h"
  18. #include "test/unit_spirv.h"
  19. #include "test/val/val_fixtures.h"
  20. namespace spvtools {
  21. namespace val {
  22. namespace {
  23. using ::testing::HasSubstr;
  24. using ValidationStateTest = spvtest::ValidateBase<bool>;
  25. const char kHeader[] =
  26. " OpCapability Shader"
  27. " OpCapability Linkage"
  28. " OpMemoryModel Logical GLSL450 ";
  29. const char kVulkanMemoryHeader[] =
  30. " OpCapability Shader"
  31. " OpCapability VulkanMemoryModelKHR"
  32. " OpExtension \"SPV_KHR_vulkan_memory_model\""
  33. " OpMemoryModel Logical VulkanKHR ";
  34. const char kVoidFVoid[] =
  35. " %void = OpTypeVoid"
  36. " %void_f = OpTypeFunction %void"
  37. " %func = OpFunction %void None %void_f"
  38. " %label = OpLabel"
  39. " OpReturn"
  40. " OpFunctionEnd ";
  41. // k*RecursiveBody examples originally from test/opt/function_test.cpp
  42. const char* kNonRecursiveBody = R"(
  43. OpEntryPoint Fragment %1 "main"
  44. OpExecutionMode %1 OriginUpperLeft
  45. %void = OpTypeVoid
  46. %4 = OpTypeFunction %void
  47. %float = OpTypeFloat 32
  48. %_struct_6 = OpTypeStruct %float %float
  49. %null = OpConstantNull %_struct_6
  50. %7 = OpTypeFunction %_struct_6
  51. %12 = OpFunction %_struct_6 None %7
  52. %13 = OpLabel
  53. OpReturnValue %null
  54. OpFunctionEnd
  55. %9 = OpFunction %_struct_6 None %7
  56. %10 = OpLabel
  57. %11 = OpFunctionCall %_struct_6 %12
  58. OpReturnValue %null
  59. OpFunctionEnd
  60. %1 = OpFunction %void Pure|Const %4
  61. %8 = OpLabel
  62. %2 = OpFunctionCall %_struct_6 %9
  63. OpKill
  64. OpFunctionEnd
  65. )";
  66. const char* kDirectlyRecursiveBody = R"(
  67. OpEntryPoint Fragment %1 "main"
  68. OpExecutionMode %1 OriginUpperLeft
  69. %void = OpTypeVoid
  70. %4 = OpTypeFunction %void
  71. %float = OpTypeFloat 32
  72. %_struct_6 = OpTypeStruct %float %float
  73. %7 = OpTypeFunction %_struct_6
  74. %9 = OpFunction %_struct_6 None %7
  75. %10 = OpLabel
  76. %11 = OpFunctionCall %_struct_6 %9
  77. OpKill
  78. OpFunctionEnd
  79. %1 = OpFunction %void Pure|Const %4
  80. %8 = OpLabel
  81. %2 = OpFunctionCall %_struct_6 %9
  82. OpReturn
  83. OpFunctionEnd
  84. )";
  85. const char* kIndirectlyRecursiveBody = R"(
  86. OpEntryPoint Fragment %1 "main"
  87. OpExecutionMode %1 OriginUpperLeft
  88. %void = OpTypeVoid
  89. %4 = OpTypeFunction %void
  90. %float = OpTypeFloat 32
  91. %_struct_6 = OpTypeStruct %float %float
  92. %null = OpConstantNull %_struct_6
  93. %7 = OpTypeFunction %_struct_6
  94. %9 = OpFunction %_struct_6 None %7
  95. %10 = OpLabel
  96. %11 = OpFunctionCall %_struct_6 %12
  97. OpReturnValue %null
  98. OpFunctionEnd
  99. %12 = OpFunction %_struct_6 None %7
  100. %13 = OpLabel
  101. %14 = OpFunctionCall %_struct_6 %9
  102. OpReturnValue %null
  103. OpFunctionEnd
  104. %1 = OpFunction %void Pure|Const %4
  105. %8 = OpLabel
  106. %2 = OpFunctionCall %_struct_6 %9
  107. OpKill
  108. OpFunctionEnd
  109. )";
  110. // Tests that the instruction count in ValidationState is correct.
  111. TEST_F(ValidationStateTest, CheckNumInstructions) {
  112. std::string spirv = std::string(kHeader) + "%int = OpTypeInt 32 0";
  113. CompileSuccessfully(spirv);
  114. EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
  115. EXPECT_EQ(size_t(4), vstate_->ordered_instructions().size());
  116. }
  117. // Tests that the number of global variables in ValidationState is correct.
  118. TEST_F(ValidationStateTest, CheckNumGlobalVars) {
  119. std::string spirv = std::string(kHeader) + R"(
  120. %int = OpTypeInt 32 0
  121. %_ptr_int = OpTypePointer Input %int
  122. %var_1 = OpVariable %_ptr_int Input
  123. %var_2 = OpVariable %_ptr_int Input
  124. )";
  125. CompileSuccessfully(spirv);
  126. EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
  127. EXPECT_EQ(unsigned(2), vstate_->num_global_vars());
  128. }
  129. // Tests that the number of local variables in ValidationState is correct.
  130. TEST_F(ValidationStateTest, CheckNumLocalVars) {
  131. std::string spirv = std::string(kHeader) + R"(
  132. %int = OpTypeInt 32 0
  133. %_ptr_int = OpTypePointer Function %int
  134. %voidt = OpTypeVoid
  135. %funct = OpTypeFunction %voidt
  136. %main = OpFunction %voidt None %funct
  137. %entry = OpLabel
  138. %var_1 = OpVariable %_ptr_int Function
  139. %var_2 = OpVariable %_ptr_int Function
  140. %var_3 = OpVariable %_ptr_int Function
  141. OpReturn
  142. OpFunctionEnd
  143. )";
  144. CompileSuccessfully(spirv);
  145. EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
  146. EXPECT_EQ(unsigned(3), vstate_->num_local_vars());
  147. }
  148. // Tests that the "id bound" in ValidationState is correct.
  149. TEST_F(ValidationStateTest, CheckIdBound) {
  150. std::string spirv = std::string(kHeader) + R"(
  151. %int = OpTypeInt 32 0
  152. %voidt = OpTypeVoid
  153. )";
  154. CompileSuccessfully(spirv);
  155. EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
  156. EXPECT_EQ(unsigned(3), vstate_->getIdBound());
  157. }
  158. // Tests that the entry_points in ValidationState is correct.
  159. TEST_F(ValidationStateTest, CheckEntryPoints) {
  160. std::string spirv = std::string(kHeader) +
  161. " OpEntryPoint Vertex %func \"shader\"" +
  162. std::string(kVoidFVoid);
  163. CompileSuccessfully(spirv);
  164. EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
  165. EXPECT_EQ(size_t(1), vstate_->entry_points().size());
  166. EXPECT_EQ(spv::Op::OpFunction,
  167. vstate_->FindDef(vstate_->entry_points()[0])->opcode());
  168. }
  169. TEST_F(ValidationStateTest, CheckStructMemberLimitOption) {
  170. spvValidatorOptionsSetUniversalLimit(
  171. options_, spv_validator_limit_max_struct_members, 32000u);
  172. EXPECT_EQ(32000u, options_->universal_limits_.max_struct_members);
  173. }
  174. TEST_F(ValidationStateTest, CheckNumGlobalVarsLimitOption) {
  175. spvValidatorOptionsSetUniversalLimit(
  176. options_, spv_validator_limit_max_global_variables, 100u);
  177. EXPECT_EQ(100u, options_->universal_limits_.max_global_variables);
  178. }
  179. TEST_F(ValidationStateTest, CheckNumLocalVarsLimitOption) {
  180. spvValidatorOptionsSetUniversalLimit(
  181. options_, spv_validator_limit_max_local_variables, 100u);
  182. EXPECT_EQ(100u, options_->universal_limits_.max_local_variables);
  183. }
  184. TEST_F(ValidationStateTest, CheckStructDepthLimitOption) {
  185. spvValidatorOptionsSetUniversalLimit(
  186. options_, spv_validator_limit_max_struct_depth, 100u);
  187. EXPECT_EQ(100u, options_->universal_limits_.max_struct_depth);
  188. }
  189. TEST_F(ValidationStateTest, CheckSwitchBranchesLimitOption) {
  190. spvValidatorOptionsSetUniversalLimit(
  191. options_, spv_validator_limit_max_switch_branches, 100u);
  192. EXPECT_EQ(100u, options_->universal_limits_.max_switch_branches);
  193. }
  194. TEST_F(ValidationStateTest, CheckFunctionArgsLimitOption) {
  195. spvValidatorOptionsSetUniversalLimit(
  196. options_, spv_validator_limit_max_function_args, 100u);
  197. EXPECT_EQ(100u, options_->universal_limits_.max_function_args);
  198. }
  199. TEST_F(ValidationStateTest, CheckCFGDepthLimitOption) {
  200. spvValidatorOptionsSetUniversalLimit(
  201. options_, spv_validator_limit_max_control_flow_nesting_depth, 100u);
  202. EXPECT_EQ(100u, options_->universal_limits_.max_control_flow_nesting_depth);
  203. }
  204. TEST_F(ValidationStateTest, CheckAccessChainIndexesLimitOption) {
  205. spvValidatorOptionsSetUniversalLimit(
  206. options_, spv_validator_limit_max_access_chain_indexes, 100u);
  207. EXPECT_EQ(100u, options_->universal_limits_.max_access_chain_indexes);
  208. }
  209. TEST_F(ValidationStateTest, CheckNonRecursiveBodyGood) {
  210. std::string spirv = std::string(kHeader) + kNonRecursiveBody;
  211. CompileSuccessfully(spirv);
  212. EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
  213. }
  214. TEST_F(ValidationStateTest, CheckVulkanNonRecursiveBodyGood) {
  215. std::string spirv = std::string(kVulkanMemoryHeader) + kNonRecursiveBody;
  216. CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
  217. EXPECT_EQ(SPV_SUCCESS,
  218. ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
  219. }
  220. TEST_F(ValidationStateTest, CheckDirectlyRecursiveBodyGood) {
  221. std::string spirv = std::string(kHeader) + kDirectlyRecursiveBody;
  222. CompileSuccessfully(spirv);
  223. EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
  224. }
  225. TEST_F(ValidationStateTest, CheckVulkanDirectlyRecursiveBodyBad) {
  226. std::string spirv = std::string(kVulkanMemoryHeader) + kDirectlyRecursiveBody;
  227. CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
  228. EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
  229. ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
  230. EXPECT_THAT(getDiagnosticString(),
  231. AnyVUID("VUID-StandaloneSpirv-None-04634"));
  232. EXPECT_THAT(getDiagnosticString(),
  233. HasSubstr("Entry points may not have a call graph with cycles.\n "
  234. " %1 = OpFunction %void Pure|Const %3\n"));
  235. }
  236. TEST_F(ValidationStateTest, CheckIndirectlyRecursiveBodyGood) {
  237. std::string spirv = std::string(kHeader) + kIndirectlyRecursiveBody;
  238. CompileSuccessfully(spirv);
  239. EXPECT_EQ(SPV_SUCCESS, ValidateAndRetrieveValidationState());
  240. }
  241. TEST_F(ValidationStateTest, CheckVulkanIndirectlyRecursiveBodyBad) {
  242. std::string spirv =
  243. std::string(kVulkanMemoryHeader) + kIndirectlyRecursiveBody;
  244. CompileSuccessfully(spirv, SPV_ENV_VULKAN_1_1);
  245. EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
  246. ValidateAndRetrieveValidationState(SPV_ENV_VULKAN_1_1));
  247. EXPECT_THAT(getDiagnosticString(),
  248. AnyVUID("VUID-StandaloneSpirv-None-04634"));
  249. EXPECT_THAT(getDiagnosticString(),
  250. HasSubstr("Entry points may not have a call graph with cycles.\n "
  251. " %1 = OpFunction %void Pure|Const %3\n"));
  252. }
  253. } // namespace
  254. } // namespace val
  255. } // namespace spvtools