Coverage Report

Created: 2017-10-03 07:32

/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/CodeGen/AsmPrinter/WinException.cpp
Line
Count
Source (jump to first uncovered line)
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/StringExtras.h"
16
#include "llvm/ADT/Twine.h"
17
#include "llvm/BinaryFormat/COFF.h"
18
#include "llvm/BinaryFormat/Dwarf.h"
19
#include "llvm/CodeGen/AsmPrinter.h"
20
#include "llvm/CodeGen/MachineFrameInfo.h"
21
#include "llvm/CodeGen/MachineFunction.h"
22
#include "llvm/CodeGen/MachineModuleInfo.h"
23
#include "llvm/CodeGen/WinEHFuncInfo.h"
24
#include "llvm/IR/DataLayout.h"
25
#include "llvm/IR/Mangler.h"
26
#include "llvm/IR/Module.h"
27
#include "llvm/MC/MCAsmInfo.h"
28
#include "llvm/MC/MCContext.h"
29
#include "llvm/MC/MCExpr.h"
30
#include "llvm/MC/MCSection.h"
31
#include "llvm/MC/MCStreamer.h"
32
#include "llvm/MC/MCSymbol.h"
33
#include "llvm/MC/MCWin64EH.h"
34
#include "llvm/Support/ErrorHandling.h"
35
#include "llvm/Support/FormattedStream.h"
36
#include "llvm/Target/TargetFrameLowering.h"
37
#include "llvm/Target/TargetLowering.h"
38
#include "llvm/Target/TargetLoweringObjectFile.h"
39
#include "llvm/Target/TargetOptions.h"
40
#include "llvm/Target/TargetRegisterInfo.h"
41
#include "llvm/Target/TargetSubtargetInfo.h"
42
using namespace llvm;
43
44
480
WinException::WinException(AsmPrinter *A) : EHStreamer(A) {
45
480
  // MSVC's EH tables are always composed of 32-bit words.  All known 64-bit
46
480
  // platforms use an imagerel32 relocation to refer to symbols.
47
480
  useImageRel32 = (A->getDataLayout().getPointerSizeInBits() == 64);
48
480
}
49
50
476
WinException::~WinException() {}
51
52
/// endModule - Emit all exception information that should come after the
53
/// content.
54
476
void WinException::endModule() {
55
476
  auto &OS = *Asm->OutStreamer;
56
476
  const Module *M = MMI->getModule();
57
476
  for (const Function &F : *M)
58
3.21k
    
if (3.21k
F.hasFnAttribute("safeseh")3.21k
)
59
27
      OS.EmitCOFFSafeSEH(Asm->getSymbol(&F));
60
476
}
61
62
1.81k
void WinException::beginFunction(const MachineFunction *MF) {
63
1.81k
  shouldEmitMoves = shouldEmitPersonality = shouldEmitLSDA = false;
64
1.81k
65
1.81k
  // If any landing pads survive, we need an EH table.
66
1.81k
  bool hasLandingPads = !MF->getLandingPads().empty();
67
1.81k
  bool hasEHFunclets = MF->hasEHFunclets();
68
1.81k
69
1.81k
  const Function *F = MF->getFunction();
70
1.81k
71
499
  shouldEmitMoves = Asm->needsSEHMoves() && MF->hasWinCFI();
72
1.81k
73
1.81k
  const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
74
1.81k
  unsigned PerEncoding = TLOF.getPersonalityEncoding();
75
1.81k
76
1.81k
  EHPersonality Per = EHPersonality::Unknown;
77
1.81k
  const Function *PerFn = nullptr;
78
1.81k
  if (
F->hasPersonalityFn()1.81k
) {
79
110
    PerFn = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
80
110
    Per = classifyEHPersonality(PerFn);
81
110
  }
82
1.81k
83
1.81k
  bool forceEmitPersonality = F->hasPersonalityFn() &&
84
110
                              !isNoOpWithoutInvoke(Per) &&
85
8
                              F->needsUnwindTableEntry();
86
1.81k
87
1.81k
  shouldEmitPersonality =
88
1.80k
      forceEmitPersonality || 
((hasLandingPads || 1.80k
hasEHFunclets1.79k
) &&
89
1.80k
                               
PerEncoding != dwarf::DW_EH_PE_omit97
&&
PerFn97
);
90
1.81k
91
1.81k
  unsigned LSDAEncoding = TLOF.getLSDAEncoding();
92
1.81k
  shouldEmitLSDA = shouldEmitPersonality &&
93
105
    LSDAEncoding != dwarf::DW_EH_PE_omit;
94
1.81k
95
1.81k
  // If we're not using CFI, we don't want the CFI or the personality, but we
96
1.81k
  // might want EH tables if we had EH pads.
97
1.81k
  if (
!Asm->MAI->usesWindowsCFI()1.81k
) {
98
708
    if (
Per == EHPersonality::MSVC_X86SEH && 708
!hasEHFunclets13
) {
99
1
      // If this is 32-bit SEH and we don't have any funclets (really invokes),
100
1
      // make sure we emit the parent offset label. Some unreferenced filter
101
1
      // functions may still refer to it.
102
1
      const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
103
1
      StringRef FLinkageName =
104
1
          GlobalValue::dropLLVMManglingEscape(MF->getFunction()->getName());
105
1
      emitEHRegistrationOffsetLabel(FuncInfo, FLinkageName);
106
1
    }
107
708
    shouldEmitLSDA = hasEHFunclets;
108
708
    shouldEmitPersonality = false;
109
708
    return;
110
708
  }
111
1.10k
112
1.10k
  beginFunclet(MF->front(), Asm->CurrentFnSym);
113
1.10k
}
114
115
/// endFunction - Gather and emit post-function exception information.
116
///
117
1.81k
void WinException::endFunction(const MachineFunction *MF) {
118
1.81k
  if (
!shouldEmitPersonality && 1.81k
!shouldEmitMoves1.75k
&&
!shouldEmitLSDA1.52k
)
119
1.48k
    return;
120
330
121
330
  const Function *F = MF->getFunction();
122
330
  EHPersonality Per = EHPersonality::Unknown;
123
330
  if (F->hasPersonalityFn())
124
97
    Per = classifyEHPersonality(F->getPersonalityFn()->stripPointerCasts());
125
330
126
330
  // Get rid of any dead landing pads if we're not using funclets. In funclet
127
330
  // schemes, the landing pad is not actually reachable. It only exists so
128
330
  // that we can emit the right table data.
129
330
  if (
!isFuncletEHPersonality(Per)330
) {
130
245
    MachineFunction *NonConstMF = const_cast<MachineFunction*>(MF);
131
245
    NonConstMF->tidyLandingPads();
132
245
  }
133
330
134
330
  endFunclet();
135
330
136
330
  // endFunclet will emit the necessary .xdata tables for x64 SEH.
137
330
  if (
Per == EHPersonality::MSVC_Win64SEH && 330
MF->hasEHFunclets()11
)
138
11
    return;
139
319
140
319
  
if (319
shouldEmitPersonality || 319
shouldEmitLSDA265
) {
141
83
    Asm->OutStreamer->PushSection();
142
83
143
83
    // Just switch sections to the right xdata section.
144
83
    MCSection *XData = Asm->OutStreamer->getAssociatedXDataSection(
145
83
        Asm->OutStreamer->getCurrentSectionOnly());
146
83
    Asm->OutStreamer->SwitchSection(XData);
147
83
148
83
    // Emit the tables appropriate to the personality function in use. If we
149
83
    // don't recognize the personality, assume it uses an Itanium-style LSDA.
150
83
    if (Per == EHPersonality::MSVC_Win64SEH)
151
0
      emitCSpecificHandlerTable(MF);
152
83
    else 
if (83
Per == EHPersonality::MSVC_X86SEH83
)
153
12
      emitExceptHandlerTable(MF);
154
71
    else 
if (71
Per == EHPersonality::MSVC_CXX71
)
155
53
      emitCXXFrameHandler3Table(MF);
156
18
    else 
if (18
Per == EHPersonality::CoreCLR18
)
157
7
      emitCLRExceptionTable(MF);
158
18
    else
159
11
      emitExceptionTable();
160
83
161
83
    Asm->OutStreamer->PopSection();
162
83
  }
163
1.81k
}
164
165
/// Retrieve the MCSymbol for a GlobalValue or MachineBasicBlock.
166
static MCSymbol *getMCSymbolForMBB(AsmPrinter *Asm,
167
416
                                   const MachineBasicBlock *MBB) {
168
416
  if (!MBB)
169
116
    return nullptr;
170
300
171
416
  assert(MBB->isEHFuncletEntry());
172
300
173
300
  // Give catches and cleanups a name based off of their parent function and
174
300
  // their funclet entry block's number.
175
300
  const MachineFunction *MF = MBB->getParent();
176
300
  const Function *F = MF->getFunction();
177
300
  StringRef FuncLinkageName = GlobalValue::dropLLVMManglingEscape(F->getName());
178
300
  MCContext &Ctx = MF->getContext();
179
300
  StringRef HandlerPrefix = MBB->isCleanupFuncletEntry() ? 
"dtor"90
:
"catch"210
;
180
416
  return Ctx.getOrCreateSymbol("?" + HandlerPrefix + "$" +
181
416
                               Twine(MBB->getNumber()) + "@?0?" +
182
416
                               FuncLinkageName + "@4HA");
183
416
}
184
185
void WinException::beginFunclet(const MachineBasicBlock &MBB,
186
1.22k
                                MCSymbol *Sym) {
187
1.22k
  CurrentFuncletEntry = &MBB;
188
1.22k
189
1.22k
  const Function *F = Asm->MF->getFunction();
190
1.22k
  // If a symbol was not provided for the funclet, invent one.
191
1.22k
  if (
!Sym1.22k
) {
192
114
    Sym = getMCSymbolForMBB(Asm, &MBB);
193
114
194
114
    // Describe our funclet symbol as a function with internal linkage.
195
114
    Asm->OutStreamer->BeginCOFFSymbolDef(Sym);
196
114
    Asm->OutStreamer->EmitCOFFSymbolStorageClass(COFF::IMAGE_SYM_CLASS_STATIC);
197
114
    Asm->OutStreamer->EmitCOFFSymbolType(COFF::IMAGE_SYM_DTYPE_FUNCTION
198
114
                                         << COFF::SCT_COMPLEX_TYPE_SHIFT);
199
114
    Asm->OutStreamer->EndCOFFSymbolDef();
200
114
201
114
    // We want our funclet's entry point to be aligned such that no nops will be
202
114
    // present after the label.
203
114
    Asm->EmitAlignment(std::max(Asm->MF->getAlignment(), MBB.getAlignment()),
204
114
                       F);
205
114
206
114
    // Now that we've emitted the alignment directive, point at our funclet.
207
114
    Asm->OutStreamer->EmitLabel(Sym);
208
114
  }
209
1.22k
210
1.22k
  // Mark 'Sym' as starting our funclet.
211
1.22k
  if (
shouldEmitMoves || 1.22k
shouldEmitPersonality841
) {
212
384
    CurrentFuncletTextSection = Asm->OutStreamer->getCurrentSectionOnly();
213
384
    Asm->OutStreamer->EmitWinCFIStartProc(Sym);
214
384
  }
215
1.22k
216
1.22k
  if (
shouldEmitPersonality1.22k
) {
217
149
    const TargetLoweringObjectFile &TLOF = Asm->getObjFileLowering();
218
149
    const Function *PerFn = nullptr;
219
149
220
149
    // Determine which personality routine we are using for this funclet.
221
149
    if (F->hasPersonalityFn())
222
149
      PerFn = dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
223
149
    const MCSymbol *PersHandlerSym =
224
149
        TLOF.getCFIPersonalitySymbol(PerFn, Asm->TM, MMI);
225
149
226
149
    // Do not emit a .seh_handler directives for cleanup funclets.
227
149
    // FIXME: This means cleanup funclets cannot handle exceptions. Given that
228
149
    // Clang doesn't produce EH constructs inside cleanup funclets and LLVM's
229
149
    // inliner doesn't allow inlining them, this isn't a major problem in
230
149
    // practice.
231
149
    if (!CurrentFuncletEntry->isCleanupFuncletEntry())
232
121
      Asm->OutStreamer->EmitWinEHHandler(PersHandlerSym, true, true);
233
149
  }
234
1.22k
}
235
236
443
void WinException::endFunclet() {
237
443
  // No funclet to process?  Great, we have nothing to do.
238
443
  if (!CurrentFuncletEntry)
239
30
    return;
240
413
241
413
  const MachineFunction *MF = Asm->MF;
242
413
  if (
shouldEmitMoves || 413
shouldEmitPersonality31
) {
243
384
    const Function *F = MF->getFunction();
244
384
    EHPersonality Per = EHPersonality::Unknown;
245
384
    if (F->hasPersonalityFn())
246
152
      Per = classifyEHPersonality(F->getPersonalityFn()->stripPointerCasts());
247
384
248
384
    // Emit an UNWIND_INFO struct describing the prologue.
249
384
    Asm->OutStreamer->EmitWinEHHandlerData();
250
384
251
384
    if (
Per == EHPersonality::MSVC_CXX && 384
shouldEmitPersonality97
&&
252
384
        
!CurrentFuncletEntry->isCleanupFuncletEntry()96
) {
253
81
      // If this is a C++ catch funclet (or the parent function),
254
81
      // emit a reference to the LSDA for the parent function.
255
81
      StringRef FuncLinkageName = GlobalValue::dropLLVMManglingEscape(F->getName());
256
81
      MCSymbol *FuncInfoXData = Asm->OutContext.getOrCreateSymbol(
257
81
          Twine("$cppxdata$", FuncLinkageName));
258
81
      Asm->OutStreamer->EmitValue(create32bitRef(FuncInfoXData), 4);
259
384
    } else 
if (303
Per == EHPersonality::MSVC_Win64SEH && 303
MF->hasEHFunclets()16
&&
260
303
               
!CurrentFuncletEntry->isEHFuncletEntry()16
) {
261
11
      // If this is the parent function in Win64 SEH, emit the LSDA immediately
262
11
      // following .seh_handlerdata.
263
11
      emitCSpecificHandlerTable(MF);
264
11
    }
265
384
266
384
    // Switch back to the funclet start .text section now that we are done
267
384
    // writing to .xdata, and emit an .seh_endproc directive to mark the end of
268
384
    // the function.
269
384
    Asm->OutStreamer->SwitchSection(CurrentFuncletTextSection);
270
384
    Asm->OutStreamer->EmitWinCFIEndProc();
271
384
  }
272
443
273
443
  // Let's make sure we don't try to end the same funclet twice.
274
443
  CurrentFuncletEntry = nullptr;
275
443
}
276
277
800
const MCExpr *WinException::create32bitRef(const MCSymbol *Value) {
278
800
  if (!Value)
279
142
    return MCConstantExpr::create(0, Asm->OutContext);
280
658
  return MCSymbolRefExpr::create(Value, useImageRel32
281
538
                                            ? MCSymbolRefExpr::VK_COFF_IMGREL32
282
120
                                            : MCSymbolRefExpr::VK_None,
283
800
                                 Asm->OutContext);
284
800
}
285
286
95
const MCExpr *WinException::create32bitRef(const GlobalValue *GV) {
287
95
  if (!GV)
288
47
    return MCConstantExpr::create(0, Asm->OutContext);
289
48
  return create32bitRef(Asm->getSymbol(GV));
290
48
}
291
292
130
const MCExpr *WinException::getLabelPlusOne(const MCSymbol *Label) {
293
130
  return MCBinaryExpr::createAdd(create32bitRef(Label),
294
130
                                 MCConstantExpr::create(1, Asm->OutContext),
295
130
                                 Asm->OutContext);
296
130
}
297
298
const MCExpr *WinException::getOffset(const MCSymbol *OffsetOf,
299
141
                                      const MCSymbol *OffsetFrom) {
300
141
  return MCBinaryExpr::createSub(
301
141
      MCSymbolRefExpr::create(OffsetOf, Asm->OutContext),
302
141
      MCSymbolRefExpr::create(OffsetFrom, Asm->OutContext), Asm->OutContext);
303
141
}
304
305
const MCExpr *WinException::getOffsetPlusOne(const MCSymbol *OffsetOf,
306
52
                                             const MCSymbol *OffsetFrom) {
307
52
  return MCBinaryExpr::createAdd(getOffset(OffsetOf, OffsetFrom),
308
52
                                 MCConstantExpr::create(1, Asm->OutContext),
309
52
                                 Asm->OutContext);
310
52
}
311
312
int WinException::getFrameIndexOffset(int FrameIndex,
313
43
                                      const WinEHFuncInfo &FuncInfo) {
314
43
  const TargetFrameLowering &TFI = *Asm->MF->getSubtarget().getFrameLowering();
315
43
  unsigned UnusedReg;
316
43
  if (
Asm->MAI->usesWindowsCFI()43
) {
317
41
    int Offset =
318
41
        TFI.getFrameIndexReferencePreferSP(*Asm->MF, FrameIndex, UnusedReg,
319
41
                                           /*IgnoreSPUpdates*/ true);
320
41
    assert(UnusedReg ==
321
41
           Asm->MF->getSubtarget()
322
41
               .getTargetLowering()
323
41
               ->getStackPointerRegisterToSaveRestore());
324
41
    return Offset;
325
41
  }
326
2
327
2
  // For 32-bit, offsets should be relative to the end of the EH registration
328
2
  // node. For 64-bit, it's relative to SP at the end of the prologue.
329
43
  assert(FuncInfo.EHRegNodeEndOffset != INT_MAX);
330
2
  int Offset = TFI.getFrameIndexReference(*Asm->MF, FrameIndex, UnusedReg);
331
2
  Offset += FuncInfo.EHRegNodeEndOffset;
332
2
  return Offset;
333
2
}
334
335
namespace {
336
337
/// Top-level state used to represent unwind to caller
338
const int NullState = -1;
339
340
struct InvokeStateChange {
341
  /// EH Label immediately after the last invoke in the previous state, or
342
  /// nullptr if the previous state was the null state.
343
  const MCSymbol *PreviousEndLabel;
344
345
  /// EH label immediately before the first invoke in the new state, or nullptr
346
  /// if the new state is the null state.
347
  const MCSymbol *NewStartLabel;
348
349
  /// State of the invoke following NewStartLabel, or NullState to indicate
350
  /// the presence of calls which may unwind to caller.
351
  int NewState;
352
};
353
354
/// Iterator that reports all the invoke state changes in a range of machine
355
/// basic blocks.  Changes to the null state are reported whenever a call that
356
/// may unwind to caller is encountered.  The MBB range is expected to be an
357
/// entire function or funclet, and the start and end of the range are treated
358
/// as being in the NullState even if there's not an unwind-to-caller call
359
/// before the first invoke or after the last one (i.e., the first state change
360
/// reported is the first change to something other than NullState, and a
361
/// change back to NullState is always reported at the end of iteration).
362
class InvokeStateChangeIterator {
363
  InvokeStateChangeIterator(const WinEHFuncInfo &EHInfo,
364
                            MachineFunction::const_iterator MFI,
365
                            MachineFunction::const_iterator MFE,
366
                            MachineBasicBlock::const_iterator MBBI,
367
                            int BaseState)
368
236
      : EHInfo(EHInfo), MFI(MFI), MFE(MFE), MBBI(MBBI), BaseState(BaseState) {
369
236
    LastStateChange.PreviousEndLabel = nullptr;
370
236
    LastStateChange.NewStartLabel = nullptr;
371
236
    LastStateChange.NewState = BaseState;
372
236
    scan();
373
236
  }
374
375
public:
376
  static iterator_range<InvokeStateChangeIterator>
377
  range(const WinEHFuncInfo &EHInfo, MachineFunction::const_iterator Begin,
378
118
        MachineFunction::const_iterator End, int BaseState = NullState) {
379
118
    // Reject empty ranges to simplify bookkeeping by ensuring that we can get
380
118
    // the end of the last block.
381
118
    assert(Begin != End);
382
118
    auto BlockBegin = Begin->begin();
383
118
    auto BlockEnd = std::prev(End)->end();
384
118
    return make_range(
385
118
        InvokeStateChangeIterator(EHInfo, Begin, End, BlockBegin, BaseState),
386
118
        InvokeStateChangeIterator(EHInfo, End, End, BlockEnd, BaseState));
387
118
  }
388
389
  // Iterator methods.
390
267
  bool operator==(const InvokeStateChangeIterator &O) const {
391
267
    assert(BaseState == O.BaseState);
392
267
    // Must be visiting same block.
393
267
    if (MFI != O.MFI)
394
91
      return false;
395
176
    // Must be visiting same isntr.
396
176
    
if (176
MBBI != O.MBBI176
)
397
0
      return false;
398
176
    // At end of block/instr iteration, we can still have two distinct states:
399
176
    // one to report the final EndLabel, and another indicating the end of the
400
176
    // state change iteration.  Check for CurrentEndLabel equality to
401
176
    // distinguish these.
402
176
    return CurrentEndLabel == O.CurrentEndLabel;
403
176
  }
404
405
267
  bool operator!=(const InvokeStateChangeIterator &O) const {
406
267
    return !operator==(O);
407
267
  }
408
149
  InvokeStateChange &operator*() { return LastStateChange; }
409
0
  InvokeStateChange *operator->() { return &LastStateChange; }
410
149
  InvokeStateChangeIterator &operator++() { return scan(); }
411
412
private:
413
  InvokeStateChangeIterator &scan();
414
415
  const WinEHFuncInfo &EHInfo;
416
  const MCSymbol *CurrentEndLabel = nullptr;
417
  MachineFunction::const_iterator MFI;
418
  MachineFunction::const_iterator MFE;
419
  MachineBasicBlock::const_iterator MBBI;
420
  InvokeStateChange LastStateChange;
421
  bool VisitingInvoke = false;
422
  int BaseState;
423
};
424
425
} // end anonymous namespace
426
427
385
InvokeStateChangeIterator &InvokeStateChangeIterator::scan() {
428
385
  bool IsNewBlock = false;
429
651
  for (; 
MFI != MFE651
;
++MFI, IsNewBlock = true266
) {
430
357
    if (IsNewBlock)
431
148
      MBBI = MFI->begin();
432
2.30k
    for (auto MBBE = MFI->end(); 
MBBI != MBBE2.30k
;
++MBBI1.94k
) {
433
2.04k
      const MachineInstr &MI = *MBBI;
434
2.04k
      if (
!VisitingInvoke && 2.04k
LastStateChange.NewState != BaseState1.77k
&&
435
2.04k
          
MI.isCall()355
&&
!EHStreamer::callToNoUnwindFunction(&MI)17
) {
436
8
        // Indicate a change of state to the null state.  We don't have
437
8
        // start/end EH labels handy but the caller won't expect them for
438
8
        // null state regions.
439
8
        LastStateChange.PreviousEndLabel = CurrentEndLabel;
440
8
        LastStateChange.NewStartLabel = nullptr;
441
8
        LastStateChange.NewState = BaseState;
442
8
        CurrentEndLabel = nullptr;
443
8
        // Don't re-visit this instr on the next scan
444
8
        ++MBBI;
445
8
        return *this;
446
8
      }
447
2.03k
448
2.03k
      // All other state changes are at EH labels before/after invokes.
449
2.03k
      
if (2.03k
!MI.isEHLabel()2.03k
)
450
1.84k
        continue;
451
184
      MCSymbol *Label = MI.getOperand(0).getMCSymbol();
452
184
      if (
Label == CurrentEndLabel184
) {
453
92
        VisitingInvoke = false;
454
92
        continue;
455
92
      }
456
92
      auto InvokeMapIter = EHInfo.LabelToStateMap.find(Label);
457
92
      // Ignore EH labels that aren't the ones inserted before an invoke
458
92
      if (InvokeMapIter == EHInfo.LabelToStateMap.end())
459
0
        continue;
460
92
      auto &StateAndEnd = InvokeMapIter->second;
461
92
      int NewState = StateAndEnd.first;
462
92
      // Keep track of the fact that we're between EH start/end labels so
463
92
      // we know not to treat the inoke we'll see as unwinding to caller.
464
92
      VisitingInvoke = true;
465
92
      if (
NewState == LastStateChange.NewState92
) {
466
9
        // The state isn't actually changing here.  Record the new end and
467
9
        // keep going.
468
9
        CurrentEndLabel = StateAndEnd.second;
469
9
        continue;
470
9
      }
471
83
      // Found a state change to report
472
83
      LastStateChange.PreviousEndLabel = CurrentEndLabel;
473
83
      LastStateChange.NewStartLabel = Label;
474
83
      LastStateChange.NewState = NewState;
475
83
      // Start keeping track of the new current end
476
83
      CurrentEndLabel = StateAndEnd.second;
477
83
      // Don't re-visit this instr on the next scan
478
83
      ++MBBI;
479
83
      return *this;
480
83
    }
481
357
  }
482
385
  // Iteration hit the end of the block range.
483
294
  
if (294
LastStateChange.NewState != BaseState294
) {
484
58
    // Report the end of the last new state
485
58
    LastStateChange.PreviousEndLabel = CurrentEndLabel;
486
58
    LastStateChange.NewStartLabel = nullptr;
487
58
    LastStateChange.NewState = BaseState;
488
58
    // Leave CurrentEndLabel non-null to distinguish this state from end.
489
58
    assert(CurrentEndLabel != nullptr);
490
58
    return *this;
491
58
  }
492
236
  // We've reported all state changes and hit the end state.
493
236
  CurrentEndLabel = nullptr;
494
236
  return *this;
495
236
}
496
497
/// Emit the language-specific data that __C_specific_handler expects.  This
498
/// handler lives in the x64 Microsoft C runtime and allows catching or cleaning
499
/// up after faults with __try, __except, and __finally.  The typeinfo values
500
/// are not really RTTI data, but pointers to filter functions that return an
501
/// integer (1, 0, or -1) indicating how to handle the exception. For __finally
502
/// blocks and other cleanups, the landing pad label is zero, and the filter
503
/// function is actually a cleanup handler with the same prototype.  A catch-all
504
/// entry is modeled with a null filter function field and a non-zero landing
505
/// pad label.
506
///
507
/// Possible filter function return values:
508
///   EXCEPTION_EXECUTE_HANDLER (1):
509
///     Jump to the landing pad label after cleanups.
510
///   EXCEPTION_CONTINUE_SEARCH (0):
511
///     Continue searching this table or continue unwinding.
512
///   EXCEPTION_CONTINUE_EXECUTION (-1):
513
///     Resume execution at the trapping PC.
514
///
515
/// Inferred table structure:
516
///   struct Table {
517
///     int NumEntries;
518
///     struct Entry {
519
///       imagerel32 LabelStart;
520
///       imagerel32 LabelEnd;
521
///       imagerel32 FilterOrFinally;  // One means catch-all.
522
///       imagerel32 LabelLPad;        // Zero means __finally.
523
///     } Entries[NumEntries];
524
///   };
525
11
void WinException::emitCSpecificHandlerTable(const MachineFunction *MF) {
526
11
  auto &OS = *Asm->OutStreamer;
527
11
  MCContext &Ctx = Asm->OutContext;
528
11
  const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
529
11
530
11
  bool VerboseAsm = OS.isVerboseAsm();
531
11
  auto AddComment = [&](const Twine &Comment) {
532
11
    if (VerboseAsm)
533
11
      OS.AddComment(Comment);
534
11
  };
535
11
536
11
  // Emit a label assignment with the SEH frame offset so we can use it for
537
11
  // llvm.x86.seh.recoverfp.
538
11
  StringRef FLinkageName =
539
11
      GlobalValue::dropLLVMManglingEscape(MF->getFunction()->getName());
540
11
  MCSymbol *ParentFrameOffset =
541
11
      Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName);
