コード例 #1
0
ファイル: simp.c プロジェクト: Zhouxiaoqing/mc
static Node *slicebase(Simp *s, Node *n, Node *off)
{
    Node *t, *u, *v;
    Type *ty;
    int sz;

    t = rval(s, n, NULL);
    u = NULL;
    ty = tybase(exprtype(n));
    switch (ty->type) {
        case Typtr:     u = t; break;
        case Tyarray:   u = addr(s, t, base(exprtype(n))); break;
        case Tyslice:   u = load(addr(s, t, mktyptr(n->line, base(exprtype(n))))); break;
        default: die("Unslicable type %s", tystr(n->expr.type));
    }
    /* safe: all types we allow here have a sub[0] that we want to grab */
    if (off) {
      off = ptrsized(s, rval(s, off, NULL));
      sz = tysize(n->expr.type->sub[0]);
      v = mul(off, disp(n->line, sz));
      return add(u, v);
    } else {
      return u;
    }
}
コード例 #2
0
ファイル: msc.c プロジェクト: 1100110/dmd
targ_size_t size(tym_t ty)
{
    int sz = (tybasic(ty) == TYvoid) ? 1 : tysize(ty);
#ifdef DEBUG
    if (sz == -1)
        WRTYxx(ty);
#endif
    assert(sz!= -1);
    return sz;
}
コード例 #3
0
ファイル: simp.c プロジェクト: Zhouxiaoqing/mc
size_t size(Node *n)
{
    Type *t;

    if (n->type == Nexpr)
        t = n->expr.type;
    else
        t = n->decl.type;
    return tysize(t);
}
コード例 #4
0
ファイル: cgxmm.c プロジェクト: davispuh/dmd
bool xmmIsAligned(elem *e)
{
    if (tyvector(e->Ety) && e->Eoper == OPvar)
    {
        Symbol *s = e->EV.sp.Vsym;
        if (s->Salignsize() < 16 ||
            e->EV.sp.Voffset & (16 - 1) ||
            tysize(e->Ety) > STACKALIGN
           )
            return false;       // definitely not aligned
    }
    return true;        // assume aligned
}
コード例 #5
0
ファイル: simp.c プロジェクト: Zhouxiaoqing/mc
static Node *simpucon(Simp *s, Node *n, Node *dst)
{
    Node *tmp, *u, *tag, *elt, *sz;
    Node *r;
    Type *ty;
    Ucon *uc;
    size_t i;

    /* find the ucon we're constructing here */
    ty = tybase(n->expr.type);
    uc = NULL;
    for (i = 0; i < ty->nmemb; i++) {
        if (!strcmp(namestr(n->expr.args[0]), namestr(ty->udecls[i]->name))) {
            uc = ty->udecls[i];
            break;
        }
    }
    if (!uc)
        die("Couldn't find union constructor");

    if (dst)
        tmp = dst;
    else
        tmp = temp(s, n);

    /* Set the tag on the ucon */
    u = addr(s, tmp, mktype(n->line, Tyuint));
    tag = mkintlit(n->line, uc->id);
    tag->expr.type = mktype(n->line, Tyuint);
    append(s, set(deref(u), tag));


    /* fill the value, if needed */
    if (!uc->etype)
        return tmp;
    elt = rval(s, n->expr.args[1], NULL);
    u = addk(u, Wordsz);
    if (stacktype(uc->etype)) {
        elt = addr(s, elt, uc->etype);
        sz = disp(n->line, tysize(uc->etype));
        r = mkexpr(n->line, Oblit, u, elt, sz, NULL);
    } else {
        r = set(deref(u), elt);
    }
    append(s, r);
    return tmp;
}
コード例 #6
0
ファイル: cgxmm.c プロジェクト: davispuh/dmd
unsigned xmmload(tym_t tym, bool aligned)
{   unsigned op;
    if (tysize(tym) == 32)
        aligned = false;
    switch (tybasic(tym))
    {
        case TYuint:
        case TYint:
        case TYlong:
        case TYulong:   op = LODD;  break;       // MOVD
        case TYfloat:
        case TYcfloat:
        case TYifloat:  op = LODSS; break;       // MOVSS
        case TYllong:
        case TYullong:  op = LODQ;  break;       // MOVQ
        case TYdouble:
        case TYcdouble:
        case TYidouble: op = LODSD; break;       // MOVSD

        case TYfloat8:
        case TYfloat4:  op = aligned ? LODAPS : LODUPS; break;      // MOVAPS / MOVUPS
        case TYdouble4:
        case TYdouble2: op = aligned ? LODAPD : LODUPD; break;      // MOVAPD / MOVUPD
        case TYschar16:
        case TYuchar16:
        case TYshort8:
        case TYushort8:
        case TYlong4:
        case TYulong4:
        case TYllong2:
        case TYullong2:
        case TYschar32:
        case TYuchar32:
        case TYshort16:
        case TYushort16:
        case TYlong8:
        case TYulong8:
        case TYllong4:
        case TYullong4: op = aligned ? LODDQA : LODDQU; break;      // MOVDQA / MOVDQU

        default:
            printf("tym = x%x\n", tym);
            assert(0);
    }
    return op;
}
コード例 #7
0
ファイル: simp.c プロジェクト: Zhouxiaoqing/mc
static Node *intconvert(Simp *s, Node *from, Type *to, int issigned)
{
    Node *r;
    size_t fromsz, tosz;

    fromsz = size(from);
    tosz = tysize(to);
    r = rval(s, from, NULL);
    if (fromsz > tosz) {
        r = mkexpr(from->line, Otrunc, r, NULL);
    } else if (tosz > fromsz) {
        if (issigned)
            r = mkexpr(from->line, Oswiden, r, NULL);
        else
            r = mkexpr(from->line, Ozwiden, r, NULL);
    }
    r->expr.type = to;
    return r;
}
コード例 #8
0
ファイル: simp.c プロジェクト: Zhouxiaoqing/mc
static Node *idxaddr(Simp *s, Node *seq, Node *idx)
{
    Node *a, *t, *u, *v; /* temps */
    Node *r; /* result */
    Type *ty;
    size_t sz;

    a = rval(s, seq, NULL);
    ty = exprtype(seq)->sub[0];
    if (exprtype(seq)->type == Tyarray)
        t = addr(s, a, ty);
    else if (seq->expr.type->type == Tyslice)
        t = load(addr(s, a, mktyptr(seq->line, ty)));
    else
        die("Can't index type %s\n", tystr(seq->expr.type));
    assert(t->expr.type->type == Typtr);
    u = rval(s, idx, NULL);
    u = ptrsized(s, u);
    sz = tysize(ty);
    v = mul(u, disp(seq->line, sz));
    r = add(t, v);
    return r;
}
コード例 #9
0
ファイル: gsroa.c プロジェクト: GooberMan/dmd
static void sliceStructs_Replace(SymInfo *sia, elem *e)
{
    while (1)
    {
        switch (e->Eoper)
        {
            case OPvar:
            {
                Symbol *s = e->EV.sp.Vsym;
                SYMIDX si = s->Ssymnum;
                //printf("e: %d %d\n", si, sia[si].canSlice);
                //elem_print(e);
                if (si >= 0 && sia[si].canSlice)
                {
                    if (tysize(e->Ety) == 2 * REGSIZE)
                    {
                        // Rewrite e as (si0 OPpair si0+1)
                        elem *e1 = el_calloc();
                        el_copy(e1, e);
                        e1->Ety = sia[si].ty0;

                        elem *e2 = el_calloc();
                        el_copy(e2, e);
                        Symbol *s1 = globsym.tab[sia[si].si0 + 1]; // +1 for second slice
                        e2->Ety = sia[si].ty1;
                        e2->EV.sp.Vsym = s1;
                        e2->Eoffset = 0;

                        e->Eoper = OPpair;
                        e->E1 = e1;
                        e->E2 = e2;
                    }
                    else if (e->Eoffset == 0)  // the first slice of the symbol is the same as the original
                    {
                    }
                    else
                    {
                        Symbol *s1 = globsym.tab[sia[si].si0 + 1]; // +1 for second slice
                        e->EV.sp.Vsym = s1;
                        e->Eoffset = 0;
                        //printf("replaced with:\n");
                        //elem_print(e);
                    }
                }
                return;
            }

            default:
                if (OTunary(e->Eoper))
                {
                    e = e->E1;
                    break;
                }
                if (OTbinary(e->Eoper))
                {
                    sliceStructs_Replace(sia, e->E2);
                    e = e->E1;
                    break;
                }
                return;
        }
    }
}
コード例 #10
0
ファイル: simp.c プロジェクト: Zhouxiaoqing/mc
size_t tysize(Type *t)
{
    size_t sz;
    size_t i;

    sz = 0;
    if (!t)
        die("size of empty type => bailing.");
    switch (t->type) {
        case Tyvoid:
            die("void has no size");
            return 1;
        case Tybool: case Tyint8:
        case Tybyte: case Tyuint8:
            return 1;
        case Tyint16: case Tyuint16:
            return 2;
        case Tyint: case Tyint32:
        case Tyuint: case Tyuint32:
        case Tychar:  /* utf32 */
            return 4;

        case Typtr: case Tyfunc:
        case Tyvalist: /* ptr to first element of valist */
            return Ptrsz;

        case Tyint64: case Tylong:
        case Tyuint64: case Tyulong:
            return 8;

            /*end integer types*/
        case Tyfloat32:
            return 4;
        case Tyfloat64:
            return 8;

        case Tyslice:
            return 2*Ptrsz; /* len; ptr */
        case Tyname:
            return tysize(t->sub[0]);
        case Tyarray:
            t->asize = fold(t->asize, 1);
            assert(exprop(t->asize) == Olit);
            return t->asize->expr.args[0]->lit.intval * tysize(t->sub[0]);
        case Tytuple:
            for (i = 0; i < t->nsub; i++) {
                sz = tyalign(sz, tysize(t->sub[i]));
                sz += tysize(t->sub[i]);
            }
            for (i = 0; i < t->nsub; i++)
                sz = tyalign(sz, tysize(t->sub[i]));
            return sz;
            break;
        case Tystruct:
            for (i = 0; i < t->nmemb; i++) {
                sz = tyalign(sz, size(t->sdecls[i]));
                sz += size(t->sdecls[i]);
            }
            /* the whole struct size should match the biggest alignment */
            for (i = 0; i < t->nmemb; i++)
                sz = tyalign(sz, size(t->sdecls[i]));
            return sz;
            break;
        case Tyunion:
            sz = Wordsz;
            for (i = 0; i < t->nmemb; i++)
                if (t->udecls[i]->etype)
                    sz = max(sz, tysize(t->udecls[i]->etype) + Wordsz);
            return align(sz, Ptrsz);
            break;
        case Tybad: case Tyvar: case Typaram: case Tyunres: case Ntypes:
            die("Type %s does not have size; why did it get down to here?", tystr(t));
            break;
    }
    return -1;
}
コード例 #11
0
ファイル: type.c プロジェクト: michelf/dmd
targ_size_t type_size(type *t)
{   targ_size_t s;
    unsigned long u;
    tym_t tyb;

    type_debug(t);
    tyb = tybasic(t->Tty);
#ifdef DEBUG
    if (tyb >= TYMAX)
        /*type_print(t),*/
        dbg_printf("tyb = x%lx\n",tyb);
#endif
    assert(tyb < TYMAX);
    s = tysize[tyb];
    if (s == (targ_size_t) -1)
    {
        switch (tyb)
        {
            // in case program plays games with function pointers
            case TYffunc:
            case TYfpfunc:
#if TX86
            case TYnfunc:       /* in case program plays games with function pointers */
            case TYhfunc:
            case TYnpfunc:
            case TYnsfunc:
            case TYfsfunc:
            case TYf16func:
            case TYifunc:
            case TYjfunc:
#endif
#if SCPP
                if (ANSI)
                    synerr(EM_unknown_size,"function"); /* size of function is not known */
#endif
                s = 1;
                break;
            case TYarray:
                if (t->Tflags & TFsizeunknown)
                {
#if SCPP
                    synerr(EM_unknown_size,"array");    /* size of array is unknown     */
#endif
                    t->Tflags &= ~TFsizeunknown;
                }
                if (t->Tflags & TFvla)
                {
                    s = tysize[pointertype];
                    break;
                }
                s = type_size(t->Tnext);
                u = t->Tdim * (unsigned long) s;
#if TX86 && SCPP
                type_chksize(u);
#endif
                s = u;
                break;
            case TYstruct:
                t = t->Ttag->Stype;     /* find main instance           */
                                        /* (for const struct X)         */
                if (t->Tflags & TFsizeunknown)
                {
#if SCPP
                    template_instantiate_forward(t->Ttag);
                    if (t->Tflags & TFsizeunknown)
                        synerr(EM_unknown_size,t->Tty & TYstruct ? prettyident(t->Ttag) : "struct");
                    t->Tflags &= ~TFsizeunknown;
#endif
                }
                assert(t->Ttag);
                s = t->Ttag->Sstruct->Sstructsize;
                break;
#if SCPP
            case TYenum:
                if (t->Ttag->Senum->SEflags & SENforward)
                    synerr(EM_unknown_size, prettyident(t->Ttag));
                s = type_size(t->Tnext);
                break;
#endif
            case TYvoid:
#if SCPP && TARGET_WINDOS               // GNUC allows it, so we will, too
                synerr(EM_void_novalue);        // voids have no value
#endif
                s = 1;
                break;
#if SCPP
            case TYref:
            case TYmemptr:
            case TYvtshape:
                s = tysize(tym_conv(t));
                break;

            case TYident:
                synerr(EM_unknown_size, t->Tident);
                s = 1;
                break;
#endif
#if MARS
            case TYref:
                s = tysize(TYnptr);
                break;
#endif
            default:
#ifdef DEBUG
                WRTYxx(t->Tty);
#endif
                assert(0);
        }
    }
    return s;
}
コード例 #12
0
ファイル: glue.c プロジェクト: Rayerd/dmd
void FuncDeclaration::toObjFile(int multiobj)
{
    FuncDeclaration *func = this;
    ClassDeclaration *cd = func->parent->isClassDeclaration();
    int reverse;
    int has_arguments;

    //printf("FuncDeclaration::toObjFile(%p, %s.%s)\n", func, parent->toChars(), func->toChars());
    //if (type) printf("type = %s\n", func->type->toChars());
#if 0
    //printf("line = %d\n",func->getWhere() / LINEINC);
    EEcontext *ee = env->getEEcontext();
    if (ee->EEcompile == 2)
    {
        if (ee->EElinnum < (func->getWhere() / LINEINC) ||
            ee->EElinnum > (func->endwhere / LINEINC)
           )
            return;             // don't compile this function
        ee->EEfunc = func->toSymbol();
    }
#endif

    if (semanticRun >= PASSobj) // if toObjFile() already run
        return;

    // If errors occurred compiling it, such as bugzilla 6118
    if (type && type->ty == Tfunction && ((TypeFunction *)type)->next->ty == Terror)
        return;

    if (!func->fbody)
    {
        return;
    }
    if (func->isUnitTestDeclaration() && !global.params.useUnitTests)
        return;

    if (multiobj && !isStaticDtorDeclaration() && !isStaticCtorDeclaration())
    {   obj_append(this);
        return;
    }

    assert(semanticRun == PASSsemantic3done);
    semanticRun = PASSobj;

    if (global.params.verbose)
        printf("function  %s\n",func->toChars());

    Symbol *s = func->toSymbol();
    func_t *f = s->Sfunc;

#if TARGET_WINDOS
    /* This is done so that the 'this' pointer on the stack is the same
     * distance away from the function parameters, so that an overriding
     * function can call the nested fdensure or fdrequire of its overridden function
     * and the stack offsets are the same.
     */
    if (isVirtual() && (fensure || frequire))
        f->Fflags3 |= Ffakeeh;
#endif

#if TARGET_OSX
    s->Sclass = SCcomdat;
#else
    s->Sclass = SCglobal;
#endif
    for (Dsymbol *p = parent; p; p = p->parent)
    {
        if (p->isTemplateInstance())
        {
            s->Sclass = SCcomdat;
            break;
        }
    }

    /* Vector operations should be comdat's
     */
    if (isArrayOp)
        s->Sclass = SCcomdat;

    if (isNested())
    {
//      if (!(config.flags3 & CFG3pic))
//          s->Sclass = SCstatic;
        f->Fflags3 |= Fnested;
    }
    else
    {
        const char *libname = (global.params.symdebug)
                                ? global.params.debuglibname
                                : global.params.defaultlibname;

        // Pull in RTL startup code
        if (func->isMain())
        {   objextdef("_main");
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
            obj_ehsections();   // initialize exception handling sections
#endif
#if TARGET_WINDOS
            objextdef("__acrtused_con");
#endif
            obj_includelib(libname);
            s->Sclass = SCglobal;
        }
        else if (strcmp(s->Sident, "main") == 0 && linkage == LINKc)
        {
#if TARGET_WINDOS
            objextdef("__acrtused_con");        // bring in C startup code
            obj_includelib("snn.lib");          // bring in C runtime library
#endif
            s->Sclass = SCglobal;
        }
        else if (func->isWinMain())
        {
            objextdef("__acrtused");
            obj_includelib(libname);
            s->Sclass = SCglobal;
        }

        // Pull in RTL startup code
        else if (func->isDllMain())
        {
            objextdef("__acrtused_dll");
            obj_includelib(libname);
            s->Sclass = SCglobal;
        }
    }

    cstate.CSpsymtab = &f->Flocsym;

    // Find module m for this function
    Module *m = NULL;
    for (Dsymbol *p = parent; p; p = p->parent)
    {
        m = p->isModule();
        if (m)
            break;
    }

    IRState irs(m, func);
    Dsymbols deferToObj;                   // write these to OBJ file later
    irs.deferToObj = &deferToObj;

    TypeFunction *tf;
    enum RET retmethod;
    symbol *shidden = NULL;
    Symbol *sthis = NULL;
    tym_t tyf;

    tyf = tybasic(s->Stype->Tty);
    //printf("linkage = %d, tyf = x%x\n", linkage, tyf);
    reverse = tyrevfunc(s->Stype->Tty);

    assert(func->type->ty == Tfunction);
    tf = (TypeFunction *)(func->type);
    has_arguments = (tf->linkage == LINKd) && (tf->varargs == 1);
    retmethod = tf->retStyle();
    if (retmethod == RETstack)
    {
        // If function returns a struct, put a pointer to that
        // as the first argument
        ::type *thidden = tf->next->pointerTo()->toCtype();
        char hiddenparam[5+4+1];
        static int hiddenparami;    // how many we've generated so far

        sprintf(hiddenparam,"__HID%d",++hiddenparami);
        shidden = symbol_name(hiddenparam,SCparameter,thidden);
        shidden->Sflags |= SFLtrue | SFLfree;
#if DMDV1
        if (func->nrvo_can && func->nrvo_var && func->nrvo_var->nestedref)
#else
        if (func->nrvo_can && func->nrvo_var && func->nrvo_var->nestedrefs.dim)
#endif
            type_setcv(&shidden->Stype, shidden->Stype->Tty | mTYvolatile);
        irs.shidden = shidden;
        this->shidden = shidden;
    }

    if (vthis)
    {
        assert(!vthis->csym);
        sthis = vthis->toSymbol();
        irs.sthis = sthis;
        if (!(f->Fflags3 & Fnested))
            f->Fflags3 |= Fmember;
    }

    Symbol **params;
    unsigned pi;

    // Estimate number of parameters, pi
    pi = (v_arguments != NULL);
    if (parameters)
        pi += parameters->dim;
    // Allow extra 2 for sthis and shidden
    params = (Symbol **)alloca((pi + 2) * sizeof(Symbol *));

    // Get the actual number of parameters, pi, and fill in the params[]
    pi = 0;
    if (v_arguments)
    {
        params[pi] = v_arguments->toSymbol();
        pi += 1;
    }
    if (parameters)
    {
        for (size_t i = 0; i < parameters->dim; i++)
        {   VarDeclaration *v = parameters->tdata()[i];
            if (v->csym)
            {
                error("compiler error, parameter '%s', bugzilla 2962?", v->toChars());
                assert(0);
            }
            params[pi + i] = v->toSymbol();
        }
        pi += parameters->dim;
    }

    if (reverse)
    {   // Reverse params[] entries
        for (size_t i = 0; i < pi/2; i++)
        {
            Symbol *sptmp = params[i];
            params[i] = params[pi - 1 - i];
            params[pi - 1 - i] = sptmp;
        }
    }

    if (shidden)
    {
#if 0
        // shidden becomes last parameter
        params[pi] = shidden;
#else
        // shidden becomes first parameter
        memmove(params + 1, params, pi * sizeof(params[0]));
        params[0] = shidden;
#endif
        pi++;
    }


    if (sthis)
    {
#if 0
        // sthis becomes last parameter
        params[pi] = sthis;
#else
        // sthis becomes first parameter
        memmove(params + 1, params, pi * sizeof(params[0]));
        params[0] = sthis;
#endif
        pi++;
    }

    if ((global.params.isLinux || global.params.isOSX || global.params.isFreeBSD || global.params.isSolaris) &&
         linkage != LINKd && shidden && sthis)
    {
        /* swap shidden and sthis
         */
        Symbol *sp = params[0];
        params[0] = params[1];
        params[1] = sp;
    }

    for (size_t i = 0; i < pi; i++)
    {   Symbol *sp = params[i];
        sp->Sclass = SCparameter;
        sp->Sflags &= ~SFLspill;
        sp->Sfl = FLpara;
        symbol_add(sp);
    }

    // Determine register assignments
    if (pi)
    {
        if (global.params.is64bit)
        {
            // Order of assignment of pointer or integer parameters
            static const unsigned char argregs[6] = { DI,SI,DX,CX,R8,R9 };
            int r = 0;
            int xmmcnt = XMM0;

            for (size_t i = 0; i < pi; i++)
            {   Symbol *sp = params[i];
                tym_t ty = tybasic(sp->Stype->Tty);
                // BUG: doesn't work for structs
                if (r < sizeof(argregs)/sizeof(argregs[0]))
                {
                    if (type_jparam(sp->Stype))
                    {
                        sp->Sclass = SCfastpar;
                        sp->Spreg = argregs[r];
                        sp->Sfl = FLauto;
                        ++r;
                    }
                }
                if (xmmcnt <= XMM7)
                {
                    if (tyfloating(ty) && tysize(ty) <= 8)
                    {
                        sp->Sclass = SCfastpar;
                        sp->Spreg = xmmcnt;
                        sp->Sfl = FLauto;
                        ++xmmcnt;
                    }
                }
            }
        }
        else
        {
            // First parameter goes in register
            Symbol *sp = params[0];
            if ((tyf == TYjfunc || tyf == TYmfunc) &&
                type_jparam(sp->Stype))
            {   sp->Sclass = SCfastpar;
                sp->Spreg = (tyf == TYjfunc) ? AX : CX;
                sp->Sfl = FLauto;
                //printf("'%s' is SCfastpar\n",sp->Sident);
            }
        }
    }

    if (func->fbody)
    {   block *b;
        Blockx bx;
        Statement *sbody;

        localgot = NULL;

        sbody = func->fbody;
        memset(&bx,0,sizeof(bx));
        bx.startblock = block_calloc();
        bx.curblock = bx.startblock;
        bx.funcsym = s;
        bx.scope_index = -1;
        bx.classdec = cd;
        bx.member = func;
        bx.module = getModule();
        irs.blx = &bx;
#if DMDV2
        buildClosure(&irs);
#endif

#if 0
        if (func->isSynchronized())
        {
            if (cd)
            {   elem *esync;
                if (func->isStatic())
                {   // monitor is in ClassInfo
                    esync = el_ptr(cd->toSymbol());
                }
                else
                {   // 'this' is the monitor
                    esync = el_var(sthis);
                }

                if (func->isStatic() || sbody->usesEH() ||
                    !(config.flags2 & CFG2seh))
                {   // BUG: what if frequire or fensure uses EH?

                    sbody = new SynchronizedStatement(func->loc, esync, sbody);
                }
                else
                {
#if TARGET_WINDOS
                    if (config.flags2 & CFG2seh)
                    {
                        /* The "jmonitor" uses an optimized exception handling frame
                         * which is a little shorter than the more general EH frame.
                         * It isn't strictly necessary.
                         */
                        s->Sfunc->Fflags3 |= Fjmonitor;
                    }
#endif
                    el_free(esync);
                }
            }
            else
            {
                error("synchronized function %s must be a member of a class", func->toChars());
            }
        }
#elif TARGET_WINDOS
        if (func->isSynchronized() && cd && config.flags2 & CFG2seh &&
            !func->isStatic() && !sbody->usesEH())
        {
            /* The "jmonitor" hack uses an optimized exception handling frame
             * which is a little shorter than the more general EH frame.
             */
            s->Sfunc->Fflags3 |= Fjmonitor;
        }
#endif

        sbody->toIR(&irs);
        bx.curblock->BC = BCret;

        f->Fstartblock = bx.startblock;
//      einit = el_combine(einit,bx.init);

        if (isCtorDeclaration())
        {
            assert(sthis);
            for (b = f->Fstartblock; b; b = b->Bnext)
            {
                if (b->BC == BCret)
                {
                    b->BC = BCretexp;
                    b->Belem = el_combine(b->Belem, el_var(sthis));
                }
            }
        }
    }

    // If static constructor
#if DMDV2
    if (isSharedStaticCtorDeclaration())        // must come first because it derives from StaticCtorDeclaration
    {
        elem *e = el_una(OPucall, TYvoid, el_var(s));
        esharedctor = el_combine(esharedctor, e);
    }
    else
#endif
    if (isStaticCtorDeclaration())
    {
        elem *e = el_una(OPucall, TYvoid, el_var(s));
        ector = el_combine(ector, e);
    }

    // If static destructor
#if DMDV2
    if (isSharedStaticDtorDeclaration())        // must come first because it derives from StaticDtorDeclaration
    {
        elem *e;

#if STATICCTOR
        e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_FATEXIT]), el_ptr(s));
        esharedctor = el_combine(esharedctor, e);
        shareddtorcount++;
