Commit 896f568b authored by Kevin Modzelewski's avatar Kevin Modzelewski

Support writing out xdecrefs in the llvm jit

It will end up spitting out something like:

%x = callattrCapi()
Py_XDECREF(x)
if (!x) throwCapiException()

We usually write something more like:

%x = callattrCapi()
if (!x) throwCapiException()
Py_DECREF(x)

But with optimizations turned on, llvm will turn them into
the same thing.
parent 65272d1a
......@@ -678,8 +678,11 @@ static ConcreteCompilerVariable* _call(IREmitter& emitter, const OpInfo& info, l
rtn = inst;
}
if (rtn_type->getBoxType() == rtn_type)
if (rtn_type->getBoxType() == rtn_type) {
emitter.setType(rtn, RefType::OWNED);
if (func_addr == runtimeCallCapi || func_addr == callattrCapi)
emitter.setNullable(rtn, true);
}
assert(rtn->getType() == rtn_type->llvmType());
if (target_exception_style == CAPI) {
......
......@@ -110,6 +110,7 @@ public:
virtual BORROWED(Box*) getFloatConstant(double d) = 0;
virtual llvm::Value* setType(llvm::Value* v, RefType reftype) = 0;
virtual llvm::Value* setNullable(llvm::Value* v, bool nullable) = 0;
virtual void refConsumed(llvm::Value* v, llvm::Instruction* inst) = 0;
virtual void refUsed(llvm::Value* v, llvm::Instruction* inst) = 0;
virtual ConcreteCompilerVariable* getNone() = 0;
......
......@@ -668,7 +668,7 @@ public:
return v;
}
llvm::Value* setNullable(llvm::Value* v, bool nullable) {
llvm::Value* setNullable(llvm::Value* v, bool nullable) override {
irstate->getRefcounts()->setNullable(v, nullable);
return v;
}
......
......@@ -223,11 +223,30 @@ void addDecrefs(llvm::Value* v, bool nullable, int num_refs, llvm::Instruction*
raise(SIGTRAP);
}
assert(!nullable);
assert(num_refs > 0);
llvm::IRBuilder<true> builder(decref_pt);
if (nullable) {
llvm::BasicBlock* cur_block = decref_pt->getParent();
llvm::BasicBlock* continue_block = cur_block->splitBasicBlock(decref_pt);
llvm::BasicBlock* decref_block
= llvm::BasicBlock::Create(g.context, "decref", decref_pt->getParent()->getParent(), continue_block);
assert(llvm::isa<llvm::BranchInst>(cur_block->getTerminator()));
cur_block->getTerminator()->eraseFromParent();
builder.SetInsertPoint(cur_block);
auto isnull = builder.CreateICmpEQ(v, getNullPtr(v->getType()));
builder.CreateCondBr(isnull, continue_block, decref_block);
builder.SetInsertPoint(decref_block);
auto jmp = builder.CreateBr(continue_block);
addDecrefs(v, false, num_refs, jmp);
return;
}
assert(!nullable);
// Deal with subtypes of Box:
while (v->getType() != g.llvm_value_type_ptr) {
v = builder.CreateConstInBoundsGEP2_32(v, 0, 0);
......
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