module_test.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  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. #include "source/opt/module.h"
  15. #include <memory>
  16. #include <vector>
  17. #include "gmock/gmock.h"
  18. #include "gtest/gtest.h"
  19. #include "source/opt/build_module.h"
  20. #include "spirv-tools/libspirv.hpp"
  21. #include "test/opt/module_utils.h"
  22. namespace spvtools {
  23. namespace opt {
  24. namespace {
  25. using ::testing::Eq;
  26. using spvtest::GetIdBound;
  27. TEST(ModuleTest, SetIdBound) {
  28. Module m;
  29. // It's initialized to 0.
  30. EXPECT_EQ(0u, GetIdBound(m));
  31. m.SetIdBound(19);
  32. EXPECT_EQ(19u, GetIdBound(m));
  33. m.SetIdBound(102);
  34. EXPECT_EQ(102u, GetIdBound(m));
  35. }
  36. // Returns an IRContext owning the module formed by assembling the given text,
  37. // then loading the result.
  38. inline std::unique_ptr<IRContext> BuildModule(std::string text) {
  39. return spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
  40. SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
  41. }
  42. TEST(ModuleTest, ComputeIdBound) {
  43. // Empty module case.
  44. EXPECT_EQ(1u, BuildModule("")->module()->ComputeIdBound());
  45. // Sensitive to result id
  46. EXPECT_EQ(2u, BuildModule("%void = OpTypeVoid")->module()->ComputeIdBound());
  47. // Sensitive to type id
  48. EXPECT_EQ(1000u,
  49. BuildModule("%a = OpTypeArray !999 3")->module()->ComputeIdBound());
  50. // Sensitive to a regular Id parameter
  51. EXPECT_EQ(2000u,
  52. BuildModule("OpDecorate !1999 0")->module()->ComputeIdBound());
  53. // Sensitive to a scope Id parameter.
  54. EXPECT_EQ(3000u,
  55. BuildModule("%f = OpFunction %void None %fntype %a = OpLabel "
  56. "OpMemoryBarrier !2999 %b\n")
  57. ->module()
  58. ->ComputeIdBound());
  59. // Sensitive to a semantics Id parameter
  60. EXPECT_EQ(4000u,
  61. BuildModule("%f = OpFunction %void None %fntype %a = OpLabel "
  62. "OpMemoryBarrier %b !3999\n")
  63. ->module()
  64. ->ComputeIdBound());
  65. }
  66. TEST(ModuleTest, OstreamOperator) {
  67. const std::string text = R"(OpCapability Shader
  68. OpCapability Linkage
  69. OpMemoryModel Logical GLSL450
  70. OpName %7 "restrict"
  71. OpDecorate %8 Restrict
  72. %9 = OpTypeVoid
  73. %10 = OpTypeInt 32 0
  74. %11 = OpTypeStruct %10 %10
  75. %12 = OpTypePointer Function %10
  76. %13 = OpTypePointer Function %11
  77. %14 = OpConstant %10 0
  78. %15 = OpConstant %10 1
  79. %7 = OpTypeFunction %9
  80. %1 = OpFunction %9 None %7
  81. %2 = OpLabel
  82. %8 = OpVariable %13 Function
  83. %3 = OpAccessChain %12 %8 %14
  84. %4 = OpLoad %10 %3
  85. %5 = OpAccessChain %12 %8 %15
  86. %6 = OpLoad %10 %5
  87. OpReturn
  88. OpFunctionEnd)";
  89. std::string s;
  90. std::ostringstream str(s);
  91. str << *BuildModule(text)->module();
  92. EXPECT_EQ(text, str.str());
  93. }
  94. TEST(ModuleTest, OstreamOperatorInt64) {
  95. const std::string text = R"(OpCapability Shader
  96. OpCapability Linkage
  97. OpCapability Int64
  98. OpMemoryModel Logical GLSL450
  99. OpName %7 "restrict"
  100. OpDecorate %5 Restrict
  101. %9 = OpTypeVoid
  102. %10 = OpTypeInt 64 0
  103. %11 = OpTypeStruct %10 %10
  104. %12 = OpTypePointer Function %10
  105. %13 = OpTypePointer Function %11
  106. %14 = OpConstant %10 0
  107. %15 = OpConstant %10 1
  108. %16 = OpConstant %10 4294967297
  109. %7 = OpTypeFunction %9
  110. %1 = OpFunction %9 None %7
  111. %2 = OpLabel
  112. %5 = OpVariable %12 Function
  113. %6 = OpLoad %10 %5
  114. OpSelectionMerge %3 None
  115. OpSwitch %6 %3 4294967297 %4
  116. %4 = OpLabel
  117. OpBranch %3
  118. %3 = OpLabel
  119. OpReturn
  120. OpFunctionEnd)";
  121. std::string s;
  122. std::ostringstream str(s);
  123. str << *BuildModule(text)->module();
  124. EXPECT_EQ(text, str.str());
  125. }
  126. TEST(ModuleTest, IdBoundTestAtLimit) {
  127. const std::string text = R"(
  128. OpCapability Shader
  129. OpCapability Linkage
  130. OpMemoryModel Logical GLSL450
  131. %1 = OpTypeVoid
  132. %2 = OpTypeFunction %1
  133. %3 = OpFunction %1 None %2
  134. %4 = OpLabel
  135. OpReturn
  136. OpFunctionEnd)";
  137. std::unique_ptr<IRContext> context = BuildModule(text);
  138. uint32_t current_bound = context->module()->id_bound();
  139. context->set_max_id_bound(current_bound);
  140. uint32_t next_id_bound = context->module()->TakeNextIdBound();
  141. EXPECT_EQ(next_id_bound, 0);
  142. EXPECT_EQ(current_bound, context->module()->id_bound());
  143. next_id_bound = context->module()->TakeNextIdBound();
  144. EXPECT_EQ(next_id_bound, 0);
  145. }
  146. TEST(ModuleTest, IdBoundTestBelowLimit) {
  147. const std::string text = R"(
  148. OpCapability Shader
  149. OpCapability Linkage
  150. OpMemoryModel Logical GLSL450
  151. %1 = OpTypeVoid
  152. %2 = OpTypeFunction %1
  153. %3 = OpFunction %1 None %2
  154. %4 = OpLabel
  155. OpReturn
  156. OpFunctionEnd)";
  157. std::unique_ptr<IRContext> context = BuildModule(text);
  158. uint32_t current_bound = context->module()->id_bound();
  159. context->set_max_id_bound(current_bound + 100);
  160. uint32_t next_id_bound = context->module()->TakeNextIdBound();
  161. EXPECT_EQ(next_id_bound, current_bound);
  162. EXPECT_EQ(current_bound + 1, context->module()->id_bound());
  163. next_id_bound = context->module()->TakeNextIdBound();
  164. EXPECT_EQ(next_id_bound, current_bound + 1);
  165. }
  166. TEST(ModuleTest, IdBoundTestNearLimit) {
  167. const std::string text = R"(
  168. OpCapability Shader
  169. OpCapability Linkage
  170. OpMemoryModel Logical GLSL450
  171. %1 = OpTypeVoid
  172. %2 = OpTypeFunction %1
  173. %3 = OpFunction %1 None %2
  174. %4 = OpLabel
  175. OpReturn
  176. OpFunctionEnd)";
  177. std::unique_ptr<IRContext> context = BuildModule(text);
  178. uint32_t current_bound = context->module()->id_bound();
  179. context->set_max_id_bound(current_bound + 1);
  180. uint32_t next_id_bound = context->module()->TakeNextIdBound();
  181. EXPECT_EQ(next_id_bound, current_bound);
  182. EXPECT_EQ(current_bound + 1, context->module()->id_bound());
  183. next_id_bound = context->module()->TakeNextIdBound();
  184. EXPECT_EQ(next_id_bound, 0);
  185. }
  186. TEST(ModuleTest, IdBoundTestUIntMax) {
  187. const std::string text = R"(
  188. OpCapability Shader
  189. OpCapability Linkage
  190. OpMemoryModel Logical GLSL450
  191. %1 = OpTypeVoid
  192. %2 = OpTypeFunction %1
  193. %3 = OpFunction %1 None %2
  194. %4294967294 = OpLabel ; ID is UINT_MAX-1
  195. OpReturn
  196. OpFunctionEnd)";
  197. std::unique_ptr<IRContext> context = BuildModule(text);
  198. uint32_t current_bound = context->module()->id_bound();
  199. // Expecting |BuildModule| to preserve the numeric ids.
  200. EXPECT_EQ(current_bound, std::numeric_limits<uint32_t>::max());
  201. context->set_max_id_bound(current_bound);
  202. uint32_t next_id_bound = context->module()->TakeNextIdBound();
  203. EXPECT_EQ(next_id_bound, 0);
  204. EXPECT_EQ(current_bound, context->module()->id_bound());
  205. }
  206. // Tests that "text" does not change when it is assembled, converted into a
  207. // module, converted back to a binary, and then disassembled.
  208. void AssembleAndDisassemble(const std::string& text) {
  209. std::unique_ptr<IRContext> context = BuildModule(text);
  210. std::vector<uint32_t> binary;
  211. context->module()->ToBinary(&binary, false);
  212. SpirvTools tools(SPV_ENV_UNIVERSAL_1_1);
  213. std::string s;
  214. tools.Disassemble(binary, &s);
  215. EXPECT_EQ(s, text);
  216. }
  217. TEST(ModuleTest, TrailingOpLine) {
  218. const std::string text = R"(OpCapability Shader
  219. OpCapability Linkage
  220. OpMemoryModel Logical GLSL450
  221. %5 = OpString "file.ext"
  222. %void = OpTypeVoid
  223. %2 = OpTypeFunction %void
  224. %3 = OpFunction %void None %2
  225. %4 = OpLabel
  226. OpReturn
  227. OpFunctionEnd
  228. OpLine %5 1 0
  229. )";
  230. AssembleAndDisassemble(text);
  231. }
  232. TEST(ModuleTest, TrailingOpNoLine) {
  233. const std::string text = R"(OpCapability Shader
  234. OpCapability Linkage
  235. OpMemoryModel Logical GLSL450
  236. %void = OpTypeVoid
  237. %2 = OpTypeFunction %void
  238. %3 = OpFunction %void None %2
  239. %4 = OpLabel
  240. OpReturn
  241. OpFunctionEnd
  242. OpNoLine
  243. )";
  244. AssembleAndDisassemble(text);
  245. }
  246. TEST(ModuleTest, MulitpleTrailingOpLine) {
  247. const std::string text = R"(OpCapability Shader
  248. OpCapability Linkage
  249. OpMemoryModel Logical GLSL450
  250. %5 = OpString "file.ext"
  251. %void = OpTypeVoid
  252. %2 = OpTypeFunction %void
  253. %3 = OpFunction %void None %2
  254. %4 = OpLabel
  255. OpReturn
  256. OpFunctionEnd
  257. OpLine %5 1 0
  258. OpNoLine
  259. OpLine %5 1 1
  260. )";
  261. AssembleAndDisassemble(text);
  262. }
  263. TEST(ModuleTest, NonSemanticInfoIteration) {
  264. const std::string text = R"(
  265. OpCapability Shader
  266. OpCapability Linkage
  267. OpExtension "SPV_KHR_non_semantic_info"
  268. %1 = OpExtInstImport "NonSemantic.Test"
  269. OpMemoryModel Logical GLSL450
  270. %2 = OpTypeVoid
  271. %3 = OpTypeFunction %2
  272. %4 = OpExtInst %2 %1 1
  273. %5 = OpFunction %2 None %3
  274. %6 = OpLabel
  275. %7 = OpExtInst %2 %1 1
  276. OpReturn
  277. OpFunctionEnd
  278. %8 = OpExtInst %2 %1 1
  279. %9 = OpFunction %2 None %3
  280. %10 = OpLabel
  281. %11 = OpExtInst %2 %1 1
  282. OpReturn
  283. OpFunctionEnd
  284. %12 = OpExtInst %2 %1 1
  285. )";
  286. std::unique_ptr<IRContext> context = BuildModule(text);
  287. std::unordered_set<uint32_t> non_semantic_ids;
  288. context->module()->ForEachInst(
  289. [&non_semantic_ids](const Instruction* inst) {
  290. if (inst->opcode() == spv::Op::OpExtInst) {
  291. non_semantic_ids.insert(inst->result_id());
  292. }
  293. },
  294. false);
  295. EXPECT_EQ(1, non_semantic_ids.count(4));
  296. EXPECT_EQ(1, non_semantic_ids.count(7));
  297. EXPECT_EQ(1, non_semantic_ids.count(8));
  298. EXPECT_EQ(1, non_semantic_ids.count(11));
  299. EXPECT_EQ(1, non_semantic_ids.count(12));
  300. }
  301. } // namespace
  302. } // namespace opt
  303. } // namespace spvtools