aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/X86/X86FrameLowering.cpp
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2011-07-13 23:03:31 +0000
committerBill Wendling <isanbard@gmail.com>2011-07-13 23:03:31 +0000
commitefe2a6557d3152a817cb097e9bc327186975ace2 (patch)
tree91e596d353567cf4dc1f4e1ff9001b22187203e0 /lib/Target/X86/X86FrameLowering.cpp
parent6f9f8845028d4d3b96c33417398034a71137d867 (diff)
downloadexternal_llvm-efe2a6557d3152a817cb097e9bc327186975ace2.zip
external_llvm-efe2a6557d3152a817cb097e9bc327186975ace2.tar.gz
external_llvm-efe2a6557d3152a817cb097e9bc327186975ace2.tar.bz2
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
Diffstat (limited to 'lib/Target/X86/X86FrameLowering.cpp')
-rw-r--r--lib/Target/X86/X86FrameLowering.cpp68
1 files changed, 55 insertions, 13 deletions
diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp
index f180cc0..af1595e 100644
--- a/lib/Target/X86/X86FrameLowering.cpp
+++ b/lib/Target/X86/X86FrameLowering.cpp
@@ -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::
getCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs,
int DataAlignmentFactor, bool IsEH) const {
uint32_t Encoding = 0;
int CFAOffset = 0;
const TargetRegisterInfo *TRI = TM.getRegisterInfo();
- SmallVector<unsigned, 8> SavedRegs;
+ unsigned SavedRegs[6] = { 0, 0, 0, 0, 0, 0 };
+ unsigned SavedRegIdx = 0;
int FramePointerReg = -1;
for (ArrayRef<MCCFIInstruction>::const_iterator
@@ -1102,9 +1144,10 @@ getCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs,
return 0;
} else if (Reg < 64) {
// DW_CFA_offset + Reg
+ if (SavedRegIdx >= 6) return 0;
int CURegNum = TRI->getCompactUnwindRegNum(Reg, IsEH);
if (CURegNum == -1) return 0;
- SavedRegs.push_back(CURegNum);
+ SavedRegs[SavedRegIdx++] = CURegNum;
} else {
// FIXME: Handle?
// 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.
CFAOffset /= 4;
if ((CFAOffset & 0xFF) != CFAOffset)
@@ -1119,20 +1165,16 @@ getCompactUnwindEncoding(ArrayRef<MCCFIInstruction> Instrs,
Encoding |= (CFAOffset & 0xFF) << 16; // Size encoding.
if (FramePointerReg != -1) {
- // Bail if there are too many registers to encode.
- if (SavedRegs.size() - 1 > 5) return 0;
-
- 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;
+ Encoding |= 0x01000000; // EBP/RBP Unwind Frame
+ for (unsigned I = 0; I != SavedRegIdx; ++I) {
+ unsigned Reg = SavedRegs[I];
if (Reg == unsigned(FramePointerReg)) continue;
- Encoding |= (Reg & 0x7) << (Idx++ * 3); // Register encoding
+ Encoding |= (Reg & 0x7) << (I * 3); // Register encoding
}
} else {
- // FIXME: Handle frameless version!
+ Encoding |= 0x02000000; // Frameless unwind with small stack
+ Encoding |= (SavedRegIdx & 0x7) << 10;
+ Encoding |= permuteEncode(SavedRegIdx, SavedRegs);
}
return Encoding;