mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-10 04:45:56 +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)
|
const LLStructType* DtoArrayType(Type* arrayTy)
|
||||||
{
|
{
|
||||||
assert(arrayTy->nextOf());
|
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");
|
Logger::println("DtoArrayInit");
|
||||||
LOG_SCOPE;
|
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* dim = DtoArrayLen(array);
|
||||||
LLValue* ptr = DtoArrayPtr(array);
|
LLValue* ptr = DtoArrayPtr(array);
|
||||||
LLValue* val;
|
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)
|
void DtoSetArray(DValue* array, LLValue* dim, LLValue* ptr)
|
||||||
{
|
{
|
||||||
Logger::println("SetArray");
|
Logger::println("SetArray");
|
||||||
|
@ -671,21 +759,6 @@ DSliceValue* DtoCatAssignArray(DValue* arr, Expression* exp)
|
||||||
|
|
||||||
#if DMDV2
|
#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)
|
DSliceValue* DtoCatArrays(Type* arrayType, Expression* exp1, Expression* exp2)
|
||||||
{
|
{
|
||||||
Logger::println("DtoCatAssignArray");
|
Logger::println("DtoCatAssignArray");
|
||||||
|
@ -697,11 +770,11 @@ DSliceValue* DtoCatArrays(Type* arrayType, Expression* exp1, Expression* exp2)
|
||||||
// TypeInfo ti
|
// TypeInfo ti
|
||||||
args.push_back(DtoTypeInfoOf(arrayType));
|
args.push_back(DtoTypeInfoOf(arrayType));
|
||||||
// byte[] x
|
// byte[] x
|
||||||
LLValue *val = getParamForArrayCat(exp1);
|
LLValue *val = DtoSlice(exp1->toElem(gIR));
|
||||||
val = DtoAggrPaint(val, fn->getFunctionType()->getParamType(1));
|
val = DtoAggrPaint(val, fn->getFunctionType()->getParamType(1));
|
||||||
args.push_back(val);
|
args.push_back(val);
|
||||||
// byte[] y
|
// byte[] y
|
||||||
val = getParamForArrayCat(exp2);
|
val = DtoSlice(exp2->toElem(gIR));
|
||||||
val = DtoAggrPaint(val, fn->getFunctionType()->getParamType(2));
|
val = DtoAggrPaint(val, fn->getFunctionType()->getParamType(2));
|
||||||
args.push_back(val);
|
args.push_back(val);
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,12 @@ LLConstant* DtoConstSlice(LLConstant* dim, LLConstant* ptr);
|
||||||
void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src);
|
void DtoArrayCopySlices(DSliceValue* dst, DSliceValue* src);
|
||||||
void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src);
|
void DtoArrayCopyToSlice(DSliceValue* dst, DValue* src);
|
||||||
|
|
||||||
void DtoArrayInit(Loc& loc, DValue* array, DValue* value);
|
void DtoArrayInit(Loc& loc, DValue* array, DValue* value, int op);
|
||||||
void DtoArrayAssign(LLValue* l, LLValue* r);
|
#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 DtoSetArray(DValue* array, LLValue* dim, LLValue* ptr);
|
||||||
void DtoSetArrayToNull(LLValue* v);
|
void DtoSetArrayToNull(LLValue* v);
|
||||||
|
|
||||||
|
|
|
@ -385,7 +385,7 @@ void DtoLeaveMonitor(LLValue* v)
|
||||||
|
|
||||||
// is this a good approach at all ?
|
// 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");
|
Logger::println("DtoAssign(...);\n");
|
||||||
LOG_SCOPE;
|
LOG_SCOPE;
|
||||||
|
@ -411,11 +411,17 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs)
|
||||||
else if (t->ty == Tarray) {
|
else if (t->ty == Tarray) {
|
||||||
// lhs is slice
|
// lhs is slice
|
||||||
if (DSliceValue* s = lhs->isSlice()) {
|
if (DSliceValue* s = lhs->isSlice()) {
|
||||||
if (DSliceValue* s2 = rhs->isSlice()) {
|
Type *elemType = t->nextOf()->toBasetype();
|
||||||
DtoArrayCopySlices(s, s2);
|
if (elemType->equals(t2)) {
|
||||||
|
DtoArrayInit(loc, s, rhs, op);
|
||||||
}
|
}
|
||||||
else if (t->nextOf()->toBasetype()->equals(t2)) {
|
#if DMDV2
|
||||||
DtoArrayInit(loc, s, rhs);
|
else if (op != -1 && op != TOKblit && arrayNeedsPostblit(elemType)) {
|
||||||
|
DtoArrayAssign(s, rhs, op);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
else if (DSliceValue *s2 = rhs->isSlice()) {
|
||||||
|
DtoArrayCopySlices(s, s2);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
DtoArrayCopyToSlice(s, rhs);
|
DtoArrayCopyToSlice(s, rhs);
|
||||||
|
@ -440,13 +446,19 @@ void DtoAssign(Loc& loc, DValue* lhs, DValue* rhs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (t->ty == Tsarray) {
|
else if (t->ty == Tsarray) {
|
||||||
// T[n] = T[n]
|
Type *elemType = t->nextOf()->toBasetype();
|
||||||
if (DtoType(lhs->getType()) == DtoType(rhs->getType())) {
|
|
||||||
DtoStaticArrayCopy(lhs->getLVal(), rhs->getRVal());
|
|
||||||
}
|
|
||||||
// T[n] = T
|
// T[n] = T
|
||||||
else if (t->nextOf()->toBasetype()->equals(t2)) {
|
if (elemType->equals(t2)) {
|
||||||
DtoArrayInit(loc, lhs, rhs);
|
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
|
// T[n] = T[] - generally only generated by frontend in rare cases
|
||||||
else if (t2->ty == Tarray && t->nextOf()->toBasetype()->equals(t2->nextOf()->toBasetype())) {
|
else if (t2->ty == Tarray && t->nextOf()->toBasetype()->equals(t2->nextOf()->toBasetype())) {
|
||||||
|
|
|
@ -72,7 +72,7 @@ void DtoEnterMonitor(LLValue* v);
|
||||||
void DtoLeaveMonitor(LLValue* v);
|
void DtoLeaveMonitor(LLValue* v);
|
||||||
|
|
||||||
// basic operations
|
// 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.
|
/// Create a null DValue.
|
||||||
DValue* DtoNullValue(Type* t);
|
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
|
// cast to object
|
||||||
// Object _d_toObject(void* p)
|
// Object _d_toObject(void* p)
|
||||||
{
|
{
|
||||||
|
|
|
@ -570,7 +570,7 @@ DValue* AssignExp::toElem(IRState* p)
|
||||||
|
|
||||||
DValue* l = e1->toElem(p);
|
DValue* l = e1->toElem(p);
|
||||||
DValue* r = e2->toElem(p);
|
DValue* r = e2->toElem(p);
|
||||||
DtoAssign(loc, l, r);
|
DtoAssign(loc, l, r, op);
|
||||||
|
|
||||||
if (l->isSlice())
|
if (l->isSlice())
|
||||||
return l;
|
return l;
|
||||||
|
@ -2628,7 +2628,7 @@ DValue* StructLiteralExp::toElem(IRState* p)
|
||||||
DVarValue field(vd->type, vd, DtoIndexStruct(mem, sd, vd));
|
DVarValue field(vd->type, vd, DtoIndexStruct(mem, sd, vd));
|
||||||
|
|
||||||
// store the initializer there
|
// store the initializer there
|
||||||
DtoAssign(loc, &field, val);
|
DtoAssign(loc, &field, val, TOKconstruct);
|
||||||
|
|
||||||
#if DMDV2
|
#if DMDV2
|
||||||
Type *tb = vd->type->toBasetype();
|
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 GC_D ${RUNTIME_GC_DIR}/*.d)
|
||||||
file(GLOB_RECURSE DCRT_D ${RUNTIME_DC_DIR}/*.d)
|
file(GLOB_RECURSE DCRT_D ${RUNTIME_DC_DIR}/*.d)
|
||||||
list(REMOVE_ITEM DCRT_D
|
list(REMOVE_ITEM DCRT_D
|
||||||
${RUNTIME_DC_DIR}/arrayassign.d
|
|
||||||
${RUNTIME_DC_DIR}/arraybyte.d
|
${RUNTIME_DC_DIR}/arraybyte.d
|
||||||
${RUNTIME_DC_DIR}/arraycast.d
|
${RUNTIME_DC_DIR}/arraycast.d
|
||||||
${RUNTIME_DC_DIR}/arraycat.d
|
${RUNTIME_DC_DIR}/arraycat.d
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue