brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.8 KiB · 12ae474 Raw
174 lines · cpp
1//===- EHPersonalities.cpp - Compute EH-related information ---------------===//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#include "llvm/IR/EHPersonalities.h"10#include "llvm/ADT/StringSwitch.h"11#include "llvm/IR/CFG.h"12#include "llvm/IR/Constants.h"13#include "llvm/IR/Function.h"14#include "llvm/IR/Instructions.h"15#include "llvm/IR/Module.h"16#include "llvm/Support/Debug.h"17#include "llvm/Support/raw_ostream.h"18#include "llvm/TargetParser/Triple.h"19using namespace llvm;20 21/// See if the given exception handling personality function is one that we22/// understand.  If so, return a description of it; otherwise return Unknown.23EHPersonality llvm::classifyEHPersonality(const Value *Pers) {24  const GlobalValue *F =25      Pers ? dyn_cast<GlobalValue>(Pers->stripPointerCasts()) : nullptr;26  if (!F || !F->getValueType() || !F->getValueType()->isFunctionTy())27    return EHPersonality::Unknown;28 29  StringRef Name = F->getName();30  if (F->getParent()->getTargetTriple().isWindowsArm64EC()) {31    // ARM64EC function symbols are mangled by prefixing them with "#".32    // Demangle them by skipping this prefix.33    Name.consume_front("#");34  }35 36  return StringSwitch<EHPersonality>(Name)37      .Case("__gnat_eh_personality", EHPersonality::GNU_Ada)38      .Case("__gxx_personality_v0", EHPersonality::GNU_CXX)39      .Case("__gxx_personality_seh0", EHPersonality::GNU_CXX)40      .Case("__gxx_personality_sj0", EHPersonality::GNU_CXX_SjLj)41      .Case("__gcc_personality_v0", EHPersonality::GNU_C)42      .Case("__gcc_personality_seh0", EHPersonality::GNU_C)43      .Case("__gcc_personality_sj0", EHPersonality::GNU_C_SjLj)44      .Case("__objc_personality_v0", EHPersonality::GNU_ObjC)45      .Case("_except_handler3", EHPersonality::MSVC_X86SEH)46      .Case("_except_handler4", EHPersonality::MSVC_X86SEH)47      .Case("__C_specific_handler", EHPersonality::MSVC_TableSEH)48      .Case("__CxxFrameHandler3", EHPersonality::MSVC_CXX)49      .Case("ProcessCLRException", EHPersonality::CoreCLR)50      // Rust mangles its personality function, so we can't test exact equality.51      .EndsWith("rust_eh_personality", EHPersonality::Rust)52      .Case("__gxx_wasm_personality_v0", EHPersonality::Wasm_CXX)53      .Case("__xlcxx_personality_v1", EHPersonality::XL_CXX)54      .Case("__zos_cxx_personality_v2", EHPersonality::ZOS_CXX)55      .Default(EHPersonality::Unknown);56}57 58StringRef llvm::getEHPersonalityName(EHPersonality Pers) {59  switch (Pers) {60  case EHPersonality::GNU_Ada:61    return "__gnat_eh_personality";62  case EHPersonality::GNU_CXX:63    return "__gxx_personality_v0";64  case EHPersonality::GNU_CXX_SjLj:65    return "__gxx_personality_sj0";66  case EHPersonality::GNU_C:67    return "__gcc_personality_v0";68  case EHPersonality::GNU_C_SjLj:69    return "__gcc_personality_sj0";70  case EHPersonality::GNU_ObjC:71    return "__objc_personality_v0";72  case EHPersonality::MSVC_X86SEH:73    return "_except_handler3";74  case EHPersonality::MSVC_TableSEH:75    return "__C_specific_handler";76  case EHPersonality::MSVC_CXX:77    return "__CxxFrameHandler3";78  case EHPersonality::CoreCLR:79    return "ProcessCLRException";80  case EHPersonality::Rust:81    llvm_unreachable(82        "Cannot get personality name of Rust personality, since it is mangled");83  case EHPersonality::Wasm_CXX:84    return "__gxx_wasm_personality_v0";85  case EHPersonality::XL_CXX:86    return "__xlcxx_personality_v1";87  case EHPersonality::ZOS_CXX:88    return "__zos_cxx_personality_v2";89  case EHPersonality::Unknown:90    llvm_unreachable("Unknown EHPersonality!");91  }92 93  llvm_unreachable("Invalid EHPersonality!");94}95 96EHPersonality llvm::getDefaultEHPersonality(const Triple &T) {97  if (T.isPS5())98    return EHPersonality::GNU_CXX;99  else100    return EHPersonality::GNU_C;101}102 103bool llvm::canSimplifyInvokeNoUnwind(const Function *F) {104  EHPersonality Personality = classifyEHPersonality(F->getPersonalityFn());105  // We can't simplify any invokes to nounwind functions if the personality106  // function wants to catch asynch exceptions.  The nounwind attribute only107  // implies that the function does not throw synchronous exceptions.108 109  // Cannot simplify CXX Personality under AsynchEH110  const llvm::Module *M = (const llvm::Module *)F->getParent();111  bool EHa = M->getModuleFlag("eh-asynch");112  return !EHa && !isAsynchronousEHPersonality(Personality);113}114 115DenseMap<BasicBlock *, ColorVector> llvm::colorEHFunclets(Function &F) {116  SmallVector<std::pair<BasicBlock *, BasicBlock *>, 16> Worklist;117  BasicBlock *EntryBlock = &F.getEntryBlock();118  DenseMap<BasicBlock *, ColorVector> BlockColors;119 120  // Build up the color map, which maps each block to its set of 'colors'.121  // For any block B the "colors" of B are the set of funclets F (possibly122  // including a root "funclet" representing the main function) such that123  // F will need to directly contain B or a copy of B (where the term "directly124  // contain" is used to distinguish from being "transitively contained" in125  // a nested funclet).126  //127  // Note: Despite not being a funclet in the truest sense, a catchswitch is128  // considered to belong to its own funclet for the purposes of coloring.129 130  DEBUG_WITH_TYPE("win-eh-prepare-coloring",131                  dbgs() << "\nColoring funclets for " << F.getName() << "\n");132 133  Worklist.push_back({EntryBlock, EntryBlock});134 135  while (!Worklist.empty()) {136    BasicBlock *Visiting;137    BasicBlock *Color;138    std::tie(Visiting, Color) = Worklist.pop_back_val();139    DEBUG_WITH_TYPE("win-eh-prepare-coloring",140                    dbgs() << "Visiting " << Visiting->getName() << ", "141                           << Color->getName() << "\n");142    BasicBlock::iterator VisitingHead = Visiting->getFirstNonPHIIt();143    if (VisitingHead->isEHPad()) {144      // Mark this funclet head as a member of itself.145      Color = Visiting;146    }147    // Note that this is a member of the given color.148    ColorVector &Colors = BlockColors[Visiting];149    if (!is_contained(Colors, Color))150      Colors.push_back(Color);151    else152      continue;153 154    DEBUG_WITH_TYPE("win-eh-prepare-coloring",155                    dbgs() << "  Assigned color \'" << Color->getName()156                           << "\' to block \'" << Visiting->getName()157                           << "\'.\n");158 159    BasicBlock *SuccColor = Color;160    Instruction *Terminator = Visiting->getTerminator();161    if (auto *CatchRet = dyn_cast<CatchReturnInst>(Terminator)) {162      Value *ParentPad = CatchRet->getCatchSwitchParentPad();163      if (isa<ConstantTokenNone>(ParentPad))164        SuccColor = EntryBlock;165      else166        SuccColor = cast<Instruction>(ParentPad)->getParent();167    }168 169    for (BasicBlock *Succ : successors(Visiting))170      Worklist.push_back({Succ, SuccColor});171  }172  return BlockColors;173}174