Home | History | Annotate | Download | only in AsmPrinter
      1 //===-- CodeGen/AsmPrinter/EHStreamer.cpp - Exception Directive Streamer --===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file contains support for writing exception info into assembly files.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #include "EHStreamer.h"
     15 #include "llvm/CodeGen/AsmPrinter.h"
     16 #include "llvm/CodeGen/MachineFunction.h"
     17 #include "llvm/CodeGen/MachineInstr.h"
     18 #include "llvm/CodeGen/MachineModuleInfo.h"
     19 #include "llvm/IR/Function.h"
     20 #include "llvm/MC/MCAsmInfo.h"
     21 #include "llvm/MC/MCStreamer.h"
     22 #include "llvm/MC/MCSymbol.h"
     23 #include "llvm/Support/LEB128.h"
     24 #include "llvm/Target/TargetLoweringObjectFile.h"
     25 
     26 using namespace llvm;
     27 
     28 EHStreamer::EHStreamer(AsmPrinter *A) : Asm(A), MMI(Asm->MMI) {}
     29 
     30 EHStreamer::~EHStreamer() {}
     31 
     32 /// How many leading type ids two landing pads have in common.
     33 unsigned EHStreamer::sharedTypeIDs(const LandingPadInfo *L,
     34                                    const LandingPadInfo *R) {
     35   const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds;
     36   unsigned LSize = LIds.size(), RSize = RIds.size();
     37   unsigned MinSize = LSize < RSize ? LSize : RSize;
     38   unsigned Count = 0;
     39 
     40   for (; Count != MinSize; ++Count)
     41     if (LIds[Count] != RIds[Count])
     42       return Count;
     43 
     44   return Count;
     45 }
     46 
     47 /// Compute the actions table and gather the first action index for each landing
     48 /// pad site.
     49 unsigned EHStreamer::
     50 computeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads,
     51                     SmallVectorImpl<ActionEntry> &Actions,
     52                     SmallVectorImpl<unsigned> &FirstActions) {
     53 
     54   // The action table follows the call-site table in the LSDA. The individual
     55   // records are of two types:
     56   //
     57   //   * Catch clause
     58   //   * Exception specification
     59   //
     60   // The two record kinds have the same format, with only small differences.
     61   // They are distinguished by the "switch value" field: Catch clauses
     62   // (TypeInfos) have strictly positive switch values, and exception
     63   // specifications (FilterIds) have strictly negative switch values. Value 0
     64   // indicates a catch-all clause.
     65   //
     66   // Negative type IDs index into FilterIds. Positive type IDs index into
     67   // TypeInfos.  The value written for a positive type ID is just the type ID
     68   // itself.  For a negative type ID, however, the value written is the
     69   // (negative) byte offset of the corresponding FilterIds entry.  The byte
     70   // offset is usually equal to the type ID (because the FilterIds entries are
     71   // written using a variable width encoding, which outputs one byte per entry
     72   // as long as the value written is not too large) but can differ.  This kind
     73   // of complication does not occur for positive type IDs because type infos are
     74   // output using a fixed width encoding.  FilterOffsets[i] holds the byte
     75   // offset corresponding to FilterIds[i].
     76 
     77   const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
     78   SmallVector<int, 16> FilterOffsets;
     79   FilterOffsets.reserve(FilterIds.size());
     80   int Offset = -1;
     81 
     82   for (std::vector<unsigned>::const_iterator
     83          I = FilterIds.begin(), E = FilterIds.end(); I != E; ++I) {
     84     FilterOffsets.push_back(Offset);
     85     Offset -= getULEB128Size(*I);
     86   }
     87 
     88   FirstActions.reserve(LandingPads.size());
     89 
     90   int FirstAction = 0;
     91   unsigned SizeActions = 0;
     92   const LandingPadInfo *PrevLPI = nullptr;
     93 
     94   for (SmallVectorImpl<const LandingPadInfo *>::const_iterator
     95          I = LandingPads.begin(), E = LandingPads.end(); I != E; ++I) {
     96     const LandingPadInfo *LPI = *I;
     97     const std::vector<int> &TypeIds = LPI->TypeIds;
     98     unsigned NumShared = PrevLPI ? sharedTypeIDs(LPI, PrevLPI) : 0;
     99     unsigned SizeSiteActions = 0;
    100 
    101     if (NumShared < TypeIds.size()) {
    102       unsigned SizeAction = 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         SizeAction = 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           SizeAction -= getSLEB128Size(Actions[PrevAction].ValueForTypeID);
    115           SizeAction += -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 = SizeAction ? -(SizeAction + SizeTypeID) : 0;
    129         SizeAction = SizeTypeID + getSLEB128Size(NextAction);
    130         SizeSiteActions += SizeAction;
    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 - SizeAction + 1;
    139     } // else identical - re-use previous FirstAction
    140 
    141     // Information used when created 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   return SizeActions;
    155 }
    156 
    157 /// Return `true' if this is a call to a function marked `nounwind'. Return
    158 /// `false' otherwise.
    159 bool EHStreamer::callToNoUnwindFunction(const MachineInstr *MI) {
    160   assert(MI->isCall() && "This should be a call instruction!");
    161 
    162   bool MarkedNoUnwind = false;
    163   bool SawFunc = false;
    164 
    165   for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
    166     const MachineOperand &MO = MI->getOperand(I);
    167 
    168     if (!MO.isGlobal()) continue;
    169 
    170     const Function *F = dyn_cast<Function>(MO.getGlobal());
    171     if (!F) continue;
    172 
    173     if (SawFunc) {
    174       // Be conservative. If we have more than one function operand for this
    175       // call, then we can't make the assumption that it's the callee and
    176       // not a parameter to the call.
    177       //
    178       // FIXME: Determine if there's a way to say that `F' is the callee or
    179       // parameter.
    180       MarkedNoUnwind = false;
    181       break;
    182     }
    183 
    184     MarkedNoUnwind = F->doesNotThrow();
    185     SawFunc = true;
    186   }
    187 
    188   return MarkedNoUnwind;
    189 }
    190 
    191 void EHStreamer::computePadMap(
    192     const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
    193     RangeMapType &PadMap) {
    194   // Invokes and nounwind calls have entries in PadMap (due to being bracketed
    195   // by try-range labels when lowered).  Ordinary calls do not, so appropriate
    196   // try-ranges for them need be deduced so we can put them in the LSDA.
    197   for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
    198     const LandingPadInfo *LandingPad = LandingPads[i];
    199     for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) {
    200       MCSymbol *BeginLabel = LandingPad->BeginLabels[j];
    201       assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!");
    202       PadRange P = { i, j };
    203       PadMap[BeginLabel] = P;
    204     }
    205   }
    206 }
    207 
    208 /// Compute the call-site table.  The entry for an invoke has a try-range
    209 /// containing the call, a non-zero landing pad, and an appropriate action.  The
    210 /// entry for an ordinary call has a try-range containing the call and zero for
    211 /// the landing pad and the action.  Calls marked 'nounwind' have no entry and
    212 /// must not be contained in the try-range of any entry - they form gaps in the
    213 /// table.  Entries must be ordered by try-range address.
    214 void EHStreamer::
    215 computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
    216                      const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
    217                      const SmallVectorImpl<unsigned> &FirstActions) {
    218   RangeMapType PadMap;
    219   computePadMap(LandingPads, PadMap);
    220 
    221   // The end label of the previous invoke or nounwind try-range.
    222   MCSymbol *LastLabel = nullptr;
    223 
    224   // Whether there is a potentially throwing instruction (currently this means
    225   // an ordinary call) between the end of the previous try-range and now.
    226   bool SawPotentiallyThrowing = false;
    227 
    228   // Whether the last CallSite entry was for an invoke.
    229   bool PreviousIsInvoke = false;
    230 
    231   bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj;
    232 
    233   // Visit all instructions in order of address.
    234   for (const auto &MBB : *Asm->MF) {
    235     for (const auto &MI : MBB) {
    236       if (!MI.isEHLabel()) {
    237         if (MI.isCall())
    238           SawPotentiallyThrowing |= !callToNoUnwindFunction(&MI);
    239         continue;
    240       }
    241 
    242       // End of the previous try-range?
    243       MCSymbol *BeginLabel = MI.getOperand(0).getMCSymbol();
    244       if (BeginLabel == LastLabel)
    245         SawPotentiallyThrowing = false;
    246 
    247       // Beginning of a new try-range?
    248       RangeMapType::const_iterator L = PadMap.find(BeginLabel);
    249       if (L == PadMap.end())
    250         // Nope, it was just some random label.
    251         continue;
    252 
    253       const PadRange &P = L->second;
    254       const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
    255       assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
    256              "Inconsistent landing pad map!");
    257 
    258       // For Dwarf exception handling (SjLj handling doesn't use this). If some
    259       // instruction between the previous try-range and this one may throw,
    260       // create a call-site entry with no landing pad for the region between the
    261       // try-ranges.
    262       if (SawPotentiallyThrowing && Asm->MAI->usesCFIForEH()) {
    263         CallSiteEntry Site = { LastLabel, BeginLabel, nullptr, 0 };
    264         CallSites.push_back(Site);
    265         PreviousIsInvoke = false;
    266       }
    267 
    268       LastLabel = LandingPad->EndLabels[P.RangeIndex];
    269       assert(BeginLabel && LastLabel && "Invalid landing pad!");
    270 
    271       if (!LandingPad->LandingPadLabel) {
    272         // Create a gap.
    273         PreviousIsInvoke = false;
    274       } else {
    275         // This try-range is for an invoke.
    276         CallSiteEntry Site = {
    277           BeginLabel,
    278           LastLabel,
    279           LandingPad,
    280           FirstActions[P.PadIndex]
    281         };
    282 
    283         // Try to merge with the previous call-site. SJLJ doesn't do this
    284         if (PreviousIsInvoke && !IsSJLJ) {
    285           CallSiteEntry &Prev = CallSites.back();
    286           if (Site.LPad == Prev.LPad && Site.Action == Prev.Action) {
    287             // Extend the range of the previous entry.
    288             Prev.EndLabel = Site.EndLabel;
    289             continue;
    290           }
    291         }
    292 
    293         // Otherwise, create a new call-site.
    294         if (!IsSJLJ)
    295           CallSites.push_back(Site);
    296         else {
    297           // SjLj EH must maintain the call sites in the order assigned
    298           // to them by the SjLjPrepare pass.
    299           unsigned SiteNo = MMI->getCallSiteBeginLabel(BeginLabel);
    300           if (CallSites.size() < SiteNo)
    301             CallSites.resize(SiteNo);
    302           CallSites[SiteNo - 1] = Site;
    303         }
    304         PreviousIsInvoke = true;
    305       }
    306     }
    307   }
    308 
    309   // If some instruction between the previous try-range and the end of the
    310   // function may throw, create a call-site entry with no landing pad for the
    311   // region following the try-range.
    312   if (SawPotentiallyThrowing && !IsSJLJ && LastLabel != nullptr) {
    313     CallSiteEntry Site = { LastLabel, nullptr, nullptr, 0 };
    314     CallSites.push_back(Site);
    315   }
    316 }
    317 
    318 /// Emit landing pads and actions.
    319 ///
    320 /// The general organization of the table is complex, but the basic concepts are
    321 /// easy.  First there is a header which describes the location and organization
    322 /// of the three components that follow.
    323 ///
    324 ///  1. The landing pad site information describes the range of code covered by
    325 ///     the try.  In our case it's an accumulation of the ranges covered by the
    326 ///     invokes in the try.  There is also a reference to the landing pad that
    327 ///     handles the exception once processed.  Finally an index into the actions
    328 ///     table.
    329 ///  2. The action table, in our case, is composed of pairs of type IDs and next
    330 ///     action offset.  Starting with the action index from the landing pad
    331 ///     site, each type ID is checked for a match to the current exception.  If
    332 ///     it matches then the exception and type id are passed on to the landing
    333 ///     pad.  Otherwise the next action is looked up.  This chain is terminated
    334 ///     with a next action of zero.  If no type id is found then the frame is
    335 ///     unwound and handling continues.
    336 ///  3. Type ID table contains references to all the C++ typeinfo for all
    337 ///     catches in the function.  This tables is reverse indexed base 1.
    338 void EHStreamer::emitExceptionTable() {
    339   const std::vector<const GlobalValue *> &TypeInfos = MMI->getTypeInfos();
    340   const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
    341   const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
    342 
    343   // Sort the landing pads in order of their type ids.  This is used to fold
    344   // duplicate actions.
    345   SmallVector<const LandingPadInfo *, 64> LandingPads;
    346   LandingPads.reserve(PadInfos.size());
    347 
    348   for (unsigned i = 0, N = PadInfos.size(); i != N; ++i)
    349     LandingPads.push_back(&PadInfos[i]);
    350 
    351   // Order landing pads lexicographically by type id.
    352   std::sort(LandingPads.begin(), LandingPads.end(),
    353             [](const LandingPadInfo *L,
    354                const LandingPadInfo *R) { return L->TypeIds < R->TypeIds; });
    355 
    356   // Compute the actions table and gather the first action index for each
    357   // landing pad site.
    358   SmallVector<ActionEntry, 32> Actions;
    359   SmallVector<unsigned, 64> FirstActions;
    360   unsigned SizeActions =
    361     computeActionsTable(LandingPads, Actions, FirstActions);
    362 
    363   // Compute the call-site table.
    364   SmallVector<CallSiteEntry, 64> CallSites;
    365   computeCallSiteTable(CallSites, LandingPads, FirstActions);
    366 
    367   // Final tallies.
    368 
    369   // Call sites.
    370   bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj;
    371   bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true;
    372 
    373   unsigned CallSiteTableLength;
    374   if (IsSJLJ)
    375     CallSiteTableLength = 0;
    376   else {
    377     unsigned SiteStartSize  = 4; // dwarf::DW_EH_PE_udata4
    378     unsigned SiteLengthSize = 4; // dwarf::DW_EH_PE_udata4
    379     unsigned LandingPadSize = 4; // dwarf::DW_EH_PE_udata4
    380     CallSiteTableLength =
    381       CallSites.size() * (SiteStartSize + SiteLengthSize + LandingPadSize);
    382   }
    383 
    384   for (unsigned i = 0, e = CallSites.size(); i < e; ++i) {
    385     CallSiteTableLength += getULEB128Size(CallSites[i].Action);
    386     if (IsSJLJ)
    387       CallSiteTableLength += getULEB128Size(i);
    388   }
    389 
    390   // Type infos.
    391   MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection();
    392   unsigned TTypeEncoding;
    393   unsigned TypeFormatSize;
    394 
    395   if (!HaveTTData) {
    396     // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say
    397     // that we're omitting that bit.
    398     TTypeEncoding = dwarf::DW_EH_PE_omit;
    399     // dwarf::DW_EH_PE_absptr
    400     TypeFormatSize = Asm->getDataLayout().getPointerSize();
    401   } else {
    402     // Okay, we have actual filters or typeinfos to emit.  As such, we need to
    403     // pick a type encoding for them.  We're about to emit a list of pointers to
    404     // typeinfo objects at the end of the LSDA.  However, unless we're in static
    405     // mode, this reference will require a relocation by the dynamic linker.
    406     //
    407     // Because of this, we have a couple of options:
    408     //
    409     //   1) If we are in -static mode, we can always use an absolute reference
    410     //      from the LSDA, because the static linker will resolve it.
    411     //
    412     //   2) Otherwise, if the LSDA section is writable, we can output the direct
    413     //      reference to the typeinfo and allow the dynamic linker to relocate
    414     //      it.  Since it is in a writable section, the dynamic linker won't
    415     //      have a problem.
    416     //
    417     //   3) Finally, if we're in PIC mode and the LDSA section isn't writable,
    418     //      we need to use some form of indirection.  For example, on Darwin,
    419     //      we can output a statically-relocatable reference to a dyld stub. The
    420     //      offset to the stub is constant, but the contents are in a section
    421     //      that is updated by the dynamic linker.  This is easy enough, but we
    422     //      need to tell the personality function of the unwinder to indirect
    423     //      through the dyld stub.
    424     //
    425     // FIXME: When (3) is actually implemented, we'll have to emit the stubs
    426     // somewhere.  This predicate should be moved to a shared location that is
    427     // in target-independent code.
    428     //
    429     TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding();
    430     TypeFormatSize = Asm->GetSizeOfEncodedValue(TTypeEncoding);
    431   }
    432 
    433   // Begin the exception table.
    434   // Sometimes we want not to emit the data into separate section (e.g. ARM
    435   // EHABI). In this case LSDASection will be NULL.
    436   if (LSDASection)
    437     Asm->OutStreamer->SwitchSection(LSDASection);
    438   Asm->EmitAlignment(2);
    439 
    440   // Emit the LSDA.
    441   MCSymbol *GCCETSym =
    442     Asm->OutContext.getOrCreateSymbol(Twine("GCC_except_table")+
    443                                       Twine(Asm->getFunctionNumber()));
    444   Asm->OutStreamer->EmitLabel(GCCETSym);
    445   Asm->OutStreamer->EmitLabel(Asm->getCurExceptionSym());
    446 
    447   // Emit the LSDA header.
    448   Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart");
    449   Asm->EmitEncodingByte(TTypeEncoding, "@TType");
    450 
    451   // The type infos need to be aligned. GCC does this by inserting padding just
    452   // before the type infos. However, this changes the size of the exception
    453   // table, so you need to take this into account when you output the exception
    454   // table size. However, the size is output using a variable length encoding.
    455   // So by increasing the size by inserting padding, you may increase the number
    456   // of bytes used for writing the size. If it increases, say by one byte, then
    457   // you now need to output one less byte of padding to get the type infos
    458   // aligned. However this decreases the size of the exception table. This
    459   // changes the value you have to output for the exception table size. Due to
    460   // the variable length encoding, the number of bytes used for writing the
    461   // length may decrease. If so, you then have to increase the amount of
    462   // padding. And so on. If you look carefully at the GCC code you will see that
    463   // it indeed does this in a loop, going on and on until the values stabilize.
    464   // We chose another solution: don't output padding inside the table like GCC
    465   // does, instead output it before the table.
    466   unsigned SizeTypes = TypeInfos.size() * TypeFormatSize;
    467   unsigned CallSiteTableLengthSize = getULEB128Size(CallSiteTableLength);
    468   unsigned TTypeBaseOffset =
    469     sizeof(int8_t) +                            // Call site format
    470     CallSiteTableLengthSize +                   // Call site table length size
    471     CallSiteTableLength +                       // Call site table length
    472     SizeActions +                               // Actions size
    473     SizeTypes;
    474   unsigned TTypeBaseOffsetSize = getULEB128Size(TTypeBaseOffset);
    475   unsigned TotalSize =
    476     sizeof(int8_t) +                            // LPStart format
    477     sizeof(int8_t) +                            // TType format
    478     (HaveTTData ? TTypeBaseOffsetSize : 0) +    // TType base offset size
    479     TTypeBaseOffset;                            // TType base offset
    480   unsigned SizeAlign = (4 - TotalSize) & 3;
    481 
    482   if (HaveTTData) {
    483     // Account for any extra padding that will be added to the call site table
    484     // length.
    485     Asm->EmitULEB128(TTypeBaseOffset, "@TType base offset", SizeAlign);
    486     SizeAlign = 0;
    487   }
    488 
    489   bool VerboseAsm = Asm->OutStreamer->isVerboseAsm();
    490 
    491   // SjLj Exception handling
    492   if (IsSJLJ) {
    493     Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
    494 
    495     // Add extra padding if it wasn't added to the TType base offset.
    496     Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign);
    497 
    498     // Emit the landing pad site information.
    499     unsigned idx = 0;
    500     for (SmallVectorImpl<CallSiteEntry>::const_iterator
    501          I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) {
    502       const CallSiteEntry &S = *I;
    503 
    504       // Offset of the landing pad, counted in 16-byte bundles relative to the
    505       // @LPStart address.
    506       if (VerboseAsm) {
    507         Asm->OutStreamer->AddComment(">> Call Site " + Twine(idx) + " <<");
    508         Asm->OutStreamer->AddComment("  On exception at call site "+Twine(idx));
    509       }
    510       Asm->EmitULEB128(idx);
    511 
    512       // Offset of the first associated action record, relative to the start of
    513       // the action table. This value is biased by 1 (1 indicates the start of
    514       // the action table), and 0 indicates that there are no actions.
    515       if (VerboseAsm) {
    516         if (S.Action == 0)
    517           Asm->OutStreamer->AddComment("  Action: cleanup");
    518         else
    519           Asm->OutStreamer->AddComment("  Action: " +
    520                                        Twine((S.Action - 1) / 2 + 1));
    521       }
    522       Asm->EmitULEB128(S.Action);
    523     }
    524   } else {
    525     // Itanium LSDA exception handling
    526 
    527     // The call-site table is a list of all call sites that may throw an
    528     // exception (including C++ 'throw' statements) in the procedure
    529     // fragment. It immediately follows the LSDA header. Each entry indicates,
    530     // for a given call, the first corresponding action record and corresponding
    531     // landing pad.
    532     //
    533     // The table begins with the number of bytes, stored as an LEB128
    534     // compressed, unsigned integer. The records immediately follow the record
    535     // count. They are sorted in increasing call-site address. Each record
    536     // indicates:
    537     //
    538     //   * The position of the call-site.
    539     //   * The position of the landing pad.
    540     //   * The first action record for that call site.
    541     //
    542     // A missing entry in the call-site table indicates that a call is not
    543     // supposed to throw.
    544 
    545     // Emit the landing pad call site table.
    546     Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
    547 
    548     // Add extra padding if it wasn't added to the TType base offset.
    549     Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign);
    550 
    551     unsigned Entry = 0;
    552     for (SmallVectorImpl<CallSiteEntry>::const_iterator
    553          I = CallSites.begin(), E = CallSites.end(); I != E; ++I) {
    554       const CallSiteEntry &S = *I;
    555 
    556       MCSymbol *EHFuncBeginSym = Asm->getFunctionBegin();
    557 
    558       MCSymbol *BeginLabel = S.BeginLabel;
    559       if (!BeginLabel)
    560         BeginLabel = EHFuncBeginSym;
    561       MCSymbol *EndLabel = S.EndLabel;
    562       if (!EndLabel)
    563         EndLabel = Asm->getFunctionEnd();
    564 
    565       // Offset of the call site relative to the previous call site, counted in
    566       // number of 16-byte bundles. The first call site is counted relative to
    567       // the start of the procedure fragment.
    568       if (VerboseAsm)
    569         Asm->OutStreamer->AddComment(">> Call Site " + Twine(++Entry) + " <<");
    570       Asm->EmitLabelDifference(BeginLabel, EHFuncBeginSym, 4);
    571       if (VerboseAsm)
    572         Asm->OutStreamer->AddComment(Twine("  Call between ") +
    573                                      BeginLabel->getName() + " and " +
    574                                      EndLabel->getName());
    575       Asm->EmitLabelDifference(EndLabel, BeginLabel, 4);
    576 
    577       // Offset of the landing pad, counted in 16-byte bundles relative to the
    578       // @LPStart address.
    579       if (!S.LPad) {
    580         if (VerboseAsm)
    581           Asm->OutStreamer->AddComment("    has no landing pad");
    582         Asm->OutStreamer->EmitIntValue(0, 4/*size*/);
    583       } else {
    584         if (VerboseAsm)
    585           Asm->OutStreamer->AddComment(Twine("    jumps to ") +
    586                                        S.LPad->LandingPadLabel->getName());
    587         Asm->EmitLabelDifference(S.LPad->LandingPadLabel, EHFuncBeginSym, 4);
    588       }
    589 
    590       // Offset of the first associated action record, relative to the start of
    591       // the action table. This value is biased by 1 (1 indicates the start of
    592       // the action table), and 0 indicates that there are no actions.
    593       if (VerboseAsm) {
    594         if (S.Action == 0)
    595           Asm->OutStreamer->AddComment("  On action: cleanup");
    596         else
    597           Asm->OutStreamer->AddComment("  On action: " +
    598                                        Twine((S.Action - 1) / 2 + 1));
    599       }
    600       Asm->EmitULEB128(S.Action);
    601     }
    602   }
    603 
    604   // Emit the Action Table.
    605   int Entry = 0;
    606   for (SmallVectorImpl<ActionEntry>::const_iterator
    607          I = Actions.begin(), E = Actions.end(); I != E; ++I) {
    608     const ActionEntry &Action = *I;
    609 
    610     if (VerboseAsm) {
    611       // Emit comments that decode the action table.
    612       Asm->OutStreamer->AddComment(">> Action Record " + Twine(++Entry) + " <<");
    613     }
    614 
    615     // Type Filter
    616     //
    617     //   Used by the runtime to match the type of the thrown exception to the
    618     //   type of the catch clauses or the types in the exception specification.
    619     if (VerboseAsm) {
    620       if (Action.ValueForTypeID > 0)
    621         Asm->OutStreamer->AddComment("  Catch TypeInfo " +
    622                                      Twine(Action.ValueForTypeID));
    623       else if (Action.ValueForTypeID < 0)
    624         Asm->OutStreamer->AddComment("  Filter TypeInfo " +
    625                                      Twine(Action.ValueForTypeID));
    626       else
    627         Asm->OutStreamer->AddComment("  Cleanup");
    628     }
    629     Asm->EmitSLEB128(Action.ValueForTypeID);
    630 
    631     // Action Record
    632     //
    633     //   Self-relative signed displacement in bytes of the next action record,
    634     //   or 0 if there is no next action record.
    635     if (VerboseAsm) {
    636       if (Action.NextAction == 0) {
    637         Asm->OutStreamer->AddComment("  No further actions");
    638       } else {
    639         unsigned NextAction = Entry + (Action.NextAction + 1) / 2;
    640         Asm->OutStreamer->AddComment("  Continue to action "+Twine(NextAction));
    641       }
    642     }
    643     Asm->EmitSLEB128(Action.NextAction);
    644   }
    645 
    646   emitTypeInfos(TTypeEncoding);
    647 
    648   Asm->EmitAlignment(2);
    649 }
    650 
    651 void EHStreamer::emitTypeInfos(unsigned TTypeEncoding) {
    652   const std::vector<const GlobalValue *> &TypeInfos = MMI->getTypeInfos();
    653   const std::vector<unsigned> &FilterIds = MMI->getFilterIds();
    654 
    655   bool VerboseAsm = Asm->OutStreamer->isVerboseAsm();
    656 
    657   int Entry = 0;
    658   // Emit the Catch TypeInfos.
    659   if (VerboseAsm && !TypeInfos.empty()) {
    660     Asm->OutStreamer->AddComment(">> Catch TypeInfos <<");
    661     Asm->OutStreamer->AddBlankLine();
    662     Entry = TypeInfos.size();
    663   }
    664 
    665   for (const GlobalValue *GV : make_range(TypeInfos.rbegin(),
    666                                           TypeInfos.rend())) {
    667     if (VerboseAsm)
    668       Asm->OutStreamer->AddComment("TypeInfo " + Twine(Entry--));
    669     Asm->EmitTTypeReference(GV, TTypeEncoding);
    670   }
    671 
    672   // Emit the Exception Specifications.
    673   if (VerboseAsm && !FilterIds.empty()) {
    674     Asm->OutStreamer->AddComment(">> Filter TypeInfos <<");
    675     Asm->OutStreamer->AddBlankLine();
    676     Entry = 0;
    677   }
    678   for (std::vector<unsigned>::const_iterator
    679          I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) {
    680     unsigned TypeID = *I;
    681     if (VerboseAsm) {
    682       --Entry;
    683       if (isFilterEHSelector(TypeID))
    684         Asm->OutStreamer->AddComment("FilterInfo " + Twine(Entry));
    685     }
    686 
    687     Asm->EmitULEB128(TypeID);
    688   }
    689 }
    690