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 |