Commit 1077e7f2 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Check CAPI exceptions before signals

Previously we would check signals first.  Which means that we would then
call into a signal handler with an active exception, which would later
trigger asserts.

For CXX functions, the exception automatically wins over the signal checking.
CPython also checks signals first.

The only tricky thing is that this was happening because the signals stuff
was hooked deeper down the stack.  So pass down the CAPI-exception data as well.
parent efd8ce63
...@@ -347,10 +347,9 @@ public: ...@@ -347,10 +347,9 @@ public:
cstop = slice_val.stop ? slice_val.stop->makeConverted(emitter, UNKNOWN)->getValue() cstop = slice_val.stop ? slice_val.stop->makeConverted(emitter, UNKNOWN)->getValue()
: emitter.setType(getNullPtr(g.llvm_value_type_ptr), RefType::BORROWED); : emitter.setType(getNullPtr(g.llvm_value_type_ptr), RefType::BORROWED);
llvm::Value* r llvm::Value* r = emitter.createCall3(info.unw_info, g.funcs.apply_slice, var->getValue(), cstart,
= emitter.createCall3(info.unw_info, g.funcs.apply_slice, var->getValue(), cstart, cstop); cstop, CAPI, getNullPtr(g.llvm_value_type_ptr));
emitter.setType(r, RefType::OWNED); emitter.setType(r, RefType::OWNED);
emitter.checkAndPropagateCapiException(info.unw_info, r, getNullPtr(g.llvm_value_type_ptr));
return new ConcreteCompilerVariable(static_cast<ConcreteCompilerType*>(return_type), r); return new ConcreteCompilerVariable(static_cast<ConcreteCompilerType*>(return_type), r);
} else { } else {
...@@ -375,20 +374,18 @@ public: ...@@ -375,20 +374,18 @@ public:
llvm::Value* uncasted llvm::Value* uncasted
= emitter.createIC(pp, (void*)(target_exception_style == CAPI ? pyston::getitem_capi : pyston::getitem), = emitter.createIC(pp, (void*)(target_exception_style == CAPI ? pyston::getitem_capi : pyston::getitem),
llvm_args, info.unw_info, target_exception_style); llvm_args, info.unw_info, target_exception_style, getNullPtr(g.llvm_value_type_ptr));
rtn = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr); rtn = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr);
emitter.setType(rtn, RefType::OWNED); emitter.setType(rtn, RefType::OWNED);
} else { } else {
rtn = emitter.createCall2(info.unw_info, rtn = emitter.createCall2(
target_exception_style == CAPI ? g.funcs.getitem_capi : g.funcs.getitem, info.unw_info, target_exception_style == CAPI ? g.funcs.getitem_capi : g.funcs.getitem, var->getValue(),
var->getValue(), converted_slice->getValue(), target_exception_style); converted_slice->getValue(), target_exception_style, getNullPtr(g.llvm_value_type_ptr));
emitter.setType(rtn, RefType::OWNED); emitter.setType(rtn, RefType::OWNED);
} }
if (target_exception_style == CAPI) { if (target_exception_style == CAPI)
emitter.setNullable(rtn, true); emitter.setNullable(rtn, true);
emitter.checkAndPropagateCapiException(info.unw_info, rtn, getNullPtr(g.llvm_value_type_ptr));
}
return new ConcreteCompilerVariable(UNKNOWN, rtn); return new ConcreteCompilerVariable(UNKNOWN, rtn);
} }
...@@ -564,19 +561,18 @@ CompilerVariable* UnknownType::getattr(IREmitter& emitter, const OpInfo& info, C ...@@ -564,19 +561,18 @@ CompilerVariable* UnknownType::getattr(IREmitter& emitter, const OpInfo& info, C
llvm_args.push_back(var->getValue()); llvm_args.push_back(var->getValue());
llvm_args.push_back(ptr); llvm_args.push_back(ptr);
llvm::Value* uncasted = emitter.createIC(pp, raw_func, llvm_args, info.unw_info, target_exception_style); llvm::Value* uncasted = emitter.createIC(pp, raw_func, llvm_args, info.unw_info, target_exception_style,
getNullPtr(g.llvm_value_type_ptr));
rtn_val = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr); rtn_val = emitter.getBuilder()->CreateIntToPtr(uncasted, g.llvm_value_type_ptr);
} else { } else {
rtn_val = emitter.createCall2(info.unw_info, llvm_func, var->getValue(), ptr, target_exception_style); rtn_val = emitter.createCall2(info.unw_info, llvm_func, var->getValue(), ptr, target_exception_style,
getNullPtr(g.llvm_value_type_ptr));
} }
emitter.setType(rtn_val, RefType::OWNED); emitter.setType(rtn_val, RefType::OWNED);
if (target_exception_style == CAPI) if (target_exception_style == CAPI)
emitter.setNullable(rtn_val, true); emitter.setNullable(rtn_val, true);
if (target_exception_style == CAPI)
emitter.checkAndPropagateCapiException(info.unw_info, rtn_val, getNullPtr(g.llvm_value_type_ptr));
return new ConcreteCompilerVariable(UNKNOWN, rtn_val); return new ConcreteCompilerVariable(UNKNOWN, rtn_val);
} }
...@@ -664,7 +660,8 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l ...@@ -664,7 +660,8 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
ICSetupInfo* pp = createCallsiteIC(info.getTypeRecorder(), args.size(), info.getBJitICInfo()); ICSetupInfo* pp = createCallsiteIC(info.getTypeRecorder(), args.size(), info.getBJitICInfo());
llvm::Instruction* uncasted = emitter.createIC(pp, func_addr, llvm_args, info.unw_info, target_exception_style); llvm::Instruction* uncasted = emitter.createIC(pp, func_addr, llvm_args, info.unw_info, target_exception_style,
getNullPtr(g.llvm_value_type_ptr));
inst = uncasted; inst = uncasted;
assert(llvm::cast<llvm::FunctionType>(llvm::cast<llvm::PointerType>(func->getType())->getElementType()) assert(llvm::cast<llvm::FunctionType>(llvm::cast<llvm::PointerType>(func->getType())->getElementType())
...@@ -679,7 +676,8 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l ...@@ -679,7 +676,8 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
//} //}
// printf("%ld %ld\n", llvm_args.size(), args.size()); // printf("%ld %ld\n", llvm_args.size(), args.size());
// printf("\n"); // printf("\n");
inst = emitter.createCall(info.unw_info, func, llvm_args, target_exception_style); inst = emitter.createCall(info.unw_info, func, llvm_args, target_exception_style,
getNullPtr(g.llvm_value_type_ptr));
rtn = inst; rtn = inst;
} }
...@@ -690,10 +688,6 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l ...@@ -690,10 +688,6 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
} }
assert(rtn->getType() == rtn_type->llvmType()); assert(rtn->getType() == rtn_type->llvmType());
if (target_exception_style == CAPI) {
emitter.checkAndPropagateCapiException(info.unw_info, rtn, getNullPtr(g.llvm_value_type_ptr));
}
for (auto v : array_passed_args) for (auto v : array_passed_args)
emitter.refUsed(v, inst); emitter.refUsed(v, inst);
...@@ -1778,13 +1772,11 @@ public: ...@@ -1778,13 +1772,11 @@ public:
: g.funcs.raiseAttributeErrorStrCapi; : g.funcs.raiseAttributeErrorStrCapi;
llvm::CallSite call = emitter.createCall3( llvm::CallSite call = emitter.createCall3(
info.unw_info, raise_func, embedRelocatablePtr(cls->tp_name, g.i8_ptr), info.unw_info, raise_func, embedRelocatablePtr(cls->tp_name, g.i8_ptr),
embedRelocatablePtr(attr->data(), g.i8_ptr), getConstantInt(attr->size(), g.i64), exception_style); embedRelocatablePtr(attr->data(), g.i8_ptr), getConstantInt(attr->size(), g.i64), exception_style,
if (exception_style == CAPI) { IREmitter::ALWAYS_THROWS);
emitter.checkAndPropagateCapiException(info.unw_info, getNullPtr(g.llvm_value_type_ptr),
getNullPtr(g.llvm_value_type_ptr)); if (exception_style == CXX)
} else {
call.setDoesNotReturn(); call.setDoesNotReturn();
}
return undefVariable(); return undefVariable();
} }
...@@ -1841,14 +1833,11 @@ public: ...@@ -1841,14 +1833,11 @@ public:
llvm::CallSite call = emitter.createCall3( llvm::CallSite call = emitter.createCall3(
info.unw_info, raise_func, embedRelocatablePtr(cls->tp_name, g.i8_ptr), info.unw_info, raise_func, embedRelocatablePtr(cls->tp_name, g.i8_ptr),
emitter.setType(embedRelocatablePtr(attr->data(), g.i8_ptr), RefType::BORROWED), emitter.setType(embedRelocatablePtr(attr->data(), g.i8_ptr), RefType::BORROWED),
getConstantInt(attr->size(), g.i64), exception_style); getConstantInt(attr->size(), g.i64), exception_style, IREmitter::ALWAYS_THROWS);
if (exception_style == CAPI) {
emitter.checkAndPropagateCapiException(info.unw_info, getNullPtr(g.llvm_value_type_ptr), if (exception_style == CXX)
getNullPtr(g.llvm_value_type_ptr));
} else {
call.setDoesNotReturn(); call.setDoesNotReturn();
} }
}
return undefVariable(); return undefVariable();
} }
...@@ -2087,9 +2076,9 @@ public: ...@@ -2087,9 +2076,9 @@ public:
g.llvm_value_type_ptr, { g.llvm_value_type_ptr, g.i64, g.i64 }, false); g.llvm_value_type_ptr, { g.llvm_value_type_ptr, g.i64, g.i64 }, false);
llvm::Value* r = emitter.createCall3( llvm::Value* r = emitter.createCall3(
info.unw_info, embedConstantPtr((void*)PySequence_GetSlice, ft->getPointerTo()), info.unw_info, embedConstantPtr((void*)PySequence_GetSlice, ft->getPointerTo()),
var->getValue(), start, stop); var->getValue(), start, stop, CAPI, getNullPtr(g.llvm_value_type_ptr));
emitter.setType(r, RefType::OWNED); emitter.setType(r, RefType::OWNED);
emitter.checkAndPropagateCapiException(info.unw_info, r, getNullPtr(g.llvm_value_type_ptr)); emitter.setNullable(r, true);
return new ConcreteCompilerVariable(static_cast<ConcreteCompilerType*>(return_type), r); return new ConcreteCompilerVariable(static_cast<ConcreteCompilerType*>(return_type), r);
} }
...@@ -2561,10 +2550,9 @@ public: ...@@ -2561,10 +2550,9 @@ public:
ExceptionStyle target_exception_style = info.preferredExceptionStyle(); ExceptionStyle target_exception_style = info.preferredExceptionStyle();
if (target_exception_style == CAPI) { if (target_exception_style == CAPI) {
llvm::CallSite call = emitter.createCall(info.unw_info, g.funcs.raiseIndexErrorStrCapi, llvm::CallSite call
embedConstantPtr("tuple", g.i8_ptr), CAPI); = emitter.createCall(info.unw_info, g.funcs.raiseIndexErrorStrCapi,
emitter.checkAndPropagateCapiException(info.unw_info, getNullPtr(g.llvm_value_type_ptr), embedConstantPtr("tuple", g.i8_ptr), CAPI, IREmitter::ALWAYS_THROWS);
getNullPtr(g.llvm_value_type_ptr));
} else { } else {
llvm::CallSite call = emitter.createCall(info.unw_info, g.funcs.raiseIndexErrorStr, llvm::CallSite call = emitter.createCall(info.unw_info, g.funcs.raiseIndexErrorStr,
embedConstantPtr("tuple", g.i8_ptr), CXX); embedConstantPtr("tuple", g.i8_ptr), CXX);
......
...@@ -86,23 +86,32 @@ public: ...@@ -86,23 +86,32 @@ public:
virtual llvm::Function* getIntrinsic(llvm::Intrinsic::ID) = 0; virtual llvm::Function* getIntrinsic(llvm::Intrinsic::ID) = 0;
// Special value for capi_exc_value that says that the target function always sets a capi exception.
static llvm::Value* ALWAYS_THROWS;
virtual llvm::Instruction* createCall(const UnwindInfo& unw_info, llvm::Value* callee, virtual llvm::Instruction* createCall(const UnwindInfo& unw_info, llvm::Value* callee,
const std::vector<llvm::Value*>& args, const std::vector<llvm::Value*>& args,
ExceptionStyle target_exception_style = CXX) = 0; ExceptionStyle target_exception_style = CXX,
llvm::Value* capi_exc_value = NULL) = 0;
virtual llvm::Instruction* createCall(const UnwindInfo& unw_info, llvm::Value* callee, virtual llvm::Instruction* createCall(const UnwindInfo& unw_info, llvm::Value* callee,
ExceptionStyle target_exception_style = CXX) = 0; ExceptionStyle target_exception_style = CXX,
llvm::Value* capi_exc_value = NULL) = 0;
virtual llvm::Instruction* createCall(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1, virtual llvm::Instruction* createCall(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1,
ExceptionStyle target_exception_style = CXX) = 0; ExceptionStyle target_exception_style = CXX,
llvm::Value* capi_exc_value = NULL) = 0;
virtual llvm::Instruction* createCall2(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1, virtual llvm::Instruction* createCall2(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1,
llvm::Value* arg2, ExceptionStyle target_exception_style = CXX) = 0; llvm::Value* arg2, ExceptionStyle target_exception_style = CXX,
llvm::Value* capi_exc_value = NULL) = 0;
virtual llvm::Instruction* createCall3(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1, virtual llvm::Instruction* createCall3(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1,
llvm::Value* arg2, llvm::Value* arg3, llvm::Value* arg2, llvm::Value* arg3,
ExceptionStyle target_exception_style = CXX) = 0; ExceptionStyle target_exception_style = CXX,
llvm::Value* capi_exc_value = NULL) = 0;
virtual llvm::Instruction* createIC(const ICSetupInfo* pp, void* func_addr, const std::vector<llvm::Value*>& args, virtual llvm::Instruction* createIC(const ICSetupInfo* pp, void* func_addr, const std::vector<llvm::Value*>& args,
const UnwindInfo& unw_info, ExceptionStyle target_exception_style = CXX) = 0; const UnwindInfo& unw_info, ExceptionStyle target_exception_style = CXX,
llvm::Value* capi_exc_value = NULL) = 0;
virtual void checkAndPropagateCapiException(const UnwindInfo& unw_info, llvm::Value* returned_val, // virtual void checkAndPropagateCapiException(const UnwindInfo& unw_info, llvm::Value* returned_val,
llvm::Value* exc_val, bool double_check = false) = 0; // llvm::Value* exc_val, bool double_check = false) = 0;
virtual llvm::Value* createDeopt(AST_stmt* current_stmt, AST_expr* node, llvm::Value* node_value) = 0; virtual llvm::Value* createDeopt(AST_stmt* current_stmt, AST_expr* node, llvm::Value* node_value) = 0;
......
...@@ -353,6 +353,8 @@ llvm::Value* IRGenState::getGlobalsIfCustom() { ...@@ -353,6 +353,8 @@ llvm::Value* IRGenState::getGlobalsIfCustom() {
// XXX This is pretty hacky, but I think I can get rid of it once I merge in Marius's new frame introspection work // XXX This is pretty hacky, but I think I can get rid of it once I merge in Marius's new frame introspection work
#define NO_CXX_INTERCEPTION ((llvm::BasicBlock*)-1) #define NO_CXX_INTERCEPTION ((llvm::BasicBlock*)-1)
llvm::Value* IREmitter::ALWAYS_THROWS = ((llvm::Value*)1);
class IREmitterImpl : public IREmitter { class IREmitterImpl : public IREmitter {
private: private:
IRGenState* irstate; IRGenState* irstate;
...@@ -404,10 +406,39 @@ private: ...@@ -404,10 +406,39 @@ private:
setCurrentBasicBlock(join_block); setCurrentBasicBlock(join_block);
} }
void checkAndPropagateCapiException(const UnwindInfo& unw_info, llvm::Value* returned_val, llvm::Value* exc_val,
bool double_check = false) {
assert(!double_check); // need to call PyErr_Occurred
assert(exc_val);
llvm::BasicBlock* normal_dest
= llvm::BasicBlock::Create(g.context, curblock->getName(), irstate->getLLVMFunction());
normal_dest->moveAfter(curblock);
llvm::BasicBlock* exc_dest = irgenerator->getCAPIExcDest(curblock, unw_info.exc_dest, unw_info.current_stmt);
if (exc_val == ALWAYS_THROWS) {
assert(returned_val->getType() == g.void_);
llvm::BasicBlock* exc_dest = irgenerator->getCAPIExcDest(curblock, unw_info.exc_dest, unw_info.current_stmt);
getBuilder()->CreateBr(exc_dest);
} else {
assert(returned_val->getType() == exc_val->getType());
llvm::Value* check_val = getBuilder()->CreateICmpEQ(returned_val, exc_val);
llvm::BranchInst* nullcheck = getBuilder()->CreateCondBr(check_val, exc_dest, normal_dest);
}
setCurrentBasicBlock(normal_dest);
}
llvm::CallSite emitCall(const UnwindInfo& unw_info, llvm::Value* callee, const std::vector<llvm::Value*>& args, llvm::CallSite emitCall(const UnwindInfo& unw_info, llvm::Value* callee, const std::vector<llvm::Value*>& args,
ExceptionStyle target_exception_style) { ExceptionStyle target_exception_style, llvm::Value* capi_exc_value) {
emitSetCurrentStmt(unw_info.current_stmt); emitSetCurrentStmt(unw_info.current_stmt);
if (target_exception_style == CAPI)
assert(capi_exc_value);
bool needs_cxx_interception; bool needs_cxx_interception;
if (unw_info.exc_dest == NO_CXX_INTERCEPTION) { if (unw_info.exc_dest == NO_CXX_INTERCEPTION) {
needs_cxx_interception = false; needs_cxx_interception = false;
...@@ -434,6 +465,8 @@ private: ...@@ -434,6 +465,8 @@ private:
llvm::InvokeInst* rtn = getBuilder()->CreateInvoke(callee, normal_dest, exc_dest, args); llvm::InvokeInst* rtn = getBuilder()->CreateInvoke(callee, normal_dest, exc_dest, args);
ASSERT(target_exception_style == CXX, "otherwise need to call checkAndPropagateCapiException");
// Note -- this code can often create critical edges between LLVM blocks. // Note -- this code can often create critical edges between LLVM blocks.
// The refcounting system has some support for handling this, but if we start generating // The refcounting system has some support for handling this, but if we start generating
// IR that it can't handle, we might have to break the critical edges here (or teach the // IR that it can't handle, we might have to break the critical edges here (or teach the
...@@ -448,8 +481,11 @@ private: ...@@ -448,8 +481,11 @@ private:
emitPendingCallsCheck(NULL); emitPendingCallsCheck(NULL);
return rtn; return rtn;
} else { } else {
llvm::CallInst* cs = getBuilder()->CreateCall(callee, args); llvm::CallInst* cs = getBuilder()->CreateCall(callee, args);
if (target_exception_style == CAPI)
checkAndPropagateCapiException(unw_info, cs, capi_exc_value);
emitPendingCallsCheck(NULL); emitPendingCallsCheck(NULL);
return cs; return cs;
} }
...@@ -458,10 +494,13 @@ private: ...@@ -458,10 +494,13 @@ private:
llvm::CallSite emitPatchpoint(llvm::Type* return_type, const ICSetupInfo* pp, llvm::Value* func, llvm::CallSite emitPatchpoint(llvm::Type* return_type, const ICSetupInfo* pp, llvm::Value* func,
const std::vector<llvm::Value*>& args, const std::vector<llvm::Value*>& args,
const std::vector<llvm::Value*>& ic_stackmap_args, const UnwindInfo& unw_info, const std::vector<llvm::Value*>& ic_stackmap_args, const UnwindInfo& unw_info,
ExceptionStyle target_exception_style) { ExceptionStyle target_exception_style, llvm::Value* capi_exc_value) {
if (pp == NULL) if (pp == NULL)
assert(ic_stackmap_args.size() == 0); assert(ic_stackmap_args.size() == 0);
if (target_exception_style == CAPI)
assert(capi_exc_value);
// Retrieve address of called function, currently handles the IR // Retrieve address of called function, currently handles the IR
// embedConstantPtr() and embedRelocatablePtr() create. // embedConstantPtr() and embedRelocatablePtr() create.
void* func_addr = nullptr; void* func_addr = nullptr;
...@@ -504,6 +543,9 @@ private: ...@@ -504,6 +543,9 @@ private:
llvm::Intrinsic::ID intrinsic_id; llvm::Intrinsic::ID intrinsic_id;
if (return_type->isIntegerTy() || return_type->isPointerTy()) { if (return_type->isIntegerTy() || return_type->isPointerTy()) {
intrinsic_id = llvm::Intrinsic::experimental_patchpoint_i64; intrinsic_id = llvm::Intrinsic::experimental_patchpoint_i64;
if (capi_exc_value && capi_exc_value->getType()->isPointerTy())
capi_exc_value = getBuilder()->CreatePtrToInt(capi_exc_value, g.i64);
} else if (return_type->isVoidTy()) { } else if (return_type->isVoidTy()) {
intrinsic_id = llvm::Intrinsic::experimental_patchpoint_void; intrinsic_id = llvm::Intrinsic::experimental_patchpoint_void;
} else if (return_type->isDoubleTy()) { } else if (return_type->isDoubleTy()) {
...@@ -513,7 +555,7 @@ private: ...@@ -513,7 +555,7 @@ private:
abort(); abort();
} }
llvm::Function* patchpoint = this->getIntrinsic(intrinsic_id); llvm::Function* patchpoint = this->getIntrinsic(intrinsic_id);
llvm::CallSite rtn = this->emitCall(unw_info, patchpoint, pp_args, target_exception_style); llvm::CallSite rtn = this->emitCall(unw_info, patchpoint, pp_args, target_exception_style, capi_exc_value);
return rtn; return rtn;
} }
...@@ -564,7 +606,7 @@ public: ...@@ -564,7 +606,7 @@ public:
llvm::Instruction* createCall(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Instruction* createCall(const UnwindInfo& unw_info, llvm::Value* callee,
const std::vector<llvm::Value*>& args, const std::vector<llvm::Value*>& args,
ExceptionStyle target_exception_style = CXX) override { ExceptionStyle target_exception_style = CXX, llvm::Value* capi_exc_value = NULL) override {
#ifndef NDEBUG #ifndef NDEBUG
// Copied the argument-type-checking from CallInst::init, since the patchpoint arguments don't // Copied the argument-type-checking from CallInst::init, since the patchpoint arguments don't
// get checked. // get checked.
...@@ -582,36 +624,42 @@ public: ...@@ -582,36 +624,42 @@ public:
} }
} }
#endif #endif
return emitCall(unw_info, callee, args, target_exception_style).getInstruction(); return emitCall(unw_info, callee, args, target_exception_style, capi_exc_value).getInstruction();
} }
llvm::Instruction* createCall(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Instruction* createCall(const UnwindInfo& unw_info, llvm::Value* callee,
ExceptionStyle target_exception_style = CXX) override { ExceptionStyle target_exception_style = CXX,
return createCall(unw_info, callee, std::vector<llvm::Value*>(), target_exception_style); llvm::Value* capi_exc_value = NULL) override {
return createCall(unw_info, callee, std::vector<llvm::Value*>(), target_exception_style, capi_exc_value);
} }
llvm::Instruction* createCall(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1, llvm::Instruction* createCall(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1,
ExceptionStyle target_exception_style = CXX) override { ExceptionStyle target_exception_style = CXX,
return createCall(unw_info, callee, std::vector<llvm::Value*>({ arg1 }), target_exception_style); llvm::Value* capi_exc_value = NULL) override {
return createCall(unw_info, callee, std::vector<llvm::Value*>({ arg1 }), target_exception_style,
capi_exc_value);
} }
llvm::Instruction* createCall2(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1, llvm::Value* arg2, llvm::Instruction* createCall2(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1,
ExceptionStyle target_exception_style = CXX) override { llvm::Value* arg2, ExceptionStyle target_exception_style = CXX,
return createCall(unw_info, callee, { arg1, arg2 }, target_exception_style); llvm::Value* capi_exc_value = NULL) override {
return createCall(unw_info, callee, { arg1, arg2 }, target_exception_style, capi_exc_value);
} }
llvm::Instruction* createCall3(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1, llvm::Value* arg2, llvm::Instruction* createCall3(const UnwindInfo& unw_info, llvm::Value* callee, llvm::Value* arg1,
llvm::Value* arg3, ExceptionStyle target_exception_style = CXX) override { llvm::Value* arg2, llvm::Value* arg3, ExceptionStyle target_exception_style = CXX,
return createCall(unw_info, callee, { arg1, arg2, arg3 }, target_exception_style); llvm::Value* capi_exc_value = NULL) override {
return createCall(unw_info, callee, { arg1, arg2, arg3 }, target_exception_style, capi_exc_value);
} }
llvm::Instruction* createIC(const ICSetupInfo* pp, void* func_addr, const std::vector<llvm::Value*>& args, llvm::Instruction* createIC(const ICSetupInfo* pp, void* func_addr, const std::vector<llvm::Value*>& args,
const UnwindInfo& unw_info, ExceptionStyle target_exception_style = CXX) override { const UnwindInfo& unw_info, ExceptionStyle target_exception_style = CXX,
llvm::Value* capi_exc_value = NULL) override {
std::vector<llvm::Value*> stackmap_args; std::vector<llvm::Value*> stackmap_args;
llvm::CallSite rtn = emitPatchpoint(pp->hasReturnValue() ? g.i64 : g.void_, pp, llvm::CallSite rtn = emitPatchpoint(pp->hasReturnValue() ? g.i64 : g.void_, pp,
embedConstantPtr(func_addr, g.i8->getPointerTo()), args, stackmap_args, embedConstantPtr(func_addr, g.i8->getPointerTo()), args, stackmap_args,
unw_info, target_exception_style); unw_info, target_exception_style, capi_exc_value);
rtn.setCallingConv(pp->getCallingConvention()); rtn.setCallingConv(pp->getCallingConvention());
return rtn.getInstruction(); return rtn.getInstruction();
...@@ -627,23 +675,6 @@ public: ...@@ -627,23 +675,6 @@ public:
return rtn; return rtn;
} }
void checkAndPropagateCapiException(const UnwindInfo& unw_info, llvm::Value* returned_val, llvm::Value* exc_val,
bool double_check = false) override {
assert(!double_check); // need to call PyErr_Occurred
llvm::BasicBlock* normal_dest
= llvm::BasicBlock::Create(g.context, curblock->getName(), irstate->getLLVMFunction());
normal_dest->moveAfter(curblock);
llvm::BasicBlock* exc_dest = irgenerator->getCAPIExcDest(curblock, unw_info.exc_dest, unw_info.current_stmt);
assert(returned_val->getType() == exc_val->getType());
llvm::Value* check_val = getBuilder()->CreateICmpEQ(returned_val, exc_val);
llvm::BranchInst* nullcheck = getBuilder()->CreateCondBr(check_val, exc_dest, normal_dest);
setCurrentBasicBlock(normal_dest);
}
Box* getIntConstant(int64_t n) override { Box* getIntConstant(int64_t n) override {
return irstate->getSourceInfo()->parent_module->getIntConstant(n); return irstate->getSourceInfo()->parent_module->getIntConstant(n);
} }
...@@ -2424,9 +2455,7 @@ private: ...@@ -2424,9 +2455,7 @@ private:
llvm::Value* exc_info = emitter.getBuilder()->CreateConstInBoundsGEP2_32(irstate->getFrameInfoVar(), 0, 0); llvm::Value* exc_info = emitter.getBuilder()->CreateConstInBoundsGEP2_32(irstate->getFrameInfoVar(), 0, 0);
if (target_exception_style == CAPI) { if (target_exception_style == CAPI) {
emitter.createCall(unw_info, g.funcs.raise0_capi, exc_info, CAPI); emitter.createCall(unw_info, g.funcs.raise0_capi, exc_info, CAPI, IREmitter::ALWAYS_THROWS);
emitter.checkAndPropagateCapiException(unw_info, getNullPtr(g.llvm_value_type_ptr),
getNullPtr(g.llvm_value_type_ptr));
emitter.getBuilder()->CreateUnreachable(); emitter.getBuilder()->CreateUnreachable();
} else { } else {
emitter.createCall(unw_info, g.funcs.raise0, exc_info); emitter.createCall(unw_info, g.funcs.raise0, exc_info);
...@@ -2450,9 +2479,7 @@ private: ...@@ -2450,9 +2479,7 @@ private:
llvm::Instruction* inst; llvm::Instruction* inst;
if (target_exception_style == CAPI) { if (target_exception_style == CAPI) {
inst = emitter.createCall(unw_info, g.funcs.raise3_capi, args, CAPI); inst = emitter.createCall(unw_info, g.funcs.raise3_capi, args, CAPI, IREmitter::ALWAYS_THROWS);
emitter.checkAndPropagateCapiException(unw_info, getNullPtr(g.llvm_value_type_ptr),
getNullPtr(g.llvm_value_type_ptr));
} else { } else {
inst = emitter.createCall(unw_info, g.funcs.raise3, args, CXX); inst = emitter.createCall(unw_info, g.funcs.raise3, args, CXX);
} }
......
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