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