From: Bill Wendling Date: Thu, 7 Jul 2011 00:54:13 +0000 (+0000) Subject: Add a target hook to encode the compact unwind information. X-Git-Url: http://plrg.eecs.uci.edu/git/?a=commitdiff_plain;h=6a6b8c3e96b9e1ca7092eafd0cfb219cbbfbdfc4;p=oota-llvm.git 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 --- diff --git a/include/llvm/Target/TargetAsmInfo.h b/include/llvm/Target/TargetAsmInfo.h index 9beff25bcfe..cdd1672be6f 100644 --- a/include/llvm/Target/TargetAsmInfo.h +++ b/include/llvm/Target/TargetAsmInfo.h @@ -30,8 +30,9 @@ class TargetAsmInfo { unsigned PointerSize; bool IsLittleEndian; TargetFrameLowering::StackDirection StackDir; - const TargetRegisterInfo *TRI; std::vector InitialFrameState; + const TargetRegisterInfo *TRI; + const TargetFrameLowering *TFI; const TargetLoweringObjectFile *TLOF; public: @@ -83,6 +84,11 @@ public: return TLOF->isFunctionEHFrameSymbolPrivate(); } + int getCompactUnwindEncoding(const std::vector &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); - } }; } diff --git a/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h index e104b1663fd..70cecbd37fb 100644 --- a/include/llvm/Target/TargetFrameLowering.h +++ b/include/llvm/Target/TargetFrameLowering.h @@ -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 @@ -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&, + int /*DataAlignmentFactor*/, + bool /*IsEH*/) const { + return 0; + } }; } // End llvm namespace diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp index cbdf410f218..bc900ca6e94 100644 --- a/lib/MC/MCDwarf.cpp +++ b/lib/MC/MCDwarf.cpp @@ -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 &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, diff --git a/lib/Target/TargetAsmInfo.cpp b/lib/Target/TargetAsmInfo.cpp index 6fa5420120f..475a942da05 100644 --- a/lib/Target/TargetAsmInfo.cpp +++ b/lib/Target/TargetAsmInfo.cpp @@ -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); } diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp index cd4e954b0a5..08c381f13a3 100644 --- a/lib/Target/X86/X86FrameLowering.cpp +++ b/lib/Target/X86/X86FrameLowering.cpp @@ -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 &Instrs, + int DataAlignmentFactor, bool IsEH) const { + uint32_t Encoding = 0; + int CFAOffset = 0; + const TargetRegisterInfo *TRI = TM.getRegisterInfo(); + SmallVector SavedRegs; + int FramePointerReg = -1; + + for (std::vector::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::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; +} diff --git a/lib/Target/X86/X86FrameLowering.h b/lib/Target/X86/X86FrameLowering.h index d71108cd058..f2b8dab6a5a 100644 --- a/lib/Target/X86/X86FrameLowering.h +++ b/lib/Target/X86/X86FrameLowering.h @@ -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 &Moves) const; int getFrameIndexOffset(const MachineFunction &MF, int FI) const; + + uint32_t getCompactUnwindEncoding(const std::vector &Instrs, + int DataAlignmentFactor, bool IsEH) const; }; } // End llvm namespace