1 // Copyright (c) 2016 Google 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 #include <memory> 16 #include <sstream> 17 #include <string> 18 #include <vector> 19 20 #include "gmock/gmock.h" 21 #include "gtest/gtest.h" 22 #include "source/opt/build_module.h" 23 #include "source/opt/module.h" 24 #include "spirv-tools/libspirv.hpp" 25 #include "test/opt/module_utils.h" 26 27 namespace spvtools { 28 namespace opt { 29 namespace { 30 31 using ::testing::Eq; 32 using spvtest::GetIdBound; 33 34 TEST(ModuleTest, SetIdBound) { 35 Module m; 36 // It's initialized to 0. 37 EXPECT_EQ(0u, GetIdBound(m)); 38 39 m.SetIdBound(19); 40 EXPECT_EQ(19u, GetIdBound(m)); 41 42 m.SetIdBound(102); 43 EXPECT_EQ(102u, GetIdBound(m)); 44 } 45 46 // Returns an IRContext owning the module formed by assembling the given text, 47 // then loading the result. 48 inline std::unique_ptr<IRContext> BuildModule(std::string text) { 49 return spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text, 50 SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS); 51 } 52 53 TEST(ModuleTest, ComputeIdBound) { 54 // Emtpy module case. 55 EXPECT_EQ(1u, BuildModule("")->module()->ComputeIdBound()); 56 // Sensitive to result id 57 EXPECT_EQ(2u, BuildModule("%void = OpTypeVoid")->module()->ComputeIdBound()); 58 // Sensitive to type id 59 EXPECT_EQ(1000u, 60 BuildModule("%a = OpTypeArray !999 3")->module()->ComputeIdBound()); 61 // Sensitive to a regular Id parameter 62 EXPECT_EQ(2000u, 63 BuildModule("OpDecorate !1999 0")->module()->ComputeIdBound()); 64 // Sensitive to a scope Id parameter. 65 EXPECT_EQ(3000u, 66 BuildModule("%f = OpFunction %void None %fntype %a = OpLabel " 67 "OpMemoryBarrier !2999 %b\n") 68 ->module() 69 ->ComputeIdBound()); 70 // Sensitive to a semantics Id parameter 71 EXPECT_EQ(4000u, 72 BuildModule("%f = OpFunction %void None %fntype %a = OpLabel " 73 "OpMemoryBarrier %b !3999\n") 74 ->module() 75 ->ComputeIdBound()); 76 } 77 78 TEST(ModuleTest, OstreamOperator) { 79 const std::string text = R"(OpCapability Shader 80 OpCapability Linkage 81 OpMemoryModel Logical GLSL450 82 OpName %7 "restrict" 83 OpDecorate %8 Restrict 84 %9 = OpTypeVoid 85 %10 = OpTypeInt 32 0 86 %11 = OpTypeStruct %10 %10 87 %12 = OpTypePointer Function %10 88 %13 = OpTypePointer Function %11 89 %14 = OpConstant %10 0 90 %15 = OpConstant %10 1 91 %7 = OpTypeFunction %9 92 %1 = OpFunction %9 None %7 93 %2 = OpLabel 94 %8 = OpVariable %13 Function 95 %3 = OpAccessChain %12 %8 %14 96 %4 = OpLoad %10 %3 97 %5 = OpAccessChain %12 %8 %15 98 %6 = OpLoad %10 %5 99 OpReturn 100 OpFunctionEnd)"; 101 102 std::string s; 103 std::ostringstream str(s); 104 str << *BuildModule(text)->module(); 105 EXPECT_EQ(text, str.str()); 106 } 107 108 TEST(ModuleTest, OstreamOperatorInt64) { 109 const std::string text = R"(OpCapability Shader 110 OpCapability Linkage 111 OpCapability Int64 112 OpMemoryModel Logical GLSL450 113 OpName %7 "restrict" 114 OpDecorate %5 Restrict 115 %9 = OpTypeVoid 116 %10 = OpTypeInt 64 0 117 %11 = OpTypeStruct %10 %10 118 %12 = OpTypePointer Function %10 119 %13 = OpTypePointer Function %11 120 %14 = OpConstant %10 0 121 %15 = OpConstant %10 1 122 %16 = OpConstant %10 4294967297 123 %7 = OpTypeFunction %9 124 %1 = OpFunction %9 None %7 125 %2 = OpLabel 126 %5 = OpVariable %12 Function 127 %6 = OpLoad %10 %5 128 OpSelectionMerge %3 None 129 OpSwitch %6 %3 4294967297 %4 130 %4 = OpLabel 131 OpBranch %3 132 %3 = OpLabel 133 OpReturn 134 OpFunctionEnd)"; 135 136 std::string s; 137 std::ostringstream str(s); 138 str << *BuildModule(text)->module(); 139 EXPECT_EQ(text, str.str()); 140 } 141 142 TEST(ModuleTest, IdBoundTestAtLimit) { 143 const std::string text = R"( 144 OpCapability Shader 145 OpCapability Linkage 146 OpMemoryModel Logical GLSL450 147 %1 = OpTypeVoid 148 %2 = OpTypeFunction %1 149 %3 = OpFunction %1 None %2 150 %4 = OpLabel 151 OpReturn 152 OpFunctionEnd)"; 153 154 std::unique_ptr<IRContext> context = BuildModule(text); 155 uint32_t current_bound = context->module()->id_bound(); 156 context->set_max_id_bound(current_bound); 157 uint32_t next_id_bound = context->module()->TakeNextIdBound(); 158 EXPECT_EQ(next_id_bound, 0); 159 EXPECT_EQ(current_bound, context->module()->id_bound()); 160 next_id_bound = context->module()->TakeNextIdBound(); 161 EXPECT_EQ(next_id_bound, 0); 162 } 163 164 TEST(ModuleTest, IdBoundTestBelowLimit) { 165 const std::string text = R"( 166 OpCapability Shader 167 OpCapability Linkage 168 OpMemoryModel Logical GLSL450 169 %1 = OpTypeVoid 170 %2 = OpTypeFunction %1 171 %3 = OpFunction %1 None %2 172 %4 = OpLabel 173 OpReturn 174 OpFunctionEnd)"; 175 176 std::unique_ptr<IRContext> context = BuildModule(text); 177 uint32_t current_bound = context->module()->id_bound(); 178 context->set_max_id_bound(current_bound + 100); 179 uint32_t next_id_bound = context->module()->TakeNextIdBound(); 180 EXPECT_EQ(next_id_bound, current_bound); 181 EXPECT_EQ(current_bound + 1, context->module()->id_bound()); 182 next_id_bound = context->module()->TakeNextIdBound(); 183 EXPECT_EQ(next_id_bound, current_bound + 1); 184 } 185 186 TEST(ModuleTest, IdBoundTestNearLimit) { 187 const std::string text = R"( 188 OpCapability Shader 189 OpCapability Linkage 190 OpMemoryModel Logical GLSL450 191 %1 = OpTypeVoid 192 %2 = OpTypeFunction %1 193 %3 = OpFunction %1 None %2 194 %4 = OpLabel 195 OpReturn 196 OpFunctionEnd)"; 197 198 std::unique_ptr<IRContext> context = BuildModule(text); 199 uint32_t current_bound = context->module()->id_bound(); 200 context->set_max_id_bound(current_bound + 1); 201 uint32_t next_id_bound = context->module()->TakeNextIdBound(); 202 EXPECT_EQ(next_id_bound, current_bound); 203 EXPECT_EQ(current_bound + 1, context->module()->id_bound()); 204 next_id_bound = context->module()->TakeNextIdBound(); 205 EXPECT_EQ(next_id_bound, 0); 206 } 207 208 TEST(ModuleTest, IdBoundTestUIntMax) { 209 const std::string text = R"( 210 OpCapability Shader 211 OpCapability Linkage 212 OpMemoryModel Logical GLSL450 213 %1 = OpTypeVoid 214 %2 = OpTypeFunction %1 215 %3 = OpFunction %1 None %2 216 %4294967294 = OpLabel ; ID is UINT_MAX-1 217 OpReturn 218 OpFunctionEnd)"; 219 220 std::unique_ptr<IRContext> context = BuildModule(text); 221 uint32_t current_bound = context->module()->id_bound(); 222 223 // Expecting |BuildModule| to preserve the numeric ids. 224 EXPECT_EQ(current_bound, std::numeric_limits<uint32_t>::max()); 225 226 context->set_max_id_bound(current_bound); 227 uint32_t next_id_bound = context->module()->TakeNextIdBound(); 228 EXPECT_EQ(next_id_bound, 0); 229 EXPECT_EQ(current_bound, context->module()->id_bound()); 230 } 231 } // namespace 232 } // namespace opt 233 } // namespace spvtools 234