#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/AsmParser/Parser.h"
#include "llvm/Bitcode/BitcodeReader.h"
#include "llvm/Bitcode/BitcodeWriter.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/UseListOrder.h"
#include "llvm/IR/Verifier.h"
#include "llvm/IRReader/IRReader.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/SystemUtils.h"
#include "llvm/Support/raw_ostream.h"
#include <random>
#include <vector>
usingnamespacellvm;
#define DEBUG_TYPE …
static cl::OptionCategory Cat("verify-uselistorder Options");
static cl::opt<std::string> InputFilename(cl::Positional,
cl::desc("<input bitcode file>"),
cl::init("-"),
cl::value_desc("filename"));
static cl::opt<bool> SaveTemps("save-temps", cl::desc("Save temp files"),
cl::cat(Cat));
static cl::opt<unsigned>
NumShuffles("num-shuffles",
cl::desc("Number of times to shuffle and verify use-lists"),
cl::init(1), cl::cat(Cat));
extern cl::opt<cl::boolOrDefault> PreserveInputDbgFormat;
namespace {
struct TempFile { … };
struct ValueMapping { … };
}
bool TempFile::init(const std::string &Ext) { … }
bool TempFile::writeBitcode(const Module &M) const { … }
bool TempFile::writeAssembly(const Module &M) const { … }
std::unique_ptr<Module> TempFile::readBitcode(LLVMContext &Context) const { … }
std::unique_ptr<Module> TempFile::readAssembly(LLVMContext &Context) const { … }
ValueMapping::ValueMapping(const Module &M) { … }
void ValueMapping::map(const Value *V) { … }
#ifndef NDEBUG
static void dumpMapping(const ValueMapping &VM) {
dbgs() << "value-mapping (size = " << VM.Values.size() << "):\n";
for (unsigned I = 0, E = VM.Values.size(); I != E; ++I) {
dbgs() << " - id = " << I << ", value = ";
VM.Values[I]->dump();
}
}
static void debugValue(const ValueMapping &M, unsigned I, StringRef Desc) {
const Value *V = M.Values[I];
dbgs() << " - " << Desc << " value = ";
V->dump();
for (const Use &U : V->uses()) {
dbgs() << " => use: op = " << U.getOperandNo()
<< ", user-id = " << M.IDs.lookup(U.getUser()) << ", user = ";
U.getUser()->dump();
}
}
static void debugUserMismatch(const ValueMapping &L, const ValueMapping &R,
unsigned I) {
dbgs() << " - fail: user mismatch: ID = " << I << "\n";
debugValue(L, I, "LHS");
debugValue(R, I, "RHS");
dbgs() << "\nlhs-";
dumpMapping(L);
dbgs() << "\nrhs-";
dumpMapping(R);
}
static void debugSizeMismatch(const ValueMapping &L, const ValueMapping &R) {
dbgs() << " - fail: map size: " << L.Values.size()
<< " != " << R.Values.size() << "\n";
dbgs() << "\nlhs-";
dumpMapping(L);
dbgs() << "\nrhs-";
dumpMapping(R);
}
#endif
static bool matches(const ValueMapping &LM, const ValueMapping &RM) { … }
static void verifyAfterRoundTrip(const Module &M,
std::unique_ptr<Module> OtherM) { … }
static void verifyBitcodeUseListOrder(const Module &M) { … }
static void verifyAssemblyUseListOrder(const Module &M) { … }
static void verifyUseListOrder(const Module &M) { … }
static void shuffleValueUseLists(Value *V, std::minstd_rand0 &Gen,
DenseSet<Value *> &Seen) { … }
static void reverseValueUseLists(Value *V, DenseSet<Value *> &Seen) { … }
template <class Changer>
static void changeUseLists(Module &M, Changer changeValueUseList) { … }
static void shuffleUseLists(Module &M, unsigned SeedOffset) { … }
static void reverseUseLists(Module &M) { … }
int main(int argc, char **argv) { … }