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