forked from OSchip/llvm-project
First draft of EH support on x86/64-linux
llvm-svn: 55899
This commit is contained in:
parent
cb0655d626
commit
82b9540046
|
@ -255,8 +255,8 @@ def int_eh_selector_i64 : Intrinsic<[llvm_i64_ty, llvm_ptr_ty, llvm_ptr_ty,
|
|||
def int_eh_typeid_for_i32 : Intrinsic<[llvm_i32_ty, llvm_ptr_ty]>;
|
||||
def int_eh_typeid_for_i64 : Intrinsic<[llvm_i64_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_return_i32 : Intrinsic<[llvm_void_ty, llvm_i32_ty, llvm_ptr_ty]>;
|
||||
def int_eh_return_i64 : Intrinsic<[llvm_void_ty, llvm_i64_ty, llvm_ptr_ty]>;
|
||||
|
||||
def int_eh_unwind_init: Intrinsic<[llvm_void_ty]>,
|
||||
GCCBuiltin<"__builtin_unwind_init">;
|
||||
|
|
|
@ -316,7 +316,6 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM)
|
|||
setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand);
|
||||
setOperationAction(ISD::EHSELECTION, MVT::i32, Expand);
|
||||
if (Subtarget->is64Bit()) {
|
||||
// FIXME: Verify
|
||||
setExceptionPointerRegister(X86::RAX);
|
||||
setExceptionSelectorRegister(X86::RDX);
|
||||
} else {
|
||||
|
@ -5596,7 +5595,7 @@ SDValue X86TargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) {
|
|||
|
||||
SDValue RetAddrFI = getReturnAddressFrameIndex(DAG);
|
||||
return DAG.getNode(ISD::SUB, getPointerTy(), RetAddrFI,
|
||||
DAG.getIntPtrConstant(!Subtarget->is64Bit() ? 4 : 8));
|
||||
DAG.getIntPtrConstant(Subtarget->is64Bit() ? 8 : 4));
|
||||
}
|
||||
|
||||
SDValue X86TargetLowering::LowerFRAME_TO_ARGS_OFFSET(SDValue Op,
|
||||
|
@ -5606,26 +5605,26 @@ SDValue X86TargetLowering::LowerFRAME_TO_ARGS_OFFSET(SDValue Op,
|
|||
|
||||
SDValue X86TargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG)
|
||||
{
|
||||
assert(!Subtarget->is64Bit() &&
|
||||
"Lowering of eh_return builtin is not supported yet on x86-64");
|
||||
|
||||
MachineFunction &MF = DAG.getMachineFunction();
|
||||
SDValue Chain = Op.getOperand(0);
|
||||
SDValue Offset = Op.getOperand(1);
|
||||
SDValue Handler = Op.getOperand(2);
|
||||
|
||||
SDValue Frame = DAG.getRegister(RegInfo->getFrameRegister(MF),
|
||||
SDValue Frame = DAG.getRegister(Subtarget->is64Bit() ? X86::RBP : X86::EBP,
|
||||
getPointerTy());
|
||||
unsigned StoreAddrReg = (Subtarget->is64Bit() ? X86::RCX : X86::ECX);
|
||||
|
||||
SDValue StoreAddr = DAG.getNode(ISD::SUB, getPointerTy(), Frame,
|
||||
DAG.getIntPtrConstant(-4UL));
|
||||
DAG.getIntPtrConstant(Subtarget->is64Bit() ?
|
||||
-8UL: -4UL));
|
||||
StoreAddr = DAG.getNode(ISD::ADD, getPointerTy(), StoreAddr, Offset);
|
||||
Chain = DAG.getStore(Chain, Handler, StoreAddr, NULL, 0);
|
||||
Chain = DAG.getCopyToReg(Chain, X86::ECX, StoreAddr);
|
||||
MF.getRegInfo().addLiveOut(X86::ECX);
|
||||
Chain = DAG.getCopyToReg(Chain, StoreAddrReg, StoreAddr);
|
||||
MF.getRegInfo().addLiveOut(StoreAddrReg);
|
||||
|
||||
return DAG.getNode(X86ISD::EH_RETURN, MVT::Other,
|
||||
Chain, DAG.getRegister(X86::ECX, getPointerTy()));
|
||||
return DAG.getNode(X86ISD::EH_RETURN,
|
||||
MVT::Other,
|
||||
Chain, DAG.getRegister(StoreAddrReg, getPointerTy()));
|
||||
}
|
||||
|
||||
SDValue X86TargetLowering::LowerTRAMPOLINE(SDValue Op,
|
||||
|
|
|
@ -129,6 +129,17 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in {
|
|||
[(brind (loadi64 addr:$dst))]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// EH Pseudo Instructions
|
||||
//
|
||||
let isTerminator = 1, isReturn = 1, isBarrier = 1,
|
||||
hasCtrlDep = 1 in {
|
||||
def EH_RETURN64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr),
|
||||
"ret\t#eh_return, addr: $addr",
|
||||
[(X86ehret GR64:$addr)]>;
|
||||
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Miscellaneous Instructions...
|
||||
//
|
||||
|
|
|
@ -159,6 +159,14 @@ X86RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const {
|
|||
|
||||
const unsigned *
|
||||
X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
||||
bool callsEHReturn = false;
|
||||
|
||||
if (MF) {
|
||||
const MachineFrameInfo *MFI = MF->getFrameInfo();
|
||||
const MachineModuleInfo *MMI = MFI->getMachineModuleInfo();
|
||||
callsEHReturn = (MMI ? MMI->callsEHReturn() : false);
|
||||
}
|
||||
|
||||
static const unsigned CalleeSavedRegs32Bit[] = {
|
||||
X86::ESI, X86::EDI, X86::EBX, X86::EBP, 0
|
||||
};
|
||||
|
@ -171,6 +179,11 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
|||
X86::RBX, X86::R12, X86::R13, X86::R14, X86::R15, X86::RBP, 0
|
||||
};
|
||||
|
||||
static const unsigned CalleeSavedRegs64EHRet[] = {
|
||||
X86::RAX, X86::RDX, X86::RBX, X86::R12,
|
||||
X86::R13, X86::R14, X86::R15, X86::RBP, 0
|
||||
};
|
||||
|
||||
static const unsigned CalleeSavedRegsWin64[] = {
|
||||
X86::RBX, X86::RBP, X86::RDI, X86::RSI,
|
||||
X86::R12, X86::R13, X86::R14, X86::R15, 0
|
||||
|
@ -180,20 +193,22 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
|||
if (IsWin64)
|
||||
return CalleeSavedRegsWin64;
|
||||
else
|
||||
return CalleeSavedRegs64Bit;
|
||||
return (callsEHReturn ? CalleeSavedRegs64EHRet : CalleeSavedRegs64Bit);
|
||||
} else {
|
||||
if (MF) {
|
||||
const MachineFrameInfo *MFI = MF->getFrameInfo();
|
||||
const MachineModuleInfo *MMI = MFI->getMachineModuleInfo();
|
||||
if (MMI && MMI->callsEHReturn())
|
||||
return CalleeSavedRegs32EHRet;
|
||||
}
|
||||
return CalleeSavedRegs32Bit;
|
||||
return (callsEHReturn ? CalleeSavedRegs32EHRet : CalleeSavedRegs32Bit);
|
||||
}
|
||||
}
|
||||
|
||||
const TargetRegisterClass* const*
|
||||
X86RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
||||
bool callsEHReturn = false;
|
||||
|
||||
if (MF) {
|
||||
const MachineFrameInfo *MFI = MF->getFrameInfo();
|
||||
const MachineModuleInfo *MMI = MFI->getMachineModuleInfo();
|
||||
callsEHReturn = (MMI ? MMI->callsEHReturn() : false);
|
||||
}
|
||||
|
||||
static const TargetRegisterClass * const CalleeSavedRegClasses32Bit[] = {
|
||||
&X86::GR32RegClass, &X86::GR32RegClass,
|
||||
&X86::GR32RegClass, &X86::GR32RegClass, 0
|
||||
|
@ -208,6 +223,12 @@ X86RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
|||
&X86::GR64RegClass, &X86::GR64RegClass,
|
||||
&X86::GR64RegClass, &X86::GR64RegClass, 0
|
||||
};
|
||||
static const TargetRegisterClass * const CalleeSavedRegClasses64EHRet[] = {
|
||||
&X86::GR64RegClass, &X86::GR64RegClass,
|
||||
&X86::GR64RegClass, &X86::GR64RegClass,
|
||||
&X86::GR64RegClass, &X86::GR64RegClass,
|
||||
&X86::GR64RegClass, &X86::GR64RegClass, 0
|
||||
};
|
||||
static const TargetRegisterClass * const CalleeSavedRegClassesWin64[] = {
|
||||
&X86::GR64RegClass, &X86::GR64RegClass,
|
||||
&X86::GR64RegClass, &X86::GR64RegClass,
|
||||
|
@ -219,17 +240,12 @@ X86RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const {
|
|||
if (IsWin64)
|
||||
return CalleeSavedRegClassesWin64;
|
||||
else
|
||||
return CalleeSavedRegClasses64Bit;
|
||||
return (callsEHReturn ?
|
||||
CalleeSavedRegClasses64EHRet : CalleeSavedRegClasses64Bit);
|
||||
} else {
|
||||
if (MF) {
|
||||
const MachineFrameInfo *MFI = MF->getFrameInfo();
|
||||
const MachineModuleInfo *MMI = MFI->getMachineModuleInfo();
|
||||
if (MMI && MMI->callsEHReturn())
|
||||
return CalleeSavedRegClasses32EHRet;
|
||||
return (callsEHReturn ?
|
||||
CalleeSavedRegClasses32EHRet : CalleeSavedRegClasses32Bit);
|
||||
}
|
||||
return CalleeSavedRegClasses32Bit;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const {
|
||||
|
@ -787,6 +803,7 @@ void X86RegisterInfo::emitEpilogue(MachineFunction &MF,
|
|||
case X86::TCRETURNri64:
|
||||
case X86::TCRETURNdi64:
|
||||
case X86::EH_RETURN:
|
||||
case X86::EH_RETURN64:
|
||||
case X86::TAILJMPd:
|
||||
case X86::TAILJMPr:
|
||||
case X86::TAILJMPm: break; // These are ok
|
||||
|
@ -860,12 +877,13 @@ void X86RegisterInfo::emitEpilogue(MachineFunction &MF,
|
|||
}
|
||||
|
||||
// We're returning from function via eh_return.
|
||||
if (RetOpcode == X86::EH_RETURN) {
|
||||
if (RetOpcode == X86::EH_RETURN || RetOpcode == X86::EH_RETURN64) {
|
||||
MBBI = prior(MBB.end());
|
||||
MachineOperand &DestAddr = MBBI->getOperand(0);
|
||||
assert(DestAddr.isRegister() && "Offset should be in register!");
|
||||
BuildMI(MBB, MBBI, TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr),StackPtr).
|
||||
addReg(DestAddr.getReg());
|
||||
BuildMI(MBB, MBBI,
|
||||
TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr),
|
||||
StackPtr).addReg(DestAddr.getReg());
|
||||
// Tail call return: adjust the stack pointer and jump to callee
|
||||
} else if (RetOpcode == X86::TCRETURNri || RetOpcode == X86::TCRETURNdi ||
|
||||
RetOpcode== X86::TCRETURNri64 || RetOpcode == X86::TCRETURNdi64) {
|
||||
|
|
Loading…
Reference in New Issue