1193323Sed//===-- CodeGen/AsmPrinter/DwarfException.cpp - Dwarf Exception Impl ------===// 2193323Sed// 3193323Sed// The LLVM Compiler Infrastructure 4193323Sed// 5193323Sed// This file is distributed under the University of Illinois Open Source 6193323Sed// License. See LICENSE.TXT for details. 7193323Sed// 8193323Sed//===----------------------------------------------------------------------===// 9193323Sed// 10198090Srdivacky// This file contains support for writing DWARF exception info into asm files. 11193323Sed// 12193323Sed//===----------------------------------------------------------------------===// 13193323Sed 14193323Sed#include "DwarfException.h" 15252723Sdim#include "llvm/ADT/SmallString.h" 16252723Sdim#include "llvm/ADT/StringExtras.h" 17252723Sdim#include "llvm/ADT/Twine.h" 18206274Srdivacky#include "llvm/CodeGen/AsmPrinter.h" 19193323Sed#include "llvm/CodeGen/MachineFrameInfo.h" 20198090Srdivacky#include "llvm/CodeGen/MachineFunction.h" 21252723Sdim#include "llvm/CodeGen/MachineModuleInfo.h" 22252723Sdim#include "llvm/IR/DataLayout.h" 23252723Sdim#include "llvm/IR/Module.h" 24198090Srdivacky#include "llvm/MC/MCAsmInfo.h" 25198090Srdivacky#include "llvm/MC/MCContext.h" 26198090Srdivacky#include "llvm/MC/MCExpr.h" 27198090Srdivacky#include "llvm/MC/MCSection.h" 28198090Srdivacky#include "llvm/MC/MCStreamer.h" 29202878Srdivacky#include "llvm/MC/MCSymbol.h" 30252723Sdim#include "llvm/Support/Dwarf.h" 31252723Sdim#include "llvm/Support/ErrorHandling.h" 32252723Sdim#include "llvm/Support/FormattedStream.h" 33202878Srdivacky#include "llvm/Target/Mangler.h" 34218893Sdim#include "llvm/Target/TargetFrameLowering.h" 35198090Srdivacky#include "llvm/Target/TargetLoweringObjectFile.h" 36198090Srdivacky#include "llvm/Target/TargetOptions.h" 37198090Srdivacky#include "llvm/Target/TargetRegisterInfo.h" 38193323Sedusing namespace llvm; 39193323Sed 40206274SrdivackyDwarfException::DwarfException(AsmPrinter *A) 41218893Sdim : Asm(A), MMI(Asm->MMI) {} 42193323Sed 43207618SrdivackyDwarfException::~DwarfException() {} 44193323Sed 45193323Sed/// SharedTypeIds - How many leading type ids two landing pads have in common. 46193323Sedunsigned DwarfException::SharedTypeIds(const LandingPadInfo *L, 47193323Sed const LandingPadInfo *R) { 48193323Sed const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds; 49193323Sed unsigned LSize = LIds.size(), RSize = RIds.size(); 50193323Sed unsigned MinSize = LSize < RSize ? LSize : RSize; 51193323Sed unsigned Count = 0; 52193323Sed 53193323Sed for (; Count != MinSize; ++Count) 54193323Sed if (LIds[Count] != RIds[Count]) 55193323Sed return Count; 56193323Sed 57193323Sed return Count; 58193323Sed} 59193323Sed 60193323Sed/// PadLT - Order landing pads lexicographically by type id. 61193323Sedbool DwarfException::PadLT(const LandingPadInfo *L, const LandingPadInfo *R) { 62193323Sed const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds; 63193323Sed unsigned LSize = LIds.size(), RSize = RIds.size(); 64193323Sed unsigned MinSize = LSize < RSize ? LSize : RSize; 65193323Sed 66193323Sed for (unsigned i = 0; i != MinSize; ++i) 67193323Sed if (LIds[i] != RIds[i]) 68193323Sed return LIds[i] < RIds[i]; 69193323Sed 70193323Sed return LSize < RSize; 71193323Sed} 72193323Sed 73198090Srdivacky/// ComputeActionsTable - Compute the actions table and gather the first action 74198090Srdivacky/// index for each landing pad site. 75198090Srdivackyunsigned DwarfException:: 76198090SrdivackyComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, 77198090Srdivacky SmallVectorImpl<ActionEntry> &Actions, 78198090Srdivacky SmallVectorImpl<unsigned> &FirstActions) { 79193323Sed 80198090Srdivacky // The action table follows the call-site table in the LSDA. The individual 81198090Srdivacky // records are of two types: 82198090Srdivacky // 83198090Srdivacky // * Catch clause 84198090Srdivacky // * Exception specification 85198090Srdivacky // 86198090Srdivacky // The two record kinds have the same format, with only small differences. 87198090Srdivacky // They are distinguished by the "switch value" field: Catch clauses 88198090Srdivacky // (TypeInfos) have strictly positive switch values, and exception 89198090Srdivacky // specifications (FilterIds) have strictly negative switch values. Value 0 90198090Srdivacky // indicates a catch-all clause. 91198090Srdivacky // 92198090Srdivacky // Negative type IDs index into FilterIds. Positive type IDs index into 93198090Srdivacky // TypeInfos. The value written for a positive type ID is just the type ID 94198090Srdivacky // itself. For a negative type ID, however, the value written is the 95193323Sed // (negative) byte offset of the corresponding FilterIds entry. The byte 96198090Srdivacky // offset is usually equal to the type ID (because the FilterIds entries are 97198090Srdivacky // written using a variable width encoding, which outputs one byte per entry 98198090Srdivacky // as long as the value written is not too large) but can differ. This kind 99198090Srdivacky // of complication does not occur for positive type IDs because type infos are 100193323Sed // output using a fixed width encoding. FilterOffsets[i] holds the byte 101193323Sed // offset corresponding to FilterIds[i]. 102198090Srdivacky 103198090Srdivacky const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); 104193323Sed SmallVector<int, 16> FilterOffsets; 105193323Sed FilterOffsets.reserve(FilterIds.size()); 106193323Sed int Offset = -1; 107198090Srdivacky 108198090Srdivacky for (std::vector<unsigned>::const_iterator 109198090Srdivacky I = FilterIds.begin(), E = FilterIds.end(); I != E; ++I) { 110193323Sed FilterOffsets.push_back(Offset); 111198090Srdivacky Offset -= MCAsmInfo::getULEB128Size(*I); 112193323Sed } 113193323Sed 114193323Sed FirstActions.reserve(LandingPads.size()); 115193323Sed 116193323Sed int FirstAction = 0; 117193323Sed unsigned SizeActions = 0; 118198090Srdivacky const LandingPadInfo *PrevLPI = 0; 119198090Srdivacky 120198090Srdivacky for (SmallVectorImpl<const LandingPadInfo *>::const_iterator 121198090Srdivacky I = LandingPads.begin(), E = LandingPads.end(); I != E; ++I) { 122198090Srdivacky const LandingPadInfo *LPI = *I; 123198090Srdivacky const std::vector<int> &TypeIds = LPI->TypeIds; 124206274Srdivacky unsigned NumShared = PrevLPI ? SharedTypeIds(LPI, PrevLPI) : 0; 125193323Sed unsigned SizeSiteActions = 0; 126193323Sed 127193323Sed if (NumShared < TypeIds.size()) { 128193323Sed unsigned SizeAction = 0; 129203954Srdivacky unsigned PrevAction = (unsigned)-1; 130193323Sed 131193323Sed if (NumShared) { 132206274Srdivacky unsigned SizePrevIds = PrevLPI->TypeIds.size(); 133193323Sed assert(Actions.size()); 134203954Srdivacky PrevAction = Actions.size() - 1; 135203954Srdivacky SizeAction = 136203954Srdivacky MCAsmInfo::getSLEB128Size(Actions[PrevAction].NextAction) + 137203954Srdivacky MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID); 138193323Sed 139193323Sed for (unsigned j = NumShared; j != SizePrevIds; ++j) { 140203954Srdivacky assert(PrevAction != (unsigned)-1 && "PrevAction is invalid!"); 141193323Sed SizeAction -= 142203954Srdivacky MCAsmInfo::getSLEB128Size(Actions[PrevAction].ValueForTypeID); 143203954Srdivacky SizeAction += -Actions[PrevAction].NextAction; 144203954Srdivacky PrevAction = Actions[PrevAction].Previous; 145193323Sed } 146193323Sed } 147193323Sed 148193323Sed // Compute the actions. 149198090Srdivacky for (unsigned J = NumShared, M = TypeIds.size(); J != M; ++J) { 150198090Srdivacky int TypeID = TypeIds[J]; 151198090Srdivacky assert(-1 - TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); 152193323Sed int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID; 153198090Srdivacky unsigned SizeTypeID = MCAsmInfo::getSLEB128Size(ValueForTypeID); 154193323Sed 155193323Sed int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; 156198090Srdivacky SizeAction = SizeTypeID + MCAsmInfo::getSLEB128Size(NextAction); 157193323Sed SizeSiteActions += SizeAction; 158193323Sed 159198090Srdivacky ActionEntry Action = { ValueForTypeID, NextAction, PrevAction }; 160193323Sed Actions.push_back(Action); 161203954Srdivacky PrevAction = Actions.size() - 1; 162193323Sed } 163193323Sed 164193323Sed // Record the first action of the landing pad site. 165193323Sed FirstAction = SizeActions + SizeSiteActions - SizeAction + 1; 166193323Sed } // else identical - re-use previous FirstAction 167193323Sed 168198090Srdivacky // Information used when created the call-site table. The action record 169198090Srdivacky // field of the call site record is the offset of the first associated 170198090Srdivacky // action record, relative to the start of the actions table. This value is 171203954Srdivacky // biased by 1 (1 indicating the start of the actions table), and 0 172198090Srdivacky // indicates that there are no actions. 173193323Sed FirstActions.push_back(FirstAction); 174193323Sed 175193323Sed // Compute this sites contribution to size. 176193323Sed SizeActions += SizeSiteActions; 177198090Srdivacky 178198090Srdivacky PrevLPI = LPI; 179193323Sed } 180193323Sed 181198090Srdivacky return SizeActions; 182198090Srdivacky} 183193323Sed 184199481Srdivacky/// CallToNoUnwindFunction - Return `true' if this is a call to a function 185199481Srdivacky/// marked `nounwind'. Return `false' otherwise. 186199481Srdivackybool DwarfException::CallToNoUnwindFunction(const MachineInstr *MI) { 187235633Sdim assert(MI->isCall() && "This should be a call instruction!"); 188199481Srdivacky 189199481Srdivacky bool MarkedNoUnwind = false; 190199481Srdivacky bool SawFunc = false; 191199481Srdivacky 192199481Srdivacky for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) { 193199481Srdivacky const MachineOperand &MO = MI->getOperand(I); 194199481Srdivacky 195206083Srdivacky if (!MO.isGlobal()) continue; 196218893Sdim 197207618Srdivacky const Function *F = dyn_cast<Function>(MO.getGlobal()); 198206083Srdivacky if (F == 0) continue; 199199481Srdivacky 200206083Srdivacky if (SawFunc) { 201206083Srdivacky // Be conservative. If we have more than one function operand for this 202206083Srdivacky // call, then we can't make the assumption that it's the callee and 203206083Srdivacky // not a parameter to the call. 204218893Sdim // 205206083Srdivacky // FIXME: Determine if there's a way to say that `F' is the callee or 206206083Srdivacky // parameter. 207206083Srdivacky MarkedNoUnwind = false; 208206083Srdivacky break; 209199481Srdivacky } 210206083Srdivacky 211206083Srdivacky MarkedNoUnwind = F->doesNotThrow(); 212206083Srdivacky SawFunc = true; 213199481Srdivacky } 214199481Srdivacky 215199481Srdivacky return MarkedNoUnwind; 216199481Srdivacky} 217199481Srdivacky 218198090Srdivacky/// ComputeCallSiteTable - Compute the call-site table. The entry for an invoke 219198090Srdivacky/// has a try-range containing the call, a non-zero landing pad, and an 220198090Srdivacky/// appropriate action. The entry for an ordinary call has a try-range 221198090Srdivacky/// containing the call and zero for the landing pad and the action. Calls 222198090Srdivacky/// marked 'nounwind' have no entry and must not be contained in the try-range 223198090Srdivacky/// of any entry - they form gaps in the table. Entries must be ordered by 224198090Srdivacky/// try-range address. 225198090Srdivackyvoid DwarfException:: 226198090SrdivackyComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, 227198090Srdivacky const RangeMapType &PadMap, 228198090Srdivacky const SmallVectorImpl<const LandingPadInfo *> &LandingPads, 229198090Srdivacky const SmallVectorImpl<unsigned> &FirstActions) { 230193323Sed // The end label of the previous invoke or nounwind try-range. 231205218Srdivacky MCSymbol *LastLabel = 0; 232193323Sed 233193323Sed // Whether there is a potentially throwing instruction (currently this means 234193323Sed // an ordinary call) between the end of the previous try-range and now. 235193323Sed bool SawPotentiallyThrowing = false; 236193323Sed 237198090Srdivacky // Whether the last CallSite entry was for an invoke. 238193323Sed bool PreviousIsInvoke = false; 239193323Sed 240193323Sed // Visit all instructions in order of address. 241206274Srdivacky for (MachineFunction::const_iterator I = Asm->MF->begin(), E = Asm->MF->end(); 242193323Sed I != E; ++I) { 243193323Sed for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); 244193323Sed MI != E; ++MI) { 245193323Sed if (!MI->isLabel()) { 246235633Sdim if (MI->isCall()) 247199481Srdivacky SawPotentiallyThrowing |= !CallToNoUnwindFunction(MI); 248193323Sed continue; 249193323Sed } 250193323Sed 251193323Sed // End of the previous try-range? 252205218Srdivacky MCSymbol *BeginLabel = MI->getOperand(0).getMCSymbol(); 253193323Sed if (BeginLabel == LastLabel) 254193323Sed SawPotentiallyThrowing = false; 255193323Sed 256193323Sed // Beginning of a new try-range? 257199481Srdivacky RangeMapType::const_iterator L = PadMap.find(BeginLabel); 258193323Sed if (L == PadMap.end()) 259193323Sed // Nope, it was just some random label. 260193323Sed continue; 261193323Sed 262198090Srdivacky const PadRange &P = L->second; 263193323Sed const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; 264193323Sed assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && 265193323Sed "Inconsistent landing pad map!"); 266193323Sed 267198090Srdivacky // For Dwarf exception handling (SjLj handling doesn't use this). If some 268198090Srdivacky // instruction between the previous try-range and this one may throw, 269198090Srdivacky // create a call-site entry with no landing pad for the region between the 270198090Srdivacky // try-ranges. 271218893Sdim if (SawPotentiallyThrowing && Asm->MAI->isExceptionHandlingDwarf()) { 272198090Srdivacky CallSiteEntry Site = { LastLabel, BeginLabel, 0, 0 }; 273193323Sed CallSites.push_back(Site); 274193323Sed PreviousIsInvoke = false; 275193323Sed } 276193323Sed 277193323Sed LastLabel = LandingPad->EndLabels[P.RangeIndex]; 278193323Sed assert(BeginLabel && LastLabel && "Invalid landing pad!"); 279193323Sed 280206083Srdivacky if (!LandingPad->LandingPadLabel) { 281206083Srdivacky // Create a gap. 282206083Srdivacky PreviousIsInvoke = false; 283206083Srdivacky } else { 284193323Sed // This try-range is for an invoke. 285198090Srdivacky CallSiteEntry Site = { 286198090Srdivacky BeginLabel, 287198090Srdivacky LastLabel, 288198090Srdivacky LandingPad->LandingPadLabel, 289198090Srdivacky FirstActions[P.PadIndex] 290198090Srdivacky }; 291193323Sed 292198090Srdivacky // Try to merge with the previous call-site. SJLJ doesn't do this 293218893Sdim if (PreviousIsInvoke && Asm->MAI->isExceptionHandlingDwarf()) { 294193323Sed CallSiteEntry &Prev = CallSites.back(); 295193323Sed if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { 296193323Sed // Extend the range of the previous entry. 297193323Sed Prev.EndLabel = Site.EndLabel; 298193323Sed continue; 299193323Sed } 300193323Sed } 301193323Sed 302193323Sed // Otherwise, create a new call-site. 303218893Sdim if (Asm->MAI->isExceptionHandlingDwarf()) 304203954Srdivacky CallSites.push_back(Site); 305203954Srdivacky else { 306203954Srdivacky // SjLj EH must maintain the call sites in the order assigned 307203954Srdivacky // to them by the SjLjPrepare pass. 308203954Srdivacky unsigned SiteNo = MMI->getCallSiteBeginLabel(BeginLabel); 309203954Srdivacky if (CallSites.size() < SiteNo) 310203954Srdivacky CallSites.resize(SiteNo); 311203954Srdivacky CallSites[SiteNo - 1] = Site; 312203954Srdivacky } 313193323Sed PreviousIsInvoke = true; 314193323Sed } 315193323Sed } 316193323Sed } 317193323Sed 318193323Sed // If some instruction between the previous try-range and the end of the 319193323Sed // function may throw, create a call-site entry with no landing pad for the 320193323Sed // region following the try-range. 321218893Sdim if (SawPotentiallyThrowing && Asm->MAI->isExceptionHandlingDwarf()) { 322198090Srdivacky CallSiteEntry Site = { LastLabel, 0, 0, 0 }; 323193323Sed CallSites.push_back(Site); 324193323Sed } 325198090Srdivacky} 326193323Sed 327198090Srdivacky/// EmitExceptionTable - Emit landing pads and actions. 328198090Srdivacky/// 329198090Srdivacky/// The general organization of the table is complex, but the basic concepts are 330198090Srdivacky/// easy. First there is a header which describes the location and organization 331198090Srdivacky/// of the three components that follow. 332198090Srdivacky/// 333198090Srdivacky/// 1. The landing pad site information describes the range of code covered by 334198090Srdivacky/// the try. In our case it's an accumulation of the ranges covered by the 335198090Srdivacky/// invokes in the try. There is also a reference to the landing pad that 336198090Srdivacky/// handles the exception once processed. Finally an index into the actions 337198090Srdivacky/// table. 338198090Srdivacky/// 2. The action table, in our case, is composed of pairs of type IDs and next 339198090Srdivacky/// action offset. Starting with the action index from the landing pad 340198090Srdivacky/// site, each type ID is checked for a match to the current exception. If 341198090Srdivacky/// it matches then the exception and type id are passed on to the landing 342198090Srdivacky/// pad. Otherwise the next action is looked up. This chain is terminated 343198090Srdivacky/// with a next action of zero. If no type id is found then the frame is 344198090Srdivacky/// unwound and handling continues. 345198090Srdivacky/// 3. Type ID table contains references to all the C++ typeinfo for all 346198090Srdivacky/// catches in the function. This tables is reverse indexed base 1. 347198090Srdivackyvoid DwarfException::EmitExceptionTable() { 348207618Srdivacky const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); 349198090Srdivacky const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); 350198090Srdivacky const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads(); 351198090Srdivacky 352198090Srdivacky // Sort the landing pads in order of their type ids. This is used to fold 353198090Srdivacky // duplicate actions. 354198090Srdivacky SmallVector<const LandingPadInfo *, 64> LandingPads; 355198090Srdivacky LandingPads.reserve(PadInfos.size()); 356198090Srdivacky 357198090Srdivacky for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) 358198090Srdivacky LandingPads.push_back(&PadInfos[i]); 359198090Srdivacky 360198090Srdivacky std::sort(LandingPads.begin(), LandingPads.end(), PadLT); 361198090Srdivacky 362198090Srdivacky // Compute the actions table and gather the first action index for each 363198090Srdivacky // landing pad site. 364198090Srdivacky SmallVector<ActionEntry, 32> Actions; 365198090Srdivacky SmallVector<unsigned, 64> FirstActions; 366203954Srdivacky unsigned SizeActions=ComputeActionsTable(LandingPads, Actions, FirstActions); 367198090Srdivacky 368198090Srdivacky // Invokes and nounwind calls have entries in PadMap (due to being bracketed 369198090Srdivacky // by try-range labels when lowered). Ordinary calls do not, so appropriate 370198090Srdivacky // try-ranges for them need be deduced when using DWARF exception handling. 371198090Srdivacky RangeMapType PadMap; 372198090Srdivacky for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { 373198090Srdivacky const LandingPadInfo *LandingPad = LandingPads[i]; 374198090Srdivacky for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) { 375205218Srdivacky MCSymbol *BeginLabel = LandingPad->BeginLabels[j]; 376198090Srdivacky assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); 377198090Srdivacky PadRange P = { i, j }; 378198090Srdivacky PadMap[BeginLabel] = P; 379198090Srdivacky } 380198090Srdivacky } 381198090Srdivacky 382198090Srdivacky // Compute the call-site table. 383198090Srdivacky SmallVector<CallSiteEntry, 64> CallSites; 384198090Srdivacky ComputeCallSiteTable(CallSites, PadMap, LandingPads, FirstActions); 385198090Srdivacky 386193323Sed // Final tallies. 387193323Sed 388193323Sed // Call sites. 389206274Srdivacky bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; 390198090Srdivacky bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true; 391218893Sdim 392204642Srdivacky unsigned CallSiteTableLength; 393198090Srdivacky if (IsSJLJ) 394204642Srdivacky CallSiteTableLength = 0; 395206274Srdivacky else { 396206274Srdivacky unsigned SiteStartSize = 4; // dwarf::DW_EH_PE_udata4 397206274Srdivacky unsigned SiteLengthSize = 4; // dwarf::DW_EH_PE_udata4 398206274Srdivacky unsigned LandingPadSize = 4; // dwarf::DW_EH_PE_udata4 399218893Sdim CallSiteTableLength = 400206274Srdivacky CallSites.size() * (SiteStartSize + SiteLengthSize + LandingPadSize); 401206274Srdivacky } 402198090Srdivacky 403198090Srdivacky for (unsigned i = 0, e = CallSites.size(); i < e; ++i) { 404204642Srdivacky CallSiteTableLength += MCAsmInfo::getULEB128Size(CallSites[i].Action); 405198090Srdivacky if (IsSJLJ) 406204642Srdivacky CallSiteTableLength += MCAsmInfo::getULEB128Size(i); 407198090Srdivacky } 408198090Srdivacky 409193323Sed // Type infos. 410198090Srdivacky const MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection(); 411203954Srdivacky unsigned TTypeEncoding; 412198090Srdivacky unsigned TypeFormatSize; 413193323Sed 414198090Srdivacky if (!HaveTTData) { 415198090Srdivacky // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say 416198090Srdivacky // that we're omitting that bit. 417203954Srdivacky TTypeEncoding = dwarf::DW_EH_PE_omit; 418206274Srdivacky // dwarf::DW_EH_PE_absptr 419245431Sdim TypeFormatSize = Asm->getDataLayout().getPointerSize(); 420198090Srdivacky } else { 421198090Srdivacky // Okay, we have actual filters or typeinfos to emit. As such, we need to 422198090Srdivacky // pick a type encoding for them. We're about to emit a list of pointers to 423198090Srdivacky // typeinfo objects at the end of the LSDA. However, unless we're in static 424198090Srdivacky // mode, this reference will require a relocation by the dynamic linker. 425198090Srdivacky // 426198090Srdivacky // Because of this, we have a couple of options: 427218893Sdim // 428198090Srdivacky // 1) If we are in -static mode, we can always use an absolute reference 429198090Srdivacky // from the LSDA, because the static linker will resolve it. 430218893Sdim // 431198090Srdivacky // 2) Otherwise, if the LSDA section is writable, we can output the direct 432198090Srdivacky // reference to the typeinfo and allow the dynamic linker to relocate 433198090Srdivacky // it. Since it is in a writable section, the dynamic linker won't 434198090Srdivacky // have a problem. 435218893Sdim // 436198090Srdivacky // 3) Finally, if we're in PIC mode and the LDSA section isn't writable, 437198090Srdivacky // we need to use some form of indirection. For example, on Darwin, 438198090Srdivacky // we can output a statically-relocatable reference to a dyld stub. The 439198090Srdivacky // offset to the stub is constant, but the contents are in a section 440198090Srdivacky // that is updated by the dynamic linker. This is easy enough, but we 441198090Srdivacky // need to tell the personality function of the unwinder to indirect 442198090Srdivacky // through the dyld stub. 443198090Srdivacky // 444198090Srdivacky // FIXME: When (3) is actually implemented, we'll have to emit the stubs 445198090Srdivacky // somewhere. This predicate should be moved to a shared location that is 446198090Srdivacky // in target-independent code. 447198090Srdivacky // 448203954Srdivacky TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding(); 449206274Srdivacky TypeFormatSize = Asm->GetSizeOfEncodedValue(TTypeEncoding); 450198090Srdivacky } 451193323Sed 452193323Sed // Begin the exception table. 453218893Sdim // Sometimes we want not to emit the data into separate section (e.g. ARM 454218893Sdim // EHABI). In this case LSDASection will be NULL. 455218893Sdim if (LSDASection) 456218893Sdim Asm->OutStreamer.SwitchSection(LSDASection); 457207618Srdivacky Asm->EmitAlignment(2); 458198090Srdivacky 459204642Srdivacky // Emit the LSDA. 460218893Sdim MCSymbol *GCCETSym = 461204961Srdivacky Asm->OutContext.GetOrCreateSymbol(Twine("GCC_except_table")+ 462206274Srdivacky Twine(Asm->getFunctionNumber())); 463204961Srdivacky Asm->OutStreamer.EmitLabel(GCCETSym); 464206274Srdivacky Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("exception", 465206274Srdivacky Asm->getFunctionNumber())); 466193323Sed 467204961Srdivacky if (IsSJLJ) 468206274Srdivacky Asm->OutStreamer.EmitLabel(Asm->GetTempSymbol("_LSDA_", 469206274Srdivacky Asm->getFunctionNumber())); 470204642Srdivacky 471204642Srdivacky // Emit the LSDA header. 472206274Srdivacky Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); 473206274Srdivacky Asm->EmitEncodingByte(TTypeEncoding, "@TType"); 474204642Srdivacky 475198090Srdivacky // The type infos need to be aligned. GCC does this by inserting padding just 476198090Srdivacky // before the type infos. However, this changes the size of the exception 477198090Srdivacky // table, so you need to take this into account when you output the exception 478198090Srdivacky // table size. However, the size is output using a variable length encoding. 479198090Srdivacky // So by increasing the size by inserting padding, you may increase the number 480198090Srdivacky // of bytes used for writing the size. If it increases, say by one byte, then 481198090Srdivacky // you now need to output one less byte of padding to get the type infos 482204642Srdivacky // aligned. However this decreases the size of the exception table. This 483198090Srdivacky // changes the value you have to output for the exception table size. Due to 484198090Srdivacky // the variable length encoding, the number of bytes used for writing the 485198090Srdivacky // length may decrease. If so, you then have to increase the amount of 486198090Srdivacky // padding. And so on. If you look carefully at the GCC code you will see that 487198090Srdivacky // it indeed does this in a loop, going on and on until the values stabilize. 488198090Srdivacky // We chose another solution: don't output padding inside the table like GCC 489198090Srdivacky // does, instead output it before the table. 490198090Srdivacky unsigned SizeTypes = TypeInfos.size() * TypeFormatSize; 491204642Srdivacky unsigned CallSiteTableLengthSize = 492204642Srdivacky MCAsmInfo::getULEB128Size(CallSiteTableLength); 493204642Srdivacky unsigned TTypeBaseOffset = 494204642Srdivacky sizeof(int8_t) + // Call site format 495204642Srdivacky CallSiteTableLengthSize + // Call site table length size 496204642Srdivacky CallSiteTableLength + // Call site table length 497204642Srdivacky SizeActions + // Actions size 498204642Srdivacky SizeTypes; 499204642Srdivacky unsigned TTypeBaseOffsetSize = MCAsmInfo::getULEB128Size(TTypeBaseOffset); 500204642Srdivacky unsigned TotalSize = 501204642Srdivacky sizeof(int8_t) + // LPStart format 502204642Srdivacky sizeof(int8_t) + // TType format 503204642Srdivacky (HaveTTData ? TTypeBaseOffsetSize : 0) + // TType base offset size 504204642Srdivacky TTypeBaseOffset; // TType base offset 505198090Srdivacky unsigned SizeAlign = (4 - TotalSize) & 3; 506198090Srdivacky 507204642Srdivacky if (HaveTTData) { 508204642Srdivacky // Account for any extra padding that will be added to the call site table 509204642Srdivacky // length. 510206274Srdivacky Asm->EmitULEB128(TTypeBaseOffset, "@TType base offset", SizeAlign); 511204642Srdivacky SizeAlign = 0; 512198090Srdivacky } 513193323Sed 514224145Sdim bool VerboseAsm = Asm->OutStreamer.isVerboseAsm(); 515224145Sdim 516198090Srdivacky // SjLj Exception handling 517198090Srdivacky if (IsSJLJ) { 518206274Srdivacky Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); 519198090Srdivacky 520204642Srdivacky // Add extra padding if it wasn't added to the TType base offset. 521206274Srdivacky Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); 522204642Srdivacky 523198090Srdivacky // Emit the landing pad site information. 524198090Srdivacky unsigned idx = 0; 525198090Srdivacky for (SmallVectorImpl<CallSiteEntry>::const_iterator 526198090Srdivacky I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) { 527198090Srdivacky const CallSiteEntry &S = *I; 528198090Srdivacky 529226890Sdim // Offset of the landing pad, counted in 16-byte bundles relative to the 530226890Sdim // @LPStart address. 531224145Sdim if (VerboseAsm) { 532235633Sdim Asm->OutStreamer.AddComment(">> Call Site " + Twine(idx) + " <<"); 533235633Sdim Asm->OutStreamer.AddComment(" On exception at call site "+Twine(idx)); 534226890Sdim } 535226890Sdim Asm->EmitULEB128(idx); 536224145Sdim 537226890Sdim // Offset of the first associated action record, relative to the start of 538226890Sdim // the action table. This value is biased by 1 (1 indicates the start of 539226890Sdim // the action table), and 0 indicates that there are no actions. 540226890Sdim if (VerboseAsm) { 541224145Sdim if (S.Action == 0) 542224145Sdim Asm->OutStreamer.AddComment(" Action: cleanup"); 543224145Sdim else 544235633Sdim Asm->OutStreamer.AddComment(" Action: " + 545235633Sdim Twine((S.Action - 1) / 2 + 1)); 546224145Sdim } 547224145Sdim Asm->EmitULEB128(S.Action); 548193323Sed } 549198090Srdivacky } else { 550198090Srdivacky // DWARF Exception handling 551218893Sdim assert(Asm->MAI->isExceptionHandlingDwarf()); 552193323Sed 553198090Srdivacky // The call-site table is a list of all call sites that may throw an 554198090Srdivacky // exception (including C++ 'throw' statements) in the procedure 555198090Srdivacky // fragment. It immediately follows the LSDA header. Each entry indicates, 556198090Srdivacky // for a given call, the first corresponding action record and corresponding 557198090Srdivacky // landing pad. 558198090Srdivacky // 559198090Srdivacky // The table begins with the number of bytes, stored as an LEB128 560198090Srdivacky // compressed, unsigned integer. The records immediately follow the record 561198090Srdivacky // count. They are sorted in increasing call-site address. Each record 562198090Srdivacky // indicates: 563198090Srdivacky // 564198090Srdivacky // * The position of the call-site. 565198090Srdivacky // * The position of the landing pad. 566198090Srdivacky // * The first action record for that call site. 567198090Srdivacky // 568198090Srdivacky // A missing entry in the call-site table indicates that a call is not 569198090Srdivacky // supposed to throw. 570193323Sed 571198090Srdivacky // Emit the landing pad call site table. 572206274Srdivacky Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); 573193323Sed 574204642Srdivacky // Add extra padding if it wasn't added to the TType base offset. 575206274Srdivacky Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); 576204642Srdivacky 577224145Sdim unsigned Entry = 0; 578198090Srdivacky for (SmallVectorImpl<CallSiteEntry>::const_iterator 579198090Srdivacky I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { 580198090Srdivacky const CallSiteEntry &S = *I; 581218893Sdim 582206274Srdivacky MCSymbol *EHFuncBeginSym = 583206274Srdivacky Asm->GetTempSymbol("eh_func_begin", Asm->getFunctionNumber()); 584218893Sdim 585205218Srdivacky MCSymbol *BeginLabel = S.BeginLabel; 586205218Srdivacky if (BeginLabel == 0) 587205218Srdivacky BeginLabel = EHFuncBeginSym; 588205218Srdivacky MCSymbol *EndLabel = S.EndLabel; 589205218Srdivacky if (EndLabel == 0) 590206274Srdivacky EndLabel = Asm->GetTempSymbol("eh_func_end", Asm->getFunctionNumber()); 591218893Sdim 592226890Sdim 593226890Sdim // Offset of the call site relative to the previous call site, counted in 594226890Sdim // number of 16-byte bundles. The first call site is counted relative to 595226890Sdim // the start of the procedure fragment. 596226890Sdim if (VerboseAsm) 597235633Sdim Asm->OutStreamer.AddComment(">> Call Site " + Twine(++Entry) + " <<"); 598226890Sdim Asm->EmitLabelDifference(BeginLabel, EHFuncBeginSym, 4); 599226890Sdim if (VerboseAsm) 600224145Sdim Asm->OutStreamer.AddComment(Twine(" Call between ") + 601224145Sdim BeginLabel->getName() + " and " + 602224145Sdim EndLabel->getName()); 603206274Srdivacky Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); 604193323Sed 605198090Srdivacky // Offset of the landing pad, counted in 16-byte bundles relative to the 606198090Srdivacky // @LPStart address. 607226890Sdim if (!S.PadLabel) { 608226890Sdim if (VerboseAsm) 609226890Sdim Asm->OutStreamer.AddComment(" has no landing pad"); 610252723Sdim Asm->OutStreamer.EmitIntValue(0, 4/*size*/); 611226890Sdim } else { 612226890Sdim if (VerboseAsm) 613226890Sdim Asm->OutStreamer.AddComment(Twine(" jumps to ") + 614226890Sdim S.PadLabel->getName()); 615206274Srdivacky Asm->EmitLabelDifference(S.PadLabel, EHFuncBeginSym, 4); 616226890Sdim } 617198090Srdivacky 618198090Srdivacky // Offset of the first associated action record, relative to the start of 619198090Srdivacky // the action table. This value is biased by 1 (1 indicates the start of 620198090Srdivacky // the action table), and 0 indicates that there are no actions. 621226890Sdim if (VerboseAsm) { 622226890Sdim if (S.Action == 0) 623226890Sdim Asm->OutStreamer.AddComment(" On action: cleanup"); 624226890Sdim else 625235633Sdim Asm->OutStreamer.AddComment(" On action: " + 626235633Sdim Twine((S.Action - 1) / 2 + 1)); 627226890Sdim } 628224145Sdim Asm->EmitULEB128(S.Action); 629198090Srdivacky } 630193323Sed } 631193323Sed 632198090Srdivacky // Emit the Action Table. 633224145Sdim int Entry = 0; 634198090Srdivacky for (SmallVectorImpl<ActionEntry>::const_iterator 635198090Srdivacky I = Actions.begin(), E = Actions.end(); I != E; ++I) { 636198090Srdivacky const ActionEntry &Action = *I; 637193323Sed 638224145Sdim if (VerboseAsm) { 639224145Sdim // Emit comments that decode the action table. 640235633Sdim Asm->OutStreamer.AddComment(">> Action Record " + Twine(++Entry) + " <<"); 641226890Sdim } 642226890Sdim 643226890Sdim // Type Filter 644226890Sdim // 645226890Sdim // Used by the runtime to match the type of the thrown exception to the 646226890Sdim // type of the catch clauses or the types in the exception specification. 647226890Sdim if (VerboseAsm) { 648226890Sdim if (Action.ValueForTypeID > 0) 649235633Sdim Asm->OutStreamer.AddComment(" Catch TypeInfo " + 650235633Sdim Twine(Action.ValueForTypeID)); 651226890Sdim else if (Action.ValueForTypeID < 0) 652235633Sdim Asm->OutStreamer.AddComment(" Filter TypeInfo " + 653235633Sdim Twine(Action.ValueForTypeID)); 654226890Sdim else 655226890Sdim Asm->OutStreamer.AddComment(" Cleanup"); 656226890Sdim } 657226890Sdim Asm->EmitSLEB128(Action.ValueForTypeID); 658224145Sdim 659226890Sdim // Action Record 660226890Sdim // 661226890Sdim // Self-relative signed displacement in bytes of the next action record, 662226890Sdim // or 0 if there is no next action record. 663226890Sdim if (VerboseAsm) { 664224145Sdim if (Action.NextAction == 0) { 665224145Sdim Asm->OutStreamer.AddComment(" No further actions"); 666224145Sdim } else { 667224145Sdim unsigned NextAction = Entry + (Action.NextAction + 1) / 2; 668235633Sdim Asm->OutStreamer.AddComment(" Continue to action "+Twine(NextAction)); 669224145Sdim } 670224145Sdim } 671224145Sdim Asm->EmitSLEB128(Action.NextAction); 672193323Sed } 673193323Sed 674252723Sdim EmitTypeInfos(TTypeEncoding); 675252723Sdim 676252723Sdim Asm->EmitAlignment(2); 677252723Sdim} 678252723Sdim 679252723Sdimvoid DwarfException::EmitTypeInfos(unsigned TTypeEncoding) { 680252723Sdim const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); 681252723Sdim const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); 682252723Sdim 683252723Sdim bool VerboseAsm = Asm->OutStreamer.isVerboseAsm(); 684252723Sdim 685252723Sdim int Entry = 0; 686198396Srdivacky // Emit the Catch TypeInfos. 687224145Sdim if (VerboseAsm && !TypeInfos.empty()) { 688224145Sdim Asm->OutStreamer.AddComment(">> Catch TypeInfos <<"); 689204961Srdivacky Asm->OutStreamer.AddBlankLine(); 690224145Sdim Entry = TypeInfos.size(); 691204961Srdivacky } 692224145Sdim 693207618Srdivacky for (std::vector<const GlobalVariable *>::const_reverse_iterator 694198090Srdivacky I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { 695199989Srdivacky const GlobalVariable *GV = *I; 696224145Sdim if (VerboseAsm) 697235633Sdim Asm->OutStreamer.AddComment("TypeInfo " + Twine(Entry--)); 698252723Sdim Asm->EmitTTypeReference(GV, TTypeEncoding); 699193323Sed } 700193323Sed 701198396Srdivacky // Emit the Exception Specifications. 702224145Sdim if (VerboseAsm && !FilterIds.empty()) { 703224145Sdim Asm->OutStreamer.AddComment(">> Filter TypeInfos <<"); 704204961Srdivacky Asm->OutStreamer.AddBlankLine(); 705224145Sdim Entry = 0; 706204961Srdivacky } 707198090Srdivacky for (std::vector<unsigned>::const_iterator 708198090Srdivacky I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { 709198090Srdivacky unsigned TypeID = *I; 710224145Sdim if (VerboseAsm) { 711224145Sdim --Entry; 712224145Sdim if (TypeID != 0) 713235633Sdim Asm->OutStreamer.AddComment("FilterInfo " + Twine(Entry)); 714224145Sdim } 715224145Sdim 716224145Sdim Asm->EmitULEB128(TypeID); 717193323Sed } 718193323Sed} 719193323Sed 720193323Sed/// EndModule - Emit all exception information that should come after the 721193323Sed/// content. 722193323Sedvoid DwarfException::EndModule() { 723235633Sdim llvm_unreachable("Should be implemented"); 724193323Sed} 725193323Sed 726198090Srdivacky/// BeginFunction - Gather pre-function exception information. Assumes it's 727198090Srdivacky/// being emitted immediately after the function entry point. 728203954Srdivackyvoid DwarfException::BeginFunction(const MachineFunction *MF) { 729235633Sdim llvm_unreachable("Should be implemented"); 730193323Sed} 731193323Sed 732193323Sed/// EndFunction - Gather and emit post-function exception information. 733193323Sed/// 734193323Sedvoid DwarfException::EndFunction() { 735235633Sdim llvm_unreachable("Should be implemented"); 736193323Sed} 737