Run postblit constructors for elements of an array.

This commit is contained in:
Alexey Prokhin 2010-12-30 14:04:24 +03:00
parent 44593f6220
commit 023b55a772
7 changed files with 162 additions and 35 deletions

View file

@ -20,6 +20,22 @@
//////////////////////////////////////////////////////////////////////////////////////////
static LLValue *DtoSlice(DValue *dval)
{
LLValue *val = dval->getRVal();
if (dval->isVar() && dval->isVar()->type->ty == Tsarray) {
// Convert static array to slice
const LLStructType *type = DtoArrayType(LLType::getInt8Ty(gIR->context()));
LLValue *array = DtoRawAlloca(type, 0, ".array");
DtoStore(DtoArrayLen(dval), DtoGEPi(array, 0, 0, ".len"));
DtoStore(DtoBitCast(val, getVoidPtrType()), DtoGEPi(array, 0, 1, ".ptr"));
val = DtoLoad(array);
}
return val;
}
//////////////////////////////////////////////////////////////////////////////////////////
const LLStructType* DtoArrayType(Type* arrayTy)
{
assert(arrayTy->nextOf());
@ -65,11 +81,20 @@ void DtoSetArrayToNull(LLValue* v)
//////////////////////////////////////////////////////////////////////////////////////////
void DtoArrayInit(Loc& loc, DValue* array, DValue* value)
void DtoArrayInit(Loc& loc, DValue* array, DValue* value, int op)
{
Logger::println("DtoArrayInit");
LOG_SCOPE;
#if DMDV2
Type *elemType = array->type->toBasetype()->nextOf()->toBasetype();
if (op != -1 && op != TOKblit && arrayNeedsPostblit(elemType))
{
DtoArraySetAssign(loc, array, value, op);
return;
}
#endif
LLValue* dim = DtoArrayLen(array);
LLValue* ptr = DtoArrayPtr(array);
LLValue* val;
@ -209,6 +234,69 @@ void DtoArrayInit(Loc& loc, DValue* array, DValue* value)
//////////////////////////////////////////////////////////////////////////////////////////
#if DMDV2
// Determine whether t is an array of structs that need a postblit.
bool arrayNeedsPostblit(Type *t)
{
t = t->toBasetype();
while (t->ty == Tsarray)
t = t->nextOf()->toBasetype();
if (t->ty == Tstruct)
return ((TypeStruct *)t)->sym->postblit != 0;
return false;
}
// Does array assignment (or initialization) from another array of the same element type.
void DtoArrayAssign(DValue *array, DValue *value, int op)
{
Logger::println("DtoArrayAssign");
LOG_SCOPE;
assert(value && array);
assert(op != TOKblit);
Type *t = value->type->toBasetype();
assert(t->nextOf());
Type *elemType = t->nextOf()->toBasetype();
LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, op == TOKconstruct ? "_d_arrayctor" : "_d_arrayassign");
LLSmallVector<LLValue*,3> args;
args.push_back(DtoTypeInfoOf(elemType));
args.push_back(DtoAggrPaint(DtoSlice(value), fn->getFunctionType()->getParamType(1)));
args.push_back(DtoAggrPaint(DtoSlice(array), fn->getFunctionType()->getParamType(2)));
LLCallSite call = gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), ".array");
call.setCallingConv(llvm::CallingConv::C);
}
// If op is TOKconstruct, does construction of an array;
// otherwise, does assignment to an array.
void DtoArraySetAssign(Loc &loc, DValue *array, DValue *value, int op)
{
Logger::println("DtoArraySetAssign");
LOG_SCOPE;
assert(array && value);
assert(op != TOKblit);
LLValue *ptr = DtoArrayPtr(array);
LLValue *len = DtoArrayLen(array);
LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, op == TOKconstruct ? "_d_arraysetctor" : "_d_arraysetassign");
LLSmallVector<LLValue*,4> args;
args.push_back(DtoBitCast(ptr, getVoidPtrType()));
args.push_back(DtoBitCast(makeLValue(loc, value), getVoidPtrType()));
args.push_back(len);
args.push_back(DtoTypeInfoOf(array->type->toBasetype()->nextOf()->toBasetype()));
LLCallSite call = gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), ".newptr");
call.setCallingConv(llvm::CallingConv::C);
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////
void DtoSetArray(DValue* array, LLValue* dim, LLValue* ptr)
{
Logger::println("SetArray");
@ -671,21 +759,6 @@ DSliceValue* DtoCatAssignArray(DValue* arr, Expression* exp)
#if DMDV2
static LLValue *getParamForArrayCat(Expression* exp)
{
DValue *dval = exp->toElem(gIR);
LLValue *val = dval->getRVal();
if (dval->isVar() && dval->isVar()->type->ty == Tsarray) {
// Convert static array to slice
const LLStructType *type = DtoArrayType(LLType::getInt8Ty(gIR->context()));
LLValue *array = DtoRawAlloca(type, 0, ".array");
DtoStore(DtoArrayLen(dval), DtoGEPi(array, 0, 0, ".len"));
DtoStore(DtoBitCast(val, getVoidPtrType()), DtoGEPi(array, 0, 1, ".ptr"));
val = DtoLoad(array);
}
return val;
}
DSliceValue* DtoCatArrays(Type* arrayType, Expression* exp1, Expression* exp2)
{
Logger::println("DtoCatAssignArray");
@ -697,11 +770,11 @@ DSliceValue* DtoCatArrays(Type* arrayType, Expression* exp1, Expression* exp2)
// TypeInfo ti
args.push_back(DtoTypeInfoOf(arrayType));
// byte[] x
LLValue *val = getParamForArrayCat(exp1);
LLValue *val = DtoSlice(exp1->toElem(gIR));
val = DtoAggrPaint(val, fn->getFunctionType()->getParamType(1));
args.push_back(val);
// byte[] y
val = getParamForArrayCat(exp2);
val = DtoSlice(exp2->toElem(gIR));
val = DtoAggrPaint(val, fn->getFunctionType()->getParamType(2));
args.push_back(val);

View file

@ -15,8 +15,12 @@ LLConstant* DtoConstSlice(LLConstant* dim, LLConstant* ptr);
void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src);
void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src);
void DtoArrayInit(Loc& loc, DValue* array, DValue* value);
void DtoArrayAssign(LLValue* l, LLValue* r);
void DtoArrayInit(Loc& loc, DValue* array, DValue* value, int op);
#if DMDV2
bool arrayNeedsPostblit(Type *t);
void DtoArrayAssign(DValue *from, DValue *to, int op);
void DtoArraySetAssign(Loc &loc, DValue *array, DValue *value, int op);
#endif
void DtoSetArray(DValue* array, LLValue* dim, LLValue* ptr);
void DtoSetArrayToNull(LLValue* v);

