// Copyright (c) 2016 Google Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "test/opt/pass_utils.h" #include <algorithm> #include <sstream> namespace spvtools { namespace opt { namespace { // Well, this is another place requiring the knowledge of the grammar and can be // stale when SPIR-V is updated. It would be nice to automatically generate // this, but the cost is just too high. const char* kDebugOpcodes[] = { // clang-format off "OpSourceContinued", "OpSource", "OpSourceExtension", "OpName", "OpMemberName", "OpString", "OpLine", "OpNoLine", "OpModuleProcessed" // clang-format on }; } // anonymous namespace MessageConsumer GetTestMessageConsumer( std::vector<Message>& expected_messages) { return [&expected_messages](spv_message_level_t level, const char* source, const spv_position_t& position, const char* message) { EXPECT_TRUE(!expected_messages.empty()); if (expected_messages.empty()) { return; } EXPECT_EQ(expected_messages[0].level, level); EXPECT_EQ(expected_messages[0].line_number, position.line); EXPECT_EQ(expected_messages[0].column_number, position.column); EXPECT_STREQ(expected_messages[0].source_file, source); EXPECT_STREQ(expected_messages[0].message, message); expected_messages.erase(expected_messages.begin()); }; } bool FindAndReplace(std::string* process_str, const std::string find_str, const std::string replace_str) { if (process_str->empty() || find_str.empty()) { return false; } bool replaced = false; // Note this algorithm has quadratic time complexity. It is OK for test cases // with short strings, but might not fit in other contexts. for (size_t pos = process_str->find(find_str, 0); pos != std::string::npos; pos = process_str->find(find_str, pos)) { process_str->replace(pos, find_str.length(), replace_str); pos += replace_str.length(); replaced = true; } return replaced; } bool ContainsDebugOpcode(const char* inst) { return std::any_of(std::begin(kDebugOpcodes), std::end(kDebugOpcodes), [inst](const char* op) { return std::string(inst).find(op) != std::string::npos; }); } std::string SelectiveJoin(const std::vector<const char*>& strings, const std::function<bool(const char*)>& skip_dictator, char delimiter) { std::ostringstream oss; for (const auto* str : strings) { if (!skip_dictator(str)) oss << str << delimiter; } return oss.str(); } std::string JoinAllInsts(const std::vector<const char*>& insts) { return SelectiveJoin(insts, [](const char*) { return false; }); } std::string JoinNonDebugInsts(const std::vector<const char*>& insts) { return SelectiveJoin( insts, [](const char* inst) { return ContainsDebugOpcode(inst); }); } } // namespace opt } // namespace spvtools