brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.1 KiB · bafaf6f Raw
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