Coverage Report

Created: 2019-07-24 05:18

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