diff --git a/gen/statements.cpp b/gen/statements.cpp index 580e9cc2..24a33fe8 100644 --- a/gen/statements.cpp +++ b/gen/statements.cpp @@ -1053,8 +1053,9 @@ void WithStatement::toIR(IRState* p) assert(body); DValue* e = exp->toElem(p); + assert(!wthis->ir.isSet()); + wthis->ir.irLocal = new IrLocal(wthis); wthis->ir.irLocal->value = e->getRVal(); - delete e; body->toIR(p); } diff --git a/gen/toir.cpp b/gen/toir.cpp index 88cdef0c..1c1c8f92 100644 --- a/gen/toir.cpp +++ b/gen/toir.cpp @@ -2550,66 +2550,76 @@ DValue* ArrayLiteralExp::toElem(IRState* p) Logger::print("ArrayLiteralExp::toElem: %s | %s\n", toChars(), type->toChars()); LOG_SCOPE; - Type* ty = DtoDType(type); - const llvm::Type* t = DtoType(ty); - Logger::cout() << "array literal has llvm type: " << *t << '\n'; + // D types + Type* arrayType = type->toBasetype(); + Type* elemType = arrayType->nextOf()->toBasetype(); - llvm::Value* mem = 0; - bool inplace_slice = false; + // is dynamic ? + bool dyn = (arrayType->ty == Tarray); + // length + size_t len = elements->dim; + // store into slice? + bool sliceInPlace = false; - if (!p->topexp() || p->topexp()->e2 != this) { - assert(DtoDType(type)->ty == Tsarray); - mem = new llvm::AllocaInst(t,"arrayliteral",p->topallocapoint()); - } - else if (p->topexp()->e2 == this) { - DValue* tlv = p->topexp()->v; - if (DSliceValue* sv = tlv->isSlice()) { - assert(sv->len == 0); - mem = sv->ptr; - inplace_slice = true; - } - else { - mem = p->topexp()->v->getLVal(); - } - assert(mem); - if (!isaPointer(mem->getType()) || - !isaArray(mem->getType()->getContainedType(0))) + // llvm target type + const llvm::Type* llType = DtoType(arrayType); + Logger::cout() << (dyn?"dynamic":"static") << " array literal with length " << len << " of D type: '" << arrayType->toChars() << "' has llvm type: '" << *llType << "'\n"; + + // llvm storage type + const llvm::Type* llStoType = llvm::ArrayType::get(DtoType(elemType), len); + Logger::cout() << "llvm storage type: '" << *llStoType << "'\n"; + + // dst pointer + llvm::Value* dstMem = 0; + + // rvalue of assignment + if (p->topexp() && p->topexp()->e2 == this) + { + DValue* topval = p->topexp()->v; + // slice assignment (copy) + if (DSliceValue* s = topval->isSlice()) { - assert(!inplace_slice); - assert(ty->ty == Tarray); - // we need to give this array literal storage - const llvm::ArrayType* arrty = llvm::ArrayType::get(DtoType(ty->next), elements->dim); - mem = new llvm::AllocaInst(arrty, "arrayliteral", p->topallocapoint()); + dstMem = s->ptr; + sliceInPlace = true; + assert(s->len == NULL); } + // static array assignment + else if (topval->getType()->toBasetype()->ty == Tsarray) + { + dstMem = topval->getLVal(); + } + // otherwise we still need to alloca storage } - else - assert(0); - Logger::cout() << "array literal mem: " << *mem << '\n'; + // alloca storage if not found already + if (!dstMem) + { + dstMem = new llvm::AllocaInst(llStoType, "arrayliteral", p->topallocapoint()); + } + Logger::cout() << "using dest mem: " << *dstMem << '\n'; - for (unsigned i=0; idim; ++i) + // store elements + for (size_t i=0; idata[i]; - llvm::Value* elemAddr = DtoGEPi(mem,0,i,"tmp",p->scopebb()); + llvm::Value* elemAddr = DtoGEPi(dstMem,0,i,"tmp",p->scopebb()); + + // emulate assignment DVarValue* vv = new DVarValue(expr->type, elemAddr, true); p->exps.push_back(IRExp(NULL, expr, vv)); DValue* e = expr->toElem(p); p->exps.pop_back(); - DImValue* im = e->isIm(); if (!im || !im->inPlace()) { DtoAssign(vv, e); } } - if (ty->ty == Tsarray || (ty->ty == Tarray && inplace_slice)) - return new DImValue(type, mem, true); - else if (ty->ty == Tarray) - return new DSliceValue(type, DtoConstSize_t(elements->dim), DtoGEPi(mem,0,0,"tmp")); - else { - assert(0); - return 0; - } + // return storage directly ? + if (!dyn || (dyn && sliceInPlace)) + return new DImValue(type, dstMem, true); + // wrap in a slice + return new DSliceValue(type, DtoConstSize_t(len), DtoGEPi(dstMem,0,0,"tmp")); } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/ir/irsymbol.cpp b/ir/irsymbol.cpp index c8d6394c..66d6e632 100644 --- a/ir/irsymbol.cpp +++ b/ir/irsymbol.cpp @@ -51,6 +51,11 @@ void IrDsymbol::reset() irField = NULL; } +bool IrDsymbol::isSet() +{ + return (irStruct || irFunc || irGlobal || irLocal || irField); +} + IrVar* IrDsymbol::getIrVar() { assert(irGlobal || irLocal || irField); diff --git a/ir/irsymbol.h b/ir/irsymbol.h index 3c8be712..a3f37b6b 100644 --- a/ir/irsymbol.h +++ b/ir/irsymbol.h @@ -47,6 +47,8 @@ struct IrDsymbol IrField* irField; IrVar* getIrVar(); llvm::Value*& getIrValue(); + + bool isSet(); }; #endif diff --git a/test/arrays.d b/test/arrays.d index 8c8b05c4..672bff04 100644 --- a/test/arrays.d +++ b/test/arrays.d @@ -1,3 +1,5 @@ +extern(C) int printf(char*, ...); + void integer() { auto arr = new int[16]; diff --git a/test/arrays13.d b/test/arrays13.d index 60acab4e..d2bb7c0a 100644 --- a/test/arrays13.d +++ b/test/arrays13.d @@ -1,8 +1,10 @@ module arrays13; +extern(C) int printf(char*, ...); + void main() { - string a = "hello"; + char[] a = "hello"; assert(a > "hel"); assert(a >= "hel"); diff --git a/test/arrays4.d b/test/arrays4.d index 77fd7e91..8b63b90d 100644 --- a/test/arrays4.d +++ b/test/arrays4.d @@ -1,5 +1,5 @@ module arrays4; -import std.stdio; + void main() { int[] arr; @@ -10,5 +10,4 @@ void main() assert(arr.length == 2); assert(arr[0] == 3); assert(arr[1] == 5); - writefln(arr); } diff --git a/test/arrays7.d b/test/arrays7.d index 6ae2163c..ceb51c39 100644 --- a/test/arrays7.d +++ b/test/arrays7.d @@ -1,5 +1,7 @@ module arrays7; +extern(C) int printf(char*, ...); + pragma(LLVM_internal, "notypeinfo") struct S { diff --git a/test/arrays8.d b/test/arrays8.d index 192da139..db289458 100644 --- a/test/arrays8.d +++ b/test/arrays8.d @@ -1,5 +1,7 @@ module arrays8; +extern(C) int printf(char*, ...); + void main() { char[] a = "hello "; diff --git a/test/with1.d b/test/with1.d index a68d11c6..39e3e1ed 100644 --- a/test/with1.d +++ b/test/with1.d @@ -10,6 +10,8 @@ void main() with(s) { i = 0; - f = 3.4; + f = 3.5; } + assert(s.i == 0); + assert(s.f == 3.5); }