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