Add a target hook to encode the compact unwind information.
authorBill Wendling <isanbard@gmail.com>
Thu, 7 Jul 2011 00:54:13 +0000 (00:54 +0000)
committerBill Wendling <isanbard@gmail.com>
Thu, 7 Jul 2011 00:54:13 +0000 (00:54 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@134577 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/TargetAsmInfo.h
include/llvm/Target/TargetFrameLowering.h
lib/MC/MCDwarf.cpp
lib/Target/TargetAsmInfo.cpp
lib/Target/X86/X86FrameLowering.cpp
lib/Target/X86/X86FrameLowering.h

index 9beff25bcfebd39362697584e8f2f68b27b1b162..cdd1672be6f8c7f80ab849f9bd49806394575276 100644 (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);
-  }
 };
 
 }
index e104b1663fdd72225c0cfbee31736f557752fcee..70cecbd37fb4366f6cd5a6969c9fe4f9ad1cecee 100644 (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
index cbdf410f2184e53647ac27a0fc5d320a693952e3..bc900ca6e949d3c00d16a01a6c14cddae47e6df0 100644 (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,
index 6fa5420120f517ef042d85b63792079a7548b4f7..475a942da059540a45418584f0760e1e328f88fc 100644 (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);
 }
index cd4e954b0a5147a9baa632032531d77a4a6bfbeb..08c381f13a37d31f66db3639ad3adb7545b65286 100644 (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;
+}
index d71108cd05862b7cb9606c43926e8f60bb300ccf..f2b8dab6a5a750c844b7d94931c596df2b785514 100644 (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