mirror of
https://github.com/RPCS3/llvm.git
synced 2025-01-09 21:50:50 +00:00
Add code to handle a "frameless" unwind stack.
The frameless unwind stack has a special encoding, the algorithm for which is in "permuteEncode". git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@135103 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
6f9f884502
commit
efe2a6557d
@ -1031,13 +1031,55 @@ X86FrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t permuteEncode(unsigned SavedCount, unsigned Registers[6]) {
|
||||||
|
uint32_t RenumRegs[6];
|
||||||
|
for (int i = 6 - SavedCount; i < 6; ++i) {
|
||||||
|
int countless = 0;
|
||||||
|
for (int j = 6 - SavedCount; j < i; ++j)
|
||||||
|
if (Registers[j] < Registers[i])
|
||||||
|
++countless;
|
||||||
|
|
||||||
|
RenumRegs[i] = Registers[i] - countless - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t permutationEncoding = 0;
|
||||||
|
switch (SavedCount) {
|
||||||
|
case 6:
|
||||||
|
permutationEncoding |= 120 * RenumRegs[0] + 24 * RenumRegs[1]
|
||||||
|
+ 6 * RenumRegs[2] + 2 * RenumRegs[3]
|
||||||
|
+ RenumRegs[4];
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
permutationEncoding |= 120 * RenumRegs[1] + 24 * RenumRegs[2]
|
||||||
|
+ 6 * RenumRegs[3] + 2 * RenumRegs[4]
|
||||||
|
+ RenumRegs[5];
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
permutationEncoding |= 60 * RenumRegs[2] + 12 * RenumRegs[3]
|
||||||
|
+ 3 * RenumRegs[4] + RenumRegs[5];
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
permutationEncoding |= 20 * RenumRegs[3] + 4 * RenumRegs[4]
|
||||||
|
+ RenumRegs[5];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
permutationEncoding |= 5 * RenumRegs[4] + RenumRegs[5];
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
permutationEncoding |= RenumRegs[5];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return permutationEncoding;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t X86FrameLowering::
|
uint32_t X86FrameLowering::
|
||||||
getCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs,
|
getCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs,
|
||||||
int DataAlignmentFactor, bool IsEH) const {
|
int DataAlignmentFactor, bool IsEH) const {
|
||||||
uint32_t Encoding = 0;
|
uint32_t Encoding = 0;
|
||||||
int CFAOffset = 0;
|
int CFAOffset = 0;
|
||||||
const TargetRegisterInfo *TRI = TM.getRegisterInfo();
|
const TargetRegisterInfo *TRI = TM.getRegisterInfo();
|
||||||
SmallVector<unsigned, 8> SavedRegs;
|
unsigned SavedRegs[6] = { 0, 0, 0, 0, 0, 0 };
|
||||||
|
unsigned SavedRegIdx = 0;
|
||||||
int FramePointerReg = -1;
|
int FramePointerReg = -1;
|
||||||
|
|
||||||
for (ArrayRef<MCCFIInstruction>::const_iterator
|
for (ArrayRef<MCCFIInstruction>::const_iterator
|
||||||
@ -1102,9 +1144,10 @@ getCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs,
|
|||||||
return 0;
|
return 0;
|
||||||
} else if (Reg < 64) {
|
} else if (Reg < 64) {
|
||||||
// DW_CFA_offset + Reg
|
// DW_CFA_offset + Reg
|
||||||
|
if (SavedRegIdx >= 6) return 0;
|
||||||
int CURegNum = TRI->getCompactUnwindRegNum(Reg, IsEH);
|
int CURegNum = TRI->getCompactUnwindRegNum(Reg, IsEH);
|
||||||
if (CURegNum == -1) return 0;
|
if (CURegNum == -1) return 0;
|
||||||
SavedRegs.push_back(CURegNum);
|
SavedRegs[SavedRegIdx++] = CURegNum;
|
||||||
} else {
|
} else {
|
||||||
// FIXME: Handle?
|
// FIXME: Handle?
|
||||||
// DW_CFA_offset_extended
|
// DW_CFA_offset_extended
|
||||||
@ -1112,6 +1155,9 @@ getCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bail if there are too many registers to encode.
|
||||||
|
if (SavedRegIdx > 6) return 0;
|
||||||
|
|
||||||
// Check if the offset is too big.
|
// Check if the offset is too big.
|
||||||
CFAOffset /= 4;
|
CFAOffset /= 4;
|
||||||
if ((CFAOffset & 0xFF) != CFAOffset)
|
if ((CFAOffset & 0xFF) != CFAOffset)
|
||||||
@ -1119,20 +1165,16 @@ getCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs,
|
|||||||
Encoding |= (CFAOffset & 0xFF) << 16; // Size encoding.
|
Encoding |= (CFAOffset & 0xFF) << 16; // Size encoding.
|
||||||
|
|
||||||
if (FramePointerReg != -1) {
|
if (FramePointerReg != -1) {
|
||||||
// Bail if there are too many registers to encode.
|
Encoding |= 0x01000000; // EBP/RBP Unwind Frame
|
||||||
if (SavedRegs.size() - 1 > 5) return 0;
|
for (unsigned I = 0; I != SavedRegIdx; ++I) {
|
||||||
|
unsigned Reg = SavedRegs[I];
|
||||||
Encoding |= 1 << 24; // EBP/RBP Unwind Frame
|
|
||||||
|
|
||||||
unsigned Idx = 0;
|
|
||||||
for (SmallVectorImpl<unsigned>::iterator
|
|
||||||
I = SavedRegs.begin(), E = SavedRegs.end(); I != E; ++I) {
|
|
||||||
unsigned Reg = *I;
|
|
||||||
if (Reg == unsigned(FramePointerReg)) continue;
|
if (Reg == unsigned(FramePointerReg)) continue;
|
||||||
Encoding |= (Reg & 0x7) << (Idx++ * 3); // Register encoding
|
Encoding |= (Reg & 0x7) << (I * 3); // Register encoding
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// FIXME: Handle frameless version!
|
Encoding |= 0x02000000; // Frameless unwind with small stack
|
||||||
|
Encoding |= (SavedRegIdx & 0x7) << 10;
|
||||||
|
Encoding |= permuteEncode(SavedRegIdx, SavedRegs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Encoding;
|
return Encoding;
|
||||||
|
Loading…
Reference in New Issue
Block a user