Lines Matching +full:step +full:- +full:up
1 //===- lib/MC/MCWin64EH.cpp - MCWin64EH implementation --------------------===//
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
23 // NOTE: All relocations generated here are 4-byte image-relative.
46 Count += (I.Offset > 512 * 1024 - 8) ? 3 : 2;
77 if (inst.Offset > 512 * 1024 - 8) {
90 b2 |= (((inst.Offset - 8) >> 3) & 0x0F) << 4;
159 EmitSymbolRefWithOfs(streamer, info->Begin, info->Begin);
160 EmitSymbolRefWithOfs(streamer, info->Begin, info->End);
161 streamer.emitValue(MCSymbolRefExpr::create(info->Symbol,
168 if (info->Symbol)
176 info->Symbol = Label;
180 if (info->ChainedParent)
183 if (info->HandlesUnwind)
185 if (info->HandlesExceptions)
190 if (info->PrologEnd)
191 EmitAbsDifference(streamer, info->PrologEnd, info->Begin);
195 uint8_t numCodes = CountOfUnwindCodes(info->Instructions);
199 if (info->LastFrameInst >= 0) {
200 WinEH::Instruction &frameInst = info->Instructions[info->LastFrameInst];
207 uint8_t numInst = info->Instructions.size();
209 WinEH::Instruction inst = info->Instructions.back();
210 info->Instructions.pop_back();
211 EmitUnwindCode(streamer, info->Begin, inst);
223 EmitRuntimeFunction(streamer, info->ChainedParent);
226 streamer.emitValue(MCSymbolRefExpr::create(info->ExceptionHandler,
240 MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
247 MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
258 MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
288 if (!Diff->evaluateAsAbsolute(value, OS->getAssembler()))
329 uint32_t InstructionBytes = 4 * (Insns.size() - 1);
444 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
498 b |= ((inst.Offset - 1) >> 3) & 0x3F;
508 reg = inst.Register - 19;
516 reg = inst.Register - 19;
519 b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
524 reg = inst.Register - 19;
532 reg = inst.Register - 19;
535 b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
540 reg = inst.Register - 19;
550 reg = inst.Register - 8;
558 reg = inst.Register - 8;
561 b = ((reg & 0x7) << 5) | ((inst.Offset >> 3) - 1);
566 reg = inst.Register - 8;
574 reg = inst.Register - 8;
577 b = ((reg & 0x3) << 6) | ((inst.Offset >> 3) - 1);
625 int Op = inst.Operation - Win64EH::UOP_SaveAnyRegI;
633 --Offset;
648 // EpilogInstrs - Unwind codes for the current epilog.
649 // Epilogs - Epilogs that potentialy match the current epilog.
655 auto InstrsIter = info->EpilogMap.find(EpilogStart);
656 assert(InstrsIter != info->EpilogMap.end() &&
658 const auto &Instrs = InstrsIter->second.Instructions;
678 unsigned PrevOffset = -1;
679 unsigned PrevRegister = -1;
682 // Convert 2-byte opcodes into equivalent 1-byte ones.
685 Inst.Register = -1;
689 Inst.Register = -1;
693 Inst.Register = -1;
700 Inst.Register = -1;
703 // as current versions of Windows (up to at least 20.04) is buggy
721 PrevRegister = -1;
722 PrevOffset = -1;
744 return -1;
748 for (int I = Epilog.size() - 1; I >= 0; I--) {
749 if (Prolog[I] != Epilog[Epilog.size() - 1 - I])
750 return -1;
758 &Prolog[Epilog.size()], Prolog.size() - Epilog.size()));
765 if (Seg->Epilogs.size() != 1)
766 return -1;
768 MCSymbol *Sym = Seg->Epilogs.begin()->first;
770 info->EpilogMap[Sym].Instructions;
775 (uint32_t)(Seg->Offset + Seg->Length - Seg->Epilogs.begin()->second);
777 return -1;
779 int RetVal = -1;
780 // Even if we don't end up sharing opcodes with the prolog, we can still
788 int Offset = getARM64OffsetInProlog(info->Instructions, Epilog);
800 info->EpilogMap.erase(Sym);
816 if (info->Instructions.back().Operation != Win64EH::UOP_SetFP)
842 // the order - that would work fine when unwinding from within
845 for (const WinEH::Instruction &Inst : info->Instructions) {
884 // RegI=10/RegF=8/CR=1/H=1, we end up with SavSZ = 216, which should
888 // "stp x19, lr, [sp, #-...]!" as that fits neither SaveRegPX nor
1007 // These are never canonical; they don't show up with the usual Arm64
1016 // "add x29, sp, #N" doesn't show up in the canonical pattern (except for
1044 // require an epilog which isn't exactly symmetrical - we shouldn't accept
1047 // the same nops. See https://github.com/llvm/llvm-project/issues/54879.
1067 RegF--; // Convert from actual number of registers, to value stored
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;
1087 for (auto &I : Seg->Epilogs)
1094 auto &EpilogInstrs = info->EpilogMap[S].Instructions;
1107 } else if ((PrologOffset = getARM64OffsetInProlog(info->Instructions,
1112 if (!Seg->HasProlog)
1128 if (info->PrologEnd)
1129 checkARM64Instructions(streamer, info->Instructions, info->Begin,
1130 info->PrologEnd, info->Function->getName(),
1139 for (auto &I : info->EpilogMap) {
1142 int64_t Offset = GetAbsDifference(streamer, Start, info->Begin);
1144 info->Function->getName(), "epilogue");
1149 Epilogs.push_back({Start, Offset, Offset + (int64_t)(Instrs.size() - 1) * 4});
1184 SegLength = Epilogs[E].Offset - SegOffset;
1189 info->Segments.push_back(Seg);
1192 RemainingLength -= SegLength;
1199 WinEH::FrameInfo::Segment(SegOffset, RawFuncLength - SegOffset,
1203 info->Segments.push_back(LastSeg);
1218 info->Symbol = Label;
1224 uint32_t PrologCodeBytes = info->PrologCodeBytes;
1227 checkARM64PackedEpilog(streamer, info, &Seg, PrologCodeBytes) : -1;
1230 // 1. Enable packed unwind info (.pdata only) for multi-segment functions.
1233 if (info->Segments.size() == 1 && PackedEpilogOffset >= 0 &&
1235 !info->HandlesExceptions && SegLength <= 0x7ff && TryPacked) {
1240 // info->Symbol was already set even if we didn't actually write any
1255 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling#function-fragments
1282 if (info->HandlesExceptions) // X
1309 uint32_t EpilogOffset = (uint32_t)(Seg.Epilogs[EpilogStart] - Seg.Offset);
1329 for (auto Inst : llvm::reverse(info->Instructions))
1334 auto &EpilogInstrs = info->EpilogMap[I.first].Instructions;
1339 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
1344 if (info->HandlesExceptions)
1346 MCSymbolRefExpr::create(info->ExceptionHandler,
1352 // https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
1356 if (info->Symbol)
1362 if (info->empty()) {
1363 info->EmitAttempted = true;
1366 if (info->EmitAttempted) {
1373 SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +
1380 simplifyARM64Opcodes(info->Instructions, false);
1381 for (auto &I : info->EpilogMap)
1385 if (!info->FuncletOrFuncEnd) {
1398 // we could emit something like ".word (endfunc-beginfunc)/4+0x10800000",
1417 RawFuncLength = GetAbsDifference(streamer, info->FuncletOrFuncEnd,
1418 info->Begin);
1423 info->PrologCodeBytes = ARM64CountOfUnwindCodes(info->Instructions);
1424 for (auto &S : info->Segments)
1428 info->Instructions.clear();
1491 for (J = 3; J > 0; J--)
1598 // https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling
1625 streamer.emitInt8(0xd0 | (inst.Register - 4) | (inst.Offset << 2));
1630 streamer.emitInt8(0xd8 | (inst.Register - 8) | (inst.Offset << 2));
1634 streamer.emitInt8(0xe0 | (inst.Register - 8));
1668 streamer.emitInt8(((inst.Register - 16) << 4) | (inst.Offset - 16));
1720 for (i = 3; i > 0; i--)
1723 for (; i >= 0; i--)
1740 return -1;
1747 for (int I = Epilog.size() - 1; I >= EndIdx; I--) {
1749 // "push {r0-r3}".
1750 if (Prolog[I] != Epilog[Epilog.size() - 1 - I])
1751 return -1;
1757 return -1;
1761 return -1;
1768 &Prolog[Epilog.size()], Prolog.size() - Epilog.size()));
1774 if (info->EpilogMap.size() != 1)
1775 return -1;
1777 const WinEH::FrameInfo::Epilog &EpilogInfo = info->EpilogMap.begin()->second;
1780 return -1;
1784 if (info->Instructions.empty() || Epilog.empty())
1785 return -1;
1790 streamer, info->FuncletOrFuncEnd, info->EpilogMap.begin()->first);
1792 return -1;
1796 return -1;
1798 int RetVal = -1;
1799 // Even if we don't end up sharing opcodes with the prolog, we can still
1808 getARMOffsetInProlog(info->Instructions, Epilog, /*CanTweakProlog=*/true);
1820 info->Instructions.front() = Epilog.back();
1824 info->EpilogMap.clear();
1839 IntRegs = -1;
1857 Folded = 4 - First;
1858 N -= Folded;
1864 IntRegs = N - 1;
1870 int Step = 0;
1875 int IntRegs = -1; // r4 - r(4+N)
1876 int FloatRegs = -1; // d8 - d(8+N)
1881 for (const WinEH::Instruction &Inst : info->Instructions) {
1905 if (Step != 0)
1907 Step = 1;
1912 // push {r4-r11,lr}
1913 if (Step != 1 && Step != 2)
1915 assert(Inst.Register >= 4 && Inst.Register <= 11); // r4-rX
1917 IntRegs = Inst.Register - 4;
1920 IntRegs--;
1924 Step = 3;
1928 if (Step == 1 && Inst.Register == 0x0f) {
1929 // push {r0-r3}
1931 Step = 2;
1936 if (Step != 1 && Step != 2)
1938 // push {r4-r9,r11,lr}
1940 // push {r1-r5}
1943 Step = 3;
1948 if (Step != 3 || !HasR11 || IntRegs >= 0 || PF > 0)
1951 Step = 4;
1955 if (Step != 3 || !HasR11 || (IntRegs < 0 && PF == 0))
1958 Step = 4;
1962 if (Step != 1 && Step != 2 && Step != 3 && Step != 4)
1969 FloatRegs = Inst.Register - 8;
1970 Step = 5;
1975 if (Step != 1 && Step != 2 && Step != 3 && Step != 4 && Step != 5)
1982 Step = 6;
1988 // r11 stored, but not chaining; can be packed if already saving r4-r10
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);
2032 Step = 6;
2054 if (Step == 6) {
2058 Step = 10;
2066 // Folded prologue, non-folded epilogue
2073 Step = 7;
2075 } else if (Step == 7 || Step == 8 || Step == 9) {
2079 Step = 10;
2085 if (Step != 6 && Step != 7)
2088 if (FloatRegs != (int)(Inst.Register - 8))
2091 Step = 8;
2096 // push {r4-r11,lr}
2097 if (Step != 6 && Step != 7 && Step != 8)
2099 assert(Inst.Register >= 4 && Inst.Register <= 11); // r4-rX
2102 // If homing and LR is backed up, we can either restore LR here
2119 // Can't express r11 here unless IntRegs describe r4-r10
2124 if (Expected != (int)(Inst.Register - 4))
2127 Step = 9;
2133 if (Step != 6 && Step != 7 && Step != 8)
2135 // push {r4-r9,r11,lr}
2137 // push {r1-r5}
2147 // If homing and LR is backed up, we can either restore LR here
2168 Expected--;
2180 Step = 9;
2185 if (Step != 6 && Step != 7 && Step != 8 && Step != 9)
2191 Step = 10;
2200 if (Step != 6 && Step != 7 && Step != 8 && Step != 9 && Step != 10)
2202 Step = 11;
2207 if (Step != 11)
2226 StackAdjust = PF > 0 ? (PF - 1) : (EF - 1);
2236 int Flag = info->Fragment ? 0x02 : 0x01;
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;
2264 info->PackedInfo |= StackAdjust << 22;
2269 // https://docs.microsoft.com/en-us/cpp/build/arm-exception-handling
2273 if (info->Symbol)
2279 if (info->empty()) {
2280 info->EmitAttempted = true;
2283 if (info->EmitAttempted) {
2290 SMLoc(), "Earlier .seh_handlerdata for " + info->Function->getName() +
2302 info->Symbol = Label;
2304 if (!info->PrologEnd)
2306 info->Function->getName() +
2309 if (info->PrologEnd && !info->Fragment)
2310 checkARMInstructions(streamer, info->Instructions, info->Begin,
2311 info->PrologEnd, info->Function->getName(),
2313 for (auto &I : info->EpilogMap) {
2317 info->Function->getName(), "epilogue");
2321 SMLoc(), "Epilogue in " + info->Function->getName() +
2327 if (!info->FuncletOrFuncEnd) {
2339 GetOptionalAbsDifference(streamer, info->FuncletOrFuncEnd, info->Begin);
2342 GetSubDivExpr(streamer, info->FuncletOrFuncEnd, info->Begin, 2);
2349 uint32_t PrologCodeBytes = ARMCountOfUnwindCodes(info->Instructions);
2352 if (!info->HandlesExceptions && RawFuncLength && FuncLength <= 0x7ff &&
2358 // info->Symbol was already set even if we didn't actually write any
2375 for (auto &I : info->EpilogMap) {
2391 info->Instructions, EpilogInstrs, CanTweakProlog)) >= 0) {
2395 info->Instructions.front() = EpilogInstrs.back();
2417 PackedEpilogOffset >= 0 ? PackedEpilogOffset : info->EpilogMap.size();
2423 if (info->HandlesExceptions) // X
2427 if (info->Fragment) // F
2456 GetOptionalAbsDifference(streamer, EpilogStart, info->Begin);
2462 OffsetExpr = GetSubDivExpr(streamer, EpilogStart, info->Begin, 2);
2464 assert(info->EpilogMap.contains(EpilogStart));
2465 unsigned Condition = info->EpilogMap[EpilogStart].Condition;
2482 uint8_t numInst = info->Instructions.size();
2484 WinEH::Instruction inst = info->Instructions.back();
2485 info->Instructions.pop_back();
2490 for (auto &I : info->EpilogMap) {
2496 int32_t BytesMod = CodeWords * 4 - TotalCodeBytes;
2501 if (info->HandlesExceptions)
2503 MCSymbolRefExpr::create(info->ExceptionHandler,
2513 for (const auto &S : info->Segments) {
2514 EmitSymbolRefWithOfs(streamer, info->Begin, S.Offset);
2515 if (info->PackedInfo)
2516 streamer.emitInt32(info->PackedInfo);
2531 EmitSymbolRefWithOfs(streamer, info->Begin, info->Begin);
2532 if (info->PackedInfo)
2533 streamer.emitInt32(info->PackedInfo);
2536 MCSymbolRefExpr::create(info->Symbol, MCSymbolRefExpr::VK_COFF_IMGREL32,
2545 if (Info->empty())
2547 MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
2558 if (!Info->Symbol)
2560 MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
2570 // function. This forces writing the xdata record already here - and
2574 // whole function, only up to this point.
2575 if (!info->FuncletOrFuncEnd) {
2576 Streamer.switchSection(info->TextSection);
2577 info->FuncletOrFuncEnd = Streamer.emitCFILabel();
2581 MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
2590 if (Info->empty())
2592 MCSection *XData = Streamer.getAssociatedXDataSection(CFI->TextSection);
2603 if (!Info->Symbol)
2605 MCSection *PData = Streamer.getAssociatedPDataSection(CFI->TextSection);
2615 // function. This forces writing the xdata record already here - and
2619 // whole function, only up to this point.
2620 if (!info->FuncletOrFuncEnd) {
2621 Streamer.switchSection(info->TextSection);
2622 info->FuncletOrFuncEnd = Streamer.emitCFILabel();
2626 MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);