Beispiel #1
0
void StructDeclaration::toDt(dt_t **pdt)
{
    if (zeroInit)
    {
        dtnzeros(pdt, structsize);
        return;
    }

    unsigned offset;
    dt_t *dt;
    dt_t *sdt = NULL;

    //printf("StructDeclaration::toDt(), this='%s'\n", toChars());
    offset = 0;

    // Note equivalence of this loop to class's
    for (size_t i = 0; i < fields.dim; i++)
    {
        VarDeclaration *v = (VarDeclaration *)fields.data[i];
        Initializer *init;

        //printf("\tfield '%s' voffset %d, offset = %d\n", v->toChars(), v->offset, offset);
        dt = NULL;
        init = v->init;
        if (init)
        {   //printf("\t\thas initializer %s\n", init->toChars());
            ExpInitializer *ei = init->isExpInitializer();
            Type *tb = v->type->toBasetype();
            if (ei && tb->ty == Tsarray)
                ((TypeSArray *)tb)->toDtElem(&dt, ei->exp);
            else
                dt = init->toDt();
        }
        else if (v->offset >= offset)
            v->type->toDt(&dt);
        if (dt)
        {
            if (v->offset < offset)
                error("overlapping initialization for struct %s.%s", toChars(), v->toChars());
            else
            {
                if (offset < v->offset)
                    dtnzeros(&sdt, v->offset - offset);
                dtcat(&sdt, dt);
                offset = v->offset + v->type->size();
            }
        }
    }

    if (offset < structsize)
        dtnzeros(&sdt, structsize - offset);
#ifdef IN_GCC
    dtcontainer(pdt, type, sdt);
#else
    dtcat(pdt, sdt);
#endif
    dt_optimize(*pdt);
}
Beispiel #2
0
void StructDeclaration::toDt(dt_t **pdt)
{
    unsigned offset;
    unsigned i;
    dt_t *dt;

    //printf("StructDeclaration::toDt(), this='%s'\n", toChars());
    offset = 0;

    // Note equivalence of this loop to class's
    for (i = 0; i < fields.dim; i++)
    {
        VarDeclaration *v = (VarDeclaration *)fields.data[i];
        //printf("\tfield '%s' voffset %d, offset = %d\n", v->toChars(), v->offset, offset);
        dt = NULL;
        int sz;

        if (v->storage_class & STCref)
        {
            sz = PTRSIZE;
            if (v->offset >= offset)
                dtnzeros(&dt, sz);
        }
        else
        {
            sz = v->type->size();
            Initializer *init = v->init;
            if (init)
            {   //printf("\t\thas initializer %s\n", init->toChars());
                ExpInitializer *ei = init->isExpInitializer();
                Type *tb = v->type->toBasetype();
                if (ei && tb->ty == Tsarray)
                    ((TypeSArray *)tb)->toDtElem(&dt, ei->exp);
                else
                    dt = init->toDt();
            }
            else if (v->offset >= offset)
                v->type->toDt(&dt);
        }
        if (dt)
        {
            if (v->offset < offset)
                error("overlapping initialization for struct %s.%s", toChars(), v->toChars());
            else
            {
                if (offset < v->offset)
                    dtnzeros(pdt, v->offset - offset);
                dtcat(pdt, dt);
                offset = v->offset + sz;
            }
        }
    }

    if (offset < structsize)
        dtnzeros(pdt, structsize - offset);

    dt_optimize(*pdt);
}
Beispiel #3
0
Datei: dt.c Projekt: Govelius/dmd
void init_common(symbol *s)
{
    //printf("init_common('%s')\n", s->Sident);
    dtnzeros(&s->Sdt,type_size(s->Stype));
    if (s->Sdt)
        s->Sdt->dt = DT_common;
}
Beispiel #4
0
dt_t *VoidInitializer::toDt()
{   /* Void initializers are set to 0, just because we need something
     * to set them to in the static data segment.
     */
    dt_t *dt = NULL;

    dtnzeros(&dt, type->size());
    return dt;
}
Beispiel #5
0
Symbol *Module::gencritsec()
{
    Symbol *s;
    type *t;

    t = Type::tint32->toCtype();
    s = symbol_name("critsec", SCstatic, t);
    s->Sfl = FLdata;
    /* Must match D_CRITICAL_SECTION in phobos/internal/critical.c
     */
    dtnzeros(&s->Sdt, PTRSIZE + (I64 ? os_critsecsize64() : os_critsecsize32()));
    outdata(s);
    return s;
}
Beispiel #6
0
Symbol *Module::gencritsec()
{
    Symbol *s;
    type *t;

    t = Type::tint32->toCtype();
    s = symbol_name("critsec", SCstatic, t);
    s->Sfl = FLdata;
    /* Must match D_CRITICAL_SECTION in phobos/internal/critical.c
     */
    dtnzeros(&s->Sdt, PTRSIZE + os_critsecsize());
#if ELFOBJ || MACHOBJ // Burton
    s->Sseg = DATA;
#endif
    outdata(s);
    return s;
}
Beispiel #7
0
void ClassDeclaration::toDt2(dt_t **pdt, ClassDeclaration *cd)
{
    unsigned offset;
    dt_t *dt;
    unsigned csymoffset;

#define LOG 0

#if LOG
    printf("ClassDeclaration::toDt2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
#endif
    if (baseClass)
    {
        baseClass->toDt2(pdt, cd);
        offset = baseClass->structsize;
    }
    else
    {
        offset = PTRSIZE * 2;
    }

    // Note equivalence of this loop to struct's
    for (size_t i = 0; i < fields.dim; i++)
    {
        VarDeclaration *v = (VarDeclaration *)fields.data[i];
        Initializer *init;

        //printf("\t\tv = '%s' v->offset = %2d, offset = %2d\n", v->toChars(), v->offset, offset);
        dt = NULL;
        init = v->init;
        if (init)
        {   //printf("\t\t%s has initializer %s\n", v->toChars(), init->toChars());
            ExpInitializer *ei = init->isExpInitializer();
            Type *tb = v->type->toBasetype();
            if (ei && tb->ty == Tsarray)
                ((TypeSArray *)tb)->toDtElem(&dt, ei->exp);
            else
                dt = init->toDt();
        }
        else if (v->offset >= offset)
        {   //printf("\t\tdefault initializer\n");
            v->type->toDt(&dt);
        }
        if (dt)
        {
            if (v->offset < offset)
                error("duplicated union initialization for %s", v->toChars());
            else
            {
                if (offset < v->offset)
                    dtnzeros(pdt, v->offset - offset);
                dtcat(pdt, dt);
                offset = v->offset + v->type->size();
            }
        }
    }

    // Interface vptr initializations
    toSymbol();                                         // define csym

    for (size_t i = 0; i < vtblInterfaces->dim; i++)
    {   BaseClass *b = (BaseClass *)vtblInterfaces->data[i];

#if 1 || INTERFACE_VIRTUAL
        for (ClassDeclaration *cd2 = cd; 1; cd2 = cd2->baseClass)
        {
            assert(cd2);
            csymoffset = cd2->baseVtblOffset(b);
            if (csymoffset != ~0)
            {
                if (offset < b->offset)
                    dtnzeros(pdt, b->offset - offset);
                dtxoff(pdt, cd2->toSymbol(), csymoffset, TYnptr);
                break;
            }
        }
#else
        csymoffset = baseVtblOffset(b);
        assert(csymoffset != ~0);
        dtxoff(pdt, csym, csymoffset, TYnptr);
#endif
        offset = b->offset + PTRSIZE;
    }

    if (offset < structsize)
        dtnzeros(pdt, structsize - offset);

#undef LOG
}
Beispiel #8
0
dt_t *ArrayInitializer::toDtBit()
{
#if DMDV1
    unsigned size;
    unsigned length;
    unsigned tadim;
    dt_t *d;
    dt_t **pdtend;
    Type *tb = type->toBasetype();

    //printf("ArrayInitializer::toDtBit('%s')\n", toChars());

    Bits databits;
    Bits initbits;

    if (tb->ty == Tsarray)
    {
        /* The 'dim' for ArrayInitializer is only the maximum dimension
         * seen in the initializer, not the type. So, for static arrays,
         * use instead the dimension of the type in order
         * to get the whole thing.
         */
        dinteger_t value = ((TypeSArray*)tb)->dim->toInteger();
        tadim = value;
        assert(tadim == value);  // truncation overflow should already be checked
        databits.resize(tadim);
        initbits.resize(tadim);
    }
    else
    {
        databits.resize(dim);
        initbits.resize(dim);
    }

    /* The default initializer may be something other than zero.
     */
    if (tb->next->defaultInit()->toInteger())
        databits.set();

    size = sizeof(databits.data[0]);

    length = 0;
    for (size_t i = 0; i < index.dim; i++)
    {   Expression *idx;
        Initializer *val;
        Expression *eval;

        idx = (Expression *)index.data[i];
        if (idx)
        {   dinteger_t value;
            value = idx->toInteger();
            length = value;
            if (length != value)
            {   error(loc, "index overflow %llu", value);
                length = 0;
            }
        }
        assert(length < dim);

        val = (Initializer *)value.data[i];
        eval = val->toExpression();
        if (initbits.test(length))
            error(loc, "duplicate initializations for index %d", length);
        initbits.set(length);
        if (eval->toInteger())          // any non-zero value is boolean 'true'
            databits.set(length);
        else
            databits.clear(length);     // boolean 'false'
        length++;
    }

    d = NULL;
#ifdef IN_GCC
    pdtend = dtnbits(&d, databits.allocdim * size, (char *)databits.data, sizeof(databits.data[0]));
#else
    pdtend = dtnbytes(&d, databits.allocdim * size, (char *)databits.data);
#endif
    switch (tb->ty)
    {
    case Tsarray:
    {
        if (dim > tadim)
        {
            error(loc, "too many initializers, %d, for array[%d]", dim, tadim);
        }
        else
        {
            tadim = (tadim + 31) / 32;
            if (databits.allocdim < tadim)
                pdtend = dtnzeros(pdtend, size * (tadim - databits.allocdim));      // pad out end of array
        }
        break;
    }

    case Tpointer:
    case Tarray:
        // Create symbol, and then refer to it
        Symbol *s;
        s = static_sym();
        s->Sdt = d;
        outdata(s);

        d = NULL;
        if (tb->ty == Tarray)
            dtsize_t(&d, dim);
        dtxoff(&d, s, 0, TYnptr);
        break;

    default:
        assert(0);
    }
    return d;
#else
    return NULL;
#endif
}
Beispiel #9
0
dt_t *ArrayInitializer::toDt()
{
    //printf("ArrayInitializer::toDt('%s')\n", toChars());
    Type *tb = type->toBasetype();
    Type *tn = tb->next->toBasetype();

    if (tn->ty == Tbit)
        return toDtBit();

    Array dts;
    unsigned size;
    unsigned length;
    dt_t *dt;
    dt_t *d;
    dt_t **pdtend;

    //printf("\tdim = %d\n", dim);
    dts.setDim(dim);
    dts.zero();

    size = tn->size();

    length = 0;
    for (size_t i = 0; i < index.dim; i++)
    {   Expression *idx;
        Initializer *val;

        idx = (Expression *)index.data[i];
        if (idx)
            length = idx->toInteger();
        //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim);

        assert(length < dim);
        val = (Initializer *)value.data[i];
        dt = val->toDt();
        if (dts.data[length])
            error(loc, "duplicate initializations for index %d", length);
        dts.data[length] = (void *)dt;
        length++;
    }

    Expression *edefault = tb->next->defaultInit();
#ifdef IN_GCC
    dt_t * sadefault = NULL;

    if (tn->ty == Tsarray)
        tn->toDt(& sadefault);
    else
        edefault->toDt(& sadefault);
#else
    unsigned n = 1;
    for (Type *tbn = tn; tbn->ty == Tsarray; tbn = tbn->next->toBasetype())
    {   TypeSArray *tsa = (TypeSArray *)tbn;

        n *= tsa->dim->toInteger();
    }
#endif

    d = NULL;
    pdtend = &d;
    for (size_t i = 0; i < dim; i++)
    {
        dt = (dt_t *)dts.data[i];
#ifdef IN_GCC
        pdtend = dtcontainer(pdtend, NULL, dt ? dt : sadefault);
#else
        if (dt)
            pdtend = dtcat(pdtend, dt);
        else
        {
            for (size_t j = 0; j < n; j++)
                pdtend = edefault->toDt(pdtend);
        }
#endif
    }
    switch (tb->ty)
    {
    case Tsarray:
    {   unsigned tadim;
        TypeSArray *ta = (TypeSArray *)tb;

        tadim = ta->dim->toInteger();
        if (dim < tadim)
        {
            if (edefault->isBool(FALSE))
                // pad out end of array
                // (ok for GDC as well)
                pdtend = dtnzeros(pdtend, size * (tadim - dim));
            else
            {
                for (size_t i = dim; i < tadim; i++)
#ifdef IN_GCC
                    pdtend = dtcontainer(pdtend, NULL, sadefault);
#else
                {   for (size_t j = 0; j < n; j++)
                        pdtend = edefault->toDt(pdtend);
                }
#endif
            }
        }
        else if (dim > tadim)
        {
#ifdef DEBUG
            printf("1: ");
#endif
            error(loc, "too many initializers, %d, for array[%d]", dim, tadim);
        }
#ifdef IN_GCC
        dt_t * cdt = NULL;
        dtcontainer(& cdt, type, d);
        d = cdt;
#endif
        break;
    }

    case Tpointer:
    case Tarray:
    {   // Create symbol, and then refer to it
        Symbol *s = static_sym();
        s->Sdt = d;
        outdata(s);

        d = NULL;
        if (tb->ty == Tarray)
            dtsize_t(&d, dim);
        dtxoff(&d, s, 0, TYnptr);
#ifdef IN_GCC
        dt_t * cdt;
        cdt = NULL;
        if (tb->ty == Tarray)
        {
            dtcontainer(& cdt, type, d);
            d = cdt;
        }
#endif
        break;
    }

    default:
        assert(0);
    }
    return d;
}
Beispiel #10
0
        void visit(InterfaceDeclaration *id)
        {
            //printf("InterfaceDeclaration::toObjFile('%s')\n", id->toChars());

            if (id->type->ty == Terror)
            {
                id->error("had semantic errors when compiling");
                return;
            }

            if (!id->members)
                return;

            if (global.params.symdebug)
                toDebug(id);

            enum_SC scclass = SCglobal;
            if (id->isInstantiated())
                scclass = SCcomdat;

            // Put out the members
            for (size_t i = 0; i < id->members->dim; i++)
            {
                Dsymbol *member = (*id->members)[i];
                visitNoMultiObj(member);
            }

            // Generate C symbols
            toSymbol(id);

            //////////////////////////////////////////////

            // Put out the TypeInfo
            genTypeInfo(id->type, NULL);
            id->type->vtinfo->accept(this);

            //////////////////////////////////////////////

            // Put out the ClassInfo
            id->csym->Sclass = scclass;
            id->csym->Sfl = FLdata;

            /* The layout is:
               {
                    void **vptr;
                    monitor_t monitor;
                    byte[] initializer;         // static initialization data
                    char[] name;                // class name
                    void *[] vtbl;
                    Interface[] interfaces;
                    Object *base;               // base class
                    void *destructor;
                    void *invariant;            // class invariant
                    uint flags;
                    void *deallocator;
                    OffsetTypeInfo[] offTi;
                    void *defaultConstructor;
                    //const(MemberInfo[]) function(string) xgetMembers;   // module getMembers() function
                    void* xgetRTInfo;
                    //TypeInfo typeinfo;
               }
             */
            dt_t *dt = NULL;

            if (Type::typeinfoclass)
                dtxoff(&dt, toVtblSymbol(Type::typeinfoclass), 0, TYnptr); // vtbl for ClassInfo
            else
                dtsize_t(&dt, 0);                // BUG: should be an assert()
            dtsize_t(&dt, 0);                    // monitor

            // initializer[]
            dtsize_t(&dt, 0);                    // size
            dtsize_t(&dt, 0);                    // initializer

            // name[]
            const char *name = id->toPrettyChars();
            size_t namelen = strlen(name);
            dt_t **pdtname = dtsize_t(&dt, namelen);
            dtxoff(&dt, id->csym, 0, TYnptr);

            // vtbl[]
            dtsize_t(&dt, 0);
            dtsize_t(&dt, 0);

            // (*vtblInterfaces)[]
            unsigned offset = Target::classinfosize;
            dtsize_t(&dt, id->vtblInterfaces->dim);
            if (id->vtblInterfaces->dim)
            {
                if (Type::typeinfoclass)
                {
                    if (Type::typeinfoclass->structsize != offset)
                    {
                        id->error("mismatch between dmd and object.d or object.di found. Check installation and import paths with -v compiler switch.");
                        fatal();
                    }
                }
                dtxoff(&dt, id->csym, offset, TYnptr);      // (*)
            }
            else
            {
                dtsize_t(&dt, 0);
            }

            // base
            assert(!id->baseClass);
            dtsize_t(&dt, 0);

            // dtor
            dtsize_t(&dt, 0);

            // invariant
            dtsize_t(&dt, 0);

            // flags
            ClassFlags::Type flags = ClassFlags::hasOffTi | ClassFlags::hasTypeInfo;
            if (id->isCOMinterface()) flags |= ClassFlags::isCOMclass;
            dtsize_t(&dt, flags);

            // deallocator
            dtsize_t(&dt, 0);

            // offTi[]
            dtsize_t(&dt, 0);
            dtsize_t(&dt, 0);            // null for now, fix later

            // defaultConstructor
            dtsize_t(&dt, 0);

            // xgetMembers
            //dtsize_t(&dt, 0);

            // xgetRTInfo
            // xgetRTInfo
            if (id->getRTInfo)
                Expression_toDt(id->getRTInfo, &dt);
            else
                dtsize_t(&dt, 0);       // no pointers

            //dtxoff(&dt, toSymbol(id->type->vtinfo), 0, TYnptr); // typeinfo

            //////////////////////////////////////////////

            // Put out (*vtblInterfaces)[]. Must immediately follow csym, because
            // of the fixup (*)

            offset += id->vtblInterfaces->dim * (4 * Target::ptrsize);
            for (size_t i = 0; i < id->vtblInterfaces->dim; i++)
            {
                BaseClass *b = (*id->vtblInterfaces)[i];
                ClassDeclaration *base = b->sym;

                // ClassInfo
                dtxoff(&dt, toSymbol(base), 0, TYnptr);

                // vtbl[]
                dtsize_t(&dt, 0);
                dtsize_t(&dt, 0);

                // this offset
                dtsize_t(&dt, b->offset);
            }

            //////////////////////////////////////////////

            dtpatchoffset(*pdtname, offset);

            dtnbytes(&dt, namelen + 1, name);
            const size_t namepad =  -(namelen + 1) & (Target::ptrsize - 1); // align
            dtnzeros(&dt, namepad);

            id->csym->Sdt = dt;
            out_readonly(id->csym);
            outdata(id->csym);
            if (id->isExport())
                objmod->export_symbol(id->csym, 0);
        }
Beispiel #11
0
dt_t *ArrayInitializer::toDt()
{
    //printf("ArrayInitializer::toDt('%s')\n", toChars());
    Type *tb = type->toBasetype();
    if (tb->ty == Tvector)
        tb = ((TypeVector *)tb)->basetype;

    Type *tn = tb->nextOf()->toBasetype();

    Dts dts;
    unsigned size;
    unsigned length;
    dt_t *dt;
    dt_t *d;
    dt_t **pdtend;

    //printf("\tdim = %d\n", dim);
    dts.setDim(dim);
    dts.zero();

    size = tn->size();

    length = 0;
    for (size_t i = 0; i < index.dim; i++)
    {   Expression *idx;
        Initializer *val;

        idx = index[i];
        if (idx)
            length = idx->toInteger();
        //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim);

        assert(length < dim);
        val = value[i];
        dt = val->toDt();
        if (dts[length])
            error(loc, "duplicate initializations for index %d", length);
        if (tn->ty == Tsarray)
            dt = createTsarrayDt(dt, tb->nextOf());
        dts[length] = dt;
        length++;
    }

    Expression *edefault = tb->nextOf()->defaultInit();
#ifdef IN_GCC
    dt_t * sadefault = NULL;

    if (tn->ty == Tsarray)
        tn->toDt(& sadefault);
    else
        edefault->toDt(& sadefault);
#else
    unsigned n = 1;
    for (Type *tbn = tn; tbn->ty == Tsarray; tbn = tbn->nextOf()->toBasetype())
    {   TypeSArray *tsa = (TypeSArray *)tbn;

        n *= tsa->dim->toInteger();
    }
#endif

    d = NULL;
    pdtend = &d;
    for (size_t i = 0; i < dim; i++)
    {
        dt = dts[i];
#ifdef IN_GCC
        pdtend = dtcontainer(pdtend, NULL, dt ? dt : sadefault);
#else
        if (dt)
            pdtend = dtcat(pdtend, dt);
        else
        {
            for (size_t j = 0; j < n; j++)
                pdtend = edefault->toDt(pdtend);
        }
#endif
    }
    switch (tb->ty)
    {
        case Tsarray:
        {   unsigned tadim;
            TypeSArray *ta = (TypeSArray *)tb;

            tadim = ta->dim->toInteger();
            if (dim < tadim)
            {
 	

#ifdef IN_GCC
                // Pad out the rest of the array with single elements.
                // Otherwise breaks -fsection-anchors on ARM when
                // backend calculates field positions for array members.
                for (size_t i = dim; i < tadim; i++)
                    pdtend = dtcontainer(pdtend, NULL, sadefault);
#else
                if (edefault->isBool(FALSE))
                    // pad out end of array
                    pdtend = dtnzeros(pdtend, size * (tadim - dim));
                else
                {
                    for (size_t i = dim; i < tadim; i++)
                    {   for (size_t j = 0; j < n; j++)
                            pdtend = edefault->toDt(pdtend);
                    }
                }
#endif
            }
            else if (dim > tadim)
            {
                error(loc, "too many initializers, %d, for array[%d]", dim, tadim);
            }
#ifdef IN_GCC
            dt_t * cdt = NULL;
            dtcontainer(& cdt, type, d);
            d = cdt;
#endif
            break;
        }

        case Tpointer:
        case Tarray:
        {   // Create symbol, and then refer to it
            Symbol *s = static_sym();
            s->Sdt = d;
            outdata(s);

            d = NULL;
            if (tb->ty == Tarray)
                dtsize_t(&d, dim);
            dtxoff(&d, s, 0, TYnptr);
#ifdef IN_GCC
            dt_t * cdt;
            cdt = NULL;
            if (tb->ty == Tarray)
            {
                dtcontainer(& cdt, type, d);
                d = cdt;
            }
#endif
            break;
        }

        default:
            assert(0);
    }
    return d;
}
Beispiel #12
0
void Module::genobjfile(int multiobj)
{
    //EEcontext *ee = env->getEEcontext();

    //printf("Module::genobjfile(multiobj = %d) %s\n", multiobj, toChars());

    lastmname = srcfile->toChars();

    obj_initfile(lastmname, NULL, toPrettyChars());

    eictor = NULL;
    ictorlocalgot = NULL;
    sctors.setDim(0);
    ectorgates.setDim(0);
    sdtors.setDim(0);
    ssharedctors.setDim(0);
    esharedctorgates.setDim(0);
    sshareddtors.setDim(0);
    stests.setDim(0);
    dtorcount = 0;
    shareddtorcount = 0;

    if (doppelganger)
    {
        /* Generate a reference to the moduleinfo, so the module constructors
         * and destructors get linked in.
         */
        Module *m = aimports[0];
        assert(m);
        if (m->sictor || m->sctor || m->sdtor || m->ssharedctor || m->sshareddtor)
        {
            Symbol *s = m->toSymbol();
            //objextern(s);
            //if (!s->Sxtrnnum) objextdef(s->Sident);
            if (!s->Sxtrnnum)
            {
                //printf("%s\n", s->Sident);
#if 0 /* This should work, but causes optlink to fail in common/newlib.asm */
                objextdef(s->Sident);
#else
#if ELFOBJ || MACHOBJ
                int nbytes = reftoident(DATA, Offset(DATA), s, 0, I64 ? (CFoff | CFoffset64) : CFoff);
#else
                int nbytes = reftoident(DATA, Doffset, s, 0, CFoff);
                Doffset += nbytes;
#endif
#endif
            }
        }
    }

    if (global.params.cov)
    {
        /* Create coverage identifier:
         *  private uint[numlines] __coverage;
         */
        cov = symbol_calloc("__coverage");
        cov->Stype = type_fake(TYint);
        cov->Stype->Tmangle = mTYman_c;
        cov->Stype->Tcount++;
        cov->Sclass = SCstatic;
        cov->Sfl = FLdata;
#if ELFOBJ || MACHOBJ
        cov->Sseg = UDATA;
#endif
        dtnzeros(&cov->Sdt, 4 * numlines);
        outdata(cov);
        slist_add(cov);

        covb = (unsigned *)calloc((numlines + 32) / 32, sizeof(*covb));
    }

    for (size_t i = 0; i < members->dim; i++)
    {
        Dsymbol *member = (*members)[i];
        member->toObjFile(multiobj);
    }

    if (global.params.cov)
    {
        /* Generate
         *      bit[numlines] __bcoverage;
         */
        Symbol *bcov = symbol_calloc("__bcoverage");
        bcov->Stype = type_fake(TYuint);
        bcov->Stype->Tcount++;
        bcov->Sclass = SCstatic;
        bcov->Sfl = FLdata;
#if ELFOBJ || MACHOBJ
        bcov->Sseg = DATA;
#endif
        dtnbytes(&bcov->Sdt, (numlines + 32) / 32 * sizeof(*covb), (char *)covb);
        outdata(bcov);

        free(covb);
        covb = NULL;

        /* Generate:
         *  _d_cover_register(uint[] __coverage, BitArray __bcoverage, string filename);
         * and prepend it to the static constructor.
         */

        /* t will be the type of the functions generated:
         *      extern (C) void func();
         */
        type *t = type_alloc(TYnfunc);
        t->Tflags |= TFprototype | TFfixed;
        t->Tmangle = mTYman_c;
        t->Tnext = tsvoid;
        tsvoid->Tcount++;

        sictor = toSymbolX("__modictor", SCglobal, t, "FZv");
        cstate.CSpsymtab = &sictor->Sfunc->Flocsym;
        localgot = ictorlocalgot;
        elem *e;

        e = el_params(el_pair(TYdarray, el_long(TYsize_t, numlines), el_ptr(cov)),
                      el_pair(TYdarray, el_long(TYsize_t, numlines), el_ptr(bcov)),
                      toEfilename(),
                      NULL);
        e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DCOVER]), e);
        eictor = el_combine(e, eictor);
        ictorlocalgot = localgot;
    }

    // If coverage / static constructor / destructor / unittest calls
    if (eictor || sctors.dim || ectorgates.dim || sdtors.dim ||
        ssharedctors.dim || esharedctorgates.dim || sshareddtors.dim || stests.dim)
    {
        if (eictor)
        {
            localgot = ictorlocalgot;

            block *b = block_calloc();
            b->BC = BCret;
            b->Belem = eictor;
            sictor->Sfunc->Fstartline.Sfilename = arg;
            sictor->Sfunc->Fstartblock = b;
            writefunc(sictor);
        }

        sctor = callFuncsAndGates(this, &sctors, &ectorgates, "__modctor");
        sdtor = callFuncsAndGates(this, &sdtors, NULL, "__moddtor");

#if DMDV2
        ssharedctor = callFuncsAndGates(this, &ssharedctors, (StaticDtorDeclarations *)&esharedctorgates, "__modsharedctor");
        sshareddtor = callFuncsAndGates(this, &sshareddtors, NULL, "__modshareddtor");
#endif
        stest = callFuncsAndGates(this, &stests, NULL, "__modtest");

        if (doppelganger)
            genmoduleinfo();
    }

    if (doppelganger)
    {
        obj_termfile();
        return;
    }

    if (global.params.multiobj)
    {   /* This is necessary because the main .obj for this module is written
         * first, but determining whether marray or massert or munittest are needed is done
         * possibly later in the doppelganger modules.
         * Another way to fix it is do the main one last.
         */
        toModuleAssert();
        toModuleUnittest();
        toModuleArray();
    }

