1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 03:33:20 +01:00
llvm-mirror/lib/Transforms/Utils/EscapeEnumerator.cpp
David Blaikie 93054c1e87 Move Analysis/Utils/Local.h back to Transforms
Review feedback from r328165. Split out just the one function from the
file that's used by Analysis. (As chandlerc pointed out, the original
change only moved the header and not the implementation anyway - which
was fine for the one function that was used (since it's a
template/inlined in the header) but not in general)

llvm-svn: 333954
2018-06-04 21:23:21 +00:00

96 lines
2.9 KiB
C++

//===- EscapeEnumerator.cpp -----------------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// Defines a helper class that enumerates all possible exits from a function,
// including exception handling.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/EscapeEnumerator.h"
#include "llvm/Analysis/EHPersonalities.h"
#include "llvm/Transforms/Utils/Local.h"
#include "llvm/IR/CallSite.h"
#include "llvm/IR/Module.h"
using namespace llvm;
static Constant *getDefaultPersonalityFn(Module *M) {
LLVMContext &C = M->getContext();
Triple T(M->getTargetTriple());
EHPersonality Pers = getDefaultEHPersonality(T);
return M->getOrInsertFunction(getEHPersonalityName(Pers),
FunctionType::get(Type::getInt32Ty(C), true));
}
IRBuilder<> *EscapeEnumerator::Next() {
if (Done)
return nullptr;
// Find all 'return', 'resume', and 'unwind' instructions.
while (StateBB != StateE) {
BasicBlock *CurBB = &*StateBB++;
// Branches and invokes do not escape, only unwind, resume, and return
// do.
TerminatorInst *TI = CurBB->getTerminator();
if (!isa<ReturnInst>(TI) && !isa<ResumeInst>(TI))
continue;
Builder.SetInsertPoint(TI);
return &Builder;
}
Done = true;
if (!HandleExceptions)
return nullptr;
if (F.doesNotThrow())
return nullptr;
// Find all 'call' instructions that may throw.
SmallVector<Instruction *, 16> Calls;
for (BasicBlock &BB : F)
for (Instruction &II : BB)
if (CallInst *CI = dyn_cast<CallInst>(&II))
if (!CI->doesNotThrow())
Calls.push_back(CI);
if (Calls.empty())
return nullptr;
// Create a cleanup block.
LLVMContext &C = F.getContext();
BasicBlock *CleanupBB = BasicBlock::Create(C, CleanupBBName, &F);
Type *ExnTy = StructType::get(Type::getInt8PtrTy(C), Type::getInt32Ty(C));
if (!F.hasPersonalityFn()) {
Constant *PersFn = getDefaultPersonalityFn(F.getParent());
F.setPersonalityFn(PersFn);
}
if (isScopedEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) {
report_fatal_error("Scoped EH not supported");
}
LandingPadInst *LPad =
LandingPadInst::Create(ExnTy, 1, "cleanup.lpad", CleanupBB);
LPad->setCleanup(true);
ResumeInst *RI = ResumeInst::Create(LPad, CleanupBB);
// Transform the 'call' instructions into 'invoke's branching to the
// cleanup block. Go in reverse order to make prettier BB names.
SmallVector<Value *, 16> Args;
for (unsigned I = Calls.size(); I != 0;) {
CallInst *CI = cast<CallInst>(Calls[--I]);
changeToInvokeAndSplitBasicBlock(CI, CleanupBB);
}
Builder.SetInsertPoint(RI);
return &Builder;
}