aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/NaCl/LowerEmExceptionsPass.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Transforms/NaCl/LowerEmExceptionsPass.cpp')
-rw-r--r--lib/Transforms/NaCl/LowerEmExceptionsPass.cpp118
1 files changed, 118 insertions, 0 deletions
diff --git a/lib/Transforms/NaCl/LowerEmExceptionsPass.cpp b/lib/Transforms/NaCl/LowerEmExceptionsPass.cpp
new file mode 100644
index 0000000000..3690537c4e
--- /dev/null
+++ b/lib/Transforms/NaCl/LowerEmExceptionsPass.cpp
@@ -0,0 +1,118 @@
+//===- LowerEmExceptions - Lower exceptions for Emscripten/JS -----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This is based off the 'cheap' version of LowerInvoke. It does two things:
+//
+// 1) Lower
+// invoke() to l1 unwind l2
+// into
+// preinvoke(); // (will clear __THREW__)
+// call();
+// threw = postinvoke(); (check __THREW__)
+// br threw, l1, l2
+//
+// 2) Lower landingpads to return a single i8*, avoid the structural type
+// which is unneeded anyhow.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Transforms/Scalar.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Intrinsics.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Target/TargetLowering.h"
+#include "llvm/Transforms/Utils/BasicBlockUtils.h"
+#include "llvm/Transforms/Utils/Local.h"
+#include "llvm/Transforms/NaCl.h"
+
+using namespace llvm;
+
+namespace {
+ class LowerEmExceptions : public ModulePass {
+ Function *PreInvoke, *PostInvoke;
+ Module *TheModule;
+
+ public:
+ static char ID; // Pass identification, replacement for typeid
+ explicit LowerEmExceptions() : ModulePass(ID), PreInvoke(NULL), PostInvoke(NULL), TheModule(NULL) {
+ initializeLowerEmExceptionsPass(*PassRegistry::getPassRegistry());
+ }
+ bool runOnModule(Module &M);
+ };
+}
+
+char LowerEmExceptions::ID = 0;
+INITIALIZE_PASS(LowerEmExceptions, "loweremexceptions",
+ "Lower invoke and unwind for js/emscripten",
+ false, false)
+
+Instruction *getSingleUse(Instruction *I) {
+ Instruction *Ret = NULL;
+ for (Instruction::use_iterator UI = I->use_begin(), UE = I->use_end(); UI != UE; ++UI) {
+ assert(Ret == NULL);
+ Ret = cast<ExtractElementInst>(*UI);
+ }
+ assert(Ret != NULL);
+ return Ret;
+}
+
+bool LowerEmExceptions::runOnModule(Module &M) {
+ TheModule = &M;
+
+ Type *Void = Type::getVoidTy(M.getContext());
+ Type *i32 = Type::getInt32Ty(M.getContext());
+
+ SmallVector<Type*, 0> ArgTypes;
+ FunctionType *VoidFunc = FunctionType::get(Void, ArgTypes, false);
+ FunctionType *IntFunc = FunctionType::get(i32, ArgTypes, false);
+
+ PreInvoke = Function::Create(VoidFunc, GlobalValue::ExternalLinkage, "preInvoke", TheModule);
+ PostInvoke = Function::Create(IntFunc, GlobalValue::ExternalLinkage, "postInvoke", TheModule);
+
+ bool Changed = false;
+
+ for (Module::iterator Iter = M.begin(), E = M.end(); Iter != E; ) {
+ Function *F = Iter++;
+ for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB) {
+ if (InvokeInst *II = dyn_cast<InvokeInst>(BB->getTerminator())) {
+ // Fix up the landingpad. First, make a copy returning just an integer
+ LandingPadInst *LP = II->getLandingPadInst();
+ unsigned Num = LP->getNumClauses();
+ LandingPadInst *NewLP = LandingPadInst::Create(i32, LP->getPersonalityFn(), Num, "", LP);
+ NewLP->setCleanup(LP->isCleanup());
+ for (unsigned i = 0; i < Num; i++) NewLP->addClause(LP->getClause(i));
+
+ // Next, replace the old LP's single use, which is an extractelement, to eliminate the ee's and use the value directly
+ ExtractElementInst *EE = cast<ExtractElementInst>(getSingleUse(LP));
+ EE->replaceAllUsesWith(NewLP);
+ EE->eraseFromParent();
+
+ // Finish the LP by replacing it
+ LP->replaceAllUsesWith(NewLP);
+ LP->eraseFromParent();
+
+ Changed = true;
+ }
+ }
+ }
+
+ return Changed;
+}
+
+ModulePass *llvm::createLowerEmExceptionsPass() {
+ return new LowerEmExceptions();
+}
+