• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
15 #include <string>
16 
17 #include "gmock/gmock.h"
18 #include "test/link/linker_fixture.h"
19 
20 namespace spvtools {
21 namespace {
22 
23 using ::testing::HasSubstr;
24 using MatchingImportsToExports = spvtest::LinkerTest;
25 
TEST_F(MatchingImportsToExports,Default)26 TEST_F(MatchingImportsToExports, Default) {
27   const std::string body1 = R"(
28 OpCapability Linkage
29 OpCapability Addresses
30 OpCapability Kernel
31 OpMemoryModel Physical64 OpenCL
32 OpDecorate %1 LinkageAttributes "foo" Import
33 %2 = OpTypeFloat 32
34 %1 = OpVariable %2 Uniform
35 %3 = OpVariable %2 Input
36 )";
37   const std::string body2 = R"(
38 OpCapability Linkage
39 OpCapability Addresses
40 OpCapability Kernel
41 OpMemoryModel Physical64 OpenCL
42 OpDecorate %1 LinkageAttributes "foo" Export
43 %2 = OpTypeFloat 32
44 %3 = OpConstant %2 42
45 %1 = OpVariable %2 Uniform %3
46 )";
47 
48   spvtest::Binary linked_binary;
49   ASSERT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary))
50       << GetErrorMessage();
51 
52   const std::string expected_res =
53       R"(OpCapability Addresses
54 OpCapability Kernel
55 OpMemoryModel Physical64 OpenCL
56 OpModuleProcessed "Linked by SPIR-V Tools Linker"
57 %1 = OpTypeFloat 32
58 %2 = OpVariable %1 Input
59 %3 = OpConstant %1 42
60 %4 = OpVariable %1 Uniform %3
61 )";
62   std::string res_body;
63   SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
64   ASSERT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body))
65       << GetErrorMessage();
66   EXPECT_EQ(expected_res, res_body);
67 }
68 
TEST_F(MatchingImportsToExports,NotALibraryExtraExports)69 TEST_F(MatchingImportsToExports, NotALibraryExtraExports) {
70   const std::string body = R"(
71 OpCapability Linkage
72 OpCapability Addresses
73 OpCapability Kernel
74 OpMemoryModel Physical64 OpenCL
75 OpDecorate %1 LinkageAttributes "foo" Export
76 %2 = OpTypeFloat 32
77 %1 = OpVariable %2 Uniform
78 )";
79 
80   spvtest::Binary linked_binary;
81   ASSERT_EQ(SPV_SUCCESS, AssembleAndLink({body}, &linked_binary))
82       << GetErrorMessage();
83 
84   const std::string expected_res =
85       R"(OpCapability Addresses
86 OpCapability Kernel
87 OpMemoryModel Physical64 OpenCL
88 OpModuleProcessed "Linked by SPIR-V Tools Linker"
89 %1 = OpTypeFloat 32
90 %2 = OpVariable %1 Uniform
91 )";
92   std::string res_body;
93   SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
94   ASSERT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body))
95       << GetErrorMessage();
96   EXPECT_EQ(expected_res, res_body);
97 }
98 
TEST_F(MatchingImportsToExports,LibraryExtraExports)99 TEST_F(MatchingImportsToExports, LibraryExtraExports) {
100   const std::string body = R"(
101 OpCapability Linkage
102 OpCapability Addresses
103 OpCapability Kernel
104 OpMemoryModel Physical64 OpenCL
105 OpDecorate %1 LinkageAttributes "foo" Export
106 %2 = OpTypeFloat 32
107 %1 = OpVariable %2 Uniform
108 )";
109 
110   spvtest::Binary linked_binary;
111   LinkerOptions options;
112   options.SetCreateLibrary(true);
113   ASSERT_EQ(SPV_SUCCESS, AssembleAndLink({body}, &linked_binary, options))
114       << GetErrorMessage();
115 
116   const std::string expected_res = R"(OpCapability Linkage
117 OpCapability Addresses
118 OpCapability Kernel
119 OpMemoryModel Physical64 OpenCL
120 OpModuleProcessed "Linked by SPIR-V Tools Linker"
121 OpDecorate %1 LinkageAttributes "foo" Export
122 %2 = OpTypeFloat 32
123 %1 = OpVariable %2 Uniform
124 )";
125   std::string res_body;
126   SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
127   ASSERT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body))
128       << GetErrorMessage();
129   EXPECT_EQ(expected_res, res_body);
130 }
131 
TEST_F(MatchingImportsToExports,UnresolvedImports)132 TEST_F(MatchingImportsToExports, UnresolvedImports) {
133   const std::string body1 = R"(
134 OpCapability Linkage
135 OpCapability Addresses
136 OpCapability Kernel
137 OpMemoryModel Physical64 OpenCL
138 OpDecorate %1 LinkageAttributes "foo" Import
139 %2 = OpTypeFloat 32
140 %1 = OpVariable %2 Uniform
141 )";
142   const std::string body2 = R"(
143 OpCapability Addresses
144 OpCapability Kernel
145 OpMemoryModel Physical64 OpenCL
146 )";
147 
148   spvtest::Binary linked_binary;
149   EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
150             AssembleAndLink({body1, body2}, &linked_binary));
151   EXPECT_THAT(GetErrorMessage(),
152               HasSubstr("Unresolved external reference to \"foo\"."));
153 }
154 
TEST_F(MatchingImportsToExports,TypeMismatch)155 TEST_F(MatchingImportsToExports, TypeMismatch) {
156   const std::string body1 = R"(
157 OpCapability Linkage
158 OpCapability Addresses
159 OpCapability Kernel
160 OpMemoryModel Physical64 OpenCL
161 OpDecorate %1 LinkageAttributes "foo" Import
162 %2 = OpTypeFloat 32
163 %1 = OpVariable %2 Uniform
164 %3 = OpVariable %2 Input
165 )";
166   const std::string body2 = R"(
167 OpCapability Linkage
168 OpCapability Addresses
169 OpCapability Kernel
170 OpMemoryModel Physical64 OpenCL
171 OpDecorate %1 LinkageAttributes "foo" Export
172 %2 = OpTypeInt 32 0
173 %3 = OpConstant %2 42
174 %1 = OpVariable %2 Uniform %3
175 )";
176 
177   spvtest::Binary linked_binary;
178   EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
179             AssembleAndLink({body1, body2}, &linked_binary))
180       << GetErrorMessage();
181   EXPECT_THAT(
182       GetErrorMessage(),
183       HasSubstr("Type mismatch on symbol \"foo\" between imported "
184                 "variable/function %1 and exported variable/function %4"));
185 }
186 
TEST_F(MatchingImportsToExports,MultipleDefinitions)187 TEST_F(MatchingImportsToExports, MultipleDefinitions) {
188   const std::string body1 = R"(
189 OpCapability Linkage
190 OpCapability Addresses
191 OpCapability Kernel
192 OpMemoryModel Physical64 OpenCL
193 OpDecorate %1 LinkageAttributes "foo" Import
194 %2 = OpTypeFloat 32
195 %1 = OpVariable %2 Uniform
196 %3 = OpVariable %2 Input
197 )";
198   const std::string body2 = R"(
199 OpCapability Linkage
200 OpCapability Addresses
201 OpCapability Kernel
202 OpMemoryModel Physical64 OpenCL
203 OpDecorate %1 LinkageAttributes "foo" Export
204 %2 = OpTypeFloat 32
205 %3 = OpConstant %2 42
206 %1 = OpVariable %2 Uniform %3
207 )";
208   const std::string body3 = R"(
209 OpCapability Linkage
210 OpCapability Addresses
211 OpCapability Kernel
212 OpMemoryModel Physical64 OpenCL
213 OpDecorate %1 LinkageAttributes "foo" Export
214 %2 = OpTypeFloat 32
215 %3 = OpConstant %2 -1
216 %1 = OpVariable %2 Uniform %3
217 )";
218 
219   spvtest::Binary linked_binary;
220   EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
221             AssembleAndLink({body1, body2, body3}, &linked_binary))
222       << GetErrorMessage();
223   EXPECT_THAT(GetErrorMessage(),
224               HasSubstr("Too many external references, 2, were found "
225                         "for \"foo\"."));
226 }
227 
TEST_F(MatchingImportsToExports,SameNameDifferentTypes)228 TEST_F(MatchingImportsToExports, SameNameDifferentTypes) {
229   const std::string body1 = R"(
230 OpCapability Linkage
231 OpCapability Addresses
232 OpCapability Kernel
233 OpMemoryModel Physical64 OpenCL
234 OpDecorate %1 LinkageAttributes "foo" Import
235 %2 = OpTypeFloat 32
236 %1 = OpVariable %2 Uniform
237 %3 = OpVariable %2 Input
238 )";
239   const std::string body2 = R"(
240 OpCapability Linkage
241 OpCapability Addresses
242 OpCapability Kernel
243 OpMemoryModel Physical64 OpenCL
244 OpDecorate %1 LinkageAttributes "foo" Export
245 %2 = OpTypeInt 32 0
246 %3 = OpConstant %2 42
247 %1 = OpVariable %2 Uniform %3
248 )";
249   const std::string body3 = R"(
250 OpCapability Linkage
251 OpCapability Addresses
252 OpCapability Kernel
253 OpMemoryModel Physical64 OpenCL
254 OpDecorate %1 LinkageAttributes "foo" Export
255 %2 = OpTypeFloat 32
256 %3 = OpConstant %2 12
257 %1 = OpVariable %2 Uniform %3
258 )";
259 
260   spvtest::Binary linked_binary;
261   EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
262             AssembleAndLink({body1, body2, body3}, &linked_binary))
263       << GetErrorMessage();
264   EXPECT_THAT(GetErrorMessage(),
265               HasSubstr("Too many external references, 2, were found "
266                         "for \"foo\"."));
267 }
268 
TEST_F(MatchingImportsToExports,DecorationMismatch)269 TEST_F(MatchingImportsToExports, DecorationMismatch) {
270   const std::string body1 = R"(
271 OpCapability Linkage
272 OpCapability Addresses
273 OpCapability Kernel
274 OpMemoryModel Physical64 OpenCL
275 OpDecorate %1 LinkageAttributes "foo" Import
276 OpDecorate %2 Constant
277 %2 = OpTypeFloat 32
278 %1 = OpVariable %2 Uniform
279 %3 = OpVariable %2 Input
280 )";
281   const std::string body2 = R"(
282 OpCapability Linkage
283 OpCapability Addresses
284 OpCapability Kernel
285 OpMemoryModel Physical64 OpenCL
286 OpDecorate %1 LinkageAttributes "foo" Export
287 %2 = OpTypeFloat 32
288 %3 = OpConstant %2 42
289 %1 = OpVariable %2 Uniform %3
290 )";
291 
292   spvtest::Binary linked_binary;
293   EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
294             AssembleAndLink({body1, body2}, &linked_binary))
295       << GetErrorMessage();
296   EXPECT_THAT(
297       GetErrorMessage(),
298       HasSubstr("Type mismatch on symbol \"foo\" between imported "
299                 "variable/function %1 and exported variable/function %4"));
300 }
301 
TEST_F(MatchingImportsToExports,FuncParamAttrDifferButStillMatchExportToImport)302 TEST_F(MatchingImportsToExports,
303        FuncParamAttrDifferButStillMatchExportToImport) {
304   const std::string body1 = R"(
305 OpCapability Linkage
306 OpCapability Addresses
307 OpCapability Kernel
308 OpMemoryModel Physical64 OpenCL
309 OpDecorate %1 LinkageAttributes "foo" Import
310 OpDecorate %2 FuncParamAttr Zext
311 %3 = OpTypeVoid
312 %4 = OpTypeInt 32 0
313 %5 = OpTypeFunction %3 %4
314 %1 = OpFunction %3 None %5
315 %2 = OpFunctionParameter %4
316 OpFunctionEnd
317 )";
318   const std::string body2 = R"(
319 OpCapability Linkage
320 OpCapability Addresses
321 OpCapability Kernel
322 OpMemoryModel Physical64 OpenCL
323 OpDecorate %1 LinkageAttributes "foo" Export
324 OpDecorate %2 FuncParamAttr Sext
325 %3 = OpTypeVoid
326 %4 = OpTypeInt 32 0
327 %5 = OpTypeFunction %3 %4
328 %1 = OpFunction %3 None %5
329 %2 = OpFunctionParameter %4
330 %6 = OpLabel
331 OpReturn
332 OpFunctionEnd
333 )";
334 
335   spvtest::Binary linked_binary;
336   ASSERT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary))
337       << GetErrorMessage();
338 
339   const std::string expected_res = R"(OpCapability Addresses
340 OpCapability Kernel
341 OpMemoryModel Physical64 OpenCL
342 OpModuleProcessed "Linked by SPIR-V Tools Linker"
343 OpDecorate %1 FuncParamAttr Sext
344 %2 = OpTypeVoid
345 %3 = OpTypeInt 32 0
346 %4 = OpTypeFunction %2 %3
347 %5 = OpFunction %2 None %4
348 %1 = OpFunctionParameter %3
349 %6 = OpLabel
350 OpReturn
351 OpFunctionEnd
352 )";
353   std::string res_body;
354   SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
355   ASSERT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body))
356       << GetErrorMessage();
357   EXPECT_EQ(expected_res, res_body);
358 }
359 
TEST_F(MatchingImportsToExports,FunctionCtrl)360 TEST_F(MatchingImportsToExports, FunctionCtrl) {
361   const std::string body1 = R"(
362 OpCapability Linkage
363 OpCapability Addresses
364 OpCapability Kernel
365 OpMemoryModel Physical64 OpenCL
366 OpDecorate %1 LinkageAttributes "foo" Import
367 %2 = OpTypeVoid
368 %3 = OpTypeFunction %2
369 %4 = OpTypeFloat 32
370 %5 = OpVariable %4 Uniform
371 %1 = OpFunction %2 None %3
372 OpFunctionEnd
373 )";
374   const std::string body2 = R"(
375 OpCapability Linkage
376 OpCapability Addresses
377 OpCapability Kernel
378 OpMemoryModel Physical64 OpenCL
379 OpDecorate %1 LinkageAttributes "foo" Export
380 %2 = OpTypeVoid
381 %3 = OpTypeFunction %2
382 %1 = OpFunction %2 Inline %3
383 %4 = OpLabel
384 OpReturn
385 OpFunctionEnd
386 )";
387 
388   spvtest::Binary linked_binary;
389   ASSERT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary))
390       << GetErrorMessage();
391 
392   const std::string expected_res =
393       R"(OpCapability Addresses
394 OpCapability Kernel
395 OpMemoryModel Physical64 OpenCL
396 OpModuleProcessed "Linked by SPIR-V Tools Linker"
397 %1 = OpTypeVoid
398 %2 = OpTypeFunction %1
399 %3 = OpTypeFloat 32
400 %4 = OpVariable %3 Uniform
401 %5 = OpFunction %1 Inline %2
402 %6 = OpLabel
403 OpReturn
404 OpFunctionEnd
405 )";
406   std::string res_body;
407   SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
408   ASSERT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body))
409       << GetErrorMessage();
410   EXPECT_EQ(expected_res, res_body);
411 }
412 
TEST_F(MatchingImportsToExports,UseExportedFuncParamAttr)413 TEST_F(MatchingImportsToExports, UseExportedFuncParamAttr) {
414   const std::string body1 = R"(
415 OpCapability Linkage
416 OpCapability Addresses
417 OpCapability Kernel
418 OpMemoryModel Physical64 OpenCL
419 OpDecorate %1 LinkageAttributes "foo" Import
420 OpDecorate %2 FuncParamAttr Zext
421 %2 = OpDecorationGroup
422 OpGroupDecorate %2 %3 %4
423 %5 = OpTypeVoid
424 %6 = OpTypeInt 32 0
425 %7 = OpTypeFunction %5 %6
426 %1 = OpFunction %5 None %7
427 %3 = OpFunctionParameter %6
428 OpFunctionEnd
429 %8 = OpFunction %5 None %7
430 %4 = OpFunctionParameter %6
431 OpFunctionEnd
432 )";
433   const std::string body2 = R"(
434 OpCapability Linkage
435 OpCapability Addresses
436 OpCapability Kernel
437 OpMemoryModel Physical64 OpenCL
438 OpDecorate %1 LinkageAttributes "foo" Export
439 OpDecorate %2 FuncParamAttr Sext
440 %3 = OpTypeVoid
441 %4 = OpTypeInt 32 0
442 %5 = OpTypeFunction %3 %4
443 %1 = OpFunction %3 None %5
444 %2 = OpFunctionParameter %4
445 %6 = OpLabel
446 OpReturn
447 OpFunctionEnd
448 )";
449 
450   spvtest::Binary linked_binary;
451   ASSERT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary))
452       << GetErrorMessage();
453 
454   const std::string expected_res = R"(OpCapability Addresses
455 OpCapability Kernel
456 OpMemoryModel Physical64 OpenCL
457 OpModuleProcessed "Linked by SPIR-V Tools Linker"
458 OpDecorate %1 FuncParamAttr Zext
459 %1 = OpDecorationGroup
460 OpGroupDecorate %1 %2
461 OpDecorate %3 FuncParamAttr Sext
462 %4 = OpTypeVoid
463 %5 = OpTypeInt 32 0
464 %6 = OpTypeFunction %4 %5
465 %7 = OpFunction %4 None %6
466 %2 = OpFunctionParameter %5
467 OpFunctionEnd
468 %8 = OpFunction %4 None %6
469 %3 = OpFunctionParameter %5
470 %9 = OpLabel
471 OpReturn
472 OpFunctionEnd
473 )";
474   std::string res_body;
475   SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
476   ASSERT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body))
477       << GetErrorMessage();
478   EXPECT_EQ(expected_res, res_body);
479 }
480 
TEST_F(MatchingImportsToExports,NamesAndDecorations)481 TEST_F(MatchingImportsToExports, NamesAndDecorations) {
482   const std::string body1 = R"(
483 OpCapability Linkage
484 OpCapability Addresses
485 OpCapability Kernel
486 OpMemoryModel Physical64 OpenCL
487 OpName %1 "foo"
488 OpName %3 "param"
489 OpDecorate %1 LinkageAttributes "foo" Import
490 OpDecorate %2 Restrict
491 OpDecorate %4 NonWritable
492 %2 = OpDecorationGroup
493 OpGroupDecorate %2 %3 %4
494 %5 = OpTypeVoid
495 %6 = OpTypeInt 32 0
496 %9 = OpTypePointer Function %6
497 %7 = OpTypeFunction %5 %9
498 %1 = OpFunction %5 None %7
499 %3 = OpFunctionParameter %9
500 OpFunctionEnd
501 %8 = OpFunction %5 None %7
502 %4 = OpFunctionParameter %9
503 OpFunctionEnd
504 )";
505   const std::string body2 = R"(
506 OpCapability Linkage
507 OpCapability Addresses
508 OpCapability Kernel
509 OpMemoryModel Physical64 OpenCL
510 OpName %1 "foo"
511 OpName %2 "param"
512 OpDecorate %1 LinkageAttributes "foo" Export
513 OpDecorate %2 Restrict
514 %3 = OpTypeVoid
515 %4 = OpTypeInt 32 0
516 %7 = OpTypePointer Function %4
517 %5 = OpTypeFunction %3 %7
518 %1 = OpFunction %3 None %5
519 %2 = OpFunctionParameter %7
520 %6 = OpLabel
521 OpReturn
522 OpFunctionEnd
523 )";
524 
525   spvtest::Binary linked_binary;
526   ASSERT_EQ(SPV_SUCCESS, AssembleAndLink({body1, body2}, &linked_binary))
527       << GetErrorMessage();
528 
529   const std::string expected_res = R"(OpCapability Addresses
530 OpCapability Kernel
531 OpMemoryModel Physical64 OpenCL
532 OpName %1 "foo"
533 OpName %2 "param"
534 OpModuleProcessed "Linked by SPIR-V Tools Linker"
535 OpDecorate %3 Restrict
536 OpDecorate %4 NonWritable
537 %3 = OpDecorationGroup
538 OpGroupDecorate %3 %4
539 OpDecorate %2 Restrict
540 %5 = OpTypeVoid
541 %6 = OpTypeInt 32 0
542 %7 = OpTypePointer Function %6
543 %8 = OpTypeFunction %5 %7
544 %9 = OpFunction %5 None %8
545 %4 = OpFunctionParameter %7
546 OpFunctionEnd
547 %1 = OpFunction %5 None %8
548 %2 = OpFunctionParameter %7
549 %10 = OpLabel
550 OpReturn
551 OpFunctionEnd
552 )";
553   std::string res_body;
554   SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
555   ASSERT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body))
556       << GetErrorMessage();
557   EXPECT_EQ(expected_res, res_body);
558 }
559 
560 }  // namespace
561 }  // namespace spvtools
562