Path: blob/main/contrib/llvm-project/llvm/lib/IR/EHPersonalities.cpp
35233 views
//===- EHPersonalities.cpp - Compute EH-related information ---------------===//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//===----------------------------------------------------------------------===//78#include "llvm/IR/EHPersonalities.h"9#include "llvm/ADT/StringSwitch.h"10#include "llvm/IR/CFG.h"11#include "llvm/IR/Constants.h"12#include "llvm/IR/Function.h"13#include "llvm/IR/Instructions.h"14#include "llvm/IR/Module.h"15#include "llvm/Support/Debug.h"16#include "llvm/Support/raw_ostream.h"17#include "llvm/TargetParser/Triple.h"18using namespace llvm;1920/// See if the given exception handling personality function is one that we21/// understand. If so, return a description of it; otherwise return Unknown.22EHPersonality llvm::classifyEHPersonality(const Value *Pers) {23const GlobalValue *F =24Pers ? dyn_cast<GlobalValue>(Pers->stripPointerCasts()) : nullptr;25if (!F || !F->getValueType() || !F->getValueType()->isFunctionTy())26return EHPersonality::Unknown;27return StringSwitch<EHPersonality>(F->getName())28.Case("__gnat_eh_personality", EHPersonality::GNU_Ada)29.Case("__gxx_personality_v0", EHPersonality::GNU_CXX)30.Case("__gxx_personality_seh0", EHPersonality::GNU_CXX)31.Case("__gxx_personality_sj0", EHPersonality::GNU_CXX_SjLj)32.Case("__gcc_personality_v0", EHPersonality::GNU_C)33.Case("__gcc_personality_seh0", EHPersonality::GNU_C)34.Case("__gcc_personality_sj0", EHPersonality::GNU_C_SjLj)35.Case("__objc_personality_v0", EHPersonality::GNU_ObjC)36.Case("_except_handler3", EHPersonality::MSVC_X86SEH)37.Case("_except_handler4", EHPersonality::MSVC_X86SEH)38.Case("__C_specific_handler", EHPersonality::MSVC_TableSEH)39.Case("__CxxFrameHandler3", EHPersonality::MSVC_CXX)40.Case("ProcessCLRException", EHPersonality::CoreCLR)41.Case("rust_eh_personality", EHPersonality::Rust)42.Case("__gxx_wasm_personality_v0", EHPersonality::Wasm_CXX)43.Case("__xlcxx_personality_v1", EHPersonality::XL_CXX)44.Case("__zos_cxx_personality_v2", EHPersonality::ZOS_CXX)45.Default(EHPersonality::Unknown);46}4748StringRef llvm::getEHPersonalityName(EHPersonality Pers) {49switch (Pers) {50case EHPersonality::GNU_Ada:51return "__gnat_eh_personality";52case EHPersonality::GNU_CXX:53return "__gxx_personality_v0";54case EHPersonality::GNU_CXX_SjLj:55return "__gxx_personality_sj0";56case EHPersonality::GNU_C:57return "__gcc_personality_v0";58case EHPersonality::GNU_C_SjLj:59return "__gcc_personality_sj0";60case EHPersonality::GNU_ObjC:61return "__objc_personality_v0";62case EHPersonality::MSVC_X86SEH:63return "_except_handler3";64case EHPersonality::MSVC_TableSEH:65return "__C_specific_handler";66case EHPersonality::MSVC_CXX:67return "__CxxFrameHandler3";68case EHPersonality::CoreCLR:69return "ProcessCLRException";70case EHPersonality::Rust:71return "rust_eh_personality";72case EHPersonality::Wasm_CXX:73return "__gxx_wasm_personality_v0";74case EHPersonality::XL_CXX:75return "__xlcxx_personality_v1";76case EHPersonality::ZOS_CXX:77return "__zos_cxx_personality_v2";78case EHPersonality::Unknown:79llvm_unreachable("Unknown EHPersonality!");80}8182llvm_unreachable("Invalid EHPersonality!");83}8485EHPersonality llvm::getDefaultEHPersonality(const Triple &T) {86if (T.isPS5())87return EHPersonality::GNU_CXX;88else89return EHPersonality::GNU_C;90}9192bool llvm::canSimplifyInvokeNoUnwind(const Function *F) {93EHPersonality Personality = classifyEHPersonality(F->getPersonalityFn());94// We can't simplify any invokes to nounwind functions if the personality95// function wants to catch asynch exceptions. The nounwind attribute only96// implies that the function does not throw synchronous exceptions.9798// Cannot simplify CXX Personality under AsynchEH99const llvm::Module *M = (const llvm::Module *)F->getParent();100bool EHa = M->getModuleFlag("eh-asynch");101return !EHa && !isAsynchronousEHPersonality(Personality);102}103104DenseMap<BasicBlock *, ColorVector> llvm::colorEHFunclets(Function &F) {105SmallVector<std::pair<BasicBlock *, BasicBlock *>, 16> Worklist;106BasicBlock *EntryBlock = &F.getEntryBlock();107DenseMap<BasicBlock *, ColorVector> BlockColors;108109// Build up the color map, which maps each block to its set of 'colors'.110// For any block B the "colors" of B are the set of funclets F (possibly111// including a root "funclet" representing the main function) such that112// F will need to directly contain B or a copy of B (where the term "directly113// contain" is used to distinguish from being "transitively contained" in114// a nested funclet).115//116// Note: Despite not being a funclet in the truest sense, a catchswitch is117// considered to belong to its own funclet for the purposes of coloring.118119DEBUG_WITH_TYPE("win-eh-prepare-coloring",120dbgs() << "\nColoring funclets for " << F.getName() << "\n");121122Worklist.push_back({EntryBlock, EntryBlock});123124while (!Worklist.empty()) {125BasicBlock *Visiting;126BasicBlock *Color;127std::tie(Visiting, Color) = Worklist.pop_back_val();128DEBUG_WITH_TYPE("win-eh-prepare-coloring",129dbgs() << "Visiting " << Visiting->getName() << ", "130<< Color->getName() << "\n");131Instruction *VisitingHead = Visiting->getFirstNonPHI();132if (VisitingHead->isEHPad()) {133// Mark this funclet head as a member of itself.134Color = Visiting;135}136// Note that this is a member of the given color.137ColorVector &Colors = BlockColors[Visiting];138if (!is_contained(Colors, Color))139Colors.push_back(Color);140else141continue;142143DEBUG_WITH_TYPE("win-eh-prepare-coloring",144dbgs() << " Assigned color \'" << Color->getName()145<< "\' to block \'" << Visiting->getName()146<< "\'.\n");147148BasicBlock *SuccColor = Color;149Instruction *Terminator = Visiting->getTerminator();150if (auto *CatchRet = dyn_cast<CatchReturnInst>(Terminator)) {151Value *ParentPad = CatchRet->getCatchSwitchParentPad();152if (isa<ConstantTokenNone>(ParentPad))153SuccColor = EntryBlock;154else155SuccColor = cast<Instruction>(ParentPad)->getParent();156}157158for (BasicBlock *Succ : successors(Visiting))159Worklist.push_back({Succ, SuccColor});160}161return BlockColors;162}163164165