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