aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/NaCl/LowerEmExceptionsPass.cpp
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2014-01-21 12:52:35 -0800
committerAlon Zakai <alonzakai@gmail.com>2014-01-21 12:52:35 -0800
commitbaa51c9f0de42aa1194a5b93400b82f3b071bca1 (patch)
tree2bc642f9954c56e53ace9b6c00bccdeb2468ec61 /lib/Transforms/NaCl/LowerEmExceptionsPass.cpp
parent6367ccb17a347bb3cf80ca21858d4869ae84c4da (diff)
do not emit pre|postinvoke calls around calls that cannot possibly throw an exception
Diffstat (limited to 'lib/Transforms/NaCl/LowerEmExceptionsPass.cpp')
-rw-r--r--lib/Transforms/NaCl/LowerEmExceptionsPass.cpp71
1 files changed, 51 insertions, 20 deletions
diff --git a/lib/Transforms/NaCl/LowerEmExceptionsPass.cpp b/lib/Transforms/NaCl/LowerEmExceptionsPass.cpp
index c35dbba4a9..27d9004bd1 100644
--- a/lib/Transforms/NaCl/LowerEmExceptionsPass.cpp
+++ b/lib/Transforms/NaCl/LowerEmExceptionsPass.cpp
@@ -81,6 +81,15 @@ INITIALIZE_PASS(LowerEmExceptions, "loweremexceptions",
"Lower invoke and unwind for js/emscripten",
false, false)
+bool canThrow(Value *V) {
+ if (Function *F = dyn_cast<Function>(V)) {
+ // intrinsics and some emscripten builtins cannot throw
+ if (F->isIntrinsic() || F->getName().startswith("emscripten_asm_")) return false;
+ return true;
+ }
+ return true; // not a function, so an indirect call - can throw, we can't tell
+}
+
bool LowerEmExceptions::runOnModule(Module &M) {
TheModule = &M;
@@ -136,26 +145,48 @@ bool LowerEmExceptions::runOnModule(Module &M) {
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
// check terminator for invokes
if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) {
- // Insert a normal call instruction folded in between pre- and post-invoke
- CallInst *Pre = CallInst::Create(PreInvoke, "", II);
-
- SmallVector<Value*,16> CallArgs(II->op_begin(), II->op_end() - 3);
- CallInst *NewCall = CallInst::Create(II->getCalledValue(),
- CallArgs, "", II);
- NewCall->takeName(II);
- NewCall->setCallingConv(II->getCallingConv());
- NewCall->setAttributes(II->getAttributes());
- NewCall->setDebugLoc(II->getDebugLoc());
- II->replaceAllUsesWith(NewCall);
- ToErase.push_back(II);
-
- CallInst *Post = CallInst::Create(PostInvoke, "", II);
- Instruction *Post1 = new TruncInst(Post, i1, "", II);
-
- // Insert a branch based on the postInvoke
- BranchInst::Create(II->getUnwindDest(), II->getNormalDest(), Post1, II);
-
- LandingPads.insert(II->getLandingPadInst());
+ bool NeedInvoke = canThrow(II->getCalledValue());
+
+ if (NeedInvoke) {
+ // Insert a normal call instruction folded in between pre- and post-invoke
+ CallInst *Pre = CallInst::Create(PreInvoke, "", II);
+
+ SmallVector<Value*,16> CallArgs(II->op_begin(), II->op_end() - 3);
+ CallInst *NewCall = CallInst::Create(II->getCalledValue(),
+ CallArgs, "", II);
+ NewCall->takeName(II);
+ NewCall->setCallingConv(II->getCallingConv());
+ NewCall->setAttributes(II->getAttributes());
+ NewCall->setDebugLoc(II->getDebugLoc());
+ II->replaceAllUsesWith(NewCall);
+ ToErase.push_back(II);
+
+ CallInst *Post = CallInst::Create(PostInvoke, "", II);
+ Instruction *Post1 = new TruncInst(Post, i1, "", II);
+
+ // Insert a branch based on the postInvoke
+ BranchInst::Create(II->getUnwindDest(), II->getNormalDest(), Post1, II);
+
+ LandingPads.insert(II->getLandingPadInst());
+ } else {
+ // This can't throw, and we don't need this invoke, just replace it with a call+branch
+ SmallVector<Value*,16> CallArgs(II->op_begin(), II->op_end() - 3);
+ CallInst *NewCall = CallInst::Create(II->getCalledValue(),
+ CallArgs, "", II);
+ NewCall->takeName(II);
+ NewCall->setCallingConv(II->getCallingConv());
+ NewCall->setAttributes(II->getAttributes());
+ NewCall->setDebugLoc(II->getDebugLoc());
+ II->replaceAllUsesWith(NewCall);
+ ToErase.push_back(II);
+
+ BranchInst::Create(II->getNormalDest(), II);
+
+ // Remove any PHI node entries from the exception destination.
+ II->getUnwindDest()->removePredecessor(BB);
+
+ LandingPads.insert(II->getLandingPadInst());
+ }
Changed = true;
}