mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
c05974478c
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).
65 lines
1.8 KiB
C++
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;
|
|
}
|