mirror of
https://github.com/revng/revng
synced 2026-06-21 14:07:57 +00:00
f8bd4c3bac
* Make the following private headers public:
* Lift/CPUStateAccessAnalysisPass.h
* Lift/CSVOffsets.h
* Lift/PTCDump.h
* Lift/VariableManager.h
* Move from revngSupport to revngLift:
* IRAnnotators.{h,cpp}
* SelfReferencingDbgAnnotationWriter.{h,cpp}
* Move from revngSupport to revngModel:
* FunctionTags.{h,cpp}
* ProgramCounterHandler.{h,cpp}
* Move from revngSupport to revngRecompile:
* OriginalAssemblyAnnotationWriter.{h,cpp}
66 lines
1.9 KiB
C++
66 lines
1.9 KiB
C++
/// \file RemoveExceptionalCalls.cpp
|
|
|
|
//
|
|
// This file is distributed under the MIT License. See LICENSE.md for details.
|
|
//
|
|
|
|
#include "llvm/IR/DebugInfoMetadata.h"
|
|
#include "llvm/IR/Function.h"
|
|
#include "llvm/IR/Instructions.h"
|
|
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
|
|
|
#include "revng/FunctionIsolation/RemoveExceptionalCalls.h"
|
|
#include "revng/Model/FunctionTags.h"
|
|
#include "revng/Support/IRHelpers.h"
|
|
|
|
using namespace llvm;
|
|
|
|
char RemoveExceptionalCalls::ID = 0;
|
|
|
|
using Register = RegisterPass<RemoveExceptionalCalls>;
|
|
static Register X("remove-exceptional-functions",
|
|
"Remove Exceptional Functions");
|
|
|
|
bool RemoveExceptionalCalls::runOnModule(llvm::Module &M) {
|
|
LLVMContext &C = M.getContext();
|
|
|
|
// Collect all calls to exceptional functions in lifted functions
|
|
std::set<CallBase *> ToErase;
|
|
for (Function &F : FunctionTags::Exceptional.functions(&M))
|
|
for (CallBase *Call : callers(&F))
|
|
if (FunctionTags::Isolated.isTagOf(Call->getParent()->getParent()))
|
|
ToErase.insert(Call);
|
|
|
|
std::set<Function *> ToCleanup;
|
|
for (CallBase *Call : ToErase) {
|
|
BasicBlock *BB = Call->getParent();
|
|
|
|
// Register function for cleanup
|
|
ToCleanup.insert(BB->getParent());
|
|
|
|
// Split containing basic block
|
|
BB->splitBasicBlock(Call);
|
|
|
|
// Record the old terminator so that we don't need to look for it again
|
|
llvm::Instruction *OldTerminator = BB->getTerminator();
|
|
|
|
// Terminate with an unreachable
|
|
auto Unreachable = new UnreachableInst(C, BB);
|
|
Unreachable->setDebugLoc(OldTerminator->getDebugLoc());
|
|
|
|
// Drop the old terminator
|
|
eraseFromParent(OldTerminator);
|
|
|
|
// Drop function call
|
|
auto *Undef = UndefValue::get(Call->getType());
|
|
Call->replaceAllUsesWith(Undef);
|
|
eraseFromParent(Call);
|
|
}
|
|
|
|
// Garbage collect dead blocks
|
|
for (Function *F : ToCleanup)
|
|
EliminateUnreachableBlocks(*F, nullptr, false);
|
|
|
|
return true;
|
|
}
|