LLVM  15.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/Optional.h"
11 #include "llvm/ADT/Twine.h"
12 #include "llvm/MC/MCContext.h"
13 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCStreamer.h"
16 #include "llvm/MC/MCSymbol.h"
17 #include "llvm/Support/Win64EH.h"
18 namespace llvm {
19 class MCSection;
20 }
21 
22 using namespace llvm;
23 
24 // NOTE: All relocations generated here are 4-byte image-relative.
25 
26 static uint8_t CountOfUnwindCodes(std::vector<WinEH::Instruction> &Insns) {
27  uint8_t Count = 0;
28  for (const auto &I : Insns) {
29  switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
30  default:
31  llvm_unreachable("Unsupported unwind code");
36  Count += 1;
37  break;
40  Count += 2;
41  break;
44  Count += 3;
45  break;
47  Count += (I.Offset > 512 * 1024 - 8) ? 3 : 2;
48  break;
49  }
50  }
51  return Count;
52 }
53 
54 static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
55  const MCSymbol *RHS) {
56  MCContext &Context = Streamer.getContext();
57  const MCExpr *Diff =
60  Streamer.emitValue(Diff, 1);
61 }
62 
63 static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
64  WinEH::Instruction &inst) {
65  uint8_t b2;
66  uint16_t w;
67  b2 = (inst.Operation & 0x0F);
68  switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
69  default:
70  llvm_unreachable("Unsupported unwind code");
72  EmitAbsDifference(streamer, inst.Label, begin);
73  b2 |= (inst.Register & 0x0F) << 4;
74  streamer.emitInt8(b2);
75  break;
77  EmitAbsDifference(streamer, inst.Label, begin);
78  if (inst.Offset > 512 * 1024 - 8) {
79  b2 |= 0x10;
80  streamer.emitInt8(b2);
81  w = inst.Offset & 0xFFF8;
82  streamer.emitInt16(w);
83  w = inst.Offset >> 16;
84  } else {
85  streamer.emitInt8(b2);
86  w = inst.Offset >> 3;
87  }
88  streamer.emitInt16(w);
89  break;
91  b2 |= (((inst.Offset - 8) >> 3) & 0x0F) << 4;
92  EmitAbsDifference(streamer, inst.Label, begin);
93  streamer.emitInt8(b2);
94  break;
96  EmitAbsDifference(streamer, inst.Label, begin);
97  streamer.emitInt8(b2);
98  break;
101  b2 |= (inst.Register & 0x0F) << 4;
102  EmitAbsDifference(streamer, inst.Label, begin);
103  streamer.emitInt8(b2);
104  w = inst.Offset >> 3;
106  w >>= 1;
107  streamer.emitInt16(w);
108  break;
111  b2 |= (inst.Register & 0x0F) << 4;
112  EmitAbsDifference(streamer, inst.Label, begin);
113  streamer.emitInt8(b2);
115  w = inst.Offset & 0xFFF0;
116  else
117  w = inst.Offset & 0xFFF8;
118  streamer.emitInt16(w);
119  w = inst.Offset >> 16;
120  streamer.emitInt16(w);
121  break;
123  if (inst.Offset == 1)
124  b2 |= 0x10;
125  EmitAbsDifference(streamer, inst.Label, begin);
126  streamer.emitInt8(b2);
127  break;
128  }
129 }
130 
131 static void EmitSymbolRefWithOfs(MCStreamer &streamer,
132  const MCSymbol *Base,
133  const MCSymbol *Other) {
134  MCContext &Context = streamer.getContext();
137  const MCExpr *Ofs = MCBinaryExpr::createSub(OtherRef, BaseRef, Context);
138  const MCSymbolRefExpr *BaseRefRel = MCSymbolRefExpr::create(Base,
140  Context);
141  streamer.emitValue(MCBinaryExpr::createAdd(BaseRefRel, Ofs, Context), 4);
142 }
143 
144 static void EmitRuntimeFunction(MCStreamer &streamer,
145  const WinEH::FrameInfo *info) {
146  MCContext &context = streamer.getContext();
147 
148  streamer.emitValueToAlignment(4);
149  EmitSymbolRefWithOfs(streamer, info->Begin, info->Begin);
150  EmitSymbolRefWithOfs(streamer, info->Begin, info->End);
151  streamer.emitValue(MCSymbolRefExpr::create(info->Symbol,
153  context), 4);
154 }
155 
156 static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
157  // If this UNWIND_INFO already has a symbol, it's already been emitted.
158  if (info->Symbol)
159  return;
160 
161  MCContext &context = streamer.getContext();
162  MCSymbol *Label = context.createTempSymbol();
163 
164  streamer.emitValueToAlignment(4);
165  streamer.emitLabel(Label);
166  info->Symbol = Label;
167 
168  // Upper 3 bits are the version number (currently 1).
169  uint8_t flags = 0x01;
170  if (info->ChainedParent)
171  flags |= Win64EH::UNW_ChainInfo << 3;
172  else {
173  if (info->HandlesUnwind)
174  flags |= Win64EH::UNW_TerminateHandler << 3;
175  if (info->HandlesExceptions)
176  flags |= Win64EH::UNW_ExceptionHandler << 3;
177  }
178  streamer.emitInt8(flags);
179 
180  if (info->PrologEnd)
181  EmitAbsDifference(streamer, info->PrologEnd, info->Begin);
182  else
183  streamer.emitInt8(0);
184 
185  uint8_t numCodes = CountOfUnwindCodes(info->Instructions);
186  streamer.emitInt8(numCodes);
187 
188  uint8_t frame = 0;
189  if (info->LastFrameInst >= 0) {
190  WinEH::Instruction &frameInst = info->Instructions[info->LastFrameInst];
191  assert(frameInst.Operation == Win64EH::UOP_SetFPReg);
192  frame = (frameInst.Register & 0x0F) | (frameInst.Offset & 0xF0);
193  }
194  streamer.emitInt8(frame);
195 
196  // Emit unwind instructions (in reverse order).
197  uint8_t numInst = info->Instructions.size();
198  for (uint8_t c = 0; c < numInst; ++c) {
199  WinEH::Instruction inst = info->Instructions.back();
200  info->Instructions.pop_back();
201  EmitUnwindCode(streamer, info->Begin, inst);
202  }
203 
204  // For alignment purposes, the instruction array will always have an even
205  // number of entries, with the final entry potentially unused (in which case
206  // the array will be one longer than indicated by the count of unwind codes
207  // field).
208  if (numCodes & 1) {
209  streamer.emitInt16(0);
210  }
211 
212  if (flags & (Win64EH::UNW_ChainInfo << 3))
213  EmitRuntimeFunction(streamer, info->ChainedParent);
214  else if (flags &
216  streamer.emitValue(MCSymbolRefExpr::create(info->ExceptionHandler,
218  context), 4);
219  else if (numCodes == 0) {
220  // The minimum size of an UNWIND_INFO struct is 8 bytes. If we're not
221  // a chained unwind info, if there is no handler, and if there are fewer
222  // than 2 slots used in the unwind code array, we have to pad to 8 bytes.
223  streamer.emitInt32(0);
224  }
225 }
226 
228  // Emit the unwind info structs first.
229  for (const auto &CFI : Streamer.getWinFrameInfos()) {
230  MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
231  Streamer.switchSection(XData);
232  ::EmitUnwindInfo(Streamer, CFI.get());
233  }
234 
235  // Now emit RUNTIME_FUNCTION entries.
236  for (const auto &CFI : Streamer.getWinFrameInfos()) {
237  MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
238  Streamer.switchSection(PData);
239  EmitRuntimeFunction(Streamer, CFI.get());
240  }
241 }
242 
245  bool HandlerData) const {
246  // Switch sections (the static function above is meant to be called from
247  // here and from Emit().
248  MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
249  Streamer.switchSection(XData);
250 
251  ::EmitUnwindInfo(Streamer, info);
252 }
253 
254 static const MCExpr *GetSubDivExpr(MCStreamer &Streamer, const MCSymbol *LHS,
255  const MCSymbol *RHS, int Div) {
256  MCContext &Context = Streamer.getContext();
257  const MCExpr *Expr =
260  if (Div != 1)
262  Context);
263  return Expr;
264 }
265 
267  const MCSymbol *LHS,
268  const MCSymbol *RHS) {
269  MCContext &Context = Streamer.getContext();
270  const MCExpr *Diff =
273  MCObjectStreamer *OS = (MCObjectStreamer *)(&Streamer);
274  // It should normally be possible to calculate the length of a function
275  // at this point, but it might not be possible in the presence of certain
276  // unusual constructs, like an inline asm with an alignment directive.
277  int64_t value;
278  if (!Diff->evaluateAsAbsolute(value, OS->getAssembler()))
279  return None;
280  return value;
281 }
282 
283 static int64_t GetAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
284  const MCSymbol *RHS) {
285  Optional<int64_t> MaybeDiff = GetOptionalAbsDifference(Streamer, LHS, RHS);
286  if (!MaybeDiff)
287  report_fatal_error("Failed to evaluate function length in SEH unwind info");
288  return *MaybeDiff;
289 }
290 
292  uint32_t Count = 0;
293  for (const auto &I : Insns) {
294  switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
295  default:
296  llvm_unreachable("Unsupported ARM64 unwind code");
298  Count += 1;
299  break;
301  Count += 2;
302  break;
304  Count += 4;
305  break;
307  Count += 1;
308  break;
310  Count += 1;
311  break;
313  Count += 1;
314  break;
316  Count += 2;
317  break;
319  Count += 2;
320  break;
322  Count += 2;
323  break;
325  Count += 2;
326  break;
328  Count += 2;
329  break;
331  Count += 2;
332  break;
334  Count += 2;
335  break;
337  Count += 2;
338  break;
340  Count += 2;
341  break;
342  case Win64EH::UOP_SetFP:
343  Count += 1;
344  break;
345  case Win64EH::UOP_AddFP:
346  Count += 2;
347  break;
348  case Win64EH::UOP_Nop:
349  Count += 1;
350  break;
351  case Win64EH::UOP_End:
352  Count += 1;
353  break;
355  Count += 1;
356  break;
358  Count += 1;
359  break;
361  Count += 1;
362  break;
364  Count += 1;
365  break;
367  Count += 1;
368  break;
369  }
370  }
371  return Count;
372 }
373 
374 // Unwind opcode encodings and restrictions are documented at
375 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
376 static void ARM64EmitUnwindCode(MCStreamer &streamer,
377  const WinEH::Instruction &inst) {
378  uint8_t b, reg;
379  switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
380  default:
381  llvm_unreachable("Unsupported ARM64 unwind code");
383  b = (inst.Offset >> 4) & 0x1F;
384  streamer.emitInt8(b);
385  break;
387  uint16_t hw = (inst.Offset >> 4) & 0x7FF;
388  b = 0xC0;
389  b |= (hw >> 8);
390  streamer.emitInt8(b);
391  b = hw & 0xFF;
392  streamer.emitInt8(b);
393  break;
394  }
396  uint32_t w;
397  b = 0xE0;
398  streamer.emitInt8(b);
399  w = inst.Offset >> 4;
400  b = (w & 0x00FF0000) >> 16;
401  streamer.emitInt8(b);
402  b = (w & 0x0000FF00) >> 8;
403  streamer.emitInt8(b);
404  b = w & 0x000000FF;
405  streamer.emitInt8(b);
406  break;
407  }
408  case Win64EH::UOP_SetFP:
409  b = 0xE1;
410  streamer.emitInt8(b);
411  break;
412  case Win64EH::UOP_AddFP:
413  b = 0xE2;
414  streamer.emitInt8(b);
415  b = (inst.Offset >> 3);
416  streamer.emitInt8(b);
417  break;
418  case Win64EH::UOP_Nop:
419  b = 0xE3;
420  streamer.emitInt8(b);
421  break;
423  b = 0x20;
424  b |= (inst.Offset >> 3) & 0x1F;
425  streamer.emitInt8(b);
426  break;
428  b = 0x80;
429  b |= ((inst.Offset - 1) >> 3) & 0x3F;
430  streamer.emitInt8(b);
431  break;
433  b = 0x40;
434  b |= (inst.Offset >> 3) & 0x3F;
435  streamer.emitInt8(b);
436  break;
438  assert(inst.Register >= 19 && "Saved reg must be >= 19");
439  reg = inst.Register - 19;
440  b = 0xD0 | ((reg & 0xC) >> 2);
441  streamer.emitInt8(b);
442  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
443  streamer.emitInt8(b);
444  break;
446  assert(inst.Register >= 19 && "Saved reg must be >= 19");
447  reg = inst.Register - 19;
448  b = 0xD4 | ((reg & 0x8) >> 3);
449  streamer.emitInt8(b);
450  b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
451  streamer.emitInt8(b);
452  break;
454  assert(inst.Register >= 19 && "Saved registers must be >= 19");
455  reg = inst.Register - 19;
456  b = 0xC8 | ((reg & 0xC) >> 2);
457  streamer.emitInt8(b);
458  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
459  streamer.emitInt8(b);
460  break;
462  assert(inst.Register >= 19 && "Saved registers must be >= 19");
463  reg = inst.Register - 19;
464  b = 0xCC | ((reg & 0xC) >> 2);
465  streamer.emitInt8(b);
466  b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
467  streamer.emitInt8(b);
468  break;
470  assert(inst.Register >= 19 && "Saved reg must be >= 19");
471  reg = inst.Register - 19;
472  assert((reg % 2) == 0 && "Saved reg must be 19+2*X");
473  reg /= 2;
474  b = 0xD6 | ((reg & 0x7) >> 2);
475  streamer.emitInt8(b);
476  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
477  streamer.emitInt8(b);
478  break;
480  assert(inst.Register >= 8 && "Saved dreg must be >= 8");
481  reg = inst.Register - 8;
482  b = 0xDC | ((reg & 0x4) >> 2);
483  streamer.emitInt8(b);
484  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
485  streamer.emitInt8(b);
486  break;
488  assert(inst.Register >= 8 && "Saved dreg must be >= 8");
489  reg = inst.Register - 8;
490  b = 0xDE;
491  streamer.emitInt8(b);
492  b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
493  streamer.emitInt8(b);
494  break;
496  assert(inst.Register >= 8 && "Saved dregs must be >= 8");
497  reg = inst.Register - 8;
498  b = 0xD8 | ((reg & 0x4) >> 2);
499  streamer.emitInt8(b);
500  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
501  streamer.emitInt8(b);
502  break;
504  assert(inst.Register >= 8 && "Saved dregs must be >= 8");
505  reg = inst.Register - 8;
506  b = 0xDA | ((reg & 0x4) >> 2);
507  streamer.emitInt8(b);
508  b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
509  streamer.emitInt8(b);
510  break;
511  case Win64EH::UOP_End:
512  b = 0xE4;
513  streamer.emitInt8(b);
514  break;
516  b = 0xE6;
517  streamer.emitInt8(b);
518  break;
520  b = 0xE8;
521  streamer.emitInt8(b);
522  break;
524  b = 0xE9;
525  streamer.emitInt8(b);
526  break;
528  b = 0xEA;
529  streamer.emitInt8(b);
530  break;
532  b = 0xEC;
533  streamer.emitInt8(b);
534  break;
535  }
536 }
537 
538 // Returns the epilog symbol of an epilog with the exact same unwind code
539 // sequence, if it exists. Otherwise, returns nullptr.
540 // EpilogInstrs - Unwind codes for the current epilog.
541 // Epilogs - Epilogs that potentialy match the current epilog.
542 static MCSymbol*
543 FindMatchingEpilog(const std::vector<WinEH::Instruction>& EpilogInstrs,
544  const std::vector<MCSymbol *>& Epilogs,
545  const WinEH::FrameInfo *info) {
546  for (auto *EpilogStart : Epilogs) {
547  auto InstrsIter = info->EpilogMap.find(EpilogStart);
548  assert(InstrsIter != info->EpilogMap.end() &&
549  "Epilog not found in EpilogMap");
550  const auto &Instrs = InstrsIter->second.Instructions;
551 
552  if (Instrs.size() != EpilogInstrs.size())
553  continue;
554 
555  bool Match = true;
556  for (unsigned i = 0; i < Instrs.size(); ++i)
557  if (Instrs[i] != EpilogInstrs[i]) {
558  Match = false;
559  break;
560  }
561 
562  if (Match)
563  return EpilogStart;
564  }
565  return nullptr;
566 }
567 
568 static void simplifyARM64Opcodes(std::vector<WinEH::Instruction> &Instructions,
569  bool Reverse) {
570  unsigned PrevOffset = -1;
571  unsigned PrevRegister = -1;
572 
573  auto VisitInstruction = [&](WinEH::Instruction &Inst) {
574  // Convert 2-byte opcodes into equivalent 1-byte ones.
575  if (Inst.Operation == Win64EH::UOP_SaveRegP && Inst.Register == 29) {
576  Inst.Operation = Win64EH::UOP_SaveFPLR;
577  Inst.Register = -1;
578  } else if (Inst.Operation == Win64EH::UOP_SaveRegPX &&
579  Inst.Register == 29) {
580  Inst.Operation = Win64EH::UOP_SaveFPLRX;
581  Inst.Register = -1;
582  } else if (Inst.Operation == Win64EH::UOP_SaveRegPX &&
583  Inst.Register == 19 && Inst.Offset <= 248) {
584  Inst.Operation = Win64EH::UOP_SaveR19R20X;
585  Inst.Register = -1;
586  } else if (Inst.Operation == Win64EH::UOP_AddFP && Inst.Offset == 0) {
587  Inst.Operation = Win64EH::UOP_SetFP;
588  } else if (Inst.Operation == Win64EH::UOP_SaveRegP &&
589  Inst.Register == PrevRegister + 2 &&
590  Inst.Offset == PrevOffset + 16) {
591  Inst.Operation = Win64EH::UOP_SaveNext;
592  Inst.Register = -1;
593  Inst.Offset = 0;
594  // Intentionally not creating UOP_SaveNext for float register pairs,
595  // as current versions of Windows (up to at least 20.04) is buggy
596  // regarding SaveNext for float pairs.
597  }
598  // Update info about the previous instruction, for detecting if
599  // the next one can be made a UOP_SaveNext
600  if (Inst.Operation == Win64EH::UOP_SaveR19R20X) {
601  PrevOffset = 0;
602  PrevRegister = 19;
603  } else if (Inst.Operation == Win64EH::UOP_SaveRegPX) {
604  PrevOffset = 0;
605  PrevRegister = Inst.Register;
606  } else if (Inst.Operation == Win64EH::UOP_SaveRegP) {
607  PrevOffset = Inst.Offset;
608  PrevRegister = Inst.Register;
609  } else if (Inst.Operation == Win64EH::UOP_SaveNext) {
610  PrevRegister += 2;
611  PrevOffset += 16;
612  } else {
613  PrevRegister = -1;
614  PrevOffset = -1;
615  }
616  };
617 
618  // Iterate over instructions in a forward order (for prologues),
619  // backwards for epilogues (i.e. always reverse compared to how the
620  // opcodes are stored).
621  if (Reverse) {
622  for (auto It = Instructions.rbegin(); It != Instructions.rend(); It++)
623  VisitInstruction(*It);
624  } else {
625  for (WinEH::Instruction &Inst : Instructions)
626  VisitInstruction(Inst);
627  }
628 }
629 
630 // Check if an epilog exists as a subset of the end of a prolog (backwards).
631 static int
632 getARM64OffsetInProlog(const std::vector<WinEH::Instruction> &Prolog,
633  const std::vector<WinEH::Instruction> &Epilog) {
634  // Can't find an epilog as a subset if it is longer than the prolog.
635  if (Epilog.size() > Prolog.size())
636  return -1;
637 
638  // Check that the epilog actually is a perfect match for the end (backwrds)
639  // of the prolog.
640  for (int I = Epilog.size() - 1; I >= 0; I--) {
641  if (Prolog[I] != Epilog[Epilog.size() - 1 - I])
642  return -1;
643  }
644 
645  // If the epilog was a subset of the prolog, find its offset.
646  if (Epilog.size() == Prolog.size())
647  return 0;
649  &Prolog[Epilog.size()], Prolog.size() - Epilog.size()));
650 }
651 
653  int PrologCodeBytes) {
654  // Can only pack if there's one single epilog
655  if (info->EpilogMap.size() != 1)
656  return -1;
657 
658  const std::vector<WinEH::Instruction> &Epilog =
659  info->EpilogMap.begin()->second.Instructions;
660 
661  // Check that the epilog actually is at the very end of the function,
662  // otherwise it can't be packed.
663  uint32_t DistanceFromEnd = (uint32_t)GetAbsDifference(
664  streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);
665  if (DistanceFromEnd / 4 != Epilog.size())
666  return -1;
667 
668  int RetVal = -1;
669  // Even if we don't end up sharing opcodes with the prolog, we can still
670  // write the offset as a packed offset, if the single epilog is located at
671  // the end of the function and the offset (pointing after the prolog) fits
672  // as a packed offset.
673  if (PrologCodeBytes <= 31 &&
674  PrologCodeBytes + ARM64CountOfUnwindCodes(Epilog) <= 124)
675  RetVal = PrologCodeBytes;
676 
677  int Offset = getARM64OffsetInProlog(info->Instructions, Epilog);
678  if (Offset < 0)
679  return RetVal;
680 
681  // Check that the offset and prolog size fits in the first word; it's
682  // unclear whether the epilog count in the extension word can be taken
683  // as packed epilog offset.
684  if (Offset > 31 || PrologCodeBytes > 124)
685  return RetVal;
686 
687  // As we choose to express the epilog as part of the prolog, remove the
688  // epilog from the map, so we don't try to emit its opcodes.
689  info->EpilogMap.clear();
690  return Offset;
691 }
692 
694  int PackedEpilogOffset) {
695  if (PackedEpilogOffset == 0) {
696  // Fully symmetric prolog and epilog, should be ok for packed format.
697  // For CR=3, the corresponding synthesized epilog actually lacks the
698  // SetFP opcode, but unwinding should work just fine despite that
699  // (if at the SetFP opcode, the unwinder considers it as part of the
700  // function body and just unwinds the full prolog instead).
701  } else if (PackedEpilogOffset == 1) {
702  // One single case of differences between prolog and epilog is allowed:
703  // The epilog can lack a single SetFP that is the last opcode in the
704  // prolog, for the CR=3 case.
705  if (info->Instructions.back().Operation != Win64EH::UOP_SetFP)
706  return false;
707  } else {
708  // Too much difference between prolog and epilog.
709  return false;
710  }
711  unsigned RegI = 0, RegF = 0;
712  int Predecrement = 0;
713  enum {
714  Start,
715  Start2,
716  IntRegs,
717  FloatRegs,
718  InputArgs,
719  StackAdjust,
720  FrameRecord,
721  End
722  } Location = Start;
723  bool StandaloneLR = false, FPLRPair = false;
724  int StackOffset = 0;
725  int Nops = 0;
726  // Iterate over the prolog and check that all opcodes exactly match
727  // the canonical order and form. A more lax check could verify that
728  // all saved registers are in the expected locations, but not enforce
729  // the order - that would work fine when unwinding from within
730  // functions, but not be exactly right if unwinding happens within
731  // prologs/epilogs.
732  for (const WinEH::Instruction &Inst : info->Instructions) {
733  switch (Inst.Operation) {
734  case Win64EH::UOP_End:
735  if (Location != Start)
736  return false;
737  Location = Start2;
738  break;
740  if (Location != Start2)
741  return false;
742  Predecrement = Inst.Offset;
743  RegI = 2;
744  Location = IntRegs;
745  break;
747  if (Location != Start2)
748  return false;
749  Predecrement = Inst.Offset;
750  if (Inst.Register == 19)
751  RegI += 1;
752  else if (Inst.Register == 30)
753  StandaloneLR = true;
754  else
755  return false;
756  // Odd register; can't be any further int registers.
757  Location = FloatRegs;
758  break;
760  // Can't have this in a canonical prologue. Either this has been
761  // canonicalized into SaveR19R20X or SaveFPLRX, or it's an unsupported
762  // register pair.
763  // It can't be canonicalized into SaveR19R20X if the offset is
764  // larger than 248 bytes, but even with the maximum case with
765  // RegI=10/RegF=8/CR=1/H=1, we end up with SavSZ = 216, which should
766  // fit into SaveR19R20X.
767  // The unwinding opcodes can't describe the otherwise seemingly valid
768  // case for RegI=1 CR=1, that would start with a
769  // "stp x19, lr, [sp, #-...]!" as that fits neither SaveRegPX nor
770  // SaveLRPair.
771  return false;
773  if (Location != IntRegs || Inst.Offset != 8 * RegI ||
774  Inst.Register != 19 + RegI)
775  return false;
776  RegI += 2;
777  break;
779  if (Location != IntRegs || Inst.Offset != 8 * RegI)
780  return false;
781  if (Inst.Register == 19 + RegI)
782  RegI += 1;
783  else if (Inst.Register == 30)
784  StandaloneLR = true;
785  else
786  return false;
787  // Odd register; can't be any further int registers.
788  Location = FloatRegs;
789  break;
791  if (Location != IntRegs || Inst.Offset != 8 * RegI ||
792  Inst.Register != 19 + RegI)
793  return false;
794  RegI += 1;
795  StandaloneLR = true;
796  Location = FloatRegs;
797  break;
799  // Packed unwind can't handle prologs that only save one single
800  // float register.
801  return false;
803  if (Location != FloatRegs || RegF == 0 || Inst.Register != 8 + RegF ||
804  Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
805  return false;
806  RegF += 1;
807  Location = InputArgs;
808  break;
810  if (Location != Start2 || Inst.Register != 8)
811  return false;
812  Predecrement = Inst.Offset;
813  RegF = 2;
814  Location = FloatRegs;
815  break;
817  if ((Location != IntRegs && Location != FloatRegs) ||
818  Inst.Register != 8 + RegF ||
819  Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
820  return false;
821  RegF += 2;
822  Location = FloatRegs;
823  break;
825  if (Location == IntRegs)
826  RegI += 2;
827  else if (Location == FloatRegs)
828  RegF += 2;
829  else
830  return false;
831  break;
832  case Win64EH::UOP_Nop:
833  if (Location != IntRegs && Location != FloatRegs && Location != InputArgs)
834  return false;
835  Location = InputArgs;
836  Nops++;
837  break;
840  if (Location != Start2 && Location != IntRegs && Location != FloatRegs &&
841  Location != InputArgs && Location != StackAdjust)
842  return false;
843  // Can have either a single decrement, or a pair of decrements with
844  // 4080 and another decrement.
845  if (StackOffset == 0)
846  StackOffset = Inst.Offset;
847  else if (StackOffset != 4080)
848  return false;
849  else
850  StackOffset += Inst.Offset;
851  Location = StackAdjust;
852  break;
854  // Not allowing FPLRX after StackAdjust; if a StackAdjust is used, it
855  // should be followed by a FPLR instead.
856  if (Location != Start2 && Location != IntRegs && Location != FloatRegs &&
857  Location != InputArgs)
858  return false;
859  StackOffset = Inst.Offset;
860  Location = FrameRecord;
861  FPLRPair = true;
862  break;
864  // This can only follow after a StackAdjust
865  if (Location != StackAdjust || Inst.Offset != 0)
866  return false;
867  Location = FrameRecord;
868  FPLRPair = true;
869  break;
870  case Win64EH::UOP_SetFP:
871  if (Location != FrameRecord)
872  return false;
873  Location = End;
874  break;
875  }
876  }
877  if (RegI > 10 || RegF > 8)
878  return false;
879  if (StandaloneLR && FPLRPair)
880  return false;
881  if (FPLRPair && Location != End)
882  return false;
883  if (Nops != 0 && Nops != 4)
884  return false;
885  int H = Nops == 4;
886  // There's an inconsistency regarding packed unwind info with homed
887  // parameters; according to the documentation, the epilog shouldn't have
888  // the same corresponding nops (and thus, to set the H bit, we should
889  // require an epilog which isn't exactly symmetrical - we shouldn't accept
890  // an exact mirrored epilog for those cases), but in practice,
891  // RtlVirtualUnwind behaves as if it does expect the epilogue to contain
892  // the same nops. See https://github.com/llvm/llvm-project/issues/54879.
893  // To play it safe, don't produce packed unwind info with homed parameters.
894  if (H)
895  return false;
896  int IntSZ = 8 * RegI;
897  if (StandaloneLR)
898  IntSZ += 8;
899  int FpSZ = 8 * RegF; // RegF not yet decremented
900  int SavSZ = (IntSZ + FpSZ + 8 * 8 * H + 0xF) & ~0xF;
901  if (Predecrement != SavSZ)
902  return false;
903  if (FPLRPair && StackOffset < 16)
904  return false;
905  if (StackOffset % 16)
906  return false;
907  uint32_t FrameSize = (StackOffset + SavSZ) / 16;
908  if (FrameSize > 0x1FF)
909  return false;
910  assert(RegF != 1 && "One single float reg not allowed");
911  if (RegF > 0)
912  RegF--; // Convert from actual number of registers, to value stored
913  assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");
914  int Flag = 0x01; // Function segments not supported yet
915  int CR = FPLRPair ? 3 : StandaloneLR ? 1 : 0;
916  info->PackedInfo |= Flag << 0;
917  info->PackedInfo |= (FuncLength & 0x7FF) << 2;
918  info->PackedInfo |= (RegF & 0x7) << 13;
919  info->PackedInfo |= (RegI & 0xF) << 16;
920  info->PackedInfo |= (H & 0x1) << 20;
921  info->PackedInfo |= (CR & 0x3) << 21;
922  info->PackedInfo |= (FrameSize & 0x1FF) << 23;
923  return true;
924 }
925 
926 // Populate the .xdata section. The format of .xdata on ARM64 is documented at
927 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
929  bool TryPacked = true) {
930  // If this UNWIND_INFO already has a symbol, it's already been emitted.
931  if (info->Symbol)
932  return;
933  // If there's no unwind info here (not even a terminating UOP_End), the
934  // unwind info is considered bogus and skipped. If this was done in
935  // response to an explicit .seh_handlerdata, the associated trailing
936  // handler data is left orphaned in the xdata section.
937  if (info->empty()) {
938  info->EmitAttempted = true;
939  return;
940  }
941  if (info->EmitAttempted) {
942  // If we tried to emit unwind info before (due to an explicit
943  // .seh_handlerdata directive), but skipped it (because there was no
944  // valid information to emit at the time), and it later got valid unwind
945  // opcodes, we can't emit it here, because the trailing handler data
946  // was already emitted elsewhere in the xdata section.
947  streamer.getContext().reportError(
948  SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +
949  " skipped due to no unwind info at the time "
950  "(.seh_handlerdata too early?), but the function later "
951  "did get unwind info that can't be emitted");
952  return;
953  }
954 
955  simplifyARM64Opcodes(info->Instructions, false);
956  for (auto &I : info->EpilogMap)
957  simplifyARM64Opcodes(I.second.Instructions, true);
958 
959  MCContext &context = streamer.getContext();
960  MCSymbol *Label = context.createTempSymbol();
961 
962  streamer.emitValueToAlignment(4);
963  streamer.emitLabel(Label);
964  info->Symbol = Label;
965 
966  int64_t RawFuncLength;
967  if (!info->FuncletOrFuncEnd) {
968  report_fatal_error("FuncletOrFuncEnd not set");
969  } else {
970  // FIXME: GetAbsDifference tries to compute the length of the function
971  // immediately, before the whole file is emitted, but in general
972  // that's impossible: the size in bytes of certain assembler directives
973  // like .align and .fill is not known until the whole file is parsed and
974  // relaxations are applied. Currently, GetAbsDifference fails with a fatal
975  // error in that case. (We mostly don't hit this because inline assembly
976  // specifying those directives is rare, and we don't normally try to
977  // align loops on AArch64.)
978  //
979  // There are two potential approaches to delaying the computation. One,
980  // we could emit something like ".word (endfunc-beginfunc)/4+0x10800000",
981  // as long as we have some conservative estimate we could use to prove
982  // that we don't need to split the unwind data. Emitting the constant
983  // is straightforward, but there's no existing code for estimating the
984  // size of the function.
985  //
986  // The other approach would be to use a dedicated, relaxable fragment,
987  // which could grow to accommodate splitting the unwind data if
988  // necessary. This is more straightforward, since it automatically works
989  // without any new infrastructure, and it's consistent with how we handle
990  // relaxation in other contexts. But it would require some refactoring
991  // to move parts of the pdata/xdata emission into the implementation of
992  // a fragment. We could probably continue to encode the unwind codes
993  // here, but we'd have to emit the pdata, the xdata header, and the
994  // epilogue scopes later, since they depend on whether the we need to
995  // split the unwind data.
996  RawFuncLength = GetAbsDifference(streamer, info->FuncletOrFuncEnd,
997  info->Begin);
998  }
999  if (RawFuncLength > 0xFFFFF)
1000  report_fatal_error("SEH unwind data splitting not yet implemented");
1001  uint32_t FuncLength = (uint32_t)RawFuncLength / 4;
1002  uint32_t PrologCodeBytes = ARM64CountOfUnwindCodes(info->Instructions);
1003  uint32_t TotalCodeBytes = PrologCodeBytes;
1004 
1005  int PackedEpilogOffset =
1006  checkARM64PackedEpilog(streamer, info, PrologCodeBytes);
1007 
1008  if (PackedEpilogOffset >= 0 &&
1009  uint32_t(PackedEpilogOffset) < PrologCodeBytes &&
1010  !info->HandlesExceptions && FuncLength <= 0x7ff && TryPacked) {
1011  // Matching prolog/epilog and no exception handlers; check if the
1012  // prolog matches the patterns that can be described by the packed
1013  // format.
1014 
1015  // info->Symbol was already set even if we didn't actually write any
1016  // unwind info there. Keep using that as indicator that this unwind
1017  // info has been generated already.
1018 
1019  if (tryARM64PackedUnwind(info, FuncLength, PackedEpilogOffset))
1020  return;
1021  }
1022 
1023  // Process epilogs.
1025  // Epilogs processed so far.
1026  std::vector<MCSymbol *> AddedEpilogs;
1027 
1028  for (auto &I : info->EpilogMap) {
1029  MCSymbol *EpilogStart = I.first;
1030  auto &EpilogInstrs = I.second.Instructions;
1031  uint32_t CodeBytes = ARM64CountOfUnwindCodes(EpilogInstrs);
1032 
1033  MCSymbol* MatchingEpilog =
1034  FindMatchingEpilog(EpilogInstrs, AddedEpilogs, info);
1035  int PrologOffset;
1036  if (MatchingEpilog) {
1037  assert(EpilogInfo.find(MatchingEpilog) != EpilogInfo.end() &&
1038  "Duplicate epilog not found");
1039  EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
1040  // Clear the unwind codes in the EpilogMap, so that they don't get output
1041  // in the logic below.
1042  EpilogInstrs.clear();
1043  } else if ((PrologOffset = getARM64OffsetInProlog(info->Instructions,
1044  EpilogInstrs)) >= 0) {
1045  EpilogInfo[EpilogStart] = PrologOffset;
1046  // Clear the unwind codes in the EpilogMap, so that they don't get output
1047  // in the logic below.
1048  EpilogInstrs.clear();
1049  } else {
1050  EpilogInfo[EpilogStart] = TotalCodeBytes;
1051  TotalCodeBytes += CodeBytes;
1052  AddedEpilogs.push_back(EpilogStart);
1053  }
1054  }
1055 
1056  // Code Words, Epilog count, E, X, Vers, Function Length
1057  uint32_t row1 = 0x0;
1058  uint32_t CodeWords = TotalCodeBytes / 4;
1059  uint32_t CodeWordsMod = TotalCodeBytes % 4;
1060  if (CodeWordsMod)
1061  CodeWords++;
1062  uint32_t EpilogCount =
1063  PackedEpilogOffset >= 0 ? PackedEpilogOffset : info->EpilogMap.size();
1064  bool ExtensionWord = EpilogCount > 31 || TotalCodeBytes > 124;
1065  if (!ExtensionWord) {
1066  row1 |= (EpilogCount & 0x1F) << 22;
1067  row1 |= (CodeWords & 0x1F) << 27;
1068  }
1069  if (info->HandlesExceptions) // X
1070  row1 |= 1 << 20;
1071  if (PackedEpilogOffset >= 0) // E
1072  row1 |= 1 << 21;
1073  row1 |= FuncLength & 0x3FFFF;
1074  streamer.emitInt32(row1);
1075 
1076  // Extended Code Words, Extended Epilog Count
1077  if (ExtensionWord) {
1078  // FIXME: We should be able to split unwind info into multiple sections.
1079  if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
1080  report_fatal_error("SEH unwind data splitting not yet implemented");
1081  uint32_t row2 = 0x0;
1082  row2 |= (CodeWords & 0xFF) << 16;
1083  row2 |= (EpilogCount & 0xFFFF);
1084  streamer.emitInt32(row2);
1085  }
1086 
1087  if (PackedEpilogOffset < 0) {
1088  // Epilog Start Index, Epilog Start Offset
1089  for (auto &I : EpilogInfo) {
1090  MCSymbol *EpilogStart = I.first;
1091  uint32_t EpilogIndex = I.second;
1092  uint32_t EpilogOffset =
1093  (uint32_t)GetAbsDifference(streamer, EpilogStart, info->Begin);
1094  if (EpilogOffset)
1095  EpilogOffset /= 4;
1096  uint32_t row3 = EpilogOffset;
1097  row3 |= (EpilogIndex & 0x3FF) << 22;
1098  streamer.emitInt32(row3);
1099  }
1100  }
1101 
1102  // Emit prolog unwind instructions (in reverse order).
1103  uint8_t numInst = info->Instructions.size();
1104  for (uint8_t c = 0; c < numInst; ++c) {
1105  WinEH::Instruction inst = info->Instructions.back();
1106  info->Instructions.pop_back();
1107  ARM64EmitUnwindCode(streamer, inst);
1108  }
1109 
1110  // Emit epilog unwind instructions
1111  for (auto &I : info->EpilogMap) {
1112  auto &EpilogInstrs = I.second.Instructions;
1113  for (const WinEH::Instruction &inst : EpilogInstrs)
1114  ARM64EmitUnwindCode(streamer, inst);
1115  }
1116 
1117  int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
1118  assert(BytesMod >= 0);
1119  for (int i = 0; i < BytesMod; i++)
1120  streamer.emitInt8(0xE3);
1121 
1122  if (info->HandlesExceptions)
1123  streamer.emitValue(
1124  MCSymbolRefExpr::create(info->ExceptionHandler,
1126  4);
1127 }
1128 
1130  uint32_t Count = 0;
1131  for (const auto &I : Insns) {
1132  switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
1133  default:
1134  llvm_unreachable("Unsupported ARM unwind code");
1136  Count += 1;
1137  break;
1139  Count += 3;
1140  break;
1142  Count += 4;
1143  break;
1145  Count += 2;
1146  break;
1148  Count += 3;
1149  break;
1151  Count += 4;
1152  break;
1154  Count += 2;
1155  break;
1156  case Win64EH::UOP_SaveSP:
1157  Count += 1;
1158  break;
1160  Count += 1;
1161  break;
1163  Count += 1;
1164  break;
1166  Count += 1;
1167  break;
1169  Count += 2;
1170  break;
1171  case Win64EH::UOP_SaveLR:
1172  Count += 2;
1173  break;
1175  Count += 2;
1176  break;
1178  Count += 2;
1179  break;
1180  case Win64EH::UOP_Nop:
1181  case Win64EH::UOP_WideNop:
1182  case Win64EH::UOP_End:
1183  case Win64EH::UOP_EndNop:
1185  Count += 1;
1186  break;
1187  case Win64EH::UOP_Custom: {
1188  int J;
1189  for (J = 3; J > 0; J--)
1190  if (I.Offset & (0xffu << (8 * J)))
1191  break;
1192  Count += J + 1;
1193  break;
1194  }
1195  }
1196  }
1197  return Count;
1198 }
1199 
1201  bool *HasCustom = nullptr) {
1202  uint32_t Count = 0;
1203  for (const auto &I : Insns) {
1204  switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
1205  default:
1206  llvm_unreachable("Unsupported ARM unwind code");
1210  Count += 2;
1211  break;
1215  Count += 4;
1216  break;
1219  Count += 4;
1220  break;
1221  case Win64EH::UOP_SaveSP:
1222  Count += 2;
1223  break;
1226  Count += 2;
1227  break;
1231  Count += 4;
1232  break;
1233  case Win64EH::UOP_SaveLR:
1234  Count += 4;
1235  break;
1236  case Win64EH::UOP_Nop:
1237  case Win64EH::UOP_EndNop:
1238  Count += 2;
1239  break;
1240  case Win64EH::UOP_WideNop:
1242  Count += 4;
1243  break;
1244  case Win64EH::UOP_End:
1245  // This doesn't map to any instruction
1246  break;
1247  case Win64EH::UOP_Custom:
1248  // We can't reason about what instructions this maps to; return a
1249  // phony number to make sure we don't accidentally do epilog packing.
1250  Count += 1000;
1251  if (HasCustom)
1252  *HasCustom = true;
1253  break;
1254  }
1255  }
1256  return Count;
1257 }
1258 
1259 static void checkARMInstructions(MCStreamer &Streamer,
1261  const MCSymbol *Begin, const MCSymbol *End,
1263  if (!End)
1264  return;
1265  Optional<int64_t> MaybeDistance =
1266  GetOptionalAbsDifference(Streamer, End, Begin);
1267  if (!MaybeDistance)
1268  return;
1269  uint32_t Distance = (uint32_t)*MaybeDistance;
1270  bool HasCustom = false;
1271  uint32_t InstructionBytes = ARMCountOfInstructionBytes(Insns, &HasCustom);
1272  if (HasCustom)
1273  return;
1274  if (Distance != InstructionBytes) {
1275  Streamer.getContext().reportError(
1276  SMLoc(), "Incorrect size for " + Name + " " + Type + ": " +
1277  Twine(Distance) +
1278  " bytes of instructions in range, but .seh directives "
1279  "corresponding to " +
1280  Twine(InstructionBytes) + " bytes\n");
1281  }
1282 }
1283 
1284 static bool isARMTerminator(const WinEH::Instruction &inst) {
1285  switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
1286  case Win64EH::UOP_End:
1287  case Win64EH::UOP_EndNop:
1289  return true;
1290  default:
1291  return false;
1292  }
1293 }
1294 
1295 // Unwind opcode encodings and restrictions are documented at
1296 // https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling
1297 static void ARMEmitUnwindCode(MCStreamer &streamer,
1298  const WinEH::Instruction &inst) {
1299  uint32_t w, lr;
1300  int i;
1301  switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
1302  default:
1303  llvm_unreachable("Unsupported ARM unwind code");
1305  assert((inst.Offset & 3) == 0);
1306  assert(inst.Offset / 4 <= 0x7f);
1307  streamer.emitInt8(inst.Offset / 4);
1308  break;
1310  assert((inst.Register & ~0x5fff) == 0);
1311  lr = (inst.Register >> 14) & 1;
1312  w = 0x8000 | (inst.Register & 0x1fff) | (lr << 13);
1313  streamer.emitInt8((w >> 8) & 0xff);
1314  streamer.emitInt8((w >> 0) & 0xff);
1315  break;
1316  case Win64EH::UOP_SaveSP:
1317  assert(inst.Register <= 0x0f);
1318  streamer.emitInt8(0xc0 | inst.Register);
1319  break;
1321  assert(inst.Register >= 4 && inst.Register <= 7);
1322  assert(inst.Offset <= 1);
1323  streamer.emitInt8(0xd0 | (inst.Register - 4) | (inst.Offset << 2));
1324  break;
1326  assert(inst.Register >= 8 && inst.Register <= 11);
1327  assert(inst.Offset <= 1);
1328  streamer.emitInt8(0xd8 | (inst.Register - 8) | (inst.Offset << 2));
1329  break;
1331  assert(inst.Register >= 8 && inst.Register <= 15);
1332  streamer.emitInt8(0xe0 | (inst.Register - 8));
1333  break;
1335  assert((inst.Offset & 3) == 0);
1336  assert(inst.Offset / 4 <= 0x3ff);
1337  w = 0xe800 | (inst.Offset / 4);
1338  streamer.emitInt8((w >> 8) & 0xff);
1339  streamer.emitInt8((w >> 0) & 0xff);
1340  break;
1342  assert((inst.Register & ~0x40ff) == 0);
1343  lr = (inst.Register >> 14) & 1;
1344  w = 0xec00 | (inst.Register & 0x0ff) | (lr << 8);
1345  streamer.emitInt8((w >> 8) & 0xff);
1346  streamer.emitInt8((w >> 0) & 0xff);
1347  break;
1348  case Win64EH::UOP_SaveLR:
1349  assert((inst.Offset & 3) == 0);
1350  assert(inst.Offset / 4 <= 0x0f);
1351  streamer.emitInt8(0xef);
1352  streamer.emitInt8(inst.Offset / 4);
1353  break;
1355  assert(inst.Register <= 15);
1356  assert(inst.Offset <= 15);
1357  assert(inst.Register <= inst.Offset);
1358  streamer.emitInt8(0xf5);
1359  streamer.emitInt8((inst.Register << 4) | inst.Offset);
1360  break;
1362  assert(inst.Register >= 16 && inst.Register <= 31);
1363  assert(inst.Offset >= 16 && inst.Offset <= 31);
1364  assert(inst.Register <= inst.Offset);
1365  streamer.emitInt8(0xf6);
1366  streamer.emitInt8(((inst.Register - 16) << 4) | (inst.Offset - 16));
1367  break;
1369  assert((inst.Offset & 3) == 0);
1370  assert(inst.Offset / 4 <= 0xffff);
1371  w = inst.Offset / 4;
1372  streamer.emitInt8(0xf7);
1373  streamer.emitInt8((w >> 8) & 0xff);
1374  streamer.emitInt8((w >> 0) & 0xff);
1375  break;
1377  assert((inst.Offset & 3) == 0);
1378  assert(inst.Offset / 4 <= 0xffffff);
1379  w = inst.Offset / 4;
1380  streamer.emitInt8(0xf8);
1381  streamer.emitInt8((w >> 16) & 0xff);
1382  streamer.emitInt8((w >> 8) & 0xff);
1383  streamer.emitInt8((w >> 0) & 0xff);
1384  break;
1386  assert((inst.Offset & 3) == 0);
1387  assert(inst.Offset / 4 <= 0xffff);
1388  w = inst.Offset / 4;
1389  streamer.emitInt8(0xf9);
1390  streamer.emitInt8((w >> 8) & 0xff);
1391  streamer.emitInt8((w >> 0) & 0xff);
1392  break;
1394  assert((inst.Offset & 3) == 0);
1395  assert(inst.Offset / 4 <= 0xffffff);
1396  w = inst.Offset / 4;
1397  streamer.emitInt8(0xfa);
1398  streamer.emitInt8((w >> 16) & 0xff);
1399  streamer.emitInt8((w >> 8) & 0xff);
1400  streamer.emitInt8((w >> 0) & 0xff);
1401  break;
1402  case Win64EH::UOP_Nop:
1403  streamer.emitInt8(0xfb);
1404  break;
1405  case Win64EH::UOP_WideNop:
1406  streamer.emitInt8(0xfc);
1407  break;
1408  case Win64EH::UOP_EndNop:
1409  streamer.emitInt8(0xfd);
1410  break;
1412  streamer.emitInt8(0xfe);
1413  break;
1414  case Win64EH::UOP_End:
1415  streamer.emitInt8(0xff);
1416  break;
1417  case Win64EH::UOP_Custom:
1418  for (i = 3; i > 0; i--)
1419  if (inst.Offset & (0xffu << (8 * i)))
1420  break;
1421  for (; i >= 0; i--)
1422  streamer.emitInt8((inst.Offset >> (8 * i)) & 0xff);
1423  break;
1424  }
1425 }
1426 
1427 // Check if an epilog exists as a subset of the end of a prolog (backwards).
1428 // An epilog may end with one out of three different end opcodes; if this
1429 // is the first epilog that shares opcodes with the prolog, we can tolerate
1430 // that this opcode differs (and the caller will update the prolog to use
1431 // the same end opcode as the epilog). If another epilog already shares
1432 // opcodes with the prolog, the ending opcode must be a strict match.
1433 static int getARMOffsetInProlog(const std::vector<WinEH::Instruction> &Prolog,
1434  const std::vector<WinEH::Instruction> &Epilog,
1435  bool CanTweakProlog) {
1436  // Can't find an epilog as a subset if it is longer than the prolog.
1437  if (Epilog.size() > Prolog.size())
1438  return -1;
1439 
1440  // Check that the epilog actually is a perfect match for the end (backwrds)
1441  // of the prolog.
1442  // If we can adjust the prolog afterwards, don't check that the end opcodes
1443  // match.
1444  int EndIdx = CanTweakProlog ? 1 : 0;
1445  for (int I = Epilog.size() - 1; I >= EndIdx; I--) {
1446  // TODO: Could also allow minor mismatches, e.g. "add sp, #16" vs
1447  // "push {r0-r3}".
1448  if (Prolog[I] != Epilog[Epilog.size() - 1 - I])
1449  return -1;
1450  }
1451 
1452  if (CanTweakProlog) {
1453  // Check that both prolog and epilog end with an expected end opcode.
1454  if (Prolog.front().Operation != Win64EH::UOP_End)
1455  return -1;
1456  if (Epilog.back().Operation != Win64EH::UOP_End &&
1457  Epilog.back().Operation != Win64EH::UOP_EndNop &&
1458  Epilog.back().Operation != Win64EH::UOP_WideEndNop)
1459  return -1;
1460  }
1461 
1462  // If the epilog was a subset of the prolog, find its offset.
1463  if (Epilog.size() == Prolog.size())
1464  return 0;
1466  &Prolog[Epilog.size()], Prolog.size() - Epilog.size()));
1467 }
1468 
1470  int PrologCodeBytes) {
1471  // Can only pack if there's one single epilog
1472  if (info->EpilogMap.size() != 1)
1473  return -1;
1474 
1475  const WinEH::FrameInfo::Epilog &EpilogInfo = info->EpilogMap.begin()->second;
1476  // Can only pack if the epilog is unconditional
1477  if (EpilogInfo.Condition != 0xe) // ARMCC::AL
1478  return -1;
1479 
1480  const std::vector<WinEH::Instruction> &Epilog = EpilogInfo.Instructions;
1481  // Make sure we have at least the trailing end opcode
1482  if (info->Instructions.empty() || Epilog.empty())
1483  return -1;
1484 
1485  // Check that the epilog actually is at the very end of the function,
1486  // otherwise it can't be packed.
1488  streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);
1489  if (!MaybeDistance)
1490  return -1;
1491  uint32_t DistanceFromEnd = (uint32_t)*MaybeDistance;
1492  uint32_t InstructionBytes = ARMCountOfInstructionBytes(Epilog);
1493  if (DistanceFromEnd != InstructionBytes)
1494  return -1;
1495 
1496  int RetVal = -1;
1497  // Even if we don't end up sharing opcodes with the prolog, we can still
1498  // write the offset as a packed offset, if the single epilog is located at
1499  // the end of the function and the offset (pointing after the prolog) fits
1500  // as a packed offset.
1501  if (PrologCodeBytes <= 31 &&
1502  PrologCodeBytes + ARMCountOfUnwindCodes(Epilog) <= 63)
1503  RetVal = PrologCodeBytes;
1504 
1505  int Offset =
1506  getARMOffsetInProlog(info->Instructions, Epilog, /*CanTweakProlog=*/true);
1507  if (Offset < 0)
1508  return RetVal;
1509 
1510  // Check that the offset and prolog size fits in the first word; it's
1511  // unclear whether the epilog count in the extension word can be taken
1512  // as packed epilog offset.
1513  if (Offset > 31 || PrologCodeBytes > 63)
1514  return RetVal;
1515 
1516  // Replace the regular end opcode of the prolog with the one from the
1517  // epilog.
1518  info->Instructions.front() = Epilog.back();
1519 
1520  // As we choose to express the epilog as part of the prolog, remove the
1521  // epilog from the map, so we don't try to emit its opcodes.
1522  info->EpilogMap.clear();
1523  return Offset;
1524 }
1525 
1526 static bool parseRegMask(unsigned Mask, bool &HasLR, bool &HasR11,
1527  unsigned &Folded, int &IntRegs) {
1528  if (Mask & (1 << 14)) {
1529  HasLR = true;
1530  Mask &= ~(1 << 14);
1531  }
1532  if (Mask & (1 << 11)) {
1533  HasR11 = true;
1534  Mask &= ~(1 << 11);
1535  }
1536  Folded = 0;
1537  IntRegs = -1;
1538  if (!Mask)
1539  return true;
1540  int First = 0;
1541  // Shift right until we have the bits at the bottom
1542  while ((Mask & 1) == 0) {
1543  First++;
1544  Mask >>= 1;
1545  }
1546  if ((Mask & (Mask + 1)) != 0)
1547  return false; // Not a consecutive series of bits? Can't be packed.
1548  // Count the bits
1549  int N = 0;
1550  while (Mask & (1 << N))
1551  N++;
1552  if (First < 4) {
1553  if (First + N < 4)
1554  return false;
1555  Folded = 4 - First;
1556  N -= Folded;
1557  First = 4;
1558  }
1559  if (First > 4)
1560  return false; // Can't be packed
1561  if (N >= 1)
1562  IntRegs = N - 1;
1563  return true;
1564 }
1565 
1567  uint32_t FuncLength) {
1568  int Step = 0;
1569  bool Homing = false;
1570  bool HasR11 = false;
1571  bool HasChain = false;
1572  bool HasLR = false;
1573  int IntRegs = -1; // r4 - r(4+N)
1574  int FloatRegs = -1; // d8 - d(8+N)
1575  unsigned PF = 0; // Number of extra pushed registers
1576  unsigned StackAdjust = 0;
1577  // Iterate over the prolog and check that all opcodes exactly match
1578  // the canonical order and form.
1579  for (const WinEH::Instruction &Inst : info->Instructions) {
1580  switch (Inst.Operation) {
1581  default:
1582  llvm_unreachable("Unsupported ARM unwind code");
1583  case Win64EH::UOP_Custom:
1590  // Can't be packed
1591  return false;
1592  case Win64EH::UOP_SaveSP:
1593  // Can't be packed; we can't rely on restoring sp from r11 when
1594  // unwinding a packed prologue.
1595  return false;
1596  case Win64EH::UOP_SaveLR:
1597  // Can't be present in a packed prologue
1598  return false;
1599 
1600  case Win64EH::UOP_End:
1601  case Win64EH::UOP_EndNop:
1603  if (Step != 0)
1604  return false;
1605  Step = 1;
1606  break;
1607 
1610  // push {r4-r11,lr}
1611  if (Step != 1 && Step != 2)
1612  return false;
1613  assert(Inst.Register >= 4 && Inst.Register <= 11); // r4-rX
1614  assert(Inst.Offset <= 1); // Lr
1615  IntRegs = Inst.Register - 4;
1616  if (Inst.Register == 11) {
1617  HasR11 = true;
1618  IntRegs--;
1619  }
1620  if (Inst.Offset)
1621  HasLR = true;
1622  Step = 3;
1623  break;
1624 
1626  if (Step == 1 && Inst.Register == 0x0f) {
1627  // push {r0-r3}
1628  Homing = true;
1629  Step = 2;
1630  break;
1631  }
1634  if (Step != 1 && Step != 2)
1635  return false;
1636  // push {r4-r9,r11,lr}
1637  // push {r11,lr}
1638  // push {r1-r5}
1639  if (!parseRegMask(Inst.Register, HasLR, HasR11, PF, IntRegs))
1640  return false;
1641  Step = 3;
1642  break;
1643 
1644  case Win64EH::UOP_Nop:
1645  // mov r11, sp
1646  if (Step != 3 || !HasR11 || IntRegs >= 0 || PF > 0)
1647  return false;
1648  HasChain = true;
1649  Step = 4;
1650  break;
1651  case Win64EH::UOP_WideNop:
1652  // add.w r11, sp, #xx
1653  if (Step != 3 || !HasR11 || (IntRegs < 0 && PF == 0))
1654  return false;
1655  HasChain = true;
1656  Step = 4;
1657  break;
1658 
1660  if (Step != 1 && Step != 2 && Step != 3 && Step != 4)
1661  return false;
1662  assert(Inst.Register >= 8 && Inst.Register <= 15);
1663  if (Inst.Register == 15)
1664  return false; // Can't pack this case, R==7 means no IntRegs
1665  if (IntRegs >= 0)
1666  return false;
1667  FloatRegs = Inst.Register - 8;
1668  Step = 5;
1669  break;
1670 
1673  if (Step != 1 && Step != 2 && Step != 3 && Step != 4 && Step != 5)
1674  return false;
1675  if (PF > 0) // Can't have both folded and explicit stack allocation
1676  return false;
1677  if (Inst.Offset / 4 >= 0x3f4)
1678  return false;
1679  StackAdjust = Inst.Offset / 4;
1680  Step = 6;
1681  break;
1682  }
1683  }
1684  if (HasR11 && !HasChain) {
1685  if (IntRegs + 4 == 10) {
1686  // r11 stored, but not chaining; can be packed if already saving r4-r10
1687  // and we can fit r11 into this range.
1688  IntRegs++;
1689  HasR11 = false;
1690  } else
1691  return false;
1692  }
1693  if (HasChain && !HasLR)
1694  return false;
1695 
1696  // Packed uneind info can't express multiple epilogues.
1697  if (info->EpilogMap.size() > 1)
1698  return false;
1699 
1700  unsigned EF = 0;
1701  int Ret = 0;
1702  if (info->EpilogMap.size() == 0) {
1703  Ret = 3; // No epilogue
1704  } else {
1705  // As the prologue and epilogue aren't exact mirrors of each other,
1706  // we have to check the epilogue too and see if it matches what we've
1707  // concluded from the prologue.
1708  const WinEH::FrameInfo::Epilog &EpilogInfo =
1709  info->EpilogMap.begin()->second;
1710  if (EpilogInfo.Condition != 0xe) // ARMCC::AL
1711  return false;
1712  const std::vector<WinEH::Instruction> &Epilog = EpilogInfo.Instructions;
1714  streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);
1715  if (!MaybeDistance)
1716  return false;
1717  uint32_t DistanceFromEnd = (uint32_t)*MaybeDistance;
1718  uint32_t InstructionBytes = ARMCountOfInstructionBytes(Epilog);
1719  if (DistanceFromEnd != InstructionBytes)
1720  return false;
1721 
1722  bool GotStackAdjust = false;
1723  bool GotFloatRegs = false;
1724  bool GotIntRegs = false;
1725  bool GotHomingRestore = false;
1726  bool GotLRRestore = false;
1727  bool NeedsReturn = false;
1728  bool GotReturn = false;
1729 
1730  Step = 6;
1731  for (const WinEH::Instruction &Inst : Epilog) {
1732  switch (Inst.Operation) {
1733  default:
1734  llvm_unreachable("Unsupported ARM unwind code");
1735  case Win64EH::UOP_Custom:
1742  case Win64EH::UOP_SaveSP:
1743  case Win64EH::UOP_Nop:
1744  case Win64EH::UOP_WideNop:
1745  // Can't be packed in an epilogue
1746  return false;
1747 
1750  if (Inst.Offset / 4 >= 0x3f4)
1751  return false;
1752  if (Step == 6) {
1753  if (Homing && FloatRegs < 0 && IntRegs < 0 && StackAdjust == 0 &&
1754  PF == 0 && Inst.Offset == 16) {
1755  GotHomingRestore = true;
1756  Step = 10;
1757  } else {
1758  if (StackAdjust > 0) {
1759  // Got stack adjust in prologue too; must match.
1760  if (StackAdjust != Inst.Offset / 4)
1761  return false;
1762  GotStackAdjust = true;
1763  } else if (PF == Inst.Offset / 4) {
1764  // Folded prologue, non-folded epilogue
1765  StackAdjust = Inst.Offset / 4;
1766  GotStackAdjust = true;
1767  } else {
1768  // StackAdjust == 0 in prologue, mismatch
1769  return false;
1770  }
1771  Step = 7;
1772  }
1773  } else if (Step == 7 || Step == 8 || Step == 9) {
1774  if (!Homing || Inst.Offset != 16)
1775  return false;
1776  GotHomingRestore = true;
1777  Step = 10;
1778  } else
1779  return false;
1780  break;
1781 
1783  if (Step != 6 && Step != 7)
1784  return false;
1785  assert(Inst.Register >= 8 && Inst.Register <= 15);
1786  if (FloatRegs != (int)(Inst.Register - 8))
1787  return false;
1788  GotFloatRegs = true;
1789  Step = 8;
1790  break;
1791 
1794  // push {r4-r11,lr}
1795  if (Step != 6 && Step != 7 && Step != 8)
1796  return false;
1797  assert(Inst.Register >= 4 && Inst.Register <= 11); // r4-rX
1798  assert(Inst.Offset <= 1); // Lr
1799  if (Homing && HasLR) {
1800  // If homing and LR is backed up, we can either restore LR here
1801  // and return with Ret == 1 or 2, or return with SaveLR below
1802  if (Inst.Offset) {
1803  GotLRRestore = true;
1804  NeedsReturn = true;
1805  } else {
1806  // Expecting a separate SaveLR below
1807  }
1808  } else {
1809  if (HasLR != (Inst.Offset == 1))
1810  return false;
1811  }
1812  GotLRRestore = Inst.Offset == 1;
1813  if (IntRegs < 0) // This opcode must include r4
1814  return false;
1815  int Expected = IntRegs;
1816  if (HasChain) {
1817  // Can't express r11 here unless IntRegs describe r4-r10
1818  if (IntRegs != 6)
1819  return false;
1820  Expected++;
1821  }
1822  if (Expected != (int)(Inst.Register - 4))
1823  return false;
1824  GotIntRegs = true;
1825  Step = 9;
1826  break;
1827  }
1828 
1831  if (Step != 6 && Step != 7 && Step != 8)
1832  return false;
1833  // push {r4-r9,r11,lr}
1834  // push {r11,lr}
1835  // push {r1-r5}
1836  bool CurHasLR = false, CurHasR11 = false;
1837  int Regs;
1838  if (!parseRegMask(Inst.Register, CurHasLR, CurHasR11, EF, Regs))
1839  return false;
1840  if (EF > 0) {
1841  if (EF != PF && EF != StackAdjust)
1842  return false;
1843  }
1844  if (Homing && HasLR) {
1845  // If homing and LR is backed up, we can either restore LR here
1846  // and return with Ret == 1 or 2, or return with SaveLR below
1847  if (CurHasLR) {
1848  GotLRRestore = true;
1849  NeedsReturn = true;
1850  } else {
1851  // Expecting a separate SaveLR below
1852  }
1853  } else {
1854  if (CurHasLR != HasLR)
1855  return false;
1856  GotLRRestore = CurHasLR;
1857  }
1858  int Expected = IntRegs;
1859  if (HasChain) {
1860  // If we have chaining, the mask must have included r11.
1861  if (!CurHasR11)
1862  return false;
1863  } else if (Expected == 7) {
1864  // If we don't have chaining, the mask could still include r11,
1865  // expressed as part of IntRegs Instead.
1866  Expected--;
1867  if (!CurHasR11)
1868  return false;
1869  } else {
1870  // Neither HasChain nor r11 included in IntRegs, must not have r11
1871  // here either.
1872  if (CurHasR11)
1873  return false;
1874  }
1875  if (Expected != Regs)
1876  return false;
1877  GotIntRegs = true;
1878  Step = 9;
1879  break;
1880  }
1881 
1882  case Win64EH::UOP_SaveLR:
1883  if (Step != 6 && Step != 7 && Step != 8 && Step != 9)
1884  return false;
1885  if (!Homing || Inst.Offset != 20 || GotLRRestore)
1886  return false;
1887  GotLRRestore = true;
1888  GotHomingRestore = true;
1889  Step = 10;
1890  break;
1891 
1892  case Win64EH::UOP_EndNop:
1894  GotReturn = true;
1895  Ret = (Inst.Operation == Win64EH::UOP_EndNop) ? 1 : 2;
1897  case Win64EH::UOP_End:
1898  if (Step != 6 && Step != 7 && Step != 8 && Step != 9 && Step != 10)
1899  return false;
1900  Step = 11;
1901  break;
1902  }
1903  }
1904 
1905  if (Step != 11)
1906  return false;
1907  if (StackAdjust > 0 && !GotStackAdjust && EF == 0)
1908  return false;
1909  if (FloatRegs >= 0 && !GotFloatRegs)
1910  return false;
1911  if (IntRegs >= 0 && !GotIntRegs)
1912  return false;
1913  if (Homing && !GotHomingRestore)
1914  return false;
1915  if (HasLR && !GotLRRestore)
1916  return false;
1917  if (NeedsReturn && !GotReturn)
1918  return false;
1919  }
1920 
1921  assert(PF == 0 || EF == 0 ||
1922  StackAdjust == 0); // Can't have adjust in all three
1923  if (PF > 0 || EF > 0) {
1924  StackAdjust = PF > 0 ? (PF - 1) : (EF - 1);
1925  assert(StackAdjust <= 3);
1926  StackAdjust |= 0x3f0;
1927  if (PF > 0)
1928  StackAdjust |= 1 << 2;
1929  if (EF > 0)
1930  StackAdjust |= 1 << 3;
1931  }
1932 
1933  assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");
1934  int Flag = info->Fragment ? 0x02 : 0x01;
1935  int H = Homing ? 1 : 0;
1936  int L = HasLR ? 1 : 0;
1937  int C = HasChain ? 1 : 0;
1938  assert(IntRegs < 0 || FloatRegs < 0);
1939  unsigned Reg, R;
1940  if (IntRegs >= 0) {
1941  Reg = IntRegs;
1942  assert(Reg <= 7);
1943  R = 0;
1944  } else if (FloatRegs >= 0) {
1945  Reg = FloatRegs;
1946  assert(Reg < 7);
1947  R = 1;
1948  } else {
1949  // No int or float regs stored (except possibly R11,LR)
1950  Reg = 7;
1951  R = 1;
1952  }
1953  info->PackedInfo |= Flag << 0;
1954  info->PackedInfo |= (FuncLength & 0x7FF) << 2;
1955  info->PackedInfo |= (Ret & 0x3) << 13;
1956  info->PackedInfo |= H << 15;
1957  info->PackedInfo |= Reg << 16;
1958  info->PackedInfo |= R << 19;
1959  info->PackedInfo |= L << 20;
1960  info->PackedInfo |= C << 21;
1961  assert(StackAdjust <= 0x3ff);
1962  info->PackedInfo |= StackAdjust << 22;
1963  return true;
1964 }
1965 
1966 // Populate the .xdata section. The format of .xdata on ARM is documented at
1967 // https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling
1969  bool TryPacked = true) {
1970  // If this UNWIND_INFO already has a symbol, it's already been emitted.
1971  if (info->Symbol)
1972  return;
1973  // If there's no unwind info here (not even a terminating UOP_End), the
1974  // unwind info is considered bogus and skipped. If this was done in
1975  // response to an explicit .seh_handlerdata, the associated trailing
1976  // handler data is left orphaned in the xdata section.
1977  if (info->empty()) {
1978  info->EmitAttempted = true;
1979  return;
1980  }
1981  if (info->EmitAttempted) {
1982  // If we tried to emit unwind info before (due to an explicit
1983  // .seh_handlerdata directive), but skipped it (because there was no
1984  // valid information to emit at the time), and it later got valid unwind
1985  // opcodes, we can't emit it here, because the trailing handler data
1986  // was already emitted elsewhere in the xdata section.
1987  streamer.getContext().reportError(
1988  SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +
1989  " skipped due to no unwind info at the time "
1990  "(.seh_handlerdata too early?), but the function later "
1991  "did get unwind info that can't be emitted");
1992  return;
1993  }
1994 
1995  MCContext &context = streamer.getContext();
1996  MCSymbol *Label = context.createTempSymbol();
1997 
1998  streamer.emitValueToAlignment(4);
1999  streamer.emitLabel(Label);
2000  info->Symbol = Label;
2001 
2002  if (!info->PrologEnd)
2003  streamer.getContext().reportError(SMLoc(), "Prologue in " +
2004  info->Function->getName() +
2005  " not correctly terminated");
2006 
2007  if (info->PrologEnd && !info->Fragment)
2008  checkARMInstructions(streamer, info->Instructions, info->Begin,
2009  info->PrologEnd, info->Function->getName(),
2010  "prologue");
2011  for (auto &I : info->EpilogMap) {
2012  MCSymbol *EpilogStart = I.first;
2013  auto &Epilog = I.second;
2014  checkARMInstructions(streamer, Epilog.Instructions, EpilogStart, Epilog.End,
2015  info->Function->getName(), "epilogue");
2016  if (Epilog.Instructions.empty() ||
2017  !isARMTerminator(Epilog.Instructions.back()))
2018  streamer.getContext().reportError(
2019  SMLoc(), "Epilogue in " + info->Function->getName() +
2020  " not correctly terminated");
2021  }
2022 
2023  Optional<int64_t> RawFuncLength;
2024  const MCExpr *FuncLengthExpr = nullptr;
2025  if (!info->FuncletOrFuncEnd) {
2026  report_fatal_error("FuncletOrFuncEnd not set");
2027  } else {
2028  // As the size of many thumb2 instructions isn't known until later,
2029  // we can't always rely on being able to calculate the absolute
2030  // length of the function here. If we can't calculate it, defer it
2031  // to a relocation.
2032  //
2033  // In such a case, we won't know if the function is too long so that
2034  // the unwind info would need to be split (but this isn't implemented
2035  // anyway).
2036  RawFuncLength =
2037  GetOptionalAbsDifference(streamer, info->FuncletOrFuncEnd, info->Begin);
2038  if (!RawFuncLength)
2039  FuncLengthExpr =
2040  GetSubDivExpr(streamer, info->FuncletOrFuncEnd, info->Begin, 2);
2041  }
2042  uint32_t FuncLength = 0;
2043  if (RawFuncLength)
2044  FuncLength = (uint32_t)*RawFuncLength / 2;
2045  if (FuncLength > 0x3FFFF)
2046  report_fatal_error("SEH unwind data splitting not yet implemented");
2047  uint32_t PrologCodeBytes = ARMCountOfUnwindCodes(info->Instructions);
2048  uint32_t TotalCodeBytes = PrologCodeBytes;
2049 
2050  if (!info->HandlesExceptions && RawFuncLength && FuncLength <= 0x7ff &&
2051  TryPacked) {
2052  // No exception handlers; check if the prolog and epilog matches the
2053  // patterns that can be described by the packed format. If we don't
2054  // know the exact function length yet, we can't do this.
2055 
2056  // info->Symbol was already set even if we didn't actually write any
2057  // unwind info there. Keep using that as indicator that this unwind
2058  // info has been generated already.
2059 
2060  if (tryARMPackedUnwind(streamer, info, FuncLength))
2061  return;
2062  }
2063 
2064  int PackedEpilogOffset =
2065  checkARMPackedEpilog(streamer, info, PrologCodeBytes);
2066 
2067  // Process epilogs.
2069  // Epilogs processed so far.
2070  std::vector<MCSymbol *> AddedEpilogs;
2071 
2072  bool CanTweakProlog = true;
2073  for (auto &I : info->EpilogMap) {
2074  MCSymbol *EpilogStart = I.first;
2075  auto &EpilogInstrs = I.second.Instructions;
2076  uint32_t CodeBytes = ARMCountOfUnwindCodes(EpilogInstrs);
2077 
2078  MCSymbol *MatchingEpilog =
2079  FindMatchingEpilog(EpilogInstrs, AddedEpilogs, info);
2080  int PrologOffset;
2081  if (MatchingEpilog) {
2082  assert(EpilogInfo.find(MatchingEpilog) != EpilogInfo.end() &&
2083  "Duplicate epilog not found");
2084  EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
2085  // Clear the unwind codes in the EpilogMap, so that they don't get output
2086  // in the logic below.
2087  EpilogInstrs.clear();
2088  } else if ((PrologOffset = getARMOffsetInProlog(
2089  info->Instructions, EpilogInstrs, CanTweakProlog)) >= 0) {
2090  if (CanTweakProlog) {
2091  // Replace the regular end opcode of the prolog with the one from the
2092  // epilog.
2093  info->Instructions.front() = EpilogInstrs.back();
2094  // Later epilogs need a strict match for the end opcode.
2095  CanTweakProlog = false;
2096  }
2097  EpilogInfo[EpilogStart] = PrologOffset;
2098  // Clear the unwind codes in the EpilogMap, so that they don't get output
2099  // in the logic below.
2100  EpilogInstrs.clear();
2101  } else {
2102  EpilogInfo[EpilogStart] = TotalCodeBytes;
2103  TotalCodeBytes += CodeBytes;
2104  AddedEpilogs.push_back(EpilogStart);
2105  }
2106  }
2107 
2108  // Code Words, Epilog count, F, E, X, Vers, Function Length
2109  uint32_t row1 = 0x0;
2110  uint32_t CodeWords = TotalCodeBytes / 4;
2111  uint32_t CodeWordsMod = TotalCodeBytes % 4;
2112  if (CodeWordsMod)
2113  CodeWords++;
2114  uint32_t EpilogCount =
2115  PackedEpilogOffset >= 0 ? PackedEpilogOffset : info->EpilogMap.size();
2116  bool ExtensionWord = EpilogCount > 31 || CodeWords > 15;
2117  if (!ExtensionWord) {
2118  row1 |= (EpilogCount & 0x1F) << 23;
2119  row1 |= (CodeWords & 0x0F) << 28;
2120  }
2121  if (info->HandlesExceptions) // X
2122  row1 |= 1 << 20;
2123  if (PackedEpilogOffset >= 0) // E
2124  row1 |= 1 << 21;
2125  if (info->Fragment) // F
2126  row1 |= 1 << 22;
2127  row1 |= FuncLength & 0x3FFFF;
2128  if (RawFuncLength)
2129  streamer.emitInt32(row1);
2130  else
2131  streamer.emitValue(
2132  MCBinaryExpr::createOr(FuncLengthExpr,
2133  MCConstantExpr::create(row1, context), context),
2134  4);
2135 
2136  // Extended Code Words, Extended Epilog Count
2137  if (ExtensionWord) {
2138  // FIXME: We should be able to split unwind info into multiple sections.
2139  if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
2140  report_fatal_error("SEH unwind data splitting not yet implemented");
2141  uint32_t row2 = 0x0;
2142  row2 |= (CodeWords & 0xFF) << 16;
2143  row2 |= (EpilogCount & 0xFFFF);
2144  streamer.emitInt32(row2);
2145  }
2146 
2147  if (PackedEpilogOffset < 0) {
2148  // Epilog Start Index, Epilog Start Offset
2149  for (auto &I : EpilogInfo) {
2150  MCSymbol *EpilogStart = I.first;
2151  uint32_t EpilogIndex = I.second;
2152 
2153  Optional<int64_t> MaybeEpilogOffset =
2154  GetOptionalAbsDifference(streamer, EpilogStart, info->Begin);
2155  const MCExpr *OffsetExpr = nullptr;
2156  uint32_t EpilogOffset = 0;
2157  if (MaybeEpilogOffset)
2158  EpilogOffset = *MaybeEpilogOffset / 2;
2159  else
2160  OffsetExpr = GetSubDivExpr(streamer, EpilogStart, info->Begin, 2);
2161 
2162  assert(info->EpilogMap.find(EpilogStart) != info->EpilogMap.end());
2163  unsigned Condition = info->EpilogMap[EpilogStart].Condition;
2164  assert(Condition <= 0xf);
2165 
2166  uint32_t row3 = EpilogOffset;
2167  row3 |= Condition << 20;
2168  row3 |= (EpilogIndex & 0x3FF) << 24;
2169  if (MaybeEpilogOffset)
2170  streamer.emitInt32(row3);
2171  else
2172  streamer.emitValue(
2174  OffsetExpr, MCConstantExpr::create(row3, context), context),
2175  4);
2176  }
2177  }
2178 
2179  // Emit prolog unwind instructions (in reverse order).
2180  uint8_t numInst = info->Instructions.size();
2181  for (uint8_t c = 0; c < numInst; ++c) {
2182  WinEH::Instruction inst = info->Instructions.back();
2183  info->Instructions.pop_back();
2184  ARMEmitUnwindCode(streamer, inst);
2185  }
2186 
2187  // Emit epilog unwind instructions
2188  for (auto &I : info->EpilogMap) {
2189  auto &EpilogInstrs = I.second.Instructions;
2190  for (uint32_t i = 0; i < EpilogInstrs.size(); i++) {
2191  WinEH::Instruction inst = EpilogInstrs[i];
2192  ARMEmitUnwindCode(streamer, inst);
2193  }
2194  }
2195 
2196  int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
2197  assert(BytesMod >= 0);
2198  for (int i = 0; i < BytesMod; i++)
2199  streamer.emitInt8(0xFB);
2200 
2201  if (info->HandlesExceptions)
2202  streamer.emitValue(
2203  MCSymbolRefExpr::create(info->ExceptionHandler,
2205  4);
2206 }
2207 
2208 static void ARMEmitRuntimeFunction(MCStreamer &streamer,
2209  const WinEH::FrameInfo *info) {
2210  MCContext &context = streamer.getContext();
2211 
2212  streamer.emitValueToAlignment(4);
2213  EmitSymbolRefWithOfs(streamer, info->Begin, info->Begin);
2214  if (info->PackedInfo)
2215  streamer.emitInt32(info->PackedInfo);
2216  else
2217  streamer.emitValue(
2219  context),
2220  4);
2221 }
2222 
2224  // Emit the unwind info structs first.
2225  for (const auto &CFI : Streamer.getWinFrameInfos()) {
2226  WinEH::FrameInfo *Info = CFI.get();
2227  if (Info->empty())
2228  continue;
2229  MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
2230  Streamer.switchSection(XData);
2231  ARM64EmitUnwindInfo(Streamer, Info);
2232  }
2233 
2234  // Now emit RUNTIME_FUNCTION entries.
2235  for (const auto &CFI : Streamer.getWinFrameInfos()) {
2236  WinEH::FrameInfo *Info = CFI.get();
2237  // ARM64EmitUnwindInfo above clears the info struct, so we can't check
2238  // empty here. But if a Symbol is set, we should create the corresponding
2239  // pdata entry.
2240  if (!Info->Symbol)
2241  continue;
2242  MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
2243  Streamer.switchSection(PData);
2244  ARMEmitRuntimeFunction(Streamer, Info);
2245  }
2246 }
2247 
2250  bool HandlerData) const {
2251  // Called if there's an .seh_handlerdata directive before the end of the
2252  // function. This forces writing the xdata record already here - and
2253  // in this case, the function isn't actually ended already, but the xdata
2254  // record needs to know the function length. In these cases, if the funclet
2255  // end hasn't been marked yet, the xdata function length won't cover the
2256  // whole function, only up to this point.
2257  if (!info->FuncletOrFuncEnd) {
2258  Streamer.switchSection(info->TextSection);
2259  info->FuncletOrFuncEnd = Streamer.emitCFILabel();
2260  }
2261  // Switch sections (the static function above is meant to be called from
2262  // here and from Emit().
2263  MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
2264  Streamer.switchSection(XData);
2265  ARM64EmitUnwindInfo(Streamer, info, /* TryPacked = */ !HandlerData);
2266 }
2267 
2269  // Emit the unwind info structs first.
2270  for (const auto &CFI : Streamer.getWinFrameInfos()) {
2271  WinEH::FrameInfo *Info = CFI.get();
2272  if (Info->empty())
2273  continue;
2274  MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
2275  Streamer.switchSection(XData);
2276  ARMEmitUnwindInfo(Streamer, Info);
2277  }
2278 
2279  // Now emit RUNTIME_FUNCTION entries.
2280  for (const auto &CFI : Streamer.getWinFrameInfos()) {
2281  WinEH::FrameInfo *Info = CFI.get();
2282  // ARMEmitUnwindInfo above clears the info struct, so we can't check
2283  // empty here. But if a Symbol is set, we should create the corresponding
2284  // pdata entry.
2285  if (!Info->Symbol)
2286  continue;
2287  MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
2288  Streamer.switchSection(PData);
2289  ARMEmitRuntimeFunction(Streamer, Info);
2290  }
2291 }
2292 
2295  bool HandlerData) const {
2296  // Called if there's an .seh_handlerdata directive before the end of the
2297  // function. This forces writing the xdata record already here - and
2298  // in this case, the function isn't actually ended already, but the xdata
2299  // record needs to know the function length. In these cases, if the funclet
2300  // end hasn't been marked yet, the xdata function length won't cover the
2301  // whole function, only up to this point.
2302  if (!info->FuncletOrFuncEnd) {
2303  Streamer.switchSection(info->TextSection);
2304  info->FuncletOrFuncEnd = Streamer.emitCFILabel();
2305  }
2306  // Switch sections (the static function above is meant to be called from
2307  // here and from Emit().
2308  MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
2309  Streamer.switchSection(XData);
2310  ARMEmitUnwindInfo(Streamer, info, /* TryPacked = */ !HandlerData);
2311 }
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:58
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::Win64EH::UNW_ExceptionHandler
@ UNW_ExceptionHandler
UNW_ExceptionHandler - Specifies that this function has an exception handler.
Definition: Win64EH.h:117
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:85
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
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:1259
Optional.h
GetOptionalAbsDifference
static Optional< int64_t > GetOptionalAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
Definition: MCWin64EH.cpp:266
ARMCountOfUnwindCodes
static uint32_t ARMCountOfUnwindCodes(ArrayRef< WinEH::Instruction > Insns)
Definition: MCWin64EH.cpp:1129
llvm::MCContext
Context object for machine code objects.
Definition: MCContext.h:76
llvm::MCConstantExpr::create
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
llvm::MCStreamer::emitInt8
void emitInt8(uint64_t Value)
Definition: MCStreamer.h:736
llvm::MapVector::clear
void clear()
Definition: MapVector.h:89
llvm::Win64EH::UOP_SaveFRegP
@ UOP_SaveFRegP
Definition: Win64EH.h:54
ARM64EmitUnwindCode
static void ARM64EmitUnwindCode(MCStreamer &streamer, const WinEH::Instruction &inst)
Definition: MCWin64EH.cpp:376
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
llvm::Win64EH::UOP_SaveNext
@ UOP_SaveNext
Definition: Win64EH.h:60
FloatRegs
static const MCPhysReg FloatRegs[32]
Definition: SparcAsmParser.cpp:153
getARM64OffsetInProlog
static int getARM64OffsetInProlog(const std::vector< WinEH::Instruction > &Prolog, const std::vector< WinEH::Instruction > &Epilog)
Definition: MCWin64EH.cpp:632
llvm::MCStreamer::emitValue
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
Definition: MCStreamer.cpp:178
getARMOffsetInProlog
static int getARMOffsetInProlog(const std::vector< WinEH::Instruction > &Prolog, const std::vector< WinEH::Instruction > &Epilog, bool CanTweakProlog)
Definition: MCWin64EH.cpp:1433
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:738
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:543
llvm::Win64EH::UOP_WideNop
@ UOP_WideNop
Definition: Win64EH.h:88
llvm::Optional< int64_t >
llvm::Win64EH::UOP_EndNop
@ UOP_EndNop
Definition: Win64EH.h:90
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:79
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:80
llvm::DiagnosticPredicateTy::Match
@ Match
RHS
Value * RHS
Definition: X86PartialReduction.cpp:76
ARMCountOfInstructionBytes
static uint32_t ARMCountOfInstructionBytes(ArrayRef< WinEH::Instruction > Insns, bool *HasCustom=nullptr)
Definition: MCWin64EH.cpp:1200
llvm::Win64EH::UNW_TerminateHandler
@ UNW_TerminateHandler
UNW_TerminateHandler - Specifies that this function has a termination handler.
Definition: Win64EH.h:120
llvm::Win64EH::UOP_TrapFrame
@ UOP_TrapFrame
Definition: Win64EH.h:61
llvm::Win64EH::UOP_Nop
@ UOP_Nop
Definition: Win64EH.h:58
llvm::RISCVFenceField::R
@ R
Definition: RISCVBaseInfo.h:241
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
EmitSymbolRefWithOfs
static void EmitSymbolRefWithOfs(MCStreamer &streamer, const MCSymbol *Base, const MCSymbol *Other)
Definition: MCWin64EH.cpp:131
llvm::Win64EH::UOP_SaveSP
@ UOP_SaveSP
Definition: Win64EH.h:79
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:2268
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:2248
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:693
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:1225
ARM64CountOfUnwindCodes
static uint32_t ARM64CountOfUnwindCodes(ArrayRef< WinEH::Instruction > Insns)
Definition: MCWin64EH.cpp:291
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:74
llvm::MCObjectStreamer
Streaming object file generation interface.
Definition: MCObjectStreamer.h:42
EmitUnwindInfo
static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info)
Definition: MCWin64EH.cpp:156
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::Win64EH::UNW_ChainInfo
@ UNW_ChainInfo
UNW_ChainInfo - Specifies that this UnwindInfo structure is chained to another one.
Definition: Win64EH.h:123
llvm::MCID::Flag
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Definition: MCInstrDesc.h:147
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:143
ARM64EmitUnwindInfo
static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info, bool TryPacked=true)
Definition: MCWin64EH.cpp:928
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:81
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
llvm::Win64EH::UOP_WideAllocHuge
@ UOP_WideAllocHuge
Definition: Win64EH.h:76
b2
int b2
Definition: README.txt:84
DebugLocVerifyLevel::None
@ None
GetAbsDifference
static int64_t GetAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
Definition: MCWin64EH.cpp:283
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
llvm::Win64EH::UOP_SaveXMM128Big
@ UOP_SaveXMM128Big
Definition: Win64EH.h:39
llvm::Win64EH::UOP_SaveFPLRX
@ UOP_SaveFPLRX
Definition: Win64EH.h:45
llvm::Win64EH::UOP_End
@ UOP_End
Definition: Win64EH.h:59
parseRegMask
static bool parseRegMask(unsigned Mask, bool &HasLR, bool &HasR11, unsigned &Folded, int &IntRegs)
Definition: MCWin64EH.cpp:1526
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:2293
llvm::MCStreamer::emitInt16
void emitInt16(uint64_t Value)
Definition: MCStreamer.h:737
llvm::Win64EH::UOP_AllocSmall
@ UOP_AllocSmall
Definition: Win64EH.h:32
checkARMPackedEpilog
static int checkARMPackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info, int PrologCodeBytes)
Definition: MCWin64EH.cpp:1469
llvm::Win64EH::UOP_WideSaveRegMask
@ UOP_WideSaveRegMask
Definition: Win64EH.h:78
llvm::MapVector::find
iterator find(const KeyT &Key)
Definition: MapVector.h:148
llvm::Win64EH::UOP_AllocHuge
@ UOP_AllocHuge
Definition: Win64EH.h:73
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:1968
llvm::Win64EH::UOP_SaveFRegD16D31
@ UOP_SaveFRegD16D31
Definition: Win64EH.h:86
EmitUnwindCode
static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin, WinEH::Instruction &inst)
Definition: MCWin64EH.cpp:63
ARMEmitUnwindCode
static void ARMEmitUnwindCode(MCStreamer &streamer, const WinEH::Instruction &inst)
Definition: MCWin64EH.cpp:1297
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:144
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:2208
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::Win64EH::UOP_SaveFReg
@ UOP_SaveFReg
Definition: Win64EH.h:52
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:1037
llvm::Win64EH::UOP_SaveLR
@ UOP_SaveLR
Definition: Win64EH.h:84
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::MCObjectStreamer::getAssembler
MCAssembler & getAssembler()
Definition: MCObjectStreamer.h:128
IntRegs
static const MCPhysReg IntRegs[32]
Definition: SparcAsmParser.cpp:143
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
simplifyARM64Opcodes
static void simplifyARM64Opcodes(std::vector< WinEH::Instruction > &Instructions, bool Reverse)
Definition: MCWin64EH.cpp:568
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
llvm::MapVector::lookup
ValueT lookup(const KeyT &Key) const
Definition: MapVector.h:111
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 is a class to represent an offset with 2 dimensions, named fixed and scalable,...
Definition: TypeSize.h:134
llvm::MCSection
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition: MCSection.h:39
LLVM_FALLTHROUGH
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
Definition: Compiler.h:280
llvm::MCContext::createTempSymbol
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:324
Prolog
@ Prolog
Definition: AArch64LowerHomogeneousPrologEpilog.cpp:125
llvm::Win64EH::UnwindEmitter::EmitUnwindInfo
void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override
Definition: MCWin64EH.cpp:243
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:2223
checkARM64PackedEpilog
static int checkARM64PackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info, int PrologCodeBytes)
Definition: MCWin64EH.cpp:652
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
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:94
uint16_t
Epilog
@ Epilog
Definition: AArch64LowerHomogeneousPrologEpilog.cpp:125
llvm::Win64EH::UOP_SaveR19R20X
@ UOP_SaveR19R20X
Definition: Win64EH.h:44
llvm::WinEH::FrameInfo::Epilog::Instructions
std::vector< Instruction > Instructions
Definition: MCWinEH.h:59
llvm::WinEH::FrameInfo::Epilog::Condition
unsigned Condition
Definition: MCWinEH.h:60
llvm::MCStreamer::getWinFrameInfos
ArrayRef< std::unique_ptr< WinEH::FrameInfo > > getWinFrameInfos() const
Definition: MCStreamer.h:321
llvm::Win64EH::UOP_SaveFRegD8D15
@ UOP_SaveFRegD8D15
Definition: Win64EH.h:82
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:254
tryARMPackedUnwind
static bool tryARMPackedUnwind(MCStreamer &streamer, WinEH::FrameInfo *info, uint32_t FuncLength)
Definition: MCWin64EH.cpp:1566
llvm::Win64EH::UOP_SaveNonVolBig
@ UOP_SaveNonVolBig
Definition: Win64EH.h:35
llvm::WinEH::FrameInfo
Definition: MCWinEH.h:39
llvm::MCStreamer::getContext
MCContext & getContext() const
Definition: MCStreamer.h:293
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::WinEH::Instruction
Definition: MCWinEH.h:21
llvm::MCStreamer::emitValueToAlignment
virtual void emitValueToAlignment(unsigned ByteAlignment, int64_t Value=0, unsigned ValueSize=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
Definition: MCStreamer.cpp:1212
llvm::Win64EH::UOP_WideAllocLarge
@ UOP_WideAllocLarge
Definition: Win64EH.h:75
isARMTerminator
static bool isARMTerminator(const WinEH::Instruction &inst)
Definition: MCWin64EH.cpp:1284
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:227
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:54
llvm::sampleprof::Base
@ Base
Definition: Discriminator.h:58
llvm::Win64EH::UOP_WideEndNop
@ UOP_WideEndNop
Definition: Win64EH.h:91
Other
Optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:1237
CountOfUnwindCodes
static uint8_t CountOfUnwindCodes(std::vector< WinEH::Instruction > &Insns)
Definition: MCWin64EH.cpp:26
MCWin64EH.h
llvm::Win64EH::UOP_SaveRegMask
@ UOP_SaveRegMask
Definition: Win64EH.h:83
llvm::Win64EH::UOP_AllocLarge
@ UOP_AllocLarge
Definition: Win64EH.h:31