mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
125 lines
3.2 KiB
C++
125 lines
3.2 KiB
C++
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/IR/Intrinsics.h"
|
|
#include "llvm/IR/Module.h"
|
|
#include "llvm/IR/ModuleSlotTracker.h"
|
|
|
|
#include "revng/Support/Assert.h"
|
|
|
|
#include "PostLiftVerifyPass.h"
|
|
|
|
using namespace llvm;
|
|
|
|
bool PostLiftVerifyPass::runOnModule(Module &M) {
|
|
Function *RootFunction = M.getFunction("root");
|
|
revng_assert(RootFunction != nullptr);
|
|
|
|
llvm::ModuleSlotTracker MST(&M, false);
|
|
|
|
for (BasicBlock &BB : *RootFunction) {
|
|
// Ignore some special basic blocks
|
|
if (BB.getName() == "dispatcher.default"
|
|
or BB.getName() == "serialize_and_jump_out"
|
|
or BB.getName() == "return_from_external" or BB.getName() == "setjmp"
|
|
or BB.getName() == "dispatcher.external")
|
|
continue;
|
|
|
|
for (Instruction &I : BB) {
|
|
bool Good = false;
|
|
|
|
switch (I.getOpcode()) {
|
|
case Instruction::Store:
|
|
case Instruction::Load:
|
|
Good = true;
|
|
break;
|
|
|
|
case Instruction::IntToPtr:
|
|
case Instruction::Add:
|
|
case Instruction::Sub:
|
|
case Instruction::Mul:
|
|
case Instruction::UDiv:
|
|
case Instruction::SDiv:
|
|
case Instruction::URem:
|
|
case Instruction::SRem:
|
|
case Instruction::And:
|
|
case Instruction::Or:
|
|
case Instruction::Xor:
|
|
case Instruction::ZExt:
|
|
case Instruction::Trunc:
|
|
case Instruction::SExt:
|
|
case Instruction::ICmp:
|
|
case Instruction::LShr:
|
|
case Instruction::AShr:
|
|
case Instruction::Shl:
|
|
case Instruction::Select:
|
|
Good = true;
|
|
break;
|
|
|
|
case Instruction::Br:
|
|
case Instruction::Switch:
|
|
case Instruction::Unreachable:
|
|
Good = true;
|
|
break;
|
|
|
|
case Instruction::PHI:
|
|
Good = true;
|
|
break;
|
|
|
|
case Instruction::ExtractValue:
|
|
Good = true;
|
|
break;
|
|
|
|
case Instruction::Call:
|
|
// Make further checks
|
|
auto *Call = cast<CallInst>(&I);
|
|
Value *CalledOperand = Call->getCalledOperand();
|
|
Function *Callee = dyn_cast_or_null<Function>(CalledOperand);
|
|
StringRef CalleeName;
|
|
if (Callee != nullptr)
|
|
CalleeName = Callee->getName();
|
|
|
|
Good = (CalleeName == "newpc" or CalleeName == "jump_to_symbol"
|
|
or CalleeName.startswith("helper_")
|
|
or CalleeName == "function_call"
|
|
or CalleeName == "helper_initialize_env"
|
|
or CalleeName == "revng_abort");
|
|
|
|
switch (Callee->getIntrinsicID()) {
|
|
case Intrinsic::fshl:
|
|
case Intrinsic::fshr:
|
|
case Intrinsic::bswap:
|
|
case Intrinsic::abs:
|
|
case Intrinsic::umin:
|
|
case Intrinsic::umax:
|
|
case Intrinsic::smin:
|
|
case Intrinsic::smax:
|
|
case Intrinsic::ctlz:
|
|
case Intrinsic::cttz:
|
|
case Intrinsic::ctpop:
|
|
Good = true;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
if (not Good) {
|
|
std::string Buffer;
|
|
{
|
|
llvm::raw_string_ostream Stream(Buffer);
|
|
Stream << "Unexpected instruction: ";
|
|
I.print(Stream, MST);
|
|
Stream << "\n";
|
|
}
|
|
revng_abort(Buffer.c_str());
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
char PostLiftVerifyPass::ID;
|