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 |