Commit 02f3513a authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #867 from kmod/exceptions

Fix "error return without exception set"
parents be24af74 a4e3cc00
...@@ -466,7 +466,7 @@ public: ...@@ -466,7 +466,7 @@ public:
= llvm::BasicBlock::Create(g.context, curblock->getName(), irstate->getLLVMFunction()); = llvm::BasicBlock::Create(g.context, curblock->getName(), irstate->getLLVMFunction());
normal_dest->moveAfter(curblock); normal_dest->moveAfter(curblock);
llvm::BasicBlock* exc_dest = irgenerator->getCAPIExcDest(unw_info.exc_dest, unw_info.current_stmt); llvm::BasicBlock* exc_dest = irgenerator->getCAPIExcDest(curblock, unw_info.exc_dest, unw_info.current_stmt);
assert(returned_val->getType() == exc_val->getType()); assert(returned_val->getType() == exc_val->getType());
llvm::Value* check_val = getBuilder()->CreateICmpEQ(returned_val, exc_val); llvm::Value* check_val = getBuilder()->CreateICmpEQ(returned_val, exc_val);
...@@ -541,7 +541,7 @@ private: ...@@ -541,7 +541,7 @@ private:
llvm::SmallVector<ExceptionState, 2> outgoing_exc_state; llvm::SmallVector<ExceptionState, 2> outgoing_exc_state;
llvm::DenseMap<llvm::BasicBlock*, llvm::BasicBlock*> cxx_exc_dests; llvm::DenseMap<llvm::BasicBlock*, llvm::BasicBlock*> cxx_exc_dests;
llvm::DenseMap<llvm::BasicBlock*, llvm::BasicBlock*> capi_exc_dests; llvm::DenseMap<llvm::BasicBlock*, llvm::BasicBlock*> capi_exc_dests;
llvm::DenseMap<llvm::BasicBlock*, AST_stmt*> capi_current_statements; llvm::DenseMap<llvm::BasicBlock*, llvm::PHINode*> capi_phis;
enum State { enum State {
RUNNING, // normal RUNNING, // normal
...@@ -2800,24 +2800,23 @@ public: ...@@ -2800,24 +2800,23 @@ public:
// Create a (or reuse an existing) block that will catch a CAPI exception, and then forward // Create a (or reuse an existing) block that will catch a CAPI exception, and then forward
// it to the "final_dest" block. ie final_dest is a block corresponding to the IR level // it to the "final_dest" block. ie final_dest is a block corresponding to the IR level
// LANDINGPAD, and this function will createa helper block that fetches the exception. // LANDINGPAD, and this function will create a helper block that fetches the exception.
// As a special-case, a NULL value for final_dest means that this helper block should // As a special-case, a NULL value for final_dest means that this helper block should
// instead propagate the exception out of the function. // instead propagate the exception out of the function.
llvm::BasicBlock* getCAPIExcDest(llvm::BasicBlock* final_dest, AST_stmt* current_stmt) { llvm::BasicBlock* getCAPIExcDest(llvm::BasicBlock* from_block, llvm::BasicBlock* final_dest,
AST_stmt* current_stmt) {
llvm::BasicBlock*& capi_exc_dest = capi_exc_dests[final_dest]; llvm::BasicBlock*& capi_exc_dest = capi_exc_dests[final_dest];
if (capi_exc_dest) { llvm::PHINode*& phi_node = capi_phis[final_dest];
assert(capi_current_statements[final_dest] == current_stmt);
return capi_exc_dest;
}
llvm::BasicBlock* orig_block = curblock; if (!capi_exc_dest) {
auto orig_block = curblock;
capi_exc_dest = llvm::BasicBlock::Create(g.context, "", irstate->getLLVMFunction()); capi_exc_dest = llvm::BasicBlock::Create(g.context, "", irstate->getLLVMFunction());
capi_current_statements[final_dest] = current_stmt;
emitter.setCurrentBasicBlock(capi_exc_dest); emitter.setCurrentBasicBlock(capi_exc_dest);
emitter.getBuilder()->CreateCall2(g.funcs.caughtCapiException, assert(!phi_node);
embedRelocatablePtr(current_stmt, g.llvm_aststmt_type_ptr), phi_node = emitter.getBuilder()->CreatePHI(g.llvm_aststmt_type_ptr, 0);
emitter.getBuilder()->CreateCall2(g.funcs.caughtCapiException, phi_node,
embedRelocatablePtr(irstate->getSourceInfo(), g.i8_ptr)); embedRelocatablePtr(irstate->getSourceInfo(), g.i8_ptr));
if (!final_dest) { if (!final_dest) {
...@@ -2855,7 +2854,14 @@ public: ...@@ -2855,7 +2854,14 @@ public:
emitter.getBuilder()->CreateBr(final_dest); emitter.getBuilder()->CreateBr(final_dest);
} }
emitter.setCurrentBasicBlock(orig_block); emitter.setCurrentBasicBlock(from_block);
}
assert(capi_exc_dest);
assert(phi_node);
phi_node->addIncoming(embedRelocatablePtr(current_stmt, g.llvm_aststmt_type_ptr), from_block);
return capi_exc_dest; return capi_exc_dest;
} }
......
...@@ -152,7 +152,8 @@ public: ...@@ -152,7 +152,8 @@ public:
virtual void addOutgoingExceptionState(ExceptionState exception_state) = 0; virtual void addOutgoingExceptionState(ExceptionState exception_state) = 0;
virtual void setIncomingExceptionState(llvm::SmallVector<ExceptionState, 2> exc_state) = 0; virtual void setIncomingExceptionState(llvm::SmallVector<ExceptionState, 2> exc_state) = 0;
virtual llvm::BasicBlock* getCXXExcDest(llvm::BasicBlock* final_dest) = 0; virtual llvm::BasicBlock* getCXXExcDest(llvm::BasicBlock* final_dest) = 0;
virtual llvm::BasicBlock* getCAPIExcDest(llvm::BasicBlock* final_dest, AST_stmt* current_stmt) = 0; virtual llvm::BasicBlock* getCAPIExcDest(llvm::BasicBlock* from_block, llvm::BasicBlock* final_dest,
AST_stmt* current_stmt) = 0;
}; };
class IREmitter; class IREmitter;
......
...@@ -2836,9 +2836,10 @@ Box* _callattrEntry(Box* obj, BoxedString* attr, CallattrFlags flags, Box* arg1, ...@@ -2836,9 +2836,10 @@ Box* _callattrEntry(Box* obj, BoxedString* attr, CallattrFlags flags, Box* arg1,
assert(!(S == CAPI && flags.null_on_nonexistent)); assert(!(S == CAPI && flags.null_on_nonexistent));
if (!rewrite_args.out_success) { if (!rewrite_args.out_success) {
rewriter.reset(NULL); rewriter.reset(NULL);
} else if (rtn) { } else if (rtn || S == CAPI) {
rewriter->commitReturning(rewrite_args.out_rtn); rewriter->commitReturning(rewrite_args.out_rtn);
} else if ((S == CAPI && !rtn) || flags.null_on_nonexistent) { } else if (flags.null_on_nonexistent) {
assert(!rewrite_args.out_rtn);
rewriter->commitReturning(rewriter->loadConst(0, rewriter->getReturnDestination())); rewriter->commitReturning(rewriter->loadConst(0, rewriter->getReturnDestination()));
} }
} else { } else {
......
...@@ -799,6 +799,16 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo ...@@ -799,6 +799,16 @@ static Box* typeCallInner(CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Bo
// Special-case unicode for now, maybe there's something about this that can eventually be generalized: // Special-case unicode for now, maybe there's something about this that can eventually be generalized:
if (cls->tp_new == unicode_cls->tp_new) { if (cls->tp_new == unicode_cls->tp_new) {
// TODO: implement
if (S == CAPI) {
try {
return typeCallInner<CXX>(NULL, argspec, arg1, arg2, arg3, args, keyword_names);
} catch (ExcInfo e) {
setCAPIException(e);
return NULL;
}
}
assert(S == CXX && "implement me"); assert(S == CXX && "implement me");
if (rewrite_args) { if (rewrite_args) {
......
class C(object):
def f(self, n):
if n == 5000:
return
else:
raise Exception()
def f(c, i):
try:
c.f(i)
except Exception:
pass
c = C()
for i in xrange(10000):
f(c, i)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment