pass_utils.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  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. #include "test/opt/pass_utils.h"
  15. #include <algorithm>
  16. #include <sstream>
  17. namespace spvtools {
  18. namespace opt {
  19. namespace {
  20. // Well, this is another place requiring the knowledge of the grammar and can be
  21. // stale when SPIR-V is updated. It would be nice to automatically generate
  22. // this, but the cost is just too high.
  23. const char* kDebugOpcodes[] = {
  24. // clang-format off
  25. "OpSourceContinued", "OpSource", "OpSourceExtension",
  26. "OpName", "OpMemberName", "OpString",
  27. "OpLine", "OpNoLine", "OpModuleProcessed"
  28. // clang-format on
  29. };
  30. } // anonymous namespace
  31. MessageConsumer GetTestMessageConsumer(
  32. std::vector<Message>& expected_messages) {
  33. return [&expected_messages](spv_message_level_t level, const char* source,
  34. const spv_position_t& position,
  35. const char* message) {
  36. EXPECT_TRUE(!expected_messages.empty());
  37. if (expected_messages.empty()) {
  38. return;
  39. }
  40. EXPECT_EQ(expected_messages[0].level, level);
  41. EXPECT_EQ(expected_messages[0].line_number, position.line);
  42. EXPECT_EQ(expected_messages[0].column_number, position.column);
  43. EXPECT_STREQ(expected_messages[0].source_file, source);
  44. EXPECT_STREQ(expected_messages[0].message, message);
  45. expected_messages.erase(expected_messages.begin());
  46. };
  47. }
  48. bool FindAndReplace(std::string* process_str, const std::string find_str,
  49. const std::string replace_str) {
  50. if (process_str->empty() || find_str.empty()) {
  51. return false;
  52. }
  53. bool replaced = false;
  54. // Note this algorithm has quadratic time complexity. It is OK for test cases
  55. // with short strings, but might not fit in other contexts.
  56. for (size_t pos = process_str->find(find_str, 0); pos != std::string::npos;
  57. pos = process_str->find(find_str, pos)) {
  58. process_str->replace(pos, find_str.length(), replace_str);
  59. pos += replace_str.length();
  60. replaced = true;
  61. }
  62. return replaced;
  63. }
  64. bool ContainsDebugOpcode(const char* inst) {
  65. return std::any_of(std::begin(kDebugOpcodes), std::end(kDebugOpcodes),
  66. [inst](const char* op) {
  67. return std::string(inst).find(op) != std::string::npos;
  68. });
  69. }
  70. std::string SelectiveJoin(const std::vector<const char*>& strings,
  71. const std::function<bool(const char*)>& skip_dictator,
  72. char delimiter) {
  73. std::ostringstream oss;
  74. for (const auto* str : strings) {
  75. if (!skip_dictator(str)) oss << str << delimiter;
  76. }
  77. return oss.str();
  78. }
  79. std::string JoinAllInsts(const std::vector<const char*>& insts) {
  80. return SelectiveJoin(insts, [](const char*) { return false; });
  81. }
  82. std::string JoinNonDebugInsts(const std::vector<const char*>& insts) {
  83. return SelectiveJoin(
  84. insts, [](const char* inst) { return ContainsDebugOpcode(inst); });
  85. }
  86. } // namespace opt
  87. } // namespace spvtools