mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
7d235f4fd0
Also do some basic cleanup: capitalize first letters, add `.` at the end of the sentences, and so on.
119 lines
3.2 KiB
C++
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;
|
|
}
|