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