Skip to content

Commit faa3abb

Browse files
author
Jim Grosbach
committed
Update the saved stack pointer in the sjlj function context following either
an alloca() or an llvm.stackrestore(). rdar://8031573 llvm-svn: 104900
1 parent c2ebe03 commit faa3abb

File tree

7 files changed

+62
-33
lines changed

7 files changed

+62
-33
lines changed

llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -862,6 +862,8 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) {
862862
case ISD::TRAMPOLINE:
863863
case ISD::FRAMEADDR:
864864
case ISD::RETURNADDR:
865+
case ISD::EH_SJLJ_SETJMP:
866+
case ISD::EH_SJLJ_LONGJMP:
865867
// These operations lie about being legal: when they claim to be legal,
866868
// they should actually be custom-lowered.
867869
Action = TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0));

llvm/lib/CodeGen/SjLjEHPrepare.cpp

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ namespace {
4646
Constant *UnregisterFn;
4747
Constant *BuiltinSetjmpFn;
4848
Constant *FrameAddrFn;
49+
Constant *StackAddrFn;
50+
Constant *StackRestoreFn;
4951
Constant *LSDAAddrFn;
5052
Value *PersonalityFn;
5153
Constant *SelectorFn;
@@ -107,6 +109,8 @@ bool SjLjEHPass::doInitialization(Module &M) {
107109
PointerType::getUnqual(FunctionContextTy),
108110
(Type *)0);
109111
FrameAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::frameaddress);
112+
StackAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::stacksave);
113+
StackRestoreFn = Intrinsic::getDeclaration(&M, Intrinsic::stackrestore);
110114
BuiltinSetjmpFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_setjmp);
111115
LSDAAddrFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_sjlj_lsda);
112116
SelectorFn = Intrinsic::getDeclaration(&M, Intrinsic::eh_selector);
@@ -294,22 +298,34 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) {
294298
// If we don't have any invokes or unwinds, there's nothing to do.
295299
if (Unwinds.empty() && Invokes.empty()) return false;
296300

297-
// Find the eh.selector.* and eh.exception calls. We'll use the first
298-
// eh.selector to determine the right personality function to use. For
299-
// SJLJ, we always use the same personality for the whole function,
300-
// not on a per-selector basis.
301+
// Find the eh.selector.*, eh.exception and alloca calls.
302+
//
303+
// Remember any allocas() that aren't in the entry block, as the
304+
// jmpbuf saved SP will need to be updated for them.
305+
//
306+
// We'll use the first eh.selector to determine the right personality
307+
// function to use. For SJLJ, we always use the same personality for the
308+
// whole function, not on a per-selector basis.
301309
// FIXME: That's a bit ugly. Better way?
302310
SmallVector<CallInst*,16> EH_Selectors;
303311
SmallVector<CallInst*,16> EH_Exceptions;
304-
for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) {
312+
SmallVector<Instruction*,16> JmpbufUpdatePoints;
313+
// Note: Skip the entry block since there's nothing there that interests
314+
// us. eh.selector and eh.exception shouldn't ever be there, and we
315+
// want to disregard any allocas that are there.
316+
for (Function::iterator BB = F.begin(), E = F.end(); ++BB != E;) {
305317
for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) {
306318
if (CallInst *CI = dyn_cast<CallInst>(I)) {
307319
if (CI->getCalledFunction() == SelectorFn) {
308320
if (!PersonalityFn) PersonalityFn = CI->getOperand(2);
309321
EH_Selectors.push_back(CI);
310322
} else if (CI->getCalledFunction() == ExceptionFn) {
311323
EH_Exceptions.push_back(CI);
324+
} else if (CI->getCalledFunction() == StackRestoreFn) {
325+
JmpbufUpdatePoints.push_back(CI);
312326
}
327+
} else if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) {
328+
JmpbufUpdatePoints.push_back(AI);
313329
}
314330
}
315331
}
@@ -419,7 +435,7 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) {
419435
// Populate the Function Context
420436
// 1. LSDA address
421437
// 2. Personality function address
422-
// 3. jmpbuf (save FP and call eh.sjlj.setjmp)
438+
// 3. jmpbuf (save SP, FP and call eh.sjlj.setjmp)
423439

424440
// LSDA address
425441
Idxs[0] = Zero;
@@ -440,31 +456,41 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) {
440456
new StoreInst(PersonalityFn, PersonalityFieldPtr, true,
441457
EntryBB->getTerminator());
442458

443-
// Save the frame pointer.
459+
// Save the frame pointer.
444460
Idxs[1] = ConstantInt::get(Int32Ty, 5);
445-
Value *FieldPtr
461+
Value *JBufPtr
446462
= GetElementPtrInst::Create(FunctionContext, Idxs, Idxs+2,
447463
"jbuf_gep",
448464
EntryBB->getTerminator());
449465
Idxs[1] = ConstantInt::get(Int32Ty, 0);
450-
Value *ElemPtr =
451-
GetElementPtrInst::Create(FieldPtr, Idxs, Idxs+2, "jbuf_fp_gep",
466+
Value *FramePtr =
467+
GetElementPtrInst::Create(JBufPtr, Idxs, Idxs+2, "jbuf_fp_gep",
452468
EntryBB->getTerminator());
453469

454470
Value *Val = CallInst::Create(FrameAddrFn,
455471
ConstantInt::get(Int32Ty, 0),
456472
"fp",
457473
EntryBB->getTerminator());
458-
new StoreInst(Val, ElemPtr, true, EntryBB->getTerminator());
459-
// Call the setjmp instrinsic. It fills in the rest of the jmpbuf
474+
new StoreInst(Val, FramePtr, true, EntryBB->getTerminator());
475+
476+
// Save the stack pointer.
477+
Idxs[1] = ConstantInt::get(Int32Ty, 2);
478+
Value *StackPtr =
479+
GetElementPtrInst::Create(JBufPtr, Idxs, Idxs+2, "jbuf_sp_gep",
480+
EntryBB->getTerminator());
481+
482+
Val = CallInst::Create(StackAddrFn, "sp", EntryBB->getTerminator());
483+
new StoreInst(Val, StackPtr, true, EntryBB->getTerminator());
484+
485+
// Call the setjmp instrinsic. It fills in the rest of the jmpbuf.
460486
Value *SetjmpArg =
461-
CastInst::Create(Instruction::BitCast, FieldPtr,
487+
CastInst::Create(Instruction::BitCast, JBufPtr,
462488
Type::getInt8PtrTy(F.getContext()), "",
463489
EntryBB->getTerminator());
464490
Value *DispatchVal = CallInst::Create(BuiltinSetjmpFn, SetjmpArg,
465491
"dispatch",
466492
EntryBB->getTerminator());
467-
// check the return value of the setjmp. non-zero goes to dispatcher
493+
// check the return value of the setjmp. non-zero goes to dispatcher.
468494
Value *IsNormal = new ICmpInst(EntryBB->getTerminator(),
469495
ICmpInst::ICMP_EQ, DispatchVal, Zero,
470496
"notunwind");
@@ -509,6 +535,16 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) {
509535
Unwinds[i]->eraseFromParent();
510536
}
511537

538+
// Following any allocas not in the entry block, update the saved SP
539+
// in the jmpbuf to the new value.
540+
for (unsigned i = 0, e = JmpbufUpdatePoints.size(); i != e; ++i) {
541+
Instruction *AI = JmpbufUpdatePoints[i];
542+
Instruction *StackAddr = CallInst::Create(StackAddrFn, "sp");
543+
StackAddr->insertAfter(AI);
544+
Instruction *StoreStackAddr = new StoreInst(StackAddr, StackPtr, true);
545+
StoreStackAddr->insertAfter(StackAddr);
546+
}
547+
512548
// Finally, for any returns from this function, if this function contains an
513549
// invoke, add a call to unregister the function context.
514550
for (unsigned i = 0, e = Returns.size(); i != e; ++i)

llvm/lib/Target/ARM/ARMBaseInstrInfo.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,11 +524,11 @@ unsigned ARMBaseInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
524524
return 10;
525525
case ARM::Int_eh_sjlj_setjmp:
526526
case ARM::Int_eh_sjlj_setjmp_nofp:
527-
return 24;
527+
return 20;
528528
case ARM::tInt_eh_sjlj_setjmp:
529529
case ARM::t2Int_eh_sjlj_setjmp:
530530
case ARM::t2Int_eh_sjlj_setjmp_nofp:
531-
return 14;
531+
return 12;
532532
case ARM::BR_JTr:
533533
case ARM::BR_JTm:
534534
case ARM::BR_JTadd:

llvm/lib/Target/ARM/ARMISelLowering.cpp

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -412,8 +412,6 @@ ARMTargetLowering::ARMTargetLowering(TargetMachine &TM)
412412

413413
// We want to custom lower some of our intrinsics.
414414
setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::Other, Custom);
415-
setOperationAction(ISD::EH_SJLJ_SETJMP, MVT::i32, Custom);
416-
setOperationAction(ISD::EH_SJLJ_LONGJMP, MVT::Other, Custom);
417415

418416
setOperationAction(ISD::SETCC, MVT::i32, Expand);
419417
setOperationAction(ISD::SETCC, MVT::f32, Expand);
@@ -1552,9 +1550,7 @@ SDValue ARMTargetLowering::LowerGLOBAL_OFFSET_TABLE(SDValue Op,
15521550
SDValue
15531551
ARMTargetLowering::LowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const {
15541552
DebugLoc dl = Op.getDebugLoc();
1555-
SDValue Val = Subtarget->isThumb() ?
1556-
DAG.getCopyFromReg(DAG.getEntryNode(), dl, ARM::SP, MVT::i32) :
1557-
DAG.getConstant(0, MVT::i32);
1553+
SDValue Val = DAG.getConstant(0, MVT::i32);
15581554
return DAG.getNode(ARMISD::EH_SJLJ_SETJMP, dl, MVT::i32, Op.getOperand(0),
15591555
Op.getOperand(1), Val);
15601556
}

llvm/lib/Target/ARM/ARMInstrInfo.td

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2534,8 +2534,7 @@ let Defs =
25342534
def Int_eh_sjlj_setjmp : XI<(outs), (ins GPR:$src, GPR:$val),
25352535
AddrModeNone, SizeSpecial, IndexModeNone,
25362536
Pseudo, NoItinerary,
2537-
"str\tsp, [$src, #+8] ${:comment} eh_setjmp begin\n\t"
2538-
"add\t$val, pc, #8\n\t"
2537+
"add\t$val, pc, #8\t${:comment} eh_setjmp begin\t"
25392538
"str\t$val, [$src, #+4]\n\t"
25402539
"mov\tr0, #0\n\t"
25412540
"add\tpc, pc, #0\n\t"
@@ -2549,8 +2548,7 @@ let Defs =
25492548
def Int_eh_sjlj_setjmp_nofp : XI<(outs), (ins GPR:$src, GPR:$val),
25502549
AddrModeNone, SizeSpecial, IndexModeNone,
25512550
Pseudo, NoItinerary,
2552-
"str\tsp, [$src, #+8] ${:comment} eh_setjmp begin\n\t"
2553-
"add\t$val, pc, #8\n\t"
2551+
"add\t$val, pc, #8\n ${:comment} eh_setjmp begin\t"
25542552
"str\t$val, [$src, #+4]\n\t"
25552553
"mov\tr0, #0\n\t"
25562554
"add\tpc, pc, #0\n\t"

llvm/lib/Target/ARM/ARMInstrThumb.td

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -923,13 +923,12 @@ let isCall = 1,
923923
// except for our own input by listing the relevant registers in Defs. By
924924
// doing so, we also cause the prologue/epilogue code to actively preserve
925925
// all of the callee-saved resgisters, which is exactly what we want.
926-
// The current SP is passed in $val, and we reuse the reg as a scratch.
926+
// $val is a scratch register for our use.
927927
let Defs =
928928
[ R0, R1, R2, R3, R4, R5, R6, R7, R12 ] in {
929929
def tInt_eh_sjlj_setjmp : ThumbXI<(outs),(ins tGPR:$src, tGPR:$val),
930930
AddrModeNone, SizeSpecial, NoItinerary,
931-
"str\t$val, [$src, #8]\t${:comment} begin eh.setjmp\n"
932-
"\tmov\t$val, pc\n"
931+
"mov\t$val, pc\t${:comment} begin eh.setjmp\n"
933932
"\tadds\t$val, #7\n"
934933
"\tstr\t$val, [$src, #4]\n"
935934
"\tmovs\tr0, #0\n"

llvm/lib/Target/ARM/ARMInstrThumb2.td

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2389,16 +2389,15 @@ let isCall = 1,
23892389
// except for our own input by listing the relevant registers in Defs. By
23902390
// doing so, we also cause the prologue/epilogue code to actively preserve
23912391
// all of the callee-saved resgisters, which is exactly what we want.
2392-
// The current SP is passed in $val, and we reuse the reg as a scratch.
2392+
// $val is a scratch register for our use.
23932393
let Defs =
23942394
[ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR, D0,
23952395
D1, D2, D3, D4, D5, D6, D7, D8, D9, D10, D11, D12, D13, D14, D15,
23962396
D16, D17, D18, D19, D20, D21, D22, D23, D24, D25, D26, D27, D28, D29, D30,
23972397
D31 ] in {
23982398
def t2Int_eh_sjlj_setjmp : Thumb2XI<(outs), (ins GPR:$src, tGPR:$val),
23992399
AddrModeNone, SizeSpecial, NoItinerary,
2400-
"str\t$val, [$src, #8]\t${:comment} begin eh.setjmp\n"
2401-
"\tmov\t$val, pc\n"
2400+
"mov\t$val, pc\t${:comment} begin eh.setjmp\n"
24022401
"\tadds\t$val, #7\n"
24032402
"\tstr\t$val, [$src, #4]\n"
24042403
"\tmovs\tr0, #0\n"
@@ -2413,8 +2412,7 @@ let Defs =
24132412
[ R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, R12, LR ] in {
24142413
def t2Int_eh_sjlj_setjmp_nofp : Thumb2XI<(outs), (ins GPR:$src, tGPR:$val),
24152414
AddrModeNone, SizeSpecial, NoItinerary,
2416-
"str\t$val, [$src, #8]\t${:comment} begin eh.setjmp\n"
2417-
"\tmov\t$val, pc\n"
2415+
"mov\t$val, pc\t${:comment} begin eh.setjmp\n"
24182416
"\tadds\t$val, #7\n"
24192417
"\tstr\t$val, [$src, #4]\n"
24202418
"\tmovs\tr0, #0\n"

0 commit comments

Comments
 (0)