changeset 88:058d3925950e trunk

[svn r92] Fixed support for statically initialized unions. lots of bugfixes as cleanups too.
author lindquist
date Tue, 06 Nov 2007 10:03:14 +0100
parents 25d4fcce53f4
children ccca1c13e13a
files dmd/aggregate.h dmd/struct.c gen/arrays.cpp gen/dvalue.cpp gen/dvalue.h gen/structs.cpp gen/structs.h gen/toir.cpp gen/tollvm.cpp gen/tollvm.h gen/toobj.cpp lphobos/phobos.d lphobos/std/c/linux/linuxextern.d lphobos/std/c/linux/socket.d test/bug51.d test/union7.d
diffstat 16 files changed, 849 insertions(+), 275 deletions(-) [+]
line wrap: on
line diff
--- a/dmd/aggregate.h	Sat Nov 03 14:48:33 2007 +0100
+++ b/dmd/aggregate.h	Tue Nov 06 10:03:14 2007 +0100
@@ -45,6 +45,8 @@
     class ConstantStruct;
 }
 
+struct DUnion;
+
 struct AggregateDeclaration : ScopeDsymbol
 {
     Type *type;
@@ -104,6 +106,7 @@
     llvm::ConstantStruct* llvmConstVtbl;
     llvm::Constant* llvmInitZ;
     bool llvmHasUnions;
+    DUnion* llvmUnion;
 
     AggregateDeclaration *isAggregateDeclaration() { return this; }
 };
--- a/dmd/struct.c	Sat Nov 03 14:48:33 2007 +0100
+++ b/dmd/struct.c	Tue Nov 06 10:03:14 2007 +0100
@@ -51,6 +51,7 @@
     llvmInitZ = NULL;
     llvmInProgress = false;
     llvmHasUnions = false;
+    llvmUnion = NULL;
 }
 
 enum PROT AggregateDeclaration::prot()
