diff --git a/gen/llvmhelpers.cpp b/gen/llvmhelpers.cpp index bfbbab2b..1662a0e7 100644 --- a/gen/llvmhelpers.cpp +++ b/gen/llvmhelpers.cpp @@ -1226,78 +1226,6 @@ LLConstant* DtoConstExpInit(Loc loc, Type* type, Expression* exp) ////////////////////////////////////////////////////////////////////////////////////////// -static LLValue* expand_value_to_sarray(Type *base, Expression* exp) -{ - Logger::println("building type %s from expression (%s) of type %s", base->toChars(), exp->toChars(), exp->type->toChars()); - const LLType* dstTy = DtoType(base); - if (Logger::enabled()) - Logger::cout() << "final llvm type requested: " << *dstTy << '\n'; - - // get initial value - LLValue* val = exp->toElem(gIR)->getRVal(); - if (DtoIsPassedByRef(exp->type)) - val = DtoLoad(val); - - Type* expbase = exp->type->toBasetype(); - Logger::println("expbase: %s", expbase->toChars()); - Type* t = base->toBasetype(); - - LLSmallVector dims; - - while(1) - { - Logger::println("t: %s", t->toChars()); - if (t->equals(expbase)) - break; - assert(t->ty == Tsarray); - TypeSArray* tsa = (TypeSArray*)t; - dims.push_back(tsa->dim->toInteger()); - assert(t->nextOf()); - t = t->nextOf()->toBasetype(); - } - - size_t i = dims.size(); - assert(i); - - std::vector inits; - while (i--) - { - // start with undefined array - const LLArrayType* arrty = LLArrayType::get(val->getType(), dims[i]); - LLValue* tmp = llvm::UndefValue::get(arrty); - for (size_t j = 0; j < dims[i]; j++) - { - tmp = gIR->ir->CreateInsertValue(tmp, val, j); - } - val = tmp; - } - - return val; -} - -LLValue* DtoExprValue(Type* type, Expression* e) -{ - Type* t1 = e->type->toBasetype(); - Type* t2 = type->toBasetype(); - - // expand static arrays - if (t2->ty == Tsarray && !t1->equals(t2)) - { - return expand_value_to_sarray(t2, e); - } - // or not - else - { - DValue* dv = e->toElem(gIR); - LLValue* v = dv->getRVal(); - if (DtoIsPassedByRef(e->type)) - v = DtoLoad(v); - return v; - } -} - -////////////////////////////////////////////////////////////////////////////////////////// - void DtoAnnotation(const char* str) { std::string s("CODE: "); diff --git a/gen/llvmhelpers.h b/gen/llvmhelpers.h index a62f8cd1..b79261b5 100644 --- a/gen/llvmhelpers.h +++ b/gen/llvmhelpers.h @@ -105,8 +105,6 @@ LLConstant* DtoConstInitializer(Loc loc, Type* type, Initializer* init); LLConstant* DtoConstExpInit(Loc loc, Type* t, Expression* exp); DValue* DtoInitializer(LLValue* target, Initializer* init); -LLValue* DtoExprValue(Type* type, Expression* e); - // annotation generator void DtoAnnotation(const char* str); diff --git a/gen/toir.cpp b/gen/toir.cpp index 1aac027a..db913148 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2409,11 +2409,15 @@ LLConstant* ArrayLiteralExp::toConstElem(IRState* p) ////////////////////////////////////////////////////////////////////////////////////////// -// building a struct literal is pretty much the same as building a default initializer. - -extern size_t add_zeros(std::vector& values, size_t diff); extern LLConstant* get_default_initializer(VarDeclaration* vd, Initializer* init); +static LLValue* write_zeroes(LLValue* mem, unsigned start, unsigned end) { + mem = DtoBitCast(mem, getVoidPtrType()); + LLValue* gep = DtoGEPi1(mem, start, ".padding"); + DtoMemSetZero(gep, DtoConstSize_t(end - start)); + return mem; +} + DValue* StructLiteralExp::toElem(IRState* p) { Logger::print("StructLiteralExp::toElem: %s @ %s\n", toChars(), type->toChars()); @@ -2422,97 +2426,62 @@ DValue* StructLiteralExp::toElem(IRState* p) // make sure the struct is fully resolved sd->codegen(Type::sir); - // final list of values to put in the struct - std::vector initvalues; - - // offset tracker - size_t offset = 0; - - // align(1) struct S { ... } - bool packed = sd->type->alignsize() == 1; + // alloca a stack slot + LLValue* mem = DtoRawAlloca(DtoType(type), 0, ".structliteral"); // ready elements data assert(elements && "struct literal has null elements"); - size_t nexprs = elements->dim;; + size_t nexprs = elements->dim; Expression** exprs = (Expression**)elements->data; + LLValue* voidptr = mem; + unsigned offset = 0; + // go through fields ArrayIter it(sd->fields); for (; !it.done(); it.next()) { VarDeclaration* vd = it.get(); + // don't re-initialize unions if (vd->offset < offset) { IF_LOG Logger::println("skipping field: %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset); continue; } + // initialize any padding so struct comparisons work + if (vd->offset != offset) + voidptr = write_zeroes(voidptr, offset, vd->offset); + offset = vd->offset + vd->type->size(); - IF_LOG Logger::println("using field: %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset); + IF_LOG Logger::println("initializing field: %s %s (+%u)", vd->type->toChars(), vd->toChars(), vd->offset); - // get next aligned offset for this field - size_t alignedoffset = offset; - if (!packed) - { - alignedoffset = realignOffset(alignedoffset, vd->type); - } - - // insert explicit padding? - if (alignedoffset < vd->offset) - { - add_zeros(initvalues, vd->offset - alignedoffset); - } - - // add initializer + // get initializer Expression* expr = (it.index < nexprs) ? exprs[it.index] : NULL; IF_LOG Logger::println("expr: %p", expr); + DValue* val; + DConstValue cv(vd->type, NULL); // Only used in one branch; value is set beforehand if (expr) { IF_LOG Logger::println("expr %zu = %s", it.index, expr->toChars()); - LLValue* v = DtoExprValue(vd->type, expr); - initvalues.push_back(v); + val = expr->toElem(gIR); } else { IF_LOG Logger::println("using default initializer"); - initvalues.push_back(get_default_initializer(vd, NULL)); + cv.c = get_default_initializer(vd, NULL); + val = &cv; } - // advance offset to right past this field - offset = vd->offset + vd->type->size(); + // get a pointer to this field + DVarValue field(vd->type, vd, DtoIndexStruct(mem, sd, vd)); + + // store the initializer there + DtoAssign(loc, &field, val); } - - // tail padding? - if (offset < sd->structsize) - { - add_zeros(initvalues, sd->structsize - offset); - } - - // build type - std::vector valuetypes; - - size_t n = initvalues.size(); - valuetypes.reserve(n); - - for (size_t i = 0; i < n; i++) - { - valuetypes.push_back(initvalues[i]->getType()); - } - - const LLType* st = llvm::StructType::get(valuetypes, packed); - - // alloca a stack slot - LLValue* mem = DtoRawAlloca(st, 0, ".structliteral"); - - // fill in values - for (size_t i = 0; i < n; i++) - { - LLValue* addr = DtoGEPi(mem, 0, i); - p->ir->CreateStore(initvalues[i], addr); - } - - // cast to default struct type - mem = DtoBitCast(mem, DtoType(sd->type->pointerTo())); + // initialize trailing padding + if (sd->structsize != offset) + write_zeroes(voidptr, offset, sd->structsize); // return as a var return new DVarValue(type, mem);