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