1292915Sdim//===- EHPersonalities.cpp - Compute EH-related information ---------------===// 2292915Sdim// 3292915Sdim// The LLVM Compiler Infrastructure 4292915Sdim// 5292915Sdim// This file is distributed under the University of Illinois Open Source 6292915Sdim// License. See LICENSE.TXT for details. 7292915Sdim// 8292915Sdim//===----------------------------------------------------------------------===// 9292915Sdim 10292915Sdim#include "llvm/Analysis/EHPersonalities.h" 11292915Sdim#include "llvm/ADT/StringSwitch.h" 12292915Sdim#include "llvm/IR/CFG.h" 13292915Sdim#include "llvm/IR/Constants.h" 14292915Sdim#include "llvm/IR/Function.h" 15292915Sdim#include "llvm/IR/Instructions.h" 16292915Sdim#include "llvm/Support/Debug.h" 17292915Sdim#include "llvm/Support/raw_ostream.h" 18292915Sdimusing namespace llvm; 19292915Sdim 20292915Sdim/// See if the given exception handling personality function is one that we 21292915Sdim/// understand. If so, return a description of it; otherwise return Unknown. 22292915SdimEHPersonality llvm::classifyEHPersonality(const Value *Pers) { 23292915Sdim const Function *F = 24292915Sdim Pers ? dyn_cast<Function>(Pers->stripPointerCasts()) : nullptr; 25292915Sdim if (!F) 26292915Sdim return EHPersonality::Unknown; 27292915Sdim return StringSwitch<EHPersonality>(F->getName()) 28292915Sdim .Case("__gnat_eh_personality", EHPersonality::GNU_Ada) 29292915Sdim .Case("__gxx_personality_v0", EHPersonality::GNU_CXX) 30292915Sdim .Case("__gcc_personality_v0", EHPersonality::GNU_C) 31292915Sdim .Case("__objc_personality_v0", EHPersonality::GNU_ObjC) 32292915Sdim .Case("_except_handler3", EHPersonality::MSVC_X86SEH) 33292915Sdim .Case("_except_handler4", EHPersonality::MSVC_X86SEH) 34292915Sdim .Case("__C_specific_handler", EHPersonality::MSVC_Win64SEH) 35292915Sdim .Case("__CxxFrameHandler3", EHPersonality::MSVC_CXX) 36292915Sdim .Case("ProcessCLRException", EHPersonality::CoreCLR) 37292915Sdim .Default(EHPersonality::Unknown); 38292915Sdim} 39292915Sdim 40292915Sdimbool llvm::canSimplifyInvokeNoUnwind(const Function *F) { 41292915Sdim EHPersonality Personality = classifyEHPersonality(F->getPersonalityFn()); 42292915Sdim // We can't simplify any invokes to nounwind functions if the personality 43292915Sdim // function wants to catch asynch exceptions. The nounwind attribute only 44292915Sdim // implies that the function does not throw synchronous exceptions. 45292915Sdim return !isAsynchronousEHPersonality(Personality); 46292915Sdim} 47292915Sdim 48292915SdimDenseMap<BasicBlock *, ColorVector> llvm::colorEHFunclets(Function &F) { 49292915Sdim SmallVector<std::pair<BasicBlock *, BasicBlock *>, 16> Worklist; 50292915Sdim BasicBlock *EntryBlock = &F.getEntryBlock(); 51292915Sdim DenseMap<BasicBlock *, ColorVector> BlockColors; 52292915Sdim 53292915Sdim // Build up the color map, which maps each block to its set of 'colors'. 54292915Sdim // For any block B the "colors" of B are the set of funclets F (possibly 55292915Sdim // including a root "funclet" representing the main function) such that 56292915Sdim // F will need to directly contain B or a copy of B (where the term "directly 57292915Sdim // contain" is used to distinguish from being "transitively contained" in 58292915Sdim // a nested funclet). 59292915Sdim // 60292915Sdim // Note: Despite not being a funclet in the truest sense, a catchswitch is 61292915Sdim // considered to belong to its own funclet for the purposes of coloring. 62292915Sdim 63292915Sdim DEBUG_WITH_TYPE("winehprepare-coloring", dbgs() << "\nColoring funclets for " 64292915Sdim << F.getName() << "\n"); 65292915Sdim 66292915Sdim Worklist.push_back({EntryBlock, EntryBlock}); 67292915Sdim 68292915Sdim while (!Worklist.empty()) { 69292915Sdim BasicBlock *Visiting; 70292915Sdim BasicBlock *Color; 71292915Sdim std::tie(Visiting, Color) = Worklist.pop_back_val(); 72292915Sdim DEBUG_WITH_TYPE("winehprepare-coloring", 73292915Sdim dbgs() << "Visiting " << Visiting->getName() << ", " 74292915Sdim << Color->getName() << "\n"); 75292915Sdim Instruction *VisitingHead = Visiting->getFirstNonPHI(); 76292915Sdim if (VisitingHead->isEHPad()) { 77292915Sdim // Mark this funclet head as a member of itself. 78292915Sdim Color = Visiting; 79292915Sdim } 80292915Sdim // Note that this is a member of the given color. 81292915Sdim ColorVector &Colors = BlockColors[Visiting]; 82292915Sdim if (std::find(Colors.begin(), Colors.end(), Color) == Colors.end()) 83292915Sdim Colors.push_back(Color); 84292915Sdim else 85292915Sdim continue; 86292915Sdim 87292915Sdim DEBUG_WITH_TYPE("winehprepare-coloring", 88292915Sdim dbgs() << " Assigned color \'" << Color->getName() 89292915Sdim << "\' to block \'" << Visiting->getName() 90292915Sdim << "\'.\n"); 91292915Sdim 92292915Sdim BasicBlock *SuccColor = Color; 93292915Sdim TerminatorInst *Terminator = Visiting->getTerminator(); 94292915Sdim if (auto *CatchRet = dyn_cast<CatchReturnInst>(Terminator)) { 95292915Sdim Value *ParentPad = CatchRet->getParentPad(); 96292915Sdim if (isa<ConstantTokenNone>(ParentPad)) 97292915Sdim SuccColor = EntryBlock; 98292915Sdim else 99292915Sdim SuccColor = cast<Instruction>(ParentPad)->getParent(); 100292915Sdim } 101292915Sdim 102292915Sdim for (BasicBlock *Succ : successors(Visiting)) 103292915Sdim Worklist.push_back({Succ, SuccColor}); 104292915Sdim } 105292915Sdim return BlockColors; 106292915Sdim} 107