DwarfException.cpp revision 3d7780580131bf5a736412bcc3b11610721bd3e2
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->SwitchToTextSection(TAI->getDwarfEHFrameSection()); 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->SwitchToTextSection(TAI->getDwarfEHFrameSection()); 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 // FIXME: This should default to what the system wants, not just "absptr". 561 if (TypeInfos.empty() && FilterIds.empty()) { 562 Asm->EmitInt8(dwarf::DW_EH_PE_omit); 563 Asm->EOL("TType format (DW_EH_PE_omit)"); 564 } else { 565 // FIXME: Instead of using "PreferredEHDataFormat", we should use a simple 566 // approach to determine what needs to happen. Basically, if the target 567 // wants the LSDA to be emitted into a read-only segment (like .text) then 568 // (unless in static mode) it can't output direct pointers to the typeinfo 569 // objects, which may be in an arbitrary locations. Instead, it has to use 570 // and indirect stub pointer to get to the typeinfo. 571 // 572 // If the target wants to dump the LSDA's into a segment writable by the 573 // dynamic linker, then it can just use a normal pointer, and the dynamic 574 // linker will fix it up. 575 576 // TODO: Replace the getDwarfExceptionSection() callback on TAI with a new 577 // getLSDASection() method on TLOF. Merge and sanitize the implementations, 578 // and figure out what the ".gcc_except_table" directive expands to on elf 579 // systems. 580 581 // 582 //if (LSDASection->isWritable()) { 583 //Asm->EmitInt8(DW_EH_PE_absptr); 584 //} else { 585 //Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_indirect | DW_EH_PE_sdata4); 586 //} 587 588 Asm->EmitInt8(TAI->PreferredEHDataFormat()); 589 590 591 // FIXME: The comment here should correspond with what PreferredEHDataFormat 592 // returned. 593 Asm->EOL("TType format (DW_EH_PE_xxxxx)"); 594 Asm->EmitULEB128Bytes(TypeOffset); 595 Asm->EOL("TType base offset"); 596 } 597#else 598 Asm->EmitInt8(dwarf::DW_EH_PE_absptr); 599 Asm->EOL("TType format (DW_EH_PE_absptr)"); 600 Asm->EmitULEB128Bytes(TypeOffset); 601 Asm->EOL("TType base offset"); 602#endif 603 604 Asm->EmitInt8(dwarf::DW_EH_PE_udata4); 605 Asm->EOL("Call site format (DW_EH_PE_udata4)"); 606 Asm->EmitULEB128Bytes(SizeSites); 607 Asm->EOL("Call-site table length"); 608 609 // Emit the landing pad site information. 610 for (SmallVectorImpl<CallSiteEntry>::const_iterator 611 I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { 612 const CallSiteEntry &S = *I; 613 const char *BeginTag; 614 unsigned BeginNumber; 615 616 if (!S.BeginLabel) { 617 BeginTag = "eh_func_begin"; 618 BeginNumber = SubprogramCount; 619 } else { 620 BeginTag = "label"; 621 BeginNumber = S.BeginLabel; 622 } 623 624 EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount, 625 true, true); 626 Asm->EOL("Region start"); 627 628 if (!S.EndLabel) 629 EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber, 630 true); 631 else 632 EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true); 633 634 Asm->EOL("Region length"); 635 636 if (!S.PadLabel) 637 Asm->EmitInt32(0); 638 else 639 EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount, 640 true, true); 641 642 Asm->EOL("Landing pad"); 643 644 Asm->EmitULEB128Bytes(S.Action); 645 Asm->EOL("Action"); 646 } 647 648 // Emit the actions. 649 for (SmallVectorImpl<ActionEntry>::const_iterator 650 I = Actions.begin(), E = Actions.end(); I != E; ++I) { 651 const ActionEntry &Action = *I; 652 Asm->EmitSLEB128Bytes(Action.ValueForTypeID); 653 Asm->EOL("TypeInfo index"); 654 Asm->EmitSLEB128Bytes(Action.NextAction); 655 Asm->EOL("Next action"); 656 } 657 658 // Emit the type ids. 659 for (std::vector<GlobalVariable *>::const_reverse_iterator 660 I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { 661 GlobalVariable *GV = *I; 662 PrintRelDirective(); 663 664 if (GV) { 665 std::string GLN; 666 O << Asm->getGlobalLinkName(GV, GLN); 667 } else { 668 O << "0"; 669 } 670 671 Asm->EOL("TypeInfo"); 672 } 673 674 // Emit the filter typeids. 675 for (std::vector<unsigned>::const_iterator 676 I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { 677 unsigned TypeID = *I; 678 Asm->EmitULEB128Bytes(TypeID); 679 Asm->EOL("Filter TypeInfo index"); 680 } 681 682 Asm->EmitAlignment(2, 0, 0, false); 683} 684 685/// EndModule - Emit all exception information that should come after the 686/// content. 687void DwarfException::EndModule() { 688 if (TimePassesIsEnabled) 689 ExceptionTimer->startTimer(); 690 691 if (shouldEmitMovesModule || shouldEmitTableModule) { 692 const std::vector<Function *> Personalities = MMI->getPersonalities(); 693 for (unsigned i = 0; i < Personalities.size(); ++i) 694 EmitCommonEHFrame(Personalities[i], i); 695 696 for (std::vector<FunctionEHFrameInfo>::iterator I = EHFrames.begin(), 697 E = EHFrames.end(); I != E; ++I) 698 EmitEHFrame(*I); 699 } 700 701 if (TimePassesIsEnabled) 702 ExceptionTimer->stopTimer(); 703} 704 705/// BeginFunction - Gather pre-function exception information. Assumes being 706/// emitted immediately after the function entry point. 707void DwarfException::BeginFunction(MachineFunction *MF) { 708 if (TimePassesIsEnabled) 709 ExceptionTimer->startTimer(); 710 711 this->MF = MF; 712 shouldEmitTable = shouldEmitMoves = false; 713 714 if (MMI && TAI->doesSupportExceptionHandling()) { 715 // Map all labels and get rid of any dead landing pads. 716 MMI->TidyLandingPads(); 717 718 // If any landing pads survive, we need an EH table. 719 if (MMI->getLandingPads().size()) 720 shouldEmitTable = true; 721 722 // See if we need frame move info. 723 if (!MF->getFunction()->doesNotThrow() || UnwindTablesMandatory) 724 shouldEmitMoves = true; 725 726 if (shouldEmitMoves || shouldEmitTable) 727 // Assumes in correct section after the entry point. 728 EmitLabel("eh_func_begin", ++SubprogramCount); 729 } 730 731 shouldEmitTableModule |= shouldEmitTable; 732 shouldEmitMovesModule |= shouldEmitMoves; 733 734 if (TimePassesIsEnabled) 735 ExceptionTimer->stopTimer(); 736} 737 738/// EndFunction - Gather and emit post-function exception information. 739/// 740void DwarfException::EndFunction() { 741 if (TimePassesIsEnabled) 742 ExceptionTimer->startTimer(); 743 744 if (shouldEmitMoves || shouldEmitTable) { 745 EmitLabel("eh_func_end", SubprogramCount); 746 EmitExceptionTable(); 747 748 // Save EH frame information 749 EHFrames.push_back( 750 FunctionEHFrameInfo(getAsm()->getCurrentFunctionEHName(MF), 751 SubprogramCount, 752 MMI->getPersonalityIndex(), 753 MF->getFrameInfo()->hasCalls(), 754 !MMI->getLandingPads().empty(), 755 MMI->getFrameMoves(), 756 MF->getFunction())); 757 } 758 759 if (TimePassesIsEnabled) 760 ExceptionTimer->stopTimer(); 761} 762