LLVM  12.0.0git
WinException.cpp
Go to the documentation of this file.
1 //===-- CodeGen/AsmPrinter/WinException.cpp - Dwarf Exception Impl ------===//
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 Win64 exception info into asm files.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "WinException.h"
14 #include "llvm/ADT/Twine.h"
15 #include "llvm/BinaryFormat/COFF.h"
25 #include "llvm/IR/DataLayout.h"
26 #include "llvm/IR/Mangler.h"
27 #include "llvm/IR/Module.h"
28 #include "llvm/MC/MCAsmInfo.h"
29 #include "llvm/MC/MCContext.h"
30 #include "llvm/MC/MCExpr.h"
31 #include "llvm/MC/MCSection.h"
32 #include "llvm/MC/MCStreamer.h"
33 #include "llvm/MC/MCSymbol.h"
39 using namespace llvm;
40 
42  // MSVC's EH tables are always composed of 32-bit words. All known 64-bit
43  // platforms use an imagerel32 relocation to refer to symbols.
44  useImageRel32 = (A->getDataLayout().getPointerSizeInBits() == 64);
45  isAArch64 = Asm->TM.getTargetTriple().isAArch64();
46 }
47 
49 
50 /// endModule - Emit all exception information that should come after the
51 /// content.
53  auto &OS = *Asm->OutStreamer;
54  const Module *M = MMI->getModule();
55  for (const Function &F : *M)
56  if (F.hasFnAttribute("safeseh"))
57  OS.EmitCOFFSafeSEH(Asm->getSymbol(&F));
58 }
59 
61  shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false;
62 
63  // If any landing pads survive, we need an EH table.
64  bool hasLandingPads = !MF->getLandingPads().empty();
65  bool hasEHFunclets = MF->hasEHFunclets();
66 
67  const Function &F = MF->getFunction();
68 
69  shouldEmitMoves = Asm->needsSEHMoves() && MF->hasWinCFI();
70 
72  unsigned PerEncoding = TLOF.getPersonalityEncoding();
73 
75  const Function *PerFn = nullptr;
76  if (F.hasPersonalityFn()) {
77  PerFn = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts());
78  Per = classifyEHPersonality(PerFn);
79  }
80 
81  bool forceEmitPersonality = F.hasPersonalityFn() &&
82  !isNoOpWithoutInvoke(Per) &&
83  F.needsUnwindTableEntry();
84 
85  shouldEmitPersonality =
86  forceEmitPersonality || ((hasLandingPads || hasEHFunclets) &&
87  PerEncoding != dwarf::DW_EH_PE_omit && PerFn);
88 
89  unsigned LSDAEncoding = TLOF.getLSDAEncoding();
90  shouldEmitLSDA = shouldEmitPersonality &&
91  LSDAEncoding != dwarf::DW_EH_PE_omit;
92 
93  // If we're not using CFI, we don't want the CFI or the personality, but we
94  // might want EH tables if we had EH pads.
95  if (!Asm->MAI->usesWindowsCFI()) {
96  if (Per == EHPersonality::MSVC_X86SEH && !hasEHFunclets) {
97  // If this is 32-bit SEH and we don't have any funclets (really invokes),
98  // make sure we emit the parent offset label. Some unreferenced filter
99  // functions may still refer to it.
100  const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
101  StringRef FLinkageName =
103  emitEHRegistrationOffsetLabel(FuncInfo, FLinkageName);
104  }
105  shouldEmitLSDA = hasEHFunclets;
106  shouldEmitPersonality = false;
107  return;
108  }
109 
111 }
112 
114  if (isAArch64 && CurrentFuncletEntry &&
115  (shouldEmitMoves || shouldEmitPersonality))
116  Asm->OutStreamer->EmitWinCFIFuncletOrFuncEnd();
117 }
118 
119 /// endFunction - Gather and emit post-function exception information.
120 ///
122  if (!shouldEmitPersonality && !shouldEmitMoves && !shouldEmitLSDA)
123  return;
124 
125  const Function &F = MF->getFunction();
127  if (F.hasPersonalityFn())
128  Per = classifyEHPersonality(F.getPersonalityFn()->stripPointerCasts());
129 
130  // Get rid of any dead landing pads if we're not using funclets. In funclet
131  // schemes, the landing pad is not actually reachable. It only exists so
132  // that we can emit the right table data.
133  if (!isFuncletEHPersonality(Per)) {
134  MachineFunction *NonConstMF = const_cast<MachineFunction*>(MF);
135  NonConstMF->tidyLandingPads();
136  }
137 
138  endFuncletImpl();
139 
140  // endFunclet will emit the necessary .xdata tables for table-based SEH.
141  if (Per == EHPersonality::MSVC_TableSEH && MF->hasEHFunclets())
142  return;
143 
144  if (shouldEmitPersonality || shouldEmitLSDA) {
145  Asm->OutStreamer->PushSection();
146 
147  // Just switch sections to the right xdata section.
148  MCSection *XData = Asm->OutStreamer->getAssociatedXDataSection(
149  Asm->OutStreamer->getCurrentSectionOnly());
150  Asm->OutStreamer->SwitchSection(XData);
151 
152  // Emit the tables appropriate to the personality function in use. If we
153  // don't recognize the personality, assume it uses an Itanium-style LSDA.
154  if (Per == EHPersonality::MSVC_TableSEH)
155  emitCSpecificHandlerTable(MF);
156  else if (Per == EHPersonality::MSVC_X86SEH)
157  emitExceptHandlerTable(MF);
158  else if (Per == EHPersonality::MSVC_CXX)
159  emitCXXFrameHandler3Table(MF);
160  else if (Per == EHPersonality::CoreCLR)
161  emitCLRExceptionTable(MF);
162  else
164 
165  Asm->OutStreamer->PopSection();
166  }
167 }
168 
169 /// Retrieve the MCSymbol for a GlobalValue or MachineBasicBlock.
171  const MachineBasicBlock *MBB) {
172  if (!MBB)
173  return nullptr;
174 
176 
177  // Give catches and cleanups a name based off of their parent function and
178  // their funclet entry block's number.
179  const MachineFunction *MF = MBB->getParent();
180  const Function &F = MF->getFunction();
181  StringRef FuncLinkageName = GlobalValue::dropLLVMManglingEscape(F.getName());
182  MCContext &Ctx = MF->getContext();
183  StringRef HandlerPrefix = MBB->isCleanupFuncletEntry() ? "dtor" : "catch";
184  return Ctx.getOrCreateSymbol("?" + HandlerPrefix + "$" +
185  Twine(MBB->getNumber()) + "@?0?" +
186  FuncLinkageName + "@4HA");
187 }
188 
190  MCSymbol *Sym) {
191  CurrentFuncletEntry = &MBB;
192 
193  const Function &F = Asm->MF->getFunction();
194  // If a symbol was not provided for the funclet, invent one.
195  if (!Sym) {
196  Sym = getMCSymbolForMBB(Asm, &MBB);
197 
198  // Describe our funclet symbol as a function with internal linkage.
199  Asm->OutStreamer->BeginCOFFSymbolDef(Sym);
200  Asm->OutStreamer->EmitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_STATIC);
201  Asm->OutStreamer->EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_FUNCTION
203  Asm->OutStreamer->EndCOFFSymbolDef();
204 
205  // We want our funclet's entry point to be aligned such that no nops will be
206  // present after the label.
208  &F);
209 
210  // Now that we've emitted the alignment directive, point at our funclet.
211  Asm->OutStreamer->emitLabel(Sym);
212  }
213 
214  // Mark 'Sym' as starting our funclet.
215  if (shouldEmitMoves || shouldEmitPersonality) {
216  CurrentFuncletTextSection = Asm->OutStreamer->getCurrentSectionOnly();
217  Asm->OutStreamer->EmitWinCFIStartProc(Sym);
218  }
219 
220  if (shouldEmitPersonality) {
222  const Function *PerFn = nullptr;
223 
224  // Determine which personality routine we are using for this funclet.
225  if (F.hasPersonalityFn())
226  PerFn = dyn_cast<Function>(F.getPersonalityFn()->stripPointerCasts());
227  const MCSymbol *PersHandlerSym =
228  TLOF.getCFIPersonalitySymbol(PerFn, Asm->TM, MMI);
229 
230  // Do not emit a .seh_handler directives for cleanup funclets.
231  // FIXME: This means cleanup funclets cannot handle exceptions. Given that
232  // Clang doesn't produce EH constructs inside cleanup funclets and LLVM's
233  // inliner doesn't allow inlining them, this isn't a major problem in
234  // practice.
235  if (!CurrentFuncletEntry->isCleanupFuncletEntry())
236  Asm->OutStreamer->EmitWinEHHandler(PersHandlerSym, true, true);
237  }
238 }
239 
241  if (isAArch64 && CurrentFuncletEntry &&
242  (shouldEmitMoves || shouldEmitPersonality)) {
243  Asm->OutStreamer->SwitchSection(CurrentFuncletTextSection);
244  Asm->OutStreamer->EmitWinCFIFuncletOrFuncEnd();
245  }
246  endFuncletImpl();
247 }
248 
249 void WinException::endFuncletImpl() {
250  // No funclet to process? Great, we have nothing to do.
251  if (!CurrentFuncletEntry)
252  return;
253 
254  const MachineFunction *MF = Asm->MF;
255  if (shouldEmitMoves || shouldEmitPersonality) {
256  const Function &F = MF->getFunction();
258  if (F.hasPersonalityFn())
259  Per = classifyEHPersonality(F.getPersonalityFn()->stripPointerCasts());
260 
261  if (Per == EHPersonality::MSVC_CXX && shouldEmitPersonality &&
262  !CurrentFuncletEntry->isCleanupFuncletEntry()) {
263  // Emit an UNWIND_INFO struct describing the prologue.
264  Asm->OutStreamer->EmitWinEHHandlerData();
265 
266  // If this is a C++ catch funclet (or the parent function),
267  // emit a reference to the LSDA for the parent function.
268  StringRef FuncLinkageName = GlobalValue::dropLLVMManglingEscape(F.getName());
269  MCSymbol *FuncInfoXData = Asm->OutContext.getOrCreateSymbol(
270  Twine("$cppxdata$", FuncLinkageName));
271  Asm->OutStreamer->emitValue(create32bitRef(FuncInfoXData), 4);
272  } else if (Per == EHPersonality::MSVC_TableSEH && MF->hasEHFunclets() &&
273  !CurrentFuncletEntry->isEHFuncletEntry()) {
274  // Emit an UNWIND_INFO struct describing the prologue.
275  Asm->OutStreamer->EmitWinEHHandlerData();
276 
277  // If this is the parent function in Win64 SEH, emit the LSDA immediately
278  // following .seh_handlerdata.
279  emitCSpecificHandlerTable(MF);
280  } else if (shouldEmitPersonality || shouldEmitLSDA) {
281  // Emit an UNWIND_INFO struct describing the prologue.
282  Asm->OutStreamer->EmitWinEHHandlerData();
283  // In these cases, no further info is written to the .xdata section
284  // right here, but is written by e.g. emitExceptionTable in endFunction()
285  // above.
286  } else {
287  // No need to emit the EH handler data right here if nothing needs
288  // writing to the .xdata section; it will be emitted for all
289  // functions that need it in the end anyway.
290  }
291 
292  // Switch back to the funclet start .text section now that we are done
293  // writing to .xdata, and emit an .seh_endproc directive to mark the end of
294  // the function.
295  Asm->OutStreamer->SwitchSection(CurrentFuncletTextSection);
296  Asm->OutStreamer->EmitWinCFIEndProc();
297  }
298 
299  // Let's make sure we don't try to end the same funclet twice.
300  CurrentFuncletEntry = nullptr;
301 }
302 
303 const MCExpr *WinException::create32bitRef(const MCSymbol *Value) {
304  if (!Value)
306  return MCSymbolRefExpr::create(Value, useImageRel32
309  Asm->OutContext);
310 }
311 
312 const MCExpr *WinException::create32bitRef(const GlobalValue *GV) {
313  if (!GV)
315  return create32bitRef(Asm->getSymbol(GV));
316 }
317 
318 const MCExpr *WinException::getLabel(const MCSymbol *Label) {
319  if (isAArch64)
321  Asm->OutContext);
322  return MCBinaryExpr::createAdd(create32bitRef(Label),
324  Asm->OutContext);
325 }
326 
327 const MCExpr *WinException::getOffset(const MCSymbol *OffsetOf,
328  const MCSymbol *OffsetFrom) {
332 }
333 
334 const MCExpr *WinException::getOffsetPlusOne(const MCSymbol *OffsetOf,
335  const MCSymbol *OffsetFrom) {
336  return MCBinaryExpr::createAdd(getOffset(OffsetOf, OffsetFrom),
338  Asm->OutContext);
339 }
340 
341 int WinException::getFrameIndexOffset(int FrameIndex,
342  const WinEHFuncInfo &FuncInfo) {
344  Register UnusedReg;
345  if (Asm->MAI->usesWindowsCFI()) {
348  /*IgnoreSPUpdates*/ true);
349  assert(UnusedReg ==
350  Asm->MF->getSubtarget()
353  return Offset.getFixed();
354  }
355 
356  // For 32-bit, offsets should be relative to the end of the EH registration
357  // node. For 64-bit, it's relative to SP at the end of the prologue.
358  assert(FuncInfo.EHRegNodeEndOffset != INT_MAX);
361  assert(!Offset.getScalable() &&
362  "Frame offsets with a scalable component are not supported");
363  return Offset.getFixed();
364 }
365 
366 namespace {
367 
368 /// Top-level state used to represent unwind to caller
369 const int NullState = -1;
370 
371 struct InvokeStateChange {
372  /// EH Label immediately after the last invoke in the previous state, or
373  /// nullptr if the previous state was the null state.
374  const MCSymbol *PreviousEndLabel;
375 
376  /// EH label immediately before the first invoke in the new state, or nullptr
377  /// if the new state is the null state.
378  const MCSymbol *NewStartLabel;
379 
380  /// State of the invoke following NewStartLabel, or NullState to indicate
381  /// the presence of calls which may unwind to caller.
382  int NewState;
383 };
384 
385 /// Iterator that reports all the invoke state changes in a range of machine
386 /// basic blocks. Changes to the null state are reported whenever a call that
387 /// may unwind to caller is encountered. The MBB range is expected to be an
388 /// entire function or funclet, and the start and end of the range are treated
389 /// as being in the NullState even if there's not an unwind-to-caller call
390 /// before the first invoke or after the last one (i.e., the first state change
391 /// reported is the first change to something other than NullState, and a
392 /// change back to NullState is always reported at the end of iteration).
393 class InvokeStateChangeIterator {
394  InvokeStateChangeIterator(const WinEHFuncInfo &EHInfo,
398  int BaseState)
399  : EHInfo(EHInfo), MFI(MFI), MFE(MFE), MBBI(MBBI), BaseState(BaseState) {
400  LastStateChange.PreviousEndLabel = nullptr;
401  LastStateChange.NewStartLabel = nullptr;
402  LastStateChange.NewState = BaseState;
403  scan();
404  }
405 
406 public:
408  range(const WinEHFuncInfo &EHInfo, MachineFunction::const_iterator Begin,
409  MachineFunction::const_iterator End, int BaseState = NullState) {
410  // Reject empty ranges to simplify bookkeeping by ensuring that we can get
411  // the end of the last block.
412  assert(Begin != End);
413  auto BlockBegin = Begin->begin();
414  auto BlockEnd = std::prev(End)->end();
415  return make_range(
416  InvokeStateChangeIterator(EHInfo, Begin, End, BlockBegin, BaseState),
417  InvokeStateChangeIterator(EHInfo, End, End, BlockEnd, BaseState));
418  }
419 
420  // Iterator methods.
421  bool operator==(const InvokeStateChangeIterator &O) const {
422  assert(BaseState == O.BaseState);
423  // Must be visiting same block.
424  if (MFI != O.MFI)
425  return false;
426  // Must be visiting same isntr.
427  if (MBBI != O.MBBI)
428  return false;
429  // At end of block/instr iteration, we can still have two distinct states:
430  // one to report the final EndLabel, and another indicating the end of the
431  // state change iteration. Check for CurrentEndLabel equality to
432  // distinguish these.
433  return CurrentEndLabel == O.CurrentEndLabel;
434  }
435 
436  bool operator!=(const InvokeStateChangeIterator &O) const {
437  return !operator==(O);
438  }
439  InvokeStateChange &operator*() { return LastStateChange; }
440  InvokeStateChange *operator->() { return &LastStateChange; }
441  InvokeStateChangeIterator &operator++() { return scan(); }
442 
443 private:
444  InvokeStateChangeIterator &scan();
445 
446  const WinEHFuncInfo &EHInfo;
447  const MCSymbol *CurrentEndLabel = nullptr;
451  InvokeStateChange LastStateChange;
452  bool VisitingInvoke = false;
453  int BaseState;
454 };
455 
456 } // end anonymous namespace
457 
458 InvokeStateChangeIterator &InvokeStateChangeIterator::scan() {
459  bool IsNewBlock = false;
460  for (; MFI != MFE; ++MFI, IsNewBlock = true) {
461  if (IsNewBlock)
462  MBBI = MFI->begin();
463  for (auto MBBE = MFI->end(); MBBI != MBBE; ++MBBI) {
464  const MachineInstr &MI = *MBBI;
465  if (!VisitingInvoke && LastStateChange.NewState != BaseState &&
466  MI.isCall() && !EHStreamer::callToNoUnwindFunction(&MI)) {
467  // Indicate a change of state to the null state. We don't have
468  // start/end EH labels handy but the caller won't expect them for
469  // null state regions.
470  LastStateChange.PreviousEndLabel = CurrentEndLabel;
471  LastStateChange.NewStartLabel = nullptr;
472  LastStateChange.NewState = BaseState;
473  CurrentEndLabel = nullptr;
474  // Don't re-visit this instr on the next scan
475  ++MBBI;
476  return *this;
477  }
478 
479  // All other state changes are at EH labels before/after invokes.
480  if (!MI.isEHLabel())
481  continue;
482  MCSymbol *Label = MI.getOperand(0).getMCSymbol();
483  if (Label == CurrentEndLabel) {
484  VisitingInvoke = false;
485  continue;
486  }
487  auto InvokeMapIter = EHInfo.LabelToStateMap.find(Label);
488  // Ignore EH labels that aren't the ones inserted before an invoke
489  if (InvokeMapIter == EHInfo.LabelToStateMap.end())
490  continue;
491  auto &StateAndEnd = InvokeMapIter->second;
492  int NewState = StateAndEnd.first;
493  // Keep track of the fact that we're between EH start/end labels so
494  // we know not to treat the inoke we'll see as unwinding to caller.
495  VisitingInvoke = true;
496  if (NewState == LastStateChange.NewState) {
497  // The state isn't actually changing here. Record the new end and
498  // keep going.
499  CurrentEndLabel = StateAndEnd.second;
500  continue;
501  }
502  // Found a state change to report
503  LastStateChange.PreviousEndLabel = CurrentEndLabel;
504  LastStateChange.NewStartLabel = Label;
505  LastStateChange.NewState = NewState;
506  // Start keeping track of the new current end
507  CurrentEndLabel = StateAndEnd.second;
508  // Don't re-visit this instr on the next scan
509  ++MBBI;
510  return *this;
511  }
512  }
513  // Iteration hit the end of the block range.
514  if (LastStateChange.NewState != BaseState) {
515  // Report the end of the last new state
516  LastStateChange.PreviousEndLabel = CurrentEndLabel;
517  LastStateChange.NewStartLabel = nullptr;
518  LastStateChange.NewState = BaseState;
519  // Leave CurrentEndLabel non-null to distinguish this state from end.
520  assert(CurrentEndLabel != nullptr);
521  return *this;
522  }
523  // We've reported all state changes and hit the end state.
524  CurrentEndLabel = nullptr;
525  return *this;
526 }
527 
528 /// Emit the language-specific data that __C_specific_handler expects. This
529 /// handler lives in the x64 Microsoft C runtime and allows catching or cleaning
530 /// up after faults with __try, __except, and __finally. The typeinfo values
531 /// are not really RTTI data, but pointers to filter functions that return an
532 /// integer (1, 0, or -1) indicating how to handle the exception. For __finally
533 /// blocks and other cleanups, the landing pad label is zero, and the filter
534 /// function is actually a cleanup handler with the same prototype. A catch-all
535 /// entry is modeled with a null filter function field and a non-zero landing
536 /// pad label.
537 ///
538 /// Possible filter function return values:
539 /// EXCEPTION_EXECUTE_HANDLER (1):
540 /// Jump to the landing pad label after cleanups.
541 /// EXCEPTION_CONTINUE_SEARCH (0):
542 /// Continue searching this table or continue unwinding.
543 /// EXCEPTION_CONTINUE_EXECUTION (-1):
544 /// Resume execution at the trapping PC.
545 ///
546 /// Inferred table structure:
547 /// struct Table {
548 /// int NumEntries;
549 /// struct Entry {
550 /// imagerel32 LabelStart;
551 /// imagerel32 LabelEnd;
552 /// imagerel32 FilterOrFinally; // One means catch-all.
553 /// imagerel32 LabelLPad; // Zero means __finally.
554 /// } Entries[NumEntries];
555 /// };
556 void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) {
557  auto &OS = *Asm->OutStreamer;
558  MCContext &Ctx = Asm->OutContext;
559  const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
560 
561  bool VerboseAsm = OS.isVerboseAsm();
562  auto AddComment = [&](const Twine &Comment) {
563  if (VerboseAsm)
564  OS.AddComment(Comment);
565  };
566 
567  if (!isAArch64) {
568  // Emit a label assignment with the SEH frame offset so we can use it for
569  // llvm.eh.recoverfp.
570  StringRef FLinkageName =
572  MCSymbol *ParentFrameOffset =
573  Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName);
574  const MCExpr *MCOffset =
576  Asm->OutStreamer->emitAssignment(ParentFrameOffset, MCOffset);
577  }
578 
579  // Use the assembler to compute the number of table entries through label
580  // difference and division.
581  MCSymbol *TableBegin =
582  Ctx.createTempSymbol("lsda_begin", /*AlwaysAddSuffix=*/true);
583  MCSymbol *TableEnd =
584  Ctx.createTempSymbol("lsda_end", /*AlwaysAddSuffix=*/true);
585  const MCExpr *LabelDiff = getOffset(TableEnd, TableBegin);
586  const MCExpr *EntrySize = MCConstantExpr::create(16, Ctx);
587  const MCExpr *EntryCount = MCBinaryExpr::createDiv(LabelDiff, EntrySize, Ctx);
588  AddComment("Number of call sites");
589  OS.emitValue(EntryCount, 4);
590 
591  OS.emitLabel(TableBegin);
592 
593  // Iterate over all the invoke try ranges. Unlike MSVC, LLVM currently only
594  // models exceptions from invokes. LLVM also allows arbitrary reordering of
595  // the code, so our tables end up looking a bit different. Rather than
596  // trying to match MSVC's tables exactly, we emit a denormalized table. For
597  // each range of invokes in the same state, we emit table entries for all
598  // the actions that would be taken in that state. This means our tables are
599  // slightly bigger, which is OK.
600  const MCSymbol *LastStartLabel = nullptr;
601  int LastEHState = -1;
602  // Break out before we enter into a finally funclet.
603  // FIXME: We need to emit separate EH tables for cleanups.
605  MachineFunction::const_iterator Stop = std::next(MF->begin());
606  while (Stop != End && !Stop->isEHFuncletEntry())
607  ++Stop;
608  for (const auto &StateChange :
609  InvokeStateChangeIterator::range(FuncInfo, MF->begin(), Stop)) {
610  // Emit all the actions for the state we just transitioned out of
611  // if it was not the null state
612  if (LastEHState != -1)
613  emitSEHActionsForRange(FuncInfo, LastStartLabel,
614  StateChange.PreviousEndLabel, LastEHState);
615  LastStartLabel = StateChange.NewStartLabel;
616  LastEHState = StateChange.NewState;
617  }
618 
619  OS.emitLabel(TableEnd);
620 }
621 
622 void WinException::emitSEHActionsForRange(const WinEHFuncInfo &FuncInfo,
623  const MCSymbol *BeginLabel,
624  const MCSymbol *EndLabel, int State) {
625  auto &OS = *Asm->OutStreamer;
626  MCContext &Ctx = Asm->OutContext;
627  bool VerboseAsm = OS.isVerboseAsm();
628  auto AddComment = [&](const Twine &Comment) {
629  if (VerboseAsm)
630  OS.AddComment(Comment);
631  };
632 
633  assert(BeginLabel && EndLabel);
634  while (State != -1) {
635  const SEHUnwindMapEntry &UME = FuncInfo.SEHUnwindMap[State];
636  const MCExpr *FilterOrFinally;
637  const MCExpr *ExceptOrNull;
638  auto *Handler = UME.Handler.get<MachineBasicBlock *>();
639  if (UME.IsFinally) {
640  FilterOrFinally = create32bitRef(getMCSymbolForMBB(Asm, Handler));
641  ExceptOrNull = MCConstantExpr::create(0, Ctx);
642  } else {
643  // For an except, the filter can be 1 (catch-all) or a function
644  // label.
645  FilterOrFinally = UME.Filter ? create32bitRef(UME.Filter)
646  : MCConstantExpr::create(1, Ctx);
647  ExceptOrNull = create32bitRef(Handler->getSymbol());
648  }
649 
650  AddComment("LabelStart");
651  OS.emitValue(getLabel(BeginLabel), 4);
652  AddComment("LabelEnd");
653  OS.emitValue(getLabel(EndLabel), 4);
654  AddComment(UME.IsFinally ? "FinallyFunclet" : UME.Filter ? "FilterFunction"
655  : "CatchAll");
656  OS.emitValue(FilterOrFinally, 4);
657  AddComment(UME.IsFinally ? "Null" : "ExceptionHandler");
658  OS.emitValue(ExceptOrNull, 4);
659 
660  assert(UME.ToState < State && "states should decrease");
661  State = UME.ToState;
662  }
663 }
664 
665 void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
666  const Function &F = MF->getFunction();
667  auto &OS = *Asm->OutStreamer;
668  const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
669 
670  StringRef FuncLinkageName = GlobalValue::dropLLVMManglingEscape(F.getName());
671 
673  MCSymbol *FuncInfoXData = nullptr;
674  if (shouldEmitPersonality) {
675  // If we're 64-bit, emit a pointer to the C++ EH data, and build a map from
676  // IPs to state numbers.
677  FuncInfoXData =
678  Asm->OutContext.getOrCreateSymbol(Twine("$cppxdata$", FuncLinkageName));
679  computeIP2StateTable(MF, FuncInfo, IPToStateTable);
680  } else {
681  FuncInfoXData = Asm->OutContext.getOrCreateLSDASymbol(FuncLinkageName);
682  }
683 
684  int UnwindHelpOffset = 0;
685  if (Asm->MAI->usesWindowsCFI())
686  UnwindHelpOffset =
687  getFrameIndexOffset(FuncInfo.UnwindHelpFrameIdx, FuncInfo);
688 
689  MCSymbol *UnwindMapXData = nullptr;
690  MCSymbol *TryBlockMapXData = nullptr;
691  MCSymbol *IPToStateXData = nullptr;
692  if (!FuncInfo.CxxUnwindMap.empty())
693  UnwindMapXData = Asm->OutContext.getOrCreateSymbol(
694  Twine("$stateUnwindMap$", FuncLinkageName));
695  if (!FuncInfo.TryBlockMap.empty())
696  TryBlockMapXData =
697  Asm->OutContext.getOrCreateSymbol(Twine("$tryMap$", FuncLinkageName));
698  if (!IPToStateTable.empty())
699  IPToStateXData =
700  Asm->OutContext.getOrCreateSymbol(Twine("$ip2state$", FuncLinkageName));
701 
702  bool VerboseAsm = OS.isVerboseAsm();
703  auto AddComment = [&](const Twine &Comment) {
704  if (VerboseAsm)
705  OS.AddComment(Comment);
706  };
707 
708  // FuncInfo {
709  // uint32_t MagicNumber
710  // int32_t MaxState;
711  // UnwindMapEntry *UnwindMap;
712  // uint32_t NumTryBlocks;
713  // TryBlockMapEntry *TryBlockMap;
714  // uint32_t IPMapEntries; // always 0 for x86
715  // IPToStateMapEntry *IPToStateMap; // always 0 for x86
716  // uint32_t UnwindHelp; // non-x86 only
717  // ESTypeList *ESTypeList;
718  // int32_t EHFlags;
719  // }
720  // EHFlags & 1 -> Synchronous exceptions only, no async exceptions.
721  // EHFlags & 2 -> ???
722  // EHFlags & 4 -> The function is noexcept(true), unwinding can't continue.
723  OS.emitValueToAlignment(4);
724  OS.emitLabel(FuncInfoXData);
725 
726  AddComment("MagicNumber");
727  OS.emitInt32(0x19930522);
728 
729  AddComment("MaxState");
730  OS.emitInt32(FuncInfo.CxxUnwindMap.size());
731 
732  AddComment("UnwindMap");
733  OS.emitValue(create32bitRef(UnwindMapXData), 4);
734 
735  AddComment("NumTryBlocks");
736  OS.emitInt32(FuncInfo.TryBlockMap.size());
737 
738  AddComment("TryBlockMap");
739  OS.emitValue(create32bitRef(TryBlockMapXData), 4);
740 
741  AddComment("IPMapEntries");
742  OS.emitInt32(IPToStateTable.size());
743 
744  AddComment("IPToStateXData");
745  OS.emitValue(create32bitRef(IPToStateXData), 4);
746 
747  if (Asm->MAI->usesWindowsCFI()) {
748  AddComment("UnwindHelp");
749  OS.emitInt32(UnwindHelpOffset);
750  }
751 
752  AddComment("ESTypeList");
753  OS.emitInt32(0);
754 
755  AddComment("EHFlags");
756  OS.emitInt32(1);
757 
758  // UnwindMapEntry {
759  // int32_t ToState;
760  // void (*Action)();
761  // };
762  if (UnwindMapXData) {
763  OS.emitLabel(UnwindMapXData);
764  for (const CxxUnwindMapEntry &UME : FuncInfo.CxxUnwindMap) {
765  MCSymbol *CleanupSym =
767  AddComment("ToState");
768  OS.emitInt32(UME.ToState);
769 
770  AddComment("Action");
771  OS.emitValue(create32bitRef(CleanupSym), 4);
772  }
773  }
774 
775  // TryBlockMap {
776  // int32_t TryLow;
777  // int32_t TryHigh;
778  // int32_t CatchHigh;
779  // int32_t NumCatches;
780  // HandlerType *HandlerArray;
781  // };
782  if (TryBlockMapXData) {
783  OS.emitLabel(TryBlockMapXData);
784  SmallVector<MCSymbol *, 1> HandlerMaps;
785  for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
786  const WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
787 
788  MCSymbol *HandlerMapXData = nullptr;
789  if (!TBME.HandlerArray.empty())
790  HandlerMapXData =
791  Asm->OutContext.getOrCreateSymbol(Twine("$handlerMap$")
792  .concat(Twine(I))
793  .concat("$")
794  .concat(FuncLinkageName));
795  HandlerMaps.push_back(HandlerMapXData);
796 
797  // TBMEs should form intervals.
798  assert(0 <= TBME.TryLow && "bad trymap interval");
799  assert(TBME.TryLow <= TBME.TryHigh && "bad trymap interval");
800  assert(TBME.TryHigh < TBME.CatchHigh && "bad trymap interval");
801  assert(TBME.CatchHigh < int(FuncInfo.CxxUnwindMap.size()) &&
802  "bad trymap interval");
803 
804  AddComment("TryLow");
805  OS.emitInt32(TBME.TryLow);
806 
807  AddComment("TryHigh");
808  OS.emitInt32(TBME.TryHigh);
809 
810  AddComment("CatchHigh");
811  OS.emitInt32(TBME.CatchHigh);
812 
813  AddComment("NumCatches");
814  OS.emitInt32(TBME.HandlerArray.size());
815 
816  AddComment("HandlerArray");
817  OS.emitValue(create32bitRef(HandlerMapXData), 4);
818  }
819 
820  // All funclets use the same parent frame offset currently.
821  unsigned ParentFrameOffset = 0;
822  if (shouldEmitPersonality) {
824  ParentFrameOffset = TFI->getWinEHParentFrameOffset(*MF);
825  }
826 
827  for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
828  const WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
829  MCSymbol *HandlerMapXData = HandlerMaps[I];
830  if (!HandlerMapXData)
831  continue;
832  // HandlerType {
833  // int32_t Adjectives;
834  // TypeDescriptor *Type;
835  // int32_t CatchObjOffset;
836  // void (*Handler)();
837  // int32_t ParentFrameOffset; // x64 and AArch64 only
838  // };
839  OS.emitLabel(HandlerMapXData);
840  for (const WinEHHandlerType &HT : TBME.HandlerArray) {
841  // Get the frame escape label with the offset of the catch object. If
842  // the index is INT_MAX, then there is no catch object, and we should
843  // emit an offset of zero, indicating that no copy will occur.
844  const MCExpr *FrameAllocOffsetRef = nullptr;
845  if (HT.CatchObj.FrameIndex != INT_MAX) {
846  int Offset = getFrameIndexOffset(HT.CatchObj.FrameIndex, FuncInfo);
847  assert(Offset != 0 && "Illegal offset for catch object!");
848  FrameAllocOffsetRef = MCConstantExpr::create(Offset, Asm->OutContext);
849  } else {
850  FrameAllocOffsetRef = MCConstantExpr::create(0, Asm->OutContext);
851  }
852 
853  MCSymbol *HandlerSym =
855 
856  AddComment("Adjectives");
857  OS.emitInt32(HT.Adjectives);
858 
859  AddComment("Type");
860  OS.emitValue(create32bitRef(HT.TypeDescriptor), 4);
861 
862  AddComment("CatchObjOffset");
863  OS.emitValue(FrameAllocOffsetRef, 4);
864 
865  AddComment("Handler");
866  OS.emitValue(create32bitRef(HandlerSym), 4);
867 
868  if (shouldEmitPersonality) {
869  AddComment("ParentFrameOffset");
870  OS.emitInt32(ParentFrameOffset);
871  }
872  }
873  }
874  }
875 
876  // IPToStateMapEntry {
877  // void *IP;
878  // int32_t State;
879  // };
880  if (IPToStateXData) {
881  OS.emitLabel(IPToStateXData);
882  for (auto &IPStatePair : IPToStateTable) {
883  AddComment("IP");
884  OS.emitValue(IPStatePair.first, 4);
885  AddComment("ToState");
886  OS.emitInt32(IPStatePair.second);
887  }
888  }
889 }
890 
891 void WinException::computeIP2StateTable(
892  const MachineFunction *MF, const WinEHFuncInfo &FuncInfo,
893  SmallVectorImpl<std::pair<const MCExpr *, int>> &IPToStateTable) {
894 
895  for (MachineFunction::const_iterator FuncletStart = MF->begin(),
896  FuncletEnd = MF->begin(),
897  End = MF->end();
898  FuncletStart != End; FuncletStart = FuncletEnd) {
899  // Find the end of the funclet
900  while (++FuncletEnd != End) {
901  if (FuncletEnd->isEHFuncletEntry()) {
902  break;
903  }
904  }
905 
906  // Don't emit ip2state entries for cleanup funclets. Any interesting
907  // exceptional actions in cleanups must be handled in a separate IR
908  // function.
909  if (FuncletStart->isCleanupFuncletEntry())
910  continue;
911 
912  MCSymbol *StartLabel;
913  int BaseState;
914  if (FuncletStart == MF->begin()) {
915  BaseState = NullState;
916  StartLabel = Asm->getFunctionBegin();
917  } else {
918  auto *FuncletPad =
919  cast<FuncletPadInst>(FuncletStart->getBasicBlock()->getFirstNonPHI());
920  assert(FuncInfo.FuncletBaseStateMap.count(FuncletPad) != 0);
921  BaseState = FuncInfo.FuncletBaseStateMap.find(FuncletPad)->second;
922  StartLabel = getMCSymbolForMBB(Asm, &*FuncletStart);
923  }
924  assert(StartLabel && "need local function start label");
925  IPToStateTable.push_back(
926  std::make_pair(create32bitRef(StartLabel), BaseState));
927 
928  for (const auto &StateChange : InvokeStateChangeIterator::range(
929  FuncInfo, FuncletStart, FuncletEnd, BaseState)) {
930  // Compute the label to report as the start of this entry; use the EH
931  // start label for the invoke if we have one, otherwise (this is a call
932  // which may unwind to our caller and does not have an EH start label, so)
933  // use the previous end label.
934  const MCSymbol *ChangeLabel = StateChange.NewStartLabel;
935  if (!ChangeLabel)
936  ChangeLabel = StateChange.PreviousEndLabel;
937  // Emit an entry indicating that PCs after 'Label' have this EH state.
938  IPToStateTable.push_back(
939  std::make_pair(getLabel(ChangeLabel), StateChange.NewState));
940  // FIXME: assert that NewState is between CatchLow and CatchHigh.
941  }
942  }
943 }
944 
945 void WinException::emitEHRegistrationOffsetLabel(const WinEHFuncInfo &FuncInfo,
946  StringRef FLinkageName) {
947  // Outlined helpers called by the EH runtime need to know the offset of the EH
948  // registration in order to recover the parent frame pointer. Now that we know
949  // we've code generated the parent, we can emit the label assignment that
950  // those helpers use to get the offset of the registration node.
951 
952  // Compute the parent frame offset. The EHRegNodeFrameIndex will be invalid if
953  // after optimization all the invokes were eliminated. We still need to emit
954  // the parent frame offset label, but it should be garbage and should never be
955  // used.
956  int64_t Offset = 0;
957  int FI = FuncInfo.EHRegNodeFrameIndex;
958  if (FI != INT_MAX) {
961  }
962 
963  MCContext &Ctx = Asm->OutContext;
964  MCSymbol *ParentFrameOffset =
965  Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName);
966  Asm->OutStreamer->emitAssignment(ParentFrameOffset,
968 }
969 
970 /// Emit the language-specific data that _except_handler3 and 4 expect. This is
971 /// functionally equivalent to the __C_specific_handler table, except it is
972 /// indexed by state number instead of IP.
973 void WinException::emitExceptHandlerTable(const MachineFunction *MF) {
974  MCStreamer &OS = *Asm->OutStreamer;
975  const Function &F = MF->getFunction();
976  StringRef FLinkageName = GlobalValue::dropLLVMManglingEscape(F.getName());
977 
978  bool VerboseAsm = OS.isVerboseAsm();
979  auto AddComment = [&](const Twine &Comment) {
980  if (VerboseAsm)
981  OS.AddComment(Comment);
982  };
983 
984  const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
985  emitEHRegistrationOffsetLabel(FuncInfo, FLinkageName);
986 
987  // Emit the __ehtable label that we use for llvm.x86.seh.lsda.
988  MCSymbol *LSDALabel = Asm->OutContext.getOrCreateLSDASymbol(FLinkageName);
989  OS.emitValueToAlignment(4);
990  OS.emitLabel(LSDALabel);
991 
992  const auto *Per = cast<Function>(F.getPersonalityFn()->stripPointerCasts());
993  StringRef PerName = Per->getName();
994  int BaseState = -1;
995  if (PerName == "_except_handler4") {
996  // The LSDA for _except_handler4 starts with this struct, followed by the
997  // scope table:
998  //
999  // struct EH4ScopeTable {
1000  // int32_t GSCookieOffset;
1001  // int32_t GSCookieXOROffset;
1002  // int32_t EHCookieOffset;
1003  // int32_t EHCookieXOROffset;
1004  // ScopeTableEntry ScopeRecord[];
1005  // };
1006  //
1007  // Offsets are %ebp relative.
1008  //
1009  // The GS cookie is present only if the function needs stack protection.
1010  // GSCookieOffset = -2 means that GS cookie is not used.
1011  //
1012  // The EH cookie is always present.
1013  //
1014  // Check is done the following way:
1015  // (ebp+CookieXOROffset) ^ [ebp+CookieOffset] == _security_cookie
1016 
1017  // Retrieve the Guard Stack slot.
1018  int GSCookieOffset = -2;
1019  const MachineFrameInfo &MFI = MF->getFrameInfo();
1020  if (MFI.hasStackProtectorIndex()) {
1021  Register UnusedReg;
1022  const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering();
1023  int SSPIdx = MFI.getStackProtectorIndex();
1024  GSCookieOffset =
1025  TFI->getFrameIndexReference(*MF, SSPIdx, UnusedReg).getFixed();
1026  }
1027 
1028  // Retrieve the EH Guard slot.
1029  // TODO(etienneb): Get rid of this value and change it for and assertion.
1030  int EHCookieOffset = 9999;
1031  if (FuncInfo.EHGuardFrameIndex != INT_MAX) {
1032  Register UnusedReg;
1033  const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering();
1034  int EHGuardIdx = FuncInfo.EHGuardFrameIndex;
1035  EHCookieOffset =
1036  TFI->getFrameIndexReference(*MF, EHGuardIdx, UnusedReg).getFixed();
1037  }
1038 
1039  AddComment("GSCookieOffset");
1040  OS.emitInt32(GSCookieOffset);
1041  AddComment("GSCookieXOROffset");
1042  OS.emitInt32(0);
1043  AddComment("EHCookieOffset");
1044  OS.emitInt32(EHCookieOffset);
1045  AddComment("EHCookieXOROffset");
1046  OS.emitInt32(0);
1047  BaseState = -2;
1048  }
1049 
1050  assert(!FuncInfo.SEHUnwindMap.empty());
1051  for (const SEHUnwindMapEntry &UME : FuncInfo.SEHUnwindMap) {
1052  auto *Handler = UME.Handler.get<MachineBasicBlock *>();
1053  const MCSymbol *ExceptOrFinally =
1054  UME.IsFinally ? getMCSymbolForMBB(Asm, Handler) : Handler->getSymbol();
1055  // -1 is usually the base state for "unwind to caller", but for
1056  // _except_handler4 it's -2. Do that replacement here if necessary.
1057  int ToState = UME.ToState == -1 ? BaseState : UME.ToState;
1058  AddComment("ToState");
1059  OS.emitInt32(ToState);
1060  AddComment(UME.IsFinally ? "Null" : "FilterFunction");
1061  OS.emitValue(create32bitRef(UME.Filter), 4);
1062  AddComment(UME.IsFinally ? "FinallyFunclet" : "ExceptionHandler");
1063  OS.emitValue(create32bitRef(ExceptOrFinally), 4);
1064  }
1065 }
1066 
1067 static int getTryRank(const WinEHFuncInfo &FuncInfo, int State) {
1068  int Rank = 0;
1069  while (State != -1) {
1070  ++Rank;
1071  State = FuncInfo.ClrEHUnwindMap[State].TryParentState;
1072  }
1073  return Rank;
1074 }
1075 
1076 static int getTryAncestor(const WinEHFuncInfo &FuncInfo, int Left, int Right) {
1077  int LeftRank = getTryRank(FuncInfo, Left);
1078  int RightRank = getTryRank(FuncInfo, Right);
1079 
1080  while (LeftRank < RightRank) {
1081  Right = FuncInfo.ClrEHUnwindMap[Right].TryParentState;
1082  --RightRank;
1083  }
1084 
1085  while (RightRank < LeftRank) {
1086  Left = FuncInfo.ClrEHUnwindMap[Left].TryParentState;
1087  --LeftRank;
1088  }
1089 
1090  while (Left != Right) {
1091  Left = FuncInfo.ClrEHUnwindMap[Left].TryParentState;
1092  Right = FuncInfo.ClrEHUnwindMap[Right].TryParentState;
1093  }
1094 
1095  return Left;
1096 }
1097 
1098 void WinException::emitCLRExceptionTable(const MachineFunction *MF) {
1099  // CLR EH "states" are really just IDs that identify handlers/funclets;
1100  // states, handlers, and funclets all have 1:1 mappings between them, and a
1101  // handler/funclet's "state" is its index in the ClrEHUnwindMap.
1102  MCStreamer &OS = *Asm->OutStreamer;
1103  const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
1104  MCSymbol *FuncBeginSym = Asm->getFunctionBegin();
1105  MCSymbol *FuncEndSym = Asm->getFunctionEnd();
1106 
1107  // A ClrClause describes a protected region.
1108  struct ClrClause {
1109  const MCSymbol *StartLabel; // Start of protected region
1110  const MCSymbol *EndLabel; // End of protected region
1111  int State; // Index of handler protecting the protected region
1112  int EnclosingState; // Index of funclet enclosing the protected region
1113  };
1114  SmallVector<ClrClause, 8> Clauses;
1115 
1116  // Build a map from handler MBBs to their corresponding states (i.e. their
1117  // indices in the ClrEHUnwindMap).
1118  int NumStates = FuncInfo.ClrEHUnwindMap.size();
1119  assert(NumStates > 0 && "Don't need exception table!");
1121  for (int State = 0; State < NumStates; ++State) {
1122  MachineBasicBlock *HandlerBlock =
1123  FuncInfo.ClrEHUnwindMap[State].Handler.get<MachineBasicBlock *>();
1124  HandlerStates[HandlerBlock] = State;
1125  // Use this loop through all handlers to verify our assumption (used in
1126  // the MinEnclosingState computation) that enclosing funclets have lower
1127  // state numbers than their enclosed funclets.
1128  assert(FuncInfo.ClrEHUnwindMap[State].HandlerParentState < State &&
1129  "ill-formed state numbering");
1130  }
1131  // Map the main function to the NullState.
1132  HandlerStates[&MF->front()] = NullState;
1133 
1134  // Write out a sentinel indicating the end of the standard (Windows) xdata
1135  // and the start of the additional (CLR) info.
1136  OS.emitInt32(0xffffffff);
1137  // Write out the number of funclets
1138  OS.emitInt32(NumStates);
1139 
1140  // Walk the machine blocks/instrs, computing and emitting a few things:
1141  // 1. Emit a list of the offsets to each handler entry, in lexical order.
1142  // 2. Compute a map (EndSymbolMap) from each funclet to the symbol at its end.
1143  // 3. Compute the list of ClrClauses, in the required order (inner before
1144  // outer, earlier before later; the order by which a forward scan with
1145  // early termination will find the innermost enclosing clause covering
1146  // a given address).
1147  // 4. A map (MinClauseMap) from each handler index to the index of the
1148  // outermost funclet/function which contains a try clause targeting the
1149  // key handler. This will be used to determine IsDuplicate-ness when
1150  // emitting ClrClauses. The NullState value is used to indicate that the
1151  // top-level function contains a try clause targeting the key handler.
1152  // HandlerStack is a stack of (PendingStartLabel, PendingState) pairs for
1153  // try regions we entered before entering the PendingState try but which
1154  // we haven't yet exited.
1156  // EndSymbolMap and MinClauseMap are maps described above.
1157  std::unique_ptr<MCSymbol *[]> EndSymbolMap(new MCSymbol *[NumStates]);
1158  SmallVector<int, 4> MinClauseMap((size_t)NumStates, NumStates);
1159 
1160  // Visit the root function and each funclet.
1161  for (MachineFunction::const_iterator FuncletStart = MF->begin(),
1162  FuncletEnd = MF->begin(),
1163  End = MF->end();
1164  FuncletStart != End; FuncletStart = FuncletEnd) {
1165  int FuncletState = HandlerStates[&*FuncletStart];
1166  // Find the end of the funclet
1167  MCSymbol *EndSymbol = FuncEndSym;
1168  while (++FuncletEnd != End) {
1169  if (FuncletEnd->isEHFuncletEntry()) {
1170  EndSymbol = getMCSymbolForMBB(Asm, &*FuncletEnd);
1171  break;
1172  }
1173  }
1174  // Emit the function/funclet end and, if this is a funclet (and not the
1175  // root function), record it in the EndSymbolMap.
1176  OS.emitValue(getOffset(EndSymbol, FuncBeginSym), 4);
1177  if (FuncletState != NullState) {
1178  // Record the end of the handler.
1179  EndSymbolMap[FuncletState] = EndSymbol;
1180  }
1181 
1182  // Walk the state changes in this function/funclet and compute its clauses.
1183  // Funclets always start in the null state.
1184  const MCSymbol *CurrentStartLabel = nullptr;
1185  int CurrentState = NullState;
1186  assert(HandlerStack.empty());
1187  for (const auto &StateChange :
1188  InvokeStateChangeIterator::range(FuncInfo, FuncletStart, FuncletEnd)) {
1189  // Close any try regions we're not still under
1190  int StillPendingState =
1191  getTryAncestor(FuncInfo, CurrentState, StateChange.NewState);
1192  while (CurrentState != StillPendingState) {
1193  assert(CurrentState != NullState &&
1194  "Failed to find still-pending state!");
1195  // Close the pending clause
1196  Clauses.push_back({CurrentStartLabel, StateChange.PreviousEndLabel,
1197  CurrentState, FuncletState});
1198  // Now the next-outer try region is current
1199  CurrentState = FuncInfo.ClrEHUnwindMap[CurrentState].TryParentState;
1200  // Pop the new start label from the handler stack if we've exited all
1201  // inner try regions of the corresponding try region.
1202  if (HandlerStack.back().second == CurrentState)
1203  CurrentStartLabel = HandlerStack.pop_back_val().first;
1204  }
1205 
1206  if (StateChange.NewState != CurrentState) {
1207  // For each clause we're starting, update the MinClauseMap so we can
1208  // know which is the topmost funclet containing a clause targeting
1209  // it.
1210  for (int EnteredState = StateChange.NewState;
1211  EnteredState != CurrentState;
1212  EnteredState =
1213  FuncInfo.ClrEHUnwindMap[EnteredState].TryParentState) {
1214  int &MinEnclosingState = MinClauseMap[EnteredState];
1215  if (FuncletState < MinEnclosingState)
1216  MinEnclosingState = FuncletState;
1217  }
1218  // Save the previous current start/label on the stack and update to
1219  // the newly-current start/state.
1220  HandlerStack.emplace_back(CurrentStartLabel, CurrentState);
1221  CurrentStartLabel = StateChange.NewStartLabel;
1222  CurrentState = StateChange.NewState;
1223  }
1224  }
1225  assert(HandlerStack.empty());
1226  }
1227 
1228  // Now emit the clause info, starting with the number of clauses.
1229  OS.emitInt32(Clauses.size());
1230  for (ClrClause &Clause : Clauses) {
1231  // Emit a CORINFO_EH_CLAUSE :
1232  /*
1233  struct CORINFO_EH_CLAUSE
1234  {
1235  CORINFO_EH_CLAUSE_FLAGS Flags; // actually a CorExceptionFlag
1236  DWORD TryOffset;
1237  DWORD TryLength; // actually TryEndOffset
1238  DWORD HandlerOffset;
1239  DWORD HandlerLength; // actually HandlerEndOffset
1240  union
1241  {
1242  DWORD ClassToken; // use for catch clauses
1243  DWORD FilterOffset; // use for filter clauses
1244  };
1245  };
1246 
1247  enum CORINFO_EH_CLAUSE_FLAGS
1248  {
1249  CORINFO_EH_CLAUSE_NONE = 0,
1250  CORINFO_EH_CLAUSE_FILTER = 0x0001, // This clause is for a filter
1251  CORINFO_EH_CLAUSE_FINALLY = 0x0002, // This clause is a finally clause
1252  CORINFO_EH_CLAUSE_FAULT = 0x0004, // This clause is a fault clause
1253  };
1254  typedef enum CorExceptionFlag
1255  {
1256  COR_ILEXCEPTION_CLAUSE_NONE,
1257  COR_ILEXCEPTION_CLAUSE_FILTER = 0x0001, // This is a filter clause
1258  COR_ILEXCEPTION_CLAUSE_FINALLY = 0x0002, // This is a finally clause
1259  COR_ILEXCEPTION_CLAUSE_FAULT = 0x0004, // This is a fault clause
1260  COR_ILEXCEPTION_CLAUSE_DUPLICATED = 0x0008, // duplicated clause. This
1261  // clause was duplicated
1262  // to a funclet which was
1263  // pulled out of line
1264  } CorExceptionFlag;
1265  */
1266  // Add 1 to the start/end of the EH clause; the IP associated with a
1267  // call when the runtime does its scan is the IP of the next instruction
1268  // (the one to which control will return after the call), so we need
1269  // to add 1 to the end of the clause to cover that offset. We also add
1270  // 1 to the start of the clause to make sure that the ranges reported
1271  // for all clauses are disjoint. Note that we'll need some additional
1272  // logic when machine traps are supported, since in that case the IP
1273  // that the runtime uses is the offset of the faulting instruction
1274  // itself; if such an instruction immediately follows a call but the
1275  // two belong to different clauses, we'll need to insert a nop between
1276  // them so the runtime can distinguish the point to which the call will
1277  // return from the point at which the fault occurs.
1278 
1279  const MCExpr *ClauseBegin =
1280  getOffsetPlusOne(Clause.StartLabel, FuncBeginSym);
1281  const MCExpr *ClauseEnd = getOffsetPlusOne(Clause.EndLabel, FuncBeginSym);
1282 
1283  const ClrEHUnwindMapEntry &Entry = FuncInfo.ClrEHUnwindMap[Clause.State];
1284  MachineBasicBlock *HandlerBlock = Entry.Handler.get<MachineBasicBlock *>();
1285  MCSymbol *BeginSym = getMCSymbolForMBB(Asm, HandlerBlock);
1286  const MCExpr *HandlerBegin = getOffset(BeginSym, FuncBeginSym);
1287  MCSymbol *EndSym = EndSymbolMap[Clause.State];
1288  const MCExpr *HandlerEnd = getOffset(EndSym, FuncBeginSym);
1289 
1290  uint32_t Flags = 0;
1291  switch (Entry.HandlerType) {
1292  case ClrHandlerType::Catch:
1293  // Leaving bits 0-2 clear indicates catch.
1294  break;
1296  Flags |= 1;
1297  break;
1299  Flags |= 2;
1300  break;
1301  case ClrHandlerType::Fault:
1302  Flags |= 4;
1303  break;
1304  }
1305  if (Clause.EnclosingState != MinClauseMap[Clause.State]) {
1306  // This is a "duplicate" clause; the handler needs to be entered from a
1307  // frame above the one holding the invoke.
1308  assert(Clause.EnclosingState > MinClauseMap[Clause.State]);
1309  Flags |= 8;
1310  }
1311  OS.emitInt32(Flags);
1312 
1313  // Write the clause start/end
1314  OS.emitValue(ClauseBegin, 4);
1315  OS.emitValue(ClauseEnd, 4);
1316 
1317  // Write out the handler start/end
1318  OS.emitValue(HandlerBegin, 4);
1319  OS.emitValue(HandlerEnd, 4);
1320 
1321  // Write out the type token or filter offset
1322  assert(Entry.HandlerType != ClrHandlerType::Filter && "NYI: filters");
1323  OS.emitInt32(Entry.TypeToken);
1324  }
1325 }
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&... Ranges)
Concatenated range across two or more ranges.
Definition: STLExtras.h:1020
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:253
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
Definition: MCStreamer.cpp:414
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
Definition: AsmPrinter.cpp:222
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition: MCSection.h:39
reference emplace_back(ArgTypes &&... Args)
Definition: SmallVector.h:856
bool usesWindowsCFI() const
Definition: MCAsmInfo.h:653
SmallVector< WinEHHandlerType, 1 > HandlerArray
Definition: WinEHFuncInfo.h:76
DenseMap< MCSymbol *, std::pair< int, MCSymbol * > > LabelToStateMap
Definition: WinEHFuncInfo.h:94
StackOffset is a class to represent an offset with 2 dimensions, named fixed and scalable,...
Definition: TypeSize.h:130
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition: AsmPrinter.h:97
static int getTryAncestor(const WinEHFuncInfo &FuncInfo, int Left, int Right)
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:381
MBBOrBasicBlock Cleanup
Definition: WinEHFuncInfo.h:42
This class represents lattice values for constants.
Definition: AllocatorList.h:23
static MCSymbol * getMCSymbolForMBB(AsmPrinter *Asm, const MachineBasicBlock *MBB)
Retrieve the MCSymbol for a GlobalValue or MachineBasicBlock.
virtual StackOffset getNonLocalFrameIndexReference(const MachineFunction &MF, int FI) const
getNonLocalFrameIndexReference - This method returns the offset used to reference a frame index locat...
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
Align getAlignment() const
getAlignment - Return the alignment of the function.
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
bool hasStackProtectorIndex() const
SmallVector< SEHUnwindMapEntry, 4 > SEHUnwindMap
Definition: WinEHFuncInfo.h:97
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition: AsmPrinter.h:92
bool isCleanupFuncletEntry() const
Returns true if this is the entry block of a cleanup funclet.
void beginFunclet(const MachineBasicBlock &MBB, MCSymbol *Sym) override
Emit target-specific EH funclet machinery.
DenseMap< const FuncletPadInst *, int > FuncletBaseStateMap
Definition: WinEHFuncInfo.h:92
static bool callToNoUnwindFunction(const MachineInstr *MI)
Return ‘true’ if this is a call to a function marked ‘nounwind’.
Definition: EHStreamer.cpp:162
virtual const TargetLowering * getTargetLowering() const
MCSymbol * getOrCreateParentFrameOffsetSymbol(StringRef FuncName)
Definition: MCContext.cpp:161
virtual StackOffset getFrameIndexReferencePreferSP(const MachineFunction &MF, int FI, Register &FrameReg, bool IgnoreSPUpdates) const
Same as getFrameIndexReference, except that the stack pointer (as opposed to the frame pointer) will ...
F(f)
MachineFunction * MF
The current machine function.
Definition: AsmPrinter.h:100
T get() const
Returns the value of the specified pointer type.
Definition: PointerUnion.h:187
Function & getFunction()
Return the LLVM function that this machine code represents.
MachineBasicBlock & MBB
MachineModuleInfo * MMI
Collected machine module information.
Definition: EHStreamer.h:36
MBBOrBasicBlock Handler
Holds the __except or __finally basic block.
Definition: WinEHFuncInfo.h:57
T dyn_cast() const
Returns the current pointer if it is of the specified pointer type, otherwise returns null.
Definition: PointerUnion.h:194
void endModule() override
Emit all exception information that should come after the content.
Emits exception handling directives.
Definition: EHStreamer.h:30
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
static StackOffset getFixed(ScalarTy Fixed)
Definition: TypeSize.h:139
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
bool isAArch64() const
Tests whether the target is AArch64 (little and big endian).
Definition: Triple.h:720
static const MCBinaryExpr * createDiv(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:530
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:43
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
void emitInt32(uint64_t Value)
Definition: MCStreamer.h:705
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
Align getAlignment() const
Return alignment of the basic block.
virtual unsigned getWinEHParentFrameOffset(const MachineFunction &MF) const
int ToState
If unwinding continues through this handler, transition to the handler at this state.
Definition: WinEHFuncInfo.h:49
Context object for machine code objects.
Definition: MCContext.h:68
virtual void AddComment(const Twine &T, bool EOL=true)
Add a textual comment.
Definition: MCStreamer.h:341
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:605
MCSymbol * getFunctionBegin() const
Definition: AsmPrinter.h:249
void tidyLandingPads(DenseMap< MCSymbol *, uintptr_t > *LPMap=nullptr, bool TidyIfNoBeginLabels=true)
Remap landing pad labels and remove any deleted landing pads.
int getNumber() const
MachineBasicBlocks are uniquely numbered at the function level, unless they're not in a MachineFuncti...
Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT))
Definition: COFF.h:265
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:520
void endFunclet() override
Similar to CxxUnwindMapEntry, but supports SEH filters.
Definition: WinEHFuncInfo.h:46
SmallVector< ClrEHUnwindMapEntry, 4 > ClrEHUnwindMap
Definition: WinEHFuncInfo.h:98
Streaming machine code generation interface.
Definition: MCStreamer.h:198
MCSymbol * CurrentFnSym
The symbol for the current function.
Definition: AsmPrinter.h:119
const MCAsmInfo * MAI
Target Asm Printer information.
Definition: AsmPrinter.h:88
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
bool hasEHFunclets() const
virtual StackOffset getFrameIndexReference(const MachineFunction &MF, int FI, Register &FrameReg) const
getFrameIndexReference - This method should return the base register and offset used to reference a f...
WinException(AsmPrinter *A)
TargetMachine & TM
Target machine description.
Definition: AsmPrinter.h:85
int getStackProtectorIndex() const
Return the index for the stack protector object.
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:82
void endFunction(const MachineFunction *) override
Gather and emit post-function exception information.
EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
ScalarTy getFixed() const
Definition: TypeSize.h:145
const Triple & getTargetTriple() const
Register getStackPointerRegisterToSaveRestore() const
If a physical register, this specifies the register that llvm.savestack/llvm.restorestack should save...
const MachineBasicBlock & front() const
AsmPrinter * Asm
Target of directive emission.
Definition: EHStreamer.h:33
MBBOrBasicBlock Handler
Definition: WinEHFuncInfo.h:69
void beginFunction(const MachineFunction *MF) override
Gather pre-function exception information.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
SmallVector< CxxUnwindMapEntry, 4 > CxxUnwindMap
Definition: WinEHFuncInfo.h:95
const std::vector< LandingPadInfo > & getLandingPads() const
Return a reference to the landing pad info for the current function.
const Function * Filter
Holds the filter expression function.
Definition: WinEHFuncInfo.h:54
uint64_t Offset
Iterator for intrusive lists based on ilist_node.
Align max(MaybeAlign Lhs, Align Rhs)
Definition: Alignment.h:350
union llvm::WinEHHandlerType::@216 CatchObj
The CatchObj starts out life as an LLVM alloca and is eventually turned frame index.
MCSymbol * getOrCreateLSDASymbol(StringRef FuncName)
Definition: MCContext.cpp:166
bool isFuncletEHPersonality(EHPersonality Pers)
Returns true if this is a personality function that invokes handler funclets (which must return to it...
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:472
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1116
Module.h This file contains the declarations for the Module class.
void markFunctionEnd() override
Information about stack frame layout on the target.
LLVM_NODISCARD T pop_back_val()
Definition: SmallVector.h:595
const WinEHFuncInfo * getWinEHFuncInfo() const
getWinEHFuncInfo - Return information about how the current function uses Windows exception handling.
MCSymbol * getFunctionEnd() const
Definition: AsmPrinter.h:250
SmallVector< WinEHTryBlockMapEntry, 4 > TryBlockMap
Definition: WinEHFuncInfo.h:96
A range adaptor for a pair of iterators.
This file contains constants used for implementing Dwarf debug support.
static StringRef dropLLVMManglingEscape(StringRef Name)
If the given string begins with the GlobalValue name mangling escape character '\1',...
Definition: GlobalValue.h:482
GlobalVariable * TypeDescriptor
Definition: WinEHFuncInfo.h:68
~WinException() override
bool operator!=(uint64_t V1, const APInt &V2)
Definition: APInt.h:2037
Representation of each machine instruction.
Definition: MachineInstr.h:62
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
virtual void emitValueToAlignment(unsigned ByteAlignment, int64_t Value=0, unsigned ValueSize=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:142
APInt operator *(APInt a, uint64_t RHS)
Definition: APInt.h:2159
bool isEHFuncletEntry() const
Returns true if this is the entry block of an EH funclet.
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:295
#define I(x, y, z)
Definition: MD5.cpp:59
virtual const TargetFrameLowering * getFrameLowering() const
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
Definition: MCStreamer.cpp:176
const Module * getModule() const
static int getTryRank(const WinEHFuncInfo &FuncInfo, int State)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
MCSymbol * emitExceptionTable()
Emit landing pads and actions.
Definition: EHStreamer.cpp:381
LLVM Value Representation.
Definition: Value.h:75
void emitAlignment(Align Alignment, const GlobalObject *GV=nullptr) const
Emit an alignment directive to the specified power of two boundary.
IRTranslator LLVM IR MI
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
bool operator==(uint64_t V1, const APInt &V2)
Definition: APInt.h:2035
virtual MCSymbol * getCFIPersonalitySymbol(const GlobalValue *GV, const TargetMachine &TM, MachineModuleInfo *MMI) const
virtual bool isVerboseAsm() const
Return true if this streamer supports verbose assembly and if it is enabled.
Definition: MCStreamer.h:318
bool isNoOpWithoutInvoke(EHPersonality Pers)
Return true if this personality may be safely removed if there are no invoke instructions remaining i...
static Expected< BitVector > scan(StringRef &S, StringRef Original)
Definition: GlobPattern.cpp:67
MachineBasicBlock MachineBasicBlock::iterator MBBI
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
This file describes how to lower LLVM code to machine code.
A function that returns a base type.
Definition: COFF.h:261