4151101e22bcc1fcb258bd78e29fbdc9524c5d2f
[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 = nullptr;
74   if (F->hasPersonalityFn())
75     Per = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
76
77   bool forceEmitPersonality =
78     F->hasPersonalityFn() && !isNoOpWithoutInvoke(classifyEHPersonality(Per)) &&
79     F->needsUnwindTableEntry();
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 =
106           Asm->OutContext.getOrCreateParentFrameOffsetSymbol(
107               GlobalValue::getRealLinkageName(F->getName()));
108
109       // Emit a symbol assignment.
110       Asm->OutStreamer->EmitAssignment(
111           HandlerTypeParentFrameOffset,
112           MCConstantExpr::create(I->second, Asm->OutContext));
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 ///
128 void WinException::endFunction(const MachineFunction *MF) {
129   if (!shouldEmitPersonality && !shouldEmitMoves && !shouldEmitLSDA)
130     return;
131
132   const Function *F = MF->getFunction();
133   EHPersonality Per = EHPersonality::Unknown;
134   if (F->hasPersonalityFn())
135     Per = classifyEHPersonality(F->getPersonalityFn());
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.
153       MCSection *XData = WinEH::UnwindEmitter::getXDataSection(
154           Asm->CurrentFnSym, Asm->OutContext);
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
167       emitExceptionTable();
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)
178     return MCConstantExpr::create(0, Asm->OutContext);
179   return MCSymbolRefExpr::create(Value, useImageRel32
180                                             ? MCSymbolRefExpr::VK_COFF_IMGREL32
181                                             : MCSymbolRefExpr::VK_None,
182                                  Asm->OutContext);
183 }
184
185 const MCExpr *WinException::create32bitRef(const Value *V) {
186   if (!V)
187     return MCConstantExpr::create(0, Asm->OutContext);
188   return create32bitRef(Asm->getSymbol(cast<GlobalValue>(V)));
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.
228   SmallVector<const LandingPadInfo *, 64> LandingPads;
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());
237   SmallVector<CallSiteEntry, 64> CallSites;
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),
275                                     MCConstantExpr::create(1, Asm->OutContext),
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 =
313       GlobalValue::getRealLinkageName(ParentF->getName());
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,
417                      FuncInfo.CatchHandlerMaxState[cast<Function>(HT.Handler)]);
418
419       assert(TBME.TryLow <= TBME.TryHigh);
420       OS.EmitIntValue(TBME.TryLow, 4);                    // TryLow
421       OS.EmitIntValue(TBME.TryHigh, 4);                   // TryHigh
422       OS.EmitIntValue(CatchHigh, 4);                      // CatchHigh
423       OS.EmitIntValue(TBME.HandlerArray.size(), 4);       // NumCatches
424       OS.EmitValue(create32bitRef(HandlerMapXData), 4);   // HandlerArray
425     }
426
427     for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
428       WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
429       MCSymbol *HandlerMapXData = HandlerMaps[I];
430       if (!HandlerMapXData)
431         continue;
432       // HandlerType {
433       //   int32_t         Adjectives;
434       //   TypeDescriptor *Type;
435       //   int32_t         CatchObjOffset;
436       //   void          (*Handler)();
437       //   int32_t         ParentFrameOffset; // x64 only
438       // };
439       OS.EmitLabel(HandlerMapXData);
440       for (const WinEHHandlerType &HT : TBME.HandlerArray) {
441         // Get the frame escape label with the offset of the catch object. If
442         // the index is -1, then there is no catch object, and we should emit an
443         // offset of zero, indicating that no copy will occur.
444         const MCExpr *FrameAllocOffsetRef = nullptr;
445         if (HT.CatchObjRecoverIdx >= 0) {
446           MCSymbol *FrameAllocOffset =
447               Asm->OutContext.getOrCreateFrameAllocSymbol(
448                   GlobalValue::getRealLinkageName(ParentF->getName()),
449                   HT.CatchObjRecoverIdx);
450           FrameAllocOffsetRef = MCSymbolRefExpr::create(
451               FrameAllocOffset, MCSymbolRefExpr::VK_None, Asm->OutContext);
452         } else {
453           FrameAllocOffsetRef = MCConstantExpr::create(0, Asm->OutContext);
454         }
455
456         OS.EmitIntValue(HT.Adjectives, 4);                    // Adjectives
457         OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4);   // Type
458         OS.EmitValue(FrameAllocOffsetRef, 4);                 // CatchObjOffset
459         OS.EmitValue(create32bitRef(HT.Handler), 4);          // Handler
460
461         if (shouldEmitPersonality) {
462           MCSymbol *ParentFrameOffset =
463               Asm->OutContext.getOrCreateParentFrameOffsetSymbol(
464                   GlobalValue::getRealLinkageName(HT.Handler->getName()));
465           const MCSymbolRefExpr *ParentFrameOffsetRef = MCSymbolRefExpr::create(
466               ParentFrameOffset, Asm->OutContext);
467           OS.EmitValue(ParentFrameOffsetRef, 4); // ParentFrameOffset
468         }
469       }
470     }
471   }
472
473   // IPToStateMapEntry {
474   //   void   *IP;
475   //   int32_t State;
476   // };
477   if (IPToStateXData) {
478     OS.EmitLabel(IPToStateXData);
479     for (auto &IPStatePair : FuncInfo.IPToStateList) {
480       OS.EmitValue(create32bitRef(IPStatePair.first), 4);   // IP
481       OS.EmitIntValue(IPStatePair.second, 4);               // State
482     }
483   }
484 }
485
486 void WinException::extendIP2StateTable(const MachineFunction *MF,
487                                        const Function *ParentF,
488                                        WinEHFuncInfo &FuncInfo) {
489   const Function *F = MF->getFunction();
490
491   // The Itanium LSDA table sorts similar landing pads together to simplify the
492   // actions table, but we don't need that.
493   SmallVector<const LandingPadInfo *, 64> LandingPads;
494   const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
495   LandingPads.reserve(PadInfos.size());
496   for (const auto &LP : PadInfos)
497     LandingPads.push_back(&LP);
498
499   RangeMapType PadMap;
500   computePadMap(LandingPads, PadMap);
501
502   // The end label of the previous invoke or nounwind try-range.
503   MCSymbol *LastLabel = Asm->getFunctionBegin();
504
505   // Whether there is a potentially throwing instruction (currently this means
506   // an ordinary call) between the end of the previous try-range and now.
507   bool SawPotentiallyThrowing = false;
508
509   int LastEHState = -2;
510
511   // The parent function and the catch handlers contribute to the 'ip2state'
512   // table.
513
514   // Include ip2state entries for the beginning of the main function and
515   // for catch handler functions.
516   if (F == ParentF) {
517     FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1));
518     LastEHState = -1;
519   } else if (FuncInfo.HandlerBaseState.count(F)) {
520     FuncInfo.IPToStateList.push_back(
521         std::make_pair(LastLabel, FuncInfo.HandlerBaseState[F]));
522     LastEHState = FuncInfo.HandlerBaseState[F];
523   }
524   for (const auto &MBB : *MF) {
525     for (const auto &MI : MBB) {
526       if (!MI.isEHLabel()) {
527         if (MI.isCall())
528           SawPotentiallyThrowing |= !callToNoUnwindFunction(&MI);
529         continue;
530       }
531
532       // End of the previous try-range?
533       MCSymbol *BeginLabel = MI.getOperand(0).getMCSymbol();
534       if (BeginLabel == LastLabel)
535         SawPotentiallyThrowing = false;
536
537       // Beginning of a new try-range?
538       RangeMapType::const_iterator L = PadMap.find(BeginLabel);
539       if (L == PadMap.end())
540         // Nope, it was just some random label.
541         continue;
542
543       const PadRange &P = L->second;
544       const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
545       assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
546              "Inconsistent landing pad map!");
547
548       // FIXME: Should this be using FuncInfo.HandlerBaseState?
549       if (SawPotentiallyThrowing && LastEHState != -1) {
550         FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1));
551         SawPotentiallyThrowing = false;
552         LastEHState = -1;
553       }
554
555       if (LandingPad->WinEHState != LastEHState)
556         FuncInfo.IPToStateList.push_back(
557             std::make_pair(BeginLabel, LandingPad->WinEHState));
558       LastEHState = LandingPad->WinEHState;
559       LastLabel = LandingPad->EndLabels[P.RangeIndex];
560     }
561   }
562 }
563
564 void WinException::emitEHRegistrationOffsetLabel(const WinEHFuncInfo &FuncInfo,
565                                                  StringRef FLinkageName) {
566   // Outlined helpers called by the EH runtime need to know the offset of the EH
567   // registration in order to recover the parent frame pointer. Now that we know
568   // we've code generated the parent, we can emit the label assignment that
569   // those helpers use to get the offset of the registration node.
570   assert(FuncInfo.EHRegNodeEscapeIndex != INT_MAX &&
571          "no EH reg node localescape index");
572   MCSymbol *ParentFrameOffset =
573       Asm->OutContext.getOrCreateParentFrameOffsetSymbol(FLinkageName);
574   MCSymbol *RegistrationOffsetSym = Asm->OutContext.getOrCreateFrameAllocSymbol(
575       FLinkageName, FuncInfo.EHRegNodeEscapeIndex);
576   const MCExpr *RegistrationOffsetSymRef =
577       MCSymbolRefExpr::create(RegistrationOffsetSym, Asm->OutContext);
578   Asm->OutStreamer->EmitAssignment(ParentFrameOffset, RegistrationOffsetSymRef);
579 }
580
581 /// Emit the language-specific data that _except_handler3 and 4 expect. This is
582 /// functionally equivalent to the __C_specific_handler table, except it is
583 /// indexed by state number instead of IP.
584 void WinException::emitExceptHandlerTable(const MachineFunction *MF) {
585   MCStreamer &OS = *Asm->OutStreamer;
586   const Function *F = MF->getFunction();
587   StringRef FLinkageName = GlobalValue::getRealLinkageName(F->getName());
588
589   WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(F);
590   emitEHRegistrationOffsetLabel(FuncInfo, FLinkageName);
591
592   // Emit the __ehtable label that we use for llvm.x86.seh.lsda.
593   MCSymbol *LSDALabel = Asm->OutContext.getOrCreateLSDASymbol(FLinkageName);
594   OS.EmitValueToAlignment(4);
595   OS.EmitLabel(LSDALabel);
596
597   const Function *Per =
598       dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
599   StringRef PerName = Per->getName();
600   int BaseState = -1;
601   if (PerName == "_except_handler4") {
602     // The LSDA for _except_handler4 starts with this struct, followed by the
603     // scope table:
604     //
605     // struct EH4ScopeTable {
606     //   int32_t GSCookieOffset;
607     //   int32_t GSCookieXOROffset;
608     //   int32_t EHCookieOffset;
609     //   int32_t EHCookieXOROffset;
610     //   ScopeTableEntry ScopeRecord[];
611     // };
612     //
613     // Only the EHCookieOffset field appears to vary, and it appears to be the
614     // offset from the final saved SP value to the retaddr.
615     OS.EmitIntValue(-2, 4);
616     OS.EmitIntValue(0, 4);
617     // FIXME: Calculate.
618     OS.EmitIntValue(9999, 4);
619     OS.EmitIntValue(0, 4);
620     BaseState = -2;
621   }
622
623   // Build a list of pointers to LandingPadInfos and then sort by WinEHState.
624   const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
625   SmallVector<const LandingPadInfo *, 4> LPads;
626   LPads.reserve((PadInfos.size()));
627   for (const LandingPadInfo &LPInfo : PadInfos)
628     LPads.push_back(&LPInfo);
629   std::sort(LPads.begin(), LPads.end(),
630             [](const LandingPadInfo *L, const LandingPadInfo *R) {
631               return L->WinEHState < R->WinEHState;
632             });
633
634   // For each action in each lpad, emit one of these:
635   // struct ScopeTableEntry {
636   //   int32_t EnclosingLevel;
637   //   int32_t (__cdecl *Filter)();
638   //   void *HandlerOrFinally;
639   // };
640   //
641   // The "outermost" action will use BaseState as its enclosing level. Each
642   // other action will refer to the previous state as its enclosing level.
643   int CurState = 0;
644   for (const LandingPadInfo *LPInfo : LPads) {
645     int EnclosingLevel = BaseState;
646     assert(CurState + int(LPInfo->SEHHandlers.size()) - 1 ==
647                LPInfo->WinEHState &&
648            "gaps in the SEH scope table");
649     for (auto I = LPInfo->SEHHandlers.rbegin(), E = LPInfo->SEHHandlers.rend();
650          I != E; ++I) {
651       const SEHHandler &Handler = *I;
652       const BlockAddress *BA = Handler.RecoverBA;
653       const Function *F = Handler.FilterOrFinally;
654       assert(F && "cannot catch all in 32-bit SEH without filter function");
655       const MCExpr *FilterOrNull =
656           create32bitRef(BA ? Asm->getSymbol(F) : nullptr);
657       const MCExpr *ExceptOrFinally = create32bitRef(
658           BA ? Asm->GetBlockAddressSymbol(BA) : Asm->getSymbol(F));
659
660       OS.EmitIntValue(EnclosingLevel, 4);
661       OS.EmitValue(FilterOrNull, 4);
662       OS.EmitValue(ExceptOrFinally, 4);
663
664       // The next state unwinds to this state.
665       EnclosingLevel = CurState;
666       CurState++;
667     }
668   }
669 }