--- a/gen/arrays.cpp	Sat Nov 03 14:48:33 2007 +0100
+++ b/gen/arrays.cpp	Tue Nov 06 10:03:14 2007 +0100
@@ -251,41 +251,59 @@
 //////////////////////////////////////////////////////////////////////////////////////////
 llvm::Constant* DtoConstArrayInitializer(ArrayInitializer* arrinit)
 {
-    Logger::println("arr init begin");
+    Logger::println("DtoConstArrayInitializer: %s | %s", arrinit->toChars(), arrinit->type->toChars());
+    LOG_SCOPE;
+
     Type* arrinittype = DtoDType(arrinit->type);
 
     Type* t;
     integer_t tdim;
     if (arrinittype->ty == Tsarray) {
+        Logger::println("static array");
         TypeSArray* tsa = (TypeSArray*)arrinittype;
         tdim = tsa->dim->toInteger();
         t = tsa;
     }
     else if (arrinittype->ty == Tarray) {
+        Logger::println("dynamic array");
         t = arrinittype;
         tdim = arrinit->dim;
     }
     else
     assert(0);
 
-    std::vector<llvm::Constant*> inits(tdim, 0);
+    Logger::println("dim = %u", tdim);
+
+    std::vector<llvm::Constant*> inits(tdim, NULL);
 
     const llvm::Type* elemty = DtoType(arrinittype->next);
 
     assert(arrinit->index.dim == arrinit->value.dim);
-    for (int i=0,j=0; i < tdim; ++i)
+    for (unsigned i=0,j=0; i < tdim; ++i)
     {
         Initializer* init = 0;
         Expression* idx = (Expression*)arrinit->index.data[j];
 
         if (idx)
         {
-            integer_t k = idx->toInteger();
-            if (i == k)
-            {
-                init = (Initializer*)arrinit->value.data[j];
-                assert(init);
-                ++j;
+            // this is pretty weird :/ idx->type turned out NULL for the initializer:
+            //     const in6_addr IN6ADDR_ANY = { s6_addr8: [0] };
+            // in std.c.linux.socket
+            if (idx->type) {
+                //integer_t k = idx->toInteger();
+                Logger::println("getting value for exp: %s | %s", idx->toChars(), idx->type->toChars());
+                llvm::Constant* cc = idx->toConstElem(gIR);
+                Logger::println("value gotten");
+                assert(cc != NULL);
+                llvm::ConstantInt* ci = llvm::dyn_cast<llvm::ConstantInt>(cc);
+                assert(ci != NULL);
+                uint64_t k = ci->getZExtValue();
+                if (i == k)
+                {
+                    init = (Initializer*)arrinit->value.data[j];
+                    assert(init);
+                    ++j;
+                }
             }
         }
         else
@@ -294,29 +312,7 @@
             ++j;
         }
 
-        llvm::Constant* v = 0;
-
-        if (!init)
-        {
-            v = t->next->defaultInit()->toConstElem(gIR);
-        }
-        else if (ExpInitializer* ex = init->isExpInitializer())
-        {
-            v = ex->exp->toConstElem(gIR);
-        }
-        else if (StructInitializer* si = init->isStructInitializer())
-        {
-            v = DtoConstStructInitializer(si);
-        }
-        else if (ArrayInitializer* ai = init->isArrayInitializer())
-        {
-            v = DtoConstArrayInitializer(ai);
-        }
-        else if (init->isVoidInitializer())
-        {
-            v = llvm::UndefValue::get(elemty);
-        }
-        else
+        llvm::Constant* v = DtoConstInitializer(t->next, init);
         assert(v);
 
         inits[i] = v;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/dvalue.cpp	Tue Nov 06 10:03:14 2007 +0100
@@ -0,0 +1,101 @@
+#include "gen/llvm.h"
+
+#include "declaration.h"
+
+#include "gen/tollvm.h"
+#include "gen/irstate.h"
+#include "gen/logger.h"
+#include "gen/dvalue.h"
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+DVarValue::DVarValue(VarDeclaration* vd, llvm::Value* llvmValue, bool lvalue)
+{
+    var = vd;
+    val = llvmValue;
+    rval = 0;
+    lval = lvalue;
+    type = var->type;
+}
+
+DVarValue::DVarValue(Type* t, llvm::Value* lv, llvm::Value* rv)
+{
+    var = 0;
+    val = lv;
+    rval = rv;
+    lval = true;
+    type = t;
+}
+
+DVarValue::DVarValue(Type* t, llvm::Value* llvmValue, bool lvalue)
+{
+    var = 0;
+    val = llvmValue;
+    rval = 0;
+    lval = lvalue;
+    type = t;
+}
+
+llvm::Value* DVarValue::getLVal()
+{
+    assert(val && lval);
+    return val;
+}
+
+llvm::Value* DVarValue::getRVal()
+{
+    assert(rval || val);
+    if (DtoIsPassedByRef(type)) {
+        if (rval) return rval;
+        return val;
+    }
+    else {
+        if (rval) return rval;
+        Logger::cout() << "val: " << *val << '\n';
+        if (llvm::isa<llvm::Argument>(val)) {
+            if (var && (var->isRef() || var->isOut()))
+                return DtoLoad(val);
+        }
+        else if (!isField() && DtoCanLoad(val)) {
+            return DtoLoad(val);
+        }
+        return val;
+    }
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+DFuncValue::DFuncValue(FuncDeclaration* fd, llvm::Value* v, llvm::Value* vt)
+{
+    func = fd;
+    type = func->type;
+    val = v;
+    vthis = vt;
+    cc = (unsigned)-1;
+}
+
+llvm::Value* DFuncValue::getLVal()
+{
+    assert(0);
+    return 0;
+}
+
+llvm::Value* DFuncValue::getRVal()
+{
+    assert(val);
+    return val;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DConstValue::getRVal()
+{
+    assert(c);
+    return c;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////////////////
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/dvalue.h	Tue Nov 06 10:03:14 2007 +0100
@@ -0,0 +1,193 @@
+#ifndef LLVMDC_GEN_DVALUE_H
+#define LLVMDC_GEN_DVALUE_H
+
+/*
+These classes are used for generating the IR. They encapsulate D values and
+provide a common interface to the most common operations. When more specialized
+handling is necessary, they hold enough information to do-the-right-thing (TM)
+*/
+
+#include <cassert>
+#include "root.h"
+
+struct Type;
+struct Dsymbol;
+struct VarDeclaration;
+struct FuncDeclaration;
+
+namespace llvm
+{
+    class Value;
+    class Type;
+    class Constant;
+}
+
+struct DImValue;
+struct DConstValue;
+struct DNullValue;
+struct DVarValue;
+struct DFieldValue;
+struct DThisValue;
+struct DFuncValue;
+struct DSliceValue;
+struct DArrayLenValue;
+struct DLValueCast;
+
+// base class for d-values
+struct DValue : Object
+{
+    virtual Type* getType() = 0;
+
+    virtual llvm::Value* getLVal() { assert(0); return 0; }
+    virtual llvm::Value* getRVal() { assert(0); return 0; }
+
+    virtual DImValue* isIm() { return NULL; }
+    virtual DConstValue* isConst() { return NULL; }
+    virtual DNullValue* isNull() { return NULL; }
+    virtual DVarValue* isVar() { return NULL; }
+    virtual DFieldValue* isField() { return NULL; }
+    virtual DThisValue* isThis() { return NULL; }
+    virtual DSliceValue* isSlice() { return NULL; }
+    virtual DFuncValue* isFunc() { return NULL; }
+    virtual DArrayLenValue* isArrayLen() { return NULL; }
+    virtual DLValueCast* isLValueCast() { return NULL; }
+
+    virtual bool inPlace() { return false; }
+
+protected:
+    DValue() {}
+    DValue(const DValue&) { }
+    DValue& operator=(const DValue&) { return *this; }
+};
+
+// immediate d-value
+struct DImValue : DValue
+{
+    Type* type;
+    llvm::Value* val;
+    bool inplace;
+
+    DImValue(Type* t, llvm::Value* v, bool i = false) { type = t; val = v; inplace = i; }
+
+    virtual llvm::Value* getRVal() { assert(val); return val; }
+
+    virtual Type* getType() { assert(type); return type; }
+    virtual DImValue* isIm() { return this; }
+
+    virtual bool inPlace() { return inplace; }
+};
+
+// constant d-value
+struct DConstValue : DValue
+{
+    Type* type;
+    llvm::Constant* c;
+
+    DConstValue(Type* t, llvm::Constant* con) { type = t; c = con; }
+
+    virtual llvm::Value* getRVal();
+
+    virtual Type* getType() { assert(type); return type; }
+    virtual DConstValue* isConst() { return this; }
+};
+
+// null d-value
+struct DNullValue : DConstValue
+{
+    DNullValue(Type* t, llvm::Constant* con) : DConstValue(t,con) {}
+    virtual DNullValue* isNull() { return this; }
+};
+
+// variable d-value
+struct DVarValue : DValue
+{
+    Type* type;
+    VarDeclaration* var;
+    llvm::Value* val;
+    llvm::Value* rval;
+    bool lval;
+
+    DVarValue(VarDeclaration* vd, llvm::Value* llvmValue, bool lvalue);
+    DVarValue(Type* vd, llvm::Value* lv, llvm::Value* rv);
+    DVarValue(Type* t, llvm::Value* llvmValue, bool lvalue);
+
+    virtual llvm::Value* getLVal();
+    virtual llvm::Value* getRVal();
+
+    virtual Type* getType() { assert(type); return type; }
+    virtual DVarValue* isVar() { return this; }
+};
+
+// field d-value
+struct DFieldValue : DVarValue
+{
+    DFieldValue(Type* t, llvm::Value* llvmValue, bool l) : DVarValue(t, llvmValue, l) {}
+    virtual DFieldValue* isField() { return this; }
+};
+
+// this d-value
+struct DThisValue : DVarValue
+{
+    DThisValue(VarDeclaration* vd, llvm::Value* llvmValue) : DVarValue(vd, llvmValue, true) {}
+    virtual DThisValue* isThis() { return this; }
+};
+
+// array length d-value
+struct DArrayLenValue : DVarValue
+{
+    DArrayLenValue(Type* t, llvm::Value* llvmValue) : DVarValue(t, llvmValue, true) {}
+    virtual DArrayLenValue* isArrayLen() { return this; }
+};
+
+// slice d-value
+struct DSliceValue : DValue
+{
+    Type* type;
+    llvm::Value* len;
+    llvm::Value* ptr;
+
+    DSliceValue(Type* t, llvm::Value* l, llvm::Value* p) { type=t; ptr=p; len=l; }
+
+    virtual Type* getType() { assert(type); return type; }
+    virtual DSliceValue* isSlice() { return this; }
+};
+
+// function d-value
+struct DFuncValue : DValue
+{
+    Type* type;
+    FuncDeclaration* func;
+    llvm::Value* val;
+    llvm::Value* vthis;
+    unsigned cc;
+
+    DFuncValue(FuncDeclaration* fd, llvm::Value* v, llvm::Value* vt = 0);
+
+    virtual llvm::Value* getLVal();
+    virtual llvm::Value* getRVal();
+
+    virtual Type* getType() { assert(type); return type; }
+    virtual DFuncValue* isFunc() { return this; }
+};
+
+// l-value cast d-value
+struct DLValueCast : DValue
+{
+    Type* type;
+    llvm::Value* lval;
+    llvm::Value* rval;
+
+    DLValueCast(Type* t, llvm::Value* l, llvm::Value* r) {
+        type = t;
+        lval = l;
+        rval = r;
+    }
+
+    virtual llvm::Value* getLVal() { assert(lval); return lval; }
+    virtual llvm::Value* getRVal() { assert(rval); return rval; }
+
+    virtual Type* getType() { assert(type); return type; }
+    virtual DLValueCast* isLValueCast() { return this; }
+};
+
+#endif // LLVMDC_GEN_DVALUE_H
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/structs.cpp	Tue Nov 06 10:03:14 2007 +0100
@@ -0,0 +1,319 @@
+#include <algorithm>
+
+#include "gen/llvm.h"
+
+#include "mtype.h"
+#include "aggregate.h"
+#include "init.h"
+#include "declaration.h"
+
+#include "gen/irstate.h"
+#include "gen/tollvm.h"
+#include "gen/arrays.h"
+#include "gen/logger.h"
+#include "gen/structs.h"
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+const llvm::Type* DtoStructType(Type* t)
+{
+    assert(0);
+    std::vector<const llvm::Type*> types;
+    return llvm::StructType::get(types);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoStructZeroInit(llvm::Value* v)
+{
+    assert(gIR);
+    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);
+
+    llvm::Value* sarr = new llvm::BitCastInst(v,sarrty,"tmp",gIR->scopebb());
+
+    llvm::Function* fn = LLVM_DeclareMemSet32();
+    std::vector<llvm::Value*> llargs;
+    llargs.resize(4);
+    llargs[0] = sarr;
+    llargs[1] = llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false);
+    llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
+    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+
+    llvm::Value* ret = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
+
+    return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoStructCopy(llvm::Value* dst, llvm::Value* src)
+{
+    Logger::cout() << "dst = " << *dst << " src = " << *src << '\n';
+    assert(dst->getType() == src->getType());
+    assert(gIR);
+
+    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);
+
+    llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
+    llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb());
+
+    llvm::Function* fn = LLVM_DeclareMemCpy32();
+    std::vector<llvm::Value*> llargs;
+    llargs.resize(4);
+    llargs[0] = dstarr;
+    llargs[1] = srcarr;
+    llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
+    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
+
+    return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+llvm::Constant* DtoConstStructInitializer(StructInitializer* si)
+{
+    Logger::println("DtoConstStructInitializer: %s", si->toChars());
+    LOG_SCOPE;
+
+    const llvm::StructType* structtype = llvm::cast<llvm::StructType>(si->ad->llvmType);
+    Logger::cout() << "llvm struct type: " << *structtype << '\n';
+
+    assert(si->value.dim == si->vars.dim);
+
+    std::vector<DUnionIdx> inits;
+    for (int i = 0; i < si->value.dim; ++i)
+    {
+        Initializer* ini = (Initializer*)si->value.data[i];
+        assert(ini);
+        VarDeclaration* vd = (VarDeclaration*)si->vars.data[i];
+        assert(vd);
+        llvm::Constant* v = DtoConstInitializer(vd->type, ini);
+        inits.push_back(DUnionIdx(vd->llvmFieldIndex, vd->llvmFieldIndexOffset, v));
+    }
+
+    return si->ad->llvmUnion->getConst(inits);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+
+llvm::Value* DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs)
+{
+    Logger::println("checking for offset %u type %s:", os, t->toChars());
+    LOG_SCOPE;
+
+    if (idxs.empty())
+        idxs.push_back(0);
+
+    const llvm::Type* llt = llvm::PointerType::get(DtoType(t));
+    const llvm::Type* st = llvm::PointerType::get(DtoType(sd->type));
+    if (ptr->getType() != st) {
+        assert(sd->llvmHasUnions);
+        ptr = gIR->ir->CreateBitCast(ptr, st, "tmp");
+    }
+
+    for (unsigned i=0; i<sd->fields.dim; ++i) {
+        VarDeclaration* vd = (VarDeclaration*)sd->fields.data[i];
+        Type* vdtype = DtoDType(vd->type);
+        Logger::println("found %u type %s", vd->offset, vdtype->toChars());
+        assert(vd->llvmFieldIndex >= 0);
+        if (os == vd->offset && vdtype == t) {
+            idxs.push_back(vd->llvmFieldIndex);
+            ptr = DtoGEP(ptr, idxs, "tmp");
+            if (ptr->getType() != llt)
+                ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
+            if (vd->llvmFieldIndexOffset)
+                ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb());
+            return ptr;
+        }
+        else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) {
+            TypeStruct* ts = (TypeStruct*)vdtype;
+            StructDeclaration* ssd = ts->sym;
+            idxs.push_back(vd->llvmFieldIndex);
+            if (vd->llvmFieldIndexOffset) {
+                Logger::println("has union field offset");
+                ptr = DtoGEP(ptr, idxs, "tmp");
+                if (ptr->getType() != llt)
+                    ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
+                ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb());
+                std::vector<unsigned> tmp;
+                return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
+            }
+            else {
+                const llvm::Type* sty = llvm::PointerType::get(DtoType(vd->type));
+                if (ptr->getType() != sty) {
+                    ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
+                    std::vector<unsigned> tmp;
+                    return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
+                }
+                else {
+                    return DtoIndexStruct(ptr, ssd, t, os-vd->offset, idxs);
+                }
+            }
+        }
+    }
+
+    size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0));
+    assert(os % llt_sz == 0);
+    ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
+    return new llvm::GetElementPtrInst(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb());
+}
+//////////////////////////////////////////////////////////////////////////////////////////
+////////////////////////////   D UNION HELPER CLASS   ////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////////////
+
+DUnion::DUnion()
+{
+    DUnionField* f = NULL;
+    IRStruct& topstruct = gIR->topstruct();
+    bool unions = false;
+    for (IRStruct::OffsetMap::iterator i=topstruct.offsets.begin(); i!=topstruct.offsets.end(); ++i)
+    {
+        unsigned o = i->first;
+        IRStruct::Offset* so = &i->second;
+        const llvm::Type* ft = so->init->getType();
+        size_t sz = gTargetData->getTypeSize(ft);
+        if (f == NULL) { // new field
+            fields.push_back(DUnionField());
+            f = &fields.back();
+            f->size = sz;
+            f->offset = o;
+            f->init = so->init;
+            f->initsize = sz; 
+            f->types.push_back(ft);
+        }
+        else if (o == f->offset) { // same offset
+            if (sz > f->size)
+                f->size = sz;
+            f->types.push_back(ft);
+            unions = true;
+        }
+        else if (o < f->offset+f->size) {
+            assert((o+sz) <= (f->offset+f->size));
+            unions = true;
+        }
+        else {
+            fields.push_back(DUnionField());
+            f = &fields.back();
+            f->size = sz;
+            f->offset = o;
+            f->init = so->init;
+            f->initsize = sz;
+            f->types.push_back(ft);
+        }
+    }
+
+    {
+        LOG_SCOPE;
+        Logger::println("******** DUnion BEGIN");
+        size_t n = fields.size();
+        for (size_t i=0; i<n; ++i) {
+            Logger::cout()<<"field #"<<i<<" offset: "<<fields[i].offset<<" size: "<<fields[i].size<<'('<<fields[i].initsize<<")\n";
+            LOG_SCOPE;
+            size_t nt = fields[i].types.size();
+            for (size_t j=0; j<nt; ++j) {
+                Logger::cout()<<*fields[i].types[j]<<'\n';
+            }
+        }
+        Logger::println("******** DUnion END");
+    }
+}
+
+static void push_nulls(size_t nbytes, std::vector<llvm::Constant*>& out)
+{
+    assert(nbytes > 0);
+    std::vector<llvm::Constant*> i(nbytes, llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false));
+    out.push_back(llvm::ConstantArray::get(llvm::ArrayType::get(llvm::Type::Int8Ty, nbytes), i));
+}
+
+llvm::Constant* DUnion::getConst(std::vector<DUnionIdx>& in)
+{
+    std::sort(in.begin(), in.end());
+    std::vector<llvm::Constant*> out;
+
+    size_t nin = in.size();
+    size_t nfields = fields.size();
+
+    size_t fi = 0;
+    size_t last = 0;
+    size_t ii = 0;
+    size_t os = 0;
+
+    for(;;)
+    {
+        if (fi == nfields) break;
+
+        bool nextSame = (ii+1 < nin) && (in[ii+1].idx == fi);
+
+        if (ii < nin && fi == in[ii].idx)
+        {
+            size_t s = gTargetData->getTypeSize(in[ii].c->getType());
+            if (in[ii].idx == last)
+            {
+                size_t nos = in[ii].idxos * s;
+                if (nos && nos-os) {
+                    assert(nos >= os);
+                    push_nulls(nos-os, out);
+                }
+                os = nos + s;
+            }
+            else
+            {
+                os = s;
+            }
+            out.push_back(in[ii].c);
+            ii++;
+            if (!nextSame)
+            {
+                if (os < fields[fi].size)
+                    push_nulls(fields[fi].size - os, out);
+                os = 0;
+                last = fi++;
+            }
+            continue;
+        }
+
+        // default initialize if necessary
+        if (ii == nin || fi < in[ii].idx)
+        {
+            DUnionField& f = fields[fi];
+            out.push_back(f.init);
+            if (f.initsize < f.size)
+                push_nulls(f.size - f.initsize, out);
+            last = fi++;
+            os = 0;
+            continue;
+        }
+    }
+
+    std::vector<const llvm::Type*> tys;
+    size_t nout = out.size();
+    for (size_t i=0; i<nout; ++i)
+        tys.push_back(out[i]->getType());
+
+    const llvm::StructType* st = llvm::StructType::get(tys);
+    return llvm::ConstantStruct::get(st, out);
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gen/structs.h	Tue Nov 06 10:03:14 2007 +0100
@@ -0,0 +1,49 @@
+#ifndef LLVMD_GEN_STRUCTS_H
+#define LLVMD_GEN_STRUCTS_H
+
+struct StructInitializer;
+const llvm::Type* DtoStructType(Type* t);
+llvm::Value* DtoStructZeroInit(llvm::Value* v);
+llvm::Value* DtoStructCopy(llvm::Value* dst, llvm::Value* src);
+llvm::Constant* DtoConstStructInitializer(StructInitializer* si);
+llvm::Value* DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs);
+
+struct DUnionField
+{
+    unsigned offset;
+    size_t size;
+    std::vector<const llvm::Type*> types;
+    llvm::Constant* init;
+    size_t initsize;
+
+    DUnionField() {
+        offset = 0;
+        size = 0;
+        init = NULL;
+        initsize = 0;
+    }
+};
+
+struct DUnionIdx
+{
+    unsigned idx,idxos;
+    llvm::Constant* c;
+
+    DUnionIdx()
+    : idx(0), c(0) {}
+    DUnionIdx(unsigned _idx, unsigned _idxos, llvm::Constant* _c)
+    : idx(_idx), idxos(_idxos), c(_c) {}
+    bool operator<(const DUnionIdx& i) const {
+        return (idx < i.idx) || (idx == i.idx && idxos < i.idxos);
+    }
+};
+
+class DUnion
+{
+    std::vector<DUnionField> fields;
+public:
+    DUnion();
+    llvm::Constant* getConst(std::vector<DUnionIdx>& in);
+};
+
+#endif
--- a/gen/toir.cpp	Sat Nov 03 14:48:33 2007 +0100
+++ b/gen/toir.cpp	Tue Nov 06 10:03:14 2007 +0100
@@ -27,6 +27,7 @@
 #include "gen/tollvm.h"
 #include "gen/runtime.h"
 #include "gen/arrays.h"
