Пример #1
0
Symbol *FuncDeclaration::toSymbol()
{
    if (!csym)
    {   Symbol *s;
        TYPE *t;
        const char *id;

#if 0
        id = ident->toChars();
#else
        id = mangle();
#endif
        //printf("FuncDeclaration::toSymbol(%s %s)\n", kind(), toChars());
        //printf("\tid = '%s'\n", id);
        //printf("\ttype = %s\n", type->toChars());
        s = symbol_calloc(id);
        slist_add(s);

        {
            s->prettyIdent = toPrettyChars();
            s->Sclass = SCglobal;
            symbol_func(s);
            func_t *f = s->Sfunc;
            if (isVirtual() && vtblIndex != -1)
                f->Fflags |= Fvirtual;
            else if (isMember2() && isStatic())
                f->Fflags |= Fstatic;
            f->Fstartline.Slinnum = loc.linnum;
            f->Fstartline.Sfilename = (char *)loc.filename;
            if (endloc.linnum)
            {   f->Fendline.Slinnum = endloc.linnum;
                f->Fendline.Sfilename = (char *)endloc.filename;
            }
            else
            {   f->Fendline.Slinnum = loc.linnum;
                f->Fendline.Sfilename = (char *)loc.filename;
            }
            t = type->toCtype();
        }

        mangle_t msave = t->Tmangle;
        if (isMain())
        {
            t->Tty = TYnfunc;
            t->Tmangle = mTYman_c;
        }
        else
        {
            switch (linkage)
            {
                case LINKwindows:
                    t->Tmangle = mTYman_std;
                    break;

                case LINKpascal:
                    t->Tty = TYnpfunc;
                    t->Tmangle = mTYman_pas;
                    break;

                case LINKc:
                    t->Tmangle = mTYman_c;
                    break;

                case LINKd:
                    t->Tmangle = mTYman_d;
                    break;

                case LINKcpp:
                {   t->Tmangle = mTYman_cpp;
                    if (isThis() && !global.params.is64bit && global.params.isWindows)
                        t->Tty = TYmfunc;
                    s->Sflags |= SFLpublic;
                    Dsymbol *parent = toParent();
                    ClassDeclaration *cd = parent->isClassDeclaration();
                    if (cd)
                    {
                        ::type *tc = cd->type->toCtype();
                        s->Sscope = tc->Tnext->Ttag;
                    }
                    StructDeclaration *sd = parent->isStructDeclaration();
                    if (sd)
                    {
                        ::type *ts = sd->type->toCtype();
                        s->Sscope = ts->Ttag;
                    }
                    break;
                }
                default:
                    printf("linkage = %d\n", linkage);
                    assert(0);
            }
        }
        if (msave)
            assert(msave == t->Tmangle);
        //printf("Tty = %x, mangle = x%x\n", t->Tty, t->Tmangle);
        t->Tcount++;
        s->Stype = t;
        //s->Sfielddef = this;

        csym = s;
    }
    return csym;
}
Пример #2
0
Файл: toir.c Проект: dheld/dmd
elem *getEthis(Loc loc, IRState *irs, Dsymbol *fd)
{
    elem *ethis;
    FuncDeclaration *thisfd = irs->getFunc();
    Dsymbol *fdparent = fd->toParent2();

    //printf("getEthis(thisfd = '%s', fd = '%s', fdparent = '%s')\n", thisfd->toPrettyChars(), fd->toPrettyChars(), fdparent->toPrettyChars());
    if (fdparent == thisfd ||
        /* These two are compiler generated functions for the in and out contracts,
         * and are called from an overriding function, not just the one they're
         * nested inside, so this hack is so they'll pass
         */
        fd->ident == Id::require || fd->ident == Id::ensure)
    {   /* Going down one nesting level, i.e. we're calling
         * a nested function from its enclosing function.
         */
#if DMDV2
        if (irs->sclosure)
            ethis = el_var(irs->sclosure);
        else
#endif
        if (irs->sthis)
        {   // We have a 'this' pointer for the current function
            ethis = el_var(irs->sthis);

            /* If no variables in the current function's frame are
             * referenced by nested functions, then we can 'skip'
             * adding this frame into the linked list of stack
             * frames.
             */
            if (thisfd->hasNestedFrameRefs())
            {   /* Local variables are referenced, can't skip.
                 * Address of 'this' gives the 'this' for the nested
                 * function
                 */
                ethis = el_una(OPaddr, TYnptr, ethis);
            }
        }
        else
        {   /* No 'this' pointer for current function,
             * use NULL if no references to the current function's frame
             */
            ethis = el_long(TYnptr, 0);
            if (thisfd->hasNestedFrameRefs())
            {   /* OPframeptr is an operator that gets the frame pointer
                 * for the current function, i.e. for the x86 it gets
                 * the value of EBP
                 */
                ethis->Eoper = OPframeptr;
            }
        }
//if (fdparent != thisfd) ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYint, 0x18));
    }
    else
    {
        if (!irs->sthis)                // if no frame pointer for this function
        {
            fd->error(loc, "is a nested function and cannot be accessed from %s", irs->getFunc()->toPrettyChars());
            ethis = el_long(TYnptr, 0); // error recovery
        }
        else
        {
            ethis = el_var(irs->sthis);
            Dsymbol *s = thisfd;
            while (fd != s)
            {   /* Go up a nesting level, i.e. we need to find the 'this'
                 * of an enclosing function.
                 * Our 'enclosing function' may also be an inner class.
                 */

                //printf("\ts = '%s'\n", s->toChars());
                thisfd = s->isFuncDeclaration();
                if (thisfd)
                {   /* Enclosing function is a function.
                     */
                    if (fdparent == s->toParent2())
                        break;
                    if (thisfd->isNested())
                    {
                        FuncDeclaration *p = s->toParent2()->isFuncDeclaration();
                        if (!p || p->hasNestedFrameRefs())
                            ethis = el_una(OPind, TYnptr, ethis);
                    }
                    else if (thisfd->vthis)
                    {
                    }
                    else
                    {   // Error should have been caught by front end
                        assert(0);
                    }
                }
                else
                {   /* Enclosed by an aggregate. That means the current
                     * function must be a member function of that aggregate.
                     */
                    ClassDeclaration *cd;
                    StructDeclaration *sd;
                    AggregateDeclaration *ad = s->isAggregateDeclaration();
                    if (!ad)
                        goto Lnoframe;
                    cd = s->isClassDeclaration();
                    if (cd && fd->isClassDeclaration() &&
                        fd->isClassDeclaration()->isBaseOf(cd, NULL))
                        break;
                    sd = s->isStructDeclaration();
                    if (fd == sd)
                        break;
                    if (!ad->isNested() || !ad->vthis)
                    {
                      Lnoframe:
                        irs->getFunc()->error(loc, "cannot get frame pointer to %s", fd->toChars());
                        return el_long(TYnptr, 0);      // error recovery
                    }
                    ethis = el_bin(OPadd, TYnptr, ethis, el_long(TYsize_t, ad->vthis->offset));
                    ethis = el_una(OPind, TYnptr, ethis);
                    if (fdparent == s->toParent2())
                        break;
                    if (fd == s->toParent2())
                    {
                        /* Remember that frames for functions that have no
                         * nested references are skipped in the linked list
                         * of frames.
                         */
                        if (s->toParent2()->isFuncDeclaration()->hasNestedFrameRefs())
                            ethis = el_una(OPind, TYnptr, ethis);
                        break;
                    }
                    if (s->toParent2()->isFuncDeclaration())
                    {
                        /* Remember that frames for functions that have no
                         * nested references are skipped in the linked list
                         * of frames.
                         */
                        if (s->toParent2()->isFuncDeclaration()->hasNestedFrameRefs())
                            ethis = el_una(OPind, TYnptr, ethis);
                    }
                }
                s = s->toParent2();
                assert(s);
            }
        }
    }
#if 0
    printf("ethis:\n");
    elem_print(ethis);
    printf("\n");
#endif
    return ethis;
}
Пример #3
0
Symbol *VarDeclaration::toSymbol()
{
    //printf("VarDeclaration::toSymbol(%s)\n", toChars());
    //if (needThis()) *(char*)0=0;
    assert(!needThis());
    if (!csym)
    {
        TYPE *t;
        const char *id;

        if (isDataseg())
            id = mangle();
        else
            id = ident->toChars();
        Symbol *s = symbol_calloc(id);
        s->Salignment = alignment;

        if (storage_class & (STCout | STCref))
        {
            // should be TYref, but problems in back end
            t = type_pointer(type->toCtype());
        }
        else if (storage_class & STClazy)
        {
            if (config.exe == EX_WIN64 && isParameter())
                t = type_fake(TYnptr);
            else
                t = type_fake(TYdelegate);          // Tdelegate as C type
            t->Tcount++;
        }
        else if (isParameter())
        {
            if (config.exe == EX_WIN64 && type->size(Loc()) > REGSIZE)
            {
                // should be TYref, but problems in back end
                t = type_pointer(type->toCtype());
            }
            else
            {
                t = type->toCParamtype();
                t->Tcount++;
            }
        }
        else
        {
            t = type->toCtype();
            t->Tcount++;
        }

        if (isDataseg())
        {
            if (isThreadlocal())
            {   /* Thread local storage
                 */
                TYPE *ts = t;
                ts->Tcount++;   // make sure a different t is allocated
                type_setty(&t, t->Tty | mTYthread);
                ts->Tcount--;

                if (global.params.vtls)
                {
                    char *p = loc.toChars();
                    fprintf(stderr, "%s: %s is thread local\n", p ? p : "", toChars());
                    if (p)
                        mem.free(p);
                }
            }
            s->Sclass = SCextern;
            s->Sfl = FLextern;
            slist_add(s);
            /* if it's global or static, then it needs to have a qualified but unmangled name.
             * This gives some explanation of the separation in treating name mangling.
             * It applies to PDB format, but should apply to CV as PDB derives from CV.
             *    http://msdn.microsoft.com/en-us/library/ff553493(VS.85).aspx
             */
            s->prettyIdent = toPrettyChars();
        }
        else
        {
            s->Sclass = SCauto;
            s->Sfl = FLauto;

            if (nestedrefs.dim)
            {
                /* Symbol is accessed by a nested function. Make sure
                 * it is not put in a register, and that the optimizer
                 * assumes it is modified across function calls and pointer
                 * dereferences.
                 */
                //printf("\tnested ref, not register\n");
                type_setcv(&t, t->Tty | mTYvolatile);
            }
        }

        if (ident == Id::va_argsave)
            /* __va_argsave is set outside of the realm of the optimizer,
             * so we tell the optimizer to leave it alone
             */
            type_setcv(&t, t->Tty | mTYvolatile);

        mangle_t m = 0;
        switch (linkage)
        {
            case LINKwindows:
                m = mTYman_std;
                break;

            case LINKpascal:
                m = mTYman_pas;
                break;

            case LINKc:
                m = mTYman_c;
                break;

            case LINKd:
                m = mTYman_d;
                break;

            case LINKcpp:
            {
                m = mTYman_cpp;

                s->Sflags = SFLpublic;
                Dsymbol *parent = toParent();
                ClassDeclaration *cd = parent->isClassDeclaration();
                if (cd)
                {
                    ::type *tc = cd->type->toCtype();
                    s->Sscope = tc->Tnext->Ttag;
                }
                StructDeclaration *sd = parent->isStructDeclaration();
                if (sd)
                {
                    ::type *ts = sd->type->toCtype();
                    s->Sscope = ts->Ttag;
                }
                break;
            }
            default:
                printf("linkage = %d\n", linkage);
                assert(0);
        }
        type_setmangle(&t, m);
        s->Stype = t;

        csym = s;
    }
    return csym;
}
Пример #4
0
/***************************************
 * Fill out remainder of elements[] with default initializers for fields[].
 * Input:
 *      loc
 *      elements    explicit arguments which given to construct object.
 *      ctorinit    true if the elements will be used for default initialization.
 * Returns false if any errors occur.
 * Otherwise, returns true and the missing arguments will be pushed in elements[].
 */
