98 lines · cpp
1//===- EscapeEnumerator.cpp -----------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Defines a helper class that enumerates all possible exits from a function,10// including exception handling.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/Transforms/Utils/EscapeEnumerator.h"15#include "llvm/IR/EHPersonalities.h"16#include "llvm/IR/Module.h"17#include "llvm/TargetParser/Triple.h"18#include "llvm/Transforms/Utils/Local.h"19 20using namespace llvm;21 22static FunctionCallee getDefaultPersonalityFn(Module *M) {23 LLVMContext &C = M->getContext();24 Triple T(M->getTargetTriple());25 EHPersonality Pers = getDefaultEHPersonality(T);26 return M->getOrInsertFunction(getEHPersonalityName(Pers),27 FunctionType::get(Type::getInt32Ty(C), true));28}29 30IRBuilder<> *EscapeEnumerator::Next() {31 if (Done)32 return nullptr;33 34 // Find all 'return', 'resume', and 'unwind' instructions.35 while (StateBB != StateE) {36 BasicBlock *CurBB = &*StateBB++;37 38 // Branches and invokes do not escape, only unwind, resume, and return39 // do.40 Instruction *TI = CurBB->getTerminator();41 if (!isa<ReturnInst>(TI) && !isa<ResumeInst>(TI))42 continue;43 44 if (CallInst *CI = CurBB->getTerminatingMustTailCall())45 TI = CI;46 Builder.SetInsertPoint(TI);47 return &Builder;48 }49 50 Done = true;51 52 if (!HandleExceptions)53 return nullptr;54 55 if (F.doesNotThrow())56 return nullptr;57 58 // Find all 'call' instructions that may throw.59 // We cannot tranform calls with musttail tag.60 SmallVector<Instruction *, 16> Calls;61 for (BasicBlock &BB : F)62 for (Instruction &II : BB)63 if (CallInst *CI = dyn_cast<CallInst>(&II))64 if (!CI->doesNotThrow() && !CI->isMustTailCall())65 Calls.push_back(CI);66 67 if (Calls.empty())68 return nullptr;69 70 // Create a cleanup block.71 LLVMContext &C = F.getContext();72 BasicBlock *CleanupBB = BasicBlock::Create(C, CleanupBBName, &F);73 Type *ExnTy = StructType::get(PointerType::getUnqual(C), Type::getInt32Ty(C));74 if (!F.hasPersonalityFn()) {75 FunctionCallee PersFn = getDefaultPersonalityFn(F.getParent());76 F.setPersonalityFn(cast<Constant>(PersFn.getCallee()));77 }78 79 if (isScopedEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) {80 report_fatal_error("Scoped EH not supported");81 }82 83 LandingPadInst *LPad =84 LandingPadInst::Create(ExnTy, 1, "cleanup.lpad", CleanupBB);85 LPad->setCleanup(true);86 ResumeInst *RI = ResumeInst::Create(LPad, CleanupBB);87 88 // Transform the 'call' instructions into 'invoke's branching to the89 // cleanup block. Go in reverse order to make prettier BB names.90 for (unsigned I = Calls.size(); I != 0;) {91 CallInst *CI = cast<CallInst>(Calls[--I]);92 changeToInvokeAndSplitBasicBlock(CI, CleanupBB, DTU);93 }94 95 Builder.SetInsertPoint(RI);96 return &Builder;97}98