Index: lib/Transforms/NaCl/PNaClSjLjEH.cpp |
diff --git a/lib/Transforms/NaCl/PNaClSjLjEH.cpp b/lib/Transforms/NaCl/PNaClSjLjEH.cpp |
index 155e8c1350872e799e9e08a6a362ec2f78d7819d..4a1bfaedbe57a839bf0650bb076977aa3c89942e 100644 |
--- a/lib/Transforms/NaCl/PNaClSjLjEH.cpp |
+++ b/lib/Transforms/NaCl/PNaClSjLjEH.cpp |
@@ -157,6 +157,12 @@ namespace { |
}; |
} |
+static cl::opt<bool> |
+AllowUndefEhFuncs("allow-undef-pnacl-eh", |
+ cl::desc("Allow required EH symbols, like `__pnacl_eh_resume`, " |
+ "to be undefined"), |
+ cl::init(false), cl::Hidden); |
+ |
char PNaClSjLjEH::ID = 0; |
INITIALIZE_PASS(PNaClSjLjEH, "pnacl-sjlj-eh", |
"Lower C++ exception handling to use setjmp()", |
@@ -174,8 +180,15 @@ void FuncRewriter::initializeFrame() { |
SetjmpIntrinsic = Intrinsic::getDeclaration(M, Intrinsic::nacl_setjmp); |
Value *EHStackTlsVarUncast = M->getGlobalVariable("__pnacl_eh_stack"); |
- if (!EHStackTlsVarUncast) |
- report_fatal_error("__pnacl_eh_stack not defined"); |
+ if (!EHStackTlsVarUncast) { |
+ if (!AllowUndefEhFuncs) { |
+ report_fatal_error("__pnacl_eh_stack not defined"); |
+ } else { |
+ EHStackTlsVarUncast = |
+ M->getOrInsertGlobal("__pnacl_eh_stack", |
+ ExceptionFrameTy->getPointerTo()); |
+ } |
+ } |
EHStackTlsVar = new BitCastInst( |
EHStackTlsVarUncast, ExceptionFrameTy->getPointerTo()->getPointerTo(), |
"pnacl_eh_stack"); |
@@ -372,8 +385,24 @@ void FuncRewriter::expandInvokeInst(InvokeInst *Invoke) { |
void FuncRewriter::expandResumeInst(ResumeInst *Resume) { |
if (!EHResumeFunc) { |
EHResumeFunc = Func->getParent()->getFunction("__pnacl_eh_resume"); |
- if (!EHResumeFunc) |
+ } |
+ if (!EHResumeFunc) { |
+ if (AllowUndefEhFuncs) { |
+ // Create a declaration of __pnacl_eh_resume: |
+ Module* M = Func->getParent(); |
+ LLVMContext& C = M->getContext(); |
+ auto Args = std::vector<Type*>(1, Type::getInt8Ty(C)->getPointerTo()); |
+ EHResumeFunc = |
+ Function::Create(FunctionType::get(Type::getVoidTy(C), |
+ Args, |
+ false), |
+ GlobalValue::ExternalLinkage, |
+ "__pnacl_eh_resume"); |
+ M->getFunctionList().insertAfter(Func, EHResumeFunc); |
+ EHResumeFunc->setDoesNotReturn(); |
+ } else { |
report_fatal_error("__pnacl_eh_resume() not defined"); |
+ } |
} |
// The "resume" instruction gets passed the landingpad's full result |