bool StructDeclaration::fill(Loc loc, Expressions *elements, bool ctorinit)
{
    //printf("StructDeclaration::fill() %s\n", toChars());
    assert(sizeok == SIZEOKdone);
    size_t nfields = fields.dim - isNested();
    bool errors = false;

    if (elements)
    {
        size_t dim = elements->dim;
        elements->setDim(nfields);
        for (size_t i = dim; i < nfields; i++)
            (*elements)[i] = NULL;
    }

    // Fill in missing any elements with default initializers
    for (size_t i = 0; i < nfields; i++)
    {
        if (elements && (*elements)[i])
            continue;
        VarDeclaration *vd = fields[i];
        VarDeclaration *vx = vd;
        if (vd->init && vd->init->isVoidInitializer())
            vx = NULL;
        // Find overlapped fields with the hole [vd->offset .. vd->offset->size()].
        size_t fieldi = i;
        for (size_t j = 0; j < nfields; j++)
        {
            if (i == j)
                continue;
            VarDeclaration *v2 = fields[j];
            bool overlap = (vd->offset < v2->offset + v2->type->size() &&
                            v2->offset < vd->offset + vd->type->size());
            if (!overlap)
                continue;

            // vd and v2 are overlapping. If either has destructors, postblits, etc., then error
            //printf("overlapping fields %s and %s\n", vd->toChars(), v2->toChars());

            VarDeclaration *v = vd;
            for (int k = 0; k < 2; ++k, v = v2)
            {
                Type *tv = v->type->baseElemOf();
                Dsymbol *sv = tv->toDsymbol(NULL);
                if (sv && !errors)
                {
                    StructDeclaration *sd = sv->isStructDeclaration();
                    if (sd && (sd->dtor || sd->inv || sd->postblit))
                    {
                        error("destructors, postblits and invariants are not allowed in overlapping fields %s and %s", vd->toChars(), v2->toChars());
                        errors = true;
                        break;
                    }
                }
            }

            if (elements)
            {
                if ((*elements)[j])
                {
                    vx = NULL;
                    break;
                }
            }
            else
            {
                vd->overlapped = true;
            }
            if (v2->init && v2->init->isVoidInitializer())
                continue;

            if (elements)
            {
                /* Prefer first found non-void-initialized field
                 * union U { int a; int b = 2; }
                 * U u;    // Error: overlapping initialization for field a and b
                 */
                if (!vx)
                    vx = v2, fieldi = j;
                else if (v2->init)
                {
                    ::error(loc, "overlapping initialization for field %s and %s",
                        v2->toChars(), vd->toChars());
                }
            }
            else
            {
                // Will fix Bugzilla 1432 by enabling this path always

                /* Prefer explicitly initialized field
                 * union U { int a; int b = 2; }
                 * U u;    // OK (u.b == 2)
                 */
                if (!vx || !vx->init && v2->init)
                    vx = v2, fieldi = j;
                else if (vx != vd &&
                    !(vx->offset < v2->offset + v2->type->size() &&
                      v2->offset < vx->offset + vx->type->size()))
                {
                    // Both vx and v2 fills vd, but vx and v2 does not overlap
                }
                else if (vx->init && v2->init)
                {
                    ::error(loc, "overlapping default initialization for field %s and %s",
                        v2->toChars(), vd->toChars());
                }
                else
                    assert(vx->init || !vx->init && !v2->init);
            }
        }
        if (elements && vx)
        {
            Expression *e;
            if (vx->type->size() == 0)
            {
                e = NULL;
            }
            else if (vx->init)
            {
                assert(!vx->init->isVoidInitializer());
                e = vx->getConstInitializer(false);
            }
            else
            {
                if ((vx->storage_class & STCnodefaultctor) && !ctorinit)
                {
                    ::error(loc, "field %s.%s must be initialized because it has no default constructor",
                            type->toChars(), vx->toChars());
                }

                /* Bugzilla 12509: Get the element of static array type.
                 */
                Type *telem = vx->type;
                if (telem->ty == Tsarray)
                {
                    /* We cannot use Type::baseElemOf() here.
                     * If the bottom of the Tsarray is an enum type, baseElemOf()
                     * will return the base of the enum, and its default initializer
                     * would be different from the enum's.
                     */
                    while (telem->toBasetype()->ty == Tsarray)
                        telem = ((TypeSArray *)telem->toBasetype())->next;

                    if (telem->ty == Tvoid)
                        telem = Type::tuns8->addMod(telem->mod);
                }
                if (telem->needsNested() && ctorinit)
                    e = telem->defaultInit(loc);
                else
                    e = telem->defaultInitLiteral(loc);
            }
            (*elements)[fieldi] = e;
        }
    }

    if (elements)
    {
        for (size_t i = 0; i < elements->dim; i++)
        {
            Expression *e = (*elements)[i];
            if (e && e->op == TOKerror)
                return false;
        }
    }
    return !errors;
}