mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-08-17 05:29:24 +00:00
Long live the exception handling!
This patch fills the last necessary bits to enable exceptions handling in LLVM. Currently only on x86-32/linux. In fact, this patch adds necessary intrinsics (and their lowering) which represent really weird target-specific gcc builtins used inside unwinder. After corresponding llvm-gcc patch will land (easy) exceptions should be more or less workable. However, exceptions handling support should not be thought as 'finished': I expect many small and not so small glitches everywhere. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@39855 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
a73d11efd4
commit
2365f51ed0
@ -1030,6 +1030,9 @@ private:
|
||||
// Personalities - Vector of all personality functions ever seen. Used to emit
|
||||
// common EH frames.
|
||||
std::vector<Function *> Personalities;
|
||||
|
||||
bool CallsEHReturn;
|
||||
bool CallsUnwindInit;
|
||||
public:
|
||||
static char ID; // Pass identification, replacement for typeid
|
||||
|
||||
@ -1072,6 +1075,12 @@ public:
|
||||
/// needsFrameInfo - Returns true if we need to gather callee-saved register
|
||||
/// move info for the frame.
|
||||
bool needsFrameInfo() const;
|
||||
|
||||
bool callsEHReturn() const { return CallsEHReturn; }
|
||||
void setCallsEHReturn(bool b) { CallsEHReturn = b; }
|
||||
|
||||
bool callsUnwindInit() const { return CallsUnwindInit; }
|
||||
void setCallsUnwindInit(bool b) { CallsUnwindInit = b; }
|
||||
|
||||
/// NextLabelID - Return the next unique label id.
|
||||
///
|
||||
|
@ -110,6 +110,11 @@ namespace ISD {
|
||||
// to the current function's frame or return address, an index of one to the
|
||||
// parent's frame or return address, and so on.
|
||||
FRAMEADDR, RETURNADDR,
|
||||
|
||||
// FRAME_TO_ARGS_OFFSET - This node represents offset from frame pointer to
|
||||
// first (possible) on-stack argument. This is needed for correct stack
|
||||
// adjustment during unwind.
|
||||
FRAME_TO_ARGS_OFFSET,
|
||||
|
||||
// RESULT, OUTCHAIN = EXCEPTIONADDR(INCHAIN) - This node represents the
|
||||
// address of the exception block on entry to an landing pad block.
|
||||
@ -119,6 +124,12 @@ namespace ISD {
|
||||
// the selection index of the exception thrown.
|
||||
EHSELECTION,
|
||||
|
||||
// OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER) - This node represents
|
||||
// 'eh_return' gcc dwarf builtin, which is used to return from
|
||||
// exception. The general meaning is: adjust stack by OFFSET and pass
|
||||
// execution to HANDLER. Many platform-related details also :)
|
||||
EH_RETURN,
|
||||
|
||||
// TargetConstant* - Like Constant*, but the DAG does not do any folding or
|
||||
// simplification of the constant.
|
||||
TargetConstant,
|
||||
|
@ -233,6 +233,14 @@ def int_eh_selector : Intrinsic<[llvm_i32_ty, llvm_ptr_ty, llvm_ptr_ty,
|
||||
llvm_vararg_ty]>;
|
||||
def int_eh_typeid_for : Intrinsic<[llvm_i32_ty, llvm_ptr_ty]>;
|
||||
|
||||
def int_eh_return : Intrinsic<[llvm_void_ty, llvm_i32_ty, llvm_ptr_ty]>,
|
||||
GCCBuiltin<"__builtin_eh_return">;
|
||||
|
||||
def int_eh_unwind_init: Intrinsic<[llvm_void_ty]>,
|
||||
GCCBuiltin<"__builtin_unwind_init">;
|
||||
|
||||
def int_eh_dwarf_cfa : Intrinsic<[llvm_ptr_ty, llvm_i32_ty]>;
|
||||
|
||||
//===---------------- Generic Variable Attribute Intrinsics----------------===//
|
||||
//
|
||||
def int_var_annotation : Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_ptr_ty,
|
||||
|
@ -396,12 +396,14 @@ public:
|
||||
/// callee saved registers on this target. The register should be in the
|
||||
/// order of desired callee-save stack frame offset. The first register is
|
||||
/// closed to the incoming stack pointer if stack grows down, and vice versa.
|
||||
virtual const unsigned* getCalleeSavedRegs() const = 0;
|
||||
virtual const unsigned* getCalleeSavedRegs(const MachineFunction *MF = 0)
|
||||
const = 0;
|
||||
|
||||
/// getCalleeSavedRegClasses - Return a null-terminated list of the preferred
|
||||
/// register classes to spill each callee saved register with. The order and
|
||||
/// length of this list match the getCalleeSaveRegs() list.
|
||||
virtual const TargetRegisterClass* const *getCalleeSavedRegClasses() const =0;
|
||||
virtual const TargetRegisterClass* const *getCalleeSavedRegClasses(
|
||||
const MachineFunction *MF) const =0;
|
||||
|
||||
/// getReservedRegs - Returns a bitset indexed by physical register number
|
||||
/// indicating if a register is a special register that has particular uses and
|
||||
|
@ -1476,6 +1476,8 @@ MachineModuleInfo::MachineModuleInfo()
|
||||
, FrameMoves()
|
||||
, LandingPads()
|
||||
, Personalities()
|
||||
, CallsEHReturn(0)
|
||||
, CallsUnwindInit(0)
|
||||
{
|
||||
// Always emit "no personality" info
|
||||
Personalities.push_back(NULL);
|
||||
@ -1523,6 +1525,8 @@ void MachineModuleInfo::EndFunction() {
|
||||
TypeInfos.clear();
|
||||
FilterIds.clear();
|
||||
FilterEnds.clear();
|
||||
CallsEHReturn = 0;
|
||||
CallsUnwindInit = 0;
|
||||
}
|
||||
|
||||
/// getDescFor - Convert a Value to a debug information descriptor.
|
||||
|
@ -121,7 +121,7 @@ void PEI::calculateCalleeSavedRegisters(MachineFunction &Fn) {
|
||||
const TargetFrameInfo *TFI = Fn.getTarget().getFrameInfo();
|
||||
|
||||
// Get the callee saved register list...
|
||||
const unsigned *CSRegs = RegInfo->getCalleeSavedRegs();
|
||||
const unsigned *CSRegs = RegInfo->getCalleeSavedRegs(&Fn);
|
||||
|
||||
// Get the function call frame set-up and tear-down instruction opcode
|
||||
int FrameSetupOpcode = RegInfo->getCallFrameSetupOpcode();
|
||||
@ -170,7 +170,7 @@ void PEI::calculateCalleeSavedRegisters(MachineFunction &Fn) {
|
||||
// function, thus needing to be saved and restored in the prolog/epilog.
|
||||
//
|
||||
const TargetRegisterClass* const *CSRegClasses =
|
||||
RegInfo->getCalleeSavedRegClasses();
|
||||
RegInfo->getCalleeSavedRegClasses(&Fn);
|
||||
std::vector<CalleeSavedInfo> CSI;
|
||||
for (unsigned i = 0; CSRegs[i]; ++i) {
|
||||
unsigned Reg = CSRegs[i];
|
||||
|
@ -640,6 +640,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
||||
break;
|
||||
case ISD::FRAMEADDR:
|
||||
case ISD::RETURNADDR:
|
||||
case ISD::FRAME_TO_ARGS_OFFSET:
|
||||
// The only option for these nodes is to custom lower them. If the target
|
||||
// does not custom lower them, then return zero.
|
||||
Tmp1 = TLI.LowerOperation(Op, DAG);
|
||||
@ -695,6 +696,21 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ISD::EH_RETURN:
|
||||
MVT::ValueType VT = Node->getValueType(0);
|
||||
// The only "good" option for this node is to custom lower it.
|
||||
switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
|
||||
default: assert(0 && "This action is not supported at all!");
|
||||
case TargetLowering::Custom:
|
||||
Result = TLI.LowerOperation(Op, DAG);
|
||||
if (Result.Val) break;
|
||||
// Fall Thru
|
||||
case TargetLowering::Legal:
|
||||
// Target does not know, how to lower this, lower to noop
|
||||
Result = LegalizeOp(Node->getOperand(0));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case ISD::AssertSext:
|
||||
case ISD::AssertZext:
|
||||
Tmp1 = LegalizeOp(Node->getOperand(0));
|
||||
|
@ -3369,8 +3369,10 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const {
|
||||
case ISD::GLOBAL_OFFSET_TABLE: return "GLOBAL_OFFSET_TABLE";
|
||||
case ISD::RETURNADDR: return "RETURNADDR";
|
||||
case ISD::FRAMEADDR: return "FRAMEADDR";
|
||||
case ISD::FRAME_TO_ARGS_OFFSET: return "FRAME_TO_ARGS_OFFSET";
|
||||
case ISD::EXCEPTIONADDR: return "EXCEPTIONADDR";
|
||||
case ISD::EHSELECTION: return "EHSELECTION";
|
||||
case ISD::EH_RETURN: return "EH_RETURN";
|
||||
case ISD::ConstantPool: return "ConstantPool";
|
||||
case ISD::ExternalSymbol: return "ExternalSymbol";
|
||||
case ISD::INTRINSIC_WO_CHAIN: {
|
||||
|
@ -2721,6 +2721,53 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
case Intrinsic::eh_return: {
|
||||
MachineModuleInfo *MMI = DAG.getMachineModuleInfo();
|
||||
|
||||
if (MMI && ExceptionHandling) {
|
||||
MMI->setCallsEHReturn(true);
|
||||
DAG.setRoot(DAG.getNode(ISD::EH_RETURN,
|
||||
MVT::Other,
|
||||
getRoot(),
|
||||
getValue(I.getOperand(1)),
|
||||
getValue(I.getOperand(2))));
|
||||
} else {
|
||||
setValue(&I, DAG.getConstant(0, TLI.getPointerTy()));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case Intrinsic::eh_unwind_init: {
|
||||
if (MachineModuleInfo *MMI = DAG.getMachineModuleInfo()) {
|
||||
MMI->setCallsUnwindInit(true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case Intrinsic::eh_dwarf_cfa: {
|
||||
if (ExceptionHandling) {
|
||||
MVT::ValueType VT = getValue(I.getOperand(1)).getValueType();
|
||||
SDOperand Offset = DAG.getNode(ISD::ADD,
|
||||
TLI.getPointerTy(),
|
||||
DAG.getNode(ISD::FRAME_TO_ARGS_OFFSET,
|
||||
VT),
|
||||
getValue(I.getOperand(1)));
|
||||
setValue(&I, DAG.getNode(ISD::ADD,
|
||||
TLI.getPointerTy(),
|
||||
DAG.getNode(ISD::FRAMEADDR,
|
||||
TLI.getPointerTy(),
|
||||
DAG.getConstant(0,
|
||||
TLI.getPointerTy())),
|
||||
Offset));
|
||||
} else {
|
||||
setValue(&I, DAG.getConstant(0, TLI.getPointerTy()));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
case Intrinsic::sqrt_f32:
|
||||
case Intrinsic::sqrt_f64:
|
||||
setValue(&I, DAG.getNode(ISD::FSQRT,
|
||||
|
@ -327,7 +327,8 @@ MachineInstr *ARMRegisterInfo::foldMemoryOperand(MachineInstr *MI,
|
||||
return NewMI;
|
||||
}
|
||||
|
||||
const unsigned* ARMRegisterInfo::getCalleeSavedRegs() const {
|
||||
const unsigned* ARMRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
|
||||
const {
|
||||
static const unsigned CalleeSavedRegs[] = {
|
||||
ARM::LR, ARM::R11, ARM::R10, ARM::R9, ARM::R8,
|
||||
ARM::R7, ARM::R6, ARM::R5, ARM::R4,
|
||||
@ -349,7 +350,7 @@ const unsigned* ARMRegisterInfo::getCalleeSavedRegs() const {
|
||||
}
|
||||
|
||||
const TargetRegisterClass* const *
|
||||
ARMRegisterInfo::getCalleeSavedRegClasses() const {
|
||||
ARMRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
||||
static const TargetRegisterClass * const CalleeSavedRegClasses[] = {
|
||||
&ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::GPRRegClass,
|
||||
&ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::GPRRegClass,
|
||||
|
@ -66,9 +66,10 @@ public:
|
||||
MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
|
||||
int FrameIndex) const;
|
||||
|
||||
const unsigned *getCalleeSavedRegs() const;
|
||||
const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const;
|
||||
|
||||
const TargetRegisterClass* const* getCalleeSavedRegClasses() const;
|
||||
const TargetRegisterClass* const* getCalleeSavedRegClasses(
|
||||
const MachineFunction *MF = 0) const;
|
||||
|
||||
BitVector getReservedRegs(const MachineFunction &MF) const;
|
||||
|
||||
|
@ -164,7 +164,8 @@ void AlphaRegisterInfo::reMaterialize(MachineBasicBlock &MBB,
|
||||
MBB.insert(I, MI);
|
||||
}
|
||||
|
||||
const unsigned* AlphaRegisterInfo::getCalleeSavedRegs() const {
|
||||
const unsigned* AlphaRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
|
||||
const {
|
||||
static const unsigned CalleeSavedRegs[] = {
|
||||
Alpha::R9, Alpha::R10,
|
||||
Alpha::R11, Alpha::R12,
|
||||
@ -178,7 +179,7 @@ const unsigned* AlphaRegisterInfo::getCalleeSavedRegs() const {
|
||||
}
|
||||
|
||||
const TargetRegisterClass* const*
|
||||
AlphaRegisterInfo::getCalleeSavedRegClasses() const {
|
||||
AlphaRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
||||
static const TargetRegisterClass * const CalleeSavedRegClasses[] = {
|
||||
&Alpha::GPRCRegClass, &Alpha::GPRCRegClass,
|
||||
&Alpha::GPRCRegClass, &Alpha::GPRCRegClass,
|
||||
|
@ -48,9 +48,10 @@ struct AlphaRegisterInfo : public AlphaGenRegisterInfo {
|
||||
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
|
||||
unsigned DestReg, const MachineInstr *Orig) const;
|
||||
|
||||
const unsigned *getCalleeSavedRegs() const;
|
||||
const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const;
|
||||
|
||||
const TargetRegisterClass* const* getCalleeSavedRegClasses() const;
|
||||
const TargetRegisterClass* const* getCalleeSavedRegClasses(
|
||||
const MachineFunction *MF = 0) const;
|
||||
|
||||
BitVector getReservedRegs(const MachineFunction &MF) const;
|
||||
|
||||
|
@ -102,7 +102,8 @@ void IA64RegisterInfo::reMaterialize(MachineBasicBlock &MBB,
|
||||
MBB.insert(I, MI);
|
||||
}
|
||||
|
||||
const unsigned* IA64RegisterInfo::getCalleeSavedRegs() const {
|
||||
const unsigned* IA64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
|
||||
const {
|
||||
static const unsigned CalleeSavedRegs[] = {
|
||||
IA64::r5, 0
|
||||
};
|
||||
@ -110,7 +111,7 @@ const unsigned* IA64RegisterInfo::getCalleeSavedRegs() const {
|
||||
}
|
||||
|
||||
const TargetRegisterClass* const*
|
||||
IA64RegisterInfo::getCalleeSavedRegClasses() const {
|
||||
IA64RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
||||
static const TargetRegisterClass * const CalleeSavedRegClasses[] = {
|
||||
&IA64::GRRegClass, 0
|
||||
};
|
||||
|
@ -47,9 +47,10 @@ struct IA64RegisterInfo : public IA64GenRegisterInfo {
|
||||
void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
|
||||
unsigned DestReg, const MachineInstr *Orig) const;
|
||||
|
||||
const unsigned *getCalleeSavedRegs() const;
|
||||
const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const;
|
||||
|
||||
const TargetRegisterClass* const* getCalleeSavedRegClasses() const;
|
||||
const TargetRegisterClass* const* getCalleeSavedRegClasses(
|
||||
const MachineFunction *MF = 0) const;
|
||||
|
||||
BitVector getReservedRegs(const MachineFunction &MF) const;
|
||||
|
||||
|
@ -248,7 +248,8 @@ void PPCRegisterInfo::reMaterialize(MachineBasicBlock &MBB,
|
||||
MBB.insert(I, MI);
|
||||
}
|
||||
|
||||
const unsigned* PPCRegisterInfo::getCalleeSavedRegs() const {
|
||||
const unsigned* PPCRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
|
||||
const {
|
||||
// 32-bit Darwin calling convention.
|
||||
static const unsigned Macho32_CalleeSavedRegs[] = {
|
||||
PPC::R13, PPC::R14, PPC::R15,
|
||||
@ -324,7 +325,7 @@ const unsigned* PPCRegisterInfo::getCalleeSavedRegs() const {
|
||||
}
|
||||
|
||||
const TargetRegisterClass* const*
|
||||
PPCRegisterInfo::getCalleeSavedRegClasses() const {
|
||||
PPCRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
||||
// 32-bit Macho calling convention.
|
||||
static const TargetRegisterClass * const Macho32_CalleeSavedRegClasses[] = {
|
||||
&PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass,
|
||||
|
@ -57,9 +57,10 @@ public:
|
||||
virtual MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
|
||||
int FrameIndex) const;
|
||||
|
||||
const unsigned *getCalleeSavedRegs() const;
|
||||
const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const;
|
||||
|
||||
const TargetRegisterClass* const* getCalleeSavedRegClasses() const;
|
||||
const TargetRegisterClass* const* getCalleeSavedRegClasses(
|
||||
const MachineFunction *MF = 0) const;
|
||||
|
||||
BitVector getReservedRegs(const MachineFunction &MF) const;
|
||||
|
||||
|
@ -121,7 +121,8 @@ MachineInstr *SparcRegisterInfo::foldMemoryOperand(MachineInstr* MI,
|
||||
return NewMI;
|
||||
}
|
||||
|
||||
const unsigned* SparcRegisterInfo::getCalleeSavedRegs() const {
|
||||
const unsigned* SparcRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
|
||||
const {
|
||||
static const unsigned CalleeSavedRegs[] = { 0 };
|
||||
return CalleeSavedRegs;
|
||||
}
|
||||
@ -143,7 +144,7 @@ BitVector SparcRegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
||||
|
||||
|
||||
const TargetRegisterClass* const*
|
||||
SparcRegisterInfo::getCalleeSavedRegClasses() const {
|
||||
SparcRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
||||
static const TargetRegisterClass * const CalleeSavedRegClasses[] = { 0 };
|
||||
return CalleeSavedRegClasses;
|
||||
}
|
||||
|
@ -51,9 +51,10 @@ struct SparcRegisterInfo : public SparcGenRegisterInfo {
|
||||
unsigned OpNum,
|
||||
int FrameIndex) const;
|
||||
|
||||
const unsigned *getCalleeSavedRegs() const;
|
||||
const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const;
|
||||
|
||||
const TargetRegisterClass* const* getCalleeSavedRegClasses() const;
|
||||
const TargetRegisterClass* const* getCalleeSavedRegClasses(
|
||||
const MachineFunction *MF = 0) const;
|
||||
|
||||
BitVector getReservedRegs(const MachineFunction &MF) const;
|
||||
|
||||
|
@ -42,6 +42,8 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
|
||||
X86ScalarSSE = Subtarget->hasSSE2();
|
||||
X86StackPtr = Subtarget->is64Bit() ? X86::RSP : X86::ESP;
|
||||
|
||||
RegInfo = TM.getRegisterInfo();
|
||||
|
||||
// Set up the TargetLowering object.
|
||||
|
||||
// X86 is weird, it always uses i8 for shift amounts and setcc results.
|
||||
@ -197,6 +199,9 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM)
|
||||
}
|
||||
// X86 ret instruction may pop stack.
|
||||
setOperationAction(ISD::RET , MVT::Other, Custom);
|
||||
if (!Subtarget->is64Bit())
|
||||
setOperationAction(ISD::EH_RETURN , MVT::Other, Custom);
|
||||
|
||||
// Darwin ABI issue.
|
||||
setOperationAction(ISD::ConstantPool , MVT::i32 , Custom);
|
||||
setOperationAction(ISD::JumpTable , MVT::i32 , Custom);
|
||||
@ -4226,6 +4231,39 @@ SDOperand X86TargetLowering::LowerFRAMEADDR(SDOperand Op, SelectionDAG &DAG) {
|
||||
DAG.getConstant(4, getPointerTy()));
|
||||
}
|
||||
|
||||
SDOperand X86TargetLowering::LowerFRAME_TO_ARGS_OFFSET(SDOperand Op,
|
||||
SelectionDAG &DAG) {
|
||||
// Is not yet supported on x86-64
|
||||
if (Subtarget->is64Bit())
|
||||
return SDOperand();
|
||||
|
||||
return DAG.getConstant(8, getPointerTy());
|
||||
}
|
||||
|
||||
SDOperand X86TargetLowering::LowerEH_RETURN(SDOperand Op, SelectionDAG &DAG)
|
||||
{
|
||||
assert(!Subtarget->is64Bit() &&
|
||||
"Lowering of eh_return builtin is not supported yet on x86-64");
|
||||
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
SDOperand Chain = Op.getOperand(0);
|
||||
SDOperand Offset = Op.getOperand(1);
|
||||
SDOperand Handler = Op.getOperand(2);
|
||||
|
||||
SDOperand Frame = DAG.getRegister(RegInfo->getFrameRegister(MF),
|
||||
getPointerTy());
|
||||
|
||||
SDOperand StoreAddr = DAG.getNode(ISD::SUB, getPointerTy(), Frame,
|
||||
DAG.getConstant(-4UL, getPointerTy()));
|
||||
StoreAddr = DAG.getNode(ISD::ADD, getPointerTy(), StoreAddr, Offset);
|
||||
Chain = DAG.getStore(Chain, Handler, StoreAddr, NULL, 0);
|
||||
Chain = DAG.getCopyToReg(Chain, X86::ECX, StoreAddr);
|
||||
MF.addLiveOut(X86::ECX);
|
||||
|
||||
return DAG.getNode(X86ISD::EH_RETURN, MVT::Other,
|
||||
Chain, DAG.getRegister(X86::ECX, getPointerTy()));
|
||||
}
|
||||
|
||||
/// LowerOperation - Provide custom lowering hooks for some operations.
|
||||
///
|
||||
SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
@ -4263,7 +4301,10 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
|
||||
case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
|
||||
case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
|
||||
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
|
||||
case ISD::FRAME_TO_ARGS_OFFSET:
|
||||
return LowerFRAME_TO_ARGS_OFFSET(Op, DAG);
|
||||
case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG);
|
||||
case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG);
|
||||
}
|
||||
return SDOperand();
|
||||
}
|
||||
@ -4311,6 +4352,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||
case X86ISD::FRCP: return "X86ISD::FRCP";
|
||||
case X86ISD::TLSADDR: return "X86ISD::TLSADDR";
|
||||
case X86ISD::THREAD_POINTER: return "X86ISD::THREAD_POINTER";
|
||||
case X86ISD::EH_RETURN: return "X86ISD::EH_RETURN";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@
|
||||
#define X86ISELLOWERING_H
|
||||
|
||||
#include "X86Subtarget.h"
|
||||
#include "X86RegisterInfo.h"
|
||||
#include "llvm/Target/TargetLowering.h"
|
||||
#include "llvm/CodeGen/SelectionDAG.h"
|
||||
|
||||
@ -184,7 +185,10 @@ namespace llvm {
|
||||
FRSQRT, FRCP,
|
||||
|
||||
// Thread Local Storage
|
||||
TLSADDR, THREAD_POINTER
|
||||
TLSADDR, THREAD_POINTER,
|
||||
|
||||
// Exception Handling helpers
|
||||
EH_RETURN
|
||||
};
|
||||
}
|
||||
|
||||
@ -370,6 +374,7 @@ namespace llvm {
|
||||
/// Subtarget - Keep a pointer to the X86Subtarget around so that we can
|
||||
/// make the right decision when generating code for different targets.
|
||||
const X86Subtarget *Subtarget;
|
||||
const MRegisterInfo *RegInfo;
|
||||
|
||||
/// X86StackPtr - X86 physical register used as stack ptr.
|
||||
unsigned X86StackPtr;
|
||||
@ -424,6 +429,8 @@ namespace llvm {
|
||||
SDOperand LowerINTRINSIC_WO_CHAIN(SDOperand Op, SelectionDAG &DAG);
|
||||
SDOperand LowerRETURNADDR(SDOperand Op, SelectionDAG &DAG);
|
||||
SDOperand LowerFRAMEADDR(SDOperand Op, SelectionDAG &DAG);
|
||||
SDOperand LowerFRAME_TO_ARGS_OFFSET(SDOperand Op, SelectionDAG &DAG);
|
||||
SDOperand LowerEH_RETURN(SDOperand Op, SelectionDAG &DAG);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,8 @@ def SDT_X86TLSADDR : SDTypeProfile<1, 1, [SDTCisPtrTy<0>, SDTCisInt<1>]>;
|
||||
|
||||
def SDT_X86TLSTP : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>;
|
||||
|
||||
def SDT_X86EHRET : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
|
||||
|
||||
def X86shld : SDNode<"X86ISD::SHLD", SDTIntShiftDOp>;
|
||||
def X86shrd : SDNode<"X86ISD::SHRD", SDTIntShiftDOp>;
|
||||
|
||||
@ -95,6 +97,9 @@ def X86tlsaddr : SDNode<"X86ISD::TLSADDR", SDT_X86TLSADDR,
|
||||
[SDNPHasChain, SDNPInFlag, SDNPOutFlag]>;
|
||||
def X86TLStp : SDNode<"X86ISD::THREAD_POINTER", SDT_X86TLSTP, []>;
|
||||
|
||||
def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET,
|
||||
[SDNPHasChain]>;
|
||||
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// X86 Operand Definitions.
|
||||
@ -2491,6 +2496,17 @@ def DWARF_LOC : I<0, Pseudo, (ops i32imm:$line, i32imm:$col, i32imm:$file),
|
||||
[(dwarf_loc (i32 imm:$line), (i32 imm:$col),
|
||||
(i32 imm:$file))]>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// EH Pseudo Instructions
|
||||
//
|
||||
let isTerminator = 1, isReturn = 1, isBarrier = 1,
|
||||
hasCtrlDep = 1, noResults = 1 in {
|
||||
def EH_RETURN : I<0xC3, RawFrm, (ops GR32:$addr),
|
||||
"ret #eh_return, addr: $addr",
|
||||
[(X86ehret GR32:$addr)]>;
|
||||
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Non-Instruction Patterns
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -903,30 +903,62 @@ MachineInstr* X86RegisterInfo::foldMemoryOperand(MachineInstr *MI,
|
||||
}
|
||||
|
||||
|
||||
const unsigned *X86RegisterInfo::getCalleeSavedRegs() const {
|
||||
const unsigned *X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF)
|
||||
const {
|
||||
static const unsigned CalleeSavedRegs32Bit[] = {
|
||||
X86::ESI, X86::EDI, X86::EBX, X86::EBP, 0
|
||||
};
|
||||
|
||||
static const unsigned CalleeSavedRegs32EHRet[] = {
|
||||
X86::EAX, X86::EDX, X86::ESI, X86::EDI, X86::EBX, X86::EBP, 0
|
||||
};
|
||||
|
||||
static const unsigned CalleeSavedRegs64Bit[] = {
|
||||
X86::RBX, X86::R12, X86::R13, X86::R14, X86::R15, X86::RBP, 0
|
||||
};
|
||||
|
||||
return Is64Bit ? CalleeSavedRegs64Bit : CalleeSavedRegs32Bit;
|
||||
if (Is64Bit)
|
||||
return CalleeSavedRegs64Bit;
|
||||
else {
|
||||
if (MF) {
|
||||
MachineFrameInfo *MFI = MF->getFrameInfo();
|
||||
MachineModuleInfo *MMI = MFI->getMachineModuleInfo();
|
||||
if (MMI && MMI->callsEHReturn())
|
||||
return CalleeSavedRegs32EHRet;
|
||||
}
|
||||
return CalleeSavedRegs32Bit;
|
||||
}
|
||||
}
|
||||
|
||||
const TargetRegisterClass* const*
|
||||
X86RegisterInfo::getCalleeSavedRegClasses() const {
|
||||
X86RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
||||
static const TargetRegisterClass * const CalleeSavedRegClasses32Bit[] = {
|
||||
&X86::GR32RegClass, &X86::GR32RegClass,
|
||||
&X86::GR32RegClass, &X86::GR32RegClass, 0
|
||||
};
|
||||
static const TargetRegisterClass * const CalleeSavedRegClasses32EHRet[] = {
|
||||
&X86::GR32RegClass, &X86::GR32RegClass,
|
||||
&X86::GR32RegClass, &X86::GR32RegClass,
|
||||
&X86::GR32RegClass, &X86::GR32RegClass, 0
|
||||
};
|
||||
static const TargetRegisterClass * const CalleeSavedRegClasses64Bit[] = {
|
||||
&X86::GR64RegClass, &X86::GR64RegClass,
|
||||
&X86::GR64RegClass, &X86::GR64RegClass,
|
||||
&X86::GR64RegClass, &X86::GR64RegClass, 0
|
||||
};
|
||||
|
||||
return Is64Bit ? CalleeSavedRegClasses64Bit : CalleeSavedRegClasses32Bit;
|
||||
if (Is64Bit)
|
||||
return CalleeSavedRegClasses64Bit;
|
||||
else {
|
||||
if (MF) {
|
||||
MachineFrameInfo *MFI = MF->getFrameInfo();
|
||||
MachineModuleInfo *MMI = MFI->getMachineModuleInfo();
|
||||
if (MMI && MMI->callsEHReturn())
|
||||
return CalleeSavedRegClasses32EHRet;
|
||||
}
|
||||
return CalleeSavedRegClasses32Bit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
||||
@ -953,9 +985,13 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
||||
// if frame pointer elimination is disabled.
|
||||
//
|
||||
bool X86RegisterInfo::hasFP(const MachineFunction &MF) const {
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
MachineModuleInfo *MMI = MFI->getMachineModuleInfo();
|
||||
|
||||
return (NoFramePointerElim ||
|
||||
MF.getFrameInfo()->hasVarSizedObjects() ||
|
||||
MF.getInfo<X86MachineFunctionInfo>()->getForceFramePointer());
|
||||
MF.getInfo<X86MachineFunctionInfo>()->getForceFramePointer() ||
|
||||
(MMI && MMI->callsUnwindInit()));
|
||||
}
|
||||
|
||||
void X86RegisterInfo::
|
||||
@ -1243,10 +1279,12 @@ void X86RegisterInfo::emitEpilogue(MachineFunction &MF,
|
||||
MachineBasicBlock &MBB) const {
|
||||
const MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
MachineBasicBlock::iterator MBBI = prior(MBB.end());
|
||||
unsigned RetOpcode = MBBI->getOpcode();
|
||||
|
||||
switch (MBBI->getOpcode()) {
|
||||
switch (RetOpcode) {
|
||||
case X86::RET:
|
||||
case X86::RETI:
|
||||
case X86::EH_RETURN:
|
||||
case X86::TAILJMPd:
|
||||
case X86::TAILJMPr:
|
||||
case X86::TAILJMPm: break; // These are ok
|
||||
@ -1288,6 +1326,14 @@ void X86RegisterInfo::emitEpilogue(MachineFunction &MF,
|
||||
emitSPUpdate(MBB, MBBI, StackPtr, NumBytes, Is64Bit, TII);
|
||||
}
|
||||
}
|
||||
|
||||
// We're returning from function via eh_return.
|
||||
if (RetOpcode == X86::EH_RETURN) {
|
||||
MachineOperand &DestAddr = MBBI->getOperand(0);
|
||||
assert(DestAddr.isReg() && "Offset should be in register!");
|
||||
BuildMI(MBB, MBBI, TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr),StackPtr).
|
||||
addReg(DestAddr.getReg());
|
||||
}
|
||||
}
|
||||
|
||||
unsigned X86RegisterInfo::getRARegister() const {
|
||||
|
@ -74,12 +74,13 @@ public:
|
||||
|
||||
/// getCalleeSavedRegs - Return a null-terminated list of all of the
|
||||
/// callee-save registers on this target.
|
||||
const unsigned *getCalleeSavedRegs() const;
|
||||
const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const;
|
||||
|
||||
/// getCalleeSavedRegClasses - Return a null-terminated list of the preferred
|
||||
/// register classes to spill each callee-saved register with. The order and
|
||||
/// length of this list match the getCalleeSavedRegs() list.
|
||||
const TargetRegisterClass* const* getCalleeSavedRegClasses() const;
|
||||
const TargetRegisterClass* const* getCalleeSavedRegClasses(
|
||||
const MachineFunction *MF = 0) const;
|
||||
|
||||
/// getReservedRegs - Returns a bitset indexed by physical register number
|
||||
/// indicating if a register is a special register that has particular uses and
|
||||
|
@ -124,8 +124,9 @@ X86TargetAsmInfo::X86TargetAsmInfo(const X86TargetMachine &TM) {
|
||||
DwarfARangesSection = "\t.section\t.debug_aranges,\"\",@progbits";
|
||||
DwarfRangesSection = "\t.section\t.debug_ranges,\"\",@progbits";
|
||||
DwarfMacInfoSection = "\t.section\t.debug_macinfo,\"\",@progbits";
|
||||
|
||||
SupportsExceptionHandling = true;
|
||||
|
||||
if (!Subtarget->is64Bit())
|
||||
SupportsExceptionHandling = true;
|
||||
DwarfEHFrameSection = "\t.section\t.eh_frame,\"aw\",@progbits";
|
||||
DwarfExceptionSection = "\t.section\t.gcc_except_table,\"a\",@progbits";
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user