79 lines
2.3 KiB
C++
79 lines
2.3 KiB
C++
// 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
|