542
11
  const MCExpr *MCOffset =
543
11
      MCConstantExpr::create(FuncInfo.SEHSetFrameOffset, Ctx);
544
11
  Asm->OutStreamer->EmitAssignment(ParentFrameOffset, MCOffset);
545
11
546
11
  // Use the assembler to compute the number of table entries through label
547
11
  // difference and division.
548
11
  MCSymbol *TableBegin =
549
11
      Ctx.createTempSymbol("lsda_begin", /*AlwaysAddSuffix=*/true);
550
11
  MCSymbol *TableEnd =
551
11
      Ctx.createTempSymbol("lsda_end", /*AlwaysAddSuffix=*/true);
552
11
  const MCExpr *LabelDiff = getOffset(TableEnd, TableBegin);
553
11
  const MCExpr *EntrySize = MCConstantExpr::create(16, Ctx);
554
11
  const MCExpr *EntryCount = MCBinaryExpr::createDiv(LabelDiff, EntrySize, Ctx);
555
11
  AddComment("Number of call sites");
556
11
  OS.EmitValue(EntryCount, 4);
557
11
558
11
  OS.EmitLabel(TableBegin);
559
11
560
11
  // Iterate over all the invoke try ranges. Unlike MSVC, LLVM currently only
561
11
  // models exceptions from invokes. LLVM also allows arbitrary reordering of