+#include "gen/structs.h"
 
 #include "gen/dvalue.h"
 
@@ -178,9 +179,12 @@
         }
         else {
             // take care of forward references of global variables
-            if (!vd->llvmTouched && vd->isDataseg())
+            if (!vd->llvmTouched && (vd->isDataseg() || (vd->storage_class & STCextern))) // !vd->onstack)
                 vd->toObjFile();
-            assert(vd->llvmValue);
+            if (!vd->llvmValue) {
+                Logger::println("global variable not resolved :/ %s", vd->toChars());
+                assert(0);
+            }
             return new DVarValue(vd, vd->llvmValue, true);
         }
     }
@@ -225,7 +229,7 @@
         assert(ts->sym->llvmInitZ);
         return ts->sym->llvmInitZ;
     }
-    assert(0 && "Only support const var exp is SymbolDeclaration");
+    assert(0 && "Only supported const VarExp is of a SymbolDeclaration");
     return NULL;
 }
 
@@ -247,14 +251,15 @@
     LOG_SCOPE;
     const llvm::Type* t = DtoType(type);
     if (llvm::isa<llvm::PointerType>(t)) {
+        Logger::println("pointer");
         llvm::Constant* i = llvm::ConstantInt::get(DtoSize_t(),(uint64_t)value,false);
         return llvm::ConstantExpr::getIntToPtr(i, t);
     }