View file

@ -385,7 +385,7 @@ void DtoLeaveMonitor(LLValue* v)
// is this a good approach at all ?
void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs)
void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs, int op)
{
Logger::println("DtoAssign(...);\n");
LOG_SCOPE;
@ -411,11 +411,17 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs)
else if (t->ty == Tarray) {
// lhs is slice
if (DSliceValue* s = lhs->isSlice()) {
if (DSliceValue* s2 = rhs->isSlice()) {
DtoArrayCopySlices(s, s2);
Type *elemType = t->nextOf()->toBasetype();
if (elemType->equals(t2)) {
DtoArrayInit(loc, s, rhs, op);
}
else if (t->nextOf()->toBasetype()->equals(t2)) {
DtoArrayInit(loc, s, rhs);
#if DMDV2
else if (op != -1 && op != TOKblit && arrayNeedsPostblit(elemType)) {
DtoArrayAssign(s, rhs, op);
}
#endif
else if (DSliceValue *s2 = rhs->isSlice()) {
DtoArrayCopySlices(s, s2);
}
else {
DtoArrayCopyToSlice(s, rhs);
@ -440,13 +446,19 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs)
}
}
else if (t->ty == Tsarray) {
// T[n] = T[n]
if (DtoType(lhs->getType()) == DtoType(rhs->getType())) {
DtoStaticArrayCopy(lhs->getLVal(), rhs->getRVal());
}
Type *elemType = t->nextOf()->toBasetype();
// T[n] = T
else if (t->nextOf()->toBasetype()->equals(t2)) {
DtoArrayInit(loc, lhs, rhs);
if (elemType->equals(t2)) {
DtoArrayInit(loc, lhs, rhs, op);
}
#if DMDV2
else if (op != -1 && op != TOKblit && arrayNeedsPostblit(elemType)) {
DtoArrayAssign(lhs, rhs, op);
}
#endif
// T[n] = T[n]
else if (DtoType(lhs->getType()) == DtoType(rhs->getType())) {
DtoStaticArrayCopy(lhs->getLVal(), rhs->getRVal());
}
// T[n] = T[] - generally only generated by frontend in rare cases
else if (t2->ty == Tarray && t->nextOf()->toBasetype()->equals(t2->nextOf()->toBasetype())) {

View file

@ -72,7 +72,7 @@ void DtoEnterMonitor(LLValue* v);
void DtoLeaveMonitor(LLValue* v);
// basic operations
void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs);
void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs, int op = -1);
/// Create a null DValue.
DValue* DtoNullValue(Type* t);

View file

@ -642,6 +642,45 @@ static void LLVM_D_BuildRuntimeModule()
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
#if DMDV2
// void[] _d_arrayassign(TypeInfo ti, void[] from, void[] to)
// void[] _d_arrayctor(TypeInfo ti, void[] from, void[] to)
{
llvm::StringRef fname("_d_arrayassign");
llvm::StringRef fname2("_d_arrayctor");
std::vector<const LLType*> types;
types.push_back(typeInfoTy);
types.push_back(voidArrayTy);
types.push_back(voidArrayTy);
const llvm::FunctionType* fty = llvm::FunctionType::get(voidArrayTy, types, false);
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M);
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M);
}
// void* _d_arraysetassign(void* p, void* value, size_t count, TypeInfo ti)
// void* _d_arraysetctor(void* p, void* value, size_t count, TypeInfo ti)
{
llvm::StringRef fname("_d_arraysetassign");
llvm::StringRef fname2("_d_arraysetctor");
std::vector<const LLType*> types;
types.push_back(voidPtrTy);
types.push_back(voidPtrTy);
types.push_back(sizeTy);
types.push_back(typeInfoTy);
const llvm::FunctionType* fty = llvm::FunctionType::get(voidPtrTy, types, false);
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M)
->setAttributes(Attr_NoAlias);
llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname2, M)
->setAttributes(Attr_NoAlias);
}
#endif
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////
// cast to object
// Object _d_toObject(void* p)
{

View file

@ -570,7 +570,7 @@ DValue* AssignExp::toElem(IRState* p)
DValue* l = e1->toElem(p);
DValue* r = e2->toElem(p);
DtoAssign(loc, l, r);
DtoAssign(loc, l, r, op);
if (l->isSlice())
return l;
@ -2628,7 +2628,7 @@ DValue* StructLiteralExp::toElem(IRState* p)
DVarValue field(vd->type, vd, DtoIndexStruct(mem, sd, vd));
// store the initializer there
DtoAssign(loc, &field, val);
DtoAssign(loc, &field, val, TOKconstruct);
#if DMDV2
Type *tb = vd->type->toBasetype();

View file

@ -69,7 +69,6 @@ elseif(D_VERSION EQUAL 2)
file(GLOB_RECURSE GC_D ${RUNTIME_GC_DIR}/*.d)
file(GLOB_RECURSE DCRT_D ${RUNTIME_DC_DIR}/*.d)
list(REMOVE_ITEM DCRT_D
${RUNTIME_DC_DIR}/arrayassign.d
${RUNTIME_DC_DIR}/arraybyte.d
${RUNTIME_DC_DIR}/arraycast.d
${RUNTIME_DC_DIR}/arraycat.d