562
11
  // the code, so our tables end up looking a bit different. Rather than
563
11
  // trying to match MSVC's tables exactly, we emit a denormalized table.  For
564
11
  // each range of invokes in the same state, we emit table entries for all
565
11
  // the actions that would be taken in that state. This means our tables are
566
11
  // slightly bigger, which is OK.
567
11
  const MCSymbol *LastStartLabel = nullptr;
568
11
  int LastEHState = -1;
569
11
  // Break out before we enter into a finally funclet.
570
11
  // FIXME: We need to emit separate EH tables for cleanups.
571
11
  MachineFunction::const_iterator End = MF->end();
572
11
  MachineFunction::const_iterator Stop = std::next(MF->begin());
573
44
  while (
Stop != End && 44
!Stop->isEHFuncletEntry()38
)
574
33
    ++Stop;
575
11
  for (const auto &StateChange :
576
26
       InvokeStateChangeIterator::range(FuncInfo, MF->begin(), Stop)) {
577
26
    // Emit all the actions for the state we just transitioned out of
578
26
    // if it was not the null state
579
26
    if (LastEHState != -1)
580
15
      emitSEHActionsForRange(FuncInfo, LastStartLabel,
581
15
                             StateChange.PreviousEndLabel, LastEHState);
582
26
    LastStartLabel = StateChange.NewStartLabel;
583
26
    LastEHState = StateChange.NewState;
584
26
  }