#if 1
    // Always generate module info, because of templates and -cov
    if (1 || needModuleInfo())
        genmoduleinfo();
#endif

    // If module assert
    for (int i = 0; i < 3; i++)
    {
        Symbol *ma;
        unsigned rt;
        unsigned bc;
        switch (i)
        {
            case 0:     ma = marray;    rt = RTLSYM_DARRAY;     bc = BCexit; break;
            case 1:     ma = massert;   rt = RTLSYM_DASSERTM;   bc = BCexit; break;
            case 2:     ma = munittest; rt = RTLSYM_DUNITTESTM; bc = BCret;  break;
            default:    assert(0);
        }

        if (ma)
        {
            elem *elinnum;

            localgot = NULL;

            // Call dassert(filename, line)
            // Get sole parameter, linnum
            {
                Symbol *sp = symbol_calloc("linnum");
                sp->Stype = type_fake(TYint);
                sp->Stype->Tcount++;
                sp->Sclass = SCfastpar;
                size_t num;
                sp->Spreg = getintegerparamsreglist(TYjfunc, &num)[0];
                sp->Sflags &= ~SFLspill;
                sp->Sfl = FLpara;       // FLauto?
                cstate.CSpsymtab = &ma->Sfunc->Flocsym;
                symbol_add(sp);

                elinnum = el_var(sp);
            }

            elem *efilename = el_ptr(toSymbol());

            elem *e = el_var(rtlsym[rt]);
            e = el_bin(OPcall, TYvoid, e, el_param(elinnum, efilename));

            block *b = block_calloc();
            b->BC = bc;
            b->Belem = e;
            ma->Sfunc->Fstartline.Sfilename = arg;
            ma->Sfunc->Fstartblock = b;
            ma->Sclass = SCglobal;
            ma->Sfl = 0;
            ma->Sflags |= rtlsym[rt]->Sflags & SFLexit;
            writefunc(ma);
        }
    }

    obj_termfile();
}
Beispiel #13
0
Datei: glue.c Projekt: alexrp/dmd
void Module::genobjfile(int multiobj)
{
    //EEcontext *ee = env->getEEcontext();

    //printf("Module::genobjfile(multiobj = %d) %s\n", multiobj, toChars());

    lastmname = srcfile->toChars();

    objmod->initfile(lastmname, NULL, toPrettyChars());

    eictor = NULL;
    ictorlocalgot = NULL;
    sctors.setDim(0);
    ectorgates.setDim(0);
    sdtors.setDim(0);
    ssharedctors.setDim(0);
    esharedctorgates.setDim(0);
    sshareddtors.setDim(0);
    stests.setDim(0);
    dtorcount = 0;
    shareddtorcount = 0;

    if (doppelganger)
    {
        /* Generate a reference to the moduleinfo, so the module constructors
         * and destructors get linked in.
         */
        Module *m = aimports[0];
        assert(m);
        if (m->sictor || m->sctor || m->sdtor || m->ssharedctor || m->sshareddtor)
        {
            Symbol *s = m->toSymbol();
            //objextern(s);
            //if (!s->Sxtrnnum) objextdef(s->Sident);
            if (!s->Sxtrnnum)
            {
                //printf("%s\n", s->Sident);
#if 0 /* This should work, but causes optlink to fail in common/newlib.asm */
                objextdef(s->Sident);
#else
                Symbol *sref = symbol_generate(SCstatic, type_fake(TYnptr));
                sref->Sfl = FLdata;
                dtxoff(&sref->Sdt, s, 0, TYnptr);
                outdata(sref);
#endif
            }
        }
    }

    if (global.params.cov)
    {
        /* Create coverage identifier:
         *  private uint[numlines] __coverage;
         */
        cov = symbol_calloc("__coverage");
        cov->Stype = type_fake(TYint);
        cov->Stype->Tmangle = mTYman_c;
        cov->Stype->Tcount++;
        cov->Sclass = SCstatic;
        cov->Sfl = FLdata;
        dtnzeros(&cov->Sdt, 4 * numlines);
        outdata(cov);
        slist_add(cov);

        covb = (unsigned *)calloc((numlines + 32) / 32, sizeof(*covb));
    }

    for (size_t i = 0; i < members->dim; i++)
    {
        Dsymbol *member = (*members)[i];
        //printf("toObjFile %s %s\n", member->kind(), member->toChars());
        member->toObjFile(multiobj);
    }

    if (global.params.cov)
    {
        /* Generate
         *      bit[numlines] __bcoverage;
         */
        Symbol *bcov = symbol_calloc("__bcoverage");
        bcov->Stype = type_fake(TYuint);
        bcov->Stype->Tcount++;
        bcov->Sclass = SCstatic;
        bcov->Sfl = FLdata;
        dtnbytes(&bcov->Sdt, (numlines + 32) / 32 * sizeof(*covb), (char *)covb);
        outdata(bcov);

        free(covb);
        covb = NULL;

        /* Generate:
         *  _d_cover_register(uint[] __coverage, BitArray __bcoverage, string filename);
         * and prepend it to the static constructor.
         */

        /* t will be the type of the functions generated:
         *      extern (C) void func();
         */
        type *t = type_function(TYnfunc, NULL, 0, false, tsvoid);
        t->Tmangle = mTYman_c;

        sictor = toSymbolX("__modictor", SCglobal, t, "FZv");
        cstate.CSpsymtab = &sictor->Sfunc->Flocsym;
        localgot = ictorlocalgot;

        elem *ecov  = el_pair(TYdarray, el_long(TYsize_t, numlines), el_ptr(cov));
        elem *ebcov = el_pair(TYdarray, el_long(TYsize_t, numlines), el_ptr(bcov));

        if (config.exe == EX_WIN64)
        {
            ecov  = addressElem(ecov,  Type::tvoid->arrayOf(), false);
            ebcov = addressElem(ebcov, Type::tvoid->arrayOf(), false);
        }

        elem *e = el_params(
                      el_long(TYuchar, global.params.covPercent),
                      ecov,
                      ebcov,
                      toEfilename(),
                      NULL);
        e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DCOVER2]), e);
        eictor = el_combine(e, eictor);
        ictorlocalgot = localgot;
    }

    // If coverage / static constructor / destructor / unittest calls
    if (eictor || sctors.dim || ectorgates.dim || sdtors.dim ||
        ssharedctors.dim || esharedctorgates.dim || sshareddtors.dim || stests.dim)
    {
        if (eictor)
        {
            localgot = ictorlocalgot;

            block *b = block_calloc();
            b->BC = BCret;
            b->Belem = eictor;
            sictor->Sfunc->Fstartline.Sfilename = arg;
            sictor->Sfunc->Fstartblock = b;
            writefunc(sictor);
        }

        sctor = callFuncsAndGates(this, &sctors, &ectorgates, "__modctor");
        sdtor = callFuncsAndGates(this, &sdtors, NULL, "__moddtor");

#if DMDV2
        ssharedctor = callFuncsAndGates(this, &ssharedctors, (StaticDtorDeclarations *)&esharedctorgates, "__modsharedctor");
        sshareddtor = callFuncsAndGates(this, &sshareddtors, NULL, "__modshareddtor");
#endif
        stest = callFuncsAndGates(this, &stests, NULL, "__modtest");

        if (doppelganger)
            genmoduleinfo();
    }

    if (doppelganger)
    {
        objmod->termfile();
        return;
    }

    if (global.params.multiobj)
    {   /* This is necessary because the main .obj for this module is written
         * first, but determining whether marray or massert or munittest are needed is done
         * possibly later in the doppelganger modules.
         * Another way to fix it is do the main one last.
         */
        toModuleAssert();
        toModuleUnittest();
        toModuleArray();
    }

    /* Always generate module info, because of templates and -cov.
     * But module info needs the runtime library, so disable it for betterC.
     */
    if (!global.params.betterC /*|| needModuleInfo()*/)
        genmoduleinfo();

    // If module assert
    for (int i = 0; i < 3; i++)
    {
        Symbol *ma;
        unsigned rt;
        unsigned bc;
        switch (i)
        {
            case 0:     ma = marray;    rt = RTLSYM_DARRAY;     bc = BCexit; break;
            case 1:     ma = massert;   rt = RTLSYM_DASSERTM;   bc = BCexit; break;
            case 2:     ma = munittest; rt = RTLSYM_DUNITTESTM; bc = BCret;  break;
            default:    assert(0);
        }

        if (ma)
        {
            elem *elinnum;

            localgot = NULL;

            // Call dassert(filename, line)
            // Get sole parameter, linnum
            {
                Symbol *sp = symbol_calloc("linnum");
                sp->Stype = type_fake(TYint);
                sp->Stype->Tcount++;
                sp->Sclass = (config.exe == EX_WIN64) ? SCshadowreg : SCfastpar;

                FuncParamRegs fpr(TYjfunc);
                fpr.alloc(sp->Stype, sp->Stype->Tty, &sp->Spreg, &sp->Spreg2);

                sp->Sflags &= ~SFLspill;
                sp->Sfl = (sp->Sclass == SCshadowreg) ? FLpara : FLfast;
                cstate.CSpsymtab = &ma->Sfunc->Flocsym;
                symbol_add(sp);

                elinnum = el_var(sp);
            }

            elem *efilename = el_ptr(toSymbol());

            elem *e = el_var(rtlsym[rt]);
            e = el_bin(OPcall, TYvoid, e, el_param(elinnum, efilename));

            block *b = block_calloc();
            b->BC = bc;
            b->Belem = e;
            ma->Sfunc->Fstartline.Sfilename = arg;
            ma->Sfunc->Fstartblock = b;
            ma->Sclass = SCglobal;
            ma->Sfl = 0;
            ma->Sflags |= rtlsym[rt]->Sflags & SFLexit;
            writefunc(ma);
        }
    }

    objmod->termfile();
}
Beispiel #14
0
dt_t *ArrayInitializer::toDt()
{
    //printf("ArrayInitializer::toDt('%s')\n", toChars());
    Type *tb = type->toBasetype();
    Type *tn = tb->nextOf()->toBasetype();

    Dts dts;
    unsigned size;
    unsigned length;
    unsigned i;
    dt_t *dt;
    dt_t *d;
    dt_t **pdtend;

    //printf("\tdim = %d\n", dim);
    dts.setDim(dim);
    dts.zero();

    size = tn->size();

    length = 0;
    for (i = 0; i < index.dim; i++)
    {   Expression *idx;
        Initializer *val;

        idx = index.tdata()[i];
        if (idx)
            length = idx->toInteger();
        //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim);

        assert(length < dim);
        val = value.tdata()[i];
        dt = val->toDt();
        if (dts.tdata()[length])
            error(loc, "duplicate initializations for index %d", length);
        dts.tdata()[length] = dt;
        length++;
    }

    Expression *edefault = tb->nextOf()->defaultInit();

    unsigned n = 1;
    for (Type *tbn = tn; tbn->ty == Tsarray; tbn = tbn->nextOf()->toBasetype())
    {   TypeSArray *tsa = (TypeSArray *)tbn;

        n *= tsa->dim->toInteger();
    }

    d = NULL;
    pdtend = &d;
    for (i = 0; i < dim; i++)
    {
        dt = dts.tdata()[i];
        if (dt)
            pdtend = dtcat(pdtend, dt);
        else
        {
            for (int j = 0; j < n; j++)
                pdtend = edefault->toDt(pdtend);
        }
    }
    switch (tb->ty)
    {
        case Tsarray:
        {   unsigned tadim;
            TypeSArray *ta = (TypeSArray *)tb;

            tadim = ta->dim->toInteger();
            if (dim < tadim)
            {
                if (edefault->isBool(FALSE))
                    // pad out end of array
                    pdtend = dtnzeros(pdtend, size * (tadim - dim));
                else
                {
                    for (i = dim; i < tadim; i++)
                    {   for (int j = 0; j < n; j++)
                            pdtend = edefault->toDt(pdtend);
                    }
                }
            }
            else if (dim > tadim)
            {
#ifdef DEBUG
                printf("1: ");
#endif
                error(loc, "too many initializers, %d, for array[%d]", dim, tadim);
            }
            break;
        }

        case Tpointer:
        case Tarray:
            // Create symbol, and then refer to it
            Symbol *s;
            s = static_sym();
            s->Sdt = d;
            outdata(s);

            d = NULL;
            if (tb->ty == Tarray)
                dtsize_t(&d, dim);
            dtxoff(&d, s, 0, TYnptr);
            break;

        default:
            assert(0);
    }
    return d;
}
Beispiel #15
0
Datei: eh.c Projekt: Geod24/dnet
symbol *except_gentables()
{
    //printf("except_gentables()\n");
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_SOLARIS
    symbol *s;
    int sz;			// size so far
    dt_t **pdt;
    unsigned fsize;		// target size of function pointer
    long spoff;
    block *b;
    int guarddim;
    int i;

    // BUG: alloca() changes the stack size, which is not reflected
    // in the fixed eh tables.
    assert(!usedalloca);

    s = symbol_generate(SCstatic,tsint);
    s->Sseg = UNKNOWN;
    symbol_keep(s);
    symbol_debug(s);

    fsize = 4;
    pdt = &s->Sdt;
    sz = 0;

    /*
	void*		pointer to start of function
	unsigned	offset of ESP from EBP
	unsigned	offset from start of function to return code
	unsigned nguards;	// dimension of guard[]
	{   unsigned offset;	// offset of start of guarded section
	    unsigned endoffset;	// ending offset of guarded section
	    int last_index;	// previous index (enclosing guarded section)
	    unsigned catchoffset;	// offset to catch block from symbol
	    void *finally;	// finally code to execute
	} guard[];
      catchoffset:
	unsigned ncatches;	// number of catch blocks
	{   void *type;		// symbol representing type
	    unsigned bpoffset;	// EBP offset of catch variable
	    void *handler;	// catch handler code
	} catch[];
     */
#define GUARD_SIZE	5	// number of 4 byte values in one guard

    sz = 0;

    // Address of start of function
    symbol_debug(funcsym_p);
    pdt = dtxoff(pdt,funcsym_p,0,TYnptr);
    sz += fsize;

    //printf("ehtables: func = %s, offset = x%x, startblock->Boffset = x%x\n", funcsym_p->Sident, funcsym_p->Soffset, startblock->Boffset);

    // Get offset of ESP from EBP
    spoff = cod3_spoff();
    pdt = dtdword(pdt,spoff);
    sz += 4;

    // Offset from start of function to return code
    pdt = dtdword(pdt,retoffset);
    sz += 4;

    // First, calculate starting catch offset
    guarddim = 0;				// max dimension of guard[]
    for (b = startblock; b; b = b->Bnext)
    {
	if (b->BC == BC_try && b->Bscope_index >= guarddim)
	    guarddim = b->Bscope_index + 1;
//	printf("b->BC = %2d, Bscope_index = %2d, last_index = %2d, offset = x%x\n",
//		b->BC, b->Bscope_index, b->Blast_index, b->Boffset);
    }

    pdt = dtdword(pdt,guarddim);
    sz += 4;

    unsigned catchoffset = sz + guarddim * (GUARD_SIZE * 4);

    // Generate guard[]
    i = 0;
    for (b = startblock; b; b = b->Bnext)
    {
	//printf("b = %p, b->Btry = %p, b->offset = %x\n", b, b->Btry, b->Boffset);
	if (b->BC == BC_try)
	{   dt_t *dt;
	    block *bhandler;
	    int nsucc;
	    unsigned endoffset;
	    block *bn;

	    assert(b->Bscope_index >= i);
	    if (i < b->Bscope_index)
	    {	int fillsize = (b->Bscope_index - i) * (GUARD_SIZE * 4);
		pdt = dtnzeros(pdt, fillsize);
		sz += fillsize;
	    }
	    i = b->Bscope_index + 1;

	    nsucc = list_nitems(b->Bsucc);
	    pdt = dtdword(pdt,b->Boffset - startblock->Boffset);	// offset to start of block

	    // Compute ending offset
	    for (bn = b->Bnext; 1; bn = bn->Bnext)
	    {
		//printf("\tbn = %p, bn->Btry = %p, bn->offset = %x\n", bn, bn->Btry, bn->Boffset);
		assert(bn);
		if (bn->Btry == b->Btry)
		{    endoffset = bn->Boffset - startblock->Boffset;
		     break;
		}
	    }
	    pdt = dtdword(pdt,endoffset);		// offset past end of guarded block

	    pdt = dtdword(pdt,b->Blast_index);		// parent index

	    if (b->jcatchvar)				// if try-catch
	    {
		pdt = dtdword(pdt,catchoffset);
		pdt = dtdword(pdt,0);			// no finally handler

		catchoffset += 4 + (nsucc - 1) * (3 * 4);
	    }
	    else					// else try-finally
	    {
		assert(nsucc == 2);
		pdt = dtdword(pdt,0);		// no catch offset
		bhandler = list_block(list_next(b->Bsucc));
		assert(bhandler->BC == BC_finally);
		// To successor of BC_finally block
		bhandler = list_block(bhandler->Bsucc);
		pdt = dtxoff(pdt,funcsym_p,bhandler->Boffset - startblock->Boffset, TYnptr);	// finally handler address
		//pdt = dtcoff(pdt,bhandler->Boffset);	// finally handler address
	    }
	    sz += GUARD_SIZE + 4;
	}
    }

    // Generate catch[]
    for (b = startblock; b; b = b->Bnext)
    {
	if (b->BC == BC_try)
	{   block *bhandler;
	    int nsucc;

	    if (b->jcatchvar)				// if try-catch
	    {	list_t bl;

		nsucc = list_nitems(b->Bsucc);
		pdt = dtdword(pdt,nsucc - 1);		// # of catch blocks
		sz += 4;

		for (bl = list_next(b->Bsucc); bl; bl = list_next(bl))
		{
		    block *bcatch = list_block(bl);

		    pdt = dtxoff(pdt,bcatch->Bcatchtype,0,TYjhandle);

		    pdt = dtdword(pdt,cod3_bpoffset(b->jcatchvar));	// EBP offset

		    pdt = dtxoff(pdt,funcsym_p,bcatch->Boffset - startblock->Boffset, TYnptr);	// catch handler address
		    //pdt = dtcoff(pdt,bcatch->Boffset);	// catch handler address

		    sz += 3 * 4;
		}
	    }
	}
    }
    assert(sz != 0);

    outdata(s);			// output the scope table

    obj_ehtables(funcsym_p,funcsym_p->Ssize,s);
#endif
    return NULL;
}
Beispiel #16
0
void except_fillInEHTable(symbol *s)
{
    unsigned fsize = NPTRSIZE;             // target size of function pointer
    dt_t **pdt = &s->Sdt;

    /*
        void*           pointer to start of function (Windows)
        unsigned        offset of ESP from EBP
        unsigned        offset from start of function to return code
        unsigned nguards;       // dimension of guard[] (Linux)
        Guard guard[];          // sorted such that the enclosing guarded sections come first
      catchoffset:
        unsigned ncatches;      // number of catch blocks
        {   void *type;         // symbol representing type
            unsigned bpoffset;  // EBP offset of catch variable
            void *handler;      // catch handler code
        } catch[];
     */

/* Be careful of this, as we need the sizeof Guard on the target, not
 * in the compiler.
 */
    unsigned GUARD_SIZE;
    if (config.ehmethod == EH_DM)
        GUARD_SIZE = (I64 ? 3*8 : 5*4);
    else if (config.ehmethod == EH_WIN32)
        GUARD_SIZE = 3*4;
    else
        assert(0);

    int sz = 0;

    // Address of start of function
    if (config.ehmethod == EH_WIN32)
    {
        symbol_debug(funcsym_p);
        pdt = dtxoff(pdt,funcsym_p,0,TYnptr);
        sz += fsize;
    }

    //printf("ehtables: func = %s, offset = x%x, startblock->Boffset = x%x\n", funcsym_p->Sident, funcsym_p->Soffset, startblock->Boffset);

    // Get offset of ESP from EBP
    long spoff = cod3_spoff();
    pdt = dtdword(pdt,spoff);
    sz += 4;

    // Offset from start of function to return code
    pdt = dtdword(pdt,retoffset);
    sz += 4;

    // First, calculate starting catch offset
    int guarddim = 0;                               // max dimension of guard[]
    int ndctors = 0;                                // number of ESCdctor's
    for (block *b = startblock; b; b = b->Bnext)
    {
        if (b->BC == BC_try && b->Bscope_index >= guarddim)
            guarddim = b->Bscope_index + 1;
//      printf("b->BC = %2d, Bscope_index = %2d, last_index = %2d, offset = x%x\n",
//              b->BC, b->Bscope_index, b->Blast_index, b->Boffset);
        if (usednteh & EHcleanup)
            for (code *c = b->Bcode; c; c = code_next(c))
            {
                if (c->Iop == (ESCAPE | ESCddtor))
                    ndctors++;
            }
    }
    //printf("guarddim = %d, ndctors = %d\n", guarddim, ndctors);

    if (config.ehmethod == EH_DM)
    {
        pdt = dtsize_t(pdt,guarddim + ndctors);
        sz += NPTRSIZE;
    }

    unsigned catchoffset = sz + (guarddim + ndctors) * GUARD_SIZE;

    // Generate guard[]
    int i = 0;
    for (block *b = startblock; b; b = b->Bnext)
    {
        //printf("b = %p, b->Btry = %p, b->offset = %x\n", b, b->Btry, b->Boffset);
        if (b->BC == BC_try)
        {
            assert(b->Bscope_index >= i);
            if (i < b->Bscope_index)
            {   int fillsize = (b->Bscope_index - i) * GUARD_SIZE;
                pdt = dtnzeros(pdt, fillsize);
                sz += fillsize;
            }
            i = b->Bscope_index + 1;

            int nsucc = b->numSucc();

            if (config.ehmethod == EH_DM)
            {
            //printf("DHandlerInfo: offset = %x", (int)(b->Boffset - startblock->Boffset));
            pdt = dtdword(pdt,b->Boffset - startblock->Boffset);        // offset to start of block

            // Compute ending offset
            unsigned endoffset;
            for (block *bn = b->Bnext; 1; bn = bn->Bnext)
            {
                //printf("\tbn = %p, bn->Btry = %p, bn->offset = %x\n", bn, bn->Btry, bn->Boffset);
                assert(bn);
                if (bn->Btry == b->Btry)
                {    endoffset = bn->Boffset - startblock->Boffset;
                     break;
                }
            }
            //printf(" endoffset = %x, prev_index = %d\n", endoffset, b->Blast_index);
            pdt = dtdword(pdt,endoffset);               // offset past end of guarded block
            }

            pdt = dtdword(pdt,b->Blast_index);          // parent index

            if (b->jcatchvar)                           // if try-catch
            {
                assert(catchoffset);
                pdt = dtdword(pdt,catchoffset);
                pdt = dtsize_t(pdt,0);                  // no finally handler

                catchoffset += NPTRSIZE + (nsucc - 1) * (3 * NPTRSIZE);
            }
            else                                        // else try-finally
            {
                assert(nsucc == 2);
                pdt = dtdword(pdt,0);           // no catch offset
                block *bhandler = b->nthSucc(1);
                assert(bhandler->BC == BC_finally);
                // To successor of BC_finally block
                bhandler = bhandler->nthSucc(0);
                // finally handler address
                if (config.ehmethod == EH_DM)
                {
                    assert(bhandler->Boffset > startblock->Boffset);
                    pdt = dtsize_t(pdt,bhandler->Boffset - startblock->Boffset);    // finally handler offset
                }
                else
                    pdt = dtcoff(pdt,bhandler->Boffset);
            }
            sz += GUARD_SIZE;
        }
    }

    /* Append to guard[] the guard blocks for temporaries that are created and destroyed
     * within a single expression. These are marked by the special instruction pairs
     * (ESCAPE | ESCdctor) and (ESCAPE | ESCddtor).
     */
    if (usednteh & EHcleanup)
    {
        #define STACKINC 16
        int stackbuf[STACKINC];
        int *stack = stackbuf;
        int stackmax = STACKINC;

    int scopeindex = guarddim;
    for (block *b = startblock; b; b = b->Bnext)
    {
        /* Set up stack of scope indices
         */
        stack[0] = b->Btry ? b->Btry->Bscope_index : -1;
        int stacki = 1;

        unsigned boffset = b->Boffset;
        for (code *c = b->Bcode; c; c = code_next(c))
        {
            if (c->Iop == (ESCAPE | ESCdctor))
            {
                code *c2 = code_next(c);
                if (config.flags2 & CFG2seh)
                    nteh_patchindex(c2, scopeindex);
                if (config.ehmethod == EH_DM)
                    pdt = dtdword(pdt,boffset - startblock->Boffset); // guard offset
                // Find corresponding ddtor instruction
                int n = 0;
                unsigned eoffset = boffset;
                unsigned foffset;
                for (; 1; c2 = code_next(c2))
                {
                    // Bugzilla 13720: optimizer might elide the corresponding ddtor
                    if (!c2)
                        goto Lnodtor;

                    if (c2->Iop == (ESCAPE | ESCddtor))
                    {
                        if (n)
                            n--;
                        else
                        {
                            foffset = eoffset;
                            code *cf = code_next(c2);
                            if (config.flags2 & CFG2seh)
                            {
                                nteh_patchindex(cf, stack[stacki - 1]);
                                foffset += calccodsize(cf);
                                cf = code_next(cf);
                            }
                            foffset += calccodsize(cf);
                            while (!cf->isJumpOP())
                            {
                                cf = code_next(cf);
                                foffset += calccodsize(cf);
                            }
                            // issue 9438
                            //cf = code_next(cf);
                            //foffset += calccodsize(cf);
                            if (config.ehmethod == EH_DM)
                                pdt = dtdword(pdt,eoffset - startblock->Boffset); // guard offset
                            break;
                        }
                    }
                    else if (c2->Iop == (ESCAPE | ESCdctor))
                    {
                        n++;
                    }
                    else
                        eoffset += calccodsize(c2);
                }
                //printf("boffset = %x, eoffset = %x, foffset = %x\n", boffset, eoffset, foffset);
                pdt = dtdword(pdt,stack[stacki - 1]);   // parent index
                pdt = dtdword(pdt,0);           // no catch offset
                if (config.ehmethod == EH_DM)
                {
                    assert(foffset > startblock->Boffset);
                    pdt = dtsize_t(pdt,foffset - startblock->Boffset);    // finally handler offset
                }
                else
                    pdt = dtcoff(pdt,foffset);  // finally handler address
                if (stacki == stackmax)
                {   // stack[] is out of space; enlarge it
                    int *pi = (int *)malloc((stackmax + STACKINC) * sizeof(int));
                    assert(pi);
                    memcpy(pi, stack, stackmax * sizeof(int));
                    if (stack != stackbuf)
                        free(stack);
                    stack = pi;
                    stackmax += STACKINC;
                }
                stack[stacki++] = scopeindex;
                ++scopeindex;
                sz += GUARD_SIZE;
            }
            else if (c->Iop == (ESCAPE | ESCddtor))
            {
                stacki--;
                assert(stacki != 0);
            }
        Lnodtor:
            boffset += calccodsize(c);
        }
    }
        if (stack != stackbuf)
            free(stack);
    }

    // Generate catch[]
    for (block *b = startblock; b; b = b->Bnext)
    {
        if (b->BC == BC_try && b->jcatchvar)         // if try-catch
        {
            int nsucc = b->numSucc();
            pdt = dtsize_t(pdt,nsucc - 1);           // # of catch blocks
            sz += NPTRSIZE;

            for (int i = 1; i < nsucc; ++i)
            {
                block *bcatch = b->nthSucc(i);

                pdt = dtxoff(pdt,bcatch->Bcatchtype,0,TYnptr);

                pdt = dtsize_t(pdt,cod3_bpoffset(b->jcatchvar));     // EBP offset

                // catch handler address
                if (config.ehmethod == EH_DM)
                {
                    assert(bcatch->Boffset > startblock->Boffset);
                    pdt = dtsize_t(pdt,bcatch->Boffset - startblock->Boffset);  // catch handler offset
                }
                else
                    pdt = dtcoff(pdt,bcatch->Boffset);

                sz += 3 * NPTRSIZE;
            }
        }
    }
    assert(sz != 0);
}
Beispiel #17
0
        void visit(ClassDeclaration *cd)
        {
            //printf("ClassDeclaration::toObjFile('%s')\n", cd->toChars());

            if (cd->type->ty == Terror)
            {
                cd->error("had semantic errors when compiling");
                return;
            }

            if (!cd->members)
                return;

            if (multiobj && !cd->hasStaticCtorOrDtor())
            {
                obj_append(cd);
                return;
            }

            if (global.params.symdebug)
                toDebug(cd);

            assert(!cd->scope);     // semantic() should have been run to completion

            enum_SC scclass = SCglobal;
            if (cd->isInstantiated())
                scclass = SCcomdat;

            // Put out the members
            for (size_t i = 0; i < cd->members->dim; i++)
            {
                Dsymbol *member = (*cd->members)[i];
                /* There might be static ctors in the members, and they cannot
                 * be put in separate obj files.
                 */
                member->accept(this);
            }

            // Generate C symbols
            toSymbol(cd);
            toVtblSymbol(cd);
            Symbol *sinit = toInitializer(cd);

            //////////////////////////////////////////////

            // Generate static initializer
            sinit->Sclass = scclass;
            sinit->Sfl = FLdata;
            ClassDeclaration_toDt(cd, &sinit->Sdt);
            out_readonly(sinit);
            outdata(sinit);

            //////////////////////////////////////////////

            // Put out the TypeInfo
            genTypeInfo(cd->type, NULL);
            //toObjFile(cd->type->vtinfo, multiobj);

            //////////////////////////////////////////////

            // Put out the ClassInfo
            cd->csym->Sclass = scclass;
            cd->csym->Sfl = FLdata;

            /* The layout is:
               {
                    void **vptr;
                    monitor_t monitor;
                    byte[] initializer;         // static initialization data
                    char[] name;                // class name
                    void *[] vtbl;
                    Interface[] interfaces;
                    ClassInfo *base;            // base class
                    void *destructor;
                    void *invariant;            // class invariant
                    ClassFlags flags;
                    void *deallocator;
                    OffsetTypeInfo[] offTi;
                    void *defaultConstructor;
                    //const(MemberInfo[]) function(string) xgetMembers;   // module getMembers() function
                    void *xgetRTInfo;
                    //TypeInfo typeinfo;
               }
             */
            dt_t *dt = NULL;
            unsigned offset = Target::classinfosize;    // must be ClassInfo.size
            if (Type::typeinfoclass)
            {
                if (Type::typeinfoclass->structsize != Target::classinfosize)
                {
        #ifdef DEBUG
                    printf("Target::classinfosize = x%x, Type::typeinfoclass->structsize = x%x\n", offset, Type::typeinfoclass->structsize);
        #endif
                    cd->error("mismatch between dmd and object.d or object.di found. Check installation and import paths with -v compiler switch.");
                    fatal();
                }
            }

            if (Type::typeinfoclass)
                dtxoff(&dt, toVtblSymbol(Type::typeinfoclass), 0, TYnptr); // vtbl for ClassInfo
            else
                dtsize_t(&dt, 0);                // BUG: should be an assert()
            dtsize_t(&dt, 0);                    // monitor

            // initializer[]
            assert(cd->structsize >= 8 || (cd->cpp && cd->structsize >= 4));
            dtsize_t(&dt, cd->structsize);           // size
            dtxoff(&dt, sinit, 0, TYnptr);      // initializer

            // name[]
            const char *name = cd->ident->toChars();
            size_t namelen = strlen(name);
            if (!(namelen > 9 && memcmp(name, "TypeInfo_", 9) == 0))
            {
                name = cd->toPrettyChars();
                namelen = strlen(name);
            }
            dt_t **pdtname = dtsize_t(&dt, namelen);
            dtxoff(&dt, cd->csym, 0, TYnptr);

            // vtbl[]
            dtsize_t(&dt, cd->vtbl.dim);
            dtxoff(&dt, cd->vtblsym, 0, TYnptr);

            // interfaces[]
            dtsize_t(&dt, cd->vtblInterfaces->dim);
            if (cd->vtblInterfaces->dim)
                dtxoff(&dt, cd->csym, offset, TYnptr);      // (*)
            else
                dtsize_t(&dt, 0);

            // base
            if (cd->baseClass)
                dtxoff(&dt, toSymbol(cd->baseClass), 0, TYnptr);
            else
                dtsize_t(&dt, 0);

            // destructor
            if (cd->dtor)
                dtxoff(&dt, toSymbol(cd->dtor), 0, TYnptr);
            else
                dtsize_t(&dt, 0);

            // invariant
            if (cd->inv)
                dtxoff(&dt, toSymbol(cd->inv), 0, TYnptr);
            else
                dtsize_t(&dt, 0);

            // flags
            ClassFlags::Type flags = ClassFlags::hasOffTi;
            if (cd->isCOMclass()) flags |= ClassFlags::isCOMclass;
            if (cd->isCPPclass()) flags |= ClassFlags::isCPPclass;
            flags |= ClassFlags::hasGetMembers;
            flags |= ClassFlags::hasTypeInfo;
            if (cd->ctor)
                flags |= ClassFlags::hasCtor;
            for (ClassDeclaration *pc = cd; pc; pc = pc->baseClass)
            {
                if (pc->dtor)
                {
                    flags |= ClassFlags::hasDtor;
                    break;
                }
            }
            if (cd->isabstract)
                flags |= ClassFlags::isAbstract;
            for (ClassDeclaration *pc = cd; pc; pc = pc->baseClass)
            {
                if (pc->members)
                {
                    for (size_t i = 0; i < pc->members->dim; i++)
                    {
                        Dsymbol *sm = (*pc->members)[i];
                        //printf("sm = %s %s\n", sm->kind(), sm->toChars());
                        if (sm->hasPointers())
                            goto L2;
                    }
                }
            }
            flags |= ClassFlags::noPointers;
          L2:
            dtsize_t(&dt, flags);


            // deallocator
            if (cd->aggDelete)
                dtxoff(&dt, toSymbol(cd->aggDelete), 0, TYnptr);
            else
                dtsize_t(&dt, 0);

            // offTi[]
            dtsize_t(&dt, 0);
            dtsize_t(&dt, 0);            // null for now, fix later

            // defaultConstructor
            if (cd->defaultCtor && !(cd->defaultCtor->storage_class & STCdisable))
                dtxoff(&dt, toSymbol(cd->defaultCtor), 0, TYnptr);
            else
                dtsize_t(&dt, 0);

            // xgetRTInfo
            if (cd->getRTInfo)
                Expression_toDt(cd->getRTInfo, &dt);
            else if (flags & ClassFlags::noPointers)
                dtsize_t(&dt, 0);
            else
                dtsize_t(&dt, 1);

            //dtxoff(&dt, toSymbol(type->vtinfo), 0, TYnptr); // typeinfo

            //////////////////////////////////////////////

            // Put out (*vtblInterfaces)[]. Must immediately follow csym, because
            // of the fixup (*)

            offset += cd->vtblInterfaces->dim * (4 * Target::ptrsize);
            for (size_t i = 0; i < cd->vtblInterfaces->dim; i++)
            {
                BaseClass *b = (*cd->vtblInterfaces)[i];
                ClassDeclaration *id = b->sym;

                /* The layout is:
                 *  struct Interface
                 *  {
                 *      ClassInfo *interface;
                 *      void *[] vtbl;
                 *      size_t offset;
                 *  }
                 */

                // Fill in vtbl[]
                b->fillVtbl(cd, &b->vtbl, 1);

                dtxoff(&dt, toSymbol(id), 0, TYnptr);         // ClassInfo

                // vtbl[]
                dtsize_t(&dt, id->vtbl.dim);
                dtxoff(&dt, cd->csym, offset, TYnptr);

                dtsize_t(&dt, b->offset);                        // this offset

                offset += id->vtbl.dim * Target::ptrsize;
            }

            // Put out the (*vtblInterfaces)[].vtbl[]
            // This must be mirrored with ClassDeclaration::baseVtblOffset()
            //printf("putting out %d interface vtbl[]s for '%s'\n", vtblInterfaces->dim, toChars());
            for (size_t i = 0; i < cd->vtblInterfaces->dim; i++)
            {
                BaseClass *b = (*cd->vtblInterfaces)[i];
                ClassDeclaration *id = b->sym;

                //printf("    interface[%d] is '%s'\n", i, id->toChars());
                size_t j = 0;
                if (id->vtblOffset())
                {
                    // First entry is ClassInfo reference
                    //dtxoff(&dt, toSymbol(id), 0, TYnptr);

                    // First entry is struct Interface reference
                    dtxoff(&dt, cd->csym, Target::classinfosize + i * (4 * Target::ptrsize), TYnptr);
                    j = 1;
                }
                assert(id->vtbl.dim == b->vtbl.dim);
                for (; j < id->vtbl.dim; j++)
                {
                    assert(j < b->vtbl.dim);
        #if 0
                    RootObject *o = b->vtbl[j];
                    if (o)
                    {
                        printf("o = %p\n", o);
                        assert(o->dyncast() == DYNCAST_DSYMBOL);
                        Dsymbol *s = (Dsymbol *)o;
                        printf("s->kind() = '%s'\n", s->kind());
                    }
        #endif
                    FuncDeclaration *fd = b->vtbl[j];
                    if (fd)
                        dtxoff(&dt, toThunkSymbol(fd, b->offset), 0, TYnptr);
                    else
                        dtsize_t(&dt, 0);
                }
            }

            // Put out the overriding interface vtbl[]s.
            // This must be mirrored with ClassDeclaration::baseVtblOffset()
            //printf("putting out overriding interface vtbl[]s for '%s' at offset x%x\n", toChars(), offset);
            ClassDeclaration *pc;
            for (pc = cd->baseClass; pc; pc = pc->baseClass)
            {
                for (size_t k = 0; k < pc->vtblInterfaces->dim; k++)
                {
                    BaseClass *bs = (*pc->vtblInterfaces)[k];
                    FuncDeclarations bvtbl;
                    if (bs->fillVtbl(cd, &bvtbl, 0))
                    {
                        //printf("\toverriding vtbl[] for %s\n", bs->sym->toChars());
                        ClassDeclaration *id = bs->sym;

                        size_t j = 0;
                        if (id->vtblOffset())
                        {
                            // First entry is ClassInfo reference
                            //dtxoff(&dt, toSymbol(id), 0, TYnptr);

                            // First entry is struct Interface reference
                            dtxoff(&dt, toSymbol(pc), Target::classinfosize + k * (4 * Target::ptrsize), TYnptr);
                            offset += Target::ptrsize;
                            j = 1;
                        }

                        for (; j < id->vtbl.dim; j++)
                        {
                            assert(j < bvtbl.dim);
                            FuncDeclaration *fd = bvtbl[j];
                            if (fd)
                                dtxoff(&dt, toThunkSymbol(fd, bs->offset), 0, TYnptr);
                            else
                                dtsize_t(&dt, 0);
                            offset += Target::ptrsize;
                        }
                    }
                }
            }

            //////////////////////////////////////////////

            dtpatchoffset(*pdtname, offset);

            dtnbytes(&dt, namelen + 1, name);
            const size_t namepad = -(namelen + 1) & (Target::ptrsize - 1); // align
            dtnzeros(&dt, namepad);

            cd->csym->Sdt = dt;
            // ClassInfo cannot be const data, because we use the monitor on it
            outdata(cd->csym);
            if (cd->isExport())
                objmod->export_symbol(cd->csym, 0);

            //////////////////////////////////////////////

            // Put out the vtbl[]
            //printf("putting out %s.vtbl[]\n", toChars());
            dt = NULL;
            if (cd->vtblOffset())
                dtxoff(&dt, cd->csym, 0, TYnptr);           // first entry is ClassInfo reference
            for (size_t i = cd->vtblOffset(); i < cd->vtbl.dim; i++)
            {
                FuncDeclaration *fd = cd->vtbl[i]->isFuncDeclaration();

                //printf("\tvtbl[%d] = %p\n", i, fd);
                if (fd && (fd->fbody || !cd->isAbstract()))
                {
                    // Ensure function has a return value (Bugzilla 4869)
                    fd->functionSemantic();

                    Symbol *s = toSymbol(fd);

                    if (cd->isFuncHidden(fd))
                    {
                        /* fd is hidden from the view of this class.
                         * If fd overlaps with any function in the vtbl[], then
                         * issue 'hidden' error.
                         */
                        for (size_t j = 1; j < cd->vtbl.dim; j++)
                        {
                            if (j == i)
                                continue;
                            FuncDeclaration *fd2 = cd->vtbl[j]->isFuncDeclaration();
                            if (!fd2->ident->equals(fd->ident))
                                continue;
                            if (fd->leastAsSpecialized(fd2) || fd2->leastAsSpecialized(fd))
                            {
                                TypeFunction *tf = (TypeFunction *)fd->type;
                                if (tf->ty == Tfunction)
                                    cd->error("use of %s%s is hidden by %s; use 'alias %s = %s.%s;' to introduce base class overload set",
                                        fd->toPrettyChars(),
                                        parametersTypeToChars(tf->parameters, tf->varargs),
                                        cd->toChars(),

                                        fd->toChars(),
                                        fd->parent->toChars(),
                                        fd->toChars());
                                else
                                    cd->error("use of %s is hidden by %s", fd->toPrettyChars(), cd->toChars());
                                break;
                            }
                        }
                    }

                    dtxoff(&dt, s, 0, TYnptr);
                }
                else
                    dtsize_t(&dt, 0);
            }
            cd->vtblsym->Sdt = dt;
            cd->vtblsym->Sclass = scclass;
            cd->vtblsym->Sfl = FLdata;
            out_readonly(cd->vtblsym);
            outdata(cd->vtblsym);
            if (cd->isExport())
                objmod->export_symbol(cd->vtblsym,0);
        }
