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