aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC/MCWin64EH.cpp
diff options
context:
space:
mode:
authorMartin Storsjö <martin@martin.st>2022-10-11 14:29:36 +0300
committerMartin Storsjö <martin@martin.st>2022-10-12 11:07:12 +0300
commitafa6bb643fd4a691262f407c3ed477c5cb293529 (patch)
treea266b0fe6c56ef851a738175f960151e02c82aec /llvm/lib/MC/MCWin64EH.cpp
parentc43bff64e903f726d456ca27fd167b91198ae169 (diff)
downloadllvm-afa6bb643fd4a691262f407c3ed477c5cb293529.zip
llvm-afa6bb643fd4a691262f407c3ed477c5cb293529.tar.gz
llvm-afa6bb643fd4a691262f407c3ed477c5cb293529.tar.bz2
[MC] [Win64EH] Generate ARM64 packed unwind info with signed return addresses
Differential Revision: https://reviews.llvm.org/D135660
Diffstat (limited to 'llvm/lib/MC/MCWin64EH.cpp')
-rw-r--r--llvm/lib/MC/MCWin64EH.cpp27
1 files changed, 19 insertions, 8 deletions
diff --git a/llvm/lib/MC/MCWin64EH.cpp b/llvm/lib/MC/MCWin64EH.cpp
index f39383e..d2afb9c 100644
--- a/llvm/lib/MC/MCWin64EH.cpp
+++ b/llvm/lib/MC/MCWin64EH.cpp
@@ -734,6 +734,7 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
enum {
Start,
Start2,
+ Start3,
IntRegs,
FloatRegs,
InputArgs,
@@ -742,6 +743,7 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
End
} Location = Start;
bool StandaloneLR = false, FPLRPair = false;
+ bool PAC = false;
int StackOffset = 0;
int Nops = 0;
// Iterate over the prolog and check that all opcodes exactly match
@@ -757,15 +759,21 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
return false;
Location = Start2;
break;
- case Win64EH::UOP_SaveR19R20X:
+ case Win64EH::UOP_PACSignReturnAddress:
if (Location != Start2)
return false;
+ PAC = true;
+ Location = Start3;
+ break;
+ case Win64EH::UOP_SaveR19R20X:
+ if (Location != Start2 && Location != Start3)
+ return false;
Predecrement = Inst.Offset;
RegI = 2;
Location = IntRegs;
break;
case Win64EH::UOP_SaveRegX:
- if (Location != Start2)
+ if (Location != Start2 && Location != Start3)
return false;
Predecrement = Inst.Offset;
if (Inst.Register == 19)
@@ -828,7 +836,7 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
Location = InputArgs;
break;
case Win64EH::UOP_SaveFRegPX:
- if (Location != Start2 || Inst.Register != 8)
+ if ((Location != Start2 && Location != Start3) || Inst.Register != 8)
return false;
Predecrement = Inst.Offset;
RegF = 2;
@@ -858,8 +866,9 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
break;
case Win64EH::UOP_AllocSmall:
case Win64EH::UOP_AllocMedium:
- if (Location != Start2 && Location != IntRegs && Location != FloatRegs &&
- Location != InputArgs && Location != StackAdjust)
+ if (Location != Start2 && Location != Start3 && Location != IntRegs &&
+ Location != FloatRegs && Location != InputArgs &&
+ Location != StackAdjust)
return false;
// Can have either a single decrement, or a pair of decrements with
// 4080 and another decrement.
@@ -874,8 +883,8 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
case Win64EH::UOP_SaveFPLRX:
// Not allowing FPLRX after StackAdjust; if a StackAdjust is used, it
// should be followed by a FPLR instead.
- if (Location != Start2 && Location != IntRegs && Location != FloatRegs &&
- Location != InputArgs)
+ if (Location != Start2 && Location != Start3 && Location != IntRegs &&
+ Location != FloatRegs && Location != InputArgs)
return false;
StackOffset = Inst.Offset;
Location = FrameRecord;
@@ -903,6 +912,8 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
return false;
if (Nops != 0 && Nops != 4)
return false;
+ if (PAC && !FPLRPair)
+ return false;
int H = Nops == 4;
// There's an inconsistency regarding packed unwind info with homed
// parameters; according to the documentation, the epilog shouldn't have
@@ -933,7 +944,7 @@ static bool tryARM64PackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
RegF--; // Convert from actual number of registers, to value stored
assert(FuncLength <= 0x7FF && "FuncLength should have been checked earlier");
int Flag = 0x01; // Function segments not supported yet
- int CR = FPLRPair ? 3 : StandaloneLR ? 1 : 0;
+ int CR = PAC ? 2 : FPLRPair ? 3 : StandaloneLR ? 1 : 0;
info->PackedInfo |= Flag << 0;
info->PackedInfo |= (FuncLength & 0x7FF) << 2;
info->PackedInfo |= (RegF & 0x7) << 13;