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