// 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