LCOV - code coverage report
Current view: top level - lib/CodeGen/AsmPrinter - EHStreamer.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 273 279 97.8 %
Date: 2017-09-14 15:23:50 Functions: 8 10 80.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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       14801 : EHStreamer::EHStreamer(AsmPrinter *A) : Asm(A), MMI(Asm->MMI) {}
      29             : 
      30       14713 : EHStreamer::~EHStreamer() {}
      31             : 
      32             : /// How many leading type ids two landing pads have in common.
      33           0 : unsigned EHStreamer::sharedTypeIDs(const LandingPadInfo *L,
      34             :                                    const LandingPadInfo *R) {
      35       19268 :   const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds;
      36       57804 :   unsigned LSize = LIds.size(), RSize = RIds.size();
      37       19268 :   unsigned MinSize = LSize < RSize ? LSize : RSize;
      38       19268 :   unsigned Count = 0;
      39             : 
      40       29544 :   for (; Count != MinSize; ++Count)
      41       15414 :     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        2471 : 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        2471 :   const std::vector<unsigned> &FilterIds = Asm->MF->getFilterIds();
      78        4942 :   SmallVector<int, 16> FilterOffsets;
      79        2471 :   FilterOffsets.reserve(FilterIds.size());
      80        2471 :   int Offset = -1;
      81             : 
      82             :   for (std::vector<unsigned>::const_iterator
      83        7430 :          I = FilterIds.begin(), E = FilterIds.end(); I != E; ++I) {
      84          17 :     FilterOffsets.push_back(Offset);
      85          17 :     Offset -= getULEB128Size(*I);
      86             :   }
      87             : 
      88        4942 :   FirstActions.reserve(LandingPads.size());
      89             : 
      90        2471 :   int FirstAction = 0;
      91        2471 :   unsigned SizeActions = 0;
      92        2471 :   const LandingPadInfo *PrevLPI = nullptr;
      93             : 
      94       21734 :   for (SmallVectorImpl<const LandingPadInfo *>::const_iterator
      95        7413 :          I = LandingPads.begin(), E = LandingPads.end(); I != E; ++I) {
      96       21734 :     const LandingPadInfo *LPI = *I;
      97       21734 :     const std::vector<int> &TypeIds = LPI->TypeIds;
      98       43468 :     unsigned NumShared = PrevLPI ? sharedTypeIDs(LPI, PrevLPI) : 0;
      99       21734 :     unsigned SizeSiteActions = 0;
     100             : 
     101       43468 :     if (NumShared < TypeIds.size()) {
     102         946 :       unsigned SizeAction = 0;
     103         946 :       unsigned PrevAction = (unsigned)-1;
     104             : 
     105         946 :       if (NumShared) {
     106          60 :         unsigned SizePrevIds = PrevLPI->TypeIds.size();
     107             :         assert(Actions.size());
     108          60 :         PrevAction = Actions.size() - 1;
     109          90 :         SizeAction = getSLEB128Size(Actions[PrevAction].NextAction) +
     110          60 :                      getSLEB128Size(Actions[PrevAction].ValueForTypeID);
     111             : 
     112          30 :         for (unsigned j = NumShared; j != SizePrevIds; ++j) {
     113             :           assert(PrevAction != (unsigned)-1 && "PrevAction is invalid!");
     114           0 :           SizeAction -= getSLEB128Size(Actions[PrevAction].ValueForTypeID);
     115           0 :           SizeAction += -Actions[PrevAction].NextAction;
     116           0 :           PrevAction = Actions[PrevAction].Previous;
     117             :         }
     118             :       }
     119             : 
     120             :       // Compute the actions.
     121        2871 :       for (unsigned J = NumShared, M = TypeIds.size(); J != M; ++J) {
     122        1958 :         int TypeID = TypeIds[J];
     123             :         assert(-1 - TypeID < (int)FilterOffsets.size() && "Unknown filter id!");
     124             :         int ValueForTypeID =
     125         993 :             isFilterEHSelector(TypeID) ? FilterOffsets[-1 - TypeID] : TypeID;
     126         979 :         unsigned SizeTypeID = getSLEB128Size(ValueForTypeID);
     127             : 
     128         979 :         int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0;
     129         979 :         SizeAction = SizeTypeID + getSLEB128Size(NextAction);
     130         979 :         SizeSiteActions += SizeAction;
     131             : 
     132         979 :         ActionEntry Action = { ValueForTypeID, NextAction, PrevAction };
     133         979 :         Actions.push_back(Action);
     134        1958 :         PrevAction = Actions.size() - 1;
     135             :       }
     136             : 
     137             :       // Record the first action of the landing pad site.
     138         946 :       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       21734 :     FirstActions.push_back(FirstAction);
     147             : 
     148             :     // Compute this sites contribution to size.
     149       21734 :     SizeActions += SizeSiteActions;
     150             : 
     151       21734 :     PrevLPI = LPI;
     152             :   }
     153             : 
     154        4942 :   return SizeActions;
     155             : }
     156             : 
     157             : /// Return `true' if this is a call to a function marked `nounwind'. Return
     158             : /// `false' otherwise.
     159      105635 : bool EHStreamer::callToNoUnwindFunction(const MachineInstr *MI) {
     160             :   assert(MI->isCall() && "This should be a call instruction!");
     161             : 
     162      105635 :   bool MarkedNoUnwind = false;
     163      105635 :   bool SawFunc = false;
     164             : 
     165      744152 :   for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
     166     1277034 :     const MachineOperand &MO = MI->getOperand(I);
     167             : 
     168      638517 :     if (!MO.isGlobal()) continue;
     169             : 
     170      209292 :     const Function *F = dyn_cast<Function>(MO.getGlobal());
     171           0 :     if (!F) continue;
     172             : 
     173      104646 :     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      104646 :     MarkedNoUnwind = F->doesNotThrow();
     185      104646 :     SawFunc = true;
     186             :   }
     187             : 
     188      105635 :   return MarkedNoUnwind;
     189             : }
     190             : 
     191        2471 : 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       26676 :   for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) {
     198       43468 :     const LandingPadInfo *LandingPad = LandingPads[i];
     199       69943 :     for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) {
     200       52950 :       MCSymbol *BeginLabel = LandingPad->BeginLabels[j];
     201             :       assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!");
     202       26475 :       PadRange P = { i, j };
     203       26475 :       PadMap[BeginLabel] = P;
     204             :     }
     205             :   }
     206        2471 : }
     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        2471 : void EHStreamer::
     215             : computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites,
     216             :                      const SmallVectorImpl<const LandingPadInfo *> &LandingPads,
     217             :                      const SmallVectorImpl<unsigned> &FirstActions) {
     218        4942 :   RangeMapType PadMap;
     219        2471 :   computePadMap(LandingPads, PadMap);
     220             : 
     221             :   // The end label of the previous invoke or nounwind try-range.
     222        2471 :   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        2471 :   bool SawPotentiallyThrowing = false;
     227             : 
     228             :   // Whether the last CallSite entry was for an invoke.
     229        2471 :   bool PreviousIsInvoke = false;
     230             : 
     231        2471 :   bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj;
     232             : 
     233             :   // Visit all instructions in order of address.
     234      104944 :   for (const auto &MBB : *Asm->MF) {
     235     2517046 :     for (const auto &MI : MBB) {
     236     2052236 :       if (!MI.isEHLabel()) {
     237      988775 :         if (MI.isCall())
     238      105618 :           SawPotentiallyThrowing |= !callToNoUnwindFunction(&MI);
     239      988775 :         continue;
     240             :       }
     241             : 
     242             :       // End of the previous try-range?
     243       74686 :       MCSymbol *BeginLabel = MI.getOperand(0).getMCSymbol();
     244       74686 :       if (BeginLabel == LastLabel)
     245       26475 :         SawPotentiallyThrowing = false;
     246             : 
     247             :       // Beginning of a new try-range?
     248      149372 :       RangeMapType::const_iterator L = PadMap.find(BeginLabel);
     249      149372 :       if (L == PadMap.end())
     250             :         // Nope, it was just some random label.
     251       48211 :         continue;
     252             : 
     253       26475 :       const PadRange &P = L->second;
     254       52950 :       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       26475 :       if (SawPotentiallyThrowing && Asm->MAI->usesCFIForEH()) {
     263        3593 :         CallSiteEntry Site = { LastLabel, BeginLabel, nullptr, 0 };
     264        3593 :         CallSites.push_back(Site);
     265        3593 :         PreviousIsInvoke = false;
     266             :       }
     267             : 
     268       52950 :       LastLabel = LandingPad->EndLabels[P.RangeIndex];
     269             :       assert(BeginLabel && LastLabel && "Invalid landing pad!");
     270             : 
     271       26475 :       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       52950 :           FirstActions[P.PadIndex]
     281       52950 :         };
     282             : 
     283             :         // Try to merge with the previous call-site. SJLJ doesn't do this
     284       26475 :         if (PreviousIsInvoke && !IsSJLJ) {
     285       44198 :           CallSiteEntry &Prev = CallSites.back();
     286       26230 :           if (Site.LPad == Prev.LPad && Site.Action == Prev.Action) {
     287             :             // Extend the range of the previous entry.
     288        4131 :             Prev.EndLabel = Site.EndLabel;
     289        4131 :             continue;
     290             :           }
     291             :         }
     292             : 
     293             :         // Otherwise, create a new call-site.
     294       22344 :         if (!IsSJLJ)
     295       22179 :           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         330 :           unsigned SiteNo = Asm->MF->getCallSiteBeginLabel(BeginLabel);
     300         330 :           if (CallSites.size() < SiteNo)
     301         130 :             CallSites.resize(SiteNo);
     302         330 :           CallSites[SiteNo - 1] = Site;
     303             :         }
     304       22344 :         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        2471 :   if (SawPotentiallyThrowing && !IsSJLJ) {
     313        2228 :     CallSiteEntry Site = { LastLabel, nullptr, nullptr, 0 };
     314        2228 :     CallSites.push_back(Site);
     315             :   }
     316        2471 : }
     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        2471 : void EHStreamer::emitExceptionTable() {
     339        2471 :   const MachineFunction *MF = Asm->MF;
     340        2471 :   const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos();
     341        2471 :   const std::vector<unsigned> &FilterIds = MF->getFilterIds();
     342        2471 :   const std::vector<LandingPadInfo> &PadInfos = MF->getLandingPads();
     343             : 
     344             :   // Sort the landing pads in order of their type ids.  This is used to fold
     345             :   // duplicate actions.
     346        4942 :   SmallVector<const LandingPadInfo *, 64> LandingPads;
     347        2471 :   LandingPads.reserve(PadInfos.size());
     348             : 
     349       26676 :   for (unsigned i = 0, N = PadInfos.size(); i != N; ++i)
     350       43468 :     LandingPads.push_back(&PadInfos[i]);
     351             : 
     352             :   // Order landing pads lexicographically by type id.
     353        7413 :   std::sort(LandingPads.begin(), LandingPads.end(),
     354             :             [](const LandingPadInfo *L,
     355       80201 :                const LandingPadInfo *R) { return L->TypeIds < R->TypeIds; });
     356             : 
     357             :   // Compute the actions table and gather the first action index for each
     358             :   // landing pad site.
     359        4942 :   SmallVector<ActionEntry, 32> Actions;
     360        4942 :   SmallVector<unsigned, 64> FirstActions;
     361             :   unsigned SizeActions =
     362        2471 :     computeActionsTable(LandingPads, Actions, FirstActions);
     363             : 
     364             :   // Compute the call-site table.
     365        4942 :   SmallVector<CallSiteEntry, 64> CallSites;
     366        2471 :   computeCallSiteTable(CallSites, LandingPads, FirstActions);
     367             : 
     368             :   // Final tallies.
     369             : 
     370             :   // Call sites.
     371        2471 :   bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj;
     372        2510 :   bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true;
     373             : 
     374             :   unsigned CallSiteTableLength;
     375        2471 :   if (IsSJLJ)
     376             :     CallSiteTableLength = 0;
     377             :   else {
     378        2442 :     unsigned SiteStartSize  = 4; // dwarf::DW_EH_PE_udata4
     379        2442 :     unsigned SiteLengthSize = 4; // dwarf::DW_EH_PE_udata4
     380        2442 :     unsigned LandingPadSize = 4; // dwarf::DW_EH_PE_udata4
     381        2442 :     CallSiteTableLength =
     382        2442 :       CallSites.size() * (SiteStartSize + SiteLengthSize + LandingPadSize);
     383             :   }
     384             : 
     385       33107 :   for (unsigned i = 0, e = CallSites.size(); i < e; ++i) {
     386       56330 :     CallSiteTableLength += getULEB128Size(CallSites[i].Action);
     387       28165 :     if (IsSJLJ)
     388         165 :       CallSiteTableLength += getULEB128Size(i);
     389             :   }
     390             : 
     391             :   // Type infos.
     392        2471 :   MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection();
     393             :   unsigned TTypeEncoding;
     394             :   unsigned TypeFormatSize;
     395             : 
     396        2471 :   if (!HaveTTData) {
     397             :     // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say
     398             :     // that we're omitting that bit.
     399          10 :     TTypeEncoding = dwarf::DW_EH_PE_omit;
     400             :     // dwarf::DW_EH_PE_absptr
     401          10 :     TypeFormatSize = Asm->getDataLayout().getPointerSize();
     402             :   } else {
     403             :     // Okay, we have actual filters or typeinfos to emit.  As such, we need to
     404             :     // pick a type encoding for them.  We're about to emit a list of pointers to
     405             :     // typeinfo objects at the end of the LSDA.  However, unless we're in static
     406             :     // mode, this reference will require a relocation by the dynamic linker.
     407             :     //
     408             :     // Because of this, we have a couple of options:
     409             :     //
     410             :     //   1) If we are in -static mode, we can always use an absolute reference
     411             :     //      from the LSDA, because the static linker will resolve it.
     412             :     //
     413             :     //   2) Otherwise, if the LSDA section is writable, we can output the direct
     414             :     //      reference to the typeinfo and allow the dynamic linker to relocate
     415             :     //      it.  Since it is in a writable section, the dynamic linker won't
     416             :     //      have a problem.
     417             :     //
     418             :     //   3) Finally, if we're in PIC mode and the LDSA section isn't writable,
     419             :     //      we need to use some form of indirection.  For example, on Darwin,
     420             :     //      we can output a statically-relocatable reference to a dyld stub. The
     421             :     //      offset to the stub is constant, but the contents are in a section
     422             :     //      that is updated by the dynamic linker.  This is easy enough, but we
     423             :     //      need to tell the personality function of the unwinder to indirect
     424             :     //      through the dyld stub.
     425             :     //
     426             :     // FIXME: When (3) is actually implemented, we'll have to emit the stubs
     427             :     // somewhere.  This predicate should be moved to a shared location that is
     428             :     // in target-independent code.
     429             :     //
     430        2461 :     TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding();
     431        2461 :     TypeFormatSize = Asm->GetSizeOfEncodedValue(TTypeEncoding);
     432             :   }
     433             : 
     434             :   // Begin the exception table.
     435             :   // Sometimes we want not to emit the data into separate section (e.g. ARM
     436             :   // EHABI). In this case LSDASection will be NULL.
     437        2471 :   if (LSDASection)
     438        4848 :     Asm->OutStreamer->SwitchSection(LSDASection);
     439        2471 :   Asm->EmitAlignment(2);
     440             : 
     441             :   // Emit the LSDA.
     442             :   MCSymbol *GCCETSym =
     443        9884 :     Asm->OutContext.getOrCreateSymbol(Twine("GCC_except_table")+
     444        9884 :                                       Twine(Asm->getFunctionNumber()));
     445        4942 :   Asm->OutStreamer->EmitLabel(GCCETSym);
     446        4942 :   Asm->OutStreamer->EmitLabel(Asm->getCurExceptionSym());
     447             : 
     448             :   // Emit the LSDA header.
     449        2471 :   Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart");
     450        2471 :   Asm->EmitEncodingByte(TTypeEncoding, "@TType");
     451             : 
     452             :   // The type infos need to be aligned. GCC does this by inserting padding just
     453             :   // before the type infos. However, this changes the size of the exception
     454             :   // table, so you need to take this into account when you output the exception
     455             :   // table size. However, the size is output using a variable length encoding.
     456             :   // So by increasing the size by inserting padding, you may increase the number
     457             :   // of bytes used for writing the size. If it increases, say by one byte, then
     458             :   // you now need to output one less byte of padding to get the type infos
     459             :   // aligned. However this decreases the size of the exception table. This
     460             :   // changes the value you have to output for the exception table size. Due to
     461             :   // the variable length encoding, the number of bytes used for writing the
     462             :   // length may decrease. If so, you then have to increase the amount of
     463             :   // padding. And so on. If you look carefully at the GCC code you will see that
     464             :   // it indeed does this in a loop, going on and on until the values stabilize.
     465             :   // We chose another solution: don't output padding inside the table like GCC
     466             :   // does, instead output it before the table.
     467        2471 :   unsigned SizeTypes = TypeInfos.size() * TypeFormatSize;
     468        2471 :   unsigned CallSiteTableLengthSize = getULEB128Size(CallSiteTableLength);
     469        2471 :   unsigned TTypeBaseOffset =
     470             :     sizeof(int8_t) +                            // Call site format
     471        2471 :     CallSiteTableLengthSize +                   // Call site table length size
     472        2471 :     CallSiteTableLength +                       // Call site table length
     473        2471 :     SizeActions +                               // Actions size
     474             :     SizeTypes;
     475        2471 :   unsigned TTypeBaseOffsetSize = getULEB128Size(TTypeBaseOffset);
     476        2471 :   unsigned TotalSize =
     477             :     sizeof(int8_t) +                            // LPStart format
     478             :     sizeof(int8_t) +                            // TType format
     479        2471 :     (HaveTTData ? TTypeBaseOffsetSize : 0) +    // TType base offset size
     480             :     TTypeBaseOffset;                            // TType base offset
     481        2471 :   unsigned SizeAlign = (4 - TotalSize) & 3;
     482             : 
     483        2471 :   if (HaveTTData) {
     484             :     // Account for any extra padding that will be added to the call site table
     485             :     // length.
     486        2461 :     Asm->EmitULEB128(TTypeBaseOffset, "@TType base offset", SizeAlign);
     487        2461 :     SizeAlign = 0;
     488             :   }
     489             : 
     490        4942 :   bool VerboseAsm = Asm->OutStreamer->isVerboseAsm();
     491             : 
     492             :   // SjLj Exception handling
     493        2471 :   if (IsSJLJ) {
     494          29 :     Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
     495             : 
     496             :     // Add extra padding if it wasn't added to the TType base offset.
     497          29 :     Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign);
     498             : 
     499             :     // Emit the landing pad site information.
     500          29 :     unsigned idx = 0;
     501         165 :     for (SmallVectorImpl<CallSiteEntry>::const_iterator
     502          58 :          I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) {
     503         165 :       const CallSiteEntry &S = *I;
     504             : 
     505             :       // Offset of the landing pad, counted in 16-byte bundles relative to the
     506             :       // @LPStart address.
     507         165 :       if (VerboseAsm) {
     508         259 :         Asm->OutStreamer->AddComment(">> Call Site " + Twine(idx) + " <<");
     509         185 :         Asm->OutStreamer->AddComment("  On exception at call site "+Twine(idx));
     510             :       }
     511         165 :       Asm->EmitULEB128(idx);
     512             : 
     513             :       // Offset of the first associated action record, relative to the start of
     514             :       // the action table. This value is biased by 1 (1 indicates the start of
     515             :       // the action table), and 0 indicates that there are no actions.
     516         165 :       if (VerboseAsm) {
     517          37 :         if (S.Action == 0)
     518          45 :           Asm->OutStreamer->AddComment("  Action: cleanup");
     519             :         else
     520          66 :           Asm->OutStreamer->AddComment("  Action: " +
     521          88 :                                        Twine((S.Action - 1) / 2 + 1));
     522             :       }
     523         165 :       Asm->EmitULEB128(S.Action);
     524             :     }
     525             :   } else {
     526             :     // Itanium LSDA exception handling
     527             : 
     528             :     // The call-site table is a list of all call sites that may throw an
     529             :     // exception (including C++ 'throw' statements) in the procedure
     530             :     // fragment. It immediately follows the LSDA header. Each entry indicates,
     531             :     // for a given call, the first corresponding action record and corresponding
     532             :     // landing pad.
     533             :     //
     534             :     // The table begins with the number of bytes, stored as an LEB128
     535             :     // compressed, unsigned integer. The records immediately follow the record
     536             :     // count. They are sorted in increasing call-site address. Each record
     537             :     // indicates:
     538             :     //
     539             :     //   * The position of the call-site.
     540             :     //   * The position of the landing pad.
     541             :     //   * The first action record for that call site.
     542             :     //
     543             :     // A missing entry in the call-site table indicates that a call is not
     544             :     // supposed to throw.
     545             : 
     546             :     // Emit the landing pad call site table.
     547        2442 :     Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site");
     548             : 
     549             :     // Add extra padding if it wasn't added to the TType base offset.
     550        2442 :     Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign);
     551             : 
     552        2442 :     unsigned Entry = 0;
     553       28000 :     for (SmallVectorImpl<CallSiteEntry>::const_iterator
     554        4884 :          I = CallSites.begin(), E = CallSites.end(); I != E; ++I) {
     555       28000 :       const CallSiteEntry &S = *I;
     556             : 
     557       28000 :       MCSymbol *EHFuncBeginSym = Asm->getFunctionBegin();
     558             : 
     559       28000 :       MCSymbol *BeginLabel = S.BeginLabel;
     560       28000 :       if (!BeginLabel)
     561        1823 :         BeginLabel = EHFuncBeginSym;
     562       28000 :       MCSymbol *EndLabel = S.EndLabel;
     563       28000 :       if (!EndLabel)
     564        2228 :         EndLabel = Asm->getFunctionEnd();
     565             : 
     566             :       // Offset of the call site relative to the previous call site, counted in
     567             :       // number of 16-byte bundles. The first call site is counted relative to
     568             :       // the start of the procedure fragment.
     569       28000 :       if (VerboseAsm)
     570        3584 :         Asm->OutStreamer->AddComment(">> Call Site " + Twine(++Entry) + " <<");
     571       28000 :       Asm->EmitLabelDifference(BeginLabel, EHFuncBeginSym, 4);
     572       28000 :       if (VerboseAsm)
     573        3072 :         Asm->OutStreamer->AddComment(Twine("  Call between ") +
     574        3584 :                                      BeginLabel->getName() + " and " +
     575        2048 :                                      EndLabel->getName());
     576       28000 :       Asm->EmitLabelDifference(EndLabel, BeginLabel, 4);
     577             : 
     578             :       // Offset of the landing pad, counted in 16-byte bundles relative to the
     579             :       // @LPStart address.
     580       28000 :       if (!S.LPad) {
     581        5821 :         if (VerboseAsm)
     582         543 :           Asm->OutStreamer->AddComment("    has no landing pad");
     583       11642 :         Asm->OutStreamer->EmitIntValue(0, 4/*size*/);
     584             :       } else {
     585       22179 :         if (VerboseAsm)
     586        1324 :           Asm->OutStreamer->AddComment(Twine("    jumps to ") +
     587        1324 :                                        S.LPad->LandingPadLabel->getName());
     588       22179 :         Asm->EmitLabelDifference(S.LPad->LandingPadLabel, EHFuncBeginSym, 4);
     589             :       }
     590             : 
     591             :       // Offset of the first associated action record, relative to the start of
     592             :       // the action table. This value is biased by 1 (1 indicates the start of
     593             :       // the action table), and 0 indicates that there are no actions.
     594       28000 :       if (VerboseAsm) {
     595         512 :         if (S.Action == 0)
     596        1011 :           Asm->OutStreamer->AddComment("  On action: cleanup");
     597             :         else
     598         525 :           Asm->OutStreamer->AddComment("  On action: " +
     599         700 :                                        Twine((S.Action - 1) / 2 + 1));
     600             :       }
     601       28000 :       Asm->EmitULEB128(S.Action);
     602             :     }
     603             :   }
     604             : 
     605             :   // Emit the Action Table.
     606        2471 :   int Entry = 0;
     607         979 :   for (SmallVectorImpl<ActionEntry>::const_iterator
     608        4942 :          I = Actions.begin(), E = Actions.end(); I != E; ++I) {
     609         979 :     const ActionEntry &Action = *I;
     610             : 
     611         979 :     if (VerboseAsm) {
     612             :       // Emit comments that decode the action table.
     613        1253 :       Asm->OutStreamer->AddComment(">> Action Record " + Twine(++Entry) + " <<");
     614             :     }
     615             : 
     616             :     // Type Filter
     617             :     //
     618             :     //   Used by the runtime to match the type of the thrown exception to the
     619             :     //   type of the catch clauses or the types in the exception specification.
     620         979 :     if (VerboseAsm) {
     621         179 :       if (Action.ValueForTypeID > 0)
     622         501 :         Asm->OutStreamer->AddComment("  Catch TypeInfo " +
     623         668 :                                      Twine(Action.ValueForTypeID));
     624          12 :       else if (Action.ValueForTypeID < 0)
     625           6 :         Asm->OutStreamer->AddComment("  Filter TypeInfo " +
     626           8 :                                      Twine(Action.ValueForTypeID));
     627             :       else
     628          30 :         Asm->OutStreamer->AddComment("  Cleanup");
     629             :     }
     630         979 :     Asm->EmitSLEB128(Action.ValueForTypeID);
     631             : 
     632             :     // Action Record
     633             :     //
     634             :     //   Self-relative signed displacement in bytes of the next action record,
     635             :     //   or 0 if there is no next action record.
     636         979 :     if (VerboseAsm) {
     637         179 :       if (Action.NextAction == 0) {
     638         456 :         Asm->OutStreamer->AddComment("  No further actions");
     639             :       } else {
     640          27 :         unsigned NextAction = Entry + (Action.NextAction + 1) / 2;
     641         135 :         Asm->OutStreamer->AddComment("  Continue to action "+Twine(NextAction));
     642             :       }
     643             :     }
     644         979 :     Asm->EmitSLEB128(Action.NextAction);
     645             :   }
     646             : 
     647        2471 :   emitTypeInfos(TTypeEncoding);
     648             : 
     649        2471 :   Asm->EmitAlignment(2);
     650        2471 : }
     651             : 
     652        2441 : void EHStreamer::emitTypeInfos(unsigned TTypeEncoding) {
     653        2441 :   const MachineFunction *MF = Asm->MF;
     654        2441 :   const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos();
     655        2441 :   const std::vector<unsigned> &FilterIds = MF->getFilterIds();
     656             : 
     657        4882 :   bool VerboseAsm = Asm->OutStreamer->isVerboseAsm();
     658             : 
     659        2441 :   int Entry = 0;
     660             :   // Emit the Catch TypeInfos.
     661        2651 :   if (VerboseAsm && !TypeInfos.empty()) {
     662         369 :     Asm->OutStreamer->AddComment(">> Catch TypeInfos <<");
     663         246 :     Asm->OutStreamer->AddBlankLine();
     664         123 :     Entry = TypeInfos.size();
     665             :   }
     666             : 
     667        2441 :   for (const GlobalValue *GV : make_range(TypeInfos.rbegin(),
     668       11620 :                                           TypeInfos.rend())) {
     669         928 :     if (VerboseAsm)
     670         705 :       Asm->OutStreamer->AddComment("TypeInfo " + Twine(Entry--));
     671         928 :     Asm->EmitTTypeReference(GV, TTypeEncoding);
     672             :   }
     673             : 
     674             :   // Emit the Exception Specifications.
     675        2651 :   if (VerboseAsm && !FilterIds.empty()) {
     676           6 :     Asm->OutStreamer->AddComment(">> Filter TypeInfos <<");
     677           4 :     Asm->OutStreamer->AddBlankLine();
     678           2 :     Entry = 0;
     679             :   }
     680             :   for (std::vector<unsigned>::const_iterator
     681        7338 :          I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) {
     682          15 :     unsigned TypeID = *I;
     683          15 :     if (VerboseAsm) {
     684           3 :       --Entry;
     685           3 :       if (isFilterEHSelector(TypeID))
     686           0 :         Asm->OutStreamer->AddComment("FilterInfo " + Twine(Entry));
     687             :     }
     688             : 
     689          15 :     Asm->EmitULEB128(TypeID);
     690             :   }
     691        2441 : }

Generated by: LCOV version 1.13