Rename llvm.frameescape and llvm.framerecover to localescape and localrecover
[oota-llvm.git] / lib / CodeGen / AsmPrinter / WinException.cpp
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"
18 #include "llvm/CodeGen/AsmPrinter.h"
19 #include "llvm/CodeGen/MachineFrameInfo.h"
20 #include "llvm/CodeGen/MachineFunction.h"
21 #include "llvm/CodeGen/MachineModuleInfo.h"
22 #include "llvm/CodeGen/WinEHFuncInfo.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"
34 #include "llvm/Support/ErrorHandling.h"
35 #include "llvm/Support/FormattedStream.h"
36 #include "llvm/Target/TargetFrameLowering.h"
37 #include "llvm/Target/TargetLoweringObjectFile.h"
38 #include "llvm/Target/TargetOptions.h"
39 #include "llvm/Target/TargetRegisterInfo.h"
40 using namespace llvm;
41
42 WinException::WinException(AsmPrinter *A) : EHStreamer(A) {
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
48 WinException::~WinException() {}
49
50 /// endModule - Emit all exception information that should come after the
51 /// content.
52 void WinException::endModule() {
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
60 void WinException::beginFunction(const MachineFunction *MF) {
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
71   const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
72   unsigned PerEncoding = TLOF.getPersonalityEncoding();
73   const Function *Per = MMI->getPersonality();
74
75   shouldEmitPersonality = hasLandingPads &&
76     PerEncoding != dwarf::DW_EH_PE_omit && Per;
77
78   unsigned LSDAEncoding = TLOF.getLSDAEncoding();
79   shouldEmitLSDA = shouldEmitPersonality &&
80     LSDAEncoding != dwarf::DW_EH_PE_omit;
81
82   // If we're not using CFI, we don't want the CFI or the personality. Emit the
83   // LSDA if this is the parent function.
84   if (!Asm->MAI->usesWindowsCFI()) {
85     shouldEmitLSDA = (hasLandingPads && F == ParentF);
86     shouldEmitPersonality = false;
87     return;
88   }
89
90   // If this was an outlined handler, we need to define the label corresponding
91   // to the offset of the parent frame relative to the stack pointer after the
92   // prologue.
93   if (F != ParentF) {
94     WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(ParentF);
95     auto I = FuncInfo.CatchHandlerParentFrameObjOffset.find(F);
96     if (I != FuncInfo.CatchHandlerParentFrameObjOffset.end()) {
97       MCSymbol *HandlerTypeParentFrameOffset =
98           Asm->OutContext.getOrCreateParentFrameOffsetSymbol(
99               GlobalValue::getRealLinkageName(F->getName()));
100
101       // Emit a symbol assignment.
102       Asm->OutStreamer->EmitAssignment(
103           HandlerTypeParentFrameOffset,
104           MCConstantExpr::create(I->second, Asm->OutContext));
105     }
106   }
107
108   if (shouldEmitMoves || shouldEmitPersonality)
109     Asm->OutStreamer->EmitWinCFIStartProc(Asm->CurrentFnSym);
110
111   if (shouldEmitPersonality) {
112     const MCSymbol *PersHandlerSym =
113         TLOF.getCFIPersonalitySymbol(Per, *Asm->Mang, Asm->TM, MMI);
114     Asm->OutStreamer->EmitWinEHHandler(PersHandlerSym, true, true);
115   }
116 }
117
118 /// endFunction - Gather and emit post-function exception information.
119 ///
120 void WinException::endFunction(const MachineFunction *MF) {
121   if (!shouldEmitPersonality && !shouldEmitMoves && !shouldEmitLSDA)
122     return;
123
124   EHPersonality Per = MMI->getPersonalityType();
125
126   // Get rid of any dead landing pads if we're not using a Windows EH scheme. In
127   // Windows EH schemes, the landing pad is not actually reachable. It only
128   // exists so that we can emit the right table data.
129   if (!isMSVCEHPersonality(Per))
130     MMI->TidyLandingPads();
131
132   if (shouldEmitPersonality || shouldEmitLSDA) {
133     Asm->OutStreamer->PushSection();
134
135     if (shouldEmitMoves || shouldEmitPersonality) {
136       // Emit an UNWIND_INFO struct describing the prologue.
137       Asm->OutStreamer->EmitWinEHHandlerData();
138     } else {
139       // Just switch sections to the right xdata section. This use of
140       // CurrentFnSym assumes that we only emit the LSDA when ending the parent
141       // function.
142       MCSection *XData = WinEH::UnwindEmitter::getXDataSection(
143           Asm->CurrentFnSym, Asm->OutContext);
144       Asm->OutStreamer->SwitchSection(XData);
145     }
146
147     // Emit the tables appropriate to the personality function in use. If we
148     // don't recognize the personality, assume it uses an Itanium-style LSDA.
149     if (Per == EHPersonality::MSVC_Win64SEH)
150       emitCSpecificHandlerTable();
151     else if (Per == EHPersonality::MSVC_X86SEH)
152       emitExceptHandlerTable(MF);
153     else if (Per == EHPersonality::MSVC_CXX)
154       emitCXXFrameHandler3Table(MF);
155     else
156       emitExceptionTable();
157
158     Asm->OutStreamer->PopSection();
159   }
160
161   if (shouldEmitMoves)
162     Asm->OutStreamer->EmitWinCFIEndProc();
163 }
164
165 const MCExpr *WinException::create32bitRef(const MCSymbol *Value) {
166   if (!Value)
167     return MCConstantExpr::create(0, Asm->OutContext);
168   return MCSymbolRefExpr::create(Value, useImageRel32
169                                             ? MCSymbolRefExpr::VK_COFF_IMGREL32
170                                             : MCSymbolRefExpr::VK_None,
171                                  Asm->OutContext);
172 }
173
174 const MCExpr *WinException::create32bitRef(const GlobalValue *GV) {
175   if (!GV)
176     return MCConstantExpr::create(0, Asm->OutContext);
177   return create32bitRef(Asm->getSymbol(GV));
178 }
179
180 /// Emit the language-specific data that __C_specific_handler expects.  This
181 /// handler lives in the x64 Microsoft C runtime and allows catching or cleaning
182 /// up after faults with __try, __except, and __finally.  The typeinfo values
183 /// are not really RTTI data, but pointers to filter functions that return an
184 /// integer (1, 0, or -1) indicating how to handle the exception. For __finally
185 /// blocks and other cleanups, the landing pad label is zero, and the filter
186 /// function is actually a cleanup handler with the same prototype.  A catch-all
187 /// entry is modeled with a null filter function field and a non-zero landing
188 /// pad label.
189 ///
190 /// Possible filter function return values:
191 ///   EXCEPTION_EXECUTE_HANDLER (1):
192 ///     Jump to the landing pad label after cleanups.
193 ///   EXCEPTION_CONTINUE_SEARCH (0):
194 ///     Continue searching this table or continue unwinding.
195 ///   EXCEPTION_CONTINUE_EXECUTION (-1):
196 ///     Resume execution at the trapping PC.
197 ///
198 /// Inferred table structure:
199 ///   struct Table {
200 ///     int NumEntries;
201 ///     struct Entry {
202 ///       imagerel32 LabelStart;
203 ///       imagerel32 LabelEnd;
204 ///       imagerel32 FilterOrFinally;  // One means catch-all.
205 ///       imagerel32 LabelLPad;        // Zero means __finally.
206 ///     } Entries[NumEntries];
207 ///   };
208 void WinException::emitCSpecificHandlerTable() {
209   const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
210
211   // Simplifying assumptions for first implementation:
212   // - Cleanups are not implemented.
213   // - Filters are not implemented.
214
215   // The Itanium LSDA table sorts similar landing pads together to simplify the
216   // actions table, but we don't need that.
217   SmallVector<const LandingPadInfo *, 64> LandingPads;
218   LandingPads.reserve(PadInfos.size());
219   for (const auto &LP : PadInfos)
220     LandingPads.push_back(&LP);
221
222   // Compute label ranges for call sites as we would for the Itanium LSDA, but
223   // use an all zero action table because we aren't using these actions.
224   SmallVector<unsigned, 64> FirstActions;
225   FirstActions.resize(LandingPads.size());
226   SmallVector<CallSiteEntry, 64> CallSites;
227   computeCallSiteTable(CallSites, LandingPads, FirstActions);
228
229   MCSymbol *EHFuncBeginSym = Asm->getFunctionBegin();
230   MCSymbol *EHFuncEndSym = Asm->getFunctionEnd();
231
232   // Emit the number of table entries.
233   unsigned NumEntries = 0;
234   for (const CallSiteEntry &CSE : CallSites) {
235     if (!CSE.LPad)
236       continue; // Ignore gaps.
237     NumEntries += CSE.LPad->SEHHandlers.size();
238   }
239   Asm->OutStreamer->EmitIntValue(NumEntries, 4);
240
241   // If there are no actions, we don't need to iterate again.
242   if (NumEntries == 0)
243     return;
244
245   // Emit the four-label records for each call site entry. The table has to be
246   // sorted in layout order, and the call sites should already be sorted.
247   for (const CallSiteEntry &CSE : CallSites) {
248     // Ignore gaps. Unlike the Itanium model, unwinding through a frame without
249     // an EH table entry will propagate the exception rather than terminating
250     // the program.
251     if (!CSE.LPad)
252       continue;
253     const LandingPadInfo *LPad = CSE.LPad;
254
255     // Compute the label range. We may reuse the function begin and end labels
256     // rather than forming new ones.
257     const MCExpr *Begin =
258         create32bitRef(CSE.BeginLabel ? CSE.BeginLabel : EHFuncBeginSym);
259     const MCExpr *End;
260     if (CSE.EndLabel) {
261       // The interval is half-open, so we have to add one to include the return
262       // address of the last invoke in the range.
263       End = MCBinaryExpr::createAdd(create32bitRef(CSE.EndLabel),
264                                     MCConstantExpr::create(1, Asm->OutContext),
265                                     Asm->OutContext);
266     } else {
267       End = create32bitRef(EHFuncEndSym);
268     }
269
270     // Emit an entry for each action.
271     for (SEHHandler Handler : LPad->SEHHandlers) {
272       Asm->OutStreamer->EmitValue(Begin, 4);
273       Asm->OutStreamer->EmitValue(End, 4);
274
275       // Emit the filter or finally function pointer, if present. Otherwise,
276       // emit '1' to indicate a catch-all.
277       const Function *F = Handler.FilterOrFinally;
278       if (F)
279         Asm->OutStreamer->EmitValue(create32bitRef(Asm->getSymbol(F)), 4);
280       else
281         Asm->OutStreamer->EmitIntValue(1, 4);
282
283       // Emit the recovery address, if present. Otherwise, this must be a
284       // finally.
285       const BlockAddress *BA = Handler.RecoverBA;
286       if (BA)
287         Asm->OutStreamer->EmitValue(
288             create32bitRef(Asm->GetBlockAddressSymbol(BA)), 4);
289       else
290         Asm->OutStreamer->EmitIntValue(0, 4);
291     }
292   }
293 }
294
295 void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
296   const Function *F = MF->getFunction();
297   const Function *ParentF = MMI->getWinEHParent(F);
298   auto &OS = *Asm->OutStreamer;
299   WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(ParentF);
300
301   StringRef ParentLinkageName =
302       GlobalValue::getRealLinkageName(ParentF->getName());
303
304   MCSymbol *FuncInfoXData = nullptr;
305   if (shouldEmitPersonality) {
306     FuncInfoXData = Asm->OutContext.getOrCreateSymbol(
307         Twine("$cppxdata$", ParentLinkageName));
308     OS.EmitValue(create32bitRef(FuncInfoXData), 4);
309
310     extendIP2StateTable(MF, ParentF, FuncInfo);
311
312     // Defer emission until we've visited the parent function and all the catch
313     // handlers.  Cleanups don't contribute to the ip2state table, so don't count
314     // them.
315     if (ParentF != F && !FuncInfo.CatchHandlerMaxState.count(F))
316       return;
317     ++FuncInfo.NumIPToStateFuncsVisited;
318     if (FuncInfo.NumIPToStateFuncsVisited != FuncInfo.CatchHandlerMaxState.size())
319       return;
320   } else {
321     FuncInfoXData = Asm->OutContext.getOrCreateLSDASymbol(ParentLinkageName);
322     emitEHRegistrationOffsetLabel(FuncInfo, ParentLinkageName);
323   }
324
325   MCSymbol *UnwindMapXData = nullptr;
326   MCSymbol *TryBlockMapXData = nullptr;
327   MCSymbol *IPToStateXData = nullptr;
328   if (!FuncInfo.UnwindMap.empty())
329     UnwindMapXData = Asm->OutContext.getOrCreateSymbol(
330         Twine("$stateUnwindMap$", ParentLinkageName));
331   if (!FuncInfo.TryBlockMap.empty())
332     TryBlockMapXData = Asm->OutContext.getOrCreateSymbol(
333         Twine("$tryMap$", ParentLinkageName));
334   if (!FuncInfo.IPToStateList.empty())
335     IPToStateXData = Asm->OutContext.getOrCreateSymbol(
336         Twine("$ip2state$", ParentLinkageName));
337
338   // FuncInfo {
339   //   uint32_t           MagicNumber
340   //   int32_t            MaxState;
341   //   UnwindMapEntry    *UnwindMap;
342   //   uint32_t           NumTryBlocks;
343   //   TryBlockMapEntry  *TryBlockMap;
344   //   uint32_t           IPMapEntries; // always 0 for x86
345   //   IPToStateMapEntry *IPToStateMap; // always 0 for x86
346   //   uint32_t           UnwindHelp;   // non-x86 only
347   //   ESTypeList        *ESTypeList;
348   //   int32_t            EHFlags;
349   // }
350   // EHFlags & 1 -> Synchronous exceptions only, no async exceptions.
351   // EHFlags & 2 -> ???
352   // EHFlags & 4 -> The function is noexcept(true), unwinding can't continue.
353   OS.EmitLabel(FuncInfoXData);
354   OS.EmitIntValue(0x19930522, 4);                      // MagicNumber
355   OS.EmitIntValue(FuncInfo.UnwindMap.size(), 4);       // MaxState
356   OS.EmitValue(create32bitRef(UnwindMapXData), 4);     // UnwindMap
357   OS.EmitIntValue(FuncInfo.TryBlockMap.size(), 4);     // NumTryBlocks
358   OS.EmitValue(create32bitRef(TryBlockMapXData), 4);   // TryBlockMap
359   OS.EmitIntValue(FuncInfo.IPToStateList.size(), 4);   // IPMapEntries
360   OS.EmitValue(create32bitRef(IPToStateXData), 4);     // IPToStateMap
361   if (Asm->MAI->usesWindowsCFI())
362     OS.EmitIntValue(FuncInfo.UnwindHelpFrameOffset, 4); // UnwindHelp
363   OS.EmitIntValue(0, 4);                               // ESTypeList
364   OS.EmitIntValue(1, 4);                               // EHFlags
365
366   // UnwindMapEntry {
367   //   int32_t ToState;
368   //   void  (*Action)();
369   // };
370   if (UnwindMapXData) {
371     OS.EmitLabel(UnwindMapXData);
372     for (const WinEHUnwindMapEntry &UME : FuncInfo.UnwindMap) {
373       OS.EmitIntValue(UME.ToState, 4);                // ToState
374       OS.EmitValue(create32bitRef(UME.Cleanup), 4);   // Action
375     }
376   }
377
378   // TryBlockMap {
379   //   int32_t      TryLow;
380   //   int32_t      TryHigh;
381   //   int32_t      CatchHigh;
382   //   int32_t      NumCatches;
383   //   HandlerType *HandlerArray;
384   // };
385   if (TryBlockMapXData) {
386     OS.EmitLabel(TryBlockMapXData);
387     SmallVector<MCSymbol *, 1> HandlerMaps;
388     for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
389       WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
390       MCSymbol *HandlerMapXData = nullptr;
391
392       if (!TBME.HandlerArray.empty())
393         HandlerMapXData =
394             Asm->OutContext.getOrCreateSymbol(Twine("$handlerMap$")
395                                                   .concat(Twine(I))
396                                                   .concat("$")
397                                                   .concat(ParentLinkageName));
398
399       HandlerMaps.push_back(HandlerMapXData);
400
401       int CatchHigh = -1;
402       for (WinEHHandlerType &HT : TBME.HandlerArray)
403         CatchHigh =
404             std::max(CatchHigh, FuncInfo.CatchHandlerMaxState[HT.Handler]);
405
406       assert(TBME.TryLow <= TBME.TryHigh);
407       OS.EmitIntValue(TBME.TryLow, 4);                    // TryLow
408       OS.EmitIntValue(TBME.TryHigh, 4);                   // TryHigh
409       OS.EmitIntValue(CatchHigh, 4);                      // CatchHigh
410       OS.EmitIntValue(TBME.HandlerArray.size(), 4);       // NumCatches
411       OS.EmitValue(create32bitRef(HandlerMapXData), 4);   // HandlerArray
412     }
413
414     for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
415       WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
416       MCSymbol *HandlerMapXData = HandlerMaps[I];
417       if (!HandlerMapXData)
418         continue;
419       // HandlerType {
420       //   int32_t         Adjectives;
421       //   TypeDescriptor *Type;
422       //   int32_t         CatchObjOffset;
423       //   void          (*Handler)();
424       //   int32_t         ParentFrameOffset; // x64 only
425       // };
426       OS.EmitLabel(HandlerMapXData);
427       for (const WinEHHandlerType &HT : TBME.HandlerArray) {
428         // Get the frame escape label with the offset of the catch object. If
429         // the index is -1, then there is no catch object, and we should emit an
430         // offset of zero, indicating that no copy will occur.
431         const MCExpr *FrameAllocOffsetRef = nullptr;
432         if (HT.CatchObjRecoverIdx >= 0) {
433           MCSymbol *FrameAllocOffset =
434               Asm->OutContext.getOrCreateFrameAllocSymbol(
435                   GlobalValue::getRealLinkageName(ParentF->getName()),
436                   HT.CatchObjRecoverIdx);
437           FrameAllocOffsetRef = MCSymbolRefExpr::create(
438               FrameAllocOffset, MCSymbolRefExpr::VK_None, Asm->OutContext);
439         } else {
440           FrameAllocOffsetRef = MCConstantExpr::create(0, Asm->OutContext);
441         }
442
443         OS.EmitIntValue(HT.Adjectives, 4);                    // Adjectives
444         OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4);   // Type
445         OS.EmitValue(FrameAllocOffsetRef, 4);                 // CatchObjOffset
446         OS.EmitValue(create32bitRef(HT.Handler), 4);          // Handler
447
448         if (shouldEmitPersonality) {
449           MCSymbol *ParentFrameOffset =
450               Asm->OutContext.getOrCreateParentFrameOffsetSymbol(
451                   GlobalValue::getRealLinkageName(HT.Handler->getName()));
452           const MCSymbolRefExpr *ParentFrameOffsetRef = MCSymbolRefExpr::create(
453               ParentFrameOffset, Asm->OutContext);
454           OS.EmitValue(ParentFrameOffsetRef, 4); // ParentFrameOffset
455         }
456       }
457     }
458   }
459
460   // IPToStateMapEntry {
461   //   void   *IP;
462   //   int32_t State;
463   // };
464   if (IPToStateXData) {
465     OS.EmitLabel(IPToStateXData);
466     for (auto &IPStatePair : FuncInfo.IPToStateList) {
467       OS.EmitValue(create32bitRef(IPStatePair.first), 4);   // IP
468       OS.EmitIntValue(IPStatePair.second, 4);               // State
469     }
470   }
471 }
472
473 void WinException::extendIP2StateTable(const MachineFunction *MF,
474                                        const Function *ParentF,
475                                        WinEHFuncInfo &FuncInfo) {
476   const Function *F = MF->getFunction();
477
478   // The Itanium LSDA table sorts similar landing pads together to simplify the
479   // actions table, but we don't need that.
480   SmallVector<const LandingPadInfo *, 64> LandingPads;
481   const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
482   LandingPads.reserve(PadInfos.size());
483   for (const auto &LP : PadInfos)
484     LandingPads.push_back(&LP);
485
486   RangeMapType PadMap;
487   computePadMap(LandingPads, PadMap);
488
489   // The end label of the previous invoke or nounwind try-range.
490   MCSymbol *LastLabel = Asm->getFunctionBegin();
491
492   // Whether there is a potentially throwing instruction (currently this means
493   // an ordinary call) between the end of the previous try-range and now.
494   bool SawPotentiallyThrowing = false;
495
496   int LastEHState = -2;
497
498   // The parent function and the catch handlers contribute to the 'ip2state'
499   // table.
500
501   // Include ip2state entries for the beginning of the main function and
502   // for catch handler functions.
503   if (F == ParentF) {
504     FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1));
505     LastEHState = -1;
506   } else if (FuncInfo.HandlerBaseState.count(F)) {
507     FuncInfo.IPToStateList.push_back(
508         std::make_pair(LastLabel, FuncInfo.HandlerBaseState[F]));
509     LastEHState = FuncInfo.HandlerBaseState[F];
510   }
511   for (const auto &MBB : *MF) {
512     for (const auto &MI : MBB) {
513       if (!MI.isEHLabel()) {
514         if (MI.isCall())
515           SawPotentiallyThrowing |= !callToNoUnwindFunction(&MI);
516         continue;
517       }
518
519       // End of the previous try-range?
520       MCSymbol *BeginLabel = MI.getOperand(0).getMCSymbol();
521       if (BeginLabel == LastLabel)
522         SawPotentiallyThrowing = false;
523
524       // Beginning of a new try-range?
525       RangeMapType::const_iterator L = PadMap.find(BeginLabel);
526       if (L == PadMap.end())
527         // Nope, it was just some random label.
528         continue;
529
530       const PadRange &P = L->second;
531       const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
532       assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
533              "Inconsistent landing pad map!");
534
535       // FIXME: Should this be using FuncInfo.HandlerBaseState?
536       if (SawPotentiallyThrowing && LastEHState != -1) {
537         FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1));
538         SawPotentiallyThrowing = false;
539         LastEHState = -1;
540       }
541
542       if (LandingPad->WinEHState != LastEHState)
543         FuncInfo.IPToStateList.push_back(
544             std::make_pair(BeginLabel, LandingPad->WinEHState));
545       LastEHState = LandingPad->WinEHState;
546       LastLabel = LandingPad->EndLabels[P.RangeIndex];
547     }
548   }
549 }
550
551 void WinException::emitEHRegistrationOffsetLabel(const WinEHFuncInfo &FuncInfo,
552                                                  StringRef FLinkageName) {
553   // Outlined helpers called by the EH runtime need to know the offset of the EH
554   // registration in order to recover the parent frame pointer. Now that we know
555   // we've code generated the parent, we can emit the label assignment that
556   // those helpers use to get the offset of the registration node.
557   assert(FuncInfo.EHRegNodeEscapeIndex != INT_MAX &&
558          "no EH reg node localescape index");
559   MCSymbol *ParentFrameOffset =
560       Asm->OutContext.getOrCreateParentFrameOffsetSymbol(FLinkageName);
561   MCSymbol *RegistrationOffsetSym = Asm->OutContext.getOrCreateFrameAllocSymbol(
562       FLinkageName, FuncInfo.EHRegNodeEscapeIndex);
563   const MCExpr *RegistrationOffsetSymRef =
564       MCSymbolRefExpr::create(RegistrationOffsetSym, Asm->OutContext);
565   Asm->OutStreamer->EmitAssignment(ParentFrameOffset, RegistrationOffsetSymRef);
566 }
567
568 /// Emit the language-specific data that _except_handler3 and 4 expect. This is
569 /// functionally equivalent to the __C_specific_handler table, except it is
570 /// indexed by state number instead of IP.
571 void WinException::emitExceptHandlerTable(const MachineFunction *MF) {
572   MCStreamer &OS = *Asm->OutStreamer;
573   const Function *F = MF->getFunction();
574   StringRef FLinkageName = GlobalValue::getRealLinkageName(F->getName());
575
576   WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(F);
577   emitEHRegistrationOffsetLabel(FuncInfo, FLinkageName);
578
579   // Emit the __ehtable label that we use for llvm.x86.seh.lsda.
580   MCSymbol *LSDALabel = Asm->OutContext.getOrCreateLSDASymbol(FLinkageName);
581   OS.EmitLabel(LSDALabel);
582
583   const Function *Per = MMI->getPersonality();
584   StringRef PerName = Per->getName();
585   int BaseState = -1;
586   if (PerName == "_except_handler4") {
587     // The LSDA for _except_handler4 starts with this struct, followed by the
588     // scope table:
589     //
590     // struct EH4ScopeTable {
591     //   int32_t GSCookieOffset;
592     //   int32_t GSCookieXOROffset;
593     //   int32_t EHCookieOffset;
594     //   int32_t EHCookieXOROffset;
595     //   ScopeTableEntry ScopeRecord[];
596     // };
597     //
598     // Only the EHCookieOffset field appears to vary, and it appears to be the
599     // offset from the final saved SP value to the retaddr.
600     OS.EmitIntValue(-2, 4);
601     OS.EmitIntValue(0, 4);
602     // FIXME: Calculate.
603     OS.EmitIntValue(9999, 4);
604     OS.EmitIntValue(0, 4);
605     BaseState = -2;
606   }
607
608   // Build a list of pointers to LandingPadInfos and then sort by WinEHState.
609   const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
610   SmallVector<const LandingPadInfo *, 4> LPads;
611   LPads.reserve((PadInfos.size()));
612   for (const LandingPadInfo &LPInfo : PadInfos)
613     LPads.push_back(&LPInfo);
614   std::sort(LPads.begin(), LPads.end(),
615             [](const LandingPadInfo *L, const LandingPadInfo *R) {
616               return L->WinEHState < R->WinEHState;
617             });
618
619   // For each action in each lpad, emit one of these:
620   // struct ScopeTableEntry {
621   //   int32_t EnclosingLevel;
622   //   int32_t (__cdecl *Filter)();
623   //   void *HandlerOrFinally;
624   // };
625   //
626   // The "outermost" action will use BaseState as its enclosing level. Each
627   // other action will refer to the previous state as its enclosing level.
628   int CurState = 0;
629   for (const LandingPadInfo *LPInfo : LPads) {
630     int EnclosingLevel = BaseState;
631     assert(CurState + int(LPInfo->SEHHandlers.size()) - 1 ==
632                LPInfo->WinEHState &&
633            "gaps in the SEH scope table");
634     for (auto I = LPInfo->SEHHandlers.rbegin(), E = LPInfo->SEHHandlers.rend();
635          I != E; ++I) {
636       const SEHHandler &Handler = *I;
637       const BlockAddress *BA = Handler.RecoverBA;
638       const Function *F = Handler.FilterOrFinally;
639       assert(F && "cannot catch all in 32-bit SEH without filter function");
640       const MCExpr *FilterOrNull =
641           create32bitRef(BA ? Asm->getSymbol(F) : nullptr);
642       const MCExpr *ExceptOrFinally = create32bitRef(
643           BA ? Asm->GetBlockAddressSymbol(BA) : Asm->getSymbol(F));
644
645       OS.EmitIntValue(EnclosingLevel, 4);
646       OS.EmitValue(FilterOrNull, 4);
647       OS.EmitValue(ExceptOrFinally, 4);
648
649       // The next state unwinds to this state.
650       EnclosingLevel = CurState;
651       CurState++;
652     }
653   }
654 }