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