Files
Alessandro Di Federico d0a78a41bf Drop direct branches to the dispatcher
Generated code now either jumps to `anypc` or `unexpectedpc`. The latter
one is to be considered a safety measure and will be populated with an
unreachable instruction on the decompilation pipeline.
2021-02-19 09:39:49 +01:00

48 lines
1.4 KiB
C++

/// \file PruneRetSuccessors.cpp
/// \brief Remove successors from return instructions
//
// This file is distributed under the MIT License. See LICENSE.md for details.
//
#include "revng/FunctionCallIdentification/PruneRetSuccessors.h"
#include "revng/Support/Debug.h"
using namespace llvm;
char PruneRetSuccessors::ID = 0;
using Register = RegisterPass<PruneRetSuccessors>;
static Register X("prs", "Prune Ret Successors", true, true);
bool PruneRetSuccessors::runOnModule(llvm::Module &M) {
auto &GCBI = getAnalysis<GeneratedCodeBasicInfoWrapperPass>().getGCBI();
auto &FCI = getAnalysis<FunctionCallIdentification>();
for (BasicBlock &BB : *GCBI.root()) {
if (not GCBI.isTranslated(&BB)
or BB.getTerminator()->getNumSuccessors() < 2)
continue;
auto Successors = GCBI.getSuccessors(&BB);
if (not Successors.UnexpectedPC or Successors.Other)
continue;
revng_assert(not Successors.AnyPC);
bool AllFallthrough = true;
for (MetaAddress SuccessorMA : Successors.Addresses) {
if (not FCI.isFallthrough(SuccessorMA)) {
AllFallthrough = false;
}
}
if (AllFallthrough) {
Instruction *OldTerminator = BB.getTerminator();
auto *NewTerminator = BranchInst::Create(GCBI.anyPC(), &BB);
NewTerminator->copyMetadata(*OldTerminator);
OldTerminator->eraseFromParent();
}
}
return true;
}