Call _d_delstruct() runtime function when deleting struct pointers.

As long as the struct has a dtor, otherwise continue forwarding
to _d_delmemory().
This commit is contained in:
Martin 2015-03-29 04:54:31 +02:00
parent 0178078af1
commit 7d0d2a1d26
4 changed files with 47 additions and 40 deletions

View file

@ -74,56 +74,52 @@ LLValue* DtoNew(Loc& loc, Type* newtype)
return DtoBitCast(mem, getPtrToType(i1ToI8(DtoType(newtype))), ".gc_mem"); return DtoBitCast(mem, getPtrToType(i1ToI8(DtoType(newtype))), ".gc_mem");
} }
void DtoDeleteMemory(Loc& loc, LLValue* ptr) void DtoDeleteMemory(Loc& loc, DValue* ptr)
{ {
// get runtime function // get runtime function
llvm::Function* fn = LLVM_D_GetRuntimeFunction(loc, gIR->module, "_d_delmemory"); llvm::Function* fn = LLVM_D_GetRuntimeFunction(loc, gIR->module, "_d_delmemory");
// build args // build args
LLValue* arg[] = { DtoBitCast(ptr, getPtrToType(getVoidPtrType()), ".tmp") }; LLValue* lval = (ptr->isLVal() ? ptr->getLVal() : makeLValue(loc, ptr));
LLValue* arg[] = { DtoBitCast(lval, fn->getFunctionType()->getParamType(0)) };
// call // call
gIR->CreateCallOrInvoke(fn, arg); gIR->CreateCallOrInvoke(fn, arg);
} }
void DtoDeleteClass(Loc& loc, LLValue* inst) void DtoDeleteStruct(Loc& loc, DValue* ptr)
{
llvm::Function* fn = LLVM_D_GetRuntimeFunction(loc, gIR->module, "_d_delstruct");
LLValue* lval = (ptr->isLVal() ? ptr->getLVal() : makeLValue(loc, ptr));
LLValue* arg[] = {
DtoBitCast(lval, fn->getFunctionType()->getParamType(0)),
DtoBitCast(DtoTypeInfoOf(ptr->type->nextOf()), fn->getFunctionType()->getParamType(1))
};
gIR->CreateCallOrInvoke(fn, arg);
}
void DtoDeleteClass(Loc& loc, DValue* inst)
{ {
// get runtime function
llvm::Function* fn = LLVM_D_GetRuntimeFunction(loc, gIR->module, "_d_delclass"); llvm::Function* fn = LLVM_D_GetRuntimeFunction(loc, gIR->module, "_d_delclass");
// druntime wants a pointer to object LLValue* lval = (inst->isLVal() ? inst->getLVal() : makeLValue(loc, inst));
LLValue *ptr = DtoRawAlloca(inst->getType(), 0, "objectPtr"); LLValue* arg[] = { DtoBitCast(lval, fn->getFunctionType()->getParamType(0)) };
DtoStore(inst, ptr);
inst = ptr;
// build args
LLValue* arg[] = {
DtoBitCast(inst, fn->getFunctionType()->getParamType(0), ".tmp")
};
// call
gIR->CreateCallOrInvoke(fn, arg); gIR->CreateCallOrInvoke(fn, arg);
} }
void DtoDeleteInterface(Loc& loc, LLValue* inst) void DtoDeleteInterface(Loc& loc, DValue* inst)
{ {
// get runtime function
llvm::Function* fn = LLVM_D_GetRuntimeFunction(loc, gIR->module, "_d_delinterface"); llvm::Function* fn = LLVM_D_GetRuntimeFunction(loc, gIR->module, "_d_delinterface");
// build args LLValue* lval = (inst->isLVal() ? inst->getLVal() : makeLValue(loc, inst));
LLValue* arg[] = { LLValue* arg[] = { DtoBitCast(lval, fn->getFunctionType()->getParamType(0)) };
DtoBitCast(inst, fn->getFunctionType()->getParamType(0), ".tmp")
};
// call
gIR->CreateCallOrInvoke(fn, arg); gIR->CreateCallOrInvoke(fn, arg);
} }
void DtoDeleteArray(Loc& loc, DValue* arr) void DtoDeleteArray(Loc& loc, DValue* arr)
{ {
// get runtime function
llvm::Function* fn = LLVM_D_GetRuntimeFunction(loc, gIR->module, "_d_delarray_t"); llvm::Function* fn = LLVM_D_GetRuntimeFunction(loc, gIR->module, "_d_delarray_t");
llvm::FunctionType* fty = fn->getFunctionType();
// build args
LLValue* arg[] = { LLValue* arg[] = {
DtoBitCast(arr->getLVal(), fn->getFunctionType()->getParamType(0)), DtoBitCast(arr->getLVal(), fty->getParamType(0)),
DtoBitCast(DtoTypeInfoOf(arr->type->nextOf()), fn->getFunctionType()->getParamType(1)) DtoBitCast(DtoTypeInfoOf(arr->type->nextOf()), fty->getParamType(1))
}; };
// call
gIR->CreateCallOrInvoke(fn, arg); gIR->CreateCallOrInvoke(fn, arg);
} }
@ -132,7 +128,6 @@ void DtoDeleteArray(Loc& loc, DValue* arr)
// ALLOCA HELPERS // ALLOCA HELPERS
////////////////////////////////////////////////////////////////////////////////////////*/ ////////////////////////////////////////////////////////////////////////////////////////*/
llvm::AllocaInst* DtoAlloca(Type* type, const char* name) llvm::AllocaInst* DtoAlloca(Type* type, const char* name)
{ {
LLType* lltype = i1ToI8(DtoType(type)); LLType* lltype = i1ToI8(DtoType(type));

View file

@ -34,9 +34,10 @@ struct EnclosingTryFinally
// dynamic memory helpers // dynamic memory helpers
LLValue* DtoNew(Loc& loc, Type* newtype); LLValue* DtoNew(Loc& loc, Type* newtype);
void DtoDeleteMemory(Loc& loc, LLValue* ptr); void DtoDeleteMemory(Loc& loc, DValue* ptr);
void DtoDeleteClass(Loc& loc, LLValue* inst); void DtoDeleteStruct(Loc& loc, DValue* ptr);
void DtoDeleteInterface(Loc& loc, LLValue* inst); void DtoDeleteClass(Loc& loc, DValue* inst);
void DtoDeleteInterface(Loc& loc, DValue* inst);
void DtoDeleteArray(Loc& loc, DValue* arr); void DtoDeleteArray(Loc& loc, DValue* arr);
// emit an alloca // emit an alloca

View file

@ -82,6 +82,7 @@ static void checkForImplicitGCCall(const Loc &loc, const char *name)
"_d_callfinalizer", "_d_callfinalizer",
"_d_delarray_t", "_d_delarray_t",
"_d_delclass", "_d_delclass",
"_d_delstruct",
"_d_delinterface", "_d_delinterface",
"_d_delmemory", "_d_delmemory",
"_d_newarrayT", "_d_newarrayT",
@ -539,6 +540,14 @@ static void LLVM_D_BuildRuntimeModule()
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
} }
// void _d_delstruct(void** p, TypeInfo_Struct inf)
{
llvm::StringRef fname("_d_delstruct");
LLType *types[] = { rt_ptr(voidPtrTy), DtoType(Type::typeinfostruct->type) };
LLFunctionType* fty = llvm::FunctionType::get(voidTy, types, false);
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
}
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////

