aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2014-01-10 14:15:31 -0800
committerAlon Zakai <alonzakai@gmail.com>2014-01-10 14:18:53 -0800
commitdaf116d3a6d43e8e4ae3f10e75181fd59e2e62a6 (patch)
tree466e0971b41cb4deb3bbfa2db5df924d91370cd6
parent523fed1e29026f50003f6058fe61e28729a60e1e (diff)
wip better approach to exceptions
-rw-r--r--lib/Target/JSBackend/JSBackend.cpp4
-rw-r--r--lib/Transforms/NaCl/ExpandI64.cpp10
-rw-r--r--lib/Transforms/NaCl/ExpandVarArgs.cpp3
-rw-r--r--lib/Transforms/NaCl/LowerEmExceptionsPass.cpp107
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;
}