1 //===- CodeGen/AsmPrinter/EHStreamer.cpp - Exception Directive Streamer ---===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file contains support for writing exception info into assembly files. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "EHStreamer.h" 14 #include "llvm/ADT/SmallVector.h" 15 #include "llvm/ADT/Twine.h" 16 #include "llvm/BinaryFormat/Dwarf.h" 17 #include "llvm/CodeGen/AsmPrinter.h" 18 #include "llvm/CodeGen/MachineFunction.h" 19 #include "llvm/CodeGen/MachineInstr.h" 20 #include "llvm/CodeGen/MachineOperand.h" 21 #include "llvm/IR/Function.h" 22 #include "llvm/MC/MCAsmInfo.h" 23 #include "llvm/MC/MCContext.h" 24 #include "llvm/MC/MCStreamer.h" 25 #include "llvm/MC/MCSymbol.h" 26 #include "llvm/MC/MCTargetOptions.h" 27 #include "llvm/Support/Casting.h" 28 #include "llvm/Support/LEB128.h" 29 #include "llvm/Target/TargetLoweringObjectFile.h" 30 #include <algorithm> 31 #include <cassert> 32 #include <cstdint> 33 #include <vector> 34 35 using namespace llvm; 36 37 EHStreamer::EHStreamer(AsmPrinter *A) : Asm(A), MMI(Asm->MMI) {} 38 39 EHStreamer::~EHStreamer() = default; 40 41 /// How many leading type ids two landing pads have in common. 42 unsigned EHStreamer::sharedTypeIDs(const LandingPadInfo *L, 43 const LandingPadInfo *R) { 44 const std::vector<int> &LIds = L->TypeIds, &RIds = R->TypeIds; 45 return std::mismatch(LIds.begin(), LIds.end(), RIds.begin(), RIds.end()) 46 .first - 47 LIds.begin(); 48 } 49 50 /// Compute the actions table and gather the first action index for each landing 51 /// pad site. 52 void EHStreamer::computeActionsTable( 53 const SmallVectorImpl<const LandingPadInfo *> &LandingPads, 54 SmallVectorImpl<ActionEntry> &Actions, 55 SmallVectorImpl<unsigned> &FirstActions) { 56 // The action table follows the call-site table in the LSDA. The individual 57 // records are of two types: 58 // 59 // * Catch clause 60 // * Exception specification 61 // 62 // The two record kinds have the same format, with only small differences. 63 // They are distinguished by the "switch value" field: Catch clauses 64 // (TypeInfos) have strictly positive switch values, and exception 65 // specifications (FilterIds) have strictly negative switch values. Value 0 66 // indicates a catch-all clause. 67 // 68 // Negative type IDs index into FilterIds. Positive type IDs index into 69 // TypeInfos. The value written for a positive type ID is just the type ID 70 // itself. For a negative type ID, however, the value written is the 71 // (negative) byte offset of the corresponding FilterIds entry. The byte 72 // offset is usually equal to the type ID (because the FilterIds entries are 73 // written using a variable width encoding, which outputs one byte per entry 74 // as long as the value written is not too large) but can differ. This kind 75 // of complication does not occur for positive type IDs because type infos are 76 // output using a fixed width encoding. FilterOffsets[i] holds the byte 77 // offset corresponding to FilterIds[i]. 78 79 const std::vector<unsigned> &FilterIds = Asm->MF->getFilterIds(); 80 SmallVector<int, 16> FilterOffsets; 81 FilterOffsets.reserve(FilterIds.size()); 82 int Offset = -1; 83 84 for (unsigned FilterId : FilterIds) { 85 FilterOffsets.push_back(Offset); 86 Offset -= getULEB128Size(FilterId); 87 } 88 89 FirstActions.reserve(LandingPads.size()); 90 91 int FirstAction = 0; 92 unsigned SizeActions = 0; // Total size of all action entries for a function 93 const LandingPadInfo *PrevLPI = nullptr; 94 95 for (const LandingPadInfo *LPI : LandingPads) { 96 const std::vector<int> &TypeIds = LPI->TypeIds; 97 unsigned NumShared = PrevLPI ? sharedTypeIDs(LPI, PrevLPI) : 0; 98 unsigned SizeSiteActions = 0; // Total size of all entries for a landingpad 99 100 if (NumShared < TypeIds.size()) { 101 // Size of one action entry (typeid + next action) 102 unsigned SizeActionEntry = 0; 103 unsigned PrevAction = (unsigned)-1; 104 105 if (NumShared) { 106 unsigned SizePrevIds = PrevLPI->TypeIds.size(); 107 assert(Actions.size()); 108 PrevAction = Actions.size() - 1; 109 SizeActionEntry = getSLEB128Size(Actions[PrevAction].NextAction) + 110 getSLEB128Size(Actions[PrevAction].ValueForTypeID); 111 112 for (unsigned j = NumShared; j != SizePrevIds; ++j) { 113 assert(PrevAction != (unsigned)-1 && "PrevAction is invalid!"); 114 SizeActionEntry -= getSLEB128Size(Actions[PrevAction].ValueForTypeID); 115 SizeActionEntry += -Actions[PrevAction].NextAction; 116 PrevAction = Actions[PrevAction].Previous; 117 } 118 } 119 120 // Compute the actions. 121 for (unsigned J = NumShared, M = TypeIds.size(); J != M; ++J) { 122 int TypeID = TypeIds[J]; 123 assert(-1 - TypeID < (int)FilterOffsets.size() && "Unknown filter id!"); 124 int ValueForTypeID = 125 isFilterEHSelector(TypeID) ? FilterOffsets[-1 - TypeID] : TypeID; 126 unsigned SizeTypeID = getSLEB128Size(ValueForTypeID); 127 128 int NextAction = SizeActionEntry ? -(SizeActionEntry + SizeTypeID) : 0; 129 SizeActionEntry = SizeTypeID + getSLEB128Size(NextAction); 130 SizeSiteActions += SizeActionEntry; 131 132 ActionEntry Action = { ValueForTypeID, NextAction, PrevAction }; 133 Actions.push_back(Action); 134 PrevAction = Actions.size() - 1; 135 } 136 137 // Record the first action of the landing pad site. 138 FirstAction = SizeActions + SizeSiteActions - SizeActionEntry + 1; 139 } // else identical - re-use previous FirstAction 140 141 // Information used when creating the call-site table. The action record 142 // field of the call site record is the offset of the first associated 143 // action record, relative to the start of the actions table. This value is 144 // biased by 1 (1 indicating the start of the actions table), and 0 145 // indicates that there are no actions. 146 FirstActions.push_back(FirstAction); 147 148 // Compute this sites contribution to size. 149 SizeActions += SizeSiteActions; 150 151 PrevLPI = LPI; 152 } 153 } 154 155 /// Return `true' if this is a call to a function marked `nounwind'. Return 156 /// `false' otherwise. 157 bool EHStreamer::callToNoUnwindFunction(const MachineInstr *MI) { 158 assert(MI->isCall() && "This should be a call instruction!"); 159 160 bool MarkedNoUnwind = false; 161 bool SawFunc = false; 162 163 for (const MachineOperand &MO : MI->operands()) { 164 if (!MO.isGlobal()) continue; 165 166 const Function *F = dyn_cast<Function>(MO.getGlobal()); 167 if (!F) continue; 168 169 if (SawFunc) { 170 // Be conservative. If we have more than one function operand for this 171 // call, then we can't make the assumption that it's the callee and 172 // not a parameter to the call. 173 // 174 // FIXME: Determine if there's a way to say that `F' is the callee or 175 // parameter. 176 MarkedNoUnwind = false; 177 break; 178 } 179 180 MarkedNoUnwind = F->doesNotThrow(); 181 SawFunc = true; 182 } 183 184 return MarkedNoUnwind; 185 } 186 187 void EHStreamer::computePadMap( 188 const SmallVectorImpl<const LandingPadInfo *> &LandingPads, 189 RangeMapType &PadMap) { 190 // Invokes and nounwind calls have entries in PadMap (due to being bracketed 191 // by try-range labels when lowered). Ordinary calls do not, so appropriate 192 // try-ranges for them need be deduced so we can put them in the LSDA. 193 for (unsigned i = 0, N = LandingPads.size(); i != N; ++i) { 194 const LandingPadInfo *LandingPad = LandingPads[i]; 195 for (unsigned j = 0, E = LandingPad->BeginLabels.size(); j != E; ++j) { 196 MCSymbol *BeginLabel = LandingPad->BeginLabels[j]; 197 MCSymbol *EndLabel = LandingPad->BeginLabels[j]; 198 // If we have deleted the code for a given invoke after registering it in 199 // the LandingPad label list, the associated symbols will not have been 200 // emitted. In that case, ignore this callsite entry. 201 if (!BeginLabel->isDefined() || !EndLabel->isDefined()) 202 continue; 203 assert(!PadMap.count(BeginLabel) && "Duplicate landing pad labels!"); 204 PadRange P = { i, j }; 205 PadMap[BeginLabel] = P; 206 } 207 } 208 } 209 210 /// Compute the call-site table. The entry for an invoke has a try-range 211 /// containing the call, a non-zero landing pad, and an appropriate action. The 212 /// entry for an ordinary call has a try-range containing the call and zero for 213 /// the landing pad and the action. Calls marked 'nounwind' have no entry and 214 /// must not be contained in the try-range of any entry - they form gaps in the 215 /// table. Entries must be ordered by try-range address. 216 /// 217 /// Call-sites are split into one or more call-site ranges associated with 218 /// different sections of the function. 219 /// 220 /// - Without -basic-block-sections, all call-sites are grouped into one 221 /// call-site-range corresponding to the function section. 222 /// 223 /// - With -basic-block-sections, one call-site range is created for each 224 /// section, with its FragmentBeginLabel and FragmentEndLabel respectively 225 // set to the beginning and ending of the corresponding section and its 226 // ExceptionLabel set to the exception symbol dedicated for this section. 227 // Later, one LSDA header will be emitted for each call-site range with its 228 // call-sites following. The action table and type info table will be 229 // shared across all ranges. 230 void EHStreamer::computeCallSiteTable( 231 SmallVectorImpl<CallSiteEntry> &CallSites, 232 SmallVectorImpl<CallSiteRange> &CallSiteRanges, 233 const SmallVectorImpl<const LandingPadInfo *> &LandingPads, 234 const SmallVectorImpl<unsigned> &FirstActions) { 235 RangeMapType PadMap; 236 computePadMap(LandingPads, PadMap); 237 238 // The end label of the previous invoke or nounwind try-range. 239 MCSymbol *LastLabel = Asm->getFunctionBegin(); 240 241 // Whether there is a potentially throwing instruction (currently this means 242 // an ordinary call) between the end of the previous try-range and now. 243 bool SawPotentiallyThrowing = false; 244 245 // Whether the last CallSite entry was for an invoke. 246 bool PreviousIsInvoke = false; 247 248 bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; 249 250 // Visit all instructions in order of address. 251 for (const auto &MBB : *Asm->MF) { 252 if (&MBB == &Asm->MF->front() || MBB.isBeginSection()) { 253 // We start a call-site range upon function entry and at the beginning of 254 // every basic block section. 255 CallSiteRanges.push_back( 256 {Asm->MBBSectionRanges[MBB.getSectionID()].BeginLabel, 257 Asm->MBBSectionRanges[MBB.getSectionID()].EndLabel, 258 Asm->getMBBExceptionSym(MBB), CallSites.size()}); 259 PreviousIsInvoke = false; 260 SawPotentiallyThrowing = false; 261 LastLabel = nullptr; 262 } 263 264 if (MBB.isEHPad()) 265 CallSiteRanges.back().IsLPRange = true; 266 267 for (const auto &MI : MBB) { 268 if (!MI.isEHLabel()) { 269 if (MI.isCall()) 270 SawPotentiallyThrowing |= !callToNoUnwindFunction(&MI); 271 continue; 272 } 273 274 // End of the previous try-range? 275 MCSymbol *BeginLabel = MI.getOperand(0).getMCSymbol(); 276 if (BeginLabel == LastLabel) 277 SawPotentiallyThrowing = false; 278 279 // Beginning of a new try-range? 280 RangeMapType::const_iterator L = PadMap.find(BeginLabel); 281 if (L == PadMap.end()) 282 // Nope, it was just some random label. 283 continue; 284 285 const PadRange &P = L->second; 286 const LandingPadInfo *LandingPad = LandingPads[P.PadIndex]; 287 assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] && 288 "Inconsistent landing pad map!"); 289 290 // For Dwarf and AIX exception handling (SjLj handling doesn't use this). 291 // If some instruction between the previous try-range and this one may 292 // throw, create a call-site entry with no landing pad for the region 293 // between the try-ranges. 294 if (SawPotentiallyThrowing && 295 (Asm->MAI->usesCFIForEH() || 296 Asm->MAI->getExceptionHandlingType() == ExceptionHandling::AIX)) { 297 CallSites.push_back({LastLabel, BeginLabel, nullptr, 0}); 298 PreviousIsInvoke = false; 299 } 300 301 LastLabel = LandingPad->EndLabels[P.RangeIndex]; 302 assert(BeginLabel && LastLabel && "Invalid landing pad!"); 303 304 if (!LandingPad->LandingPadLabel) { 305 // Create a gap. 306 PreviousIsInvoke = false; 307 } else { 308 // This try-range is for an invoke. 309 CallSiteEntry Site = { 310 BeginLabel, 311 LastLabel, 312 LandingPad, 313 FirstActions[P.PadIndex] 314 }; 315 316 // Try to merge with the previous call-site. SJLJ doesn't do this 317 if (PreviousIsInvoke && !IsSJLJ) { 318 CallSiteEntry &Prev = CallSites.back(); 319 if (Site.LPad == Prev.LPad && Site.Action == Prev.Action) { 320 // Extend the range of the previous entry. 321 Prev.EndLabel = Site.EndLabel; 322 continue; 323 } 324 } 325 326 // Otherwise, create a new call-site. 327 if (!IsSJLJ) 328 CallSites.push_back(Site); 329 else { 330 // SjLj EH must maintain the call sites in the order assigned 331 // to them by the SjLjPrepare pass. 332 unsigned SiteNo = Asm->MF->getCallSiteBeginLabel(BeginLabel); 333 if (CallSites.size() < SiteNo) 334 CallSites.resize(SiteNo); 335 CallSites[SiteNo - 1] = Site; 336 } 337 PreviousIsInvoke = true; 338 } 339 } 340 341 // We end the call-site range upon function exit and at the end of every 342 // basic block section. 343 if (&MBB == &Asm->MF->back() || MBB.isEndSection()) { 344 // If some instruction between the previous try-range and the end of the 345 // function may throw, create a call-site entry with no landing pad for 346 // the region following the try-range. 347 if (SawPotentiallyThrowing && !IsSJLJ) { 348 CallSiteEntry Site = {LastLabel, CallSiteRanges.back().FragmentEndLabel, 349 nullptr, 0}; 350 CallSites.push_back(Site); 351 SawPotentiallyThrowing = false; 352 } 353 CallSiteRanges.back().CallSiteEndIdx = CallSites.size(); 354 } 355 } 356 } 357 358 /// Emit landing pads and actions. 359 /// 360 /// The general organization of the table is complex, but the basic concepts are 361 /// easy. First there is a header which describes the location and organization 362 /// of the three components that follow. 363 /// 364 /// 1. The landing pad site information describes the range of code covered by 365 /// the try. In our case it's an accumulation of the ranges covered by the 366 /// invokes in the try. There is also a reference to the landing pad that 367 /// handles the exception once processed. Finally an index into the actions 368 /// table. 369 /// 2. The action table, in our case, is composed of pairs of type IDs and next 370 /// action offset. Starting with the action index from the landing pad 371 /// site, each type ID is checked for a match to the current exception. If 372 /// it matches then the exception and type id are passed on to the landing 373 /// pad. Otherwise the next action is looked up. This chain is terminated 374 /// with a next action of zero. If no type id is found then the frame is 375 /// unwound and handling continues. 376 /// 3. Type ID table contains references to all the C++ typeinfo for all 377 /// catches in the function. This tables is reverse indexed base 1. 378 /// 379 /// Returns the starting symbol of an exception table. 380 MCSymbol *EHStreamer::emitExceptionTable() { 381 const MachineFunction *MF = Asm->MF; 382 const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos(); 383 const std::vector<unsigned> &FilterIds = MF->getFilterIds(); 384 const std::vector<LandingPadInfo> &PadInfos = MF->getLandingPads(); 385 386 // Sort the landing pads in order of their type ids. This is used to fold 387 // duplicate actions. 388 SmallVector<const LandingPadInfo *, 64> LandingPads; 389 LandingPads.reserve(PadInfos.size()); 390 391 for (const LandingPadInfo &LPI : PadInfos) { 392 // If a landing-pad has an associated label, but the label wasn't ever 393 // emitted, then skip it. (This can occur if the landingpad's MBB was 394 // deleted). 395 if (LPI.LandingPadLabel && !LPI.LandingPadLabel->isDefined()) 396 continue; 397 LandingPads.push_back(&LPI); 398 } 399 400 // Order landing pads lexicographically by type id. 401 llvm::sort(LandingPads, [](const LandingPadInfo *L, const LandingPadInfo *R) { 402 return L->TypeIds < R->TypeIds; 403 }); 404 405 // Compute the actions table and gather the first action index for each 406 // landing pad site. 407 SmallVector<ActionEntry, 32> Actions; 408 SmallVector<unsigned, 64> FirstActions; 409 computeActionsTable(LandingPads, Actions, FirstActions); 410 411 // Compute the call-site table and call-site ranges. Normally, there is only 412 // one call-site-range which covers the whole function. With 413 // -basic-block-sections, there is one call-site-range per basic block 414 // section. 415 SmallVector<CallSiteEntry, 64> CallSites; 416 SmallVector<CallSiteRange, 4> CallSiteRanges; 417 computeCallSiteTable(CallSites, CallSiteRanges, LandingPads, FirstActions); 418 419 bool IsSJLJ = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::SjLj; 420 bool IsWasm = Asm->MAI->getExceptionHandlingType() == ExceptionHandling::Wasm; 421 bool HasLEB128Directives = Asm->MAI->hasLEB128Directives(); 422 unsigned CallSiteEncoding = 423 IsSJLJ ? static_cast<unsigned>(dwarf::DW_EH_PE_udata4) : 424 Asm->getObjFileLowering().getCallSiteEncoding(); 425 bool HaveTTData = !TypeInfos.empty() || !FilterIds.empty(); 426 427 // Type infos. 428 MCSection *LSDASection = Asm->getObjFileLowering().getSectionForLSDA( 429 MF->getFunction(), *Asm->CurrentFnSym, Asm->TM); 430 unsigned TTypeEncoding; 431 432 if (!HaveTTData) { 433 // If there is no TypeInfo, then we just explicitly say that we're omitting 434 // that bit. 435 TTypeEncoding = dwarf::DW_EH_PE_omit; 436 } else { 437 // Okay, we have actual filters or typeinfos to emit. As such, we need to 438 // pick a type encoding for them. We're about to emit a list of pointers to 439 // typeinfo objects at the end of the LSDA. However, unless we're in static 440 // mode, this reference will require a relocation by the dynamic linker. 441 // 442 // Because of this, we have a couple of options: 443 // 444 // 1) If we are in -static mode, we can always use an absolute reference 445 // from the LSDA, because the static linker will resolve it. 446 // 447 // 2) Otherwise, if the LSDA section is writable, we can output the direct 448 // reference to the typeinfo and allow the dynamic linker to relocate 449 // it. Since it is in a writable section, the dynamic linker won't 450 // have a problem. 451 // 452 // 3) Finally, if we're in PIC mode and the LDSA section isn't writable, 453 // we need to use some form of indirection. For example, on Darwin, 454 // we can output a statically-relocatable reference to a dyld stub. The 455 // offset to the stub is constant, but the contents are in a section 456 // that is updated by the dynamic linker. This is easy enough, but we 457 // need to tell the personality function of the unwinder to indirect 458 // through the dyld stub. 459 // 460 // FIXME: When (3) is actually implemented, we'll have to emit the stubs 461 // somewhere. This predicate should be moved to a shared location that is 462 // in target-independent code. 463 // 464 TTypeEncoding = Asm->getObjFileLowering().getTTypeEncoding(); 465 } 466 467 // Begin the exception table. 468 // Sometimes we want not to emit the data into separate section (e.g. ARM 469 // EHABI). In this case LSDASection will be NULL. 470 if (LSDASection) 471 Asm->OutStreamer->switchSection(LSDASection); 472 Asm->emitAlignment(Align(4)); 473 474 // Emit the LSDA. 475 MCSymbol *GCCETSym = 476 Asm->OutContext.getOrCreateSymbol(Twine("GCC_except_table")+ 477 Twine(Asm->getFunctionNumber())); 478 Asm->OutStreamer->emitLabel(GCCETSym); 479 MCSymbol *CstEndLabel = Asm->createTempSymbol( 480 CallSiteRanges.size() > 1 ? "action_table_base" : "cst_end"); 481 482 MCSymbol *TTBaseLabel = nullptr; 483 if (HaveTTData) 484 TTBaseLabel = Asm->createTempSymbol("ttbase"); 485 486 const bool VerboseAsm = Asm->OutStreamer->isVerboseAsm(); 487 488 // Helper for emitting references (offsets) for type table and the end of the 489 // call-site table (which marks the beginning of the action table). 490 // * For Itanium, these references will be emitted for every callsite range. 491 // * For SJLJ and Wasm, they will be emitted only once in the LSDA header. 492 auto EmitTypeTableRefAndCallSiteTableEndRef = [&]() { 493 Asm->emitEncodingByte(TTypeEncoding, "@TType"); 494 if (HaveTTData) { 495 // N.B.: There is a dependency loop between the size of the TTBase uleb128 496 // here and the amount of padding before the aligned type table. The 497 // assembler must sometimes pad this uleb128 or insert extra padding 498 // before the type table. See PR35809 or GNU as bug 4029. 499 MCSymbol *TTBaseRefLabel = Asm->createTempSymbol("ttbaseref"); 500 Asm->emitLabelDifferenceAsULEB128(TTBaseLabel, TTBaseRefLabel); 501 Asm->OutStreamer->emitLabel(TTBaseRefLabel); 502 } 503 504 // The Action table follows the call-site table. So we emit the 505 // label difference from here (start of the call-site table for SJLJ and 506 // Wasm, and start of a call-site range for Itanium) to the end of the 507 // whole call-site table (end of the last call-site range for Itanium). 508 MCSymbol *CstBeginLabel = Asm->createTempSymbol("cst_begin"); 509 Asm->emitEncodingByte(CallSiteEncoding, "Call site"); 510 Asm->emitLabelDifferenceAsULEB128(CstEndLabel, CstBeginLabel); 511 Asm->OutStreamer->emitLabel(CstBeginLabel); 512 }; 513 514 // An alternative path to EmitTypeTableRefAndCallSiteTableEndRef. 515 // For some platforms, the system assembler does not accept the form of 516 // `.uleb128 label2 - label1`. In those situations, we would need to calculate 517 // the size between label1 and label2 manually. 518 // In this case, we would need to calculate the LSDA size and the call 519 // site table size. 520 auto EmitTypeTableOffsetAndCallSiteTableOffset = [&]() { 521 assert(CallSiteEncoding == dwarf::DW_EH_PE_udata4 && !HasLEB128Directives && 522 "Targets supporting .uleb128 do not need to take this path."); 523 if (CallSiteRanges.size() > 1) 524 report_fatal_error( 525 "-fbasic-block-sections is not yet supported on " 526 "platforms that do not have general LEB128 directive support."); 527 528 uint64_t CallSiteTableSize = 0; 529 const CallSiteRange &CSRange = CallSiteRanges.back(); 530 for (size_t CallSiteIdx = CSRange.CallSiteBeginIdx; 531 CallSiteIdx < CSRange.CallSiteEndIdx; ++CallSiteIdx) { 532 const CallSiteEntry &S = CallSites[CallSiteIdx]; 533 // Each call site entry consists of 3 udata4 fields (12 bytes) and 534 // 1 ULEB128 field. 535 CallSiteTableSize += 12 + getULEB128Size(S.Action); 536 assert(isUInt<32>(CallSiteTableSize) && "CallSiteTableSize overflows."); 537 } 538 539 Asm->emitEncodingByte(TTypeEncoding, "@TType"); 540 if (HaveTTData) { 541 const unsigned ByteSizeOfCallSiteOffset = 542 getULEB128Size(CallSiteTableSize); 543 uint64_t ActionTableSize = 0; 544 for (const ActionEntry &Action : Actions) { 545 // Each action entry consists of two SLEB128 fields. 546 ActionTableSize += getSLEB128Size(Action.ValueForTypeID) + 547 getSLEB128Size(Action.NextAction); 548 assert(isUInt<32>(ActionTableSize) && "ActionTableSize overflows."); 549 } 550 551 const unsigned TypeInfoSize = 552 Asm->GetSizeOfEncodedValue(TTypeEncoding) * MF->getTypeInfos().size(); 553 554 const uint64_t LSDASizeBeforeAlign = 555 1 // Call site encoding byte. 556 + ByteSizeOfCallSiteOffset // ULEB128 encoding of CallSiteTableSize. 557 + CallSiteTableSize // Call site table content. 558 + ActionTableSize; // Action table content. 559 560 const uint64_t LSDASizeWithoutAlign = LSDASizeBeforeAlign + TypeInfoSize; 561 const unsigned ByteSizeOfLSDAWithoutAlign = 562 getULEB128Size(LSDASizeWithoutAlign); 563 const uint64_t DisplacementBeforeAlign = 564 2 // LPStartEncoding and TypeTableEncoding. 565 + ByteSizeOfLSDAWithoutAlign + LSDASizeBeforeAlign; 566 567 // The type info area starts with 4 byte alignment. 568 const unsigned NeedAlignVal = (4 - DisplacementBeforeAlign % 4) % 4; 569 uint64_t LSDASizeWithAlign = LSDASizeWithoutAlign + NeedAlignVal; 570 const unsigned ByteSizeOfLSDAWithAlign = 571 getULEB128Size(LSDASizeWithAlign); 572 573 // The LSDASizeWithAlign could use 1 byte less padding for alignment 574 // when the data we use to represent the LSDA Size "needs" to be 1 byte 575 // larger than the one previously calculated without alignment. 576 if (ByteSizeOfLSDAWithAlign > ByteSizeOfLSDAWithoutAlign) 577 LSDASizeWithAlign -= 1; 578 579 Asm->OutStreamer->emitULEB128IntValue(LSDASizeWithAlign, 580 ByteSizeOfLSDAWithAlign); 581 } 582 583 Asm->emitEncodingByte(CallSiteEncoding, "Call site"); 584 Asm->OutStreamer->emitULEB128IntValue(CallSiteTableSize); 585 }; 586 587 // SjLj / Wasm Exception handling 588 if (IsSJLJ || IsWasm) { 589 Asm->OutStreamer->emitLabel(Asm->getMBBExceptionSym(Asm->MF->front())); 590 591 // emit the LSDA header. 592 Asm->emitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); 593 EmitTypeTableRefAndCallSiteTableEndRef(); 594 595 unsigned idx = 0; 596 for (SmallVectorImpl<CallSiteEntry>::const_iterator 597 I = CallSites.begin(), E = CallSites.end(); I != E; ++I, ++idx) { 598 const CallSiteEntry &S = *I; 599 600 // Index of the call site entry. 601 if (VerboseAsm) { 602 Asm->OutStreamer->AddComment(">> Call Site " + Twine(idx) + " <<"); 603 Asm->OutStreamer->AddComment(" On exception at call site "+Twine(idx)); 604 } 605 Asm->emitULEB128(idx); 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(" Action: cleanup"); 613 else 614 Asm->OutStreamer->AddComment(" Action: " + 615 Twine((S.Action - 1) / 2 + 1)); 616 } 617 Asm->emitULEB128(S.Action); 618 } 619 Asm->OutStreamer->emitLabel(CstEndLabel); 620 } else { 621 // Itanium LSDA exception handling 622 623 // The call-site table is a list of all call sites that may throw an 624 // exception (including C++ 'throw' statements) in the procedure 625 // fragment. It immediately follows the LSDA header. Each entry indicates, 626 // for a given call, the first corresponding action record and corresponding 627 // landing pad. 628 // 629 // The table begins with the number of bytes, stored as an LEB128 630 // compressed, unsigned integer. The records immediately follow the record 631 // count. They are sorted in increasing call-site address. Each record 632 // indicates: 633 // 634 // * The position of the call-site. 635 // * The position of the landing pad. 636 // * The first action record for that call site. 637 // 638 // A missing entry in the call-site table indicates that a call is not 639 // supposed to throw. 640 641 assert(CallSiteRanges.size() != 0 && "No call-site ranges!"); 642 643 // There should be only one call-site range which includes all the landing 644 // pads. Find that call-site range here. 645 const CallSiteRange *LandingPadRange = nullptr; 646 for (const CallSiteRange &CSRange : CallSiteRanges) { 647 if (CSRange.IsLPRange) { 648 assert(LandingPadRange == nullptr && 649 "All landing pads must be in a single callsite range."); 650 LandingPadRange = &CSRange; 651 } 652 } 653 654 // The call-site table is split into its call-site ranges, each being 655 // emitted as: 656 // [ LPStartEncoding | LPStart ] 657 // [ TypeTableEncoding | TypeTableOffset ] 658 // [ CallSiteEncoding | CallSiteTableEndOffset ] 659 // cst_begin -> { call-site entries contained in this range } 660 // 661 // and is followed by the next call-site range. 662 // 663 // For each call-site range, CallSiteTableEndOffset is computed as the 664 // difference between cst_begin of that range and the last call-site-table's 665 // end label. This offset is used to find the action table. 666 667 unsigned Entry = 0; 668 for (const CallSiteRange &CSRange : CallSiteRanges) { 669 if (CSRange.CallSiteBeginIdx != 0) { 670 // Align the call-site range for all ranges except the first. The 671 // first range is already aligned due to the exception table alignment. 672 Asm->emitAlignment(Align(4)); 673 } 674 Asm->OutStreamer->emitLabel(CSRange.ExceptionLabel); 675 676 // Emit the LSDA header. 677 // LPStart is omitted if either we have a single call-site range (in which 678 // case the function entry is treated as @LPStart) or if this function has 679 // no landing pads (in which case @LPStart is undefined). 680 if (CallSiteRanges.size() == 1 || LandingPadRange == nullptr) { 681 Asm->emitEncodingByte(dwarf::DW_EH_PE_omit, "@LPStart"); 682 } else if (!Asm->isPositionIndependent()) { 683 // For more than one call-site ranges, LPStart must be explicitly 684 // specified. 685 // For non-PIC we can simply use the absolute value. 686 Asm->emitEncodingByte(dwarf::DW_EH_PE_absptr, "@LPStart"); 687 Asm->OutStreamer->emitSymbolValue(LandingPadRange->FragmentBeginLabel, 688 Asm->MAI->getCodePointerSize()); 689 } else { 690 // For PIC mode, we Emit a PC-relative address for LPStart. 691 Asm->emitEncodingByte(dwarf::DW_EH_PE_pcrel, "@LPStart"); 692 MCContext &Context = Asm->OutStreamer->getContext(); 693 MCSymbol *Dot = Context.createTempSymbol(); 694 Asm->OutStreamer->emitLabel(Dot); 695 Asm->OutStreamer->emitValue( 696 MCBinaryExpr::createSub( 697 MCSymbolRefExpr::create(LandingPadRange->FragmentBeginLabel, 698 Context), 699 MCSymbolRefExpr::create(Dot, Context), Context), 700 Asm->MAI->getCodePointerSize()); 701 } 702 703 if (HasLEB128Directives) 704 EmitTypeTableRefAndCallSiteTableEndRef(); 705 else 706 EmitTypeTableOffsetAndCallSiteTableOffset(); 707 708 for (size_t CallSiteIdx = CSRange.CallSiteBeginIdx; 709 CallSiteIdx != CSRange.CallSiteEndIdx; ++CallSiteIdx) { 710 const CallSiteEntry &S = CallSites[CallSiteIdx]; 711 712 MCSymbol *EHFuncBeginSym = CSRange.FragmentBeginLabel; 713 MCSymbol *EHFuncEndSym = CSRange.FragmentEndLabel; 714 715 MCSymbol *BeginLabel = S.BeginLabel; 716 if (!BeginLabel) 717 BeginLabel = EHFuncBeginSym; 718 MCSymbol *EndLabel = S.EndLabel; 719 if (!EndLabel) 720 EndLabel = EHFuncEndSym; 721 722 // Offset of the call site relative to the start of the procedure. 723 if (VerboseAsm) 724 Asm->OutStreamer->AddComment(">> Call Site " + Twine(++Entry) + 725 " <<"); 726 Asm->emitCallSiteOffset(BeginLabel, EHFuncBeginSym, CallSiteEncoding); 727 if (VerboseAsm) 728 Asm->OutStreamer->AddComment(Twine(" Call between ") + 729 BeginLabel->getName() + " and " + 730 EndLabel->getName()); 731 Asm->emitCallSiteOffset(EndLabel, BeginLabel, CallSiteEncoding); 732 733 // Offset of the landing pad relative to the start of the landing pad 734 // fragment. 735 if (!S.LPad) { 736 if (VerboseAsm) 737 Asm->OutStreamer->AddComment(" has no landing pad"); 738 Asm->emitCallSiteValue(0, CallSiteEncoding); 739 } else { 740 if (VerboseAsm) 741 Asm->OutStreamer->AddComment(Twine(" jumps to ") + 742 S.LPad->LandingPadLabel->getName()); 743 Asm->emitCallSiteOffset(S.LPad->LandingPadLabel, 744 LandingPadRange->FragmentBeginLabel, 745 CallSiteEncoding); 746 } 747 748 // Offset of the first associated action record, relative to the start 749 // of the action table. This value is biased by 1 (1 indicates the start 750 // of the action table), and 0 indicates that there are no actions. 751 if (VerboseAsm) { 752 if (S.Action == 0) 753 Asm->OutStreamer->AddComment(" On action: cleanup"); 754 else 755 Asm->OutStreamer->AddComment(" On action: " + 756 Twine((S.Action - 1) / 2 + 1)); 757 } 758 Asm->emitULEB128(S.Action); 759 } 760 } 761 Asm->OutStreamer->emitLabel(CstEndLabel); 762 } 763 764 // Emit the Action Table. 765 int Entry = 0; 766 for (const ActionEntry &Action : Actions) { 767 if (VerboseAsm) { 768 // Emit comments that decode the action table. 769 Asm->OutStreamer->AddComment(">> Action Record " + Twine(++Entry) + " <<"); 770 } 771 772 // Type Filter 773 // 774 // Used by the runtime to match the type of the thrown exception to the 775 // type of the catch clauses or the types in the exception specification. 776 if (VerboseAsm) { 777 if (Action.ValueForTypeID > 0) 778 Asm->OutStreamer->AddComment(" Catch TypeInfo " + 779 Twine(Action.ValueForTypeID)); 780 else if (Action.ValueForTypeID < 0) 781 Asm->OutStreamer->AddComment(" Filter TypeInfo " + 782 Twine(Action.ValueForTypeID)); 783 else 784 Asm->OutStreamer->AddComment(" Cleanup"); 785 } 786 Asm->emitSLEB128(Action.ValueForTypeID); 787 788 // Action Record 789 if (VerboseAsm) { 790 if (Action.Previous == unsigned(-1)) { 791 Asm->OutStreamer->AddComment(" No further actions"); 792 } else { 793 Asm->OutStreamer->AddComment(" Continue to action " + 794 Twine(Action.Previous + 1)); 795 } 796 } 797 Asm->emitSLEB128(Action.NextAction); 798 } 799 800 if (HaveTTData) { 801 Asm->emitAlignment(Align(4)); 802 emitTypeInfos(TTypeEncoding, TTBaseLabel); 803 } 804 805 Asm->emitAlignment(Align(4)); 806 return GCCETSym; 807 } 808 809 void EHStreamer::emitTypeInfos(unsigned TTypeEncoding, MCSymbol *TTBaseLabel) { 810 const MachineFunction *MF = Asm->MF; 811 const std::vector<const GlobalValue *> &TypeInfos = MF->getTypeInfos(); 812 const std::vector<unsigned> &FilterIds = MF->getFilterIds(); 813 814 const bool VerboseAsm = Asm->OutStreamer->isVerboseAsm(); 815 816 int Entry = 0; 817 // Emit the Catch TypeInfos. 818 if (VerboseAsm && !TypeInfos.empty()) { 819 Asm->OutStreamer->AddComment(">> Catch TypeInfos <<"); 820 Asm->OutStreamer->addBlankLine(); 821 Entry = TypeInfos.size(); 822 } 823 824 for (const GlobalValue *GV : llvm::reverse(TypeInfos)) { 825 if (VerboseAsm) 826 Asm->OutStreamer->AddComment("TypeInfo " + Twine(Entry--)); 827 Asm->emitTTypeReference(GV, TTypeEncoding); 828 } 829 830 Asm->OutStreamer->emitLabel(TTBaseLabel); 831 832 // Emit the Exception Specifications. 833 if (VerboseAsm && !FilterIds.empty()) { 834 Asm->OutStreamer->AddComment(">> Filter TypeInfos <<"); 835 Asm->OutStreamer->addBlankLine(); 836 Entry = 0; 837 } 838 for (std::vector<unsigned>::const_iterator 839 I = FilterIds.begin(), E = FilterIds.end(); I < E; ++I) { 840 unsigned TypeID = *I; 841 if (VerboseAsm) { 842 --Entry; 843 if (isFilterEHSelector(TypeID)) 844 Asm->OutStreamer->AddComment("FilterInfo " + Twine(Entry)); 845 } 846 847 Asm->emitULEB128(TypeID); 848 } 849 } 850