diff options
author | Alon Zakai <alonzakai@gmail.com> | 2014-01-10 14:15:31 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2014-01-10 14:18:53 -0800 |
commit | daf116d3a6d43e8e4ae3f10e75181fd59e2e62a6 (patch) | |
tree | 466e0971b41cb4deb3bbfa2db5df924d91370cd6 | |
parent | 523fed1e29026f50003f6058fe61e28729a60e1e (diff) |
wip better approach to exceptions
-rw-r--r-- | lib/Target/JSBackend/JSBackend.cpp | 4 | ||||
-rw-r--r-- | lib/Transforms/NaCl/ExpandI64.cpp | 10 | ||||
-rw-r--r-- | lib/Transforms/NaCl/ExpandVarArgs.cpp | 3 | ||||
-rw-r--r-- | lib/Transforms/NaCl/LowerEmExceptionsPass.cpp | 107 |
4 files changed, 90 insertions, 34 deletions
diff --git a/lib/Target/JSBackend/JSBackend.cpp b/lib/Target/JSBackend/JSBackend.cpp index 2cc66c3a4b..098b86915f 100644 --- a/lib/Target/JSBackend/JSBackend.cpp +++ b/lib/Target/JSBackend/JSBackend.cpp @@ -1256,6 +1256,10 @@ void JSWriter::generateInstruction(const Instruction *I, raw_string_ostream& Cod Code << ")|0;"; break; } + case Instruction::Resume: { + Code << "___resumeException(" + getValueAsStr(I->getOperand(0)) + "|0);"; + break; + } } // append debug info if (MDNode *N = I->getMetadata("dbg")) { diff --git a/lib/Transforms/NaCl/ExpandI64.cpp b/lib/Transforms/NaCl/ExpandI64.cpp index 0bc7cab794..eb0b9ea09a 100644 --- a/lib/Transforms/NaCl/ExpandI64.cpp +++ b/lib/Transforms/NaCl/ExpandI64.cpp @@ -829,10 +829,12 @@ void ExpandI64::ensureFuncs() { Shl = Function::Create(FourFunc, GlobalValue::ExternalLinkage, "bitshift64Shl", TheModule); - SmallVector<Type*, 0> GetHighArgTypes; - FunctionType *GetHighFunc = FunctionType::get(i32, GetHighArgTypes, false); - GetHigh = Function::Create(GetHighFunc, GlobalValue::ExternalLinkage, - "getHigh32", TheModule); + if (!TheModule->getFunction("getHigh32")) { + SmallVector<Type*, 0> GetHighArgTypes; + FunctionType *GetHighFunc = FunctionType::get(i32, GetHighArgTypes, false); + GetHigh = Function::Create(GetHighFunc, GlobalValue::ExternalLinkage, + "getHigh32", TheModule); + } Type *V = Type::getVoidTy(TheModule->getContext()); diff --git a/lib/Transforms/NaCl/ExpandVarArgs.cpp b/lib/Transforms/NaCl/ExpandVarArgs.cpp index 089a8170d9..a24f0d111d 100644 --- a/lib/Transforms/NaCl/ExpandVarArgs.cpp +++ b/lib/Transforms/NaCl/ExpandVarArgs.cpp @@ -68,7 +68,8 @@ INITIALIZE_PASS(ExpandVarArgs, "expand-varargs", static bool isEmscriptenJSArgsFunc(StringRef Name) { return Name.equals("emscripten_asm_const_int") || - Name.equals("emscripten_asm_const_double"); + Name.equals("emscripten_asm_const_double") || + Name.equals("emscripten_landingpad"); } static void ExpandVarArgFunc(Function *Func) { diff --git a/lib/Transforms/NaCl/LowerEmExceptionsPass.cpp b/lib/Transforms/NaCl/LowerEmExceptionsPass.cpp index 3690537c4e..fdf78bf6eb 100644 --- a/lib/Transforms/NaCl/LowerEmExceptionsPass.cpp +++ b/lib/Transforms/NaCl/LowerEmExceptionsPass.cpp @@ -37,17 +37,33 @@ #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/Local.h" #include "llvm/Transforms/NaCl.h" +#include <vector> + +#include "llvm/Support/raw_ostream.h" +#include <stdio.h> +#define dump(x) fprintf(stderr, x "\n") +#define dumpv(x, ...) fprintf(stderr, x "\n", __VA_ARGS__) +#define dumpfail(x) { fprintf(stderr, x "\n"); fprintf(stderr, "%s : %d\n", __FILE__, __LINE__); report_fatal_error("fail"); } +#define dumpfailv(x, ...) { fprintf(stderr, x "\n", __VA_ARGS__); fprintf(stderr, "%s : %d\n", __FILE__, __LINE__); report_fatal_error("fail"); } +#define dumpIR(value) { \ + std::string temp; \ + raw_string_ostream stream(temp); \ + stream << *(value); \ + fprintf(stderr, "%s\n", temp.c_str()); \ +} +#undef assert +#define assert(x) { if (!(x)) dumpfail(#x); } using namespace llvm; namespace { class LowerEmExceptions : public ModulePass { - Function *PreInvoke, *PostInvoke; + Function *GetHigh, *PreInvoke, *PostInvoke, *LandingPad; Module *TheModule; public: static char ID; // Pass identification, replacement for typeid - explicit LowerEmExceptions() : ModulePass(ID), PreInvoke(NULL), PostInvoke(NULL), TheModule(NULL) { + explicit LowerEmExceptions() : ModulePass(ID), GetHigh(NULL), PreInvoke(NULL), PostInvoke(NULL), LandingPad(NULL), TheModule(NULL) { initializeLowerEmExceptionsPass(*PassRegistry::getPassRegistry()); } bool runOnModule(Module &M); @@ -59,56 +75,89 @@ 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()); + // Add functions + Type *i32 = Type::getInt32Ty(M.getContext()); + Type *i8 = Type::getInt8Ty(M.getContext()); + Type *i1 = Type::getInt1Ty(M.getContext()); + Type *i8P = i8->getPointerTo(); + Type *Void = Type::getVoidTy(M.getContext()); + + if (!TheModule->getFunction("getHigh32")) { + FunctionType *GetHighFunc = FunctionType::get(i32, false); + GetHigh = Function::Create(GetHighFunc, GlobalValue::ExternalLinkage, + "getHigh32", TheModule); + } - SmallVector<Type*, 0> ArgTypes; - FunctionType *VoidFunc = FunctionType::get(Void, ArgTypes, false); - FunctionType *IntFunc = FunctionType::get(i32, ArgTypes, false); + FunctionType *VoidFunc = FunctionType::get(Void, false); + PreInvoke = Function::Create(VoidFunc, GlobalValue::ExternalLinkage, "emscripten_preinvoke", TheModule); - PreInvoke = Function::Create(VoidFunc, GlobalValue::ExternalLinkage, "preInvoke", TheModule); - PostInvoke = Function::Create(IntFunc, GlobalValue::ExternalLinkage, "postInvoke", TheModule); + FunctionType *Int1Func = FunctionType::get(i1, false); + PostInvoke = Function::Create(Int1Func, GlobalValue::ExternalLinkage, "emscripten_postinvoke", TheModule); + + FunctionType *LandingPadFunc = FunctionType::get(i32, true); + LandingPad = Function::Create(LandingPadFunc, GlobalValue::ExternalLinkage, "emscripten_landingpad", TheModule); + + // Process bool Changed = false; + std::vector<Instruction*> ToErase; + 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 + // 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); + + // Insert a branch based on the postInvoke + BranchInst::Create(II->getNormalDest(), II->getUnwindDest(), Post, II); + + // Replace the landingpad with a landingpad call to get the low part, and a getHigh for the high 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)); + SmallVector<Value*,16> NewLPArgs; + NewLPArgs.push_back(LP->getPersonalityFn()); + for (unsigned i = 0; i < Num; i++) NewLPArgs.push_back(LP->getClause(i)); + NewLPArgs.push_back(LP->isCleanup() ? ConstantInt::getTrue(i1) : ConstantInt::getFalse(i1)); + CallInst *NewLP = CallInst::Create(LandingPad, NewLPArgs, "", LP); - // 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(); + Instruction *High = CallInst::Create(GetHigh, "", LP); - // Finish the LP by replacing it - LP->replaceAllUsesWith(NewLP); - LP->eraseFromParent(); + // New recreate an aggregate for them, which will be all simplified later (simplification cannot handle landingpad, hence all this) + SmallVector<unsigned, 1> IVArgsA; + IVArgsA.push_back(0); + InsertValueInst *IVA = InsertValueInst::Create(UndefValue::get(LP->getType()), NewLP, IVArgsA, "", LP); + SmallVector<unsigned, 1> IVArgsB; + IVArgsB.push_back(1); + InsertValueInst *IVB = InsertValueInst::Create(IVA, High, IVArgsB, "", LP); + + LP->replaceAllUsesWith(IVB); + ToErase.push_back(LP); Changed = true; } } } + for (unsigned i = 0; i < ToErase.size(); i++) ToErase[i]->eraseFromParent(); + return Changed; } |