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