1// Copyright (c) 2015-2016 The Khronos Group 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
15// Assembler tests for instructions in the "Barrier Instructions" section
16// of the SPIR-V spec.
17
18#include <string>
19
20#include "gmock/gmock.h"
21#include "test/test_fixture.h"
22#include "test/unit_spirv.h"
23
24namespace spvtools {
25namespace {
26
27using spvtest::MakeInstruction;
28using spvtest::TextToBinaryTest;
29using ::testing::_;
30using ::testing::ElementsAre;
31using ::testing::Eq;
32
33// Test OpMemoryBarrier
34
35using OpMemoryBarrier = spvtest::TextToBinaryTest;
36
37TEST_F(OpMemoryBarrier, Good) {
38  const std::string input = "OpMemoryBarrier %1 %2\n";
39  EXPECT_THAT(CompiledInstructions(input),
40              Eq(MakeInstruction(spv::Op::OpMemoryBarrier, {1, 2})));
41  EXPECT_THAT(EncodeAndDecodeSuccessfully(input), Eq(input));
42}
43
44TEST_F(OpMemoryBarrier, BadMissingScopeId) {
45  const std::string input = "OpMemoryBarrier\n";
46  EXPECT_THAT(CompileFailure(input),
47              Eq("Expected operand for OpMemoryBarrier instruction, but found "
48                 "the end of the stream."));
49}
50
51TEST_F(OpMemoryBarrier, BadInvalidScopeId) {
52  const std::string input = "OpMemoryBarrier 99\n";
53  EXPECT_THAT(CompileFailure(input), Eq("Expected id to start with %."));
54}
55
56TEST_F(OpMemoryBarrier, BadMissingMemorySemanticsId) {
57  const std::string input = "OpMemoryBarrier %scope\n";
58  EXPECT_THAT(CompileFailure(input),
59              Eq("Expected operand for OpMemoryBarrier instruction, but found "
60                 "the end of the stream."));
61}
62
63TEST_F(OpMemoryBarrier, BadInvalidMemorySemanticsId) {
64  const std::string input = "OpMemoryBarrier %scope 14\n";
65  EXPECT_THAT(CompileFailure(input), Eq("Expected id to start with %."));
66}
67
68// TODO(dneto): OpControlBarrier
69// TODO(dneto): OpGroupAsyncCopy
70// TODO(dneto): OpGroupWaitEvents
71// TODO(dneto): OpGroupAll
72// TODO(dneto): OpGroupAny
73// TODO(dneto): OpGroupBroadcast
74// TODO(dneto): OpGroupIAdd
75// TODO(dneto): OpGroupFAdd
76// TODO(dneto): OpGroupFMin
77// TODO(dneto): OpGroupUMin
78// TODO(dneto): OpGroupSMin
79// TODO(dneto): OpGroupFMax
80// TODO(dneto): OpGroupUMax
81// TODO(dneto): OpGroupSMax
82
83using NamedMemoryBarrierTest = spvtest::TextToBinaryTest;
84
85// OpMemoryNamedBarrier is not in 1.0, but it is enabled by a capability.
86// We should be able to assemble it.  Validation checks are in another test
87// file.
88TEST_F(NamedMemoryBarrierTest, OpcodeAssemblesInV10) {
89  EXPECT_THAT(
90      CompiledInstructions("OpMemoryNamedBarrier %bar %scope %semantics",
91                           SPV_ENV_UNIVERSAL_1_0),
92      ElementsAre(spvOpcodeMake(4, spv::Op::OpMemoryNamedBarrier), _, _, _));
93}
94
95TEST_F(NamedMemoryBarrierTest, ArgumentCount) {
96  EXPECT_THAT(CompileFailure("OpMemoryNamedBarrier", SPV_ENV_UNIVERSAL_1_1),
97              Eq("Expected operand for OpMemoryNamedBarrier instruction, but "
98                 "found the end of the stream."));
99  EXPECT_THAT(
100      CompileFailure("OpMemoryNamedBarrier %bar", SPV_ENV_UNIVERSAL_1_1),
101      Eq("Expected operand for OpMemoryNamedBarrier instruction, but found the "
102         "end of the stream."));
103  EXPECT_THAT(
104      CompileFailure("OpMemoryNamedBarrier %bar %scope", SPV_ENV_UNIVERSAL_1_1),
105      Eq("Expected operand for OpMemoryNamedBarrier instruction, but found the "
106         "end of the stream."));
107  EXPECT_THAT(
108      CompiledInstructions("OpMemoryNamedBarrier %bar %scope %semantics",
109                           SPV_ENV_UNIVERSAL_1_1),
110      ElementsAre(spvOpcodeMake(4, spv::Op::OpMemoryNamedBarrier), _, _, _));
111  EXPECT_THAT(
112      CompileFailure("OpMemoryNamedBarrier %bar %scope %semantics %extra",
113                     SPV_ENV_UNIVERSAL_1_1),
114      Eq("Expected '=', found end of stream."));
115}
116
117TEST_F(NamedMemoryBarrierTest, ArgumentTypes) {
118  EXPECT_THAT(CompileFailure("OpMemoryNamedBarrier 123 %scope %semantics",
119                             SPV_ENV_UNIVERSAL_1_1),
120              Eq("Expected id to start with %."));
121  EXPECT_THAT(CompileFailure("OpMemoryNamedBarrier %bar %scope \"semantics\"",
122                             SPV_ENV_UNIVERSAL_1_1),
123              Eq("Expected id to start with %."));
124}
125
126using TypeNamedBarrierTest = spvtest::TextToBinaryTest;
127
128TEST_F(TypeNamedBarrierTest, OpcodeAssemblesInV10) {
129  EXPECT_THAT(
130      CompiledInstructions("%t = OpTypeNamedBarrier", SPV_ENV_UNIVERSAL_1_0),
131      ElementsAre(spvOpcodeMake(2, spv::Op::OpTypeNamedBarrier), _));
132}
133
134TEST_F(TypeNamedBarrierTest, ArgumentCount) {
135  EXPECT_THAT(CompileFailure("OpTypeNamedBarrier", SPV_ENV_UNIVERSAL_1_1),
136              Eq("Expected <result-id> at the beginning of an instruction, "
137                 "found 'OpTypeNamedBarrier'."));
138  EXPECT_THAT(
139      CompiledInstructions("%t = OpTypeNamedBarrier", SPV_ENV_UNIVERSAL_1_1),
140      ElementsAre(spvOpcodeMake(2, spv::Op::OpTypeNamedBarrier), _));
141  EXPECT_THAT(
142      CompileFailure("%t = OpTypeNamedBarrier 1 2 3", SPV_ENV_UNIVERSAL_1_1),
143      Eq("Expected <opcode> or <result-id> at the beginning of an instruction, "
144         "found '1'."));
145}
146
147using NamedBarrierInitializeTest = spvtest::TextToBinaryTest;
148
149TEST_F(NamedBarrierInitializeTest, OpcodeAssemblesInV10) {
150  EXPECT_THAT(
151      CompiledInstructions("%bar = OpNamedBarrierInitialize %type %count",
152                           SPV_ENV_UNIVERSAL_1_0),
153      ElementsAre(spvOpcodeMake(4, spv::Op::OpNamedBarrierInitialize), _, _,
154                  _));
155}
156
157TEST_F(NamedBarrierInitializeTest, ArgumentCount) {
158  EXPECT_THAT(
159      CompileFailure("%bar = OpNamedBarrierInitialize", SPV_ENV_UNIVERSAL_1_1),
160      Eq("Expected operand for OpNamedBarrierInitialize instruction, but found "
161         "the end of the stream."));
162  EXPECT_THAT(CompileFailure("%bar = OpNamedBarrierInitialize %ype",
163                             SPV_ENV_UNIVERSAL_1_1),
164              Eq("Expected operand for OpNamedBarrierInitialize instruction, "
165                 "but found the end of the stream."));
166  EXPECT_THAT(
167      CompiledInstructions("%bar = OpNamedBarrierInitialize %type %count",
168                           SPV_ENV_UNIVERSAL_1_1),
169      ElementsAre(spvOpcodeMake(4, spv::Op::OpNamedBarrierInitialize), _, _,
170                  _));
171  EXPECT_THAT(
172      CompileFailure("%bar = OpNamedBarrierInitialize %type %count \"extra\"",
173                     SPV_ENV_UNIVERSAL_1_1),
174      Eq("Expected <opcode> or <result-id> at the beginning of an instruction, "
175         "found '\"extra\"'."));
176}
177
178}  // namespace
179}  // namespace spvtools
180