Files
revng-revng/lib/FunctionCallIdentification/PruneRetSuccessors.cpp
Ivan Krysak 7d235f4fd0 Enforce licence header consistency
Also do some basic cleanup: capitalize first letters, add `.`
at the end of the sentences, and so on.
2023-07-03 15:23:10 +00:00

119 lines
3.2 KiB
C++

/// \file PruneRetSuccessors.cpp
/// 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);
struct SuccessorsList {
bool AnyPC = false;
bool UnexpectedPC = false;
bool Other = false;
std::set<MetaAddress> Addresses;
bool operator==(const SuccessorsList &Other) const = default;
static SuccessorsList other() {
SuccessorsList Result;
Result.Other = true;
return Result;
}
bool hasSuccessors() const {
return AnyPC or UnexpectedPC or Other or Addresses.size() != 0;
}
void dump() const debug_function { dump(dbg); }
template<typename O>
void dump(O &Output) const {
Output << "AnyPC: " << AnyPC << "\n";
Output << "UnexpectedPC: " << UnexpectedPC << "\n";
Output << "Other: " << Other << "\n";
Output << "Addresses:\n";
for (const MetaAddress &Address : Addresses) {
Output << " ";
Address.dump(Output);
Output << "\n";
}
}
};
static SuccessorsList getSuccessors(GeneratedCodeBasicInfo &GCBI,
BasicBlock *BB) {
bool IsRoot = BB->getParent() == GCBI.root();
SuccessorsList Result;
df_iterator_default_set<BasicBlock *> Visited;
if (IsRoot) {
Visited.insert(GCBI.anyPC());
Visited.insert(GCBI.unexpectedPC());
}
for (BasicBlock *Block : depth_first_ext(BB, Visited)) {
for (BasicBlock *Successor : successors(Block)) {
revng_assert(Successor != GCBI.dispatcher());
MetaAddress Address = getBasicBlockID(Successor).start();
const auto IBDHB = BlockType::IndirectBranchDispatcherHelperBlock;
if (Address.isValid()) {
Visited.insert(Successor);
Result.Addresses.insert(Address);
} else if (IsRoot and Successor == GCBI.anyPC()) {
Result.AnyPC = true;
} else if (IsRoot and Successor == GCBI.unexpectedPC()) {
Result.UnexpectedPC = true;
} else if (getType(Successor) == IBDHB) {
// Ignore
} else {
Result.Other = true;
}
}
}
return Result;
}
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 = getSuccessors(GCBI, &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);
eraseFromParent(OldTerminator);
}
}
return true;
}