1 //===- CodeGen/AsmPrinter/EHStreamer.cpp - Exception Directive Streamer ---===// 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 exception info into assembly files. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "EHStreamer.h" 15 #include "llvm/ADT/SmallVector.h" 16 #include "llvm/ADT/Twine.h" 17 #include "llvm/ADT/iterator_range.h" 18 #include "llvm/BinaryFormat/Dwarf.h" 19 #include "llvm/CodeGen/AsmPrinter.h" 20 #include "llvm/CodeGen/MachineFunction.h" 21 #include "llvm/CodeGen/MachineInstr.h" 22 #include "llvm/CodeGen/MachineOperand.h" 23 #include "llvm/CodeGen/TargetLoweringObjectFile.h" 24 #include "llvm/IR/DataLayout.h" 25 #include "llvm/IR/Function.h" 26 #include "llvm/MC/MCAsmInfo.h" 27 #include "llvm/MC/MCContext.h" 28 #include "llvm/MC/MCStreamer.h" 29 #include "llvm/MC/MCSymbol.h" 30 #include "llvm/MC/MCTargetOptions.h" 31 #include "llvm/Support/Casting.h" 32 #include "llvm/Support/LEB128.h" 33 #include <algorithm> 34 #include <cassert> 35 #include <cstdint> 36 #include <vector> 37 38 using namespace llvm; 39 40 EHStreamer::EHStreamer(AsmPrinter *A) : Asm(A), MMI(Asm->MMI) {} 41 42 EHStreamer::~EHStreamer() = default; 43 44 /// How many leading type ids two landing pads have in common. 45 unsigned EHStreamer::sharedTypeIDs(const LandingPadInfo *L, 46 const LandingPadInfo *R) { 47 const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds; 48 unsigned LSize = LIds.size(), RSize = RIds.size(); 49 unsigned MinSize = LSize < RSize ? LSize : RSize; 50 unsigned Count = 0; 51 52 for (; Count != MinSize; ++Count) 53 if (LIds[Count] != RIds[Count]) 54 return Count; 55 56 return Count; 57 } 58 59 /// Compute the actions table and gather the first action index for each landing 60 /// pad site. 61 unsigned EHStreamer:: 62 computeActionsTable(const SmallVectorImpl<const LandingPadInfo*> &LandingPads, 63 SmallVectorImpl<ActionEntry> &Actions, 64 SmallVectorImpl<unsigned> &FirstActions) { 65 // The action table follows the call-site table in the LSDA. The individual 66 // records are of two types: 67 // 68 // * Catch clause 69 // * Exception specification 70 // 71 // The two record kinds have the same format, with only small differences. 72 // They are distinguished by the "switch value" field: Catch clauses 73 // (TypeInfos) have strictly positive switch values, and exception 74 // specifications (FilterIds) have strictly negative switch values. Value 0 75 // indicates a catch-all clause. 76 // 77 // Negative type IDs index into FilterIds. Positive type IDs index into 78 // TypeInfos. The value written for a positive type ID is just the type ID 79 // itself. For a negative type ID, however, the value written is the 80 // (negative) byte offset of the corresponding FilterIds entry. The byte 81 // offset is usually equal to the type ID (because the FilterIds entries are 82 // written using a variable width encoding, which outputs one byte per entry 83 // as long as the value written is not too large) but can differ. This kind 84 // of complication does not occur for positive type IDs because type infos are 85 // output using a fixed width encoding. FilterOffsets[i] holds the byte 86 // offset corresponding to FilterIds[i]. 87 88 const std::vector<unsigned> &FilterIds = Asm->MF->getFilterIds(); 89 SmallVector<int, 16> FilterOffsets; 90 FilterOffsets.reserve(FilterIds.size()); 91 int Offset = -1; 92 93 for (std::vector<unsigned>::const_iterator 94 I = FilterIds.begin(), E = FilterIds.end(); I != E; ++I) { 95 FilterOffsets.push_back(Offset); 96 Offset -= getULEB128Size(*I); 97 } 98 99 FirstActions.reserve(LandingPads.size()); 100 101 int FirstAction = 0; 102 unsigned SizeActions = 0; 103 const LandingPadInfo *PrevLPI = nullptr; 104 105 for (SmallVectorImpl<const LandingPadInfo *>::const_iterator 106 I = LandingPads.begin(), E = LandingPads.end(); I != E; ++I) { 107 const LandingPadInfo *LPI = *I; 108 const std::vector<int> &TypeIds = LPI->TypeIds; 109 unsigned NumShared = PrevLPI ? sharedTypeIDs(LPI, PrevLPI) : 0; 110 unsigned SizeSiteActions = 0; 111 112 if (NumShared < TypeIds.size()) { 113 unsigned SizeAction = 0; 114 unsigned PrevAction = (unsigned)-1; 115 116 if (NumShared) { 117 unsigned SizePrevIds = PrevLPI->TypeIds.size(); 118 assert(Actions.size()); 119 PrevAction = Actions.size() - 1; 120 SizeAction = getSLEB128Size(Actions[PrevAction].NextAction) + 121 getSLEB128Size(Actions[PrevAction].ValueForTypeID); 122 123 for (unsigned j = NumShared; j != SizePrevIds; ++j) { 124 assert(PrevAction != (unsigned)-1 && "PrevAction is invalid!"); 125 SizeAction -= getSLEB128Size(Actions[PrevAction].ValueForTypeID); 126 SizeAction += -Actions[PrevAction].NextAction; 127 PrevAction = Actions[PrevAction].Previous; 128 } 129 } 130 131 // Compute the actions. 132 for (unsigned J = NumShared, M = TypeIds.size(); J != M; ++J) { 133 int TypeID = TypeIds[J]; 134 assert(-1 - TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); 135 int ValueForTypeID = 136 isFilterEHSelector(TypeID) ? FilterOffsets[-1 - TypeID] : TypeID; 137 unsigned SizeTypeID = getSLEB128Size(ValueForTypeID); 138 139 int NextAction = SizeAction ? -(SizeAction + SizeTypeID) : 0; 140 SizeAction = SizeTypeID + getSLEB128Size(NextAction); 141 SizeSiteActions += SizeAction; 142 143 ActionEntry Action = { ValueForTypeID, NextAction, PrevAction }; 144 Actions.push_back(Action); 145 PrevAction = Actions.size() - 1; 146 } 147 148 // Record the first action of the landing pad site. 149 FirstAction = SizeActions + SizeSiteActions - SizeAction + 1; 150 } // else identical - re-use previous FirstAction 151 152 // Information used when creating the call-site table. The action record 153 // field of the call site record is the offset of the first associated 154 // action record, relative to the start of the actions table. This value is 155 // biased by 1 (1 indicating the start of the actions table), and 0 156 // indicates that there are no actions. 157 FirstActions.push_back(FirstAction); 158 159 // Compute this sites contribution to size. 160 SizeActions += SizeSiteActions; 161 162 PrevLPI = LPI; 163 } 164 165 return SizeActions; 166 } 167 168 /// Return `true' if this is a call to a function marked `nounwind'. Return 169 /// `false' otherwise. 170 bool EHStreamer::callToNoUnwindFunction(const MachineInstr *MI) { 171 assert(MI->isCall() && "This should be a call instruction!"); 172 173 bool MarkedNoUnwind = false; 174 bool SawFunc = false; 175 176 for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) { 177 const MachineOperand &MO = MI->getOperand(I); 178 179 if (!MO.isGlobal()) continue; 180 181 const Function *F = dyn_cast<Function>(MO.getGlobal()); 182 if (!F) continue; 183 184 if (SawFunc) { 185 // Be conservative. If we have more than one function operand for this 186 // call, then we can't make the assumption that it's the callee and 187 // not a parameter to the call. 188 // 189 // FIXME: Determine if there's a way to say that `F' is the callee or 190 // parameter. 191 MarkedNoUnwind = false; 192 break; 193 } 194 195 MarkedNoUnwind = F->doesNotThrow(); 196 SawFunc = true; 197 } 198 199 return MarkedNoUnwind; 200 } 201 202 void EHStreamer::computePadMap( 203 const SmallVectorImpl<const LandingPadInfo *> &LandingPads, 204 RangeMapType &PadMap) { 205 // Invokes and nounwind calls have entries in PadMap (due to being bracketed 206 // by try-range labels when lowered). Ordinary calls do not, so appropriate 207 // try-ranges for them need be deduced so we can put them in the LSDA. 208 for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { 209 const LandingPadInfo *LandingPad = LandingPads[i]; 210 for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) { 211 MCSymbol *BeginLabel = LandingPad->BeginLabels[j]; 212 assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); 213 PadRange P = { i, j }; 214 PadMap[BeginLabel] = P; 215 } 216 } 217 } 218 219 /// Compute the call-site table. The entry for an invoke has a try-range 220 /// containing the call, a non-zero landing pad, and an appropriate action. The 221 /// entry for an ordinary call has a try-range containing the call and zero for 222 /// the landing pad and the action. Calls marked 'nounwind' have no entry and 223 /// must not be contained in the try-range of any entry - they form gaps in the 224 /// table. Entries must be ordered by try-range address. 225 void EHStreamer:: 226 computeCallSiteTable(SmallVectorImpl<CallSiteEntry> &CallSites, 227 const SmallVectorImpl<const LandingPadInfo *> &LandingPads, 228 const SmallVectorImpl<unsigned> &FirstActions) { 229 RangeMapType PadMap; 230 computePadMap(LandingPads, PadMap); 231 232 // The end label of the previous invoke or nounwind try-range. 233 MCSymbol *LastLabel = nullptr; 234 235 // Whether there is a potentially throwing instruction (currently this means 236 // an ordinary call) between the end of the previous try-range and now. 237 bool SawPotentiallyThrowing = false; 238 239 // Whether the last CallSite entry was for an invoke. 240 bool PreviousIsInvoke = false; 241 242 bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; 243 244 // Visit all instructions in order of address. 245 for (const auto &MBB : *Asm->MF) { 246 for (const auto &MI : MBB) { 247 if (!MI.isEHLabel()) { 248 if (MI.isCall()) 249 SawPotentiallyThrowing |= !callToNoUnwindFunction(&MI); 250 continue; 251 } 252 253 // End of the previous try-range? 254 MCSymbol *BeginLabel = MI.getOperand(0).getMCSymbol(); 255 if (BeginLabel == LastLabel) 256 SawPotentiallyThrowing = false; 257 258 // Beginning of a new try-range? 259 RangeMapType::const_iterator L = PadMap.find(BeginLabel); 260 if (L == PadMap.end()) 261 // Nope, it was just some random label. 262 continue; 263 264 const PadRange &P = L->second; 265 const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; 266 assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && 267 "Inconsistent landing pad map!"); 268 269 // For Dwarf exception handling (SjLj handling doesn't use this). If some 270 // instruction between the previous try-range and this one may throw, 271 // create a call-site entry with no landing pad for the region between the 272 // try-ranges. 273 if (SawPotentiallyThrowing && Asm->MAI->usesCFIForEH()) { 274 CallSiteEntry Site = { LastLabel, BeginLabel, nullptr, 0 }; 275 CallSites.push_back(Site); 276 PreviousIsInvoke = false; 277 } 278 279 LastLabel = LandingPad->EndLabels[P.RangeIndex]; 280 assert(BeginLabel && LastLabel && "Invalid landing pad!"); 281 282 if (!LandingPad->LandingPadLabel) { 283 // Create a gap. 284 PreviousIsInvoke = false; 285 } else { 286 // This try-range is for an invoke. 287 CallSiteEntry Site = { 288 BeginLabel, 289 LastLabel, 290 LandingPad, 291 FirstActions[P.PadIndex] 292 }; 293 294 // Try to merge with the previous call-site. SJLJ doesn't do this 295 if (PreviousIsInvoke && !IsSJLJ) { 296 CallSiteEntry &Prev = CallSites.back(); 297 if (Site.LPad == Prev.LPad && Site.Action == Prev.Action) { 298 // Extend the range of the previous entry. 299 Prev.EndLabel = Site.EndLabel; 300 continue; 301 } 302 } 303 304 // Otherwise, create a new call-site. 305 if (!IsSJLJ) 306 CallSites.push_back(Site); 307 else { 308 // SjLj EH must maintain the call sites in the order assigned 309 // to them by the SjLjPrepare pass. 310 unsigned SiteNo = Asm->MF->getCallSiteBeginLabel(BeginLabel); 311 if (CallSites.size() < SiteNo) 312 CallSites.resize(SiteNo); 313 CallSites[SiteNo - 1] = Site; 314 } 315 PreviousIsInvoke = true; 316 } 317 } 318 } 319 320 // If some instruction between the previous try-range and the end of the 321 // function may throw, create a call-site entry with no landing pad for the 322 // region following the try-range. 323 if (SawPotentiallyThrowing && !IsSJLJ) { 324 CallSiteEntry Site = { LastLabel, nullptr, nullptr, 0 }; 325 CallSites.push_back(Site); 326 } 327 } 328 329 /// Emit landing pads and actions. 330 /// 331 /// The general organization of the table is complex, but the basic concepts are 332 /// easy. First there is a header which describes the location and organization 333 /// of the three components that follow. 334 /// 335 /// 1. The landing pad site information describes the range of code covered by 336 /// the try. In our case it's an accumulation of the ranges covered by the 337 /// invokes in the try. There is also a reference to the landing pad that 338 /// handles the exception once processed. Finally an index into the actions 339 /// table. 340 /// 2. The action table, in our case, is composed of pairs of type IDs and next 341 /// action offset. Starting with the action index from the landing pad 342 /// site, each type ID is checked for a match to the current exception. If 343 /// it matches then the exception and type id are passed on to the landing 344 /// pad. Otherwise the next action is looked up. This chain is terminated 345 /// with a next action of zero. If no type id is found then the frame is 346 /// unwound and handling continues. 347 /// 3. Type ID table contains references to all the C++ typeinfo for all 348 /// catches in the function. This tables is reverse indexed base 1. 349 void EHStreamer::emitExceptionTable() { 350 const MachineFunction *MF = Asm->MF; 351 const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos(); 352 const std::vector<unsigned> &FilterIds = MF->getFilterIds(); 353 const std::vector<LandingPadInfo> &PadInfos = MF->getLandingPads(); 354 355 // Sort the landing pads in order of their type ids. This is used to fold 356 // duplicate actions. 357 SmallVector<const LandingPadInfo *, 64> LandingPads; 358 LandingPads.reserve(PadInfos.size()); 359 360 for (unsigned i = 0, N = PadInfos.size(); i != N; ++i) 361 LandingPads.push_back(&PadInfos[i]); 362 363 // Order landing pads lexicographically by type id. 364 std::sort(LandingPads.begin(), LandingPads.end(), 365 [](const LandingPadInfo *L, 366 const LandingPadInfo *R) { return L->TypeIds < R->TypeIds; }); 367 368 // Compute the actions table and gather the first action index for each 369 // landing pad site. 370 SmallVector<ActionEntry, 32> Actions; 371 SmallVector<unsigned, 64> FirstActions; 372 unsigned SizeActions = 373 computeActionsTable(LandingPads, Actions, FirstActions); 374 375 // Compute the call-site table. 376 SmallVector<CallSiteEntry, 64> CallSites; 377 computeCallSiteTable(CallSites, LandingPads, FirstActions); 378 379 // Final tallies. 380 381 // Call sites. 382 bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; 383 bool HaveTTData = IsSJLJ ? (!TypeInfos.empty() || !FilterIds.empty()) : true; 384 385 unsigned CallSiteTableLength; 386 if (IsSJLJ) 387 CallSiteTableLength = 0; 388 else { 389 unsigned SiteStartSize = 4; // dwarf::DW_EH_PE_udata4 390 unsigned SiteLengthSize = 4; // dwarf::DW_EH_PE_udata4 391 unsigned LandingPadSize = 4; // dwarf::DW_EH_PE_udata4 392 CallSiteTableLength = 393 CallSites.size() * (SiteStartSize + SiteLengthSize + LandingPadSize); 394 } 395 396 for (unsigned i = 0, e = CallSites.size(); i < e; ++i) { 397 CallSiteTableLength += getULEB128Size(CallSites[i].Action); 398 if (IsSJLJ) 399 CallSiteTableLength += getULEB128Size(i); 400 } 401 402 // Type infos. 403 MCSection *LSDASection = Asm->getObjFileLowering().getLSDASection(); 404 unsigned TTypeEncoding; 405 unsigned TypeFormatSize; 406 407 if (!HaveTTData) { 408 // For SjLj exceptions, if there is no TypeInfo, then we just explicitly say 409 // that we're omitting that bit. 410 TTypeEncoding = dwarf::DW_EH_PE_omit; 411 // dwarf::DW_EH_PE_absptr 412 TypeFormatSize = Asm->getDataLayout().getPointerSize(); 413 } else { 414 // Okay, we have actual filters or typeinfos to emit. As such, we need to 415 // pick a type encoding for them. We're about to emit a list of pointers to 416 // typeinfo objects at the end of the LSDA. However, unless we're in static 417 // mode, this reference will require a relocation by the dynamic linker. 418 // 419 // Because of this, we have a couple of options: 420 // 421 // 1) If we are in -static mode, we can always use an absolute reference 422 // from the LSDA, because the static linker will resolve it. 423 // 424 // 2) Otherwise, if the LSDA section is writable, we can output the direct 425 // reference to the typeinfo and allow the dynamic linker to relocate 426 // it. Since it is in a writable section, the dynamic linker won't 427 // have a problem. 428 // 429 // 3) Finally, if we're in PIC mode and the LDSA section isn't writable, 430 // we need to use some form of indirection. For example, on Darwin, 431 // we can output a statically-relocatable reference to a dyld stub. The 432 // offset to the stub is constant, but the contents are in a section 433 // that is updated by the dynamic linker. This is easy enough, but we 434 // need to tell the personality function of the unwinder to indirect 435 // through the dyld stub. 436 // 437 // FIXME: When (3) is actually implemented, we'll have to emit the stubs 438 // somewhere. This predicate should be moved to a shared location that is 439 // in target-independent code. 440 // 441 TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding(); 442 TypeFormatSize = Asm->GetSizeOfEncodedValue(TTypeEncoding); 443 } 444 445 // Begin the exception table. 446 // Sometimes we want not to emit the data into separate section (e.g. ARM 447 // EHABI). In this case LSDASection will be NULL. 448 if (LSDASection) 449 Asm->OutStreamer->SwitchSection(LSDASection); 450 Asm->EmitAlignment(2); 451 452 // Emit the LSDA. 453 MCSymbol *GCCETSym = 454 Asm->OutContext.getOrCreateSymbol(Twine("GCC_except_table")+ 455 Twine(Asm->getFunctionNumber())); 456 Asm->OutStreamer->EmitLabel(GCCETSym); 457 Asm->OutStreamer->EmitLabel(Asm->getCurExceptionSym()); 458 459 // Emit the LSDA header. 460 Asm->EmitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); 461 Asm->EmitEncodingByte(TTypeEncoding, "@TType"); 462 463 // The type infos need to be aligned. GCC does this by inserting padding just 464 // before the type infos. However, this changes the size of the exception 465 // table, so you need to take this into account when you output the exception 466 // table size. However, the size is output using a variable length encoding. 467 // So by increasing the size by inserting padding, you may increase the number 468 // of bytes used for writing the size. If it increases, say by one byte, then 469 // you now need to output one less byte of padding to get the type infos 470 // aligned. However this decreases the size of the exception table. This 471 // changes the value you have to output for the exception table size. Due to 472 // the variable length encoding, the number of bytes used for writing the 473 // length may decrease. If so, you then have to increase the amount of 474 // padding. And so on. If you look carefully at the GCC code you will see that 475 // it indeed does this in a loop, going on and on until the values stabilize. 476 // We chose another solution: don't output padding inside the table like GCC 477 // does, instead output it before the table. 478 unsigned SizeTypes = TypeInfos.size() * TypeFormatSize; 479 unsigned CallSiteTableLengthSize = getULEB128Size(CallSiteTableLength); 480 unsigned TTypeBaseOffset = 481 sizeof(int8_t) + // Call site format 482 CallSiteTableLengthSize + // Call site table length size 483 CallSiteTableLength + // Call site table length 484 SizeActions + // Actions size 485 SizeTypes; 486 unsigned TTypeBaseOffsetSize = getULEB128Size(TTypeBaseOffset); 487 unsigned TotalSize = 488 sizeof(int8_t) + // LPStart format 489 sizeof(int8_t) + // TType format 490 (HaveTTData ? TTypeBaseOffsetSize : 0) + // TType base offset size 491 TTypeBaseOffset; // TType base offset 492 unsigned PadBytes = (4 - TotalSize) & 3; 493 494 if (HaveTTData) { 495 // Account for any extra padding that will be added to the call site table 496 // length. 497 Asm->EmitPaddedULEB128(TTypeBaseOffset, TTypeBaseOffsetSize + PadBytes, 498 "@TType base offset"); 499 PadBytes = 0; 500 } 501 502 bool VerboseAsm = Asm->OutStreamer->isVerboseAsm(); 503 504 // SjLj Exception handling 505 if (IsSJLJ) { 506 Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); 507 508 // Add extra padding if it wasn't added to the TType base offset. 509 Asm->EmitPaddedULEB128(CallSiteTableLength, 510 CallSiteTableLengthSize + PadBytes, 511 "Call site table length"); 512 513 // Emit the landing pad site information. 514 unsigned idx = 0; 515 for (SmallVectorImpl<CallSiteEntry>::const_iterator 516 I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) { 517 const CallSiteEntry &S = *I; 518 519 // Offset of the landing pad, counted in 16-byte bundles relative to the 520 // @LPStart address. 521 if (VerboseAsm) { 522 Asm->OutStreamer->AddComment(">> Call Site " + Twine(idx) + " <<"); 523 Asm->OutStreamer->AddComment(" On exception at call site "+Twine(idx)); 524 } 525 Asm->EmitULEB128(idx); 526 527 // Offset of the first associated action record, relative to the start of 528 // the action table. This value is biased by 1 (1 indicates the start of 529 // the action table), and 0 indicates that there are no actions. 530 if (VerboseAsm) { 531 if (S.Action == 0) 532 Asm->OutStreamer->AddComment(" Action: cleanup"); 533 else 534 Asm->OutStreamer->AddComment(" Action: " + 535 Twine((S.Action - 1) / 2 + 1)); 536 } 537 Asm->EmitULEB128(S.Action); 538 } 539 } else { 540 // Itanium LSDA exception handling 541 542 // The call-site table is a list of all call sites that may throw an 543 // exception (including C++ 'throw' statements) in the procedure 544 // fragment. It immediately follows the LSDA header. Each entry indicates, 545 // for a given call, the first corresponding action record and corresponding 546 // landing pad. 547 // 548 // The table begins with the number of bytes, stored as an LEB128 549 // compressed, unsigned integer. The records immediately follow the record 550 // count. They are sorted in increasing call-site address. Each record 551 // indicates: 552 // 553 // * The position of the call-site. 554 // * The position of the landing pad. 555 // * The first action record for that call site. 556 // 557 // A missing entry in the call-site table indicates that a call is not 558 // supposed to throw. 559 560 // Emit the landing pad call site table. 561 Asm->EmitEncodingByte(dwarf::DW_EH_PE_udata4, "Call site"); 562 563 // Add extra padding if it wasn't added to the TType base offset. 564 Asm->EmitPaddedULEB128(CallSiteTableLength, 565 CallSiteTableLengthSize + PadBytes, 566 "Call site table length"); 567 568 unsigned Entry = 0; 569 for (SmallVectorImpl<CallSiteEntry>::const_iterator 570 I = CallSites.begin(), E = CallSites.end(); I != E; ++I) { 571 const CallSiteEntry &S = *I; 572 573 MCSymbol *EHFuncBeginSym = Asm->getFunctionBegin(); 574 575 MCSymbol *BeginLabel = S.BeginLabel; 576 if (!BeginLabel) 577 BeginLabel = EHFuncBeginSym; 578 MCSymbol *EndLabel = S.EndLabel; 579 if (!EndLabel) 580 EndLabel = Asm->getFunctionEnd(); 581 582 // Offset of the call site relative to the previous call site, counted in 583 // number of 16-byte bundles. The first call site is counted relative to 584 // the start of the procedure fragment. 585 if (VerboseAsm) 586 Asm->OutStreamer->AddComment(">> Call Site " + Twine(++Entry) + " <<"); 587 Asm->EmitLabelDifference(BeginLabel, EHFuncBeginSym, 4); 588 if (VerboseAsm) 589 Asm->OutStreamer->AddComment(Twine(" Call between ") + 590 BeginLabel->getName() + " and " + 591 EndLabel->getName()); 592 Asm->EmitLabelDifference(EndLabel, BeginLabel, 4); 593 594 // Offset of the landing pad, counted in 16-byte bundles relative to the 595 // @LPStart address. 596 if (!S.LPad) { 597 if (VerboseAsm) 598 Asm->OutStreamer->AddComment(" has no landing pad"); 599 Asm->OutStreamer->EmitIntValue(0, 4/*size*/); 600 } else { 601 if (VerboseAsm) 602 Asm->OutStreamer->AddComment(Twine(" jumps to ") + 603 S.LPad->LandingPadLabel->getName()); 604 Asm->EmitLabelDifference(S.LPad->LandingPadLabel, EHFuncBeginSym, 4); 605 } 606 607 // Offset of the first associated action record, relative to the start of 608 // the action table. This value is biased by 1 (1 indicates the start of 609 // the action table), and 0 indicates that there are no actions. 610 if (VerboseAsm) { 611 if (S.Action == 0) 612 Asm->OutStreamer->AddComment(" On action: cleanup"); 613 else 614 Asm->OutStreamer->AddComment(" On action: " + 615 Twine((S.Action - 1) / 2 + 1)); 616 } 617 Asm->EmitULEB128(S.Action); 618 } 619 } 620 621 // Emit the Action Table. 622 int Entry = 0; 623 for (SmallVectorImpl<ActionEntry>::const_iterator 624 I = Actions.begin(), E = Actions.end(); I != E; ++I) { 625 const ActionEntry &Action = *I; 626 627 if (VerboseAsm) { 628 // Emit comments that decode the action table. 629 Asm->OutStreamer->AddComment(">> Action Record " + Twine(++Entry) + " <<"); 630 } 631 632 // Type Filter 633 // 634 // Used by the runtime to match the type of the thrown exception to the 635 // type of the catch clauses or the types in the exception specification. 636 if (VerboseAsm) { 637 if (Action.ValueForTypeID > 0) 638 Asm->OutStreamer->AddComment(" Catch TypeInfo " + 639 Twine(Action.ValueForTypeID)); 640 else if (Action.ValueForTypeID < 0) 641 Asm->OutStreamer->AddComment(" Filter TypeInfo " + 642 Twine(Action.ValueForTypeID)); 643 else 644 Asm->OutStreamer->AddComment(" Cleanup"); 645 } 646 Asm->EmitSLEB128(Action.ValueForTypeID); 647 648 // Action Record 649 // 650 // Self-relative signed displacement in bytes of the next action record, 651 // or 0 if there is no next action record. 652 if (VerboseAsm) { 653 if (Action.NextAction == 0) { 654 Asm->OutStreamer->AddComment(" No further actions"); 655 } else { 656 unsigned NextAction = Entry + (Action.NextAction + 1) / 2; 657 Asm->OutStreamer->AddComment(" Continue to action "+Twine(NextAction)); 658 } 659 } 660 Asm->EmitSLEB128(Action.NextAction); 661 } 662 663 emitTypeInfos(TTypeEncoding); 664 665 Asm->EmitAlignment(2); 666 } 667 668 void EHStreamer::emitTypeInfos(unsigned TTypeEncoding) { 669 const MachineFunction *MF = Asm->MF; 670 const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos(); 671 const std::vector<unsigned> &FilterIds = MF->getFilterIds(); 672 673 bool VerboseAsm = Asm->OutStreamer->isVerboseAsm(); 674 675 int Entry = 0; 676 // Emit the Catch TypeInfos. 677 if (VerboseAsm && !TypeInfos.empty()) { 678 Asm->OutStreamer->AddComment(">> Catch TypeInfos <<"); 679 Asm->OutStreamer->AddBlankLine(); 680 Entry = TypeInfos.size(); 681 } 682 683 for (const GlobalValue *GV : make_range(TypeInfos.rbegin(), 684 TypeInfos.rend())) { 685 if (VerboseAsm) 686 Asm->OutStreamer->AddComment("TypeInfo " + Twine(Entry--)); 687 Asm->EmitTTypeReference(GV, TTypeEncoding); 688 } 689 690 // Emit the Exception Specifications. 691 if (VerboseAsm && !FilterIds.empty()) { 692 Asm->OutStreamer->AddComment(">> Filter TypeInfos <<"); 693 Asm->OutStreamer->AddBlankLine(); 694 Entry = 0; 695 } 696 for (std::vector<unsigned>::const_iterator 697 I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { 698 unsigned TypeID = *I; 699 if (VerboseAsm) { 700 --Entry; 701 if (isFilterEHSelector(TypeID)) 702 Asm->OutStreamer->AddComment("FilterInfo " + Twine(Entry)); 703 } 704 705 Asm->EmitULEB128(TypeID); 706 } 707 } 708