-    else if (llvm::isa<llvm::IntegerType>(t)) {
-        return llvm::ConstantInt::get(t,(uint64_t)value,!type->isunsigned());
-    }
-    assert(0);
-    return NULL;
+    assert(llvm::isa<llvm::IntegerType>(t));
+    llvm::Constant* c = llvm::ConstantInt::get(t,(uint64_t)value,!type->isunsigned());
+    assert(c);
+    Logger::cout() << "value = " << *c << '\n';
+    return c;
 }
 
 //////////////////////////////////////////////////////////////////////////////////////////
@@ -1447,7 +1452,7 @@
     if (isslice) {
         return new DSliceValue(type, rval2, rval);
     }
-    else if (u->isLValueCast() || u->isVar()) {
+    else if (u->isLValueCast() || (u->isVar() && u->isVar()->lval)) {
         return new DLValueCast(type, u->getLVal(), rval);
     }
     else if (p->topexp() && p->topexp()->e1 == this) {
@@ -2875,7 +2880,7 @@
 STUB(AssocArrayLiteralExp);
 //STUB(StructLiteralExp);
 
-#define CONSTSTUB(x) llvm::Constant* x::toConstElem(IRState * p) {error("const Exp type "#x" not implemented: '%s' type: '%s'", toChars(), type->toChars()); assert(0); fatal(); return NULL; }
+#define CONSTSTUB(x) llvm::Constant* x::toConstElem(IRState * p) {error("const Exp type "#x" not implemented: '%s' type: '%s'", toChars(), type->toChars()); fatal(); return NULL; }
 CONSTSTUB(Expression);
 //CONSTSTUB(IntegerExp);
 //CONSTSTUB(RealExp);
--- a/gen/tollvm.cpp	Sat Nov 03 14:48:33 2007 +0100
+++ b/gen/tollvm.cpp	Tue Nov 06 10:03:14 2007 +0100
@@ -14,6 +14,7 @@
 #include "gen/runtime.h"
 #include "gen/arrays.h"
 #include "gen/dvalue.h"
+#include "gen/structs.h"
 
 bool DtoIsPassedByRef(Type* type)
 {
@@ -375,16 +376,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-const llvm::Type* DtoStructType(Type* t)
-{
-    assert(0);
-    std::vector<const llvm::Type*> types;
-    return llvm::StructType::get(types);
-}
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 static llvm::Function* LLVM_DeclareMemIntrinsic(const char* name, int bits, bool set=false)
 {
     assert(bits == 32 || bits == 64);
@@ -456,132 +447,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-llvm::Value* DtoStructZeroInit(llvm::Value* v)
-{
-    assert(gIR);
-    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);
-
-    llvm::Value* sarr = new llvm::BitCastInst(v,sarrty,"tmp",gIR->scopebb());
-
-    llvm::Function* fn = LLVM_DeclareMemSet32();
-    std::vector<llvm::Value*> llargs;
-    llargs.resize(4);
-    llargs[0] = sarr;
-    llargs[1] = llvm::ConstantInt::get(llvm::Type::Int8Ty, 0, false);
-    llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
-    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-
-    llvm::Value* ret = new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
-
-    return ret;
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
-llvm::Value* DtoStructCopy(llvm::Value* dst, llvm::Value* src)
-{
-    Logger::cout() << "dst = " << *dst << " src = " << *src << '\n';
-    assert(dst->getType() == src->getType());
-    assert(gIR);
-
-    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);
-
-    llvm::Value* dstarr = new llvm::BitCastInst(dst,arrty,"tmp",gIR->scopebb());
-    llvm::Value* srcarr = new llvm::BitCastInst(src,arrty,"tmp",gIR->scopebb());
-
-    llvm::Function* fn = LLVM_DeclareMemCpy32();
-    std::vector<llvm::Value*> llargs;
-    llargs.resize(4);
-    llargs[0] = dstarr;
-    llargs[1] = srcarr;
-    llargs[2] = llvm::ConstantInt::get(llvm::Type::Int32Ty, n, false);
-    llargs[3] = llvm::ConstantInt::get(llvm::Type::Int32Ty, 0, false);
-
-    return new llvm::CallInst(fn, llargs.begin(), llargs.end(), "", gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-llvm::Constant* DtoConstStructInitializer(StructInitializer* si)
-{
-    llvm::StructType* structtype = llvm::cast<llvm::StructType>(si->ad->llvmType);
-    size_t n = structtype->getNumElements();
-
-    assert(si->value.dim == si->vars.dim);
-
-    std::vector<llvm::Constant*> inits;
-    inits.resize(n, NULL);
-    for (int i = 0; i < si->value.dim; ++i)
-    {
-        Initializer* ini = (Initializer*)si->value.data[i];
-        assert(ini);
-
-        VarDeclaration* vd = (VarDeclaration*)si->vars.data[i];
-        Type* vdtype = DtoDType(vd->type);
-        assert(vd);
-        Logger::println("vars[%d] = %s", i, vd->toChars());
-
-        llvm::Constant* v = 0;
-
-        assert(vd->llvmFieldIndex >= 0);
-        unsigned idx = vd->llvmFieldIndex;
-
-        if (ExpInitializer* ex = ini->isExpInitializer())
-        {
-            v = ex->exp->toConstElem(gIR);
-        }
-        else if (StructInitializer* si = ini->isStructInitializer())
-        {
-            v = DtoConstStructInitializer(si);
-        }
-        else if (ArrayInitializer* ai = ini->isArrayInitializer())
-        {
-            v = DtoConstArrayInitializer(ai);
-        }
-        else if (ini->isVoidInitializer())
-        {
-            v = llvm::UndefValue::get(structtype->getElementType(idx));
-        }
-        else
-        assert(v);
-
-        inits[idx] = v;
-        Logger::cout() << "init[" << idx << "] = " << *v << '\n';
-    }
-
-    // fill out nulls
-    assert(si->ad->llvmInitZ);
-    if (si->ad->llvmInitZ->isNullValue())
-    {
-        for (int i = 0; i < n; ++i)
-        {
-            if (inits[i] == 0)
-            {
-                inits[i] = llvm::Constant::getNullValue(structtype->getElementType(i));
-            }
-        }
-    }
-    else
-    {
-        for (int i = 0; i < n; ++i)
-        {
-            if (inits[i] == 0)
-            {
-                inits[i] = si->ad->llvmInitZ->getOperand(i);
-            }
-        }
-    }
-
-    return llvm::ConstantStruct::get(structtype, inits);
-}
-
-
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 llvm::Value* DtoNullDelegate(llvm::Value* v)
 {
     assert(gIR);
@@ -1495,65 +1360,6 @@
 
 //////////////////////////////////////////////////////////////////////////////////////////
 
-llvm::Value* DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs)
-{
-    Logger::println("checking for offset %u type %s:", os, t->toChars());
-    LOG_SCOPE;
-
-    if (idxs.empty())
-        idxs.push_back(0);
-
-    const llvm::Type* llt = llvm::PointerType::get(DtoType(t));
-
-    for (unsigned i=0; i<sd->fields.dim; ++i) {
-        VarDeclaration* vd = (VarDeclaration*)sd->fields.data[i];
-        Type* vdtype = DtoDType(vd->type);
-        Logger::println("found %u type %s", vd->offset, vdtype->toChars());
-        assert(vd->llvmFieldIndex >= 0);
-        if (os == vd->offset && vdtype == t) {
-            idxs.push_back(vd->llvmFieldIndex);
-            ptr = DtoGEP(ptr, idxs, "tmp");
-            if (ptr->getType() != llt)
-                ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
-            if (vd->llvmFieldIndexOffset)
-                ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb());
-            return ptr;
-        }
-        else if (vdtype->ty == Tstruct && (vd->offset + vdtype->size()) > os) {
-            TypeStruct* ts = (TypeStruct*)vdtype;
-            StructDeclaration* ssd = ts->sym;
-            idxs.push_back(vd->llvmFieldIndex);
-            if (vd->llvmFieldIndexOffset) {
-                Logger::println("has union field offset");
-                ptr = DtoGEP(ptr, idxs, "tmp");
-                if (ptr->getType() != llt)
-                    ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
-                ptr = new llvm::GetElementPtrInst(ptr, DtoConstUint(vd->llvmFieldIndexOffset), "tmp", gIR->scopebb());
-                std::vector<unsigned> tmp;
-                return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
-            }
-            else {
-                const llvm::Type* sty = llvm::PointerType::get(DtoType(vd->type));
-                if (ptr->getType() != sty) {
-                    ptr = gIR->ir->CreateBitCast(ptr, sty, "tmp");
-                    std::vector<unsigned> tmp;
-                    return DtoIndexStruct(ptr, ssd, t, os-vd->offset, tmp);
-                }
-                else {
-                    return DtoIndexStruct(ptr, ssd, t, os-vd->offset, idxs);
-                }
-            }
-        }
-    }
-
-    size_t llt_sz = gTargetData->getTypeSize(llt->getContainedType(0));
-    assert(os % llt_sz == 0);
-    ptr = gIR->ir->CreateBitCast(ptr, llt, "tmp");
-    return new llvm::GetElementPtrInst(ptr, DtoConstUint(os / llt_sz), "tmp", gIR->scopebb());
-}
-
-//////////////////////////////////////////////////////////////////////////////////////////
-
 bool DtoIsTemplateInstance(Dsymbol* s)
 {
     if (!s) return false;
@@ -1563,3 +1369,28 @@
         return DtoIsTemplateInstance(s->parent);
     return false;
 }
+
+void DtoLazyStaticInit(bool istempl, llvm::Value* gvar, Initializer* init, Type* t)
+{
+    // create a flag to make sure initialization only happens once
+    llvm::GlobalValue::LinkageTypes gflaglink = istempl ? llvm::GlobalValue::WeakLinkage : llvm::GlobalValue::InternalLinkage;
+    std::string gflagname(gvar->getName());
+    gflagname.append("__initflag");
+    llvm::GlobalVariable* gflag = new llvm::GlobalVariable(llvm::Type::Int1Ty,false,gflaglink,DtoConstBool(false),gflagname,gIR->module);
+
+    // check flag and do init if not already done
+    llvm::BasicBlock* oldend = gIR->scopeend();
+    llvm::BasicBlock* initbb = new llvm::BasicBlock("ifnotinit",gIR->topfunc(),oldend);
+    llvm::BasicBlock* endinitbb = new llvm::BasicBlock("ifnotinitend",gIR->topfunc(),oldend);
+    llvm::Value* cond = gIR->ir->CreateICmpEQ(gIR->ir->CreateLoad(gflag,"tmp"),DtoConstBool(false));
+    gIR->ir->CreateCondBr(cond, initbb, endinitbb);
+    gIR->scope() = IRScope(initbb,endinitbb);
+    DValue* ie = DtoInitializer(init);
+    if (!ie->inPlace()) {
+        DValue* dst = new DVarValue(t, gvar, true);
+        DtoAssign(dst, ie);
+    }
+    gIR->ir->CreateStore(DtoConstBool(true), gflag);
+    gIR->ir->CreateBr(endinitbb);
+    gIR->scope() = IRScope(endinitbb,oldend);
+}
--- a/gen/tollvm.h	Sat Nov 03 14:48:33 2007 +0100
+++ b/gen/tollvm.h	Tue Nov 06 10:03:14 2007 +0100
@@ -3,18 +3,12 @@
 
 // D -> LLVM helpers
 
-struct StructInitializer;
 struct DValue;
 
 const llvm::Type* DtoType(Type* t);
 bool DtoIsPassedByRef(Type* type);
 Type* DtoDType(Type* t);
 
-const llvm::Type* DtoStructType(Type* t);
-llvm::Value* DtoStructZeroInit(llvm::Value* v);
-llvm::Value* DtoStructCopy(llvm::Value* dst, llvm::Value* src);
-llvm::Constant* DtoConstStructInitializer(StructInitializer* si);
-
 const llvm::FunctionType* DtoFunctionType(Type* t, const llvm::Type* thistype, bool ismain = false);
 const llvm::FunctionType* DtoFunctionType(FuncDeclaration* fdecl);
 llvm::Function* DtoDeclareFunction(FuncDeclaration* fdecl);
@@ -66,9 +60,9 @@
 llvm::Constant* DtoConstStringPtr(const char* str, const char* section = 0);
 llvm::Constant* DtoConstBool(bool);
 
-llvm::Value* DtoIndexStruct(llvm::Value* ptr, StructDeclaration* sd, Type* t, unsigned os, std::vector<unsigned>& idxs);
+bool DtoIsTemplateInstance(Dsymbol* s);
 
-bool DtoIsTemplateInstance(Dsymbol* s);
+void DtoLazyStaticInit(bool istempl, llvm::Value* gvar, Initializer* init, Type* t);
 
 // llvm wrappers
 void DtoMemCpy(llvm::Value* dst, llvm::Value* src, llvm::Value* nbytes);
--- a/gen/toobj.cpp	Sat Nov 03 14:48:33 2007 +0100
+++ b/gen/toobj.cpp	Tue Nov 06 10:03:14 2007 +0100
@@ -36,6 +36,7 @@
 #include "gen/logger.h"
 #include "gen/tollvm.h"
 #include "gen/arrays.h"
+#include "gen/structs.h"
 #include "gen/todebug.h"
 #include "gen/runtime.h"
 
@@ -287,6 +288,8 @@
         gIR->module->addTypeName(mangle(),ts->llvmType);
     }
 
+    llvmUnion = new DUnion; // uses gIR->topstruct()
+
     // generate static data
     llvm::GlobalValue::LinkageTypes _linkage = llvm::GlobalValue::ExternalLinkage;
     llvm::Constant* _init = 0;
@@ -572,6 +575,7 @@
 
     if (aliassym)
     {
+        Logger::println("alias sym");
         toAlias()->toObjFile();
         return;
     }
@@ -608,35 +612,13 @@
         Logger::println("Creating global variable");
         std::string _name(mangle());
 
-        llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,0,_name,M);
-        llvmValue = gvar;
+        bool emitRTstaticInit = false;
 
         if (!(storage_class & STCextern) && (getModule() == gIR->dmodule || istempl))
         {
             if (parent && parent->isFuncDeclaration() && init && init->isExpInitializer()) {
                 _init = DtoConstInitializer(t, NULL);
-                // create a flag to make sure initialization only happens once
-                llvm::GlobalValue::LinkageTypes gflaglink = istempl ? llvm::GlobalValue::WeakLinkage : llvm::GlobalValue::InternalLinkage;
-                std::string gflagname(_name);
-                gflagname.append("__initflag");
-                llvm::GlobalVariable* gflag = new llvm::GlobalVariable(llvm::Type::Int1Ty,false,gflaglink,DtoConstBool(false),gflagname,M);
-
-                // check flag and do init if not already done
-                llvm::BasicBlock* oldend = gIR->scopeend();
-                llvm::BasicBlock* initbb = new llvm::BasicBlock("ifnotinit",gIR->topfunc(),oldend);
-                llvm::BasicBlock* endinitbb = new llvm::BasicBlock("ifnotinitend",gIR->topfunc(),oldend);
-                llvm::Value* cond = gIR->ir->CreateICmpEQ(gIR->ir->CreateLoad(gflag,"tmp"),DtoConstBool(false));
-                gIR->ir->CreateCondBr(cond, initbb, endinitbb);
-                gIR->scope() = IRScope(initbb,endinitbb);
-                elem* ie = DtoInitializer(init);
-                if (!ie->inPlace()) {
-                    DValue* dst = new DVarValue(t, gvar, true);
-                    DtoAssign(dst, ie);
-                    delete dst;
-                }
-                gIR->ir->CreateStore(DtoConstBool(true), gflag);
-                gIR->ir->CreateBr(endinitbb);
-                gIR->scope() = IRScope(endinitbb,oldend);
+                emitRTstaticInit = true;
             }
             else {
                 _init = DtoConstInitializer(t, init);
@@ -668,10 +650,15 @@
                     //assert(0);
                 }
             }
+        }
 
-            Logger::cout() << "final init = " << *_init << '\n';
-            gvar->setInitializer(_init);
-        }
+        if (_init && _init->getType() != _type)
+            _type = _init->getType();
+        llvm::GlobalVariable* gvar = new llvm::GlobalVariable(_type,_isconst,_linkage,_init,_name,M);
+        llvmValue = gvar;
+
+        if (emitRTstaticInit)
+            DtoLazyStaticInit(istempl, gvar, init, t);
 
         llvmDModule = gIR->dmodule;
 
