module_test.cpp 9.1 KB

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