LLVM 23.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/MCAssembler.h"
12#include "llvm/MC/MCContext.h"
13#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCStreamer.h"
16#include "llvm/MC/MCSymbol.h"
17#include "llvm/MC/MCValue.h"
20
21namespace llvm {
22class MCSection;
23}
24
25using namespace llvm;
26
27namespace {
28/// MCExpr that represents the epilog unwind code in an unwind table.
29class MCUnwindV2EpilogTargetExpr final : public MCTargetExpr {
30 const WinEH::FrameInfo &FrameInfo;
31 const MCSymbol *UnwindV2Start;
32 const MCSymbol *EpilogEnd;
33 uint8_t EpilogSize;
34 SMLoc Loc;
35
36 MCUnwindV2EpilogTargetExpr(const WinEH::FrameInfo &FrameInfo,
37 const WinEH::FrameInfo::Epilog &Epilog,
38 uint8_t EpilogSize_)
39 : FrameInfo(FrameInfo), UnwindV2Start(Epilog.UnwindV2Start),
40 EpilogEnd(Epilog.End), EpilogSize(EpilogSize_), Loc(Epilog.Loc) {
41 assert(UnwindV2Start && "Epilog must have a start");
42 assert(EpilogEnd && "Epilog must have an end");
43 }
44
45public:
46 static MCUnwindV2EpilogTargetExpr *
47 create(const WinEH::FrameInfo &FrameInfo,
48 const WinEH::FrameInfo::Epilog &Epilog, uint8_t EpilogSize_,
49 MCContext &Ctx) {
50 return new (Ctx) MCUnwindV2EpilogTargetExpr(FrameInfo, Epilog, EpilogSize_);
51 }
52
53 void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override {
54 OS << ":epilog:";
55 UnwindV2Start->print(OS, MAI);
56 }
57
58 bool evaluateAsRelocatableImpl(MCValue &Res,
59 const MCAssembler *Asm) const override;
60
61 void visitUsedExpr(MCStreamer &Streamer) const override {
62 // Contains no sub-expressions.
63 }
64
65 MCFragment *findAssociatedFragment() const override {
66 return UnwindV2Start->getFragment();
67 }
68};
69} // namespace
70
71// NOTE: All relocations generated here are 4-byte image-relative.
72
73static uint8_t CountOfUnwindCodes(std::vector<WinEH::Instruction> &Insns) {
74 uint8_t Count = 0;
75 for (const auto &I : Insns) {
76 switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
77 default:
78 llvm_unreachable("Unsupported unwind code");
83 Count += 1;
84 break;
87 Count += 2;
88 break;
91 Count += 3;
92 break;
94 Count += (I.Offset > 512 * 1024 - 8) ? 3 : 2;
95 break;
96 }
97 }
98 return Count;
99}
100
101static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
102 const MCSymbol *RHS) {
103 MCContext &Context = Streamer.getContext();
104 const MCExpr *Diff =
106 MCSymbolRefExpr::create(RHS, Context), Context);
107 Streamer.emitValue(Diff, 1);
108}
109
110/// Emit a 16-bit (2-byte LE) label difference. If the difference is
111/// evaluatable at this point, validate that it fits in [0, UINT16_MAX]
112/// and emit it as a constant; otherwise emit a 16-bit fixup.
113static void EmitAbsDifference16(MCStreamer &Streamer, const MCSymbol *LHS,
114 const MCSymbol *RHS) {
115 MCContext &Context = Streamer.getContext();
116 const MCExpr *Diff =
118 MCSymbolRefExpr::create(RHS, Context), Context);
119 int64_t Value;
120 if (Diff->evaluateAsAbsolute(
121 Value, static_cast<MCObjectStreamer &>(Streamer).getAssembler())) {
122 if (Value < 0 || Value > UINT16_MAX)
123 Context.reportError(
124 SMLoc(),
125 "Label difference out of 16-bit unsigned range for V3 unwind info");
126 }
127 // Always emit a 2-byte value so subsequent emission stays in sync; if a
128 // diagnostic was reported, the object file will be discarded by the caller.
129 Streamer.emitValue(Diff, 2);
130}
131
132static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin,
133 WinEH::Instruction &inst) {
134 uint8_t b2;
135 uint16_t w;
136 b2 = (inst.Operation & 0x0F);
137 switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
138 default:
139 llvm_unreachable("Unsupported unwind code");
141 // Reachable from hand-written .s if a UOP_Push2 ends up in a V1/V2
142 // frame (e.g. via a per-function `.seh_unwindversion` downgrade after
143 // `.seh_push2regs`). Emit a recoverable diagnostic and skip the op so
144 // the assembler doesn't keep writing malformed bytes.
145 streamer.getContext().reportError(
146 SMLoc(), "UOP_Push2 (PUSH2 with two registers) requires V3 unwind "
147 "info. Use `.seh_unwindversion 3`.");
148 return;
150 EmitAbsDifference(streamer, inst.Label, begin);
151 b2 |= (inst.Register & 0x0F) << 4;
152 streamer.emitInt8(b2);
153 break;
155 EmitAbsDifference(streamer, inst.Label, begin);
156 if (inst.Offset > 512 * 1024 - 8) {
157 b2 |= 0x10;
158 streamer.emitInt8(b2);
159 w = inst.Offset & 0xFFF8;
160 streamer.emitInt16(w);
161 w = inst.Offset >> 16;
162 } else {
163 streamer.emitInt8(b2);
164 w = inst.Offset >> 3;
165 }
166 streamer.emitInt16(w);
167 break;
169 b2 |= (((inst.Offset - 8) >> 3) & 0x0F) << 4;
170 EmitAbsDifference(streamer, inst.Label, begin);
171 streamer.emitInt8(b2);
172 break;
174 EmitAbsDifference(streamer, inst.Label, begin);
175 streamer.emitInt8(b2);
176 break;
179 b2 |= (inst.Register & 0x0F) << 4;
180 EmitAbsDifference(streamer, inst.Label, begin);
181 streamer.emitInt8(b2);
182 w = inst.Offset >> 3;
184 w >>= 1;
185 streamer.emitInt16(w);
186 break;
189 b2 |= (inst.Register & 0x0F) << 4;
190 EmitAbsDifference(streamer, inst.Label, begin);
191 streamer.emitInt8(b2);
193 w = inst.Offset & 0xFFF0;
194 else
195 w = inst.Offset & 0xFFF8;
196 streamer.emitInt16(w);
197 w = inst.Offset >> 16;
198 streamer.emitInt16(w);
199 break;
201 if (inst.Offset == 1)
202 b2 |= 0x10;
203 EmitAbsDifference(streamer, inst.Label, begin);
204 streamer.emitInt8(b2);
205 break;
206 }
207}
208
209static void EmitSymbolRefWithOfs(MCStreamer &streamer,
210 const MCSymbol *Base,
211 int64_t Offset) {
212 MCContext &Context = streamer.getContext();
213 const MCConstantExpr *OffExpr = MCConstantExpr::create(Offset, Context);
214 const MCSymbolRefExpr *BaseRefRel = MCSymbolRefExpr::create(Base,
216 Context);
217 streamer.emitValue(MCBinaryExpr::createAdd(BaseRefRel, OffExpr, Context), 4);
218}
219
220static void EmitSymbolRefWithOfs(MCStreamer &streamer,
221 const MCSymbol *Base,
222 const MCSymbol *Other) {
223 MCContext &Context = streamer.getContext();
224 const MCSymbolRefExpr *BaseRef = MCSymbolRefExpr::create(Base, Context);
225 const MCSymbolRefExpr *OtherRef = MCSymbolRefExpr::create(Other, Context);
226 const MCExpr *Ofs = MCBinaryExpr::createSub(OtherRef, BaseRef, Context);
227 const MCSymbolRefExpr *BaseRefRel = MCSymbolRefExpr::create(Base,
229 Context);
230 streamer.emitValue(MCBinaryExpr::createAdd(BaseRefRel, Ofs, Context), 4);
231}
232
233static void EmitRuntimeFunction(MCStreamer &streamer,
234 const WinEH::FrameInfo *info) {
235 MCContext &context = streamer.getContext();
236
237 streamer.emitValueToAlignment(Align(4));
238 EmitSymbolRefWithOfs(streamer, info->Begin, info->Begin);
239 EmitSymbolRefWithOfs(streamer, info->Begin, info->End);
240 streamer.emitValue(MCSymbolRefExpr::create(info->Symbol,
242 context), 4);
243}
244
245static std::optional<int64_t>
247 const MCSymbol *RHS) {
248 MCContext &Context = Assembler.getContext();
249 const MCExpr *Diff =
251 MCSymbolRefExpr::create(RHS, Context), Context);
252 // It should normally be possible to calculate the length of a function
253 // at this point, but it might not be possible in the presence of certain
254 // unusual constructs, like an inline asm with an alignment directive.
255 int64_t value;
256 if (!Diff->evaluateAsAbsolute(value, Assembler))
257 return std::nullopt;
258 return value;
259}
260
261//===----------------------------------------------------------------------===//
262// V3 UNWIND_INFO Emission
263// See https://learn.microsoft.com/en-us/cpp/build/x64-unwind-information-v3
264//===----------------------------------------------------------------------===//
265
266/// Encode a single WinEH::Instruction as V3 WOD bytes.
267/// Appends encoded bytes to Out.
270 switch (static_cast<Win64EH::UnwindOpcodes>(Inst.Operation)) {
272 // WOD_PUSH: 1 byte, bits [2:0] = 4, bits [7:3] = register (5-bit)
273 uint8_t Reg = Inst.Register & 0x1F;
274 Out.push_back((Reg << 3) | Win64EH::WOD_PUSH);
275 break;
276 }
278 // WOD_ALLOC_SMALL: 1 byte, bits [3:0] = 8, bits [7:4] = (size/8 - 1)
279 // V1/V2 stores (size-8)/8 in OpInfo; actual size = Offset.
280 // Inst.Offset is the raw allocation size.
281 if (Inst.Offset < 8 || Inst.Offset > 128 || Inst.Offset % 8 != 0)
283 "UOP_AllocSmall outside expected range or alignment");
284 uint8_t Encoded = ((Inst.Offset / 8 - 1) & 0x0F);
285 Out.push_back((Encoded << 4) | Win64EH::WOD_ALLOC_SMALL);
286 break;
287 }
289 if (Inst.Offset > 512 * 1024 - 8) {
290 // WOD_ALLOC_HUGE: 5 bytes, byte[0] = 1, bytes[1:4] = LE32(size)
292 uint32_t Size = Inst.Offset;
293 Out.push_back(Size & 0xFF);
294 Out.push_back((Size >> 8) & 0xFF);
295 Out.push_back((Size >> 16) & 0xFF);
296 Out.push_back((Size >> 24) & 0xFF);
297 } else {
298 // WOD_ALLOC_LARGE: 3 bytes, byte[0] = 2, bytes[1:2] = LE16(size/8)
300 uint16_t Scaled = Inst.Offset / 8;
301 Out.push_back(Scaled & 0xFF);
302 Out.push_back((Scaled >> 8) & 0xFF);
303 }
304 break;
305 }
307 // WOD_SET_FPREG: 2 bytes, byte[0] = 0, byte[1] = reg(4) | (offset/16)(4)
308 // The frame register field is only 4 bits, so EGPR (R16-R31) cannot be
309 // used as the frame pointer in V3 unwind info.
310 if (Inst.Register > 0x0F)
312 "SET_FPREG frame register does not fit in 4 bits");
314 uint8_t Reg = Inst.Register & 0x0F;
315 uint8_t Off = (Inst.Offset / 16) & 0x0F;
316 Out.push_back(Reg | (Off << 4));
317 break;
318 }
320 // WOD_SAVE_NONVOL: 3 bytes, bits [2:0] = 6, bits [7:3] = reg,
321 // bytes[1:2] = LE16(displacement/8)
322 uint8_t Reg = Inst.Register & 0x1F;
323 Out.push_back((Reg << 3) | Win64EH::WOD_SAVE_NONVOL);
324 uint16_t Disp = Inst.Offset / 8;
325 Out.push_back(Disp & 0xFF);
326 Out.push_back((Disp >> 8) & 0xFF);
327 break;
328 }
330 // WOD_SAVE_NONVOL_FAR: 5 bytes, bits [2:0] = 5, bits [7:3] = reg,
331 // bytes[1:4] = LE32(displacement)
332 uint8_t Reg = Inst.Register & 0x1F;
333 Out.push_back((Reg << 3) | Win64EH::WOD_SAVE_NONVOL_FAR);
334 uint32_t Disp = Inst.Offset;
335 Out.push_back(Disp & 0xFF);
336 Out.push_back((Disp >> 8) & 0xFF);
337 Out.push_back((Disp >> 16) & 0xFF);
338 Out.push_back((Disp >> 24) & 0xFF);
339 break;
340 }
342 // WOD_SAVE_XMM128: 3 bytes, bits [3:0] = 10, bits [7:4] = reg,
343 // bytes[1:2] = LE16(displacement/16)
344 // The XMM register field is only 4 bits, so XMM16-XMM31 (AVX-512 EVEX)
345 // cannot be encoded. Such registers are caller-saved on Win64 and should
346 // never reach here from codegen.
347 if (Inst.Register > 0x0F)
349 "SAVE_XMM128 register does not fit in 4 bits (XMM16-31 unsupported)");
350 uint8_t Reg = Inst.Register & 0x0F;
351 Out.push_back((Reg << 4) | Win64EH::WOD_SAVE_XMM128);
352 uint16_t Disp = Inst.Offset / 16;
353 Out.push_back(Disp & 0xFF);
354 Out.push_back((Disp >> 8) & 0xFF);
355 break;
356 }
358 // WOD_SAVE_XMM128_FAR: 5 bytes, bits [3:0] = 9, bits [7:4] = reg,
359 // bytes[1:4] = LE32(displacement)
360 if (Inst.Register > 0x0F)
361 reportFatalInternalError("SAVE_XMM128_FAR register does not fit in 4 "
362 "bits (XMM16-31 unsupported)");
363 uint8_t Reg = Inst.Register & 0x0F;
364 Out.push_back((Reg << 4) | Win64EH::WOD_SAVE_XMM128_FAR);
365 uint32_t Disp = Inst.Offset;
366 Out.push_back(Disp & 0xFF);
367 Out.push_back((Disp >> 8) & 0xFF);
368 Out.push_back((Disp >> 16) & 0xFF);
369 Out.push_back((Disp >> 24) & 0xFF);
370 break;
371 }
373 // WOD_PUSH_CANONICAL_FRAME: 2 bytes, byte[0] = 3, byte[1] = type
375 Out.push_back(Inst.Offset == 1 ? 1 : 0);
376 break;
377 }
378 case Win64EH::UOP_Push2: {
379 uint8_t Reg1 = Inst.Register & 0x1F;
380 uint8_t Reg2 = Inst.Register2 & 0x1F;
381 // Optimization: if registers are consecutive, use WOD_PUSH_CONSECUTIVE_2
382 // (opcode 7, 1 byte) instead of WOD_PUSH2 (opcode 32, 2 bytes).
383 if (Reg2 == Reg1 + 1) {
384 // WOD_PUSH_CONSECUTIVE_2: bits [2:0] = 111b, bits [7:3] = Register
386 } else {
387 // WOD_PUSH2: 2 bytes
388 // Byte 0: [5:0] = 100000b (opcode 32), [7:6] = Register1[1:0]
389 // Byte 1: [2:0] = Register1[4:2], [7:3] = Register2
390 Out.push_back(((Reg1 & 0x03) << 6) | Win64EH::WOD_PUSH2);
391 Out.push_back(((Reg2 & 0x1F) << 3) | ((Reg1 >> 2) & 0x07));
392 }
393 break;
394 }
395 default:
396 llvm_unreachable("Unsupported unwind operation for V3 encoding");
397 }
398}
399
400/// Try to find Needle as a contiguous subsequence within Haystack.
401/// Returns the byte offset if found, or std::nullopt.
402static std::optional<uint16_t> FindInPool(ArrayRef<uint8_t> Haystack,
403 ArrayRef<uint8_t> Needle) {
404 assert(!Needle.empty() && "FindInPool called with empty Needle");
405 auto It = std::search(Haystack.begin(), Haystack.end(), Needle.begin(),
406 Needle.end());
407 if (It == Haystack.end())
408 return std::nullopt;
409 return static_cast<uint16_t>(std::distance(Haystack.begin(), It));
410}
411
412/// Compare the relative IP offset arrays of two epilogs.
415 const MCAssembler &Asm) {
416 if (A.Instructions.size() != B.Instructions.size())
417 return false;
418 for (unsigned I = 0; I < A.Instructions.size(); ++I) {
419 auto OffA = GetOptionalAbsDifference(Asm, A.Instructions[I].Label, A.Start);
420 auto OffB = GetOptionalAbsDifference(Asm, B.Instructions[I].Label, B.Start);
421 if (!OffA || !OffB || *OffA != *OffB)
422 return false;
423 }
424 return true;
425}
426
427/// Emit V3 UNWIND_INFO for a single frame.
428static void EmitUnwindInfoV3(MCStreamer &Streamer, WinEH::FrameInfo *Info) {
429 // Should have been checked by our caller.
430 assert(!Info->Symbol && "UNWIND_INFO already has a symbol");
431
432 MCContext &Context = Streamer.getContext();
433 MCObjectStreamer *OS = static_cast<MCObjectStreamer *>(&Streamer);
434 const MCAssembler &Asm = OS->getAssembler();
435
436 MCSymbol *Label = Context.createTempSymbol();
437 Streamer.emitValueToAlignment(Align(4));
438 Streamer.emitLabel(Label);
439 Info->Symbol = Label;
440
441 // ===================================================================
442 // Phase 1: Data preparation — compute all metadata before emitting.
443 // ===================================================================
444
445 // --- Build prolog WOD pool (body-to-entry order) ---
447 for (auto It = Info->Instructions.rbegin(); It != Info->Instructions.rend();
448 ++It)
449 Win64EH::EncodeWOD(*It, WODPool);
450
451 // --- Build prolog IP offset label pairs (body-to-entry order) ---
453 unsigned PrologOpCount = Info->Instructions.size();
454 if (PrologOpCount > 31) {
456 "Too many prolog unwind codes for V3 encoding. Maximum "
457 "is 31. This function has " +
458 Twine(PrologOpCount));
459 }
460 for (auto It = Info->Instructions.rbegin(); It != Info->Instructions.rend();
461 ++It)
462 PrologIpLabels.push_back({It->Label, Info->Begin});
463
464 // --- Determine if UNW_FLAG_LARGE is needed for the prolog ---
465 // Conservative: if we KNOW a value exceeds 255 or can't measure, use LARGE.
466 // Reject evaluatable values that are negative or exceed the 16-bit unsigned
467 // range supported by LARGE, since those would be silently truncated.
468 bool NeedsLargeProlog = false;
469 if (Info->PrologEnd) {
470 auto MaybePrologSize =
471 GetOptionalAbsDifference(Asm, Info->PrologEnd, Info->Begin);
472 if (MaybePrologSize) {
473 if (*MaybePrologSize < 0)
474 reportFatalUsageError("Negative SizeOfProlog in V3 unwind info");
475 if (*MaybePrologSize > UINT16_MAX)
477 "SizeOfProlog exceeds 16-bit range for V3 unwind info");
478 NeedsLargeProlog = (*MaybePrologSize > 255);
479 } else {
480 NeedsLargeProlog = true; // Can't measure -> be conservative
481 }
482 }
483 for (auto &[InstLabel, BeginLabel] : PrologIpLabels) {
484 if (NeedsLargeProlog)
485 break;
486 auto MaybeOffset = GetOptionalAbsDifference(Asm, InstLabel, BeginLabel);
487 if (MaybeOffset) {
488 if (*MaybeOffset < 0)
489 reportFatalUsageError("Negative prolog IP offset in V3 unwind info");
490 if (*MaybeOffset > UINT16_MAX)
492 "Prolog IP offset exceeds 16-bit range for V3 unwind info");
493 NeedsLargeProlog = (*MaybeOffset > 255);
494 } else {
495 NeedsLargeProlog = true; // Can't measure -> be conservative
496 }
497 }
498
499 // --- Per-epilog data preparation ---
500 struct EpilogEmitInfo {
503 uint16_t FirstOp;
504 uint8_t NumberOfOps;
505 bool Inherited;
506 bool NeedsLarge; // EPILOG_INFO_LARGE needed for this epilog
507 };
508
510 for (const auto &[EpilogSym, Epilog] : Info->EpilogMap) {
511 if (Epilog.Instructions.empty())
512 continue;
513
514 EpilogEmitInfo EI;
515 EI.Epilog = &Epilog;
516 EI.NumberOfOps = Epilog.Instructions.size();
517 if (EI.NumberOfOps > 31)
519 "Too many epilog unwind codes for V3 encoding. Maximum "
520 "is 31. This epilog has " +
521 Twine(EI.NumberOfOps));
522 EI.Inherited = false;
523 EI.NeedsLarge = false;
524
525 // Determine if EPILOG_INFO_LARGE is needed.
526 // Check IpOffsetOfLastInstruction (EpilogEnd - EpilogStart).
527 // Reject negative or out-of-range evaluatable values.
528 auto MaybeLastInstOfs =
529 GetOptionalAbsDifference(Asm, Epilog.End, Epilog.Start);
530 if (MaybeLastInstOfs) {
531 if (*MaybeLastInstOfs < 0)
533 "Negative IpOffsetOfLastInstruction in V3 unwind info");
534 if (*MaybeLastInstOfs > UINT16_MAX)
536 "IpOffsetOfLastInstruction exceeds 16-bit range for "
537 "V3 unwind info");
538 EI.NeedsLarge = (*MaybeLastInstOfs > 255);
539 } else {
540 EI.NeedsLarge = true; // Can't measure -> be conservative
541 }
542
543 // Check each epilog IP offset.
544 for (const auto &EpiInst : Epilog.Instructions) {
545 if (EI.NeedsLarge)
546 break;
547 auto MaybeOffset =
548 GetOptionalAbsDifference(Asm, EpiInst.Label, Epilog.Start);
549 if (MaybeOffset) {
550 if (*MaybeOffset < 0)
551 reportFatalUsageError("Negative epilog IP offset in V3 unwind info");
552 if (*MaybeOffset > UINT16_MAX)
554 "Epilog IP offset exceeds 16-bit range for V3 unwind info");
555 EI.NeedsLarge = (*MaybeOffset > 255);
556 } else {
557 EI.NeedsLarge = true; // Can't measure -> be conservative
558 }
559 }
560
561 // Encode this epilog's WODs (forward order: body-to-terminator).
562 for (const auto &Inst : Epilog.Instructions)
563 Win64EH::EncodeWOD(Inst, EI.WODBytes);
564
565 // Pool sharing: try to re-use existing bytes in the pool rather than
566 // appending.
567 if (auto Offset = FindInPool(WODPool, EI.WODBytes)) {
568 EI.FirstOp = *Offset;
569 } else {
570 EI.FirstOp = WODPool.size();
571 WODPool.append(EI.WODBytes.begin(), EI.WODBytes.end());
572 }
573
574 EpilogInfos.push_back(std::move(EI));
575 }
576 if (EpilogInfos.size() > 7)
577 reportFatalUsageError("Too many epilogs for V3 encoding. Maximum is 7."
578 " This function has " +
579 Twine(EpilogInfos.size()));
580
581 // --- Inheritance decisions ---
582 // Per the V3 spec, an epilog descriptor with NumberOfOps == 0 inherits its
583 // effective NumberOfOps, FirstOp, IpOffsetOfLastInstruction, and IP offset
584 // array from the first preceding descriptor with NumberOfOps != 0 (the
585 // "base"), not necessarily the immediately preceding descriptor. An epilog
586 // can therefore use the inherited (3-byte) descriptor when FirstOp,
587 // NumberOfOps, and relative IP offsets all match that base. NeedsLarge is a
588 // deterministic function of those fields (it is set when an IP offset exceeds
589 // the 1-byte range), so a matching FirstOp/NumberOfOps and IP offsets imply a
590 // matching NeedsLarge; we assert that invariant rather than test it.
591 for (unsigned I = 1, Base = 0; I < EpilogInfos.size(); ++I) {
592 auto &BaseEI = EpilogInfos[Base];
593 auto &Curr = EpilogInfos[I];
594 if (Curr.FirstOp == BaseEI.FirstOp &&
595 Curr.NumberOfOps == BaseEI.NumberOfOps &&
596 EpilogIpOffsetsMatch(*Curr.Epilog, *BaseEI.Epilog,
597 OS->getAssembler())) {
598 assert(Curr.NeedsLarge == BaseEI.NeedsLarge &&
599 "NeedsLarge must follow from matching FirstOp, NumberOfOps, and "
600 "IP offsets");
601 Curr.Inherited = true;
602 } else
603 Base = I; // Curr is a full descriptor; it becomes the new base.
604 }
605
606 // --- Compute payload sizes ---
607 unsigned PrologIpEntrySize = NeedsLargeProlog ? 2 : 1;
608 unsigned EpilogDescBytes = 0;
609 for (const auto &EI : EpilogInfos) {
610 if (EI.Inherited) {
611 EpilogDescBytes += 3;
612 } else if (EI.NeedsLarge) {
613 // EPILOG_INFO_V3 (3) + EPILOG_INFO_LARGE_EX_V3 (4) + IP offsets (N*2)
614 EpilogDescBytes += 7 + EI.NumberOfOps * 2;
615 } else {
616 // EPILOG_INFO_V3 (3) + EPILOG_INFO_EX_V3 (3) + IP offsets (N*1)
617 EpilogDescBytes += 6 + EI.NumberOfOps;
618 }
619 }
620
621 unsigned PrologIpBytes = PrologOpCount * PrologIpEntrySize;
622 unsigned WODPoolBytes = WODPool.size();
623 // When UNW_FLAG_LARGE is set, the SizeOfPrologHighByte sits at the start
624 // of the payload (immediately after the 4-byte fixed header) and is
625 // counted in PayloadWords. See decodeUnwindInfoV3 / the V3 spec:
626 // handler_offset = ALIGN_UP(sizeof(UNWIND_INFO_V3) + PayloadWords * 2, 4)
627 unsigned LargeHeaderBytes = NeedsLargeProlog ? 1 : 0;
628 unsigned TotalPayloadBytes =
629 LargeHeaderBytes + PrologIpBytes + EpilogDescBytes + WODPoolBytes;
630 if (TotalPayloadBytes > 255 * 2) {
631 reportFatalUsageError("Too much unwind info for V3 encoding. Maximum is "
632 "510 bytes. This function has " +
633 Twine(TotalPayloadBytes));
634 }
635 uint8_t PayloadWords = (TotalPayloadBytes + 1) / 2;
636
637 // ===================================================================
638 // Phase 2: Emission — emit header, payload, and trailer.
639 // ===================================================================
640
641 // --- Emit header (4 bytes, or 5 when UNW_FLAG_LARGE) ---
642 uint8_t Flags = 0;
643 if (Info->ChainedParent)
644 Flags |= Win64EH::UNW_ChainInfo;
645 else {
646 if (Info->HandlesUnwind)
648 if (Info->HandlesExceptions)
650 }
651 if (NeedsLargeProlog)
652 Flags |= Win64EH::UNW_FlagLarge;
653
654 // Byte 0: (Flags << 3) | Version(3)
655 Streamer.emitInt8((Flags << 3) | 3);
656
657 // Byte 1: SizeOfProlog (low byte, or full 8-bit value when not LARGE)
658 if (Info->PrologEnd) {
659 if (NeedsLargeProlog) {
660 // Emit low byte as a fixup; we'll emit the high byte after Byte 3.
661 // Use a 2-byte value at a temp symbol and extract bytes, OR just emit
662 // the known value if evaluable.
663 auto MaybePrologSize =
664 GetOptionalAbsDifference(Asm, Info->PrologEnd, Info->Begin);
665 if (MaybePrologSize) {
666 Streamer.emitInt8(*MaybePrologSize & 0xFF);
667 } else {
668 // Emit as 1-byte fixup for the low byte.
669 EmitAbsDifference(Streamer, Info->PrologEnd, Info->Begin);
670 }
671 } else {
672 EmitAbsDifference(Streamer, Info->PrologEnd, Info->Begin);
673 }
674 } else {
675 Streamer.emitInt8(0);
676 }
677
678 // Byte 2: PayloadWords
679 Streamer.emitInt8(PayloadWords);
680
681 // Byte 3: (NumberOfEpilogs << 5) | NumberOfPrologOps
682 uint8_t NumberOfEpilogs = EpilogInfos.size();
683 Streamer.emitInt8((NumberOfEpilogs << 5) | (PrologOpCount & 0x1F));
684
685 // Byte 4 (LARGE only): SizeOfPrologHighByte
686 if (NeedsLargeProlog) {
687 if (Info->PrologEnd) {
688 auto MaybePrologSize =
689 GetOptionalAbsDifference(Asm, Info->PrologEnd, Info->Begin);
690 if (MaybePrologSize) {
691 Streamer.emitInt8((*MaybePrologSize >> 8) & 0xFF);
692 } else {
693 // Can't evaluate at this point — emit a fixup that shifts the
694 // difference right by 8 to extract the high byte.
695 const MCExpr *Diff = MCBinaryExpr::createSub(
696 MCSymbolRefExpr::create(Info->PrologEnd, Context),
697 MCSymbolRefExpr::create(Info->Begin, Context), Context);
698 const MCExpr *HighByte = MCBinaryExpr::createLShr(
699 Diff, MCConstantExpr::create(8, Context), Context);
700 Streamer.emitValue(HighByte, 1);
701 }
702 } else {
703 Streamer.emitInt8(0);
704 }
705 }
706
707 // --- Emit prolog IP offsets (8-bit or 16-bit) ---
708 for (auto &[InstLabel, BeginLabel] : PrologIpLabels) {
709 if (NeedsLargeProlog)
710 EmitAbsDifference16(Streamer, InstLabel, BeginLabel);
711 else
712 EmitAbsDifference(Streamer, InstLabel, BeginLabel);
713 }
714
715 // --- Emit epilog descriptors ---
716 const MCSymbol *PrevEpilogStart = nullptr;
717 [[maybe_unused]] uint8_t BaseEpiFlags = 0;
718 for (const auto &EI : EpilogInfos) {
719 const auto &Epilog = *EI.Epilog;
720
721 // FlagsAndNumOps: bits [2:0] = flags, bits [7:3] = NumberOfOps.
722 // For inherited descriptors, NumberOfOps = 0.
723 //
724 // Per the V3 spec, Flags bits 0 and 1 are NOT inherited by a descriptor
725 // with NumberOfOps == 0; the producer must replicate them so they have the
726 // same value as the base descriptor's. Since inheritance requires a
727 // matching NeedsLarge value, EI.NeedsLarge already equals the base's, so we
728 // emit EPILOG_INFO_LARGE for inherited descriptors too.
729 uint8_t EpiFlags = 0;
730 if (EI.NeedsLarge)
731 EpiFlags |= Win64EH::EPILOG_INFO_LARGE;
732 // An inherited descriptor must replicate the base descriptor's flags bits
733 // 0 and 1; verify we are about to emit a byte consistent with the base.
734 assert((!EI.Inherited || (EpiFlags & 0x03) == (BaseEpiFlags & 0x03)) &&
735 "inherited epilog must replicate base descriptor's flags bits 0-1");
736 if (!EI.Inherited)
737 BaseEpiFlags = EpiFlags;
738 uint8_t EpiNumOps = EI.Inherited ? 0 : EI.NumberOfOps;
739 Streamer.emitInt8((EpiNumOps << 3) | EpiFlags);
740
741 // EpilogOffset: signed 16-bit.
742 // For the first epilog: byte offset from fragment start to epilog start.
743 // For subsequent epilogs: delta from the previous epilog's start position.
744 // Emit as a fixup since we may not know the exact distance yet.
745 {
746 const MCSymbol *Base = PrevEpilogStart ? PrevEpilogStart : Info->Begin;
747 const MCExpr *EpilogOffsetExpr = MCBinaryExpr::createSub(
748 MCSymbolRefExpr::create(Epilog.Start, Context),
749 MCSymbolRefExpr::create(Base, Context), Context);
750 // Validate the epilog offset fits in a signed 16-bit field if we can
751 // evaluate it now.
752 int64_t OffsetValue;
753 if (EpilogOffsetExpr->evaluateAsAbsolute(OffsetValue,
754 OS->getAssembler())) {
755 if (OffsetValue < INT16_MIN || OffsetValue > INT16_MAX)
757 "Epilog offset out of signed 16-bit range for V3 encoding");
758 }
759 OS->ensureHeadroom(2);
760 OS->addFixup(EpilogOffsetExpr, FK_Data_2);
761 OS->appendContents(2, 0);
762 }
763 PrevEpilogStart = Epilog.Start;
764
765 // Full descriptor fields (only for non-inherited epilogs).
766 if (!EI.Inherited) {
767 // FirstOp: byte offset into WOD pool (2 bytes LE).
768 Streamer.emitInt8(EI.FirstOp & 0xFF);
769 Streamer.emitInt8((EI.FirstOp >> 8) & 0xFF);
770
771 // IpOffsetOfLastInstruction: 8-bit or 16-bit depending on
772 // EPILOG_INFO_LARGE.
773 {
774 const MCExpr *LastInstOffsetExpr = MCBinaryExpr::createSub(
775 MCSymbolRefExpr::create(Epilog.End, Context),
776 MCSymbolRefExpr::create(Epilog.Start, Context), Context);
777 unsigned FixupSize = EI.NeedsLarge ? 2 : 1;
778 OS->ensureHeadroom(FixupSize);
779 OS->addFixup(LastInstOffsetExpr, EI.NeedsLarge ? FK_Data_2 : FK_Data_1);
780 OS->appendContents(FixupSize, 0);
781 }
782
783 // Epilog IP offsets (forward order: body-to-terminator).
784 for (const auto &EpiInst : Epilog.Instructions) {
785 if (EI.NeedsLarge)
786 EmitAbsDifference16(Streamer, EpiInst.Label, Epilog.Start);
787 else
788 EmitAbsDifference(Streamer, EpiInst.Label, Epilog.Start);
789 }
790 }
791 }
792
793 // --- Emit WOD pool ---
794 for (uint8_t B : WODPool)
795 Streamer.emitInt8(B);
796
797 // --- Pad to PayloadWords * 2 bytes ---
798 // PayloadWords = (TotalPayloadBytes + 1) / 2, so at most 1 byte of padding.
799 if (TotalPayloadBytes % 2 != 0)
800 Streamer.emitInt8(0);
801
802 // --- Pad to 4-byte boundary before handler/chain info ---
803 // Per the V3 spec, the handler RVA / chained RUNTIME_FUNCTION begins at
804 // handler_offset = ALIGN_UP(sizeof(UNWIND_INFO_V3) + PayloadWords * 2, 4)
805 // The unwind info structure itself is 4-byte aligned, so when PayloadWords
806 // is odd, the natural end of the payload sits at +2 mod 4 and requires 2
807 // additional zero bytes of padding before the handler/chain.
808 if (PayloadWords % 2 != 0)
809 Streamer.emitInt16(0);
810
811 // --- Emit handler/chained info (same position as V1/V2) ---
812 if (Flags & Win64EH::UNW_ChainInfo)
813 EmitRuntimeFunction(Streamer, Info->ChainedParent);
814 else if (Flags &
816 Streamer.emitValue(
817 MCSymbolRefExpr::create(Info->ExceptionHandler,
819 4);
820 else if (PayloadWords == 0) {
821 // Minimum size: pad to 8 bytes total.
822 Streamer.emitInt32(0);
823 }
824}
825
827 // If this UNWIND_INFO already has a symbol, it's already been emitted.
828 if (info->Symbol)
829 return;
830
831 // V3 has a completely different binary layout; dispatch to separate emitter.
832 if (info->Version == 3) {
833 EmitUnwindInfoV3(streamer, info);
834 return;
835 }
836
837 // UOP_Push2 is V3-only and cannot be encoded in V1/V2. Detect this early
838 // (before counting codes) so the error is reported cleanly. This is
839 // reachable from hand-written .s if `.seh_push2regs` is followed by a
840 // per-function `.seh_unwindversion 1` or `2` downgrade.
841 for (const auto &Inst : info->Instructions) {
842 if (Inst.Operation == Win64EH::UOP_Push2) {
843 streamer.getContext().reportError(
844 SMLoc(), "UOP_Push2 (PUSH2 with two registers) requires V3 unwind "
845 "info. Use `.seh_unwindversion 3`.");
846 // Mark the frame as emitted (with no UNWIND_INFO) and bail so we don't
847 // emit malformed bytes or hit a downstream assertion.
848 info->Symbol = streamer.getContext().createTempSymbol();
849 return;
850 }
851 }
852
853 MCContext &context = streamer.getContext();
854 MCObjectStreamer *OS = (MCObjectStreamer *)(&streamer);
855 MCSymbol *Label = context.createTempSymbol();
856
857 streamer.emitValueToAlignment(Align(4));
858 streamer.emitLabel(Label);
859 info->Symbol = Label;
860
861 uint8_t numCodes = CountOfUnwindCodes(info->Instructions);
862 bool LastEpilogIsAtEnd = false;
863 bool AddPaddingEpilogCode = false;
864 uint8_t EpilogSize = 0;
865 bool EnableUnwindV2 = (info->Version >= 2) && !info->EpilogMap.empty();
866 if (EnableUnwindV2) {
867 auto &LastEpilog = info->EpilogMap.back().second;
868
869 // Calculate the size of the epilogs. Note that we +1 to the size so that
870 // the terminator instruction is also included in the epilog (the Windows
871 // unwinder does a simple range check versus the current instruction pointer
872 // so, although there are terminators that are large than 1 byte, the
873 // starting address of the terminator instruction will always be considered
874 // inside the epilog).
875 assert(
876 LastEpilog.UnwindV2Start &&
877 "If unwind v2 is enabled, epilog must have a unwind v2 start marker");
878 assert(LastEpilog.End && "Epilog must have an end");
879 auto MaybeSize = GetOptionalAbsDifference(
880 OS->getAssembler(), LastEpilog.End, LastEpilog.UnwindV2Start);
881 if (!MaybeSize) {
882 context.reportError(LastEpilog.Loc,
883 "Failed to evaluate epilog size for Unwind v2 in " +
884 info->Function->getName());
885 return;
886 }
887 assert(*MaybeSize >= 0);
888 if (*MaybeSize >= (int64_t)UINT8_MAX) {
889 context.reportError(LastEpilog.Loc,
890 "Epilog size is too large for Unwind v2 in " +
891 info->Function->getName());
892 return;
893 }
894 EpilogSize = *MaybeSize + 1;
895
896 // If the last epilog is at the end of the function, we can use a special
897 // encoding for it. Because of our +1 trick for the size, this will only
898 // work where that final terminator instruction is 1 byte long.
899 // NOTE: At the point where the unwind info is emitted, the function may not
900 // have ended yet (e.g., if there is EH Handler Data), so assume that we
901 // aren't at the end (since we can't calculate it).
902 if (info->End) {
903 auto LastEpilogToFuncEnd = GetOptionalAbsDifference(
904 OS->getAssembler(), info->End, LastEpilog.UnwindV2Start);
905 LastEpilogIsAtEnd = (LastEpilogToFuncEnd == EpilogSize);
906 }
907
908 // If we have an odd number of epilog codes, we need to add a padding code.
909 size_t numEpilogCodes =
910 info->EpilogMap.size() + (LastEpilogIsAtEnd ? 0 : 1);
911 if ((numEpilogCodes % 2) != 0) {
912 AddPaddingEpilogCode = true;
913 numEpilogCodes++;
914 }
915
916 // Too many epilogs to handle.
917 if ((size_t)numCodes + numEpilogCodes > UINT8_MAX) {
918 context.reportError(info->FunctionLoc,
919 "Too many unwind codes with Unwind v2 enabled in " +
920 info->Function->getName());
921 return;
922 }
923
924 numCodes += numEpilogCodes;
925 }
926
927 // Upper 3 bits are the version number.
928 uint8_t flags = info->Version;
929 if (info->ChainedParent)
930 flags |= Win64EH::UNW_ChainInfo << 3;
931 else {
932 if (info->HandlesUnwind)
933 flags |= Win64EH::UNW_TerminateHandler << 3;
934 if (info->HandlesExceptions)
935 flags |= Win64EH::UNW_ExceptionHandler << 3;
936 }
937 streamer.emitInt8(flags);
938
939 if (info->PrologEnd)
940 EmitAbsDifference(streamer, info->PrologEnd, info->Begin);
941 else
942 streamer.emitInt8(0);
943
944 streamer.emitInt8(numCodes);
945
946 uint8_t frame = 0;
947 if (info->LastFrameInst >= 0) {
948 WinEH::Instruction &frameInst = info->Instructions[info->LastFrameInst];
950 frame = (frameInst.Register & 0x0F) | (frameInst.Offset & 0xF0);
951 }
952 streamer.emitInt8(frame);
953
954 // Emit the epilog instructions.
955 if (EnableUnwindV2) {
956 // Ensure the fixups and appended content apply to the same fragment.
957 // size byte + flags byte + 2 per epilog (for the distance).
958 OS->ensureHeadroom(2 + info->EpilogMap.size() * 2);
959
960 bool IsLast = true;
961 for (const auto &Epilog : llvm::reverse(info->EpilogMap)) {
962 if (IsLast) {
963 IsLast = false;
964 uint8_t Flags = LastEpilogIsAtEnd ? 0x01 : 0;
965 OS->emitInt8(EpilogSize);
966 OS->emitInt8((Flags << 4) | Win64EH::UOP_Epilog);
967
968 if (LastEpilogIsAtEnd)
969 continue;
970 }
971
972 // Each epilog is emitted as a fixup, since we can't measure the distance
973 // between the start of the epilog and the end of the function until
974 // layout has been completed.
975 auto *MCE = MCUnwindV2EpilogTargetExpr::create(*info, Epilog.second,
976 EpilogSize, context);
977 OS->addFixup(MCE, FK_Data_2);
978 OS->appendContents(2, 0);
979 }
980 }
981 if (AddPaddingEpilogCode)
982 streamer.emitInt16(Win64EH::UOP_Epilog << 8);
983
984 // Emit unwind instructions (in reverse order).
985 uint8_t numInst = info->Instructions.size();
986 for (uint8_t c = 0; c < numInst; ++c) {
987 WinEH::Instruction inst = info->Instructions.back();
988 info->Instructions.pop_back();
989 EmitUnwindCode(streamer, info->Begin, inst);
990 }
991
992 // For alignment purposes, the instruction array will always have an even
993 // number of entries, with the final entry potentially unused (in which case
994 // the array will be one longer than indicated by the count of unwind codes
995 // field).
996 if (numCodes & 1) {
997 streamer.emitInt16(0);
998 }
999
1000 if (flags & (Win64EH::UNW_ChainInfo << 3))
1001 EmitRuntimeFunction(streamer, info->ChainedParent);
1002 else if (flags &
1004 streamer.emitValue(MCSymbolRefExpr::create(info->ExceptionHandler,
1006 context), 4);
1007 else if (numCodes == 0) {
1008 // The minimum size of an UNWIND_INFO struct is 8 bytes. If we're not
1009 // a chained unwind info, if there is no handler, and if there are fewer
1010 // than 2 slots used in the unwind code array, we have to pad to 8 bytes.
1011 streamer.emitInt32(0);
1012 }
1013}
1014
1015bool MCUnwindV2EpilogTargetExpr::evaluateAsRelocatableImpl(
1016 MCValue &Res, const MCAssembler *Asm) const {
1017 // Calculate the offset to this epilog, and validate it's within the allowed
1018 // range.
1019 auto Offset = GetOptionalAbsDifference(*Asm, FrameInfo.End, UnwindV2Start);
1020 if (!Offset) {
1021 Asm->getContext().reportError(
1022 Loc, "Failed to evaluate epilog offset for Unwind v2 in " +
1023 FrameInfo.Function->getName());
1024 return false;
1025 }
1026 assert(*Offset > 0);
1027 constexpr uint16_t MaxEpilogOffset = 0x0fff;
1028 if (*Offset > MaxEpilogOffset) {
1029 Asm->getContext().reportError(
1030 Loc, "Epilog offset is too large for Unwind v2 in " +
1031 FrameInfo.Function->getName());
1032 return false;
1033 }
1034
1035 // Validate that all epilogs are the same size.
1036 auto Size = GetOptionalAbsDifference(*Asm, EpilogEnd, UnwindV2Start);
1037 if (Size != (EpilogSize - 1)) {
1038 Asm->getContext().reportError(
1039 Loc, "Size of this epilog does not match size of last epilog in " +
1040 FrameInfo.Function->getName());
1041 return false;
1042 }
1043
1044 auto HighBits = *Offset >> 8;
1045 Res = MCValue::get((HighBits << 12) | (Win64EH::UOP_Epilog << 8) |
1046 (*Offset & 0xFF));
1047 return true;
1048}
1049
1051 // Emit the unwind info structs first.
1052 for (const auto &CFI : Streamer.getWinFrameInfos()) {
1053 MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
1054 Streamer.switchSection(XData);
1055 ::EmitUnwindInfo(Streamer, CFI.get());
1056 }
1057
1058 // Now emit RUNTIME_FUNCTION entries.
1059 for (const auto &CFI : Streamer.getWinFrameInfos()) {
1060 MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
1061 Streamer.switchSection(PData);
1062 EmitRuntimeFunction(Streamer, CFI.get());
1063 }
1064}
1065
1068 bool HandlerData) const {
1069 // Switch sections (the static function above is meant to be called from
1070 // here and from Emit().
1071 MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
1072 Streamer.switchSection(XData);
1073
1074 ::EmitUnwindInfo(Streamer, info);
1075}
1076
1077static const MCExpr *GetSubDivExpr(MCStreamer &Streamer, const MCSymbol *LHS,
1078 const MCSymbol *RHS, int Div) {
1079 MCContext &Context = Streamer.getContext();
1080 const MCExpr *Expr =
1082 MCSymbolRefExpr::create(RHS, Context), Context);
1083 if (Div != 1)
1084 Expr = MCBinaryExpr::createDiv(Expr, MCConstantExpr::create(Div, Context),
1085 Context);
1086 return Expr;
1087}
1088
1089static std::optional<int64_t> GetOptionalAbsDifference(MCStreamer &Streamer,
1090 const MCSymbol *LHS,
1091 const MCSymbol *RHS) {
1092 MCObjectStreamer *OS = (MCObjectStreamer *)(&Streamer);
1094}
1095
1096static int64_t GetAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS,
1097 const MCSymbol *RHS) {
1098 std::optional<int64_t> MaybeDiff =
1099 GetOptionalAbsDifference(Streamer, LHS, RHS);
1100 if (!MaybeDiff)
1101 report_fatal_error("Failed to evaluate function length in SEH unwind info");
1102 return *MaybeDiff;
1103}
1104
1107 const MCSymbol *Begin, const MCSymbol *End,
1108 StringRef Name, StringRef Type) {
1109 if (!End)
1110 return;
1111 std::optional<int64_t> MaybeDistance =
1112 GetOptionalAbsDifference(Streamer, End, Begin);
1113 if (!MaybeDistance)
1114 return;
1115 uint32_t Distance = (uint32_t)*MaybeDistance;
1116
1117 for (const auto &I : Insns) {
1118 switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
1119 default:
1120 break;
1126 // Can't reason about these opcodes and how they map to actual
1127 // instructions.
1128 return;
1129 }
1130 }
1131 // Exclude the end opcode which doesn't map to an instruction.
1132 uint32_t InstructionBytes = 4 * (Insns.size() - 1);
1133 if (Distance != InstructionBytes) {
1134 Streamer.getContext().reportError(
1135 SMLoc(), "Incorrect size for " + Name + " " + Type + ": " +
1136 Twine(Distance) +
1137 " bytes of instructions in range, but .seh directives "
1138 "corresponding to " +
1139 Twine(InstructionBytes) + " bytes\n");
1140 }
1141}
1142
1144 uint32_t Count = 0;
1145 for (const auto &I : Insns) {
1146 switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
1147 default:
1148 llvm_unreachable("Unsupported ARM64 unwind code");
1150 Count += 1;
1151 break;
1153 Count += 2;
1154 break;
1156 Count += 4;
1157 break;
1159 Count += 1;
1160 break;
1162 Count += 1;
1163 break;
1165 Count += 1;
1166 break;
1168 Count += 2;
1169 break;
1171 Count += 2;
1172 break;
1174 Count += 2;
1175 break;
1177 Count += 2;
1178 break;
1180 Count += 2;
1181 break;
1183 Count += 2;
1184 break;
1186 Count += 2;
1187 break;
1189 Count += 2;
1190 break;
1192 Count += 2;
1193 break;
1194 case Win64EH::UOP_SetFP:
1195 Count += 1;
1196 break;
1197 case Win64EH::UOP_AddFP:
1198 Count += 2;
1199 break;
1200 case Win64EH::UOP_Nop:
1201 Count += 1;
1202 break;
1203 case Win64EH::UOP_End:
1204 Count += 1;
1205 break;
1207 Count += 1;
1208 break;
1210 Count += 1;
1211 break;
1213 Count += 1;
1214 break;
1216 Count += 1;
1217 break;
1219 Count += 1;
1220 break;
1222 Count += 1;
1223 break;
1225 Count += 1;
1226 break;
1228 Count += 2;
1229 break;
1244 Count += 3;
1245 break;
1246 }
1247 }
1248 return Count;
1249}
1250
1251// Unwind opcode encodings and restrictions are documented at
1252// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
1253static void ARM64EmitUnwindCode(MCStreamer &streamer,
1254 const WinEH::Instruction &inst) {
1255 uint8_t b, reg;
1256 switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
1257 default:
1258 llvm_unreachable("Unsupported ARM64 unwind code");
1260 b = (inst.Offset >> 4) & 0x1F;
1261 streamer.emitInt8(b);
1262 break;
1264 uint16_t hw = (inst.Offset >> 4) & 0x7FF;
1265 b = 0xC0;
1266 b |= (hw >> 8);
1267 streamer.emitInt8(b);
1268 b = hw & 0xFF;
1269 streamer.emitInt8(b);
1270 break;
1271 }
1273 uint32_t w;
1274 b = 0xE0;
1275 streamer.emitInt8(b);
1276 w = inst.Offset >> 4;
1277 b = (w & 0x00FF0000) >> 16;
1278 streamer.emitInt8(b);
1279 b = (w & 0x0000FF00) >> 8;
1280 streamer.emitInt8(b);
1281 b = w & 0x000000FF;
1282 streamer.emitInt8(b);
1283 break;
1284 }
1285 case Win64EH::UOP_SetFP:
1286 b = 0xE1;
1287 streamer.emitInt8(b);
1288 break;
1289 case Win64EH::UOP_AddFP:
1290 b = 0xE2;
1291 streamer.emitInt8(b);
1292 b = (inst.Offset >> 3);
1293 streamer.emitInt8(b);
1294 break;
1295 case Win64EH::UOP_Nop:
1296 b = 0xE3;
1297 streamer.emitInt8(b);
1298 break;
1300 b = 0x20;
1301 b |= (inst.Offset >> 3) & 0x1F;
1302 streamer.emitInt8(b);
1303 break;
1305 b = 0x80;
1306 b |= ((inst.Offset >> 3) - 1) & 0x3F;
1307 streamer.emitInt8(b);
1308 break;
1310 b = 0x40;
1311 b |= (inst.Offset >> 3) & 0x3F;
1312 streamer.emitInt8(b);
1313 break;
1315 assert(inst.Register >= 19 && "Saved reg must be >= 19");
1316 reg = inst.Register - 19;
1317 b = 0xD0 | ((reg & 0xC) >> 2);
1318 streamer.emitInt8(b);
1319 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
1320 streamer.emitInt8(b);
1321 break;
1323 assert(inst.Register >= 19 && "Saved reg must be >= 19");
1324 reg = inst.Register - 19;
1325 b = 0xD4 | ((reg & 0x8) >> 3);
1326 streamer.emitInt8(b);
1327 b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
1328 streamer.emitInt8(b);
1329 break;
1331 assert(inst.Register >= 19 && "Saved registers must be >= 19");
1332 reg = inst.Register - 19;
1333 b = 0xC8 | ((reg & 0xC) >> 2);
1334 streamer.emitInt8(b);
1335 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
1336 streamer.emitInt8(b);
1337 break;
1339 assert(inst.Register >= 19 && "Saved registers must be >= 19");
1340 reg = inst.Register - 19;
1341 b = 0xCC | ((reg & 0xC) >> 2);
1342 streamer.emitInt8(b);
1343 b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
1344 streamer.emitInt8(b);
1345 break;
1347 assert(inst.Register >= 19 && "Saved reg must be >= 19");
1348 reg = inst.Register - 19;
1349 assert((reg % 2) == 0 && "Saved reg must be 19+2*X");
1350 reg /= 2;
1351 b = 0xD6 | ((reg & 0x7) >> 2);
1352 streamer.emitInt8(b);
1353 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
1354 streamer.emitInt8(b);
1355 break;
1357 assert(inst.Register >= 8 && "Saved dreg must be >= 8");
1358 reg = inst.Register - 8;
1359 b = 0xDC | ((reg & 0x4) >> 2);
1360 streamer.emitInt8(b);
1361 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
1362 streamer.emitInt8(b);
1363 break;
1365 assert(inst.Register >= 8 && "Saved dreg must be >= 8");
1366 reg = inst.Register - 8;
1367 b = 0xDE;
1368 streamer.emitInt8(b);
1369 b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
1370 streamer.emitInt8(b);
1371 break;
1373 assert(inst.Register >= 8 && "Saved dregs must be >= 8");
1374 reg = inst.Register - 8;
1375 b = 0xD8 | ((reg & 0x4) >> 2);
1376 streamer.emitInt8(b);
1377 b = ((reg & 0x3) << 6) | (inst.Offset >> 3);
1378 streamer.emitInt8(b);
1379 break;
1381 assert(inst.Register >= 8 && "Saved dregs must be >= 8");
1382 reg = inst.Register - 8;
1383 b = 0xDA | ((reg & 0x4) >> 2);
1384 streamer.emitInt8(b);
1385 b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
1386 streamer.emitInt8(b);
1387 break;
1388 case Win64EH::UOP_End:
1389 b = 0xE4;
1390 streamer.emitInt8(b);
1391 break;
1393 b = 0xE6;
1394 streamer.emitInt8(b);
1395 break;
1397 b = 0xE8;
1398 streamer.emitInt8(b);
1399 break;
1401 b = 0xE9;
1402 streamer.emitInt8(b);
1403 break;
1405 b = 0xEA;
1406 streamer.emitInt8(b);
1407 break;
1409 b = 0xEB;
1410 streamer.emitInt8(b);
1411 break;
1413 b = 0xEC;
1414 streamer.emitInt8(b);
1415 break;
1417 b = 0xFC;
1418 streamer.emitInt8(b);
1419 break;
1432 // This assumes the opcodes are listed in the enum in a particular order.
1434 int Writeback = Op / 6;
1435 int Paired = Op % 2;
1436 int Mode = (Op / 2) % 3;
1437 int Offset = inst.Offset >> 3;
1438 if (Writeback || Paired || Mode == 2)
1439 Offset >>= 1;
1440 if (Writeback)
1441 --Offset;
1442 b = 0xE7;
1443 streamer.emitInt8(b);
1444 assert(inst.Register < 32);
1445 b = inst.Register | (Writeback << 5) | (Paired << 6);
1446 streamer.emitInt8(b);
1447 b = Offset | (Mode << 6);
1448 streamer.emitInt8(b);
1449 break;
1450 }
1451 case Win64EH::UOP_AllocZ: {
1452 b = 0xDF;
1453 streamer.emitInt8(b);
1454 b = inst.Offset;
1455 streamer.emitInt8(b);
1456 break;
1457 }
1458 case Win64EH::UOP_SaveZReg: {
1459 assert(inst.Register >= 8 && inst.Register <= 23);
1460 assert(inst.Offset < 256);
1461 b = 0xE7;
1462 streamer.emitInt8(b);
1463 reg = inst.Register - 8;
1464 b = ((inst.Offset & 0xC0) >> 1) | reg;
1465 streamer.emitInt8(b);
1466 b = 0xC0 | (inst.Offset & 0x3F);
1467 streamer.emitInt8(b);
1468 break;
1469 }
1470 case Win64EH::UOP_SavePReg: {
1471 assert(inst.Register >= 4 && inst.Register <= 15);
1472 assert(inst.Offset < 256);
1473 b = 0xE7;
1474 streamer.emitInt8(b);
1475 reg = inst.Register;
1476 b = ((inst.Offset & 0xC0) >> 1) | 0x10 | reg;
1477 streamer.emitInt8(b);
1478 b = 0xC0 | (inst.Offset & 0x3F);
1479 streamer.emitInt8(b);
1480 break;
1481 }
1482 }
1483}
1484
1485// Returns the epilog symbol of an epilog with the exact same unwind code
1486// sequence, if it exists. Otherwise, returns nullptr.
1487// EpilogInstrs - Unwind codes for the current epilog.
1488// Epilogs - Epilogs that potentialy match the current epilog.
1489static MCSymbol*
1490FindMatchingEpilog(const std::vector<WinEH::Instruction>& EpilogInstrs,
1491 const std::vector<MCSymbol *>& Epilogs,
1492 const WinEH::FrameInfo *info) {
1493 for (auto *EpilogStart : Epilogs) {
1494 auto InstrsIter = info->EpilogMap.find(EpilogStart);
1495 assert(InstrsIter != info->EpilogMap.end() &&
1496 "Epilog not found in EpilogMap");
1497 const auto &Instrs = InstrsIter->second.Instructions;
1498
1499 if (Instrs.size() != EpilogInstrs.size())
1500 continue;
1501
1502 bool Match = true;
1503 for (unsigned i = 0; i < Instrs.size(); ++i)
1504 if (Instrs[i] != EpilogInstrs[i]) {
1505 Match = false;
1506 break;
1507 }
1508
1509 if (Match)
1510 return EpilogStart;
1511 }
1512 return nullptr;
1513}
1514
1515static void simplifyARM64Opcodes(std::vector<WinEH::Instruction> &Instructions,
1516 bool Reverse) {
1517 unsigned PrevOffset = -1;
1518 unsigned PrevRegister = -1;
1519
1520 // Iterate over instructions in a forward order (for prologues),
1521 // backwards for epilogues (i.e. always reverse compared to how the
1522 // opcodes are stored).
1523 for (WinEH::Instruction &Inst :
1524 llvm::reverse_conditionally(Instructions, Reverse)) {
1525 // Convert 2-byte opcodes into equivalent 1-byte ones.
1526 if (Inst.Operation == Win64EH::UOP_SaveRegP && Inst.Register == 29) {
1527 Inst.Operation = Win64EH::UOP_SaveFPLR;
1528 Inst.Register = -1;
1529 } else if (Inst.Operation == Win64EH::UOP_SaveRegPX &&
1530 Inst.Register == 29) {
1531 Inst.Operation = Win64EH::UOP_SaveFPLRX;
1532 Inst.Register = -1;
1533 } else if (Inst.Operation == Win64EH::UOP_SaveRegPX &&
1534 Inst.Register == 19 && Inst.Offset <= 248) {
1535 Inst.Operation = Win64EH::UOP_SaveR19R20X;
1536 Inst.Register = -1;
1537 } else if (Inst.Operation == Win64EH::UOP_AddFP && Inst.Offset == 0) {
1538 Inst.Operation = Win64EH::UOP_SetFP;
1539 } else if (Inst.Operation == Win64EH::UOP_SaveRegP &&
1540 Inst.Register == PrevRegister + 2 &&
1541 Inst.Offset == PrevOffset + 16) {
1542 Inst.Operation = Win64EH::UOP_SaveNext;
1543 Inst.Register = -1;
1544 Inst.Offset = 0;
1545 // Intentionally not creating UOP_SaveNext for float register pairs,
1546 // as current versions of Windows (up to at least 20.04) is buggy
1547 // regarding SaveNext for float pairs.
1548 }
1549 // Update info about the previous instruction, for detecting if
1550 // the next one can be made a UOP_SaveNext
1551 if (Inst.Operation == Win64EH::UOP_SaveR19R20X) {
1552 PrevOffset = 0;
1553 PrevRegister = 19;
1554 } else if (Inst.Operation == Win64EH::UOP_SaveRegPX) {
1555 PrevOffset = 0;
1556 PrevRegister = Inst.Register;
1557 } else if (Inst.Operation == Win64EH::UOP_SaveRegP) {
1558 PrevOffset = Inst.Offset;
1559 PrevRegister = Inst.Register;
1560 } else if (Inst.Operation == Win64EH::UOP_SaveNext) {
1561 PrevRegister += 2;
1562 PrevOffset += 16;
1563 } else {
1564 PrevRegister = -1;
1565 PrevOffset = -1;
1566 }
1567 }
1568}
1569
1570// Check if an epilog exists as a subset of the end of a prolog (backwards).
1571static int
1572getARM64OffsetInProlog(const std::vector<WinEH::Instruction> &Prolog,
1573 const std::vector<WinEH::Instruction> &Epilog) {
1574 // Can't find an epilog as a subset if it is longer than the prolog.
1575 if (Epilog.size() > Prolog.size())
1576 return -1;
1577
1578 // Check that the epilog actually is a perfect match for the end (backwrds)
1579 // of the prolog.
1580 for (int I = Epilog.size() - 1; I >= 0; I--) {
1581 if (Prolog[I] != Epilog[Epilog.size() - 1 - I])
1582 return -1;
1583 }
1584
1585 if (Epilog.size() == Prolog.size())
1586 return 0;
1587
1588 // If the epilog was a subset of the prolog, find its offset.
1590 &Prolog[Epilog.size()], Prolog.size() - Epilog.size()));
1591}
1592
1595 int PrologCodeBytes) {
1596 // Can only pack if there's one single epilog
1597 if (Seg->Epilogs.size() != 1)
1598 return -1;
1599
1600 MCSymbol *Sym = Seg->Epilogs.begin()->first;
1601 const std::vector<WinEH::Instruction> &Epilog =
1602 info->EpilogMap[Sym].Instructions;
1603
1604 // Check that the epilog actually is at the very end of the function,
1605 // otherwise it can't be packed.
1606 uint32_t DistanceFromEnd =
1607 (uint32_t)(Seg->Offset + Seg->Length - Seg->Epilogs.begin()->second);
1608 if (DistanceFromEnd / 4 != Epilog.size())
1609 return -1;
1610
1611 int RetVal = -1;
1612 // Even if we don't end up sharing opcodes with the prolog, we can still
1613 // write the offset as a packed offset, if the single epilog is located at
1614 // the end of the function and the offset (pointing after the prolog) fits
1615 // as a packed offset.
1616 if (PrologCodeBytes <= 31 &&
1617 PrologCodeBytes + ARM64CountOfUnwindCodes(Epilog) <= 124)
1618 RetVal = PrologCodeBytes;
1619
1620 int Offset = getARM64OffsetInProlog(info->Instructions, Epilog);
1621 if (Offset < 0)
1622 return RetVal;
1623
1624 // Check that the offset and prolog size fits in the first word; it's
1625 // unclear whether the epilog count in the extension word can be taken
1626 // as packed epilog offset.
1627 if (Offset > 31 || PrologCodeBytes > 124)
1628 return RetVal;
1629
1630 // As we choose to express the epilog as part of the prolog, remove the
1631 // epilog from the map, so we don't try to emit its opcodes.
1632 info->EpilogMap.erase(Sym);
1633 return Offset;
1634}
1635
1637 int PackedEpilogOffset) {
1638 if (PackedEpilogOffset == 0) {
1639 // Fully symmetric prolog and epilog, should be ok for packed format.
1640 // For CR=3, the corresponding synthesized epilog actually lacks the
1641 // SetFP opcode, but unwinding should work just fine despite that
1642 // (if at the SetFP opcode, the unwinder considers it as part of the
1643 // function body and just unwinds the full prolog instead).
1644 } else if (PackedEpilogOffset == 1) {
1645 // One single case of differences between prolog and epilog is allowed:
1646 // The epilog can lack a single SetFP that is the last opcode in the
1647 // prolog, for the CR=3 case.
1648 if (info->Instructions.back().Operation != Win64EH::UOP_SetFP)
1649 return false;
1650 } else {
1651 // Too much difference between prolog and epilog.
1652 return false;
1653 }
1654 unsigned RegI = 0, RegF = 0;
1655 int Predecrement = 0;
1656 enum {
1657 Start,
1658 Start2,
1659 Start3,
1660 IntRegs,
1661 FloatRegs,
1662 InputArgs,
1663 StackAdjust,
1664 FrameRecord,
1665 End
1666 } Location = Start;
1667 bool StandaloneLR = false, FPLRPair = false;
1668 bool PAC = false;
1669 int StackOffset = 0;
1670 int Nops = 0;
1671 // Iterate over the prolog and check that all opcodes exactly match
1672 // the canonical order and form. A more lax check could verify that
1673 // all saved registers are in the expected locations, but not enforce
1674 // the order - that would work fine when unwinding from within
1675 // functions, but not be exactly right if unwinding happens within
1676 // prologs/epilogs.
1677 for (auto It = info->Instructions.begin(), EndIt = info->Instructions.end();
1678 It != EndIt; It++) {
1679 const WinEH::Instruction &Inst = *It;
1680 switch (Inst.Operation) {
1681 case Win64EH::UOP_End:
1682 if (Location != Start)
1683 return false;
1684 Location = Start2;
1685 break;
1687 if (Location != Start2)
1688 return false;
1689 PAC = true;
1690 Location = Start3;
1691 break;
1693 if (Location != Start2 && Location != Start3)
1694 return false;
1695 Predecrement = Inst.Offset;
1696 RegI = 2;
1697 Location = IntRegs;
1698 break;
1700 if (Location != Start2 && Location != Start3)
1701 return false;
1702 Predecrement = Inst.Offset;
1703 if (Inst.Register == 19)
1704 RegI += 1;
1705 else if (Inst.Register == 30)
1706 StandaloneLR = true;
1707 else
1708 return false;
1709 // Odd register; can't be any further int registers.
1710 Location = FloatRegs;
1711 break;
1713 // Can't have this in a canonical prologue. Either this has been
1714 // canonicalized into SaveR19R20X or SaveFPLRX, or it's an unsupported
1715 // register pair.
1716 // It can't be canonicalized into SaveR19R20X if the offset is
1717 // larger than 248 bytes, but even with the maximum case with
1718 // RegI=10/RegF=8/CR=1/H=1, we end up with SavSZ = 216, which should
1719 // fit into SaveR19R20X.
1720 // The unwinding opcodes can't describe the otherwise seemingly valid
1721 // case for RegI=1 CR=1, that would start with a
1722 // "stp x19, lr, [sp, #-...]!" as that fits neither SaveRegPX nor
1723 // SaveLRPair.
1724 return false;
1726 if (Location != IntRegs || Inst.Offset != 8 * RegI ||
1727 Inst.Register != 19 + RegI)
1728 return false;
1729 RegI += 2;
1730 break;
1732 if (Location != IntRegs || Inst.Offset != 8 * RegI)
1733 return false;
1734 if (Inst.Register == 19 + RegI)
1735 RegI += 1;
1736 else if (Inst.Register == 30)
1737 StandaloneLR = true;
1738 else
1739 return false;
1740 // Odd register; can't be any further int registers.
1741 Location = FloatRegs;
1742 break;
1744 if (Location != IntRegs || Inst.Offset != 8 * RegI ||
1745 Inst.Register != 19 + RegI)
1746 return false;
1747 RegI += 1;
1748 StandaloneLR = true;
1749 Location = FloatRegs;
1750 break;
1752 // Packed unwind can't handle prologs that only save one single
1753 // float register.
1754 return false;
1756 if (Location != FloatRegs || RegF == 0 || Inst.Register != 8 + RegF ||
1757 Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
1758 return false;
1759 RegF += 1;
1760 Location = InputArgs;
1761 break;
1763 if ((Location != Start2 && Location != Start3) || Inst.Register != 8)
1764 return false;
1765 Predecrement = Inst.Offset;
1766 RegF = 2;
1767 Location = FloatRegs;
1768 break;
1770 if ((Location != IntRegs && Location != FloatRegs) ||
1771 Inst.Register != 8 + RegF ||
1772 Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
1773 return false;
1774 RegF += 2;
1775 Location = FloatRegs;
1776 break;
1778 if (Location == IntRegs)
1779 RegI += 2;
1780 else if (Location == FloatRegs)
1781 RegF += 2;
1782 else
1783 return false;
1784 break;
1785 case Win64EH::UOP_Nop:
1786 if (Location != IntRegs && Location != FloatRegs && Location != InputArgs)
1787 return false;
1788 Location = InputArgs;
1789 Nops++;
1790 break;
1793 if (Location != Start2 && Location != Start3 && Location != IntRegs &&
1794 Location != FloatRegs && Location != InputArgs &&
1795 Location != StackAdjust)
1796 return false;
1797 // Becuase there's no save_lrpair_x opcode, the case of CR=01,
1798 // RegI=1 is handled as a special case with a pair of instructions; an
1799 // alloc followed by a regular save_lrpair. So when encountering an
1800 // alloc here, check if this is the start of such an instruction pair.
1801 if (Location == Start2) { // Can't have this at Start3, after PACSignLR
1802 auto NextIt = It + 1;
1803 if (NextIt != EndIt) {
1804 const WinEH::Instruction &NextInst = *NextIt;
1805 if (NextInst.Operation == Win64EH::UOP_SaveLRPair &&
1806 NextInst.Offset == 0 && NextInst.Register == 19) {
1807 assert(Predecrement == 0);
1808 assert(RegI == 0);
1809 assert(!StandaloneLR);
1810 Predecrement = Inst.Offset;
1811 RegI = 1;
1812 StandaloneLR = true;
1813 Location = FloatRegs;
1814 It++; // Consume both the Alloc and the SaveLRPair
1815 continue;
1816 }
1817 }
1818 }
1819 // Can have either a single decrement, or a pair of decrements with
1820 // 4080 and another decrement.
1821 if (StackOffset == 0)
1822 StackOffset = Inst.Offset;
1823 else if (StackOffset != 4080)
1824 return false;
1825 else
1826 StackOffset += Inst.Offset;
1827 Location = StackAdjust;
1828 break;
1830 // Not allowing FPLRX after StackAdjust; if a StackAdjust is used, it
1831 // should be followed by a FPLR instead.
1832 if (Location != Start2 && Location != Start3 && Location != IntRegs &&
1833 Location != FloatRegs && Location != InputArgs)
1834 return false;
1835 StackOffset = Inst.Offset;
1836 Location = FrameRecord;
1837 FPLRPair = true;
1838 break;
1840 // This can only follow after a StackAdjust
1841 if (Location != StackAdjust || Inst.Offset != 0)
1842 return false;
1843 Location = FrameRecord;
1844 FPLRPair = true;
1845 break;
1846 case Win64EH::UOP_SetFP:
1847 if (Location != FrameRecord)
1848 return false;
1849 Location = End;
1850 break;
1863 // These are never canonical; they don't show up with the usual Arm64
1864 // calling convention.
1865 return false;
1867 // Allocations this large can't be represented in packed unwind (and
1868 // usually don't fit the canonical form anyway because we need to use
1869 // __chkstk to allocate the stack space).
1870 return false;
1871 case Win64EH::UOP_AddFP:
1872 // "add x29, sp, #N" doesn't show up in the canonical pattern (except for
1873 // N=0, which is UOP_SetFP).
1874 return false;
1878 // Canonical prologues don't support spilling SVE registers.
1879 return false;
1885 // These are special opcodes that aren't normally generated.
1886 return false;
1887 default:
1888 report_fatal_error("Unknown Arm64 unwind opcode");
1889 }
1890 }
1891 if (RegI > 10 || RegF > 8)
1892 return false;
1893 if (StandaloneLR && FPLRPair)
1894 return false;
1895 if (FPLRPair && Location != End)
1896 return false;
1897 if (Nops != 0 && Nops != 4)
1898 return false;
1899 if (PAC && !FPLRPair)
1900 return false;
1901 int H = Nops == 4;
1902 // For packed unwind info with the H bit set, the prolog and epilog
1903 // actually shouldn't be symmetrical; the epilog shouldn't have any
1904 // nop instructions/opcodes while the prolog has them. We currently
1905 // require exactly symmetrical prologs/epilogs, which is wrong for this
1906 // case - therefore, don't emit packed unwind info for this case.
1907 // See https://github.com/llvm/llvm-project/issues/54879 for details.
1908 //
1909 // Additionally - older versions of Windows also deviated from the
1910 // documentation here; older versions of Windows (at least up until
1911 // 10.0.22000.2176) incorrectly did assume that the epilog has matching
1912 // nop instructions. This is fixed at least in version 10.0.26100.6899.
1913 // As long as we can't assume that the generated code always will run on
1914 // a new enough version, don't emit the packed format here, even if the
1915 // implementation would be fixed to match for the asymmetrical form
1916 // according to the documentation.
1917 if (H)
1918 return false;
1919 // Older versions of Windows (at least in 10.0.22000.2176) incorrectly
1920 // unwind packed unwind info with CR=01, RegI=1, RegF>0, see
1921 // https://github.com/llvm/llvm-project/issues/169588#issuecomment-3584907886.
1922 // This issue only exists in older versions; current versions
1923 // (10.0.26100.6899) do handle it correctly. As long as we can't be sure
1924 // that we won't run on older versions, avoid producing the packed form
1925 // here.
1926 if (StandaloneLR && RegI == 1 && RegF > 0)
1927 return false;
1928 int IntSZ = 8 * RegI;
1929 if (StandaloneLR)
1930 IntSZ += 8;
1931 int FpSZ = 8 * RegF; // RegF not yet decremented
1932 int SavSZ = (IntSZ + FpSZ + 8 * 8 * H + 0xF) & ~0xF;
1933 if (Predecrement != SavSZ)
1934 return false;
1935 if (FPLRPair && StackOffset < 16)
1936 return false;
1937 if (StackOffset % 16)
1938 return false;
1939 uint32_t FrameSize = (StackOffset + SavSZ) / 16;
1940 if (FrameSize > 0x1FF)
1941 return false;
1942 assert(RegF != 1 && "One single float reg not allowed");
1943 if (RegF > 0)
1944 RegF--; // Convert from actual number of registers, to value stored
1945 assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");
1946 int Flag = 0x01; // Function segments not supported yet
1947 int CR = PAC ? 2 : FPLRPair ? 3 : StandaloneLR ? 1 : 0;
1948 info->PackedInfo |= Flag << 0;
1949 info->PackedInfo |= (FuncLength & 0x7FF) << 2;
1950 info->PackedInfo |= (RegF & 0x7) << 13;
1951 info->PackedInfo |= (RegI & 0xF) << 16;
1952 info->PackedInfo |= (H & 0x1) << 20;
1953 info->PackedInfo |= (CR & 0x3) << 21;
1954 info->PackedInfo |= (FrameSize & 0x1FF) << 23;
1955 return true;
1956}
1957
1960 uint32_t &TotalCodeBytes,
1961 MapVector<MCSymbol *, uint32_t> &EpilogInfo) {
1962
1963 std::vector<MCSymbol *> EpilogStarts;
1964 for (auto &I : Seg->Epilogs)
1965 EpilogStarts.push_back(I.first);
1966
1967 // Epilogs processed so far.
1968 std::vector<MCSymbol *> AddedEpilogs;
1969 for (auto *S : EpilogStarts) {
1970 MCSymbol *EpilogStart = S;
1971 auto &EpilogInstrs = info->EpilogMap[S].Instructions;
1972 uint32_t CodeBytes = ARM64CountOfUnwindCodes(EpilogInstrs);
1973
1974 MCSymbol* MatchingEpilog =
1975 FindMatchingEpilog(EpilogInstrs, AddedEpilogs, info);
1976 int PrologOffset;
1977 if (MatchingEpilog) {
1978 assert(EpilogInfo.contains(MatchingEpilog) &&
1979 "Duplicate epilog not found");
1980 EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
1981 // Clear the unwind codes in the EpilogMap, so that they don't get output
1982 // in ARM64EmitUnwindInfoForSegment().
1983 EpilogInstrs.clear();
1984 } else if ((PrologOffset = getARM64OffsetInProlog(info->Instructions,
1985 EpilogInstrs)) >= 0) {
1986 EpilogInfo[EpilogStart] = PrologOffset;
1987 // If the segment doesn't have a prolog, an end_c will be emitted before
1988 // prolog opcodes. So epilog start index in opcodes array is moved by 1.
1989 if (!Seg->HasProlog)
1990 EpilogInfo[EpilogStart] += 1;
1991 // Clear the unwind codes in the EpilogMap, so that they don't get output
1992 // in ARM64EmitUnwindInfoForSegment().
1993 EpilogInstrs.clear();
1994 } else {
1995 EpilogInfo[EpilogStart] = TotalCodeBytes;
1996 TotalCodeBytes += CodeBytes;
1997 AddedEpilogs.push_back(EpilogStart);
1998 }
1999 }
2000}
2001
2004 int64_t RawFuncLength) {
2005 if (info->PrologEnd)
2006 checkARM64Instructions(streamer, info->Instructions, info->Begin,
2007 info->PrologEnd, info->Function->getName(),
2008 "prologue");
2009 struct EpilogStartEnd {
2010 MCSymbol *Start;
2011 int64_t Offset;
2012 int64_t End;
2013 };
2014 // Record Start and End of each epilog.
2016 for (auto &I : info->EpilogMap) {
2017 MCSymbol *Start = I.first;
2018 auto &Instrs = I.second.Instructions;
2019 int64_t Offset = GetAbsDifference(streamer, Start, info->Begin);
2020 checkARM64Instructions(streamer, Instrs, Start, I.second.End,
2021 info->Function->getName(), "epilogue");
2022 assert((Epilogs.size() == 0 || Offset >= Epilogs.back().End) &&
2023 "Epilogs should be monotonically ordered");
2024 // Exclue the end opcode from Instrs.size() when calculating the end of the
2025 // epilog.
2026 Epilogs.push_back({Start, Offset, Offset + (int64_t)(Instrs.size() - 1) * 4});
2027 }
2028
2029 unsigned E = 0;
2030 int64_t SegLimit = 0xFFFFC;
2031 int64_t SegOffset = 0;
2032
2033 if (RawFuncLength > SegLimit) {
2034
2035 int64_t RemainingLength = RawFuncLength;
2036
2037 while (RemainingLength > SegLimit) {
2038 // Try divide the function into segments, requirements:
2039 // 1. Segment length <= 0xFFFFC;
2040 // 2. Each Prologue or Epilogue must be fully within a segment.
2041 int64_t SegLength = SegLimit;
2042 int64_t SegEnd = SegOffset + SegLength;
2043 // Keep record on symbols and offsets of epilogs in this segment.
2044 MapVector<MCSymbol *, int64_t> EpilogsInSegment;
2045
2046 while (E < Epilogs.size() && Epilogs[E].End < SegEnd) {
2047 // Epilogs within current segment.
2048 EpilogsInSegment[Epilogs[E].Start] = Epilogs[E].Offset;
2049 ++E;
2050 }
2051
2052 // At this point, we have:
2053 // 1. Put all epilogs in segments already. No action needed here; or
2054 // 2. Found an epilog that will cross segments boundry. We need to
2055 // move back current segment's end boundry, so the epilog is entirely
2056 // in the next segment; or
2057 // 3. Left at least one epilog that is entirely after this segment.
2058 // It'll be handled by the next iteration, or the last segment.
2059 if (E < Epilogs.size() && Epilogs[E].Offset <= SegEnd)
2060 // Move back current Segment's end boundry.
2061 SegLength = Epilogs[E].Offset - SegOffset;
2062
2063 auto Seg = WinEH::FrameInfo::Segment(
2064 SegOffset, SegLength, /* HasProlog */!SegOffset);
2065 Seg.Epilogs = std::move(EpilogsInSegment);
2066 info->Segments.push_back(Seg);
2067
2068 SegOffset += SegLength;
2069 RemainingLength -= SegLength;
2070 }
2071 }
2072
2073 // Add the last segment when RawFuncLength > 0xFFFFC,
2074 // or the only segment otherwise.
2075 auto LastSeg =
2076 WinEH::FrameInfo::Segment(SegOffset, RawFuncLength - SegOffset,
2077 /* HasProlog */!SegOffset);
2078 for (; E < Epilogs.size(); ++E)
2079 LastSeg.Epilogs[Epilogs[E].Start] = Epilogs[E].Offset;
2080 info->Segments.push_back(LastSeg);
2081}
2082
2086 bool TryPacked = true) {
2087 MCContext &context = streamer.getContext();
2088 MCSymbol *Label = context.createTempSymbol();
2089
2090 streamer.emitValueToAlignment(Align(4));
2091 streamer.emitLabel(Label);
2092 Seg.Symbol = Label;
2093 // Use the 1st segemnt's label as function's.
2094 if (Seg.Offset == 0)
2095 info->Symbol = Label;
2096
2097 bool HasProlog = Seg.HasProlog;
2098 bool HasEpilogs = (Seg.Epilogs.size() != 0);
2099
2100 uint32_t SegLength = (uint32_t)Seg.Length / 4;
2101 uint32_t PrologCodeBytes = info->PrologCodeBytes;
2102
2103 int PackedEpilogOffset = HasEpilogs ?
2104 checkARM64PackedEpilog(streamer, info, &Seg, PrologCodeBytes) : -1;
2105
2106 // TODO:
2107 // 1. Enable packed unwind info (.pdata only) for multi-segment functions.
2108 // 2. Emit packed unwind info (.pdata only) for segments that have neithor
2109 // prolog nor epilog.
2110 if (info->Segments.size() == 1 && PackedEpilogOffset >= 0 &&
2111 uint32_t(PackedEpilogOffset) < PrologCodeBytes &&
2112 !info->HandlesExceptions && SegLength <= 0x7ff && TryPacked) {
2113 // Matching prolog/epilog and no exception handlers; check if the
2114 // prolog matches the patterns that can be described by the packed
2115 // format.
2116
2117 // info->Symbol was already set even if we didn't actually write any
2118 // unwind info there. Keep using that as indicator that this unwind
2119 // info has been generated already.
2120 if (tryARM64PackedUnwind(info, SegLength, PackedEpilogOffset))
2121 return;
2122 }
2123
2124 // If the prolog is not in this segment, we need to emit an end_c, which takes
2125 // 1 byte, before prolog unwind ops.
2126 if (!HasProlog) {
2127 PrologCodeBytes += 1;
2128 if (PackedEpilogOffset >= 0)
2129 PackedEpilogOffset += 1;
2130 // If a segment has neither prolog nor epilog, "With full .xdata record,
2131 // Epilog Count = 1. Epilog Start Index points to end_c."
2132 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling#function-fragments
2133 // TODO: We can remove this if testing shows zero epilog scope is ok with
2134 // MS unwinder.
2135 if (!HasEpilogs)
2136 // Pack the fake epilog into phantom prolog.
2137 PackedEpilogOffset = 0;
2138 }
2139
2140 uint32_t TotalCodeBytes = PrologCodeBytes;
2141
2142 // Process epilogs.
2144 ARM64ProcessEpilogs(info, &Seg, TotalCodeBytes, EpilogInfo);
2145
2146 // Code Words, Epilog count, E, X, Vers, Function Length
2147 uint32_t row1 = 0x0;
2148 uint32_t CodeWords = TotalCodeBytes / 4;
2149 uint32_t CodeWordsMod = TotalCodeBytes % 4;
2150 if (CodeWordsMod)
2151 CodeWords++;
2152 uint32_t EpilogCount =
2153 PackedEpilogOffset >= 0 ? PackedEpilogOffset : Seg.Epilogs.size();
2154 bool ExtensionWord = EpilogCount > 31 || TotalCodeBytes > 124;
2155 if (!ExtensionWord) {
2156 row1 |= (EpilogCount & 0x1F) << 22;
2157 row1 |= (CodeWords & 0x1F) << 27;
2158 }
2159 if (info->HandlesExceptions) // X
2160 row1 |= 1 << 20;
2161 if (PackedEpilogOffset >= 0) // E
2162 row1 |= 1 << 21;
2163 row1 |= SegLength & 0x3FFFF;
2164 streamer.emitInt32(row1);
2165
2166 // Extended Code Words, Extended Epilog Count
2167 if (ExtensionWord) {
2168 // FIXME: We should be able to split unwind info into multiple sections.
2169 if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
2171 "SEH unwind data splitting is only implemented for large functions, "
2172 "cases of too many code words or too many epilogs will be done "
2173 "later");
2174 uint32_t row2 = 0x0;
2175 row2 |= (CodeWords & 0xFF) << 16;
2176 row2 |= (EpilogCount & 0xFFFF);
2177 streamer.emitInt32(row2);
2178 }
2179
2180 if (PackedEpilogOffset < 0) {
2181 // Epilog Start Index, Epilog Start Offset
2182 for (auto &I : EpilogInfo) {
2183 MCSymbol *EpilogStart = I.first;
2184 uint32_t EpilogIndex = I.second;
2185 // Epilog offset within the Segment.
2186 uint32_t EpilogOffset = (uint32_t)(Seg.Epilogs[EpilogStart] - Seg.Offset);
2187 if (EpilogOffset)
2188 EpilogOffset /= 4;
2189 uint32_t row3 = EpilogOffset;
2190 row3 |= (EpilogIndex & 0x3FF) << 22;
2191 streamer.emitInt32(row3);
2192 }
2193 }
2194
2195 // Note that even for segments that have no prolog, we still need to emit
2196 // prolog unwinding opcodes so that the unwinder knows how to unwind from
2197 // such a segment.
2198 // The end_c opcode at the start indicates to the unwinder that the actual
2199 // prolog is outside of the current segment, and the unwinder shouldn't try
2200 // to check for unwinding from a partial prolog.
2201 if (!HasProlog)
2202 // Emit an end_c.
2203 streamer.emitInt8((uint8_t)0xE5);
2204
2205 // Emit prolog unwind instructions (in reverse order).
2206 for (auto Inst : llvm::reverse(info->Instructions))
2207 ARM64EmitUnwindCode(streamer, Inst);
2208
2209 // Emit epilog unwind instructions
2210 for (auto &I : Seg.Epilogs) {
2211 auto &EpilogInstrs = info->EpilogMap[I.first].Instructions;
2212 for (const WinEH::Instruction &inst : EpilogInstrs)
2213 ARM64EmitUnwindCode(streamer, inst);
2214 }
2215
2216 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
2217 assert(BytesMod >= 0);
2218 for (int i = 0; i < BytesMod; i++)
2219 streamer.emitInt8(0xE3);
2220
2221 if (info->HandlesExceptions)
2222 streamer.emitValue(
2223 MCSymbolRefExpr::create(info->ExceptionHandler,
2225 4);
2226}
2227
2228// Populate the .xdata section. The format of .xdata on ARM64 is documented at
2229// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
2231 bool TryPacked = true) {
2232 // If this UNWIND_INFO already has a symbol, it's already been emitted.
2233 if (info->Symbol)
2234 return;
2235 // If there's no unwind info here (not even a terminating UOP_End), the
2236 // unwind info is considered bogus and skipped. If this was done in
2237 // response to an explicit .seh_handlerdata, the associated trailing
2238 // handler data is left orphaned in the xdata section.
2239 if (info->empty()) {
2240 info->EmitAttempted = true;
2241 return;
2242 }
2243 if (info->EmitAttempted) {
2244 // If we tried to emit unwind info before (due to an explicit
2245 // .seh_handlerdata directive), but skipped it (because there was no
2246 // valid information to emit at the time), and it later got valid unwind
2247 // opcodes, we can't emit it here, because the trailing handler data
2248 // was already emitted elsewhere in the xdata section.
2249 streamer.getContext().reportError(
2250 SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +
2251 " skipped due to no unwind info at the time "
2252 "(.seh_handlerdata too early?), but the function later "
2253 "did get unwind info that can't be emitted");
2254 return;
2255 }
2256
2257 simplifyARM64Opcodes(info->Instructions, false);
2258 for (auto &I : info->EpilogMap)
2259 simplifyARM64Opcodes(I.second.Instructions, true);
2260
2261 int64_t RawFuncLength;
2262 if (!info->FuncletOrFuncEnd) {
2263 report_fatal_error("FuncletOrFuncEnd not set");
2264 } else {
2265 // FIXME: GetAbsDifference tries to compute the length of the function
2266 // immediately, before the whole file is emitted, but in general
2267 // that's impossible: the size in bytes of certain assembler directives
2268 // like .align and .fill is not known until the whole file is parsed and
2269 // relaxations are applied. Currently, GetAbsDifference fails with a fatal
2270 // error in that case. (We mostly don't hit this because inline assembly
2271 // specifying those directives is rare, and we don't normally try to
2272 // align loops on AArch64.)
2273 //
2274 // There are two potential approaches to delaying the computation. One,
2275 // we could emit something like ".word (endfunc-beginfunc)/4+0x10800000",
2276 // as long as we have some conservative estimate we could use to prove
2277 // that we don't need to split the unwind data. Emitting the constant
2278 // is straightforward, but there's no existing code for estimating the
2279 // size of the function.
2280 //
2281 // The other approach would be to use a dedicated, relaxable fragment,
2282 // which could grow to accommodate splitting the unwind data if
2283 // necessary. This is more straightforward, since it automatically works
2284 // without any new infrastructure, and it's consistent with how we handle
2285 // relaxation in other contexts. But it would require some refactoring
2286 // to move parts of the pdata/xdata emission into the implementation of
2287 // a fragment. We could probably continue to encode the unwind codes
2288 // here, but we'd have to emit the pdata, the xdata header, and the
2289 // epilogue scopes later, since they depend on whether the we need to
2290 // split the unwind data.
2291 //
2292 // If this is fixed, remove code in AArch64ISelLowering.cpp that
2293 // disables loop alignment on Windows.
2294 RawFuncLength = GetAbsDifference(streamer, info->FuncletOrFuncEnd,
2295 info->Begin);
2296 }
2297
2298 ARM64FindSegmentsInFunction(streamer, info, RawFuncLength);
2299
2300 info->PrologCodeBytes = ARM64CountOfUnwindCodes(info->Instructions);
2301 for (auto &S : info->Segments)
2302 ARM64EmitUnwindInfoForSegment(streamer, info, S, TryPacked);
2303
2304 // Clear prolog instructions after unwind info is emitted for all segments.
2305 info->Instructions.clear();
2306}
2307
2309 uint32_t Count = 0;
2310 for (const auto &I : Insns) {
2311 switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
2312 default:
2313 llvm_unreachable("Unsupported ARM unwind code");
2315 Count += 1;
2316 break;
2318 Count += 3;
2319 break;
2321 Count += 4;
2322 break;
2324 Count += 2;
2325 break;
2327 Count += 3;
2328 break;
2330 Count += 4;
2331 break;
2333 Count += 2;
2334 break;
2336 Count += 1;
2337 break;
2339 Count += 1;
2340 break;
2342 Count += 1;
2343 break;
2345 Count += 1;
2346 break;
2348 Count += 2;
2349 break;
2351 Count += 2;
2352 break;
2354 Count += 2;
2355 break;
2357 Count += 2;
2358 break;
2359 case Win64EH::UOP_Nop:
2361 case Win64EH::UOP_End:
2364 Count += 1;
2365 break;
2366 case Win64EH::UOP_Custom: {
2367 int J;
2368 for (J = 3; J > 0; J--)
2369 if (I.Offset & (0xffu << (8 * J)))
2370 break;
2371 Count += J + 1;
2372 break;
2373 }
2374 }
2375 }
2376 return Count;
2377}
2378
2380 bool *HasCustom = nullptr) {
2381 uint32_t Count = 0;
2382 for (const auto &I : Insns) {
2383 switch (static_cast<Win64EH::UnwindOpcodes>(I.Operation)) {
2384 default:
2385 llvm_unreachable("Unsupported ARM unwind code");
2389 Count += 2;
2390 break;
2394 Count += 4;
2395 break;
2398 Count += 4;
2399 break;
2401 Count += 2;
2402 break;
2405 Count += 2;
2406 break;
2410 Count += 4;
2411 break;
2413 Count += 4;
2414 break;
2415 case Win64EH::UOP_Nop:
2417 Count += 2;
2418 break;
2421 Count += 4;
2422 break;
2423 case Win64EH::UOP_End:
2424 // This doesn't map to any instruction
2425 break;
2427 // We can't reason about what instructions this maps to; return a
2428 // phony number to make sure we don't accidentally do epilog packing.
2429 Count += 1000;
2430 if (HasCustom)
2431 *HasCustom = true;
2432 break;
2433 }
2434 }
2435 return Count;
2436}
2437
2438static void checkARMInstructions(MCStreamer &Streamer,
2440 const MCSymbol *Begin, const MCSymbol *End,
2441 StringRef Name, StringRef Type) {
2442 if (!End)
2443 return;
2444 std::optional<int64_t> MaybeDistance =
2445 GetOptionalAbsDifference(Streamer, End, Begin);
2446 if (!MaybeDistance)
2447 return;
2448 uint32_t Distance = (uint32_t)*MaybeDistance;
2449 bool HasCustom = false;
2450 uint32_t InstructionBytes = ARMCountOfInstructionBytes(Insns, &HasCustom);
2451 if (HasCustom)
2452 return;
2453 if (Distance != InstructionBytes) {
2454 Streamer.getContext().reportError(
2455 SMLoc(), "Incorrect size for " + Name + " " + Type + ": " +
2456 Twine(Distance) +
2457 " bytes of instructions in range, but .seh directives "
2458 "corresponding to " +
2459 Twine(InstructionBytes) + " bytes\n");
2460 }
2461}
2462
2463static bool isARMTerminator(const WinEH::Instruction &inst) {
2464 switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
2465 case Win64EH::UOP_End:
2468 return true;
2469 default:
2470 return false;
2471 }
2472}
2473
2474// Unwind opcode encodings and restrictions are documented at
2475// https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling
2476static void ARMEmitUnwindCode(MCStreamer &streamer,
2477 const WinEH::Instruction &inst) {
2478 uint32_t w, lr;
2479 int i;
2480 switch (static_cast<Win64EH::UnwindOpcodes>(inst.Operation)) {
2481 default:
2482 llvm_unreachable("Unsupported ARM unwind code");
2484 assert((inst.Offset & 3) == 0);
2485 assert(inst.Offset / 4 <= 0x7f);
2486 streamer.emitInt8(inst.Offset / 4);
2487 break;
2489 assert((inst.Register & ~0x5fff) == 0);
2490 lr = (inst.Register >> 14) & 1;
2491 w = 0x8000 | (inst.Register & 0x1fff) | (lr << 13);
2492 streamer.emitInt8((w >> 8) & 0xff);
2493 streamer.emitInt8((w >> 0) & 0xff);
2494 break;
2496 assert(inst.Register <= 0x0f);
2497 streamer.emitInt8(0xc0 | inst.Register);
2498 break;
2500 assert(inst.Register >= 4 && inst.Register <= 7);
2501 assert(inst.Offset <= 1);
2502 streamer.emitInt8(0xd0 | (inst.Register - 4) | (inst.Offset << 2));
2503 break;
2505 assert(inst.Register >= 8 && inst.Register <= 11);
2506 assert(inst.Offset <= 1);
2507 streamer.emitInt8(0xd8 | (inst.Register - 8) | (inst.Offset << 2));
2508 break;
2510 assert(inst.Register >= 8 && inst.Register <= 15);
2511 streamer.emitInt8(0xe0 | (inst.Register - 8));
2512 break;
2514 assert((inst.Offset & 3) == 0);
2515 assert(inst.Offset / 4 <= 0x3ff);
2516 w = 0xe800 | (inst.Offset / 4);
2517 streamer.emitInt8((w >> 8) & 0xff);
2518 streamer.emitInt8((w >> 0) & 0xff);
2519 break;
2521 assert((inst.Register & ~0x40ff) == 0);
2522 lr = (inst.Register >> 14) & 1;
2523 w = 0xec00 | (inst.Register & 0x0ff) | (lr << 8);
2524 streamer.emitInt8((w >> 8) & 0xff);
2525 streamer.emitInt8((w >> 0) & 0xff);
2526 break;
2528 assert((inst.Offset & 3) == 0);
2529 assert(inst.Offset / 4 <= 0x0f);
2530 streamer.emitInt8(0xef);
2531 streamer.emitInt8(inst.Offset / 4);
2532 break;
2534 assert(inst.Register <= 15);
2535 assert(inst.Offset <= 15);
2536 assert(inst.Register <= inst.Offset);
2537 streamer.emitInt8(0xf5);
2538 streamer.emitInt8((inst.Register << 4) | inst.Offset);
2539 break;
2541 assert(inst.Register >= 16 && inst.Register <= 31);
2542 assert(inst.Offset >= 16 && inst.Offset <= 31);
2543 assert(inst.Register <= inst.Offset);
2544 streamer.emitInt8(0xf6);
2545 streamer.emitInt8(((inst.Register - 16) << 4) | (inst.Offset - 16));
2546 break;
2548 assert((inst.Offset & 3) == 0);
2549 assert(inst.Offset / 4 <= 0xffff);
2550 w = inst.Offset / 4;
2551 streamer.emitInt8(0xf7);
2552 streamer.emitInt8((w >> 8) & 0xff);
2553 streamer.emitInt8((w >> 0) & 0xff);
2554 break;
2556 assert((inst.Offset & 3) == 0);
2557 assert(inst.Offset / 4 <= 0xffffff);
2558 w = inst.Offset / 4;
2559 streamer.emitInt8(0xf8);
2560 streamer.emitInt8((w >> 16) & 0xff);
2561 streamer.emitInt8((w >> 8) & 0xff);
2562 streamer.emitInt8((w >> 0) & 0xff);
2563 break;
2565 assert((inst.Offset & 3) == 0);
2566 assert(inst.Offset / 4 <= 0xffff);
2567 w = inst.Offset / 4;
2568 streamer.emitInt8(0xf9);
2569 streamer.emitInt8((w >> 8) & 0xff);
2570 streamer.emitInt8((w >> 0) & 0xff);
2571 break;
2573 assert((inst.Offset & 3) == 0);
2574 assert(inst.Offset / 4 <= 0xffffff);
2575 w = inst.Offset / 4;
2576 streamer.emitInt8(0xfa);
2577 streamer.emitInt8((w >> 16) & 0xff);
2578 streamer.emitInt8((w >> 8) & 0xff);
2579 streamer.emitInt8((w >> 0) & 0xff);
2580 break;
2581 case Win64EH::UOP_Nop:
2582 streamer.emitInt8(0xfb);
2583 break;
2585 streamer.emitInt8(0xfc);
2586 break;
2588 streamer.emitInt8(0xfd);
2589 break;
2591 streamer.emitInt8(0xfe);
2592 break;
2593 case Win64EH::UOP_End:
2594 streamer.emitInt8(0xff);
2595 break;
2597 for (i = 3; i > 0; i--)
2598 if (inst.Offset & (0xffu << (8 * i)))
2599 break;
2600 for (; i >= 0; i--)
2601 streamer.emitInt8((inst.Offset >> (8 * i)) & 0xff);
2602 break;
2603 }
2604}
2605
2606// Check if an epilog exists as a subset of the end of a prolog (backwards).
2607// An epilog may end with one out of three different end opcodes; if this
2608// is the first epilog that shares opcodes with the prolog, we can tolerate
2609// that this opcode differs (and the caller will update the prolog to use
2610// the same end opcode as the epilog). If another epilog already shares
2611// opcodes with the prolog, the ending opcode must be a strict match.
2612static int getARMOffsetInProlog(const std::vector<WinEH::Instruction> &Prolog,
2613 const std::vector<WinEH::Instruction> &Epilog,
2614 bool CanTweakProlog) {
2615 // Can't find an epilog as a subset if it is longer than the prolog.
2616 if (Epilog.size() > Prolog.size())
2617 return -1;
2618
2619 // Check that the epilog actually is a perfect match for the end (backwrds)
2620 // of the prolog.
2621 // If we can adjust the prolog afterwards, don't check that the end opcodes
2622 // match.
2623 int EndIdx = CanTweakProlog ? 1 : 0;
2624 for (int I = Epilog.size() - 1; I >= EndIdx; I--) {
2625 // TODO: Could also allow minor mismatches, e.g. "add sp, #16" vs
2626 // "push {r0-r3}".
2627 if (Prolog[I] != Epilog[Epilog.size() - 1 - I])
2628 return -1;
2629 }
2630
2631 if (CanTweakProlog) {
2632 // Check that both prolog and epilog end with an expected end opcode.
2633 if (Prolog.front().Operation != Win64EH::UOP_End)
2634 return -1;
2635 if (Epilog.back().Operation != Win64EH::UOP_End &&
2636 Epilog.back().Operation != Win64EH::UOP_EndNop &&
2637 Epilog.back().Operation != Win64EH::UOP_WideEndNop)
2638 return -1;
2639 }
2640
2641 // If the epilog was a subset of the prolog, find its offset.
2642 if (Epilog.size() == Prolog.size())
2643 return 0;
2645 &Prolog[Epilog.size()], Prolog.size() - Epilog.size()));
2646}
2647
2649 int PrologCodeBytes) {
2650 // Can only pack if there's one single epilog
2651 if (info->EpilogMap.size() != 1)
2652 return -1;
2653
2654 const WinEH::FrameInfo::Epilog &EpilogInfo = info->EpilogMap.begin()->second;
2655 // Can only pack if the epilog is unconditional
2656 if (EpilogInfo.Condition != 0xe) // ARMCC::AL
2657 return -1;
2658
2659 const std::vector<WinEH::Instruction> &Epilog = EpilogInfo.Instructions;
2660 // Make sure we have at least the trailing end opcode
2661 if (info->Instructions.empty() || Epilog.empty())
2662 return -1;
2663
2664 // Check that the epilog actually is at the very end of the function,
2665 // otherwise it can't be packed.
2666 std::optional<int64_t> MaybeDistance = GetOptionalAbsDifference(
2667 streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);
2668 if (!MaybeDistance)
2669 return -1;
2670 uint32_t DistanceFromEnd = (uint32_t)*MaybeDistance;
2671 uint32_t InstructionBytes = ARMCountOfInstructionBytes(Epilog);
2672 if (DistanceFromEnd != InstructionBytes)
2673 return -1;
2674
2675 int RetVal = -1;
2676 // Even if we don't end up sharing opcodes with the prolog, we can still
2677 // write the offset as a packed offset, if the single epilog is located at
2678 // the end of the function and the offset (pointing after the prolog) fits
2679 // as a packed offset.
2680 if (PrologCodeBytes <= 31 &&
2681 PrologCodeBytes + ARMCountOfUnwindCodes(Epilog) <= 63)
2682 RetVal = PrologCodeBytes;
2683
2684 int Offset =
2685 getARMOffsetInProlog(info->Instructions, Epilog, /*CanTweakProlog=*/true);
2686 if (Offset < 0)
2687 return RetVal;
2688
2689 // Check that the offset and prolog size fits in the first word; it's
2690 // unclear whether the epilog count in the extension word can be taken
2691 // as packed epilog offset.
2692 if (Offset > 31 || PrologCodeBytes > 63)
2693 return RetVal;
2694
2695 // Replace the regular end opcode of the prolog with the one from the
2696 // epilog.
2697 info->Instructions.front() = Epilog.back();
2698
2699 // As we choose to express the epilog as part of the prolog, remove the
2700 // epilog from the map, so we don't try to emit its opcodes.
2701 info->EpilogMap.clear();
2702 return Offset;
2703}
2704
2705static bool parseRegMask(unsigned Mask, bool &HasLR, bool &HasR11,
2706 unsigned &Folded, int &IntRegs) {
2707 if (Mask & (1 << 14)) {
2708 HasLR = true;
2709 Mask &= ~(1 << 14);
2710 }
2711 if (Mask & (1 << 11)) {
2712 HasR11 = true;
2713 Mask &= ~(1 << 11);
2714 }
2715 Folded = 0;
2716 IntRegs = -1;
2717 if (!Mask)
2718 return true;
2719 int First = 0;
2720 // Shift right until we have the bits at the bottom
2721 while ((Mask & 1) == 0) {
2722 First++;
2723 Mask >>= 1;
2724 }
2725 if ((Mask & (Mask + 1)) != 0)
2726 return false; // Not a consecutive series of bits? Can't be packed.
2727 // Count the bits
2728 int N = 0;
2729 while (Mask & (1 << N))
2730 N++;
2731 if (First < 4) {
2732 if (First + N < 4)
2733 return false;
2734 Folded = 4 - First;
2735 N -= Folded;
2736 First = 4;
2737 }
2738 if (First > 4)
2739 return false; // Can't be packed
2740 if (N >= 1)
2741 IntRegs = N - 1;
2742 return true;
2743}
2744
2746 uint32_t FuncLength) {
2747 int Step = 0;
2748 bool Homing = false;
2749 bool HasR11 = false;
2750 bool HasChain = false;
2751 bool HasLR = false;
2752 int IntRegs = -1; // r4 - r(4+N)
2753 int FloatRegs = -1; // d8 - d(8+N)
2754 unsigned PF = 0; // Number of extra pushed registers
2755 unsigned StackAdjust = 0;
2756 // Iterate over the prolog and check that all opcodes exactly match
2757 // the canonical order and form.
2758 for (const WinEH::Instruction &Inst : info->Instructions) {
2759 switch (Inst.Operation) {
2760 default:
2761 llvm_unreachable("Unsupported ARM unwind code");
2769 // Can't be packed
2770 return false;
2772 // Can't be packed; we can't rely on restoring sp from r11 when
2773 // unwinding a packed prologue.
2774 return false;
2776 // Can't be present in a packed prologue
2777 return false;
2778
2779 case Win64EH::UOP_End:
2782 if (Step != 0)
2783 return false;
2784 Step = 1;
2785 break;
2786
2789 // push {r4-r11,lr}
2790 if (Step != 1 && Step != 2)
2791 return false;
2792 assert(Inst.Register >= 4 && Inst.Register <= 11); // r4-rX
2793 assert(Inst.Offset <= 1); // Lr
2794 IntRegs = Inst.Register - 4;
2795 if (Inst.Register == 11) {
2796 HasR11 = true;
2797 IntRegs--;
2798 }
2799 if (Inst.Offset)
2800 HasLR = true;
2801 Step = 3;
2802 break;
2803
2805 if (Step == 1 && Inst.Register == 0x0f) {
2806 // push {r0-r3}
2807 Homing = true;
2808 Step = 2;
2809 break;
2810 }
2811 [[fallthrough]];
2813 if (Step != 1 && Step != 2)
2814 return false;
2815 // push {r4-r9,r11,lr}
2816 // push {r11,lr}
2817 // push {r1-r5}
2818 if (!parseRegMask(Inst.Register, HasLR, HasR11, PF, IntRegs))
2819 return false;
2820 Step = 3;
2821 break;
2822
2823 case Win64EH::UOP_Nop:
2824 // mov r11, sp
2825 if (Step != 3 || !HasR11 || IntRegs >= 0 || PF > 0)
2826 return false;
2827 HasChain = true;
2828 Step = 4;
2829 break;
2831 // add.w r11, sp, #xx
2832 if (Step != 3 || !HasR11 || (IntRegs < 0 && PF == 0))
2833 return false;
2834 HasChain = true;
2835 Step = 4;
2836 break;
2837
2839 if (Step != 1 && Step != 2 && Step != 3 && Step != 4)
2840 return false;
2841 assert(Inst.Register >= 8 && Inst.Register <= 15);
2842 if (Inst.Register == 15)
2843 return false; // Can't pack this case, R==7 means no IntRegs
2844 if (IntRegs >= 0)
2845 return false;
2846 FloatRegs = Inst.Register - 8;
2847 Step = 5;
2848 break;
2849
2852 if (Step != 1 && Step != 2 && Step != 3 && Step != 4 && Step != 5)
2853 return false;
2854 if (PF > 0) // Can't have both folded and explicit stack allocation
2855 return false;
2856 if (Inst.Offset / 4 >= 0x3f4)
2857 return false;
2858 StackAdjust = Inst.Offset / 4;
2859 Step = 6;
2860 break;
2861 }
2862 }
2863 if (HasR11 && !HasChain) {
2864 if (IntRegs + 4 == 10) {
2865 // r11 stored, but not chaining; can be packed if already saving r4-r10
2866 // and we can fit r11 into this range.
2867 IntRegs++;
2868 HasR11 = false;
2869 } else
2870 return false;
2871 }
2872 if (HasChain && !HasLR)
2873 return false;
2874
2875 // Packed uneind info can't express multiple epilogues.
2876 if (info->EpilogMap.size() > 1)
2877 return false;
2878
2879 unsigned EF = 0;
2880 int Ret = 0;
2881 if (info->EpilogMap.size() == 0) {
2882 Ret = 3; // No epilogue
2883 } else {
2884 // As the prologue and epilogue aren't exact mirrors of each other,
2885 // we have to check the epilogue too and see if it matches what we've
2886 // concluded from the prologue.
2887 const WinEH::FrameInfo::Epilog &EpilogInfo =
2888 info->EpilogMap.begin()->second;
2889 if (EpilogInfo.Condition != 0xe) // ARMCC::AL
2890 return false;
2891 const std::vector<WinEH::Instruction> &Epilog = EpilogInfo.Instructions;
2892 std::optional<int64_t> MaybeDistance = GetOptionalAbsDifference(
2893 streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);
2894 if (!MaybeDistance)
2895 return false;
2896 uint32_t DistanceFromEnd = (uint32_t)*MaybeDistance;
2897 uint32_t InstructionBytes = ARMCountOfInstructionBytes(Epilog);
2898 if (DistanceFromEnd != InstructionBytes)
2899 return false;
2900
2901 bool GotStackAdjust = false;
2902 bool GotFloatRegs = false;
2903 bool GotIntRegs = false;
2904 bool GotHomingRestore = false;
2905 bool GotLRRestore = false;
2906 bool NeedsReturn = false;
2907 bool GotReturn = false;
2908
2909 Step = 6;
2910 for (const WinEH::Instruction &Inst : Epilog) {
2911 switch (Inst.Operation) {
2912 default:
2913 llvm_unreachable("Unsupported ARM unwind code");
2922 case Win64EH::UOP_Nop:
2924 // Can't be packed in an epilogue
2925 return false;
2926
2929 if (Inst.Offset / 4 >= 0x3f4)
2930 return false;
2931 if (Step == 6) {
2932 if (Homing && FloatRegs < 0 && IntRegs < 0 && StackAdjust == 0 &&
2933 PF == 0 && Inst.Offset == 16) {
2934 GotHomingRestore = true;
2935 Step = 10;
2936 } else {
2937 if (StackAdjust > 0) {
2938 // Got stack adjust in prologue too; must match.
2939 if (StackAdjust != Inst.Offset / 4)
2940 return false;
2941 GotStackAdjust = true;
2942 } else if (PF == Inst.Offset / 4) {
2943 // Folded prologue, non-folded epilogue
2944 StackAdjust = Inst.Offset / 4;
2945 GotStackAdjust = true;
2946 } else {
2947 // StackAdjust == 0 in prologue, mismatch
2948 return false;
2949 }
2950 Step = 7;
2951 }
2952 } else if (Step == 7 || Step == 8 || Step == 9) {
2953 if (!Homing || Inst.Offset != 16)
2954 return false;
2955 GotHomingRestore = true;
2956 Step = 10;
2957 } else
2958 return false;
2959 break;
2960
2962 if (Step != 6 && Step != 7)
2963 return false;
2964 assert(Inst.Register >= 8 && Inst.Register <= 15);
2965 if (FloatRegs != (int)(Inst.Register - 8))
2966 return false;
2967 GotFloatRegs = true;
2968 Step = 8;
2969 break;
2970
2973 // push {r4-r11,lr}
2974 if (Step != 6 && Step != 7 && Step != 8)
2975 return false;
2976 assert(Inst.Register >= 4 && Inst.Register <= 11); // r4-rX
2977 assert(Inst.Offset <= 1); // Lr
2978 if (Homing && HasLR) {
2979 // If homing and LR is backed up, we can either restore LR here
2980 // and return with Ret == 1 or 2, or return with SaveLR below
2981 if (Inst.Offset) {
2982 GotLRRestore = true;
2983 NeedsReturn = true;
2984 } else {
2985 // Expecting a separate SaveLR below
2986 }
2987 } else {
2988 if (HasLR != (Inst.Offset == 1))
2989 return false;
2990 }
2991 GotLRRestore = Inst.Offset == 1;
2992 if (IntRegs < 0) // This opcode must include r4
2993 return false;
2994 int Expected = IntRegs;
2995 if (HasChain) {
2996 // Can't express r11 here unless IntRegs describe r4-r10
2997 if (IntRegs != 6)
2998 return false;
2999 Expected++;
3000 }
3001 if (Expected != (int)(Inst.Register - 4))
3002 return false;
3003 GotIntRegs = true;
3004 Step = 9;
3005 break;
3006 }
3007
3010 if (Step != 6 && Step != 7 && Step != 8)
3011 return false;
3012 // push {r4-r9,r11,lr}
3013 // push {r11,lr}
3014 // push {r1-r5}
3015 bool CurHasLR = false, CurHasR11 = false;
3016 int Regs;
3017 if (!parseRegMask(Inst.Register, CurHasLR, CurHasR11, EF, Regs))
3018 return false;
3019 if (EF > 0) {
3020 if (EF != PF && EF != StackAdjust)
3021 return false;
3022 }
3023 if (Homing && HasLR) {
3024 // If homing and LR is backed up, we can either restore LR here
3025 // and return with Ret == 1 or 2, or return with SaveLR below
3026 if (CurHasLR) {
3027 GotLRRestore = true;
3028 NeedsReturn = true;
3029 } else {
3030 // Expecting a separate SaveLR below
3031 }
3032 } else {
3033 if (CurHasLR != HasLR)
3034 return false;
3035 GotLRRestore = CurHasLR;
3036 }
3037 int Expected = IntRegs;
3038 if (HasChain) {
3039 // If we have chaining, the mask must have included r11.
3040 if (!CurHasR11)
3041 return false;
3042 } else if (Expected == 7) {
3043 // If we don't have chaining, the mask could still include r11,
3044 // expressed as part of IntRegs Instead.
3045 Expected--;
3046 if (!CurHasR11)
3047 return false;
3048 } else {
3049 // Neither HasChain nor r11 included in IntRegs, must not have r11
3050 // here either.
3051 if (CurHasR11)
3052 return false;
3053 }
3054 if (Expected != Regs)
3055 return false;
3056 GotIntRegs = true;
3057 Step = 9;
3058 break;
3059 }
3060
3062 if (Step != 6 && Step != 7 && Step != 8 && Step != 9)
3063 return false;
3064 if (!Homing || Inst.Offset != 20 || GotLRRestore)
3065 return false;
3066 GotLRRestore = true;
3067 GotHomingRestore = true;
3068 Step = 10;
3069 break;
3070
3073 GotReturn = true;
3074 Ret = (Inst.Operation == Win64EH::UOP_EndNop) ? 1 : 2;
3075 [[fallthrough]];
3076 case Win64EH::UOP_End:
3077 if (Step != 6 && Step != 7 && Step != 8 && Step != 9 && Step != 10)
3078 return false;
3079 Step = 11;
3080 break;
3081 }
3082 }
3083
3084 if (Step != 11)
3085 return false;
3086 if (StackAdjust > 0 && !GotStackAdjust && EF == 0)
3087 return false;
3088 if (FloatRegs >= 0 && !GotFloatRegs)
3089 return false;
3090 if (IntRegs >= 0 && !GotIntRegs)
3091 return false;
3092 if (Homing && !GotHomingRestore)
3093 return false;
3094 if (HasLR && !GotLRRestore)
3095 return false;
3096 if (NeedsReturn && !GotReturn)
3097 return false;
3098 }
3099
3100 assert(PF == 0 || EF == 0 ||
3101 StackAdjust == 0); // Can't have adjust in all three
3102 if (PF > 0 || EF > 0) {
3103 StackAdjust = PF > 0 ? (PF - 1) : (EF - 1);
3104 assert(StackAdjust <= 3);
3105 StackAdjust |= 0x3f0;
3106 if (PF > 0)
3107 StackAdjust |= 1 << 2;
3108 if (EF > 0)
3109 StackAdjust |= 1 << 3;
3110 }
3111
3112 assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");
3113 int Flag = info->Fragment ? 0x02 : 0x01;
3114 int H = Homing ? 1 : 0;
3115 int L = HasLR ? 1 : 0;
3116 int C = HasChain ? 1 : 0;
3117 assert(IntRegs < 0 || FloatRegs < 0);
3118 unsigned Reg, R;
3119 if (IntRegs >= 0) {
3120 Reg = IntRegs;
3121 assert(Reg <= 7);
3122 R = 0;
3123 } else if (FloatRegs >= 0) {
3124 Reg = FloatRegs;
3125 assert(Reg < 7);
3126 R = 1;
3127 } else {
3128 // No int or float regs stored (except possibly R11,LR)
3129 Reg = 7;
3130 R = 1;
3131 }
3132 info->PackedInfo |= Flag << 0;
3133 info->PackedInfo |= (FuncLength & 0x7FF) << 2;
3134 info->PackedInfo |= (Ret & 0x3) << 13;
3135 info->PackedInfo |= H << 15;
3136 info->PackedInfo |= Reg << 16;
3137 info->PackedInfo |= R << 19;
3138 info->PackedInfo |= L << 20;
3139 info->PackedInfo |= C << 21;
3140 assert(StackAdjust <= 0x3ff);
3141 info->PackedInfo |= StackAdjust << 22;
3142 return true;
3143}
3144
3145// Populate the .xdata section. The format of .xdata on ARM is documented at
3146// https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling
3148 bool TryPacked = true) {
3149 // If this UNWIND_INFO already has a symbol, it's already been emitted.
3150 if (info->Symbol)
3151 return;
3152 // If there's no unwind info here (not even a terminating UOP_End), the
3153 // unwind info is considered bogus and skipped. If this was done in
3154 // response to an explicit .seh_handlerdata, the associated trailing
3155 // handler data is left orphaned in the xdata section.
3156 if (info->empty()) {
3157 info->EmitAttempted = true;
3158 return;
3159 }
3160 if (info->EmitAttempted) {
3161 // If we tried to emit unwind info before (due to an explicit
3162 // .seh_handlerdata directive), but skipped it (because there was no
3163 // valid information to emit at the time), and it later got valid unwind
3164 // opcodes, we can't emit it here, because the trailing handler data
3165 // was already emitted elsewhere in the xdata section.
3166 streamer.getContext().reportError(
3167 SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +
3168 " skipped due to no unwind info at the time "
3169 "(.seh_handlerdata too early?), but the function later "
3170 "did get unwind info that can't be emitted");
3171 return;
3172 }
3173
3174 MCContext &context = streamer.getContext();
3175 MCSymbol *Label = context.createTempSymbol();
3176
3177 streamer.emitValueToAlignment(Align(4));
3178 streamer.emitLabel(Label);
3179 info->Symbol = Label;
3180
3181 if (!info->PrologEnd)
3182 streamer.getContext().reportError(SMLoc(), "Prologue in " +
3183 info->Function->getName() +
3184 " not correctly terminated");
3185
3186 if (info->PrologEnd && !info->Fragment)
3187 checkARMInstructions(streamer, info->Instructions, info->Begin,
3188 info->PrologEnd, info->Function->getName(),
3189 "prologue");
3190 for (auto &I : info->EpilogMap) {
3191 MCSymbol *EpilogStart = I.first;
3192 auto &Epilog = I.second;
3193 checkARMInstructions(streamer, Epilog.Instructions, EpilogStart, Epilog.End,
3194 info->Function->getName(), "epilogue");
3195 if (Epilog.Instructions.empty() ||
3196 !isARMTerminator(Epilog.Instructions.back()))
3197 streamer.getContext().reportError(
3198 SMLoc(), "Epilogue in " + info->Function->getName() +
3199 " not correctly terminated");
3200 }
3201
3202 std::optional<int64_t> RawFuncLength;
3203 const MCExpr *FuncLengthExpr = nullptr;
3204 if (!info->FuncletOrFuncEnd) {
3205 report_fatal_error("FuncletOrFuncEnd not set");
3206 } else {
3207 // As the size of many thumb2 instructions isn't known until later,
3208 // we can't always rely on being able to calculate the absolute
3209 // length of the function here. If we can't calculate it, defer it
3210 // to a relocation.
3211 //
3212 // In such a case, we won't know if the function is too long so that
3213 // the unwind info would need to be split (but this isn't implemented
3214 // anyway).
3215 RawFuncLength =
3216 GetOptionalAbsDifference(streamer, info->FuncletOrFuncEnd, info->Begin);
3217 if (!RawFuncLength)
3218 FuncLengthExpr =
3219 GetSubDivExpr(streamer, info->FuncletOrFuncEnd, info->Begin, 2);
3220 }
3221 uint32_t FuncLength = 0;
3222 if (RawFuncLength)
3223 FuncLength = (uint32_t)*RawFuncLength / 2;
3224 if (FuncLength > 0x3FFFF)
3225 report_fatal_error("SEH unwind data splitting not yet implemented");
3226 uint32_t PrologCodeBytes = ARMCountOfUnwindCodes(info->Instructions);
3227 uint32_t TotalCodeBytes = PrologCodeBytes;
3228
3229 if (!info->HandlesExceptions && RawFuncLength && FuncLength <= 0x7ff &&
3230 TryPacked) {
3231 // No exception handlers; check if the prolog and epilog matches the
3232 // patterns that can be described by the packed format. If we don't
3233 // know the exact function length yet, we can't do this.
3234
3235 // info->Symbol was already set even if we didn't actually write any
3236 // unwind info there. Keep using that as indicator that this unwind
3237 // info has been generated already.
3238
3239 if (tryARMPackedUnwind(streamer, info, FuncLength))
3240 return;
3241 }
3242
3243 int PackedEpilogOffset =
3244 checkARMPackedEpilog(streamer, info, PrologCodeBytes);
3245
3246 // Process epilogs.
3248 // Epilogs processed so far.
3249 std::vector<MCSymbol *> AddedEpilogs;
3250
3251 bool CanTweakProlog = true;
3252 for (auto &I : info->EpilogMap) {
3253 MCSymbol *EpilogStart = I.first;
3254 auto &EpilogInstrs = I.second.Instructions;
3255 uint32_t CodeBytes = ARMCountOfUnwindCodes(EpilogInstrs);
3256
3257 MCSymbol *MatchingEpilog =
3258 FindMatchingEpilog(EpilogInstrs, AddedEpilogs, info);
3259 int PrologOffset;
3260 if (MatchingEpilog) {
3261 assert(EpilogInfo.contains(MatchingEpilog) &&
3262 "Duplicate epilog not found");
3263 EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
3264 // Clear the unwind codes in the EpilogMap, so that they don't get output
3265 // in the logic below.
3266 EpilogInstrs.clear();
3267 } else if ((PrologOffset = getARMOffsetInProlog(
3268 info->Instructions, EpilogInstrs, CanTweakProlog)) >= 0) {
3269 if (CanTweakProlog) {
3270 // Replace the regular end opcode of the prolog with the one from the
3271 // epilog.
3272 info->Instructions.front() = EpilogInstrs.back();
3273 // Later epilogs need a strict match for the end opcode.
3274 CanTweakProlog = false;
3275 }
3276 EpilogInfo[EpilogStart] = PrologOffset;
3277 // Clear the unwind codes in the EpilogMap, so that they don't get output
3278 // in the logic below.
3279 EpilogInstrs.clear();
3280 } else {
3281 EpilogInfo[EpilogStart] = TotalCodeBytes;
3282 TotalCodeBytes += CodeBytes;
3283 AddedEpilogs.push_back(EpilogStart);
3284 }
3285 }
3286
3287 // Code Words, Epilog count, F, E, X, Vers, Function Length
3288 uint32_t row1 = 0x0;
3289 uint32_t CodeWords = TotalCodeBytes / 4;
3290 uint32_t CodeWordsMod = TotalCodeBytes % 4;
3291 if (CodeWordsMod)
3292 CodeWords++;
3293 uint32_t EpilogCount =
3294 PackedEpilogOffset >= 0 ? PackedEpilogOffset : info->EpilogMap.size();
3295 bool ExtensionWord = EpilogCount > 31 || CodeWords > 15;
3296 if (!ExtensionWord) {
3297 row1 |= (EpilogCount & 0x1F) << 23;
3298 row1 |= (CodeWords & 0x0F) << 28;
3299 }
3300 if (info->HandlesExceptions) // X
3301 row1 |= 1 << 20;
3302 if (PackedEpilogOffset >= 0) // E
3303 row1 |= 1 << 21;
3304 if (info->Fragment) // F
3305 row1 |= 1 << 22;
3306 row1 |= FuncLength & 0x3FFFF;
3307 if (RawFuncLength)
3308 streamer.emitInt32(row1);
3309 else
3310 streamer.emitValue(
3311 MCBinaryExpr::createOr(FuncLengthExpr,
3312 MCConstantExpr::create(row1, context), context),
3313 4);
3314
3315 // Extended Code Words, Extended Epilog Count
3316 if (ExtensionWord) {
3317 // FIXME: We should be able to split unwind info into multiple sections.
3318 if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
3319 report_fatal_error("SEH unwind data splitting not yet implemented");
3320 uint32_t row2 = 0x0;
3321 row2 |= (CodeWords & 0xFF) << 16;
3322 row2 |= (EpilogCount & 0xFFFF);
3323 streamer.emitInt32(row2);
3324 }
3325
3326 if (PackedEpilogOffset < 0) {
3327 // Epilog Start Index, Epilog Start Offset
3328 for (auto &I : EpilogInfo) {
3329 MCSymbol *EpilogStart = I.first;
3330 uint32_t EpilogIndex = I.second;
3331
3332 std::optional<int64_t> MaybeEpilogOffset =
3333 GetOptionalAbsDifference(streamer, EpilogStart, info->Begin);
3334 const MCExpr *OffsetExpr = nullptr;
3335 uint32_t EpilogOffset = 0;
3336 if (MaybeEpilogOffset)
3337 EpilogOffset = *MaybeEpilogOffset / 2;
3338 else
3339 OffsetExpr = GetSubDivExpr(streamer, EpilogStart, info->Begin, 2);
3340
3341 assert(info->EpilogMap.contains(EpilogStart));
3342 unsigned Condition = info->EpilogMap[EpilogStart].Condition;
3343 assert(Condition <= 0xf);
3344
3345 uint32_t row3 = EpilogOffset;
3346 row3 |= Condition << 20;
3347 row3 |= (EpilogIndex & 0x3FF) << 24;
3348 if (MaybeEpilogOffset)
3349 streamer.emitInt32(row3);
3350 else
3351 streamer.emitValue(
3353 OffsetExpr, MCConstantExpr::create(row3, context), context),
3354 4);
3355 }
3356 }
3357
3358 // Emit prolog unwind instructions (in reverse order).
3359 uint8_t numInst = info->Instructions.size();
3360 for (uint8_t c = 0; c < numInst; ++c) {
3361 WinEH::Instruction inst = info->Instructions.back();
3362 info->Instructions.pop_back();
3363 ARMEmitUnwindCode(streamer, inst);
3364 }
3365
3366 // Emit epilog unwind instructions
3367 for (auto &I : info->EpilogMap) {
3368 auto &EpilogInstrs = I.second.Instructions;
3369 for (const WinEH::Instruction &inst : EpilogInstrs)
3370 ARMEmitUnwindCode(streamer, inst);
3371 }
3372
3373 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
3374 assert(BytesMod >= 0);
3375 for (int i = 0; i < BytesMod; i++)
3376 streamer.emitInt8(0xFB);
3377
3378 if (info->HandlesExceptions)
3379 streamer.emitValue(
3380 MCSymbolRefExpr::create(info->ExceptionHandler,
3382 4);
3383}
3384
3386 const WinEH::FrameInfo *info) {
3387 MCContext &context = streamer.getContext();
3388
3389 streamer.emitValueToAlignment(Align(4));
3390 for (const auto &S : info->Segments) {
3391 EmitSymbolRefWithOfs(streamer, info->Begin, S.Offset);
3392 if (info->PackedInfo)
3393 streamer.emitInt32(info->PackedInfo);
3394 else
3395 streamer.emitValue(
3397 context),
3398 4);
3399 }
3400}
3401
3402
3404 const WinEH::FrameInfo *info) {
3405 MCContext &context = streamer.getContext();
3406
3407 streamer.emitValueToAlignment(Align(4));
3408 EmitSymbolRefWithOfs(streamer, info->Begin, info->Begin);
3409 if (info->PackedInfo)
3410 streamer.emitInt32(info->PackedInfo);
3411 else
3412 streamer.emitValue(
3414 context),
3415 4);
3416}
3417
3419 // Emit the unwind info structs first.
3420 for (const auto &CFI : Streamer.getWinFrameInfos()) {
3421 WinEH::FrameInfo *Info = CFI.get();
3422 if (Info->empty())
3423 continue;
3424 MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
3425 Streamer.switchSection(XData);
3426 ARM64EmitUnwindInfo(Streamer, Info);
3427 }
3428
3429 // Now emit RUNTIME_FUNCTION entries.
3430 for (const auto &CFI : Streamer.getWinFrameInfos()) {
3431 WinEH::FrameInfo *Info = CFI.get();
3432 // ARM64EmitUnwindInfo above clears the info struct, so we can't check
3433 // empty here. But if a Symbol is set, we should create the corresponding
3434 // pdata entry.
3435 if (!Info->Symbol)
3436 continue;
3437 MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
3438 Streamer.switchSection(PData);
3439 ARM64EmitRuntimeFunction(Streamer, Info);
3440 }
3441}
3442
3445 bool HandlerData) const {
3446 // Called if there's an .seh_handlerdata directive before the end of the
3447 // function. This forces writing the xdata record already here - and
3448 // in this case, the function isn't actually ended already, but the xdata
3449 // record needs to know the function length. In these cases, if the funclet
3450 // end hasn't been marked yet, the xdata function length won't cover the
3451 // whole function, only up to this point.
3452 if (!info->FuncletOrFuncEnd) {
3453 Streamer.switchSection(info->TextSection);
3454 info->FuncletOrFuncEnd = Streamer.emitCFILabel();
3455 }
3456 // Switch sections (the static function above is meant to be called from
3457 // here and from Emit().
3458 MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
3459 Streamer.switchSection(XData);
3460 ARM64EmitUnwindInfo(Streamer, info, /* TryPacked = */ !HandlerData);
3461}
3462
3464 // Emit the unwind info structs first.
3465 for (const auto &CFI : Streamer.getWinFrameInfos()) {
3466 WinEH::FrameInfo *Info = CFI.get();
3467 if (Info->empty())
3468 continue;
3469 MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
3470 Streamer.switchSection(XData);
3471 ARMEmitUnwindInfo(Streamer, Info);
3472 }
3473
3474 // Now emit RUNTIME_FUNCTION entries.
3475 for (const auto &CFI : Streamer.getWinFrameInfos()) {
3476 WinEH::FrameInfo *Info = CFI.get();
3477 // ARMEmitUnwindInfo above clears the info struct, so we can't check
3478 // empty here. But if a Symbol is set, we should create the corresponding
3479 // pdata entry.
3480 if (!Info->Symbol)
3481 continue;
3482 MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
3483 Streamer.switchSection(PData);
3484 ARMEmitRuntimeFunction(Streamer, Info);
3485 }
3486}
3487
3490 bool HandlerData) const {
3491 // Called if there's an .seh_handlerdata directive before the end of the
3492 // function. This forces writing the xdata record already here - and
3493 // in this case, the function isn't actually ended already, but the xdata
3494 // record needs to know the function length. In these cases, if the funclet
3495 // end hasn't been marked yet, the xdata function length won't cover the
3496 // whole function, only up to this point.
3497 if (!info->FuncletOrFuncEnd) {
3498 Streamer.switchSection(info->TextSection);
3499 info->FuncletOrFuncEnd = Streamer.emitCFILabel();
3500 }
3501 // Switch sections (the static function above is meant to be called from
3502 // here and from Emit().
3503 MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
3504 Streamer.switchSection(XData);
3505 ARMEmitUnwindInfo(Streamer, info, /* TryPacked = */ !HandlerData);
3506}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
@ Scaled
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
lazy value info
static int checkARM64PackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info, WinEH::FrameInfo::Segment *Seg, int PrologCodeBytes)
static void ARM64EmitUnwindInfoForSegment(MCStreamer &streamer, WinEH::FrameInfo *info, WinEH::FrameInfo::Segment &Seg, bool TryPacked=true)
static uint32_t ARMCountOfUnwindCodes(ArrayRef< WinEH::Instruction > Insns)
static uint32_t ARM64CountOfUnwindCodes(ArrayRef< WinEH::Instruction > Insns)
static void checkARMInstructions(MCStreamer &Streamer, ArrayRef< WinEH::Instruction > Insns, const MCSymbol *Begin, const MCSymbol *End, StringRef Name, StringRef Type)
static bool isARMTerminator(const WinEH::Instruction &inst)
static void ARM64EmitUnwindCode(MCStreamer &streamer, const WinEH::Instruction &inst)
static void simplifyARM64Opcodes(std::vector< WinEH::Instruction > &Instructions, bool Reverse)
static void ARMEmitUnwindCode(MCStreamer &streamer, const WinEH::Instruction &inst)
static bool EpilogIpOffsetsMatch(const WinEH::FrameInfo::Epilog &A, const WinEH::FrameInfo::Epilog &B, const MCAssembler &Asm)
Compare the relative IP offset arrays of two epilogs.
static std::optional< int64_t > GetOptionalAbsDifference(const MCAssembler &Assembler, const MCSymbol *LHS, const MCSymbol *RHS)
static int getARM64OffsetInProlog(const std::vector< WinEH::Instruction > &Prolog, const std::vector< WinEH::Instruction > &Epilog)
static void ARMEmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength, int PackedEpilogOffset)
static void EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info)
static void EmitUnwindCode(MCStreamer &streamer, const MCSymbol *begin, WinEH::Instruction &inst)
static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info, bool TryPacked=true)
static int getARMOffsetInProlog(const std::vector< WinEH::Instruction > &Prolog, const std::vector< WinEH::Instruction > &Epilog, bool CanTweakProlog)
static void ARM64EmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
static void EmitSymbolRefWithOfs(MCStreamer &streamer, const MCSymbol *Base, int64_t Offset)
static bool parseRegMask(unsigned Mask, bool &HasLR, bool &HasR11, unsigned &Folded, int &IntRegs)
static int checkARMPackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info, int PrologCodeBytes)
static void EmitAbsDifference16(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
Emit a 16-bit (2-byte LE) label difference.
static int64_t GetAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
static void ARM64FindSegmentsInFunction(MCStreamer &streamer, WinEH::FrameInfo *info, int64_t RawFuncLength)
static bool tryARMPackedUnwind(MCStreamer &streamer, WinEH::FrameInfo *info, uint32_t FuncLength)
static void EmitUnwindInfoV3(MCStreamer &Streamer, WinEH::FrameInfo *Info)
Emit V3 UNWIND_INFO for a single frame.
static MCSymbol * FindMatchingEpilog(const std::vector< WinEH::Instruction > &EpilogInstrs, const std::vector< MCSymbol * > &Epilogs, const WinEH::FrameInfo *info)
static void EmitRuntimeFunction(MCStreamer &streamer, const WinEH::FrameInfo *info)
static void checkARM64Instructions(MCStreamer &Streamer, ArrayRef< WinEH::Instruction > Insns, const MCSymbol *Begin, const MCSymbol *End, StringRef Name, StringRef Type)
static const MCExpr * GetSubDivExpr(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS, int Div)
static void EmitAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
static void ARMEmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info, bool TryPacked=true)
static uint32_t ARMCountOfInstructionBytes(ArrayRef< WinEH::Instruction > Insns, bool *HasCustom=nullptr)
static void ARM64ProcessEpilogs(WinEH::FrameInfo *info, WinEH::FrameInfo::Segment *Seg, uint32_t &TotalCodeBytes, MapVector< MCSymbol *, uint32_t > &EpilogInfo)
static std::optional< uint16_t > FindInPool(ArrayRef< uint8_t > Haystack, ArrayRef< uint8_t > Needle)
Try to find Needle as a contiguous subsequence within Haystack.
static uint8_t CountOfUnwindCodes(std::vector< WinEH::Instruction > &Insns)
Definition MCWin64EH.cpp:73
#define I(x, y, z)
Definition MD5.cpp:57
#define H(x, y, z)
Definition MD5.cpp:56
Register Reg
static void printImpl(const MCAsmInfo &MAI, raw_ostream &OS, const MCSpecifierExpr &Expr)
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static const MCPhysReg IntRegs[32]
Value * RHS
Value * LHS
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
iterator end() const
Definition ArrayRef.h:130
size_t size() const
Get the array size.
Definition ArrayRef.h:141
iterator begin() const
Definition ArrayRef.h:129
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
Tagged union holding either a T or a Error.
Definition Error.h:485
MCContext & getContext() const
static const MCBinaryExpr * createLShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:423
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:343
static const MCBinaryExpr * createOr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:408
static const MCBinaryExpr * createDiv(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:353
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:428
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Definition MCContext.h:83
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
LLVM_ABI void reportError(SMLoc L, const Twine &Msg)
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
Streaming object file generation interface.
MCAssembler & getAssembler()
void appendContents(ArrayRef< char > Contents)
void addFixup(const MCExpr *Value, MCFixupKind Kind)
void ensureHeadroom(size_t Headroom)
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition MCSection.h:573
Streaming machine code generation interface.
Definition MCStreamer.h:222
virtual MCSymbol * emitCFILabel()
When emitting an object file, create and emit a real label.
MCSection * getAssociatedPDataSection(const MCSection *TextSec)
Get the .pdata section used for the given section.
MCContext & getContext() const
Definition MCStreamer.h:326
MCSection * getAssociatedXDataSection(const MCSection *TextSec)
Get the .xdata section used for the given section.
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
virtual void emitValueToAlignment(Align Alignment, int64_t Fill=0, uint8_t FillLen=1, unsigned MaxBytesToEmit=0)
Emit some number of copies of Value until the byte alignment ByteAlignment is reached.
void emitInt16(uint64_t Value)
Definition MCStreamer.h:766
virtual void switchSection(MCSection *Section, uint32_t Subsec=0)
Set the current section where code is being emitted to Section.
void emitInt32(uint64_t Value)
Definition MCStreamer.h:767
ArrayRef< std::unique_ptr< WinEH::FrameInfo > > getWinFrameInfos() const
Definition MCStreamer.h:359
void emitInt8(uint64_t Value)
Definition MCStreamer.h:765
Represent a reference to a symbol from inside an expression.
Definition MCExpr.h:190
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:214
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition MCSymbol.cpp:59
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
MCFragment * getFragment() const
Definition MCSymbol.h:345
static MCValue get(const MCSymbol *SymA, const MCSymbol *SymB=nullptr, int64_t Val=0, uint32_t Specifier=0)
Definition MCValue.h:56
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:38
Represents a location in source code.
Definition SMLoc.h:22
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StackOffset holds a fixed and a scalable offset in bytes.
Definition TypeSize.h:30
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM Value Representation.
Definition Value.h:75
void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override
void Emit(MCStreamer &Streamer) const override
This emits the unwind info sections (.pdata and .xdata in PE/COFF).
void Emit(MCStreamer &Streamer) const override
This emits the unwind info sections (.pdata and .xdata in PE/COFF).
void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override
void Emit(MCStreamer &Streamer) const override
This emits the unwind info sections (.pdata and .xdata in PE/COFF).
void EmitUnwindInfo(MCStreamer &Streamer, WinEH::FrameInfo *FI, bool HandlerData) const override
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ EPILOG_INFO_LARGE
When set, the extended descriptor uses EPILOG_INFO_LARGE_EX_V3 (16-bit IpOffsetOfLastInstruction) and...
Definition Win64EH.h:261
@ UNW_TerminateHandler
UNW_TerminateHandler - Specifies that this function has a termination handler.
Definition Win64EH.h:151
@ UNW_FlagLarge
UNW_FlagLarge - V3 only.
Definition Win64EH.h:158
@ UNW_ExceptionHandler
UNW_ExceptionHandler - Specifies that this function has an exception handler.
Definition Win64EH.h:148
@ UNW_ChainInfo
UNW_ChainInfo - Specifies that this UnwindInfo structure is chained to another one.
Definition Win64EH.h:154
UnwindOpcodes
UnwindOpcodes - Enumeration whose values specify a single operation in the prolog of a function.
Definition Win64EH.h:30
@ UOP_SaveAnyRegDPX
Definition Win64EH.h:79
@ UOP_SaveRegsR4R7LR
Definition Win64EH.h:102
@ UOP_ClearUnwoundToCall
Definition Win64EH.h:68
@ UOP_SaveNonVolBig
Definition Win64EH.h:39
@ UOP_WideAllocMedium
Definition Win64EH.h:96
@ UOP_SaveAnyRegDX
Definition Win64EH.h:78
@ UOP_SaveFRegD0D15
Definition Win64EH.h:107
@ UOP_SaveAnyRegQP
Definition Win64EH.h:75
@ UOP_SaveAnyRegD
Definition Win64EH.h:72
@ UOP_WideSaveRegsR4R11LR
Definition Win64EH.h:103
@ UOP_SaveAnyRegIPX
Definition Win64EH.h:77
@ UOP_WideAllocHuge
Definition Win64EH.h:98
@ UOP_SaveAnyRegQX
Definition Win64EH.h:80
@ UOP_SaveAnyRegIX
Definition Win64EH.h:76
@ UOP_SaveXMM128Big
Definition Win64EH.h:43
@ UOP_SaveAnyRegQ
Definition Win64EH.h:74
@ UOP_SaveAnyRegDP
Definition Win64EH.h:73
@ UOP_SaveFRegD8D15
Definition Win64EH.h:104
@ UOP_PushMachFrame
Definition Win64EH.h:44
@ UOP_SaveR19R20X
Definition Win64EH.h:48
@ UOP_SaveAnyRegQPX
Definition Win64EH.h:81
@ UOP_WideAllocLarge
Definition Win64EH.h:97
@ UOP_WideSaveRegMask
Definition Win64EH.h:100
@ UOP_AllocMedium
Definition Win64EH.h:47
@ UOP_SaveAnyRegIP
Definition Win64EH.h:71
@ UOP_SaveFRegD16D31
Definition Win64EH.h:108
@ UOP_SaveAnyRegI
Definition Win64EH.h:70
@ WOD_SAVE_XMM128_FAR
Definition Win64EH.h:251
@ WOD_PUSH_CANONICAL_FRAME
Definition Win64EH.h:245
@ WOD_PUSH_CONSECUTIVE_2
Definition Win64EH.h:249
@ WOD_SAVE_NONVOL_FAR
Definition Win64EH.h:247
LLVM_ABI void EncodeWOD(const WinEH::Instruction &Inst, SmallVectorImpl< uint8_t > &Out)
Encode a single WinEH::Instruction as V3 WOD bytes.
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:558
FunctionAddr VTableAddr Value
Definition InstrProf.h:137
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
Definition Error.cpp:173
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
auto reverse_conditionally(ContainerTy &&C, bool ShouldReverse)
Return a range that conditionally reverses C.
Definition STLExtras.h:1422
@ Other
Any other memory.
Definition ModRef.h:68
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
@ FK_Data_1
A one-byte fixup.
Definition MCFixup.h:34
@ FK_Data_2
A two-byte fixup.
Definition MCFixup.h:35
DWARFExpression::Operation Op
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
Definition Error.cpp:177
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
MapVector< MCSymbol *, int64_t > Epilogs
Definition MCWinEH.h:86
const MCSymbol * Function
Definition MCWinEH.h:51
const MCSymbol * End
Definition MCWinEH.h:48
const MCSymbol * Label
Definition MCWinEH.h:24