@@ -46,6 +46,8 @@ namespace {
46
46
Constant *UnregisterFn;
47
47
Constant *BuiltinSetjmpFn;
48
48
Constant *FrameAddrFn;
49
+ Constant *StackAddrFn;
50
+ Constant *StackRestoreFn;
49
51
Constant *LSDAAddrFn;
50
52
Value *PersonalityFn;
51
53
Constant *SelectorFn;
@@ -107,6 +109,8 @@ bool SjLjEHPass::doInitialization(Module &M) {
107
109
PointerType::getUnqual (FunctionContextTy),
108
110
(Type *)0 );
109
111
FrameAddrFn = Intrinsic::getDeclaration (&M, Intrinsic::frameaddress);
112
+ StackAddrFn = Intrinsic::getDeclaration (&M, Intrinsic::stacksave);
113
+ StackRestoreFn = Intrinsic::getDeclaration (&M, Intrinsic::stackrestore);
110
114
BuiltinSetjmpFn = Intrinsic::getDeclaration (&M, Intrinsic::eh_sjlj_setjmp);
111
115
LSDAAddrFn = Intrinsic::getDeclaration (&M, Intrinsic::eh_sjlj_lsda);
112
116
SelectorFn = Intrinsic::getDeclaration (&M, Intrinsic::eh_selector);
@@ -294,22 +298,34 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) {
294
298
// If we don't have any invokes or unwinds, there's nothing to do.
295
299
if (Unwinds.empty () && Invokes.empty ()) return false ;
296
300
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.
301
309
// FIXME: That's a bit ugly. Better way?
302
310
SmallVector<CallInst*,16 > EH_Selectors;
303
311
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;) {
305
317
for (BasicBlock::iterator I = BB->begin (), E = BB->end (); I != E; ++I) {
306
318
if (CallInst *CI = dyn_cast<CallInst>(I)) {
307
319
if (CI->getCalledFunction () == SelectorFn) {
308
320
if (!PersonalityFn) PersonalityFn = CI->getOperand (2 );
309
321
EH_Selectors.push_back (CI);
310
322
} else if (CI->getCalledFunction () == ExceptionFn) {
311
323
EH_Exceptions.push_back (CI);
324
+ } else if (CI->getCalledFunction () == StackRestoreFn) {
325
+ JmpbufUpdatePoints.push_back (CI);
312
326
}
327
+ } else if (AllocaInst *AI = dyn_cast<AllocaInst>(I)) {
328
+ JmpbufUpdatePoints.push_back (AI);
313
329
}
314
330
}
315
331
}
@@ -419,7 +435,7 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) {
419
435
// Populate the Function Context
420
436
// 1. LSDA address
421
437
// 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)
423
439
424
440
// LSDA address
425
441
Idxs[0 ] = Zero;
@@ -440,31 +456,41 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) {
440
456
new StoreInst (PersonalityFn, PersonalityFieldPtr, true ,
441
457
EntryBB->getTerminator ());
442
458
443
- // Save the frame pointer.
459
+ // Save the frame pointer.
444
460
Idxs[1 ] = ConstantInt::get (Int32Ty, 5 );
445
- Value *FieldPtr
461
+ Value *JBufPtr
446
462
= GetElementPtrInst::Create (FunctionContext, Idxs, Idxs+2 ,
447
463
" jbuf_gep" ,
448
464
EntryBB->getTerminator ());
449
465
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" ,
452
468
EntryBB->getTerminator ());
453
469
454
470
Value *Val = CallInst::Create (FrameAddrFn,
455
471
ConstantInt::get (Int32Ty, 0 ),
456
472
" fp" ,
457
473
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.
460
486
Value *SetjmpArg =
461
- CastInst::Create (Instruction::BitCast, FieldPtr ,
487
+ CastInst::Create (Instruction::BitCast, JBufPtr ,
462
488
Type::getInt8PtrTy (F.getContext ()), " " ,
463
489
EntryBB->getTerminator ());
464
490
Value *DispatchVal = CallInst::Create (BuiltinSetjmpFn, SetjmpArg,
465
491
" dispatch" ,
466
492
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.
468
494
Value *IsNormal = new ICmpInst (EntryBB->getTerminator (),
469
495
ICmpInst::ICMP_EQ, DispatchVal, Zero,
470
496
" notunwind" );
@@ -509,6 +535,16 @@ bool SjLjEHPass::insertSjLjEHSupport(Function &F) {
509
535
Unwinds[i]->eraseFromParent ();
510
536
}
511
537
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
+
512
548
// Finally, for any returns from this function, if this function contains an
513
549
// invoke, add a call to unregister the function context.
514
550
for (unsigned i = 0 , e = Returns.size (); i != e; ++i)
0 commit comments