Path: blob/main/contrib/llvm-project/llvm/lib/Transforms/Utils/EscapeEnumerator.cpp
35271 views
//===- EscapeEnumerator.cpp -----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Defines a helper class that enumerates all possible exits from a function,9// including exception handling.10//11//===----------------------------------------------------------------------===//1213#include "llvm/Transforms/Utils/EscapeEnumerator.h"14#include "llvm/IR/EHPersonalities.h"15#include "llvm/IR/Module.h"16#include "llvm/TargetParser/Triple.h"17#include "llvm/Transforms/Utils/Local.h"1819using namespace llvm;2021static FunctionCallee getDefaultPersonalityFn(Module *M) {22LLVMContext &C = M->getContext();23Triple T(M->getTargetTriple());24EHPersonality Pers = getDefaultEHPersonality(T);25return M->getOrInsertFunction(getEHPersonalityName(Pers),26FunctionType::get(Type::getInt32Ty(C), true));27}2829IRBuilder<> *EscapeEnumerator::Next() {30if (Done)31return nullptr;3233// Find all 'return', 'resume', and 'unwind' instructions.34while (StateBB != StateE) {35BasicBlock *CurBB = &*StateBB++;3637// Branches and invokes do not escape, only unwind, resume, and return38// do.39Instruction *TI = CurBB->getTerminator();40if (!isa<ReturnInst>(TI) && !isa<ResumeInst>(TI))41continue;4243if (CallInst *CI = CurBB->getTerminatingMustTailCall())44TI = CI;45Builder.SetInsertPoint(TI);46return &Builder;47}4849Done = true;5051if (!HandleExceptions)52return nullptr;5354if (F.doesNotThrow())55return nullptr;5657// Find all 'call' instructions that may throw.58// We cannot tranform calls with musttail tag.59SmallVector<Instruction *, 16> Calls;60for (BasicBlock &BB : F)61for (Instruction &II : BB)62if (CallInst *CI = dyn_cast<CallInst>(&II))63if (!CI->doesNotThrow() && !CI->isMustTailCall())64Calls.push_back(CI);6566if (Calls.empty())67return nullptr;6869// Create a cleanup block.70LLVMContext &C = F.getContext();71BasicBlock *CleanupBB = BasicBlock::Create(C, CleanupBBName, &F);72Type *ExnTy = StructType::get(PointerType::getUnqual(C), Type::getInt32Ty(C));73if (!F.hasPersonalityFn()) {74FunctionCallee PersFn = getDefaultPersonalityFn(F.getParent());75F.setPersonalityFn(cast<Constant>(PersFn.getCallee()));76}7778if (isScopedEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) {79report_fatal_error("Scoped EH not supported");80}8182LandingPadInst *LPad =83LandingPadInst::Create(ExnTy, 1, "cleanup.lpad", CleanupBB);84LPad->setCleanup(true);85ResumeInst *RI = ResumeInst::Create(LPad, CleanupBB);8687// Transform the 'call' instructions into 'invoke's branching to the88// cleanup block. Go in reverse order to make prettier BB names.89SmallVector<Value *, 16> Args;90for (unsigned I = Calls.size(); I != 0;) {91CallInst *CI = cast<CallInst>(Calls[--I]);92changeToInvokeAndSplitBasicBlock(CI, CleanupBB, DTU);93}9495Builder.SetInsertPoint(RI);96return &Builder;97}9899100