e706d73dee2ac32c7fe8b12c92724c6e474a1aa6
[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(MF);
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(const MachineFunction *MF) {
226   const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
227
228   WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(MF->getFunction());
229   if (!FuncInfo.SEHUnwindMap.empty())
230     report_fatal_error("x64 SEH tables not yet implemented");
231
232   // Simplifying assumptions for first implementation:
233   // - Cleanups are not implemented.
234   // - Filters are not implemented.
235
236   // The Itanium LSDA table sorts similar landing pads together to simplify the
237   // actions table, but we don't need that.
238   SmallVector<const LandingPadInfo *, 64> LandingPads;
239   LandingPads.reserve(PadInfos.size());
240   for (const auto &LP : PadInfos)
241     LandingPads.push_back(&LP);
242
243   // Compute label ranges for call sites as we would for the Itanium LSDA, but
244   // use an all zero action table because we aren't using these actions.
245   SmallVector<unsigned, 64> FirstActions;
246   FirstActions.resize(LandingPads.size());
247   SmallVector<CallSiteEntry, 64> CallSites;
248   computeCallSiteTable(CallSites, LandingPads, FirstActions);
249
250   MCSymbol *EHFuncBeginSym = Asm->getFunctionBegin();
251   MCSymbol *EHFuncEndSym = Asm->getFunctionEnd();
252
253   // Emit the number of table entries.
254   unsigned NumEntries = 0;
255   for (const CallSiteEntry &CSE : CallSites) {
256     if (!CSE.LPad)
257       continue; // Ignore gaps.
258     NumEntries += CSE.LPad->SEHHandlers.size();
259   }
260   Asm->OutStreamer->EmitIntValue(NumEntries, 4);
261
262   // If there are no actions, we don't need to iterate again.
263   if (NumEntries == 0)
264     return;
265
266   // Emit the four-label records for each call site entry. The table has to be
267   // sorted in layout order, and the call sites should already be sorted.
268   for (const CallSiteEntry &CSE : CallSites) {
269     // Ignore gaps. Unlike the Itanium model, unwinding through a frame without
270     // an EH table entry will propagate the exception rather than terminating
271     // the program.
272     if (!CSE.LPad)
273       continue;
274     const LandingPadInfo *LPad = CSE.LPad;
275
276     // Compute the label range. We may reuse the function begin and end labels
277     // rather than forming new ones.
278     const MCExpr *Begin =
279         create32bitRef(CSE.BeginLabel ? CSE.BeginLabel : EHFuncBeginSym);
280     const MCExpr *End;
281     if (CSE.EndLabel) {
282       // The interval is half-open, so we have to add one to include the return
283       // address of the last invoke in the range.
284       End = MCBinaryExpr::createAdd(create32bitRef(CSE.EndLabel),
285                                     MCConstantExpr::create(1, Asm->OutContext),
286                                     Asm->OutContext);
287     } else {
288       End = create32bitRef(EHFuncEndSym);
289     }
290
291     // Emit an entry for each action.
292     for (SEHHandler Handler : LPad->SEHHandlers) {
293       Asm->OutStreamer->EmitValue(Begin, 4);
294       Asm->OutStreamer->EmitValue(End, 4);
295
296       // Emit the filter or finally function pointer, if present. Otherwise,
297       // emit '1' to indicate a catch-all.
298       const Function *F = Handler.FilterOrFinally;
299       if (F)
300         Asm->OutStreamer->EmitValue(create32bitRef(Asm->getSymbol(F)), 4);
301       else
302         Asm->OutStreamer->EmitIntValue(1, 4);
303
304       // Emit the recovery address, if present. Otherwise, this must be a
305       // finally.
306       const BlockAddress *BA = Handler.RecoverBA;
307       if (BA)
308         Asm->OutStreamer->EmitValue(
309             create32bitRef(Asm->GetBlockAddressSymbol(BA)), 4);
310       else
311         Asm->OutStreamer->EmitIntValue(0, 4);
312     }
313   }
314 }
315
316 /// Retreive the MCSymbol for a GlobalValue or MachineBasicBlock. GlobalValues
317 /// are used in the old WinEH scheme, and they will be removed eventually.
318 static MCSymbol *getMCSymbolForMBBOrGV(AsmPrinter *Asm, ValueOrMBB Handler) {
319   if (Handler.is<MachineBasicBlock *>())
320     return Handler.get<MachineBasicBlock *>()->getSymbol();
321   else
322     return Asm->getSymbol(cast<GlobalValue>(Handler.get<const Value *>()));
323 }
324
325 void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
326   const Function *F = MF->getFunction();
327   const Function *ParentF = MMI->getWinEHParent(F);
328   auto &OS = *Asm->OutStreamer;
329   WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(ParentF);
330
331   StringRef ParentLinkageName =
332       GlobalValue::getRealLinkageName(ParentF->getName());
333
334   MCSymbol *FuncInfoXData = nullptr;
335   if (shouldEmitPersonality) {
336     FuncInfoXData = Asm->OutContext.getOrCreateSymbol(
337         Twine("$cppxdata$", ParentLinkageName));
338     OS.EmitValue(create32bitRef(FuncInfoXData), 4);
339
340     extendIP2StateTable(MF, ParentF, FuncInfo);
341
342     if (!MMI->hasEHFunclets()) {
343       // Defer emission until we've visited the parent function and all the
344       // catch handlers.  Cleanups don't contribute to the ip2state table, so
345       // don't count them.
346       if (ParentF != F && !FuncInfo.CatchHandlerMaxState.count(F))
347         return;
348       ++FuncInfo.NumIPToStateFuncsVisited;
349       if (FuncInfo.NumIPToStateFuncsVisited !=
350           FuncInfo.CatchHandlerMaxState.size())
351         return;
352     }
353   } else {
354     FuncInfoXData = Asm->OutContext.getOrCreateLSDASymbol(ParentLinkageName);
355     emitEHRegistrationOffsetLabel(FuncInfo, ParentLinkageName);
356   }
357
358   MCSymbol *UnwindMapXData = nullptr;
359   MCSymbol *TryBlockMapXData = nullptr;
360   MCSymbol *IPToStateXData = nullptr;
361   if (!FuncInfo.UnwindMap.empty())
362     UnwindMapXData = Asm->OutContext.getOrCreateSymbol(
363         Twine("$stateUnwindMap$", ParentLinkageName));
364   if (!FuncInfo.TryBlockMap.empty())
365     TryBlockMapXData = Asm->OutContext.getOrCreateSymbol(
366         Twine("$tryMap$", ParentLinkageName));
367   if (!FuncInfo.IPToStateList.empty())
368     IPToStateXData = Asm->OutContext.getOrCreateSymbol(
369         Twine("$ip2state$", ParentLinkageName));
370
371   // FuncInfo {
372   //   uint32_t           MagicNumber
373   //   int32_t            MaxState;
374   //   UnwindMapEntry    *UnwindMap;
375   //   uint32_t           NumTryBlocks;
376   //   TryBlockMapEntry  *TryBlockMap;
377   //   uint32_t           IPMapEntries; // always 0 for x86
378   //   IPToStateMapEntry *IPToStateMap; // always 0 for x86
379   //   uint32_t           UnwindHelp;   // non-x86 only
380   //   ESTypeList        *ESTypeList;
381   //   int32_t            EHFlags;
382   // }
383   // EHFlags & 1 -> Synchronous exceptions only, no async exceptions.
384   // EHFlags & 2 -> ???
385   // EHFlags & 4 -> The function is noexcept(true), unwinding can't continue.
386   OS.EmitValueToAlignment(4);
387   OS.EmitLabel(FuncInfoXData);
388   OS.EmitIntValue(0x19930522, 4);                      // MagicNumber
389   OS.EmitIntValue(FuncInfo.UnwindMap.size(), 4);       // MaxState
390   OS.EmitValue(create32bitRef(UnwindMapXData), 4);     // UnwindMap
391   OS.EmitIntValue(FuncInfo.TryBlockMap.size(), 4);     // NumTryBlocks
392   OS.EmitValue(create32bitRef(TryBlockMapXData), 4);   // TryBlockMap
393   OS.EmitIntValue(FuncInfo.IPToStateList.size(), 4);   // IPMapEntries
394   OS.EmitValue(create32bitRef(IPToStateXData), 4);     // IPToStateMap
395   if (Asm->MAI->usesWindowsCFI())
396     OS.EmitIntValue(FuncInfo.UnwindHelpFrameOffset, 4); // UnwindHelp
397   OS.EmitIntValue(0, 4);                               // ESTypeList
398   OS.EmitIntValue(1, 4);                               // EHFlags
399
400   // UnwindMapEntry {
401   //   int32_t ToState;
402   //   void  (*Action)();
403   // };
404   if (UnwindMapXData) {
405     OS.EmitLabel(UnwindMapXData);
406     for (const WinEHUnwindMapEntry &UME : FuncInfo.UnwindMap) {
407       OS.EmitIntValue(UME.ToState, 4);                // ToState
408       OS.EmitValue(create32bitRef(UME.Cleanup), 4);   // Action
409     }
410   }
411
412   // TryBlockMap {
413   //   int32_t      TryLow;
414   //   int32_t      TryHigh;
415   //   int32_t      CatchHigh;
416   //   int32_t      NumCatches;
417   //   HandlerType *HandlerArray;
418   // };
419   if (TryBlockMapXData) {
420     OS.EmitLabel(TryBlockMapXData);
421     SmallVector<MCSymbol *, 1> HandlerMaps;
422     for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
423       WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
424       MCSymbol *HandlerMapXData = nullptr;
425
426       if (!TBME.HandlerArray.empty())
427         HandlerMapXData =
428             Asm->OutContext.getOrCreateSymbol(Twine("$handlerMap$")
429                                                   .concat(Twine(I))
430                                                   .concat("$")
431                                                   .concat(ParentLinkageName));
432
433       HandlerMaps.push_back(HandlerMapXData);
434
435       int CatchHigh = TBME.CatchHigh;
436       if (CatchHigh == -1) {
437         for (WinEHHandlerType &HT : TBME.HandlerArray)
438           CatchHigh =
439               std::max(CatchHigh, FuncInfo.CatchHandlerMaxState[cast<Function>(
440                                       HT.Handler.get<const Value *>())]);
441       }
442
443       assert(TBME.TryLow <= TBME.TryHigh);
444       OS.EmitIntValue(TBME.TryLow, 4);                    // TryLow
445       OS.EmitIntValue(TBME.TryHigh, 4);                   // TryHigh
446       OS.EmitIntValue(CatchHigh, 4);                      // CatchHigh
447       OS.EmitIntValue(TBME.HandlerArray.size(), 4);       // NumCatches
448       OS.EmitValue(create32bitRef(HandlerMapXData), 4);   // HandlerArray
449     }
450
451     for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); I != E; ++I) {
452       WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
453       MCSymbol *HandlerMapXData = HandlerMaps[I];
454       if (!HandlerMapXData)
455         continue;
456       // HandlerType {
457       //   int32_t         Adjectives;
458       //   TypeDescriptor *Type;
459       //   int32_t         CatchObjOffset;
460       //   void          (*Handler)();
461       //   int32_t         ParentFrameOffset; // x64 only
462       // };
463       OS.EmitLabel(HandlerMapXData);
464       for (const WinEHHandlerType &HT : TBME.HandlerArray) {
465         // Get the frame escape label with the offset of the catch object. If
466         // the index is -1, then there is no catch object, and we should emit an
467         // offset of zero, indicating that no copy will occur.
468         const MCExpr *FrameAllocOffsetRef = nullptr;
469         if (HT.CatchObjRecoverIdx >= 0) {
470           MCSymbol *FrameAllocOffset =
471               Asm->OutContext.getOrCreateFrameAllocSymbol(
472                   GlobalValue::getRealLinkageName(ParentF->getName()),
473                   HT.CatchObjRecoverIdx);
474           FrameAllocOffsetRef = MCSymbolRefExpr::create(
475               FrameAllocOffset, MCSymbolRefExpr::VK_None, Asm->OutContext);
476         } else {
477           FrameAllocOffsetRef = MCConstantExpr::create(0, Asm->OutContext);
478         }
479
480         MCSymbol *HandlerSym = getMCSymbolForMBBOrGV(Asm, HT.Handler);
481
482         OS.EmitIntValue(HT.Adjectives, 4);                  // Adjectives
483         OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4); // Type
484         OS.EmitValue(FrameAllocOffsetRef, 4);               // CatchObjOffset
485         OS.EmitValue(create32bitRef(HandlerSym), 4);        // Handler
486
487         if (shouldEmitPersonality) {
488           if (FuncInfo.CatchHandlerParentFrameObjOffset.empty()) {
489             // With the new IR, this is always 16 + 8 + getMaxCallFrameSize().
490             // Keep this in sync with X86FrameLowering::emitPrologue.
491             int ParentFrameOffset =
492                 16 + 8 + MF->getFrameInfo()->getMaxCallFrameSize();
493             OS.EmitIntValue(ParentFrameOffset, 4); // ParentFrameOffset
494           } else {
495             MCSymbol *ParentFrameOffset =
496                 Asm->OutContext.getOrCreateParentFrameOffsetSymbol(
497                     GlobalValue::getRealLinkageName(
498                         HT.Handler.get<const Value *>()->getName()));
499             const MCSymbolRefExpr *ParentFrameOffsetRef =
500                 MCSymbolRefExpr::create(ParentFrameOffset, Asm->OutContext);
501             OS.EmitValue(ParentFrameOffsetRef, 4); // ParentFrameOffset
502           }
503         }
504       }
505     }
506   }
507
508   // IPToStateMapEntry {
509   //   void   *IP;
510   //   int32_t State;
511   // };
512   if (IPToStateXData) {
513     OS.EmitLabel(IPToStateXData);
514     for (auto &IPStatePair : FuncInfo.IPToStateList) {
515       OS.EmitValue(create32bitRef(IPStatePair.first), 4);   // IP
516       OS.EmitIntValue(IPStatePair.second, 4);               // State
517     }
518   }
519 }
520
521 void WinException::extendIP2StateTable(const MachineFunction *MF,
522                                        const Function *ParentF,
523                                        WinEHFuncInfo &FuncInfo) {
524   const Function *F = MF->getFunction();
525
526   // The Itanium LSDA table sorts similar landing pads together to simplify the
527   // actions table, but we don't need that.
528   SmallVector<const LandingPadInfo *, 64> LandingPads;
529   const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
530   LandingPads.reserve(PadInfos.size());
531   for (const auto &LP : PadInfos)
532     LandingPads.push_back(&LP);
533
534   RangeMapType PadMap;
535   computePadMap(LandingPads, PadMap);
536
537   // The end label of the previous invoke or nounwind try-range.
538   MCSymbol *LastLabel = Asm->getFunctionBegin();
539
540   // Whether there is a potentially throwing instruction (currently this means
541   // an ordinary call) between the end of the previous try-range and now.
542   bool SawPotentiallyThrowing = false;
543
544   int LastEHState = -2;
545
546   // The parent function and the catch handlers contribute to the 'ip2state'
547   // table.
548
549   // Include ip2state entries for the beginning of the main function and
550   // for catch handler functions.
551   if (F == ParentF) {
552     FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1));
553     LastEHState = -1;
554   } else if (FuncInfo.HandlerBaseState.count(F)) {
555     FuncInfo.IPToStateList.push_back(
556         std::make_pair(LastLabel, FuncInfo.HandlerBaseState[F]));
557     LastEHState = FuncInfo.HandlerBaseState[F];
558   }
559   for (const auto &MBB : *MF) {
560     for (const auto &MI : MBB) {
561       if (!MI.isEHLabel()) {
562         if (MI.isCall())
563           SawPotentiallyThrowing |= !callToNoUnwindFunction(&MI);
564         continue;
565       }
566
567       // End of the previous try-range?
568       MCSymbol *BeginLabel = MI.getOperand(0).getMCSymbol();
569       if (BeginLabel == LastLabel)
570         SawPotentiallyThrowing = false;
571
572       // Beginning of a new try-range?
573       RangeMapType::const_iterator L = PadMap.find(BeginLabel);
574       if (L == PadMap.end())
575         // Nope, it was just some random label.
576         continue;
577
578       const PadRange &P = L->second;
579       const LandingPadInfo *LandingPad = LandingPads[P.PadIndex];
580       assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
581              "Inconsistent landing pad map!");
582
583       // FIXME: Should this be using FuncInfo.HandlerBaseState?
584       if (SawPotentiallyThrowing && LastEHState != -1) {
585         FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1));
586         SawPotentiallyThrowing = false;
587         LastEHState = -1;
588       }
589
590       if (LandingPad->WinEHState != LastEHState)
591         FuncInfo.IPToStateList.push_back(
592             std::make_pair(BeginLabel, LandingPad->WinEHState));
593       LastEHState = LandingPad->WinEHState;
594       LastLabel = LandingPad->EndLabels[P.RangeIndex];
595     }
596   }
597 }
598
599 void WinException::emitEHRegistrationOffsetLabel(const WinEHFuncInfo &FuncInfo,
600                                                  StringRef FLinkageName) {
601   // Outlined helpers called by the EH runtime need to know the offset of the EH
602   // registration in order to recover the parent frame pointer. Now that we know
603   // we've code generated the parent, we can emit the label assignment that
604   // those helpers use to get the offset of the registration node.
605   assert(FuncInfo.EHRegNodeEscapeIndex != INT_MAX &&
606          "no EH reg node localescape index");
607   MCSymbol *ParentFrameOffset =
608       Asm->OutContext.getOrCreateParentFrameOffsetSymbol(FLinkageName);
609   MCSymbol *RegistrationOffsetSym = Asm->OutContext.getOrCreateFrameAllocSymbol(
610       FLinkageName, FuncInfo.EHRegNodeEscapeIndex);
611   const MCExpr *RegistrationOffsetSymRef =
612       MCSymbolRefExpr::create(RegistrationOffsetSym, Asm->OutContext);
613   Asm->OutStreamer->EmitAssignment(ParentFrameOffset, RegistrationOffsetSymRef);
614 }
615
616 /// Emit the language-specific data that _except_handler3 and 4 expect. This is
617 /// functionally equivalent to the __C_specific_handler table, except it is
618 /// indexed by state number instead of IP.
619 void WinException::emitExceptHandlerTable(const MachineFunction *MF) {
620   MCStreamer &OS = *Asm->OutStreamer;
621   const Function *F = MF->getFunction();
622   StringRef FLinkageName = GlobalValue::getRealLinkageName(F->getName());
623
624   WinEHFuncInfo &FuncInfo = MMI->getWinEHFuncInfo(F);
625   emitEHRegistrationOffsetLabel(FuncInfo, FLinkageName);
626
627   // Emit the __ehtable label that we use for llvm.x86.seh.lsda.
628   MCSymbol *LSDALabel = Asm->OutContext.getOrCreateLSDASymbol(FLinkageName);
629   OS.EmitValueToAlignment(4);
630   OS.EmitLabel(LSDALabel);
631
632   const Function *Per =
633       dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
634   StringRef PerName = Per->getName();
635   int BaseState = -1;
636   if (PerName == "_except_handler4") {
637     // The LSDA for _except_handler4 starts with this struct, followed by the
638     // scope table:
639     //
640     // struct EH4ScopeTable {
641     //   int32_t GSCookieOffset;
642     //   int32_t GSCookieXOROffset;
643     //   int32_t EHCookieOffset;
644     //   int32_t EHCookieXOROffset;
645     //   ScopeTableEntry ScopeRecord[];
646     // };
647     //
648     // Only the EHCookieOffset field appears to vary, and it appears to be the
649     // offset from the final saved SP value to the retaddr.
650     OS.EmitIntValue(-2, 4);
651     OS.EmitIntValue(0, 4);
652     // FIXME: Calculate.
653     OS.EmitIntValue(9999, 4);
654     OS.EmitIntValue(0, 4);
655     BaseState = -2;
656   }
657
658   if (!FuncInfo.SEHUnwindMap.empty()) {
659     for (SEHUnwindMapEntry &UME : FuncInfo.SEHUnwindMap) {
660       MCSymbol *ExceptOrFinally =
661           UME.Handler.get<MachineBasicBlock *>()->getSymbol();
662       OS.EmitIntValue(UME.ToState, 4);                  // ToState
663       OS.EmitValue(create32bitRef(UME.Filter), 4);      // Filter
664       OS.EmitValue(create32bitRef(ExceptOrFinally), 4); // Except/Finally
665     }
666     return;
667   }
668   // FIXME: The following code is for the old landingpad-based SEH
669   // implementation. Remove it when possible.
670
671   // Build a list of pointers to LandingPadInfos and then sort by WinEHState.
672   const std::vector<LandingPadInfo> &PadInfos = MMI->getLandingPads();
673   SmallVector<const LandingPadInfo *, 4> LPads;
674   LPads.reserve((PadInfos.size()));
675   for (const LandingPadInfo &LPInfo : PadInfos)
676     LPads.push_back(&LPInfo);
677   std::sort(LPads.begin(), LPads.end(),
678             [](const LandingPadInfo *L, const LandingPadInfo *R) {
679               return L->WinEHState < R->WinEHState;
680             });
681
682   // For each action in each lpad, emit one of these:
683   // struct ScopeTableEntry {
684   //   int32_t EnclosingLevel;
685   //   int32_t (__cdecl *Filter)();
686   //   void *HandlerOrFinally;
687   // };
688   //
689   // The "outermost" action will use BaseState as its enclosing level. Each
690   // other action will refer to the previous state as its enclosing level.
691   int CurState = 0;
692   for (const LandingPadInfo *LPInfo : LPads) {
693     int EnclosingLevel = BaseState;
694     assert(CurState + int(LPInfo->SEHHandlers.size()) - 1 ==
695                LPInfo->WinEHState &&
696            "gaps in the SEH scope table");
697     for (auto I = LPInfo->SEHHandlers.rbegin(), E = LPInfo->SEHHandlers.rend();
698          I != E; ++I) {
699       const SEHHandler &Handler = *I;
700       const BlockAddress *BA = Handler.RecoverBA;
701       const Function *F = Handler.FilterOrFinally;
702       assert(F && "cannot catch all in 32-bit SEH without filter function");
703       const MCExpr *FilterOrNull =
704           create32bitRef(BA ? Asm->getSymbol(F) : nullptr);
705       const MCExpr *ExceptOrFinally = create32bitRef(
706           BA ? Asm->GetBlockAddressSymbol(BA) : Asm->getSymbol(F));
707
708       OS.EmitIntValue(EnclosingLevel, 4);
709       OS.EmitValue(FilterOrNull, 4);
710       OS.EmitValue(ExceptOrFinally, 4);
711
712       // The next state unwinds to this state.
713       EnclosingLevel = CurState;
714       CurState++;
715     }
716   }
717 }