id_descriptor.cpp 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. // Copyright (c) 2017 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 "source/id_descriptor.h"
  15. #include <cassert>
  16. #include <iostream>
  17. #include "source/opcode.h"
  18. #include "source/operand.h"
  19. namespace spvtools {
  20. namespace {
  21. // Hashes an array of words. Order of words is important.
  22. uint32_t HashU32Array(const std::vector<uint32_t>& words) {
  23. // The hash function is a sum of hashes of each word seeded by word index.
  24. // Knuth's multiplicative hash is used to hash the words.
  25. const uint32_t kKnuthMulHash = 2654435761;
  26. uint32_t val = 0;
  27. for (uint32_t i = 0; i < words.size(); ++i) {
  28. val += (words[i] + i + 123) * kKnuthMulHash;
  29. }
  30. return val;
  31. }
  32. } // namespace
  33. uint32_t IdDescriptorCollection::ProcessInstruction(
  34. const spv_parsed_instruction_t& inst) {
  35. if (!inst.result_id) return 0;
  36. assert(words_.empty());
  37. words_.push_back(inst.words[0]);
  38. for (size_t operand_index = 0; operand_index < inst.num_operands;
  39. ++operand_index) {
  40. const auto& operand = inst.operands[operand_index];
  41. if (spvIsIdType(operand.type)) {
  42. const uint32_t id = inst.words[operand.offset];
  43. const auto it = id_to_descriptor_.find(id);
  44. // Forward declared ids are not hashed.
  45. if (it != id_to_descriptor_.end()) {
  46. words_.push_back(it->second);
  47. }
  48. } else {
  49. for (size_t operand_word_index = 0;
  50. operand_word_index < operand.num_words; ++operand_word_index) {
  51. words_.push_back(inst.words[operand.offset + operand_word_index]);
  52. }
  53. }
  54. }
  55. uint32_t descriptor =
  56. custom_hash_func_ ? custom_hash_func_(words_) : HashU32Array(words_);
  57. if (descriptor == 0) descriptor = 1;
  58. assert(descriptor);
  59. words_.clear();
  60. const auto result = id_to_descriptor_.emplace(inst.result_id, descriptor);
  61. assert(result.second);
  62. (void)result;
  63. return descriptor;
  64. }
  65. } // namespace spvtools