| // Copyright (c) 2017 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 "source/id_descriptor.h" |
| |
| #include <cassert> |
| #include <iostream> |
| |
| #include "source/opcode.h" |
| #include "source/operand.h" |
| |
| namespace spvtools { |
| namespace { |
| |
| // Hashes an array of words. Order of words is important. |
| uint32_t HashU32Array(const std::vector<uint32_t>& words) { |
| // The hash function is a sum of hashes of each word seeded by word index. |
| // Knuth's multiplicative hash is used to hash the words. |
| const uint32_t kKnuthMulHash = 2654435761; |
| uint32_t val = 0; |
| for (uint32_t i = 0; i < words.size(); ++i) { |
| val += (words[i] + i + 123) * kKnuthMulHash; |
| } |
| return val; |
| } |
| |
| } // namespace |
| |
| uint32_t IdDescriptorCollection::ProcessInstruction( |
| const spv_parsed_instruction_t& inst) { |
| if (!inst.result_id) return 0; |
| |
| assert(words_.empty()); |
| words_.push_back(inst.words[0]); |
| |
| for (size_t operand_index = 0; operand_index < inst.num_operands; |
| ++operand_index) { |
| const auto& operand = inst.operands[operand_index]; |
| if (spvIsIdType(operand.type)) { |
| const uint32_t id = inst.words[operand.offset]; |
| const auto it = id_to_descriptor_.find(id); |
| // Forward declared ids are not hashed. |
| if (it != id_to_descriptor_.end()) { |
| words_.push_back(it->second); |
| } |
| } else { |
| for (size_t operand_word_index = 0; |
| operand_word_index < operand.num_words; ++operand_word_index) { |
| words_.push_back(inst.words[operand.offset + operand_word_index]); |
| } |
| } |
| } |
| |
| uint32_t descriptor = |
| custom_hash_func_ ? custom_hash_func_(words_) : HashU32Array(words_); |
| if (descriptor == 0) descriptor = 1; |
| assert(descriptor); |
| |
| words_.clear(); |
| |
| const auto result = id_to_descriptor_.emplace(inst.result_id, descriptor); |
| assert(result.second); |
| (void)result; |
| return descriptor; |
| } |
| |
| } // namespace spvtools |