--- a/lphobos/phobos.d	Sat Nov 03 14:48:33 2007 +0100
+++ b/lphobos/phobos.d	Tue Nov 06 10:03:14 2007 +0100
@@ -3,7 +3,28 @@
 import
 std.array,
 std.ctype,
+std.intrinsic,
+std.stdint,
 std.stdio,
 std.stdarg,
 std.uni,
-std.utf;
\ No newline at end of file
+std.utf,
+
+std.c.fenv,
+std.c.locale,
+std.c.math,
+std.c.process,
+std.c.stdarg,
+std.c.stddef,
+std.c.stdio,
+std.c.stdlib,
+std.c.string,
+std.c.time;
+
+version(linux) {
+    import
+    std.c.linux.linux,
+    std.c.linux.linuxextern,
+    std.c.linux.pthread,
+    std.c.linux.socket;
+}
--- a/lphobos/std/c/linux/linuxextern.d	Sat Nov 03 14:48:33 2007 +0100
+++ b/lphobos/std/c/linux/linuxextern.d	Tue Nov 06 10:03:14 2007 +0100
@@ -12,7 +12,7 @@
 
 module std.c.linux.linuxextern;
 
-extern (C)
+extern extern (C)
 {
     void* __libc_stack_end;
     int __data_start;
--- a/lphobos/std/c/linux/socket.d	Sat Nov 03 14:48:33 2007 +0100
+++ b/lphobos/std/c/linux/socket.d	Tue Nov 06 10:03:14 2007 +0100
@@ -331,7 +331,7 @@
 }
 
 