View file

@ -1991,10 +1991,14 @@ public:
DValue* dval = toElem(e->e1); DValue* dval = toElem(e->e1);
Type* et = e->e1->type->toBasetype(); Type* et = e->e1->type->toBasetype();
// simple pointer // pointer
if (et->ty == Tpointer) if (et->ty == Tpointer)
{ {
DtoDeleteMemory(e->loc, dval->isLVal() ? dval->getLVal() : makeLValue(e->loc, dval)); Type* elementType = et->nextOf()->toBasetype();
if (elementType->ty == Tstruct && static_cast<TypeStruct*>(elementType)->sym->dtor)
DtoDeleteStruct(e->loc, dval);
else
DtoDeleteMemory(e->loc, dval);
} }
// class // class
else if (et->ty == Tclass) else if (et->ty == Tclass)
@ -2003,8 +2007,7 @@ public:
TypeClass* tc = static_cast<TypeClass*>(et); TypeClass* tc = static_cast<TypeClass*>(et);
if (tc->sym->isInterfaceDeclaration()) if (tc->sym->isInterfaceDeclaration())
{ {
LLValue *val = dval->getLVal(); DtoDeleteInterface(e->loc, dval);
DtoDeleteInterface(e->loc, val);
onstack = true; onstack = true;
} }
else if (DVarValue* vv = dval->isVar()) { else if (DVarValue* vv = dval->isVar()) {
@ -2013,11 +2016,10 @@ public:
onstack = true; onstack = true;
} }
} }
if (!onstack) {
LLValue* rval = dval->getRVal(); if (!onstack)
DtoDeleteClass(e->loc, rval); DtoDeleteClass(e->loc, dval); // sets dval to null
} else if (dval->isVar()) {
if (dval->isVar()) {
LLValue* lval = dval->getLVal(); LLValue* lval = dval->getLVal();
DtoStore(LLConstant::getNullValue(lval->getType()->getContainedType(0)), lval); DtoStore(LLConstant::getNullValue(lval->getType()->getContainedType(0)), lval);
} }