Ejemplo n.º 1
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);
            dtsize_t(&dt, namelen);
            dtabytes(&dt, TYnptr, 0, namelen + 1, name);

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

            // (*vtblInterfaces)[]
            unsigned offset;
            dtsize_t(&dt, id->vtblInterfaces->dim);
            if (id->vtblInterfaces->dim)
            {
                offset = Target::classinfosize;    // must be ClassInfo.size
                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
            {
                offset = 0;
                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);
            }

            id->csym->Sdt = dt;
            out_readonly(id->csym);
            outdata(id->csym);
            if (id->isExport())
                objmod->export_symbol(id->csym, 0);
        }
Ejemplo n.º 2
0
        void visit(VarDeclaration *vd)
        {

            //printf("VarDeclaration::toObjFile(%p '%s' type=%s) protection %d\n", vd, vd->toChars(), vd->type->toChars(), vd->protection);
            //printf("\talign = %d\n", vd->alignment);

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

            if (vd->aliassym)
            {
                visitNoMultiObj(vd->toAlias());
                return;
            }

            // Do not store variables we cannot take the address of
            if (!vd->canTakeAddressOf())
            {
                return;
            }

            if (!vd->isDataseg() || vd->storage_class & STCextern)
                return;

            Symbol *s = toSymbol(vd);
            unsigned sz = vd->type->size();

            Dsymbol *parent = vd->toParent();
            s->Sclass = SCglobal;

            do
            {
                /* Global template data members need to be in comdat's
                 * in case multiple .obj files instantiate the same
                 * template with the same types.
                 */
                if (parent->isTemplateInstance() && !parent->isTemplateMixin())
                {
                    s->Sclass = SCcomdat;
                    break;
                }
                parent = parent->parent;
            } while (parent);
            s->Sfl = FLdata;

            if (vd->init)
            {
                s->Sdt = Initializer_toDt(vd->init);

                // Look for static array that is block initialized
                ExpInitializer *ie = vd->init->isExpInitializer();

                Type *tb = vd->type->toBasetype();
                if (tb->ty == Tsarray && ie &&
                    !tb->nextOf()->equals(ie->exp->type->toBasetype()->nextOf()) &&
                    ie->exp->implicitConvTo(tb->nextOf())
                    )
                {
                    size_t dim = ((TypeSArray *)tb)->dim->toInteger();

                    // Duplicate Sdt 'dim-1' times, as we already have the first one
                    dt_t **pdt = &s->Sdt;
                    while (--dim > 0)
                    {
                        pdt = Expression_toDt(ie->exp, pdt);
                    }
                }
            }
            else
            {
                Type_toDt(vd->type, &s->Sdt);
            }
            dt_optimize(s->Sdt);

            // See if we can convert a comdat to a comdef,
            // which saves on exe file space.
            if (s->Sclass == SCcomdat &&
                s->Sdt &&
                dtallzeros(s->Sdt) &&
                !vd->isThreadlocal())
            {
                s->Sclass = SCglobal;
                dt2common(&s->Sdt);
            }

            if (!sz && vd->type->toBasetype()->ty != Tsarray)
                assert(0); // this shouldn't be possible

            if (sz || objmod->allowZeroSize())
            {
                outdata(s);
                if (vd->isExport())
                    objmod->export_symbol(s, 0);
            }
        }
Ejemplo n.º 3
0
        void visit(VarDeclaration *vd)
        {

            //printf("VarDeclaration::toObjFile(%p '%s' type=%s) protection %d\n", vd, vd->toChars(), vd->type->toChars(), vd->protection);
            //printf("\talign = %d\n", vd->alignment);

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

            if (vd->aliassym)
            {
                visitNoMultiObj(vd->toAlias());
                return;
            }

            // Do not store variables we cannot take the address of
            if (!vd->canTakeAddressOf())
            {
                return;
            }

            if (!vd->isDataseg() || vd->storage_class & STCextern)
                return;

            Symbol *s = toSymbol(vd);
            d_uns64 sz64 = vd->type->size(vd->loc);
            if (sz64 == SIZE_INVALID)
            {
                vd->error("size overflow");
                return;
            }
            if (sz64 >= 0x1000000)  // there has to be some 'reasonable' limit on the size
            {
                vd->error("size of x%llx exceeds max allowed size 0x100_0000", sz64);
            }
            unsigned sz = (unsigned)sz64;

            Dsymbol *parent = vd->toParent();
            s->Sclass = SCglobal;

            do
            {
                /* Global template data members need to be in comdat's
                 * in case multiple .obj files instantiate the same
                 * template with the same types.
                 */
                if (parent->isTemplateInstance() && !parent->isTemplateMixin())
                {
                    s->Sclass = SCcomdat;
                    break;
                }
                parent = parent->parent;
            } while (parent);
            s->Sfl = FLdata;

            if (config.objfmt == OBJ_MACH && I64 && (s->ty() & mTYLINK) == mTYthread)
            {
                DtBuilder dtb;
                tlsToDt(vd, s, dtb);
                s->Sdt = dtb.finish();
            }

            else if (vd->_init)
            {
                DtBuilder dtb;
                initializerToDt(vd, dtb);
                s->Sdt = dtb.finish();
            }
            else
            {
                DtBuilder dtb;
                Type_toDt(vd->type, &dtb);
                s->Sdt = dtb.finish();
            }

            // See if we can convert a comdat to a comdef,
            // which saves on exe file space.
            if (s->Sclass == SCcomdat &&
                s->Sdt &&
                dtallzeros(s->Sdt) &&
                !vd->isThreadlocal())
            {
                s->Sclass = SCglobal;
                dt2common(&s->Sdt);
            }

            if (!sz && vd->type->toBasetype()->ty != Tsarray)
                assert(0); // this shouldn't be possible

            if (sz || objmod->allowZeroSize())
            {
                outdata(s);
                if (vd->isExport())
                    objmod->export_symbol(s, 0);
            }
        }