matching_imports_to_exports_test.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404
  1. // Copyright (c) 2017 Pierre Moreau
  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 <string>
  15. #include "gmock/gmock.h"
  16. #include "test/link/linker_fixture.h"
  17. namespace spvtools {
  18. namespace {
  19. using ::testing::HasSubstr;
  20. using MatchingImportsToExports = spvtest::LinkerTest;
  21. TEST_F(MatchingImportsToExports, Default) {
  22. const std::string body1 = R"(
  23. OpCapability Linkage
  24. OpDecorate %1 LinkageAttributes "foo" Import
  25. %2 = OpTypeFloat 32
  26. %1 = OpVariable %2 Uniform
  27. %3 = OpVariable %2 Input
  28. )";
  29. const std::string body2 = R"(
  30. OpCapability Linkage
  31. OpDecorate %1 LinkageAttributes "foo" Export
  32. %2 = OpTypeFloat 32
  33. %3 = OpConstant %2 42
  34. %1 = OpVariable %2 Uniform %3
  35. )";
  36. spvtest::Binary linked_binary;
  37. EXPECT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary))
  38. << GetErrorMessage();
  39. const std::string expected_res =
  40. R"(OpModuleProcessed "Linked by SPIR-V Tools Linker"
  41. %1 = OpTypeFloat 32
  42. %2 = OpVariable %1 Input
  43. %3 = OpConstant %1 42
  44. %4 = OpVariable %1 Uniform %3
  45. )";
  46. std::string res_body;
  47. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  48. EXPECT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body))
  49. << GetErrorMessage();
  50. EXPECT_EQ(expected_res, res_body);
  51. }
  52. TEST_F(MatchingImportsToExports, NotALibraryExtraExports) {
  53. const std::string body = R"(
  54. OpCapability Linkage
  55. OpDecorate %1 LinkageAttributes "foo" Export
  56. %2 = OpTypeFloat 32
  57. %1 = OpVariable %2 Uniform
  58. )";
  59. spvtest::Binary linked_binary;
  60. EXPECT_EQ(SPV_SUCCESS, AssembleAndLink({body}, &linked_binary))
  61. << GetErrorMessage();
  62. const std::string expected_res =
  63. R"(OpModuleProcessed "Linked by SPIR-V Tools Linker"
  64. %1 = OpTypeFloat 32
  65. %2 = OpVariable %1 Uniform
  66. )";
  67. std::string res_body;
  68. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  69. EXPECT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body))
  70. << GetErrorMessage();
  71. EXPECT_EQ(expected_res, res_body);
  72. }
  73. TEST_F(MatchingImportsToExports, LibraryExtraExports) {
  74. const std::string body = R"(
  75. OpCapability Linkage
  76. OpDecorate %1 LinkageAttributes "foo" Export
  77. %2 = OpTypeFloat 32
  78. %1 = OpVariable %2 Uniform
  79. )";
  80. spvtest::Binary linked_binary;
  81. LinkerOptions options;
  82. options.SetCreateLibrary(true);
  83. EXPECT_EQ(SPV_SUCCESS, AssembleAndLink({body}, &linked_binary, options))
  84. << GetErrorMessage();
  85. const std::string expected_res = R"(OpCapability Linkage
  86. OpModuleProcessed "Linked by SPIR-V Tools Linker"
  87. OpDecorate %1 LinkageAttributes "foo" Export
  88. %2 = OpTypeFloat 32
  89. %1 = OpVariable %2 Uniform
  90. )";
  91. std::string res_body;
  92. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  93. EXPECT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body))
  94. << GetErrorMessage();
  95. EXPECT_EQ(expected_res, res_body);
  96. }
  97. TEST_F(MatchingImportsToExports, UnresolvedImports) {
  98. const std::string body1 = R"(
  99. OpCapability Linkage
  100. OpDecorate %1 LinkageAttributes "foo" Import
  101. %2 = OpTypeFloat 32
  102. %1 = OpVariable %2 Uniform
  103. )";
  104. const std::string body2 = R"()";
  105. spvtest::Binary linked_binary;
  106. EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
  107. AssembleAndLink({body1, body2}, &linked_binary));
  108. EXPECT_THAT(GetErrorMessage(),
  109. HasSubstr("Unresolved external reference to \"foo\"."));
  110. }
  111. TEST_F(MatchingImportsToExports, TypeMismatch) {
  112. const std::string body1 = R"(
  113. OpCapability Linkage
  114. OpDecorate %1 LinkageAttributes "foo" Import
  115. %2 = OpTypeFloat 32
  116. %1 = OpVariable %2 Uniform
  117. %3 = OpVariable %2 Input
  118. )";
  119. const std::string body2 = R"(
  120. OpCapability Linkage
  121. OpDecorate %1 LinkageAttributes "foo" Export
  122. %2 = OpTypeInt 32 0
  123. %3 = OpConstant %2 42
  124. %1 = OpVariable %2 Uniform %3
  125. )";
  126. spvtest::Binary linked_binary;
  127. EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
  128. AssembleAndLink({body1, body2}, &linked_binary))
  129. << GetErrorMessage();
  130. EXPECT_THAT(
  131. GetErrorMessage(),
  132. HasSubstr("Type mismatch on symbol \"foo\" between imported "
  133. "variable/function %1 and exported variable/function %4"));
  134. }
  135. TEST_F(MatchingImportsToExports, MultipleDefinitions) {
  136. const std::string body1 = R"(
  137. OpCapability Linkage
  138. OpDecorate %1 LinkageAttributes "foo" Import
  139. %2 = OpTypeFloat 32
  140. %1 = OpVariable %2 Uniform
  141. %3 = OpVariable %2 Input
  142. )";
  143. const std::string body2 = R"(
  144. OpCapability Linkage
  145. OpDecorate %1 LinkageAttributes "foo" Export
  146. %2 = OpTypeFloat 32
  147. %3 = OpConstant %2 42
  148. %1 = OpVariable %2 Uniform %3
  149. )";
  150. const std::string body3 = R"(
  151. OpCapability Linkage
  152. OpDecorate %1 LinkageAttributes "foo" Export
  153. %2 = OpTypeFloat 32
  154. %3 = OpConstant %2 -1
  155. %1 = OpVariable %2 Uniform %3
  156. )";
  157. spvtest::Binary linked_binary;
  158. EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
  159. AssembleAndLink({body1, body2, body3}, &linked_binary))
  160. << GetErrorMessage();
  161. EXPECT_THAT(GetErrorMessage(),
  162. HasSubstr("Too many external references, 2, were found "
  163. "for \"foo\"."));
  164. }
  165. TEST_F(MatchingImportsToExports, SameNameDifferentTypes) {
  166. const std::string body1 = R"(
  167. OpCapability Linkage
  168. OpDecorate %1 LinkageAttributes "foo" Import
  169. %2 = OpTypeFloat 32
  170. %1 = OpVariable %2 Uniform
  171. %3 = OpVariable %2 Input
  172. )";
  173. const std::string body2 = R"(
  174. OpCapability Linkage
  175. OpDecorate %1 LinkageAttributes "foo" Export
  176. %2 = OpTypeInt 32 0
  177. %3 = OpConstant %2 42
  178. %1 = OpVariable %2 Uniform %3
  179. )";
  180. const std::string body3 = R"(
  181. OpCapability Linkage
  182. OpDecorate %1 LinkageAttributes "foo" Export
  183. %2 = OpTypeFloat 32
  184. %3 = OpConstant %2 12
  185. %1 = OpVariable %2 Uniform %3
  186. )";
  187. spvtest::Binary linked_binary;
  188. EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
  189. AssembleAndLink({body1, body2, body3}, &linked_binary))
  190. << GetErrorMessage();
  191. EXPECT_THAT(GetErrorMessage(),
  192. HasSubstr("Too many external references, 2, were found "
  193. "for \"foo\"."));
  194. }
  195. TEST_F(MatchingImportsToExports, DecorationMismatch) {
  196. const std::string body1 = R"(
  197. OpCapability Linkage
  198. OpDecorate %1 LinkageAttributes "foo" Import
  199. OpDecorate %2 Constant
  200. %2 = OpTypeFloat 32
  201. %1 = OpVariable %2 Uniform
  202. %3 = OpVariable %2 Input
  203. )";
  204. const std::string body2 = R"(
  205. OpCapability Linkage
  206. OpDecorate %1 LinkageAttributes "foo" Export
  207. %2 = OpTypeFloat 32
  208. %3 = OpConstant %2 42
  209. %1 = OpVariable %2 Uniform %3
  210. )";
  211. spvtest::Binary linked_binary;
  212. EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
  213. AssembleAndLink({body1, body2}, &linked_binary))
  214. << GetErrorMessage();
  215. EXPECT_THAT(
  216. GetErrorMessage(),
  217. HasSubstr("Type mismatch on symbol \"foo\" between imported "
  218. "variable/function %1 and exported variable/function %4"));
  219. }
  220. TEST_F(MatchingImportsToExports,
  221. FuncParamAttrDifferButStillMatchExportToImport) {
  222. const std::string body1 = R"(
  223. OpCapability Kernel
  224. OpCapability Linkage
  225. OpDecorate %1 LinkageAttributes "foo" Import
  226. OpDecorate %2 FuncParamAttr Zext
  227. %3 = OpTypeVoid
  228. %4 = OpTypeInt 32 0
  229. %5 = OpTypeFunction %3 %4
  230. %1 = OpFunction %3 None %5
  231. %2 = OpFunctionParameter %4
  232. OpFunctionEnd
  233. )";
  234. const std::string body2 = R"(
  235. OpCapability Kernel
  236. OpCapability Linkage
  237. OpDecorate %1 LinkageAttributes "foo" Export
  238. OpDecorate %2 FuncParamAttr Sext
  239. %3 = OpTypeVoid
  240. %4 = OpTypeInt 32 0
  241. %5 = OpTypeFunction %3 %4
  242. %1 = OpFunction %3 None %5
  243. %2 = OpFunctionParameter %4
  244. %6 = OpLabel
  245. OpReturn
  246. OpFunctionEnd
  247. )";
  248. spvtest::Binary linked_binary;
  249. EXPECT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary))
  250. << GetErrorMessage();
  251. const std::string expected_res = R"(OpCapability Kernel
  252. OpModuleProcessed "Linked by SPIR-V Tools Linker"
  253. OpDecorate %1 FuncParamAttr Sext
  254. %2 = OpTypeVoid
  255. %3 = OpTypeInt 32 0
  256. %4 = OpTypeFunction %2 %3
  257. %5 = OpFunction %2 None %4
  258. %1 = OpFunctionParameter %3
  259. %6 = OpLabel
  260. OpReturn
  261. OpFunctionEnd
  262. )";
  263. std::string res_body;
  264. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  265. EXPECT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body))
  266. << GetErrorMessage();
  267. EXPECT_EQ(expected_res, res_body);
  268. }
  269. TEST_F(MatchingImportsToExports, FunctionCtrl) {
  270. const std::string body1 = R"(
  271. OpCapability Linkage
  272. OpDecorate %1 LinkageAttributes "foo" Import
  273. %2 = OpTypeVoid
  274. %3 = OpTypeFunction %2
  275. %4 = OpTypeFloat 32
  276. %5 = OpVariable %4 Uniform
  277. %1 = OpFunction %2 None %3
  278. OpFunctionEnd
  279. )";
  280. const std::string body2 = R"(
  281. OpCapability Linkage
  282. OpDecorate %1 LinkageAttributes "foo" Export
  283. %2 = OpTypeVoid
  284. %3 = OpTypeFunction %2
  285. %1 = OpFunction %2 Inline %3
  286. %4 = OpLabel
  287. OpReturn
  288. OpFunctionEnd
  289. )";
  290. spvtest::Binary linked_binary;
  291. EXPECT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary))
  292. << GetErrorMessage();
  293. const std::string expected_res =
  294. R"(OpModuleProcessed "Linked by SPIR-V Tools Linker"
  295. %1 = OpTypeVoid
  296. %2 = OpTypeFunction %1
  297. %3 = OpTypeFloat 32
  298. %4 = OpVariable %3 Uniform
  299. %5 = OpFunction %1 Inline %2
  300. %6 = OpLabel
  301. OpReturn
  302. OpFunctionEnd
  303. )";
  304. std::string res_body;
  305. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  306. EXPECT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body))
  307. << GetErrorMessage();
  308. EXPECT_EQ(expected_res, res_body);
  309. }
  310. TEST_F(MatchingImportsToExports, UseExportedFuncParamAttr) {
  311. const std::string body1 = R"(
  312. OpCapability Kernel
  313. OpCapability Linkage
  314. OpDecorate %1 LinkageAttributes "foo" Import
  315. OpDecorate %2 FuncParamAttr Zext
  316. %2 = OpDecorationGroup
  317. OpGroupDecorate %2 %3 %4
  318. %5 = OpTypeVoid
  319. %6 = OpTypeInt 32 0
  320. %7 = OpTypeFunction %5 %6
  321. %1 = OpFunction %5 None %7
  322. %3 = OpFunctionParameter %6
  323. OpFunctionEnd
  324. %8 = OpFunction %5 None %7
  325. %4 = OpFunctionParameter %6
  326. OpFunctionEnd
  327. )";
  328. const std::string body2 = R"(
  329. OpCapability Kernel
  330. OpCapability Linkage
  331. OpDecorate %1 LinkageAttributes "foo" Export
  332. OpDecorate %2 FuncParamAttr Sext
  333. %3 = OpTypeVoid
  334. %4 = OpTypeInt 32 0
  335. %5 = OpTypeFunction %3 %4
  336. %1 = OpFunction %3 None %5
  337. %2 = OpFunctionParameter %4
  338. %6 = OpLabel
  339. OpReturn
  340. OpFunctionEnd
  341. )";
  342. spvtest::Binary linked_binary;
  343. EXPECT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary))
  344. << GetErrorMessage();
  345. const std::string expected_res = R"(OpCapability Kernel
  346. OpModuleProcessed "Linked by SPIR-V Tools Linker"
  347. OpDecorate %1 FuncParamAttr Zext
  348. %1 = OpDecorationGroup
  349. OpGroupDecorate %1 %2
  350. OpDecorate %3 FuncParamAttr Sext
  351. %4 = OpTypeVoid
  352. %5 = OpTypeInt 32 0
  353. %6 = OpTypeFunction %4 %5
  354. %7 = OpFunction %4 None %6
  355. %2 = OpFunctionParameter %5
  356. OpFunctionEnd
  357. %8 = OpFunction %4 None %6
  358. %3 = OpFunctionParameter %5
  359. %9 = OpLabel
  360. OpReturn
  361. OpFunctionEnd
  362. )";
  363. std::string res_body;
  364. SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
  365. EXPECT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body))
  366. << GetErrorMessage();
  367. EXPECT_EQ(expected_res, res_body);
  368. }
  369. } // namespace
  370. } // namespace spvtools