mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-09 12:32:33 +03:00
Run postblit constructors for elements of an array.
This commit is contained in:
parent
44593f6220
commit
023b55a772
7 changed files with 162 additions and 35 deletions
109
gen/arrays.cpp
109
gen/arrays.cpp
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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())) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue