Commit 12e5d956 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Things are pretty hacky, but basic refcounting seems to be working ok

parent 3404d138
......@@ -271,6 +271,9 @@ llvm::Value* IRGenState::getGlobalsIfCustom() {
return getGlobals();
}
// 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)
class IREmitterImpl : public IREmitter {
private:
IRGenState* irstate;
......@@ -280,10 +283,14 @@ private:
llvm::CallSite emitCall(const UnwindInfo& unw_info, llvm::Value* callee, const std::vector<llvm::Value*>& args,
ExceptionStyle target_exception_style) {
bool needs_refcounting_fixup = true;
bool needs_cxx_interception
= (target_exception_style == CXX
&& (needs_refcounting_fixup || unw_info.hasHandler() || irstate->getExceptionStyle() == CAPI));
bool needs_cxx_interception;
if (unw_info.exc_dest == NO_CXX_INTERCEPTION) {
needs_cxx_interception = false;
} else {
bool needs_refcounting_fixup = true;
needs_cxx_interception = (target_exception_style == CXX && (needs_refcounting_fixup || unw_info.hasHandler()
|| irstate->getExceptionStyle() == CAPI));
}
if (needs_cxx_interception) {
// Create the invoke:
......@@ -297,7 +304,7 @@ private:
final_exc_dest = NULL; // signal to reraise as a capi exception
}
llvm::BasicBlock* exc_dest = irgenerator->getCXXExcDest(final_exc_dest);
llvm::BasicBlock* exc_dest = irgenerator->getCXXExcDest(unw_info);
normal_dest->moveAfter(curblock);
llvm::InvokeInst* rtn = getBuilder()->CreateInvoke(callee, normal_dest, exc_dest, args);
......@@ -410,7 +417,7 @@ public:
return llvm::BasicBlock::Create(g.context, name, irstate->getLLVMFunction());
}
llvm::Value* createCall(const UnwindInfo& unw_info, llvm::Value* callee, const std::vector<llvm::Value*>& args,
llvm::Instruction* createCall(const UnwindInfo& unw_info, llvm::Value* callee, const std::vector<llvm::Value*>& args,
ExceptionStyle target_exception_style = CXX) override {
#ifndef NDEBUG
// Copied the argument-type-checking from CallInst::init, since the patchpoint arguments don't
......@@ -440,9 +447,9 @@ public:
if (rtn_type == cs->getType()) {
return cs.getInstruction();
} else if (rtn_type == g.i1) {
return getBuilder()->CreateTrunc(cs.getInstruction(), rtn_type);
return llvm::cast<llvm::Instruction>(getBuilder()->CreateTrunc(cs.getInstruction(), rtn_type));
} else if (llvm::isa<llvm::PointerType>(rtn_type)) {
return getBuilder()->CreateIntToPtr(cs.getInstruction(), rtn_type);
return llvm::cast<llvm::Instruction>(getBuilder()->CreateIntToPtr(cs.getInstruction(), rtn_type));
} else {
cs.getInstruction()->getType()->dump();
rtn_type->dump();
......@@ -453,27 +460,27 @@ public:
}
}
llvm::Value* createCall(const UnwindInfo& unw_info, llvm::Value* callee,
llvm::Instruction* createCall(const UnwindInfo& unw_info, llvm::Value* callee,
ExceptionStyle target_exception_style = CXX) override {
return createCall(unw_info, callee, std::vector<llvm::Value*>(), target_exception_style);
}
llvm::Value* 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 {
return createCall(unw_info, callee, std::vector<llvm::Value*>({ arg1 }), target_exception_style);
}
llvm::Value* 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, llvm::Value* arg2,
ExceptionStyle target_exception_style = CXX) override {
return createCall(unw_info, callee, { arg1, arg2 }, target_exception_style);
}
llvm::Value* 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* arg2,
llvm::Value* arg3, ExceptionStyle target_exception_style = CXX) override {
return createCall(unw_info, callee, { arg1, arg2, arg3 }, target_exception_style);
}
llvm::Value* 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 {
std::vector<llvm::Value*> stackmap_args;
......@@ -2756,11 +2763,18 @@ public:
return capi_exc_dest;
}
llvm::BasicBlock* getCXXExcDest(llvm::BasicBlock* final_dest) override {
llvm::BasicBlock* getCXXExcDest(const UnwindInfo& unw_info) override {
//llvm::BasicBlock*& cxx_exc_dest = cxx_exc_dests[final_dest];
//if (cxx_exc_dest)
//return cxx_exc_dest;
llvm::BasicBlock* final_dest;
if (unw_info.hasHandler()) {
final_dest = unw_info.exc_dest;
} else {
final_dest = NULL;
}
llvm::BasicBlock* orig_block = curblock;
llvm::BasicBlock* cxx_exc_dest = llvm::BasicBlock::Create(g.context, "", irstate->getLLVMFunction());
......@@ -2812,7 +2826,8 @@ public:
irstate->getRefcounts()->refConsumed(exc_traceback, call_inst);
builder->CreateRet(getNullPtr(g.llvm_value_type_ptr));
} else {
auto call_inst = emitter.getBuilder()->CreateCall3(g.funcs.rawThrow, exc_type, exc_value, exc_traceback);
auto call_inst = emitter.createCall3(UnwindInfo(unw_info.current_stmt, NO_CXX_INTERCEPTION),
g.funcs.rawThrow, exc_type, exc_value, exc_traceback);
irstate->getRefcounts()->refConsumed(exc_type, call_inst);
irstate->getRefcounts()->refConsumed(exc_value, call_inst);
irstate->getRefcounts()->refConsumed(exc_traceback, call_inst);
......
......@@ -41,6 +41,7 @@ struct PatchpointInfo;
class ScopeInfo;
class TypeAnalysis;
class RefcountTracker;
class UnwindInfo;
typedef std::unordered_map<InternedString, CompilerVariable*> SymbolTable;
typedef std::map<InternedString, CompilerVariable*> SortedSymbolTable;
......@@ -163,7 +164,7 @@ public:
std::vector<llvm::Value*>& stackmap_args) = 0;
virtual void addOutgoingExceptionState(ExceptionState exception_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(const UnwindInfo&) = 0;
virtual llvm::BasicBlock* getCAPIExcDest(llvm::BasicBlock* from_block, llvm::BasicBlock* final_dest,
AST_stmt* current_stmt) = 0;
virtual CFGBlock* getCFGBlock() = 0;
......
......@@ -342,9 +342,17 @@ void RefcountTracker::addRefcounts(IRGenState* irstate) {
num_consumed = it->second;
if (num_times_as_op[op] > num_consumed) {
if (rt->vars[op].reftype == RefType::BORROWED) {
} else {
assert(state.refs.count(op) && "handle this case (last reference of an owned var)");
if (rt->vars[op].reftype == RefType::OWNED) {
if (state.refs[op] == 0) {
if (llvm::InvokeInst* invoke = llvm::dyn_cast<llvm::InvokeInst>(&I)) {
addDecrefs(op, 1, findIncrefPt(invoke->getNormalDest()));
addDecrefs(op, 1, findIncrefPt(invoke->getUnwindDest()));
} else {
assert(&I != I.getParent()->getTerminator());
addDecrefs(op, 1, I.getNextNode());
}
state.refs[op] = 1;
}
}
}
......
......@@ -276,6 +276,7 @@ extern "C" void reraiseCapiExcAsCxx() {
}
extern "C" void rawThrow(Box* type, Box* value, Box* tb) {
startReraise();
throw ExcInfo(type, value, tb);
}
......
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