Add a target hook to encode the compact unwind information.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134577 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bill Wendling 2011-07-07 00:54:13 +00:00
parent e727d67c58
commit 6a6b8c3e96
6 changed files with 130 additions and 14 deletions

View File

@ -30,8 +30,9 @@ class TargetAsmInfo {
unsigned PointerSize;
bool IsLittleEndian;
TargetFrameLowering::StackDirection StackDir;
const TargetRegisterInfo *TRI;
std::vector<MachineMove> InitialFrameState;
const TargetRegisterInfo *TRI;
const TargetFrameLowering *TFI;
const TargetLoweringObjectFile *TLOF;
public:
@ -83,6 +84,11 @@ public:
return TLOF->isFunctionEHFrameSymbolPrivate();
}
int getCompactUnwindEncoding(const std::vector<MCCFIInstruction> &Instrs,
int DataAlignmentFactor, bool IsEH) const {
return TFI->getCompactUnwindEncoding(Instrs, DataAlignmentFactor, IsEH);
}
const unsigned *getCalleeSavedRegs(MachineFunction *MF = 0) const {
return TRI->getCalleeSavedRegs(MF);
}
@ -106,10 +112,6 @@ public:
int getSEHRegNum(unsigned RegNum) const {
return TRI->getSEHRegNum(RegNum);
}
int getCompactUnwindRegNum(unsigned RegNum, bool isEH) const {
return TRI->getCompactUnwindRegNum(RegNum, isEH);
}
};
}

View File

@ -14,6 +14,7 @@
#ifndef LLVM_TARGET_TARGETFRAMELOWERING_H
#define LLVM_TARGET_TARGETFRAMELOWERING_H
#include "llvm/MC/MCDwarf.h"
#include "llvm/CodeGen/MachineBasicBlock.h"
#include <utility>
@ -189,6 +190,14 @@ public:
///
virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
}
/// getCompactUnwindEncoding - Get the compact unwind encoding for the
/// function. Return 0 if the compact unwind isn't available.
virtual uint32_t getCompactUnwindEncoding(const std::vector<MCCFIInstruction>&,
int /*DataAlignmentFactor*/,
bool /*IsEH*/) const {
return 0;
}
};
} // End llvm namespace

View File

