LLVM  17.0.0git
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"
14 #include "llvm/MC/MCStreamer.h"
15 #include "llvm/MC/MCSymbol.h"
16 #include "llvm/Support/Win64EH.h"
17 namespace llvm {
18 class MCSection;
19 }
20 
21 using namespace llvm;
22 
23 // NOTE: All relocations generated here are 4-byte image-relative.
24 
25 static uint8_t CountOfUnwindCodes(std::vector<WinEH::Instruction> &Insns) {
26  uint8_t Count = 0;
27  for (const auto &I : Insns) {
28  switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
29  default:
30  llvm_unreachable("Unsupported unwind code");
35  Count += 1;
36  break;
39  Count += 2;
40  break;
43  Count += 3;
44  break;
46  Count += (I.Offset > 512 * 1024 - 8) ? 3 : 2;
47  break;
48  }
49  }
50  return Count;
51 }
52 
53 static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
54  const MCSymbol *RHS) {
55  MCContext &Context = Streamer.getContext();
56  const MCExpr *Diff =
59  Streamer.emitValue(Diff, 1);
60 }
61 
62 static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
63  WinEH::Instruction &inst) {
64  uint8_t b2;
65  uint16_t w;
66  b2 = (inst.Operation & 0x0F);
67  switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
68  default:
69  llvm_unreachable("Unsupported unwind code");
71  EmitAbsDifference(streamer, inst.Label, begin);
72  b2 |= (inst.Register & 0x0F) << 4;
73  streamer.emitInt8(b2);
74  break;
76  EmitAbsDifference(streamer, inst.Label, begin);
77  if (inst.Offset > 512 * 1024 - 8) {
78  b2 |= 0x10;
79  streamer.emitInt8(b2);
80  w = inst.Offset & 0xFFF8;
81  streamer.emitInt16(w);
82  w = inst.Offset >> 16;
83  } else {
84  streamer.emitInt8(b2);
85  w = inst.Offset >> 3;
86  }
87  streamer.emitInt16(w);
88  break;
90  b2 |= (((inst.Offset - 8) >> 3) & 0x0F) << 4;
91  EmitAbsDifference(streamer, inst.Label, begin);
92  streamer.emitInt8(b2);
93  break;
95  EmitAbsDifference(streamer, inst.Label, begin);
96  streamer.emitInt8(b2);
97  break;
100  b2 |= (inst.Register & 0x0F) << 4;
101  EmitAbsDifference(streamer, inst.Label, begin);
102  streamer.emitInt8(b2);
103  w = inst.Offset >> 3;
105  w >>= 1;
106  streamer.emitInt16(w);
107  break;
110  b2 |= (inst.Register & 0x0F) << 4;
111  EmitAbsDifference(streamer, inst.Label, begin);
112  streamer.emitInt8(b2);
114  w = inst.Offset & 0xFFF0;
115  else
116  w = inst.Offset & 0xFFF8;
117  streamer.emitInt16(w);
118  w = inst.Offset >> 16;
119  streamer.emitInt16(w);
120  break;
122  if (inst.Offset == 1)
123  b2 |= 0x10;
124  EmitAbsDifference(streamer, inst.Label, begin);
125  streamer.emitInt8(b2);
126  break;
127  }
128 }
129 
130 static void EmitSymbolRefWithOfs(MCStreamer &streamer,
131  const MCSymbol *Base,
132  int64_t Offset) {
133  MCContext &Context = streamer.getContext();
135  const MCSymbolRefExpr *BaseRefRel = MCSymbolRefExpr::create(Base,
137  Context);
138  streamer.emitValue(MCBinaryExpr::createAdd(BaseRefRel, OffExpr, Context), 4);
139 }
140 
141 static void EmitSymbolRefWithOfs(MCStreamer &streamer,
142  const MCSymbol *Base,
143  const MCSymbol *Other) {
144  MCContext &Context = streamer.getContext();
147  const MCExpr *Ofs = MCBinaryExpr::createSub(OtherRef, BaseRef, Context);
148  const MCSymbolRefExpr *BaseRefRel = MCSymbolRefExpr::create(Base,
150  Context);
151  streamer.emitValue(MCBinaryExpr::createAdd(BaseRefRel, Ofs, Context), 4);
152 }
153 
154 static void EmitRuntimeFunction(MCStreamer &streamer,
155  const WinEH::FrameInfo *info) {
156  MCContext &context = streamer.getContext();
157 
158  streamer.emitValueToAlignment(Align(4));
159  EmitSymbolRefWithOfs(streamer, info->Begin, info->Begin);
160  EmitSymbolRefWithOfs(streamer, info->Begin, info->End);
161  streamer.emitValue(MCSymbolRefExpr::create(info->Symbol,
163  context), 4);
164 }
165 
166 static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
167  // If this UNWIND_INFO already has a symbol, it's already been emitted.
168  if (info->Symbol)
169  return;
170 
171  MCContext &context = streamer.getContext();
172  MCSymbol *Label = context.createTempSymbol();
173 
174  streamer.emitValueToAlignment(Align(4));
175  streamer.emitLabel(Label);
176  info->Symbol = Label;
177 
178  // Upper 3 bits are the version number (currently 1).
179  uint8_t flags = 0x01;
180  if (info->ChainedParent)
181  flags |= Win64EH::UNW_ChainInfo << 3;
182  else {
183  if (info->HandlesUnwind)
184  flags |= Win64EH::UNW_TerminateHandler << 3;
185  if (info->HandlesExceptions)
186  flags |= Win64EH::UNW_ExceptionHandler << 3;
187  }
188  streamer.emitInt8(flags);
189 
190  if (info->PrologEnd)
191  EmitAbsDifference(streamer, info->PrologEnd, info->Begin);
192  else
193  streamer.emitInt8(0);
194 
195  uint8_t numCodes = CountOfUnwindCodes(info->Instructions);
196  streamer.emitInt8(numCodes);
197 
198  uint8_t frame = 0;
199  if (info->LastFrameInst >= 0) {
200  WinEH::Instruction &frameInst = info->Instructions[info->LastFrameInst];
201  assert(frameInst.Operation == Win64EH::UOP_SetFPReg);
202  frame = (frameInst.Register & 0x0F) | (frameInst.Offset & 0xF0);
203  }
204  streamer.emitInt8(frame);
205 
206  // Emit unwind instructions (in reverse order).
207  uint8_t numInst = info->Instructions.size();
208  for (uint8_t c = 0; c < numInst; ++c) {
209  WinEH::Instruction inst = info->Instructions.back();
210  info->Instructions.pop_back();
211  EmitUnwindCode(streamer, info->Begin, inst);
212  }
213 
214  // For alignment purposes, the instruction array will always have an even
215  // number of entries, with the final entry potentially unused (in which case
216  // the array will be one longer than indicated by the count of unwind codes
217  // field).
218  if (numCodes & 1) {
219  streamer.emitInt16(0);
220  }
221 
222  if (flags & (Win64EH::UNW_ChainInfo << 3))
223  EmitRuntimeFunction(streamer, info->ChainedParent);
224  else if (flags &
226  streamer.emitValue(MCSymbolRefExpr::create(info->ExceptionHandler,
228  context), 4);
229  else if (numCodes == 0) {
230  // The minimum size of an UNWIND_INFO struct is 8 bytes. If we're not
231  // a chained unwind info, if there is no handler, and if there are fewer
232  // than 2 slots used in the unwind code array, we have to pad to 8 bytes.
233  streamer.emitInt32(0);
234  }
235 }
236 
238  // Emit the unwind info structs first.
239  for (const auto &CFI : Streamer.getWinFrameInfos()) {
240  MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
241  Streamer.switchSection(XData);
242  ::EmitUnwindInfo(Streamer, CFI.get());
243  }
244 
245  // Now emit RUNTIME_FUNCTION entries.
246  for (const auto &CFI : Streamer.getWinFrameInfos()) {
247  MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
248  Streamer.switchSection(PData);
249  EmitRuntimeFunction(Streamer, CFI.get());
250  }
251 }
252 
255  bool HandlerData) const {
256  // Switch sections (the static function above is meant to be called from
257  // here and from Emit().
258  MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
259  Streamer.switchSection(XData);
260 
261  ::EmitUnwindInfo(Streamer, info);
262 }
263 
264 static const MCExpr *GetSubDivExpr(MCStreamer &Streamer, const MCSymbol *LHS,
265  const MCSymbol *RHS, int Div) {
266  MCContext &Context = Streamer.getContext();
267  const MCExpr *Expr =
270  if (Div != 1)
272  Context);
273  return Expr;
274 }
275 
276 static std::optional<int64_t> GetOptionalAbsDifference(MCStreamer &Streamer,
277  const MCSymbol *LHS,
278  const MCSymbol *RHS) {
279  MCContext &Context = Streamer.getContext();
280  const MCExpr *Diff =
283  MCObjectStreamer *OS = (MCObjectStreamer *)(&Streamer);
284  // It should normally be possible to calculate the length of a function
285  // at this point, but it might not be possible in the presence of certain
286  // unusual constructs, like an inline asm with an alignment directive.
287  int64_t value;
288  if (!Diff->evaluateAsAbsolute(value, OS->getAssembler()))
289  return std::nullopt;
290  return value;
291 }
292 
293 static int64_t GetAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
294  const MCSymbol *RHS) {
295  std::optional<int64_t> MaybeDiff =
296  GetOptionalAbsDifference(Streamer, LHS, RHS);
297  if (!MaybeDiff)
298  report_fatal_error("Failed to evaluate function length in SEH unwind info");
299  return *MaybeDiff;
300 }
301 
302 static void checkARM64Instructions(MCStreamer &Streamer,
304  const MCSymbol *Begin, const MCSymbol *End,
306  if (!End)
307  return;
308  std::optional<int64_t> MaybeDistance =
309  GetOptionalAbsDifference(Streamer, End, Begin);
310  if (!MaybeDistance)
311  return;
312  uint32_t Distance = (uint32_t)*MaybeDistance;
313 
314  for (const auto &I : Insns) {
315  switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
316  default:
317  break;
322  // Can't reason about these opcodes and how they map to actual
323  // instructions.
324  return;
325  }
326  }
327  // Exclude the end opcode which doesn't map to an instruction.
328  uint32_t InstructionBytes = 4 * (Insns.size() - 1);
329  if (Distance != InstructionBytes) {
330  Streamer.getContext().reportError(
331  SMLoc(), "Incorrect size for " + Name + " " + Type + ": " +
332  Twine(Distance) +
333  " bytes of instructions in range, but .seh directives "
334  "corresponding to " +
335  Twine(InstructionBytes) + " bytes\n");
336  }
337 }
338 
340  uint32_t Count = 0;
341  for (const auto &I : Insns) {
342  switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
343  default:
344  llvm_unreachable("Unsupported ARM64 unwind code");
346  Count += 1;
347  break;
349  Count += 2;
350  break;
352  Count += 4;
353  break;
355  Count += 1;
356  break;
358  Count += 1;
359  break;
361  Count += 1;
362  break;
364  Count += 2;
365  break;
367  Count += 2;
368  break;
370  Count += 2;
371  break;
373  Count += 2;
374  break;
376  Count += 2;
377  break;
379  Count += 2;
380  break;
382  Count += 2;
383  break;
385  Count += 2;
386  break;
388  Count += 2;
389  break;
390  case Win64EH::UOP_SetFP:
391  Count += 1;
392  break;
393  case Win64EH::UOP_AddFP:
394  Count += 2;
395  break;
396  case Win64EH::UOP_Nop:
397  Count += 1;
398  break;
399  case Win64EH::UOP_End:
400  Count += 1;
401  break;
403  Count += 1;
404  break;
406  Count += 1;
407  break;
409  Count += 1;
410  break;
412  Count += 1;
413  break;
415  Count += 1;
416  break;
418  Count += 1;
419  break;
432  Count += 3;
433  break;
434  }
435  }
436  return Count;
437 }
438 
439 // Unwind opcode encodings and restrictions are documented at
440 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
441 static void ARM64EmitUnwindCode(MCStreamer &streamer,
442  const WinEH::Instruction &inst) {
443  uint8_t b, reg;
444  switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
445  default:
446  llvm_unreachable("Unsupported ARM64 unwind code");
448  b = (inst.Offset >> 4) & 0x1F;
449  streamer.emitInt8(b);
450  break;
452  uint16_t hw = (inst.Offset >> 4) & 0x7FF;
453  b = 0xC0;
454  b |= (hw >> 8);
455  streamer.emitInt8(b);
456  b = hw & 0xFF;
457  streamer.emitInt8(b);
458  break;
459  }
461  uint32_t w;
462  b = 0xE0;
463  streamer.emitInt8(b);
464  w = inst.Offset >> 4;
465  b = (w & 0x00FF0000) >> 16;
466  streamer.emitInt8(b);
467  b = (w & 0x0000FF00) >> 8;
468  streamer.emitInt8(b);
469  b = w & 0x000000FF;
470  streamer.emitInt8(b);
471  break;
472  }
473  case Win64EH::UOP_SetFP:
474  b = 0xE1;
475  streamer.emitInt8(b);
476  break;
477  case Win64EH::UOP_AddFP:
478  b = 0xE2;
479  streamer.emitInt8(b);
480  b = (inst.Offset >> 3);
481  streamer.emitInt8(b);
482  break;
483  case Win64EH::UOP_Nop:
484  b = 0xE3;
485  streamer.emitInt8(b);
486  break;
488  b = 0x20;
489  b |= (inst.Offset >> 3) & 0x1F;
490  streamer.emitInt8(b);
491  break;
493  b = 0x80;
494  b |= ((inst.Offset - 1) >> 3) & 0x3F;
495  streamer.emitInt8(b);
496  break;
498  b = 0x40;
499  b |= (inst.Offset >> 3) & 0x3F;
500  streamer.emitInt8(b);
501  break;
503  assert(inst.Register >= 19 && "Saved reg must be >= 19");
504  reg = inst.Register - 19;
505  b = 0xD0 | ((reg & 0xC) >> 2);
506  streamer.emitInt8(b);
507  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
508  streamer.emitInt8(b);
509  break;
511  assert(inst.Register >= 19 && "Saved reg must be >= 19");
512  reg = inst.Register - 19;
513  b = 0xD4 | ((reg & 0x8) >> 3);
514  streamer.emitInt8(b);
515  b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
516  streamer.emitInt8(b);
517  break;
519  assert(inst.Register >= 19 && "Saved registers must be >= 19");
520  reg = inst.Register - 19;
521  b = 0xC8 | ((reg & 0xC) >> 2);
522  streamer.emitInt8(b);
523  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
524  streamer.emitInt8(b);
525  break;
527  assert(inst.Register >= 19 && "Saved registers must be >= 19");
528  reg = inst.Register - 19;
529  b = 0xCC | ((reg & 0xC) >> 2);
530  streamer.emitInt8(b);
531  b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
532  streamer.emitInt8(b);
533  break;
535  assert(inst.Register >= 19 && "Saved reg must be >= 19");
536  reg = inst.Register - 19;
537  assert((reg % 2) == 0 && "Saved reg must be 19+2*X");
538  reg /= 2;
539  b = 0xD6 | ((reg & 0x7) >> 2);
540  streamer.emitInt8(b);
541  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
542  streamer.emitInt8(b);
543  break;
545  assert(inst.Register >= 8 && "Saved dreg must be >= 8");
546  reg = inst.Register - 8;
547  b = 0xDC | ((reg & 0x4) >> 2);
548  streamer.emitInt8(b);
549  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
550  streamer.emitInt8(b);
551  break;
553  assert(inst.Register >= 8 && "Saved dreg must be >= 8");
554  reg = inst.Register - 8;
555  b = 0xDE;
556  streamer.emitInt8(b);
557  b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
558  streamer.emitInt8(b);
559  break;
561  assert(inst.Register >= 8 && "Saved dregs must be >= 8");
562  reg = inst.Register - 8;
563  b = 0xD8 | ((reg & 0x4) >> 2);
564  streamer.emitInt8(b);
565  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
566  streamer.emitInt8(b);
567  break;
569  assert(inst.Register >= 8 && "Saved dregs must be >= 8");
570  reg = inst.Register - 8;
571  b = 0xDA | ((reg & 0x4) >> 2);
572  streamer.emitInt8(b);
573  b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
574  streamer.emitInt8(b);
575  break;
576  case Win64EH::UOP_End:
577  b = 0xE4;
578  streamer.emitInt8(b);
579  break;
581  b = 0xE6;
582  streamer.emitInt8(b);
583  break;
585  b = 0xE8;
586  streamer.emitInt8(b);
587  break;
589  b = 0xE9;
590  streamer.emitInt8(b);
591  break;
593  b = 0xEA;
594  streamer.emitInt8(b);
595  break;
597  b = 0xEC;
598  streamer.emitInt8(b);
599  break;
601  b = 0xFC;
602  streamer.emitInt8(b);
603  break;
616  // This assumes the opcodes are listed in the enum in a particular order.
618  int Writeback = Op / 6;
619  int Paired = Op % 2;
620  int Mode = (Op / 2) % 3;
621  int Offset = inst.Offset >> 3;
622  if (Writeback || Paired || Mode == 2)
623  Offset >>= 1;
624  if (Writeback)
625  --Offset;
626  b = 0xE7;
627  streamer.emitInt8(b);
628  assert(inst.Register < 32);
629  b = inst.Register | (Writeback << 5) | (Paired << 6);
630  streamer.emitInt8(b);
631  b = Offset | (Mode << 6);
632  streamer.emitInt8(b);
633  break;
634  }
635  }
636 }
637 
638 // Returns the epilog symbol of an epilog with the exact same unwind code
639 // sequence, if it exists. Otherwise, returns nullptr.
640 // EpilogInstrs - Unwind codes for the current epilog.
641 // Epilogs - Epilogs that potentialy match the current epilog.
642 static MCSymbol*
643 FindMatchingEpilog(const std::vector<WinEH::Instruction>& EpilogInstrs,
644  const std::vector<MCSymbol *>& Epilogs,
645  const WinEH::FrameInfo *info) {
646  for (auto *EpilogStart : Epilogs) {
647  auto InstrsIter = info->EpilogMap.find(EpilogStart);
648  assert(InstrsIter != info->EpilogMap.end() &&
649  "Epilog not found in EpilogMap");
650  const auto &Instrs = InstrsIter->second.Instructions;
651 
652  if (Instrs.size() != EpilogInstrs.size())
653  continue;
654 
655  bool Match = true;
656  for (unsigned i = 0; i < Instrs.size(); ++i)
657  if (Instrs[i] != EpilogInstrs[i]) {
658  Match = false;
659  break;
660  }
661 
662  if (Match)
663  return EpilogStart;
664  }
665  return nullptr;
666 }
667 
668 static void simplifyARM64Opcodes(std::vector<WinEH::Instruction> &Instructions,
669  bool Reverse) {
670  unsigned PrevOffset = -1;
671  unsigned PrevRegister = -1;
672 
673  auto VisitInstruction = [&](WinEH::Instruction &Inst) {
674  // Convert 2-byte opcodes into equivalent 1-byte ones.
675  if (Inst.Operation == Win64EH::UOP_SaveRegP && Inst.Register == 29) {
676  Inst.Operation = Win64EH::UOP_SaveFPLR;
677  Inst.Register = -1;
678  } else if (Inst.Operation == Win64EH::UOP_SaveRegPX &&
679  Inst.Register == 29) {
680  Inst.Operation = Win64EH::UOP_SaveFPLRX;
681  Inst.Register = -1;
682  } else if (Inst.Operation == Win64EH::UOP_SaveRegPX &&
683  Inst.Register == 19 && Inst.Offset <= 248) {
684  Inst.Operation = Win64EH::UOP_SaveR19R20X;
685  Inst.Register = -1;
686  } else if (Inst.Operation == Win64EH::UOP_AddFP && Inst.Offset == 0) {
687  Inst.Operation = Win64EH::UOP_SetFP;
688  } else if (Inst.Operation == Win64EH::UOP_SaveRegP &&
689  Inst.Register == PrevRegister + 2 &&
690  Inst.Offset == PrevOffset + 16) {
691  Inst.Operation = Win64EH::UOP_SaveNext;
692  Inst.Register = -1;
693  Inst.Offset = 0;
694  // Intentionally not creating UOP_SaveNext for float register pairs,
695  // as current versions of Windows (up to at least 20.04) is buggy
696  // regarding SaveNext for float pairs.
697  }
698  // Update info about the previous instruction, for detecting if
699  // the next one can be made a UOP_SaveNext
700  if (Inst.Operation == Win64EH::UOP_SaveR19R20X) {
701  PrevOffset = 0;
702  PrevRegister = 19;
703  } else if (Inst.Operation == Win64EH::UOP_SaveRegPX) {
704  PrevOffset = 0;
705  PrevRegister = Inst.Register;
706  } else if (Inst.Operation == Win64EH::UOP_SaveRegP) {
707  PrevOffset = Inst.Offset;
708  PrevRegister = Inst.Register;
709  } else if (Inst.Operation == Win64EH::UOP_SaveNext) {
710  PrevRegister += 2;
711  PrevOffset += 16;
712  } else {
713  PrevRegister = -1;
714  PrevOffset = -1;
715  }
716  };
717 
718  // Iterate over instructions in a forward order (for prologues),
719  // backwards for epilogues (i.e. always reverse compared to how the
720  // opcodes are stored).
721  if (Reverse) {
722  for (auto It = Instructions.rbegin(); It != Instructions.rend(); It++)
723  VisitInstruction(*It);
724  } else {
725  for (WinEH::Instruction &Inst : Instructions)
726  VisitInstruction(Inst);
727  }
728 }
729 
730 // Check if an epilog exists as a subset of the end of a prolog (backwards).
731 static int
732 getARM64OffsetInProlog(const std::vector<WinEH::Instruction> &Prolog,
733  const std::vector<WinEH::Instruction> &Epilog) {
734  // Can't find an epilog as a subset if it is longer than the prolog.
735  if (Epilog.size() > Prolog.size())
736  return -1;
737 
738  // Check that the epilog actually is a perfect match for the end (backwrds)
739  // of the prolog.
740  for (int I = Epilog.size() - 1; I >= 0; I--) {
741  if (Prolog[I] != Epilog[Epilog.size() - 1 - I])
742  return -1;
743  }
744 
745  if (Epilog.size() == Prolog.size())
746  return 0;
747 
748  // If the epilog was a subset of the prolog, find its offset.
750  &Prolog[Epilog.size()], Prolog.size() - Epilog.size()));
751 }
752 
755  int PrologCodeBytes) {
756  // Can only pack if there's one single epilog
757  if (Seg->Epilogs.size() != 1)
758  return -1;
759 
760  MCSymbol *Sym = Seg->Epilogs.begin()->first;
761  const std::vector<WinEH::Instruction> &Epilog =
762  info->EpilogMap[Sym].Instructions;
763 
764  // Check that the epilog actually is at the very end of the function,
765  // otherwise it can't be packed.
766  uint32_t DistanceFromEnd =
767  (uint32_t)(Seg->Offset + Seg->Length - Seg->Epilogs.begin()->second);
768  if (DistanceFromEnd / 4 != Epilog.size())
769  return -1;
770 
771  int RetVal = -1;
772  // Even if we don't end up sharing opcodes with the prolog, we can still
773  // write the offset as a packed offset, if the single epilog is located at
774  // the end of the function and the offset (pointing after the prolog) fits
775  // as a packed offset.
776  if (PrologCodeBytes <= 31 &&
777  PrologCodeBytes + ARM64CountOfUnwindCodes(Epilog) <= 124)
778  RetVal = PrologCodeBytes;
779 
780  int Offset = getARM64OffsetInProlog(info->Instructions, Epilog);
781  if (Offset < 0)
782  return RetVal;
783 
784  // Check that the offset and prolog size fits in the first word; it's
785  // unclear whether the epilog count in the extension word can be taken
786  // as packed epilog offset.
787  if (Offset > 31 || PrologCodeBytes > 124)
788  return RetVal;
789 
790  // As we choose to express the epilog as part of the prolog, remove the
791  // epilog from the map, so we don't try to emit its opcodes.
792  info->EpilogMap.erase(Sym);
793  return Offset;
794 }
795 
797  int PackedEpilogOffset) {
798  if (PackedEpilogOffset == 0) {
799  // Fully symmetric prolog and epilog, should be ok for packed format.
800  // For CR=3, the corresponding synthesized epilog actually lacks the
801  // SetFP opcode, but unwinding should work just fine despite that
802  // (if at the SetFP opcode, the unwinder considers it as part of the
803  // function body and just unwinds the full prolog instead).
804  } else if (PackedEpilogOffset == 1) {
805  // One single case of differences between prolog and epilog is allowed:
806  // The epilog can lack a single SetFP that is the last opcode in the
807  // prolog, for the CR=3 case.
808  if (info->Instructions.back().Operation != Win64EH::UOP_SetFP)
809  return false;
810  } else {
811  // Too much difference between prolog and epilog.
812  return false;
813  }
814  unsigned RegI = 0, RegF = 0;
815  int Predecrement = 0;
816  enum {
817  Start,
818  Start2,
819  Start3,
820  IntRegs,
821  FloatRegs,
822  InputArgs,
823  StackAdjust,
824  FrameRecord,
825  End
826  } Location = Start;
827  bool StandaloneLR = false, FPLRPair = false;
828  bool PAC = false;
829  int StackOffset = 0;
830  int Nops = 0;
831  // Iterate over the prolog and check that all opcodes exactly match
832  // the canonical order and form. A more lax check could verify that
833  // all saved registers are in the expected locations, but not enforce
834  // the order - that would work fine when unwinding from within
835  // functions, but not be exactly right if unwinding happens within
836  // prologs/epilogs.
837  for (const WinEH::Instruction &Inst : info->Instructions) {
838  switch (Inst.Operation) {
839  case Win64EH::UOP_End:
840  if (Location != Start)
841  return false;
842  Location = Start2;
843  break;
845  if (Location != Start2)
846  return false;
847  PAC = true;
848  Location = Start3;
849  break;
851  if (Location != Start2 && Location != Start3)
852  return false;
853  Predecrement = Inst.Offset;
854  RegI = 2;
855  Location = IntRegs;
856  break;
858  if (Location != Start2 && Location != Start3)
859  return false;
860  Predecrement = Inst.Offset;
861  if (Inst.Register == 19)
862  RegI += 1;
863  else if (Inst.Register == 30)
864  StandaloneLR = true;
865  else
866  return false;
867  // Odd register; can't be any further int registers.
868  Location = FloatRegs;
869  break;
871  // Can't have this in a canonical prologue. Either this has been
872  // canonicalized into SaveR19R20X or SaveFPLRX, or it's an unsupported
873  // register pair.
874  // It can't be canonicalized into SaveR19R20X if the offset is
875  // larger than 248 bytes, but even with the maximum case with
876  // RegI=10/RegF=8/CR=1/H=1, we end up with SavSZ = 216, which should
877  // fit into SaveR19R20X.
878  // The unwinding opcodes can't describe the otherwise seemingly valid
879  // case for RegI=1 CR=1, that would start with a
880  // "stp x19, lr, [sp, #-...]!" as that fits neither SaveRegPX nor
881  // SaveLRPair.
882  return false;
884  if (Location != IntRegs || Inst.Offset != 8 * RegI ||
885  Inst.Register != 19 + RegI)
886  return false;
887  RegI += 2;
888  break;
890  if (Location != IntRegs || Inst.Offset != 8 * RegI)
891  return false;
892  if (Inst.Register == 19 + RegI)
893  RegI += 1;
894  else if (Inst.Register == 30)
895  StandaloneLR = true;
896  else
897  return false;
898  // Odd register; can't be any further int registers.
899  Location = FloatRegs;
900  break;
902  if (Location != IntRegs || Inst.Offset != 8 * RegI ||
903  Inst.Register != 19 + RegI)
904  return false;
905  RegI += 1;
906  StandaloneLR = true;
907  Location = FloatRegs;
908  break;
910  // Packed unwind can't handle prologs that only save one single
911  // float register.
912  return false;
914  if (Location != FloatRegs || RegF == 0 || Inst.Register != 8 + RegF ||
915  Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
916  return false;
917  RegF += 1;
918  Location = InputArgs;
919  break;
921  if ((Location != Start2 && Location != Start3) || Inst.Register != 8)
922  return false;
923  Predecrement = Inst.Offset;
924  RegF = 2;
925  Location = FloatRegs;
926  break;
928  if ((Location != IntRegs && Location != FloatRegs) ||
929  Inst.Register != 8 + RegF ||
930  Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
931  return false;
932  RegF += 2;
933  Location = FloatRegs;
934  break;
936  if (Location == IntRegs)
937  RegI += 2;
938  else if (Location == FloatRegs)
939  RegF += 2;
940  else
941  return false;
942  break;
943  case Win64EH::UOP_Nop:
944  if (Location != IntRegs && Location != FloatRegs && Location != InputArgs)
945  return false;
946  Location = InputArgs;
947  Nops++;
948  break;
951  if (Location != Start2 && Location != Start3 && Location != IntRegs &&
952  Location != FloatRegs && Location != InputArgs &&
953  Location != StackAdjust)
954  return false;
955  // Can have either a single decrement, or a pair of decrements with
956  // 4080 and another decrement.
957  if (StackOffset == 0)
958  StackOffset = Inst.Offset;
959  else if (StackOffset != 4080)
960  return false;
961  else
962  StackOffset += Inst.Offset;
963  Location = StackAdjust;
964  break;
966  // Not allowing FPLRX after StackAdjust; if a StackAdjust is used, it
967  // should be followed by a FPLR instead.
968  if (Location != Start2 && Location != Start3 && Location != IntRegs &&
969  Location != FloatRegs && Location != InputArgs)
970  return false;
971  StackOffset = Inst.Offset;
972  Location = FrameRecord;
973  FPLRPair = true;
974  break;
976  // This can only follow after a StackAdjust
977  if (Location != StackAdjust || Inst.Offset != 0)
978  return false;
979  Location = FrameRecord;
980  FPLRPair = true;
981  break;
982  case Win64EH::UOP_SetFP:
983  if (Location != FrameRecord)
984  return false;
985  Location = End;
986  break;
999  // These are never canonical; they don't show up with the usual Arm64
1000  // calling convention.
1001  return false;
1003  // Allocations this large can't be represented in packed unwind (and
1004  // usually don't fit the canonical form anyway because we need to use
1005  // __chkstk to allocate the stack space).
1006  return false;
1007  case Win64EH::UOP_AddFP:
1008  // "add x29, sp, #N" doesn't show up in the canonical pattern (except for
1009  // N=0, which is UOP_SetFP).
1010  return false;
1012  case Win64EH::UOP_Context:
1015  // These are special opcodes that aren't normally generated.
1016  return false;
1017  default:
1018  report_fatal_error("Unknown Arm64 unwind opcode");
1019  }
1020  }
1021  if (RegI > 10 || RegF > 8)
1022  return false;
1023  if (StandaloneLR && FPLRPair)
1024  return false;
1025  if (FPLRPair && Location != End)
1026  return false;
1027  if (Nops != 0 && Nops != 4)
1028  return false;
1029  if (PAC && !FPLRPair)
1030  return false;
1031  int H = Nops == 4;
1032  // There's an inconsistency regarding packed unwind info with homed
1033  // parameters; according to the documentation, the epilog shouldn't have
1034  // the same corresponding nops (and thus, to set the H bit, we should
1035  // require an epilog which isn't exactly symmetrical - we shouldn't accept
1036  // an exact mirrored epilog for those cases), but in practice,
1037  // RtlVirtualUnwind behaves as if it does expect the epilogue to contain
1038  // the same nops. See https://github.com/llvm/llvm-project/issues/54879.
1039  // To play it safe, don't produce packed unwind info with homed parameters.
1040  if (H)
1041  return false;
1042  int IntSZ = 8 * RegI;
1043  if (StandaloneLR)
1044  IntSZ += 8;
1045  int FpSZ = 8 * RegF; // RegF not yet decremented
1046  int SavSZ = (IntSZ + FpSZ + 8 * 8 * H + 0xF) & ~0xF;
1047  if (Predecrement != SavSZ)
1048  return false;
1049  if (FPLRPair && StackOffset < 16)
1050  return false;
1051  if (StackOffset % 16)
1052  return false;
1053  uint32_t FrameSize = (StackOffset + SavSZ) / 16;
1054  if (FrameSize > 0x1FF)
1055  return false;
1056  assert(RegF != 1 && "One single float reg not allowed");
1057  if (RegF > 0)
1058  RegF--; // Convert from actual number of registers, to value stored
1059  assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");
1060  int Flag = 0x01; // Function segments not supported yet
1061  int CR = PAC ? 2 : FPLRPair ? 3 : StandaloneLR ? 1 : 0;
1062  info->PackedInfo |= Flag << 0;
1063  info->PackedInfo |= (FuncLength & 0x7FF) << 2;
1064  info->PackedInfo |= (RegF & 0x7) << 13;
1065  info->PackedInfo |= (RegI & 0xF) << 16;
1066  info->PackedInfo |= (H & 0x1) << 20;
1067  info->PackedInfo |= (CR & 0x3) << 21;
1068  info->PackedInfo |= (FrameSize & 0x1FF) << 23;
1069  return true;
1070 }
1071 
1074  uint32_t &TotalCodeBytes,
1075  MapVector<MCSymbol *, uint32_t> &EpilogInfo) {
1076 
1077  std::vector<MCSymbol *> EpilogStarts;
1078  for (auto &I : Seg->Epilogs)
1079  EpilogStarts.push_back(I.first);
1080 
1081  // Epilogs processed so far.
1082  std::vector<MCSymbol *> AddedEpilogs;
1083  for (auto *S : EpilogStarts) {
1084  MCSymbol *EpilogStart = S;
1085  auto &EpilogInstrs = info->EpilogMap[S].Instructions;
1086  uint32_t CodeBytes = ARM64CountOfUnwindCodes(EpilogInstrs);
1087 
1088  MCSymbol* MatchingEpilog =
1089  FindMatchingEpilog(EpilogInstrs, AddedEpilogs, info);
1090  int PrologOffset;
1091  if (MatchingEpilog) {
1092  assert(EpilogInfo.find(MatchingEpilog) != EpilogInfo.end() &&
1093  "Duplicate epilog not found");
1094  EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
1095  // Clear the unwind codes in the EpilogMap, so that they don't get output
1096  // in ARM64EmitUnwindInfoForSegment().
1097  EpilogInstrs.clear();
1098  } else if ((PrologOffset = getARM64OffsetInProlog(info->Instructions,
1099  EpilogInstrs)) >= 0) {
1100  EpilogInfo[EpilogStart] = PrologOffset;
1101  // If the segment doesn't have a prolog, an end_c will be emitted before
1102  // prolog opcodes. So epilog start index in opcodes array is moved by 1.
1103  if (!Seg->HasProlog)
1104  EpilogInfo[EpilogStart] += 1;
1105  // Clear the unwind codes in the EpilogMap, so that they don't get output
1106  // in ARM64EmitUnwindInfoForSegment().
1107  EpilogInstrs.clear();
1108  } else {
1109  EpilogInfo[EpilogStart] = TotalCodeBytes;
1110  TotalCodeBytes += CodeBytes;
1111  AddedEpilogs.push_back(EpilogStart);
1112  }
1113  }
1114 }
1115 
1118  int64_t RawFuncLength) {
1119  if (info->PrologEnd)
1120  checkARM64Instructions(streamer, info->Instructions, info->Begin,
1121  info->PrologEnd, info->Function->getName(),
1122  "prologue");
1123  struct EpilogStartEnd {
1124  MCSymbol *Start;
1125  int64_t Offset;
1126  int64_t End;
1127  };
1128  // Record Start and End of each epilog.
1130  for (auto &I : info->EpilogMap) {
1131  MCSymbol *Start = I.first;
1132  auto &Instrs = I.second.Instructions;
1133  int64_t Offset = GetAbsDifference(streamer, Start, info->Begin);
1134  checkARM64Instructions(streamer, Instrs, Start, I.second.End,
1135  info->Function->getName(), "epilogue");
1136  assert((Epilogs.size() == 0 || Offset >= Epilogs.back().End) &&
1137  "Epilogs should be monotonically ordered");
1138  // Exclue the end opcode from Instrs.size() when calculating the end of the
1139  // epilog.
1140  Epilogs.push_back({Start, Offset, Offset + (int64_t)(Instrs.size() - 1) * 4});
1141  }
1142 
1143  unsigned E = 0;
1144  int64_t SegLimit = 0xFFFFC;
1145  int64_t SegOffset = 0;
1146 
1147  if (RawFuncLength > SegLimit) {
1148 
1149  int64_t RemainingLength = RawFuncLength;
1150 
1151  while (RemainingLength > SegLimit) {
1152  // Try divide the function into segments, requirements:
1153  // 1. Segment length <= 0xFFFFC;
1154  // 2. Each Prologue or Epilogue must be fully within a segment.
1155  int64_t SegLength = SegLimit;
1156  int64_t SegEnd = SegOffset + SegLength;
1157  // Keep record on symbols and offsets of epilogs in this segment.
1158  MapVector<MCSymbol *, int64_t> EpilogsInSegment;
1159 
1160  while (E < Epilogs.size() && Epilogs[E].End < SegEnd) {
1161  // Epilogs within current segment.
1162  EpilogsInSegment[Epilogs[E].Start] = Epilogs[E].Offset;
1163  ++E;
1164  }
1165 
1166  // At this point, we have:
1167  // 1. Put all epilogs in segments already. No action needed here; or
1168  // 2. Found an epilog that will cross segments boundry. We need to
1169  // move back current segment's end boundry, so the epilog is entirely
1170  // in the next segment; or
1171  // 3. Left at least one epilog that is entirely after this segment.
1172  // It'll be handled by the next iteration, or the last segment.
1173  if (E < Epilogs.size() && Epilogs[E].Offset <= SegEnd)
1174  // Move back current Segment's end boundry.
1175  SegLength = Epilogs[E].Offset - SegOffset;
1176 
1177  auto Seg = WinEH::FrameInfo::Segment(
1178  SegOffset, SegLength, /* HasProlog */!SegOffset);
1179  Seg.Epilogs = std::move(EpilogsInSegment);
1180  info->Segments.push_back(Seg);
1181 
1182  SegOffset += SegLength;
1183  RemainingLength -= SegLength;
1184  }
1185  }
1186 
1187  // Add the last segment when RawFuncLength > 0xFFFFC,
1188  // or the only segment otherwise.
1189  auto LastSeg =
1190  WinEH::FrameInfo::Segment(SegOffset, RawFuncLength - SegOffset,
1191  /* HasProlog */!SegOffset);
1192  for (; E < Epilogs.size(); ++E)
1193  LastSeg.Epilogs[Epilogs[E].Start] = Epilogs[E].Offset;
1194  info->Segments.push_back(LastSeg);
1195 }
1196 
1200  bool TryPacked = true) {
1201  MCContext &context = streamer.getContext();
1202  MCSymbol *Label = context.createTempSymbol();
1203 
1204  streamer.emitValueToAlignment(Align(4));
1205  streamer.emitLabel(Label);
1206  Seg.Symbol = Label;
1207  // Use the 1st segemnt's label as function's.
1208  if (Seg.Offset == 0)
1209  info->Symbol = Label;
1210 
1211  bool HasProlog = Seg.HasProlog;
1212  bool HasEpilogs = (Seg.Epilogs.size() != 0);
1213 
1214  uint32_t SegLength = (uint32_t)Seg.Length / 4;
1215  uint32_t PrologCodeBytes = info->PrologCodeBytes;
1216 
1217  int PackedEpilogOffset = HasEpilogs ?
1218  checkARM64PackedEpilog(streamer, info, &Seg, PrologCodeBytes) : -1;
1219 
1220  // TODO:
1221  // 1. Enable packed unwind info (.pdata only) for multi-segment functions.
1222  // 2. Emit packed unwind info (.pdata only) for segments that have neithor
1223  // prolog nor epilog.
1224  if (info->Segments.size() == 1 && PackedEpilogOffset >= 0 &&
1225  uint32_t(PackedEpilogOffset) < PrologCodeBytes &&
1226  !info->HandlesExceptions && SegLength <= 0x7ff && TryPacked) {
1227  // Matching prolog/epilog and no exception handlers; check if the
1228  // prolog matches the patterns that can be described by the packed
1229  // format.
1230 
1231  // info->Symbol was already set even if we didn't actually write any
1232  // unwind info there. Keep using that as indicator that this unwind
1233  // info has been generated already.
1234  if (tryARM64PackedUnwind(info, SegLength, PackedEpilogOffset))
1235  return;
1236  }
1237 
1238  // If the prolog is not in this segment, we need to emit an end_c, which takes
1239  // 1 byte, before prolog unwind ops.
1240  if (!HasProlog) {
1241  PrologCodeBytes += 1;
1242  if (PackedEpilogOffset >= 0)
1243  PackedEpilogOffset += 1;
1244  // If a segment has neither prolog nor epilog, "With full .xdata record,
1245  // Epilog Count = 1. Epilog Start Index points to end_c."
1246  // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling#function-fragments
1247  // TODO: We can remove this if testing shows zero epilog scope is ok with
1248  // MS unwinder.
1249  if (!HasEpilogs)
1250  // Pack the fake epilog into phantom prolog.
1251  PackedEpilogOffset = 0;
1252  }
1253 
1254  uint32_t TotalCodeBytes = PrologCodeBytes;
1255 
1256  // Process epilogs.
1258  ARM64ProcessEpilogs(info, &Seg, TotalCodeBytes, EpilogInfo);
1259 
1260  // Code Words, Epilog count, E, X, Vers, Function Length
1261  uint32_t row1 = 0x0;
1262  uint32_t CodeWords = TotalCodeBytes / 4;
1263  uint32_t CodeWordsMod = TotalCodeBytes % 4;
1264  if (CodeWordsMod)
1265  CodeWords++;
1266  uint32_t EpilogCount =
1267  PackedEpilogOffset >= 0 ? PackedEpilogOffset : Seg.Epilogs.size();
1268  bool ExtensionWord = EpilogCount > 31 || TotalCodeBytes > 124;
1269  if (!ExtensionWord) {
1270  row1 |= (EpilogCount & 0x1F) << 22;
1271  row1 |= (CodeWords & 0x1F) << 27;
1272  }
1273  if (info->HandlesExceptions) // X
1274  row1 |= 1 << 20;
1275  if (PackedEpilogOffset >= 0) // E
1276  row1 |= 1 << 21;
1277  row1 |= SegLength & 0x3FFFF;
1278  streamer.emitInt32(row1);
1279 
1280  // Extended Code Words, Extended Epilog Count
1281  if (ExtensionWord) {
1282  // FIXME: We should be able to split unwind info into multiple sections.
1283  if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
1285  "SEH unwind data splitting is only implemented for large functions, "
1286  "cases of too many code words or too many epilogs will be done "
1287  "later");
1288  uint32_t row2 = 0x0;
1289  row2 |= (CodeWords & 0xFF) << 16;
1290  row2 |= (EpilogCount & 0xFFFF);
1291  streamer.emitInt32(row2);
1292  }
1293 
1294  if (PackedEpilogOffset < 0) {
1295  // Epilog Start Index, Epilog Start Offset
1296  for (auto &I : EpilogInfo) {
1297  MCSymbol *EpilogStart = I.first;
1298  uint32_t EpilogIndex = I.second;
1299  // Epilog offset within the Segment.
1300  uint32_t EpilogOffset = (uint32_t)(Seg.Epilogs[EpilogStart] - Seg.Offset);
1301  if (EpilogOffset)
1302  EpilogOffset /= 4;
1303  uint32_t row3 = EpilogOffset;
1304  row3 |= (EpilogIndex & 0x3FF) << 22;
1305  streamer.emitInt32(row3);
1306  }
1307  }
1308 
1309  // Note that even for segments that have no prolog, we still need to emit
1310  // prolog unwinding opcodes so that the unwinder knows how to unwind from
1311  // such a segment.
1312  // The end_c opcode at the start indicates to the unwinder that the actual
1313  // prolog is outside of the current segment, and the unwinder shouldn't try
1314  // to check for unwinding from a partial prolog.
1315  if (!HasProlog)
1316  // Emit an end_c.
1317  streamer.emitInt8((uint8_t)0xE5);
1318 
1319  // Emit prolog unwind instructions (in reverse order).
1320  for (auto Inst : llvm::reverse(info->Instructions))
1321  ARM64EmitUnwindCode(streamer, Inst);
1322 
1323  // Emit epilog unwind instructions
1324  for (auto &I : Seg.Epilogs) {
1325  auto &EpilogInstrs = info->EpilogMap[I.first].Instructions;
1326  for (const WinEH::Instruction &inst : EpilogInstrs)
1327  ARM64EmitUnwindCode(streamer, inst);
1328  }
1329 
1330  int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
1331  assert(BytesMod >= 0);
1332  for (int i = 0; i < BytesMod; i++)
1333  streamer.emitInt8(0xE3);
1334 
1335  if (info->HandlesExceptions)
1336  streamer.emitValue(
1337  MCSymbolRefExpr::create(info->ExceptionHandler,
1339  4);
1340 }
1341 
1342 // Populate the .xdata section. The format of .xdata on ARM64 is documented at
1343 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
1345  bool TryPacked = true) {
1346  // If this UNWIND_INFO already has a symbol, it's already been emitted.
1347  if (info->Symbol)
1348  return;
1349  // If there's no unwind info here (not even a terminating UOP_End), the
1350  // unwind info is considered bogus and skipped. If this was done in
1351  // response to an explicit .seh_handlerdata, the associated trailing
1352  // handler data is left orphaned in the xdata section.
1353  if (info->empty()) {
1354  info->EmitAttempted = true;
1355  return;
1356  }
1357  if (info->EmitAttempted) {
1358  // If we tried to emit unwind info before (due to an explicit
1359  // .seh_handlerdata directive), but skipped it (because there was no
1360  // valid information to emit at the time), and it later got valid unwind
1361  // opcodes, we can't emit it here, because the trailing handler data
1362  // was already emitted elsewhere in the xdata section.
1363  streamer.getContext().reportError(
1364  SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +
1365  " skipped due to no unwind info at the time "
1366  "(.seh_handlerdata too early?), but the function later "
1367  "did get unwind info that can't be emitted");
1368  return;
1369  }
1370 
1371  simplifyARM64Opcodes(info->Instructions, false);
1372  for (auto &I : info->EpilogMap)
1373  simplifyARM64Opcodes(I.second.Instructions, true);
1374 
1375  int64_t RawFuncLength;
1376  if (!info->FuncletOrFuncEnd) {
1377  report_fatal_error("FuncletOrFuncEnd not set");
1378  } else {
1379  // FIXME: GetAbsDifference tries to compute the length of the function
1380  // immediately, before the whole file is emitted, but in general
1381  // that's impossible: the size in bytes of certain assembler directives
1382  // like .align and .fill is not known until the whole file is parsed and
1383  // relaxations are applied. Currently, GetAbsDifference fails with a fatal
1384  // error in that case. (We mostly don't hit this because inline assembly
1385  // specifying those directives is rare, and we don't normally try to
1386  // align loops on AArch64.)
1387  //
1388  // There are two potential approaches to delaying the computation. One,
1389  // we could emit something like ".word (endfunc-beginfunc)/4+0x10800000",
1390  // as long as we have some conservative estimate we could use to prove
1391  // that we don't need to split the unwind data. Emitting the constant
1392  // is straightforward, but there's no existing code for estimating the
1393  // size of the function.
1394  //
1395  // The other approach would be to use a dedicated, relaxable fragment,
1396  // which could grow to accommodate splitting the unwind data if
1397  // necessary. This is more straightforward, since it automatically works
1398  // without any new infrastructure, and it's consistent with how we handle
1399  // relaxation in other contexts. But it would require some refactoring
1400  // to move parts of the pdata/xdata emission into the implementation of
1401  // a fragment. We could probably continue to encode the unwind codes
1402  // here, but we'd have to emit the pdata, the xdata header, and the
1403  // epilogue scopes later, since they depend on whether the we need to
1404  // split the unwind data.
1405  RawFuncLength = GetAbsDifference(streamer, info->FuncletOrFuncEnd,
1406  info->Begin);
1407  }
1408 
1409  ARM64FindSegmentsInFunction(streamer, info, RawFuncLength);
1410 
1411  info->PrologCodeBytes = ARM64CountOfUnwindCodes(info->Instructions);
1412  for (auto &S : info->Segments)
1413  ARM64EmitUnwindInfoForSegment(streamer, info, S, TryPacked);
1414 
1415  // Clear prolog instructions after unwind info is emitted for all segments.
1416  info->Instructions.clear();
1417 }
1418 
1420  uint32_t Count = 0;
1421  for (const auto &I : Insns) {
1422  switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
1423  default:
1424  llvm_unreachable("Unsupported ARM unwind code");
1426  Count += 1;
1427  break;
1429  Count += 3;
1430  break;
1432  Count += 4;
1433  break;
1435  Count += 2;
1436  break;
1438  Count += 3;
1439  break;
1441  Count += 4;
1442  break;
1444  Count += 2;
1445  break;
1446  case Win64EH::UOP_SaveSP:
1447  Count += 1;
1448  break;
1450  Count += 1;
1451  break;
1453  Count += 1;
1454  break;
1456  Count += 1;
1457  break;
1459  Count += 2;
1460  break;
1461  case Win64EH::UOP_SaveLR:
1462  Count += 2;
1463  break;
1465  Count += 2;
1466  break;
1468  Count += 2;
1469  break;
1470  case Win64EH::UOP_Nop:
1471  case Win64EH::UOP_WideNop:
1472  case Win64EH::UOP_End:
1473  case Win64EH::UOP_EndNop:
1475  Count += 1;
1476  break;
1477  case Win64EH::UOP_Custom: {
1478  int J;
1479  for (J = 3; J > 0; J--)
1480  if (I.Offset & (0xffu << (8 * J)))
1481  break;
1482  Count += J + 1;
1483  break;
1484  }
1485  }
1486  }
1487  return Count;
1488 }
1489 
1491  bool *HasCustom = nullptr) {
1492  uint32_t Count = 0;
1493  for (const auto &I : Insns) {
1494  switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
1495  default:
1496  llvm_unreachable("Unsupported ARM unwind code");
1500  Count += 2;
1501  break;
1505  Count += 4;
1506  break;
1509  Count += 4;
1510  break;
1511  case Win64EH::UOP_SaveSP:
1512  Count += 2;
1513  break;
1516  Count += 2;
1517  break;
1521  Count += 4;
1522  break;
1523  case Win64EH::UOP_SaveLR:
1524  Count += 4;
1525  break;
1526  case Win64EH::UOP_Nop:
1527  case Win64EH::UOP_EndNop:
1528  Count += 2;
1529  break;
1530  case Win64EH::UOP_WideNop:
1532  Count += 4;
1533  break;
1534  case Win64EH::UOP_End:
1535  // This doesn't map to any instruction
1536  break;
1537  case Win64EH::UOP_Custom:
1538  // We can't reason about what instructions this maps to; return a
1539  // phony number to make sure we don't accidentally do epilog packing.
1540  Count += 1000;
1541  if (HasCustom)
1542  *HasCustom = true;
1543  break;
1544  }
1545  }
1546  return Count;
1547 }
1548 
1549 static void checkARMInstructions(MCStreamer &Streamer,
1551  const MCSymbol *Begin, const MCSymbol *End,
1552  StringRef Name, StringRef Type) {
1553  if (!End)
1554  return;
1555  std::optional<int64_t> MaybeDistance =
1556  GetOptionalAbsDifference(Streamer, End, Begin);
1557  if (!MaybeDistance)
1558  return;
1559  uint32_t Distance = (uint32_t)*MaybeDistance;
1560  bool HasCustom = false;
1561  uint32_t InstructionBytes = ARMCountOfInstructionBytes(Insns, &HasCustom);
1562  if (HasCustom)
1563  return;
1564  if (Distance != InstructionBytes) {
1565  Streamer.getContext().reportError(
1566  SMLoc(), "Incorrect size for " + Name + " " + Type + ": " +
1567  Twine(Distance) +
1568  " bytes of instructions in range, but .seh directives "
1569  "corresponding to " +
1570  Twine(InstructionBytes) + " bytes\n");
1571  }
1572 }
1573 
1574 static bool isARMTerminator(const WinEH::Instruction &inst) {
1575  switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
1576  case Win64EH::UOP_End:
1577  case Win64EH::UOP_EndNop:
1579  return true;
1580  default:
1581  return false;
1582  }
1583 }
1584 
1585 // Unwind opcode encodings and restrictions are documented at
1586 // https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling
1587 static void ARMEmitUnwindCode(MCStreamer &streamer,
1588  const WinEH::Instruction &inst) {
1589  uint32_t w, lr;
1590  int i;
1591  switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
1592  default:
1593  llvm_unreachable("Unsupported ARM unwind code");
1595  assert((inst.Offset & 3) == 0);
1596  assert(inst.Offset / 4 <= 0x7f);
1597  streamer.emitInt8(inst.Offset / 4);
1598  break;
1600  assert((inst.Register & ~0x5fff) == 0);
1601  lr = (inst.Register >> 14) & 1;
1602  w = 0x8000 | (inst.Register & 0x1fff) | (lr << 13);
1603  streamer.emitInt8((w >> 8) & 0xff);
1604  streamer.emitInt8((w >> 0) & 0xff);
1605  break;
1606  case Win64EH::UOP_SaveSP:
1607  assert(inst.Register <= 0x0f);
1608  streamer.emitInt8(0xc0 | inst.Register);
1609  break;
1611  assert(inst.Register >= 4 && inst.Register <= 7);
1612  assert(inst.Offset <= 1);
1613  streamer.emitInt8(0xd0 | (inst.Register - 4) | (inst.Offset << 2));
1614  break;
1616  assert(inst.Register >= 8 && inst.Register <= 11);
1617  assert(inst.Offset <= 1);
1618  streamer.emitInt8(0xd8 | (inst.Register - 8) | (inst.Offset << 2));
1619  break;
1621  assert(inst.Register >= 8 && inst.Register <= 15);
1622  streamer.emitInt8(0xe0 | (inst.Register - 8));
1623  break;
1625  assert((inst.Offset & 3) == 0);
1626  assert(inst.Offset / 4 <= 0x3ff);
1627  w = 0xe800 | (inst.Offset / 4);
1628  streamer.emitInt8((w >> 8) & 0xff);
1629  streamer.emitInt8((w >> 0) & 0xff);
1630  break;
1632  assert((inst.Register & ~0x40ff) == 0);
1633  lr = (inst.Register >> 14) & 1;
1634  w = 0xec00 | (inst.Register & 0x0ff) | (lr << 8);
1635  streamer.emitInt8((w >> 8) & 0xff);
1636  streamer.emitInt8((w >> 0) & 0xff);
1637  break;
1638  case Win64EH::UOP_SaveLR:
1639  assert((inst.Offset & 3) == 0);
1640  assert(inst.Offset / 4 <= 0x0f);
1641  streamer.emitInt8(0xef);
1642  streamer.emitInt8(inst.Offset / 4);
1643  break;
1645  assert(inst.Register <= 15);
1646  assert(inst.Offset <= 15);
1647  assert(inst.Register <= inst.Offset);
1648  streamer.emitInt8(0xf5);
1649  streamer.emitInt8((inst.Register << 4) | inst.Offset);
1650  break;
1652  assert(inst.Register >= 16 && inst.Register <= 31);
1653  assert(inst.Offset >= 16 && inst.Offset <= 31);
1654  assert(inst.Register <= inst.Offset);
1655  streamer.emitInt8(0xf6);
1656  streamer.emitInt8(((inst.Register - 16) << 4) | (inst.Offset - 16));
1657  break;
1659  assert((inst.Offset & 3) == 0);
1660  assert(inst.Offset / 4 <= 0xffff);
1661  w = inst.Offset / 4;
1662  streamer.emitInt8(0xf7);
1663  streamer.emitInt8((w >> 8) & 0xff);
1664  streamer.emitInt8((w >> 0) & 0xff);
1665  break;
1667  assert((inst.Offset & 3) == 0);
1668  assert(inst.Offset / 4 <= 0xffffff);
1669  w = inst.Offset / 4;
1670  streamer.emitInt8(0xf8);
1671  streamer.emitInt8((w >> 16) & 0xff);
1672  streamer.emitInt8((w >> 8) & 0xff);
1673  streamer.emitInt8((w >> 0) & 0xff);
1674  break;
1676  assert((inst.Offset & 3) == 0);
1677  assert(inst.Offset / 4 <= 0xffff);
1678  w = inst.Offset / 4;
1679  streamer.emitInt8(0xf9);
1680  streamer.emitInt8((w >> 8) & 0xff);
1681  streamer.emitInt8((w >> 0) & 0xff);
1682  break;
1684  assert((inst.Offset & 3) == 0);
1685  assert(inst.Offset / 4 <= 0xffffff);
1686  w = inst.Offset / 4;
1687  streamer.emitInt8(0xfa);
1688  streamer.emitInt8((w >> 16) & 0xff);
1689  streamer.emitInt8((w >> 8) & 0xff);
1690  streamer.emitInt8((w >> 0) & 0xff);
1691  break;
1692  case Win64EH::UOP_Nop:
1693  streamer.emitInt8(0xfb);
1694  break;
1695  case Win64EH::UOP_WideNop:
1696  streamer.emitInt8(0xfc);
1697  break;
1698  case Win64EH::UOP_EndNop:
1699  streamer.emitInt8(0xfd);
1700  break;
1702  streamer.emitInt8(0xfe);
1703  break;
1704  case Win64EH::UOP_End:
1705  streamer.emitInt8(0xff);
1706  break;
1707  case Win64EH::UOP_Custom:
1708  for (i = 3; i > 0; i--)
1709  if (inst.Offset & (0xffu << (8 * i)))
1710  break;
1711  for (; i >= 0; i--)
1712  streamer.emitInt8((inst.Offset >> (8 * i)) & 0xff);
1713  break;
1714  }
1715 }
1716 
1717 // Check if an epilog exists as a subset of the end of a prolog (backwards).
1718 // An epilog may end with one out of three different end opcodes; if this
1719 // is the first epilog that shares opcodes with the prolog, we can tolerate
1720 // that this opcode differs (and the caller will update the prolog to use
1721 // the same end opcode as the epilog). If another epilog already shares
1722 // opcodes with the prolog, the ending opcode must be a strict match.
1723 static int getARMOffsetInProlog(const std::vector<WinEH::Instruction> &Prolog,
1724  const std::vector<WinEH::Instruction> &Epilog,
1725  bool CanTweakProlog) {
1726  // Can't find an epilog as a subset if it is longer than the prolog.
1727  if (Epilog.size() > Prolog.size())
1728  return -1;
1729 
1730  // Check that the epilog actually is a perfect match for the end (backwrds)
1731  // of the prolog.
1732  // If we can adjust the prolog afterwards, don't check that the end opcodes
1733  // match.
1734  int EndIdx = CanTweakProlog ? 1 : 0;
1735  for (int I = Epilog.size() - 1; I >= EndIdx; I--) {
1736  // TODO: Could also allow minor mismatches, e.g. "add sp, #16" vs
1737  // "push {r0-r3}".
1738  if (Prolog[I] != Epilog[Epilog.size() - 1 - I])
1739  return -1;
1740  }
1741 
1742  if (CanTweakProlog) {
1743  // Check that both prolog and epilog end with an expected end opcode.
1744  if (Prolog.front().Operation != Win64EH::UOP_End)
1745  return -1;
1746  if (Epilog.back().Operation != Win64EH::UOP_End &&
1747  Epilog.back().Operation != Win64EH::UOP_EndNop &&
1748  Epilog.back().Operation != Win64EH::UOP_WideEndNop)
1749  return -1;
1750  }
1751 
1752  // If the epilog was a subset of the prolog, find its offset.
1753  if (Epilog.size() == Prolog.size())
1754  return 0;
1756  &Prolog[Epilog.size()], Prolog.size() - Epilog.size()));
1757 }
1758 
1760  int PrologCodeBytes) {
1761  // Can only pack if there's one single epilog
1762  if (info->EpilogMap.size() != 1)
1763  return -1;
1764 
1765  const WinEH::FrameInfo::Epilog &EpilogInfo = info->EpilogMap.begin()->second;
1766  // Can only pack if the epilog is unconditional
1767  if (EpilogInfo.Condition != 0xe) // ARMCC::AL
1768  return -1;
1769 
1770  const std::vector<WinEH::Instruction> &Epilog = EpilogInfo.Instructions;
1771  // Make sure we have at least the trailing end opcode
1772  if (info->Instructions.empty() || Epilog.empty())
1773  return -1;
1774 
1775  // Check that the epilog actually is at the very end of the function,
1776  // otherwise it can't be packed.
1777  std::optional<int64_t> MaybeDistance = GetOptionalAbsDifference(
1778  streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);
1779  if (!MaybeDistance)
1780  return -1;
1781  uint32_t DistanceFromEnd = (uint32_t)*MaybeDistance;
1782  uint32_t InstructionBytes = ARMCountOfInstructionBytes(Epilog);
1783  if (DistanceFromEnd != InstructionBytes)
1784  return -1;
1785 
1786  int RetVal = -1;
1787  // Even if we don't end up sharing opcodes with the prolog, we can still
1788  // write the offset as a packed offset, if the single epilog is located at
1789  // the end of the function and the offset (pointing after the prolog) fits
1790  // as a packed offset.
1791  if (PrologCodeBytes <= 31 &&
1792  PrologCodeBytes + ARMCountOfUnwindCodes(Epilog) <= 63)
1793  RetVal = PrologCodeBytes;
1794 
1795  int Offset =
1796  getARMOffsetInProlog(info->Instructions, Epilog, /*CanTweakProlog=*/true);
1797  if (Offset < 0)
1798  return RetVal;
1799 
1800  // Check that the offset and prolog size fits in the first word; it's
1801  // unclear whether the epilog count in the extension word can be taken
1802  // as packed epilog offset.
1803  if (Offset > 31 || PrologCodeBytes > 63)
1804  return RetVal;
1805 
1806  // Replace the regular end opcode of the prolog with the one from the
1807  // epilog.
1808  info->Instructions.front() = Epilog.back();
1809 
1810  // As we choose to express the epilog as part of the prolog, remove the
1811  // epilog from the map, so we don't try to emit its opcodes.
1812  info->EpilogMap.clear();
1813  return Offset;
1814 }
1815 
1816 static bool parseRegMask(unsigned Mask, bool &HasLR, bool &HasR11,
1817  unsigned &Folded, int &IntRegs) {
1818  if (Mask & (1 << 14)) {
1819  HasLR = true;
1820  Mask &= ~(1 << 14);
1821  }
1822  if (Mask & (1 << 11)) {
1823  HasR11 = true;
1824  Mask &= ~(1 << 11);
1825  }
1826  Folded = 0;
1827  IntRegs = -1;
1828  if (!Mask)
1829  return true;
1830  int First = 0;
1831  // Shift right until we have the bits at the bottom
1832  while ((Mask & 1) == 0) {
1833  First++;
1834  Mask >>= 1;
1835  }
1836  if ((Mask & (Mask + 1)) != 0)
1837  return false; // Not a consecutive series of bits? Can't be packed.
1838  // Count the bits
1839  int N = 0;
1840  while (Mask & (1 << N))
1841  N++;
1842  if (First < 4) {
1843  if (First + N < 4)
1844  return false;
1845  Folded = 4 - First;
1846  N -= Folded;
1847  First = 4;
1848  }
1849  if (First > 4)
1850  return false; // Can't be packed
1851  if (N >= 1)
1852  IntRegs = N - 1;
1853  return true;
1854 }
1855 
1857  uint32_t FuncLength) {
1858  int Step = 0;
1859  bool Homing = false;
1860  bool HasR11 = false;
1861  bool HasChain = false;
1862  bool HasLR = false;
1863  int IntRegs = -1; // r4 - r(4+N)
1864  int FloatRegs = -1; // d8 - d(8+N)
1865  unsigned PF = 0; // Number of extra pushed registers
1866  unsigned StackAdjust = 0;
1867  // Iterate over the prolog and check that all opcodes exactly match
1868  // the canonical order and form.
1869  for (const WinEH::Instruction &Inst : info->Instructions) {
1870  switch (Inst.Operation) {
1871  default:
1872  llvm_unreachable("Unsupported ARM unwind code");
1873  case Win64EH::UOP_Custom:
1880  // Can't be packed
1881  return false;
1882  case Win64EH::UOP_SaveSP:
1883  // Can't be packed; we can't rely on restoring sp from r11 when
1884  // unwinding a packed prologue.
1885  return false;
1886  case Win64EH::UOP_SaveLR:
1887  // Can't be present in a packed prologue
1888  return false;
1889 
1890  case Win64EH::UOP_End:
1891  case Win64EH::UOP_EndNop:
1893  if (Step != 0)
1894  return false;
1895  Step = 1;
1896  break;
1897 
1900  // push {r4-r11,lr}
1901  if (Step != 1 && Step != 2)
1902  return false;
1903  assert(Inst.Register >= 4 && Inst.Register <= 11); // r4-rX
1904  assert(Inst.Offset <= 1); // Lr
1905  IntRegs = Inst.Register - 4;
1906  if (Inst.Register == 11) {
1907  HasR11 = true;
1908  IntRegs--;
1909  }
1910  if (Inst.Offset)
1911  HasLR = true;
1912  Step = 3;
1913  break;
1914 
1916  if (Step == 1 && Inst.Register == 0x0f) {
1917  // push {r0-r3}
1918  Homing = true;
1919  Step = 2;
1920  break;
1921  }
1922  [[fallthrough]];
1924  if (Step != 1 && Step != 2)
1925  return false;
1926  // push {r4-r9,r11,lr}
1927  // push {r11,lr}
1928  // push {r1-r5}
1929  if (!parseRegMask(Inst.Register, HasLR, HasR11, PF, IntRegs))
1930  return false;
1931  Step = 3;
1932  break;
1933 
1934  case Win64EH::UOP_Nop:
1935  // mov r11, sp
1936  if (Step != 3 || !HasR11 || IntRegs >= 0 || PF > 0)
1937  return false;
1938  HasChain = true;
1939  Step = 4;
1940  break;
1941  case Win64EH::UOP_WideNop:
1942  // add.w r11, sp, #xx
1943  if (Step != 3 || !HasR11 || (IntRegs < 0 && PF == 0))
1944  return false;
1945  HasChain = true;
1946  Step = 4;
1947  break;
1948 
1950  if (Step != 1 && Step != 2 && Step != 3 && Step != 4)
1951  return false;
1952  assert(Inst.Register >= 8 && Inst.Register <= 15);
1953  if (Inst.Register == 15)
1954  return false; // Can't pack this case, R==7 means no IntRegs
1955  if (IntRegs >= 0)
1956  return false;
1957  FloatRegs = Inst.Register - 8;
1958  Step = 5;
1959  break;
1960 
1963  if (Step != 1 && Step != 2 && Step != 3 && Step != 4 && Step != 5)
1964  return false;
1965  if (PF > 0) // Can't have both folded and explicit stack allocation
1966  return false;
1967  if (Inst.Offset / 4 >= 0x3f4)
1968  return false;
1969  StackAdjust = Inst.Offset / 4;
1970  Step = 6;
1971  break;
1972  }
1973  }
1974  if (HasR11 && !HasChain) {
1975  if (IntRegs + 4 == 10) {
1976  // r11 stored, but not chaining; can be packed if already saving r4-r10
1977  // and we can fit r11 into this range.
1978  IntRegs++;
1979  HasR11 = false;
1980  } else
1981  return false;
1982  }
1983  if (HasChain && !HasLR)
1984  return false;
1985 
1986  // Packed uneind info can't express multiple epilogues.
1987  if (info->EpilogMap.size() > 1)
1988  return false;
1989 
1990  unsigned EF = 0;
1991  int Ret = 0;
1992  if (info->EpilogMap.size() == 0) {
1993  Ret = 3; // No epilogue
1994  } else {
1995  // As the prologue and epilogue aren't exact mirrors of each other,
1996  // we have to check the epilogue too and see if it matches what we've
1997  // concluded from the prologue.
1998  const WinEH::FrameInfo::Epilog &EpilogInfo =
1999  info->EpilogMap.begin()->second;
2000  if (EpilogInfo.Condition != 0xe) // ARMCC::AL
2001  return false;
2002  const std::vector<WinEH::Instruction> &Epilog = EpilogInfo.Instructions;
2003  std::optional<int64_t> MaybeDistance = GetOptionalAbsDifference(
2004  streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);
2005  if (!MaybeDistance)
2006  return false;
2007  uint32_t DistanceFromEnd = (uint32_t)*MaybeDistance;
2008  uint32_t InstructionBytes = ARMCountOfInstructionBytes(Epilog);
2009  if (DistanceFromEnd != InstructionBytes)
2010  return false;
2011 
2012  bool GotStackAdjust = false;
2013  bool GotFloatRegs = false;
2014  bool GotIntRegs = false;
2015  bool GotHomingRestore = false;
2016  bool GotLRRestore = false;
2017  bool NeedsReturn = false;
2018  bool GotReturn = false;
2019 
2020  Step = 6;
2021  for (const WinEH::Instruction &Inst : Epilog) {
2022  switch (Inst.Operation) {
2023  default:
2024  llvm_unreachable("Unsupported ARM unwind code");
2025  case Win64EH::UOP_Custom:
2032  case Win64EH::UOP_SaveSP:
2033  case Win64EH::UOP_Nop:
2034  case Win64EH::UOP_WideNop:
2035  // Can't be packed in an epilogue
2036  return false;
2037 
2040  if (Inst.Offset / 4 >= 0x3f4)
2041  return false;
2042  if (Step == 6) {
2043  if (Homing && FloatRegs < 0 && IntRegs < 0 && StackAdjust == 0 &&
2044  PF == 0 && Inst.Offset == 16) {
2045  GotHomingRestore = true;
2046  Step = 10;
2047  } else {
2048  if (StackAdjust > 0) {
2049  // Got stack adjust in prologue too; must match.
2050  if (StackAdjust != Inst.Offset / 4)
2051  return false;
2052  GotStackAdjust = true;
2053  } else if (PF == Inst.Offset / 4) {
2054  // Folded prologue, non-folded epilogue
2055  StackAdjust = Inst.Offset / 4;
2056  GotStackAdjust = true;
2057  } else {
2058  // StackAdjust == 0 in prologue, mismatch
2059  return false;
2060  }
2061  Step = 7;
2062  }
2063  } else if (Step == 7 || Step == 8 || Step == 9) {
2064  if (!Homing || Inst.Offset != 16)
2065  return false;
2066  GotHomingRestore = true;
2067  Step = 10;
2068  } else
2069  return false;
2070  break;
2071 
2073  if (Step != 6 && Step != 7)
2074  return false;
2075  assert(Inst.Register >= 8 && Inst.Register <= 15);
2076  if (FloatRegs != (int)(Inst.Register - 8))
2077  return false;
2078  GotFloatRegs = true;
2079  Step = 8;
2080  break;
2081 
2084  // push {r4-r11,lr}
2085  if (Step != 6 && Step != 7 && Step != 8)
2086  return false;
2087  assert(Inst.Register >= 4 && Inst.Register <= 11); // r4-rX
2088  assert(Inst.Offset <= 1); // Lr
2089  if (Homing && HasLR) {
2090  // If homing and LR is backed up, we can either restore LR here
2091  // and return with Ret == 1 or 2, or return with SaveLR below
2092  if (Inst.Offset) {
2093  GotLRRestore = true;
2094  NeedsReturn = true;
2095  } else {
2096  // Expecting a separate SaveLR below
2097  }
2098  } else {
2099  if (HasLR != (Inst.Offset == 1))
2100  return false;
2101  }
2102  GotLRRestore = Inst.Offset == 1;
2103  if (IntRegs < 0) // This opcode must include r4
2104  return false;
2105  int Expected = IntRegs;
2106  if (HasChain) {
2107  // Can't express r11 here unless IntRegs describe r4-r10
2108  if (IntRegs != 6)
2109  return false;
2110  Expected++;
2111  }
2112  if (Expected != (int)(Inst.Register - 4))
2113  return false;
2114  GotIntRegs = true;
2115  Step = 9;
2116  break;
2117  }
2118 
2121  if (Step != 6 && Step != 7 && Step != 8)
2122  return false;
2123  // push {r4-r9,r11,lr}
2124  // push {r11,lr}
2125  // push {r1-r5}
2126  bool CurHasLR = false, CurHasR11 = false;
2127  int Regs;
2128  if (!parseRegMask(Inst.Register, CurHasLR, CurHasR11, EF, Regs))
2129  return false;
2130  if (EF > 0) {
2131  if (EF != PF && EF != StackAdjust)
2132  return false;
2133  }
2134  if (Homing && HasLR) {
2135  // If homing and LR is backed up, we can either restore LR here
2136  // and return with Ret == 1 or 2, or return with SaveLR below
2137  if (CurHasLR) {
2138  GotLRRestore = true;
2139  NeedsReturn = true;
2140  } else {
2141  // Expecting a separate SaveLR below
2142  }
2143  } else {
2144  if (CurHasLR != HasLR)
2145  return false;
2146  GotLRRestore = CurHasLR;
2147  }
2148  int Expected = IntRegs;
2149  if (HasChain) {
2150  // If we have chaining, the mask must have included r11.
2151  if (!CurHasR11)
2152  return false;
2153  } else if (Expected == 7) {
2154  // If we don't have chaining, the mask could still include r11,
2155  // expressed as part of IntRegs Instead.
2156  Expected--;
2157  if (!CurHasR11)
2158  return false;
2159  } else {
2160  // Neither HasChain nor r11 included in IntRegs, must not have r11
2161  // here either.
2162  if (CurHasR11)
2163  return false;
2164  }
2165  if (Expected != Regs)
2166  return false;
2167  GotIntRegs = true;
2168  Step = 9;
2169  break;
2170  }
2171 
2172  case Win64EH::UOP_SaveLR:
2173  if (Step != 6 && Step != 7 && Step != 8 && Step != 9)
2174  return false;
2175  if (!Homing || Inst.Offset != 20 || GotLRRestore)
2176  return false;
2177  GotLRRestore = true;
2178  GotHomingRestore = true;
2179  Step = 10;
2180  break;
2181 
2182  case Win64EH::UOP_EndNop:
2184  GotReturn = true;
2185  Ret = (Inst.Operation == Win64EH::UOP_EndNop) ? 1 : 2;
2186  [[fallthrough]];
2187  case Win64EH::UOP_End:
2188  if (Step != 6 && Step != 7 && Step != 8 && Step != 9 && Step != 10)
2189  return false;
2190  Step = 11;
2191  break;
2192  }
2193  }
2194 
2195  if (Step != 11)
2196  return false;
2197  if (StackAdjust > 0 && !GotStackAdjust && EF == 0)
2198  return false;
2199  if (FloatRegs >= 0 && !GotFloatRegs)
2200  return false;
2201  if (IntRegs >= 0 && !GotIntRegs)
2202  return false;
2203  if (Homing && !GotHomingRestore)
2204  return false;
2205  if (HasLR && !GotLRRestore)
2206  return false;
2207  if (NeedsReturn && !GotReturn)
2208  return false;
2209  }
2210 
2211  assert(PF == 0 || EF == 0 ||
2212  StackAdjust == 0); // Can't have adjust in all three
2213  if (PF > 0 || EF > 0) {
2214  StackAdjust = PF > 0 ? (PF - 1) : (EF - 1);
2215  assert(StackAdjust <= 3);
2216  StackAdjust |= 0x3f0;
2217  if (PF > 0)
2218  StackAdjust |= 1 << 2;
2219  if (EF > 0)
2220  StackAdjust |= 1 << 3;
2221  }
2222 
2223  assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");
2224  int Flag = info->Fragment ? 0x02 : 0x01;
2225  int H = Homing ? 1 : 0;
2226  int L = HasLR ? 1 : 0;
2227  int C = HasChain ? 1 : 0;
2228  assert(IntRegs < 0 || FloatRegs < 0);
2229  unsigned Reg, R;
2230  if (IntRegs >= 0) {
2231  Reg = IntRegs;
2232  assert(Reg <= 7);
2233  R = 0;
2234  } else if (FloatRegs >= 0) {
2235  Reg = FloatRegs;
2236  assert(Reg < 7);
2237  R = 1;
2238  } else {
2239  // No int or float regs stored (except possibly R11,LR)
2240  Reg = 7;
2241  R = 1;
2242  }
2243  info->PackedInfo |= Flag << 0;
2244  info->PackedInfo |= (FuncLength & 0x7FF) << 2;
2245  info->PackedInfo |= (Ret & 0x3) << 13;
2246  info->PackedInfo |= H << 15;
2247  info->PackedInfo |= Reg << 16;
2248  info->PackedInfo |= R << 19;
2249  info->PackedInfo |= L << 20;
2250  info->PackedInfo |= C << 21;
2251  assert(StackAdjust <= 0x3ff);
2252  info->PackedInfo |= StackAdjust << 22;
2253  return true;
2254 }
2255 
2256 // Populate the .xdata section. The format of .xdata on ARM is documented at
2257 // https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling
2259  bool TryPacked = true) {
2260  // If this UNWIND_INFO already has a symbol, it's already been emitted.
2261  if (info->Symbol)
2262  return;
2263  // If there's no unwind info here (not even a terminating UOP_End), the
2264  // unwind info is considered bogus and skipped. If this was done in
2265  // response to an explicit .seh_handlerdata, the associated trailing
2266  // handler data is left orphaned in the xdata section.
2267  if (info->empty()) {
2268  info->EmitAttempted = true;
2269  return;
2270  }
2271  if (info->EmitAttempted) {
2272  // If we tried to emit unwind info before (due to an explicit
2273  // .seh_handlerdata directive), but skipped it (because there was no
2274  // valid information to emit at the time), and it later got valid unwind
2275  // opcodes, we can't emit it here, because the trailing handler data
2276  // was already emitted elsewhere in the xdata section.
2277  streamer.getContext().reportError(
2278  SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +
2279  " skipped due to no unwind info at the time "
2280  "(.seh_handlerdata too early?), but the function later "
2281  "did get unwind info that can't be emitted");
2282  return;
2283  }
2284 
2285  MCContext &context = streamer.getContext();
2286  MCSymbol *Label = context.createTempSymbol();
2287 
2288  streamer.emitValueToAlignment(Align(4));
2289  streamer.emitLabel(Label);
2290  info->Symbol = Label;
2291 
2292  if (!info->PrologEnd)
2293  streamer.getContext().reportError(SMLoc(), "Prologue in " +
2294  info->Function->getName() +
2295  " not correctly terminated");
2296 
2297  if (info->PrologEnd && !info->Fragment)
2298  checkARMInstructions(streamer, info->Instructions, info->Begin,
2299  info->PrologEnd, info->Function->getName(),
2300  "prologue");
2301  for (auto &I : info->EpilogMap) {
2302  MCSymbol *EpilogStart = I.first;
2303  auto &Epilog = I.second;
2304  checkARMInstructions(streamer, Epilog.Instructions, EpilogStart, Epilog.End,
2305  info->Function->getName(), "epilogue");
2306  if (Epilog.Instructions.empty() ||
2307  !isARMTerminator(Epilog.Instructions.back()))
2308  streamer.getContext().reportError(
2309  SMLoc(), "Epilogue in " + info->Function->getName() +
2310  " not correctly terminated");
2311  }
2312 
2313  std::optional<int64_t> RawFuncLength;
2314  const MCExpr *FuncLengthExpr = nullptr;
2315  if (!info->FuncletOrFuncEnd) {
2316  report_fatal_error("FuncletOrFuncEnd not set");
2317  } else {
2318  // As the size of many thumb2 instructions isn't known until later,
2319  // we can't always rely on being able to calculate the absolute
2320  // length of the function here. If we can't calculate it, defer it
2321  // to a relocation.
2322  //
2323  // In such a case, we won't know if the function is too long so that
2324  // the unwind info would need to be split (but this isn't implemented
2325  // anyway).
2326  RawFuncLength =
2327  GetOptionalAbsDifference(streamer, info->FuncletOrFuncEnd, info->Begin);
2328  if (!RawFuncLength)
2329  FuncLengthExpr =
2330  GetSubDivExpr(streamer, info->FuncletOrFuncEnd, info->Begin, 2);
2331  }
2332  uint32_t FuncLength = 0;
2333  if (RawFuncLength)
2334  FuncLength = (uint32_t)*RawFuncLength / 2;
2335  if (FuncLength > 0x3FFFF)
2336  report_fatal_error("SEH unwind data splitting not yet implemented");
2337  uint32_t PrologCodeBytes = ARMCountOfUnwindCodes(info->Instructions);
2338  uint32_t TotalCodeBytes = PrologCodeBytes;
2339 
2340  if (!info->HandlesExceptions && RawFuncLength && FuncLength <= 0x7ff &&
2341  TryPacked) {
2342  // No exception handlers; check if the prolog and epilog matches the
2343  // patterns that can be described by the packed format. If we don't
2344  // know the exact function length yet, we can't do this.
2345 
2346  // info->Symbol was already set even if we didn't actually write any
2347  // unwind info there. Keep using that as indicator that this unwind
2348  // info has been generated already.
2349 
2350  if (tryARMPackedUnwind(streamer, info, FuncLength))
2351  return;
2352  }
2353 
2354  int PackedEpilogOffset =
2355  checkARMPackedEpilog(streamer, info, PrologCodeBytes);
2356 
2357  // Process epilogs.
2359  // Epilogs processed so far.
2360  std::vector<MCSymbol *> AddedEpilogs;
2361 
2362  bool CanTweakProlog = true;
2363  for (auto &I : info->EpilogMap) {
2364  MCSymbol *EpilogStart = I.first;
2365  auto &EpilogInstrs = I.second.Instructions;
2366  uint32_t CodeBytes = ARMCountOfUnwindCodes(EpilogInstrs);
2367 
2368  MCSymbol *MatchingEpilog =
2369  FindMatchingEpilog(EpilogInstrs, AddedEpilogs, info);
2370  int PrologOffset;
2371  if (MatchingEpilog) {
2372  assert(EpilogInfo.find(MatchingEpilog) != EpilogInfo.end() &&
2373  "Duplicate epilog not found");
2374  EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
2375  // Clear the unwind codes in the EpilogMap, so that they don't get output
2376  // in the logic below.
2377  EpilogInstrs.clear();
2378  } else if ((PrologOffset = getARMOffsetInProlog(
2379  info->Instructions, EpilogInstrs, CanTweakProlog)) >= 0) {
2380  if (CanTweakProlog) {
2381  // Replace the regular end opcode of the prolog with the one from the
2382  // epilog.
2383  info->Instructions.front() = EpilogInstrs.back();
2384  // Later epilogs need a strict match for the end opcode.
2385  CanTweakProlog = false;
2386  }
2387  EpilogInfo[EpilogStart] = PrologOffset;
2388  // Clear the unwind codes in the EpilogMap, so that they don't get output
2389  // in the logic below.
2390  EpilogInstrs.clear();
2391  } else {
2392  EpilogInfo[EpilogStart] = TotalCodeBytes;
2393  TotalCodeBytes += CodeBytes;
2394  AddedEpilogs.push_back(EpilogStart);
2395  }
2396  }
2397 
2398  // Code Words, Epilog count, F, E, X, Vers, Function Length
2399  uint32_t row1 = 0x0;
2400  uint32_t CodeWords = TotalCodeBytes / 4;
2401  uint32_t CodeWordsMod = TotalCodeBytes % 4;
2402  if (CodeWordsMod)
2403  CodeWords++;
2404  uint32_t EpilogCount =
2405  PackedEpilogOffset >= 0 ? PackedEpilogOffset : info->EpilogMap.size();
2406  bool ExtensionWord = EpilogCount > 31 || CodeWords > 15;
2407  if (!ExtensionWord) {
2408  row1 |= (EpilogCount & 0x1F) << 23;
2409  row1 |= (CodeWords & 0x0F) << 28;
2410  }
2411  if (info->HandlesExceptions) // X
2412  row1 |= 1 << 20;
2413  if (PackedEpilogOffset >= 0) // E
2414  row1 |= 1 << 21;
2415  if (info->Fragment) // F
2416  row1 |= 1 << 22;
2417  row1 |= FuncLength & 0x3FFFF;
2418  if (RawFuncLength)
2419  streamer.emitInt32(row1);
2420  else
2421  streamer.emitValue(
2422  MCBinaryExpr::createOr(FuncLengthExpr,
2423  MCConstantExpr::create(row1, context), context),
2424  4);
2425 
2426  // Extended Code Words, Extended Epilog Count
2427  if (ExtensionWord) {
2428  // FIXME: We should be able to split unwind info into multiple sections.
2429  if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
2430  report_fatal_error("SEH unwind data splitting not yet implemented");
2431  uint32_t row2 = 0x0;
2432  row2 |= (CodeWords & 0xFF) << 16;
2433  row2 |= (EpilogCount & 0xFFFF);
2434  streamer.emitInt32(row2);
2435  }
2436 
2437  if (PackedEpilogOffset < 0) {
2438  // Epilog Start Index, Epilog Start Offset
2439  for (auto &I : EpilogInfo) {
2440  MCSymbol *EpilogStart = I.first;
2441  uint32_t EpilogIndex = I.second;
2442 
2443  std::optional<int64_t> MaybeEpilogOffset =
2444  GetOptionalAbsDifference(streamer, EpilogStart, info->Begin);
2445  const MCExpr *OffsetExpr = nullptr;
2446  uint32_t EpilogOffset = 0;
2447  if (MaybeEpilogOffset)
2448  EpilogOffset = *MaybeEpilogOffset / 2;
2449  else
2450  OffsetExpr = GetSubDivExpr(streamer, EpilogStart, info->Begin, 2);
2451 
2452  assert(info->EpilogMap.find(EpilogStart) != info->EpilogMap.end());
2453  unsigned Condition = info->EpilogMap[EpilogStart].Condition;
2454  assert(Condition <= 0xf);
2455 
2456  uint32_t row3 = EpilogOffset;
2457  row3 |= Condition << 20;
2458  row3 |= (EpilogIndex & 0x3FF) << 24;
2459  if (MaybeEpilogOffset)
2460  streamer.emitInt32(row3);
2461  else
2462  streamer.emitValue(
2464  OffsetExpr, MCConstantExpr::create(row3, context), context),
2465  4);
2466  }
2467  }
2468 
2469  // Emit prolog unwind instructions (in reverse order).
2470  uint8_t numInst = info->Instructions.size();
2471  for (uint8_t c = 0; c < numInst; ++c) {
2472  WinEH::Instruction inst = info->Instructions.back();
2473  info->Instructions.pop_back();
2474  ARMEmitUnwindCode(streamer, inst);
2475  }
2476 
2477  // Emit epilog unwind instructions
2478  for (auto &I : info->EpilogMap) {
2479  auto &EpilogInstrs = I.second.Instructions;
2480  for (const WinEH::Instruction &inst : EpilogInstrs)
2481  ARMEmitUnwindCode(streamer, inst);
2482  }
2483 
2484  int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
2485  assert(BytesMod >= 0);
2486  for (int i = 0; i < BytesMod; i++)
2487  streamer.emitInt8(0xFB);
2488 
2489  if (info->HandlesExceptions)
2490  streamer.emitValue(
2491  MCSymbolRefExpr::create(info->ExceptionHandler,
2493  4);
2494 }
2495 
2496 static void ARM64EmitRuntimeFunction(MCStreamer &streamer,
2497  const WinEH::FrameInfo *info) {
2498  MCContext &context = streamer.getContext();
2499 
2500  streamer.emitValueToAlignment(Align(4));
2501  for (const auto &S : info->Segments) {
2502  EmitSymbolRefWithOfs(streamer, info->Begin, S.Offset);
2503  if (info->PackedInfo)
2504  streamer.emitInt32(info->PackedInfo);
2505  else
2506  streamer.emitValue(
2508  context),
2509  4);
2510  }
2511 }
2512 
2513 
2514 static void ARMEmitRuntimeFunction(MCStreamer &streamer,
2515  const WinEH::FrameInfo *info) {
2516  MCContext &context = streamer.getContext();
2517 
2518  streamer.emitValueToAlignment(Align(4));
2519  EmitSymbolRefWithOfs(streamer, info->Begin, info->Begin);
2520  if (info->PackedInfo)
2521  streamer.emitInt32(info->PackedInfo);
2522  else
2523  streamer.emitValue(
2525  context),
2526  4);
2527 }
2528 
2530  // Emit the unwind info structs first.
2531  for (const auto &CFI : Streamer.getWinFrameInfos()) {
2532  WinEH::FrameInfo *Info = CFI.get();
2533  if (Info->empty())
2534  continue;
2535  MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
2536  Streamer.switchSection(XData);
2537  ARM64EmitUnwindInfo(Streamer, Info);
2538  }
2539 
2540  // Now emit RUNTIME_FUNCTION entries.
2541  for (const auto &CFI : Streamer.getWinFrameInfos()) {
2542  WinEH::FrameInfo *Info = CFI.get();
2543  // ARM64EmitUnwindInfo above clears the info struct, so we can't check
2544  // empty here. But if a Symbol is set, we should create the corresponding
2545  // pdata entry.
2546  if (!Info->Symbol)
2547  continue;
2548  MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
2549  Streamer.switchSection(PData);
2550  ARM64EmitRuntimeFunction(Streamer, Info);
2551  }
2552 }
2553 
2556  bool HandlerData) const {
2557  // Called if there's an .seh_handlerdata directive before the end of the
2558  // function. This forces writing the xdata record already here - and
2559  // in this case, the function isn't actually ended already, but the xdata
2560  // record needs to know the function length. In these cases, if the funclet
2561  // end hasn't been marked yet, the xdata function length won't cover the
2562  // whole function, only up to this point.
2563  if (!info->FuncletOrFuncEnd) {
2564  Streamer.switchSection(info->TextSection);
2565  info->FuncletOrFuncEnd = Streamer.emitCFILabel();
2566  }
2567  // Switch sections (the static function above is meant to be called from
2568  // here and from Emit().
2569  MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
2570  Streamer.switchSection(XData);
2571  ARM64EmitUnwindInfo(Streamer, info, /* TryPacked = */ !HandlerData);
2572 }
2573 
2575  // Emit the unwind info structs first.
2576  for (const auto &CFI : Streamer.getWinFrameInfos()) {
2577  WinEH::FrameInfo *Info = CFI.get();
2578  if (Info->empty())
2579  continue;
2580  MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
2581  Streamer.switchSection(XData);
2582  ARMEmitUnwindInfo(Streamer, Info);
2583  }
2584 
2585  // Now emit RUNTIME_FUNCTION entries.
2586  for (const auto &CFI : Streamer.getWinFrameInfos()) {
2587  WinEH::FrameInfo *Info = CFI.get();
2588  // ARMEmitUnwindInfo above clears the info struct, so we can't check
2589  // empty here. But if a Symbol is set, we should create the corresponding
2590  // pdata entry.
2591  if (!Info->Symbol)
2592  continue;
2593  MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
2594  Streamer.switchSection(PData);
2595  ARMEmitRuntimeFunction(Streamer, Info);
2596  }
2597 }
2598 
2601  bool HandlerData) const {
2602  // Called if there's an .seh_handlerdata directive before the end of the
2603  // function. This forces writing the xdata record already here - and
2604  // in this case, the function isn't actually ended already, but the xdata
2605  // record needs to know the function length. In these cases, if the funclet
2606  // end hasn't been marked yet, the xdata function length won't cover the
2607  // whole function, only up to this point.
2608  if (!info->FuncletOrFuncEnd) {
2609  Streamer.switchSection(info->TextSection);
2610  info->FuncletOrFuncEnd = Streamer.emitCFILabel();
2611  }
2612  // Switch sections (the static function above is meant to be called from
2613  // here and from Emit().
2614  MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
2615  Streamer.switchSection(XData);
2616  ARMEmitUnwindInfo(Streamer, info, /* TryPacked = */ !HandlerData);
2617 }
llvm::Win64EH::UOP_AllocMedium
@ UOP_AllocMedium
Definition: Win64EH.h:43
llvm::Win64EH::UOP_SaveXMM128
@ UOP_SaveXMM128
Definition: Win64EH.h:38
i
i
Definition: README.txt:29
llvm::WinEH::FrameInfo::Epilog
Definition: MCWinEH.h:59
llvm::MCBinaryExpr::createDiv
static const MCBinaryExpr * createDiv(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:535
llvm::WinEH::Instruction::Label
const MCSymbol * Label
Definition: MCWinEH.h:22
llvm::WinEH::Instruction::Offset
unsigned Offset
Definition: MCWinEH.h:23
llvm::MCStreamer::getAssociatedXDataSection
MCSection * getAssociatedXDataSection(const MCSection *TextSec)
Get the .xdata section used for the given section.
Definition: MCStreamer.cpp:852
llvm::Win64EH::UOP_SaveFRegD0D15
@ UOP_SaveFRegD0D15
Definition: Win64EH.h:99
llvm::Win64EH::UOP_SaveAnyRegDX
@ UOP_SaveAnyRegDX
Definition: Win64EH.h:73
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::MCSymbol
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
llvm::WinEH::Instruction::Register
unsigned Register
Definition: MCWinEH.h:24
checkARMInstructions
static void checkARMInstructions(MCStreamer &Streamer, ArrayRef< WinEH::Instruction > Insns, const MCSymbol *Begin, const MCSymbol *End, StringRef Name, StringRef Type)
Definition: MCWin64EH.cpp:1549
llvm::Win64EH::UOP_PACSignLR
@ UOP_PACSignLR
Definition: Win64EH.h:64
ARMCountOfUnwindCodes
static uint32_t ARMCountOfUnwindCodes(ArrayRef< WinEH::Instruction > Insns)
Definition: MCWin64EH.cpp:1419
llvm::MCContext
Context object for machine code objects.
Definition: MCContext.h:76
llvm::Win64EH::UOP_SaveAnyRegQX
@ UOP_SaveAnyRegQX
Definition: Win64EH.h:75
llvm::MCConstantExpr::create
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
ARM64EmitUnwindInfoForSegment
static void ARM64EmitUnwindInfoForSegment(MCStreamer &streamer, WinEH::FrameInfo *info, WinEH::FrameInfo::Segment &Seg, bool TryPacked=true)
Definition: MCWin64EH.cpp:1197
llvm::MCStreamer::emitInt8
void emitInt8(uint64_t Value)
Definition: MCStreamer.h:742
llvm::MapVector::clear
void clear()
Definition: MapVector.h:89
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1199
llvm::Win64EH::UOP_SaveFRegP
@ UOP_SaveFRegP
Definition: Win64EH.h:54
ARM64EmitUnwindCode
static void ARM64EmitUnwindCode(MCStreamer &streamer, const WinEH::Instruction &inst)
Definition: MCWin64EH.cpp:441
llvm::X86Disassembler::Reg
Reg
All possible values of the reg field in the ModR/M byte.
Definition: X86DisassemblerDecoder.h:462
llvm::Win64EH::UOP_SaveRegPX
@ UOP_SaveRegPX
Definition: Win64EH.h:50
EmitSymbolRefWithOfs
static void EmitSymbolRefWithOfs(MCStreamer &streamer, const MCSymbol *Base, int64_t Offset)
Definition: MCWin64EH.cpp:130
llvm::WinEH::FrameInfo::Segment::HasProlog
bool HasProlog
Definition: MCWinEH.h:70
llvm::Win64EH::UOP_SaveNext
@ UOP_SaveNext
Definition: Win64EH.h:60
FloatRegs
static const MCPhysReg FloatRegs[32]
Definition: SparcAsmParser.cpp:154
getARM64OffsetInProlog
static int getARM64OffsetInProlog(const std::vector< WinEH::Instruction > &Prolog, const std::vector< WinEH::Instruction > &Epilog)
Definition: MCWin64EH.cpp:732
llvm::MCStreamer::emitValue
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
Definition: MCStreamer.cpp:180
getARMOffsetInProlog
static int getARMOffsetInProlog(const std::vector< WinEH::Instruction > &Prolog, const std::vector< WinEH::Instruction > &Epilog, bool CanTweakProlog)
Definition: MCWin64EH.cpp:1723
llvm::Win64EH::UOP_PushNonVol
@ UOP_PushNonVol
Definition: Win64EH.h:30
llvm::Type
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
llvm::Win64EH::UOP_SaveLRPair
@ UOP_SaveLRPair
Definition: Win64EH.h:51
llvm::MCStreamer::emitCFILabel
virtual MCSymbol * emitCFILabel()
When emitting an object file, create and emit a real label.
Definition: MCStreamer.cpp:486
Instructions
Code Generation Notes for reduce the size of the ISel and reduce repetition in the implementation In a small number of this can cause even when no optimisation has taken place Instructions
Definition: MSA.txt:11
llvm::MCStreamer::emitInt32
void emitInt32(uint64_t Value)
Definition: MCStreamer.h:744
llvm::sys::path::begin
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:226
FindMatchingEpilog
static MCSymbol * FindMatchingEpilog(const std::vector< WinEH::Instruction > &EpilogInstrs, const std::vector< MCSymbol * > &Epilogs, const WinEH::FrameInfo *info)
Definition: MCWin64EH.cpp:643
llvm::Win64EH::UOP_SaveAnyRegQPX
@ UOP_SaveAnyRegQPX
Definition: Win64EH.h:76
llvm::Win64EH::UOP_WideNop
@ UOP_WideNop
Definition: Win64EH.h:102
llvm::Win64EH::UOP_EndNop
@ UOP_EndNop
Definition: Win64EH.h:104
llvm::MapVector
This class implements a map that also provides access to all stored values in a deterministic order.
Definition: MapVector.h:37
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:80
llvm::MipsISD::Ret
@ Ret
Definition: MipsISelLowering.h:119
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
llvm::Win64EH::UOP_SaveRegsR4R7LR
@ UOP_SaveRegsR4R7LR
Definition: Win64EH.h:94
llvm::DiagnosticPredicateTy::Match
@ Match
ARM64EmitRuntimeFunction
static void ARM64EmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
Definition: MCWin64EH.cpp:2496
RHS
Value * RHS
Definition: X86PartialReduction.cpp:76
ARMCountOfInstructionBytes
static uint32_t ARMCountOfInstructionBytes(ArrayRef< WinEH::Instruction > Insns, bool *HasCustom=nullptr)
Definition: MCWin64EH.cpp:1490
llvm::Win64EH::UOP_TrapFrame
@ UOP_TrapFrame
Definition: Win64EH.h:61
ARM64FindSegmentsInFunction
static void ARM64FindSegmentsInFunction(MCStreamer &streamer, WinEH::FrameInfo *info, int64_t RawFuncLength)
Definition: MCWin64EH.cpp:1116
llvm::Win64EH::UOP_Nop
@ UOP_Nop
Definition: Win64EH.h:58
llvm::Win64EH::UOP_SaveAnyRegIX
@ UOP_SaveAnyRegIX
Definition: Win64EH.h:71
llvm::Win64EH::UNW_TerminateHandler
@ UNW_TerminateHandler
UNW_TerminateHandler - Specifies that this function has a termination handler.
Definition: Win64EH.h:134
Context
LLVMContext & Context
Definition: NVVMIntrRange.cpp:66
MCObjectStreamer.h
llvm::BitmaskEnumDetail::Mask
constexpr std::underlying_type_t< E > Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Definition: BitmaskEnum.h:80
llvm::MCStreamer
Streaming machine code generation interface.
Definition: MCStreamer.h:212
LHS
Value * LHS
Definition: X86PartialReduction.cpp:75
llvm::Win64EH::UOP_SaveSP
@ UOP_SaveSP
Definition: Win64EH.h:93
GetOptionalAbsDifference
static std::optional< int64_t > GetOptionalAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
Definition: MCWin64EH.cpp:276
llvm::Win64EH::UOP_AddFP
@ UOP_AddFP
Definition: Win64EH.h:57
llvm::SMLoc
Represents a location in source code.
Definition: SMLoc.h:23
llvm::Win64EH::ARMUnwindEmitter::Emit
void Emit(MCStreamer &Streamer) const override
This emits the unwind info sections (.pdata and .xdata in PE/COFF).
Definition: MCWin64EH.cpp:2574
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::MCStreamer::getAssociatedPDataSection
MCSection * getAssociatedPDataSection(const MCSection *TextSec)
Get the .pdata section used for the given section.
Definition: MCStreamer.cpp:846
llvm::Win64EH::UOP_SaveRegX
@ UOP_SaveRegX
Definition: Win64EH.h:48
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
Twine.h
llvm::Win64EH::ARM64UnwindEmitter::EmitUnwindInfo
void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override
Definition: MCWin64EH.cpp:2554
MCContext.h
llvm::Win64EH::UOP_SetFPReg
@ UOP_SetFPReg
Definition: Win64EH.h:33
tryARM64PackedUnwind
static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength, int PackedEpilogOffset)
Definition: MCWin64EH.cpp:796
llvm::MCStreamer::emitLabel
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
Definition: MCStreamer.cpp:423
llvm::MCStreamer::switchSection
virtual void switchSection(MCSection *Section, const MCExpr *Subsection=nullptr)
Set the current section where code is being emitted to Section.
Definition: MCStreamer.cpp:1234
ARM64CountOfUnwindCodes
static uint32_t ARM64CountOfUnwindCodes(ArrayRef< WinEH::Instruction > Insns)
Definition: MCWin64EH.cpp:339
MCSymbol.h
llvm::Win64EH::UOP_SaveReg
@ UOP_SaveReg
Definition: Win64EH.h:47
b
the resulting code requires compare and branches when and if the revised code is with conditional branches instead of More there is a byte word extend before each where there should be only and the condition codes are not remembered when the same two values are compared twice More LSR enhancements i8 and i32 load store addressing modes are identical int b
Definition: README.txt:418
llvm::Win64EH::UOP_WideAllocMedium
@ UOP_WideAllocMedium
Definition: Win64EH.h:88
llvm::Win64EH::UOP_SaveAnyRegQ
@ UOP_SaveAnyRegQ
Definition: Win64EH.h:69
llvm::MCObjectStreamer
Streaming object file generation interface.
Definition: MCObjectStreamer.h:42
EmitUnwindInfo
static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info)
Definition: MCWin64EH.cpp:166
llvm::Win64EH::UOP_SaveFRegX
@ UOP_SaveFRegX
Definition: Win64EH.h:53
First
into llvm powi allowing the code generator to produce balanced multiplication trees First
Definition: README.txt:54
llvm::MCID::Flag
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Definition: MCInstrDesc.h:148
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:145
ARM64EmitUnwindInfo
static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info, bool TryPacked=true)
Definition: MCWin64EH.cpp:1344
lr
Common register allocation spilling lr str lr
Definition: README.txt:6
llvm::Win64EH::UOP_SetFP
@ UOP_SetFP
Definition: Win64EH.h:56
llvm::Win64EH::UOP_WideSaveRegsR4R11LR
@ UOP_WideSaveRegsR4R11LR
Definition: Win64EH.h:95
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
llvm::Win64EH::UOP_WideAllocHuge
@ UOP_WideAllocHuge
Definition: Win64EH.h:90
b2
int b2
Definition: README.txt:84
GetAbsDifference
static int64_t GetAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
Definition: MCWin64EH.cpp:293
Align
uint64_t Align
Definition: ELFObjHandler.cpp:82
c
the resulting code requires compare and branches when and if the revised code is with conditional branches instead of More there is a byte word extend before each where there should be only and the condition codes are not remembered when the same two values are compared twice More LSR enhancements i8 and i32 load store addressing modes are identical int int c
Definition: README.txt:418
ARM64ProcessEpilogs
static void ARM64ProcessEpilogs(WinEH::FrameInfo *info, WinEH::FrameInfo::Segment *Seg, uint32_t &TotalCodeBytes, MapVector< MCSymbol *, uint32_t > &EpilogInfo)
Definition: MCWin64EH.cpp:1072
llvm::Win64EH::UOP_SaveXMM128Big
@ UOP_SaveXMM128Big
Definition: Win64EH.h:39
llvm::WinEH::FrameInfo::Segment::Offset
int64_t Offset
Definition: MCWinEH.h:68
llvm::WinEH::FrameInfo::Segment::Epilogs
MapVector< MCSymbol *, int64_t > Epilogs
Definition: MCWinEH.h:73
llvm::Win64EH::UOP_SaveFPLRX
@ UOP_SaveFPLRX
Definition: Win64EH.h:45
llvm::Win64EH::UOP_End
@ UOP_End
Definition: Win64EH.h:59
llvm::MCConstantExpr
Definition: MCExpr.h:144
llvm::Win64EH::UOP_SaveAnyRegI
@ UOP_SaveAnyRegI
Definition: Win64EH.h:65
parseRegMask
static bool parseRegMask(unsigned Mask, bool &HasLR, bool &HasR11, unsigned &Folded, int &IntRegs)
Definition: MCWin64EH.cpp:1816
llvm::Win64EH::UnwindOpcodes
UnwindOpcodes
UnwindOpcodes - Enumeration whose values specify a single operation in the prolog of a function.
Definition: Win64EH.h:26
llvm::Win64EH::ARMUnwindEmitter::EmitUnwindInfo
void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override
Definition: MCWin64EH.cpp:2599
llvm::MCStreamer::emitInt16
void emitInt16(uint64_t Value)
Definition: MCStreamer.h:743
llvm::Win64EH::UOP_AllocSmall
@ UOP_AllocSmall
Definition: Win64EH.h:32
checkARMPackedEpilog
static int checkARMPackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info, int PrologCodeBytes)
Definition: MCWin64EH.cpp:1759
llvm::Win64EH::UOP_WideSaveRegMask
@ UOP_WideSaveRegMask
Definition: Win64EH.h:92
llvm::MapVector::find
iterator find(const KeyT &Key)
Definition: MapVector.h:148
llvm::Win64EH::UOP_AllocHuge
@ UOP_AllocHuge
Definition: Win64EH.h:87
llvm::Win64EH::UOP_SaveAnyRegDPX
@ UOP_SaveAnyRegDPX
Definition: Win64EH.h:74
llvm::MCBinaryExpr::createOr
static const MCBinaryExpr * createOr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:590
ARMEmitUnwindInfo
static void ARMEmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info, bool TryPacked=true)
Definition: MCWin64EH.cpp:2258
llvm::Win64EH::UOP_SaveFRegD16D31
@ UOP_SaveFRegD16D31
Definition: Win64EH.h:100
EmitUnwindCode
static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin, WinEH::Instruction &inst)
Definition: MCWin64EH.cpp:62
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
ARMEmitUnwindCode
static void ARMEmitUnwindCode(MCStreamer &streamer, const WinEH::Instruction &inst)
Definition: MCWin64EH.cpp:1587
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::Win64EH::UOP_Context
@ UOP_Context
Definition: Win64EH.h:62
EmitRuntimeFunction
static void EmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
Definition: MCWin64EH.cpp:154
llvm::WinEH::Instruction::Operation
unsigned Operation
Definition: MCWinEH.h:25
Win64EH.h
ARMEmitRuntimeFunction
static void ARMEmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
Definition: MCWin64EH.cpp:2514
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::Win64EH::UOP_SaveFReg
@ UOP_SaveFReg
Definition: Win64EH.h:52
llvm::WinEH::FrameInfo::Segment
Definition: MCWinEH.h:67
llvm::MCBinaryExpr::createSub
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:610
llvm::MCContext::reportError
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:1055
Mode
SI Whole Quad Mode
Definition: SIWholeQuadMode.cpp:262
llvm::Win64EH::UOP_SaveLR
@ UOP_SaveLR
Definition: Win64EH.h:98
llvm::Win64EH::UOP_SaveNonVol
@ UOP_SaveNonVol
Definition: Win64EH.h:34
llvm::MCSymbolRefExpr
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:192
llvm::Win64EH::UOP_SaveFRegPX
@ UOP_SaveFRegPX
Definition: Win64EH.h:55
info
lazy value info
Definition: LazyValueInfo.cpp:58
llvm::MCBinaryExpr::createAdd
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:525
llvm::WinEH::FrameInfo::Segment::Symbol
MCSymbol * Symbol
Definition: MCWinEH.h:71
llvm::MCObjectStreamer::getAssembler
MCAssembler & getAssembler()
Definition: MCObjectStreamer.h:128
IntRegs
static const MCPhysReg IntRegs[32]
Definition: SparcAsmParser.cpp:144
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:33
simplifyARM64Opcodes
static void simplifyARM64Opcodes(std::vector< WinEH::Instruction > &Instructions, bool Reverse)
Definition: MCWin64EH.cpp:668
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm::MapVector::lookup
ValueT lookup(const KeyT &Key) const
Definition: MapVector.h:111
llvm::Offset
@ Offset
Definition: DWP.cpp:406
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
uint32_t
llvm::StackOffset
StackOffset holds a fixed and a scalable offset in bytes.
Definition: TypeSize.h:36
llvm::Win64EH::UOP_SaveAnyRegIP
@ UOP_SaveAnyRegIP
Definition: Win64EH.h:66
llvm::MCSection
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition: MCSection.h:39
llvm::MCStreamer::emitValueToAlignment
virtual void emitValueToAlignment(Align Alignment, int64_t Value=0, unsigned ValueSize=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
Definition: MCStreamer.cpp:1222
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::MCContext::createTempSymbol
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:318
Prolog
@ Prolog
Definition: AArch64LowerHomogeneousPrologEpilog.cpp:126
llvm::Win64EH::UnwindEmitter::EmitUnwindInfo
void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override
Definition: MCWin64EH.cpp:253
llvm::MapVector::end
iterator end()
Definition: MapVector.h:72
llvm::Win64EH::ARM64UnwindEmitter::Emit
void Emit(MCStreamer &Streamer) const override
This emits the unwind info sections (.pdata and .xdata in PE/COFF).
Definition: MCWin64EH.cpp:2529
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
llvm::Win64EH::UOP_ClearUnwoundToCall
@ UOP_ClearUnwoundToCall
Definition: Win64EH.h:63
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:50
H
#define H(x, y, z)
Definition: MD5.cpp:57
llvm::Win64EH::UOP_Custom
@ UOP_Custom
Definition: Win64EH.h:108
uint16_t
Epilog
@ Epilog
Definition: AArch64LowerHomogeneousPrologEpilog.cpp:126
llvm::AMDGPU::SendMsg::Op
Op
Definition: SIDefines.h:354
llvm::Win64EH::UOP_SaveAnyRegIPX
@ UOP_SaveAnyRegIPX
Definition: Win64EH.h:72
llvm::Win64EH::UOP_SaveR19R20X
@ UOP_SaveR19R20X
Definition: Win64EH.h:44
llvm::Win64EH::UOP_SaveAnyRegD
@ UOP_SaveAnyRegD
Definition: Win64EH.h:67
llvm::WinEH::FrameInfo::Epilog::Instructions
std::vector< Instruction > Instructions
Definition: MCWinEH.h:60
llvm::WinEH::FrameInfo::Epilog::Condition
unsigned Condition
Definition: MCWinEH.h:61
llvm::MCStreamer::getWinFrameInfos
ArrayRef< std::unique_ptr< WinEH::FrameInfo > > getWinFrameInfos() const
Definition: MCStreamer.h:321
llvm::Win64EH::UOP_SaveFRegD8D15
@ UOP_SaveFRegD8D15
Definition: Win64EH.h:96
llvm::MCSymbolRefExpr::VK_COFF_IMGREL32
@ VK_COFF_IMGREL32
Definition: MCExpr.h:316
llvm::MCSymbolRefExpr::create
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:386
GetSubDivExpr
static const MCExpr * GetSubDivExpr(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS, int Div)
Definition: MCWin64EH.cpp:264
llvm::Win64EH::UNW_ExceptionHandler
@ UNW_ExceptionHandler
UNW_ExceptionHandler - Specifies that this function has an exception handler.
Definition: Win64EH.h:131
tryARMPackedUnwind
static bool tryARMPackedUnwind(MCStreamer &streamer, WinEH::FrameInfo *info, uint32_t FuncLength)
Definition: MCWin64EH.cpp:1856
checkARM64Instructions
static void checkARM64Instructions(MCStreamer &Streamer, ArrayRef< WinEH::Instruction > Insns, const MCSymbol *Begin, const MCSymbol *End, StringRef Name, StringRef Type)
Definition: MCWin64EH.cpp:302
llvm::Win64EH::UOP_SaveNonVolBig
@ UOP_SaveNonVolBig
Definition: Win64EH.h:35
llvm::WinEH::FrameInfo
Definition: MCWinEH.h:39
Other
std::optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:1260
llvm::MCStreamer::getContext
MCContext & getContext() const
Definition: MCStreamer.h:293
llvm::Win64EH::UOP_SaveAnyRegQP
@ UOP_SaveAnyRegQP
Definition: Win64EH.h:70
llvm::Win64EH::UNW_ChainInfo
@ UNW_ChainInfo
UNW_ChainInfo - Specifies that this UnwindInfo structure is chained to another one.
Definition: Win64EH.h:137
N
#define N
MCStreamer.h
llvm::Win64EH::UOP_SaveRegP
@ UOP_SaveRegP
Definition: Win64EH.h:49
llvm::Win64EH::UOP_SaveFPLR
@ UOP_SaveFPLR
Definition: Win64EH.h:46
llvm::Win64EH::UOP_SaveAnyRegDP
@ UOP_SaveAnyRegDP
Definition: Win64EH.h:68
llvm::WinEH::Instruction
Definition: MCWinEH.h:21
llvm::Win64EH::UOP_WideAllocLarge
@ UOP_WideAllocLarge
Definition: Win64EH.h:89
llvm::reverse
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:484
checkARM64PackedEpilog
static int checkARM64PackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info, WinEH::FrameInfo::Segment *Seg, int PrologCodeBytes)
Definition: MCWin64EH.cpp:753
isARMTerminator
static bool isARMTerminator(const WinEH::Instruction &inst)
Definition: MCWin64EH.cpp:1574
llvm::Win64EH::UnwindEmitter::Emit
void Emit(MCStreamer &Streamer) const override
This emits the unwind info sections (.pdata and .xdata in PE/COFF).
Definition: MCWin64EH.cpp:237
MCExpr.h
llvm::Win64EH::UOP_PushMachFrame
@ UOP_PushMachFrame
Definition: Win64EH.h:40
llvm::MCExpr
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
EmitAbsDifference
static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
Definition: MCWin64EH.cpp:53
llvm::sampleprof::Base
@ Base
Definition: Discriminator.h:58
llvm::Win64EH::UOP_WideEndNop
@ UOP_WideEndNop
Definition: Win64EH.h:105
llvm::WinEH::FrameInfo::Segment::Length
int64_t Length
Definition: MCWinEH.h:69
CountOfUnwindCodes
static uint8_t CountOfUnwindCodes(std::vector< WinEH::Instruction > &Insns)
Definition: MCWin64EH.cpp:25
MCWin64EH.h
llvm::Win64EH::UOP_SaveRegMask
@ UOP_SaveRegMask
Definition: Win64EH.h:97
llvm::Win64EH::UOP_AllocLarge
@ UOP_AllocLarge
Definition: Win64EH.h:31