Beispiel #18
0
dt_t *ArrayInitializer::toDt()
{
    //printf("ArrayInitializer::toDt('%s')\n", toChars());
    Type *tb = type->toBasetype();
    if (tb->ty == Tvector)
        tb = ((TypeVector *)tb)->basetype;

    Type *tn = tb->nextOf()->toBasetype();

    //printf("\tdim = %d\n", dim);
    Dts dts;
    dts.setDim(dim);
    dts.zero();

    unsigned size = tn->size();

    unsigned length = 0;
    for (size_t i = 0; i < index.dim; i++)
    {
        Expression *idx = index[i];
        if (idx)
            length = idx->toInteger();
        //printf("\tindex[%d] = %p, length = %u, dim = %u\n", i, idx, length, dim);

        assert(length < dim);
        Initializer *val = value[i];
        dt_t *dt = val->toDt();
        if (dts[length])
            error(loc, "duplicate initializations for index %d", length);
        dts[length] = dt;
        length++;
    }

    Expression *edefault = tb->nextOf()->defaultInit();

    size_t n = 1;
    for (Type *tbn = tn; tbn->ty == Tsarray; tbn = tbn->nextOf()->toBasetype())
    {   TypeSArray *tsa = (TypeSArray *)tbn;

        n *= tsa->dim->toInteger();
    }

    dt_t *d = NULL;
    dt_t **pdtend = &d;
    for (size_t i = 0; i < dim; i++)
    {
        dt_t *dt = dts[i];
        if (dt)
            pdtend = dtcat(pdtend, dt);
        else
        {
            for (size_t j = 0; j < n; j++)
                pdtend = edefault->toDt(pdtend);
        }
    }
    switch (tb->ty)
    {
        case Tsarray:
        {   size_t tadim;
            TypeSArray *ta = (TypeSArray *)tb;

            tadim = ta->dim->toInteger();
            if (dim < tadim)
            {
                if (edefault->isBool(false))
                    // pad out end of array
                    pdtend = dtnzeros(pdtend, size * (tadim - dim));
                else
                {
                    for (size_t i = dim; i < tadim; i++)
                    {   for (size_t j = 0; j < n; j++)
                            pdtend = edefault->toDt(pdtend);
                    }
                }
            }
            else if (dim > tadim)
            {
                error(loc, "too many initializers, %d, for array[%d]", dim, tadim);
            }
            break;
        }

        case Tpointer:
        case Tarray:
        {
            dt_t *dtarray = d;
            d = NULL;
            if (tb->ty == Tarray)
                dtsize_t(&d, dim);
            dtdtoff(&d, dtarray, 0);
            break;
        }

        default:
            assert(0);
    }
    return d;
}
Beispiel #19
0
void genObjFile(Module *m, bool multiobj)
{
    //EEcontext *ee = env->getEEcontext();

    //printf("Module::genobjfile(multiobj = %d) %s\n", multiobj, m->toChars());

    if (m->ident == Id::entrypoint)
    {
        bool v = global.params.verbose;
        global.params.verbose = false;

        for (size_t i = 0; i < m->members->dim; i++)
        {
            Dsymbol *member = (*m->members)[i];
            //printf("toObjFile %s %s\n", member->kind(), member->toChars());
            toObjFile(member, global.params.multiobj);
        }

        global.params.verbose = v;
        return;
    }

    lastmname = m->srcfile->toChars();

    objmod->initfile(lastmname, NULL, m->toPrettyChars());

    eictor = NULL;
    ictorlocalgot = NULL;
    sctors.setDim(0);
    ectorgates.setDim(0);
    sdtors.setDim(0);
    ssharedctors.setDim(0);
    esharedctorgates.setDim(0);
    sshareddtors.setDim(0);
    stests.setDim(0);

    if (m->doppelganger)
    {
        /* Generate a reference to the moduleinfo, so the module constructors
         * and destructors get linked in.
         */
        Module *mod = m->aimports[0];
        assert(mod);
        if (mod->sictor || mod->sctor || mod->sdtor || mod->ssharedctor || mod->sshareddtor)
        {
            Symbol *s = toSymbol(mod);
            //objextern(s);
            //if (!s->Sxtrnnum) objextdef(s->Sident);
            if (!s->Sxtrnnum)
            {
                //printf("%s\n", s->Sident);
#if 0 /* This should work, but causes optlink to fail in common/newlib.asm */
                objextdef(s->Sident);
#else
                Symbol *sref = symbol_generate(SCstatic, type_fake(TYnptr));
                sref->Sfl = FLdata;
                dtxoff(&sref->Sdt, s, 0, TYnptr);
                outdata(sref);
#endif
            }
        }
    }

    if (global.params.cov)
    {
        /* Create coverage identifier:
         *  private uint[numlines] __coverage;
         */
        m->cov = symbol_calloc("__coverage");
        m->cov->Stype = type_fake(TYint);
        m->cov->Stype->Tmangle = mTYman_c;
        m->cov->Stype->Tcount++;
        m->cov->Sclass = SCstatic;
        m->cov->Sfl = FLdata;
        dtnzeros(&m->cov->Sdt, 4 * m->numlines);
        outdata(m->cov);
        slist_add(m->cov);

        m->covb = (unsigned *)calloc((m->numlines + 32) / 32, sizeof(*m->covb));
    }

    for (size_t i = 0; i < m->members->dim; i++)
    {
        Dsymbol *member = (*m->members)[i];
        //printf("toObjFile %s %s\n", member->kind(), member->toChars());
        toObjFile(member, multiobj);
    }

    if (global.params.cov)
    {
        /* Generate
         *      bit[numlines] __bcoverage;
         */
        Symbol *bcov = symbol_calloc("__bcoverage");
        bcov->Stype = type_fake(TYuint);
        bcov->Stype->Tcount++;
        bcov->Sclass = SCstatic;
        bcov->Sfl = FLdata;
        dtnbytes(&bcov->Sdt, (m->numlines + 32) / 32 * sizeof(*m->covb), (char *)m->covb);
        outdata(bcov);

        free(m->covb);
        m->covb = NULL;

        /* Generate:
         *  _d_cover_register(uint[] __coverage, BitArray __bcoverage, string filename);
         * and prepend it to the static constructor.
         */

        /* t will be the type of the functions generated:
         *      extern (C) void func();
         */
        type *t = type_function(TYnfunc, NULL, 0, false, tsvoid);
        t->Tmangle = mTYman_c;

        m->sictor = toSymbolX(m, "__modictor", SCglobal, t, "FZv");
        cstate.CSpsymtab = &m->sictor->Sfunc->Flocsym;
        localgot = ictorlocalgot;

        elem *ecov  = el_pair(TYdarray, el_long(TYsize_t, m->numlines), el_ptr(m->cov));
        elem *ebcov = el_pair(TYdarray, el_long(TYsize_t, m->numlines), el_ptr(bcov));

        if (config.exe == EX_WIN64)
        {
            ecov  = addressElem(ecov,  Type::tvoid->arrayOf(), false);
            ebcov = addressElem(ebcov, Type::tvoid->arrayOf(), false);
        }

        elem *efilename = toEfilename(m);
        if (config.exe == EX_WIN64)
            efilename = addressElem(efilename, Type::tstring, true);

        elem *e = el_params(
                      el_long(TYuchar, global.params.covPercent),
                      ecov,
                      ebcov,
                      efilename,
                      NULL);
        e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DCOVER2]), e);
        eictor = el_combine(e, eictor);
        ictorlocalgot = localgot;
    }

    // If coverage / static constructor / destructor / unittest calls
    if (eictor || sctors.dim || ectorgates.dim || sdtors.dim ||
        ssharedctors.dim || esharedctorgates.dim || sshareddtors.dim || stests.dim)
    {
        if (eictor)
        {
            localgot = ictorlocalgot;

            block *b = block_calloc();
            b->BC = BCret;
            b->Belem = eictor;
            m->sictor->Sfunc->Fstartline.Sfilename = m->arg;
            m->sictor->Sfunc->Fstartblock = b;
            writefunc(m->sictor);
        }

        m->sctor = callFuncsAndGates(m, &sctors, &ectorgates, "__modctor");
        m->sdtor = callFuncsAndGates(m, &sdtors, NULL, "__moddtor");

        m->ssharedctor = callFuncsAndGates(m, &ssharedctors, (StaticDtorDeclarations *)&esharedctorgates, "__modsharedctor");
        m->sshareddtor = callFuncsAndGates(m, &sshareddtors, NULL, "__modshareddtor");
        m->stest = callFuncsAndGates(m, &stests, NULL, "__modtest");

        if (m->doppelganger)
            genModuleInfo(m);
    }

    if (m->doppelganger)
    {
        objmod->termfile();
        return;
    }

    if (global.params.multiobj)
    {
        /* This is necessary because the main .obj for this module is written
         * first, but determining whether marray or massert or munittest are needed is done
         * possibly later in the doppelganger modules.
         * Another way to fix it is do the main one last.
         */
        toModuleAssert(m);
        toModuleUnittest(m);
        toModuleArray(m);
    }

    /* Always generate module info, because of templates and -cov.
     * But module info needs the runtime library, so disable it for betterC.
     */
    if (!global.params.betterC /*|| needModuleInfo()*/)
        genModuleInfo(m);

    genhelpers(m, false);

    objmod->termfile();
}
Beispiel #20
0
dt_t *StructInitializer::toDt()
{
    Array dts;
    dt_t *dt;
    dt_t *d;
    dt_t **pdtend;
    unsigned offset;

    //printf("StructInitializer::toDt('%s')\n", toChars());
    dts.setDim(ad->fields.dim);
    dts.zero();

    for (size_t i = 0; i < vars.dim; i++)
    {
        VarDeclaration *v = (VarDeclaration *)vars.data[i];
        Initializer *val = (Initializer *)value.data[i];

        //printf("vars[%d] = %s\n", i, v->toChars());

        for (size_t j = 0; 1; j++)
        {
            assert(j < dts.dim);
            //printf(" adfield[%d] = %s\n", j, ((VarDeclaration *)ad->fields.data[j])->toChars());
            if ((VarDeclaration *)ad->fields.data[j] == v)
            {
                if (dts.data[j])
                    error(loc, "field %s of %s already initialized", v->toChars(), ad->toChars());
                dts.data[j] = (void *)val->toDt();
                break;
            }
        }
    }

    dt = NULL;
    pdtend = &dt;
    offset = 0;
    for (size_t j = 0; j < dts.dim; j++)
    {
        VarDeclaration *v = (VarDeclaration *)ad->fields.data[j];

        d = (dt_t *)dts.data[j];
        if (!d)
        {   // An instance specific initializer was not provided.
            // Look to see if there's a default initializer from the
            // struct definition
            if (v->init)
            {
                d = v->init->toDt();
            }
            else if (v->offset >= offset)
            {
                unsigned k;
                unsigned offset2 = v->offset + v->type->size();
                // Make sure this field does not overlap any explicitly
                // initialized field.
                for (k = j + 1; 1; k++)
                {
                    if (k == dts.dim)           // didn't find any overlap
                    {
                        v->type->toDt(&d);
                        break;
                    }
                    VarDeclaration *v2 = (VarDeclaration *)ad->fields.data[k];

                    if (v2->offset < offset2 && dts.data[k])
                        break;                  // overlap
                }
            }
        }
        if (d)
        {
            if (v->offset < offset)
                error(loc, "duplicate union initialization for %s", v->toChars());
            else
            {   size_t sz = dt_size(d);
                size_t vsz = v->type->size();
                size_t voffset = v->offset;

                if (sz > vsz)
                {   assert(v->type->ty == Tsarray && vsz == 0);
                    error(loc, "zero length array %s has non-zero length initializer", v->toChars());
                }

                unsigned dim = 1;
                for (Type *vt = v->type->toBasetype();
                        vt->ty == Tsarray;
                        vt = vt->next->toBasetype())
                {   TypeSArray *tsa = (TypeSArray *)vt;
                    dim *= tsa->dim->toInteger();
                }
                //printf("sz = %d, dim = %d, vsz = %d\n", sz, dim, vsz);
                assert(sz == vsz || sz * dim <= vsz);

                for (size_t i = 0; i < dim; i++)
                {
                    if (offset < voffset)
                        pdtend = dtnzeros(pdtend, voffset - offset);
                    if (!d)
                    {
                        if (v->init)
                            d = v->init->toDt();
                        else
                            v->type->toDt(&d);
                    }
                    pdtend = dtcat(pdtend, d);
                    d = NULL;
                    offset = voffset + sz;
                    voffset += vsz / dim;
                    if (sz == vsz)
                        break;
                }
            }
        }
    }
    if (offset < ad->structsize)
        dtnzeros(pdtend, ad->structsize - offset);

#ifdef IN_GCC
    dt_t * cdt = NULL;
    dtcontainer(&cdt, ad->type, dt);
    dt = cdt;
#endif
    return dt;
}
Beispiel #21
0
void Module::genobjfile(int multiobj)
{
    //EEcontext *ee = env->getEEcontext();

    //printf("Module::genobjfile(multiobj = %d) %s\n", multiobj, toChars());

    lastmname = srcfile->toChars();

    obj_initfile(lastmname, NULL, toPrettyChars());

    eictor = NULL;
    ictorlocalgot = NULL;
    ector = NULL;
    ectorgates.setDim(0);
    edtor = NULL;
    etest = NULL;
    dtorcount = 0;

    if (doppelganger)
    {
	/* Generate a reference to the moduleinfo, so the module constructors
	 * and destructors get linked in.
	 */
	Module *m = (Module *)aimports.data[0];
	assert(m);
	if (m->sictor || m->sctor || m->sdtor)
	{
	    Symbol *s = m->toSymbol();
	    //objextern(s);
	    //if (!s->Sxtrnnum) objextdef(s->Sident);
	    if (!s->Sxtrnnum)
	    {
		//printf("%s\n", s->Sident);
#if 0 /* This should work, but causes optlink to fail in common/newlib.asm */
		objextdef(s->Sident);
#else
#if ELFOBJ || MACHOBJ
		int nbytes = reftoident(DATA, Offset(DATA), s, 0, CFoff);
		Offset(DATA) += nbytes;
#else
		int nbytes = reftoident(DATA, Doffset, s, 0, CFoff);
		Doffset += nbytes;
#endif
#endif
	    }
	}
    }

    if (global.params.cov)
    {
	/* Create coverage identifier:
	 *  private uint[numlines] __coverage;
	 */
	cov = symbol_calloc("__coverage");
	cov->Stype = type_fake(TYint);
	cov->Stype->Tmangle = mTYman_c;
	cov->Stype->Tcount++;
	cov->Sclass = SCstatic;
	cov->Sfl = FLdata;
#if ELFOBJ || MACHOBJ
	cov->Sseg = UDATA;
#endif
	dtnzeros(&cov->Sdt, 4 * numlines);
	outdata(cov);
	slist_add(cov);

	covb = (unsigned *)calloc((numlines + 32) / 32, sizeof(*covb));
    }

    for (int i = 0; i < members->dim; i++)
    {
	Dsymbol *member = (Dsymbol *)members->data[i];
	member->toObjFile(multiobj);
    }

    if (global.params.cov)
    {
	/* Generate
	 *	bit[numlines] __bcoverage;
	 */
	Symbol *bcov = symbol_calloc("__bcoverage");
	bcov->Stype = type_fake(TYuint);
	bcov->Stype->Tcount++;
	bcov->Sclass = SCstatic;
	bcov->Sfl = FLdata;
#if ELFOBJ || MACHOBJ
	bcov->Sseg = DATA;
#endif
	dtnbytes(&bcov->Sdt, (numlines + 32) / 32 * sizeof(*covb), (char *)covb);
	outdata(bcov);

	free(covb);
	covb = NULL;

	/* Generate:
	 *  _d_cover_register(uint[] __coverage, BitArray __bcoverage, string filename);
	 * and prepend it to the static constructor.
	 */

	/* t will be the type of the functions generated:
	 *	extern (C) void func();
	 */
	type *t = type_alloc(TYnfunc);
	t->Tflags |= TFprototype | TFfixed;
	t->Tmangle = mTYman_c;
	t->Tnext = tsvoid;
	tsvoid->Tcount++;

	sictor = toSymbolX("__modictor", SCglobal, t, "FZv");
	cstate.CSpsymtab = &sictor->Sfunc->Flocsym;
	localgot = ictorlocalgot;
	elem *e;

	e = el_params(el_ptr(cov), el_long(TYuint, numlines),
		      el_ptr(bcov), el_long(TYuint, numlines),
		      toEfilename(),
		      NULL);
	e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_DCOVER]), e);
	eictor = el_combine(e, eictor);
	ictorlocalgot = localgot;
    }

    // If coverage / static constructor / destructor / unittest calls
    if (eictor || ector || ectorgates.dim || edtor || etest)
    {
	/* t will be the type of the functions generated:
	 *	extern (C) void func();
	 */
	type *t = type_alloc(TYnfunc);
	t->Tflags |= TFprototype | TFfixed;
	t->Tmangle = mTYman_c;
	t->Tnext = tsvoid;
	tsvoid->Tcount++;

	static char moddeco[] = "FZv";

	if (eictor)
	{
	    localgot = ictorlocalgot;

	    block *b = block_calloc();
	    b->BC = BCret;
	    b->Belem = eictor;
	    sictor->Sfunc->Fstartblock = b;
	    writefunc(sictor);
	}

	if (ector || ectorgates.dim)
	{
	    localgot = NULL;
	    sctor = toSymbolX("__modctor", SCglobal, t, moddeco);
	    cstate.CSpsymtab = &sctor->Sfunc->Flocsym;

	    for (int i = 0; i < ectorgates.dim; i++)
	    {	StaticDtorDeclaration *f = (StaticDtorDeclaration *)ectorgates.data[i];

		Symbol *s = f->vgate->toSymbol();
		elem *e = el_var(s);
		e = el_bin(OPaddass, TYint, e, el_long(TYint, 1));
		ector = el_combine(ector, e);
	    }

	    block *b = block_calloc();
	    b->BC = BCret;
	    b->Belem = ector;
	    sctor->Sfunc->Fstartblock = b;
	    writefunc(sctor);
#if STATICCTOR
	    obj_staticctor(sctor, dtorcount, 1);
#endif
	}

	if (edtor)
	{
	    localgot = NULL;
	    sdtor = toSymbolX("__moddtor", SCglobal, t, moddeco);

	    block *b = block_calloc();
	    b->BC = BCret;
	    b->Belem = edtor;
	    sdtor->Sfunc->Fstartblock = b;
	    writefunc(sdtor);
	}

	if (etest)
	{
	    localgot = NULL;
	    stest = toSymbolX("__modtest", SCglobal, t, moddeco);

	    block *b = block_calloc();
	    b->BC = BCret;
	    b->Belem = etest;
	    stest->Sfunc->Fstartblock = b;
	    writefunc(stest);
	}

	if (doppelganger)
	    genmoduleinfo();
    }

    if (doppelganger)
    {
	obj_termfile();
	return;
    }

    if (global.params.multiobj)
    {	/* This is necessary because the main .obj for this module is written
	 * first, but determining whether marray or massert are needed is done
	 * possibly later in the doppelganger modules.
	 * Another way to fix it is do the main one last.
	 */
	toModuleAssert();
	toModuleArray();
    }

    // If module assert
    for (int i = 0; i < 2; i++)
    {
	Symbol *ma = i ? marray : massert;

	if (ma)
	{
	    elem *elinnum;
	    elem *efilename;

	    localgot = NULL;

	    // Call dassert(filename, line)
	    // Get sole parameter, linnum
	    {
		Symbol *sp;

		sp = symbol_calloc("linnum");
		sp->Stype = type_fake(TYint);
		sp->Stype->Tcount++;
		sp->Sclass = SCfastpar;
		sp->Spreg = AX;
		sp->Sflags &= ~SFLspill;
		sp->Sfl = FLpara;	// FLauto?
		cstate.CSpsymtab = &ma->Sfunc->Flocsym;
		symbol_add(sp);

		elinnum = el_var(sp);
	    }

	    efilename = toEmodulename();

	    elem *e = el_var(rtlsym[i ? RTLSYM_DARRAY : RTLSYM_DASSERT]);
	    e = el_bin(OPcall, TYvoid, e, el_param(elinnum, efilename));

	    block *b = block_calloc();
	    b->BC = BCret;
	    b->Belem = e;
	    ma->Sfunc->Fstartblock = b;
	    ma->Sclass = SCglobal;
	    ma->Sfl = 0;
	    writefunc(ma);
	}
    }

