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
20namespace spvtools {
21namespace {
22
23using ::testing::HasSubstr;
24using PartialLinkage = spvtest::LinkerTest;
25
26TEST_F(PartialLinkage, Allowed) {
27  const std::string body1 = R"(
28OpCapability Linkage
29OpCapability Addresses
30OpCapability Kernel
31OpMemoryModel Physical64 OpenCL
32OpDecorate %1 LinkageAttributes "foo" Import
33OpDecorate %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"(
39OpCapability Linkage
40OpCapability Addresses
41OpCapability Kernel
42OpMemoryModel Physical64 OpenCL
43OpDecorate %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
57OpCapability Addresses
58OpCapability Kernel
59OpMemoryModel Physical64 OpenCL
60OpModuleProcessed "Linked by SPIR-V Tools Linker"
61OpDecorate %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
74TEST_F(PartialLinkage, Disallowed) {
75  const std::string body1 = R"(
76OpCapability Linkage
77OpCapability Addresses
78OpCapability Kernel
79OpMemoryModel Physical64 OpenCL
80OpDecorate %1 LinkageAttributes "foo" Import
81OpDecorate %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"(
87OpCapability Linkage
88OpCapability Addresses
89OpCapability Kernel
90OpMemoryModel Physical64 OpenCL
91OpDecorate %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