585
11
586
11
  OS.EmitLabel(TableEnd);
587
11
}
588
589
void WinException::emitSEHActionsForRange(const WinEHFuncInfo &FuncInfo,
590
                                          const MCSymbol *BeginLabel,
591
15
                                          const MCSymbol *EndLabel, int State) {
592
15
  auto &OS = *Asm->OutStreamer;
593
15
  MCContext &Ctx = Asm->OutContext;
594
15
595
15
  bool VerboseAsm = OS.isVerboseAsm();
596
84
  auto AddComment = [&](const Twine &Comment) {
597
84
    if (VerboseAsm)
598
84
      OS.AddComment(Comment);
599
84
  };
600
15
601
15
  assert(BeginLabel && EndLabel);
602
36
  while (
State != -136
) {
603
21
    const SEHUnwindMapEntry &UME = FuncInfo.SEHUnwindMap[State];
604
21
    const MCExpr *FilterOrFinally;
605
21
    const MCExpr *ExceptOrNull;
606
21
    auto *Handler = UME.Handler.get<MachineBasicBlock *>();
607
21
    if (
UME.IsFinally21
) {
608
5
      FilterOrFinally = create32bitRef(getMCSymbolForMBB(Asm, Handler));
609
5
      ExceptOrNull = MCConstantExpr::create(0, Ctx);
610
21
    } else {
611
16
      // For an except, the filter can be 1 (catch-all) or a function
612
16
      // label.
613
11
      FilterOrFinally = UME.Filter ? create32bitRef(UME.Filter)
614
5
                                   : MCConstantExpr::create(1, Ctx);
615
16
      ExceptOrNull = create32bitRef(Handler->getSymbol());
616
16
    }
617
21
618
21
    AddComment("LabelStart");
619
21
    OS.EmitValue(getLabelPlusOne(BeginLabel), 4);
620
21
    AddComment("LabelEnd");
621
21
    OS.EmitValue(getLabelPlusOne(EndLabel), 4);
622
21
    AddComment(UME.IsFinally ? 
"FinallyFunclet"5
:
UME.Filter ? 16
"FilterFunction"11
623
5
                                                             : "CatchAll");
624
21
    OS.EmitValue(FilterOrFinally, 4);
625
21
    AddComment(UME.IsFinally ? 
"Null"5
:
"ExceptionHandler"16
);
626
21
    OS.EmitValue(ExceptOrNull, 4);
627
21
628
21
    assert(UME.ToState < State && "states should decrease");
629
21
    State = UME.ToState;
630
21
  }
631
15
}
632
633
53
void WinException::emitCXXFrameHandler3Table(const MachineFunction *MF) {
634
53
  const Function *F = MF->getFunction();
635
53
  auto &OS = *Asm->OutStreamer;
636
53
  const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
637
53
638
53
  StringRef FuncLinkageName = GlobalValue::dropLLVMManglingEscape(F->getName());
639
53
640
53
  SmallVector<std::pair<const MCExpr *, int>, 4> IPToStateTable;
641
53
  MCSymbol *FuncInfoXData = nullptr;
642
53
  if (
shouldEmitPersonality53
) {
643
35
    // If we're 64-bit, emit a pointer to the C++ EH data, and build a map from
644
35
    // IPs to state numbers.
645
35
    FuncInfoXData =
646
35
        Asm->OutContext.getOrCreateSymbol(Twine("$cppxdata$", FuncLinkageName));
647
35
    computeIP2StateTable(MF, FuncInfo, IPToStateTable);
648
53
  } else {
649
18
    FuncInfoXData = Asm->OutContext.getOrCreateLSDASymbol(FuncLinkageName);
650
18
  }
651
53
652
53
  int UnwindHelpOffset = 0;
653
53
  if (Asm->MAI->usesWindowsCFI())
654
35
    UnwindHelpOffset =
655
35
        getFrameIndexOffset(FuncInfo.UnwindHelpFrameIdx, FuncInfo);
656
53
657
53
  MCSymbol *UnwindMapXData = nullptr;
658
53
  MCSymbol *TryBlockMapXData = nullptr;
659
53
  MCSymbol *IPToStateXData = nullptr;
660
53
  if (!FuncInfo.CxxUnwindMap.empty())
661
53
    UnwindMapXData = Asm->OutContext.getOrCreateSymbol(
662
53
        Twine("$stateUnwindMap$", FuncLinkageName));
663
53
  if (!FuncInfo.TryBlockMap.empty())
664
45
    TryBlockMapXData =
665
45
        Asm->OutContext.getOrCreateSymbol(Twine("$tryMap$", FuncLinkageName));
666
53
  if (!IPToStateTable.empty())
667
35
    IPToStateXData =
668
35
        Asm->OutContext.getOrCreateSymbol(Twine("$ip2state$", FuncLinkageName));
669
53
670
53
  bool VerboseAsm = OS.isVerboseAsm();
671
1.72k
  auto AddComment = [&](const Twine &Comment) {
672
1.72k
    if (VerboseAsm)
673
1.72k
      OS.AddComment(Comment);
674
1.72k
  };
675
53
676
53
  // FuncInfo {
677
53
  //   uint32_t           MagicNumber
678
53
  //   int32_t            MaxState;
679
53
  //   UnwindMapEntry    *UnwindMap;
680
53
  //   uint32_t           NumTryBlocks;
681
53
  //   TryBlockMapEntry  *TryBlockMap;
682
53
  //   uint32_t           IPMapEntries; // always 0 for x86
683
53
  //   IPToStateMapEntry *IPToStateMap; // always 0 for x86
684
53
  //   uint32_t           UnwindHelp;   // non-x86 only
685
53
  //   ESTypeList        *ESTypeList;
686
53
  //   int32_t            EHFlags;
687
53
  // }
688
53
  // EHFlags & 1 -> Synchronous exceptions only, no async exceptions.
689
53
  // EHFlags & 2 -> ???
690
53
  // EHFlags & 4 -> The function is noexcept(true), unwinding can't continue.
691
53
  OS.EmitValueToAlignment(4);
692
53
  OS.EmitLabel(FuncInfoXData);
693
53
694
53
  AddComment("MagicNumber");
695
53
  OS.EmitIntValue(0x19930522, 4);
696
53
697
53
  AddComment("MaxState");
698
53
  OS.EmitIntValue(FuncInfo.CxxUnwindMap.size(), 4);
699
53
700
53
  AddComment("UnwindMap");
701
53
  OS.EmitValue(create32bitRef(UnwindMapXData), 4);
702
53
703
53
  AddComment("NumTryBlocks");
704
53
  OS.EmitIntValue(FuncInfo.TryBlockMap.size(), 4);
705
53
706
53
  AddComment("TryBlockMap");
707
53
  OS.EmitValue(create32bitRef(TryBlockMapXData), 4);
708
53
709
53
  AddComment("IPMapEntries");
710
53
  OS.EmitIntValue(IPToStateTable.size(), 4);
711
53
712
53
  AddComment("IPToStateXData");
713
53
  OS.EmitValue(create32bitRef(IPToStateXData), 4);
714
53
715
53
  if (
Asm->MAI->usesWindowsCFI()53
) {
716
35
    AddComment("UnwindHelp");
717
35
    OS.EmitIntValue(UnwindHelpOffset, 4);
718
35
  }
719
53
720
53
  AddComment("ESTypeList");
721
53
  OS.EmitIntValue(0, 4);
722
53
723
53
  AddComment("EHFlags");
724
53
  OS.EmitIntValue(1, 4);
725
53
726
53
  // UnwindMapEntry {
727
53
  //   int32_t ToState;
728
53
  //   void  (*Action)();
729
53
  // };
730
53
  if (
UnwindMapXData53
) {
731
53
    OS.EmitLabel(UnwindMapXData);
732
138
    for (const CxxUnwindMapEntry &UME : FuncInfo.CxxUnwindMap) {
733
138
      MCSymbol *CleanupSym =
734
138
          getMCSymbolForMBB(Asm, UME.Cleanup.dyn_cast<MachineBasicBlock *>());
735
138
      AddComment("ToState");
736
138
      OS.EmitIntValue(UME.ToState, 4);
737
138
738
138
      AddComment("Action");
739
138
      OS.EmitValue(create32bitRef(CleanupSym), 4);
740
138
    }
741
53
  }
742
53
743
53
  // TryBlockMap {
744
53
  //   int32_t      TryLow;
745
53
  //   int32_t      TryHigh;
746
53
  //   int32_t      CatchHigh;
747
53
  //   int32_t      NumCatches;
748
53
  //   HandlerType *HandlerArray;
749
53
  // };
750
53
  if (
TryBlockMapXData53
) {
751
45
    OS.EmitLabel(TryBlockMapXData);
752
45
    SmallVector<MCSymbol *, 1> HandlerMaps;
753
103
    for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); 
I != E103
;
++I58
) {
754
58
      const WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
755
58
756
58
      MCSymbol *HandlerMapXData = nullptr;
757
58
      if (!TBME.HandlerArray.empty())
758
58
        HandlerMapXData =
759
58
            Asm->OutContext.getOrCreateSymbol(Twine("$handlerMap$")
760
58
                                                  .concat(Twine(I))
761
58
                                                  .concat("$")
762
58
                                                  .concat(FuncLinkageName));
763
58
      HandlerMaps.push_back(HandlerMapXData);
764
58
765
58
      // TBMEs should form intervals.
766
58
      assert(0 <= TBME.TryLow && "bad trymap interval");
767
58
      assert(TBME.TryLow <= TBME.TryHigh && "bad trymap interval");
768
58
      assert(TBME.TryHigh < TBME.CatchHigh && "bad trymap interval");
769
58
      assert(TBME.CatchHigh < int(FuncInfo.CxxUnwindMap.size()) &&
770
58
             "bad trymap interval");
771
58
772
58
      AddComment("TryLow");
773
58
      OS.EmitIntValue(TBME.TryLow, 4);
774
58
775
58
      AddComment("TryHigh");
776
58
      OS.EmitIntValue(TBME.TryHigh, 4);
777
58
778
58
      AddComment("CatchHigh");
779
58
      OS.EmitIntValue(TBME.CatchHigh, 4);
780
58
781
58
      AddComment("NumCatches");
782
58
      OS.EmitIntValue(TBME.HandlerArray.size(), 4);
783
58
784
58
      AddComment("HandlerArray");
785
58
      OS.EmitValue(create32bitRef(HandlerMapXData), 4);
786
58
    }
