DwarfException.cpp revision d7e8ddc5012d22398eba6b8094e2fd7821bac9cc
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/CodeGen/MachineLocation.h" 21#include "llvm/MC/MCAsmInfo.h" 22#include "llvm/MC/MCContext.h" 23#include "llvm/MC/MCExpr.h" 24#include "llvm/MC/MCSection.h" 25#include "llvm/MC/MCStreamer.h" 26#include "llvm/MC/MCSymbol.h" 27#include "llvm/Target/Mangler.h" 28#include "llvm/Target/TargetData.h" 29#include "llvm/Target/TargetFrameLowering.h" 30#include "llvm/Target/TargetLoweringObjectFile.h" 31#include "llvm/Target/TargetMachine.h" 32#include "llvm/Target/TargetOptions.h" 33#include "llvm/Target/TargetRegisterInfo.h" 34#include "llvm/Support/Dwarf.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->getDesc().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->getDesc().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 && 273 Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { 274 CallSiteEntry Site = { LastLabel, BeginLabel, 0, 0 }; 275 CallSites.push_back(Site); 276 PreviousIsInvoke = false; 277 } 278 279 LastLabel = LandingPad->EndLabels[P.RangeIndex]; 280 assert(BeginLabel && LastLabel && "Invalid landing pad!"); 281 282 if (!LandingPad->LandingPadLabel) { 283 // Create a gap. 284 PreviousIsInvoke = false; 285 } else { 286 // This try-range is for an invoke. 287 CallSiteEntry Site = { 288 BeginLabel, 289 LastLabel, 290 LandingPad->LandingPadLabel, 291 FirstActions[P.PadIndex] 292 }; 293 294 // Try to merge with the previous call-site. SJLJ doesn't do this 295 if (PreviousIsInvoke && 296 Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { 297 CallSiteEntry &Prev = CallSites.back(); 298 if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { 299 // Extend the range of the previous entry. 300 Prev.EndLabel = Site.EndLabel; 301 continue; 302 } 303 } 304 305 // Otherwise, create a new call-site. 306 if (Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) 307 CallSites.push_back(Site); 308 else { 309 // SjLj EH must maintain the call sites in the order assigned 310 // to them by the SjLjPrepare pass. 311 unsigned SiteNo = MMI->getCallSiteBeginLabel(BeginLabel); 312 if (CallSites.size() < SiteNo) 313 CallSites.resize(SiteNo); 314 CallSites[SiteNo - 1] = Site; 315 } 316 PreviousIsInvoke = true; 317 } 318 } 319 } 320 321 // If some instruction between the previous try-range and the end of the 322 // function may throw, create a call-site entry with no landing pad for the 323 // region following the try-range. 324 if (SawPotentiallyThrowing && 325 Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { 326 CallSiteEntry Site = { LastLabel, 0, 0, 0 }; 327 CallSites.push_back(Site); 328 } 329} 330 331/// EmitExceptionTable - Emit landing pads and actions. 332/// 333/// The general organization of the table is complex, but the basic concepts are 334/// easy. First there is a header which describes the location and organization 335/// of the three components that follow. 336/// 337/// 1. The landing pad site information describes the range of code covered by 338/// the try. In our case it's an accumulation of the ranges covered by the 339/// invokes in the try. There is also a reference to the landing pad that 340/// handles the exception once processed. Finally an index into the actions 341/// table. 342/// 2. The action table, in our case, is composed of pairs of type IDs and next 343/// action offset. Starting with the action index from the landing pad 344/// site, each type ID is checked for a match to the current exception. If 345/// it matches then the exception and type id are passed on to the landing 346/// pad. Otherwise the next action is looked up. This chain is terminated 347/// with a next action of zero. If no type id is found then the frame is 348/// unwound and handling continues. 349/// 3. Type ID table contains references to all the C++ typeinfo for all 350/// catches in the function. This tables is reverse indexed base 1. 351void DwarfException::EmitExceptionTable() { 352 const std::vector<const GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); 353 const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); 354 const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads(); 355 356 // Sort the landing pads in order of their type ids. This is used to fold 357 // duplicate actions. 358 SmallVector<const LandingPadInfo *, 64> LandingPads; 359 LandingPads.reserve(PadInfos.size()); 360 361 for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) 362 LandingPads.push_back(&PadInfos[i]); 363 364 std::sort(LandingPads.begin(), LandingPads.end(), PadLT); 365 366 // Compute the actions table and gather the first action index for each 367 // landing pad site. 368 SmallVector<ActionEntry, 32> Actions; 369 SmallVector<unsigned, 64> FirstActions; 370 unsigned SizeActions=ComputeActionsTable(LandingPads, Actions, FirstActions); 371 372 // Invokes and nounwind calls have entries in PadMap (due to being bracketed 373 // by try-range labels when lowered). Ordinary calls do not, so appropriate 374 // try-ranges for them need be deduced when using DWARF exception handling. 375 RangeMapType PadMap; 376 for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { 377 const LandingPadInfo *LandingPad = LandingPads[i]; 378 for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) { 379 MCSymbol *BeginLabel = LandingPad->BeginLabels[j]; 380 assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); 381 PadRange P = { i, j }; 382 PadMap[BeginLabel] = P; 383 } 384 } 385 386 // Compute the call-site table. 387 SmallVector<CallSiteEntry, 64> CallSites; 388 ComputeCallSiteTable(CallSites, PadMap, LandingPads, FirstActions); 389 390 // Final tallies. 391 392 // Call sites. 393 bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; 394 bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true; 395 396 unsigned CallSiteTableLength; 397 if (IsSJLJ) 398 CallSiteTableLength = 0; 399 else { 400 unsigned SiteStartSize = 4; // dwarf::DW_EH_PE_udata4 401 unsigned SiteLengthSize = 4; // dwarf::DW_EH_PE_udata4 402 unsigned LandingPadSize = 4; // dwarf::DW_EH_PE_udata4 403 CallSiteTableLength = 404 CallSites.size() * (SiteStartSize + SiteLengthSize + LandingPadSize); 405 } 406 407 for (unsigned i = 0, e = CallSites.size(); i < e; ++i) { 408 CallSiteTableLength += MCAsmInfo::getULEB128Size(CallSites[i].Action); 409 if (IsSJLJ) 410 CallSiteTableLength += MCAsmInfo::getULEB128Size(i); 411 } 412 413 // Type infos. 414 const MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection(); 415 unsigned TTypeEncoding; 416 unsigned TypeFormatSize; 417 418 if (!HaveTTData) { 419 // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say 420 // that we're omitting that bit. 421 TTypeEncoding = dwarf::DW_EH_PE_omit; 422 // dwarf::DW_EH_PE_absptr 423 TypeFormatSize = Asm->getTargetData().getPointerSize(); 424 } else { 425 // Okay, we have actual filters or typeinfos to emit. As such, we need to 426 // pick a type encoding for them. We're about to emit a list of pointers to 427 // typeinfo objects at the end of the LSDA. However, unless we're in static 428 // mode, this reference will require a relocation by the dynamic linker. 429 // 430 // Because of this, we have a couple of options: 431 // 432 // 1) If we are in -static mode, we can always use an absolute reference 433 // from the LSDA, because the static linker will resolve it. 434 // 435 // 2) Otherwise, if the LSDA section is writable, we can output the direct 436 // reference to the typeinfo and allow the dynamic linker to relocate 437 // it. Since it is in a writable section, the dynamic linker won't 438 // have a problem. 439 // 440 // 3) Finally, if we're in PIC mode and the LDSA section isn't writable, 441 // we need to use some form of indirection. For example, on Darwin, 442 // we can output a statically-relocatable reference to a dyld stub. The 443 // offset to the stub is constant, but the contents are in a section 444 // that is updated by the dynamic linker. This is easy enough, but we 445 // need to tell the personality function of the unwinder to indirect 446 // through the dyld stub. 447 // 448 // FIXME: When (3) is actually implemented, we'll have to emit the stubs 449 // somewhere. This predicate should be moved to a shared location that is 450 // in target-independent code. 451 // 452 TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding(); 453 TypeFormatSize = Asm->GetSizeOfEncodedValue(TTypeEncoding); 454 } 455 456 // Begin the exception table. 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 // SjLj Exception handling 516 if (IsSJLJ) { 517 Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); 518 519 // Add extra padding if it wasn't added to the TType base offset. 520 Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); 521 522 // Emit the landing pad site information. 523 unsigned idx = 0; 524 for (SmallVectorImpl<CallSiteEntry>::const_iterator 525 I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) { 526 const CallSiteEntry &S = *I; 527 528 // Offset of the landing pad, counted in 16-byte bundles relative to the 529 // @LPStart address. 530 Asm->EmitULEB128(idx, "Landing pad"); 531 532 // Offset of the first associated action record, relative to the start of 533 // the action table. This value is biased by 1 (1 indicates the start of 534 // the action table), and 0 indicates that there are no actions. 535 Asm->EmitULEB128(S.Action, "Action"); 536 } 537 } else { 538 // DWARF Exception handling 539 assert(Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Dwarf); 540 541 // The call-site table is a list of all call sites that may throw an 542 // exception (including C++ 'throw' statements) in the procedure 543 // fragment. It immediately follows the LSDA header. Each entry indicates, 544 // for a given call, the first corresponding action record and corresponding 545 // landing pad. 546 // 547 // The table begins with the number of bytes, stored as an LEB128 548 // compressed, unsigned integer. The records immediately follow the record 549 // count. They are sorted in increasing call-site address. Each record 550 // indicates: 551 // 552 // * The position of the call-site. 553 // * The position of the landing pad. 554 // * The first action record for that call site. 555 // 556 // A missing entry in the call-site table indicates that a call is not 557 // supposed to throw. 558 559 // Emit the landing pad call site table. 560 Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); 561 562 // Add extra padding if it wasn't added to the TType base offset. 563 Asm->EmitULEB128(CallSiteTableLength, "Call site table length", SizeAlign); 564 565 for (SmallVectorImpl<CallSiteEntry>::const_iterator 566 I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { 567 const CallSiteEntry &S = *I; 568 569 MCSymbol *EHFuncBeginSym = 570 Asm->GetTempSymbol("eh_func_begin", Asm->getFunctionNumber()); 571 572 MCSymbol *BeginLabel = S.BeginLabel; 573 if (BeginLabel == 0) 574 BeginLabel = EHFuncBeginSym; 575 MCSymbol *EndLabel = S.EndLabel; 576 if (EndLabel == 0) 577 EndLabel = Asm->GetTempSymbol("eh_func_end", Asm->getFunctionNumber()); 578 579 // Offset of the call site relative to the previous call site, counted in 580 // number of 16-byte bundles. The first call site is counted relative to 581 // the start of the procedure fragment. 582 Asm->OutStreamer.AddComment("Region start"); 583 Asm->EmitLabelDifference(BeginLabel, EHFuncBeginSym, 4); 584 585 Asm->OutStreamer.AddComment("Region length"); 586 Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); 587 588 589 // Offset of the landing pad, counted in 16-byte bundles relative to the 590 // @LPStart address. 591 Asm->OutStreamer.AddComment("Landing pad"); 592 if (!S.PadLabel) 593 Asm->OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/); 594 else 595 Asm->EmitLabelDifference(S.PadLabel, EHFuncBeginSym, 4); 596 597 // Offset of the first associated action record, relative to the start of 598 // the action table. This value is biased by 1 (1 indicates the start of 599 // the action table), and 0 indicates that there are no actions. 600 Asm->EmitULEB128(S.Action, "Action"); 601 } 602 } 603 604 // Emit the Action Table. 605 if (Actions.size() != 0) { 606 Asm->OutStreamer.AddComment("-- Action Record Table --"); 607 Asm->OutStreamer.AddBlankLine(); 608 } 609 610 for (SmallVectorImpl<ActionEntry>::const_iterator 611 I = Actions.begin(), E = Actions.end(); I != E; ++I) { 612 const ActionEntry &Action = *I; 613 Asm->OutStreamer.AddComment("Action Record"); 614 Asm->OutStreamer.AddBlankLine(); 615 616 // Type Filter 617 // 618 // Used by the runtime to match the type of the thrown exception to the 619 // type of the catch clauses or the types in the exception specification. 620 Asm->EmitSLEB128(Action.ValueForTypeID, " TypeInfo index"); 621 622 // Action Record 623 // 624 // Self-relative signed displacement in bytes of the next action record, 625 // or 0 if there is no next action record. 626 Asm->EmitSLEB128(Action.NextAction, " Next action"); 627 } 628 629 // Emit the Catch TypeInfos. 630 if (!TypeInfos.empty()) { 631 Asm->OutStreamer.AddComment("-- Catch TypeInfos --"); 632 Asm->OutStreamer.AddBlankLine(); 633 } 634 for (std::vector<const GlobalVariable *>::const_reverse_iterator 635 I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { 636 const GlobalVariable *GV = *I; 637 638 Asm->OutStreamer.AddComment("TypeInfo"); 639 if (GV) 640 Asm->EmitReference(GV, TTypeEncoding); 641 else 642 Asm->OutStreamer.EmitIntValue(0,Asm->GetSizeOfEncodedValue(TTypeEncoding), 643 0); 644 } 645 646 // Emit the Exception Specifications. 647 if (!FilterIds.empty()) { 648 Asm->OutStreamer.AddComment("-- Filter IDs --"); 649 Asm->OutStreamer.AddBlankLine(); 650 } 651 for (std::vector<unsigned>::const_iterator 652 I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { 653 unsigned TypeID = *I; 654 Asm->EmitULEB128(TypeID, TypeID != 0 ? "Exception specification" : 0); 655 } 656 657 Asm->EmitAlignment(2); 658} 659 660/// EndModule - Emit all exception information that should come after the 661/// content. 662void DwarfException::EndModule() { 663 assert(0 && "Should be implemented"); 664} 665 666/// BeginFunction - Gather pre-function exception information. Assumes it's 667/// being emitted immediately after the function entry point. 668void DwarfException::BeginFunction(const MachineFunction *MF) { 669 assert(0 && "Should be implemented"); 670} 671 672/// EndFunction - Gather and emit post-function exception information. 673/// 674void DwarfException::EndFunction() { 675 assert(0 && "Should be implemented"); 676} 677