| OLD | NEW |
| 1 //===- PNaClSjLjEH.cpp - Lower C++ exception handling to use setjmp()------===// | 1 //===- PNaClSjLjEH.cpp - Lower C++ exception handling to use setjmp()------===// |
| 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 // The PNaClSjLjEH pass is part of an implementation of C++ exception | 10 // The PNaClSjLjEH pass is part of an implementation of C++ exception |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 150 Frame(NULL), FrameJmpBuf(NULL), FrameNextPtr(NULL), FrameExcInfo(NULL), | 150 Frame(NULL), FrameJmpBuf(NULL), FrameNextPtr(NULL), FrameExcInfo(NULL), |
| 151 EHResumeFunc(NULL) {} | 151 EHResumeFunc(NULL) {} |
| 152 | 152 |
| 153 Value *createSetjmpWrappedCall(InvokeInst *Invoke); | 153 Value *createSetjmpWrappedCall(InvokeInst *Invoke); |
| 154 void expandInvokeInst(InvokeInst *Invoke); | 154 void expandInvokeInst(InvokeInst *Invoke); |
| 155 void expandResumeInst(ResumeInst *Resume); | 155 void expandResumeInst(ResumeInst *Resume); |
| 156 void expandFunc(); | 156 void expandFunc(); |
| 157 }; | 157 }; |
| 158 } | 158 } |
| 159 | 159 |
| 160 static cl::opt<bool> |
| 161 AllowUndefEhFuncs("allow-undef-pnacl-eh", |
| 162 cl::desc("Allow required EH symbols, like `__pnacl_eh_resume`,
" |
| 163 "to be undefined"), |
| 164 cl::init(false), cl::Hidden); |
| 165 |
| 160 char PNaClSjLjEH::ID = 0; | 166 char PNaClSjLjEH::ID = 0; |
| 161 INITIALIZE_PASS(PNaClSjLjEH, "pnacl-sjlj-eh", | 167 INITIALIZE_PASS(PNaClSjLjEH, "pnacl-sjlj-eh", |
| 162 "Lower C++ exception handling to use setjmp()", | 168 "Lower C++ exception handling to use setjmp()", |
| 163 false, false) | 169 false, false) |
| 164 | 170 |
| 165 static const int kPNaClJmpBufSize = 1024; | 171 static const int kPNaClJmpBufSize = 1024; |
| 166 static const int kPNaClJmpBufAlign = 8; | 172 static const int kPNaClJmpBufAlign = 8; |
| 167 | 173 |
| 168 void FuncRewriter::initializeFrame() { | 174 void FuncRewriter::initializeFrame() { |
| 169 if (FrameInitialized) | 175 if (FrameInitialized) |
| 170 return; | 176 return; |
| 171 FrameInitialized = true; | 177 FrameInitialized = true; |
| 172 Module *M = Func->getParent(); | 178 Module *M = Func->getParent(); |
| 173 | 179 |
| 174 SetjmpIntrinsic = Intrinsic::getDeclaration(M, Intrinsic::nacl_setjmp); | 180 SetjmpIntrinsic = Intrinsic::getDeclaration(M, Intrinsic::nacl_setjmp); |
| 175 | 181 |
| 176 Value *EHStackTlsVarUncast = M->getGlobalVariable("__pnacl_eh_stack"); | 182 Value *EHStackTlsVarUncast = M->getGlobalVariable("__pnacl_eh_stack"); |
| 177 if (!EHStackTlsVarUncast) | 183 if (!EHStackTlsVarUncast) { |
| 178 report_fatal_error("__pnacl_eh_stack not defined"); | 184 if (!AllowUndefEhFuncs) { |
| 185 report_fatal_error("__pnacl_eh_stack not defined"); |
| 186 } else { |
| 187 EHStackTlsVarUncast = |
| 188 M->getOrInsertGlobal("__pnacl_eh_stack", |
| 189 ExceptionFrameTy->getPointerTo()); |
| 190 } |
| 191 } |
| 179 EHStackTlsVar = new BitCastInst( | 192 EHStackTlsVar = new BitCastInst( |
| 180 EHStackTlsVarUncast, ExceptionFrameTy->getPointerTo()->getPointerTo(), | 193 EHStackTlsVarUncast, ExceptionFrameTy->getPointerTo()->getPointerTo(), |
| 181 "pnacl_eh_stack"); | 194 "pnacl_eh_stack"); |
| 182 Func->getEntryBlock().getInstList().push_front(EHStackTlsVar); | 195 Func->getEntryBlock().getInstList().push_front(EHStackTlsVar); |
| 183 | 196 |
| 184 // Allocate the new exception frame. This is reused across all | 197 // Allocate the new exception frame. This is reused across all |
| 185 // invoke instructions in the function. | 198 // invoke instructions in the function. |
| 186 Type *I32 = Type::getInt32Ty(M->getContext()); | 199 Type *I32 = Type::getInt32Ty(M->getContext()); |
| 187 Frame = new AllocaInst(ExceptionFrameTy, ConstantInt::get(I32, 1), | 200 Frame = new AllocaInst(ExceptionFrameTy, ConstantInt::get(I32, 1), |
| 188 kPNaClJmpBufAlign, "invoke_frame"); | 201 kPNaClJmpBufAlign, "invoke_frame"); |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 365 CopyDebug(BranchInst::Create(Invoke->getNormalDest(), Invoke->getUnwindDest(), | 378 CopyDebug(BranchInst::Create(Invoke->getNormalDest(), Invoke->getUnwindDest(), |
| 366 IsZero, Invoke), | 379 IsZero, Invoke), |
| 367 Invoke); | 380 Invoke); |
| 368 | 381 |
| 369 Invoke->eraseFromParent(); | 382 Invoke->eraseFromParent(); |
| 370 } | 383 } |
| 371 | 384 |
| 372 void FuncRewriter::expandResumeInst(ResumeInst *Resume) { | 385 void FuncRewriter::expandResumeInst(ResumeInst *Resume) { |
| 373 if (!EHResumeFunc) { | 386 if (!EHResumeFunc) { |
| 374 EHResumeFunc = Func->getParent()->getFunction("__pnacl_eh_resume"); | 387 EHResumeFunc = Func->getParent()->getFunction("__pnacl_eh_resume"); |
| 375 if (!EHResumeFunc) | 388 } |
| 389 if (!EHResumeFunc) { |
| 390 if (AllowUndefEhFuncs) { |
| 391 // Create a declaration of __pnacl_eh_resume: |
| 392 Module* M = Func->getParent(); |
| 393 LLVMContext& C = M->getContext(); |
| 394 auto Args = std::vector<Type*>(1, Type::getInt8Ty(C)->getPointerTo()); |
| 395 EHResumeFunc = |
| 396 Function::Create(FunctionType::get(Type::getVoidTy(C), |
| 397 Args, |
| 398 false), |
| 399 GlobalValue::ExternalLinkage, |
| 400 "__pnacl_eh_resume"); |
| 401 M->getFunctionList().insertAfter(Func, EHResumeFunc); |
| 402 EHResumeFunc->setDoesNotReturn(); |
| 403 } else { |
| 376 report_fatal_error("__pnacl_eh_resume() not defined"); | 404 report_fatal_error("__pnacl_eh_resume() not defined"); |
| 405 } |
| 377 } | 406 } |
| 378 | 407 |
| 379 // The "resume" instruction gets passed the landingpad's full result | 408 // The "resume" instruction gets passed the landingpad's full result |
| 380 // (struct LandingPadResult above). Extract the exception_obj field | 409 // (struct LandingPadResult above). Extract the exception_obj field |
| 381 // to pass to __pnacl_eh_resume(), which doesn't need the | 410 // to pass to __pnacl_eh_resume(), which doesn't need the |
| 382 // matched_clause_id field. | 411 // matched_clause_id field. |
| 383 unsigned Indexes[] = { 0 }; | 412 unsigned Indexes[] = { 0 }; |
| 384 Value *ExceptionPtr = | 413 Value *ExceptionPtr = |
| 385 CopyDebug(ExtractValueInst::Create(Resume->getValue(), Indexes, | 414 CopyDebug(ExtractValueInst::Create(Resume->getValue(), Indexes, |
| 386 "resume_exc", Resume), Resume); | 415 "resume_exc", Resume), Resume); |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 FuncRewriter Rewriter(ExceptionFrameTy, &ExcInfoWriter, Func); | 485 FuncRewriter Rewriter(ExceptionFrameTy, &ExcInfoWriter, Func); |
| 457 Rewriter.expandFunc(); | 486 Rewriter.expandFunc(); |
| 458 } | 487 } |
| 459 ExcInfoWriter.defineGlobalVariables(&M); | 488 ExcInfoWriter.defineGlobalVariables(&M); |
| 460 return true; | 489 return true; |
| 461 } | 490 } |
| 462 | 491 |
| 463 ModulePass *llvm::createPNaClSjLjEHPass() { | 492 ModulePass *llvm::createPNaClSjLjEHPass() { |
| 464 return new PNaClSjLjEH(); | 493 return new PNaClSjLjEH(); |
| 465 } | 494 } |
| OLD | NEW |