DwarfException.cpp revision 2c3026df5ac39a51016de56a1c80812455747c4a
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 // For Dwarf exception handling (SjLj handling doesn't use this) 409 // If some instruction between the previous try-range and this one may 410 // throw, create a call-site entry with no landing pad for the region 411 // between the try-ranges. 412 if (SawPotentiallyThrowing && 413 TAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { 414 CallSiteEntry Site = {LastLabel, BeginLabel, 0, 0}; 415 CallSites.push_back(Site); 416 PreviousIsInvoke = false; 417 } 418 419 LastLabel = LandingPad->EndLabels[P.RangeIndex]; 420 assert(BeginLabel && LastLabel && "Invalid landing pad!"); 421 422 if (LandingPad->LandingPadLabel) { 423 // This try-range is for an invoke. 424 CallSiteEntry Site = {BeginLabel, LastLabel, 425 LandingPad->LandingPadLabel, 426 FirstActions[P.PadIndex]}; 427 428 // Try to merge with the previous call-site. 429 if (PreviousIsInvoke) { 430 CallSiteEntry &Prev = CallSites.back(); 431 if (Site.PadLabel == Prev.PadLabel && Site.Action == Prev.Action) { 432 // Extend the range of the previous entry. 433 Prev.EndLabel = Site.EndLabel; 434 continue; 435 } 436 } 437 438 // Otherwise, create a new call-site. 439 CallSites.push_back(Site); 440 PreviousIsInvoke = true; 441 } else { 442 // Create a gap. 443 PreviousIsInvoke = false; 444 } 445 } 446 } 447 448 // If some instruction between the previous try-range and the end of the 449 // function may throw, create a call-site entry with no landing pad for the 450 // region following the try-range. 451 if (SawPotentiallyThrowing && 452 TAI->getExceptionHandlingType() == ExceptionHandling::Dwarf) { 453 CallSiteEntry Site = {LastLabel, 0, 0, 0}; 454 CallSites.push_back(Site); 455 } 456} 457 458/// EmitExceptionTable - Emit landing pads and actions. 459/// 460/// The general organization of the table is complex, but the basic concepts are 461/// easy. First there is a header which describes the location and organization 462/// of the three components that follow. 463/// 464/// 1. The landing pad site information describes the range of code covered by 465/// the try. In our case it's an accumulation of the ranges covered by the 466/// invokes in the try. There is also a reference to the landing pad that 467/// handles the exception once processed. Finally an index into the actions 468/// table. 469/// 2. The action table, in our case, is composed of pairs of type ids and next 470/// action offset. Starting with the action index from the landing pad 471/// site, each type Id is checked for a match to the current exception. If 472/// it matches then the exception and type id are passed on to the landing 473/// pad. Otherwise the next action is looked up. This chain is terminated 474/// with a next action of zero. If no type id is found the the frame is 475/// unwound and handling continues. 476/// 3. Type id table contains references to all the C++ typeinfo for all 477/// catches in the function. This tables is reversed indexed base 1. 478void DwarfException::EmitExceptionTable() { 479 const std::vector<GlobalVariable *> &TypeInfos = MMI->getTypeInfos(); 480 const std::vector<unsigned> &FilterIds = MMI->getFilterIds(); 481 const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads(); 482 if (PadInfos.empty()) return; 483 484 // Sort the landing pads in order of their type ids. This is used to fold 485 // duplicate actions. 486 SmallVector<const LandingPadInfo *, 64> LandingPads; 487 LandingPads.reserve(PadInfos.size()); 488 489 for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) 490 LandingPads.push_back(&PadInfos[i]); 491 492 std::sort(LandingPads.begin(), LandingPads.end(), PadLT); 493 494 // Compute the actions table and gather the first action index for each 495 // landing pad site. 496 SmallVector<ActionEntry, 32> Actions; 497 SmallVector<unsigned, 64> FirstActions; 498 unsigned SizeActions = ComputeActionsTable(LandingPads, Actions, FirstActions); 499 500 // Invokes and nounwind calls have entries in PadMap (due to being bracketed 501 // by try-range labels when lowered). Ordinary calls do not, so appropriate 502 // try-ranges for them need be deduced when using Dwarf exception handling. 503 RangeMapType PadMap; 504 for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { 505 const LandingPadInfo *LandingPad = LandingPads[i]; 506 for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) { 507 unsigned BeginLabel = LandingPad->BeginLabels[j]; 508 assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); 509 PadRange P = { i, j }; 510 PadMap[BeginLabel] = P; 511 } 512 } 513 514 // Compute the call-site table. 515 SmallVector<CallSiteEntry, 64> CallSites; 516 ComputeCallSiteTable(CallSites, PadMap, LandingPads, FirstActions); 517 518 // Final tallies. 519 520 // Call sites. 521 const unsigned SiteStartSize = sizeof(int32_t); // DW_EH_PE_udata4 522 const unsigned SiteLengthSize = sizeof(int32_t); // DW_EH_PE_udata4 523 const unsigned LandingPadSize = sizeof(int32_t); // DW_EH_PE_udata4 524 unsigned SizeSites; 525 526 bool HaveTTData = (TAI->getExceptionHandlingType() == ExceptionHandling::SjLj) 527 ? (!TypeInfos.empty() || !FilterIds.empty()) : true; 528 529 530 if (TAI->getExceptionHandlingType() == ExceptionHandling::SjLj) { 531 SizeSites = 0; 532 } else 533 SizeSites = CallSites.size() * 534 (SiteStartSize + SiteLengthSize + LandingPadSize); 535 for (unsigned i = 0, e = CallSites.size(); i < e; ++i) { 536 SizeSites += TargetAsmInfo::getULEB128Size(CallSites[i].Action); 537 if (TAI->getExceptionHandlingType() == ExceptionHandling::SjLj) 538 SizeSites += TargetAsmInfo::getULEB128Size(i); 539 } 540 // Type infos. 541 const unsigned TypeInfoSize = TD->getPointerSize(); // DW_EH_PE_absptr 542 unsigned SizeTypes = TypeInfos.size() * TypeInfoSize; 543 544 unsigned TypeOffset = sizeof(int8_t) + // Call site format 545 TargetAsmInfo::getULEB128Size(SizeSites) + // Call-site table length 546 SizeSites + SizeActions + SizeTypes; 547 548 unsigned TotalSize = sizeof(int8_t) + // LPStart format 549 sizeof(int8_t) + // TType format 550 (HaveTTData ? 551 TargetAsmInfo::getULEB128Size(TypeOffset) : 0) + // TType base offset 552 TypeOffset; 553 554 unsigned SizeAlign = (4 - TotalSize) & 3; 555 556 // Begin the exception table. 557 const MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection(); 558 Asm->SwitchToSection(LSDASection); 559 Asm->EmitAlignment(2, 0, 0, false); 560 O << "GCC_except_table" << SubprogramCount << ":\n"; 561 562 for (unsigned i = 0; i != SizeAlign; ++i) { 563 Asm->EmitInt8(0); 564 Asm->EOL("Padding"); 565 } 566 567 EmitLabel("exception", SubprogramCount); 568 if (TAI->getExceptionHandlingType() == ExceptionHandling::SjLj) { 569 std::string SjLjName = "_lsda_"; 570 SjLjName += MF->getFunction()->getName().str(); 571 EmitLabel(SjLjName.c_str(), 0); 572 } 573 574 // Emit the header. 575 Asm->EmitInt8(dwarf::DW_EH_PE_omit); 576 Asm->EOL("LPStart format (DW_EH_PE_omit)"); 577 578#if 0 579 if (TypeInfos.empty() && FilterIds.empty()) { 580 // If there are no typeinfos or filters, there is nothing to emit, optimize 581 // by specifying the "omit" encoding. 582 Asm->EmitInt8(dwarf::DW_EH_PE_omit); 583 Asm->EOL("TType format (DW_EH_PE_omit)"); 584 } else { 585 // Okay, we have actual filters or typeinfos to emit. As such, we need to 586 // pick a type encoding for them. We're about to emit a list of pointers to 587 // typeinfo objects at the end of the LSDA. However, unless we're in static 588 // mode, this reference will require a relocation by the dynamic linker. 589 // 590 // Because of this, we have a couple of options: 591 // 1) If we are in -static mode, we can always use an absolute reference 592 // from the LSDA, because the static linker will resolve it. 593 // 2) Otherwise, if the LSDA section is writable, we can output the direct 594 // reference to the typeinfo and allow the dynamic linker to relocate 595 // it. Since it is in a writable section, the dynamic linker won't 596 // have a problem. 597 // 3) Finally, if we're in PIC mode and the LDSA section isn't writable, 598 // we need to use some form of indirection. For example, on Darwin, 599 // we can output a statically-relocatable reference to a dyld stub. The 600 // offset to the stub is constant, but the contents are in a section 601 // that is updated by the dynamic linker. This is easy enough, but we 602 // need to tell the personality function of the unwinder to indirect 603 // through the dyld stub. 604 // 605 // FIXME: When this is actually implemented, we'll have to emit the stubs 606 // somewhere. This predicate should be moved to a shared location that is 607 // in target-independent code. 608 // 609 if (LSDASection->isWritable() || 610 Asm->TM.getRelocationModel() == Reloc::Static) { 611 Asm->EmitInt8(DW_EH_PE_absptr); 612 Asm->EOL("TType format (DW_EH_PE_absptr)"); 613 } else { 614 Asm->EmitInt8(DW_EH_PE_pcrel | DW_EH_PE_indirect | DW_EH_PE_sdata4); 615 Asm->EOL("TType format (DW_EH_PE_pcrel | DW_EH_PE_indirect" 616 " | DW_EH_PE_sdata4)"); 617 } 618 Asm->EmitULEB128Bytes(TypeOffset); 619 Asm->EOL("TType base offset"); 620 } 621#else 622 // For SjLj exceptions, if there is no TypeInfo, then we just explicitly 623 // say that we're omitting that bit. 624 // FIXME: does this apply to Dwarf also? The above #if 0 implies yes? 625 if (!HaveTTData) { 626 Asm->EmitInt8(dwarf::DW_EH_PE_omit); 627 Asm->EOL("TType format (DW_EH_PE_omit)"); 628 } else { 629 Asm->EmitInt8(dwarf::DW_EH_PE_absptr); 630 Asm->EOL("TType format (DW_EH_PE_absptr)"); 631 Asm->EmitULEB128Bytes(TypeOffset); 632 Asm->EOL("TType base offset"); 633 } 634#endif 635 636 // SjLj Exception handilng 637 if (TAI->getExceptionHandlingType() == ExceptionHandling::SjLj) { 638 Asm->EmitInt8(dwarf::DW_EH_PE_udata4); 639 Asm->EOL("Call site format (DW_EH_PE_udata4)"); 640 Asm->EmitULEB128Bytes(SizeSites); 641 Asm->EOL("Call-site table length"); 642 643 // Emit the landing pad site information. 644 unsigned idx = 0; 645 for (SmallVectorImpl<CallSiteEntry>::const_iterator 646 I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) { 647 const CallSiteEntry &S = *I; 648 Asm->EmitULEB128Bytes(idx); 649 Asm->EOL("Landing pad"); 650 Asm->EmitULEB128Bytes(S.Action); 651 Asm->EOL("Action"); 652 } 653 } else { 654 // DWARF Exception handling 655 assert(TAI->getExceptionHandlingType() == ExceptionHandling::Dwarf); 656 657 Asm->EmitInt8(dwarf::DW_EH_PE_udata4); 658 Asm->EOL("Call site format (DW_EH_PE_udata4)"); 659 Asm->EmitULEB128Bytes(SizeSites); 660 Asm->EOL("Call-site table length"); 661 662 // Emit the landing pad site information. 663 for (SmallVectorImpl<CallSiteEntry>::const_iterator 664 I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { 665 const CallSiteEntry &S = *I; 666 const char *BeginTag; 667 unsigned BeginNumber; 668 669 if (!S.BeginLabel) { 670 BeginTag = "eh_func_begin"; 671 BeginNumber = SubprogramCount; 672 } else { 673 BeginTag = "label"; 674 BeginNumber = S.BeginLabel; 675 } 676 677 EmitSectionOffset(BeginTag, "eh_func_begin", BeginNumber, SubprogramCount, 678 true, true); 679 Asm->EOL("Region start"); 680 681 if (!S.EndLabel) 682 EmitDifference("eh_func_end", SubprogramCount, BeginTag, BeginNumber, 683 true); 684 else 685 EmitDifference("label", S.EndLabel, BeginTag, BeginNumber, true); 686 687 Asm->EOL("Region length"); 688 689 if (!S.PadLabel) 690 Asm->EmitInt32(0); 691 else 692 EmitSectionOffset("label", "eh_func_begin", S.PadLabel, SubprogramCount, 693 true, true); 694 695 Asm->EOL("Landing pad"); 696 697 Asm->EmitULEB128Bytes(S.Action); 698 Asm->EOL("Action"); 699 } 700 } 701 702 // Emit the actions. 703 for (SmallVectorImpl<ActionEntry>::const_iterator 704 I = Actions.begin(), E = Actions.end(); I != E; ++I) { 705 const ActionEntry &Action = *I; 706 Asm->EmitSLEB128Bytes(Action.ValueForTypeID); 707 Asm->EOL("TypeInfo index"); 708 Asm->EmitSLEB128Bytes(Action.NextAction); 709 Asm->EOL("Next action"); 710 } 711 712 // Emit the type ids. 713 for (std::vector<GlobalVariable *>::const_reverse_iterator 714 I = TypeInfos.rbegin(), E = TypeInfos.rend(); I != E; ++I) { 715 GlobalVariable *GV = *I; 716 PrintRelDirective(); 717 718 if (GV) { 719 std::string GLN; 720 O << Asm->getGlobalLinkName(GV, GLN); 721 } else { 722 O << "0"; 723 } 724 725 Asm->EOL("TypeInfo"); 726 } 727 728 // Emit the filter typeids. 729 for (std::vector<unsigned>::const_iterator 730 I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { 731 unsigned TypeID = *I; 732 Asm->EmitULEB128Bytes(TypeID); 733 Asm->EOL("Filter TypeInfo index"); 734 } 735 736 Asm->EmitAlignment(2, 0, 0, false); 737} 738 739/// EndModule - Emit all exception information that should come after the 740/// content. 741void DwarfException::EndModule() { 742 if (TAI->getExceptionHandlingType() != ExceptionHandling::Dwarf) 743 return; 744 if (TimePassesIsEnabled) 745 ExceptionTimer->startTimer(); 746 747 if (shouldEmitMovesModule || shouldEmitTableModule) { 748 const std::vector<Function *> Personalities = MMI->getPersonalities(); 749 for (unsigned i = 0; i < Personalities.size(); ++i) 750 EmitCommonEHFrame(Personalities[i], i); 751 752 for (std::vector<FunctionEHFrameInfo>::iterator I = EHFrames.begin(), 753 E = EHFrames.end(); I != E; ++I) 754 EmitEHFrame(*I); 755 } 756 757 if (TimePassesIsEnabled) 758 ExceptionTimer->stopTimer(); 759} 760 761/// BeginFunction - Gather pre-function exception information. Assumes being 762/// emitted immediately after the function entry point. 763void DwarfException::BeginFunction(MachineFunction *MF) { 764 if (TimePassesIsEnabled) 765 ExceptionTimer->startTimer(); 766 767 this->MF = MF; 768 shouldEmitTable = shouldEmitMoves = false; 769 770 if (MMI && TAI->doesSupportExceptionHandling()) { 771 // Map all labels and get rid of any dead landing pads. 772 MMI->TidyLandingPads(); 773 774 // If any landing pads survive, we need an EH table. 775 if (MMI->getLandingPads().size()) 776 shouldEmitTable = true; 777 778 // See if we need frame move info. 779 if (!MF->getFunction()->doesNotThrow() || UnwindTablesMandatory) 780 shouldEmitMoves = true; 781 782 if (shouldEmitMoves || shouldEmitTable) 783 // Assumes in correct section after the entry point. 784 EmitLabel("eh_func_begin", ++SubprogramCount); 785 } 786 787 shouldEmitTableModule |= shouldEmitTable; 788 shouldEmitMovesModule |= shouldEmitMoves; 789 790 if (TimePassesIsEnabled) 791 ExceptionTimer->stopTimer(); 792} 793 794/// EndFunction - Gather and emit post-function exception information. 795/// 796void DwarfException::EndFunction() { 797 if (TimePassesIsEnabled) 798 ExceptionTimer->startTimer(); 799 800 if (shouldEmitMoves || shouldEmitTable) { 801 EmitLabel("eh_func_end", SubprogramCount); 802 EmitExceptionTable(); 803 804 // Save EH frame information 805 EHFrames.push_back( 806 FunctionEHFrameInfo(getAsm()->getCurrentFunctionEHName(MF), 807 SubprogramCount, 808 MMI->getPersonalityIndex(), 809 MF->getFrameInfo()->hasCalls(), 810 !MMI->getLandingPads().empty(), 811 MMI->getFrameMoves(), 812 MF->getFunction())); 813 } 814 815 if (TimePassesIsEnabled) 816 ExceptionTimer->stopTimer(); 817} 818