LLVM  3.7.0
WinException.cpp
Go to the documentation of this file.
1 //===-- CodeGen/AsmPrinter/WinException.cpp - Dwarf Exception Impl ------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains support for writing Win64 exception info into asm files.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "WinException.h"
15 #include "llvm/ADT/SmallString.h"
16 #include "llvm/ADT/StringExtras.h"
17 #include "llvm/ADT/Twine.h"
23 #include "llvm/IR/DataLayout.h"
24 #include "llvm/IR/Mangler.h"
25 #include "llvm/IR/Module.h"
26 #include "llvm/MC/MCAsmInfo.h"
27 #include "llvm/MC/MCContext.h"
28 #include "llvm/MC/MCExpr.h"
29 #include "llvm/MC/MCSection.h"
30 #include "llvm/MC/MCStreamer.h"
31 #include "llvm/MC/MCSymbol.h"
32 #include "llvm/MC/MCWin64EH.h"
33 #include "llvm/Support/Dwarf.h"
40 using namespace llvm;
41 
43  // MSVC's EH tables are always composed of 32-bit words. All known 64-bit
44  // platforms use an imagerel32 relocation to refer to symbols.
45  useImageRel32 = (A->getDataLayout().getPointerSizeInBits() == 64);
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 = !MMI->getLandingPads().empty();
65 
66  const Function *F = MF->getFunction();
67  const Function *ParentF = MMI->getWinEHParent(F);
68 
69  shouldEmitMoves = Asm->needsSEHMoves();
70 
72  unsigned PerEncoding = TLOF.getPersonalityEncoding();
73  const Function *Per = nullptr;
74  if (F->hasPersonalityFn())
75  Per = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
76 
77  bool forceEmitPersonality =
80 
81  shouldEmitPersonality = forceEmitPersonality || (hasLandingPads &&
82  PerEncoding != dwarf::DW_EH_PE_omit && Per);
83 
84  unsigned LSDAEncoding = TLOF.getLSDAEncoding();
85  shouldEmitLSDA = shouldEmitPersonality &&
86  LSDAEncoding != dwarf::DW_EH_PE_omit;
87 
88  // If we're not using CFI, we don't want the CFI or the personality. If
89  // WinEHPrepare outlined something, we should emit the LSDA.
90  if (!Asm->MAI->usesWindowsCFI()) {
91  bool HasOutlinedChildren =
92  F->hasFnAttribute("wineh-parent") && F == ParentF;
93  shouldEmitLSDA = HasOutlinedChildren;
94  shouldEmitPersonality = false;
95  return;
96  }
97 
98  // If this was an outlined handler, we need to define the label corresponding
99  // to the offset of the parent frame relative to the stack pointer after the
100  // prologue.
101  if (F != ParentF) {
102  WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(ParentF);
103  auto I = FuncInfo.CatchHandlerParentFrameObjOffset.find(F);
104  if (I != FuncInfo.CatchHandlerParentFrameObjOffset.end()) {
105  MCSymbol *HandlerTypeParentFrameOffset =
108 
109  // Emit a symbol assignment.
110  Asm->OutStreamer->EmitAssignment(
111  HandlerTypeParentFrameOffset,
113  }
114  }
115 
116  if (shouldEmitMoves || shouldEmitPersonality)
117  Asm->OutStreamer->EmitWinCFIStartProc(Asm->CurrentFnSym);
118 
119  if (shouldEmitPersonality) {
120  const MCSymbol *PersHandlerSym =
121  TLOF.getCFIPersonalitySymbol(Per, *Asm->Mang, Asm->TM, MMI);
122  Asm->OutStreamer->EmitWinEHHandler(PersHandlerSym, true, true);
123  }
124 }
125 
126 /// endFunction - Gather and emit post-function exception information.
127 ///
129  if (!shouldEmitPersonality && !shouldEmitMoves && !shouldEmitLSDA)
130  return;
131 
132  const Function *F = MF->getFunction();
134  if (F->hasPersonalityFn())
136 
137  // Get rid of any dead landing pads if we're not using a Windows EH scheme. In
138  // Windows EH schemes, the landing pad is not actually reachable. It only
139  // exists so that we can emit the right table data.
140  if (!isMSVCEHPersonality(Per))
141  MMI->TidyLandingPads();
142 
143  if (shouldEmitPersonality || shouldEmitLSDA) {
144  Asm->OutStreamer->PushSection();
145 
146  if (shouldEmitMoves || shouldEmitPersonality) {
147  // Emit an UNWIND_INFO struct describing the prologue.
148  Asm->OutStreamer->EmitWinEHHandlerData();
149  } else {
150  // Just switch sections to the right xdata section. This use of
151  // CurrentFnSym assumes that we only emit the LSDA when ending the parent
152  // function.
155  Asm->OutStreamer->SwitchSection(XData);
156  }
157 
158  // Emit the tables appropriate to the personality function in use. If we
159  // don't recognize the personality, assume it uses an Itanium-style LSDA.
160  if (Per == EHPersonality::MSVC_Win64SEH)
161  emitCSpecificHandlerTable();
162  else if (Per == EHPersonality::MSVC_X86SEH)
163  emitExceptHandlerTable(MF);
164  else if (Per == EHPersonality::MSVC_CXX)
165  emitCXXFrameHandler3Table(MF);
166  else
168 
169  Asm->OutStreamer->PopSection();
170  }
171 
172  if (shouldEmitMoves)
173  Asm->OutStreamer->EmitWinCFIEndProc();
174 }
175 
176 const MCExpr *WinException::create32bitRef(const MCSymbol *Value) {
177  if (!Value)
179  return MCSymbolRefExpr::create(Value, useImageRel32
182  Asm->OutContext);
183 }
184 
185 const MCExpr *WinException::create32bitRef(const GlobalValue *GV) {
186  if (!GV)
188  return create32bitRef(Asm->getSymbol(GV));
189 }
190 
191 /// Emit the language-specific data that __C_specific_handler expects. This
192 /// handler lives in the x64 Microsoft C runtime and allows catching or cleaning
193 /// up after faults with __try, __except, and __finally. The typeinfo values
194 /// are not really RTTI data, but pointers to filter functions that return an
195 /// integer (1, 0, or -1) indicating how to handle the exception. For __finally
196 /// blocks and other cleanups, the landing pad label is zero, and the filter
197 /// function is actually a cleanup handler with the same prototype. A catch-all
198 /// entry is modeled with a null filter function field and a non-zero landing
199 /// pad label.
200 ///
201 /// Possible filter function return values:
202 /// EXCEPTION_EXECUTE_HANDLER (1):
203 /// Jump to the landing pad label after cleanups.
204 /// EXCEPTION_CONTINUE_SEARCH (0):
205 /// Continue searching this table or continue unwinding.
206 /// EXCEPTION_CONTINUE_EXECUTION (-1):
207 /// Resume execution at the trapping PC.
208 ///
209 /// Inferred table structure:
210 /// struct Table {
211 /// int NumEntries;
212 /// struct Entry {
213 /// imagerel32 LabelStart;
214 /// imagerel32 LabelEnd;
215 /// imagerel32 FilterOrFinally; // One means catch-all.
216 /// imagerel32 LabelLPad; // Zero means __finally.
217 /// } Entries[NumEntries];
218 /// };
219 void WinException::emitCSpecificHandlerTable() {
220  const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
221 
222  // Simplifying assumptions for first implementation:
223  // - Cleanups are not implemented.
224  // - Filters are not implemented.
225 
226  // The Itanium LSDA table sorts similar landing pads together to simplify the
227  // actions table, but we don't need that.
229  LandingPads.reserve(PadInfos.size());
230  for (const auto &LP : PadInfos)
231  LandingPads.push_back(&LP);
232 
233  // Compute label ranges for call sites as we would for the Itanium LSDA, but
234  // use an all zero action table because we aren't using these actions.
235  SmallVector<unsigned, 64> FirstActions;
236  FirstActions.resize(LandingPads.size());
238  computeCallSiteTable(CallSites, LandingPads, FirstActions);
239 
240  MCSymbol *EHFuncBeginSym = Asm->getFunctionBegin();
241  MCSymbol *EHFuncEndSym = Asm->getFunctionEnd();
242 
243  // Emit the number of table entries.
244  unsigned NumEntries = 0;
245  for (const CallSiteEntry &CSE : CallSites) {
246  if (!CSE.LPad)
247  continue; // Ignore gaps.
248  NumEntries += CSE.LPad->SEHHandlers.size();
249  }
250  Asm->OutStreamer->EmitIntValue(NumEntries, 4);
251 
252  // If there are no actions, we don't need to iterate again.
253  if (NumEntries == 0)
254  return;
255 
256  // Emit the four-label records for each call site entry. The table has to be
257  // sorted in layout order, and the call sites should already be sorted.
258  for (const CallSiteEntry &CSE : CallSites) {
259  // Ignore gaps. Unlike the Itanium model, unwinding through a frame without
260  // an EH table entry will propagate the exception rather than terminating
261  // the program.
262  if (!CSE.LPad)
263  continue;
264  const LandingPadInfo *LPad = CSE.LPad;
265 
266  // Compute the label range. We may reuse the function begin and end labels
267  // rather than forming new ones.
268  const MCExpr *Begin =
269  create32bitRef(CSE.BeginLabel ? CSE.BeginLabel : EHFuncBeginSym);
270  const MCExpr *End;
271  if (CSE.EndLabel) {
272  // The interval is half-open, so we have to add one to include the return
273  // address of the last invoke in the range.
274  End = MCBinaryExpr::createAdd(create32bitRef(CSE.EndLabel),
276  Asm->OutContext);
277  } else {
278  End = create32bitRef(EHFuncEndSym);
279  }
280 
281  // Emit an entry for each action.
282  for (SEHHandler Handler : LPad->SEHHandlers) {
283  Asm->OutStreamer->EmitValue(Begin, 4);
284  Asm->OutStreamer->EmitValue(End, 4);
285 
286  // Emit the filter or finally function pointer, if present. Otherwise,
287  // emit '1' to indicate a catch-all.
288  const Function *F = Handler.FilterOrFinally;
289  if (F)
290  Asm->OutStreamer->EmitValue(create32bitRef(Asm->getSymbol(F)), 4);
291  else
292  Asm->OutStreamer->EmitIntValue(1, 4);
293 
294  // Emit the recovery address, if present. Otherwise, this must be a
295  // finally.
296  const BlockAddress *BA = Handler.RecoverBA;
297  if (BA)
298  Asm->OutStreamer->EmitValue(
299  create32bitRef(Asm->GetBlockAddressSymbol(BA)), 4);
300  else
301  Asm->OutStreamer->EmitIntValue(0, 4);
302  }
303  }
304 }
305 
306 void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
307  const Function *F = MF->getFunction();
308  const Function *ParentF = MMI->getWinEHParent(F);
309  auto &OS = *Asm->OutStreamer;
310  WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(ParentF);
311 
312  StringRef ParentLinkageName =
314 
315  MCSymbol *FuncInfoXData = nullptr;
316  if (shouldEmitPersonality) {
317  FuncInfoXData = Asm->OutContext.getOrCreateSymbol(
318  Twine("$cppxdata$", ParentLinkageName));
319  OS.EmitValue(create32bitRef(FuncInfoXData), 4);
320 
321  extendIP2StateTable(MF, ParentF, FuncInfo);
322 
323  // Defer emission until we've visited the parent function and all the catch
324  // handlers. Cleanups don't contribute to the ip2state table, so don't count
325  // them.
326  if (ParentF != F && !FuncInfo.CatchHandlerMaxState.count(F))
327  return;
328  ++FuncInfo.NumIPToStateFuncsVisited;
329  if (FuncInfo.NumIPToStateFuncsVisited != FuncInfo.CatchHandlerMaxState.size())
330  return;
331  } else {
332  FuncInfoXData = Asm->OutContext.getOrCreateLSDASymbol(ParentLinkageName);
333  emitEHRegistrationOffsetLabel(FuncInfo, ParentLinkageName);
334  }
335 
336  MCSymbol *UnwindMapXData = nullptr;
337  MCSymbol *TryBlockMapXData = nullptr;
338  MCSymbol *IPToStateXData = nullptr;
339  if (!FuncInfo.UnwindMap.empty())
340  UnwindMapXData = Asm->OutContext.getOrCreateSymbol(
341  Twine("$stateUnwindMap$", ParentLinkageName));
342  if (!FuncInfo.TryBlockMap.empty())
343  TryBlockMapXData = Asm->OutContext.getOrCreateSymbol(
344  Twine("$tryMap$", ParentLinkageName));
345  if (!FuncInfo.IPToStateList.empty())
346  IPToStateXData = Asm->OutContext.getOrCreateSymbol(
347  Twine("$ip2state$", ParentLinkageName));
348 
349  // FuncInfo {
350  // uint32_t MagicNumber
351  // int32_t MaxState;
352  // UnwindMapEntry *UnwindMap;
353  // uint32_t NumTryBlocks;
354  // TryBlockMapEntry *TryBlockMap;
355  // uint32_t IPMapEntries; // always 0 for x86
356  // IPToStateMapEntry *IPToStateMap; // always 0 for x86
357  // uint32_t UnwindHelp; // non-x86 only
358  // ESTypeList *ESTypeList;
359  // int32_t EHFlags;
360  // }
361  // EHFlags & 1 -> Synchronous exceptions only, no async exceptions.
362  // EHFlags & 2 -> ???
363  // EHFlags & 4 -> The function is noexcept(true), unwinding can't continue.
364  OS.EmitValueToAlignment(4);
365  OS.EmitLabel(FuncInfoXData);
366  OS.EmitIntValue(0x19930522, 4); // MagicNumber
367  OS.EmitIntValue(FuncInfo.UnwindMap.size(), 4); // MaxState
368  OS.EmitValue(create32bitRef(UnwindMapXData), 4); // UnwindMap
369  OS.EmitIntValue(FuncInfo.TryBlockMap.size(), 4); // NumTryBlocks
370  OS.EmitValue(create32bitRef(TryBlockMapXData), 4); // TryBlockMap
371  OS.EmitIntValue(FuncInfo.IPToStateList.size(), 4); // IPMapEntries
372  OS.EmitValue(create32bitRef(IPToStateXData), 4); // IPToStateMap
373  if (Asm->MAI->usesWindowsCFI())
374  OS.EmitIntValue(FuncInfo.UnwindHelpFrameOffset, 4); // UnwindHelp
375  OS.EmitIntValue(0, 4); // ESTypeList
376  OS.EmitIntValue(1, 4); // EHFlags
377 
378  // UnwindMapEntry {
379  // int32_t ToState;
380  // void (*Action)();
381  // };
382  if (UnwindMapXData) {
383  OS.EmitLabel(UnwindMapXData);
384  for (const WinEHUnwindMapEntry &UME : FuncInfo.UnwindMap) {
385  OS.EmitIntValue(UME.ToState, 4); // ToState
386  OS.EmitValue(create32bitRef(UME.Cleanup), 4); // Action
387  }
388  }
389 
390  // TryBlockMap {
391  // int32_t TryLow;
392  // int32_t TryHigh;
393  // int32_t CatchHigh;
394  // int32_t NumCatches;
395  // HandlerType *HandlerArray;
396  // };
397  if (TryBlockMapXData) {
398  OS.EmitLabel(TryBlockMapXData);
399  SmallVector<MCSymbol *, 1> HandlerMaps;
400  for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
401  WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
402  MCSymbol *HandlerMapXData = nullptr;
403 
404  if (!TBME.HandlerArray.empty())
405  HandlerMapXData =
406  Asm->OutContext.getOrCreateSymbol(Twine("$handlerMap$")
407  .concat(Twine(I))
408  .concat("$")
409  .concat(ParentLinkageName));
410 
411  HandlerMaps.push_back(HandlerMapXData);
412 
413  int CatchHigh = -1;
414  for (WinEHHandlerType &HT : TBME.HandlerArray)
415  CatchHigh =
416  std::max(CatchHigh, FuncInfo.CatchHandlerMaxState[HT.Handler]);
417 
418  assert(TBME.TryLow <= TBME.TryHigh);
419  OS.EmitIntValue(TBME.TryLow, 4); // TryLow
420  OS.EmitIntValue(TBME.TryHigh, 4); // TryHigh
421  OS.EmitIntValue(CatchHigh, 4); // CatchHigh
422  OS.EmitIntValue(TBME.HandlerArray.size(), 4); // NumCatches
423  OS.EmitValue(create32bitRef(HandlerMapXData), 4); // HandlerArray
424  }
425 
426  for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
427  WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
428  MCSymbol *HandlerMapXData = HandlerMaps[I];
429  if (!HandlerMapXData)
430  continue;
431  // HandlerType {
432  // int32_t Adjectives;
433  // TypeDescriptor *Type;
434  // int32_t CatchObjOffset;
435  // void (*Handler)();
436  // int32_t ParentFrameOffset; // x64 only
437  // };
438  OS.EmitLabel(HandlerMapXData);
439  for (const WinEHHandlerType &HT : TBME.HandlerArray) {
440  // Get the frame escape label with the offset of the catch object. If
441  // the index is -1, then there is no catch object, and we should emit an
442  // offset of zero, indicating that no copy will occur.
443  const MCExpr *FrameAllocOffsetRef = nullptr;
444  if (HT.CatchObjRecoverIdx >= 0) {
445  MCSymbol *FrameAllocOffset =
448  HT.CatchObjRecoverIdx);
449  FrameAllocOffsetRef = MCSymbolRefExpr::create(
450  FrameAllocOffset, MCSymbolRefExpr::VK_None, Asm->OutContext);
451  } else {
452  FrameAllocOffsetRef = MCConstantExpr::create(0, Asm->OutContext);
453  }
454 
455  OS.EmitIntValue(HT.Adjectives, 4); // Adjectives
456  OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4); // Type
457  OS.EmitValue(FrameAllocOffsetRef, 4); // CatchObjOffset
458  OS.EmitValue(create32bitRef(HT.Handler), 4); // Handler
459 
460  if (shouldEmitPersonality) {
461  MCSymbol *ParentFrameOffset =
464  const MCSymbolRefExpr *ParentFrameOffsetRef = MCSymbolRefExpr::create(
465  ParentFrameOffset, Asm->OutContext);
466  OS.EmitValue(ParentFrameOffsetRef, 4); // ParentFrameOffset
467  }
468  }
469  }
470  }
471 
472  // IPToStateMapEntry {
473  // void *IP;
474  // int32_t State;
475  // };
476  if (IPToStateXData) {
477  OS.EmitLabel(IPToStateXData);
478  for (auto &IPStatePair : FuncInfo.IPToStateList) {
479  OS.EmitValue(create32bitRef(IPStatePair.first), 4); // IP
480  OS.EmitIntValue(IPStatePair.second, 4); // State
481  }
482  }
483 }
484 
485 void WinException::extendIP2StateTable(const MachineFunction *MF,
486  const Function *ParentF,
487  WinEHFuncInfo &FuncInfo) {
488  const Function *F = MF->getFunction();
489 
490  // The Itanium LSDA table sorts similar landing pads together to simplify the
491  // actions table, but we don't need that.
493  const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
494  LandingPads.reserve(PadInfos.size());
495  for (const auto &LP : PadInfos)
496  LandingPads.push_back(&LP);
497 
498  RangeMapType PadMap;
499  computePadMap(LandingPads, PadMap);
500 
501  // The end label of the previous invoke or nounwind try-range.
502  MCSymbol *LastLabel = Asm->getFunctionBegin();
503 
504  // Whether there is a potentially throwing instruction (currently this means
505  // an ordinary call) between the end of the previous try-range and now.
506  bool SawPotentiallyThrowing = false;
507 
508  int LastEHState = -2;
509 
510  // The parent function and the catch handlers contribute to the 'ip2state'
511  // table.
512 
513  // Include ip2state entries for the beginning of the main function and
514  // for catch handler functions.
515  if (F == ParentF) {
516  FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1));
517  LastEHState = -1;
518  } else if (FuncInfo.HandlerBaseState.count(F)) {
519  FuncInfo.IPToStateList.push_back(
520  std::make_pair(LastLabel, FuncInfo.HandlerBaseState[F]));
521  LastEHState = FuncInfo.HandlerBaseState[F];
522  }
523  for (const auto &MBB : *MF) {
524  for (const auto &MI : MBB) {
525  if (!MI.isEHLabel()) {
526  if (MI.isCall())
527  SawPotentiallyThrowing |= !callToNoUnwindFunction(&MI);
528  continue;
529  }
530 
531  // End of the previous try-range?
532  MCSymbol *BeginLabel = MI.getOperand(0).getMCSymbol();
533  if (BeginLabel == LastLabel)
534  SawPotentiallyThrowing = false;
535 
536  // Beginning of a new try-range?
537  RangeMapType::const_iterator L = PadMap.find(BeginLabel);
538  if (L == PadMap.end())
539  // Nope, it was just some random label.
540  continue;
541 
542  const PadRange &P = L->second;
543  const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
544  assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
545  "Inconsistent landing pad map!");
546 
547  // FIXME: Should this be using FuncInfo.HandlerBaseState?
548  if (SawPotentiallyThrowing && LastEHState != -1) {
549  FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1));
550  SawPotentiallyThrowing = false;
551  LastEHState = -1;
552  }
553 
554  if (LandingPad->WinEHState != LastEHState)
555  FuncInfo.IPToStateList.push_back(
556  std::make_pair(BeginLabel, LandingPad->WinEHState));
557  LastEHState = LandingPad->WinEHState;
558  LastLabel = LandingPad->EndLabels[P.RangeIndex];
559  }
560  }
561 }
562 
563 void WinException::emitEHRegistrationOffsetLabel(const WinEHFuncInfo &FuncInfo,
564  StringRef FLinkageName) {
565  // Outlined helpers called by the EH runtime need to know the offset of the EH
566  // registration in order to recover the parent frame pointer. Now that we know
567  // we've code generated the parent, we can emit the label assignment that
568  // those helpers use to get the offset of the registration node.
569  assert(FuncInfo.EHRegNodeEscapeIndex != INT_MAX &&
570  "no EH reg node localescape index");
571  MCSymbol *ParentFrameOffset =
573  MCSymbol *RegistrationOffsetSym = Asm->OutContext.getOrCreateFrameAllocSymbol(
574  FLinkageName, FuncInfo.EHRegNodeEscapeIndex);
575  const MCExpr *RegistrationOffsetSymRef =
576  MCSymbolRefExpr::create(RegistrationOffsetSym, Asm->OutContext);
577  Asm->OutStreamer->EmitAssignment(ParentFrameOffset, RegistrationOffsetSymRef);
578 }
579 
580 /// Emit the language-specific data that _except_handler3 and 4 expect. This is
581 /// functionally equivalent to the __C_specific_handler table, except it is
582 /// indexed by state number instead of IP.
583 void WinException::emitExceptHandlerTable(const MachineFunction *MF) {
584  MCStreamer &OS = *Asm->OutStreamer;
585  const Function *F = MF->getFunction();
587 
588  WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(F);
589  emitEHRegistrationOffsetLabel(FuncInfo, FLinkageName);
590 
591  // Emit the __ehtable label that we use for llvm.x86.seh.lsda.
592  MCSymbol *LSDALabel = Asm->OutContext.getOrCreateLSDASymbol(FLinkageName);
593  OS.EmitValueToAlignment(4);
594  OS.EmitLabel(LSDALabel);
595 
596  const Function *Per =
598  StringRef PerName = Per->getName();
599  int BaseState = -1;
600  if (PerName == "_except_handler4") {
601  // The LSDA for _except_handler4 starts with this struct, followed by the
602  // scope table:
603  //
604  // struct EH4ScopeTable {
605  // int32_t GSCookieOffset;
606  // int32_t GSCookieXOROffset;
607  // int32_t EHCookieOffset;
608  // int32_t EHCookieXOROffset;
609  // ScopeTableEntry ScopeRecord[];
610  // };
611  //
612  // Only the EHCookieOffset field appears to vary, and it appears to be the
613  // offset from the final saved SP value to the retaddr.
614  OS.EmitIntValue(-2, 4);
615  OS.EmitIntValue(0, 4);
616  // FIXME: Calculate.
617  OS.EmitIntValue(9999, 4);
618  OS.EmitIntValue(0, 4);
619  BaseState = -2;
620  }
621 
622  // Build a list of pointers to LandingPadInfos and then sort by WinEHState.
623  const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
625  LPads.reserve((PadInfos.size()));
626  for (const LandingPadInfo &LPInfo : PadInfos)
627  LPads.push_back(&LPInfo);
628  std::sort(LPads.begin(), LPads.end(),
629  [](const LandingPadInfo *L, const LandingPadInfo *R) {
630  return L->WinEHState < R->WinEHState;
631  });
632 
633  // For each action in each lpad, emit one of these:
634  // struct ScopeTableEntry {
635  // int32_t EnclosingLevel;
636  // int32_t (__cdecl *Filter)();
637  // void *HandlerOrFinally;
638  // };
639  //
640  // The "outermost" action will use BaseState as its enclosing level. Each
641  // other action will refer to the previous state as its enclosing level.
642  int CurState = 0;
643  for (const LandingPadInfo *LPInfo : LPads) {
644  int EnclosingLevel = BaseState;
645  assert(CurState + int(LPInfo->SEHHandlers.size()) - 1 ==
646  LPInfo->WinEHState &&
647  "gaps in the SEH scope table");
648  for (auto I = LPInfo->SEHHandlers.rbegin(), E = LPInfo->SEHHandlers.rend();
649  I != E; ++I) {
650  const SEHHandler &Handler = *I;
651  const BlockAddress *BA = Handler.RecoverBA;
652  const Function *F = Handler.FilterOrFinally;
653  assert(F && "cannot catch all in 32-bit SEH without filter function");
654  const MCExpr *FilterOrNull =
655  create32bitRef(BA ? Asm->getSymbol(F) : nullptr);
656  const MCExpr *ExceptOrFinally = create32bitRef(
657  BA ? Asm->GetBlockAddressSymbol(BA) : Asm->getSymbol(F));
658 
659  OS.EmitIntValue(EnclosingLevel, 4);
660  OS.EmitValue(FilterOrNull, 4);
661  OS.EmitValue(ExceptOrFinally, 4);
662 
663  // The next state unwinds to this state.
664  EnclosingLevel = CurState;
665  CurState++;
666  }
667  }
668 }
Instances of this class represent a uniqued identifier for a section in the current translation unit...
Definition: MCSection.h:48
SmallVector< WinEHHandlerType, 1 > HandlerArray
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition: AsmPrinter.h:83
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:315
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:339
DenseMap< MCSymbol *, PadRange > RangeMapType
Definition: EHStreamer.h:53
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:39
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:114
WinEHFuncInfo & getWinEHFuncInfo(const Function *F)
const DataLayout & getDataLayout() const
Return information about data layout.
Definition: AsmPrinter.cpp:139
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition: AsmPrinter.h:78
const Function * FilterOrFinally
MCSymbol * getOrCreateFrameAllocSymbol(StringRef FuncName, unsigned Idx)
Gets a symbol that will be defined to the final stack offset of a local variable after codegen...
Definition: MCContext.cpp:146
bool callToNoUnwindFunction(const MachineInstr *MI)
Return `true' if this is a call to a function marked `nounwind'.
Definition: EHStreamer.cpp:159
MCSymbol * getOrCreateParentFrameOffsetSymbol(StringRef FuncName)
Definition: MCContext.cpp:152
F(f)
const Function * getFunction() const
getFunction - Return the LLVM function that this machine code represents
void reserve(size_type N)
Definition: SmallVector.h:401
StringRef getName() const
Return a constant reference to the value's name.
Definition: Value.cpp:188
MachineModuleInfo * MMI
Collected machine module information.
Definition: EHStreamer.h:39
BlockAddress - The address of a basic block.
Definition: Constants.h:802
void endModule() override
Emit all exception information that should come after the content.
Emits exception handling directives.
Definition: EHStreamer.h:33
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:79
SmallVector< MCSymbol *, 1 > EndLabels
SmallVector< SEHHandler, 1 > SEHHandlers
separate const offset from Split GEPs to a variadic base and a constant offset for better CSE
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:33
const Module * getModule() const
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:159
int EHRegNodeEscapeIndex
localescape index of the 32-bit EH registration node.
void emitExceptionTable()
Emit landing pads and actions.
Definition: EHStreamer.cpp:338
LandingPadInfo - This structure is used to retain landing pad info for the current function...
Mangler * Mang
Name-mangler for global names.
Definition: AsmPrinter.h:93
void computeCallSiteTable(SmallVectorImpl< CallSiteEntry > &CallSites, const SmallVectorImpl< const LandingPadInfo * > &LPs, const SmallVectorImpl< unsigned > &FirstActions)
Compute the call-site table.
Definition: EHStreamer.cpp:215
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:446
virtual void EmitIntValue(uint64_t Value, unsigned Size)
Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers...
Definition: MCStreamer.cpp:79
#define P(N)
Streaming machine code generation interface.
Definition: MCStreamer.h:157
Constant * stripPointerCasts()
Definition: Constant.h:170
MCSymbol * CurrentFnSym
The symbol for the current function.
Definition: AsmPrinter.h:98
const MCAsmInfo * MAI
Target Asm Printer information.
Definition: AsmPrinter.h:74
SmallVector< MCSymbol *, 1 > BeginLabels
WinException(AsmPrinter *A)
TargetMachine & TM
Target machine description.
Definition: AsmPrinter.h:70
bool hasPersonalityFn() const
Get the personality function associated with this function.
Definition: Function.h:132
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:66
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.
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.
Definition: MCStreamer.cpp:688
DenseMap< const Function *, int > CatchHandlerParentFrameObjOffset
AsmPrinter * Asm
Target of directive emission.
Definition: EHStreamer.h:36
void beginFunction(const MachineFunction *MF) override
Gather pre-function exception information.
DenseMap< const Function *, int > CatchHandlerMaxState
virtual void EmitLabel(MCSymbol *Symbol)
Emit a label for Symbol into the current section.
Definition: MCStreamer.cpp:203
unsigned getLSDAEncoding() const
MCSymbol * getOrCreateLSDASymbol(StringRef FuncName)
Definition: MCContext.cpp:157
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:861
Module.h This file contains the declarations for the Module class.
bool needsUnwindTableEntry() const
True if this function needs an unwind table.
Definition: Function.h:354
unsigned getPersonalityEncoding() const
SmallVector< WinEHTryBlockMapEntry, 4 > TryBlockMap
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:285
GlobalVariable * TypeDescriptor
~WinException() override
const Function * getWinEHParent(const Function *F) const
static StringRef getRealLinkageName(StringRef Name)
If special LLVM prefix that is used to inform the asm printer to not emit usual symbol prefix before ...
Definition: GlobalValue.h:306
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition: Function.h:217
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:111
Constant * getPersonalityFn() const
Definition: Function.h:133
const std::vector< LandingPadInfo > & getLandingPads() const
getLandingPads - Return a reference to the landing pad info for the current function.
MCSymbol * getFunctionBegin() const
Definition: AsmPrinter.h:158
void computePadMap(const SmallVectorImpl< const LandingPadInfo * > &LandingPads, RangeMapType &PadMap)
Definition: EHStreamer.cpp:191
#define I(x, y, z)
Definition: MD5.cpp:54
MCSymbol * GetBlockAddressSymbol(const BlockAddress *BA) const
Return the MCSymbol used to satisfy BlockAddress uses of the specified basic block.
unsigned getPointerSizeInBits(unsigned AS=0) const
Layout pointer size, in bits FIXME: The defaults need to be removed once all of the backends/clients ...
Definition: DataLayout.h:329
MCSymbol * getFunctionEnd() const
Definition: AsmPrinter.h:159
unsigned NumIPToStateFuncsVisited
static MCSection * getXDataSection(const MCSymbol *Function, MCContext &Context)
Definition: MCWinEH.cpp:70
void EmitValue(const MCExpr *Value, unsigned Size, const SMLoc &Loc=SMLoc())
Definition: MCStreamer.cpp:110
void TidyLandingPads(DenseMap< MCSymbol *, uintptr_t > *LPMap=nullptr)
TidyLandingPads - Remap landing pad labels and remove any deleted landing pads.
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
Definition: AsmPrinter.cpp:134
SmallVector< std::pair< MCSymbol *, int >, 4 > IPToStateList
LLVM Value Representation.
Definition: Value.h:69
virtual MCSymbol * getCFIPersonalitySymbol(const GlobalValue *GV, Mangler &Mang, const TargetMachine &TM, MachineModuleInfo *MMI) const
const BlockAddress * RecoverBA
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
DenseMap< const Function *, int > HandlerBaseState
bool isNoOpWithoutInvoke(EHPersonality Pers)
Return true if this personality may be safely removed if there are no invoke instructions remaining i...
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx)
Definition: MCExpr.cpp:150
bool isMSVCEHPersonality(EHPersonality Pers)
Returns true if this is an MSVC personality function.
SmallVector< WinEHUnwindMapEntry, 4 > UnwindMap
bool usesWindowsCFI() const
Definition: MCAsmInfo.h:521
void resize(size_type N)
Definition: SmallVector.h:376