# HG changeset patch # User lindquist # Date 1193811842 -3600 # Node ID 9e1bd80a7e983cdcb2948d00b2b9207f1073e775 # Parent ab8f5ec40a14962f24d20923b532b02381f14bd3 [svn r80] Fixed union literals diff -r ab8f5ec40a14 -r 9e1bd80a7e98 gen/toir.c --- a/gen/toir.c Wed Oct 31 04:55:48 2007 +0100 +++ b/gen/toir.c Wed Oct 31 07:24:02 2007 +0100 @@ -1667,36 +1667,52 @@ LOG_SCOPE; elem* e = new elem; - llvm::Value* sptr = 0; - - // if there is no lval, this is probably a temporary struct literal. correct? + llvm::Value* sptr; + const llvm::Type* llt = LLVM_DtoType(type); + + // temporary struct literal if (!p->topexp() || p->topexp()->e2 != this) { - sptr = new llvm::AllocaInst(LLVM_DtoType(type),"tmpstructliteral",p->topallocapoint()); + sptr = new llvm::AllocaInst(llt,"tmpstructliteral",p->topallocapoint()); e->mem = sptr; e->type = elem::VAR; } // already has memory - else if (p->topexp()->e2 == this) + else { + assert(p->topexp()->e2 == this); sptr = p->topexp()->v; } - else - assert(0); - - assert(sptr); - - llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false); - - if (sd->isUnionDeclaration()) { - Logger::println("num elements = %d", elements->dim); - //assert(elements->dim == 1); - Expression* vx = (Expression*)elements->data[0]; - assert(vx); - - Type* vxtype = LLVM_DtoDType(vx->type); - const llvm::Type* llvxty = llvm::PointerType::get(LLVM_DtoType(vxtype)); - llvm::Value* arrptr = p->ir->CreateBitCast(sptr, llvxty, "tmp"); + + // num elements in literal + unsigned n = elements->dim; + + // unions might have different types for each literal + if (sd->llvmHasUnions) { + // build the type of the literal + std::vector tys; + for (unsigned i=0; idata[i]; + if (!vx) continue; + tys.push_back(LLVM_DtoType(vx->type)); + } + const llvm::StructType* t = llvm::StructType::get(tys); + if (t != llt) { + assert(gTargetData->getTypeSize(t) == gTargetData->getTypeSize(llt)); + sptr = p->ir->CreateBitCast(sptr, llvm::PointerType::get(t), "tmp"); + Logger::cout() << "sptr type is now: " << *t << '\n'; + } + } + + // build + unsigned j = 0; + for (unsigned i=0; idata[i]; + if (!vx) continue; + + Logger::cout() << "getting index " << j << " of " << *sptr << '\n'; + llvm::Value* arrptr = LLVM_DtoGEPi(sptr,0,j,"tmp",p->scopebb()); p->exps.push_back(IRExp(NULL,vx,arrptr)); elem* ve = vx->toElem(p); @@ -1705,36 +1721,13 @@ if (!ve->inplace) { llvm::Value* val = ve->getValue(); Logger::cout() << *val << " | " << *arrptr << '\n'; + + Type* vxtype = LLVM_DtoDType(vx->type); LLVM_DtoAssign(vxtype, arrptr, val); } delete ve; - } - else { - unsigned n = elements->dim; - for (unsigned i=0; iscopebb()); - - Expression* vx = (Expression*)elements->data[i]; - if (vx != 0) { - p->exps.push_back(IRExp(NULL,vx,arrptr)); - elem* ve = vx->toElem(p); - p->exps.pop_back(); - - if (!ve->inplace) { - llvm::Value* val = ve->getValue(); - Logger::cout() << *val << " | " << *arrptr << '\n'; - - Type* vxtype = LLVM_DtoDType(vx->type); - LLVM_DtoAssign(vxtype, arrptr, val); - } - delete ve; - } - else { - assert(0); - } - } + + j++; } e->inplace = true; diff -r ab8f5ec40a14 -r 9e1bd80a7e98 test/union4.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/union4.d Wed Oct 31 07:24:02 2007 +0100 @@ -0,0 +1,16 @@ +module union4; + +pragma(LLVM_internal, "notypeinfo") +union U { + struct { float x,y,z; } + float[3] xyz; +} + +void main() { + const float[3] a = [1f,2,3]; + U u = U(1,2,3); + assert(u.xyz == a); + assert(u.x == 1); + assert(u.y == 2); + assert(u.z == 3); +} diff -r ab8f5ec40a14 -r 9e1bd80a7e98 test/union5.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test/union5.d Wed Oct 31 07:24:02 2007 +0100 @@ -0,0 +1,39 @@ +module union5; + +pragma(LLVM_internal, "notypeinfo") +{ + union S + { + T t; + U u; + uint i; + struct { + ushort sl,sh; + } + } + + struct T + { + int i; + } + + struct U + { + float f; + } +} + +void main() +{ + S s; + assert(s.t.i == 0); + assert(s.u.f == 0); + s.t.i = -1; + assert(s.i == 0xFFFF_FFFF); + float f = 3.1415; + s.u.f = f; + uint pi = *cast(uint*)&f; + assert(s.i == pi); + assert(s.sl == (pi&0xFFFF)); + assert(s.sh == (pi>>>16)); +}