Files
revng-revng/lib/RemoveUnexpectedPCPass/RemoveUnexpectedPCPass.cpp
T
Andrea Gussoni c05974478c Add RemoveUnexpectedPCPass
Add a pass which removes the `unexpectedpc` as successor of the `switch`
instructions. This simplifies the subsequent analyses.

This pass also removes the unreachable basic blocks dandling around (as
the `unexpectedpc` and `anypc` blocks when they are not needed).
2019-03-08 15:31:30 +01:00

65 lines
1.8 KiB
C++

/// \file RemoveUnexpectedPCPass.cpp
/// \brief FunctionPass that applies the comb to the RegionCFG of a function
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
// Standard includes
#include <sstream>
#include <stdlib.h>
// LLVM includes
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_os_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
#include "llvm/Transforms/Utils/Local.h"
// revng includes
#include "revng/Support/Debug.h"
#include "revng/Support/IRHelpers.h"
// Local libraries includes
#include "revng-c/RemoveUnexpectedPCPass/RemoveUnexpectedPCPass.h"
using namespace llvm;
char RemoveUnexpectedPC::ID = 0;
static RegisterPass<RemoveUnexpectedPC>
X("removeunexpectedpc", "Remove unexpectedpc from switches", false, false);
bool RemoveUnexpectedPC::runOnFunction(Function &F) {
if (!F.getName().startswith("bb.")) {
return false;
}
ReversePostOrderTraversal<llvm::Function *> RPOT(&F);
for (BasicBlock *BB : RPOT) {
LLVMContext &Context = getContext(&F);
TerminatorInst *Terminator = BB->getTerminator();
if (auto *Switch = dyn_cast<SwitchInst>(Terminator)) {
// Get a pointer to the last successor basic block.
revng_assert(Switch->getNumCases() > 0);
unsigned SuccessorNumber = Switch->getNumSuccessors();
BasicBlock *LastSuccessor = Switch->getSuccessor(SuccessorNumber - 1);
// Remove the last successor from the cases.
ConstantInt *LastCase = Switch->findCaseDest(LastSuccessor);
Switch->removeCase(Switch->findCaseValue(LastCase));
// Make the last successor the default case.
Switch->setDefaultDest(LastSuccessor);
}
}
removeUnreachableBlocks(F);
return true;
}