DwarfException.cpp revision 35039ac24163e99cfab161620a9fb41f944a63d5
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/MachineModuleInfo.h" 17#include "llvm/CodeGen/MachineFrameInfo.h" 18#include "llvm/CodeGen/MachineLocation.h" 19#include "llvm/Support/Dwarf.h" 20#include "llvm/Support/Timer.h" 21#include "llvm/Support/raw_ostream.h" 22#include "llvm/Target/TargetAsmInfo.h" 23#include "llvm/Target/TargetData.h" 24#include "llvm/Target/TargetFrameInfo.h" 25#include "llvm/Target/TargetLoweringObjectFile.h" 26#include "llvm/Target/TargetOptions.h" 27#include "llvm/Target/TargetRegisterInfo.h" 28#include "llvm/ADT/StringExtras.h" 29using namespace llvm; 30 31static TimerGroup &getDwarfTimerGroup() { 32 static TimerGroup DwarfTimerGroup("Dwarf Exception"); 33 return DwarfTimerGroup; 34} 35 36DwarfException::DwarfException(raw_ostream &OS, AsmPrinter *A, 37 const TargetAsmInfo *T) 38 : Dwarf(OS, A, T, "eh"), shouldEmitTable(false), shouldEmitMoves(false), 39 shouldEmitTableModule(false), shouldEmitMovesModule(false), 40 ExceptionTimer(0) { 41 if (TimePassesIsEnabled) 42 ExceptionTimer = new Timer("Dwarf Exception Writer", 43 getDwarfTimerGroup()); 44} 45 46DwarfException::~DwarfException() { 47 delete ExceptionTimer; 48} 49 50void DwarfException::EmitCommonEHFrame(const Function *Personality, 51 unsigned Index) { 52 // Size and sign of stack growth. 53 int stackGrowth = 54 Asm->TM.getFrameInfo()->getStackGrowthDirection() == 55 TargetFrameInfo::StackGrowsUp ? 56 TD->getPointerSize() : -TD->getPointerSize(); 57 58 // Begin eh frame section. 59 Asm->SwitchToSection(Asm->getObjFileLowering().getEHFrameSection()); 60 61 if (TAI->is_EHSymbolPrivate()) 62 O << TAI->getPrivateGlobalPrefix(); 63 64 O << "EH_frame" << Index << ":\n"; 65 EmitLabel("section_eh_frame", Index); 66 67 // Define base labels. 68 EmitLabel("eh_frame_common", Index); 69 70 // Define the eh frame length. 71 EmitDifference("eh_frame_common_end", Index, 72 "eh_frame_common_begin", Index, true); 73 Asm->EOL("Length of Common Information Entry"); 74 75 // EH frame header. 76 EmitLabel("eh_frame_common_begin", Index); 77 Asm->EmitInt32((int)0); 78 Asm->EOL("CIE Identifier Tag"); 79 Asm->EmitInt8(dwarf::DW_CIE_VERSION); 80 Asm->EOL("CIE Version"); 81 82 // The personality presence indicates that language specific information will 83 // show up in the eh frame. 84 Asm->EmitString(Personality ? "zPLR" : "zR"); 85 Asm->EOL("CIE Augmentation"); 86 87 // Round out reader. 88 Asm->EmitULEB128Bytes(1); 89 Asm->EOL("CIE Code Alignment Factor"); 90 Asm->EmitSLEB128Bytes(stackGrowth); 91 Asm->EOL("CIE Data Alignment Factor"); 92 Asm->EmitInt8(RI->getDwarfRegNum(RI->getRARegister(), true)); 93 Asm->EOL("CIE Return Address Column"); 94 95 // If there is a personality, we need to indicate the functions location. 96 if (Personality) { 97 Asm->EmitULEB128Bytes(7); 98 Asm->EOL("Augmentation Size"); 99 100 if (TAI->getNeedsIndirectEncoding()) { 101 Asm->EmitInt8(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4 | 102 dwarf::DW_EH_PE_indirect); 103 Asm->EOL("Personality (pcrel sdata4 indirect)"); 104 } else { 105 Asm->EmitInt8(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); 106 Asm->EOL("Personality (pcrel sdata4)"); 107 } 108 109 PrintRelDirective(true); 110 O << TAI->getPersonalityPrefix(); 111 Asm->EmitExternalGlobal((const GlobalVariable *)(Personality)); 112 O << TAI->getPersonalitySuffix(); 113 if (strcmp(TAI->getPersonalitySuffix(), "+4@GOTPCREL")) 114 O << "-" << TAI->getPCSymbol(); 115 Asm->EOL("Personality"); 116 117 Asm->EmitInt8(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); 118 Asm->EOL("LSDA Encoding (pcrel sdata4)"); 119 120 Asm->EmitInt8(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); 121 Asm->EOL("FDE Encoding (pcrel sdata4)"); 122 } else { 123 Asm->EmitULEB128Bytes(1); 124 Asm->EOL("Augmentation Size"); 125 126 Asm->EmitInt8(dwarf::DW_EH_PE_pcrel | dwarf::DW_EH_PE_sdata4); 127 Asm->EOL("FDE Encoding (pcrel sdata4)"); 128 } 129 130 // Indicate locations of general callee saved registers in frame. 131 std::vector<MachineMove> Moves; 132 RI->getInitialFrameState(Moves); 133 EmitFrameMoves(NULL, 0, Moves, true); 134 135 // On Darwin the linker honors the alignment of eh_frame, which means it must 136 // be 8-byte on 64-bit targets to match what gcc does. Otherwise you get 137 // holes which confuse readers of eh_frame. 138 Asm->EmitAlignment(TD->getPointerSize() == sizeof(int32_t) ? 2 : 3, 139 0, 0, false); 140 EmitLabel("eh_frame_common_end", Index); 141 142 Asm->EOL(); 143} 144 145/// EmitEHFrame - Emit function exception frame information. 146/// 147void DwarfException::EmitEHFrame(const FunctionEHFrameInfo &EHFrameInfo) { 148 assert(!EHFrameInfo.function->hasAvailableExternallyLinkage() && 149 "Should not emit 'available externally' functions at all"); 150 151 const Function *TheFunc = EHFrameInfo.function; 152 153 Asm->SwitchToSection(Asm->getObjFileLowering().getEHFrameSection()); 154 155 // Externally visible entry into the functions eh frame info. If the 156 // corresponding function is static, this should not be externally visible. 157 if (!TheFunc->hasLocalLinkage()) 158 if (const char *GlobalEHDirective = TAI->getGlobalEHDirective()) 159 O << GlobalEHDirective << EHFrameInfo.FnName << "\n"; 160 161 // If corresponding function is weak definition, this should be too. 162 if (TheFunc->isWeakForLinker() && TAI->getWeakDefDirective()) 163 O << TAI->getWeakDefDirective() << EHFrameInfo.FnName << "\n"; 164 165 // If there are no calls then you can't unwind. This may mean we can omit the 166 // EH Frame, but some environments do not handle weak absolute symbols. If 167 // UnwindTablesMandatory is set we cannot do this optimization; the unwind 168 // info is to be available for non-EH uses. 169 if (!EHFrameInfo.hasCalls && !UnwindTablesMandatory && 170 (!TheFunc->isWeakForLinker() || 171 !TAI->getWeakDefDirective() || 172 TAI->getSupportsWeakOmittedEHFrame())) { 173 O << EHFrameInfo.FnName << " = 0\n"; 174 // This name has no connection to the function, so it might get 175 // dead-stripped when the function is not, erroneously. Prohibit 176 // dead-stripping unconditionally. 177 if (const char *UsedDirective = TAI->getUsedDirective()) 178 O << UsedDirective << EHFrameInfo.FnName << "\n\n"; 179 } else { 180 O << EHFrameInfo.FnName << ":\n"; 181 182 // EH frame header. 183 EmitDifference("eh_frame_end", EHFrameInfo.Number, 184 "eh_frame_begin", EHFrameInfo.Number, true); 185 Asm->EOL("Length of Frame Information Entry"); 186 187 EmitLabel("eh_frame_begin", EHFrameInfo.Number); 188 189 EmitSectionOffset("eh_frame_begin", "eh_frame_common", 190 EHFrameInfo.Number, EHFrameInfo.PersonalityIndex, 191 true, true, false); 192 193 Asm->EOL("FDE CIE offset"); 194 195 EmitReference("eh_func_begin", EHFrameInfo.Number, true, true); 196 Asm->EOL("FDE initial location"); 197 EmitDifference("eh_func_end", EHFrameInfo.Number, 198 "eh_func_begin", EHFrameInfo.Number, true); 199 Asm->EOL("FDE address range"); 200 201 // If there is a personality and landing pads then point to the language 202 // specific data area in the exception table. 203 if (EHFrameInfo.PersonalityIndex) { 204 Asm->EmitULEB128Bytes(4); 205 Asm->EOL("Augmentation size"); 206 207 if (EHFrameInfo.hasLandingPads) 208 EmitReference("exception", EHFrameInfo.Number, true, true); 209 else 210 Asm->EmitInt32((int)0); 211 Asm->EOL("Language Specific Data Area"); 212 } else { 213 Asm->EmitULEB128Bytes(0); 214 Asm->EOL("Augmentation size"); 215 } 216 217 // Indicate locations of function specific callee saved registers in frame. 218 EmitFrameMoves("eh_func_begin", EHFrameInfo.Number, EHFrameInfo.Moves, 219 true); 220 221 // On Darwin the linker honors the alignment of eh_frame, which means it 222 // must be 8-byte on 64-bit targets to match what gcc does. Otherwise you 223 // get holes which confuse readers of eh_frame. 224 Asm->EmitAlignment(TD->getPointerSize() == sizeof(int32_t) ? 2 : 3, 225 0, 0, false); 226 EmitLabel("eh_frame_end", EHFrameInfo.Number); 227 228 // If the function is marked used, this table should be also. We cannot 229 // make the mark unconditional in this case, since retaining the table also 230 // retains the function in this case, and there is code around that depends 231 // on unused functions (calling undefined externals) being dead-stripped to 232 // link correctly. Yes, there really is. 233 if (MMI->isUsedFunction(EHFrameInfo.function)) 234 if (const char *UsedDirective = TAI->getUsedDirective()) 235 O << UsedDirective << EHFrameInfo.FnName << "\n\n"; 236 } 237} 238 239/// SharedTypeIds - How many leading type ids two landing pads have in common. 240unsigned DwarfException::SharedTypeIds(const LandingPadInfo *L, 241 const LandingPadInfo *R) { 242 const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds; 243 unsigned LSize = LIds.size(), RSize = RIds.size(); 244 unsigned MinSize = LSize < RSize ? LSize : RSize; 245 unsigned Count = 0; 246 247 for (; Count != MinSize; ++Count) 248 if (LIds[Count] != RIds[Count]) 249 return Count; 250 251 return Count; 252} 253 254/// PadLT - Order landing pads lexicographically by type id. 255bool DwarfException::PadLT(const LandingPadInfo *L, const LandingPadInfo *R) { 256 const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds; 257 unsigned LSize = LIds.size(), RSize = RIds.size(); 258 unsigned MinSize = LSize < RSize ? LSize : RSize; 259 260 for (unsigned i = 0; i != MinSize; ++i) 261 if (LIds[i] != RIds[i]) 262 return LIds[i] < RIds[i]; 263 264 return LSize < RSize; 265} 266 267/// ComputeActionsTable - Compute the actions table and gather the first action 268/// index for each landing pad site. 269unsigned DwarfException:: 270ComputeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, 271 SmallVectorImpl<ActionEntry> &Actions, 272 SmallVectorImpl<unsigned> &FirstActions) { 273 // Negative type IDs index into FilterIds. Positive type IDs index into 274 // TypeInfos. The value written for a positive type ID is just the type ID 275 // itself. For a negative type ID, however, the value written is the 276 // (negative) byte offset of the corresponding FilterIds entry. The byte 277 // offset is usually equal to the type ID (because the FilterIds entries are 278 // written using a variable width encoding, which outputs one byte per entry 279 // as long as the value written is not too large) but can differ. This kind 280 // of complication does not occur for positive type IDs because type infos are 281 // output using a fixed width encoding. FilterOffsets[i] holds the byte 282 // offset corresponding to FilterIds[i]. 283 284 const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); 285 SmallVector<int, 16> FilterOffsets; 286 FilterOffsets.reserve(FilterIds.size()); 287 int Offset = -1; 288 289 for (std::vector<unsigned>::const_iterator 290 I = FilterIds.begin(), E = FilterIds.end(); I != E; ++I) { 291 FilterOffsets.push_back(Offset); 292 Offset -= TargetAsmInfo::getULEB128Size(*I); 293 } 294 295 FirstActions.reserve(LandingPads.size()); 296 297 int FirstAction = 0; 298 unsigned SizeActions = 0; 299 const LandingPadInfo *PrevLPI = 0; 300 301 for (SmallVectorImpl<const LandingPadInfo *>::const_iterator 302 I = LandingPads.begin(), E = LandingPads.end(); I != E; ++I) { 303 const LandingPadInfo *LPI = *I; 304 const std::vector<int> &TypeIds = LPI->TypeIds; 305 const unsigned NumShared = PrevLPI ? SharedTypeIds(LPI, PrevLPI) : 0; 306 unsigned SizeSiteActions = 0; 307 308 if (NumShared < TypeIds.size()) { 309 unsigned SizeAction = 0; 310 ActionEntry *PrevAction = 0; 311 312 if (NumShared) { 313 const unsigned SizePrevIds = PrevLPI->TypeIds.size(); 314 assert(Actions.size()); 315 PrevAction = &Actions.back(); 316 SizeAction = TargetAsmInfo::getSLEB128Size(PrevAction->NextAction) + 317 TargetAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); 318 319 for (unsigned j = NumShared; j != SizePrevIds; ++j) { 320 SizeAction -= 321 TargetAsmInfo::getSLEB128Size(PrevAction->ValueForTypeID); 322 SizeAction += -PrevAction->NextAction; 323 PrevAction = PrevAction->Previous; 324 } 325 } 326 327 // Compute the actions. 328 for (unsigned J = NumShared, M = TypeIds.size(); J != M; ++J) { 329 int TypeID = TypeIds[J]; 330 assert(-1 - TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); 331 int ValueForTypeID = TypeID < 0 ? FilterOffsets[-1 - TypeID] : TypeID; 332 unsigned SizeTypeID = TargetAsmInfo::getSLEB128Size(ValueForTypeID); 333 334 int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; 335 SizeAction = SizeTypeID + TargetAsmInfo::getSLEB128Size(NextAction); 336 SizeSiteActions += SizeAction; 337 338 ActionEntry Action = {ValueForTypeID, NextAction, PrevAction}; 339 Actions.push_back(Action); 340 PrevAction = &Actions.back(); 341 } 342 343 // Record the first action of the landing pad site. 344 FirstAction = SizeActions + SizeSiteActions - SizeAction + 1; 345 } // else identical - re-use previous FirstAction 346 347 FirstActions.push_back(FirstAction); 348 349 // Compute this sites contribution to size. 350 SizeActions += SizeSiteActions; 351 352 PrevLPI = LPI; 353 } 354 355 return SizeActions; 356} 357 358/// ComputeCallSiteTable - Compute the call-site table. The entry for an invoke 359/// has a try-range containing the call, a non-zero landing pad and an 360/// appropriate action. The entry for an ordinary call has a try-range 361/// containing the call and zero for the landing pad and the action. Calls 362/// marked 'nounwind' have no entry and must not be contained in the try-range 363/// of any entry - they form gaps in the table. Entries must be ordered by 364/// try-range address. 365void DwarfException:: 366ComputeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, 367 const RangeMapType &PadMap, 368 const SmallVectorImpl<const LandingPadInfo *> &LandingPads, 369 const SmallVectorImpl<unsigned> &FirstActions) { 370 // The end label of the previous invoke or nounwind try-range. 371 unsigned LastLabel = 0; 372 373 // Whether there is a potentially throwing instruction (currently this means 374 // an ordinary call) between the end of the previous try-range and now. 375 bool SawPotentiallyThrowing = false; 376 377 // Whether the last CallSite entry was for an invoke. 378 bool PreviousIsInvoke = false; 379 380 // Visit all instructions in order of address. 381 for (MachineFunction::const_iterator I = MF->begin(), E = MF->end(); 382 I != E; ++I) { 383 for (MachineBasicBlock::const_iterator MI = I->begin(), E = I->end(); 384 MI != E; ++MI) { 385 if (!MI->isLabel()) { 386 SawPotentiallyThrowing |= MI->getDesc().isCall(); 387 continue; 388 } 389 390 unsigned BeginLabel = MI->getOperand(0).getImm(); 391 assert(BeginLabel && "Invalid label!"); 392 393 // End of the previous try-range? 394 if (BeginLabel == LastLabel) 395 SawPotentiallyThrowing = false; 396 397 // Beginning of a new try-range? 398 RangeMapType::iterator L = PadMap.find(BeginLabel); 399 if (L == PadMap.end()) 400 // Nope, it was just some random label. 401 continue; 402 403 PadRange P = L->second; 404 const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; 405 assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && 406 "Inconsistent landing pad map!"); 407 408 // If some instruction between the previous try-range and this one may 409 // throw, create a call-site entry with no landing pad for the region 410 // between the try-ranges. 411 if (SawPotentiallyThrowing) { 412 CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0}; 413 CallSites.push_back(Site); 414 PreviousIsInvoke = false; 415 } 416 417 LastLabel = LandingPad->EndLabels[P.RangeIndex]; 418 assert(BeginLabel && LastLabel && "Invalid landing pad!"); 419 420 if (LandingPad->LandingPadLabel) { 421 // This try-range is for an invoke. 422 CallSiteEntry Site = {BeginLabel, LastLabel, 423 LandingPad->LandingPadLabel, 424 FirstActions[P.PadIndex]}; 425 426 // Try to merge with the previous call-site. 427 if (PreviousIsInvoke) { 428 CallSiteEntry &Prev = CallSites.back(); 429 if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { 430 // Extend the range of the previous entry. 431 Prev.EndLabel = Site.EndLabel; 432 continue; 433 } 434 } 435 436 // Otherwise, create a new call-site. 437 CallSites.push_back(Site); 438 PreviousIsInvoke = true; 439 } else { 440 // Create a gap. 441 PreviousIsInvoke = false; 442 } 443 } 444 } 445 446 // If some instruction between the previous try-range and the end of the 447 // function may throw, create a call-site entry with no landing pad for the 448 // region following the try-range. 449 if (SawPotentiallyThrowing) { 450 CallSiteEntry Site = {LastLabel, 0, 0, 0}; 451 CallSites.push_back(Site); 452 } 453} 454 455/// EmitExceptionTable - Emit landing pads and actions. 456/// 457/// The general organization of the table is complex, but the basic concepts are 458/// easy. First there is a header which describes the location and organization 459/// of the three components that follow. 460/// 461/// 1. The landing pad site information describes the range of code covered by 462/// the try. In our case it's an accumulation of the ranges covered by the 463/// invokes in the try. There is also a reference to the landing pad that 464/// handles the exception once processed. Finally an index into the actions 465/// table. 466/// 2. The action table, in our case, is composed of pairs of type ids and next 467/// action offset. Starting with the action index from the landing pad 468/// site, each type Id is checked for a match to the current exception. If 469/// it matches then the exception and type id are passed on to the landing 470/// pad. Otherwise the next action is looked up. This chain is terminated 471/// with a next action of zero. If no type id is found the the frame is 472/// unwound and handling continues. 473/// 3. Type id table contains references to all the C++ typeinfo for all 474/// catches in the function. This tables is reversed indexed base 1. 475void DwarfException::EmitExceptionTable() { 476 const std::vector<GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); 477 const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); 478 const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads(); 479 if (PadInfos.empty()) return; 480 481 // Sort the landing pads in order of their type ids. This is used to fold 482 // duplicate actions. 483 SmallVector<const LandingPadInfo *, 64> LandingPads; 484 LandingPads.reserve(PadInfos.size()); 485 486 for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) 487 LandingPads.push_back(&PadInfos[i]); 488 489 std::sort(LandingPads.begin(), LandingPads.end(), PadLT); 490 491 // Compute the actions table and gather the first action index for each 492 // landing pad site. 493 SmallVector<ActionEntry, 32> Actions; 494 SmallVector<unsigned, 64> FirstActions; 495 unsigned SizeActions = ComputeActionsTable(LandingPads, Actions, FirstActions); 496 497 // Invokes and nounwind calls have entries in PadMap (due to being bracketed 498 // by try-range labels when lowered). Ordinary calls do not, so appropriate 499 // try-ranges for them need be deduced. 500 RangeMapType PadMap; 501 for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { 502 const LandingPadInfo *LandingPad = LandingPads[i]; 503 for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) { 504 unsigned BeginLabel = LandingPad->BeginLabels[j]; 505 assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); 506 PadRange P = { i, j }; 507 PadMap[BeginLabel] = P; 508 } 509 } 510 511 // Compute the call-site table. 512 SmallVector<CallSiteEntry, 64> CallSites; 513 ComputeCallSiteTable(CallSites, PadMap, LandingPads, FirstActions); 514 515 // Final tallies. 516 517 // Call sites. 518 const unsigned SiteStartSize = sizeof(int32_t); // DW_EH_PE_udata4 519 const unsigned SiteLengthSize = sizeof(int32_t); // DW_EH_PE_udata4 520 const unsigned LandingPadSize = sizeof(int32_t); // DW_EH_PE_udata4 521 unsigned SizeSites = CallSites.size() * (SiteStartSize + 522 SiteLengthSize + 523 LandingPadSize); 524 for (unsigned i = 0, e = CallSites.size(); i < e; ++i) 525 SizeSites += TargetAsmInfo::getULEB128Size(CallSites[i].Action); 526 527 // Type infos. 528 const unsigned TypeInfoSize = TD->getPointerSize(); // DW_EH_PE_absptr 529 unsigned SizeTypes = TypeInfos.size() * TypeInfoSize; 530 531 unsigned TypeOffset = sizeof(int8_t) + // Call site format 532 TargetAsmInfo::getULEB128Size(SizeSites) + // Call-site table length 533 SizeSites + SizeActions + SizeTypes; 534 535 unsigned TotalSize = sizeof(int8_t) + // LPStart format 536 sizeof(int8_t) + // TType format 537 TargetAsmInfo::getULEB128Size(TypeOffset) + // TType base offset 538 TypeOffset; 539 540 unsigned SizeAlign = (4 - TotalSize) & 3; 541 542 // Begin the exception table. 543 const MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection(); 544 Asm->SwitchToSection(LSDASection); 545 Asm->EmitAlignment(2, 0, 0, false); 546 O << "GCC_except_table" << SubprogramCount << ":\n"; 547 548 for (unsigned i = 0; i != SizeAlign; ++i) { 549 Asm->EmitInt8(0); 550 Asm->EOL("Padding"); 551 } 552 553 EmitLabel("exception", SubprogramCount); 554 555 // Emit the header. 556 Asm->EmitInt8(dwarf::DW_EH_PE_omit); 557 Asm->EOL("LPStart format (DW_EH_PE_omit)"); 558 559#if 0 560 if (TypeInfos.empty() && FilterIds.empty()) { 561 // If there are no typeinfos or filters, there is nothing to emit, optimize 562 // by specifying the "omit" encoding. 563 Asm->EmitInt8(dwarf::DW_EH_PE_omit); 564 Asm->EOL("TType format (DW_EH_PE_omit)"); 565 } else { 566 // Okay, we have actual filters or typeinfos to emit. As such, we need to 567 // pick a type encoding for them. We're about to emit a list of pointers to 568 // typeinfo objects at the end of the LSDA. However, unless we're in static 569 // mode, this reference will require a relocation by the dynamic linker. 570 // 571 // Because of this, we have a couple of options: 572 // 1) If we are in -static mode, we can always use an absolute reference 573 // from the LSDA, because the static linker will resolve it. 574 // 2) Otherwise, if the LSDA section is writable, we can output the direct 575 // reference to the typeinfo and allow the dynamic linker to relocate 576 // it. Since it is in a writable section, the dynamic linker won't 577 // have a problem. 578 // 3) Finally, if we're in PIC mode and the LDSA section isn't writable, 579 // we need to use some form of indirection. For example, on Darwin, 580 // we can output a statically-relocatable reference to a dyld stub. The 581 // offset to the stub is constant, but the contents are in a section 582 // that is updated by the dynamic linker. This is easy enough, but we 583 // need to tell the personality function of the unwinder to indirect 584 // through the dyld stub. 585 // 586 // FIXME: When this is actually implemented, we'll have to emit the stubs 587 // somewhere. This predicate should be moved to a shared location that is 588 // in target-independent code. 589 // 590 if (LSDASection->isWritable() || 591 Asm->TM.getRelocationModel() == Reloc::Static) { 592 Asm->EmitInt8(DW_EH_PE_absptr); 593 Asm->EOL("TType format (DW_EH_PE_absptr)"); 594 } else { 595 Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_indirect | DW_EH_PE_sdata4); 596 Asm->EOL("TType format (DW_EH_PE_pcrel | DW_EH_PE_indirect" 597 " | DW_EH_PE_sdata4)"); 598 } 599 Asm->EmitULEB128Bytes(TypeOffset); 600 Asm->EOL("TType base offset"); 601 } 602#else 603 Asm->EmitInt8(dwarf::DW_EH_PE_absptr); 604 Asm->EOL("TType format (DW_EH_PE_absptr)"); 605 Asm->EmitULEB128Bytes(TypeOffset); 606 Asm->EOL("TType base offset"); 607#endif 608 609 Asm->EmitInt8(dwarf::DW_EH_PE_udata4); 610 Asm->EOL("Call site format (DW_EH_PE_udata4)"); 611 Asm->EmitULEB128Bytes(SizeSites); 612 Asm->EOL("Call-site table length"); 613 614 // Emit the landing pad site information. 615 for (SmallVectorImpl<CallSiteEntry>::const_iterator 616 I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { 617 const CallSiteEntry &S = *I; 618 const char *BeginTag; 619 unsigned BeginNumber; 620 621 if (!S.BeginLabel) { 622 BeginTag = "eh_func_begin"; 623 BeginNumber = SubprogramCount; 624 } else { 625 BeginTag = "label"; 626 BeginNumber = S.BeginLabel; 627 } 628 629 EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount, 630 true, true); 631 Asm->EOL("Region start"); 632 633 if (!S.EndLabel) 634 EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber, 635 true); 636 else 637 EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true); 638 639 Asm->EOL("Region length"); 640 641 if (!S.PadLabel) 642 Asm->EmitInt32(0); 643 else 644 EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount, 645 true, true); 646 647 Asm->EOL("Landing pad"); 648 649 Asm->EmitULEB128Bytes(S.Action); 650 Asm->EOL("Action"); 651 } 652 653 // Emit the actions. 654 for (SmallVectorImpl<ActionEntry>::const_iterator 655 I = Actions.begin(), E = Actions.end(); I != E; ++I) { 656 const ActionEntry &Action = *I; 657 Asm->EmitSLEB128Bytes(Action.ValueForTypeID); 658 Asm->EOL("TypeInfo index"); 659 Asm->EmitSLEB128Bytes(Action.NextAction); 660 Asm->EOL("Next action"); 661 } 662 663 // Emit the type ids. 664 for (std::vector<GlobalVariable *>::const_reverse_iterator 665 I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { 666 GlobalVariable *GV = *I; 667 PrintRelDirective(); 668 669 if (GV) { 670 std::string GLN; 671 O << Asm->getGlobalLinkName(GV, GLN); 672 } else { 673 O << "0"; 674 } 675 676 Asm->EOL("TypeInfo"); 677 } 678 679 // Emit the filter typeids. 680 for (std::vector<unsigned>::const_iterator 681 I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { 682 unsigned TypeID = *I; 683 Asm->EmitULEB128Bytes(TypeID); 684 Asm->EOL("Filter TypeInfo index"); 685 } 686 687 Asm->EmitAlignment(2, 0, 0, false); 688} 689 690/// EndModule - Emit all exception information that should come after the 691/// content. 692void DwarfException::EndModule() { 693 if (TimePassesIsEnabled) 694 ExceptionTimer->startTimer(); 695 696 if (shouldEmitMovesModule || shouldEmitTableModule) { 697 const std::vector<Function *> Personalities = MMI->getPersonalities(); 698 for (unsigned i = 0; i < Personalities.size(); ++i) 699 EmitCommonEHFrame(Personalities[i], i); 700 701 for (std::vector<FunctionEHFrameInfo>::iterator I = EHFrames.begin(), 702 E = EHFrames.end(); I != E; ++I) 703 EmitEHFrame(*I); 704 } 705 706 if (TimePassesIsEnabled) 707 ExceptionTimer->stopTimer(); 708} 709 710/// BeginFunction - Gather pre-function exception information. Assumes being 711/// emitted immediately after the function entry point. 712void DwarfException::BeginFunction(MachineFunction *MF) { 713 if (TimePassesIsEnabled) 714 ExceptionTimer->startTimer(); 715 716 this->MF = MF; 717 shouldEmitTable = shouldEmitMoves = false; 718 719 if (MMI && TAI->doesSupportExceptionHandling()) { 720 // Map all labels and get rid of any dead landing pads. 721 MMI->TidyLandingPads(); 722 723 // If any landing pads survive, we need an EH table. 724 if (MMI->getLandingPads().size()) 725 shouldEmitTable = true; 726 727 // See if we need frame move info. 728 if (!MF->getFunction()->doesNotThrow() || UnwindTablesMandatory) 729 shouldEmitMoves = true; 730 731 if (shouldEmitMoves || shouldEmitTable) 732 // Assumes in correct section after the entry point. 733 EmitLabel("eh_func_begin", ++SubprogramCount); 734 } 735 736 shouldEmitTableModule |= shouldEmitTable; 737 shouldEmitMovesModule |= shouldEmitMoves; 738 739 if (TimePassesIsEnabled) 740 ExceptionTimer->stopTimer(); 741} 742 743/// EndFunction - Gather and emit post-function exception information. 744/// 745void DwarfException::EndFunction() { 746 if (TimePassesIsEnabled) 747 ExceptionTimer->startTimer(); 748 749 if (shouldEmitMoves || shouldEmitTable) { 750 EmitLabel("eh_func_end", SubprogramCount); 751 EmitExceptionTable(); 752 753 // Save EH frame information 754 EHFrames.push_back( 755 FunctionEHFrameInfo(getAsm()->getCurrentFunctionEHName(MF), 756 SubprogramCount, 757 MMI->getPersonalityIndex(), 758 MF->getFrameInfo()->hasCalls(), 759 !MMI->getLandingPads().empty(), 760 MMI->getFrameMoves(), 761 MF->getFunction())); 762 } 763 764 if (TimePassesIsEnabled) 765 ExceptionTimer->stopTimer(); 766} 767