| OLD | NEW |
| 1 //===- LowerEmSetjmp - Lower setjmp/longjmp for Emscripten/JS -----------===// | 1 //===- LowerEmSetjmp - Lower setjmp/longjmp for Emscripten/JS -----------===// |
| 2 // | 2 // |
| 3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
| 4 // | 4 // |
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
| 7 // | 7 // |
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
| 9 // | 9 // |
| 10 // Lowers setjmp to a reasonably-performant approach for emscripten. The idea | 10 // Lowers setjmp to a reasonably-performant approach for emscripten. The idea |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 206 FunctionPhisMap SetjmpOutputPhis; | 206 FunctionPhisMap SetjmpOutputPhis; |
| 207 std::vector<Instruction*> ToErase; | 207 std::vector<Instruction*> ToErase; |
| 208 | 208 |
| 209 if (Setjmp) { | 209 if (Setjmp) { |
| 210 for (Instruction::user_iterator UI = Setjmp->user_begin(), UE = Setjmp->user
_end(); UI != UE; ++UI) { | 210 for (Instruction::user_iterator UI = Setjmp->user_begin(), UE = Setjmp->user
_end(); UI != UE; ++UI) { |
| 211 User *U = *UI; | 211 User *U = *UI; |
| 212 if (CallInst *CI = dyn_cast<CallInst>(U)) { | 212 if (CallInst *CI = dyn_cast<CallInst>(U)) { |
| 213 BasicBlock *SJBB = CI->getParent(); | 213 BasicBlock *SJBB = CI->getParent(); |
| 214 // The tail is everything right after the call, and will be reached once
when setjmp is | 214 // The tail is everything right after the call, and will be reached once
when setjmp is |
| 215 // called, and later when longjmp returns to the setjmp | 215 // called, and later when longjmp returns to the setjmp |
| 216 BasicBlock *Tail = SplitBlock(SJBB, CI->getNextNode(), this); | 216 BasicBlock *Tail = SplitBlock(SJBB, CI->getNextNode()); |
| 217 // Add a phi to the tail, which will be the output of setjmp, which indi
cates if this is the | 217 // Add a phi to the tail, which will be the output of setjmp, which indi
cates if this is the |
| 218 // first call or a longjmp back. The phi directly uses the right value b
ased on where we | 218 // first call or a longjmp back. The phi directly uses the right value b
ased on where we |
| 219 // arrive from | 219 // arrive from |
| 220 PHINode *SetjmpOutput = PHINode::Create(i32, 2, "", Tail->getFirstNonPHI
()); | 220 PHINode *SetjmpOutput = PHINode::Create(i32, 2, "", Tail->getFirstNonPHI
()); |
| 221 SetjmpOutput->addIncoming(ConstantInt::get(i32, 0), SJBB); // setjmp ini
tial call returns 0 | 221 SetjmpOutput->addIncoming(ConstantInt::get(i32, 0), SJBB); // setjmp ini
tial call returns 0 |
| 222 CI->replaceAllUsesWith(SetjmpOutput); // The proper output is now this,
not the setjmp call itself | 222 CI->replaceAllUsesWith(SetjmpOutput); // The proper output is now this,
not the setjmp call itself |
| 223 // longjmp returns to the setjmp will add themselves to this phi | 223 // longjmp returns to the setjmp will add themselves to this phi |
| 224 Phis& P = SetjmpOutputPhis[SJBB->getParent()]; | 224 Phis& P = SetjmpOutputPhis[SJBB->getParent()]; |
| 225 P.push_back(SetjmpOutput); | 225 P.push_back(SetjmpOutput); |
| 226 // fix call target | 226 // fix call target |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 261 if (Function *CF = dyn_cast<Function>(V)) if (CF->isIntrinsic()) conti
nue; | 261 if (Function *CF = dyn_cast<Function>(V)) if (CF->isIntrinsic()) conti
nue; |
| 262 // TODO: proper analysis of what can actually longjmp. Currently we as
sume anything but setjmp can. | 262 // TODO: proper analysis of what can actually longjmp. Currently we as
sume anything but setjmp can. |
| 263 // This may longjmp, so we need to check if it did. Split at that poin
t, and | 263 // This may longjmp, so we need to check if it did. Split at that poin
t, and |
| 264 // envelop the call in pre/post invoke, if we need to | 264 // envelop the call in pre/post invoke, if we need to |
| 265 CallInst *After; | 265 CallInst *After; |
| 266 Instruction *Check = NULL; | 266 Instruction *Check = NULL; |
| 267 if (Iter != E && (After = dyn_cast<CallInst>(Iter)) && After->getCalle
dValue() == PostInvoke) { | 267 if (Iter != E && (After = dyn_cast<CallInst>(Iter)) && After->getCalle
dValue() == PostInvoke) { |
| 268 // use the pre|postinvoke that exceptions lowering already made | 268 // use the pre|postinvoke that exceptions lowering already made |
| 269 Check = Iter++; | 269 Check = Iter++; |
| 270 } | 270 } |
| 271 BasicBlock *Tail = SplitBlock(BB, Iter, this); // Iter already points
to the next instruction, as we need | 271 BasicBlock *Tail = SplitBlock(BB, Iter); // Iter already points to the
next instruction, as we need |
| 272 TerminatorInst *TI = BB->getTerminator(); | 272 TerminatorInst *TI = BB->getTerminator(); |
| 273 if (!Check) { | 273 if (!Check) { |
| 274 // no existing pre|postinvoke, create our own | 274 // no existing pre|postinvoke, create our own |
| 275 CallInst::Create(PreInvoke, "", CI); | 275 CallInst::Create(PreInvoke, "", CI); |
| 276 Check = CallInst::Create(PostInvoke, "", TI); // CI is at the end of
the block | 276 Check = CallInst::Create(PostInvoke, "", TI); // CI is at the end of
the block |
| 277 | 277 |
| 278 // If we are calling a function that is noreturn, we must remove tha
t attribute. The code we | 278 // If we are calling a function that is noreturn, we must remove tha
t attribute. The code we |
| 279 // insert here does expect it to return, after we catch the exceptio
n. | 279 // insert here does expect it to return, after we catch the exceptio
n. |
| 280 if (CI->doesNotReturn()) { | 280 if (CI->doesNotReturn()) { |
| 281 if (Function *F = dyn_cast<Function>(CI->getCalledValue())) { | 281 if (Function *F = dyn_cast<Function>(CI->getCalledValue())) { |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 340 doRegToMem(*F); | 340 doRegToMem(*F); |
| 341 doMemToReg(*F); | 341 doMemToReg(*F); |
| 342 } | 342 } |
| 343 | 343 |
| 344 return true; | 344 return true; |
| 345 } | 345 } |
| 346 | 346 |
| 347 ModulePass *llvm::createLowerEmSetjmpPass() { | 347 ModulePass *llvm::createLowerEmSetjmpPass() { |
| 348 return new LowerEmSetjmp(); | 348 return new LowerEmSetjmp(); |
| 349 } | 349 } |
| OLD | NEW |