forked from OSchip/llvm-project
[MC] [Win64EH] Try to generate packed unwind info where possible
In practice, this only gives modest savings (for a 6.5 MB DLL with 230 KB xdata, the xdata sections shrinks by around 2.5 KB); to gain more, the frame lowering would need to be tweaked to more often generate frame layouts that match the canonical layouts that can be written in packed form. Differential Revision: https://reviews.llvm.org/D87371
This commit is contained in:
parent
fe3c1195cf
commit
f69e090d7d
|
@ -45,6 +45,7 @@ struct FrameInfo {
|
|||
const MCSymbol *PrologEnd = nullptr;
|
||||
const MCSymbol *Symbol = nullptr;
|
||||
MCSection *TextSection = nullptr;
|
||||
uint32_t PackedInfo = 0;
|
||||
|
||||
bool HandlesUnwind = false;
|
||||
bool HandlesExceptions = false;
|
||||
|
|
|
@ -648,9 +648,233 @@ static int checkPackedEpilog(MCStreamer &streamer, WinEH::FrameInfo *info,
|
|||
return Offset;
|
||||
}
|
||||
|
||||
static bool tryPackedUnwind(WinEH::FrameInfo *info, uint32_t FuncLength,
|
||||
int PackedEpilogOffset) {
|
||||
if (PackedEpilogOffset == 0) {
|
||||
// Fully symmetric prolog and epilog, should be ok for packed format.
|
||||
// For CR=3, the corresponding synthesized epilog actually lacks the
|
||||
// SetFP opcode, but unwinding should work just fine despite that
|
||||
// (if at the SetFP opcode, the unwinder considers it as part of the
|
||||
// function body and just unwinds the full prolog instead).
|
||||
} else if (PackedEpilogOffset == 1) {
|
||||
// One single case of differences between prolog and epilog is allowed:
|
||||
// The epilog can lack a single SetFP that is the last opcode in the
|
||||
// prolog, for the CR=3 case.
|
||||
if (info->Instructions.back().Operation != Win64EH::UOP_SetFP)
|
||||
return false;
|
||||
} else {
|
||||
// Too much difference between prolog and epilog.
|
||||
return false;
|
||||
}
|
||||
unsigned RegI = 0, RegF = 0;
|
||||
int Predecrement = 0;
|
||||
enum {
|
||||
Start,
|
||||
Start2,
|
||||
IntRegs,
|
||||
FloatRegs,
|
||||
InputArgs,
|
||||
StackAdjust,
|
||||
FrameRecord,
|
||||
End
|
||||
} Location = Start;
|
||||
bool StandaloneLR = false, FPLRPair = false;
|
||||
int StackOffset = 0;
|
||||
int Nops = 0;
|
||||
// Iterate over the prolog and check that all opcodes exactly match
|
||||
// the canonical order and form. A more lax check could verify that
|
||||
// all saved registers are in the expected locations, but not enforce
|
||||
// the order - that would work fine when unwinding from within
|
||||
// functions, but not be exactly right if unwinding happens within
|
||||
// prologs/epilogs.
|
||||
for (const WinEH::Instruction &Inst : info->Instructions) {
|
||||
switch (Inst.Operation) {
|
||||
case Win64EH::UOP_End:
|
||||
if (Location != Start)
|
||||
return false;
|
||||
Location = Start2;
|
||||
break;
|
||||
case Win64EH::UOP_SaveR19R20X:
|
||||
if (Location != Start2)
|
||||
return false;
|
||||
Predecrement = Inst.Offset;
|
||||
RegI = 2;
|
||||
Location = IntRegs;
|
||||
break;
|
||||
case Win64EH::UOP_SaveRegX:
|
||||
if (Location != Start2)
|
||||
return false;
|
||||
Predecrement = Inst.Offset;
|
||||
if (Inst.Register == 19)
|
||||
RegI += 1;
|
||||
else if (Inst.Register == 30)
|
||||
StandaloneLR = true;
|
||||
else
|
||||
return false;
|
||||
// Odd register; can't be any further int registers.
|
||||
Location = FloatRegs;
|
||||
break;
|
||||
case Win64EH::UOP_SaveRegPX:
|
||||
// Can't have this in a canonical prologue. Either this has been
|
||||
// canonicalized into SaveR19R20X or SaveFPLRX, or it's an unsupported
|
||||
// register pair.
|
||||
// It can't be canonicalized into SaveR19R20X if the offset is
|
||||
// larger than 248 bytes, but even with the maximum case with
|
||||
// RegI=10/RegF=8/CR=1/H=1, we end up with SavSZ = 216, which should
|
||||
// fit into SaveR19R20X.
|
||||
// The unwinding opcodes can't describe the otherwise seemingly valid
|
||||
// case for RegI=1 CR=1, that would start with a
|
||||
// "stp x19, lr, [sp, #-...]!" as that fits neither SaveRegPX nor
|
||||
// SaveLRPair.
|
||||
return false;
|
||||
case Win64EH::UOP_SaveRegP:
|
||||
if (Location != IntRegs || Inst.Offset != 8 * RegI ||
|
||||
Inst.Register != 19 + RegI)
|
||||
return false;
|
||||
RegI += 2;
|
||||
break;
|
||||
case Win64EH::UOP_SaveReg:
|
||||
if (Location != IntRegs || Inst.Offset != 8 * RegI)
|
||||
return false;
|
||||
if (Inst.Register == 19 + RegI)
|
||||
RegI += 1;
|
||||
else if (Inst.Register == 30)
|
||||
StandaloneLR = true;
|
||||
else
|
||||
return false;
|
||||
// Odd register; can't be any further int registers.
|
||||
Location = FloatRegs;
|
||||
break;
|
||||
case Win64EH::UOP_SaveLRPair:
|
||||
if (Location != IntRegs || Inst.Offset != 8 * RegI ||
|
||||
Inst.Register != 19 + RegI)
|
||||
return false;
|
||||
RegI += 1;
|
||||
StandaloneLR = true;
|
||||
Location = FloatRegs;
|
||||
break;
|
||||
case Win64EH::UOP_SaveFRegX:
|
||||
// Packed unwind can't handle prologs that only save one single
|
||||
// float register.
|
||||
return false;
|
||||
case Win64EH::UOP_SaveFReg:
|
||||
if (Location != FloatRegs || RegF == 0 || Inst.Register != 8 + RegF ||
|
||||
Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
|
||||
return false;
|
||||
RegF += 1;
|
||||
Location = InputArgs;
|
||||
break;
|
||||
case Win64EH::UOP_SaveFRegPX:
|
||||
if (Location != Start2 || Inst.Register != 8)
|
||||
return false;
|
||||
Predecrement = Inst.Offset;
|
||||
RegF = 2;
|
||||
Location = FloatRegs;
|
||||
break;
|
||||
case Win64EH::UOP_SaveFRegP:
|
||||
if ((Location != IntRegs && Location != FloatRegs) ||
|
||||
Inst.Register != 8 + RegF ||
|
||||
Inst.Offset != 8 * (RegI + (StandaloneLR ? 1 : 0) + RegF))
|
||||
return false;
|
||||
RegF += 2;
|
||||
Location = FloatRegs;
|
||||
break;
|
||||
case Win64EH::UOP_SaveNext:
|
||||
if (Location == IntRegs)
|
||||
RegI += 2;
|
||||
else if (Location == FloatRegs)
|
||||
RegF += 2;
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
case Win64EH::UOP_Nop:
|
||||
if (Location != IntRegs && Location != FloatRegs && Location != InputArgs)
|
||||
return false;
|
||||
Location = InputArgs;
|
||||
Nops++;
|
||||
break;
|
||||
case Win64EH::UOP_AllocSmall:
|
||||
case Win64EH::UOP_AllocMedium:
|
||||
if (Location != Start2 && 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.
|
||||
if (StackOffset == 0)
|
||||
StackOffset = Inst.Offset;
|
||||
else if (StackOffset != 4080)
|
||||
return false;
|
||||
else
|
||||
StackOffset += Inst.Offset;
|
||||
Location = StackAdjust;
|
||||
break;
|
||||
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)
|
||||
return false;
|
||||
StackOffset = Inst.Offset;
|
||||
Location = FrameRecord;
|
||||
FPLRPair = true;
|
||||
break;
|
||||
case Win64EH::UOP_SaveFPLR:
|
||||
// This can only follow after a StackAdjust
|
||||
if (Location != StackAdjust || Inst.Offset != 0)
|
||||
return false;
|
||||
Location = FrameRecord;
|
||||
FPLRPair = true;
|
||||
break;
|
||||
case Win64EH::UOP_SetFP:
|
||||
if (Location != FrameRecord)
|
||||
return false;
|
||||
Location = End;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (RegI > 10 || RegF > 8)
|
||||
return false;
|
||||
if (StandaloneLR && FPLRPair)
|
||||
return false;
|
||||
if (FPLRPair && Location != End)
|
||||
return false;
|
||||
if (Nops != 0 && Nops != 4)
|
||||
return false;
|
||||
int H = Nops == 4;
|
||||
int IntSZ = 8 * RegI;
|
||||
if (StandaloneLR)
|
||||
IntSZ += 8;
|
||||
int FpSZ = 8 * RegF; // RegF not yet decremented
|
||||
int SavSZ = (IntSZ + FpSZ + 8 * 8 * H + 0xF) & ~0xF;
|
||||
if (Predecrement != SavSZ)
|
||||
return false;
|
||||
if (FPLRPair && StackOffset < 16)
|
||||
return false;
|
||||
if (StackOffset % 16)
|
||||
return false;
|
||||
uint32_t FrameSize = (StackOffset + SavSZ) / 16;
|
||||
if (FrameSize > 0x1FF)
|
||||
return false;
|
||||
assert(RegF != 1 && "One single float reg not allowed");
|
||||
if (RegF > 0)
|
||||
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;
|
||||
info->PackedInfo |= Flag << 0;
|
||||
info->PackedInfo |= (FuncLength & 0x7FF) << 2;
|
||||
info->PackedInfo |= (RegF & 0x7) << 13;
|
||||
info->PackedInfo |= (RegI & 0xF) << 16;
|
||||
info->PackedInfo |= (H & 0x1) << 20;
|
||||
info->PackedInfo |= (CR & 0x3) << 21;
|
||||
info->PackedInfo |= (FrameSize & 0x1FF) << 23;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Populate the .xdata section. The format of .xdata on ARM64 is documented at
|
||||
// https://docs.microsoft.com/en-us/cpp/build/arm64-exception-handling
|
||||
static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
|
||||
static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info,
|
||||
bool TryPacked = true) {
|
||||
// If this UNWIND_INFO already has a symbol, it's already been emitted.
|
||||
if (info->Symbol)
|
||||
return;
|
||||
|
@ -728,6 +952,20 @@ static void ARM64EmitUnwindInfo(MCStreamer &streamer, WinEH::FrameInfo *info) {
|
|||
|
||||
int PackedEpilogOffset = checkPackedEpilog(streamer, info, PrologCodeBytes);
|
||||
|
||||
if (PackedEpilogOffset >= 0 && !info->HandlesExceptions &&
|
||||
FuncLength <= 0x7ff && TryPacked) {
|
||||
// Matching prolog/epilog and no exception handlers; check if the
|
||||
// prolog matches the patterns that can be described by the packed
|
||||
// format.
|
||||
|
||||
// info->Symbol was already set even if we didn't actually write any
|
||||
// unwind info there. Keep using that as indicator that this unwind
|
||||
// info has been generated already.
|
||||
|
||||
if (tryPackedUnwind(info, FuncLength, PackedEpilogOffset))
|
||||
return;
|
||||
}
|
||||
|
||||
// Process epilogs.
|
||||
MapVector<MCSymbol *, uint32_t> EpilogInfo;
|
||||
// Epilogs processed so far.
|
||||
|
@ -835,10 +1073,13 @@ static void ARM64EmitRuntimeFunction(MCStreamer &streamer,
|
|||
|
||||
streamer.emitValueToAlignment(4);
|
||||
EmitSymbolRefWithOfs(streamer, info->Function, info->Begin);
|
||||
streamer.emitValue(MCSymbolRefExpr::create(info->Symbol,
|
||||
MCSymbolRefExpr::VK_COFF_IMGREL32,
|
||||
context),
|
||||
4);
|
||||
if (info->PackedInfo)
|
||||
streamer.emitInt32(info->PackedInfo);
|
||||
else
|
||||
streamer.emitValue(
|
||||
MCSymbolRefExpr::create(info->Symbol, MCSymbolRefExpr::VK_COFF_IMGREL32,
|
||||
context),
|
||||
4);
|
||||
}
|
||||
|
||||
void llvm::Win64EH::ARM64UnwindEmitter::Emit(MCStreamer &Streamer) const {
|
||||
|
@ -882,5 +1123,5 @@ void llvm::Win64EH::ARM64UnwindEmitter::EmitUnwindInfo(
|
|||
// here and from Emit().
|
||||
MCSection *XData = Streamer.getAssociatedXDataSection(info->TextSection);
|
||||
Streamer.SwitchSection(XData);
|
||||
ARM64EmitUnwindInfo(Streamer, info);
|
||||
ARM64EmitUnwindInfo(Streamer, info, false);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,947 @@
|
|||
// Check that we generate the packed unwind info format whe possible.
|
||||
|
||||
// For tests that don't generate packed unwind info, we still check that
|
||||
// the epilog was packed (so that the testcase otherwise had all other
|
||||
// preconditions for possibly making packed unwind info).
|
||||
|
||||
// REQUIRES: aarch64-registered-target
|
||||
// RUN: llvm-mc -filetype=obj -triple aarch64-windows %s -o %t.o
|
||||
// RUN: llvm-readobj --unwind %t.o | FileCheck %s
|
||||
|
||||
// CHECK: UnwindInformation [
|
||||
// CHECK-NEXT: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: func1
|
||||
// CHECK-NEXT: Fragment: No
|
||||
// CHECK-NEXT: FunctionLength: 88
|
||||
// CHECK-NEXT: RegF: 7
|
||||
// CHECK-NEXT: RegI: 10
|
||||
// CHECK-NEXT: HomedParameters: No
|
||||
// CHECK-NEXT: CR: 0
|
||||
// CHECK-NEXT: FrameSize: 160
|
||||
// CHECK-NEXT: Prologue [
|
||||
// CHECK-NEXT: sub sp, sp, #16
|
||||
// CHECK-NEXT: stp d14, d15, [sp, #128]
|
||||
// CHECK-NEXT: stp d12, d13, [sp, #112]
|
||||
// CHECK-NEXT: stp d10, d11, [sp, #96]
|
||||
// CHECK-NEXT: stp d8, d9, [sp, #80]
|
||||
// CHECK-NEXT: stp x27, x28, [sp, #64]
|
||||
// CHECK-NEXT: stp x25, x26, [sp, #48]
|
||||
// CHECK-NEXT: stp x23, x24, [sp, #32]
|
||||
// CHECK-NEXT: stp x21, x22, [sp, #16]
|
||||
// CHECK-NEXT: stp x19, x20, [sp, #-144]!
|
||||
// CHECK-NEXT: end
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: func2
|
||||
// CHECK-NEXT: Fragment: No
|
||||
// CHECK-NEXT: FunctionLength: 48
|
||||
// CHECK-NEXT: RegF: 2
|
||||
// CHECK-NEXT: RegI: 3
|
||||
// CHECK-NEXT: HomedParameters: No
|
||||
// CHECK-NEXT: CR: 0
|
||||
// CHECK-NEXT: FrameSize: 48
|
||||
// CHECK-NEXT: Prologue [
|
||||
// CHECK-NEXT: str d10, [sp, #40]
|
||||
// CHECK-NEXT: stp d8, d9, [sp, #24]
|
||||
// CHECK-NEXT: str x21, [sp, #16]
|
||||
// CHECK-NEXT: stp x19, x20, [sp, #-48]!
|
||||
// CHECK-NEXT: end
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: func3
|
||||
// CHECK-NEXT: Fragment: No
|
||||
// CHECK-NEXT: FunctionLength: 32
|
||||
// CHECK-NEXT: RegF: 3
|
||||
// CHECK-NEXT: RegI: 1
|
||||
// CHECK-NEXT: HomedParameters: No
|
||||
// CHECK-NEXT: CR: 0
|
||||
// CHECK-NEXT: FrameSize: 48
|
||||
// CHECK-NEXT: Prologue [
|
||||
// CHECK-NEXT: stp d10, d11, [sp, #24]
|
||||
// CHECK-NEXT: stp d8, d9, [sp, #8]
|
||||
// CHECK-NEXT: str x19, [sp, #-48]!
|
||||
// CHECK-NEXT: end
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: func4
|
||||
// CHECK-NEXT: Fragment: No
|
||||
// CHECK-NEXT: FunctionLength: 24
|
||||
// CHECK-NEXT: RegF: 1
|
||||
// CHECK-NEXT: RegI: 0
|
||||
// CHECK-NEXT: HomedParameters: No
|
||||
// CHECK-NEXT: CR: 0
|
||||
// CHECK-NEXT: FrameSize: 48
|
||||
// CHECK-NEXT: Prologue [
|
||||
// CHECK-NEXT: sub sp, sp, #32
|
||||
// CHECK-NEXT: stp d8, d9, [sp, #-16]!
|
||||
// CHECK-NEXT: end
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: func5
|
||||
// CHECK-NEXT: Fragment: No
|
||||
// CHECK-NEXT: FunctionLength: 56
|
||||
// CHECK-NEXT: RegF: 0
|
||||
// CHECK-NEXT: RegI: 1
|
||||
// CHECK-NEXT: HomedParameters: Yes
|
||||
// CHECK-NEXT: CR: 0
|
||||
// CHECK-NEXT: FrameSize: 112
|
||||
// CHECK-NEXT: Prologue [
|
||||
// CHECK-NEXT: sub sp, sp, #32
|
||||
// CHECK-NEXT: stp x6, x7, [sp, #56]
|
||||
// CHECK-NEXT: stp x4, x5, [sp, #40]
|
||||
// CHECK-NEXT: stp x2, x3, [sp, #24]
|
||||
// CHECK-NEXT: stp x0, x1, [sp, #8]
|
||||
// CHECK-NEXT: str x19, [sp, #-80]!
|
||||
// CHECK-NEXT: end
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: func6
|
||||
// CHECK-NEXT: Fragment: No
|
||||
// CHECK-NEXT: FunctionLength: 24
|
||||
// CHECK-NEXT: RegF: 0
|
||||
// CHECK-NEXT: RegI: 0
|
||||
// CHECK-NEXT: HomedParameters: No
|
||||
// CHECK-NEXT: CR: 1
|
||||
// CHECK-NEXT: FrameSize: 32
|
||||
// CHECK-NEXT: Prologue [
|
||||
// CHECK-NEXT: sub sp, sp, #16
|
||||
// CHECK-NEXT: str lr, [sp, #-16]!
|
||||
// CHECK-NEXT: end
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: func7
|
||||
// CHECK-NEXT: Fragment: No
|
||||
// CHECK-NEXT: FunctionLength: 24
|
||||
// CHECK-NEXT: RegF: 0
|
||||
// CHECK-NEXT: RegI: 2
|
||||
// CHECK-NEXT: HomedParameters: No
|
||||
// CHECK-NEXT: CR: 1
|
||||
// CHECK-NEXT: FrameSize: 32
|
||||
// CHECK-NEXT: Prologue [
|
||||
// CHECK-NEXT: str lr, [sp, #16]
|
||||
// CHECK-NEXT: stp x19, x20, [sp, #-32]!
|
||||
// CHECK-NEXT: end
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: func8
|
||||
// CHECK-NEXT: Fragment: No
|
||||
// CHECK-NEXT: FunctionLength: 32
|
||||
// CHECK-NEXT: RegF: 0
|
||||
// CHECK-NEXT: RegI: 3
|
||||
// CHECK-NEXT: HomedParameters: No
|
||||
// CHECK-NEXT: CR: 1
|
||||
// CHECK-NEXT: FrameSize: 48
|
||||
// CHECK-NEXT: Prologue [
|
||||
// CHECK-NEXT: sub sp, sp, #16
|
||||
// CHECK-NEXT: stp x21, lr, [sp, #16]
|
||||
// CHECK-NEXT: stp x19, x20, [sp, #-32]!
|
||||
// CHECK-NEXT: end
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: func9
|
||||
// CHECK-NEXT: Fragment: No
|
||||
// CHECK-NEXT: FunctionLength: 32
|
||||
// CHECK-NEXT: RegF: 0
|
||||
// CHECK-NEXT: RegI: 2
|
||||
// CHECK-NEXT: HomedParameters: No
|
||||
// CHECK-NEXT: CR: 3
|
||||
// CHECK-NEXT: FrameSize: 48
|
||||
// CHECK-NEXT: Prologue [
|
||||
// CHECK-NEXT: mov x29, sp
|
||||
// CHECK-NEXT: stp x29, lr, [sp, #-32]!
|
||||
// CHECK-NEXT: stp x19, x20, [sp, #-16]!
|
||||
// CHECK-NEXT: end
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: func10
|
||||
// CHECK-NEXT: Fragment: No
|
||||
// CHECK-NEXT: FunctionLength: 24
|
||||
// CHECK-NEXT: RegF: 0
|
||||
// CHECK-NEXT: RegI: 0
|
||||
// CHECK-NEXT: HomedParameters: No
|
||||
// CHECK-NEXT: CR: 3
|
||||
// CHECK-NEXT: FrameSize: 32
|
||||
// CHECK-NEXT: Prologue [
|
||||
// CHECK-NEXT: mov x29, sp
|
||||
// CHECK-NEXT: stp x29, lr, [sp, #-32]!
|
||||
// CHECK-NEXT: end
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: func11
|
||||
// CHECK-NEXT: Fragment: No
|
||||
// CHECK-NEXT: FunctionLength: 40
|
||||
// CHECK-NEXT: RegF: 0
|
||||
// CHECK-NEXT: RegI: 2
|
||||
// CHECK-NEXT: HomedParameters: No
|
||||
// CHECK-NEXT: CR: 3
|
||||
// CHECK-NEXT: FrameSize: 544
|
||||
// CHECK-NEXT: Prologue [
|
||||
// CHECK-NEXT: mov x29, sp
|
||||
// CHECK-NEXT: stp x29, lr, [sp, #0]
|
||||
// CHECK-NEXT: sub sp, sp, #528
|
||||
// CHECK-NEXT: stp x19, x20, [sp, #-16]!
|
||||
// CHECK-NEXT: end
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: func12
|
||||
// CHECK-NEXT: Fragment: No
|
||||
// CHECK-NEXT: FunctionLength: 48
|
||||
// CHECK-NEXT: RegF: 0
|
||||
// CHECK-NEXT: RegI: 2
|
||||
// CHECK-NEXT: HomedParameters: No
|
||||
// CHECK-NEXT: CR: 3
|
||||
// CHECK-NEXT: FrameSize: 4112
|
||||
// CHECK-NEXT: Prologue [
|
||||
// CHECK-NEXT: mov x29, sp
|
||||
// CHECK-NEXT: stp x29, lr, [sp, #0]
|
||||
// CHECK-NEXT: sub sp, sp, #16
|
||||
// CHECK-NEXT: sub sp, sp, #4080
|
||||
// CHECK-NEXT: stp x19, x20, [sp, #-16]!
|
||||
// CHECK-NEXT: end
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: func13
|
||||
// CHECK-NEXT: Fragment: No
|
||||
// CHECK-NEXT: FunctionLength: 32
|
||||
// CHECK-NEXT: RegF: 0
|
||||
// CHECK-NEXT: RegI: 2
|
||||
// CHECK-NEXT: HomedParameters: No
|
||||
// CHECK-NEXT: CR: 0
|
||||
// CHECK-NEXT: FrameSize: 4112
|
||||
// CHECK-NEXT: Prologue [
|
||||
// CHECK-NEXT: sub sp, sp, #16
|
||||
// CHECK-NEXT: sub sp, sp, #4080
|
||||
// CHECK-NEXT: stp x19, x20, [sp, #-16]!
|
||||
// CHECK-NEXT: end
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: func14
|
||||
// CHECK-NEXT: Fragment: No
|
||||
// CHECK-NEXT: FunctionLength: 32
|
||||
// CHECK-NEXT: RegF: 2
|
||||
// CHECK-NEXT: RegI: 0
|
||||
// CHECK-NEXT: HomedParameters: No
|
||||
// CHECK-NEXT: CR: 1
|
||||
// CHECK-NEXT: FrameSize: 32
|
||||
// CHECK-NEXT: Prologue [
|
||||
// CHECK-NEXT: str d10, [sp, #24]
|
||||
// CHECK-NEXT: stp d8, d9, [sp, #8]
|
||||
// CHECK-NEXT: str lr, [sp, #-32]!
|
||||
// CHECK-NEXT: end
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: func15
|
||||
// CHECK-NEXT: Fragment: No
|
||||
// CHECK-NEXT: FunctionLength: 20
|
||||
// CHECK-NEXT: RegF: 0
|
||||
// CHECK-NEXT: RegI: 0
|
||||
// CHECK-NEXT: HomedParameters: No
|
||||
// CHECK-NEXT: CR: 3
|
||||
// CHECK-NEXT: FrameSize: 32
|
||||
// CHECK-NEXT: Prologue [
|
||||
// CHECK-NEXT: mov x29, sp
|
||||
// CHECK-NEXT: stp x29, lr, [sp, #-32]!
|
||||
// CHECK-NEXT: end
|
||||
// CHECK-NEXT: ]
|
||||
// CHECK-NEXT: }
|
||||
// CHECK: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: nonpacked1
|
||||
// CHECK-NEXT: ExceptionRecord:
|
||||
// CHECK-NEXT: ExceptionData {
|
||||
// CHECK: EpiloguePacked: Yes
|
||||
// CHECK: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: nonpacked2
|
||||
// CHECK-NEXT: ExceptionRecord:
|
||||
// CHECK-NEXT: ExceptionData {
|
||||
// CHECK: EpiloguePacked: Yes
|
||||
// CHECK: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: nonpacked3
|
||||
// CHECK-NEXT: ExceptionRecord:
|
||||
// CHECK-NEXT: ExceptionData {
|
||||
// CHECK: EpiloguePacked: Yes
|
||||
// CHECK: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: nonpacked4
|
||||
// CHECK-NEXT: ExceptionRecord:
|
||||
// CHECK-NEXT: ExceptionData {
|
||||
// CHECK: EpiloguePacked: Yes
|
||||
// CHECK: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: nonpacked5
|
||||
// CHECK-NEXT: ExceptionRecord:
|
||||
// CHECK-NEXT: ExceptionData {
|
||||
// CHECK: EpiloguePacked: Yes
|
||||
// CHECK: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: nonpacked6
|
||||
// CHECK-NEXT: ExceptionRecord:
|
||||
// CHECK-NEXT: ExceptionData {
|
||||
// CHECK: EpiloguePacked: Yes
|
||||
// CHECK: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: nonpacked7
|
||||
// CHECK-NEXT: ExceptionRecord:
|
||||
// CHECK-NEXT: ExceptionData {
|
||||
// CHECK: EpiloguePacked: Yes
|
||||
// CHECK: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: nonpacked8
|
||||
// CHECK-NEXT: ExceptionRecord:
|
||||
// CHECK-NEXT: ExceptionData {
|
||||
// CHECK: EpiloguePacked: Yes
|
||||
// CHECK: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: nonpacked9
|
||||
// CHECK-NEXT: ExceptionRecord:
|
||||
// CHECK-NEXT: ExceptionData {
|
||||
// CHECK: EpiloguePacked: Yes
|
||||
// CHECK: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: nonpacked10
|
||||
// CHECK-NEXT: ExceptionRecord:
|
||||
// CHECK-NEXT: ExceptionData {
|
||||
// CHECK: EpiloguePacked: Yes
|
||||
// CHECK: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: nonpacked11
|
||||
// CHECK-NEXT: ExceptionRecord:
|
||||
// CHECK-NEXT: ExceptionData {
|
||||
// CHECK: EpiloguePacked: Yes
|
||||
// CHECK: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: nonpacked12
|
||||
// CHECK-NEXT: ExceptionRecord:
|
||||
// CHECK-NEXT: ExceptionData {
|
||||
// CHECK: EpiloguePacked: Yes
|
||||
// CHECK: RuntimeFunction {
|
||||
// CHECK-NEXT: Function: nonpacked13
|
||||
// CHECK-NEXT: ExceptionRecord:
|
||||
// CHECK-NEXT: ExceptionData {
|
||||
// CHECK: EpiloguePacked: Yes
|
||||
|
||||
.text
|
||||
func1:
|
||||
.seh_proc func1
|
||||
stp x19, x20, [sp, #-144]!
|
||||
.seh_save_r19r20_x 144
|
||||
stp x21, x22, [sp, #16]
|
||||
.seh_save_regp x21, 16
|
||||
stp x23, x24, [sp, #32]
|
||||
.seh_save_next
|
||||
stp x25, x26, [sp, #48]
|
||||
.seh_save_next
|
||||
stp x27, x28, [sp, #64]
|
||||
.seh_save_next
|
||||
stp d8, d9, [sp, #80]
|
||||
.seh_save_fregp d8, 80
|
||||
stp d10, d11, [sp, #96]
|
||||
.seh_save_fregp d10, 96
|
||||
stp d12, d13, [sp, #112]
|
||||
.seh_save_fregp d12, 112
|
||||
stp d14, d15, [sp, #128]
|
||||
.seh_save_fregp d14, 128
|
||||
sub sp, sp, #16
|
||||
.seh_stackalloc 16
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
add sp, sp, #16
|
||||
.seh_stackalloc 16
|
||||
ldp d14, d15, [sp, #128]
|
||||
.seh_save_fregp d14, 128
|
||||
ldp d12, d13, [sp, #112]
|
||||
.seh_save_fregp d12, 112
|
||||
ldp d10, d11, [sp, #96]
|
||||
.seh_save_fregp d10, 96
|
||||
ldp d8, d9, [sp, #80]
|
||||
.seh_save_fregp d8, 80
|
||||
ldp x27, x28, [sp, #64]
|
||||
.seh_save_next
|
||||
ldp x25, x26, [sp, #48]
|
||||
.seh_save_next
|
||||
ldp x23, x24, [sp, #32]
|
||||
.seh_save_next
|
||||
ldp x21, x22, [sp, #16]
|
||||
.seh_save_next
|
||||
ldp x19, x20, [sp], #144
|
||||
.seh_save_regp_x x19, 144
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
func2:
|
||||
.seh_proc func2
|
||||
stp x19, x20, [sp, #-48]!
|
||||
.seh_save_r19r20_x 48
|
||||
str x21, [sp, #16]
|
||||
.seh_save_reg x21, 16
|
||||
stp d8, d9, [sp, #24]
|
||||
.seh_save_fregp d8, 24
|
||||
str d10, [sp, #40]
|
||||
.seh_save_freg d10, 40
|
||||
sub sp, sp, #0
|
||||
.seh_stackalloc 0
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
add sp, sp, #0
|
||||
.seh_stackalloc 0
|
||||
ldr d10, [sp, #40]
|
||||
.seh_save_freg d10, 40
|
||||
ldp d8, d9, [sp, #24]
|
||||
.seh_save_fregp d8, 24
|
||||
ldr x21, [sp, #16]
|
||||
.seh_save_reg x21, 16
|
||||
ldp x19, x20, [sp], #48
|
||||
.seh_save_r19r20_x 48
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
func3:
|
||||
.seh_proc func3
|
||||
str x19, [sp, #-48]!
|
||||
.seh_save_reg_x x19, 48
|
||||
stp d8, d9, [sp, #8]
|
||||
.seh_save_fregp d8, 8
|
||||
stp d10, d11, [sp, #24]
|
||||
.seh_save_fregp d10, 24
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
ldp d10, d11, [sp, #24]
|
||||
.seh_save_fregp d10, 24
|
||||
ldp d8, d9, [sp, #8]
|
||||
.seh_save_fregp d8, 8
|
||||
ldr x19, [sp], #48
|
||||
.seh_save_reg_x x19, 48
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
func4:
|
||||
.seh_proc func4
|
||||
stp d8, d9, [sp, #-16]!
|
||||
.seh_save_fregp_x d8, 16
|
||||
sub sp, sp, #32
|
||||
.seh_stackalloc 32
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
add sp, sp, #32
|
||||
.seh_stackalloc 32
|
||||
ldp d8, d9, [sp], #16
|
||||
.seh_save_fregp_x d8, 16
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
func5:
|
||||
.seh_proc func5
|
||||
str x19, [sp, #-80]!
|
||||
.seh_save_reg_x x19, 80
|
||||
stp x0, x1, [sp, #8]
|
||||
.seh_nop
|
||||
stp x2, x3, [sp, #24]
|
||||
.seh_nop
|
||||
stp x4, x5, [sp, #40]
|
||||
.seh_nop
|
||||
stp x6, x7, [sp, #56]
|
||||
.seh_nop
|
||||
sub sp, sp, #32
|
||||
.seh_stackalloc 32
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
add sp, sp, #32
|
||||
.seh_stackalloc 32
|
||||
nop
|
||||
.seh_nop
|
||||
nop
|
||||
.seh_nop
|
||||
nop
|
||||
.seh_nop
|
||||
nop
|
||||
.seh_nop
|
||||
ldr x19, [sp], #80
|
||||
.seh_save_reg_x x19, 80
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
func6:
|
||||
.seh_proc func6
|
||||
str lr, [sp, #-16]!
|
||||
.seh_save_reg_x lr, 16
|
||||
sub sp, sp, #16
|
||||
.seh_stackalloc 16
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
add sp, sp, #16
|
||||
.seh_stackalloc 16
|
||||
ldr lr, [sp], #16
|
||||
.seh_save_reg_x lr, 16
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
func7:
|
||||
.seh_proc func7
|
||||
stp x19, x20, [sp, #-32]!
|
||||
.seh_save_r19r20_x 32
|
||||
str lr, [sp, #16]
|
||||
.seh_save_reg lr, 16
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
ldr lr, [sp, #16]
|
||||
.seh_save_reg lr, 16
|
||||
ldp x19, x20, [sp], #32
|
||||
.seh_save_r19r20_x 32
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
func8:
|
||||
.seh_proc func8
|
||||
stp x19, x20, [sp, #-32]!
|
||||
.seh_save_r19r20_x 32
|
||||
stp x21, lr, [sp, #16]
|
||||
.seh_save_lrpair x21, 16
|
||||
sub sp, sp, #16
|
||||
.seh_stackalloc 16
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
add sp, sp, #16
|
||||
.seh_stackalloc 16
|
||||
ldp x21, lr, [sp, #16]
|
||||
.seh_save_lrpair x21, 16
|
||||
ldp x19, x20, [sp], #32
|
||||
.seh_save_r19r20_x 32
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
func9:
|
||||
.seh_proc func9
|
||||
stp x19, x20, [sp, #-16]!
|
||||
.seh_save_r19r20_x 16
|
||||
stp x29, lr, [sp, #-32]!
|
||||
.seh_save_fplr_x 32
|
||||
mov x29, sp
|
||||
.seh_set_fp
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
mov sp, x29
|
||||
.seh_set_fp
|
||||
ldp x29, lr, [sp], #32
|
||||
.seh_save_fplr_x 32
|
||||
ldp x19, x20, [sp], #16
|
||||
.seh_save_r19r20_x 16
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
func10:
|
||||
.seh_proc func10
|
||||
stp x29, lr, [sp, #-32]!
|
||||
.seh_save_fplr_x 32
|
||||
mov x29, sp
|
||||
.seh_set_fp
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
mov sp, x29
|
||||
.seh_set_fp
|
||||
ldp x29, lr, [sp], #32
|
||||
.seh_save_fplr_x 32
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
func11:
|
||||
.seh_proc func11
|
||||
stp x19, x20, [sp, #-16]!
|
||||
.seh_save_r19r20_x 16
|
||||
sub sp, sp, #528
|
||||
.seh_stackalloc 528
|
||||
stp x29, lr, [sp, #0]
|
||||
.seh_save_fplr 0
|
||||
mov x29, sp
|
||||
.seh_set_fp
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
mov sp, x29
|
||||
.seh_set_fp
|
||||
ldp x29, lr, [sp, #0]
|
||||
.seh_save_fplr 0
|
||||
add sp, sp, #528
|
||||
.seh_stackalloc 528
|
||||
ldp x19, x20, [sp], #16
|
||||
.seh_save_r19r20_x 16
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
func12:
|
||||
.seh_proc func12
|
||||
stp x19, x20, [sp, #-16]!
|
||||
.seh_save_r19r20_x 16
|
||||
sub sp, sp, #4080
|
||||
.seh_stackalloc 4080
|
||||
sub sp, sp, #16
|
||||
.seh_stackalloc 16
|
||||
stp x29, lr, [sp, #0]
|
||||
.seh_save_fplr 0
|
||||
mov x29, sp
|
||||
.seh_set_fp
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
mov sp, x29
|
||||
.seh_set_fp
|
||||
ldp x29, lr, [sp, #0]
|
||||
.seh_save_fplr 0
|
||||
add sp, sp, #16
|
||||
.seh_stackalloc 16
|
||||
add sp, sp, #4080
|
||||
.seh_stackalloc 4080
|
||||
ldp x19, x20, [sp], #16
|
||||
.seh_save_r19r20_x 16
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
func13:
|
||||
.seh_proc func13
|
||||
stp x19, x20, [sp, #-16]!
|
||||
.seh_save_r19r20_x 16
|
||||
sub sp, sp, #4080
|
||||
.seh_stackalloc 4080
|
||||
sub sp, sp, #16
|
||||
.seh_stackalloc 16
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
add sp, sp, #16
|
||||
.seh_stackalloc 16
|
||||
add sp, sp, #4080
|
||||
.seh_stackalloc 4080
|
||||
ldp x19, x20, [sp], #16
|
||||
.seh_save_r19r20_x 16
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
func14:
|
||||
.seh_proc func14
|
||||
str lr, [sp, #-32]!
|
||||
.seh_save_reg_x lr, 32
|
||||
stp d8, d9, [sp, #8]
|
||||
.seh_save_fregp d8, 8
|
||||
str d10, [sp, #24]
|
||||
.seh_save_freg d10, 24
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
ldr d10, [sp, #24]
|
||||
.seh_save_freg d10, 24
|
||||
ldp d8, d9, [sp, #8]
|
||||
.seh_save_fregp d8, 8
|
||||
ldr lr, [sp], #32
|
||||
.seh_save_reg_x lr, 32
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
func15:
|
||||
.seh_proc func15
|
||||
stp x29, lr, [sp, #-32]!
|
||||
.seh_save_fplr_x 32
|
||||
mov x29, sp
|
||||
.seh_set_fp
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
// Epilogue missing the .seh_set_fp, but still generating packed info.
|
||||
ldp x29, lr, [sp], #32
|
||||
.seh_save_fplr_x 32
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
nonpacked1:
|
||||
.seh_proc nonpacked1
|
||||
// Can't be packed; can't save integer registers after float registers.
|
||||
stp d8, d9, [sp, #-32]!
|
||||
.seh_save_fregp_x d8, 32
|
||||
stp x19, x20, [sp, #16]!
|
||||
.seh_save_regp x19, 16
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
ldp x19, x20, [sp, #16]
|
||||
.seh_save_regp x19, 16
|
||||
ldp d8, d9, [sp], #32
|
||||
.seh_save_fregp_x d8, 32
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
nonpacked2:
|
||||
.seh_proc nonpacked2
|
||||
// Can't be packed; x21/x22 aren't saved in the expected spot
|
||||
stp x19, x20, [sp, #-48]!
|
||||
.seh_save_r19r20_x 48
|
||||
stp x21, x22, [sp, #32]
|
||||
.seh_save_regp x21, 32
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
ldp x21, x22, [sp, #32]
|
||||
.seh_save_regp x21, 32
|
||||
ldp x19, x20, [sp], #48
|
||||
.seh_save_r19r20_x 48
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
nonpacked3:
|
||||
.seh_proc nonpacked3
|
||||
// Can't be packed; x29/x30 can't be treated as the other saved registers
|
||||
stp x19, x20, [sp, #-96]!
|
||||
.seh_save_r19r20_x 96
|
||||
stp x21, x22, [sp, #16]
|
||||
.seh_save_next
|
||||
stp x23, x24, [sp, #32]
|
||||
.seh_save_next
|
||||
stp x25, x26, [sp, #48]
|
||||
.seh_save_next
|
||||
stp x27, x28, [sp, #64]
|
||||
.seh_save_next
|
||||
stp x29, x30, [sp, #80]
|
||||
.seh_save_next
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
ldp x29, x30, [sp, #80]
|
||||
.seh_save_next
|
||||
ldp x27, x28, [sp, #64]
|
||||
.seh_save_next
|
||||
ldp x25, x26, [sp, #48]
|
||||
.seh_save_next
|
||||
ldp x23, x24, [sp, #32]
|
||||
.seh_save_next
|
||||
ldp x21, x22, [sp, #16]
|
||||
.seh_save_next
|
||||
ldp x19, x20, [sp], #96
|
||||
.seh_save_r19r20_x 96
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
nonpacked4:
|
||||
.seh_proc nonpacked4
|
||||
// Can't be packed; more predecrement for x19/x20 than used for
|
||||
// corresponding RegI/RegF/LR saves
|
||||
stp x19, x20, [sp, #-32]!
|
||||
.seh_save_r19r20_x 32
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
ldp x19, x20, [sp], #32
|
||||
.seh_save_r19r20_x 32
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
nonpacked5:
|
||||
.seh_proc nonpacked5
|
||||
// Can't be packed; can't save LR twice
|
||||
stp x19, x20, [sp, #-32]!
|
||||
.seh_save_r19r20_x 32
|
||||
str lr, [sp, #16]
|
||||
.seh_save_reg lr, 16
|
||||
str lr, [sp, #24]
|
||||
.seh_save_reg lr, 24
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
ldr lr, [sp, #24]
|
||||
.seh_save_reg lr, 24
|
||||
ldr lr, [sp, #16]
|
||||
.seh_save_reg lr, 16
|
||||
ldp x19, x20, [sp], #32
|
||||
.seh_save_r19r20_x 32
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
nonpacked6:
|
||||
.seh_proc nonpacked6
|
||||
// Can't be packed; can't save LR both standalone (CR 1) and as FPLR (CR 3)
|
||||
stp x19, x20, [sp, #-32]!
|
||||
.seh_save_r19r20_x 32
|
||||
str lr, [sp, #16]
|
||||
.seh_save_reg lr, 16
|
||||
stp x29, lr, [sp, #-16]!
|
||||
.seh_save_fplr_x 16
|
||||
mov x29, sp
|
||||
.seh_set_fp
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
mov sp, x29
|
||||
.seh_set_fp
|
||||
ldp x29, lr, [sp], #32
|
||||
.seh_save_fplr_x 16
|
||||
ldr lr, [sp, #16]
|
||||
.seh_save_reg lr, 16
|
||||
ldp x19, x20, [sp], #32
|
||||
.seh_save_r19r20_x 32
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
nonpacked7:
|
||||
.seh_proc nonpacked7
|
||||
// Can't be packed; too many saved FP regs
|
||||
stp d8, d9, [sp, #-80]!
|
||||
.seh_save_fregp_x d8, 80
|
||||
stp d10, d11, [sp, #16]
|
||||
.seh_save_fregp d10, 16
|
||||
stp d12, d13, [sp, #32]
|
||||
.seh_save_fregp d12, 32
|
||||
stp d14, d15, [sp, #48]
|
||||
.seh_save_fregp d14, 48
|
||||
stp d16, d17, [sp, #64]
|
||||
.seh_save_next
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
ldp d16, d17, [sp, #64]
|
||||
.seh_save_next
|
||||
ldp d14, d15, [sp, #48]
|
||||
.seh_save_fregp d14, 48
|
||||
ldp d12, d13, [sp, #32]
|
||||
.seh_save_fregp d12, 32
|
||||
ldp d10, d11, [sp, #16]
|
||||
.seh_save_fregp d10, 16
|
||||
ldp d8, d9, [sp], #80
|
||||
.seh_save_fregp_x d8, 80
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
nonpacked8:
|
||||
.seh_proc nonpacked8
|
||||
// Can't be packed; Can't handle only a single FP reg
|
||||
str d8, [sp, #-16]!
|
||||
.seh_save_freg_x d8, 16
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
ldr d8, [sp], #16
|
||||
.seh_save_freg_x d8, 16
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
nonpacked9:
|
||||
.seh_proc nonpacked9
|
||||
// Can't be packed; can't have a separate stack adjustment with save_fplr_x
|
||||
sub sp, sp, #32
|
||||
.seh_stackalloc 32
|
||||
stp x29, lr, [sp, #-16]!
|
||||
.seh_save_fplr_x 16
|
||||
mov x29, sp
|
||||
.seh_set_fp
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
mov sp, x29
|
||||
.seh_set_fp
|
||||
ldp x29, lr, [sp], #32
|
||||
.seh_save_fplr_x 16
|
||||
add sp, sp, #32
|
||||
.seh_stackalloc 32
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
nonpacked10:
|
||||
.seh_proc nonpacked10
|
||||
// Can't be packed; wrong predecrement
|
||||
stp x19, x20, [sp, #-16]!
|
||||
.seh_save_r19r20_x 16
|
||||
stp x21, x22, [sp, #16]
|
||||
.seh_save_next
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
ldp x21, x22, [sp, #16]
|
||||
.seh_save_next
|
||||
ldp x19, x20, [sp], #16
|
||||
.seh_save_r19r20_x 16
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
nonpacked11:
|
||||
.seh_proc nonpacked11
|
||||
// Can't be packed; too big stack allocation
|
||||
sub sp, sp, #4080
|
||||
.seh_stackalloc 4080
|
||||
sub sp, sp, #8192
|
||||
.seh_stackalloc 8192
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
add sp, sp, #8192
|
||||
.seh_stackalloc 8192
|
||||
add sp, sp, #4080
|
||||
.seh_stackalloc 4080
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
nonpacked12:
|
||||
.seh_proc nonpacked12
|
||||
// Can't be packed; missing .seh_set_fp
|
||||
stp x29, lr, [sp, #-32]!
|
||||
.seh_save_fplr_x 32
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
ldp x29, lr, [sp], #32
|
||||
.seh_save_fplr_x 32
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endproc
|
||||
|
||||
nonpacked13:
|
||||
.seh_proc nonpacked13
|
||||
// Can't be packed; not doing a packed info if .seh_handlerdata is used
|
||||
sub sp, sp, #16
|
||||
.seh_stackalloc 16
|
||||
.seh_endprologue
|
||||
nop
|
||||
.seh_startepilogue
|
||||
add sp, sp, #16
|
||||
.seh_stackalloc 16
|
||||
.seh_endepilogue
|
||||
ret
|
||||
.seh_endfunclet
|
||||
.seh_handlerdata
|
||||
.long 0
|
||||
.text
|
||||
.seh_endproc
|
Loading…
Reference in New Issue