1 // Copyright (c) 2018 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 PartialLinkage = spvtest::LinkerTest;
25 
TEST_F(PartialLinkage,Allowed)26 TEST_F(PartialLinkage, Allowed) {
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 OpDecorate %2 LinkageAttributes "bar" Import
34 %3 = OpTypeFloat 32
35 %1 = OpVariable %3 Uniform
36 %2 = OpVariable %3 Uniform
37 )";
38   const std::string body2 = R"(
39 OpCapability Linkage
40 OpCapability Addresses
41 OpCapability Kernel
42 OpMemoryModel Physical64 OpenCL
43 OpDecorate %1 LinkageAttributes "bar" Export
44 %2 = OpTypeFloat 32
45 %3 = OpConstant %2 3.1415
46 %1 = OpVariable %2 Uniform %3
47 )";
48 
49   spvtest::Binary linked_binary;
50   LinkerOptions linker_options;
51   linker_options.SetAllowPartialLinkage(true);
52   ASSERT_EQ(SPV_SUCCESS,
53             AssembleAndLink({body1, body2}, &linked_binary, linker_options))
54       << GetErrorMessage();
55 
56   const std::string expected_res = R"(OpCapability Linkage
57 OpCapability Addresses
58 OpCapability Kernel
59 OpMemoryModel Physical64 OpenCL
60 OpModuleProcessed "Linked by SPIR-V Tools Linker"
61 OpDecorate %1 LinkageAttributes "foo" Import
62 %2 = OpTypeFloat 32
63 %1 = OpVariable %2 Uniform
64 %3 = OpConstant %2 3.1415
65 %4 = OpVariable %2 Uniform %3
66 )";
67   std::string res_body;
68   SetDisassembleOptions(SPV_BINARY_TO_TEXT_OPTION_NO_HEADER);
69   ASSERT_EQ(SPV_SUCCESS, Disassemble(linked_binary, &res_body))
70       << GetErrorMessage();
71   EXPECT_EQ(expected_res, res_body);
72 }
73 
TEST_F(PartialLinkage,Disallowed)74 TEST_F(PartialLinkage, Disallowed) {
75   const std::string body1 = R"(
76 OpCapability Linkage
77 OpCapability Addresses
78 OpCapability Kernel
79 OpMemoryModel Physical64 OpenCL
80 OpDecorate %1 LinkageAttributes "foo" Import
81 OpDecorate %2 LinkageAttributes "bar" Import
82 %3 = OpTypeFloat 32
83 %1 = OpVariable %3 Uniform
84 %2 = OpVariable %3 Uniform
85 )";
86   const std::string body2 = R"(
87 OpCapability Linkage
88 OpCapability Addresses
89 OpCapability Kernel
90 OpMemoryModel Physical64 OpenCL
91 OpDecorate %1 LinkageAttributes "bar" Export
92 %2 = OpTypeFloat 32
93 %3 = OpConstant %2 3.1415
94 %1 = OpVariable %2 Uniform %3
95 )";
96 
97   spvtest::Binary linked_binary;
98   EXPECT_EQ(SPV_ERROR_INVALID_BINARY,
99             AssembleAndLink({body1, body2}, &linked_binary));
100   EXPECT_THAT(GetErrorMessage(),
101               HasSubstr("Unresolved external reference to \"foo\"."));
102 }
103 
104 }  // namespace
105 }  // namespace spvtools
106