#else
        SharedStaticDtorDeclaration *f = isSharedStaticDtorDeclaration();
        assert(f);
        if (f->vgate)
        {   /* Increment destructor's vgate at construction time
             */
            esharedctorgates.push(f);
        }

        e = el_una(OPucall, TYvoid, el_var(s));
        eshareddtor = el_combine(e, eshareddtor);
#endif
    }
    else
#endif
    if (isStaticDtorDeclaration())
    {
        elem *e;

#if STATICCTOR
        e = el_bin(OPcall, TYvoid, el_var(rtlsym[RTLSYM_FATEXIT]), el_ptr(s));
        ector = el_combine(ector, e);
        dtorcount++;
#else
        StaticDtorDeclaration *f = isStaticDtorDeclaration();
        assert(f);
        if (f->vgate)
        {   /* Increment destructor's vgate at construction time
             */
            ectorgates.push(f);
        }

        e = el_una(OPucall, TYvoid, el_var(s));
        edtor = el_combine(e, edtor);
#endif
    }

    // If unit test
    if (isUnitTestDeclaration())
    {
        elem *e = el_una(OPucall, TYvoid, el_var(s));
        etest = el_combine(etest, e);
    }

    if (global.errors)
        return;

    writefunc(s);
    if (isExport())
        obj_export(s, Poffset);

    for (size_t i = 0; i < irs.deferToObj->dim; i++)
    {
        Dsymbol *s = irs.deferToObj->tdata()[i];
        s->toObjFile(0);
    }