787
45
788
45
    // All funclets use the same parent frame offset currently.
789
45
    unsigned ParentFrameOffset = 0;
790
45
    if (
shouldEmitPersonality45
) {
791
31
      const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering();
792
31
      ParentFrameOffset = TFI->getWinEHParentFrameOffset(*MF);
793
31
    }
794
45
795
103
    for (size_t I = 0, E = FuncInfo.TryBlockMap.size(); 
I != E103
;
++I58
) {
796
58
      const WinEHTryBlockMapEntry &TBME = FuncInfo.TryBlockMap[I];
797
58
      MCSymbol *HandlerMapXData = HandlerMaps[I];
798
58
      if (!HandlerMapXData)
799
0
        continue;
800
58
      // HandlerType {
801
58
      //   int32_t         Adjectives;
802
58
      //   TypeDescriptor *Type;
803
58
      //   int32_t         CatchObjOffset;
804
58
      //   void          (*Handler)();
805
58
      //   int32_t         ParentFrameOffset; // x64 only
806
58
      // };
807
58
      OS.EmitLabel(HandlerMapXData);
808
65
      for (const WinEHHandlerType &HT : TBME.HandlerArray) {
809
65
        // Get the frame escape label with the offset of the catch object. If
810
65
        // the index is INT_MAX, then there is no catch object, and we should
811
65
        // emit an offset of zero, indicating that no copy will occur.
812
65
        const MCExpr *FrameAllocOffsetRef = nullptr;
813
65
        if (
HT.CatchObj.FrameIndex != INT_MAX65
) {
814
8
          int Offset = getFrameIndexOffset(HT.CatchObj.FrameIndex, FuncInfo);
815
8
          assert(Offset != 0 && "Illegal offset for catch object!");
816
8
          FrameAllocOffsetRef = MCConstantExpr::create(Offset, Asm->OutContext);
817
65
        } else {
818
57
          FrameAllocOffsetRef = MCConstantExpr::create(0, Asm->OutContext);
819
57
        }
820
65
821
65
        MCSymbol *HandlerSym =
822
65
            getMCSymbolForMBB(Asm, HT.Handler.dyn_cast<MachineBasicBlock *>());
823
65
824
65
        AddComment("Adjectives");
825
65
        OS.EmitIntValue(HT.Adjectives, 4);
826
65
827
65
        AddComment("Type");
828
65
        OS.EmitValue(create32bitRef(HT.TypeDescriptor), 4);
829
65
830
65
        AddComment("CatchObjOffset");
831
65
        OS.EmitValue(FrameAllocOffsetRef, 4);
832
65
833
65
        AddComment("Handler");
834
65
        OS.EmitValue(create32bitRef(HandlerSym), 4);
835
65
836
65
        if (
shouldEmitPersonality65
) {
837
46
          AddComment("ParentFrameOffset");
838
46
          OS.EmitIntValue(ParentFrameOffset, 4);
839
46
        }
840
65
      }
841
58
    }
