aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Target/TargetAsmInfo.h12
-rw-r--r--include/llvm/Target/TargetFrameLowering.h9
-rw-r--r--lib/MC/MCDwarf.cpp14
-rw-r--r--lib/Target/TargetAsmInfo.cpp7
-rw-r--r--lib/Target/X86/X86FrameLowering.cpp98
-rw-r--r--lib/Target/X86/X86FrameLowering.h4
6 files changed, 130 insertions, 14 deletions
diff --git a/include/llvm/Target/TargetAsmInfo.h b/include/llvm/Target/TargetAsmInfo.h
index 9beff25bcf..cdd1672be6 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<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);
- }
};
}
diff --git a/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h
index e104b1663f..70cecbd37f 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 <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
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp
index cbdf410f21..bc900ca6e9 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<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,
diff --git a/lib/Target/TargetAsmInfo.cpp b/lib/Target/TargetAsmInfo.cpp
index 6fa5420120..475a942da0 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 cd4e954b0a..08c381f13a 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<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;
+}
diff --git a/lib/Target/X86/X86FrameLowering.h b/lib/Target/X86/X86FrameLowering.h
index d71108cd05..f2b8dab6a5 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<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