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