[svn r80] Fixed union literals

This commit is contained in:
Tomas Lindquist Olsen
2007-10-31 07:24:02 +01:00
parent 0e0d7eca12
commit fcdb174faf
3 changed files with 90 additions and 42 deletions

View File

@@ -1667,36 +1667,52 @@ elem* StructLiteralExp::toElem(IRState* p)
LOG_SCOPE;
elem* e = new elem;
llvm::Value* sptr = 0;
llvm::Value* sptr;
const llvm::Type* llt = LLVM_DtoType(type);
// if there is no lval, this is probably a temporary struct literal. correct?
// 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);
// num elements in literal
unsigned n = elements->dim;
llvm::Value* zero = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
// unions might have different types for each literal
if (sd->llvmHasUnions) {
// build the type of the literal
std::vector<const llvm::Type*> tys;
for (unsigned i=0; i<n; ++i) {
Expression* vx = (Expression*)elements->data[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';
}
}
if (sd->isUnionDeclaration()) {
Logger::println("num elements = %d", elements->dim);
//assert(elements->dim == 1);
Expression* vx = (Expression*)elements->data[0];
assert(vx);
// build
unsigned j = 0;
for (unsigned i=0; i<n; ++i)
{
Expression* vx = (Expression*)elements->data[i];
if (!vx) continue;
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");
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 @@ elem* StructLiteralExp::toElem(IRState* p)
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; i<n; ++i)
{
llvm::Value* offset = llvm::ConstantInt::get(llvm::Type::Int32Ty, i, false);
llvm::Value* arrptr = LLVM_DtoGEP(sptr,zero,offset,"tmp",p->scopebb());
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;

16
test/union4.d Normal file
View File

@@ -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);
}

39
test/union5.d Normal file
View File

@@ -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));
}