xref: /freebsd/contrib/llvm-project/llvm/lib/CodeGen/AsmPrinter/DwarfCFIException.cpp (revision d30a1689f5b37e78ea189232a8b94a7011dc0dc8)
1 //===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf Exception Impl ------===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains support for writing DWARF exception info into asm files.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "DwarfException.h"
14 #include "llvm/ADT/Twine.h"
15 #include "llvm/BinaryFormat/Dwarf.h"
16 #include "llvm/CodeGen/AsmPrinter.h"
17 #include "llvm/CodeGen/MachineFunction.h"
18 #include "llvm/CodeGen/MachineModuleInfo.h"
19 #include "llvm/IR/DataLayout.h"
20 #include "llvm/IR/Mangler.h"
21 #include "llvm/IR/Module.h"
22 #include "llvm/MC/MCAsmInfo.h"
23 #include "llvm/MC/MCContext.h"
24 #include "llvm/MC/MCExpr.h"
25 #include "llvm/MC/MCSection.h"
26 #include "llvm/MC/MCStreamer.h"
27 #include "llvm/MC/MCSymbol.h"
28 #include "llvm/MC/MachineLocation.h"
29 #include "llvm/Support/ErrorHandling.h"
30 #include "llvm/Support/FormattedStream.h"
31 #include "llvm/Target/TargetLoweringObjectFile.h"
32 #include "llvm/Target/TargetMachine.h"
33 #include "llvm/Target/TargetOptions.h"
34 using namespace llvm;
35 
36 DwarfCFIExceptionBase::DwarfCFIExceptionBase(AsmPrinter *A) : EHStreamer(A) {}
37 
38 void DwarfCFIExceptionBase::markFunctionEnd() {
39   endFragment();
40 
41   // Map all labels and get rid of any dead landing pads.
42   if (!Asm->MF->getLandingPads().empty()) {
43     MachineFunction *NonConstMF = const_cast<MachineFunction*>(Asm->MF);
44     NonConstMF->tidyLandingPads();
45   }
46 }
47 
48 void DwarfCFIExceptionBase::endFragment() {
49   if (shouldEmitCFI && !Asm->MF->hasBBSections())
50     Asm->OutStreamer->emitCFIEndProc();
51 }
52 
53 DwarfCFIException::DwarfCFIException(AsmPrinter *A)
54     : DwarfCFIExceptionBase(A) {}
55 
56 DwarfCFIException::~DwarfCFIException() {}
57 
58 /// endModule - Emit all exception information that should come after the
59 /// content.
60 void DwarfCFIException::endModule() {
61   // SjLj uses this pass and it doesn't need this info.
62   if (!Asm->MAI->usesCFIForEH())
63     return;
64 
65   const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
66 
67   unsigned PerEncoding = TLOF.getPersonalityEncoding();
68 
69   if ((PerEncoding & 0x80) != dwarf::DW_EH_PE_indirect)
70     return;
71 
72   // Emit references to all used personality functions
73   for (const Function *Personality : MMI->getPersonalities()) {
74     if (!Personality)
75       continue;
76     MCSymbol *Sym = Asm->getSymbol(Personality);
77     TLOF.emitPersonalityValue(*Asm->OutStreamer, Asm->getDataLayout(), Sym);
78   }
79 }
80 
81 static MCSymbol *getExceptionSym(AsmPrinter *Asm,
82                                  const MachineBasicBlock *MBB) {
83   return Asm->getMBBExceptionSym(*MBB);
84 }
85 
86 void DwarfCFIException::beginFunction(const MachineFunction *MF) {
87   shouldEmitPersonality = shouldEmitLSDA = false;
88   const Function &F = MF->getFunction();
89 
90   // If any landing pads survive, we need an EH table.
91   bool hasLandingPads = !MF->getLandingPads().empty();
92 
93   // See if we need frame move info.
94   bool shouldEmitMoves =
95       Asm->getFunctionCFISectionType(*MF) != AsmPrinter::CFISection::None;
96 
97   const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
98   unsigned PerEncoding = TLOF.getPersonalityEncoding();
99   const Function *Per = nullptr;
100   if (F.hasPersonalityFn())
101     Per = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts());
102 
103   // Emit a personality function even when there are no landing pads
104   forceEmitPersonality =
105       // ...if a personality function is explicitly specified
106       F.hasPersonalityFn() &&
107       // ... and it's not known to be a noop in the absence of invokes
108       !isNoOpWithoutInvoke(classifyEHPersonality(Per)) &&
109       // ... and we're not explicitly asked not to emit it
110       F.needsUnwindTableEntry();
111 
112   shouldEmitPersonality =
113       (forceEmitPersonality ||
114        (hasLandingPads && PerEncoding != dwarf::DW_EH_PE_omit)) &&
115       Per;
116 
117   unsigned LSDAEncoding = TLOF.getLSDAEncoding();
118   shouldEmitLSDA = shouldEmitPersonality &&
119     LSDAEncoding != dwarf::DW_EH_PE_omit;
120 
121   const MCAsmInfo &MAI = *MF->getMMI().getContext().getAsmInfo();
122   if (MAI.getExceptionHandlingType() != ExceptionHandling::None)
123     shouldEmitCFI =
124         MAI.usesCFIForEH() && (shouldEmitPersonality || shouldEmitMoves);
125   else
126     shouldEmitCFI = Asm->needsCFIForDebug() && shouldEmitMoves;
127 
128   beginFragment(&*MF->begin(), getExceptionSym);
129 }
130 
131 void DwarfCFIException::beginFragment(const MachineBasicBlock *MBB,
132                                       ExceptionSymbolProvider ESP) {
133   if (!shouldEmitCFI)
134     return;
135 
136   if (!hasEmittedCFISections) {
137     AsmPrinter::CFISection CFISecType = Asm->getModuleCFISectionType();
138     // If we don't say anything it implies `.cfi_sections .eh_frame`, so we
139     // chose not to be verbose in that case. And with `ForceDwarfFrameSection`,
140     // we should always emit .debug_frame.
141     if (CFISecType == AsmPrinter::CFISection::Debug ||
142         Asm->TM.Options.ForceDwarfFrameSection)
143       Asm->OutStreamer->emitCFISections(
144           CFISecType == AsmPrinter::CFISection::EH, true);
145     hasEmittedCFISections = true;
146   }
147 
148   Asm->OutStreamer->emitCFIStartProc(/*IsSimple=*/false);
149 
150   // Indicate personality routine, if any.
151   if (!shouldEmitPersonality)
152     return;
153 
154   auto &F = MBB->getParent()->getFunction();
155   auto *P = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts());
156   assert(P && "Expected personality function");
157 
158   // If we are forced to emit this personality, make sure to record
159   // it because it might not appear in any landingpad
160   if (forceEmitPersonality)
161     MMI->addPersonality(P);
162 
163   const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
164   unsigned PerEncoding = TLOF.getPersonalityEncoding();
165   const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(P, Asm->TM, MMI);
166   Asm->OutStreamer->emitCFIPersonality(Sym, PerEncoding);
167 
168   // Provide LSDA information.
169   if (shouldEmitLSDA)
170     Asm->OutStreamer->emitCFILsda(ESP(Asm, MBB), TLOF.getLSDAEncoding());
171 }
172 
173 /// endFunction - Gather and emit post-function exception information.
174 ///
175 void DwarfCFIException::endFunction(const MachineFunction *MF) {
176   if (!shouldEmitPersonality)
177     return;
178 
179   emitExceptionTable();
180 }
181 
182 void DwarfCFIException::beginBasicBlock(const MachineBasicBlock &MBB) {
183   beginFragment(&MBB, getExceptionSym);
184 }
185 
186 void DwarfCFIException::endBasicBlock(const MachineBasicBlock &MBB) {
187   if (shouldEmitCFI)
188     Asm->OutStreamer->emitCFIEndProc();
189 }
190