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/BinaryFormat/Dwarf.h" |
15 | #include "llvm/CodeGen/AsmPrinter.h" |
16 | #include "llvm/CodeGen/MachineFunction.h" |
17 | #include "llvm/CodeGen/MachineModuleInfo.h" |
18 | #include "llvm/MC/MCAsmInfo.h" |
19 | #include "llvm/MC/MCContext.h" |
20 | #include "llvm/MC/MCStreamer.h" |
21 | #include "llvm/Target/TargetLoweringObjectFile.h" |
22 | #include "llvm/Target/TargetMachine.h" |
23 | #include "llvm/Target/TargetOptions.h" |
24 | using namespace llvm; |
25 | |
26 | DwarfCFIException::DwarfCFIException(AsmPrinter *A) : EHStreamer(A) {} |
27 | |
28 | DwarfCFIException::~DwarfCFIException() = default; |
29 | |
30 | void DwarfCFIException::addPersonality(const GlobalValue *Personality) { |
31 | if (!llvm::is_contained(Range&: Personalities, Element: Personality)) |
32 | Personalities.push_back(x: Personality); |
33 | } |
34 | |
35 | /// endModule - Emit all exception information that should come after the |
36 | /// content. |
37 | void DwarfCFIException::endModule() { |
38 | // SjLj uses this pass and it doesn't need this info. |
39 | if (!Asm->MAI->usesCFIForEH()) |
40 | return; |
41 | |
42 | const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); |
43 | |
44 | unsigned PerEncoding = TLOF.getPersonalityEncoding(); |
45 | |
46 | if ((PerEncoding & 0x80) != dwarf::DW_EH_PE_indirect) |
47 | return; |
48 | |
49 | // Emit indirect reference table for all used personality functions |
50 | for (const GlobalValue *Personality : Personalities) { |
51 | MCSymbol *Sym = Asm->getSymbol(GV: Personality); |
52 | TLOF.emitPersonalityValue(Streamer&: *Asm->OutStreamer, TM: Asm->getDataLayout(), Sym); |
53 | } |
54 | Personalities.clear(); |
55 | } |
56 | |
57 | void DwarfCFIException::beginFunction(const MachineFunction *MF) { |
58 | shouldEmitPersonality = shouldEmitLSDA = false; |
59 | const Function &F = MF->getFunction(); |
60 | |
61 | // If any landing pads survive, we need an EH table. |
62 | bool hasLandingPads = !MF->getLandingPads().empty(); |
63 | |
64 | // See if we need frame move info. |
65 | bool shouldEmitMoves = |
66 | Asm->getFunctionCFISectionType(MF: *MF) != AsmPrinter::CFISection::None; |
67 | |
68 | const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); |
69 | unsigned PerEncoding = TLOF.getPersonalityEncoding(); |
70 | const GlobalValue *Per = nullptr; |
71 | if (F.hasPersonalityFn()) |
72 | Per = dyn_cast<GlobalValue>(Val: F.getPersonalityFn()->stripPointerCasts()); |
73 | |
74 | // Emit a personality function even when there are no landing pads |
75 | forceEmitPersonality = |
76 | // ...if a personality function is explicitly specified |
77 | F.hasPersonalityFn() && |
78 | // ... and it's not known to be a noop in the absence of invokes |
79 | !isNoOpWithoutInvoke(Pers: classifyEHPersonality(Pers: Per)) && |
80 | // ... and we're not explicitly asked not to emit it |
81 | F.needsUnwindTableEntry(); |
82 | |
83 | shouldEmitPersonality = |
84 | (forceEmitPersonality || |
85 | (hasLandingPads && PerEncoding != dwarf::DW_EH_PE_omit)) && |
86 | Per; |
87 | |
88 | unsigned LSDAEncoding = TLOF.getLSDAEncoding(); |
89 | shouldEmitLSDA = shouldEmitPersonality && |
90 | LSDAEncoding != dwarf::DW_EH_PE_omit; |
91 | |
92 | const MCAsmInfo &MAI = *MF->getMMI().getContext().getAsmInfo(); |
93 | if (MAI.getExceptionHandlingType() != ExceptionHandling::None) |
94 | shouldEmitCFI = |
95 | MAI.usesCFIForEH() && (shouldEmitPersonality || shouldEmitMoves); |
96 | else |
97 | shouldEmitCFI = Asm->usesCFIWithoutEH() && shouldEmitMoves; |
98 | } |
99 | |
100 | void DwarfCFIException::beginBasicBlockSection(const MachineBasicBlock &MBB) { |
101 | if (!shouldEmitCFI) |
102 | return; |
103 | |
104 | if (!hasEmittedCFISections) { |
105 | AsmPrinter::CFISection CFISecType = Asm->getModuleCFISectionType(); |
106 | // If we don't say anything it implies `.cfi_sections .eh_frame`, so we |
107 | // chose not to be verbose in that case. And with `ForceDwarfFrameSection`, |
108 | // we should always emit .debug_frame. |
109 | if (CFISecType == AsmPrinter::CFISection::Debug || |
110 | Asm->TM.Options.ForceDwarfFrameSection) |
111 | Asm->OutStreamer->emitCFISections( |
112 | EH: CFISecType == AsmPrinter::CFISection::EH, Debug: true); |
113 | hasEmittedCFISections = true; |
114 | } |
115 | |
116 | Asm->OutStreamer->emitCFIStartProc(/*IsSimple=*/false); |
117 | |
118 | // Indicate personality routine, if any. |
119 | if (!shouldEmitPersonality) |
120 | return; |
121 | |
122 | auto &F = MBB.getParent()->getFunction(); |
123 | auto *P = dyn_cast<GlobalValue>(Val: F.getPersonalityFn()->stripPointerCasts()); |
124 | assert(P && "Expected personality function" ); |
125 | // Record the personality function. |
126 | addPersonality(Personality: P); |
127 | |
128 | const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering(); |
129 | unsigned PerEncoding = TLOF.getPersonalityEncoding(); |
130 | const MCSymbol *Sym = TLOF.getCFIPersonalitySymbol(GV: P, TM: Asm->TM, MMI); |
131 | Asm->OutStreamer->emitCFIPersonality(Sym, Encoding: PerEncoding); |
132 | |
133 | // Provide LSDA information. |
134 | if (shouldEmitLSDA) |
135 | Asm->OutStreamer->emitCFILsda(Sym: Asm->getMBBExceptionSym(MBB), |
136 | Encoding: TLOF.getLSDAEncoding()); |
137 | } |
138 | |
139 | void DwarfCFIException::endBasicBlockSection(const MachineBasicBlock &MBB) { |
140 | if (shouldEmitCFI) |
141 | Asm->OutStreamer->emitCFIEndProc(); |
142 | } |
143 | |
144 | /// endFunction - Gather and emit post-function exception information. |
145 | /// |
146 | void DwarfCFIException::endFunction(const MachineFunction *MF) { |
147 | if (!shouldEmitPersonality) |
148 | return; |
149 | |
150 | emitExceptionTable(); |
151 | } |
152 | |