@ -499,7 +499,6 @@ namespace {
bool UsingCFI;
bool IsEH;
const MCSymbol *SectionStart;
public:
FrameEmitterImpl(bool usingCFI, bool isEH, const MCSymbol *sectionStart) :
CFAOffset(0), CIENum(0), UsingCFI(usingCFI), IsEH(isEH),
@ -714,6 +713,11 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer,
// .quad __gxx_personality
// .quad except_tab1
uint32_t Encoding =
TAI.getCompactUnwindEncoding(Frame.Instructions,
getDataAlignmentFactor(Streamer), IsEH);
if (!Encoding) return false;
Streamer.SwitchSection(TAI.getCompactUnwindSection());
// Range Start
@ -728,12 +732,10 @@ bool FrameEmitterImpl::EmitCompactUnwind(MCStreamer &Streamer,
if (VerboseAsm) Streamer.AddComment("Range Length");
Streamer.EmitAbsValue(Range, 4);
// FIXME:
// Compact Encoding
const std::vector<MachineMove> &Moves = TAI.getInitialFrameState();
uint32_t Encoding = 0;
Size = getSizeForEncoding(Streamer, dwarf::DW_EH_PE_udata4);
if (VerboseAsm) Streamer.AddComment("Compact Unwind Encoding");
if (VerboseAsm) Streamer.AddComment(Twine("Compact Unwind Encoding: 0x") +
Twine(llvm::utohexstr(Encoding)));
Streamer.EmitIntValue(Encoding, Size);
// Personality Function
@ -774,7 +776,7 @@ const MCSymbol &FrameEmitterImpl::EmitCIE(MCStreamer &streamer,
streamer.EmitLabel(sectionStart);
CIENum++;
MCSymbol *sectionEnd = streamer.getContext().CreateTempSymbol();
MCSymbol *sectionEnd = context.CreateTempSymbol();
// Length
const MCExpr *Length = MakeStartMinusEndExpr(streamer, *sectionStart,

View File

@ -20,8 +20,9 @@ TargetAsmInfo::TargetAsmInfo(const TargetMachine &TM) {
const TargetData &TD = *TM.getTargetData();
IsLittleEndian = TD.isLittleEndian();
PointerSize = TD.getPointerSize();
const TargetFrameLowering &TFI = *TM.getFrameLowering();
StackDir = TFI.getStackGrowthDirection();
TFI = TM.getFrameLowering();
StackDir = TFI->getStackGrowthDirection();
TRI = TM.getRegisterInfo();
TFI.getInitialFrameState(InitialFrameState);
TFI->getInitialFrameState(InitialFrameState);
}

View File

@ -23,6 +23,7 @@
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Support/CommandLine.h"
@ -1029,3 +1030,100 @@ X86FrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
FrameIdx = 0;
}
}
uint32_t X86FrameLowering::
getCompactUnwindEncoding(const std::vector<MCCFIInstruction> &Instrs,
int DataAlignmentFactor, bool IsEH) const {
uint32_t Encoding = 0;
int CFAOffset = 0;
const TargetRegisterInfo *TRI = TM.getRegisterInfo();
SmallVector<unsigned, 8> SavedRegs;
int FramePointerReg = -1;
for (std::vector<MCCFIInstruction>::const_iterator
I = Instrs.begin(), E = Instrs.end(); I != E; ++I) {
const MCCFIInstruction &Inst = *I;
MCSymbol *Label = Inst.getLabel();
// Ignore invalid labels.
if (Label && !Label->isDefined()) continue;
unsigned Operation = Inst.getOperation();
if (Operation != MCCFIInstruction::Move &&
Operation != MCCFIInstruction::RelMove)
// FIXME: We can't handle this frame just yet.
return 0;
const MachineLocation &Dst = Inst.getDestination();
const MachineLocation &Src = Inst.getSource();
const bool IsRelative = (Operation == MCCFIInstruction::RelMove);
if (Dst.isReg() && Dst.getReg() == MachineLocation::VirtualFP) {
if (Src.getReg() == MachineLocation::VirtualFP) {
// DW_CFA_def_cfa_offset
if (IsRelative)
CFAOffset += Src.getOffset();
else
CFAOffset = -Src.getOffset();
} // else DW_CFA_def_cfa
continue;
}
if (Src.isReg() && Src.getReg() == MachineLocation::VirtualFP) {
// DW_CFA_def_cfa_register
FramePointerReg = Dst.getReg();
continue;
}
unsigned Reg = Src.getReg();
int Offset = Dst.getOffset();
if (IsRelative)
Offset -= CFAOffset;
Offset /= DataAlignmentFactor;
if (Offset < 0) {
// FIXME: Handle?
// DW_CFA_offset_extended_sf
return 0;
} else if (Reg < 64) {
// DW_CFA_offset + Reg
SavedRegs.push_back(Reg);
} else {
// FIXME: Handle?
// DW_CFA_offset_extended
return 0;
}
}
CFAOffset /= 4;
// Check if the offset is too big.
if ((CFAOffset & 0xFF) != CFAOffset)
return 0;
// Bail if there are too many registers to encode.
unsigned NumRegsToEncode = SavedRegs.size() - (FramePointerReg != -1 ? 1 : 0);
if (NumRegsToEncode > 5) return 0;
if (TRI->getLLVMRegNum(FramePointerReg, IsEH) != X86::EBP &&
TRI->getLLVMRegNum(FramePointerReg, IsEH) != X86::RBP)
// FIXME: Handle frameless version!
return 0;
Encoding |= 1 << 24;
Encoding |= (CFAOffset & 0xFF) << 16;
unsigned Idx = 0;
for (SmallVectorImpl<unsigned>::iterator
I = SavedRegs.begin(), E = SavedRegs.end(); I != E; ++I) {
if (*I == unsigned(FramePointerReg)) continue;
int CURegNum = TRI->getCompactUnwindRegNum(*I, IsEH);
if (CURegNum == -1) return 0;
Encoding |= (CURegNum & 0x7) << (Idx++ * 3);
}
return Encoding;
}

View File

@ -15,6 +15,7 @@
#define X86_FRAMELOWERING_H
#include "X86Subtarget.h"
#include "llvm/MC/MCDwarf.h"
#include "llvm/Target/TargetFrameLowering.h"
namespace llvm {
@ -58,6 +59,9 @@ public:
void getInitialFrameState(std::vector<MachineMove> &Moves) const;
int getFrameIndexOffset(const MachineFunction &MF, int FI) const;
uint32_t getCompactUnwindEncoding(const std::vector<MCCFIInstruction> &Instrs,
int DataAlignmentFactor, bool IsEH) const;
};
} // End llvm namespace