#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
    // A hack to get a pointer to this function put in the .dtors segment
    if (ident && memcmp(ident->toChars(), "_STD", 4) == 0)
        obj_staticdtor(s);
#endif
#if DMDV2
    if (irs.startaddress)
    {
        printf("Setting start address\n");
        obj_startaddress(irs.startaddress);
    }
#endif
}
コード例 #13
0
ファイル: newman.c プロジェクト: marler8997/dmd
char *template_mangle(symbol *s,param_t *arglist)
{
    /*  mangling ::= '$' template_name { type | expr }
        type ::= "T" mangled type
        expr ::= integer | string | address | float | double | long_double
        integer ::= "I" dimension
        string ::= "S" string
        address ::= "R" zname
        float ::= "F" hex_digits
        double ::= "D" hex_digits
        long_double ::= "L" hex_digits
     */
    param_t *p;

    assert(s);
    symbol_debug(s);
    //assert(s->Sclass == SCtemplate);

    //printf("\ntemplate_mangle(s = '%s', arglist = %p)\n", s->Sident, arglist);
    //arglist->print_list();

    MangleInuse m;
    mangle.znamei = 0;
    mangle.argi = 0;
    mangle.np = mangle.buf;
    mangle.buf[BUFIDMAX + 1] = 0x55;

    if (NEWTEMPMANGLE)
        STR("?$");
    else
        CHAR('$');

    // BUG: this is for templates nested inside class scopes.
    // Need to check if it creates names that are properly unmanglable.
    cpp_zname(s->Sident);
    if (s->Sscope)
        cpp_scope(s->Sscope);

    for (p = arglist; p; p = p->Pnext)
    {
        if (p->Ptype)
        {   /* Argument is a type       */
            if (!NEWTEMPMANGLE)
                CHAR('T');
            cpp_argument_list(p->Ptype, 1);
        }
        else if (p->Psym)
        {
            CHAR('V');  // this is a 'class' name, but it should be a 'template' name
            cpp_ecsu_name(p->Psym);
        }
        else
        {   /* Argument is an expression        */
            elem *e = p->Pelem;
            tym_t ty = tybasic(e->ET->Tty);
            char *p;
            char a[2];
            int ni;
            char c;

        L2:
            switch (e->Eoper)
            {   case OPconst:
                    switch (ty)
                    {   case TYfloat:   ni = FLOATSIZE;  c = 'F'; goto L1;
                        case TYdouble_alias:
                        case TYdouble:  ni = DOUBLESIZE; c = 'D'; goto L1;
                        case TYldouble: ni = tysize(TYldouble); c = 'L'; goto L1;
                        L1:
                            if (NEWTEMPMANGLE)
                                CHAR('$');
                            CHAR(c);
                            p = (char *)&e->EV.Vdouble;
                            while (ni--)
                            {   char c;
#if __GNUC__
                                static char hex[16] =
                                    {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
#else
                                static char hex[16] = "0123456789ABCDEF";
#endif

                                c = *p++;
                                CHAR(hex[c & 15]);
                                CHAR(hex[(c >> 4) & 15]);
                            }
                            break;
                        default:
#ifdef DEBUG
                            if (!tyintegral(ty) && !tymptr(ty))
                                elem_print(e);
#endif
                            assert(tyintegral(ty) || tymptr(ty));
                            if (NEWTEMPMANGLE)
                                STR("$0");
                            else
                                CHAR('I');
                            cpp_dimension(el_tolongt(e));
                            break;
                    }
                    break;
                case OPstring:
                    if (NEWTEMPMANGLE)
                        STR("$S");
                    else
                        CHAR('S');
                    if (e->EV.ss.Voffset)
                        synerr(EM_const_init);          // constant initializer expected
                    cpp_string(e->EV.ss.Vstring,e->EV.ss.Vstrlen);
                    break;
                case OPrelconst:
                    if (e->EV.sp.Voffset)
                        synerr(EM_const_init);          // constant initializer expected
                    s = e->EV.sp.Vsym;
                    if (NEWTEMPMANGLE)
                    {   STR("$1");
                        cpp_decorated_name(s);
                    }
                    else
                    {   CHAR('R');
                        cpp_zname(s->Sident);
                    }
                    break;
                case OPvar:
                    if (e->EV.sp.Vsym->Sflags & SFLvalue &&
                        tybasic(e->ET->Tty) != TYstruct)
                    {
                        e = e->EV.sp.Vsym->Svalue;
                        goto L2;
                    }
                    else if (e->EV.sp.Vsym->Sclass == SCconst /*&&
                             pstate.STintemplate*/)
                    {
                        CHAR('V');              // pretend to be a class name
                        cpp_zname(e->EV.sp.Vsym->Sident);
                        break;
                    }
                default:
#if SCPP
#ifdef DEBUG
                    if (!errcnt)
                        elem_print(e);
#endif
                    synerr(EM_const_init);              // constant initializer expected
                    assert(errcnt);
#endif
                    break;
            }
        }
    }
    *mangle.np = 0;
    //printf("template_mangle() = '%s'\n", mangle.buf);
    assert(strlen(mangle.buf) <= BUFIDMAX);
    assert(mangle.buf[BUFIDMAX + 1] == 0x55);
    return mangle.buf;
}
コード例 #14
0
ファイル: cgxmm.c プロジェクト: davispuh/dmd
code *orthxmm(elem *e, regm_t *pretregs)
{
    //printf("orthxmm(e = %p, *pretregs = %s)\n", e, regm_str(*pretregs));
    elem *e1 = e->E1;
    elem *e2 = e->E2;

    // float + ifloat is not actually addition
    if ((e->Eoper == OPadd || e->Eoper == OPmin) &&
        ((tyreal(e1->Ety) && tyimaginary(e2->Ety)) ||
         (tyreal(e2->Ety) && tyimaginary(e1->Ety))))
    {
        regm_t retregs = *pretregs & XMMREGS;
        if (!retregs)
            retregs = XMMREGS;

        unsigned reg;
        regm_t rretregs;
        unsigned rreg;
        if (tyreal(e1->Ety))
        {
            reg = findreg(retregs);
            rreg = findreg(retregs & ~mask[reg]);
            retregs = mask[reg];
            rretregs = mask[rreg];
        }
        else
        {
            // Pick the second register, not the first
            rreg = findreg(retregs);
            rretregs = mask[rreg];
            reg = findreg(retregs & ~rretregs);
            retregs = mask[reg];
        }
        assert(retregs && rretregs);

        CodeBuilder cdb;
        cdb.append(codelem(e1,&retregs,FALSE)); // eval left leaf
        cdb.append(scodelem(e2, &rretregs, retregs, TRUE));  // eval right leaf

        retregs |= rretregs;
        if (e->Eoper == OPmin)
        {
            unsigned nretregs = XMMREGS & ~retregs;
            unsigned sreg; // hold sign bit
            unsigned sz = tysize(e1->Ety);
            cdb.append(allocreg(&nretregs,&sreg,e2->Ety));
            targ_size_t signbit = 0x80000000;
            if (sz == 8)
                signbit = 0x8000000000000000LL;
            cdb.append(movxmmconst(sreg, sz, signbit, 0));
            cdb.append(getregs(nretregs));
            unsigned xop = (sz == 8) ? XORPD : XORPS;       // XORPD/S rreg,sreg
            cdb.gen2(xop,modregxrmx(3,rreg-XMM0,sreg-XMM0));
        }
        if (retregs != *pretregs)
            cdb.append(fixresult(e,retregs,pretregs));
        return cdb.finish();
    }

    regm_t retregs = *pretregs & XMMREGS;
    if (!retregs)
        retregs = XMMREGS;
    CodeBuilder cdb;
    cdb.append(codelem(e1,&retregs,FALSE)); // eval left leaf
    unsigned reg = findreg(retregs);
    regm_t rretregs = XMMREGS & ~retregs;
    cdb.append(scodelem(e2, &rretregs, retregs, TRUE));  // eval right leaf

    unsigned rreg = findreg(rretregs);
    unsigned op = xmmoperator(e1->Ety, e->Eoper);

    /* We should take advantage of mem addressing modes for OP XMM,MEM
     * but we do not at the moment.
     */
    if (OTrel(e->Eoper))
    {
        retregs = mPSW;
        cdb.gen2(op,modregxrmx(3,rreg-XMM0,reg-XMM0));
        checkSetVex(cdb.last(), e1->Ety);
        return cdb.finish();
    }
    else
        cdb.append(getregs(retregs));

    cdb.gen2(op,modregxrmx(3,reg-XMM0,rreg-XMM0));
    checkSetVex(cdb.last(), e1->Ety);
    if (retregs != *pretregs)
        cdb.append(fixresult(e,retregs,pretregs));

    return cdb.finish();
}
コード例 #15
0
ファイル: cgxmm.c プロジェクト: davispuh/dmd
code *xmmeq(elem *e, unsigned op, elem *e1, elem *e2,regm_t *pretregs)
{
    tym_t tymll;
    unsigned reg;
    int i;
    code cs;
    elem *e11;
    bool regvar;                  /* TRUE means evaluate into register variable */
    regm_t varregm;
    unsigned varreg;
    targ_int postinc;

    //printf("xmmeq(e1 = %p, e2 = %p, *pretregs = %s)\n", e1, e2, regm_str(*pretregs));
    int e2oper = e2->Eoper;
    tym_t tyml = tybasic(e1->Ety);              /* type of lvalue               */
    regm_t retregs = *pretregs;

    if (!(retregs & XMMREGS))
        retregs = XMMREGS;              // pick any XMM reg

    bool aligned = xmmIsAligned(e1);
    cs.Iop = (op == OPeq) ? xmmstore(tyml, aligned) : op;
    regvar = FALSE;
    varregm = 0;
    if (config.flags4 & CFG4optimized)
    {
        // Be careful of cases like (x = x+x+x). We cannot evaluate in
        // x if x is in a register.
        if (isregvar(e1,&varregm,&varreg) &&    // if lvalue is register variable
            doinreg(e1->EV.sp.Vsym,e2) &&       // and we can compute directly into it
            varregm & XMMREGS
           )
        {   regvar = TRUE;
            retregs = varregm;
            reg = varreg;       /* evaluate directly in target register */
        }
    }
    if (*pretregs & mPSW && !EOP(e1))     // if evaluating e1 couldn't change flags
    {   // Be careful that this lines up with jmpopcode()
        retregs |= mPSW;
        *pretregs &= ~mPSW;
    }
    CodeBuilder cdb;
    cdb.append(scodelem(e2,&retregs,0,TRUE));    // get rvalue

    // Look for special case of (*p++ = ...), where p is a register variable
    if (e1->Eoper == OPind &&
        ((e11 = e1->E1)->Eoper == OPpostinc || e11->Eoper == OPpostdec) &&
        e11->E1->Eoper == OPvar &&
        e11->E1->EV.sp.Vsym->Sfl == FLreg
       )
    {
        postinc = e11->E2->EV.Vint;
        if (e11->Eoper == OPpostdec)
            postinc = -postinc;
        cdb.append(getlvalue(&cs,e11,RMstore | retregs));
        freenode(e11->E2);
    }
    else
    {   postinc = 0;
        cdb.append(getlvalue(&cs,e1,RMstore | retregs));       // get lvalue (cl == CNIL if regvar)
    }

    cdb.append(getregs_imm(regvar ? varregm : 0));

    reg = findreg(retregs & XMMREGS);
    cs.Irm |= modregrm(0,(reg - XMM0) & 7,0);
    if ((reg - XMM0) & 8)
        cs.Irex |= REX_R;

    // Do not generate mov from register onto itself
    if (!(regvar && reg == XMM0 + ((cs.Irm & 7) | (cs.Irex & REX_B ? 8 : 0))))
    {
        cdb.gen(&cs);         // MOV EA+offset,reg
        if (op == OPeq)
            checkSetVex(cdb.last(), tyml);
    }

    if (e1->Ecount ||                     // if lvalue is a CSE or
        regvar)                           // rvalue can't be a CSE
    {
        cdb.append(getregs_imm(retregs));        // necessary if both lvalue and
                                        //  rvalue are CSEs (since a reg
                                        //  can hold only one e at a time)
        cssave(e1,retregs,EOP(e1));     // if lvalue is a CSE
    }

    cdb.append(fixresult(e,retregs,pretregs));
Lp:
    if (postinc)
    {
        int reg = findreg(idxregm(&cs));
        if (*pretregs & mPSW)
        {   // Use LEA to avoid touching the flags
            unsigned rm = cs.Irm & 7;
            if (cs.Irex & REX_B)
                rm |= 8;
            cdb.genc1(0x8D,buildModregrm(2,reg,rm),FLconst,postinc);
            if (tysize(e11->E1->Ety) == 8)
                code_orrex(cdb.last(), REX_W);
        }
        else if (I64)
        {
            cdb.genc2(0x81,modregrmx(3,0,reg),postinc);
            if (tysize(e11->E1->Ety) == 8)
                code_orrex(cdb.last(), REX_W);
        }
        else
        {
            if (postinc == 1)
                cdb.gen1(0x40 + reg);         // INC reg
            else if (postinc == -(targ_int)1)
                cdb.gen1(0x48 + reg);         // DEC reg
            else
            {
                cdb.genc2(0x81,modregrm(3,0,reg),postinc);
            }
        }
    }
    freenode(e1);
    return cdb.finish();
}
コード例 #16
0
ファイル: cgxmm.c プロジェクト: davispuh/dmd
void checkSetVex(code *c, tym_t ty)
{
    if (config.avx || tysize(ty) == 32)
    {
        unsigned vreg = (c->Irm >> 3) & 7;
        if (c->Irex & REX_R)
            vreg |= 8;
        int VEX_L = 0;

        // TODO: This is too simplistic, depending on the instruction, vex.vvvv
        // encodes NDS, NDD, DDS, or no operand (NOO). The code below assumes
        // NDS (non-destructive source), except for the incomplete list of 2
        // operand instructions (NOO) handled by the switch.
        switch (c->Iop)
        {
            case LODSS:
            case LODSD:
            case STOSS:
            case STOSD:
                if ((c->Irm & 0xC0) == 0xC0)
                    break;
            case LODAPS:
            case LODUPS:
            case LODAPD:
            case LODUPD:
            case LODDQA:
            case LODDQU:
            case LODD:
            case LODQ:
            case STOAPS:
            case STOUPS:
            case STOAPD:
            case STOUPD:
            case STODQA:
            case STODQU:
            case STOD:
            case STOQ:
            case COMISS:
            case COMISD:
            case UCOMISS:
            case UCOMISD:
            case MOVDDUP:
            case MOVSHDUP:
            case MOVSLDUP:
            case VBROADCASTSS:
            case PSHUFD:
            case PSHUFHW:
            case PSHUFLW:
                vreg = 0;       // for 2 operand vex instructions
                break;

            case VBROADCASTSD:
            case VBROADCASTF128:
                VEX_L = 1;
                vreg = 0;       // for 2 operand vex instructions
                break;
        }

        unsigned op = 0xC4000000 | (c->Iop & 0xFF);
        switch (c->Iop & 0xFFFFFF00)
        {
            #define MM_PP(mm, pp) ((mm << 16) | (pp << 8))
            case 0x00000F00: op |= MM_PP(1,0); break;
            case 0x00660F00: op |= MM_PP(1,1); break;
            case 0x00F30F00: op |= MM_PP(1,2); break;
            case 0x00F20F00: op |= MM_PP(1,3); break;
            case 0x660F3800: op |= MM_PP(2,1); break;
            case 0x660F3A00: op |= MM_PP(3,1); break;
            default:
                printf("Iop = %x\n", c->Iop);
                assert(0);
            #undef MM_PP
        }
        c->Iop = op;
        c->Ivex.pfx = 0xC4;
        c->Ivex.r = !(c->Irex & REX_R);
        c->Ivex.x = !(c->Irex & REX_X);
        c->Ivex.b = !(c->Irex & REX_B);
        c->Ivex.w = (c->Irex & REX_W) != 0;
        c->Ivex.l = (tysize(ty) == 32) | VEX_L;

        c->Ivex.vvvv = ~vreg;

        c->Iflags |= CFvex;
        checkSetVex3(c);
    }
コード例 #17
0
ファイル: cgxmm.c プロジェクト: davispuh/dmd
/***************
 * Generate code for OPvecfill (broadcast).
 * OPvecfill takes the single value in e1 and
 * fills the vector type with it.
 */
code *cdvecfill(elem *e, regm_t *pretregs)
{
    //printf("cdvecfill(e = %p, *pretregs = %s)\n",e,regm_str(*pretregs));

    regm_t retregs = *pretregs & XMMREGS;
    if (!retregs)
        retregs = XMMREGS;

    CodeBuilder cdb;
    code *c;
    code cs;

    elem *e1 = e->E1;
#if 0
    if ((e1->Eoper == OPind && !e1->Ecount) || e1->Eoper == OPvar)
    {
        cr = getlvalue(&cs, e1, RMload | retregs);     // get addressing mode
    }
    else
    {
        unsigned rretregs = XMMREGS & ~retregs;
        cr = scodelem(op2, &rretregs, retregs, TRUE);
        unsigned rreg = findreg(rretregs) - XMM0;
        cs.Irm = modregrm(3,0,rreg & 7);
        cs.Iflags = 0;
        cs.Irex = 0;
        if (rreg & 8)
            cs.Irex |= REX_B;
    }
#endif

    unsigned reg;
    unsigned rreg;
    unsigned varreg;
    regm_t varregm;
    tym_t ty = tybasic(e->Ety);
    switch (ty)
    {
        case TYfloat4:
        case TYfloat8:
            if (config.avx &&
                ((e1->Eoper == OPind && !e1->Ecount) || e1->Eoper == OPvar && !isregvar(e1,&varregm,&varreg)) ||
                tysize(ty) == 32 && !isregvar(e1,&varregm,&varreg)
               )
            {
              Lint:
                if (e1->Eoper == OPvar)
                    e1->EV.sp.Vsym->Sflags &= ~GTregcand;

                // VBROADCASTSS XMM,MEM
                cdb.append(getlvalue(&cs, e1, 0));         // get addressing mode
                assert((cs.Irm & 0xC0) != 0xC0);           // AVX1 doesn't have register source operands
                cdb.append(allocreg(&retregs,&reg,ty));
                cs.Iop = VBROADCASTSS;
                cs.Irex &= ~REX_W;
                code_newreg(&cs,reg - XMM0);
                checkSetVex(&cs,ty);
                cdb.gen(&cs);
            }
            else
            {
                // SHUFPS XMM0,XMM0,0    0F C6 /r ib
                c = codelem(e1,&retregs,FALSE); // eval left leaf
                cdb.append(c);
                reg = findreg(retregs) - XMM0;
                cdb.append(getregs(retregs));
                cs.Iop = SHUFPS;
                cs.Irm = modregxrmx(3,reg,reg);
                cs.Iflags = 0;
                cs.IFL2 = FLconst;
                cs.IEV2.Vsize_t = 0;
                if (config.avx >= 2 || tysize(ty) == 32)
                {
                    // VBROADCASTSS XMM,XMM
                    cs.Iop = VBROADCASTSS;
                    checkSetVex(&cs, ty);
                }
                cdb.gen(&cs);
            }
            break;

        case TYdouble2:
        case TYdouble4:
            if (config.avx &&
                ((e1->Eoper == OPind && !e1->Ecount) || e1->Eoper == OPvar && !isregvar(e1,&varregm,&varreg)) ||
                tysize(ty) == 32 && !isregvar(e1,&varregm,&varreg)
               )
            {
                if (e1->Eoper == OPvar)
                    e1->EV.sp.Vsym->Sflags &= ~GTregcand;

                // VBROADCASTSD XMM,MEM
                cdb.append(getlvalue(&cs, e1, 0));         // get addressing mode
                assert((cs.Irm & 0xC0) != 0xC0);           // AVX1 doesn't have register source operands
                cdb.append(allocreg(&retregs,&reg,ty));
                cs.Iop = VBROADCASTSD;
                cs.Irex &= ~REX_W;
                code_newreg(&cs,reg - XMM0);
                checkSetVex(&cs,ty);
                cdb.gen(&cs);
            }
            else
            {
                // UNPCKLPD XMM0,XMM0     66 0F 14 /r
                c = codelem(e1,&retregs,FALSE); // eval left leaf
                cdb.append(c);
                reg = findreg(retregs) - XMM0;
                cdb.append(getregs(retregs));
                cs.Iop = UNPCKLPD;
                cs.Irm = modregxrmx(3,reg,reg);
                cs.Iflags = 0;
                if (config.avx >= 2 || tysize(ty) == 32)
                {
                    // VBROADCASTSD XMM,XMM
                    cs.Iop = VBROADCASTSD;
                    checkSetVex(&cs, ty);
                }
                cdb.gen(&cs);
            }
            break;

        case TYschar16:
        case TYuchar16:
        case TYschar32:
        case TYuchar32:
        {
            /* MOVD      XMM0,r
             * PUNPCKLBW XMM0,XMM0
             * PUNPCKLWD XMM0,XMM0
             * PSHUFD    XMM0,XMM0,0
             */
            regm_t regm = ALLREGS;
            c = codelem(e1,&regm,FALSE); // eval left leaf
            cdb.append(c);
            unsigned r = findreg(regm);

            c = allocreg(&retregs,&reg, e->Ety);
            cdb.append(c);
            reg -= XMM0;
            cdb.gen2(LODD,modregxrmx(3,reg,r));     // MOVD reg,r
            checkSetVex(cdb.last(),TYschar16);

            cs.Iop = PUNPCKLBW;
            cs.Irm = modregxrmx(3,reg,reg);
            cs.Iflags = 0;
            cdb.gen(&cs);
            cs.Iop = PUNPCKLWD;
            cdb.gen(&cs);

            cs.Iop = PSHUFD;
            cs.IFL2 = FLconst;
            cs.IEV2.Vsize_t = 0;
            checkSetVex(&cs,TYschar16);
            cdb.gen(&cs);
            if (tysize(ty) == 32)
            {
                // VINSERTF128 YMM0,YMM0,XMM0,1
                cs.Iop = VINSERTF128;
                cs.Irm = modregxrmx(3,reg,reg);
                cs.Iflags = 0;
                cs.IFL2 = FLconst;
                cs.IEV2.Vsize_t = 1;
                checkSetVex(&cs,ty);
                cdb.gen(&cs);
            }
            break;
        }

        case TYshort8:
        case TYushort8:
        case TYshort16:
        case TYushort16:
        {
            regm_t regm = ALLREGS;
            c = codelem(e1,&regm,FALSE); // eval left leaf
            cdb.append(c);
            unsigned r = findreg(regm);

            if (config.avx || tysize(ty) == 32)
            {
                /*
                 * VPXOR XMM0,XMM0,XMM0
                 * VPINSRW XMM0,XMM0,r,0
                 * VPINSRW XMM0,XMM0,r,1
                 * VPINSRW XMM0,XMM0,r,2
                 * VPINSRW XMM0,XMM0,r,3
                 */
                cdb.append(allocreg(&retregs,&reg, ty));
                cdb.gen2(PXOR,modregxrmx(3,reg-XMM0,reg-XMM0));
                checkSetVex(cdb.last(), TYshort8);
                for (int i = 0; i < tysize(ty) / 4; ++i)
                {
                    cdb.genc2(PINSRW,modregxrmx(3,reg-XMM0,r),i);
                    checkSetVex(cdb.last(), TYshort8);
                }
                if (tysize(ty) == 32)
                {
                    // VINSERTF128 YMM0,YMM0,XMM0,1
                    cs.Iop = VINSERTF128;
                    cs.Irm = modregxrmx(3,reg-XMM0,reg-XMM0);
                    cs.Iflags = 0;
                    cs.IFL2 = FLconst;
                    cs.IEV2.Vsize_t = 1;
                    checkSetVex(&cs,ty);
                    cdb.gen(&cs);
                }
                else
                {
                    // VPSHUFD XMM0,XMM0,0
                    cs.Iop = PSHUFD;
                    cs.Irm = modregxrmx(3,reg-XMM0,reg-XMM0);
                    cs.Iflags = 0;
                    cs.IFL2 = FLconst;
                    cs.IEV2.Vsize_t = 0;
                    checkSetVex(&cs,ty);
                    cdb.gen(&cs);
                }
            }
            else
            {
                /* MOVD      XMM0,r
                 * PUNPCKLWD XMM0,XMM0
                 * PSHUFD    XMM0,XMM0,0
                 */
                c = allocreg(&retregs,&reg, e->Ety);
                cdb.append(c);
                reg -= XMM0;
                cdb.gen2(LODD,modregxrmx(3,reg,r));     // MOVD reg,r
                checkSetVex(cdb.last(),e->Ety);

                cs.Iop = PUNPCKLWD;
                cs.Irm = modregxrmx(3,reg,reg);
                cs.Iflags = 0;
                cdb.gen(&cs);

                cs.Iop = PSHUFD;
                cs.IFL2 = FLconst;
                cs.IEV2.Vsize_t = 0;
                cdb.gen(&cs);
            }
            break;
        }

        case TYlong8:
        case TYulong8:
        case TYlong4:
        case TYulong4:
        {
            if (config.avx &&
                ((e1->Eoper == OPind && !e1->Ecount) || e1->Eoper == OPvar && !isregvar(e1,&varregm,&varreg)) ||
                tysize(ty) == 32 && !isregvar(e1,&varregm,&varreg))
            {
                goto Lint;
            }
            /* MOVD      XMM1,r
             * PSHUFD    XMM0,XMM1,0
             */
            regm_t regm = ALLREGS;
            c = codelem(e1,&regm,FALSE); // eval left leaf
            cdb.append(c);
            unsigned r = findreg(regm);

            c = allocreg(&retregs,&reg, e->Ety);
            cdb.append(c);
            reg -= XMM0;
            cdb.gen2(LODD,modregxrmx(3,reg,r));     // MOVD reg,r

            cs.Iop = PSHUFD;
            cs.Irm = modregxrmx(3,reg,reg);
            cs.Iflags = 0;
            cs.IFL2 = FLconst;
            cs.IEV2.Vsize_t = 0;
            if (config.avx >= 2 || tysize(ty) == 32)
            {
                // VBROADCASTSS XMM,XMM
                cs.Iop = VBROADCASTSS;
                checkSetVex(&cs, ty);
            }
            cdb.gen(&cs);
            break;
        }

        case TYllong2:
        case TYullong2:
        case TYllong4:
        case TYullong4:
            if (config.avx || tysize(ty) >= 32)
            {
                if (e1->Eoper == OPvar)
                    e1->EV.sp.Vsym->Sflags &= ~GTregcand;

                // VMOVDDUP XMM,MEM
                cdb.append(getlvalue(&cs, e1, 0));         // get addressing mode
                if ((cs.Irm & 0xC0) == 0xC0)
                {
                    unsigned sreg = ((cs.Irm & 7) | (cs.Irex & REX_B ? 8 : 0));
                    regm_t sregm = XMMREGS;
                    cdb.append(fixresult(e1, mask[sreg], &sregm));
                    unsigned rmreg = findreg(sregm);
                    cs.Irm = (cs.Irm & ~7) | ((rmreg - XMM0) & 7);
                    if ((rmreg - XMM0) & 8)
                        cs.Irex |= REX_B;
                    else
                        cs.Irex &= ~REX_B;
                }
                cdb.append(allocreg(&retregs,&reg,ty));
                if (config.avx >= 2 ||  tysize(ty) >= 32)
                {
                    cs.Iop = VBROADCASTSD;
                    cs.Irex &= ~REX_W;
                }
                else
                    cs.Iop = MOVDDUP;
                code_newreg(&cs,reg - XMM0);
                checkSetVex(&cs,ty);
                cdb.gen(&cs);
            }
            else
            {
                /* MOVQ XMM0,mem128
                 * PUNPCKLQDQ XMM0,XMM0
                 */
                c = codelem(e1,&retregs,FALSE); // eval left leaf
                cdb.append(c);
                unsigned reg = findreg(retregs);
                reg -= XMM0;
                //cdb.gen2(LODD,modregxrmx(3,reg,r));     // MOVQ reg,r

                cs.Iop = PUNPCKLQDQ;
                cs.Irm = modregxrmx(3,reg,reg);
                cs.Iflags = 0;
                cdb.gen(&cs);
            }
            break;

        default:
            assert(0);
    }

    c = fixresult(e,retregs,pretregs);
    cdb.append(c);
    return cdb.finish();
}
コード例 #18
0
ファイル: gsroa.c プロジェクト: GooberMan/dmd
static void sliceStructs_Gather(SymInfo *sia, elem *e)
{
    while (1)
    {
        switch (e->Eoper)
        {
            case OPvar:
            {
                SYMIDX si = e->EV.sp.Vsym->Ssymnum;
                if (si >= 0 && sia[si].canSlice)
                {
                    assert(si < globsym.top);
                    unsigned sz = tysize(e->Ety);
                    if (sz == 2 * REGSIZE && !tyfv(e->Ety))
                    {
                        // Rewritten as OPpair later
                    }
                    else if (sz == REGSIZE &&
                        (e->Eoffset == 0 || e->Eoffset == REGSIZE))
                    {
                        if (!sia[si].accessSlice)
                        {
                            sia[si].ty0 = TYnptr;
                            sia[si].ty1 = TYnptr;
                        }
                        sia[si].accessSlice = true;
                        if (e->Eoffset == 0)
                            sia[si].ty0 = tybasic(e->Ety);
                        else
                            sia[si].ty1 = tybasic(e->Ety);
                    }
                    else
                    {
                        sia[si].canSlice = false;
                    }
                }
                return;
            }

            default:
                if (OTassign(e->Eoper))
                {
                    if (OTbinary(e->Eoper))
                        sliceStructs_Gather(sia, e->E2);

                    // Assignment to a whole var will disallow SROA
                    if (e->E1->Eoper == OPvar)
                    {
                        elem *e1 = e->E1;
                        SYMIDX si = e1->EV.sp.Vsym->Ssymnum;
                        if (si >= 0 && sia[si].canSlice)
                        {
                            assert(si < globsym.top);
                            if (tysize(e1->Ety) != REGSIZE ||
                                (e1->Eoffset != 0 && e1->Eoffset != REGSIZE))
                            {
                                sia[si].canSlice = false;
                            }
                        }
                        return;
                    }
                    e = e->E1;
                    break;
                }
                if (OTunary(e->Eoper))
                {
                    e = e->E1;
                    break;
                }
                if (OTbinary(e->Eoper))
                {
                    sliceStructs_Gather(sia, e->E2);
                    e = e->E1;
                    break;
                }
                return;
        }
    }
}
コード例 #19
0
ファイル: gsroa.c プロジェクト: AndrejMitrovic/dmd
static void sliceStructs_Gather(SymInfo *sia, elem *e)
{
    while (1)
    {
        switch (e->Eoper)
        {
            case OPvar:
            {
                SYMIDX si = e->EV.sp.Vsym->Ssymnum;
                if (si >= 0 && sia[si].canSlice)
                {
                    assert(si < globsym.top);
                    unsigned sz = tysize(e->Ety);
                    if (sz == 2 * REGSIZE)
                    {
                        // Rewrite as OPpair later
                        sia[si].usePair = true;

                        /* OPpair cannot handle XMM registers, cdpair() and fixresult()
                         */
                        if (tyfloating(sia[si].ty0) || tyfloating(sia[si].ty1))
                            sia[si].canSlice = false;
                    }
                    else if (sz == REGSIZE &&
                        (e->Eoffset == 0 || e->Eoffset == REGSIZE))
                    {
                        if (!sia[si].accessSlice)
                        {
                            sia[si].ty0 = TYnptr;
                            sia[si].ty1 = TYnptr;
                        }
                        sia[si].accessSlice = true;
                        if (e->Eoffset == 0)
                            sia[si].ty0 = tybasic(e->Ety);
                        else
                            sia[si].ty1 = tybasic(e->Ety);
                        // Cannot slice float fields if the symbol is also accessed using OPpair (see above)
                        if (sia[si].usePair && (tyfloating(sia[si].ty0) || tyfloating(sia[si].ty1)))
                            sia[si].canSlice = false;
                    }
                    else
                    {
                        sia[si].canSlice = false;
                    }
                }
                return;
            }

            default:
                if (OTassign(e->Eoper))
                {
                    if (OTbinary(e->Eoper))
                        sliceStructs_Gather(sia, e->E2);

                    // Assignment to a whole var will disallow SROA
                    if (e->E1->Eoper == OPvar)
                    {
                        elem *e1 = e->E1;
                        SYMIDX si = e1->EV.sp.Vsym->Ssymnum;
                        if (si >= 0 && sia[si].canSlice)
                        {
                            assert(si < globsym.top);
                            if (tysize(e1->Ety) != REGSIZE ||
                                (e1->Eoffset != 0 && e1->Eoffset != REGSIZE))
                            {
                                sia[si].canSlice = false;
                            }
                        }
                        return;
                    }
                    e = e->E1;
                    break;
                }
                if (OTunary(e->Eoper))
                {
                    e = e->E1;
                    break;
                }
                if (OTbinary(e->Eoper))
                {
                    sliceStructs_Gather(sia, e->E2);
                    e = e->E1;
                    break;
                }
                return;
        }
    }
}