-const in6_addr IN6ADDR_ANY = { s6_addr8: [0] };
+const in6_addr IN6ADDR_ANY;
 const in6_addr IN6ADDR_LOOPBACK = { s6_addr8: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] };
 //alias IN6ADDR_ANY IN6ADDR_ANY_INIT;
 //alias IN6ADDR_LOOPBACK IN6ADDR_LOOPBACK_INIT;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/bug51.d	Tue Nov 06 10:03:14 2007 +0100
@@ -0,0 +1,26 @@
+module bug51;
+
+import std.stdint;
+
+union in6_addr
+{
+    private union _in6_u_t
+    {
+        uint8_t[16] u6_addr8;
+        uint16_t[8] u6_addr16;
+        uint32_t[4] u6_addr32;
+    }
+    _in6_u_t in6_u;
+
+    uint8_t[16] s6_addr8;
+    uint16_t[8] s6_addr16;
+    uint32_t[4] s6_addr32;
+}
+
+
+const in6_addr IN6ADDR_ANY = { s6_addr8: [0] };
+const in6_addr IN6ADDR_LOOPBACK = { s6_addr8: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1] };
+
+void main()
+{
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/union7.d	Tue Nov 06 10:03:14 2007 +0100
@@ -0,0 +1,48 @@
+module union7;
+
+pragma(LLVM_internal, "notypeinfo")
+struct Union
+{
+    union {
+        double g;
+        struct {
+            short s1,s2,s3,s4;
+        }
+    }
+    union {
+        float f;
+        long l;
+    }
+}
+
+Union a = { f:4f };
+Union b = { 3.0, f:2 };
+Union c = { l:42, g:2.0 };
+Union d = { s2:3 };
+Union e = { s1:3, s4:4, l:5 };
+
+void main()
+{
+    assert(a.f == 4f);
+    assert(a.g !<>= 0.0);
+    assert((a.l>>>32) == 0);
+
+    assert(b.g == 3.0);
+    assert(b.f == 2f);
+
+    assert(c.l == 42);
+    assert(c.g == 2.0);
+
+    assert(d.s1 == 0);
+    assert(d.s2 == 3);
+    assert(d.s3 == 0);
+    assert(d.s4 == 0);
+    {assert(d.f !<>= 0f);}
+    {}
+    assert(e.s1 == 3);
+    assert(e.s2 == 0);
+    assert(e.s3 == 0);
+    {assert(e.s4 == 4);}
+    {}
+    assert(e.l == 5);
+}