85 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			85 lines
		
	
	
		
			2.0 KiB
		
	
	
	
		
			C++
		
	
	
	
//===-- StructuralHash.cpp - IR Hash for expensive checks -------*- C++ -*-===//
 | 
						|
//
 | 
						|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | 
						|
// See https://llvm.org/LICENSE.txt for license information.
 | 
						|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
 | 
						|
#ifdef EXPENSIVE_CHECKS
 | 
						|
 | 
						|
#include "llvm/IR/StructuralHash.h"
 | 
						|
#include "llvm/IR/Function.h"
 | 
						|
#include "llvm/IR/Module.h"
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
 | 
						|
namespace {
 | 
						|
namespace details {
 | 
						|
 | 
						|
// Basic hashing mechanism to detect structural change to the IR, used to verify
 | 
						|
// pass return status consistency with actual change. Loosely copied from
 | 
						|
// llvm/lib/Transforms/Utils/FunctionComparator.cpp
 | 
						|
 | 
						|
class StructuralHash {
 | 
						|
  uint64_t Hash = 0x6acaa36bef8325c5ULL;
 | 
						|
 | 
						|
  void update(uint64_t V) { Hash = hashing::detail::hash_16_bytes(Hash, V); }
 | 
						|
 | 
						|
public:
 | 
						|
  StructuralHash() = default;
 | 
						|
 | 
						|
  void update(const Function &F) {
 | 
						|
    if (F.empty())
 | 
						|
      return;
 | 
						|
 | 
						|
    update(F.isVarArg());
 | 
						|
    update(F.arg_size());
 | 
						|
 | 
						|
    SmallVector<const BasicBlock *, 8> BBs;
 | 
						|
    SmallPtrSet<const BasicBlock *, 16> VisitedBBs;
 | 
						|
 | 
						|
    BBs.push_back(&F.getEntryBlock());
 | 
						|
    VisitedBBs.insert(BBs[0]);
 | 
						|
    while (!BBs.empty()) {
 | 
						|
      const BasicBlock *BB = BBs.pop_back_val();
 | 
						|
      update(45798); // Block header
 | 
						|
      for (auto &Inst : *BB)
 | 
						|
        update(Inst.getOpcode());
 | 
						|
 | 
						|
      const Instruction *Term = BB->getTerminator();
 | 
						|
      for (unsigned i = 0, e = Term->getNumSuccessors(); i != e; ++i) {
 | 
						|
        if (!VisitedBBs.insert(Term->getSuccessor(i)).second)
 | 
						|
          continue;
 | 
						|
        BBs.push_back(Term->getSuccessor(i));
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  void update(const Module &M) {
 | 
						|
    for (const Function &F : M)
 | 
						|
      update(F);
 | 
						|
  }
 | 
						|
 | 
						|
  uint64_t getHash() const { return Hash; }
 | 
						|
};
 | 
						|
 | 
						|
} // namespace details
 | 
						|
 | 
						|
} // namespace
 | 
						|
 | 
						|
uint64_t llvm::StructuralHash(const Function &F) {
 | 
						|
  details::StructuralHash H;
 | 
						|
  H.update(F);
 | 
						|
  return H.getHash();
 | 
						|
}
 | 
						|
 | 
						|
uint64_t llvm::StructuralHash(const Module &M) {
 | 
						|
  details::StructuralHash H;
 | 
						|
  H.update(M);
 | 
						|
  return H.getHash();
 | 
						|
}
 | 
						|
 | 
						|
#endif
 |