#if 1
    // Always generate module info, because of templates and -cov
    if (1 || needModuleInfo())
	genmoduleinfo();
#endif
    
    obj_termfile();
}
Beispiel #22
0
Datei: eh.c Projekt: nischu7/dmd
void except_fillInEHTable(symbol *s)
{
    unsigned fsize = NPTRSIZE;             // target size of function pointer
    dt_t **pdt = &s->Sdt;

    /*
        void*           pointer to start of function
        unsigned        offset of ESP from EBP
        unsigned        offset from start of function to return code
        unsigned nguards;       // dimension of guard[] (Linux)
        Guard guard[];
      catchoffset:
        unsigned ncatches;      // number of catch blocks
        {   void *type;         // symbol representing type
            unsigned bpoffset;  // EBP offset of catch variable
            void *handler;      // catch handler code
        } catch[];
     */

/* Be careful of this, as we need the sizeof Guard on the target, not
 * in the compiler.
 */
#if OUREH
#define GUARD_SIZE      (I64 ? 3*8 : 5*4)     // sizeof(Guard)
#else
#define GUARD_SIZE      (sizeof(Guard))
#endif

    int sz = 0;

    // Address of start of function
    symbol_debug(funcsym_p);
    pdt = dtxoff(pdt,funcsym_p,0,TYnptr);
    sz += fsize;

    //printf("ehtables: func = %s, offset = x%x, startblock->Boffset = x%x\n", funcsym_p->Sident, funcsym_p->Soffset, startblock->Boffset);

    // Get offset of ESP from EBP
    long spoff = cod3_spoff();
    pdt = dtdword(pdt,spoff);
    sz += 4;

    // Offset from start of function to return code
    pdt = dtdword(pdt,retoffset);
    sz += 4;

    // First, calculate starting catch offset
    int guarddim = 0;                               // max dimension of guard[]
    for (block *b = startblock; b; b = b->Bnext)
    {
        if (b->BC == BC_try && b->Bscope_index >= guarddim)
            guarddim = b->Bscope_index + 1;
//      printf("b->BC = %2d, Bscope_index = %2d, last_index = %2d, offset = x%x\n",
//              b->BC, b->Bscope_index, b->Blast_index, b->Boffset);
    }

#if OUREH
    pdt = dtsize_t(pdt,guarddim);
    sz += NPTRSIZE;
#endif

    unsigned catchoffset = sz + guarddim * GUARD_SIZE;

    // Generate guard[]
    int i = 0;
    for (block *b = startblock; b; b = b->Bnext)
    {
        //printf("b = %p, b->Btry = %p, b->offset = %x\n", b, b->Btry, b->Boffset);
        if (b->BC == BC_try)
        {
            assert(b->Bscope_index >= i);
            if (i < b->Bscope_index)
            {   int fillsize = (b->Bscope_index - i) * GUARD_SIZE;
                pdt = dtnzeros(pdt, fillsize);
                sz += fillsize;
            }
            i = b->Bscope_index + 1;

            int nsucc = list_nitems(b->Bsucc);

#if OUREH
            //printf("DHandlerInfo: offset = %x", (int)(b->Boffset - startblock->Boffset));
            pdt = dtdword(pdt,b->Boffset - startblock->Boffset);        // offset to start of block

            // Compute ending offset
            unsigned endoffset;
            for (block *bn = b->Bnext; 1; bn = bn->Bnext)
            {
                //printf("\tbn = %p, bn->Btry = %p, bn->offset = %x\n", bn, bn->Btry, bn->Boffset);
                assert(bn);
                if (bn->Btry == b->Btry)
                {    endoffset = bn->Boffset - startblock->Boffset;
                     break;
                }
            }
            //printf(" endoffset = %x, prev_index = %d\n", endoffset, b->Blast_index);
            pdt = dtdword(pdt,endoffset);               // offset past end of guarded block
#endif

            pdt = dtdword(pdt,b->Blast_index);          // parent index

            if (b->jcatchvar)                           // if try-catch
            {
                pdt = dtdword(pdt,catchoffset);
                pdt = dtsize_t(pdt,0);                  // no finally handler

                catchoffset += NPTRSIZE + (nsucc - 1) * (3 * NPTRSIZE);
            }
            else                                        // else try-finally
            {
                assert(nsucc == 2);
                pdt = dtdword(pdt,0);           // no catch offset
                block *bhandler = list_block(list_next(b->Bsucc));
                assert(bhandler->BC == BC_finally);
                // To successor of BC_finally block
                bhandler = list_block(bhandler->Bsucc);
#if OUREH
                pdt = dtxoff(pdt,funcsym_p,bhandler->Boffset - startblock->Boffset, TYnptr);    // finally handler address
#else
                pdt = dtcoff(pdt,bhandler->Boffset);  // finally handler address
#endif
            }
            sz += GUARD_SIZE;
        }
    }

    // Generate catch[]
    for (block *b = startblock; b; b = b->Bnext)
    {
        if (b->BC == BC_try)
        {   block *bhandler;
            int nsucc;

            if (b->jcatchvar)                           // if try-catch
            {   list_t bl;

                nsucc = list_nitems(b->Bsucc);
                pdt = dtsize_t(pdt,nsucc - 1);           // # of catch blocks
                sz += NPTRSIZE;

                for (bl = list_next(b->Bsucc); bl; bl = list_next(bl))
                {
                    block *bcatch = list_block(bl);

                    pdt = dtxoff(pdt,bcatch->Bcatchtype,0,TYjhandle);

                    pdt = dtsize_t(pdt,cod3_bpoffset(b->jcatchvar));     // EBP offset

#if OUREH
                    pdt = dtxoff(pdt,funcsym_p,bcatch->Boffset - startblock->Boffset, TYnptr);  // catch handler address
#else
                    pdt = dtcoff(pdt,bcatch->Boffset);        // catch handler address
#endif
                    sz += 3 * NPTRSIZE;
                }
            }
        }
    }
    assert(sz != 0);
}