xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/EHContGuardTargets.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===-- EHContGuardTargets.cpp - EH continuation target symbols -*- C++ -*-===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric ///
9*700637cbSDimitry Andric /// \file
10*700637cbSDimitry Andric /// This file contains a machine function pass to insert a symbol before each
11*700637cbSDimitry Andric /// valid target where the unwinder in Windows may continue exectution after an
12*700637cbSDimitry Andric /// exception is thrown and store this in the MachineFunction's EHContTargets
13*700637cbSDimitry Andric /// vector. This will be used to emit the table of valid targets used by Windows
14*700637cbSDimitry Andric /// EH Continuation Guard.
15*700637cbSDimitry Andric ///
16*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
17*700637cbSDimitry Andric 
18*700637cbSDimitry Andric #include "llvm/ADT/Statistic.h"
19*700637cbSDimitry Andric #include "llvm/CodeGen/MachineBasicBlock.h"
20*700637cbSDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
21*700637cbSDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
22*700637cbSDimitry Andric #include "llvm/CodeGen/Passes.h"
23*700637cbSDimitry Andric #include "llvm/IR/Module.h"
24*700637cbSDimitry Andric #include "llvm/InitializePasses.h"
25*700637cbSDimitry Andric 
26*700637cbSDimitry Andric using namespace llvm;
27*700637cbSDimitry Andric 
28*700637cbSDimitry Andric #define DEBUG_TYPE "ehcontguard-catchret"
29*700637cbSDimitry Andric 
30*700637cbSDimitry Andric STATISTIC(EHContGuardTargetsFound, "Number of EHCont Guard targets");
31*700637cbSDimitry Andric 
32*700637cbSDimitry Andric namespace {
33*700637cbSDimitry Andric 
34*700637cbSDimitry Andric /// MachineFunction pass to insert a symbol before each valid catchret target
35*700637cbSDimitry Andric /// and store these in the MachineFunction's CatchRetTargets vector.
36*700637cbSDimitry Andric class EHContGuardTargets : public MachineFunctionPass {
37*700637cbSDimitry Andric public:
38*700637cbSDimitry Andric   static char ID;
39*700637cbSDimitry Andric 
EHContGuardTargets()40*700637cbSDimitry Andric   EHContGuardTargets() : MachineFunctionPass(ID) {
41*700637cbSDimitry Andric     initializeEHContGuardTargetsPass(*PassRegistry::getPassRegistry());
42*700637cbSDimitry Andric   }
43*700637cbSDimitry Andric 
getPassName() const44*700637cbSDimitry Andric   StringRef getPassName() const override {
45*700637cbSDimitry Andric     return "EH Cont Guard catchret targets";
46*700637cbSDimitry Andric   }
47*700637cbSDimitry Andric 
48*700637cbSDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
49*700637cbSDimitry Andric };
50*700637cbSDimitry Andric 
51*700637cbSDimitry Andric } // end anonymous namespace
52*700637cbSDimitry Andric 
53*700637cbSDimitry Andric char EHContGuardTargets::ID = 0;
54*700637cbSDimitry Andric 
55*700637cbSDimitry Andric INITIALIZE_PASS(EHContGuardTargets, "EHContGuardTargets",
56*700637cbSDimitry Andric                 "Insert symbols at valid targets for /guard:ehcont", false,
57*700637cbSDimitry Andric                 false)
createEHContGuardTargetsPass()58*700637cbSDimitry Andric FunctionPass *llvm::createEHContGuardTargetsPass() {
59*700637cbSDimitry Andric   return new EHContGuardTargets();
60*700637cbSDimitry Andric }
61*700637cbSDimitry Andric 
runOnMachineFunction(MachineFunction & MF)62*700637cbSDimitry Andric bool EHContGuardTargets::runOnMachineFunction(MachineFunction &MF) {
63*700637cbSDimitry Andric 
64*700637cbSDimitry Andric   // Skip modules for which the ehcontguard flag is not set.
65*700637cbSDimitry Andric   if (!MF.getFunction().getParent()->getModuleFlag("ehcontguard"))
66*700637cbSDimitry Andric     return false;
67*700637cbSDimitry Andric 
68*700637cbSDimitry Andric   // Skip functions that do not have targets
69*700637cbSDimitry Andric   if (!MF.hasEHContTarget())
70*700637cbSDimitry Andric     return false;
71*700637cbSDimitry Andric 
72*700637cbSDimitry Andric   bool Result = false;
73*700637cbSDimitry Andric 
74*700637cbSDimitry Andric   for (MachineBasicBlock &MBB : MF) {
75*700637cbSDimitry Andric     if (MBB.isEHContTarget()) {
76*700637cbSDimitry Andric       MF.addEHContTarget(MBB.getEHContSymbol());
77*700637cbSDimitry Andric       EHContGuardTargetsFound++;
78*700637cbSDimitry Andric       Result = true;
79*700637cbSDimitry Andric     }
80*700637cbSDimitry Andric   }
81*700637cbSDimitry Andric 
82*700637cbSDimitry Andric   return Result;
83*700637cbSDimitry Andric }
84