842
45
  }
843
53
844
53
  // IPToStateMapEntry {
845
53
  //   void   *IP;
846
53
  //   int32_t State;
847
53
  // };
848
53
  if (
IPToStateXData53
) {
849
35
    OS.EmitLabel(IPToStateXData);
850
169
    for (auto &IPStatePair : IPToStateTable) {
851
169
      AddComment("IP");
852
169
      OS.EmitValue(IPStatePair.first, 4);
853
169
      AddComment("ToState");
854
169
      OS.EmitIntValue(IPStatePair.second, 4);
855
169
    }
856
35
  }
857
53
}
858
859
void WinException::computeIP2StateTable(
860
    const MachineFunction *MF, const WinEHFuncInfo &FuncInfo,
861
35
    SmallVectorImpl<std::pair<const MCExpr *, int>> &IPToStateTable) {
862
35
863
35
  for (MachineFunction::const_iterator FuncletStart = MF->begin(),
864
35
                                       FuncletEnd = MF->begin(),
865
35
                                       End = MF->end();
866
131
       
FuncletStart != End131
;
FuncletStart = FuncletEnd96
) {
867
96
    // Find the end of the funclet
868
188
    while (
++FuncletEnd != End188
) {
869
153
      if (
FuncletEnd->isEHFuncletEntry()153
) {
870
61
        break;
871
61
      }
872
153
    }
873
96
874
96
    // Don't emit ip2state entries for cleanup funclets. Any interesting
875
96
    // exceptional actions in cleanups must be handled in a separate IR
876
96
    // function.
877
96
    if (FuncletStart->isCleanupFuncletEntry())
878
15
      continue;
879
81
880
81
    MCSymbol *StartLabel;
881
81
    int BaseState;
882
81
    if (
FuncletStart == MF->begin()81
) {
883
35
      BaseState = NullState;
884
35
      StartLabel = Asm->getFunctionBegin();
885
81
    } else {
886
46
      auto *FuncletPad =
887
46
          cast<FuncletPadInst>(FuncletStart->getBasicBlock()->getFirstNonPHI());
888
46
      assert(FuncInfo.FuncletBaseStateMap.count(FuncletPad) != 0);
889
46
      BaseState = FuncInfo.FuncletBaseStateMap.find(FuncletPad)->second;
890
46
      StartLabel = getMCSymbolForMBB(Asm, &*FuncletStart);
891
46
    }
892
81
    assert(StartLabel && "need local function start label");
893
81
    IPToStateTable.push_back(
894
81
        std::make_pair(create32bitRef(StartLabel), BaseState));
895
81
896
81
    for (const auto &StateChange : InvokeStateChangeIterator::range(
897
88
             FuncInfo, FuncletStart, FuncletEnd, BaseState)) {
898
88
      // Compute the label to report as the start of this entry; use the EH
899
88
      // start label for the invoke if we have one, otherwise (this is a call
900
88
      // which may unwind to our caller and does not have an EH start label, so)
901
88
      // use the previous end label.
902
88
      const MCSymbol *ChangeLabel = StateChange.NewStartLabel;
903
88
      if (!ChangeLabel)
904
39
        ChangeLabel = StateChange.PreviousEndLabel;
905
88
      // Emit an entry indicating that PCs after 'Label' have this EH state.
906
88
      IPToStateTable.push_back(
907
88
          std::make_pair(getLabelPlusOne(ChangeLabel), StateChange.NewState));
908
88
      // FIXME: assert that NewState is between CatchLow and CatchHigh.
909
88
    }
910
96
  }
911
35
}
912
913
void WinException::emitEHRegistrationOffsetLabel(const WinEHFuncInfo &FuncInfo,
914
13
                                                 StringRef FLinkageName) {
915
13
  // Outlined helpers called by the EH runtime need to know the offset of the EH
916
13
  // registration in order to recover the parent frame pointer. Now that we know
917
13
  // we've code generated the parent, we can emit the label assignment that
918
13
  // those helpers use to get the offset of the registration node.
919
13
920
13
  // Compute the parent frame offset. The EHRegNodeFrameIndex will be invalid if
921
13
  // after optimization all the invokes were eliminated. We still need to emit
922
13
  // the parent frame offset label, but it should be garbage and should never be
923
13
  // used.
924
13
  int64_t Offset = 0;
925
13
  int FI = FuncInfo.EHRegNodeFrameIndex;
926
13
  if (
FI != INT_MAX13
) {
927
12
    const TargetFrameLowering *TFI = Asm->MF->getSubtarget().getFrameLowering();
928
12
    unsigned UnusedReg;
929
12
    Offset = TFI->getFrameIndexReference(*Asm->MF, FI, UnusedReg);
930
12
  }
931
13
932
13
  MCContext &Ctx = Asm->OutContext;
933
13
  MCSymbol *ParentFrameOffset =
934
13
      Ctx.getOrCreateParentFrameOffsetSymbol(FLinkageName);
935
13
  Asm->OutStreamer->EmitAssignment(ParentFrameOffset,
936
13
                                   MCConstantExpr::create(Offset, Ctx));
937
13
}
938
939
/// Emit the language-specific data that _except_handler3 and 4 expect. This is
940
/// functionally equivalent to the __C_specific_handler table, except it is
941
/// indexed by state number instead of IP.
942
12
void WinException::emitExceptHandlerTable(const MachineFunction *MF) {
943
12
  MCStreamer &OS = *Asm->OutStreamer;
944
12
  const Function *F = MF->getFunction();
945
12
  StringRef FLinkageName = GlobalValue::dropLLVMManglingEscape(F->getName());
946
12
947
12
  bool VerboseAsm = OS.isVerboseAsm();
948
65
  auto AddComment = [&](const Twine &Comment) {
949
65
    if (VerboseAsm)
950
65
      OS.AddComment(Comment);
951
65
  };
952
12
953
12
  const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
954
12
  emitEHRegistrationOffsetLabel(FuncInfo, FLinkageName);
955
12
956
12
  // Emit the __ehtable label that we use for llvm.x86.seh.lsda.
957
12
  MCSymbol *LSDALabel = Asm->OutContext.getOrCreateLSDASymbol(FLinkageName);
958
12
  OS.EmitValueToAlignment(4);
959
12
  OS.EmitLabel(LSDALabel);
960
12
961
12
  const Function *Per =
962
12
      dyn_cast<Function>(F->getPersonalityFn()->stripPointerCasts());
963
12
  StringRef PerName = Per->getName();
964
12
  int BaseState = -1;
965
12
  if (
PerName == "_except_handler4"12
) {
966
2
    // The LSDA for _except_handler4 starts with this struct, followed by the
967
2
    // scope table:
968
2
    //
969
2
    // struct EH4ScopeTable {
970
2
    //   int32_t GSCookieOffset;
971
2
    //   int32_t GSCookieXOROffset;
972
2
    //   int32_t EHCookieOffset;
973
2
    //   int32_t EHCookieXOROffset;
974
2
    //   ScopeTableEntry ScopeRecord[];
975
2
    // };
976
2
    //
977
2
    // Offsets are %ebp relative.
978
2
    //
979
2
    // The GS cookie is present only if the function needs stack protection.
980
2
    // GSCookieOffset = -2 means that GS cookie is not used.
981
2
    //
982
2
    // The EH cookie is always present.
983
2
    //
984
2
    // Check is done the following way:
985
2
    //    (ebp+CookieXOROffset) ^ [ebp+CookieOffset] == _security_cookie
986
2
987
2
    // Retrieve the Guard Stack slot.
988
2
    int GSCookieOffset = -2;
989
2
    const MachineFrameInfo &MFI = MF->getFrameInfo();
990
2
    if (
MFI.hasStackProtectorIndex()2
) {
991
0
      unsigned UnusedReg;
992
0
      const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering();
993
0
      int SSPIdx = MFI.getStackProtectorIndex();
994
0
      GSCookieOffset = TFI->getFrameIndexReference(*MF, SSPIdx, UnusedReg);
995
0
    }
996
2
997
2
    // Retrieve the EH Guard slot.
998
2
    // TODO(etienneb): Get rid of this value and change it for and assertion.
999
2
    int EHCookieOffset = 9999;
1000
2
    if (
FuncInfo.EHGuardFrameIndex != INT_MAX2
) {
1001
2
      unsigned UnusedReg;
1002
2
      const TargetFrameLowering *TFI = MF->getSubtarget().getFrameLowering();
1003
2
      int EHGuardIdx = FuncInfo.EHGuardFrameIndex;
1004
2
      EHCookieOffset = TFI->getFrameIndexReference(*MF, EHGuardIdx, UnusedReg);
1005
2
    }
1006
2
1007
2
    AddComment("GSCookieOffset");
1008
2
    OS.EmitIntValue(GSCookieOffset, 4);
1009
2
    AddComment("GSCookieXOROffset");
1010
2
    OS.EmitIntValue(0, 4);
1011
2
    AddComment("EHCookieOffset");
1012
2
    OS.EmitIntValue(EHCookieOffset, 4);
1013
2
    AddComment("EHCookieXOROffset");
1014
2
    OS.EmitIntValue(0, 4);
1015
2
    BaseState = -2;
1016
2
  }
1017
12
1018
12
  assert(!FuncInfo.SEHUnwindMap.empty());
1019
19
  for (const SEHUnwindMapEntry &UME : FuncInfo.SEHUnwindMap) {
1020
19
    auto *Handler = UME.Handler.get<MachineBasicBlock *>();
1021
19
    const MCSymbol *ExceptOrFinally =
1022
19
        UME.IsFinally ? 
getMCSymbolForMBB(Asm, Handler)3
:
Handler->getSymbol()16
;
1023
19
    // -1 is usually the base state for "unwind to caller", but for
1024
19
    // _except_handler4 it's -2. Do that replacement here if necessary.
1025
19
    int ToState = UME.ToState == -1 ? 
BaseState14
:
UME.ToState5
;
1026
19
    AddComment("ToState");
1027
19
    OS.EmitIntValue(ToState, 4);
1028
19
    AddComment(UME.IsFinally ? 
"Null"3
:
"FilterFunction"16
);
1029
19
    OS.EmitValue(create32bitRef(UME.Filter), 4);
1030
19
    AddComment(UME.IsFinally ? 
"FinallyFunclet"3
:
"ExceptionHandler"16
);
1031
19
    OS.EmitValue(create32bitRef(ExceptOrFinally), 4);
1032
19
  }
1033
12
}
1034
1035
70
static int getTryRank(const WinEHFuncInfo &FuncInfo, int State) {
1036
70
  int Rank = 0;
1037
126
  while (
State != -1126
) {
1038
56
    ++Rank;
1039
56
    State = FuncInfo.ClrEHUnwindMap[State].TryParentState;
1040
56
  }
1041
70
  return Rank;
1042
70
}
1043
1044
35
static int getTryAncestor(const WinEHFuncInfo &FuncInfo, int Left, int Right) {
1045
35
  int LeftRank = getTryRank(FuncInfo, Left);
1046
35
  int RightRank = getTryRank(FuncInfo, Right);
1047
35
1048
60
  while (
LeftRank < RightRank60
) {
1049
25
    Right = FuncInfo.ClrEHUnwindMap[Right].TryParentState;
1050
25
    --RightRank;
1051
25
  }
1052
35
1053
60
  while (
RightRank < LeftRank60
) {
1054
25
    Left = FuncInfo.ClrEHUnwindMap[Left].TryParentState;
1055
25
    --LeftRank;
1056
25
  }
1057
35
1058
36
  while (
Left != Right36
) {
1059
1
    Left = FuncInfo.ClrEHUnwindMap[Left].TryParentState;
1060
1
    Right = FuncInfo.ClrEHUnwindMap[Right].TryParentState;
1061
1
  }
1062
35
1063
35
  return Left;
1064
35
}
1065
1066
7
void WinException::emitCLRExceptionTable(const MachineFunction *MF) {
1067
7
  // CLR EH "states" are really just IDs that identify handlers/funclets;
1068
7
  // states, handlers, and funclets all have 1:1 mappings between them, and a
1069
7
  // handler/funclet's "state" is its index in the ClrEHUnwindMap.
1070
7
  MCStreamer &OS = *Asm->OutStreamer;
1071
7
  const WinEHFuncInfo &FuncInfo = *MF->getWinEHFuncInfo();
1072
7
  MCSymbol *FuncBeginSym = Asm->getFunctionBegin();
1073
7
  MCSymbol *FuncEndSym = Asm->getFunctionEnd();
1074
7
1075
7
  // A ClrClause describes a protected region.
1076
7
  struct ClrClause {
1077
7
    const MCSymbol *StartLabel; // Start of protected region
1078
7
    const MCSymbol *EndLabel;   // End of protected region
1079
7
    int State;          // Index of handler protecting the protected region
1080
7
    int EnclosingState; // Index of funclet enclosing the protected region
1081
7
  };
1082
7
  SmallVector<ClrClause, 8> Clauses;
1083
7
1084
7
  // Build a map from handler MBBs to their corresponding states (i.e. their
1085
7
  // indices in the ClrEHUnwindMap).
1086
7
  int NumStates = FuncInfo.ClrEHUnwindMap.size();
1087
7
  assert(NumStates > 0 && "Don't need exception table!");
1088
7
  DenseMap<const MachineBasicBlock *, int> HandlerStates;
1089
26
  for (int State = 0; 
State < NumStates26
;
++State19
) {
1090
19
    MachineBasicBlock *HandlerBlock =
1091
19
        FuncInfo.ClrEHUnwindMap[State].Handler.get<MachineBasicBlock *>();
1092
19
    HandlerStates[HandlerBlock] = State;
1093
19
    // Use this loop through all handlers to verify our assumption (used in
1094
19
    // the MinEnclosingState computation) that enclosing funclets have lower
1095
19
    // state numbers than their enclosed funclets.
1096
19
    assert(FuncInfo.ClrEHUnwindMap[State].HandlerParentState < State &&
1097
19
           "ill-formed state numbering");
1098
19
  }
1099
7
  // Map the main function to the NullState.
1100
7
  HandlerStates[&MF->front()] = NullState;
1101
7
1102
7
  // Write out a sentinel indicating the end of the standard (Windows) xdata
1103
7
  // and the start of the additional (CLR) info.
1104
7
  OS.EmitIntValue(0xffffffff, 4);
1105
7
  // Write out the number of funclets
1106
7
  OS.EmitIntValue(NumStates, 4);
1107
7
1108
7
  // Walk the machine blocks/instrs, computing and emitting a few things:
1109
7
  // 1. Emit a list of the offsets to each handler entry, in lexical order.
1110
7
  // 2. Compute a map (EndSymbolMap) from each funclet to the symbol at its end.
1111
7
  // 3. Compute the list of ClrClauses, in the required order (inner before
1112
7
  //    outer, earlier before later; the order by which a forward scan with
1113
7
  //    early termination will find the innermost enclosing clause covering
1114
7
  //    a given address).
1115
7
  // 4. A map (MinClauseMap) from each handler index to the index of the
1116
7
  //    outermost funclet/function which contains a try clause targeting the
1117
7
  //    key handler.  This will be used to determine IsDuplicate-ness when
1118
7
  //    emitting ClrClauses.  The NullState value is used to indicate that the
1119
7
  //    top-level function contains a try clause targeting the key handler.
1120
7
  // HandlerStack is a stack of (PendingStartLabel, PendingState) pairs for
1121
7
  // try regions we entered before entering the PendingState try but which
1122
7
  // we haven't yet exited.
1123
7
  SmallVector<std::pair<const MCSymbol *, int>, 4> HandlerStack;
1124
7
  // EndSymbolMap and MinClauseMap are maps described above.
1125
7
  std::unique_ptr<MCSymbol *[]> EndSymbolMap(new MCSymbol *[NumStates]);
1126
7
  SmallVector<int, 4> MinClauseMap((size_t)NumStates, NumStates);
1127
7
1128
7
  // Visit the root function and each funclet.
1129
7
  for (MachineFunction::const_iterator FuncletStart = MF->begin(),
1130
7
                                       FuncletEnd = MF->begin(),
1131
7
                                       End = MF->end();
1132
33
       
FuncletStart != End33
;
FuncletStart = FuncletEnd26
) {
1133
26
    int FuncletState = HandlerStates[&*FuncletStart];
1134
26
    // Find the end of the funclet
1135
26
    MCSymbol *EndSymbol = FuncEndSym;
1136
49
    while (
++FuncletEnd != End49
) {
1137
42
      if (
FuncletEnd->isEHFuncletEntry()42
) {
1138
19
        EndSymbol = getMCSymbolForMBB(Asm, &*FuncletEnd);
1139
19
        break;
1140
19
      }
1141
42
    }
1142
26
    // Emit the function/funclet end and, if this is a funclet (and not the
1143
26
    // root function), record it in the EndSymbolMap.
1144
26
    OS.EmitValue(getOffset(EndSymbol, FuncBeginSym), 4);
1145
26
    if (
FuncletState != NullState26
) {
1146
19
      // Record the end of the handler.
1147
19
      EndSymbolMap[FuncletState] = EndSymbol;
1148
19
    }
1149
26
1150
26
    // Walk the state changes in this function/funclet and compute its clauses.
1151
26
    // Funclets always start in the null state.
1152
26
    const MCSymbol *CurrentStartLabel = nullptr;
1153
26
    int CurrentState = NullState;
1154
26
    assert(HandlerStack.empty());
1155
26
    for (const auto &StateChange :
1156
35
         InvokeStateChangeIterator::range(FuncInfo, FuncletStart, FuncletEnd)) {
1157
35
      // Close any try regions we're not still under
1158
35
      int StillPendingState =
1159
35
          getTryAncestor(FuncInfo, CurrentState, StateChange.NewState);
1160
61
      while (
CurrentState != StillPendingState61
) {
1161
26
        assert(CurrentState != NullState &&
1162
26
               "Failed to find still-pending state!");
1163
26
        // Close the pending clause
1164
26
        Clauses.push_back({CurrentStartLabel, StateChange.PreviousEndLabel,
1165
26
                           CurrentState, FuncletState});
1166
26
        // Now the next-outer try region is current
1167
26
        CurrentState = FuncInfo.ClrEHUnwindMap[CurrentState].TryParentState;
1168
26
        // Pop the new start label from the handler stack if we've exited all
1169
26
        // inner try regions of the corresponding try region.
1170
26
        if (HandlerStack.back().second == CurrentState)
1171
19
          CurrentStartLabel = HandlerStack.pop_back_val().first;
1172
26
      }
1173
35
1174
35
      if (
StateChange.NewState != CurrentState35
) {
1175
19
        // For each clause we're starting, update the MinClauseMap so we can
1176
19
        // know which is the topmost funclet containing a clause targeting
1177
19
        // it.
1178
19
        for (int EnteredState = StateChange.NewState;
1179
45
             EnteredState != CurrentState;
1180
26
             EnteredState =
1181
19
                 FuncInfo.ClrEHUnwindMap[EnteredState].TryParentState) {
1182
26
          int &MinEnclosingState = MinClauseMap[EnteredState];
1183
26
          if (FuncletState < MinEnclosingState)
1184
22
            MinEnclosingState = FuncletState;
1185
26
        }
1186
19
        // Save the previous current start/label on the stack and update to
1187
19
        // the newly-current start/state.
1188
19
        HandlerStack.emplace_back(CurrentStartLabel, CurrentState);
1189
19
        CurrentStartLabel = StateChange.NewStartLabel;
1190
19
        CurrentState = StateChange.NewState;
1191
19
      }
1192
35
    }
1193
26
    assert(HandlerStack.empty());
1194
26
  }
1195
7
1196
7
  // Now emit the clause info, starting with the number of clauses.
1197
7
  OS.EmitIntValue(Clauses.size(), 4);
1198
26
  for (ClrClause &Clause : Clauses) {
1199
26
    // Emit a CORINFO_EH_CLAUSE :
1200
26
    /*
1201
26
      struct CORINFO_EH_CLAUSE
1202
26
      {
1203
26
          CORINFO_EH_CLAUSE_FLAGS Flags;         // actually a CorExceptionFlag
1204
26
          DWORD                   TryOffset;
1205
26
          DWORD                   TryLength;     // actually TryEndOffset
1206
26
          DWORD                   HandlerOffset;
1207
26
          DWORD                   HandlerLength; // actually HandlerEndOffset
1208
26
          union
1209
26
          {
1210
26
              DWORD               ClassToken;   // use for catch clauses
1211
26
              DWORD               FilterOffset; // use for filter clauses
1212
26
          };
1213
26
      };
1214
26
1215
26
      enum CORINFO_EH_CLAUSE_FLAGS
1216
26
      {
1217
26
          CORINFO_EH_CLAUSE_NONE    = 0,
1218
26
          CORINFO_EH_CLAUSE_FILTER  = 0x0001, // This clause is for a filter
1219
26
          CORINFO_EH_CLAUSE_FINALLY = 0x0002, // This clause is a finally clause
1220
26
          CORINFO_EH_CLAUSE_FAULT   = 0x0004, // This clause is a fault clause
1221
26
      };
1222
26
      typedef enum CorExceptionFlag
1223
26
      {
1224
26
          COR_ILEXCEPTION_CLAUSE_NONE,
1225
26
          COR_ILEXCEPTION_CLAUSE_FILTER  = 0x0001, // This is a filter clause
1226
26
          COR_ILEXCEPTION_CLAUSE_FINALLY = 0x0002, // This is a finally clause
1227
26
          COR_ILEXCEPTION_CLAUSE_FAULT = 0x0004,   // This is a fault clause
1228
26
          COR_ILEXCEPTION_CLAUSE_DUPLICATED = 0x0008, // duplicated clause. This
1229
26
                                                      // clause was duplicated
1230
26
                                                      // to a funclet which was
1231
26
                                                      // pulled out of line
1232
26
      } CorExceptionFlag;
1233
26
    */
1234
26
    // Add 1 to the start/end of the EH clause; the IP associated with a
1235
26
    // call when the runtime does its scan is the IP of the next instruction
1236
26
    // (the one to which control will return after the call), so we need
1237
26
    // to add 1 to the end of the clause to cover that offset.  We also add
1238
26
    // 1 to the start of the clause to make sure that the ranges reported
1239
26
    // for all clauses are disjoint.  Note that we'll need some additional
1240
26
    // logic when machine traps are supported, since in that case the IP
1241
26
    // that the runtime uses is the offset of the faulting instruction
1242
26
    // itself; if such an instruction immediately follows a call but the
1243
26
    // two belong to different clauses, we'll need to insert a nop between
1244
26
    // them so the runtime can distinguish the point to which the call will
1245
26
    // return from the point at which the fault occurs.
1246
26
1247
26
    const MCExpr *ClauseBegin =
1248
26
        getOffsetPlusOne(Clause.StartLabel, FuncBeginSym);
1249
26
    const MCExpr *ClauseEnd = getOffsetPlusOne(Clause.EndLabel, FuncBeginSym);
1250
26
1251
26
    const ClrEHUnwindMapEntry &Entry = FuncInfo.ClrEHUnwindMap[Clause.State];
1252
26
    MachineBasicBlock *HandlerBlock = Entry.Handler.get<MachineBasicBlock *>();
1253
26
    MCSymbol *BeginSym = getMCSymbolForMBB(Asm, HandlerBlock);
1254
26
    const MCExpr *HandlerBegin = getOffset(BeginSym, FuncBeginSym);
1255
26
    MCSymbol *EndSym = EndSymbolMap[Clause.State];
1256
26
    const MCExpr *HandlerEnd = getOffset(EndSym, FuncBeginSym);
1257
26
1258
26
    uint32_t Flags = 0;
1259
26
    switch (Entry.HandlerType) {
1260
12
    case ClrHandlerType::Catch:
1261
12
      // Leaving bits 0-2 clear indicates catch.
1262
12
      break;
1263
0
    case ClrHandlerType::Filter:
1264
0
      Flags |= 1;
1265
0
      break;
1266
4
    case ClrHandlerType::Finally:
1267
4
      Flags |= 2;
1268
4
      break;
1269
10
    case ClrHandlerType::Fault:
1270
10
      Flags |= 4;
1271
10
      break;
1272
26
    }
1273
26
    
if (26
Clause.EnclosingState != MinClauseMap[Clause.State]26
) {
1274
7
      // This is a "duplicate" clause; the handler needs to be entered from a
1275
7
      // frame above the one holding the invoke.
1276
7
      assert(Clause.EnclosingState > MinClauseMap[Clause.State]);
1277
7
      Flags |= 8;
1278
7
    }
1279
26
    OS.EmitIntValue(Flags, 4);
1280
26
1281
26
    // Write the clause start/end
1282
26
    OS.EmitValue(ClauseBegin, 4);
1283
26
    OS.EmitValue(ClauseEnd, 4);
1284
26
1285
26
    // Write out the handler start/end
1286
26
    OS.EmitValue(HandlerBegin, 4);
1287
26
    OS.EmitValue(HandlerEnd, 4);
1288
26
1289
26
    // Write out the type token or filter offset
1290
26
    assert(Entry.HandlerType != ClrHandlerType::Filter && "NYI: filters");
1291
26
    OS.EmitIntValue(Entry.TypeToken, 4);
1292
26
  }
1293
7
}