27 for (
const auto &
I : Insns) {
46 Count += (
I.Offset > 512 * 1024 - 8) ? 3 : 2;
77 if (inst.
Offset > 512 * 1024 - 8) {
90 b2 |= (((inst.
Offset - 8) >> 3) & 0x0F) << 4;
176 info->Symbol = Label;
179 uint8_t flags = 0x01;
180 if (
info->ChainedParent)
183 if (
info->HandlesUnwind)
185 if (
info->HandlesExceptions)
199 if (
info->LastFrameInst >= 0) {
207 uint8_t numInst =
info->Instructions.size();
208 for (uint8_t c = 0; c < numInst; ++c) {
210 info->Instructions.pop_back();
229 else if (numCodes == 0) {
255 bool HandlerData)
const {
288 if (!Diff->evaluateAsAbsolute(
value,
OS->getAssembler()))
295 std::optional<int64_t> MaybeDiff =
308 std::optional<int64_t> MaybeDistance =
314 for (
const auto &
I : Insns) {
330 if (Distance != InstructionBytes) {
334 " bytes of instructions in range, but .seh directives "
335 "corresponding to " +
336 Twine(InstructionBytes) +
" bytes\n");
342 for (
const auto &
I : Insns) {
452 b = (inst.
Offset >> 4) & 0x1F;
469 b = (w & 0x00FF0000) >> 16;
471 b = (w & 0x0000FF00) >> 8;
493 b |= (inst.
Offset >> 3) & 0x1F;
498 b |= ((inst.
Offset - 1) >> 3) & 0x3F;
503 b |= (inst.
Offset >> 3) & 0x3F;
509 b = 0xD0 | ((reg & 0xC) >> 2);
511 b = ((reg & 0x3) << 6) | (inst.
Offset >> 3);
517 b = 0xD4 | ((reg & 0x8) >> 3);
519 b = ((reg & 0x7) << 5) | ((inst.
Offset >> 3) - 1);
525 b = 0xC8 | ((reg & 0xC) >> 2);
527 b = ((reg & 0x3) << 6) | (inst.
Offset >> 3);
533 b = 0xCC | ((reg & 0xC) >> 2);
535 b = ((reg & 0x3) << 6) | ((inst.
Offset >> 3) - 1);
541 assert((reg % 2) == 0 &&
"Saved reg must be 19+2*X");
543 b = 0xD6 | ((reg & 0x7) >> 2);
545 b = ((reg & 0x3) << 6) | (inst.
Offset >> 3);
551 b = 0xDC | ((reg & 0x4) >> 2);
553 b = ((reg & 0x3) << 6) | (inst.
Offset >> 3);
561 b = ((reg & 0x7) << 5) | ((inst.
Offset >> 3) - 1);
567 b = 0xD8 | ((reg & 0x4) >> 2);
569 b = ((reg & 0x3) << 6) | (inst.
Offset >> 3);
575 b = 0xDA | ((reg & 0x4) >> 2);
577 b = ((reg & 0x3) << 6) | ((inst.
Offset >> 3) - 1);
626 int Writeback =
Op / 6;
630 if (Writeback || Paired ||
Mode == 2)
637 b = inst.
Register | (Writeback << 5) | (Paired << 6);
652 const std::vector<MCSymbol *>& Epilogs,
654 for (
auto *EpilogStart : Epilogs) {
655 auto InstrsIter =
info->EpilogMap.find(EpilogStart);
657 "Epilog not found in EpilogMap");
658 const auto &Instrs = InstrsIter->second.Instructions;
660 if (Instrs.size() != EpilogInstrs.size())
664 for (
unsigned i = 0; i < Instrs.size(); ++i)
665 if (Instrs[i] != EpilogInstrs[i]) {
678 unsigned PrevOffset = -1;
679 unsigned PrevRegister = -1;
687 Inst.Register == 29) {
691 Inst.Register == 19 && Inst.Offset <= 248) {
697 Inst.Register == PrevRegister + 2 &&
698 Inst.Offset == PrevOffset + 16) {
713 PrevRegister = Inst.Register;
715 PrevOffset = Inst.Offset;
716 PrevRegister = Inst.Register;
730 for (
auto It = Instructions.rbegin(); It != Instructions.rend(); It++)
731 VisitInstruction(*It);
734 VisitInstruction(Inst);
741 const std::vector<WinEH::Instruction> &
Epilog) {
748 for (
int I =
Epilog.size() - 1;
I >= 0;
I--) {
763 int PrologCodeBytes) {
769 const std::vector<WinEH::Instruction> &
Epilog =
770 info->EpilogMap[
Sym].Instructions;
776 if (DistanceFromEnd / 4 !=
Epilog.size())
784 if (PrologCodeBytes <= 31 &&
786 RetVal = PrologCodeBytes;
795 if (
Offset > 31 || PrologCodeBytes > 124)
805 int PackedEpilogOffset) {
806 if (PackedEpilogOffset == 0) {
812 }
else if (PackedEpilogOffset == 1) {
822 unsigned RegI = 0, RegF = 0;
823 int Predecrement = 0;
835 bool StandaloneLR =
false, FPLRPair =
false;
848 if (Location != Start)
853 if (Location != Start2)
859 if (Location != Start2 && Location != Start3)
861 Predecrement = Inst.
Offset;
866 if (Location != Start2 && Location != Start3)
868 Predecrement = Inst.
Offset;
876 Location = FloatRegs;
907 Location = FloatRegs;
915 Location = FloatRegs;
922 if (Location != FloatRegs || RegF == 0 || Inst.
Register != 8 + RegF ||
923 Inst.
Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
926 Location = InputArgs;
929 if ((Location != Start2 && Location != Start3) || Inst.
Register != 8)
931 Predecrement = Inst.
Offset;
933 Location = FloatRegs;
936 if ((Location !=
IntRegs && Location != FloatRegs) ||
938 Inst.
Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
941 Location = FloatRegs;
946 else if (Location == FloatRegs)
952 if (Location !=
IntRegs && Location != FloatRegs && Location != InputArgs)
954 Location = InputArgs;
959 if (Location != Start2 && Location != Start3 && Location !=
IntRegs &&
960 Location != FloatRegs && Location != InputArgs &&
961 Location != StackAdjust)
971 Location = StackAdjust;
976 if (Location != Start2 && Location != Start3 && Location !=
IntRegs &&
977 Location != FloatRegs && Location != InputArgs)
980 Location = FrameRecord;
985 if (Location != StackAdjust || Inst.
Offset != 0)
987 Location = FrameRecord;
991 if (Location != FrameRecord)
1030 if (RegI > 10 || RegF > 8)
1032 if (StandaloneLR && FPLRPair)
1034 if (FPLRPair && Location !=
End)
1036 if (Nops != 0 && Nops != 4)
1038 if (PAC && !FPLRPair)
1051 int IntSZ = 8 * RegI;
1054 int FpSZ = 8 * RegF;
1055 int SavSZ = (IntSZ + FpSZ + 8 * 8 *
H + 0xF) & ~0xF;
1056 if (Predecrement != SavSZ)
1063 if (FrameSize > 0x1FF)
1065 assert(RegF != 1 &&
"One single float reg not allowed");
1068 assert(FuncLength <= 0x7FF &&
"FuncLength should have been checked earlier");
1070 int CR = PAC ? 2 : FPLRPair ? 3 : StandaloneLR ? 1 : 0;
1071 info->PackedInfo |= Flag << 0;
1072 info->PackedInfo |= (FuncLength & 0x7FF) << 2;
1073 info->PackedInfo |= (RegF & 0x7) << 13;
1074 info->PackedInfo |= (RegI & 0xF) << 16;
1075 info->PackedInfo |= (
H & 0x1) << 20;
1076 info->PackedInfo |= (CR & 0x3) << 21;
1077 info->PackedInfo |= (FrameSize & 0x1FF) << 23;
1086 std::vector<MCSymbol *> EpilogStarts;
1088 EpilogStarts.push_back(
I.first);
1091 std::vector<MCSymbol *> AddedEpilogs;
1092 for (
auto *S : EpilogStarts) {
1094 auto &EpilogInstrs =
info->EpilogMap[S].Instructions;
1100 if (MatchingEpilog) {
1102 "Duplicate epilog not found");
1103 EpilogInfo[EpilogStart] = EpilogInfo.
lookup(MatchingEpilog);
1106 EpilogInstrs.clear();
1108 EpilogInstrs)) >= 0) {
1109 EpilogInfo[EpilogStart] = PrologOffset;
1113 EpilogInfo[EpilogStart] += 1;
1116 EpilogInstrs.
clear();
1118 EpilogInfo[EpilogStart] = TotalCodeBytes;
1119 TotalCodeBytes += CodeBytes;
1120 AddedEpilogs.push_back(EpilogStart);
1127 int64_t RawFuncLength) {
1128 if (
info->PrologEnd)
1130 info->PrologEnd,
info->Function->getName(),
1132 struct EpilogStartEnd {
1139 for (
auto &
I :
info->EpilogMap) {
1141 auto &Instrs =
I.second.Instructions;
1144 info->Function->getName(),
"epilogue");
1146 "Epilogs should be monotonically ordered");
1153 int64_t SegLimit = 0xFFFFC;
1154 int64_t SegOffset = 0;
1156 if (RawFuncLength > SegLimit) {
1158 int64_t RemainingLength = RawFuncLength;
1160 while (RemainingLength > SegLimit) {
1164 int64_t SegLength = SegLimit;
1165 int64_t SegEnd = SegOffset + SegLength;
1169 while (E < Epilogs.
size() && Epilogs[E].End < SegEnd) {
1171 EpilogsInSegment[Epilogs[E].Start] = Epilogs[E].Offset;
1182 if (E < Epilogs.
size() && Epilogs[E].Offset <= SegEnd)
1184 SegLength = Epilogs[E].
Offset - SegOffset;
1187 SegOffset, SegLength, !SegOffset);
1188 Seg.Epilogs = std::move(EpilogsInSegment);
1189 info->Segments.push_back(Seg);
1191 SegOffset += SegLength;
1192 RemainingLength -= SegLength;
1201 for (; E < Epilogs.
size(); ++E)
1202 LastSeg.Epilogs[Epilogs[E].Start] = Epilogs[E].Offset;
1203 info->Segments.push_back(LastSeg);
1209 bool TryPacked =
true) {
1218 info->Symbol = Label;
1221 bool HasEpilogs = (Seg.
Epilogs.size() != 0);
1226 int PackedEpilogOffset = HasEpilogs ?
1233 if (
info->Segments.size() == 1 && PackedEpilogOffset >= 0 &&
1234 uint32_t(PackedEpilogOffset) < PrologCodeBytes &&
1235 !
info->HandlesExceptions && SegLength <= 0x7ff && TryPacked) {
1250 PrologCodeBytes += 1;
1251 if (PackedEpilogOffset >= 0)
1252 PackedEpilogOffset += 1;
1260 PackedEpilogOffset = 0;
1263 uint32_t TotalCodeBytes = PrologCodeBytes;
1271 uint32_t CodeWords = TotalCodeBytes / 4;
1272 uint32_t CodeWordsMod = TotalCodeBytes % 4;
1276 PackedEpilogOffset >= 0 ? PackedEpilogOffset : Seg.
Epilogs.size();
1277 bool ExtensionWord = EpilogCount > 31 || TotalCodeBytes > 124;
1278 if (!ExtensionWord) {
1279 row1 |= (EpilogCount & 0x1F) << 22;
1280 row1 |= (CodeWords & 0x1F) << 27;
1282 if (
info->HandlesExceptions)
1284 if (PackedEpilogOffset >= 0)
1286 row1 |= SegLength & 0x3FFFF;
1290 if (ExtensionWord) {
1292 if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
1294 "SEH unwind data splitting is only implemented for large functions, "
1295 "cases of too many code words or too many epilogs will be done "
1298 row2 |= (CodeWords & 0xFF) << 16;
1299 row2 |= (EpilogCount & 0xFFFF);
1303 if (PackedEpilogOffset < 0) {
1305 for (
auto &
I : EpilogInfo) {
1313 row3 |= (EpilogIndex & 0x3FF) << 22;
1334 auto &EpilogInstrs =
info->EpilogMap[
I.first].Instructions;
1339 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
1341 for (
int i = 0; i < BytesMod; i++)
1344 if (
info->HandlesExceptions)
1354 bool TryPacked =
true) {
1362 if (
info->empty()) {
1363 info->EmitAttempted =
true;
1366 if (
info->EmitAttempted) {
1373 SMLoc(),
"Earlier .seh_handlerdata for " +
info->Function->getName() +
1374 " skipped due to no unwind info at the time "
1375 "(.seh_handlerdata too early?), but the function later "
1376 "did get unwind info that can't be emitted");
1381 for (
auto &
I :
info->EpilogMap)
1384 int64_t RawFuncLength;
1385 if (!
info->FuncletOrFuncEnd) {
1424 for (
auto &S :
info->Segments)
1428 info->Instructions.clear();
1433 for (
const auto &
I : Insns) {
1491 for (J = 3; J > 0; J--)
1492 if (
I.Offset & (0xffu << (8 * J)))
1503 bool *HasCustom =
nullptr) {
1505 for (
const auto &
I : Insns) {
1567 std::optional<int64_t> MaybeDistance =
1572 bool HasCustom =
false;
1576 if (Distance != InstructionBytes) {
1580 " bytes of instructions in range, but .seh directives "
1581 "corresponding to " +
1582 Twine(InstructionBytes) +
" bytes\n");
1614 w = 0x8000 | (inst.
Register & 0x1fff) | (lr << 13);
1615 streamer.
emitInt8((w >> 8) & 0xff);
1616 streamer.
emitInt8((w >> 0) & 0xff);
1639 w = 0xe800 | (inst.
Offset / 4);
1640 streamer.
emitInt8((w >> 8) & 0xff);
1641 streamer.
emitInt8((w >> 0) & 0xff);
1646 w = 0xec00 | (inst.
Register & 0x0ff) | (lr << 8);
1647 streamer.
emitInt8((w >> 8) & 0xff);
1648 streamer.
emitInt8((w >> 0) & 0xff);
1675 streamer.
emitInt8((w >> 8) & 0xff);
1676 streamer.
emitInt8((w >> 0) & 0xff);
1683 streamer.
emitInt8((w >> 16) & 0xff);
1684 streamer.
emitInt8((w >> 8) & 0xff);
1685 streamer.
emitInt8((w >> 0) & 0xff);
1692 streamer.
emitInt8((w >> 8) & 0xff);
1693 streamer.
emitInt8((w >> 0) & 0xff);
1700 streamer.
emitInt8((w >> 16) & 0xff);
1701 streamer.
emitInt8((w >> 8) & 0xff);
1702 streamer.
emitInt8((w >> 0) & 0xff);
1720 for (i = 3; i > 0; i--)
1721 if (inst.
Offset & (0xffu << (8 * i)))
1736 const std::vector<WinEH::Instruction> &
Epilog,
1737 bool CanTweakProlog) {
1746 int EndIdx = CanTweakProlog ? 1 : 0;
1747 for (
int I =
Epilog.size() - 1;
I >= EndIdx;
I--) {
1754 if (CanTweakProlog) {
1772 int PrologCodeBytes) {
1774 if (
info->EpilogMap.size() != 1)
1784 if (
info->Instructions.empty() ||
Epilog.empty())
1790 streamer,
info->FuncletOrFuncEnd,
info->EpilogMap.begin()->first);
1795 if (DistanceFromEnd != InstructionBytes)
1803 if (PrologCodeBytes <= 31 &&
1805 RetVal = PrologCodeBytes;
1815 if (
Offset > 31 || PrologCodeBytes > 63)
1824 info->EpilogMap.clear();
1829 unsigned &Folded,
int &
IntRegs) {
1830 if (Mask & (1 << 14)) {
1834 if (Mask & (1 << 11)) {
1844 while ((Mask & 1) == 0) {
1848 if ((Mask & (Mask + 1)) != 0)
1852 while (Mask & (1 <<
N))
1871 bool Homing =
false;
1872 bool HasR11 =
false;
1873 bool HasChain =
false;
1878 unsigned StackAdjust = 0;
1913 if (Step != 1 && Step != 2)
1928 if (Step == 1 && Inst.
Register == 0x0f) {
1936 if (Step != 1 && Step != 2)
1948 if (Step != 3 || !HasR11 ||
IntRegs >= 0 || PF > 0)
1955 if (Step != 3 || !HasR11 || (
IntRegs < 0 && PF == 0))
1962 if (Step != 1 && Step != 2 && Step != 3 && Step != 4)
1975 if (Step != 1 && Step != 2 && Step != 3 && Step != 4 && Step != 5)
1979 if (Inst.
Offset / 4 >= 0x3f4)
1981 StackAdjust = Inst.
Offset / 4;
1986 if (HasR11 && !HasChain) {
1995 if (HasChain && !HasLR)
1999 if (
info->EpilogMap.size() > 1)
2004 if (
info->EpilogMap.size() == 0) {
2011 info->EpilogMap.begin()->second;
2016 streamer,
info->FuncletOrFuncEnd,
info->EpilogMap.begin()->first);
2021 if (DistanceFromEnd != InstructionBytes)
2024 bool GotStackAdjust =
false;
2025 bool GotFloatRegs =
false;
2026 bool GotIntRegs =
false;
2027 bool GotHomingRestore =
false;
2028 bool GotLRRestore =
false;
2029 bool NeedsReturn =
false;
2030 bool GotReturn =
false;
2052 if (Inst.
Offset / 4 >= 0x3f4)
2055 if (Homing && FloatRegs < 0 &&
IntRegs < 0 && StackAdjust == 0 &&
2056 PF == 0 && Inst.
Offset == 16) {
2057 GotHomingRestore =
true;
2060 if (StackAdjust > 0) {
2062 if (StackAdjust != Inst.
Offset / 4)
2064 GotStackAdjust =
true;
2065 }
else if (PF == Inst.
Offset / 4) {
2067 StackAdjust = Inst.
Offset / 4;
2068 GotStackAdjust =
true;
2075 }
else if (Step == 7 || Step == 8 || Step == 9) {
2076 if (!Homing || Inst.
Offset != 16)
2078 GotHomingRestore =
true;
2085 if (Step != 6 && Step != 7)
2088 if (FloatRegs != (
int)(Inst.
Register - 8))
2090 GotFloatRegs =
true;
2097 if (Step != 6 && Step != 7 && Step != 8)
2101 if (Homing && HasLR) {
2105 GotLRRestore =
true;
2111 if (HasLR != (Inst.
Offset == 1))
2114 GotLRRestore = Inst.
Offset == 1;
2133 if (Step != 6 && Step != 7 && Step != 8)
2138 bool CurHasLR =
false, CurHasR11 =
false;
2143 if (EF != PF && EF != StackAdjust)
2146 if (Homing && HasLR) {
2150 GotLRRestore =
true;
2156 if (CurHasLR != HasLR)
2158 GotLRRestore = CurHasLR;
2185 if (Step != 6 && Step != 7 && Step != 8 && Step != 9)
2187 if (!Homing || Inst.
Offset != 20 || GotLRRestore)
2189 GotLRRestore =
true;
2190 GotHomingRestore =
true;
2200 if (Step != 6 && Step != 7 && Step != 8 && Step != 9 && Step != 10)
2209 if (StackAdjust > 0 && !GotStackAdjust && EF == 0)
2211 if (FloatRegs >= 0 && !GotFloatRegs)
2213 if (
IntRegs >= 0 && !GotIntRegs)
2215 if (Homing && !GotHomingRestore)
2217 if (HasLR && !GotLRRestore)
2219 if (NeedsReturn && !GotReturn)
2223 assert(PF == 0 || EF == 0 ||
2225 if (PF > 0 || EF > 0) {
2226 StackAdjust = PF > 0 ? (PF - 1) : (EF - 1);
2227 assert(StackAdjust <= 3);
2228 StackAdjust |= 0x3f0;
2230 StackAdjust |= 1 << 2;
2232 StackAdjust |= 1 << 3;
2235 assert(FuncLength <= 0x7FF &&
"FuncLength should have been checked earlier");
2236 int Flag =
info->Fragment ? 0x02 : 0x01;
2237 int H = Homing ? 1 : 0;
2238 int L = HasLR ? 1 : 0;
2239 int C = HasChain ? 1 : 0;
2246 }
else if (FloatRegs >= 0) {
2255 info->PackedInfo |= Flag << 0;
2256 info->PackedInfo |= (FuncLength & 0x7FF) << 2;
2257 info->PackedInfo |= (Ret & 0x3) << 13;
2258 info->PackedInfo |=
H << 15;
2259 info->PackedInfo |= Reg << 16;
2260 info->PackedInfo |= R << 19;
2261 info->PackedInfo |= L << 20;
2262 info->PackedInfo |=
C << 21;
2263 assert(StackAdjust <= 0x3ff);
2264 info->PackedInfo |= StackAdjust << 22;
2271 bool TryPacked =
true) {
2279 if (
info->empty()) {
2280 info->EmitAttempted =
true;
2283 if (
info->EmitAttempted) {
2290 SMLoc(),
"Earlier .seh_handlerdata for " +
info->Function->getName() +
2291 " skipped due to no unwind info at the time "
2292 "(.seh_handlerdata too early?), but the function later "
2293 "did get unwind info that can't be emitted");
2302 info->Symbol = Label;
2304 if (!
info->PrologEnd)
2306 info->Function->getName() +
2307 " not correctly terminated");
2309 if (
info->PrologEnd && !
info->Fragment)
2311 info->PrologEnd,
info->Function->getName(),
2313 for (
auto &
I :
info->EpilogMap) {
2317 info->Function->getName(),
"epilogue");
2318 if (
Epilog.Instructions.empty() ||
2321 SMLoc(),
"Epilogue in " +
info->Function->getName() +
2322 " not correctly terminated");
2325 std::optional<int64_t> RawFuncLength;
2326 const MCExpr *FuncLengthExpr =
nullptr;
2327 if (!
info->FuncletOrFuncEnd) {
2346 FuncLength = (
uint32_t)*RawFuncLength / 2;
2347 if (FuncLength > 0x3FFFF)
2350 uint32_t TotalCodeBytes = PrologCodeBytes;
2352 if (!
info->HandlesExceptions && RawFuncLength && FuncLength <= 0x7ff &&
2366 int PackedEpilogOffset =
2372 std::vector<MCSymbol *> AddedEpilogs;
2374 bool CanTweakProlog =
true;
2375 for (
auto &
I :
info->EpilogMap) {
2377 auto &EpilogInstrs =
I.second.Instructions;
2383 if (MatchingEpilog) {
2385 "Duplicate epilog not found");
2386 EpilogInfo[EpilogStart] = EpilogInfo.
lookup(MatchingEpilog);
2389 EpilogInstrs.clear();
2391 info->Instructions, EpilogInstrs, CanTweakProlog)) >= 0) {
2392 if (CanTweakProlog) {
2395 info->Instructions.front() = EpilogInstrs.back();
2397 CanTweakProlog =
false;
2399 EpilogInfo[EpilogStart] = PrologOffset;
2402 EpilogInstrs.
clear();
2404 EpilogInfo[EpilogStart] = TotalCodeBytes;
2405 TotalCodeBytes += CodeBytes;
2406 AddedEpilogs.push_back(EpilogStart);
2412 uint32_t CodeWords = TotalCodeBytes / 4;
2413 uint32_t CodeWordsMod = TotalCodeBytes % 4;
2417 PackedEpilogOffset >= 0 ? PackedEpilogOffset :
info->EpilogMap.size();
2418 bool ExtensionWord = EpilogCount > 31 || CodeWords > 15;
2419 if (!ExtensionWord) {
2420 row1 |= (EpilogCount & 0x1F) << 23;
2421 row1 |= (CodeWords & 0x0F) << 28;
2423 if (
info->HandlesExceptions)
2425 if (PackedEpilogOffset >= 0)
2429 row1 |= FuncLength & 0x3FFFF;
2439 if (ExtensionWord) {
2441 if (CodeWords > 0xFF || EpilogCount > 0xFFFF)
2444 row2 |= (CodeWords & 0xFF) << 16;
2445 row2 |= (EpilogCount & 0xFFFF);
2449 if (PackedEpilogOffset < 0) {
2451 for (
auto &
I : EpilogInfo) {
2455 std::optional<int64_t> MaybeEpilogOffset =
2457 const MCExpr *OffsetExpr =
nullptr;
2459 if (MaybeEpilogOffset)
2460 EpilogOffset = *MaybeEpilogOffset / 2;
2464 assert(
info->EpilogMap.contains(EpilogStart));
2465 unsigned Condition =
info->EpilogMap[EpilogStart].Condition;
2466 assert(Condition <= 0xf);
2469 row3 |= Condition << 20;
2470 row3 |= (EpilogIndex & 0x3FF) << 24;
2471 if (MaybeEpilogOffset)
2482 uint8_t numInst =
info->Instructions.size();
2483 for (uint8_t c = 0; c < numInst; ++c) {
2485 info->Instructions.pop_back();
2490 for (
auto &
I :
info->EpilogMap) {
2491 auto &EpilogInstrs =
I.second.Instructions;
2496 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
2498 for (
int i = 0; i < BytesMod; i++)
2501 if (
info->HandlesExceptions)
2513 for (
const auto &S :
info->Segments) {
2515 if (
info->PackedInfo)
2532 if (
info->PackedInfo)
2568 bool HandlerData)
const {
2575 if (!
info->FuncletOrFuncEnd) {
2613 bool HandlerData)
const {
2620 if (!
info->FuncletOrFuncEnd) {
Analysis containing CSE Info
Given that RA is a live value
std::optional< std::vector< StOtherPiece > > Other
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 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 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 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 std::optional< int64_t > GetOptionalAbsDifference(MCStreamer &Streamer, const MCSymbol *LHS, const MCSymbol *RHS)
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 uint8_t CountOfUnwindCodes(std::vector< WinEH::Instruction > &Insns)
static cl::opt< RegAllocEvictionAdvisorAnalysis::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysis::AdvisorMode::Development, "development", "for training")))
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const MCPhysReg IntRegs[32]
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
size - Get the array size.
This class represents an Operation in the Expression.
Tagged union holding either a T or a Error.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
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 const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Context object for machine code objects.
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
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.
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 Value=0, unsigned ValueSize=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)
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
This class implements a map that also provides access to all stored values in a deterministic order.
bool contains(const KeyT &Key) const
ValueT lookup(const KeyT &Key) const
Represents a location in source code.
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.
StringRef - 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.
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.
@ UNW_TerminateHandler
UNW_TerminateHandler - Specifies that this function has a termination handler.
@ 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
This is an optimization pass for GlobalISel generic memory operations.
auto reverse(ContainerTy &&C)
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
This struct is a compact representation of a valid (non-zero power of two) alignment.
std::vector< Instruction > Instructions
MapVector< MCSymbol *, int64_t > Epilogs