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