mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-06 10:57:35 +03:00
Call postblit on a struct when appending it to an array. Use _d_arraycatnT to concatenate multiple arrays.
Before, _d_arraycatT was used to concatenate multiple arrays. That caused an issue when postblit was called on a struct multiple times. The next code asserted due to the issue: void main() { static struct S { int x; int pad; this(this) { ++x; } } auto sarr = new S[1]; auto sarr2 = sarr ~ sarr ~ sarr; assert(sarr2[0].x == 1); assert(sarr2[1].x == 1); assert(sarr2[2].x == 1); assert(sarr[0].x == 0); }
This commit is contained in:
parent
9864129fb8
commit
0caba6672d
5 changed files with 98 additions and 40 deletions
|
@ -23,7 +23,7 @@
|
|||
static LLValue *DtoSlice(DValue *dval)
|
||||
{
|
||||
LLValue *val = dval->getRVal();
|
||||
if (dval->isVar() && dval->isVar()->type->ty == Tsarray) {
|
||||
if (dval->getType()->toBasetype()->ty == Tsarray) {
|
||||
// Convert static array to slice
|
||||
const LLStructType *type = DtoArrayType(LLType::getInt8Ty(gIR->context()));
|
||||
LLValue *array = DtoRawAlloca(type, 0, ".array");
|
||||
|
@ -36,6 +36,25 @@ static LLValue *DtoSlice(DValue *dval)
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static LLValue *DtoSlicePtr(DValue *dval)
|
||||
{
|
||||
Loc loc;
|
||||
const LLStructType *type = DtoArrayType(LLType::getInt8Ty(gIR->context()));
|
||||
Type *vt = dval->getType()->toBasetype();
|
||||
if (vt->ty == Tarray)
|
||||
return makeLValue(loc, dval);
|
||||
|
||||
bool isStaticArray = vt->ty == Tsarray;
|
||||
LLValue *val = isStaticArray ? dval->getRVal() : makeLValue(loc, dval);
|
||||
LLValue *array = DtoRawAlloca(type, 0, ".array");
|
||||
LLValue *len = isStaticArray ? DtoArrayLen(dval) : DtoConstSize_t(1);
|
||||
DtoStore(len, DtoGEPi(array, 0, 0, ".len"));
|
||||
DtoStore(DtoBitCast(val, getVoidPtrType()), DtoGEPi(array, 0, 1, ".ptr"));
|
||||
return array;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const LLStructType* DtoArrayType(Type* arrayTy)
|
||||
{
|
||||
assert(arrayTy->nextOf());
|
||||
|
@ -751,6 +770,7 @@ void DtoCatAssignElement(Loc& loc, Type* arrayType, DValue* array, Expression* e
|
|||
val = DtoGEP1(val, oldLength, "lastElem");
|
||||
val = DtoBitCast(val, DtoType(arrayType->nextOf()->pointerTo()));
|
||||
DtoAssign(loc, new DVarValue(arrayType->nextOf(), val), expVal);
|
||||
callPostblit(loc, exp, val);
|
||||
}
|
||||
|
||||
#else
|
||||
|
@ -846,23 +866,46 @@ DSliceValue* DtoCatArrays(Type* arrayType, Expression* exp1, Expression* exp2)
|
|||
Logger::println("DtoCatAssignArray");
|
||||
LOG_SCOPE;
|
||||
|
||||
// Prepare arguments
|
||||
LLFunction* fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_arraycatT");
|
||||
LLSmallVector<LLValue*,3> args;
|
||||
// TypeInfo ti
|
||||
args.push_back(DtoTypeInfoOf(arrayType));
|
||||
// byte[] x
|
||||
LLValue *val = DtoSlice(exp1->toElem(gIR));
|
||||
val = DtoAggrPaint(val, fn->getFunctionType()->getParamType(1));
|
||||
args.push_back(val);
|
||||
// byte[] y
|
||||
val = DtoSlice(exp2->toElem(gIR));
|
||||
val = DtoAggrPaint(val, fn->getFunctionType()->getParamType(2));
|
||||
args.push_back(val);
|
||||
std::vector<LLValue*> args;
|
||||
LLFunction* fn = 0;
|
||||
|
||||
// Call _d_arraycatT
|
||||
LLValue* newArray = gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), ".appendedArray").getInstruction();
|
||||
if (exp1->op == TOKcat)
|
||||
{ // handle multiple concat
|
||||
fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_arraycatnT");
|
||||
|
||||
args.push_back(DtoSlicePtr(exp2->toElem(gIR)));
|
||||
CatExp *ce = (CatExp*)exp1;
|
||||
do
|
||||
{
|
||||
args.push_back(DtoSlicePtr(ce->e2->toElem(gIR)));
|
||||
ce = (CatExp *)ce->e1;
|
||||
|
||||
} while (ce->op == TOKcat);
|
||||
args.push_back(DtoSlicePtr(ce->toElem(gIR)));
|
||||
// uint n
|
||||
args.push_back(DtoConstUint(args.size()));
|
||||
// TypeInfo ti
|
||||
args.push_back(DtoTypeInfoOf(arrayType));
|
||||
|
||||
std::reverse(args.begin(), args.end());
|
||||
}
|
||||
else
|
||||
{
|
||||
fn = LLVM_D_GetRuntimeFunction(gIR->module, "_d_arraycatT");
|
||||
|
||||
// TypeInfo ti
|
||||
args.push_back(DtoTypeInfoOf(arrayType));
|
||||
// byte[] x
|
||||
LLValue *val = DtoSlice(exp1->toElem(gIR));
|
||||
val = DtoAggrPaint(val, fn->getFunctionType()->getParamType(1));
|
||||
args.push_back(val);
|
||||
// byte[] y
|
||||
val = DtoSlice(exp2->toElem(gIR));
|
||||
val = DtoAggrPaint(val, fn->getFunctionType()->getParamType(2));
|
||||
args.push_back(val);
|
||||
}
|
||||
|
||||
LLValue *newArray = gIR->CreateCallOrInvoke(fn, args.begin(), args.end(), ".appendedArray").getInstruction();
|
||||
return getSlice(arrayType, newArray);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue