LLVM  10.0.0svn
MCWin64EH.cpp
Go to the documentation of this file.
1 //===- lib/MC/MCWin64EH.cpp - MCWin64EH implementation --------------------===//
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 #include "llvm/MC/MCWin64EH.h"
10 #include "llvm/ADT/Twine.h"
11 #include "llvm/MC/MCContext.h"
12 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCSectionCOFF.h"
16 #include "llvm/MC/MCStreamer.h"
17 #include "llvm/MC/MCSymbol.h"
18 #include "llvm/Support/Win64EH.h"
19 
20 using namespace llvm;
21 
22 // NOTE: All relocations generated here are 4-byte image-relative.
23 
24 static uint8_t CountOfUnwindCodes(std::vector<WinEH::Instruction> &Insns) {
25  uint8_t Count = 0;
26  for (const auto &I : Insns) {
27  switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
28  default:
29  llvm_unreachable("Unsupported unwind code");
34  Count += 1;
35  break;
38  Count += 2;
39  break;
42  Count += 3;
43  break;
45  Count += (I.Offset > 512 * 1024 - 8) ? 3 : 2;
46  break;
47  }
48  }
49  return Count;
50 }
51 
52 static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
53  const MCSymbol *RHS) {
54  MCContext &Context = Streamer.getContext();
55  const MCExpr *Diff =
57  MCSymbolRefExpr::create(RHS, Context), Context);
58  Streamer.EmitValue(Diff, 1);
59 }
60 
61 static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
62  WinEH::Instruction &inst) {
63  uint8_t b2;
64  uint16_t w;
65  b2 = (inst.Operation & 0x0F);
66  switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
67  default:
68  llvm_unreachable("Unsupported unwind code");
70  EmitAbsDifference(streamer, inst.Label, begin);
71  b2 |= (inst.Register & 0x0F) << 4;
72  streamer.EmitIntValue(b2, 1);
73  break;
75  EmitAbsDifference(streamer, inst.Label, begin);
76  if (inst.Offset > 512 * 1024 - 8) {
77  b2 |= 0x10;
78  streamer.EmitIntValue(b2, 1);
79  w = inst.Offset & 0xFFF8;
80  streamer.EmitIntValue(w, 2);
81  w = inst.Offset >> 16;
82  } else {
83  streamer.EmitIntValue(b2, 1);
84  w = inst.Offset >> 3;
85  }
86  streamer.EmitIntValue(w, 2);
87  break;
89  b2 |= (((inst.Offset - 8) >> 3) & 0x0F) << 4;
90  EmitAbsDifference(streamer, inst.Label, begin);
91  streamer.EmitIntValue(b2, 1);
92  break;
94  EmitAbsDifference(streamer, inst.Label, begin);
95  streamer.EmitIntValue(b2, 1);
96  break;
99  b2 |= (inst.Register & 0x0F) << 4;
100  EmitAbsDifference(streamer, inst.Label, begin);
101  streamer.EmitIntValue(b2, 1);
102  w = inst.Offset >> 3;
104  w >>= 1;
105  streamer.EmitIntValue(w, 2);
106  break;
109  b2 |= (inst.Register & 0x0F) << 4;
110  EmitAbsDifference(streamer, inst.Label, begin);
111  streamer.EmitIntValue(b2, 1);
113  w = inst.Offset & 0xFFF0;
114  else
115  w = inst.Offset & 0xFFF8;
116  streamer.EmitIntValue(w, 2);
117  w = inst.Offset >> 16;
118  streamer.EmitIntValue(w, 2);
119  break;
121  if (inst.Offset == 1)
122  b2 |= 0x10;
123  EmitAbsDifference(streamer, inst.Label, begin);
124  streamer.EmitIntValue(b2, 1);
125  break;
126  }
127 }
128 
129 static void EmitSymbolRefWithOfs(MCStreamer &streamer,
130  const MCSymbol *Base,
131  const MCSymbol *Other) {
132  MCContext &Context = streamer.getContext();
133  const MCSymbolRefExpr *BaseRef = MCSymbolRefExpr::create(Base, Context);
134  const MCSymbolRefExpr *OtherRef = MCSymbolRefExpr::create(Other, Context);
135  const MCExpr *Ofs = MCBinaryExpr::createSub(OtherRef, BaseRef, Context);
136  const MCSymbolRefExpr *BaseRefRel = MCSymbolRefExpr::create(Base,
138  Context);
139  streamer.EmitValue(MCBinaryExpr::createAdd(BaseRefRel, Ofs, Context), 4);
140 }
141 
142 static void EmitRuntimeFunction(MCStreamer &streamer,
143  const WinEH::FrameInfo *info) {
144  MCContext &context = streamer.getContext();
145 
146  streamer.EmitValueToAlignment(4);
147  EmitSymbolRefWithOfs(streamer, info->Function, info->Begin);
148  EmitSymbolRefWithOfs(streamer, info->Function, info->End);
151  context), 4);
152 }
153 
154 static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
155  // If this UNWIND_INFO already has a symbol, it's already been emitted.
156  if (info->Symbol)
157  return;
158 
159  MCContext &context = streamer.getContext();
160  MCSymbol *Label = context.createTempSymbol();
161 
162  streamer.EmitValueToAlignment(4);
163  streamer.EmitLabel(Label);
164  info->Symbol = Label;
165 
166  // Upper 3 bits are the version number (currently 1).
167  uint8_t flags = 0x01;
168  if (info->ChainedParent)
169  flags |= Win64EH::UNW_ChainInfo << 3;
170  else {
171  if (info->HandlesUnwind)
172  flags |= Win64EH::UNW_TerminateHandler << 3;
173  if (info->HandlesExceptions)
174  flags |= Win64EH::UNW_ExceptionHandler << 3;
175  }
176  streamer.EmitIntValue(flags, 1);
177 
178  if (info->PrologEnd)
179  EmitAbsDifference(streamer, info->PrologEnd, info->Begin);
180  else
181  streamer.EmitIntValue(0, 1);
182 
183  uint8_t numCodes = CountOfUnwindCodes(info->Instructions);
184  streamer.EmitIntValue(numCodes, 1);
185 
186  uint8_t frame = 0;
187  if (info->LastFrameInst >= 0) {
188  WinEH::Instruction &frameInst = info->Instructions[info->LastFrameInst];
189  assert(frameInst.Operation == Win64EH::UOP_SetFPReg);
190  frame = (frameInst.Register & 0x0F) | (frameInst.Offset & 0xF0);
191  }
192  streamer.EmitIntValue(frame, 1);
193 
194  // Emit unwind instructions (in reverse order).
195  uint8_t numInst = info->Instructions.size();
196  for (uint8_t c = 0; c < numInst; ++c) {
197  WinEH::Instruction inst = info->Instructions.back();
198  info->Instructions.pop_back();
199  EmitUnwindCode(streamer, info->Begin, inst);
200  }
201 
202  // For alignment purposes, the instruction array will always have an even
203  // number of entries, with the final entry potentially unused (in which case
204  // the array will be one longer than indicated by the count of unwind codes
205  // field).
206  if (numCodes & 1) {
207  streamer.EmitIntValue(0, 2);
208  }
209 
210  if (flags & (Win64EH::UNW_ChainInfo << 3))
211  EmitRuntimeFunction(streamer, info->ChainedParent);
212  else if (flags &
216  context), 4);
217  else if (numCodes == 0) {
218  // The minimum size of an UNWIND_INFO struct is 8 bytes. If we're not
219  // a chained unwind info, if there is no handler, and if there are fewer
220  // than 2 slots used in the unwind code array, we have to pad to 8 bytes.
221  streamer.EmitIntValue(0, 4);
222  }
223 }
224 
226  // Emit the unwind info structs first.
227  for (const auto &CFI : Streamer.getWinFrameInfos()) {
228  MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
229  Streamer.SwitchSection(XData);
230  ::EmitUnwindInfo(Streamer, CFI.get());
231  }
232 
233  // Now emit RUNTIME_FUNCTION entries.
234  for (const auto &CFI : Streamer.getWinFrameInfos()) {
235  MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
236  Streamer.SwitchSection(PData);
237  EmitRuntimeFunction(Streamer, CFI.get());
238  }
239 }
240 
242  MCStreamer &Streamer, WinEH::FrameInfo *info) const {
243  // Switch sections (the static function above is meant to be called from
244  // here and from Emit().
245  MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
246  Streamer.SwitchSection(XData);
247 
248  ::EmitUnwindInfo(Streamer, info);
249 }
250 
251 static int64_t GetAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
252  const MCSymbol *RHS) {
253  MCContext &Context = Streamer.getContext();
254  const MCExpr *Diff =
256  MCSymbolRefExpr::create(RHS, Context), Context);
257  MCObjectStreamer *OS = (MCObjectStreamer *)(&Streamer);
258  // It should normally be possible to calculate the length of a function
259  // at this point, but it might not be possible in the presence of certain
260  // unusual constructs, like an inline asm with an alignment directive.
261  int64_t value;
262  if (!Diff->evaluateAsAbsolute(value, OS->getAssembler()))
263  report_fatal_error("Failed to evaluate function length in SEH unwind info");
264  return value;
265 }
266 
267 static uint32_t
268 ARM64CountOfUnwindCodes(const std::vector<WinEH::Instruction> &Insns) {
269  uint32_t Count = 0;
270  for (const auto &I : Insns) {
271  switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
272  default:
273  llvm_unreachable("Unsupported ARM64 unwind code");
275  Count += 1;
276  break;
278  Count += 2;
279  break;
281  Count += 4;
282  break;
284  Count += 1;
285  break;
287  Count += 1;
288  break;
290  Count += 2;
291  break;
293  Count += 2;
294  break;
296  Count += 2;
297  break;
299  Count += 2;
300  break;
302  Count += 2;
303  break;
305  Count += 2;
306  break;
308  Count += 2;
309  break;
311  Count += 2;
312  break;
313  case Win64EH::UOP_SetFP:
314  Count += 1;
315  break;
316  case Win64EH::UOP_AddFP:
317  Count += 2;
318  break;
319  case Win64EH::UOP_Nop:
320  Count += 1;
321  break;
322  case Win64EH::UOP_End:
323  Count += 1;
324  break;
325  }
326  }
327  return Count;
328 }
329 
330 // Unwind opcode encodings and restrictions are documented at
331 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
332 static void ARM64EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
333  WinEH::Instruction &inst) {
334  uint8_t b, reg;
335  switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
336  default:
337  llvm_unreachable("Unsupported ARM64 unwind code");
339  b = (inst.Offset >> 4) & 0x1F;
340  streamer.EmitIntValue(b, 1);
341  break;
343  uint16_t hw = (inst.Offset >> 4) & 0x7FF;
344  b = 0xC0;
345  b |= (hw >> 8);
346  streamer.EmitIntValue(b, 1);
347  b = hw & 0xFF;
348  streamer.EmitIntValue(b, 1);
349  break;
350  }
352  uint32_t w;
353  b = 0xE0;
354  streamer.EmitIntValue(b, 1);
355  w = inst.Offset >> 4;
356  b = (w & 0x00FF0000) >> 16;
357  streamer.EmitIntValue(b, 1);
358  b = (w & 0x0000FF00) >> 8;
359  streamer.EmitIntValue(b, 1);
360  b = w & 0x000000FF;
361  streamer.EmitIntValue(b, 1);
362  break;
363  }
364  case Win64EH::UOP_SetFP:
365  b = 0xE1;
366  streamer.EmitIntValue(b, 1);
367  break;
368  case Win64EH::UOP_AddFP:
369  b = 0xE2;
370  streamer.EmitIntValue(b, 1);
371  b = (inst.Offset >> 3);
372  streamer.EmitIntValue(b, 1);
373  break;
374  case Win64EH::UOP_Nop:
375  b = 0xE3;
376  streamer.EmitIntValue(b, 1);
377  break;
379  b = 0x80;
380  b |= ((inst.Offset - 1) >> 3) & 0x3F;
381  streamer.EmitIntValue(b, 1);
382  break;
384  b = 0x40;
385  b |= (inst.Offset >> 3) & 0x3F;
386  streamer.EmitIntValue(b, 1);
387  break;
389  assert(inst.Register >= 19 && "Saved reg must be >= 19");
390  reg = inst.Register - 19;
391  b = 0xD0 | ((reg & 0xC) >> 2);
392  streamer.EmitIntValue(b, 1);
393  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
394  streamer.EmitIntValue(b, 1);
395  break;
397  assert(inst.Register >= 19 && "Saved reg must be >= 19");
398  reg = inst.Register - 19;
399  b = 0xD4 | ((reg & 0x8) >> 3);
400  streamer.EmitIntValue(b, 1);
401  b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
402  streamer.EmitIntValue(b, 1);
403  break;
405  assert(inst.Register >= 19 && "Saved registers must be >= 19");
406  reg = inst.Register - 19;
407  b = 0xC8 | ((reg & 0xC) >> 2);
408  streamer.EmitIntValue(b, 1);
409  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
410  streamer.EmitIntValue(b, 1);
411  break;
413  assert(inst.Register >= 19 && "Saved registers must be >= 19");
414  reg = inst.Register - 19;
415  b = 0xCC | ((reg & 0xC) >> 2);
416  streamer.EmitIntValue(b, 1);
417  b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
418  streamer.EmitIntValue(b, 1);
419  break;
421  assert(inst.Register >= 8 && "Saved dreg must be >= 8");
422  reg = inst.Register - 8;
423  b = 0xDC | ((reg & 0x4) >> 2);
424  streamer.EmitIntValue(b, 1);
425  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
426  streamer.EmitIntValue(b, 1);
427  break;
429  assert(inst.Register >= 8 && "Saved dreg must be >= 8");
430  reg = inst.Register - 8;
431  b = 0xDE;
432  streamer.EmitIntValue(b, 1);
433  b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
434  streamer.EmitIntValue(b, 1);
435  break;
437  assert(inst.Register >= 8 && "Saved dregs must be >= 8");
438  reg = inst.Register - 8;
439  b = 0xD8 | ((reg & 0x4) >> 2);
440  streamer.EmitIntValue(b, 1);
441  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
442  streamer.EmitIntValue(b, 1);
443  break;
445  assert(inst.Register >= 8 && "Saved dregs must be >= 8");
446  reg = inst.Register - 8;
447  b = 0xDA | ((reg & 0x4) >> 2);
448  streamer.EmitIntValue(b, 1);
449  b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
450  streamer.EmitIntValue(b, 1);
451  break;
452  case Win64EH::UOP_End:
453  b = 0xE4;
454  streamer.EmitIntValue(b, 1);
455  break;
456  }
457 }
458 
459 // Returns the epilog symbol of an epilog with the exact same unwind code
460 // sequence, if it exists. Otherwise, returns nulltpr.
461 // EpilogInstrs - Unwind codes for the current epilog.
462 // Epilogs - Epilogs that potentialy match the current epilog.
463 static MCSymbol*
464 FindMatchingEpilog(const std::vector<WinEH::Instruction>& EpilogInstrs,
465  const std::vector<MCSymbol *>& Epilogs,
466  const WinEH::FrameInfo *info) {
467  for (auto *EpilogStart : Epilogs) {
468  auto InstrsIter = info->EpilogMap.find(EpilogStart);
469  assert(InstrsIter != info->EpilogMap.end() &&
470  "Epilog not found in EpilogMap");
471  const auto &Instrs = InstrsIter->second;
472 
473  if (Instrs.size() != EpilogInstrs.size())
474  continue;
475 
476  bool Match = true;
477  for (unsigned i = 0; i < Instrs.size(); ++i)
478  if (Instrs[i].Operation != EpilogInstrs[i].Operation ||
479  Instrs[i].Offset != EpilogInstrs[i].Offset ||
480  Instrs[i].Register != EpilogInstrs[i].Register) {
481  Match = false;
482  break;
483  }
484 
485  if (Match)
486  return EpilogStart;
487  }
488  return nullptr;
489 }
490 
491 // Populate the .xdata section. The format of .xdata on ARM64 is documented at
492 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
494  // If this UNWIND_INFO already has a symbol, it's already been emitted.
495  if (info->Symbol)
496  return;
497 
498  MCContext &context = streamer.getContext();
499  MCSymbol *Label = context.createTempSymbol();
500 
501  streamer.EmitValueToAlignment(4);
502  streamer.EmitLabel(Label);
503  info->Symbol = Label;
504 
505  int64_t RawFuncLength;
506  if (!info->FuncletOrFuncEnd) {
507  // FIXME: This is very wrong; we emit SEH data which covers zero bytes
508  // of code. But otherwise test/MC/AArch64/seh.s crashes.
509  RawFuncLength = 0;
510  } else {
511  // FIXME: GetAbsDifference tries to compute the length of the function
512  // immediately, before the whole file is emitted, but in general
513  // that's impossible: the size in bytes of certain assembler directives
514  // like .align and .fill is not known until the whole file is parsed and
515  // relaxations are applied. Currently, GetAbsDifference fails with a fatal
516  // error in that case. (We mostly don't hit this because inline assembly
517  // specifying those directives is rare, and we don't normally try to
518  // align loops on AArch64.)
519  //
520  // There are two potential approaches to delaying the computation. One,
521  // we could emit something like ".word (endfunc-beginfunc)/4+0x10800000",
522  // as long as we have some conservative estimate we could use to prove
523  // that we don't need to split the unwind data. Emitting the constant
524  // is straightforward, but there's no existing code for estimating the
525  // size of the function.
526  //
527  // The other approach would be to use a dedicated, relaxable fragment,
528  // which could grow to accommodate splitting the unwind data if
529  // necessary. This is more straightforward, since it automatically works
530  // without any new infrastructure, and it's consistent with how we handle
531  // relaxation in other contexts. But it would require some refactoring
532  // to move parts of the pdata/xdata emission into the implementation of
533  // a fragment. We could probably continue to encode the unwind codes
534  // here, but we'd have to emit the pdata, the xdata header, and the
535  // epilogue scopes later, since they depend on whether the we need to
536  // split the unwind data.
537  RawFuncLength = GetAbsDifference(streamer, info->FuncletOrFuncEnd,
538  info->Begin);
539  }
540  if (RawFuncLength > 0xFFFFF)
541  report_fatal_error("SEH unwind data splitting not yet implemented");
542  uint32_t FuncLength = (uint32_t)RawFuncLength / 4;
543  uint32_t PrologCodeBytes = ARM64CountOfUnwindCodes(info->Instructions);
544  uint32_t TotalCodeBytes = PrologCodeBytes;
545 
546  // Process epilogs.
548  // Epilogs processed so far.
549  std::vector<MCSymbol *> AddedEpilogs;
550 
551  for (auto &I : info->EpilogMap) {
552  MCSymbol *EpilogStart = I.first;
553  auto &EpilogInstrs = I.second;
554  uint32_t CodeBytes = ARM64CountOfUnwindCodes(EpilogInstrs);
555 
556  MCSymbol* MatchingEpilog =
557  FindMatchingEpilog(EpilogInstrs, AddedEpilogs, info);
558  if (MatchingEpilog) {
559  assert(EpilogInfo.find(MatchingEpilog) != EpilogInfo.end() &&
560  "Duplicate epilog not found");
561  EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
562  // Clear the unwind codes in the EpilogMap, so that they don't get output
563  // in the logic below.
564  EpilogInstrs.clear();
565  } else {
566  EpilogInfo[EpilogStart] = TotalCodeBytes;
567  TotalCodeBytes += CodeBytes;
568  AddedEpilogs.push_back(EpilogStart);
569  }
570  }
571 
572  // Code Words, Epilog count, E, X, Vers, Function Length
573  uint32_t row1 = 0x0;
574  uint32_t CodeWords = TotalCodeBytes / 4;
575  uint32_t CodeWordsMod = TotalCodeBytes % 4;
576  if (CodeWordsMod)
577  CodeWords++;
578  uint32_t EpilogCount = info->EpilogMap.size();
579  bool ExtensionWord = EpilogCount > 31 || TotalCodeBytes > 124;
580  if (!ExtensionWord) {
581  row1 |= (EpilogCount & 0x1F) << 22;
582  row1 |= (CodeWords & 0x1F) << 27;
583  }
584  // E is always 0 right now, TODO: packed epilog setup
585  if (info->HandlesExceptions) // X
586  row1 |= 1 << 20;
587  row1 |= FuncLength & 0x3FFFF;
588  streamer.EmitIntValue(row1, 4);
589 
590  // Extended Code Words, Extended Epilog Count
591  if (ExtensionWord) {
592  // FIXME: We should be able to split unwind info into multiple sections.
593  // FIXME: We should share epilog codes across epilogs, where possible,
594  // which would make this issue show up less frequently.
595  if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
596  report_fatal_error("SEH unwind data splitting not yet implemented");
597  uint32_t row2 = 0x0;
598  row2 |= (CodeWords & 0xFF) << 16;
599  row2 |= (EpilogCount & 0xFFFF);
600  streamer.EmitIntValue(row2, 4);
601  }
602 
603  // Epilog Start Index, Epilog Start Offset
604  for (auto &I : EpilogInfo) {
605  MCSymbol *EpilogStart = I.first;
606  uint32_t EpilogIndex = I.second;
607  uint32_t EpilogOffset =
608  (uint32_t)GetAbsDifference(streamer, EpilogStart, info->Begin);
609  if (EpilogOffset)
610  EpilogOffset /= 4;
611  uint32_t row3 = EpilogOffset;
612  row3 |= (EpilogIndex & 0x3FF) << 22;
613  streamer.EmitIntValue(row3, 4);
614  }
615 
616  // Emit prolog unwind instructions (in reverse order).
617  uint8_t numInst = info->Instructions.size();
618  for (uint8_t c = 0; c < numInst; ++c) {
619  WinEH::Instruction inst = info->Instructions.back();
620  info->Instructions.pop_back();
621  ARM64EmitUnwindCode(streamer, info->Begin, inst);
622  }
623 
624  // Emit epilog unwind instructions
625  for (auto &I : info->EpilogMap) {
626  auto &EpilogInstrs = I.second;
627  for (uint32_t i = 0; i < EpilogInstrs.size(); i++) {
628  WinEH::Instruction inst = EpilogInstrs[i];
629  ARM64EmitUnwindCode(streamer, info->Begin, inst);
630  }
631  }
632 
633  int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
634  assert(BytesMod >= 0);
635  for (int i = 0; i < BytesMod; i++)
636  streamer.EmitIntValue(0xE3, 1);
637 
638  if (info->HandlesExceptions)
639  streamer.EmitValue(
642  4);
643 }
644 
645 static void ARM64EmitRuntimeFunction(MCStreamer &streamer,
646  const WinEH::FrameInfo *info) {
647  MCContext &context = streamer.getContext();
648 
649  streamer.EmitValueToAlignment(4);
650  EmitSymbolRefWithOfs(streamer, info->Function, info->Begin);
653  context),
654  4);
655 }
656 
658  // Emit the unwind info structs first.
659  for (const auto &CFI : Streamer.getWinFrameInfos()) {
660  MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
661  Streamer.SwitchSection(XData);
662  ARM64EmitUnwindInfo(Streamer, CFI.get());
663  }
664 
665  // Now emit RUNTIME_FUNCTION entries.
666  for (const auto &CFI : Streamer.getWinFrameInfos()) {
667  MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
668  Streamer.SwitchSection(PData);
669  ARM64EmitRuntimeFunction(Streamer, CFI.get());
670  }
671 }
672 
674  MCStreamer &Streamer, WinEH::FrameInfo *info) const {
675  // Switch sections (the static function above is meant to be called from
676  // here and from Emit().
677  MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
678  Streamer.SwitchSection(XData);
679  ARM64EmitUnwindInfo(Streamer, info);
680 }
Instances of this class represent a uniqued identifier for a section in the current translation unit...
Definition: MCSection.h:39
LLVMContext & Context
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:224
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:329
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:139
This class represents lattice values for constants.
Definition: AllocatorList.h:23
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
static void ARM64EmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
Definition: MCWin64EH.cpp:645
const MCSymbol * End
Definition: MCWinEH.h:33
static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin, WinEH::Instruction &inst)
Definition: MCWin64EH.cpp:61
This class implements a map that also provides access to all stored values in a deterministic order...
Definition: MapVector.h:37
std::vector< Instruction > Instructions
Definition: MCWinEH.h:46
static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info)
Definition: MCWin64EH.cpp:493
MCContext & getContext() const
Definition: MCStreamer.h:258
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:169
static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
Definition: MCWin64EH.cpp:52
ArrayRef< std::unique_ptr< WinEH::FrameInfo > > getWinFrameInfos() const
Definition: MCStreamer.h:283
Context object for machine code objects.
Definition: MCContext.h:65
UNW_ChainInfo - Specifies that this UnwindInfo structure is chained to another one.
Definition: Win64EH.h:83
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:552
Streaming object file generation interface.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:467
iterator find(const KeyT &Key)
Definition: MapVector.h:147
virtual void EmitIntValue(uint64_t Value, unsigned Size)
Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers...
Definition: MCStreamer.cpp:131
void EmitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
Definition: MCStreamer.cpp:162
static uint32_t ARM64CountOfUnwindCodes(const std::vector< WinEH::Instruction > &Insns)
Definition: MCWin64EH.cpp:268
static void EmitSymbolRefWithOfs(MCStreamer &streamer, const MCSymbol *Base, const MCSymbol *Other)
Definition: MCWin64EH.cpp:129
Streaming machine code generation interface.
Definition: MCStreamer.h:196
MCSymbol * createTempSymbol(bool CanBeUnnamed=true)
Create and return a new assembler temporary symbol with a unique but unspecified name.
Definition: MCContext.cpp:225
const FrameInfo * ChainedParent
Definition: MCWinEH.h:45
UNW_TerminateHandler - Specifies that this function has a termination handler.
Definition: Win64EH.h:80
static void EmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
Definition: MCWin64EH.cpp:142
PowerPC Reduce CR logical Operation
virtual void SwitchSection(MCSection *Section, const MCExpr *Subsection=nullptr)
Set the current section where code is being emitted to Section.
MCAssembler & getAssembler()
MCSection * getAssociatedPDataSection(const MCSection *TextSec)
Get the .pdata section used for the given section.
Definition: MCStreamer.cpp:801
virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value=0, unsigned ValueSize=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI) const override
Definition: MCWin64EH.cpp:241
const MCSymbol * Symbol
Definition: MCWinEH.h:38
lazy value info
const MCSymbol * Begin
Definition: MCWinEH.h:32
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const MCSymbol * PrologEnd
Definition: MCWinEH.h:37
const MCSection * TextSection
Definition: MCWinEH.h:39
const MCSymbol * Label
Definition: MCWinEH.h:22
void Emit(MCStreamer &Streamer) const override
This emits the unwind info sections (.pdata and .xdata in PE/COFF).
Definition: MCWin64EH.cpp:657
MapVector< MCSymbol *, std::vector< Instruction > > EpilogMap
Definition: MCWinEH.h:47
const MCSymbol * Function
Definition: MCWinEH.h:36
ValueT lookup(const KeyT &Key) const
Definition: MapVector.h:110
static MCSymbol * FindMatchingEpilog(const std::vector< WinEH::Instruction > &EpilogInstrs, const std::vector< MCSymbol *> &Epilogs, const WinEH::FrameInfo *info)
Definition: MCWin64EH.cpp:464
const MCSymbol * FuncletOrFuncEnd
Definition: MCWinEH.h:34
#define I(x, y, z)
Definition: MD5.cpp:58
static uint8_t CountOfUnwindCodes(std::vector< WinEH::Instruction > &Insns)
Definition: MCWin64EH.cpp:24
iterator end()
Definition: MapVector.h:71
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static int64_t GetAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
Definition: MCWin64EH.cpp:251
UNW_ExceptionHandler - Specifies that this function has an exception handler.
Definition: Win64EH.h:77
static void ARM64EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin, WinEH::Instruction &inst)
Definition: MCWin64EH.cpp:332
void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI) const override
Definition: MCWin64EH.cpp:673
virtual void EmitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
Definition: MCStreamer.cpp:400
static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info)
Definition: MCWin64EH.cpp:154
const MCSymbol * ExceptionHandler
Definition: MCWinEH.h:35
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
void Emit(MCStreamer &Streamer) const override
This emits the unwind info sections (.pdata and .xdata in PE/COFF).
Definition: MCWin64EH.cpp:225
MCSection * getAssociatedXDataSection(const MCSection *TextSec)
Get the .xdata section used for the given section.
Definition: MCStreamer.cpp:807