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