aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Target/JSBackend/CallHandlers.h15
-rw-r--r--lib/Transforms/NaCl/LowerEmSetjmp.cpp8
2 files changed, 19 insertions, 4 deletions
diff --git a/lib/Target/JSBackend/CallHandlers.h b/lib/Target/JSBackend/CallHandlers.h
index d81be51a41..219527429a 100644
--- a/lib/Target/JSBackend/CallHandlers.h
+++ b/lib/Target/JSBackend/CallHandlers.h
@@ -130,11 +130,17 @@ DEF_CALL_HANDLER(emscripten_resume, {
// setjmp support
+DEF_CALL_HANDLER(emscripten_prep_setjmp, {
+ return getAssign("_setjmpTable", Type::getInt32Ty(CI->getContext())) + "STACKTOP; STACKTOP=(STACKTOP+168)|0";
+})
DEF_CALL_HANDLER(emscripten_setjmp, {
- return CH___default__(CI, "_saveSetjmp");
+ // env, label, table
+ Declares.insert("_saveSetjmp");
+ return "_saveSetjmp(" + getValueAsStr(CI->getOperand(0)) + "," + getValueAsStr(CI->getOperand(1)) + ",_setjmpTable|0)|0";
})
DEF_CALL_HANDLER(emscripten_longjmp, {
- return CH___default__(CI, "longjmp");
+ Declares.insert("longjmp");
+ return CH___default__(CI, "_longjmp");
})
DEF_CALL_HANDLER(emscripten_check_longjmp, {
return "checkyourself";
@@ -594,6 +600,11 @@ void setupCallHandlers() {
SETUP_CALL_HANDLER(emscripten_postinvoke);
SETUP_CALL_HANDLER(emscripten_landingpad);
SETUP_CALL_HANDLER(emscripten_resume);
+ SETUP_CALL_HANDLER(emscripten_prep_setjmp);
+ SETUP_CALL_HANDLER(emscripten_setjmp);
+ SETUP_CALL_HANDLER(emscripten_longjmp);
+ SETUP_CALL_HANDLER(emscripten_check_longjmp);
+ SETUP_CALL_HANDLER(emscripten_get_longjmp_result);
SETUP_CALL_HANDLER(getHigh32);
SETUP_CALL_HANDLER(setHigh32);
SETUP_CALL_HANDLER(FPtoILow);
diff --git a/lib/Transforms/NaCl/LowerEmSetjmp.cpp b/lib/Transforms/NaCl/LowerEmSetjmp.cpp
index 21532f4efb..1f0bf75cd0 100644
--- a/lib/Transforms/NaCl/LowerEmSetjmp.cpp
+++ b/lib/Transforms/NaCl/LowerEmSetjmp.cpp
@@ -77,6 +77,7 @@ bool LowerEmSetjmp::runOnModule(Module &M) {
assert(Setjmp && Longjmp); // must see setjmp *and* longjmp if one of them is present
Type *i32 = Type::getInt32Ty(M.getContext());
+ Type *Void = Type::getVoidTy(M.getContext());
// Add functions
@@ -92,6 +93,9 @@ bool LowerEmSetjmp::runOnModule(Module &M) {
Function *CheckLongjmp = Function::Create(IntFunc, GlobalValue::ExternalLinkage, "emscripten_check_longjmp", TheModule);
Function *GetLongjmpResult = Function::Create(IntFunc, GlobalValue::ExternalLinkage, "emscripten_get_longjmp_result", TheModule);
+ FunctionType *VoidFunc = FunctionType::get(Void, false);
+ Function *PrepSetjmp = Function::Create(VoidFunc, GlobalValue::ExternalLinkage, "emscripten_prep_setjmp", TheModule);
+
// Process all callers of setjmp and longjmp. Start with setjmp.
typedef std::vector<PHINode*> Phis;
@@ -138,7 +142,7 @@ bool LowerEmSetjmp::runOnModule(Module &M) {
Function *F = I->first;
Phis& P = I->second;
- // FIXME: add prelude
+ CallInst::Create(PrepSetjmp, "", F->begin()->begin()); // FIXME: adding after other allocas might be better
// Add a basic block to "rethrow" a longjmp, that we caught but is not for us
// XXX we should call longjmp here, with proper params! return only works if the caller checks for longjmping
@@ -154,7 +158,7 @@ bool LowerEmSetjmp::runOnModule(Module &M) {
CallInst *CI;
if ((CI = dyn_cast<CallInst>(I))) {
Value *V = CI->getCalledValue();
- if (V == EmSetjmp || V == CheckLongjmp || V == GetLongjmpResult) continue;
+ if (V == PrepSetjmp || V == EmSetjmp || V == CheckLongjmp || V == GetLongjmpResult) continue;
if (Function *CF = dyn_cast<Function>(V)) if (CF->isIntrinsic()) continue;
// TODO: proper analysis of what can actually longjmp. Currently we assume anything but setjmp can.
// This may longjmp, so we need to check if it did. Split at that point.