File: | llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp |
Warning: | line 678, column 43 Access to field 'FragmentBeginLabel' results in a dereference of a null pointer (loaded from variable 'LandingPadRange') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===- CodeGen/AsmPrinter/EHStreamer.cpp - Exception Directive Streamer ---===// | ||||
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 exception info into assembly files. | ||||
10 | // | ||||
11 | //===----------------------------------------------------------------------===// | ||||
12 | |||||
13 | #include "EHStreamer.h" | ||||
14 | #include "llvm/ADT/SmallVector.h" | ||||
15 | #include "llvm/ADT/Twine.h" | ||||
16 | #include "llvm/ADT/iterator_range.h" | ||||
17 | #include "llvm/BinaryFormat/Dwarf.h" | ||||
18 | #include "llvm/CodeGen/AsmPrinter.h" | ||||
19 | #include "llvm/CodeGen/MachineFunction.h" | ||||
20 | #include "llvm/CodeGen/MachineInstr.h" | ||||
21 | #include "llvm/CodeGen/MachineOperand.h" | ||||
22 | #include "llvm/IR/DataLayout.h" | ||||
23 | #include "llvm/IR/Function.h" | ||||
24 | #include "llvm/MC/MCAsmInfo.h" | ||||
25 | #include "llvm/MC/MCContext.h" | ||||
26 | #include "llvm/MC/MCStreamer.h" | ||||
27 | #include "llvm/MC/MCSymbol.h" | ||||
28 | #include "llvm/MC/MCTargetOptions.h" | ||||
29 | #include "llvm/Support/Casting.h" | ||||
30 | #include "llvm/Support/LEB128.h" | ||||
31 | #include "llvm/Target/TargetLoweringObjectFile.h" | ||||
32 | #include <algorithm> | ||||
33 | #include <cassert> | ||||
34 | #include <cstdint> | ||||
35 | #include <vector> | ||||
36 | |||||
37 | using namespace llvm; | ||||
38 | |||||
39 | EHStreamer::EHStreamer(AsmPrinter *A) : Asm(A), MMI(Asm->MMI) {} | ||||
40 | |||||
41 | EHStreamer::~EHStreamer() = default; | ||||
42 | |||||
43 | /// How many leading type ids two landing pads have in common. | ||||
44 | unsigned EHStreamer::sharedTypeIDs(const LandingPadInfo *L, | ||||
45 | const LandingPadInfo *R) { | ||||
46 | const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds; | ||||
47 | return std::mismatch(LIds.begin(), LIds.end(), RIds.begin(), RIds.end()) | ||||
48 | .first - | ||||
49 | LIds.begin(); | ||||
50 | } | ||||
51 | |||||
52 | /// Compute the actions table and gather the first action index for each landing | ||||
53 | /// pad site. | ||||
54 | void EHStreamer::computeActionsTable( | ||||
55 | const SmallVectorImpl<const LandingPadInfo *> &LandingPads, | ||||
56 | SmallVectorImpl<ActionEntry> &Actions, | ||||
57 | SmallVectorImpl<unsigned> &FirstActions) { | ||||
58 | // The action table follows the call-site table in the LSDA. The individual | ||||
59 | // records are of two types: | ||||
60 | // | ||||
61 | // * Catch clause | ||||
62 | // * Exception specification | ||||
63 | // | ||||
64 | // The two record kinds have the same format, with only small differences. | ||||
65 | // They are distinguished by the "switch value" field: Catch clauses | ||||
66 | // (TypeInfos) have strictly positive switch values, and exception | ||||
67 | // specifications (FilterIds) have strictly negative switch values. Value 0 | ||||
68 | // indicates a catch-all clause. | ||||
69 | // | ||||
70 | // Negative type IDs index into FilterIds. Positive type IDs index into | ||||
71 | // TypeInfos. The value written for a positive type ID is just the type ID | ||||
72 | // itself. For a negative type ID, however, the value written is the | ||||
73 | // (negative) byte offset of the corresponding FilterIds entry. The byte | ||||
74 | // offset is usually equal to the type ID (because the FilterIds entries are | ||||
75 | // written using a variable width encoding, which outputs one byte per entry | ||||
76 | // as long as the value written is not too large) but can differ. This kind | ||||
77 | // of complication does not occur for positive type IDs because type infos are | ||||
78 | // output using a fixed width encoding. FilterOffsets[i] holds the byte | ||||
79 | // offset corresponding to FilterIds[i]. | ||||
80 | |||||
81 | const std::vector<unsigned> &FilterIds = Asm->MF->getFilterIds(); | ||||
82 | SmallVector<int, 16> FilterOffsets; | ||||
83 | FilterOffsets.reserve(FilterIds.size()); | ||||
84 | int Offset = -1; | ||||
85 | |||||
86 | for (unsigned FilterId : FilterIds) { | ||||
87 | FilterOffsets.push_back(Offset); | ||||
88 | Offset -= getULEB128Size(FilterId); | ||||
89 | } | ||||
90 | |||||
91 | FirstActions.reserve(LandingPads.size()); | ||||
92 | |||||
93 | int FirstAction = 0; | ||||
94 | unsigned SizeActions = 0; // Total size of all action entries for a function | ||||
95 | const LandingPadInfo *PrevLPI = nullptr; | ||||
96 | |||||
97 | for (const LandingPadInfo *LPI : LandingPads) { | ||||
98 | const std::vector<int> &TypeIds = LPI->TypeIds; | ||||
99 | unsigned NumShared = PrevLPI ? sharedTypeIDs(LPI, PrevLPI) : 0; | ||||
100 | unsigned SizeSiteActions = 0; // Total size of all entries for a landingpad | ||||
101 | |||||
102 | if (NumShared < TypeIds.size()) { | ||||
103 | // Size of one action entry (typeid + next action) | ||||
104 | unsigned SizeActionEntry = 0; | ||||
105 | unsigned PrevAction = (unsigned)-1; | ||||
106 | |||||
107 | if (NumShared) { | ||||
108 | unsigned SizePrevIds = PrevLPI->TypeIds.size(); | ||||
109 | assert(Actions.size())(static_cast <bool> (Actions.size()) ? void (0) : __assert_fail ("Actions.size()", "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp" , 109, __extension__ __PRETTY_FUNCTION__)); | ||||
110 | PrevAction = Actions.size() - 1; | ||||
111 | SizeActionEntry = getSLEB128Size(Actions[PrevAction].NextAction) + | ||||
112 | getSLEB128Size(Actions[PrevAction].ValueForTypeID); | ||||
113 | |||||
114 | for (unsigned j = NumShared; j != SizePrevIds; ++j) { | ||||
115 | assert(PrevAction != (unsigned)-1 && "PrevAction is invalid!")(static_cast <bool> (PrevAction != (unsigned)-1 && "PrevAction is invalid!") ? void (0) : __assert_fail ("PrevAction != (unsigned)-1 && \"PrevAction is invalid!\"" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp" , 115, __extension__ __PRETTY_FUNCTION__)); | ||||
116 | SizeActionEntry -= getSLEB128Size(Actions[PrevAction].ValueForTypeID); | ||||
117 | SizeActionEntry += -Actions[PrevAction].NextAction; | ||||
118 | PrevAction = Actions[PrevAction].Previous; | ||||
119 | } | ||||
120 | } | ||||
121 | |||||
122 | // Compute the actions. | ||||
123 | for (unsigned J = NumShared, M = TypeIds.size(); J != M; ++J) { | ||||
124 | int TypeID = TypeIds[J]; | ||||
125 | assert(-1 - TypeID < (int)FilterOffsets.size() && "Unknown filter id!")(static_cast <bool> (-1 - TypeID < (int)FilterOffsets .size() && "Unknown filter id!") ? void (0) : __assert_fail ("-1 - TypeID < (int)FilterOffsets.size() && \"Unknown filter id!\"" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp" , 125, __extension__ __PRETTY_FUNCTION__)); | ||||
126 | int ValueForTypeID = | ||||
127 | isFilterEHSelector(TypeID) ? FilterOffsets[-1 - TypeID] : TypeID; | ||||
128 | unsigned SizeTypeID = getSLEB128Size(ValueForTypeID); | ||||
129 | |||||
130 | int NextAction = SizeActionEntry ? -(SizeActionEntry + SizeTypeID) : 0; | ||||
131 | SizeActionEntry = SizeTypeID + getSLEB128Size(NextAction); | ||||
132 | SizeSiteActions += SizeActionEntry; | ||||
133 | |||||
134 | ActionEntry Action = { ValueForTypeID, NextAction, PrevAction }; | ||||
135 | Actions.push_back(Action); | ||||
136 | PrevAction = Actions.size() - 1; | ||||
137 | } | ||||
138 | |||||
139 | // Record the first action of the landing pad site. | ||||
140 | FirstAction = SizeActions + SizeSiteActions - SizeActionEntry + 1; | ||||
141 | } // else identical - re-use previous FirstAction | ||||
142 | |||||
143 | // Information used when creating the call-site table. The action record | ||||
144 | // field of the call site record is the offset of the first associated | ||||
145 | // action record, relative to the start of the actions table. This value is | ||||
146 | // biased by 1 (1 indicating the start of the actions table), and 0 | ||||
147 | // indicates that there are no actions. | ||||
148 | FirstActions.push_back(FirstAction); | ||||
149 | |||||
150 | // Compute this sites contribution to size. | ||||
151 | SizeActions += SizeSiteActions; | ||||
152 | |||||
153 | PrevLPI = LPI; | ||||
154 | } | ||||
155 | } | ||||
156 | |||||
157 | /// Return `true' if this is a call to a function marked `nounwind'. Return | ||||
158 | /// `false' otherwise. | ||||
159 | bool EHStreamer::callToNoUnwindFunction(const MachineInstr *MI) { | ||||
160 | assert(MI->isCall() && "This should be a call instruction!")(static_cast <bool> (MI->isCall() && "This should be a call instruction!" ) ? void (0) : __assert_fail ("MI->isCall() && \"This should be a call instruction!\"" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp" , 160, __extension__ __PRETTY_FUNCTION__)); | ||||
161 | |||||
162 | bool MarkedNoUnwind = false; | ||||
163 | bool SawFunc = false; | ||||
164 | |||||
165 | for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) { | ||||
166 | const MachineOperand &MO = MI->getOperand(I); | ||||
167 | |||||
168 | if (!MO.isGlobal()) continue; | ||||
169 | |||||
170 | const Function *F = dyn_cast<Function>(MO.getGlobal()); | ||||
171 | if (!F) continue; | ||||
172 | |||||
173 | if (SawFunc) { | ||||
174 | // Be conservative. If we have more than one function operand for this | ||||
175 | // call, then we can't make the assumption that it's the callee and | ||||
176 | // not a parameter to the call. | ||||
177 | // | ||||
178 | // FIXME: Determine if there's a way to say that `F' is the callee or | ||||
179 | // parameter. | ||||
180 | MarkedNoUnwind = false; | ||||
181 | break; | ||||
182 | } | ||||
183 | |||||
184 | MarkedNoUnwind = F->doesNotThrow(); | ||||
185 | SawFunc = true; | ||||
186 | } | ||||
187 | |||||
188 | return MarkedNoUnwind; | ||||
189 | } | ||||
190 | |||||
191 | void EHStreamer::computePadMap( | ||||
192 | const SmallVectorImpl<const LandingPadInfo *> &LandingPads, | ||||
193 | RangeMapType &PadMap) { | ||||
194 | // Invokes and nounwind calls have entries in PadMap (due to being bracketed | ||||
195 | // by try-range labels when lowered). Ordinary calls do not, so appropriate | ||||
196 | // try-ranges for them need be deduced so we can put them in the LSDA. | ||||
197 | for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { | ||||
198 | const LandingPadInfo *LandingPad = LandingPads[i]; | ||||
199 | for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) { | ||||
200 | MCSymbol *BeginLabel = LandingPad->BeginLabels[j]; | ||||
201 | assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!")(static_cast <bool> (!PadMap.count(BeginLabel) && "Duplicate landing pad labels!") ? void (0) : __assert_fail ( "!PadMap.count(BeginLabel) && \"Duplicate landing pad labels!\"" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp" , 201, __extension__ __PRETTY_FUNCTION__)); | ||||
202 | PadRange P = { i, j }; | ||||
203 | PadMap[BeginLabel] = P; | ||||
204 | } | ||||
205 | } | ||||
206 | } | ||||
207 | |||||
208 | /// Compute the call-site table. The entry for an invoke has a try-range | ||||
209 | /// containing the call, a non-zero landing pad, and an appropriate action. The | ||||
210 | /// entry for an ordinary call has a try-range containing the call and zero for | ||||
211 | /// the landing pad and the action. Calls marked 'nounwind' have no entry and | ||||
212 | /// must not be contained in the try-range of any entry - they form gaps in the | ||||
213 | /// table. Entries must be ordered by try-range address. | ||||
214 | /// | ||||
215 | /// Call-sites are split into one or more call-site ranges associated with | ||||
216 | /// different sections of the function. | ||||
217 | /// | ||||
218 | /// - Without -basic-block-sections, all call-sites are grouped into one | ||||
219 | /// call-site-range corresponding to the function section. | ||||
220 | /// | ||||
221 | /// - With -basic-block-sections, one call-site range is created for each | ||||
222 | /// section, with its FragmentBeginLabel and FragmentEndLabel respectively | ||||
223 | // set to the beginning and ending of the corresponding section and its | ||||
224 | // ExceptionLabel set to the exception symbol dedicated for this section. | ||||
225 | // Later, one LSDA header will be emitted for each call-site range with its | ||||
226 | // call-sites following. The action table and type info table will be | ||||
227 | // shared across all ranges. | ||||
228 | void EHStreamer::computeCallSiteTable( | ||||
229 | SmallVectorImpl<CallSiteEntry> &CallSites, | ||||
230 | SmallVectorImpl<CallSiteRange> &CallSiteRanges, | ||||
231 | const SmallVectorImpl<const LandingPadInfo *> &LandingPads, | ||||
232 | const SmallVectorImpl<unsigned> &FirstActions) { | ||||
233 | RangeMapType PadMap; | ||||
234 | computePadMap(LandingPads, PadMap); | ||||
235 | |||||
236 | // The end label of the previous invoke or nounwind try-range. | ||||
237 | MCSymbol *LastLabel = Asm->getFunctionBegin(); | ||||
238 | |||||
239 | // Whether there is a potentially throwing instruction (currently this means | ||||
240 | // an ordinary call) between the end of the previous try-range and now. | ||||
241 | bool SawPotentiallyThrowing = false; | ||||
242 | |||||
243 | // Whether the last CallSite entry was for an invoke. | ||||
244 | bool PreviousIsInvoke = false; | ||||
245 | |||||
246 | bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; | ||||
247 | |||||
248 | // Visit all instructions in order of address. | ||||
249 | for (const auto &MBB : *Asm->MF) { | ||||
250 | if (&MBB == &Asm->MF->front() || MBB.isBeginSection()) { | ||||
251 | // We start a call-site range upon function entry and at the beginning of | ||||
252 | // every basic block section. | ||||
253 | CallSiteRanges.push_back( | ||||
254 | {Asm->MBBSectionRanges[MBB.getSectionIDNum()].BeginLabel, | ||||
255 | Asm->MBBSectionRanges[MBB.getSectionIDNum()].EndLabel, | ||||
256 | Asm->getMBBExceptionSym(MBB), CallSites.size()}); | ||||
257 | PreviousIsInvoke = false; | ||||
258 | SawPotentiallyThrowing = false; | ||||
259 | LastLabel = nullptr; | ||||
260 | } | ||||
261 | |||||
262 | if (MBB.isEHPad()) | ||||
263 | CallSiteRanges.back().IsLPRange = true; | ||||
264 | |||||
265 | for (const auto &MI : MBB) { | ||||
266 | if (!MI.isEHLabel()) { | ||||
267 | if (MI.isCall()) | ||||
268 | SawPotentiallyThrowing |= !callToNoUnwindFunction(&MI); | ||||
269 | continue; | ||||
270 | } | ||||
271 | |||||
272 | // End of the previous try-range? | ||||
273 | MCSymbol *BeginLabel = MI.getOperand(0).getMCSymbol(); | ||||
274 | if (BeginLabel == LastLabel) | ||||
275 | SawPotentiallyThrowing = false; | ||||
276 | |||||
277 | // Beginning of a new try-range? | ||||
278 | RangeMapType::const_iterator L = PadMap.find(BeginLabel); | ||||
279 | if (L == PadMap.end()) | ||||
280 | // Nope, it was just some random label. | ||||
281 | continue; | ||||
282 | |||||
283 | const PadRange &P = L->second; | ||||
284 | const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; | ||||
285 | assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&(static_cast <bool> (BeginLabel == LandingPad->BeginLabels [P.RangeIndex] && "Inconsistent landing pad map!") ? void (0) : __assert_fail ("BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && \"Inconsistent landing pad map!\"" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp" , 286, __extension__ __PRETTY_FUNCTION__)) | ||||
286 | "Inconsistent landing pad map!")(static_cast <bool> (BeginLabel == LandingPad->BeginLabels [P.RangeIndex] && "Inconsistent landing pad map!") ? void (0) : __assert_fail ("BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && \"Inconsistent landing pad map!\"" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp" , 286, __extension__ __PRETTY_FUNCTION__)); | ||||
287 | |||||
288 | // For Dwarf and AIX exception handling (SjLj handling doesn't use this). | ||||
289 | // If some instruction between the previous try-range and this one may | ||||
290 | // throw, create a call-site entry with no landing pad for the region | ||||
291 | // between the try-ranges. | ||||
292 | if (SawPotentiallyThrowing && | ||||
293 | (Asm->MAI->usesCFIForEH() || | ||||
294 | Asm->MAI->getExceptionHandlingType() == ExceptionHandling::AIX)) { | ||||
295 | CallSites.push_back({LastLabel, BeginLabel, nullptr, 0}); | ||||
296 | PreviousIsInvoke = false; | ||||
297 | } | ||||
298 | |||||
299 | LastLabel = LandingPad->EndLabels[P.RangeIndex]; | ||||
300 | assert(BeginLabel && LastLabel && "Invalid landing pad!")(static_cast <bool> (BeginLabel && LastLabel && "Invalid landing pad!") ? void (0) : __assert_fail ("BeginLabel && LastLabel && \"Invalid landing pad!\"" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp" , 300, __extension__ __PRETTY_FUNCTION__)); | ||||
301 | |||||
302 | if (!LandingPad->LandingPadLabel) { | ||||
303 | // Create a gap. | ||||
304 | PreviousIsInvoke = false; | ||||
305 | } else { | ||||
306 | // This try-range is for an invoke. | ||||
307 | CallSiteEntry Site = { | ||||
308 | BeginLabel, | ||||
309 | LastLabel, | ||||
310 | LandingPad, | ||||
311 | FirstActions[P.PadIndex] | ||||
312 | }; | ||||
313 | |||||
314 | // Try to merge with the previous call-site. SJLJ doesn't do this | ||||
315 | if (PreviousIsInvoke && !IsSJLJ) { | ||||
316 | CallSiteEntry &Prev = CallSites.back(); | ||||
317 | if (Site.LPad == Prev.LPad && Site.Action == Prev.Action) { | ||||
318 | // Extend the range of the previous entry. | ||||
319 | Prev.EndLabel = Site.EndLabel; | ||||
320 | continue; | ||||
321 | } | ||||
322 | } | ||||
323 | |||||
324 | // Otherwise, create a new call-site. | ||||
325 | if (!IsSJLJ) | ||||
326 | CallSites.push_back(Site); | ||||
327 | else { | ||||
328 | // SjLj EH must maintain the call sites in the order assigned | ||||
329 | // to them by the SjLjPrepare pass. | ||||
330 | unsigned SiteNo = Asm->MF->getCallSiteBeginLabel(BeginLabel); | ||||
331 | if (CallSites.size() < SiteNo) | ||||
332 | CallSites.resize(SiteNo); | ||||
333 | CallSites[SiteNo - 1] = Site; | ||||
334 | } | ||||
335 | PreviousIsInvoke = true; | ||||
336 | } | ||||
337 | } | ||||
338 | |||||
339 | // We end the call-site range upon function exit and at the end of every | ||||
340 | // basic block section. | ||||
341 | if (&MBB == &Asm->MF->back() || MBB.isEndSection()) { | ||||
342 | // If some instruction between the previous try-range and the end of the | ||||
343 | // function may throw, create a call-site entry with no landing pad for | ||||
344 | // the region following the try-range. | ||||
345 | if (SawPotentiallyThrowing && !IsSJLJ) { | ||||
346 | CallSiteEntry Site = {LastLabel, CallSiteRanges.back().FragmentEndLabel, | ||||
347 | nullptr, 0}; | ||||
348 | CallSites.push_back(Site); | ||||
349 | SawPotentiallyThrowing = false; | ||||
350 | } | ||||
351 | CallSiteRanges.back().CallSiteEndIdx = CallSites.size(); | ||||
352 | } | ||||
353 | } | ||||
354 | } | ||||
355 | |||||
356 | /// Emit landing pads and actions. | ||||
357 | /// | ||||
358 | /// The general organization of the table is complex, but the basic concepts are | ||||
359 | /// easy. First there is a header which describes the location and organization | ||||
360 | /// of the three components that follow. | ||||
361 | /// | ||||
362 | /// 1. The landing pad site information describes the range of code covered by | ||||
363 | /// the try. In our case it's an accumulation of the ranges covered by the | ||||
364 | /// invokes in the try. There is also a reference to the landing pad that | ||||
365 | /// handles the exception once processed. Finally an index into the actions | ||||
366 | /// table. | ||||
367 | /// 2. The action table, in our case, is composed of pairs of type IDs and next | ||||
368 | /// action offset. Starting with the action index from the landing pad | ||||
369 | /// site, each type ID is checked for a match to the current exception. If | ||||
370 | /// it matches then the exception and type id are passed on to the landing | ||||
371 | /// pad. Otherwise the next action is looked up. This chain is terminated | ||||
372 | /// with a next action of zero. If no type id is found then the frame is | ||||
373 | /// unwound and handling continues. | ||||
374 | /// 3. Type ID table contains references to all the C++ typeinfo for all | ||||
375 | /// catches in the function. This tables is reverse indexed base 1. | ||||
376 | /// | ||||
377 | /// Returns the starting symbol of an exception table. | ||||
378 | MCSymbol *EHStreamer::emitExceptionTable() { | ||||
379 | const MachineFunction *MF = Asm->MF; | ||||
380 | const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos(); | ||||
381 | const std::vector<unsigned> &FilterIds = MF->getFilterIds(); | ||||
382 | const std::vector<LandingPadInfo> &PadInfos = MF->getLandingPads(); | ||||
383 | |||||
384 | // Sort the landing pads in order of their type ids. This is used to fold | ||||
385 | // duplicate actions. | ||||
386 | SmallVector<const LandingPadInfo *, 64> LandingPads; | ||||
387 | LandingPads.reserve(PadInfos.size()); | ||||
388 | |||||
389 | for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) | ||||
| |||||
390 | LandingPads.push_back(&PadInfos[i]); | ||||
391 | |||||
392 | // Order landing pads lexicographically by type id. | ||||
393 | llvm::sort(LandingPads, [](const LandingPadInfo *L, const LandingPadInfo *R) { | ||||
394 | return L->TypeIds < R->TypeIds; | ||||
395 | }); | ||||
396 | |||||
397 | // Compute the actions table and gather the first action index for each | ||||
398 | // landing pad site. | ||||
399 | SmallVector<ActionEntry, 32> Actions; | ||||
400 | SmallVector<unsigned, 64> FirstActions; | ||||
401 | computeActionsTable(LandingPads, Actions, FirstActions); | ||||
402 | |||||
403 | // Compute the call-site table and call-site ranges. Normally, there is only | ||||
404 | // one call-site-range which covers the whole funciton. With | ||||
405 | // -basic-block-sections, there is one call-site-range per basic block | ||||
406 | // section. | ||||
407 | SmallVector<CallSiteEntry, 64> CallSites; | ||||
408 | SmallVector<CallSiteRange, 4> CallSiteRanges; | ||||
409 | computeCallSiteTable(CallSites, CallSiteRanges, LandingPads, FirstActions); | ||||
410 | |||||
411 | bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; | ||||
412 | bool IsWasm = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Wasm; | ||||
413 | bool HasLEB128Directives = Asm->MAI->hasLEB128Directives(); | ||||
414 | unsigned CallSiteEncoding = | ||||
415 | IsSJLJ
| ||||
416 | Asm->getObjFileLowering().getCallSiteEncoding(); | ||||
417 | bool HaveTTData = !TypeInfos.empty() || !FilterIds.empty(); | ||||
418 | |||||
419 | // Type infos. | ||||
420 | MCSection *LSDASection = Asm->getObjFileLowering().getSectionForLSDA( | ||||
421 | MF->getFunction(), *Asm->CurrentFnSym, Asm->TM); | ||||
422 | unsigned TTypeEncoding; | ||||
423 | |||||
424 | if (!HaveTTData
| ||||
425 | // If there is no TypeInfo, then we just explicitly say that we're omitting | ||||
426 | // that bit. | ||||
427 | TTypeEncoding = dwarf::DW_EH_PE_omit; | ||||
428 | } else { | ||||
429 | // Okay, we have actual filters or typeinfos to emit. As such, we need to | ||||
430 | // pick a type encoding for them. We're about to emit a list of pointers to | ||||
431 | // typeinfo objects at the end of the LSDA. However, unless we're in static | ||||
432 | // mode, this reference will require a relocation by the dynamic linker. | ||||
433 | // | ||||
434 | // Because of this, we have a couple of options: | ||||
435 | // | ||||
436 | // 1) If we are in -static mode, we can always use an absolute reference | ||||
437 | // from the LSDA, because the static linker will resolve it. | ||||
438 | // | ||||
439 | // 2) Otherwise, if the LSDA section is writable, we can output the direct | ||||
440 | // reference to the typeinfo and allow the dynamic linker to relocate | ||||
441 | // it. Since it is in a writable section, the dynamic linker won't | ||||
442 | // have a problem. | ||||
443 | // | ||||
444 | // 3) Finally, if we're in PIC mode and the LDSA section isn't writable, | ||||
445 | // we need to use some form of indirection. For example, on Darwin, | ||||
446 | // we can output a statically-relocatable reference to a dyld stub. The | ||||
447 | // offset to the stub is constant, but the contents are in a section | ||||
448 | // that is updated by the dynamic linker. This is easy enough, but we | ||||
449 | // need to tell the personality function of the unwinder to indirect | ||||
450 | // through the dyld stub. | ||||
451 | // | ||||
452 | // FIXME: When (3) is actually implemented, we'll have to emit the stubs | ||||
453 | // somewhere. This predicate should be moved to a shared location that is | ||||
454 | // in target-independent code. | ||||
455 | // | ||||
456 | TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding(); | ||||
457 | } | ||||
458 | |||||
459 | // Begin the exception table. | ||||
460 | // Sometimes we want not to emit the data into separate section (e.g. ARM | ||||
461 | // EHABI). In this case LSDASection will be NULL. | ||||
462 | if (LSDASection) | ||||
463 | Asm->OutStreamer->SwitchSection(LSDASection); | ||||
464 | Asm->emitAlignment(Align(4)); | ||||
465 | |||||
466 | // Emit the LSDA. | ||||
467 | MCSymbol *GCCETSym = | ||||
468 | Asm->OutContext.getOrCreateSymbol(Twine("GCC_except_table")+ | ||||
469 | Twine(Asm->getFunctionNumber())); | ||||
470 | Asm->OutStreamer->emitLabel(GCCETSym); | ||||
471 | MCSymbol *CstEndLabel = Asm->createTempSymbol( | ||||
472 | CallSiteRanges.size() > 1 ? "action_table_base" : "cst_end"); | ||||
473 | |||||
474 | MCSymbol *TTBaseLabel = nullptr; | ||||
475 | if (HaveTTData
| ||||
476 | TTBaseLabel = Asm->createTempSymbol("ttbase"); | ||||
477 | |||||
478 | const bool VerboseAsm = Asm->OutStreamer->isVerboseAsm(); | ||||
479 | |||||
480 | // Helper for emitting references (offsets) for type table and the end of the | ||||
481 | // call-site table (which marks the beginning of the action table). | ||||
482 | // * For Itanium, these references will be emitted for every callsite range. | ||||
483 | // * For SJLJ and Wasm, they will be emitted only once in the LSDA header. | ||||
484 | auto EmitTypeTableRefAndCallSiteTableEndRef = [&]() { | ||||
485 | Asm->emitEncodingByte(TTypeEncoding, "@TType"); | ||||
486 | if (HaveTTData) { | ||||
487 | // N.B.: There is a dependency loop between the size of the TTBase uleb128 | ||||
488 | // here and the amount of padding before the aligned type table. The | ||||
489 | // assembler must sometimes pad this uleb128 or insert extra padding | ||||
490 | // before the type table. See PR35809 or GNU as bug 4029. | ||||
491 | MCSymbol *TTBaseRefLabel = Asm->createTempSymbol("ttbaseref"); | ||||
492 | Asm->emitLabelDifferenceAsULEB128(TTBaseLabel, TTBaseRefLabel); | ||||
493 | Asm->OutStreamer->emitLabel(TTBaseRefLabel); | ||||
494 | } | ||||
495 | |||||
496 | // The Action table follows the call-site table. So we emit the | ||||
497 | // label difference from here (start of the call-site table for SJLJ and | ||||
498 | // Wasm, and start of a call-site range for Itanium) to the end of the | ||||
499 | // whole call-site table (end of the last call-site range for Itanium). | ||||
500 | MCSymbol *CstBeginLabel = Asm->createTempSymbol("cst_begin"); | ||||
501 | Asm->emitEncodingByte(CallSiteEncoding, "Call site"); | ||||
502 | Asm->emitLabelDifferenceAsULEB128(CstEndLabel, CstBeginLabel); | ||||
503 | Asm->OutStreamer->emitLabel(CstBeginLabel); | ||||
504 | }; | ||||
505 | |||||
506 | // An alternative path to EmitTypeTableRefAndCallSiteTableEndRef. | ||||
507 | // For some platforms, the system assembler does not accept the form of | ||||
508 | // `.uleb128 label2 - label1`. In those situations, we would need to calculate | ||||
509 | // the size between label1 and label2 manually. | ||||
510 | // In this case, we would need to calculate the LSDA size and the call | ||||
511 | // site table size. | ||||
512 | auto EmitTypeTableOffsetAndCallSiteTableOffset = [&]() { | ||||
513 | assert(CallSiteEncoding == dwarf::DW_EH_PE_udata4 && !HasLEB128Directives &&(static_cast <bool> (CallSiteEncoding == dwarf::DW_EH_PE_udata4 && !HasLEB128Directives && "Targets supporting .uleb128 do not need to take this path." ) ? void (0) : __assert_fail ("CallSiteEncoding == dwarf::DW_EH_PE_udata4 && !HasLEB128Directives && \"Targets supporting .uleb128 do not need to take this path.\"" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp" , 514, __extension__ __PRETTY_FUNCTION__)) | ||||
514 | "Targets supporting .uleb128 do not need to take this path.")(static_cast <bool> (CallSiteEncoding == dwarf::DW_EH_PE_udata4 && !HasLEB128Directives && "Targets supporting .uleb128 do not need to take this path." ) ? void (0) : __assert_fail ("CallSiteEncoding == dwarf::DW_EH_PE_udata4 && !HasLEB128Directives && \"Targets supporting .uleb128 do not need to take this path.\"" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp" , 514, __extension__ __PRETTY_FUNCTION__)); | ||||
515 | if (CallSiteRanges.size() > 1) | ||||
516 | report_fatal_error( | ||||
517 | "-fbasic-block-sections is not yet supported on " | ||||
518 | "platforms that do not have general LEB128 directive support."); | ||||
519 | |||||
520 | uint64_t CallSiteTableSize = 0; | ||||
521 | const CallSiteRange &CSRange = CallSiteRanges.back(); | ||||
522 | for (size_t CallSiteIdx = CSRange.CallSiteBeginIdx; | ||||
523 | CallSiteIdx < CSRange.CallSiteEndIdx; ++CallSiteIdx) { | ||||
524 | const CallSiteEntry &S = CallSites[CallSiteIdx]; | ||||
525 | // Each call site entry consists of 3 udata4 fields (12 bytes) and | ||||
526 | // 1 ULEB128 field. | ||||
527 | CallSiteTableSize += 12 + getULEB128Size(S.Action); | ||||
528 | assert(isUInt<32>(CallSiteTableSize) && "CallSiteTableSize overflows.")(static_cast <bool> (isUInt<32>(CallSiteTableSize ) && "CallSiteTableSize overflows.") ? void (0) : __assert_fail ("isUInt<32>(CallSiteTableSize) && \"CallSiteTableSize overflows.\"" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp" , 528, __extension__ __PRETTY_FUNCTION__)); | ||||
529 | } | ||||
530 | |||||
531 | Asm->emitEncodingByte(TTypeEncoding, "@TType"); | ||||
532 | if (HaveTTData) { | ||||
533 | const unsigned ByteSizeOfCallSiteOffset = | ||||
534 | getULEB128Size(CallSiteTableSize); | ||||
535 | uint64_t ActionTableSize = 0; | ||||
536 | for (const ActionEntry &Action : Actions) { | ||||
537 | // Each action entry consists of two SLEB128 fields. | ||||
538 | ActionTableSize += getSLEB128Size(Action.ValueForTypeID) + | ||||
539 | getSLEB128Size(Action.NextAction); | ||||
540 | assert(isUInt<32>(ActionTableSize) && "ActionTableSize overflows.")(static_cast <bool> (isUInt<32>(ActionTableSize) && "ActionTableSize overflows.") ? void (0) : __assert_fail ("isUInt<32>(ActionTableSize) && \"ActionTableSize overflows.\"" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp" , 540, __extension__ __PRETTY_FUNCTION__)); | ||||
541 | } | ||||
542 | |||||
543 | const unsigned TypeInfoSize = | ||||
544 | Asm->GetSizeOfEncodedValue(TTypeEncoding) * MF->getTypeInfos().size(); | ||||
545 | |||||
546 | const uint64_t LSDASizeBeforeAlign = | ||||
547 | 1 // Call site encoding byte. | ||||
548 | + ByteSizeOfCallSiteOffset // ULEB128 encoding of CallSiteTableSize. | ||||
549 | + CallSiteTableSize // Call site table content. | ||||
550 | + ActionTableSize; // Action table content. | ||||
551 | |||||
552 | const uint64_t LSDASizeWithoutAlign = LSDASizeBeforeAlign + TypeInfoSize; | ||||
553 | const unsigned ByteSizeOfLSDAWithoutAlign = | ||||
554 | getULEB128Size(LSDASizeWithoutAlign); | ||||
555 | const uint64_t DisplacementBeforeAlign = | ||||
556 | 2 // LPStartEncoding and TypeTableEncoding. | ||||
557 | + ByteSizeOfLSDAWithoutAlign + LSDASizeBeforeAlign; | ||||
558 | |||||
559 | // The type info area starts with 4 byte alignment. | ||||
560 | const unsigned NeedAlignVal = (4 - DisplacementBeforeAlign % 4) % 4; | ||||
561 | uint64_t LSDASizeWithAlign = LSDASizeWithoutAlign + NeedAlignVal; | ||||
562 | const unsigned ByteSizeOfLSDAWithAlign = | ||||
563 | getULEB128Size(LSDASizeWithAlign); | ||||
564 | |||||
565 | // The LSDASizeWithAlign could use 1 byte less padding for alignment | ||||
566 | // when the data we use to represent the LSDA Size "needs" to be 1 byte | ||||
567 | // larger than the one previously calculated without alignment. | ||||
568 | if (ByteSizeOfLSDAWithAlign > ByteSizeOfLSDAWithoutAlign) | ||||
569 | LSDASizeWithAlign -= 1; | ||||
570 | |||||
571 | Asm->OutStreamer->emitULEB128IntValue(LSDASizeWithAlign, | ||||
572 | ByteSizeOfLSDAWithAlign); | ||||
573 | } | ||||
574 | |||||
575 | Asm->emitEncodingByte(CallSiteEncoding, "Call site"); | ||||
576 | Asm->OutStreamer->emitULEB128IntValue(CallSiteTableSize); | ||||
577 | }; | ||||
578 | |||||
579 | // SjLj / Wasm Exception handling | ||||
580 | if (IsSJLJ
| ||||
581 | Asm->OutStreamer->emitLabel(Asm->getMBBExceptionSym(Asm->MF->front())); | ||||
582 | |||||
583 | // emit the LSDA header. | ||||
584 | Asm->emitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); | ||||
585 | EmitTypeTableRefAndCallSiteTableEndRef(); | ||||
586 | |||||
587 | unsigned idx = 0; | ||||
588 | for (SmallVectorImpl<CallSiteEntry>::const_iterator | ||||
589 | I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) { | ||||
590 | const CallSiteEntry &S = *I; | ||||
591 | |||||
592 | // Index of the call site entry. | ||||
593 | if (VerboseAsm) { | ||||
594 | Asm->OutStreamer->AddComment(">> Call Site " + Twine(idx) + " <<"); | ||||
595 | Asm->OutStreamer->AddComment(" On exception at call site "+Twine(idx)); | ||||
596 | } | ||||
597 | Asm->emitULEB128(idx); | ||||
598 | |||||
599 | // Offset of the first associated action record, relative to the start of | ||||
600 | // the action table. This value is biased by 1 (1 indicates the start of | ||||
601 | // the action table), and 0 indicates that there are no actions. | ||||
602 | if (VerboseAsm) { | ||||
603 | if (S.Action == 0) | ||||
604 | Asm->OutStreamer->AddComment(" Action: cleanup"); | ||||
605 | else | ||||
606 | Asm->OutStreamer->AddComment(" Action: " + | ||||
607 | Twine((S.Action - 1) / 2 + 1)); | ||||
608 | } | ||||
609 | Asm->emitULEB128(S.Action); | ||||
610 | } | ||||
611 | Asm->OutStreamer->emitLabel(CstEndLabel); | ||||
612 | } else { | ||||
613 | // Itanium LSDA exception handling | ||||
614 | |||||
615 | // The call-site table is a list of all call sites that may throw an | ||||
616 | // exception (including C++ 'throw' statements) in the procedure | ||||
617 | // fragment. It immediately follows the LSDA header. Each entry indicates, | ||||
618 | // for a given call, the first corresponding action record and corresponding | ||||
619 | // landing pad. | ||||
620 | // | ||||
621 | // The table begins with the number of bytes, stored as an LEB128 | ||||
622 | // compressed, unsigned integer. The records immediately follow the record | ||||
623 | // count. They are sorted in increasing call-site address. Each record | ||||
624 | // indicates: | ||||
625 | // | ||||
626 | // * The position of the call-site. | ||||
627 | // * The position of the landing pad. | ||||
628 | // * The first action record for that call site. | ||||
629 | // | ||||
630 | // A missing entry in the call-site table indicates that a call is not | ||||
631 | // supposed to throw. | ||||
632 | |||||
633 | assert(CallSiteRanges.size() != 0 && "No call-site ranges!")(static_cast <bool> (CallSiteRanges.size() != 0 && "No call-site ranges!") ? void (0) : __assert_fail ("CallSiteRanges.size() != 0 && \"No call-site ranges!\"" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp" , 633, __extension__ __PRETTY_FUNCTION__)); | ||||
634 | |||||
635 | // There should be only one call-site range which includes all the landing | ||||
636 | // pads. Find that call-site range here. | ||||
637 | const CallSiteRange *LandingPadRange = nullptr; | ||||
638 | for (const CallSiteRange &CSRange : CallSiteRanges) { | ||||
639 | if (CSRange.IsLPRange) { | ||||
640 | assert(LandingPadRange == nullptr &&(static_cast <bool> (LandingPadRange == nullptr && "All landing pads must be in a single callsite range.") ? void (0) : __assert_fail ("LandingPadRange == nullptr && \"All landing pads must be in a single callsite range.\"" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp" , 641, __extension__ __PRETTY_FUNCTION__)) | ||||
641 | "All landing pads must be in a single callsite range.")(static_cast <bool> (LandingPadRange == nullptr && "All landing pads must be in a single callsite range.") ? void (0) : __assert_fail ("LandingPadRange == nullptr && \"All landing pads must be in a single callsite range.\"" , "/build/llvm-toolchain-snapshot-13~++20210726100616+dead50d4427c/llvm/lib/CodeGen/AsmPrinter/EHStreamer.cpp" , 641, __extension__ __PRETTY_FUNCTION__)); | ||||
642 | LandingPadRange = &CSRange; | ||||
643 | } | ||||
644 | } | ||||
645 | |||||
646 | // The call-site table is split into its call-site ranges, each being | ||||
647 | // emitted as: | ||||
648 | // [ LPStartEncoding | LPStart ] | ||||
649 | // [ TypeTableEncoding | TypeTableOffset ] | ||||
650 | // [ CallSiteEncoding | CallSiteTableEndOffset ] | ||||
651 | // cst_begin -> { call-site entries contained in this range } | ||||
652 | // | ||||
653 | // and is followed by the next call-site range. | ||||
654 | // | ||||
655 | // For each call-site range, CallSiteTableEndOffset is computed as the | ||||
656 | // difference between cst_begin of that range and the last call-site-table's | ||||
657 | // end label. This offset is used to find the action table. | ||||
658 | |||||
659 | unsigned Entry = 0; | ||||
660 | for (const CallSiteRange &CSRange : CallSiteRanges) { | ||||
661 | if (CSRange.CallSiteBeginIdx != 0) { | ||||
662 | // Align the call-site range for all ranges except the first. The | ||||
663 | // first range is already aligned due to the exception table alignment. | ||||
664 | Asm->emitAlignment(Align(4)); | ||||
665 | } | ||||
666 | Asm->OutStreamer->emitLabel(CSRange.ExceptionLabel); | ||||
667 | |||||
668 | // Emit the LSDA header. | ||||
669 | // If only one call-site range exists, LPStart is omitted as it is the | ||||
670 | // same as the function entry. | ||||
671 | if (CallSiteRanges.size() == 1) { | ||||
672 | Asm->emitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); | ||||
673 | } else if (!Asm->isPositionIndependent()) { | ||||
674 | // For more than one call-site ranges, LPStart must be explicitly | ||||
675 | // specified. | ||||
676 | // For non-PIC we can simply use the absolute value. | ||||
677 | Asm->emitEncodingByte(dwarf::DW_EH_PE_absptr, "@LPStart"); | ||||
678 | Asm->OutStreamer->emitSymbolValue(LandingPadRange->FragmentBeginLabel, | ||||
| |||||
679 | Asm->MAI->getCodePointerSize()); | ||||
680 | } else { | ||||
681 | // For PIC mode, we Emit a PC-relative address for LPStart. | ||||
682 | Asm->emitEncodingByte(dwarf::DW_EH_PE_pcrel, "@LPStart"); | ||||
683 | MCContext &Context = Asm->OutStreamer->getContext(); | ||||
684 | MCSymbol *Dot = Context.createTempSymbol(); | ||||
685 | Asm->OutStreamer->emitLabel(Dot); | ||||
686 | Asm->OutStreamer->emitValue( | ||||
687 | MCBinaryExpr::createSub( | ||||
688 | MCSymbolRefExpr::create(LandingPadRange->FragmentBeginLabel, | ||||
689 | Context), | ||||
690 | MCSymbolRefExpr::create(Dot, Context), Context), | ||||
691 | Asm->MAI->getCodePointerSize()); | ||||
692 | } | ||||
693 | |||||
694 | if (HasLEB128Directives) | ||||
695 | EmitTypeTableRefAndCallSiteTableEndRef(); | ||||
696 | else | ||||
697 | EmitTypeTableOffsetAndCallSiteTableOffset(); | ||||
698 | |||||
699 | for (size_t CallSiteIdx = CSRange.CallSiteBeginIdx; | ||||
700 | CallSiteIdx != CSRange.CallSiteEndIdx; ++CallSiteIdx) { | ||||
701 | const CallSiteEntry &S = CallSites[CallSiteIdx]; | ||||
702 | |||||
703 | MCSymbol *EHFuncBeginSym = CSRange.FragmentBeginLabel; | ||||
704 | MCSymbol *EHFuncEndSym = CSRange.FragmentEndLabel; | ||||
705 | |||||
706 | MCSymbol *BeginLabel = S.BeginLabel; | ||||
707 | if (!BeginLabel) | ||||
708 | BeginLabel = EHFuncBeginSym; | ||||
709 | MCSymbol *EndLabel = S.EndLabel; | ||||
710 | if (!EndLabel) | ||||
711 | EndLabel = EHFuncEndSym; | ||||
712 | |||||
713 | // Offset of the call site relative to the start of the procedure. | ||||
714 | if (VerboseAsm) | ||||
715 | Asm->OutStreamer->AddComment(">> Call Site " + Twine(++Entry) + | ||||
716 | " <<"); | ||||
717 | Asm->emitCallSiteOffset(BeginLabel, EHFuncBeginSym, CallSiteEncoding); | ||||
718 | if (VerboseAsm) | ||||
719 | Asm->OutStreamer->AddComment(Twine(" Call between ") + | ||||
720 | BeginLabel->getName() + " and " + | ||||
721 | EndLabel->getName()); | ||||
722 | Asm->emitCallSiteOffset(EndLabel, BeginLabel, CallSiteEncoding); | ||||
723 | |||||
724 | // Offset of the landing pad relative to the start of the landing pad | ||||
725 | // fragment. | ||||
726 | if (!S.LPad) { | ||||
727 | if (VerboseAsm) | ||||
728 | Asm->OutStreamer->AddComment(" has no landing pad"); | ||||
729 | Asm->emitCallSiteValue(0, CallSiteEncoding); | ||||
730 | } else { | ||||
731 | if (VerboseAsm) | ||||
732 | Asm->OutStreamer->AddComment(Twine(" jumps to ") + | ||||
733 | S.LPad->LandingPadLabel->getName()); | ||||
734 | Asm->emitCallSiteOffset(S.LPad->LandingPadLabel, | ||||
735 | LandingPadRange->FragmentBeginLabel, | ||||
736 | CallSiteEncoding); | ||||
737 | } | ||||
738 | |||||
739 | // Offset of the first associated action record, relative to the start | ||||
740 | // of the action table. This value is biased by 1 (1 indicates the start | ||||
741 | // of the action table), and 0 indicates that there are no actions. | ||||
742 | if (VerboseAsm) { | ||||
743 | if (S.Action == 0) | ||||
744 | Asm->OutStreamer->AddComment(" On action: cleanup"); | ||||
745 | else | ||||
746 | Asm->OutStreamer->AddComment(" On action: " + | ||||
747 | Twine((S.Action - 1) / 2 + 1)); | ||||
748 | } | ||||
749 | Asm->emitULEB128(S.Action); | ||||
750 | } | ||||
751 | } | ||||
752 | Asm->OutStreamer->emitLabel(CstEndLabel); | ||||
753 | } | ||||
754 | |||||
755 | // Emit the Action Table. | ||||
756 | int Entry = 0; | ||||
757 | for (const ActionEntry &Action : Actions) { | ||||
758 | if (VerboseAsm) { | ||||
759 | // Emit comments that decode the action table. | ||||
760 | Asm->OutStreamer->AddComment(">> Action Record " + Twine(++Entry) + " <<"); | ||||
761 | } | ||||
762 | |||||
763 | // Type Filter | ||||
764 | // | ||||
765 | // Used by the runtime to match the type of the thrown exception to the | ||||
766 | // type of the catch clauses or the types in the exception specification. | ||||
767 | if (VerboseAsm) { | ||||
768 | if (Action.ValueForTypeID > 0) | ||||
769 | Asm->OutStreamer->AddComment(" Catch TypeInfo " + | ||||
770 | Twine(Action.ValueForTypeID)); | ||||
771 | else if (Action.ValueForTypeID < 0) | ||||
772 | Asm->OutStreamer->AddComment(" Filter TypeInfo " + | ||||
773 | Twine(Action.ValueForTypeID)); | ||||
774 | else | ||||
775 | Asm->OutStreamer->AddComment(" Cleanup"); | ||||
776 | } | ||||
777 | Asm->emitSLEB128(Action.ValueForTypeID); | ||||
778 | |||||
779 | // Action Record | ||||
780 | if (VerboseAsm) { | ||||
781 | if (Action.Previous == unsigned(-1)) { | ||||
782 | Asm->OutStreamer->AddComment(" No further actions"); | ||||
783 | } else { | ||||
784 | Asm->OutStreamer->AddComment(" Continue to action " + | ||||
785 | Twine(Action.Previous + 1)); | ||||
786 | } | ||||
787 | } | ||||
788 | Asm->emitSLEB128(Action.NextAction); | ||||
789 | } | ||||
790 | |||||
791 | if (HaveTTData) { | ||||
792 | Asm->emitAlignment(Align(4)); | ||||
793 | emitTypeInfos(TTypeEncoding, TTBaseLabel); | ||||
794 | } | ||||
795 | |||||
796 | Asm->emitAlignment(Align(4)); | ||||
797 | return GCCETSym; | ||||
798 | } | ||||
799 | |||||
800 | void EHStreamer::emitTypeInfos(unsigned TTypeEncoding, MCSymbol *TTBaseLabel) { | ||||
801 | const MachineFunction *MF = Asm->MF; | ||||
802 | const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos(); | ||||
803 | const std::vector<unsigned> &FilterIds = MF->getFilterIds(); | ||||
804 | |||||
805 | const bool VerboseAsm = Asm->OutStreamer->isVerboseAsm(); | ||||
806 | |||||
807 | int Entry = 0; | ||||
808 | // Emit the Catch TypeInfos. | ||||
809 | if (VerboseAsm && !TypeInfos.empty()) { | ||||
810 | Asm->OutStreamer->AddComment(">> Catch TypeInfos <<"); | ||||
811 | Asm->OutStreamer->AddBlankLine(); | ||||
812 | Entry = TypeInfos.size(); | ||||
813 | } | ||||
814 | |||||
815 | for (const GlobalValue *GV : make_range(TypeInfos.rbegin(), | ||||
816 | TypeInfos.rend())) { | ||||
817 | if (VerboseAsm) | ||||
818 | Asm->OutStreamer->AddComment("TypeInfo " + Twine(Entry--)); | ||||
819 | Asm->emitTTypeReference(GV, TTypeEncoding); | ||||
820 | } | ||||
821 | |||||
822 | Asm->OutStreamer->emitLabel(TTBaseLabel); | ||||
823 | |||||
824 | // Emit the Exception Specifications. | ||||
825 | if (VerboseAsm && !FilterIds.empty()) { | ||||
826 | Asm->OutStreamer->AddComment(">> Filter TypeInfos <<"); | ||||
827 | Asm->OutStreamer->AddBlankLine(); | ||||
828 | Entry = 0; | ||||
829 | } | ||||
830 | for (std::vector<unsigned>::const_iterator | ||||
831 | I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { | ||||
832 | unsigned TypeID = *I; | ||||
833 | if (VerboseAsm) { | ||||
834 | --Entry; | ||||
835 | if (isFilterEHSelector(TypeID)) | ||||
836 | Asm->OutStreamer->AddComment("FilterInfo " + Twine(Entry)); | ||||
837 | } | ||||
838 | |||||
839 | Asm->emitULEB128(TypeID); | ||||
840 | } | ||||
841 | } |