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