xref: /llvm-project/llvm/lib/IR/EHPersonalities.cpp (revision 6292a808b3524d9ba6f4ce55bc5b9e547b088dd8)
13b387d10SStefan Gränitz //===- EHPersonalities.cpp - Compute EH-related information ---------------===//
23b387d10SStefan Gränitz //
33b387d10SStefan Gränitz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43b387d10SStefan Gränitz // See https://llvm.org/LICENSE.txt for license information.
53b387d10SStefan Gränitz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63b387d10SStefan Gränitz //
73b387d10SStefan Gränitz //===----------------------------------------------------------------------===//
83b387d10SStefan Gränitz 
93b387d10SStefan Gränitz #include "llvm/IR/EHPersonalities.h"
103b387d10SStefan Gränitz #include "llvm/ADT/StringSwitch.h"
113b387d10SStefan Gränitz #include "llvm/IR/CFG.h"
123b387d10SStefan Gränitz #include "llvm/IR/Constants.h"
133b387d10SStefan Gränitz #include "llvm/IR/Function.h"
143b387d10SStefan Gränitz #include "llvm/IR/Instructions.h"
150efe1113SPhoebe Wang #include "llvm/IR/Module.h"
163b387d10SStefan Gränitz #include "llvm/Support/Debug.h"
173b387d10SStefan Gränitz #include "llvm/Support/raw_ostream.h"
1862c7f035SArchibald Elliott #include "llvm/TargetParser/Triple.h"
193b387d10SStefan Gränitz using namespace llvm;
203b387d10SStefan Gränitz 
213b387d10SStefan Gränitz /// See if the given exception handling personality function is one that we
223b387d10SStefan Gränitz /// understand.  If so, return a description of it; otherwise return Unknown.
233b387d10SStefan Gränitz EHPersonality llvm::classifyEHPersonality(const Value *Pers) {
243b387d10SStefan Gränitz   const GlobalValue *F =
253b387d10SStefan Gränitz       Pers ? dyn_cast<GlobalValue>(Pers->stripPointerCasts()) : nullptr;
263b387d10SStefan Gränitz   if (!F || !F->getValueType() || !F->getValueType()->isFunctionTy())
273b387d10SStefan Gränitz     return EHPersonality::Unknown;
283b387d10SStefan Gränitz   return StringSwitch<EHPersonality>(F->getName())
293b387d10SStefan Gränitz       .Case("__gnat_eh_personality", EHPersonality::GNU_Ada)
303b387d10SStefan Gränitz       .Case("__gxx_personality_v0", EHPersonality::GNU_CXX)
313b387d10SStefan Gränitz       .Case("__gxx_personality_seh0", EHPersonality::GNU_CXX)
323b387d10SStefan Gränitz       .Case("__gxx_personality_sj0", EHPersonality::GNU_CXX_SjLj)
333b387d10SStefan Gränitz       .Case("__gcc_personality_v0", EHPersonality::GNU_C)
343b387d10SStefan Gränitz       .Case("__gcc_personality_seh0", EHPersonality::GNU_C)
353b387d10SStefan Gränitz       .Case("__gcc_personality_sj0", EHPersonality::GNU_C_SjLj)
363b387d10SStefan Gränitz       .Case("__objc_personality_v0", EHPersonality::GNU_ObjC)
373b387d10SStefan Gränitz       .Case("_except_handler3", EHPersonality::MSVC_X86SEH)
383b387d10SStefan Gränitz       .Case("_except_handler4", EHPersonality::MSVC_X86SEH)
393b387d10SStefan Gränitz       .Case("__C_specific_handler", EHPersonality::MSVC_TableSEH)
403b387d10SStefan Gränitz       .Case("__CxxFrameHandler3", EHPersonality::MSVC_CXX)
413b387d10SStefan Gränitz       .Case("ProcessCLRException", EHPersonality::CoreCLR)
423b387d10SStefan Gränitz       .Case("rust_eh_personality", EHPersonality::Rust)
433b387d10SStefan Gränitz       .Case("__gxx_wasm_personality_v0", EHPersonality::Wasm_CXX)
443b387d10SStefan Gränitz       .Case("__xlcxx_personality_v1", EHPersonality::XL_CXX)
45d5022d9aSKai Nacke       .Case("__zos_cxx_personality_v2", EHPersonality::ZOS_CXX)
463b387d10SStefan Gränitz       .Default(EHPersonality::Unknown);
473b387d10SStefan Gränitz }
483b387d10SStefan Gränitz 
493b387d10SStefan Gränitz StringRef llvm::getEHPersonalityName(EHPersonality Pers) {
503b387d10SStefan Gränitz   switch (Pers) {
513b387d10SStefan Gränitz   case EHPersonality::GNU_Ada:
523b387d10SStefan Gränitz     return "__gnat_eh_personality";
533b387d10SStefan Gränitz   case EHPersonality::GNU_CXX:
543b387d10SStefan Gränitz     return "__gxx_personality_v0";
553b387d10SStefan Gränitz   case EHPersonality::GNU_CXX_SjLj:
563b387d10SStefan Gränitz     return "__gxx_personality_sj0";
573b387d10SStefan Gränitz   case EHPersonality::GNU_C:
583b387d10SStefan Gränitz     return "__gcc_personality_v0";
593b387d10SStefan Gränitz   case EHPersonality::GNU_C_SjLj:
603b387d10SStefan Gränitz     return "__gcc_personality_sj0";
613b387d10SStefan Gränitz   case EHPersonality::GNU_ObjC:
623b387d10SStefan Gränitz     return "__objc_personality_v0";
633b387d10SStefan Gränitz   case EHPersonality::MSVC_X86SEH:
643b387d10SStefan Gränitz     return "_except_handler3";
653b387d10SStefan Gränitz   case EHPersonality::MSVC_TableSEH:
663b387d10SStefan Gränitz     return "__C_specific_handler";
673b387d10SStefan Gränitz   case EHPersonality::MSVC_CXX:
683b387d10SStefan Gränitz     return "__CxxFrameHandler3";
693b387d10SStefan Gränitz   case EHPersonality::CoreCLR:
703b387d10SStefan Gränitz     return "ProcessCLRException";
713b387d10SStefan Gränitz   case EHPersonality::Rust:
723b387d10SStefan Gränitz     return "rust_eh_personality";
733b387d10SStefan Gränitz   case EHPersonality::Wasm_CXX:
743b387d10SStefan Gränitz     return "__gxx_wasm_personality_v0";
753b387d10SStefan Gränitz   case EHPersonality::XL_CXX:
763b387d10SStefan Gränitz     return "__xlcxx_personality_v1";
77d5022d9aSKai Nacke   case EHPersonality::ZOS_CXX:
78d5022d9aSKai Nacke     return "__zos_cxx_personality_v2";
793b387d10SStefan Gränitz   case EHPersonality::Unknown:
803b387d10SStefan Gränitz     llvm_unreachable("Unknown EHPersonality!");
813b387d10SStefan Gränitz   }
823b387d10SStefan Gränitz 
833b387d10SStefan Gränitz   llvm_unreachable("Invalid EHPersonality!");
843b387d10SStefan Gränitz }
853b387d10SStefan Gränitz 
863b387d10SStefan Gränitz EHPersonality llvm::getDefaultEHPersonality(const Triple &T) {
873b387d10SStefan Gränitz   if (T.isPS5())
883b387d10SStefan Gränitz     return EHPersonality::GNU_CXX;
893b387d10SStefan Gränitz   else
903b387d10SStefan Gränitz     return EHPersonality::GNU_C;
913b387d10SStefan Gränitz }
923b387d10SStefan Gränitz 
933b387d10SStefan Gränitz bool llvm::canSimplifyInvokeNoUnwind(const Function *F) {
943b387d10SStefan Gränitz   EHPersonality Personality = classifyEHPersonality(F->getPersonalityFn());
953b387d10SStefan Gränitz   // We can't simplify any invokes to nounwind functions if the personality
963b387d10SStefan Gränitz   // function wants to catch asynch exceptions.  The nounwind attribute only
973b387d10SStefan Gränitz   // implies that the function does not throw synchronous exceptions.
980efe1113SPhoebe Wang 
990efe1113SPhoebe Wang   // Cannot simplify CXX Personality under AsynchEH
1000efe1113SPhoebe Wang   const llvm::Module *M = (const llvm::Module *)F->getParent();
1010efe1113SPhoebe Wang   bool EHa = M->getModuleFlag("eh-asynch");
1020efe1113SPhoebe Wang   return !EHa && !isAsynchronousEHPersonality(Personality);
1033b387d10SStefan Gränitz }
1043b387d10SStefan Gränitz 
1053b387d10SStefan Gränitz DenseMap<BasicBlock *, ColorVector> llvm::colorEHFunclets(Function &F) {
1063b387d10SStefan Gränitz   SmallVector<std::pair<BasicBlock *, BasicBlock *>, 16> Worklist;
1073b387d10SStefan Gränitz   BasicBlock *EntryBlock = &F.getEntryBlock();
1083b387d10SStefan Gränitz   DenseMap<BasicBlock *, ColorVector> BlockColors;
1093b387d10SStefan Gränitz 
1103b387d10SStefan Gränitz   // Build up the color map, which maps each block to its set of 'colors'.
1113b387d10SStefan Gränitz   // For any block B the "colors" of B are the set of funclets F (possibly
1123b387d10SStefan Gränitz   // including a root "funclet" representing the main function) such that
1133b387d10SStefan Gränitz   // F will need to directly contain B or a copy of B (where the term "directly
1143b387d10SStefan Gränitz   // contain" is used to distinguish from being "transitively contained" in
1153b387d10SStefan Gränitz   // a nested funclet).
1163b387d10SStefan Gränitz   //
1173b387d10SStefan Gränitz   // Note: Despite not being a funclet in the truest sense, a catchswitch is
1183b387d10SStefan Gränitz   // considered to belong to its own funclet for the purposes of coloring.
1193b387d10SStefan Gränitz 
1208a9bbac6Spaperchalice   DEBUG_WITH_TYPE("win-eh-prepare-coloring",
1213b387d10SStefan Gränitz                   dbgs() << "\nColoring funclets for " << F.getName() << "\n");
1223b387d10SStefan Gränitz 
1233b387d10SStefan Gränitz   Worklist.push_back({EntryBlock, EntryBlock});
1243b387d10SStefan Gränitz 
1253b387d10SStefan Gränitz   while (!Worklist.empty()) {
1263b387d10SStefan Gränitz     BasicBlock *Visiting;
1273b387d10SStefan Gränitz     BasicBlock *Color;
1283b387d10SStefan Gränitz     std::tie(Visiting, Color) = Worklist.pop_back_val();
1298a9bbac6Spaperchalice     DEBUG_WITH_TYPE("win-eh-prepare-coloring",
1303b387d10SStefan Gränitz                     dbgs() << "Visiting " << Visiting->getName() << ", "
1313b387d10SStefan Gränitz                            << Color->getName() << "\n");
132*6292a808SJeremy Morse     BasicBlock::iterator VisitingHead = Visiting->getFirstNonPHIIt();
1333b387d10SStefan Gränitz     if (VisitingHead->isEHPad()) {
1343b387d10SStefan Gränitz       // Mark this funclet head as a member of itself.
1353b387d10SStefan Gränitz       Color = Visiting;
1363b387d10SStefan Gränitz     }
1373b387d10SStefan Gränitz     // Note that this is a member of the given color.
1383b387d10SStefan Gränitz     ColorVector &Colors = BlockColors[Visiting];
1393b387d10SStefan Gränitz     if (!is_contained(Colors, Color))
1403b387d10SStefan Gränitz       Colors.push_back(Color);
1413b387d10SStefan Gränitz     else
1423b387d10SStefan Gränitz       continue;
1433b387d10SStefan Gränitz 
1448a9bbac6Spaperchalice     DEBUG_WITH_TYPE("win-eh-prepare-coloring",
1453b387d10SStefan Gränitz                     dbgs() << "  Assigned color \'" << Color->getName()
1463b387d10SStefan Gränitz                            << "\' to block \'" << Visiting->getName()
1473b387d10SStefan Gränitz                            << "\'.\n");
1483b387d10SStefan Gränitz 
1493b387d10SStefan Gränitz     BasicBlock *SuccColor = Color;
1503b387d10SStefan Gränitz     Instruction *Terminator = Visiting->getTerminator();
1513b387d10SStefan Gränitz     if (auto *CatchRet = dyn_cast<CatchReturnInst>(Terminator)) {
1523b387d10SStefan Gränitz       Value *ParentPad = CatchRet->getCatchSwitchParentPad();
1533b387d10SStefan Gränitz       if (isa<ConstantTokenNone>(ParentPad))
1543b387d10SStefan Gränitz         SuccColor = EntryBlock;
1553b387d10SStefan Gränitz       else
1563b387d10SStefan Gränitz         SuccColor = cast<Instruction>(ParentPad)->getParent();
1573b387d10SStefan Gränitz     }
1583b387d10SStefan Gränitz 
1593b387d10SStefan Gränitz     for (BasicBlock *Succ : successors(Visiting))
1603b387d10SStefan Gränitz       Worklist.push_back({Succ, SuccColor});
1613b387d10SStefan Gränitz   }
1623b387d10SStefan Gränitz   return BlockColors;
1633b387d10SStefan Gränitz }
164