- Idx.push_back(Constant::getNullValue(Type::IntTy));
- Idx.push_back(ConstantUInt::get(Type::UIntTy, 0));
- Value *NextFieldPtr = new GetElementPtrInst(RecPtr, Idx, "NextField", RI);
- Value *NextRec = new LoadInst(NextFieldPtr, "NextRecord", RI);
- new StoreInst(NextRec, JBListHead, RI);
-
- // Now that we popped the top of the JBList, get a pointer to the jmpbuf and
- // longjmp.
- Idx[1] = ConstantUInt::get(Type::UIntTy, 1);
- Idx[0] = new GetElementPtrInst(RecPtr, Idx, "JmpBuf", RI);
- Idx[1] = ConstantInt::get(Type::IntTy, 1);
- new CallInst(LongJmpFn, Idx, "", RI);
-
- // Now we set up the terminate block.
- RI = TermBlock->getTerminator();
-
- // Insert a new call to write(2, AbortMessage, AbortMessageLength);
- writeAbortMessage(RI);
-
- // Insert a call to abort()
- (new CallInst(AbortFn, std::vector<Value*>(), "", RI))->setTailCall();
+ Idx.push_back(Constant::getNullValue(Type::Int32Ty));
+ Idx.push_back(ConstantInt::get(Type::Int32Ty, 1));
+ OldJmpBufPtr = new GetElementPtrInst(JmpBuf, Idx, "OldBuf",
+ EntryBB->getTerminator());
+
+ // Copy the JBListHead to the alloca.
+ Value *OldBuf = new LoadInst(JBListHead, "oldjmpbufptr", true,
+ EntryBB->getTerminator());
+ new StoreInst(OldBuf, OldJmpBufPtr, true, EntryBB->getTerminator());
+
+ // Add the new jumpbuf to the list.
+ new StoreInst(JmpBuf, JBListHead, true, EntryBB->getTerminator());
+
+ // Create the catch block. The catch block is basically a big switch
+ // statement that goes to all of the invoke catch blocks.
+ BasicBlock *CatchBB = new BasicBlock("setjmp.catch", &F);
+
+ // Create an alloca which keeps track of which invoke is currently
+ // executing. For normal calls it contains zero.
+ AllocaInst *InvokeNum = new AllocaInst(Type::Int32Ty, 0, "invokenum",
+ EntryBB->begin());
+ new StoreInst(ConstantInt::get(Type::Int32Ty, 0), InvokeNum, true,
+ EntryBB->getTerminator());
+
+ // Insert a load in the Catch block, and a switch on its value. By default,
+ // we go to a block that just does an unwind (which is the correct action
+ // for a standard call).
+ BasicBlock *UnwindBB = new BasicBlock("unwindbb", &F);
+ Unwinds.push_back(new UnwindInst(UnwindBB));
+
+ Value *CatchLoad = new LoadInst(InvokeNum, "invoke.num", true, CatchBB);
+ SwitchInst *CatchSwitch =
+ new SwitchInst(CatchLoad, UnwindBB, Invokes.size(), CatchBB);
+
+ // Now that things are set up, insert the setjmp call itself.
+
+ // Split the entry block to insert the conditional branch for the setjmp.
+ BasicBlock *ContBlock = EntryBB->splitBasicBlock(EntryBB->getTerminator(),
+ "setjmp.cont");
+
+ Idx[1] = ConstantInt::get(Type::Int32Ty, 0);
+ Value *JmpBufPtr = new GetElementPtrInst(JmpBuf, Idx, "TheJmpBuf",
+ EntryBB->getTerminator());
+ Value *SJRet = new CallInst(SetJmpFn, JmpBufPtr, "sjret",
+ EntryBB->getTerminator());
+
+ // Compare the return value to zero.
+ Value *IsNormal = new ICmpInst(ICmpInst::ICMP_EQ, SJRet,
+ Constant::getNullValue(SJRet->getType()),
+ "notunwind", EntryBB->getTerminator());
+ // Nuke the uncond branch.
+ EntryBB->getTerminator()->eraseFromParent();
+
+ // Put in a new condbranch in its place.
+ new BranchInst(ContBlock, CatchBB, IsNormal, EntryBB);
+
+ // At this point, we are all set up, rewrite each invoke instruction.
+ for (unsigned i = 0, e = Invokes.size(); i != e; ++i)
+ rewriteExpensiveInvoke(Invokes[i], i+1, InvokeNum, CatchSwitch);