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