29class MCUnwindV2EpilogTargetExpr final :
public MCTargetExpr {
30 const WinEH::FrameInfo &FrameInfo;
36 MCUnwindV2EpilogTargetExpr(
const WinEH::FrameInfo &FrameInfo,
37 const WinEH::FrameInfo::Epilog &
Epilog,
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");
46 static MCUnwindV2EpilogTargetExpr *
47 create(
const WinEH::FrameInfo &FrameInfo,
48 const WinEH::FrameInfo::Epilog &
Epilog, uint8_t EpilogSize_,
50 return new (Ctx) MCUnwindV2EpilogTargetExpr(FrameInfo,
Epilog, EpilogSize_);
53 void printImpl(raw_ostream &OS,
const MCAsmInfo *MAI)
const override {
55 UnwindV2Start->
print(OS, MAI);
58 bool evaluateAsRelocatableImpl(MCValue &Res,
59 const MCAssembler *Asm)
const override;
61 void visitUsedExpr(MCStreamer &Streamer)
const override {
65 MCFragment *findAssociatedFragment()
const override {
78class MCUnwindV3EpilogOffsetTargetExpr final :
public MCTargetExpr {
79 const WinEH::FrameInfo &FrameInfo;
84 MCUnwindV3EpilogOffsetTargetExpr(
const WinEH::FrameInfo &FrameInfo,
85 const MCSymbol *EpilogStart,
86 const MCSymbol *PrevEpilogStart, SMLoc Loc)
87 : FrameInfo(FrameInfo), EpilogStart(EpilogStart),
88 PrevEpilogStart(PrevEpilogStart), Loc(Loc) {}
91 static MCUnwindV3EpilogOffsetTargetExpr *
92 create(
const WinEH::FrameInfo &FrameInfo,
const MCSymbol *EpilogStart,
93 const MCSymbol *PrevEpilogStart, SMLoc Loc, MCContext &Ctx) {
94 return new (Ctx) MCUnwindV3EpilogOffsetTargetExpr(FrameInfo, EpilogStart,
95 PrevEpilogStart, Loc);
98 void printImpl(raw_ostream &OS,
const MCAsmInfo *MAI)
const override {
99 OS <<
":epilogoffset:";
100 EpilogStart->
print(OS, MAI);
103 bool evaluateAsRelocatableImpl(MCValue &Res,
104 const MCAssembler *Asm)
const override;
106 void visitUsedExpr(MCStreamer &Streamer)
const override {
110 MCFragment *findAssociatedFragment()
const override {
120 for (
const auto &
I : Insns) {
139 Count += (
I.Offset > 512 * 1024 - 8) ? 3 : 2;
165 if (Diff->evaluateAsAbsolute(
170 "Label difference out of 16-bit unsigned range for V3 unwind info");
191 SMLoc(),
"UOP_Push2 (PUSH2 with two registers) requires V3 unwind "
192 "info. Use `.seh_unwindversion 3`.");
201 if (inst.
Offset > 512 * 1024 - 8) {
214 b2 |= (((inst.
Offset - 8) >> 3) & 0x0F) << 4;
290static std::optional<int64_t>
301 if (!Diff->evaluateAsAbsolute(value, Assembler))
328 "UOP_AllocSmall outside expected range or alignment");
334 if (Inst.
Offset > 512 * 1024 - 8) {
357 "SET_FPREG frame register does not fit in 4 bits");
394 "SAVE_XMM128 register does not fit in 4 bits (XMM16-31 unsupported)");
407 "bits (XMM16-31 unsupported)");
428 if (Reg2 == Reg1 + 1) {
436 Out.
push_back(((Reg2 & 0x1F) << 3) | ((Reg1 >> 2) & 0x07));
449 assert(!Needle.
empty() &&
"FindInPool called with empty Needle");
450 auto It = std::search(Haystack.
begin(), Haystack.
end(), Needle.
begin(),
452 if (It == Haystack.
end())
454 return static_cast<uint16_t>(std::distance(Haystack.
begin(), It));
461 if (
A.Instructions.size() !=
B.Instructions.size())
463 for (
unsigned I = 0;
I <
A.Instructions.size(); ++
I) {
466 if (!OffA || !OffB || *OffA != *OffB)
475 assert(!Info->Symbol &&
"UNWIND_INFO already has a symbol");
481 MCSymbol *Label = Context.createTempSymbol();
484 Info->Symbol = Label;
492 for (
auto It = Info->Instructions.rbegin(); It != Info->Instructions.rend();
498 unsigned PrologOpCount = Info->Instructions.
size();
499 if (PrologOpCount > 31) {
501 "Too many prolog unwind codes for V3 encoding. Maximum "
502 "is 31. This function has " +
503 Twine(PrologOpCount));
505 for (
auto It = Info->Instructions.rbegin(); It != Info->Instructions.rend();
507 PrologIpLabels.
push_back({It->Label, Info->Begin});
513 bool NeedsLargeProlog =
false;
514 if (Info->PrologEnd) {
515 auto MaybePrologSize =
517 if (MaybePrologSize) {
518 if (*MaybePrologSize < 0)
520 if (*MaybePrologSize > UINT16_MAX)
522 "SizeOfProlog exceeds 16-bit range for V3 unwind info");
523 NeedsLargeProlog = (*MaybePrologSize > 255);
525 NeedsLargeProlog =
true;
528 for (
auto &[InstLabel, BeginLabel] : PrologIpLabels) {
529 if (NeedsLargeProlog)
533 if (*MaybeOffset < 0)
535 if (*MaybeOffset > UINT16_MAX)
537 "Prolog IP offset exceeds 16-bit range for V3 unwind info");
538 NeedsLargeProlog = (*MaybeOffset > 255);
540 NeedsLargeProlog =
true;
545 struct EpilogEmitInfo {
555 for (
const auto &[EpilogSym,
Epilog] : Info->EpilogMap) {
556 if (
Epilog.Instructions.empty())
561 EI.NumberOfOps =
Epilog.Instructions.size();
562 if (EI.NumberOfOps > 31)
564 "Too many epilog unwind codes for V3 encoding. Maximum "
565 "is 31. This epilog has " +
566 Twine(EI.NumberOfOps));
567 EI.Inherited =
false;
568 EI.NeedsLarge =
false;
573 auto MaybeLastInstOfs =
575 if (MaybeLastInstOfs) {
576 if (*MaybeLastInstOfs < 0)
578 "Negative IpOffsetOfLastInstruction in V3 unwind info");
579 if (*MaybeLastInstOfs > UINT16_MAX)
581 "IpOffsetOfLastInstruction exceeds 16-bit range for "
583 EI.NeedsLarge = (*MaybeLastInstOfs > 255);
585 EI.NeedsLarge =
true;
589 for (
const auto &EpiInst :
Epilog.Instructions) {
595 if (*MaybeOffset < 0)
597 if (*MaybeOffset > UINT16_MAX)
599 "Epilog IP offset exceeds 16-bit range for V3 unwind info");
600 EI.NeedsLarge = (*MaybeOffset > 255);
602 EI.NeedsLarge =
true;
607 for (
const auto &Inst :
Epilog.Instructions)
615 EI.FirstOp = WODPool.
size();
616 WODPool.
append(EI.WODBytes.begin(), EI.WODBytes.end());
621 if (EpilogInfos.
size() > 7)
623 " This function has " +
633 std::reverse(EpilogInfos.
begin(), EpilogInfos.
end());
645 for (
unsigned I = 1,
Base = 0;
I < EpilogInfos.
size(); ++
I) {
646 auto &BaseEI = EpilogInfos[
Base];
647 auto &Curr = EpilogInfos[
I];
648 if (Curr.FirstOp == BaseEI.FirstOp &&
649 Curr.NumberOfOps == BaseEI.NumberOfOps &&
652 assert(Curr.NeedsLarge == BaseEI.NeedsLarge &&
653 "NeedsLarge must follow from matching FirstOp, NumberOfOps, and "
655 Curr.Inherited =
true;
661 unsigned PrologIpEntrySize = NeedsLargeProlog ? 2 : 1;
662 unsigned EpilogDescBytes = 0;
663 for (
const auto &EI : EpilogInfos) {
665 EpilogDescBytes += 3;
666 }
else if (EI.NeedsLarge) {
668 EpilogDescBytes += 7 + EI.NumberOfOps * 2;
671 EpilogDescBytes += 6 + EI.NumberOfOps;
675 unsigned PrologIpBytes = PrologOpCount * PrologIpEntrySize;
676 unsigned WODPoolBytes = WODPool.
size();
681 unsigned LargeHeaderBytes = NeedsLargeProlog ? 1 : 0;
682 unsigned TotalPayloadBytes =
683 LargeHeaderBytes + PrologIpBytes + EpilogDescBytes + WODPoolBytes;
684 if (TotalPayloadBytes > 255 * 2) {
686 "510 bytes. This function has " +
687 Twine(TotalPayloadBytes));
689 uint8_t PayloadWords = (TotalPayloadBytes + 1) / 2;
697 if (Info->ChainedParent)
700 if (Info->HandlesUnwind)
702 if (Info->HandlesExceptions)
705 if (NeedsLargeProlog)
709 Streamer.
emitInt8((Flags << 3) | 3);
712 if (Info->PrologEnd) {
713 if (NeedsLargeProlog) {
717 auto MaybePrologSize =
719 if (MaybePrologSize) {
720 Streamer.
emitInt8(*MaybePrologSize & 0xFF);
737 Streamer.
emitInt8((NumberOfEpilogs << 5) | (PrologOpCount & 0x1F));
740 if (NeedsLargeProlog) {
741 if (Info->PrologEnd) {
742 auto MaybePrologSize =
744 if (MaybePrologSize) {
745 Streamer.
emitInt8((*MaybePrologSize >> 8) & 0xFF);
762 for (
auto &[InstLabel, BeginLabel] : PrologIpLabels) {
763 if (NeedsLargeProlog)
770 const MCSymbol *PrevEpilogStart =
nullptr;
771 [[maybe_unused]]
uint8_t BaseEpiFlags = 0;
772 for (
const auto &EI : EpilogInfos) {
773 const auto &
Epilog = *EI.Epilog;
788 assert((!EI.Inherited || (EpiFlags & 0x03) == (BaseEpiFlags & 0x03)) &&
789 "inherited epilog must replicate base descriptor's flags bits 0-1");
791 BaseEpiFlags = EpiFlags;
792 uint8_t EpiNumOps = EI.Inherited ? 0 : EI.NumberOfOps;
793 Streamer.
emitInt8((EpiNumOps << 3) | EpiFlags);
802 const MCExpr *EpilogOffsetExpr = MCUnwindV3EpilogOffsetTargetExpr::create(
803 *Info,
Epilog.Start, PrevEpilogStart,
Epilog.Loc, Context);
808 PrevEpilogStart =
Epilog.Start;
813 Streamer.
emitInt8(EI.FirstOp & 0xFF);
814 Streamer.
emitInt8((EI.FirstOp >> 8) & 0xFF);
822 unsigned FixupSize = EI.NeedsLarge ? 2 : 1;
829 for (
const auto &EpiInst :
Epilog.Instructions) {
844 if (TotalPayloadBytes % 2 != 0)
853 if (PayloadWords % 2 != 0)
865 else if (PayloadWords == 0) {
877 if (
info->Version == 3) {
886 for (
const auto &Inst :
info->Instructions) {
889 SMLoc(),
"UOP_Push2 (PUSH2 with two registers) requires V3 unwind "
890 "info. Use `.seh_unwindversion 3`.");
904 info->Symbol = Label;
907 bool LastEpilogIsAtEnd =
false;
908 bool AddPaddingEpilogCode =
false;
910 bool EnableUnwindV2 = (
info->Version >= 2) && !
info->EpilogMap.empty();
911 if (EnableUnwindV2) {
912 auto &LastEpilog =
info->EpilogMap.back().second;
921 LastEpilog.UnwindV2Start &&
922 "If unwind v2 is enabled, epilog must have a unwind v2 start marker");
923 assert(LastEpilog.End &&
"Epilog must have an end");
925 OS->
getAssembler(), LastEpilog.End, LastEpilog.UnwindV2Start);
928 "Failed to evaluate epilog size for Unwind v2 in " +
929 info->Function->getName());
933 if (*MaybeSize >= (int64_t)UINT8_MAX) {
935 "Epilog size is too large for Unwind v2 in " +
936 info->Function->getName());
939 EpilogSize = *MaybeSize + 1;
950 LastEpilogIsAtEnd = (LastEpilogToFuncEnd == EpilogSize);
954 size_t numEpilogCodes =
955 info->EpilogMap.size() + (LastEpilogIsAtEnd ? 0 : 1);
956 if ((numEpilogCodes % 2) != 0) {
957 AddPaddingEpilogCode =
true;
962 if ((
size_t)numCodes + numEpilogCodes > UINT8_MAX) {
964 "Too many unwind codes with Unwind v2 enabled in " +
965 info->Function->getName());
969 numCodes += numEpilogCodes;
974 if (
info->ChainedParent)
977 if (
info->HandlesUnwind)
979 if (
info->HandlesExceptions)
992 if (
info->LastFrameInst >= 0) {
1000 if (EnableUnwindV2) {
1009 uint8_t Flags = LastEpilogIsAtEnd ? 0x01 : 0;
1013 if (LastEpilogIsAtEnd)
1020 auto *MCE = MCUnwindV2EpilogTargetExpr::create(*
info,
Epilog.second,
1021 EpilogSize, context);
1026 if (AddPaddingEpilogCode)
1031 for (
uint8_t c = 0; c < numInst; ++c) {
1033 info->Instructions.pop_back();
1052 else if (numCodes == 0) {
1060bool MCUnwindV2EpilogTargetExpr::evaluateAsRelocatableImpl(
1066 Asm->getContext().reportError(
1067 Loc,
"Failed to evaluate epilog offset for Unwind v2 in " +
1072 constexpr uint16_t MaxEpilogOffset = 0x0fff;
1073 if (*
Offset > MaxEpilogOffset) {
1074 Asm->getContext().reportError(
1075 Loc,
"Epilog offset is too large for Unwind v2 in " +
1082 if (
Size != (EpilogSize - 1)) {
1083 Asm->getContext().reportError(
1084 Loc,
"Size of this epilog does not match size of last epilog in " +
1089 auto HighBits = *
Offset >> 8;
1095bool MCUnwindV3EpilogOffsetTargetExpr::evaluateAsRelocatableImpl(
1096 MCValue &Res,
const MCAssembler *Asm)
const {
1101 const MCSymbol *
Base = PrevEpilogStart ? PrevEpilogStart : FrameInfo.
End;
1103 Asm->getContext().reportError(
1104 Loc,
"Missing fragment end for V3 epilog offset in " +
1111 Asm->getContext().reportError(
1112 Loc,
"Failed to evaluate epilog offset for V3 unwind info in " +
1117 Asm->getContext().reportError(
1118 Loc,
"Epilog offset " + Twine(*
Offset) +
1119 " out of signed 16-bit range for V3 encoding in " +
1146 bool HandlerData)
const {
1176 std::optional<int64_t> MaybeDiff =
1189 std::optional<int64_t> MaybeDistance =
1195 for (
const auto &
I : Insns) {
1211 if (Distance != InstructionBytes) {
1213 SMLoc(),
"Incorrect size for " + Name +
" " +
Type +
": " +
1215 " bytes of instructions in range, but .seh directives "
1216 "corresponding to " +
1217 Twine(InstructionBytes) +
" bytes\n");
1223 for (
const auto &
I : Insns) {
1338 b = (inst.
Offset >> 4) & 0x1F;
1355 b = (w & 0x00FF0000) >> 16;
1357 b = (w & 0x0000FF00) >> 8;
1379 b |= (inst.
Offset >> 3) & 0x1F;
1384 b |= ((inst.
Offset >> 3) - 1) & 0x3F;
1389 b |= (inst.
Offset >> 3) & 0x3F;
1395 b = 0xD0 | ((reg & 0xC) >> 2);
1397 b = ((reg & 0x3) << 6) | (inst.
Offset >> 3);
1403 b = 0xD4 | ((reg & 0x8) >> 3);
1405 b = ((reg & 0x7) << 5) | ((inst.
Offset >> 3) - 1);
1411 b = 0xC8 | ((reg & 0xC) >> 2);
1413 b = ((reg & 0x3) << 6) | (inst.
Offset >> 3);
1419 b = 0xCC | ((reg & 0xC) >> 2);
1421 b = ((reg & 0x3) << 6) | ((inst.
Offset >> 3) - 1);
1427 assert((reg % 2) == 0 &&
"Saved reg must be 19+2*X");
1429 b = 0xD6 | ((reg & 0x7) >> 2);
1431 b = ((reg & 0x3) << 6) | (inst.
Offset >> 3);
1437 b = 0xDC | ((reg & 0x4) >> 2);
1439 b = ((reg & 0x3) << 6) | (inst.
Offset >> 3);
1447 b = ((reg & 0x7) << 5) | ((inst.
Offset >> 3) - 1);
1453 b = 0xD8 | ((reg & 0x4) >> 2);
1455 b = ((reg & 0x3) << 6) | (inst.
Offset >> 3);
1461 b = 0xDA | ((reg & 0x4) >> 2);
1463 b = ((reg & 0x3) << 6) | ((inst.
Offset >> 3) - 1);
1512 int Writeback =
Op / 6;
1513 int Paired =
Op % 2;
1516 if (Writeback || Paired ||
Mode == 2)
1523 b = inst.
Register | (Writeback << 5) | (Paired << 6);
1542 b = ((inst.
Offset & 0xC0) >> 1) | reg;
1544 b = 0xC0 | (inst.
Offset & 0x3F);
1554 b = ((inst.
Offset & 0xC0) >> 1) | 0x10 | reg;
1556 b = 0xC0 | (inst.
Offset & 0x3F);
1569 const std::vector<MCSymbol *>& Epilogs,
1571 for (
auto *EpilogStart : Epilogs) {
1572 auto InstrsIter =
info->EpilogMap.find(EpilogStart);
1573 assert(InstrsIter !=
info->EpilogMap.end() &&
1574 "Epilog not found in EpilogMap");
1575 const auto &Instrs = InstrsIter->second.Instructions;
1577 if (Instrs.size() != EpilogInstrs.size())
1581 for (
unsigned i = 0; i < Instrs.size(); ++i)
1582 if (Instrs[i] != EpilogInstrs[i]) {
1595 unsigned PrevOffset = -1;
1596 unsigned PrevRegister = -1;
1608 Inst.Register == 29) {
1612 Inst.Register == 19 && Inst.Offset <= 248) {
1618 Inst.Register == PrevRegister + 2 &&
1619 Inst.Offset == PrevOffset + 16) {
1634 PrevRegister = Inst.Register;
1636 PrevOffset = Inst.Offset;
1637 PrevRegister = Inst.Register;
1651 const std::vector<WinEH::Instruction> &
Epilog) {
1658 for (
int I =
Epilog.size() - 1;
I >= 0;
I--) {
1673 int PrologCodeBytes) {
1679 const std::vector<WinEH::Instruction> &
Epilog =
1680 info->EpilogMap[Sym].Instructions;
1686 if (DistanceFromEnd / 4 !=
Epilog.size())
1694 if (PrologCodeBytes <= 31 &&
1696 RetVal = PrologCodeBytes;
1705 if (
Offset > 31 || PrologCodeBytes > 124)
1710 info->EpilogMap.erase(Sym);
1715 int PackedEpilogOffset) {
1716 if (PackedEpilogOffset == 0) {
1722 }
else if (PackedEpilogOffset == 1) {
1732 unsigned RegI = 0, RegF = 0;
1733 int Predecrement = 0;
1745 bool StandaloneLR =
false, FPLRPair =
false;
1755 for (
auto It =
info->Instructions.begin(), EndIt =
info->Instructions.end();
1756 It != EndIt; It++) {
1760 if (Location != Start)
1765 if (Location != Start2)
1771 if (Location != Start2 && Location != Start3)
1773 Predecrement = Inst.
Offset;
1778 if (Location != Start2 && Location != Start3)
1780 Predecrement = Inst.
Offset;
1784 StandaloneLR =
true;
1788 Location = FloatRegs;
1815 StandaloneLR =
true;
1819 Location = FloatRegs;
1826 StandaloneLR =
true;
1827 Location = FloatRegs;
1834 if (Location != FloatRegs || RegF == 0 || Inst.
Register != 8 + RegF ||
1835 Inst.
Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
1838 Location = InputArgs;
1841 if ((Location != Start2 && Location != Start3) || Inst.
Register != 8)
1843 Predecrement = Inst.
Offset;
1845 Location = FloatRegs;
1848 if ((Location !=
IntRegs && Location != FloatRegs) ||
1850 Inst.
Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
1853 Location = FloatRegs;
1858 else if (Location == FloatRegs)
1864 if (Location !=
IntRegs && Location != FloatRegs && Location != InputArgs)
1866 Location = InputArgs;
1871 if (Location != Start2 && Location != Start3 && Location !=
IntRegs &&
1872 Location != FloatRegs && Location != InputArgs &&
1873 Location != StackAdjust)
1879 if (Location == Start2) {
1880 auto NextIt = It + 1;
1881 if (NextIt != EndIt) {
1885 assert(Predecrement == 0);
1888 Predecrement = Inst.
Offset;
1890 StandaloneLR =
true;
1891 Location = FloatRegs;
1905 Location = StackAdjust;
1910 if (Location != Start2 && Location != Start3 && Location !=
IntRegs &&
1911 Location != FloatRegs && Location != InputArgs)
1914 Location = FrameRecord;
1919 if (Location != StackAdjust || Inst.
Offset != 0)
1921 Location = FrameRecord;
1925 if (Location != FrameRecord)
1969 if (RegI > 10 || RegF > 8)
1971 if (StandaloneLR && FPLRPair)
1973 if (FPLRPair && Location != End)
1975 if (Nops != 0 && Nops != 4)
1977 if (PAC && !FPLRPair)
2004 if (StandaloneLR && RegI == 1 && RegF > 0)
2006 int IntSZ = 8 * RegI;
2009 int FpSZ = 8 * RegF;
2010 int SavSZ = (IntSZ + FpSZ + 8 * 8 *
H + 0xF) & ~0xF;
2011 if (Predecrement != SavSZ)
2018 if (FrameSize > 0x1FF)
2020 assert(RegF != 1 &&
"One single float reg not allowed");
2023 assert(FuncLength <= 0x7FF &&
"FuncLength should have been checked earlier");
2025 int CR = PAC ? 2 : FPLRPair ? 3 : StandaloneLR ? 1 : 0;
2026 info->PackedInfo |= Flag << 0;
2027 info->PackedInfo |= (FuncLength & 0x7FF) << 2;
2028 info->PackedInfo |= (RegF & 0x7) << 13;
2029 info->PackedInfo |= (RegI & 0xF) << 16;
2030 info->PackedInfo |= (
H & 0x1) << 20;
2031 info->PackedInfo |= (CR & 0x3) << 21;
2032 info->PackedInfo |= (FrameSize & 0x1FF) << 23;
2041 std::vector<MCSymbol *> EpilogStarts;
2043 EpilogStarts.push_back(
I.first);
2046 std::vector<MCSymbol *> AddedEpilogs;
2047 for (
auto *S : EpilogStarts) {
2049 auto &EpilogInstrs =
info->EpilogMap[S].Instructions;
2055 if (MatchingEpilog) {
2056 assert(EpilogInfo.contains(MatchingEpilog) &&
2057 "Duplicate epilog not found");
2058 EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
2061 EpilogInstrs.clear();
2063 EpilogInstrs)) >= 0) {
2064 EpilogInfo[EpilogStart] = PrologOffset;
2068 EpilogInfo[EpilogStart] += 1;
2071 EpilogInstrs.clear();
2073 EpilogInfo[EpilogStart] = TotalCodeBytes;
2074 TotalCodeBytes += CodeBytes;
2075 AddedEpilogs.push_back(EpilogStart);
2082 int64_t RawFuncLength) {
2083 if (
info->PrologEnd)
2085 info->PrologEnd,
info->Function->getName(),
2087 struct EpilogStartEnd {
2094 for (
auto &
I :
info->EpilogMap) {
2096 auto &Instrs =
I.second.Instructions;
2099 info->Function->getName(),
"epilogue");
2101 "Epilogs should be monotonically ordered");
2108 int64_t SegLimit = 0xFFFFC;
2109 int64_t SegOffset = 0;
2111 if (RawFuncLength > SegLimit) {
2113 int64_t RemainingLength = RawFuncLength;
2115 while (RemainingLength > SegLimit) {
2119 int64_t SegLength = SegLimit;
2120 int64_t SegEnd = SegOffset + SegLength;
2124 while (
E < Epilogs.
size() && Epilogs[
E].End < SegEnd) {
2126 EpilogsInSegment[Epilogs[
E].Start] = Epilogs[
E].Offset;
2137 if (
E < Epilogs.
size() && Epilogs[
E].Offset <= SegEnd)
2139 SegLength = Epilogs[
E].Offset - SegOffset;
2142 SegOffset, SegLength, !SegOffset);
2143 Seg.Epilogs = std::move(EpilogsInSegment);
2144 info->Segments.push_back(Seg);
2146 SegOffset += SegLength;
2147 RemainingLength -= SegLength;
2156 for (;
E < Epilogs.
size(); ++
E)
2157 LastSeg.Epilogs[Epilogs[
E].Start] = Epilogs[
E].Offset;
2158 info->Segments.push_back(LastSeg);
2164 bool TryPacked =
true) {
2173 info->Symbol = Label;
2176 bool HasEpilogs = (Seg.
Epilogs.size() != 0);
2181 int PackedEpilogOffset = HasEpilogs ?
2188 if (
info->Segments.size() == 1 && PackedEpilogOffset >= 0 &&
2189 uint32_t(PackedEpilogOffset) < PrologCodeBytes &&
2190 !
info->HandlesExceptions && SegLength <= 0x7ff && TryPacked) {
2205 PrologCodeBytes += 1;
2206 if (PackedEpilogOffset >= 0)
2207 PackedEpilogOffset += 1;
2215 PackedEpilogOffset = 0;
2218 uint32_t TotalCodeBytes = PrologCodeBytes;
2226 uint32_t CodeWords = TotalCodeBytes / 4;
2227 uint32_t CodeWordsMod = TotalCodeBytes % 4;
2231 PackedEpilogOffset >= 0 ? PackedEpilogOffset : Seg.
Epilogs.size();
2232 bool ExtensionWord = EpilogCount > 31 || TotalCodeBytes > 124;
2233 if (!ExtensionWord) {
2234 row1 |= (EpilogCount & 0x1F) << 22;
2235 row1 |= (CodeWords & 0x1F) << 27;
2237 if (
info->HandlesExceptions)
2239 if (PackedEpilogOffset >= 0)
2241 row1 |= SegLength & 0x3FFFF;
2245 if (ExtensionWord) {
2247 if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
2249 "SEH unwind data splitting is only implemented for large functions, "
2250 "cases of too many code words or too many epilogs will be done "
2253 row2 |= (CodeWords & 0xFF) << 16;
2254 row2 |= (EpilogCount & 0xFFFF);
2258 if (PackedEpilogOffset < 0) {
2260 for (
auto &
I : EpilogInfo) {
2268 row3 |= (EpilogIndex & 0x3FF) << 22;
2289 auto &EpilogInstrs =
info->EpilogMap[
I.first].Instructions;
2294 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
2296 for (
int i = 0; i < BytesMod; i++)
2299 if (
info->HandlesExceptions)
2309 bool TryPacked =
true) {
2317 if (
info->empty()) {
2318 info->EmitAttempted =
true;
2321 if (
info->EmitAttempted) {
2328 SMLoc(),
"Earlier .seh_handlerdata for " +
info->Function->getName() +
2329 " skipped due to no unwind info at the time "
2330 "(.seh_handlerdata too early?), but the function later "
2331 "did get unwind info that can't be emitted");
2336 for (
auto &
I :
info->EpilogMap)
2339 int64_t RawFuncLength;
2340 if (!
info->FuncletOrFuncEnd) {
2379 for (
auto &S :
info->Segments)
2383 info->Instructions.clear();
2388 for (
const auto &
I : Insns) {
2446 for (J = 3; J > 0; J--)
2447 if (
I.Offset & (0xffu << (8 * J)))
2458 bool *HasCustom =
nullptr) {
2460 for (
const auto &
I : Insns) {
2522 std::optional<int64_t> MaybeDistance =
2527 bool HasCustom =
false;
2531 if (Distance != InstructionBytes) {
2533 SMLoc(),
"Incorrect size for " + Name +
" " +
Type +
": " +
2535 " bytes of instructions in range, but .seh directives "
2536 "corresponding to " +
2537 Twine(InstructionBytes) +
" bytes\n");
2569 w = 0x8000 | (inst.
Register & 0x1fff) | (lr << 13);
2570 streamer.
emitInt8((w >> 8) & 0xff);
2571 streamer.
emitInt8((w >> 0) & 0xff);
2594 w = 0xe800 | (inst.
Offset / 4);
2595 streamer.
emitInt8((w >> 8) & 0xff);
2596 streamer.
emitInt8((w >> 0) & 0xff);
2601 w = 0xec00 | (inst.
Register & 0x0ff) | (lr << 8);
2602 streamer.
emitInt8((w >> 8) & 0xff);
2603 streamer.
emitInt8((w >> 0) & 0xff);
2630 streamer.
emitInt8((w >> 8) & 0xff);
2631 streamer.
emitInt8((w >> 0) & 0xff);
2638 streamer.
emitInt8((w >> 16) & 0xff);
2639 streamer.
emitInt8((w >> 8) & 0xff);
2640 streamer.
emitInt8((w >> 0) & 0xff);
2647 streamer.
emitInt8((w >> 8) & 0xff);
2648 streamer.
emitInt8((w >> 0) & 0xff);
2655 streamer.
emitInt8((w >> 16) & 0xff);
2656 streamer.
emitInt8((w >> 8) & 0xff);
2657 streamer.
emitInt8((w >> 0) & 0xff);
2675 for (i = 3; i > 0; i--)
2676 if (inst.
Offset & (0xffu << (8 * i)))
2691 const std::vector<WinEH::Instruction> &
Epilog,
2692 bool CanTweakProlog) {
2701 int EndIdx = CanTweakProlog ? 1 : 0;
2702 for (
int I =
Epilog.size() - 1;
I >= EndIdx;
I--) {
2709 if (CanTweakProlog) {
2727 int PrologCodeBytes) {
2729 if (
info->EpilogMap.size() != 1)
2734 if (EpilogInfo.Condition != 0xe)
2737 const std::vector<WinEH::Instruction> &
Epilog = EpilogInfo.Instructions;
2739 if (
info->Instructions.empty() ||
Epilog.empty())
2745 streamer,
info->FuncletOrFuncEnd,
info->EpilogMap.begin()->first);
2750 if (DistanceFromEnd != InstructionBytes)
2758 if (PrologCodeBytes <= 31 &&
2760 RetVal = PrologCodeBytes;
2770 if (
Offset > 31 || PrologCodeBytes > 63)
2779 info->EpilogMap.clear();
2784 unsigned &Folded,
int &
IntRegs) {
2785 if (Mask & (1 << 14)) {
2789 if (Mask & (1 << 11)) {
2799 while ((Mask & 1) == 0) {
2803 if ((Mask & (Mask + 1)) != 0)
2807 while (Mask & (1 <<
N))
2826 bool Homing =
false;
2827 bool HasR11 =
false;
2828 bool HasChain =
false;
2833 unsigned StackAdjust = 0;
2868 if (Step != 1 && Step != 2)
2883 if (Step == 1 && Inst.
Register == 0x0f) {
2891 if (Step != 1 && Step != 2)
2903 if (Step != 3 || !HasR11 ||
IntRegs >= 0 || PF > 0)
2910 if (Step != 3 || !HasR11 || (
IntRegs < 0 && PF == 0))
2917 if (Step != 1 && Step != 2 && Step != 3 && Step != 4)
2930 if (Step != 1 && Step != 2 && Step != 3 && Step != 4 && Step != 5)
2934 if (Inst.
Offset / 4 >= 0x3f4)
2936 StackAdjust = Inst.
Offset / 4;
2941 if (HasR11 && !HasChain) {
2950 if (HasChain && !HasLR)
2954 if (
info->EpilogMap.size() > 1)
2959 if (
info->EpilogMap.size() == 0) {
2966 info->EpilogMap.begin()->second;
2967 if (EpilogInfo.Condition != 0xe)
2969 const std::vector<WinEH::Instruction> &
Epilog = EpilogInfo.Instructions;
2971 streamer,
info->FuncletOrFuncEnd,
info->EpilogMap.begin()->first);
2976 if (DistanceFromEnd != InstructionBytes)
2979 bool GotStackAdjust =
false;
2980 bool GotFloatRegs =
false;
2981 bool GotIntRegs =
false;
2982 bool GotHomingRestore =
false;
2983 bool GotLRRestore =
false;
2984 bool NeedsReturn =
false;
2985 bool GotReturn =
false;
3007 if (Inst.
Offset / 4 >= 0x3f4)
3010 if (Homing && FloatRegs < 0 &&
IntRegs < 0 && StackAdjust == 0 &&
3011 PF == 0 && Inst.
Offset == 16) {
3012 GotHomingRestore =
true;
3015 if (StackAdjust > 0) {
3017 if (StackAdjust != Inst.
Offset / 4)
3019 GotStackAdjust =
true;
3020 }
else if (PF == Inst.
Offset / 4) {
3022 StackAdjust = Inst.
Offset / 4;
3023 GotStackAdjust =
true;
3030 }
else if (Step == 7 || Step == 8 || Step == 9) {
3031 if (!Homing || Inst.
Offset != 16)
3033 GotHomingRestore =
true;
3040 if (Step != 6 && Step != 7)
3043 if (FloatRegs != (
int)(Inst.
Register - 8))
3045 GotFloatRegs =
true;
3052 if (Step != 6 && Step != 7 && Step != 8)
3056 if (Homing && HasLR) {
3060 GotLRRestore =
true;
3066 if (HasLR != (Inst.
Offset == 1))
3069 GotLRRestore = Inst.
Offset == 1;
3088 if (Step != 6 && Step != 7 && Step != 8)
3093 bool CurHasLR =
false, CurHasR11 =
false;
3098 if (EF != PF && EF != StackAdjust)
3101 if (Homing && HasLR) {
3105 GotLRRestore =
true;
3111 if (CurHasLR != HasLR)
3113 GotLRRestore = CurHasLR;
3140 if (Step != 6 && Step != 7 && Step != 8 && Step != 9)
3142 if (!Homing || Inst.
Offset != 20 || GotLRRestore)
3144 GotLRRestore =
true;
3145 GotHomingRestore =
true;
3155 if (Step != 6 && Step != 7 && Step != 8 && Step != 9 && Step != 10)
3164 if (StackAdjust > 0 && !GotStackAdjust && EF == 0)
3166 if (FloatRegs >= 0 && !GotFloatRegs)
3168 if (
IntRegs >= 0 && !GotIntRegs)
3170 if (Homing && !GotHomingRestore)
3172 if (HasLR && !GotLRRestore)
3174 if (NeedsReturn && !GotReturn)
3178 assert(PF == 0 || EF == 0 ||
3180 if (PF > 0 || EF > 0) {
3181 StackAdjust = PF > 0 ? (PF - 1) : (EF - 1);
3182 assert(StackAdjust <= 3);
3183 StackAdjust |= 0x3f0;
3185 StackAdjust |= 1 << 2;
3187 StackAdjust |= 1 << 3;
3190 assert(FuncLength <= 0x7FF &&
"FuncLength should have been checked earlier");
3191 int Flag =
info->Fragment ? 0x02 : 0x01;
3192 int H = Homing ? 1 : 0;
3193 int L = HasLR ? 1 : 0;
3194 int C = HasChain ? 1 : 0;
3201 }
else if (FloatRegs >= 0) {
3210 info->PackedInfo |= Flag << 0;
3211 info->PackedInfo |= (FuncLength & 0x7FF) << 2;
3212 info->PackedInfo |= (Ret & 0x3) << 13;
3213 info->PackedInfo |=
H << 15;
3214 info->PackedInfo |=
Reg << 16;
3215 info->PackedInfo |= R << 19;
3216 info->PackedInfo |= L << 20;
3217 info->PackedInfo |=
C << 21;
3218 assert(StackAdjust <= 0x3ff);
3219 info->PackedInfo |= StackAdjust << 22;
3226 bool TryPacked =
true) {
3234 if (
info->empty()) {
3235 info->EmitAttempted =
true;
3238 if (
info->EmitAttempted) {
3245 SMLoc(),
"Earlier .seh_handlerdata for " +
info->Function->getName() +
3246 " skipped due to no unwind info at the time "
3247 "(.seh_handlerdata too early?), but the function later "
3248 "did get unwind info that can't be emitted");
3257 info->Symbol = Label;
3259 if (!
info->PrologEnd)
3261 info->Function->getName() +
3262 " not correctly terminated");
3264 if (
info->PrologEnd && !
info->Fragment)
3266 info->PrologEnd,
info->Function->getName(),
3268 for (
auto &
I :
info->EpilogMap) {
3272 info->Function->getName(),
"epilogue");
3273 if (
Epilog.Instructions.empty() ||
3276 SMLoc(),
"Epilogue in " +
info->Function->getName() +
3277 " not correctly terminated");
3280 std::optional<int64_t> RawFuncLength;
3281 const MCExpr *FuncLengthExpr =
nullptr;
3282 if (!
info->FuncletOrFuncEnd) {
3301 FuncLength = (
uint32_t)*RawFuncLength / 2;
3302 if (FuncLength > 0x3FFFF)
3305 uint32_t TotalCodeBytes = PrologCodeBytes;
3307 if (!
info->HandlesExceptions && RawFuncLength && FuncLength <= 0x7ff &&
3321 int PackedEpilogOffset =
3327 std::vector<MCSymbol *> AddedEpilogs;
3329 bool CanTweakProlog =
true;
3330 for (
auto &
I :
info->EpilogMap) {
3332 auto &EpilogInstrs =
I.second.Instructions;
3338 if (MatchingEpilog) {
3339 assert(EpilogInfo.contains(MatchingEpilog) &&
3340 "Duplicate epilog not found");
3341 EpilogInfo[EpilogStart] = EpilogInfo.lookup(MatchingEpilog);
3344 EpilogInstrs.clear();
3346 info->Instructions, EpilogInstrs, CanTweakProlog)) >= 0) {
3347 if (CanTweakProlog) {
3350 info->Instructions.front() = EpilogInstrs.back();
3352 CanTweakProlog =
false;
3354 EpilogInfo[EpilogStart] = PrologOffset;
3357 EpilogInstrs.clear();
3359 EpilogInfo[EpilogStart] = TotalCodeBytes;
3360 TotalCodeBytes += CodeBytes;
3361 AddedEpilogs.push_back(EpilogStart);
3367 uint32_t CodeWords = TotalCodeBytes / 4;
3368 uint32_t CodeWordsMod = TotalCodeBytes % 4;
3372 PackedEpilogOffset >= 0 ? PackedEpilogOffset :
info->EpilogMap.size();
3373 bool ExtensionWord = EpilogCount > 31 || CodeWords > 15;
3374 if (!ExtensionWord) {
3375 row1 |= (EpilogCount & 0x1F) << 23;
3376 row1 |= (CodeWords & 0x0F) << 28;
3378 if (
info->HandlesExceptions)
3380 if (PackedEpilogOffset >= 0)
3384 row1 |= FuncLength & 0x3FFFF;
3394 if (ExtensionWord) {
3396 if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
3399 row2 |= (CodeWords & 0xFF) << 16;
3400 row2 |= (EpilogCount & 0xFFFF);
3404 if (PackedEpilogOffset < 0) {
3406 for (
auto &
I : EpilogInfo) {
3410 std::optional<int64_t> MaybeEpilogOffset =
3412 const MCExpr *OffsetExpr =
nullptr;
3414 if (MaybeEpilogOffset)
3415 EpilogOffset = *MaybeEpilogOffset / 2;
3419 assert(
info->EpilogMap.contains(EpilogStart));
3420 unsigned Condition =
info->EpilogMap[EpilogStart].Condition;
3421 assert(Condition <= 0xf);
3424 row3 |= Condition << 20;
3425 row3 |= (EpilogIndex & 0x3FF) << 24;
3426 if (MaybeEpilogOffset)
3438 for (
uint8_t c = 0; c < numInst; ++c) {
3440 info->Instructions.pop_back();
3445 for (
auto &
I :
info->EpilogMap) {
3446 auto &EpilogInstrs =
I.second.Instructions;
3451 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
3453 for (
int i = 0; i < BytesMod; i++)
3456 if (
info->HandlesExceptions)
3468 for (
const auto &S :
info->Segments) {
3470 if (
info->PackedInfo)
3487 if (
info->PackedInfo)
3523 bool HandlerData)
const {
3530 if (!
info->FuncletOrFuncEnd) {
3568 bool HandlerData)
const {
3575 if (!
info->FuncletOrFuncEnd) {
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
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")
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)
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]
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
Tagged union holding either a T or a Error.
MCContext & getContext() const
static const MCBinaryExpr * createLShr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
static const MCBinaryExpr * createOr(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createDiv(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
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.
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.
Streaming machine code generation interface.
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
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)
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)
ArrayRef< std::unique_ptr< WinEH::FrameInfo > > getWinFrameInfos() const
void emitInt8(uint64_t Value)
Represent a reference to a symbol from inside an expression.
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
StringRef getName() const
getName - Get the symbol name.
MCFragment * getFragment() const
static MCValue get(const MCSymbol *SymA, const MCSymbol *SymB=nullptr, int64_t Val=0, uint32_t Specifier=0)
This class implements a map that also provides access to all stored values in a deterministic order.
Represents a location in source code.
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.
Represent a constant reference to a string, i.e.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
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.
@ EPILOG_INFO_LARGE
When set, the extended descriptor uses EPILOG_INFO_LARGE_EX_V3 (16-bit IpOffsetOfLastInstruction) and...
@ UNW_TerminateHandler
UNW_TerminateHandler - Specifies that this function has a termination handler.
@ UNW_FlagLarge
UNW_FlagLarge - V3 only.
@ UNW_ExceptionHandler
UNW_ExceptionHandler - Specifies that this function has an exception handler.
@ UNW_ChainInfo
UNW_ChainInfo - Specifies that this UnwindInfo structure is chained to another one.
UnwindOpcodes
UnwindOpcodes - Enumeration whose values specify a single operation in the prolog of a function.
@ UOP_WideSaveRegsR4R11LR
@ WOD_PUSH_CANONICAL_FRAME
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.
FunctionAddr VTableAddr Value
LLVM_ABI void reportFatalInternalError(Error Err)
Report a fatal error that indicates a bug in LLVM.
auto reverse(ContainerTy &&C)
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionAddr VTableAddr Count
auto reverse_conditionally(ContainerTy &&C, bool ShouldReverse)
Return a range that conditionally reverses C.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
@ FK_Data_1
A one-byte fixup.
@ FK_Data_2
A two-byte fixup.
DWARFExpression::Operation Op
LLVM_ABI void reportFatalUsageError(Error Err)
Report a fatal error that does not indicate a bug in LLVM.
This struct is a compact representation of a valid (non-zero power of two) alignment.
MapVector< MCSymbol *, int64_t > Epilogs
const MCSymbol * Function