diff --git a/gen/arrays.c b/gen/arrays.c index 565cc918..211addf7 100644 --- a/gen/arrays.c +++ b/gen/arrays.c @@ -445,16 +445,8 @@ void LLVM_DtoCatArrayElement(llvm::Value* arr, Expression* exp) elem* e = exp->toElem(gIR); Type* et = LLVM_DtoDType(exp->type); - - if (et->ty == Tstruct) { - TypeStruct* ts = (TypeStruct*)et; - LLVM_DtoStructCopy(ts,ptr,e->getValue()); - } - else { - llvm::Value* val = e->getValue(); - Logger::cout() << "ptr = '" << *ptr << "' element = '" << *val << "'\n"; - new llvm::StoreInst(val, ptr, gIR->scopebb()); - } + LLVM_DtoAssign(et, ptr, e->getValue()); + delete e; } ////////////////////////////////////////////////////////////////////////////////////////// diff --git a/gen/statements.c b/gen/statements.c index ff308a7c..f71dc14f 100644 --- a/gen/statements.c +++ b/gen/statements.c @@ -69,9 +69,8 @@ void ReturnStatement::toIR(IRState* p) if (expty == Tstruct) { if (!e->inplace) { - TypeStruct* ts = (TypeStruct*)exptype; assert(e->mem); - LLVM_DtoStructCopy(ts,f->llvmRetArg,e->mem); + LLVM_DtoStructCopy(f->llvmRetArg,e->mem); } } else if (expty == Tdelegate) { @@ -649,7 +648,7 @@ void ForeachStatement::toIR(IRState* p) if (key) key->llvmValue = keyvar; const llvm::Type* valtype = LLVM_DtoType(value->type); - llvm::Value* valvar = new llvm::AllocaInst(keytype, "foreachval", p->topallocapoint()); + llvm::Value* valvar = !value->isRef() ? new llvm::AllocaInst(valtype, "foreachval", p->topallocapoint()) : NULL; Type* aggrtype = LLVM_DtoDType(aggr->type); if (aggrtype->ty == Tsarray) @@ -708,10 +707,20 @@ void ForeachStatement::toIR(IRState* p) // get value for this iteration llvm::Constant* zero = llvm::ConstantInt::get(keytype,0,false); + llvm::Value* loadedKey = p->ir->CreateLoad(keyvar,"tmp"); if (aggrtype->ty == Tsarray) - value->llvmValue = LLVM_DtoGEP(val,zero,new llvm::LoadInst(keyvar,"tmp",p->scopebb()),"tmp",p->scopebb()); + value->llvmValue = LLVM_DtoGEP(val,zero,loadedKey,"tmp"); else if (aggrtype->ty == Tarray) - value->llvmValue = new llvm::GetElementPtrInst(val,new llvm::LoadInst(keyvar,"tmp",p->scopebb()),"tmp",p->scopebb()); + value->llvmValue = new llvm::GetElementPtrInst(val,loadedKey,"tmp",p->scopebb()); + + if (!value->isRef()) { + elem* e = new elem; + e->mem = value->llvmValue; + e->type = elem::VAR; + LLVM_DtoAssign(LLVM_DtoDType(value->type), valvar, e->getValue()); + delete e; + value->llvmValue = valvar; + } // body p->scope() = IRScope(p->scopebb(),endbb); diff --git a/gen/toir.c b/gen/toir.c index 467cac77..6b9952fa 100644 --- a/gen/toir.c +++ b/gen/toir.c @@ -499,8 +499,7 @@ elem* AssignExp::toElem(IRState* p) if (e2ty == Tstruct) { // struct literals do the assignment themselvs (in place) if (!r->inplace) { - TypeStruct* ts = (TypeStruct*)e2type; - LLVM_DtoStructCopy(ts,l->mem,r->getValue()); + LLVM_DtoStructCopy(l->mem,r->getValue()); } else { e->inplace = true; @@ -510,8 +509,7 @@ elem* AssignExp::toElem(IRState* p) else if (e2type->isintegral()){ IntegerExp* iexp = (IntegerExp*)e2; assert(iexp->value == 0 && "Only integral struct initializer allowed is zero"); - TypeStruct* st = (TypeStruct*)e1type; - LLVM_DtoStructZeroInit(st, l->mem); + LLVM_DtoStructZeroInit(l->mem); } // :x else @@ -1550,18 +1548,7 @@ elem* StructLiteralExp::toElem(IRState* p) Logger::cout() << *val << " | " << *arrptr << '\n'; Type* vxtype = LLVM_DtoDType(vx->type); - if (vxtype->ty == Tstruct) { - TypeStruct* ts = (TypeStruct*)vxtype; - LLVM_DtoStructCopy(ts,arrptr,val); - } - else if (vxtype->ty == Tarray) { - LLVM_DtoArrayAssign(arrptr,val); - } - else if (vxtype->ty == Tsarray) { - LLVM_DtoStaticArrayCopy(arrptr,val); - } - else - new llvm::StoreInst(val, arrptr, p->scopebb()); + LLVM_DtoAssign(vxtype, arrptr, val); } delete ve; } @@ -2058,10 +2045,10 @@ elem* NewExp::toElem(IRState* p) else if (ntype->ty == Tstruct) { TypeStruct* ts = (TypeStruct*)ntype; if (ts->isZeroInit()) { - LLVM_DtoStructZeroInit(ts,e->mem); + LLVM_DtoStructZeroInit(e->mem); } else { - LLVM_DtoStructCopy(ts,e->mem,ts->llvmInit); + LLVM_DtoStructCopy(e->mem,ts->llvmInit); } } diff --git a/gen/tollvm.c b/gen/tollvm.c index 50dfd07b..b5ee98e2 100644 --- a/gen/tollvm.c +++ b/gen/tollvm.c @@ -435,10 +435,10 @@ llvm::Function* LLVM_DeclareMemCpy64() ////////////////////////////////////////////////////////////////////////////////////////// -llvm::Value* LLVM_DtoStructZeroInit(TypeStruct* t, llvm::Value* v) +llvm::Value* LLVM_DtoStructZeroInit(llvm::Value* v) { assert(gIR); - uint64_t n = gTargetData->getTypeSize(t->llvmType); + uint64_t n = gTargetData->getTypeSize(v->getType()->getContainedType(0)); //llvm::Type* sarrty = llvm::PointerType::get(llvm::ArrayType::get(llvm::Type::Int8Ty, n)); llvm::Type* sarrty = llvm::PointerType::get(llvm::Type::Int8Ty); @@ -459,12 +459,12 @@ llvm::Value* LLVM_DtoStructZeroInit(TypeStruct* t, llvm::Value* v) ////////////////////////////////////////////////////////////////////////////////////////// -llvm::Value* LLVM_DtoStructCopy(TypeStruct* t, llvm::Value* dst, llvm::Value* src) +llvm::Value* LLVM_DtoStructCopy(llvm::Value* dst, llvm::Value* src) { assert(dst->getType() == src->getType()); assert(gIR); - uint64_t n = gTargetData->getTypeSize(t->llvmType); + uint64_t n = gTargetData->getTypeSize(dst->getType()->getContainedType(0)); //llvm::Type* sarrty = llvm::PointerType::get(llvm::ArrayType::get(llvm::Type::Int8Ty, n)); llvm::Type* arrty = llvm::PointerType::get(llvm::Type::Int8Ty); @@ -1110,11 +1110,11 @@ llvm::Value* LLVM_DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expr llvm::Value* allocaInst = 0; llvm::BasicBlock* entryblock = &gIR->topfunc()->front(); //const llvm::PointerType* pty = llvm::cast(arg->mem->getType()); - const llvm::PointerType* pty = llvm::PointerType::get(LLVM_DtoType(argexp->type)); + const llvm::Type* realtypell = LLVM_DtoType(realtype); + const llvm::PointerType* pty = llvm::PointerType::get(realtypell); if (argty == Tstruct) { allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint()); - TypeStruct* ts = (TypeStruct*)LLVM_DtoDType(argexp->type); - LLVM_DtoStructCopy(ts,allocaInst,arg->mem); + LLVM_DtoStructCopy(allocaInst,arg->mem); } else if (argty == Tdelegate) { allocaInst = new llvm::AllocaInst(pty->getElementType(), "tmpparam", gIR->topallocapoint()); @@ -1122,7 +1122,7 @@ llvm::Value* LLVM_DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expr } else if (argty == Tarray) { if (arg->type == elem::SLICE) { - allocaInst = new llvm::AllocaInst(LLVM_DtoType(argexp->type), "tmpparam", gIR->topallocapoint()); + allocaInst = new llvm::AllocaInst(realtypell, "tmpparam", gIR->topallocapoint()); LLVM_DtoSetArray(allocaInst, arg->arg, arg->mem); } else { @@ -1209,3 +1209,31 @@ llvm::Value* LLVM_DtoNestedVariable(VarDeclaration* vd) assert(0 && "nested var not found"); return NULL; } + +////////////////////////////////////////////////////////////////////////////////////////// + +void LLVM_DtoAssign(Type* t, llvm::Value* lhs, llvm::Value* rhs) +{ + Logger::cout() << "assignment:" << '\n' << *lhs << *rhs << '\n'; + + if (t->ty == Tstruct) { + assert(lhs->getType() == rhs->getType()); + LLVM_DtoStructCopy(lhs,rhs); + } + else if (t->ty == Tarray) { + assert(lhs->getType() == rhs->getType()); + LLVM_DtoArrayAssign(lhs,rhs); + } + else if (t->ty == Tsarray) { + assert(lhs->getType() == rhs->getType()); + LLVM_DtoStaticArrayCopy(lhs,rhs); + } + else if (t->ty == Tdelegate) { + assert(lhs->getType() == rhs->getType()); + LLVM_DtoDelegateCopy(lhs,rhs); + } + else { + assert(lhs->getType()->getContainedType(0) == rhs->getType()); + gIR->ir->CreateStore(rhs, lhs); + } +} diff --git a/gen/tollvm.h b/gen/tollvm.h index a394be0d..7d6568a0 100644 --- a/gen/tollvm.h +++ b/gen/tollvm.h @@ -7,8 +7,8 @@ bool LLVM_DtoIsPassedByRef(Type* type); Type* LLVM_DtoDType(Type* t); const llvm::Type* LLVM_DtoStructType(Type* t); -llvm::Value* LLVM_DtoStructZeroInit(TypeStruct* t, llvm::Value* v); -llvm::Value* LLVM_DtoStructCopy(TypeStruct* t, llvm::Value* dst, llvm::Value* src); +llvm::Value* LLVM_DtoStructZeroInit(llvm::Value* v); +llvm::Value* LLVM_DtoStructCopy(llvm::Value* dst, llvm::Value* src); llvm::Constant* LLVM_DtoConstStructInitializer(StructInitializer* si); const llvm::FunctionType* LLVM_DtoFunctionType(Type* t, const llvm::Type* thisparam = 0); @@ -56,4 +56,6 @@ llvm::Value* LLVM_DtoArgument(const llvm::Type* paramtype, Argument* fnarg, Expr llvm::Value* LLVM_DtoNestedVariable(VarDeclaration* vd); +void LLVM_DtoAssign(Type* lhsType, llvm::Value* lhs, llvm::Value* rhs); + #include "enums.h" diff --git a/test/foreach5.d b/test/foreach5.d new file mode 100644 index 00000000..4509cde1 --- /dev/null +++ b/test/foreach5.d @@ -0,0 +1,24 @@ +module foreach5; + +void main() +{ + int[3] arr = [1,2,3]; + + foreach(v;arr) { + v++; + } + + printf("%d\n", arr[0]); + assert(arr[0] == 1); + assert(arr[1] == 2); + assert(arr[2] == 3); + + foreach(ref v;arr) { + v++; + } + + printf("%d\n", arr[0]); + assert(arr[0] == 2); + assert(arr[1] == 3); + assert(arr[2] == 4); +} diff --git a/test/foreach6.d b/test/foreach6.d new file mode 100644 index 00000000..f8c23169 --- /dev/null +++ b/test/foreach6.d @@ -0,0 +1,15 @@ +module foreach6; + +struct S +{ + long l; + float f; +} + +void main() +{ + S[4] arr; + foreach(i,v;arr) { + v = S(i,i*2.5); + } +}