mirror of
https://github.com/xomboverlord/ldc.git
synced 2026-04-12 06:49:02 +02: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:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user