diff --git a/gen/arrays.cpp b/gen/arrays.cpp index 475807b1..52472686 100644 --- a/gen/arrays.cpp +++ b/gen/arrays.cpp @@ -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 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 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); } diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index 68118008..80e6e4b0 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1733,3 +1733,28 @@ LLValue* makeLValue(Loc& loc, DValue* value) return valuePointer; } + +////////////////////////////////////////////////////////////////////////////////////////// + +#if DMDV2 +void callPostblit(Loc &loc, Expression *exp, LLValue *val) +{ + + Type *tb = exp->type->toBasetype(); + if ((exp->op == TOKvar || exp->op == TOKdotvar || exp->op == TOKstar || exp->op == TOKthis) && + tb->ty == Tstruct) + { StructDeclaration *sd = ((TypeStruct *)tb)->sym; + if (sd->postblit) + { + FuncDeclaration *fd = sd->postblit; + if (fd->storage_class & STCdisable) + fd->toParent()->error(loc, "is not copyable because it is annotated with @disable"); + fd->codegen(Type::sir); + Expressions args; + DFuncValue dfn(fd, fd->ir.irFunc->func, val); + DtoCallFunction(loc, Type::basic[Tvoid], &dfn, &args); + } + } +} +#endif + diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index ca934e54..f0d9fb5c 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -152,6 +152,10 @@ size_t realignOffset(size_t offset, Type* type); /// functions without problems. LLValue* makeLValue(Loc& loc, DValue* value); +#if DMDV2 +void callPostblit(Loc &loc, Expression *exp, LLValue *val); +#endif + //////////////////////////////////////////// // gen/tocall.cpp stuff below //////////////////////////////////////////// diff --git a/gen/runtime.cpp b/gen/runtime.cpp index 67c61502..0ad25f6c 100644 --- a/gen/runtime.cpp +++ b/gen/runtime.cpp @@ -439,6 +439,14 @@ static void LLVM_D_BuildRuntimeModule() const llvm::FunctionType* fty = llvm::FunctionType::get(voidArrayTy, types, false); llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); } + // byte[] _d_arraycatnT(TypeInfo ti, uint n, ...) + { + llvm::StringRef fname("_d_arraycatnT"); + std::vector types; + types.push_back(typeInfoTy); + const llvm::FunctionType* fty = llvm::FunctionType::get(voidArrayTy, types, true); + llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, fname, M); + } #else // DMDV1 // byte[] _d_arrayappendcT(TypeInfo ti, void* array, void* element) { diff --git a/gen/statements.cpp b/gen/statements.cpp index a3ef2754..adb52f71 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -47,28 +47,6 @@ void CompoundStatement::toIR(IRState* p) ////////////////////////////////////////////////////////////////////////////// -#if DMDV2 -static void callPostblitHelper(Loc &loc, Expression *exp, LLValue *val) -{ - - Type *tb = exp->type->toBasetype(); - if ((exp->op == TOKvar || exp->op == TOKdotvar || exp->op == TOKstar || exp->op == TOKthis) && - tb->ty == Tstruct) - { StructDeclaration *sd = ((TypeStruct *)tb)->sym; - if (sd->postblit) - { - FuncDeclaration *fd = sd->postblit; - if (fd->storage_class & STCdisable) - fd->toParent()->error(loc, "is not copyable because it is annotated with @disable"); - fd->codegen(Type::sir); - Expressions args; - DFuncValue dfn(fd, fd->ir.irFunc->func, val); - DtoCallFunction(loc, Type::basic[Tvoid], &dfn, &args); - } - } -} -#endif - void ReturnStatement::toIR(IRState* p) { Logger::println("ReturnStatement::toIR(): %s", loc.toChars()); @@ -101,7 +79,7 @@ void ReturnStatement::toIR(IRState* p) #if DMDV2 // call postblit if necessary if (!p->func()->type->isref) - callPostblitHelper(loc, exp, rvar->getLVal()); + callPostblit(loc, exp, rvar->getLVal()); #endif // emit scopes @@ -127,7 +105,7 @@ void ReturnStatement::toIR(IRState* p) #if DMDV2 // call postblit if necessary if (!p->func()->type->isref) - callPostblitHelper(loc, exp, dval->getRVal()); + callPostblit(loc, exp, dval->getRVal()); // do abi specific transformations on the return value v = p->func()->type->fty.putRet(exp->type, dval, p->func()->type->isref); #else