LLVM  15.0.0git
MCWin64EH.cpp
Go to the documentation of this file.
1 //===- lib/MC/MCWin64EH.cpp - MCWin64EH implementation --------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/MC/MCWin64EH.h"
10 #include "llvm/ADT/Twine.h"
11 #include "llvm/MC/MCContext.h"
12 #include "llvm/MC/MCExpr.h"
14 #include "llvm/MC/MCStreamer.h"
15 #include "llvm/MC/MCSymbol.h"
16 #include "llvm/Support/Win64EH.h"
17 namespace llvm {
18 class MCSection;
19 }
20 
21 using namespace llvm;
22 
23 // NOTE: All relocations generated here are 4-byte image-relative.
24 
25 static uint8_t CountOfUnwindCodes(std::vector<WinEH::Instruction> &Insns) {
26  uint8_t Count = 0;
27  for (const auto &I : Insns) {
28  switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
29  default:
30  llvm_unreachable("Unsupported unwind code");
35  Count += 1;
36  break;
39  Count += 2;
40  break;
43  Count += 3;
44  break;
46  Count += (I.Offset > 512 * 1024 - 8) ? 3 : 2;
47  break;
48  }
49  }
50  return Count;
51 }
52 
53 static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
54  const MCSymbol *RHS) {
55  MCContext &Context = Streamer.getContext();
56  const MCExpr *Diff =
59  Streamer.emitValue(Diff, 1);
60 }
61 
62 static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
63  WinEH::Instruction &inst) {
64  uint8_t b2;
65  uint16_t w;
66  b2 = (inst.Operation & 0x0F);
67  switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
68  default:
69  llvm_unreachable("Unsupported unwind code");
71  EmitAbsDifference(streamer, inst.Label, begin);
72  b2 |= (inst.Register & 0x0F) << 4;
73  streamer.emitInt8(b2);
74  break;
76  EmitAbsDifference(streamer, inst.Label, begin);
77  if (inst.Offset > 512 * 1024 - 8) {
78  b2 |= 0x10;
79  streamer.emitInt8(b2);
80  w = inst.Offset & 0xFFF8;
81  streamer.emitInt16(w);
82  w = inst.Offset >> 16;
83  } else {
84  streamer.emitInt8(b2);
85  w = inst.Offset >> 3;
86  }
87  streamer.emitInt16(w);
88  break;
90  b2 |= (((inst.Offset - 8) >> 3) & 0x0F) << 4;
91  EmitAbsDifference(streamer, inst.Label, begin);
92  streamer.emitInt8(b2);
93  break;
95  EmitAbsDifference(streamer, inst.Label, begin);
96  streamer.emitInt8(b2);
97  break;
100  b2 |= (inst.Register & 0x0F) << 4;
101  EmitAbsDifference(streamer, inst.Label, begin);
102  streamer.emitInt8(b2);
103  w = inst.Offset >> 3;
105  w >>= 1;
106  streamer.emitInt16(w);
107  break;
110  b2 |= (inst.Register & 0x0F) << 4;
111  EmitAbsDifference(streamer, inst.Label, begin);
112  streamer.emitInt8(b2);
114  w = inst.Offset & 0xFFF0;
115  else
116  w = inst.Offset & 0xFFF8;
117  streamer.emitInt16(w);
118  w = inst.Offset >> 16;
119  streamer.emitInt16(w);
120  break;
122  if (inst.Offset == 1)
123  b2 |= 0x10;
124  EmitAbsDifference(streamer, inst.Label, begin);
125  streamer.emitInt8(b2);
126  break;
127  }
128 }
129 
130 static void EmitSymbolRefWithOfs(MCStreamer &streamer,
131  const MCSymbol *Base,
132  const MCSymbol *Other) {
133  MCContext &Context = streamer.getContext();
136  const MCExpr *Ofs = MCBinaryExpr::createSub(OtherRef, BaseRef, Context);
137  const MCSymbolRefExpr *BaseRefRel = MCSymbolRefExpr::create(Base,
139  Context);
140  streamer.emitValue(MCBinaryExpr::createAdd(BaseRefRel, Ofs, Context), 4);
141 }
142 
143 static void EmitRuntimeFunction(MCStreamer &streamer,
144  const WinEH::FrameInfo *info) {
145  MCContext &context = streamer.getContext();
146 
147  streamer.emitValueToAlignment(4);
148  EmitSymbolRefWithOfs(streamer, info->Begin, info->Begin);
149  EmitSymbolRefWithOfs(streamer, info->Begin, info->End);
150  streamer.emitValue(MCSymbolRefExpr::create(info->Symbol,
152  context), 4);
153 }
154 
155 static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
156  // If this UNWIND_INFO already has a symbol, it's already been emitted.
157  if (info->Symbol)
158  return;
159 
160  MCContext &context = streamer.getContext();
161  MCSymbol *Label = context.createTempSymbol();
162 
163  streamer.emitValueToAlignment(4);
164  streamer.emitLabel(Label);
165  info->Symbol = Label;
166 
167  // Upper 3 bits are the version number (currently 1).
168  uint8_t flags = 0x01;
169  if (info->ChainedParent)
170  flags |= Win64EH::UNW_ChainInfo << 3;
171  else {
172  if (info->HandlesUnwind)
173  flags |= Win64EH::UNW_TerminateHandler << 3;
174  if (info->HandlesExceptions)
175  flags |= Win64EH::UNW_ExceptionHandler << 3;
176  }
177  streamer.emitInt8(flags);
178 
179  if (info->PrologEnd)
180  EmitAbsDifference(streamer, info->PrologEnd, info->Begin);
181  else
182  streamer.emitInt8(0);
183 
184  uint8_t numCodes = CountOfUnwindCodes(info->Instructions);
185  streamer.emitInt8(numCodes);
186 
187  uint8_t frame = 0;
188  if (info->LastFrameInst >= 0) {
189  WinEH::Instruction &frameInst = info->Instructions[info->LastFrameInst];
190  assert(frameInst.Operation == Win64EH::UOP_SetFPReg);
191  frame = (frameInst.Register & 0x0F) | (frameInst.Offset & 0xF0);
192  }
193  streamer.emitInt8(frame);
194 
195  // Emit unwind instructions (in reverse order).
196  uint8_t numInst = info->Instructions.size();
197  for (uint8_t c = 0; c < numInst; ++c) {
198  WinEH::Instruction inst = info->Instructions.back();
199  info->Instructions.pop_back();
200  EmitUnwindCode(streamer, info->Begin, inst);
201  }
202 
203  // For alignment purposes, the instruction array will always have an even
204  // number of entries, with the final entry potentially unused (in which case
205  // the array will be one longer than indicated by the count of unwind codes
206  // field).
207  if (numCodes & 1) {
208  streamer.emitInt16(0);
209  }
210 
211  if (flags & (Win64EH::UNW_ChainInfo << 3))
212  EmitRuntimeFunction(streamer, info->ChainedParent);
213  else if (flags &
215  streamer.emitValue(MCSymbolRefExpr::create(info->ExceptionHandler,
217  context), 4);
218  else if (numCodes == 0) {
219  // The minimum size of an UNWIND_INFO struct is 8 bytes. If we're not
220  // a chained unwind info, if there is no handler, and if there are fewer
221  // than 2 slots used in the unwind code array, we have to pad to 8 bytes.
222  streamer.emitInt32(0);
223  }
224 }
225 
227  // Emit the unwind info structs first.
228  for (const auto &CFI : Streamer.getWinFrameInfos()) {
229  MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
230  Streamer.SwitchSection(XData);
231  ::EmitUnwindInfo(Streamer, CFI.get());
232  }
233 
234  // Now emit RUNTIME_FUNCTION entries.
235  for (const auto &CFI : Streamer.getWinFrameInfos()) {
236  MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
237  Streamer.SwitchSection(PData);
238  EmitRuntimeFunction(Streamer, CFI.get());
239  }
240 }
241 
244  bool HandlerData) const {
245  // Switch sections (the static function above is meant to be called from
246  // here and from Emit().
247  MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
248  Streamer.SwitchSection(XData);
249 
250  ::EmitUnwindInfo(Streamer, info);
251 }
252 
253 static int64_t GetAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
254  const MCSymbol *RHS) {
255  MCContext &Context = Streamer.getContext();
256  const MCExpr *Diff =
259  MCObjectStreamer *OS = (MCObjectStreamer *)(&Streamer);
260  // It should normally be possible to calculate the length of a function
261  // at this point, but it might not be possible in the presence of certain
262  // unusual constructs, like an inline asm with an alignment directive.
263  int64_t value;
264  if (!Diff->evaluateAsAbsolute(value, OS->getAssembler()))
265  report_fatal_error("Failed to evaluate function length in SEH unwind info");
266  return value;
267 }
268 
270  uint32_t Count = 0;
271  for (const auto &I : Insns) {
272  switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
273  default:
274  llvm_unreachable("Unsupported ARM64 unwind code");
276  Count += 1;
277  break;
279  Count += 2;
280  break;
282  Count += 4;
283  break;
285  Count += 1;
286  break;
288  Count += 1;
289  break;
291  Count += 1;
292  break;
294  Count += 2;
295  break;
297  Count += 2;
298  break;
300  Count += 2;
301  break;
303  Count += 2;
304  break;
306  Count += 2;
307  break;
309  Count += 2;
310  break;
312  Count += 2;
313  break;
315  Count += 2;
316  break;
318  Count += 2;
319  break;
320  case Win64EH::UOP_SetFP:
321  Count += 1;
322  break;
323  case Win64EH::UOP_AddFP:
324  Count += 2;
325  break;
326  case Win64EH::UOP_Nop:
327  Count += 1;
328  break;
329  case Win64EH::UOP_End:
330  Count += 1;
331  break;
333  Count += 1;
334  break;
336  Count += 1;
337  break;
339  Count += 1;
340  break;
342  Count += 1;
343  break;
345  Count += 1;
346  break;
347  }
348  }
349  return Count;
350 }
351 
352 // Unwind opcode encodings and restrictions are documented at
353 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
354 static void ARM64EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
355  const WinEH::Instruction &inst) {
356  uint8_t b, reg;
357  switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
358  default:
359  llvm_unreachable("Unsupported ARM64 unwind code");
361  b = (inst.Offset >> 4) & 0x1F;
362  streamer.emitInt8(b);
363  break;
365  uint16_t hw = (inst.Offset >> 4) & 0x7FF;
366  b = 0xC0;
367  b |= (hw >> 8);
368  streamer.emitInt8(b);
369  b = hw & 0xFF;
370  streamer.emitInt8(b);
371  break;
372  }
374  uint32_t w;
375  b = 0xE0;
376  streamer.emitInt8(b);
377  w = inst.Offset >> 4;
378  b = (w & 0x00FF0000) >> 16;
379  streamer.emitInt8(b);
380  b = (w & 0x0000FF00) >> 8;
381  streamer.emitInt8(b);
382  b = w & 0x000000FF;
383  streamer.emitInt8(b);
384  break;
385  }
386  case Win64EH::UOP_SetFP:
387  b = 0xE1;
388  streamer.emitInt8(b);
389  break;
390  case Win64EH::UOP_AddFP:
391  b = 0xE2;
392  streamer.emitInt8(b);
393  b = (inst.Offset >> 3);
394  streamer.emitInt8(b);
395  break;
396  case Win64EH::UOP_Nop:
397  b = 0xE3;
398  streamer.emitInt8(b);
399  break;
401  b = 0x20;
402  b |= (inst.Offset >> 3) & 0x1F;
403  streamer.emitInt8(b);
404  break;
406  b = 0x80;
407  b |= ((inst.Offset - 1) >> 3) & 0x3F;
408  streamer.emitInt8(b);
409  break;
411  b = 0x40;
412  b |= (inst.Offset >> 3) & 0x3F;
413  streamer.emitInt8(b);
414  break;
416  assert(inst.Register >= 19 && "Saved reg must be >= 19");
417  reg = inst.Register - 19;
418  b = 0xD0 | ((reg & 0xC) >> 2);
419  streamer.emitInt8(b);
420  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
421  streamer.emitInt8(b);
422  break;
424  assert(inst.Register >= 19 && "Saved reg must be >= 19");
425  reg = inst.Register - 19;
426  b = 0xD4 | ((reg & 0x8) >> 3);
427  streamer.emitInt8(b);
428  b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
429  streamer.emitInt8(b);
430  break;
432  assert(inst.Register >= 19 && "Saved registers must be >= 19");
433  reg = inst.Register - 19;
434  b = 0xC8 | ((reg & 0xC) >> 2);
435  streamer.emitInt8(b);
436  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
437  streamer.emitInt8(b);
438  break;
440  assert(inst.Register >= 19 && "Saved registers must be >= 19");
441  reg = inst.Register - 19;
442  b = 0xCC | ((reg & 0xC) >> 2);
443  streamer.emitInt8(b);
444  b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
445  streamer.emitInt8(b);
446  break;
448  assert(inst.Register >= 19 && "Saved reg must be >= 19");
449  reg = inst.Register - 19;
450  assert((reg % 2) == 0 && "Saved reg must be 19+2*X");
451  reg /= 2;
452  b = 0xD6 | ((reg & 0x7) >> 2);
453  streamer.emitInt8(b);
454  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
455  streamer.emitInt8(b);
456  break;
458  assert(inst.Register >= 8 && "Saved dreg must be >= 8");
459  reg = inst.Register - 8;
460  b = 0xDC | ((reg & 0x4) >> 2);
461  streamer.emitInt8(b);
462  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
463  streamer.emitInt8(b);
464  break;
466  assert(inst.Register >= 8 && "Saved dreg must be >= 8");
467  reg = inst.Register - 8;
468  b = 0xDE;
469  streamer.emitInt8(b);
470  b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
471  streamer.emitInt8(b);
472  break;
474  assert(inst.Register >= 8 && "Saved dregs must be >= 8");
475  reg = inst.Register - 8;
476  b = 0xD8 | ((reg & 0x4) >> 2);
477  streamer.emitInt8(b);
478  b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
479  streamer.emitInt8(b);
480  break;
482  assert(inst.Register >= 8 && "Saved dregs must be >= 8");
483  reg = inst.Register - 8;
484  b = 0xDA | ((reg & 0x4) >> 2);
485  streamer.emitInt8(b);
486  b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
487  streamer.emitInt8(b);
488  break;
489  case Win64EH::UOP_End:
490  b = 0xE4;
491  streamer.emitInt8(b);
492  break;
494  b = 0xE6;
495  streamer.emitInt8(b);
496  break;
498  b = 0xE8;
499  streamer.emitInt8(b);
500  break;
502  b = 0xE9;
503  streamer.emitInt8(b);
504  break;
506  b = 0xEA;
507  streamer.emitInt8(b);
508  break;
510  b = 0xEC;
511  streamer.emitInt8(b);
512  break;
513  }
514 }
515 
516 // Returns the epilog symbol of an epilog with the exact same unwind code
517 // sequence, if it exists. Otherwise, returns nullptr.
518 // EpilogInstrs - Unwind codes for the current epilog.
519 // Epilogs - Epilogs that potentialy match the current epilog.
520 static MCSymbol*
521 FindMatchingEpilog(const std::vector<WinEH::Instruction>& EpilogInstrs,
522  const std::vector<MCSymbol *>& Epilogs,
523  const WinEH::FrameInfo *info) {
524  for (auto *EpilogStart : Epilogs) {
525  auto InstrsIter = info->EpilogMap.find(EpilogStart);
526  assert(InstrsIter != info->EpilogMap.end() &&
527  "Epilog not found in EpilogMap");
528  const auto &Instrs = InstrsIter->second;
529 
530  if (Instrs.size() != EpilogInstrs.size())
531  continue;
532 
533  bool Match = true;
534  for (unsigned i = 0; i < Instrs.size(); ++i)
535  if (Instrs[i] != EpilogInstrs[i]) {
536  Match = false;
537  break;
538  }
539 
540  if (Match)
541  return EpilogStart;
542  }
543  return nullptr;
544 }
545 
546 static void simplifyOpcodes(std::vector<WinEH::Instruction> &Instructions,
547  bool Reverse) {
548  unsigned PrevOffset = -1;
549  unsigned PrevRegister = -1;
550 
551  auto VisitInstruction = [&](WinEH::Instruction &Inst) {
552  // Convert 2-byte opcodes into equivalent 1-byte ones.
553  if (Inst.Operation == Win64EH::UOP_SaveRegP && Inst.Register == 29) {
554  Inst.Operation = Win64EH::UOP_SaveFPLR;
555  Inst.Register = -1;
556  } else if (Inst.Operation == Win64EH::UOP_SaveRegPX &&
557  Inst.Register == 29) {
558  Inst.Operation = Win64EH::UOP_SaveFPLRX;
559  Inst.Register = -1;
560  } else if (Inst.Operation == Win64EH::UOP_SaveRegPX &&
561  Inst.Register == 19 && Inst.Offset <= 248) {
562  Inst.Operation = Win64EH::UOP_SaveR19R20X;
563  Inst.Register = -1;
564  } else if (Inst.Operation == Win64EH::UOP_AddFP && Inst.Offset == 0) {
565  Inst.Operation = Win64EH::UOP_SetFP;
566  } else if (Inst.Operation == Win64EH::UOP_SaveRegP &&
567  Inst.Register == PrevRegister + 2 &&
568  Inst.Offset == PrevOffset + 16) {
569  Inst.Operation = Win64EH::UOP_SaveNext;
570  Inst.Register = -1;
571  Inst.Offset = 0;
572  // Intentionally not creating UOP_SaveNext for float register pairs,
573  // as current versions of Windows (up to at least 20.04) is buggy
574  // regarding SaveNext for float pairs.
575  }
576  // Update info about the previous instruction, for detecting if
577  // the next one can be made a UOP_SaveNext
578  if (Inst.Operation == Win64EH::UOP_SaveR19R20X) {
579  PrevOffset = 0;
580  PrevRegister = 19;
581  } else if (Inst.Operation == Win64EH::UOP_SaveRegPX) {
582  PrevOffset = 0;
583  PrevRegister = Inst.Register;
584  } else if (Inst.Operation == Win64EH::UOP_SaveRegP) {
585  PrevOffset = Inst.Offset;
586  PrevRegister = Inst.Register;
587  } else if (Inst.Operation == Win64EH::UOP_SaveNext) {
588  PrevRegister += 2;
589  PrevOffset += 16;
590  } else {
591  PrevRegister = -1;
592  PrevOffset = -1;
593  }
594  };
595 
596  // Iterate over instructions in a forward order (for prologues),
597  // backwards for epilogues (i.e. always reverse compared to how the
598  // opcodes are stored).
599  if (Reverse) {
600  for (auto It = Instructions.rbegin(); It != Instructions.rend(); It++)
601  VisitInstruction(*It);
602  } else {
603  for (WinEH::Instruction &Inst : Instructions)
604  VisitInstruction(Inst);
605  }
606 }
607 
608 // Check if an epilog exists as a subset of the end of a prolog (backwards).
609 static int getOffsetInProlog(const std::vector<WinEH::Instruction> &Prolog,
610  const std::vector<WinEH::Instruction> &Epilog) {
611  // Can't find an epilog as a subset if it is longer than the prolog.
612  if (Epilog.size() > Prolog.size())
613  return -1;
614 
615  // Check that the epilog actually is a perfect match for the end (backwrds)
616  // of the prolog.
617  for (int I = Epilog.size() - 1; I >= 0; I--) {
618  if (Prolog[I] != Epilog[Epilog.size() - 1 - I])
619  return -1;
620  }
621 
622  // If the epilog was a subset of the prolog, find its offset.
623  if (Epilog.size() == Prolog.size())
624  return 0;
626  &Prolog[Epilog.size()], Prolog.size() - Epilog.size()));
627 }
628 
630  int PrologCodeBytes) {
631  // Can only pack if there's one single epilog
632  if (info->EpilogMap.size() != 1)
633  return -1;
634 
635  const std::vector<WinEH::Instruction> &Epilog =
636  info->EpilogMap.begin()->second;
637 
638  // Check that the epilog actually is at the very end of the function,
639  // otherwise it can't be packed.
640  uint32_t DistanceFromEnd = (uint32_t)GetAbsDifference(
641  streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);
642  if (DistanceFromEnd / 4 != Epilog.size())
643  return -1;
644 
645  int RetVal = -1;
646  // Even if we don't end up sharing opcodes with the prolog, we can still
647  // write the offset as a packed offset, if the single epilog is located at
648  // the end of the function and the offset (pointing after the prolog) fits
649  // as a packed offset.
650  if (PrologCodeBytes <= 31 &&
651  PrologCodeBytes + ARM64CountOfUnwindCodes(Epilog) <= 124)
652  RetVal = PrologCodeBytes;
653 
654  int Offset = getOffsetInProlog(info->Instructions, Epilog);
655  if (Offset < 0)
656  return RetVal;
657 
658  // Check that the offset and prolog size fits in the first word; it's
659  // unclear whether the epilog count in the extension word can be taken
660  // as packed epilog offset.
661  if (Offset > 31 || PrologCodeBytes > 124)
662  return RetVal;
663 
664  // As we choose to express the epilog as part of the prolog, remove the
665  // epilog from the map, so we don't try to emit its opcodes.
666  info->EpilogMap.clear();
667  return Offset;
668 }
669 
671  int PackedEpilogOffset) {
672  if (PackedEpilogOffset == 0) {
673  // Fully symmetric prolog and epilog, should be ok for packed format.
674  // For CR=3, the corresponding synthesized epilog actually lacks the
675  // SetFP opcode, but unwinding should work just fine despite that
676  // (if at the SetFP opcode, the unwinder considers it as part of the
677  // function body and just unwinds the full prolog instead).
678  } else if (PackedEpilogOffset == 1) {
679  // One single case of differences between prolog and epilog is allowed:
680  // The epilog can lack a single SetFP that is the last opcode in the
681  // prolog, for the CR=3 case.
682  if (info->Instructions.back().Operation != Win64EH::UOP_SetFP)
683  return false;
684  } else {
685  // Too much difference between prolog and epilog.
686  return false;
687  }
688  unsigned RegI = 0, RegF = 0;
689  int Predecrement = 0;
690  enum {
691  Start,
692  Start2,
693  IntRegs,
694  FloatRegs,
695  InputArgs,
696  StackAdjust,
697  FrameRecord,
698  End
699  } Location = Start;
700  bool StandaloneLR = false, FPLRPair = false;
701  int StackOffset = 0;
702  int Nops = 0;
703  // Iterate over the prolog and check that all opcodes exactly match
704  // the canonical order and form. A more lax check could verify that
705  // all saved registers are in the expected locations, but not enforce
706  // the order - that would work fine when unwinding from within
707  // functions, but not be exactly right if unwinding happens within
708  // prologs/epilogs.
709  for (const WinEH::Instruction &Inst : info->Instructions) {
710  switch (Inst.Operation) {
711  case Win64EH::UOP_End:
712  if (Location != Start)
713  return false;
714  Location = Start2;
715  break;
717  if (Location != Start2)
718  return false;
719  Predecrement = Inst.Offset;
720  RegI = 2;
721  Location = IntRegs;
722  break;
724  if (Location != Start2)
725  return false;
726  Predecrement = Inst.Offset;
727  if (Inst.Register == 19)
728  RegI += 1;
729  else if (Inst.Register == 30)
730  StandaloneLR = true;
731  else
732  return false;
733  // Odd register; can't be any further int registers.
734  Location = FloatRegs;
735  break;
737  // Can't have this in a canonical prologue. Either this has been
738  // canonicalized into SaveR19R20X or SaveFPLRX, or it's an unsupported
739  // register pair.
740  // It can't be canonicalized into SaveR19R20X if the offset is
741  // larger than 248 bytes, but even with the maximum case with
742  // RegI=10/RegF=8/CR=1/H=1, we end up with SavSZ = 216, which should
743  // fit into SaveR19R20X.
744  // The unwinding opcodes can't describe the otherwise seemingly valid
745  // case for RegI=1 CR=1, that would start with a
746  // "stp x19, lr, [sp, #-...]!" as that fits neither SaveRegPX nor
747  // SaveLRPair.
748  return false;
750  if (Location != IntRegs || Inst.Offset != 8 * RegI ||
751  Inst.Register != 19 + RegI)
752  return false;
753  RegI += 2;
754  break;
756  if (Location != IntRegs || Inst.Offset != 8 * RegI)
757  return false;
758  if (Inst.Register == 19 + RegI)
759  RegI += 1;
760  else if (Inst.Register == 30)
761  StandaloneLR = true;
762  else
763  return false;
764  // Odd register; can't be any further int registers.
765  Location = FloatRegs;
766  break;
768  if (Location != IntRegs || Inst.Offset != 8 * RegI ||
769  Inst.Register != 19 + RegI)
770  return false;
771  RegI += 1;
772  StandaloneLR = true;
773  Location = FloatRegs;
774  break;
776  // Packed unwind can't handle prologs that only save one single
777  // float register.
778  return false;
780  if (Location != FloatRegs || RegF == 0 || Inst.Register != 8 + RegF ||
781  Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
782  return false;
783  RegF += 1;
784  Location = InputArgs;
785  break;
787  if (Location != Start2 || Inst.Register != 8)
788  return false;
789  Predecrement = Inst.Offset;
790  RegF = 2;
791  Location = FloatRegs;
792  break;
794  if ((Location != IntRegs && Location != FloatRegs) ||
795  Inst.Register != 8 + RegF ||
796  Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
797  return false;
798  RegF += 2;
799  Location = FloatRegs;
800  break;
802  if (Location == IntRegs)
803  RegI += 2;
804  else if (Location == FloatRegs)
805  RegF += 2;
806  else
807  return false;
808  break;
809  case Win64EH::UOP_Nop:
810  if (Location != IntRegs && Location != FloatRegs && Location != InputArgs)
811  return false;
812  Location = InputArgs;
813  Nops++;
814  break;
817  if (Location != Start2 && Location != IntRegs && Location != FloatRegs &&
818  Location != InputArgs && Location != StackAdjust)
819  return false;
820  // Can have either a single decrement, or a pair of decrements with
821  // 4080 and another decrement.
822  if (StackOffset == 0)
823  StackOffset = Inst.Offset;
824  else if (StackOffset != 4080)
825  return false;
826  else
827  StackOffset += Inst.Offset;
828  Location = StackAdjust;
829  break;
831  // Not allowing FPLRX after StackAdjust; if a StackAdjust is used, it
832  // should be followed by a FPLR instead.
833  if (Location != Start2 && Location != IntRegs && Location != FloatRegs &&
834  Location != InputArgs)
835  return false;
836  StackOffset = Inst.Offset;
837  Location = FrameRecord;
838  FPLRPair = true;
839  break;
841  // This can only follow after a StackAdjust
842  if (Location != StackAdjust || Inst.Offset != 0)
843  return false;
844  Location = FrameRecord;
845  FPLRPair = true;
846  break;
847  case Win64EH::UOP_SetFP:
848  if (Location != FrameRecord)
849  return false;
850  Location = End;
851  break;
852  }
853  }
854  if (RegI > 10 || RegF > 8)
855  return false;
856  if (StandaloneLR && FPLRPair)
857  return false;
858  if (FPLRPair && Location != End)
859  return false;
860  if (Nops != 0 && Nops != 4)
861  return false;
862  int H = Nops == 4;
863  int IntSZ = 8 * RegI;
864  if (StandaloneLR)
865  IntSZ += 8;
866  int FpSZ = 8 * RegF; // RegF not yet decremented
867  int SavSZ = (IntSZ + FpSZ + 8 * 8 * H + 0xF) & ~0xF;
868  if (Predecrement != SavSZ)
869  return false;
870  if (FPLRPair && StackOffset < 16)
871  return false;
872  if (StackOffset % 16)
873  return false;
874  uint32_t FrameSize = (StackOffset + SavSZ) / 16;
875  if (FrameSize > 0x1FF)
876  return false;
877  assert(RegF != 1 && "One single float reg not allowed");
878  if (RegF > 0)
879  RegF--; // Convert from actual number of registers, to value stored
880  assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");
881  int Flag = 0x01; // Function segments not supported yet
882  int CR = FPLRPair ? 3 : StandaloneLR ? 1 : 0;
883  info->PackedInfo |= Flag << 0;
884  info->PackedInfo |= (FuncLength & 0x7FF) << 2;
885  info->PackedInfo |= (RegF & 0x7) << 13;
886  info->PackedInfo |= (RegI & 0xF) << 16;
887  info->PackedInfo |= (H & 0x1) << 20;
888  info->PackedInfo |= (CR & 0x3) << 21;
889  info->PackedInfo |= (FrameSize & 0x1FF) << 23;
890  return true;
891 }
892 
893 // Populate the .xdata section. The format of .xdata on ARM64 is documented at
894 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
896  bool TryPacked = true) {
897  // If this UNWIND_INFO already has a symbol, it's already been emitted.
898  if (info->Symbol)
899  return;
900  // If there's no unwind info here (not even a terminating UOP_End), the
901  // unwind info is considered bogus and skipped. If this was done in
902  // response to an explicit .seh_handlerdata, the associated trailing
903  // handler data is left orphaned in the xdata section.
904  if (info->empty()) {
905  info->EmitAttempted = true;
906  return;
907  }
908  if (info->EmitAttempted) {
909  // If we tried to emit unwind info before (due to an explicit
910  // .seh_handlerdata directive), but skipped it (because there was no
911  // valid information to emit at the time), and it later got valid unwind
912  // opcodes, we can't emit it here, because the trailing handler data
913  // was already emitted elsewhere in the xdata section.
914  streamer.getContext().reportError(
915  SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +
916  " skipped due to no unwind info at the time "
917  "(.seh_handlerdata too early?), but the function later "
918  "did get unwind info that can't be emitted");
919  return;
920  }
921 
922  simplifyOpcodes(info->Instructions, false);
923  for (auto &I : info->EpilogMap)
924  simplifyOpcodes(I.second, true);
925 
926  MCContext &context = streamer.getContext();
927  MCSymbol *Label = context.createTempSymbol();
928 
929  streamer.emitValueToAlignment(4);
930  streamer.emitLabel(Label);
931  info->Symbol = Label;
932 
933  int64_t RawFuncLength;
934  if (!info->FuncletOrFuncEnd) {
935  report_fatal_error("FuncletOrFuncEnd not set");
936  } else {
937  // FIXME: GetAbsDifference tries to compute the length of the function
938  // immediately, before the whole file is emitted, but in general
939  // that's impossible: the size in bytes of certain assembler directives
940  // like .align and .fill is not known until the whole file is parsed and
941  // relaxations are applied. Currently, GetAbsDifference fails with a fatal
942  // error in that case. (We mostly don't hit this because inline assembly
943  // specifying those directives is rare, and we don't normally try to
944  // align loops on AArch64.)
945  //
946  // There are two potential approaches to delaying the computation. One,
947  // we could emit something like ".word (endfunc-beginfunc)/4+0x10800000",
948  // as long as we have some conservative estimate we could use to prove
949  // that we don't need to split the unwind data. Emitting the constant
950  // is straightforward, but there's no existing code for estimating the
951  // size of the function.
952  //
953  // The other approach would be to use a dedicated, relaxable fragment,
954  // which could grow to accommodate splitting the unwind data if
955  // necessary. This is more straightforward, since it automatically works
956  // without any new infrastructure, and it's consistent with how we handle
957  // relaxation in other contexts. But it would require some refactoring
958  // to move parts of the pdata/xdata emission into the implementation of
959  // a fragment. We could probably continue to encode the unwind codes
960  // here, but we'd have to emit the pdata, the xdata header, and the
961  // epilogue scopes later, since they depend on whether the we need to
962  // split the unwind data.
963  RawFuncLength = GetAbsDifference(streamer, info->FuncletOrFuncEnd,
964  info->Begin);
965  }
966  if (RawFuncLength > 0xFFFFF)
967  report_fatal_error("SEH unwind data splitting not yet implemented");
968  uint32_t FuncLength = (uint32_t)RawFuncLength / 4;
969  uint32_t PrologCodeBytes = ARM64CountOfUnwindCodes(info->Instructions);
970  uint32_t TotalCodeBytes = PrologCodeBytes;
971 
972  int PackedEpilogOffset = checkPackedEpilog(streamer, info, PrologCodeBytes);
973 
974  if (PackedEpilogOffset >= 0 &&
975  uint32_t(PackedEpilogOffset) < PrologCodeBytes &&
976  !info->HandlesExceptions && FuncLength <= 0x7ff && TryPacked) {
977  // Matching prolog/epilog and no exception handlers; check if the
978  // prolog matches the patterns that can be described by the packed
979  // format.
980 
981  // info->Symbol was already set even if we didn't actually write any
982  // unwind info there. Keep using that as indicator that this unwind
983  // info has been generated already.
984 
985  if (tryPackedUnwind(info, FuncLength, PackedEpilogOffset))
986  return;
987  }
988 
989  // Process epilogs.
991  // Epilogs processed so far.
992  std::vector<MCSymbol *> AddedEpilogs;
993 
994  for (auto &I : info->EpilogMap) {
995  MCSymbol *EpilogStart = I.first;
996  auto &EpilogInstrs = I.second;
997  uint32_t CodeBytes = ARM64CountOfUnwindCodes(EpilogInstrs);
998 
999  MCSymbol* MatchingEpilog =
1000  FindMatchingEpilog(EpilogInstrs, AddedEpilogs, info);
1001  int PrologOffset;
1002  if (MatchingEpilog) {
1003  assert(EpilogInfo.find(MatchingEpilog) != EpilogInfo.end() &&
1004  "Duplicate epilog not found");
1005  EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
1006  // Clear the unwind codes in the EpilogMap, so that they don't get output
1007  // in the logic below.
1008  EpilogInstrs.clear();
1009  } else if ((PrologOffset =
1010  getOffsetInProlog(info->Instructions, EpilogInstrs)) >= 0) {
1011  EpilogInfo[EpilogStart] = PrologOffset;
1012  // Clear the unwind codes in the EpilogMap, so that they don't get output
1013  // in the logic below.
1014  EpilogInstrs.clear();
1015  } else {
1016  EpilogInfo[EpilogStart] = TotalCodeBytes;
1017  TotalCodeBytes += CodeBytes;
1018  AddedEpilogs.push_back(EpilogStart);
1019  }
1020  }
1021 
1022  // Code Words, Epilog count, E, X, Vers, Function Length
1023  uint32_t row1 = 0x0;
1024  uint32_t CodeWords = TotalCodeBytes / 4;
1025  uint32_t CodeWordsMod = TotalCodeBytes % 4;
1026  if (CodeWordsMod)
1027  CodeWords++;
1028  uint32_t EpilogCount =
1029  PackedEpilogOffset >= 0 ? PackedEpilogOffset : info->EpilogMap.size();
1030  bool ExtensionWord = EpilogCount > 31 || TotalCodeBytes > 124;
1031  if (!ExtensionWord) {
1032  row1 |= (EpilogCount & 0x1F) << 22;
1033  row1 |= (CodeWords & 0x1F) << 27;
1034  }
1035  if (info->HandlesExceptions) // X
1036  row1 |= 1 << 20;
1037  if (PackedEpilogOffset >= 0) // E
1038  row1 |= 1 << 21;
1039  row1 |= FuncLength & 0x3FFFF;
1040  streamer.emitInt32(row1);
1041 
1042  // Extended Code Words, Extended Epilog Count
1043  if (ExtensionWord) {
1044  // FIXME: We should be able to split unwind info into multiple sections.
1045  if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
1046  report_fatal_error("SEH unwind data splitting not yet implemented");
1047  uint32_t row2 = 0x0;
1048  row2 |= (CodeWords & 0xFF) << 16;
1049  row2 |= (EpilogCount & 0xFFFF);
1050  streamer.emitInt32(row2);
1051  }
1052 
1053  if (PackedEpilogOffset < 0) {
1054  // Epilog Start Index, Epilog Start Offset
1055  for (auto &I : EpilogInfo) {
1056  MCSymbol *EpilogStart = I.first;
1057  uint32_t EpilogIndex = I.second;
1058  uint32_t EpilogOffset =
1059  (uint32_t)GetAbsDifference(streamer, EpilogStart, info->Begin);
1060  if (EpilogOffset)
1061  EpilogOffset /= 4;
1062  uint32_t row3 = EpilogOffset;
1063  row3 |= (EpilogIndex & 0x3FF) << 22;
1064  streamer.emitInt32(row3);
1065  }
1066  }
1067 
1068  // Emit prolog unwind instructions (in reverse order).
1069  uint8_t numInst = info->Instructions.size();
1070  for (uint8_t c = 0; c < numInst; ++c) {
1071  WinEH::Instruction inst = info->Instructions.back();
1072  info->Instructions.pop_back();
1073  ARM64EmitUnwindCode(streamer, info->Begin, inst);
1074  }
1075 
1076  // Emit epilog unwind instructions
1077  for (auto &I : info->EpilogMap) {
1078  auto &EpilogInstrs = I.second;
1079  for (const WinEH::Instruction &inst : EpilogInstrs)
1080  ARM64EmitUnwindCode(streamer, info->Begin, inst);
1081  }
1082 
1083  int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
1084  assert(BytesMod >= 0);
1085  for (int i = 0; i < BytesMod; i++)
1086  streamer.emitInt8(0xE3);
1087 
1088  if (info->HandlesExceptions)
1089  streamer.emitValue(
1090  MCSymbolRefExpr::create(info->ExceptionHandler,
1092  4);
1093 }
1094 
1095 static void ARM64EmitRuntimeFunction(MCStreamer &streamer,
1096  const WinEH::FrameInfo *info) {
1097  MCContext &context = streamer.getContext();
1098 
1099  streamer.emitValueToAlignment(4);
1100  EmitSymbolRefWithOfs(streamer, info->Begin, info->Begin);
1101  if (info->PackedInfo)
1102  streamer.emitInt32(info->PackedInfo);
1103  else
1104  streamer.emitValue(
1106  context),
1107  4);
1108 }
1109 
1111  // Emit the unwind info structs first.
1112  for (const auto &CFI : Streamer.getWinFrameInfos()) {
1113  WinEH::FrameInfo *Info = CFI.get();
1114  if (Info->empty())
1115  continue;
1116  MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
1117  Streamer.SwitchSection(XData);
1118  ARM64EmitUnwindInfo(Streamer, Info);
1119  }
1120 
1121  // Now emit RUNTIME_FUNCTION entries.
1122  for (const auto &CFI : Streamer.getWinFrameInfos()) {
1123  WinEH::FrameInfo *Info = CFI.get();
1124  // ARM64EmitUnwindInfo above clears the info struct, so we can't check
1125  // empty here. But if a Symbol is set, we should create the corresponding
1126  // pdata entry.
1127  if (!Info->Symbol)
1128  continue;
1129  MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
1130  Streamer.SwitchSection(PData);
1131  ARM64EmitRuntimeFunction(Streamer, Info);
1132  }
1133 }
1134 
1137  bool HandlerData) const {
1138  // Called if there's an .seh_handlerdata directive before the end of the
1139  // function. This forces writing the xdata record already here - and
1140  // in this case, the function isn't actually ended already, but the xdata
1141  // record needs to know the function length. In these cases, if the funclet
1142  // end hasn't been marked yet, the xdata function length won't cover the
1143  // whole function, only up to this point.
1144  if (!info->FuncletOrFuncEnd) {
1145  Streamer.SwitchSection(info->TextSection);
1146  info->FuncletOrFuncEnd = Streamer.emitCFILabel();
1147  }
1148  // Switch sections (the static function above is meant to be called from
1149  // here and from Emit().
1150  MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
1151  Streamer.SwitchSection(XData);
1152  ARM64EmitUnwindInfo(Streamer, info, /* TryPacked = */ !HandlerData);
1153 }
llvm::Win64EH::UOP_AllocMedium
@ UOP_AllocMedium
Definition: Win64EH.h:40
llvm::Win64EH::UOP_SaveXMM128
@ UOP_SaveXMM128
Definition: Win64EH.h:35
i
i
Definition: README.txt:29
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:845
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::MCSymbol
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
llvm::WinEH::Instruction::Register
unsigned Register
Definition: MCWinEH.h:24
llvm::MCContext
Context object for machine code objects.
Definition: MCContext.h:74
getOffsetInProlog
static int getOffsetInProlog(const std::vector< WinEH::Instruction > &Prolog, const std::vector< WinEH::Instruction > &Epilog)
Definition: MCWin64EH.cpp:609
llvm::MCStreamer::emitInt8
void emitInt8(uint64_t Value)
Definition: MCStreamer.h:725
llvm::MapVector::clear
void clear()
Definition: MapVector.h:89
llvm::Win64EH::UOP_SaveFRegP
@ UOP_SaveFRegP
Definition: Win64EH.h:51
llvm::Win64EH::UOP_SaveRegPX
@ UOP_SaveRegPX
Definition: Win64EH.h:47
llvm::Win64EH::UOP_SaveNext
@ UOP_SaveNext
Definition: Win64EH.h:57
FloatRegs
static const MCPhysReg FloatRegs[32]
Definition: SparcAsmParser.cpp:146
llvm::MCStreamer::emitValue
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
Definition: MCStreamer.cpp:178
llvm::Win64EH::UOP_PushNonVol
@ UOP_PushNonVol
Definition: Win64EH.h:27
llvm::Win64EH::UOP_SaveLRPair
@ UOP_SaveLRPair
Definition: Win64EH.h:48
llvm::MCStreamer::emitCFILabel
virtual MCSymbol * emitCFILabel()
When emitting an object file, create and emit a real label.
Definition: MCStreamer.cpp:479
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:727
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:521
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::DiagnosticPredicateTy::Match
@ Match
ARM64EmitRuntimeFunction
static void ARM64EmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
Definition: MCWin64EH.cpp:1095
RHS
Value * RHS
Definition: X86PartialReduction.cpp:76
llvm::Win64EH::UOP_TrapFrame
@ UOP_TrapFrame
Definition: Win64EH.h:58
llvm::Win64EH::UOP_Nop
@ UOP_Nop
Definition: Win64EH.h:55
Context
LLVMContext & Context
Definition: NVVMIntrRange.cpp:66
MCObjectStreamer.h
llvm::MCStreamer
Streaming machine code generation interface.
Definition: MCStreamer.h:201
LHS
Value * LHS
Definition: X86PartialReduction.cpp:75
EmitSymbolRefWithOfs
static void EmitSymbolRefWithOfs(MCStreamer &streamer, const MCSymbol *Base, const MCSymbol *Other)
Definition: MCWin64EH.cpp:130
llvm::Win64EH::UNW_ExceptionHandler
@ UNW_ExceptionHandler
UNW_ExceptionHandler - Specifies that this function has an exception handler.
Definition: Win64EH.h:83
llvm::Win64EH::UOP_AddFP
@ UOP_AddFP
Definition: Win64EH.h:54
llvm::SMLoc
Represents a location in source code.
Definition: SMLoc.h:23
llvm::MCStreamer::getAssociatedPDataSection
MCSection * getAssociatedPDataSection(const MCSection *TextSec)
Get the .pdata section used for the given section.
Definition: MCStreamer.cpp:839
llvm::Win64EH::UOP_SaveRegX
@ UOP_SaveRegX
Definition: Win64EH.h:45
Twine.h
llvm::Win64EH::ARM64UnwindEmitter::EmitUnwindInfo
void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override
Definition: MCWin64EH.cpp:1135
MCContext.h
llvm::Win64EH::UOP_SetFPReg
@ UOP_SetFPReg
Definition: Win64EH.h:30
llvm::MCStreamer::emitLabel
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
Definition: MCStreamer.cpp:416
ARM64CountOfUnwindCodes
static uint32_t ARM64CountOfUnwindCodes(ArrayRef< WinEH::Instruction > Insns)
Definition: MCWin64EH.cpp:269
llvm::Win64EH::UNW_TerminateHandler
@ UNW_TerminateHandler
UNW_TerminateHandler - Specifies that this function has a termination handler.
Definition: Win64EH.h:86
MCSymbol.h
llvm::Win64EH::UOP_SaveReg
@ UOP_SaveReg
Definition: Win64EH.h:44
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::MCObjectStreamer
Streaming object file generation interface.
Definition: MCObjectStreamer.h:42
EmitUnwindInfo
static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info)
Definition: MCWin64EH.cpp:155
llvm::Win64EH::UOP_SaveFRegX
@ UOP_SaveFRegX
Definition: Win64EH.h:50
llvm::MCID::Flag
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Definition: MCInstrDesc.h:147
llvm::report_fatal_error
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:143
ARM64EmitUnwindInfo
static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info, bool TryPacked=true)
Definition: MCWin64EH.cpp:895
llvm::Win64EH::UOP_SetFP
@ UOP_SetFP
Definition: Win64EH.h:53
Info
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
b2
int b2
Definition: README.txt:84
GetAbsDifference
static int64_t GetAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
Definition: MCWin64EH.cpp:253
c
the resulting code requires compare and branches when and if the revised code is with conditional branches instead of More there is a byte word extend before each where there should be only and the condition codes are not remembered when the same two values are compared twice More LSR enhancements i8 and i32 load store addressing modes are identical int int c
Definition: README.txt:418
llvm::Win64EH::UOP_SaveXMM128Big
@ UOP_SaveXMM128Big
Definition: Win64EH.h:36
llvm::Win64EH::UOP_SaveFPLRX
@ UOP_SaveFPLRX
Definition: Win64EH.h:42
llvm::Win64EH::UOP_End
@ UOP_End
Definition: Win64EH.h:56
llvm::Win64EH::UnwindOpcodes
UnwindOpcodes
UnwindOpcodes - Enumeration whose values specify a single operation in the prolog of a function.
Definition: Win64EH.h:26
llvm::MCStreamer::emitInt16
void emitInt16(uint64_t Value)
Definition: MCStreamer.h:726
llvm::Win64EH::UOP_AllocSmall
@ UOP_AllocSmall
Definition: Win64EH.h:29
llvm::MapVector::find
iterator find(const KeyT &Key)
Definition: MapVector.h:148
checkPackedEpilog
static int checkPackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info, int PrologCodeBytes)
Definition: MCWin64EH.cpp:629
EmitUnwindCode
static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin, WinEH::Instruction &inst)
Definition: MCWin64EH.cpp:62
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::Win64EH::UOP_Context
@ UOP_Context
Definition: Win64EH.h:59
EmitRuntimeFunction
static void EmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
Definition: MCWin64EH.cpp:143
llvm::WinEH::Instruction::Operation
unsigned Operation
Definition: MCWinEH.h:25
Win64EH.h
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::Win64EH::UOP_SaveFReg
@ UOP_SaveFReg
Definition: Win64EH.h:49
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:1002
llvm::Win64EH::UOP_SaveNonVol
@ UOP_SaveNonVol
Definition: Win64EH.h:31
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:52
ARM64EmitUnwindCode
static void ARM64EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin, const WinEH::Instruction &inst)
Definition: MCWin64EH.cpp:354
info
lazy value info
Definition: LazyValueInfo.cpp:58
llvm::MCBinaryExpr::createAdd
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:525
llvm::MCObjectStreamer::getAssembler
MCAssembler & getAssembler()
Definition: MCObjectStreamer.h:128
IntRegs
static const MCPhysReg IntRegs[32]
Definition: SparcAsmParser.cpp:136
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:32
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
simplifyOpcodes
static void simplifyOpcodes(std::vector< WinEH::Instruction > &Instructions, bool Reverse)
Definition: MCWin64EH.cpp:546
llvm::Win64EH::UNW_ChainInfo
@ UNW_ChainInfo
UNW_ChainInfo - Specifies that this UnwindInfo structure is chained to another one.
Definition: Win64EH.h:89
llvm::MCContext::createTempSymbol
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:321
Prolog
@ Prolog
Definition: AArch64LowerHomogeneousPrologEpilog.cpp:125
llvm::Win64EH::UnwindEmitter::EmitUnwindInfo
void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override
Definition: MCWin64EH.cpp:242
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:1110
llvm::Win64EH::UOP_ClearUnwoundToCall
@ UOP_ClearUnwoundToCall
Definition: Win64EH.h:60
H
#define H(x, y, z)
Definition: MD5.cpp:57
uint16_t
Epilog
@ Epilog
Definition: AArch64LowerHomogeneousPrologEpilog.cpp:125
llvm::Win64EH::UOP_SaveR19R20X
@ UOP_SaveR19R20X
Definition: Win64EH.h:41
llvm::MCStreamer::getWinFrameInfos
ArrayRef< std::unique_ptr< WinEH::FrameInfo > > getWinFrameInfos() const
Definition: MCStreamer.h:310
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
llvm::Win64EH::UOP_SaveNonVolBig
@ UOP_SaveNonVolBig
Definition: Win64EH.h:32
llvm::WinEH::FrameInfo
Definition: MCWinEH.h:39
llvm::MCStreamer::getContext
MCContext & getContext() const
Definition: MCStreamer.h:282
MCStreamer.h
llvm::Win64EH::UOP_SaveRegP
@ UOP_SaveRegP
Definition: Win64EH.h:46
llvm::Win64EH::UOP_SaveFPLR
@ UOP_SaveFPLR
Definition: Win64EH.h:43
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:1207
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:226
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:1220
MCExpr.h
llvm::Win64EH::UOP_PushMachFrame
@ UOP_PushMachFrame
Definition: Win64EH.h:37
llvm::MCExpr
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
tryPackedUnwind
static bool tryPackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength, int PackedEpilogOffset)
Definition: MCWin64EH.cpp:670
EmitAbsDifference
static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
Definition: MCWin64EH.cpp:53
llvm::sampleprof::Base
@ Base
Definition: Discriminator.h:58
Other
Optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:1225
CountOfUnwindCodes
static uint8_t CountOfUnwindCodes(std::vector< WinEH::Instruction > &Insns)
Definition: MCWin64EH.cpp:25
MCWin64EH.h
llvm::Win64EH::UOP_AllocLarge
@ UOP_AllocLarge
Definition: Win64EH.h:28