[llvm-commits] [llvm] r71610 - in /llvm/trunk: include/llvm/CodeGen/MachineFunction.h include/llvm/Intrinsics.td lib/CodeGen/MachineFunction.cpp lib/CodeGen/PrologEpilogInserter.cpp lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp lib/Target/ARM/ARMISelLowering.cpp lib/Target/ARM/ARMISelLowering.h lib/Target/ARM/ARMInstrInfo.cpp lib/Target/ARM/ARMInstrInfo.td
Jim Grosbach
grosbach at apple.com
Tue May 12 16:59:14 PDT 2009
Author: grosbach
Date: Tue May 12 18:59:14 2009
New Revision: 71610
URL: http://llvm.org/viewvc/llvm-project?rev=71610&view=rev
Log:
Add support for GCC compatible builtin setjmp and longjmp intrinsics. This is
a supporting preliminary patch for GCC-compatible SjLJ exception handling. Note that these intrinsics are not designed to be invoked directly by the user, but
rather used by the front-end as target hooks for exception handling.
Modified:
llvm/trunk/include/llvm/CodeGen/MachineFunction.h
llvm/trunk/include/llvm/Intrinsics.td
llvm/trunk/lib/CodeGen/MachineFunction.cpp
llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp
llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
llvm/trunk/lib/Target/ARM/ARMISelLowering.h
llvm/trunk/lib/Target/ARM/ARMInstrInfo.cpp
llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
Modified: llvm/trunk/include/llvm/CodeGen/MachineFunction.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineFunction.h?rev=71610&r1=71609&r2=71610&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MachineFunction.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MachineFunction.h Tue May 12 18:59:14 2009
@@ -70,6 +70,10 @@
const Function *Fn;
const TargetMachine &Target;
+ // HasBuiltinSetjmp - true if the function uses builtin_setjmp. Used to
+ // adjust callee-saved register tracking.
+ bool HasBuiltinSetjmp;
+
// RegInfo - Information about each register in use in the function.
MachineRegisterInfo *RegInfo;
@@ -123,6 +127,14 @@
///
const TargetMachine &getTarget() const { return Target; }
+ /// doesHaveBuiltinSetjmp - Return whether this function uses builtin_setjmp
+ ///
+ bool doesHaveBuiltinSetjmp() const { return HasBuiltinSetjmp; }
+
+ /// setHasBuiltinSetjmp - Mark whether this function uses builtin_setjmp
+ ///
+ void setHasBuiltinSetjmp (bool flag) { HasBuiltinSetjmp = flag; }
+
/// getRegInfo - Return information about the registers currently in use.
///
MachineRegisterInfo &getRegInfo() { return *RegInfo; }
Modified: llvm/trunk/include/llvm/Intrinsics.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Intrinsics.td?rev=71610&r1=71609&r2=71610&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Intrinsics.td (original)
+++ llvm/trunk/include/llvm/Intrinsics.td Tue May 12 18:59:14 2009
@@ -299,6 +299,11 @@
def int_eh_dwarf_cfa : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>;
+let Properties = [IntrNoMem] in {
+def int_builtinsetjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>;
+def int_builtinlongjmp : Intrinsic<[llvm_void_ty], [llvm_ptr_ty, llvm_i32_ty]>;
+}
+
//===---------------- Generic Variable Attribute Intrinsics----------------===//
//
def int_var_annotation : Intrinsic<[llvm_void_ty],
Modified: llvm/trunk/lib/CodeGen/MachineFunction.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/MachineFunction.cpp?rev=71610&r1=71609&r2=71610&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/MachineFunction.cpp (original)
+++ llvm/trunk/lib/CodeGen/MachineFunction.cpp Tue May 12 18:59:14 2009
@@ -121,6 +121,7 @@
MachineRegisterInfo(*TM.getRegisterInfo());
else
RegInfo = 0;
+ HasBuiltinSetjmp = false;
MFInfo = 0;
FrameInfo = new (Allocator.Allocate<MachineFrameInfo>())
MachineFrameInfo(*TM.getFrameInfo());
Modified: llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp?rev=71610&r1=71609&r2=71610&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp (original)
+++ llvm/trunk/lib/CodeGen/PrologEpilogInserter.cpp Tue May 12 18:59:14 2009
@@ -180,7 +180,7 @@
std::vector<CalleeSavedInfo> CSI;
for (unsigned i = 0; CSRegs[i]; ++i) {
unsigned Reg = CSRegs[i];
- if (Fn.getRegInfo().isPhysRegUsed(Reg)) {
+ if (Fn.getRegInfo().isPhysRegUsed(Reg) || Fn.doesHaveBuiltinSetjmp()) {
// If the reg is modified, save it!
CSI.push_back(CalleeSavedInfo(Reg, CSRegClasses[i]));
} else {
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp?rev=71610&r1=71609&r2=71610&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp Tue May 12 18:59:14 2009
@@ -3849,6 +3849,12 @@
case Intrinsic::longjmp:
return "_longjmp"+!TLI.usesUnderscoreLongJmp();
break;
+ case Intrinsic::builtinsetjmp:
+ // Mark this function has using builtin_setjmp so context gets preserved
+ DAG.getMachineFunction().setHasBuiltinSetjmp(true);
+ // Turn it into a target intrinsic node for the codegen
+ visitTargetIntrinsic(I, Intrinsic);
+ return 0;
case Intrinsic::memcpy: {
SDValue Op1 = getValue(I.getOperand(1));
SDValue Op2 = getValue(I.getOperand(2));
Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp?rev=71610&r1=71609&r2=71610&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.cpp Tue May 12 18:59:14 2009
@@ -1035,14 +1035,19 @@
return DAG.getNode(ARMISD::PIC_ADD, dl, PtrVT, Result, PICLabel);
}
-static SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) {
+SDValue
+ARMTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) {
MVT PtrVT = DAG.getTargetLoweringInfo().getPointerTy();
unsigned IntNo = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
+ DebugLoc dl = Op.getDebugLoc();
switch (IntNo) {
default: return SDValue(); // Don't custom lower most intrinsics.
case Intrinsic::arm_thread_pointer:
- return DAG.getNode(ARMISD::THREAD_POINTER, DebugLoc::getUnknownLoc(),
- PtrVT);
+ return DAG.getNode(ARMISD::THREAD_POINTER, dl, PtrVT);
+ case Intrinsic::builtinsetjmp:
+ SDValue Res = DAG.getNode(ARMISD::BUILTIN_SETJMP, dl, MVT::i32,
+ Op.getOperand(1));
+ return Res;
}
}
@@ -1431,6 +1436,20 @@
return DAG.getNode(ARMISD::CNEG, dl, VT, AbsVal, AbsVal, ARMCC, CCR, Cmp);
}
+SDValue ARMTargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) {
+ MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
+ MFI->setFrameAddressIsTaken(true);
+ MVT VT = Op.getValueType();
+ DebugLoc dl = Op.getDebugLoc(); // FIXME probably not meaningful
+ unsigned Depth = cast<ConstantSDNode>(Op.getOperand(0))->getZExtValue();
+ unsigned FrameReg = (Subtarget->isThumb() || Subtarget->useThumbBacktraces())
+ ? ARM::R7 : ARM::R11;
+ SDValue FrameAddr = DAG.getCopyFromReg(DAG.getEntryNode(), dl, FrameReg, VT);
+ while (Depth--)
+ FrameAddr = DAG.getLoad(VT, dl, DAG.getEntryNode(), FrameAddr, NULL, 0);
+ return FrameAddr;
+}
+
SDValue
ARMTargetLowering::EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl,
SDValue Chain,
@@ -1612,7 +1631,7 @@
case ISD::FCOPYSIGN: return LowerFCOPYSIGN(Op, DAG);
case ISD::FORMAL_ARGUMENTS: return LowerFORMAL_ARGUMENTS(Op, DAG);
case ISD::RETURNADDR: break;
- case ISD::FRAMEADDR: break;
+ case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
case ISD::GLOBAL_OFFSET_TABLE: return LowerGLOBAL_OFFSET_TABLE(Op, DAG);
case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
case ISD::BIT_CONVERT: return ExpandBIT_CONVERT(Op.getNode(), DAG);
Modified: llvm/trunk/lib/Target/ARM/ARMISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMISelLowering.h?rev=71610&r1=71609&r2=71610&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMISelLowering.h (original)
+++ llvm/trunk/lib/Target/ARM/ARMISelLowering.h Tue May 12 18:59:14 2009
@@ -64,6 +64,9 @@
FMRRD, // double to two gprs.
FMDRR, // Two gprs to double.
+ BUILTIN_SETJMP, // exception handling setjmp
+ BUILTIN_LONGJMP, // exception handling longjmp
+
THREAD_POINTER
};
}
@@ -154,6 +157,7 @@
SDNode *LowerCallResult(SDValue Chain, SDValue InFlag, CallSDNode *TheCall,
unsigned CallingConv, SelectionDAG &DAG);
SDValue LowerCALL(SDValue Op, SelectionDAG &DAG);
+ SDValue LowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG);
SDValue LowerRET(SDValue Op, SelectionDAG &DAG);
SDValue LowerGlobalAddressDarwin(SDValue Op, SelectionDAG &DAG);
SDValue LowerGlobalAddressELF(SDValue Op, SelectionDAG &DAG);
@@ -165,6 +169,7 @@
SDValue LowerGLOBAL_OFFSET_TABLE(SDValue Op, SelectionDAG &DAG);
SDValue LowerFORMAL_ARGUMENTS(SDValue Op, SelectionDAG &DAG);
SDValue LowerBR_JT(SDValue Op, SelectionDAG &DAG);
+ SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG);
SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl,
SDValue Chain,
Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.cpp?rev=71610&r1=71609&r2=71610&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.cpp (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.cpp Tue May 12 18:59:14 2009
@@ -991,6 +991,7 @@
// If this machine instr is a constant pool entry, its size is recorded as
// operand #2.
return MI->getOperand(2).getImm();
+ case ARM::Int_builtin_setjmp: return 12;
case ARM::BR_JTr:
case ARM::BR_JTm:
case ARM::BR_JTadd:
Modified: llvm/trunk/lib/Target/ARM/ARMInstrInfo.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/ARM/ARMInstrInfo.td?rev=71610&r1=71609&r2=71610&view=diff
==============================================================================
--- llvm/trunk/lib/Target/ARM/ARMInstrInfo.td (original)
+++ llvm/trunk/lib/Target/ARM/ARMInstrInfo.td Tue May 12 18:59:14 2009
@@ -40,6 +40,7 @@
SDTCisPtrTy<1>, SDTCisVT<2, i32>]>;
def SDT_ARMThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>;
+def SDT_ARMBuiltinSetjmp : SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisPtrTy<1>]>;
// Node definitions.
def ARMWrapper : SDNode<"ARMISD::Wrapper", SDTIntUnaryOp>;
@@ -84,6 +85,7 @@
def ARMrrx : SDNode<"ARMISD::RRX" , SDTIntUnaryOp, [SDNPInFlag ]>;
def ARMthread_pointer: SDNode<"ARMISD::THREAD_POINTER", SDT_ARMThreadPointer>;
+def ARMbuiltin_setjmp: SDNode<"ARMISD::BUILTIN_SETJMP", SDT_ARMBuiltinSetjmp>;
//===----------------------------------------------------------------------===//
// ARM Instruction Predicate Definitions.
@@ -1266,6 +1268,27 @@
}
//===----------------------------------------------------------------------===//
+// SJLJ Exception handling intrinsics
+// setjmp() is a three instruction sequence to store the return address
+// and save #0 in R0 for the non-longjmp case.
+// Since by its nature we may be coming from some other function to get
+// here, and we're using the stack frame for the containing function to
+// save/restore registers, we can't keep anything live in regs across
+// the setjmp(), else it will almost certainly have been tromped upon
+// when we get here from a longjmp(). We force everthing out of registers
+// except for our own input by listing the relevant registers in Defs.
+let Defs =
+ [ R0, R1, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR,
+ D0, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15 ] in {
+ def Int_builtin_setjmp : XI<(outs), (ins GPR:$src),
+ AddrModeNone, SizeSpecial, IndexModeNone, Pseudo,
+ "add r0, pc, #4\n\t"
+ "str r0, [$src, #+4]\n\t"
+ "mov r0, #0 @ setjmp", "",
+ [(set R0, (ARMbuiltin_setjmp GPR:$src))]>;
+}
+
+//===----------------------------------------------------------------------===//
// Non-Instruction Patterns
//
More information about the llvm-commits
mailing list