Exemplo n.º 1
0
Arquivo: cgxmm.c Projeto: dsagal/dmd
code *xmmopass(elem *e,regm_t *pretregs)
{   elem *e1 = e->E1;
    elem *e2 = e->E2;
    tym_t ty1 = tybasic(e1->Ety);
    unsigned sz1 = tysize[ty1];
    regm_t rretregs = XMMREGS & ~*pretregs;
    if (!rretregs)
        rretregs = XMMREGS;

    code *cr = codelem(e2,&rretregs,FALSE); // eval right leaf
    unsigned rreg = findreg(rretregs);

    code cs;
    code *cl,*cg;

    regm_t retregs;
    unsigned reg;
    bool regvar = FALSE;
    if (config.flags4 & CFG4optimized)
    {
        // Be careful of cases like (x = x+x+x). We cannot evaluate in
        // x if x is in a register.
        unsigned varreg;
        regm_t varregm;
        if (isregvar(e1,&varregm,&varreg) &&    // if lvalue is register variable
            doinreg(e1->EV.sp.Vsym,e2)          // and we can compute directly into it
           )
        {   regvar = TRUE;
            retregs = varregm;
            reg = varreg;                       // evaluate directly in target register
            cl = NULL;
            cg = getregs(retregs);              // destroy these regs
        }
    }

    if (!regvar)
    {
        cl = getlvalue(&cs,e1,rretregs);        // get EA
        retregs = *pretregs & XMMREGS & ~rretregs;
        if (!retregs)
            retregs = XMMREGS & ~rretregs;
        cg = allocreg(&retregs,&reg,ty1);
        cs.Iop = xmmload(ty1);                  // MOVSD xmm,xmm_m64
        code_newreg(&cs,reg - XMM0);
        cg = gen(cg,&cs);
    }

    unsigned op = xmmoperator(e1->Ety, e->Eoper);
    code *co = gen2(CNIL,op,modregxrmx(3,reg-XMM0,rreg-XMM0));

    if (!regvar)
    {
        cs.Iop = xmmstore(ty1);           // reverse operand order of MOVS[SD]
        gen(co,&cs);
    }

    if (e1->Ecount ||                     // if lvalue is a CSE or
        regvar)                           // rvalue can't be a CSE
    {
        cl = cat(cl,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
    }

    co = cat(co,fixresult(e,retregs,pretregs));
    freenode(e1);
    return cat4(cr,cl,cg,co);
}
Exemplo n.º 2
0
Arquivo: cgcs.c Projeto: dacki/dmd
STATIC void ecom(elem **pe)
{ int i,op;
  HCSArray hcsarraySave;
  unsigned hash;
  elem *e,*ehash;
  tym_t tym;

  e = *pe;
  assert(e);
  elem_debug(e);
#ifdef DEBUG
  assert(e->Ecount == 0);
  //assert(e->Ecomsub == 0);
#endif
  tym = tybasic(e->Ety);
  op = e->Eoper;
  switch (op)
  {
    case OPconst:
    case OPvar:
    case OPrelconst:
        break;
    case OPstreq:
    case OPpostinc:
    case OPpostdec:
    case OPeq:
    case OPaddass:
    case OPminass:
    case OPmulass:
    case OPdivass:
    case OPmodass:
    case OPshrass:
    case OPashrass:
    case OPshlass:
    case OPandass:
    case OPxorass:
    case OPorass:
    case OPvecsto:
#if TX86
        /* Reverse order of evaluation for double op=. This is so that  */
        /* the pushing of the address of the second operand is easier.  */
        /* However, with the 8087 we don't need the kludge.             */
        if (op != OPeq && tym == TYdouble && !config.inline8087)
        {       if (EOP(e->E1))
                        ecom(&e->E1->E1);
                ecom(&e->E2);
        }
        else
#endif
        {
            /* Don't mark the increment of an i++ or i-- as a CSE, if it */
            /* can be done with an INC or DEC instruction.               */
            if (!(OTpost(op) && elemisone(e->E2)))
                ecom(&e->E2);           /* evaluate 2nd operand first   */
    case OPnegass:
            if (EOP(e->E1))             /* if lvalue is an operator     */
            {
                if (e->E1->Eoper != OPind)
                    elem_print(e);
                assert(e->E1->Eoper == OPind);
                ecom(&(e->E1->E1));
            }
        }
        touchlvalue(e->E1);
        if (!OTpost(op))                /* lvalue of i++ or i-- is not a cse*/
        {
            hash = cs_comphash(e->E1);
            vec_setbit(hash % CSVECDIM,csvec);
            addhcstab(e->E1,hash);              // add lvalue to hcstab[]
        }
        return;

    case OPbtc:
    case OPbts:
    case OPbtr:
    case OPcmpxchg:
        ecom(&e->E1);
        ecom(&e->E2);
        touchfunc(0);                   // indirect assignment
        return;

    case OPandand:
    case OPoror:
        ecom(&e->E1);
        hcsarraySave = hcsarray;
        ecom(&e->E2);
        hcsarray = hcsarraySave;        // no common subs by E2
        return;                         /* if comsub then logexp() will */
                                        /* break                        */
    case OPcond:
        ecom(&e->E1);
        hcsarraySave = hcsarray;
        ecom(&e->E2->E1);               // left condition
        hcsarray = hcsarraySave;        // no common subs by E2
        ecom(&e->E2->E2);               // right condition
        hcsarray = hcsarraySave;        // no common subs by E2
        return;                         // can't be a common sub

    case OPcall:
    case OPcallns:
        ecom(&e->E2);                   /* eval right first             */
        /* FALL-THROUGH */
    case OPucall:
    case OPucallns:
        ecom(&e->E1);
        touchfunc(1);
        return;
    case OPstrpar:                      /* so we don't break logexp()   */
#if TX86
    case OPinp:                 /* never CSE the I/O instruction itself */
#endif
        ecom(&e->E1);
        /* FALL-THROUGH */
    case OPasm:
    case OPstrthis:             // don't CSE these
    case OPframeptr:
    case OPgot:
    case OPctor:
    case OPdtor:
    case OPdctor:
    case OPmark:
        return;

    case OPddtor:
        touchall();
        ecom(&e->E1);
        touchall();
        return;

    case OPparam:
#if TX86
    case OPoutp:
#endif
        ecom(&e->E1);
    case OPinfo:
        ecom(&e->E2);
        return;
    case OPcomma:
    case OPremquo:
        ecom(&e->E1);
        ecom(&e->E2);
        break;
#if TARGET_SEGMENTED
    case OPvp_fp:
    case OPcvp_fp:
        ecom(&e->E1);
        touchaccess(e);
        break;
#endif
    case OPind:
        ecom(&e->E1);
        /* Generally, CSEing a *(double *) results in worse code        */
        if (tyfloating(tym))
            return;
        break;
    case OPstrcpy:
    case OPstrcat:
    case OPmemcpy:
    case OPmemset:
        ecom(&e->E2);
    case OPsetjmp:
        ecom(&e->E1);
        touchfunc(0);
        return;
    default:                            /* other operators */
        if (!EBIN(e))
           WROP(e->Eoper);
        assert(EBIN(e));
    case OPadd:
    case OPmin:
    case OPmul:
    case OPdiv:
    case OPor:
    case OPxor:
    case OPand:
    case OPeqeq:
    case OPne:
#if TX86
    case OPscale:
    case OPyl2x:
    case OPyl2xp1:
#endif
        ecom(&e->E1);
        ecom(&e->E2);
        break;
    case OPstring:
    case OPaddr:
    case OPbit:
        WROP(e->Eoper);
        elem_print(e);
        assert(0);              /* optelem() should have removed these  */
        /* NOTREACHED */

    // Explicitly list all the unary ops for speed
    case OPnot: case OPcom: case OPneg: case OPuadd:
    case OPabs: case OPrndtol: case OPrint:
    case OPpreinc: case OPpredec:
    case OPbool: case OPstrlen: case OPs16_32: case OPu16_32:
    case OPd_s32: case OPd_u32:
    case OPs32_d: case OPu32_d: case OPd_s16: case OPs16_d: case OP32_16:
    case OPd_f: case OPf_d:
    case OPd_ld: case OPld_d:
    case OPc_r: case OPc_i:
    case OPu8_16: case OPs8_16: case OP16_8:
    case OPu32_64: case OPs32_64: case OP64_32: case OPmsw:
    case OPu64_128: case OPs64_128: case OP128_64:
    case OPd_s64: case OPs64_d: case OPd_u64: case OPu64_d:
    case OPstrctor: case OPu16_d: case OPd_u16:
    case OParrow:
    case OPvoid: case OPnullcheck:
    case OPbsf: case OPbsr: case OPbswap: case OPpopcnt: case OPvector:
    case OPld_u64:
#if TX86
    case OPsqrt: case OPsin: case OPcos:
#endif
#if TARGET_SEGMENTED
    case OPoffset: case OPnp_fp: case OPnp_f16p: case OPf16p_np:
#endif
        ecom(&e->E1);
        break;
    case OPhalt:
        return;
  }

  /* don't CSE structures or unions or volatile stuff   */
  if (tym == TYstruct ||
      tym == TYvoid ||
      e->Ety & mTYvolatile
#if TX86
      || tyxmmreg(tym)
      // don't CSE doubles if inline 8087 code (code generator can't handle it)
      || (tyfloating(tym) && config.inline8087)
#endif
     )
        return;

  hash = cs_comphash(e);                /* must be AFTER leaves are done */

  /* Search for a match in hcstab[].
   * Search backwards, as most likely matches will be towards the end
   * of the list.
   */

#ifdef DEBUG
  if (debugx) dbg_printf("elem: %p hash: %6d\n",e,hash);
#endif
  int csveci = hash % CSVECDIM;
  if (vec_testbit(csveci,csvec))
  {
    for (i = hcsarray.top; i--;)
    {
#ifdef DEBUG
        if (debugx)
            dbg_printf("i: %2d Hhash: %6d Helem: %p\n",
                i,hcstab[i].Hhash,hcstab[i].Helem);
#endif
        if (hash == hcstab[i].Hhash && (ehash = hcstab[i].Helem) != NULL)
        {
            /* if elems are the same and we still have room for more    */
            if (el_match(e,ehash) && ehash->Ecount < 0xFF)
            {
                /* Make sure leaves are also common subexpressions
                 * to avoid false matches.
                 */
                if (!OTleaf(op))
                {
                    if (!e->E1->Ecount)
                        continue;
                    if (OTbinary(op) && !e->E2->Ecount)
                        continue;
                }
                ehash->Ecount++;
                *pe = ehash;
#ifdef DEBUG
                if (debugx)
                        dbg_printf("**MATCH** %p with %p\n",e,*pe);
#endif
                el_free(e);
                return;
            }
        }
    }
  }
  else
    vec_setbit(csveci,csvec);
  addhcstab(e,hash);                    // add this elem to hcstab[]
}
Exemplo n.º 3
0
Arquivo: toir.c Projeto: dheld/dmd
void FuncDeclaration::buildClosure(IRState *irs)
{
    if (needsClosure())
    {   // Generate closure on the heap
        // BUG: doesn't capture variadic arguments passed to this function

#if DMDV2
        /* BUG: doesn't handle destructors for the local variables.
         * The way to do it is to make the closure variables the fields
         * of a class object:
         *    class Closure
         *    {   vtbl[]
         *        monitor
         *        ptr to destructor
         *        sthis
         *        ... closure variables ...
         *        ~this() { call destructor }
         *    }
         */
#endif
        //printf("FuncDeclaration::buildClosure()\n");
        Symbol *sclosure;
        sclosure = symbol_name("__closptr",SCauto,Type::tvoidptr->toCtype());
        sclosure->Sflags |= SFLtrue | SFLfree;
        symbol_add(sclosure);
        irs->sclosure = sclosure;

        unsigned offset = PTRSIZE;      // leave room for previous sthis
        for (size_t i = 0; i < closureVars.dim; i++)
        {   VarDeclaration *v = closureVars[i];
            assert(v->isVarDeclaration());

#if DMDV2
            if (v->needsAutoDtor())
                /* Because the value needs to survive the end of the scope!
                 */
                v->error("has scoped destruction, cannot build closure");
            if (v->isargptr)
                /* See Bugzilla 2479
                 * This is actually a bug, but better to produce a nice
                 * message at compile time rather than memory corruption at runtime
                 */
                v->error("cannot reference variadic arguments from closure");
#endif
            /* Align and allocate space for v in the closure
             * just like AggregateDeclaration::addField() does.
             */
            unsigned memsize;
            unsigned memalignsize;
            structalign_t xalign;
#if DMDV2
            if (v->storage_class & STClazy)
            {
                /* Lazy variables are really delegates,
                 * so give same answers that TypeDelegate would
                 */
                memsize = PTRSIZE * 2;
                memalignsize = memsize;
                xalign = global.structalign;
            }
            else if (v->isRef() || v->isOut())
            {    // reference parameters are just pointers
                memsize = PTRSIZE;
                memalignsize = memsize;
                xalign = global.structalign;
            }
            else
#endif
            {
                memsize = v->type->size();
                memalignsize = v->type->alignsize();
                xalign = v->alignment;
            }
            AggregateDeclaration::alignmember(xalign, memalignsize, &offset);
            v->offset = offset;
            offset += memsize;

            /* Can't do nrvo if the variable is put in a closure, since
             * what the shidden points to may no longer exist.
             */
            if (nrvo_can && nrvo_var == v)
            {
                nrvo_can = 0;
            }
        }
        // offset is now the size of the closure

        // Allocate memory for the closure
        elem *e;
        e = el_long(TYsize_t, offset);
        e = el_bin(OPcall, TYnptr, el_var(rtlsym[RTLSYM_ALLOCMEMORY]), e);

        // Assign block of memory to sclosure
        //    sclosure = allocmemory(sz);
        e = el_bin(OPeq, TYvoid, el_var(sclosure), e);

        // Set the first element to sthis
        //    *(sclosure + 0) = sthis;
        elem *ethis;
        if (irs->sthis)
            ethis = el_var(irs->sthis);
        else
            ethis = el_long(TYnptr, 0);
        elem *ex = el_una(OPind, TYnptr, el_var(sclosure));
        ex = el_bin(OPeq, TYnptr, ex, ethis);
        e = el_combine(e, ex);

        // Copy function parameters into closure
        for (size_t i = 0; i < closureVars.dim; i++)
        {   VarDeclaration *v = closureVars[i];

            if (!v->isParameter())
                continue;
            tym_t tym = v->type->totym();
            if (
#if !SARRAYVALUE
                v->type->toBasetype()->ty == Tsarray ||
#endif
                v->isOut() || v->isRef())
                tym = TYnptr;   // reference parameters are just pointers
#if DMDV2
            else if (v->storage_class & STClazy)
                tym = TYdelegate;
#endif
            ex = el_bin(OPadd, TYnptr, el_var(sclosure), el_long(TYsize_t, v->offset));
            ex = el_una(OPind, tym, ex);
            if (tybasic(ex->Ety) == TYstruct || tybasic(ex->Ety) == TYarray)
            {
                ::type *t = v->type->toCtype();
                ex->ET = t;
                ex = el_bin(OPstreq, tym, ex, el_var(v->toSymbol()));
                ex->ET = t;
            }
            else
                ex = el_bin(OPeq, tym, ex, el_var(v->toSymbol()));

            e = el_combine(e, ex);
        }

        block_appendexp(irs->blx->curblock, e);
    }
}
Exemplo n.º 4
0
STATIC void cpp_basic_data_type(type *t)
{   char c;
    int i;

    //printf("cpp_basic_data_type(t)\n");
    //type_print(t);
    switch (tybasic(t->Tty))
    {
    case TYschar:
        c = 'C';
        goto dochar;
    case TYchar:
        c = 'D';
        goto dochar;
    case TYuchar:
        c = 'E';
        goto dochar;
    case TYshort:
        c = 'F';
        goto dochar;
    case TYushort:
        c = 'G';
        goto dochar;
    case TYint:
        c = 'H';
        goto dochar;
    case TYuint:
        c = 'I';
        goto dochar;
    case TYlong:
        c = 'J';
        goto dochar;
    case TYulong:
        c = 'K';
        goto dochar;
    case TYfloat:
        c = 'M';
        goto dochar;
    case TYdouble:
        c = 'N';
        goto dochar;

    case TYdouble_alias:
        if (intsize == 4)
        {   c = 'O';
            goto dochar;
        }
        c = 'Z';
        goto dochar2;

    case TYldouble:
        if (intsize == 2)
        {   c = 'O';
            goto dochar;
        }
        c = 'Z';
        goto dochar2;
dochar:
        CHAR(c);
        break;

    case TYllong:
        c = 'J';
        goto dochar2;
    case TYullong:
        c = 'K';
        goto dochar2;
    case TYbool:
        c = 'N';
        goto dochar2;   // was 'X' prior to 8.1b8
    case TYwchar_t:
        if (config.flags4 & CFG4nowchar_t)
        {
            c = 'G';
            goto dochar;    // same as TYushort
        }
        else
        {
            pstate.STflags |= PFLmfc;
            c = 'Y';
            goto dochar2;
        }

    // Digital Mars extensions
    case TYifloat:
        c = 'R';
        goto dochar2;
    case TYidouble:
        c = 'S';
        goto dochar2;
    case TYildouble:
        c = 'T';
        goto dochar2;
    case TYcfloat:
        c = 'U';
        goto dochar2;
    case TYcdouble:
        c = 'V';
        goto dochar2;
    case TYcldouble:
        c = 'W';
        goto dochar2;

    case TYchar16:
        c = 'X';
        goto dochar2;
    case TYdchar:
        c = 'Y';
        goto dochar2;
    case TYnullptr:
        c = 'Z';
        goto dochar2;

dochar2:
        CHAR('_');
        goto dochar;

#if TARGET_SEGMENTED
    case TYsptr:
    case TYcptr:
    case TYf16ptr:
    case TYfptr:
    case TYhptr:
    case TYvptr:
#endif
#if !MARS
    case TYmemptr:
#endif
    case TYnptr:
        c = 'P' + cpp_cvidx(t->Tty);
        CHAR(c);
        if(I64)
            CHAR('E'); // __ptr64 modifier
        cpp_pointer_type(t);
        break;
    case TYstruct:
    case TYenum:
        cpp_ecsu_data_type(t);
        break;
    case TYarray:
        i = cpp_cvidx(t->Tty);
        i |= 1;                     // always const
        CHAR('P' + i);
        cpp_pointer_type(t);
        break;
    case TYvoid:
        c = 'X';
        goto dochar;
#if !MARS
    case TYident:
        if (pstate.STintemplate)
        {
            CHAR('V');              // pretend to be a class name
            cpp_zname(t->Tident);
        }
        else
        {
#if SCPP
            cpperr(EM_no_type,t->Tident);   // no type for argument
#endif
            c = 'X';
            goto dochar;
        }
        break;
    case TYtemplate:
        if (pstate.STintemplate)
        {
            CHAR('V');              // pretend to be a class name
            cpp_zname(((typetemp_t *)t)->Tsym->Sident);
        }
        else
            goto Ldefault;
        break;
#endif

    default:
Ldefault:
        if (tyfunc(t->Tty))
            cpp_function_type(t);
        else
        {
#if SCPP
#ifdef DEBUG
            if (!errcnt)
                type_print(t);
#endif
            assert(errcnt);
#endif
        }
    }
}
Exemplo n.º 5
0
Arquivo: glue.c Projeto: iteratif/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;
    }
    else
    {   // Register return style cannot make nrvo.
        // Auto functions keep the nrvo_can flag up to here,
        // so we should eliminate it before entering backend.
        nrvo_can = 0;
    }

    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)[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)
    {
        size_t numintegerregs = 0, numfloatregs = 0;
        const unsigned char* argregs = getintegerparamsreglist(tyf, &numintegerregs);
        const unsigned char* floatregs = getfloatparamsreglist(tyf, &numfloatregs);

        // Order of assignment of pointer or integer parameters
        int r = 0;
        int xmmcnt = 0;

        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 < numintegerregs)
            {
                if ((I64 || (i == 0 && (tyf == TYjfunc || tyf == TYmfunc))) && type_jparam(sp->Stype))
                {
                    sp->Sclass = SCfastpar;
                    sp->Spreg = argregs[r];
                    sp->Sfl = FLauto;
                    ++r;
                }
            }
            if (xmmcnt < numfloatregs)
            {
                if (tyxmmreg(ty))
                {
                    sp->Sclass = SCfastpar;
                    sp->Spreg = floatregs[xmmcnt];
                    sp->Sfl = FLauto;
                    ++xmmcnt;
                }
            }
        }
    }

    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
    {
        ssharedctors.push(s);
    }
    else
#endif
    if (isStaticCtorDeclaration())
    {
        sctors.push(s);
    }

    // If static destructor
#if DMDV2
    if (isSharedStaticDtorDeclaration())        // must come first because it derives from StaticDtorDeclaration
    {
        SharedStaticDtorDeclaration *f = isSharedStaticDtorDeclaration();
        assert(f);
        if (f->vgate)
        {   /* Increment destructor's vgate at construction time
             */
            esharedctorgates.push(f);
        }

        sshareddtors.shift(s);
    }
    else
#endif
    if (isStaticDtorDeclaration())
    {
        StaticDtorDeclaration *f = isStaticDtorDeclaration();
        assert(f);
        if (f->vgate)
        {   /* Increment destructor's vgate at construction time
             */
            ectorgates.push(f);
        }

        sdtors.shift(s);
    }

    // If unit test
    if (isUnitTestDeclaration())
    {
        stests.push(s);
    }

    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)[i];

        FuncDeclaration *fd = s->isFuncDeclaration();
        if (fd)
        {   FuncDeclaration *fdp = fd->toParent2()->isFuncDeclaration();
            if (fdp && fdp->semanticRun < PASSobj)
            {   /* Bugzilla 7595
                 * FuncDeclaration::buildClosure() relies on nested functions
                 * being toObjFile'd after the outer function. Otherwise, the
                 * v->offset's for the closure variables are wrong.
                 * So, defer fd until after fdp is done.
                 */
                fdp->deferred.push(fd);
                continue;
            }
        }

        s->toObjFile(0);
    }

    for (size_t i = 0; i < deferred.dim; i++)
    {
        FuncDeclaration *fd = deferred[i];
        fd->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
}
Exemplo n.º 6
0
Arquivo: glue.c Projeto: alexrp/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 (global.errors)
        return;

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

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

    if (semanticRun == PASSsemanticdone)
    {
        /* What happened is this function failed semantic3() with errors,
         * but the errors were gagged.
         * Try to reproduce those errors, and then fail.
         */
        error("errors compiling the function");
        return;
    }
    assert(semanticRun == PASSsemantic3done);
    semanticRun = PASSobj;

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

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

    // tunnel type of "this" to debug info generation
    if (AggregateDeclaration* ad = func->parent->isAggregateDeclaration())
    {
        ::type* t = ad->getType()->toCtype();
        if(cd)
            t = t->Tnext; // skip reference
        f->Fclass = (Classsym *)t;
    }

#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;

        /* The enclosing function must have its code generated first,
         * so we know things like where its local symbols are stored.
         */
        FuncDeclaration *fdp = toAliasFunc()->toParent2()->isFuncDeclaration();
        // Bug 8016 - only include the function if it is a template instance
        Dsymbol * owner = NULL;
        if (fdp)
        {   owner =  fdp->toParent();
            while (owner && !owner->isTemplateInstance())
                owner = owner->toParent();
        }

        if (owner && fdp && fdp->semanticRun == PASSsemantic3done &&
            !fdp->isUnitTestDeclaration())
        {
            /* Can't do unittest's out of order, they are order dependent in that their
             * execution is done in lexical order, and some modules (std.datetime *cough*
             * *cough*) rely on this.
             */
            fdp->toObjFile(multiobj);
        }
    }
    else
    {
        const char *libname = (global.params.symdebug)
                                ? global.params.debuglibname
                                : global.params.defaultlibname;

        // Pull in RTL startup code (but only once)
        if (func->isMain() && onlyOneMain(loc))
        {
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
            objmod->external_def("_main");
            objmod->ehsections();   // initialize exception handling sections
#endif
#if TARGET_WINDOS
            if (I64)
            {
                objmod->external_def("main");
                objmod->ehsections();   // initialize exception handling sections
            }
            else
            {
                objmod->external_def("_main");
                objmod->external_def("__acrtused_con");
            }
#endif
            objmod->includelib(libname);
            s->Sclass = SCglobal;
        }
        else if (strcmp(s->Sident, "main") == 0 && linkage == LINKc)
        {
#if TARGET_WINDOS
            if (I64)
            {
                objmod->includelib("LIBCMT");
                objmod->includelib("OLDNAMES");
            }
            else
            {
                objmod->external_def("__acrtused_con");        // bring in C startup code
                objmod->includelib("snn.lib");          // bring in C runtime library
            }
#endif
            s->Sclass = SCglobal;
        }
#if TARGET_WINDOS
        else if (func->isWinMain() && onlyOneMain(loc))
        {
            if (I64)
            {
                objmod->includelib("uuid");
                objmod->includelib("LIBCMT");
                objmod->includelib("OLDNAMES");
                objmod->ehsections();   // initialize exception handling sections
            }
            else
            {
                objmod->external_def("__acrtused");
            }
            objmod->includelib(libname);
            s->Sclass = SCglobal;
        }

        // Pull in RTL startup code
        else if (func->isDllMain() && onlyOneMain(loc))
        {
            if (I64)
            {
                objmod->includelib("uuid");
                objmod->includelib("LIBCMT");
                objmod->includelib("OLDNAMES");
                objmod->ehsections();   // initialize exception handling sections
            }
            else
            {
                objmod->external_def("__acrtused_dll");
            }
            objmod->includelib(libname);
            s->Sclass = SCglobal;
        }
#endif
    }

    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;
    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;
    }
    else
    {   // Register return style cannot make nrvo.
        // Auto functions keep the nrvo_can flag up to here,
        // so we should eliminate it before entering backend.
        nrvo_can = 0;
    }

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

    // Estimate number of parameters, pi
    size_t pi = (v_arguments != NULL);
    if (parameters)
        pi += parameters->dim;

    // Create a temporary buffer, params[], to hold function parameters
    Symbol *paramsbuf[10];
    Symbol **params = paramsbuf;    // allocate on stack if possible
    if (pi + 2 > 10)                // allow extra 2 for sthis and shidden
    {   params = (Symbol **)malloc((pi + 2) * sizeof(Symbol *));
        assert(params);
    }

    // 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)[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)
    {
        FuncParamRegs fpr(tyf);

        for (size_t i = 0; i < pi; i++)
        {   Symbol *sp = params[i];
            if (fpr.alloc(sp->Stype, sp->Stype->Tty, &sp->Spreg, &sp->Spreg2))
            {
                sp->Sclass = (config.exe == EX_WIN64) ? SCshadowreg : SCfastpar;
                sp->Sfl = (sp->Sclass == SCshadowreg) ? FLpara : FLfast;
            }
        }
    }

    // Done with params
    if (params != paramsbuf)
        free(params);
    params = NULL;

    if (func->fbody)
    {
        localgot = NULL;

        Statement *sbody = func->fbody;

        Blockx bx;
        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;

        /* Doing this in semantic3() caused all kinds of problems:
         * 1. couldn't reliably get the final mangling of the function name due to fwd refs
         * 2. impact on function inlining
         * 3. what to do when writing out .di files, or other pretty printing
         */
        if (global.params.trace)
        {   /* Wrap the entire function body in:
             *   trace_pro("funcname");
             *   try
             *     body;
             *   finally
             *     _c_trace_epi();
             */
            StringExp *se = new StringExp(Loc(), s->Sident);
            se->type = new TypeDArray(Type::tchar->immutableOf());
            se->type = se->type->semantic(Loc(), NULL);
            Expressions *exps = new Expressions();
            exps->push(se);
            FuncDeclaration *fdpro = FuncDeclaration::genCfunc(Type::tvoid, "trace_pro");
            Expression *ec = new VarExp(Loc(), fdpro);
            Expression *e = new CallExp(Loc(), ec, exps);
            e->type = Type::tvoid;
            Statement *sp = new ExpStatement(loc, e);

            FuncDeclaration *fdepi = FuncDeclaration::genCfunc(Type::tvoid, "_c_trace_epi");
            ec = new VarExp(Loc(), fdepi);
            e = new CallExp(Loc(), ec);
            e->type = Type::tvoid;
            Statement *sf = new ExpStatement(loc, e);

            Statement *stf;
            if (sbody->blockExit(tf->isnothrow) == BEfallthru)
                stf = new CompoundStatement(Loc(), sbody, sf);
            else
                stf = new TryFinallyStatement(Loc(), sbody, sf);
            sbody = new CompoundStatement(Loc(), sp, stf);
        }

#if DMDV2
        buildClosure(&irs);
#endif

#if TARGET_WINDOS
        if (func->isSynchronized() && cd && config.flags2 & CFG2seh &&
            !func->isStatic() && !sbody->usesEH() && !global.params.trace)
        {
            /* 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 (block *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
    {
        ssharedctors.push(s);
    }
    else
#endif
    if (isStaticCtorDeclaration())
    {
        sctors.push(s);
    }

    // If static destructor
#if DMDV2
    if (isSharedStaticDtorDeclaration())        // must come first because it derives from StaticDtorDeclaration
    {
        SharedStaticDtorDeclaration *f = isSharedStaticDtorDeclaration();
        assert(f);
        if (f->vgate)
        {   /* Increment destructor's vgate at construction time
             */
            esharedctorgates.push(f);
        }

        sshareddtors.shift(s);
    }
    else
#endif
    if (isStaticDtorDeclaration())
    {
        StaticDtorDeclaration *f = isStaticDtorDeclaration();
        assert(f);
        if (f->vgate)
        {   /* Increment destructor's vgate at construction time
             */
            ectorgates.push(f);
        }

        sdtors.shift(s);
    }

    // If unit test
    if (isUnitTestDeclaration())
    {
        stests.push(s);
    }

    if (global.errors)
        return;

    writefunc(s);
    if (isExport())
        objmod->export_symbol(s, Para.offset);

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

        FuncDeclaration *fd = s->isFuncDeclaration();
        if (fd)
        {   FuncDeclaration *fdp = fd->toParent2()->isFuncDeclaration();
            if (fdp && fdp->semanticRun < PASSobj)
            {   /* Bugzilla 7595
                 * FuncDeclaration::buildClosure() relies on nested functions
                 * being toObjFile'd after the outer function. Otherwise, the
                 * v->offset's for the closure variables are wrong.
                 * So, defer fd until after fdp is done.
                 */
                fdp->deferred.push(fd);
                continue;
            }
        }

        s->toObjFile(0);
    }

    for (size_t i = 0; i < deferred.dim; i++)
    {
        FuncDeclaration *fd = deferred[i];
        fd->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)
        objmod->staticdtor(s);
#endif
#if DMDV2
    if (irs.startaddress)
    {
        //printf("Setting start address\n");
        objmod->startaddress(irs.startaddress);
    }
#endif
}
Exemplo n.º 7
0
type *type_copy(type *t)
{   type *tn;
    param_t *p;

    type_debug(t);
#if SCPP
    if (tybasic(t->Tty) == TYtemplate)
    {
        tn = type_alloc_template(((typetemp_t *)t)->Tsym);
    }
    else
#endif
        tn = type_alloc(t->Tty);
    *tn = *t;
    switch (tybasic(tn->Tty))
    {
#if SCPP
            case TYtemplate:
                ((typetemp_t *)tn)->Tsym = ((typetemp_t *)t)->Tsym;
                goto L1;

            case TYident:
                tn->Tident = (char *)MEM_PH_STRDUP(t->Tident);
                break;
#endif

            case TYarray:
                if (tn->Tflags & TFvla)
                    tn->Tel = el_copytree(tn->Tel);
                break;

            default:
                if (tyfunc(tn->Tty))
                {
                L1:
                    tn->Tparamtypes = NULL;
                    for (p = t->Tparamtypes; p; p = p->Pnext)
                    {   param_t *pn;

                        pn = param_append_type(&tn->Tparamtypes,p->Ptype);
                        if (p->Pident)
                        {
                            pn->Pident = (char *)MEM_PH_STRDUP(p->Pident);
                        }
                        assert(!p->Pelem);
                    }
                }
#if SCPP
                else if (tn->Talternate && typtr(tn->Tty))
                    tn->Talternate->Tcount++;
#endif
#if MARS
                else if (tn->Tkey && typtr(tn->Tty))
                    tn->Tkey->Tcount++;
#endif
                break;
    }
    if (tn->Tnext)
    {   type_debug(tn->Tnext);
        tn->Tnext->Tcount++;
    }
    tn->Tcount = 0;
    return tn;
}
Exemplo n.º 8
0
Arquivo: cgxmm.c Projeto: 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();
}
Exemplo n.º 9
0
Arquivo: cgxmm.c Projeto: 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();
}
Exemplo n.º 10
0
Arquivo: s2ir.c Projeto: Rayerd/dmd
void ForeachRangeStatement::toIR(IRState *irs)
{
    assert(0);
#if 0
    Type *tab;
    elem *eaggr;
    elem *elwr;
    elem *eupr;
    elem *e;
    elem *elength;
    tym_t keytym;

    //printf("ForeachStatement::toIR()\n");
    block *bpre;
    block *bcond;
    block *bbody;
    block *bbodyx;
    Blockx *blx = irs->blx;

    IRState mystate(irs,this);
    mystate.breakBlock = block_calloc(blx);
    mystate.contBlock = block_calloc(blx);

    incUsage(irs, lwr->loc);
    elwr = lwr->toElem(irs);

    incUsage(irs, upr->loc);
    eupr = upr->toElem(irs);

    /* Create skey, the index to the array.
     * Initialize skey to elwr (foreach) or eupr (foreach_reverse).
     */
    Symbol *skey = key->toSymbol();
    symbol_add(skey);
    keytym = key->type->totym();

    elem *ekey;
    if (key->offset)            // if key is member of a closure
    {
        assert(irs->sclosure);
        ekey = el_var(irs->sclosure);
        ekey = el_bin(OPadd, TYnptr, ekey, el_long(TYint, key->offset));
        ekey = el_una(OPind, keytym, ekey);
    }
    else
        ekey = el_var(skey);

    elem *einit = (op == TOKforeach_reverse) ? eupr : elwr;
    e = el_bin(OPeq, keytym, ekey, einit);   // skey = einit;
    block_appendexp(blx->curblock, e);

    /* Make a copy of the end condition, so it only
     * gets evaluated once.
     */
    elem *eend = (op == TOKforeach_reverse) ? elwr : eupr;
    Symbol *send = symbol_genauto(eend);
    e = el_bin(OPeq, eend->Ety, el_var(send), eend);
    assert(tybasic(e->Ety) != TYstruct);
    block_appendexp(blx->curblock, e);

    bpre = blx->curblock;
    block_next(blx,BCgoto,NULL);
    bcond = blx->curblock;

    if (op == TOKforeach_reverse)
    {
        // Construct (key > elwr)
        e = el_bin(OPgt, TYint, el_copytree(ekey), el_var(send));
    }
    else
    {
        // Construct (key < eupr)
        e = el_bin(OPlt, TYint, el_copytree(ekey), el_var(send));
    }

    // The size of the increment
    size_t sz = 1;
    Type *tkeyb = key->type->toBasetype();
    if (tkeyb->ty == Tpointer)
        sz = tkeyb->nextOf()->size();

    bcond->Belem = e;
    block_next(blx, BCiftrue, NULL);

    if (op == TOKforeach_reverse)
    {
        // Construct (skey -= 1)
        e = el_bin(OPminass, keytym, el_copytree(ekey), el_long(keytym, sz));
        block_appendexp(blx->curblock, e);
    }

    bbody = blx->curblock;
    if (body)
        body->toIR(&mystate);
    bbodyx = blx->curblock;
    block_next(blx,BCgoto,mystate.contBlock);

    if (op == TOKforeach)
    {
        // Construct (skey += 1)
        e = el_bin(OPaddass, keytym, el_copytree(ekey), el_long(keytym, sz));
        mystate.contBlock->Belem = e;
    }
    block_next(blx,BCgoto,mystate.breakBlock);

    list_append(&bpre->Bsucc,bcond);
    list_append(&bcond->Bsucc,bbody);
    list_append(&bcond->Bsucc,mystate.breakBlock);
    list_append(&bbodyx->Bsucc,mystate.contBlock);
    list_append(&mystate.contBlock->Bsucc,bcond);
#endif
}
Exemplo n.º 11
0
Arquivo: cgxmm.c Projeto: davispuh/dmd
code *cdvector(elem *e, regm_t *pretregs)
{
    /* e should look like one of:
     *    vector
     *      |
     *    param
     *    /   \
     *  param op2
     *  /   \
     * op   op1
     */

    if (!config.fpxmmregs)
    {   printf("SIMD operations not supported on this platform\n");
        exit(1);
    }

    unsigned n = el_nparams(e->E1);
    elem **params = (elem **)malloc(n * sizeof(elem *));
    assert(params);
    elem **tmp = params;
    el_paramArray(&tmp, e->E1);

#if 0
    printf("cdvector()\n");
    for (int i = 0; i < n; i++)
    {
        printf("[%d]: ", i);
        elem_print(params[i]);
    }
#endif

    if (*pretregs == 0)
    {   /* Evaluate for side effects only
         */
        CodeBuilder cdb;
        for (int i = 0; i < n; i++)
        {
            cdb.append(codelem(params[i], pretregs, FALSE));
            *pretregs = 0;      // in case they got set
        }
        return cdb.finish();
    }

    assert(n >= 2 && n <= 4);

    elem *eop = params[0];
    elem *op1 = params[1];
    elem *op2 = NULL;
    tym_t ty2 = 0;
    if (n >= 3)
    {   op2 = params[2];
        ty2 = tybasic(op2->Ety);
    }

    unsigned op = el_tolong(eop);
#ifdef DEBUG
    assert(!isXMMstore(op));
#endif
    tym_t ty1 = tybasic(op1->Ety);
    unsigned sz1 = _tysize[ty1];
//    assert(sz1 == 16);       // float or double

    regm_t retregs;
    CodeBuilder cdb;
    if (n == 3 && ty2 == TYuchar && op2->Eoper == OPconst)
    {   // Handle: op xmm,imm8

        retregs = *pretregs & XMMREGS;
        if (!retregs)
            retregs = XMMREGS;
        cdb.append(codelem(op1,&retregs,FALSE)); // eval left leaf
        unsigned reg = findreg(retregs);
        int r;
        switch (op)
        {
            case PSLLD:  r = 6; op = 0x660F72;  break;
            case PSLLQ:  r = 6; op = 0x660F73;  break;
            case PSLLW:  r = 6; op = 0x660F71;  break;
            case PSRAD:  r = 4; op = 0x660F72;  break;
            case PSRAW:  r = 4; op = 0x660F71;  break;
            case PSRLD:  r = 2; op = 0x660F72;  break;
            case PSRLQ:  r = 2; op = 0x660F73;  break;
            case PSRLW:  r = 2; op = 0x660F71;  break;
            case PSRLDQ: r = 3; op = 0x660F73;  break;
            case PSLLDQ: r = 7; op = 0x660F73;  break;

            default:
                printf("op = x%x\n", op);
                assert(0);
                break;
        }
        cdb.append(getregs(retregs));
        cdb.genc2(op,modregrmx(3,r,reg-XMM0), el_tolong(op2));
    }
    else if (n == 2)
    {   /* Handle: op xmm,mem
         * where xmm is written only, not read
         */
        code cs;

        if ((op1->Eoper == OPind && !op1->Ecount) || op1->Eoper == OPvar)
        {
            cdb.append(getlvalue(&cs, op1, RMload));     // get addressing mode
        }
        else
        {
            regm_t rretregs = XMMREGS;
            cdb.append(codelem(op1, &rretregs, FALSE));
            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;
        }

        retregs = *pretregs & XMMREGS;
        if (!retregs)
            retregs = XMMREGS;
        unsigned reg;
        cdb.append(allocreg(&retregs, &reg, e->Ety));
        code_newreg(&cs, reg - XMM0);
        cs.Iop = op;
        cdb.gen(&cs);
    }
    else if (n == 3 || n == 4)
    {   /* Handle:
         *      op xmm,mem        // n = 3
         *      op xmm,mem,imm8   // n = 4
         * Both xmm and mem are operands, evaluate xmm first.
         */

        code cs;

        retregs = *pretregs & XMMREGS;
        if (!retregs)
            retregs = XMMREGS;
        cdb.append(codelem(op1,&retregs,FALSE)); // eval left leaf
        unsigned reg = findreg(retregs);

        if ((op2->Eoper == OPind && !op2->Ecount) || op2->Eoper == OPvar)
        {
            cdb.append(getlvalue(&cs, op2, RMload | retregs));     // get addressing mode
        }
        else
        {
            unsigned rretregs = XMMREGS & ~retregs;
            cdb.append(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;
        }

        cdb.append(getregs(retregs));
        if (n == 4)
        {
            switch (op)
            {
                case CMPPD:   case CMPSS:   case CMPSD:   case CMPPS:
                case PSHUFD:  case PSHUFHW: case PSHUFLW:
                case BLENDPD: case BLENDPS: case DPPD:    case DPPS:
                case MPSADBW: case PBLENDW:
                case ROUNDPD: case ROUNDPS: case ROUNDSD: case ROUNDSS:
                case SHUFPD:  case SHUFPS:
                    break;
                default:
                    printf("op = x%x\n", op);
                    assert(0);
                    break;
            }
            elem *imm8 = params[3];
            cs.IFL2 = FLconst;
            cs.IEV2.Vsize_t = el_tolong(imm8);
        }
        code_newreg(&cs, reg - XMM0);
        cs.Iop = op;
        cdb.gen(&cs);
    }
    else
        assert(0);
    cdb.append(fixresult(e,retregs,pretregs));
    free(params);
    freenode(e);
    return cdb.finish();
}
Exemplo n.º 12
0
Arquivo: s2ir.c Projeto: Rayerd/dmd
void ForeachStatement::toIR(IRState *irs)
{
    printf("ForeachStatement::toIR() %s\n", toChars());
    assert(0);  // done by "lowering" in the front end
#if 0
    Type *tab;
    elem *eaggr;
    elem *e;
    elem *elength;
    tym_t keytym;

    //printf("ForeachStatement::toIR()\n");
    block *bpre;
    block *bcond;
    block *bbody;
    block *bbodyx;
    Blockx *blx = irs->blx;

    IRState mystate(irs,this);
    mystate.breakBlock = block_calloc(blx);
    mystate.contBlock = block_calloc(blx);

    tab = aggr->type->toBasetype();
    assert(tab->ty == Tarray || tab->ty == Tsarray);

    incUsage(irs, aggr->loc);
    eaggr = aggr->toElem(irs);

    /* Create sp: pointer to start of array data
     */

    Symbol *sp = symbol_genauto(TYnptr);

    if (tab->ty == Tarray)
    {
        // stmp is copy of eaggr (the array), so eaggr is evaluated only once
        Symbol *stmp;

        // Initialize stmp
        stmp = symbol_genauto(eaggr);
        e = el_bin(OPeq, eaggr->Ety, el_var(stmp), eaggr);
        block_appendexp(blx->curblock, e);

        // Initialize sp
        e = el_una(OPmsw, TYnptr, el_var(stmp));
        e = el_bin(OPeq, TYnptr, el_var(sp), e);
        block_appendexp(blx->curblock, e);

        // Get array.length
        elength = el_var(stmp);
        elength->Ety = TYsize_t;
    }
    else // Tsarray
    {
        // Initialize sp
        e = el_una(OPaddr, TYnptr, eaggr);
        e = el_bin(OPeq, TYnptr, el_var(sp), e);
        block_appendexp(blx->curblock, e);

        // Get array.length
        elength = el_long(TYsize_t, ((TypeSArray *)tab)->dim->toInteger());
    }

    Symbol *spmax;
    Symbol *skey;

    if (key)
    {
        /* Create skey, the index to the array.
         * Initialize skey to 0 (foreach) or .length (foreach_reverse).
         */
        skey = key->toSymbol();
        symbol_add(skey);
        keytym = key->type->totym();
        elem *einit = (op == TOKforeach_reverse) ? elength : el_long(keytym, 0);
        e = el_bin(OPeq, keytym, el_var(skey), einit);
    }
    else
    {
        /* Create spmax, pointer past end of data.
         * Initialize spmax = sp + array.length * size
         */
        spmax = symbol_genauto(TYnptr);
        e = el_bin(OPmul, TYsize_t, elength, el_long(TYsize_t, tab->nextOf()->size()));
        e = el_bin(OPadd, TYnptr, el_var(sp), e);
        e = el_bin(OPeq, TYnptr, el_var(spmax), e);

        /* For foreach_reverse, swap sp and spmax
         */
        if (op == TOKforeach_reverse)
        {   Symbol *s = sp;
            sp = spmax;
            spmax = s;
        }
    }
    block_appendexp(blx->curblock, e);

    bpre = blx->curblock;
    block_next(blx,BCgoto,NULL);
    bcond = blx->curblock;

    if (key)
    {
        if (op == TOKforeach_reverse)
        {
            // Construct (key != 0)
            e = el_bin(OPne, TYint, el_var(skey), el_long(keytym, 0));
        }
        else
        {
            // Construct (key < elength)
            e = el_bin(OPlt, TYint, el_var(skey), elength);
        }
    }
    else
    {
        if (op == TOKforeach_reverse)
        {
            // Construct (sp > spmax)
            e = el_bin(OPgt, TYint, el_var(sp), el_var(spmax));
        }
        else
        {
            // Construct (sp < spmax)
            e = el_bin(OPlt, TYint, el_var(sp), el_var(spmax));
        }
    }
    bcond->Belem = e;
    block_next(blx, BCiftrue, NULL);

    if (op == TOKforeach_reverse)
    {
        if (key)
        {   // Construct (skey -= 1)
            e = el_bin(OPminass, keytym, el_var(skey), el_long(keytym, 1));
        }
        else
        {   // Construct (sp--)
            e = el_bin(OPminass, TYnptr, el_var(sp), el_long(TYsize_t, tab->nextOf()->size()));
        }
        block_appendexp(blx->curblock, e);
    }

    Symbol *s;
    FuncDeclaration *fd = NULL;
    if (value->toParent2())
        fd = value->toParent2()->isFuncDeclaration();
    int nrvo = 0;
    if (fd && fd->nrvo_can && fd->nrvo_var == value)
    {
        s = fd->shidden;
        nrvo = 1;
    }
    else
    {   s = value->toSymbol();
        symbol_add(s);
    }

    // Construct (value = *sp) or (value = sp[skey * elemsize])
    tym_t tym = value->type->totym();
    if (key)
    {   // sp + skey * elemsize
        e = el_bin(OPmul, keytym, el_var(skey), el_long(keytym, tab->nextOf()->size()));
        e = el_bin(OPadd, TYnptr, el_var(sp), e);
    }
    else
        e = el_var(sp);

    elem *evalue;
#if DMDV2
    if (value->offset)  // if value is a member of a closure
    {
        assert(irs->sclosure);
        evalue = el_var(irs->sclosure);
        evalue = el_bin(OPadd, TYnptr, evalue, el_long(TYint, value->offset));
        evalue = el_una(OPind, value->type->totym(), evalue);
    }
    else
#endif
        evalue = el_var(s);

    if (value->isOut() || value->isRef())
    {
        assert(value->storage_class & (STCout | STCref));
        e = el_bin(OPeq, TYnptr, evalue, e);
    }
    else
    {
        if (nrvo)
            evalue = el_una(OPind, tym, evalue);
        StructDeclaration *sd = needsPostblit(value->type);
        if (tybasic(tym) == TYstruct)
        {
            e = el_bin(OPeq, tym, evalue, el_una(OPind, tym, e));
            e->Eoper = OPstreq;
            e->ET = value->type->toCtype();
#if DMDV2
            // Call postblit on e
            if (sd)
            {   FuncDeclaration *fd = sd->postblit;
                elem *ec = el_copytree(evalue);
                ec = el_una(OPaddr, TYnptr, ec);
                ec = callfunc(loc, irs, 1, Type::tvoid, ec, sd->type->pointerTo(), fd, fd->type, NULL, NULL);
                e = el_combine(e, ec);
            }
#endif
        }
        else if (tybasic(tym) == TYarray)
        {
            if (sd)
            {
                /* Generate:
                 *      _d_arrayctor(ti, efrom, eto)
                 */
                Expression *ti = value->type->toBasetype()->nextOf()->toBasetype()->getTypeInfo(NULL);
                elem *esize = el_long(TYsize_t, ((TypeSArray *)value->type->toBasetype())->dim->toInteger());
                elem *eto = el_pair(TYdarray, esize, el_una(OPaddr, TYnptr, evalue));
                elem *efrom = el_pair(TYdarray, el_copytree(esize), e);
                elem *ep = el_params(eto, efrom, ti->toElem(irs), NULL);
                int rtl = RTLSYM_ARRAYCTOR;
                e = el_bin(OPcall, TYvoid, el_var(rtlsym[rtl]), ep);
            }
            else
            {
                e = el_bin(OPeq, tym, evalue, el_una(OPind, tym, e));
                e->Eoper = OPstreq;
                e->Ejty = e->Ety = TYstruct;
                e->ET = value->type->toCtype();
            }
        }
        else
            e = el_bin(OPeq, tym, evalue, el_una(OPind, tym, e));
    }
    incUsage(irs, loc);
    block_appendexp(blx->curblock, e);

    bbody = blx->curblock;
    if (body)
        body->toIR(&mystate);
    bbodyx = blx->curblock;
    block_next(blx,BCgoto,mystate.contBlock);

    if (op == TOKforeach)
    {
        if (key)
        {   // Construct (skey += 1)
            e = el_bin(OPaddass, keytym, el_var(skey), el_long(keytym, 1));
        }
        else
        {   // Construct (sp++)
            e = el_bin(OPaddass, TYnptr, el_var(sp), el_long(TYsize_t, tab->nextOf()->size()));
        }
        mystate.contBlock->Belem = e;
    }
    block_next(blx,BCgoto,mystate.breakBlock);

    list_append(&bpre->Bsucc,bcond);
    list_append(&bcond->Bsucc,bbody);
    list_append(&bcond->Bsucc,mystate.breakBlock);
    list_append(&bbodyx->Bsucc,mystate.contBlock);
    list_append(&mystate.contBlock->Bsucc,bcond);
#endif
}
Exemplo n.º 13
0
Arquivo: s2ir.c Projeto: Rayerd/dmd
void ReturnStatement::toIR(IRState *irs)
{
    Blockx *blx = irs->blx;

    incUsage(irs, loc);
    if (exp)
    {   elem *e;

        FuncDeclaration *func = irs->getFunc();
        assert(func);
        assert(func->type->ty == Tfunction);
        TypeFunction *tf = (TypeFunction *)(func->type);

        enum RET retmethod = tf->retStyle();
        if (retmethod == RETstack)
        {
            elem *es;

            /* If returning struct literal, write result
             * directly into return value
             */
            if (exp->op == TOKstructliteral)
            {   StructLiteralExp *se = (StructLiteralExp *)exp;
                char save[sizeof(StructLiteralExp)];
                memcpy(save, se, sizeof(StructLiteralExp));
                se->sym = irs->shidden;
                se->soffset = 0;
                se->fillHoles = 1;
                e = exp->toElemDtor(irs);
                memcpy(se, save, sizeof(StructLiteralExp));

            }
            else
                e = exp->toElemDtor(irs);
            assert(e);

            if (exp->op == TOKstructliteral ||
                    (func->nrvo_can && func->nrvo_var))
            {
                // Return value via hidden pointer passed as parameter
                // Write exp; return shidden;
                es = e;
            }
            else
            {
                // Return value via hidden pointer passed as parameter
                // Write *shidden=exp; return shidden;
                int op;
                tym_t ety;

                ety = e->Ety;
                es = el_una(OPind,ety,el_var(irs->shidden));
                op = (tybasic(ety) == TYstruct) ? OPstreq : OPeq;
                es = el_bin(op, ety, es, e);
                if (op == OPstreq)
                    es->ET = exp->type->toCtype();
#if DMDV2
                /* Call postBlit() on *shidden
                 */
                Type *tb = exp->type->toBasetype();
                //if (tb->ty == Tstruct) exp->dump(0);
                if ((exp->op == TOKvar || exp->op == TOKdotvar || exp->op == TOKstar || exp->op == TOKthis) &&
                        tb->ty == Tstruct)
                {   StructDeclaration *sd = ((TypeStruct *)tb)->sym;
                    if (sd->postblit)
                    {   FuncDeclaration *fd = sd->postblit;
                        if (fd->storage_class & STCdisable)
                        {
                            fd->toParent()->error(loc, "is not copyable because it is annotated with @disable");
                        }
                        elem *ec = el_var(irs->shidden);
                        ec = callfunc(loc, irs, 1, Type::tvoid, ec, tb->pointerTo(), fd, fd->type, NULL, NULL);
                        es = el_bin(OPcomma, ec->Ety, es, ec);
                    }

#if 0
                    /* It has been moved, so disable destructor
                     */
                    if (exp->op == TOKvar)
                    {   VarExp *ve = (VarExp *)exp;
                        VarDeclaration *v = ve->var->isVarDeclaration();
                        if (v && v->rundtor)
                        {
                            elem *er = el_var(v->rundtor->toSymbol());
                            er = el_bin(OPeq, TYint, er, el_long(TYint, 0));
                            es = el_bin(OPcomma, TYint, es, er);
                        }
                    }
#endif
                }
#endif
            }
            e = el_var(irs->shidden);
            e = el_bin(OPcomma, e->Ety, es, e);
        }
#if DMDV2
        else if (tf->isref)
        {   // Reference return, so convert to a pointer
            Expression *ae = exp->addressOf(NULL);
            e = ae->toElemDtor(irs);
        }
#endif
        else
        {
            e = exp->toElemDtor(irs);
            assert(e);
        }

        elem_setLoc(e, loc);
        block_appendexp(blx->curblock, e);
        block_next(blx, BCretexp, NULL);
    }
    else
        block_next(blx, BCret, NULL);
}
Exemplo n.º 14
0
void cod5_prol_epi()
{   tym_t tym;
    tym_t tyf;
    block *b;
    block *bp;
    list_t bl;
    int nepis;

    tyf = funcsym_p->ty();
    tym = tybasic(tyf);

goto L1;
    if (!(config.flags4 & CFG4optimized) ||
        anyiasm ||
        usedalloca ||
        usednteh ||
        tyf & (mTYnaked | mTYloadds) ||
        tym == TYifunc ||
        tym == TYmfunc ||       // can't yet handle ECX passed as parameter
        tym == TYjfunc ||       // can't yet handle EAX passed as parameter
        config.flags & (CFGalwaysframe | CFGtrace) ||
//      config.fulltypes ||
        (config.wflags & WFwindows && tyfarfunc(tym)) ||
        need_prolog(startblock)
       )
    {   // First block gets the prolog, all return blocks
        // get the epilog.
        //printf("not even a candidate\n");
    L1:
        cod5_noprol();
        return;
    }

    // Turn on BFLoutsideprolog for all blocks outside the ones needing the prolog.

    for (b = startblock; b; b = b->Bnext)
        b->Bflags &= ~BFLoutsideprolog;                 // start with them all off

    pe_add(startblock);

    // Look for only one block (bp) that will hold the prolog
    bp = NULL;
    nepis = 0;
    for (b = startblock; b; b = b->Bnext)
    {   int mark;

        if (b->Bflags & BFLoutsideprolog)
            continue;

        // If all predecessors are marked
        mark = 0;
        assert(b->Bpred);
        for (bl = b->Bpred; bl; bl = list_next(bl))
        {
            if (list_block(bl)->Bflags & BFLoutsideprolog)
            {
                if (mark == 2)
                    goto L1;
                mark = 1;
            }
            else
            {
                if (mark == 1)
                    goto L1;
                mark = 2;
            }
        }
        if (mark == 1)
        {
            if (bp)             // if already have one
                goto L1;
            bp = b;
        }

        // See if b is an epilog
        mark = 0;
        for (bl = b->Bsucc; bl; bl = list_next(bl))
        {
            if (list_block(bl)->Bflags & BFLoutsideprolog)
            {
                if (mark == 2)
                    goto L1;
                mark = 1;
            }
            else
            {
                if (mark == 1)
                    goto L1;
                mark = 2;
            }
        }
        if (mark == 1 || b->BC == BCret || b->BC == BCretexp)
        {   b->Bflags |= BFLepilog;
            nepis++;
            if (nepis > 1 && config.flags4 & CFG4space)
                goto L1;
        }
    }
    if (bp)
    {   bp->Bflags |= BFLprolog;
        //printf("=============== prolog opt\n");
    }
}
Exemplo n.º 15
0
    void visit(TypeStruct *t)
    {
        //printf("TypeStruct::toCtype() '%s'\n", t->sym->toChars());
        Type *tm = t->mutableOf();
        if (tm->ctype)
        {
            t->ctype = type_alloc(tybasic(tm->ctype->Tty));
            t->ctype->Tcount++;
            if (t->ctype->Tty == TYstruct)
            {
                Symbol *s = tm->ctype->Ttag;
                t->ctype->Ttag = (Classsym *)s;            // structure tag name
            }
            // Add modifiers
            switch (t->mod)
            {
                case 0:
                    assert(0);
                    break;
                case MODconst:
                case MODwild:
                case MODwildconst:
                    t->ctype->Tty |= mTYconst;
                    break;
                case MODshared:
                    t->ctype->Tty |= mTYshared;
                    break;
                case MODshared | MODconst:
                case MODshared | MODwild:
                case MODshared | MODwildconst:
                    t->ctype->Tty |= mTYshared | mTYconst;
                    break;
                case MODimmutable:
                    t->ctype->Tty |= mTYimmutable;
                    break;
                default:
                    assert(0);
            }
        }
        else
        {
            StructDeclaration *sym = t->sym;
            if (sym->ident == Id::__c_long_double)
            {
                t->ctype = type_fake(TYdouble);
                t->ctype->Tcount++;
                return;
            }
            t->ctype = type_struct_class(sym->toPrettyChars(true), sym->alignsize, sym->structsize,
                    sym->arg1type ? Type_toCtype(sym->arg1type) : NULL,
                    sym->arg2type ? Type_toCtype(sym->arg2type) : NULL,
                    sym->isUnionDeclaration() != 0,
                    false,
                    sym->isPOD() != 0);

            tm->ctype = t->ctype;

            /* Add in fields of the struct
             * (after setting ctype to avoid infinite recursion)
             */
            if (global.params.symdebug)
            {
                for (size_t i = 0; i < sym->fields.dim; i++)
                {
                    VarDeclaration *v = sym->fields[i];
                    symbol_struct_addField(t->ctype->Ttag, v->ident->toChars(), Type_toCtype(v->type), v->offset);
                }
            }
        }

        //printf("t = %p, Tflags = x%x\n", ctype, ctype->Tflags);
    }
Exemplo n.º 16
0
Arquivo: cgxmm.c Projeto: davispuh/dmd
code *xmmpost(elem *e,regm_t *pretregs)
{
    elem *e1 = e->E1;
    elem *e2 = e->E2;
    tym_t ty1 = tybasic(e1->Ety);

    CodeBuilder cdb;

    regm_t retregs;
    unsigned reg;
    bool regvar = FALSE;
    if (config.flags4 & CFG4optimized)
    {
        // Be careful of cases like (x = x+x+x). We cannot evaluate in
        // x if x is in a register.
        unsigned varreg;
        regm_t varregm;
        if (isregvar(e1,&varregm,&varreg) &&    // if lvalue is register variable
            doinreg(e1->EV.sp.Vsym,e2)          // and we can compute directly into it
           )
        {
            regvar = TRUE;
            retregs = varregm;
            reg = varreg;                       // evaluate directly in target register
            cdb.append(getregs(retregs));       // destroy these regs
        }
    }

    code cs;
    if (!regvar)
    {
        code *c = getlvalue(&cs,e1,0);          // get EA
        cdb.append(c);
        retregs = XMMREGS & ~*pretregs;
        if (!retregs)
            retregs = XMMREGS;
        c = allocreg(&retregs,&reg,ty1);
        cdb.append(c);
        cs.Iop = xmmload(ty1, true);            // MOVSD xmm,xmm_m64
        code_newreg(&cs,reg - XMM0);
        cdb.gen(&cs);
        checkSetVex(cdb.last(), ty1);
    }

    // Result register
    regm_t resultregs = XMMREGS & *pretregs & ~retregs;
    if (!resultregs)
        resultregs = XMMREGS & ~retregs;
    unsigned resultreg;
    code *c = allocreg(&resultregs, &resultreg, ty1);
    cdb.append(c);

    cdb.gen2(xmmload(ty1,true),modregxrmx(3,resultreg-XMM0,reg-XMM0));   // MOVSS/D resultreg,reg
    checkSetVex(cdb.last(), ty1);

    regm_t rretregs = XMMREGS & ~(*pretregs | retregs | resultregs);
    if (!rretregs)
        rretregs = XMMREGS & ~(retregs | resultregs);
    c = codelem(e2,&rretregs,FALSE); // eval right leaf
    cdb.append(c);
    unsigned rreg = findreg(rretregs);

    unsigned op = xmmoperator(e1->Ety, e->Eoper);
    cdb.gen2(op,modregxrmx(3,reg-XMM0,rreg-XMM0));  // ADD reg,rreg
    checkSetVex(cdb.last(), e1->Ety);

    if (!regvar)
    {
        cs.Iop = xmmstore(ty1,true);      // reverse operand order of MOVS[SD]
        cdb.gen(&cs);
        checkSetVex(cdb.last(), ty1);
    }

    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,resultregs,pretregs));
    freenode(e1);
    return cdb.finish();
}
Exemplo n.º 17
0
Arquivo: debug.c Projeto: spott/dmd
void WReqn(elem *e)
{ static int nest;

  if (!e)
        return;
  if (OTunary(e->Eoper))
  {
        WROP(e->Eoper);
        if (OTbinary(e->E1->Eoper))
        {       nest++;
                ferr("(");
                WReqn(e->E1);
                ferr(")");
                nest--;
        }
        else
                WReqn(e->E1);
  }
  else if (e->Eoper == OPcomma && !nest)
  {     WReqn(e->E1);
        dbg_printf(";\n\t");
        WReqn(e->E2);
  }
  else if (OTbinary(e->Eoper))
  {
        if (OTbinary(e->E1->Eoper))
        {       nest++;
                ferr("(");
                WReqn(e->E1);
                ferr(")");
                nest--;
        }
        else
                WReqn(e->E1);
        ferr(" ");
        WROP(e->Eoper);
        if (e->Eoper == OPstreq)
            dbg_printf("%ld",(long)type_size(e->ET));
        ferr(" ");
        if (OTbinary(e->E2->Eoper))
        {       nest++;
                ferr("(");
                WReqn(e->E2);
                ferr(")");
                nest--;
        }
        else
                WReqn(e->E2);
  }
  else
  {
        switch (e->Eoper)
        {   case OPconst:
                switch (tybasic(e->Ety))
                {
                    case TYfloat:
                        dbg_printf("%g <float> ",e->EV.Vfloat);
                        break;
                    case TYdouble:
                        dbg_printf("%g ",e->EV.Vdouble);
                        break;
                    case TYldouble:
                        dbg_printf("%Lg ",e->EV.Vldouble);
                        break;
                    case TYcent:
                    case TYucent:
                        dbg_printf("%lld+%lld ", e->EV.Vcent.msw, e->EV.Vcent.lsw);
                        break;
                    default:
                        dbg_printf("%lld ",el_tolong(e));
                        break;
                }
                break;
            case OPrelconst:
                ferr("#");
                /* FALL-THROUGH */
            case OPvar:
                dbg_printf("%s",e->EV.sp.Vsym->Sident);
                if (e->EV.sp.Vsym->Ssymnum != -1)
                    dbg_printf("(%d)",e->EV.sp.Vsym->Ssymnum);
                if (e->Eoffset != 0)
                {
                    if (sizeof(e->Eoffset) == 8)
                        dbg_printf(".x%llx", e->Eoffset);
                    else
                        dbg_printf(".%ld",(long)e->Eoffset);
                }
                break;
            case OPasm:
            case OPstring:
                dbg_printf("\"%s\"",e->EV.ss.Vstring);
                if (e->EV.ss.Voffset)
                    dbg_printf("+%ld",(long)e->EV.ss.Voffset);
                break;
            case OPmark:
            case OPgot:
            case OPframeptr:
            case OPhalt:
                WROP(e->Eoper);
                break;
            case OPstrthis:
                break;
            default:
                WROP(e->Eoper);
                assert(0);
        }
  }
}
Exemplo n.º 18
0
Arquivo: cgxmm.c Projeto: davispuh/dmd
static unsigned xmmoperator(tym_t tym, unsigned oper)
{
    tym = tybasic(tym);
    unsigned op;
    switch (oper)
    {
        case OPadd:
        case OPaddass:
        case OPpostinc:
            switch (tym)
            {
                case TYfloat:
                case TYifloat:  op = ADDSS;  break;
                case TYdouble:
                case TYidouble: op = ADDSD;  break;

                // SIMD vector types
                case TYfloat8:
                case TYfloat4:  op = ADDPS;  break;
                case TYdouble4:
                case TYdouble2: op = ADDPD;  break;
                case TYschar32:
                case TYuchar32:
                case TYschar16:
                case TYuchar16: op = PADDB;  break;
                case TYshort16:
                case TYushort16:
                case TYshort8:
                case TYushort8: op = PADDW;  break;
                case TYlong8:
                case TYulong8:
                case TYlong4:
                case TYulong4:  op = PADDD;  break;
                case TYllong4:
                case TYullong4:
                case TYllong2:
                case TYullong2: op = PADDQ;  break;

                default:
                    printf("tym = x%x\n", tym);
                    assert(0);
            }
            break;

        case OPmin:
        case OPminass:
        case OPpostdec:
            switch (tym)
            {
                case TYfloat:
                case TYifloat:  op = SUBSS;  break;
                case TYdouble:
                case TYidouble: op = SUBSD;  break;

                // SIMD vector types
                case TYfloat8:
                case TYfloat4:  op = SUBPS;  break;
                case TYdouble4:
                case TYdouble2: op = SUBPD;  break;
                case TYschar32:
                case TYuchar32:
                case TYschar16:
                case TYuchar16: op = PSUBB;  break;
                case TYshort16:
                case TYushort16:
                case TYshort8:
                case TYushort8: op = PSUBW;  break;
                case TYlong8:
                case TYulong8:
                case TYlong4:
                case TYulong4:  op = PSUBD;  break;
                case TYllong4:
                case TYullong4:
                case TYllong2:
                case TYullong2: op = PSUBQ;  break;

                default:        assert(0);
            }
            break;

        case OPmul:
        case OPmulass:
            switch (tym)
            {
                case TYfloat:
                case TYifloat:  op = MULSS;  break;
                case TYdouble:
                case TYidouble: op = MULSD;  break;

                // SIMD vector types
                case TYfloat8:
                case TYfloat4:  op = MULPS;  break;
                case TYdouble4:
                case TYdouble2: op = MULPD;  break;
                case TYshort16:
                case TYushort16:
                case TYshort8:
                case TYushort8: op = PMULLW; break;

                default:        assert(0);
            }
            break;

        case OPdiv:
        case OPdivass:
            switch (tym)
            {
                case TYfloat:
                case TYifloat:  op = DIVSS;  break;
                case TYdouble:
                case TYidouble: op = DIVSD;  break;

                // SIMD vector types
                case TYfloat8:
                case TYfloat4:  op = DIVPS;  break;
                case TYdouble4:
                case TYdouble2: op = DIVPD;  break;

                default:        assert(0);
            }
            break;

        case OPor:
        case OPorass:
            switch (tym)
            {
                // SIMD vector types
                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 = POR; break;

                default:        assert(0);
            }
            break;

        case OPand:
        case OPandass:
            switch (tym)
            {
                // SIMD vector types
                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 = PAND; break;

                default:        assert(0);
            }
            break;

        case OPxor:
        case OPxorass:
            switch (tym)
            {
                // SIMD vector types
                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 = PXOR; break;

                default:        assert(0);
            }
            break;

        case OPlt:
        case OPle:
        case OPgt:
        case OPge:
        case OPne:
        case OPeqeq:
        case OPunord:        /* !<>=         */
        case OPlg:           /* <>           */
        case OPleg:          /* <>=          */
        case OPule:          /* !>           */
        case OPul:           /* !>=          */
        case OPuge:          /* !<           */
        case OPug:           /* !<=          */
        case OPue:           /* !<>          */
        case OPngt:
        case OPnge:
        case OPnlt:
        case OPnle:
        case OPord:
        case OPnlg:
        case OPnleg:
        case OPnule:
        case OPnul:
        case OPnuge:
        case OPnug:
        case OPnue:
            switch (tym)
            {
                case TYfloat:
                case TYifloat:  op = UCOMISS;  break;
                case TYdouble:
                case TYidouble: op = UCOMISD;  break;

                default:        assert(0);
            }
            break;

        default:
            assert(0);
    }
    return op;
}
Exemplo n.º 19
0
void type_print(type *t)
{
  type_debug(t);
  dbg_printf("Tty="); WRTYxx(t->Tty);
  dbg_printf(" Tmangle=%d",t->Tmangle);
  dbg_printf(" Tflags=x%x",t->Tflags);
  dbg_printf(" Tcount=%d",t->Tcount);
  if (!(t->Tflags & TFsizeunknown) &&
        tybasic(t->Tty) != TYvoid &&
        tybasic(t->Tty) != TYident &&
        tybasic(t->Tty) != TYtemplate &&
        tybasic(t->Tty) != TYmfunc &&
        tybasic(t->Tty) != TYarray)
      dbg_printf(" Tsize=%lld",(long long)type_size(t));
  dbg_printf(" Tnext=%p",t->Tnext);
  switch (tybasic(t->Tty))
  {     case TYstruct:
        case TYmemptr:
            dbg_printf(" Ttag=%p,'%s'",t->Ttag,t->Ttag->Sident);
            //dbg_printf(" Sfldlst=%p",t->Ttag->Sstruct->Sfldlst);
            break;

        case TYarray:
            dbg_printf(" Tdim=%ld",(long)t->Tdim);
            break;

        case TYident:
            dbg_printf(" Tident='%s'",t->Tident);
            break;
        case TYtemplate:
            dbg_printf(" Tsym='%s'",((typetemp_t *)t)->Tsym->Sident);
            {   param_t *p;
                int i;

                i = 1;
                for (p = t->Tparamtypes; p; p = p->Pnext)
                {   dbg_printf("\nTP%d (%p): ",i++,p);
                    fflush(stdout);

dbg_printf("Pident=%p,Ptype=%p,Pelem=%p,Pnext=%p ",p->Pident,p->Ptype,p->Pelem,p->Pnext);
                    param_debug(p);
                    if (p->Pident)
                        printf("'%s' ", p->Pident);
                    if (p->Ptype)
                        type_print(p->Ptype);
                    if (p->Pelem)
                        elem_print(p->Pelem);
                }
            }
            break;

        default:
            if (tyfunc(t->Tty))
            {   param_t *p;
                int i;

                i = 1;
                for (p = t->Tparamtypes; p; p = p->Pnext)
                {   dbg_printf("\nP%d (%p): ",i++,p);
                    fflush(stdout);

dbg_printf("Pident=%p,Ptype=%p,Pelem=%p,Pnext=%p ",p->Pident,p->Ptype,p->Pelem,p->Pnext);
                    param_debug(p);
                    if (p->Pident)
                        printf("'%s' ", p->Pident);
                    type_print(p->Ptype);
                }
            }
            break;
  }
  dbg_printf("\n");
  if (t->Tnext) type_print(t->Tnext);
}
Exemplo n.º 20
0
void sliceStructs()
{
    if (debugc) printf("sliceStructs()\n");
    size_t sia_length = globsym.top;
    /* 3 is because it is used for two arrays, sia[] and sia2[].
     * sia2[] can grow to twice the size of sia[], as symbols can get split into two.
     */
    SymInfo *sia = (SymInfo *)malloc(3 * sia_length * sizeof(SymInfo));
    assert(sia);
    SymInfo *sia2 = sia + sia_length;

    bool anySlice = false;
    for (int si = 0; si < globsym.top; si++)
    {
        Symbol *s = globsym.tab[si];
        //printf("slice1: %s\n", s->Sident);

        if ((s->Sflags & (GTregcand | SFLunambig)) != (GTregcand | SFLunambig))
        {
            sia[si].canSlice = false;
            continue;
        }

        targ_size_t sz = type_size(s->Stype);
        if (sz != 2 * REGSIZE ||
            tyfv(s->Stype->Tty) || tybasic(s->Stype->Tty) == TYhptr)    // because there is no TYseg
        {
            sia[si].canSlice = false;
            continue;
        }

        switch (s->Sclass)
        {
            case SCfastpar:
            case SCregister:
            case SCauto:
            case SCshadowreg:
            case SCparameter:
                anySlice = true;
                sia[si].canSlice = true;
                sia[si].accessSlice = false;
                // We can't slice whole XMM registers
                if (tyxmmreg(s->Stype->Tty) &&
                    s->Spreg >= XMM0 && s->Spreg <= XMM15 && s->Spreg2 == NOREG)
                {
                    sia[si].canSlice = false;
                }
                break;

            case SCstack:
            case SCpseudo:
            case SCstatic:
            case SCbprel:
                sia[si].canSlice = false;
                break;

            default:
                symbol_print(s);
                assert(0);
        }
    }

    if (!anySlice)
        goto Ldone;

    for (block *b = startblock; b; b = b->Bnext)
    {
        if (b->BC == BCasm)
            goto Ldone;
        if (b->Belem)
            sliceStructs_Gather(sia, b->Belem);
    }

    {   // scope needed because of goto skipping declarations
        bool any = false;
        int n = 0;              // the number of symbols added
        for (int si = 0; si < sia_length; si++)
        {
            sia2[si + n].canSlice = false;
            if (sia[si].canSlice)
            {
                // If never did access it as a slice, don't slice
                if (!sia[si].accessSlice)
                {
                    sia[si].canSlice = false;
                    continue;
                }

                /* Split slice-able symbol sold into two symbols,
                 * (sold,snew) in adjacent slots in the symbol table.
                 */
                Symbol *sold = globsym.tab[si + n];

                size_t idlen = 2 + strlen(sold->Sident) + 2;
                char *id = (char *)malloc(idlen + 1);
                assert(id);
                sprintf(id, "__%s_%d", sold->Sident, REGSIZE);
                if (debugc) printf("creating slice symbol %s\n", id);
                Symbol *snew = symbol_calloc(id, idlen);
                free(id);
                snew->Sclass = sold->Sclass;
                snew->Sfl = sold->Sfl;
                snew->Sflags = sold->Sflags;
                if (snew->Sclass == SCfastpar || snew->Sclass == SCshadowreg)
                {
                    snew->Spreg = sold->Spreg2;
                    snew->Spreg2 = NOREG;
                    sold->Spreg2 = NOREG;
                }
                type_free(sold->Stype);
                sold->Stype = type_fake(sia[si].ty0);
                sold->Stype->Tcount++;
                snew->Stype = type_fake(sia[si].ty1);
                snew->Stype->Tcount++;

                SYMIDX sinew = symbol_add(snew);
                for (int i = sinew; i > si + n + 1; --i)
                {
                    globsym.tab[i] = globsym.tab[i - 1];
                    globsym.tab[i]->Ssymnum += 1;
                }
                globsym.tab[si + n + 1] = snew;
                snew->Ssymnum = si + n + 1;

                sia2[si + n].canSlice = true;
                sia2[si + n].si0 = si + n;
                sia2[si + n].ty0 = sia[si].ty0;
                sia2[si + n].ty1 = sia[si].ty1;
                ++n;
                any = true;
            }
        }
        if (!any)
            goto Ldone;
    }

    for (int si = 0; si < globsym.top; si++)
    {
        Symbol *s = globsym.tab[si];
        assert(s->Ssymnum == si);
    }

    for (block *b = startblock; b; b = b->Bnext)
    {
        if (b->Belem)
            sliceStructs_Replace(sia2, b->Belem);
    }

Ldone:
    free(sia);
}
Exemplo n.º 21
0
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 = LNGDBLSIZE;
                    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;
}
Exemplo n.º 22
0
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;
        }
    }
}
Exemplo n.º 23
0
void outdata(symbol *s)
{
#if HTOD
    return;
#endif
    dt_t *dtstart,*dt;
    targ_size_t datasize,a;
    int seg;
    targ_size_t offset;
    int flags;
    char *p;
    tym_t ty;
    int tls;

    symbol_debug(s);
#ifdef DEBUG
    debugy && dbg_printf("outdata('%s')\n",s->Sident);
#endif
    //printf("outdata('%s', ty=x%x)\n",s->Sident,s->Stype->Tty);
    //symbol_print(s);

    // Data segment variables are always live on exit from a function
    s->Sflags |= SFLlivexit;

    dtstart = s->Sdt;
    s->Sdt = NULL;                      // it will be free'd
#if SCPP && TARGET_WINDOS
    if (eecontext.EEcompile)
    {   s->Sfl = (s->ty() & mTYfar) ? FLfardata : FLextern;
        s->Sseg = UNKNOWN;
        goto Lret;                      // don't output any data
    }
#endif
    datasize = 0;
    tls = 0;
    ty = s->ty();
    if (ty & mTYexport && config.wflags & WFexpdef && s->Sclass != SCstatic)
        obj_export(s,0);        // export data definition
    for (dt = dtstart; dt; dt = dt->DTnext)
    {
        //printf("dt = %p, dt = %d\n",dt,dt->dt);
        switch (dt->dt)
        {   case DT_abytes:
            {   // Put out the data for the string, and
                // reserve a spot for a pointer to that string
#if ELFOBJ || MACHOBJ
                datasize += size(dt->Dty);
                dt->DTabytes += elf_data_cdata(dt->DTpbytes,dt->DTnbytes,&dt->DTseg);
#else
                targ_size_t *poffset;
                datasize += size(dt->Dty);
                if (tybasic(dt->Dty) == TYcptr)
                {   seg = cseg;
                    poffset = &Coffset;
                }
#if SCPP
                else if (tybasic(dt->Dty) == TYfptr &&
                         dt->DTnbytes > config.threshold)
                {
                    seg = obj_fardata(s->Sident,dt->DTnbytes,&offset);
                    poffset = &offset;
                }
#endif
                else
                {   seg = DATA;
                    poffset = &Doffset;
                }
                dt->DTseg = seg;
                dt->DTabytes += *poffset;
                obj_bytes(seg,*poffset,dt->DTnbytes,dt->DTpbytes);
                *poffset += dt->DTnbytes;
#endif
                break;
            }
            case DT_ibytes:
                datasize += dt->DTn;
                break;
            case DT_nbytes:
                //printf("DT_nbytes %d\n", dt->DTnbytes);
                datasize += dt->DTnbytes;
                break;
            case DT_symsize:
#if MARS
                assert(0);
#else
                dt->DTazeros = type_size(s->Stype);
#endif
                goto case_azeros;
            case DT_azeros:
                /* A block of zeros
                 */
                //printf("DT_azeros %d\n", dt->DTazeros);
            case_azeros:
                datasize += dt->DTazeros;
                if (dt == dtstart && !dt->DTnext && s->Sclass != SCcomdat)
                {   /* first and only, so put in BSS segment
                     */
                    switch (ty & mTYLINK)
                    {
#if OMFOBJ
                        case mTYfar:                    // if far data
                            seg = obj_fardata(s->Sident,datasize,&s->Soffset);
                            s->Sfl = FLfardata;
                            break;
#endif
                        case mTYcs:
                            seg = cseg;
                            Coffset = align(datasize,Coffset);
                            s->Soffset = Coffset;
                            Coffset += datasize;
                            s->Sfl = FLcsdata;
                            break;
                        case mTYthread:
                        {   seg_data *pseg = obj_tlsseg_bss();
#if ELFOBJ || MACHOBJ
                            s->Sseg = pseg->SDseg;
                            elf_data_start(s, datasize, pseg->SDseg);
                            obj_lidata(pseg->SDseg, pseg->SDoffset, datasize);
#else
                            targ_size_t TDoffset = pseg->SDoffset;
                            TDoffset = align(datasize,TDoffset);
                            s->Soffset = TDoffset;
                            TDoffset += datasize;
                            pseg->SDoffset = TDoffset;
#endif
                            seg = pseg->SDseg;
                            s->Sfl = FLtlsdata;
                            tls = 1;
                            break;
                        }
                        default:
#if ELFOBJ || MACHOBJ
                            seg = elf_data_start(s,datasize,UDATA);
                            obj_lidata(s->Sseg,s->Soffset,datasize);
#else
                            seg = UDATA;
                            UDoffset = align(datasize,UDoffset);
                            s->Soffset = UDoffset;
                            UDoffset += datasize;
#endif
                            s->Sfl = FLudata;           // uninitialized data
                            break;
                    }
#if ELFOBJ || MACHOBJ
                    assert(s->Sseg != UNKNOWN);
                    if (s->Sclass == SCglobal || s->Sclass == SCstatic)
                        objpubdef(s->Sseg,s,s->Soffset);        /* do the definition    */
                                            /* if a pubdef to be done */
#else
                    s->Sseg = seg;
                    if (s->Sclass == SCglobal)          /* if a pubdef to be done */
                        objpubdef(seg,s,s->Soffset);    /* do the definition    */
#endif
                    searchfixlist(s);
                    if (config.fulltypes &&
                        !(s->Sclass == SCstatic && funcsym_p)) // not local static
                        cv_outsym(s);
#if SCPP
                    out_extdef(s);
#endif
                    goto Lret;
                }
                break;
            case DT_common:
                assert(!dt->DTnext);
                outcommon(s,dt->DTazeros);
                goto Lret;

            case DT_xoff:
            {   symbol *sb = dt->DTsym;

                if (tyfunc(sb->ty()))
#if SCPP
                    nwc_mustwrite(sb);
#else
                    ;
#endif
                else if (sb->Sdt)               // if initializer for symbol
                    outdata(sb);                // write out data for symbol
            }
            case DT_coff:
                datasize += size(dt->Dty);
                break;
            case DT_1byte:
                datasize++;
                break;
            default:
#ifdef DEBUG
                dbg_printf("dt = %p, dt = %d\n",dt,dt->dt);
#endif
                assert(0);
        }
    }
Exemplo n.º 24
0
void FuncDeclaration_toObjFile(FuncDeclaration *fd, bool multiobj)
{
    ClassDeclaration *cd = fd->parent->isClassDeclaration();
    //printf("FuncDeclaration::toObjFile(%p, %s.%s)\n", fd, fd->parent->toChars(), fd->toChars());

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

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

    if (fd->type && fd->type->ty == Tfunction && ((TypeFunction *)fd->type)->next == NULL)
        return;

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

    if (fd->semantic3Errors)
        return;

    if (global.errors)
        return;

    if (!fd->fbody)
        return;

    UnitTestDeclaration *ud = fd->isUnitTestDeclaration();
    if (ud && !global.params.useUnitTests)
        return;

    if (multiobj && !fd->isStaticDtorDeclaration() && !fd->isStaticCtorDeclaration())
    {
        obj_append(fd);
        return;
    }

    if (fd->semanticRun == PASSsemanticdone)
    {
        /* What happened is this function failed semantic3() with errors,
         * but the errors were gagged.
         * Try to reproduce those errors, and then fail.
         */
        fd->error("errors compiling the function");
        return;
    }
    assert(fd->semanticRun == PASSsemantic3done);
    assert(fd->ident != Id::empty);

    for (FuncDeclaration *fd2 = fd; fd2; )
    {
        if (fd2->inNonRoot())
            return;
        if (fd2->isNested())
            fd2 = fd2->toParent2()->isFuncDeclaration();
        else
            break;
    }

    if (UnitTestDeclaration *udp = needsDeferredNested(fd))
    {
        /* Can't do unittest's out of order, they are order dependent in that their
         * execution is done in lexical order.
         */
        udp->deferredNested.push(fd);
        //printf("%s @[%s]\n\t--> pushed to unittest @[%s]\n",
        //    fd->toPrettyChars(), fd->loc.toChars(), udp->loc.toChars());
        return;
    }

    if (fd->isArrayOp && isDruntimeArrayOp(fd->ident))
    {
        // Implementation is in druntime
        return;
    }

    // start code generation
    fd->semanticRun = PASSobj;

    if (global.params.verbose)
        fprintf(global.stdmsg, "function  %s\n", fd->toPrettyChars());

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

    // tunnel type of "this" to debug info generation
    if (AggregateDeclaration* ad = fd->parent->isAggregateDeclaration())
    {
        ::type* t = Type_toCtype(ad->getType());
        if (cd)
            t = t->Tnext; // skip reference
        f->Fclass = (Classsym *)t;
    }

    /* 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 (fd->isVirtual() && (fd->fensure || fd->frequire))
        f->Fflags3 |= Ffakeeh;

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

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

    if (fd->inlinedNestedCallees)
    {
        /* Bugzilla 15333: If fd contains inlined expressions that come from
         * nested function bodies, the enclosing of the functions must be
         * generated first, in order to calculate correct frame pointer offset.
         */
        for (size_t i = 0; i < fd->inlinedNestedCallees->dim; i++)
        {
            FuncDeclaration *f = (*fd->inlinedNestedCallees)[i];
            FuncDeclaration *fp = f->toParent2()->isFuncDeclaration();;
            if (fp && fp->semanticRun < PASSobj)
            {
                toObjFile(fp, multiobj);
            }
        }
    }

    if (fd->isNested())
    {
        //if (!(config.flags3 & CFG3pic))
        //    s->Sclass = SCstatic;
        f->Fflags3 |= Fnested;

        /* The enclosing function must have its code generated first,
         * in order to calculate correct frame pointer offset.
         */
        FuncDeclaration *fdp = fd->toParent2()->isFuncDeclaration();
        if (fdp && fdp->semanticRun < PASSobj)
        {
            toObjFile(fdp, multiobj);
        }
    }
    else
    {
        const char *libname = (global.params.symdebug)
                                ? global.params.debuglibname
                                : global.params.defaultlibname;

        // Pull in RTL startup code (but only once)
        if (fd->isMain() && onlyOneMain(fd->loc))
        {
#if TARGET_LINUX || TARGET_OSX || TARGET_FREEBSD || TARGET_OPENBSD || TARGET_SOLARIS
            objmod->external_def("_main");
            objmod->ehsections();   // initialize exception handling sections
#endif
            if (global.params.mscoff)
            {
                objmod->external_def("main");
                objmod->ehsections();   // initialize exception handling sections
            }
            else if (config.exe == EX_WIN32)
            {
                objmod->external_def("_main");
                objmod->external_def("__acrtused_con");
            }
            objmod->includelib(libname);
            s->Sclass = SCglobal;
        }
        else if (strcmp(s->Sident, "main") == 0 && fd->linkage == LINKc)
        {
            if (global.params.mscoff)
            {
                objmod->includelib("LIBCMT");
                objmod->includelib("OLDNAMES");
            }
            else if (config.exe == EX_WIN32)
            {
                objmod->external_def("__acrtused_con");        // bring in C startup code
                objmod->includelib("snn.lib");          // bring in C runtime library
            }
            s->Sclass = SCglobal;
        }
#if TARGET_WINDOS
        else if (fd->isWinMain() && onlyOneMain(fd->loc))
        {
            if (global.params.mscoff)
            {
                objmod->includelib("uuid");
                objmod->includelib("LIBCMT");
                objmod->includelib("OLDNAMES");
                objmod->ehsections();   // initialize exception handling sections
            }
            else
            {
                objmod->external_def("__acrtused");
            }
            objmod->includelib(libname);
            s->Sclass = SCglobal;
        }

        // Pull in RTL startup code
        else if (fd->isDllMain() && onlyOneMain(fd->loc))
        {
            if (global.params.mscoff)
            {
                objmod->includelib("uuid");
                objmod->includelib("LIBCMT");
                objmod->includelib("OLDNAMES");
                objmod->ehsections();   // initialize exception handling sections
            }
            else
            {
                objmod->external_def("__acrtused_dll");
            }
            objmod->includelib(libname);
            s->Sclass = SCglobal;
        }
#endif
    }

    symtab_t *symtabsave = cstate.CSpsymtab;
    cstate.CSpsymtab = &f->Flocsym;

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

    IRState irs(m, fd);
    Dsymbols deferToObj;                   // write these to OBJ file later
    irs.deferToObj = &deferToObj;
    void *labels = NULL;
    irs.labels = &labels;

    symbol *shidden = NULL;
    Symbol *sthis = NULL;
    tym_t tyf = tybasic(s->Stype->Tty);
    //printf("linkage = %d, tyf = x%x\n", linkage, tyf);
    int reverse = tyrevfunc(s->Stype->Tty);

    assert(fd->type->ty == Tfunction);
    TypeFunction *tf = (TypeFunction *)fd->type;
    RET retmethod = retStyle(tf);
    if (retmethod == RETstack)
    {
        // If function returns a struct, put a pointer to that
        // as the first argument
        ::type *thidden = Type_toCtype(tf->next->pointerTo());
        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 (fd->nrvo_can && fd->nrvo_var && fd->nrvo_var->nestedrefs.dim)
            type_setcv(&shidden->Stype, shidden->Stype->Tty | mTYvolatile);
        irs.shidden = shidden;
        fd->shidden = shidden;
    }
    else
    {
        // Register return style cannot make nrvo.
        // Auto functions keep the nrvo_can flag up to here,
        // so we should eliminate it before entering backend.
        fd->nrvo_can = 0;
    }

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

    // Estimate number of parameters, pi
    size_t pi = (fd->v_arguments != NULL);
    if (fd->parameters)
        pi += fd->parameters->dim;

    // Create a temporary buffer, params[], to hold function parameters
    Symbol *paramsbuf[10];
    Symbol **params = paramsbuf;    // allocate on stack if possible
    if (pi + 2 > 10)                // allow extra 2 for sthis and shidden
    {
        params = (Symbol **)malloc((pi + 2) * sizeof(Symbol *));
        assert(params);
    }

    // Get the actual number of parameters, pi, and fill in the params[]
    pi = 0;
    if (fd->v_arguments)
    {
        params[pi] = toSymbol(fd->v_arguments);
        pi += 1;
    }
    if (fd->parameters)
    {
        for (size_t i = 0; i < fd->parameters->dim; i++)
        {
            VarDeclaration *v = (*fd->parameters)[i];
            //printf("param[%d] = %p, %s\n", i, v, v->toChars());
            assert(!v->csym);
            params[pi + i] = toSymbol(v);
        }
        pi += fd->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) &&
         fd->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)
    {
        FuncParamRegs fpr(tyf);

        for (size_t i = 0; i < pi; i++)
        {
            Symbol *sp = params[i];
            if (fpr.alloc(sp->Stype, sp->Stype->Tty, &sp->Spreg, &sp->Spreg2))
            {
                sp->Sclass = (config.exe == EX_WIN64) ? SCshadowreg : SCfastpar;
                sp->Sfl = (sp->Sclass == SCshadowreg) ? FLpara : FLfast;
            }
        }
    }

    // Done with params
    if (params != paramsbuf)
        free(params);
    params = NULL;

    if (fd->fbody)
    {
        localgot = NULL;

        Statement *sbody = fd->fbody;

        Blockx bx;
        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 = fd;
        bx.module = fd->getModule();
        irs.blx = &bx;

        // Initialize argptr
        if (fd->v_argptr)
        {
            // Declare va_argsave
            if (global.params.is64bit &&
                !global.params.isWindows)
            {
                type *t = type_struct_class("__va_argsave_t", 16, 8 * 6 + 8 * 16 + 8 * 3, NULL, NULL, false, false, true);
                // The backend will pick this up by name
                Symbol *s = symbol_name("__va_argsave", SCauto, t);
                s->Stype->Tty |= mTYvolatile;
                symbol_add(s);
            }

            Symbol *s = toSymbol(fd->v_argptr);
            symbol_add(s);
            elem *e = el_una(OPva_start, TYnptr, el_ptr(s));
            block_appendexp(irs.blx->curblock, e);
        }

        /* Doing this in semantic3() caused all kinds of problems:
         * 1. couldn't reliably get the final mangling of the function name due to fwd refs
         * 2. impact on function inlining
         * 3. what to do when writing out .di files, or other pretty printing
         */
        if (global.params.trace && !fd->isCMain())
        {
            /* The profiler requires TLS, and TLS may not be set up yet when C main()
             * gets control (i.e. OSX), leading to a crash.
             */
            /* Wrap the entire function body in:
             *   trace_pro("funcname");
             *   try
             *     body;
             *   finally
             *     _c_trace_epi();
             */
            StringExp *se = StringExp::create(Loc(), s->Sident);
            se->type = Type::tstring;
            se->type = se->type->semantic(Loc(), NULL);
            Expressions *exps = Expressions_create();
            exps->push(se);
            FuncDeclaration *fdpro = FuncDeclaration::genCfunc(NULL, Type::tvoid, "trace_pro");
            Expression *ec = VarExp::create(Loc(), fdpro);
            Expression *e = CallExp::create(Loc(), ec, exps);
            e->type = Type::tvoid;
            Statement *sp = ExpStatement::create(fd->loc, e);

            FuncDeclaration *fdepi = FuncDeclaration::genCfunc(NULL, Type::tvoid, "_c_trace_epi");
            ec = VarExp::create(Loc(), fdepi);
            e = CallExp::create(Loc(), ec);
            e->type = Type::tvoid;
            Statement *sf = ExpStatement::create(fd->loc, e);

            Statement *stf;
            if (sbody->blockExit(fd, false) == BEfallthru)
                stf = CompoundStatement::create(Loc(), sbody, sf);
            else
                stf = TryFinallyStatement::create(Loc(), sbody, sf);
            sbody = CompoundStatement::create(Loc(), sp, stf);
        }

        if (fd->interfaceVirtual)
        {
            // Adjust the 'this' pointer instead of using a thunk
            assert(irs.sthis);
            elem *ethis = el_var(irs.sthis);
            elem *e = el_bin(OPminass, TYnptr, ethis, el_long(TYsize_t, fd->interfaceVirtual->offset));
            block_appendexp(irs.blx->curblock, e);
        }

        buildClosure(fd, &irs);

        if (config.ehmethod == EH_WIN32 && fd->isSynchronized() && cd &&
            !fd->isStatic() && !sbody->usesEH() && !global.params.trace)
        {
            /* The "jmonitor" hack uses an optimized exception handling frame
             * which is a little shorter than the more general EH frame.
             */
            s->Sfunc->Fflags3 |= Fjmonitor;
        }

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

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

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

    // If static constructor
    if (fd->isSharedStaticCtorDeclaration())        // must come first because it derives from StaticCtorDeclaration
    {
        ssharedctors.push(s);
    }
    else if (fd->isStaticCtorDeclaration())
    {
        sctors.push(s);
    }

    // If static destructor
    if (fd->isSharedStaticDtorDeclaration())        // must come first because it derives from StaticDtorDeclaration
    {
        SharedStaticDtorDeclaration *f = fd->isSharedStaticDtorDeclaration();
        assert(f);
        if (f->vgate)
        {
            /* Increment destructor's vgate at construction time
             */
            esharedctorgates.push(f);
        }

        sshareddtors.shift(s);
    }
    else if (fd->isStaticDtorDeclaration())
    {
        StaticDtorDeclaration *f = fd->isStaticDtorDeclaration();
        assert(f);
        if (f->vgate)
        {
            /* Increment destructor's vgate at construction time
             */
            ectorgates.push(f);
        }

        sdtors.shift(s);
    }

    // If unit test
    if (ud)
    {
        stests.push(s);
    }

    if (global.errors)
    {
        // Restore symbol table
        cstate.CSpsymtab = symtabsave;
        return;
    }

    writefunc(s);
    // Restore symbol table
    cstate.CSpsymtab = symtabsave;

    if (fd->isExport())
        objmod->export_symbol(s, Para.offset);

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

    if (ud)
    {
        for (size_t i = 0; i < ud->deferredNested.dim; i++)
        {
            FuncDeclaration *fd = ud->deferredNested[i];
            toObjFile(fd, false);
        }
    }

#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 (fd->ident && memcmp(fd->ident->toChars(), "_STD", 4) == 0)
        objmod->staticdtor(s);
#endif
    if (irs.startaddress)
    {
        //printf("Setting start address\n");
        objmod->startaddress(irs.startaddress);
    }
}
Exemplo n.º 25
0
Arquivo: out.c Projeto: TurkeyMan/dmd
void outdata(symbol *s)
{
#if HTOD
    return;
#endif
    int seg;
    targ_size_t offset;
    int flags;
    const int codeseg = cseg;

    symbol_debug(s);
#ifdef DEBUG
    debugy && dbg_printf("outdata('%s')\n",s->Sident);
#endif
    //printf("outdata('%s', ty=x%x)\n",s->Sident,s->Stype->Tty);
    //symbol_print(s);

    // Data segment variables are always live on exit from a function
    s->Sflags |= SFLlivexit;

    dt_t *dtstart = s->Sdt;
    s->Sdt = NULL;                      // it will be free'd
    targ_size_t datasize = 0;
    tym_t ty = s->ty();
#if SCPP && TARGET_WINDOS
    if (eecontext.EEcompile)
    {   s->Sfl = (s->ty() & mTYfar) ? FLfardata : FLextern;
        s->Sseg = UNKNOWN;
        goto Lret;                      // don't output any data
    }
#endif
    if (ty & mTYexport && config.wflags & WFexpdef && s->Sclass != SCstatic)
        objmod->export_symbol(s,0);        // export data definition
    for (dt_t *dt = dtstart; dt; dt = dt->DTnext)
    {
        //printf("\tdt = %p, dt = %d\n",dt,dt->dt);
        switch (dt->dt)
        {   case DT_abytes:
            {   // Put out the data for the string, and
                // reserve a spot for a pointer to that string
                datasize += size(dt->Dty);      // reserve spot for pointer to string
#if TARGET_SEGMENTED
                if (tybasic(dt->Dty) == TYcptr)
                {   dt->DTseg = codeseg;
                    dt->DTabytes += Offset(codeseg);
                    goto L1;
                }
                else if (tybasic(dt->Dty) == TYfptr &&
                         dt->DTnbytes > config.threshold)
                {
                    targ_size_t foffset;
                    dt->DTseg = objmod->fardata(s->Sident,dt->DTnbytes,&foffset);
                    dt->DTabytes += foffset;
                L1:
                    objmod->write_bytes(SegData[dt->DTseg],dt->DTnbytes,dt->DTpbytes);
                    break;
                }
                else
#endif
                {
                    dt->DTabytes += objmod->data_readonly(dt->DTpbytes,dt->DTnbytes,&dt->DTseg);
                }
                break;
            }
            case DT_ibytes:
                datasize += dt->DTn;
                break;
            case DT_nbytes:
                //printf("DT_nbytes %d\n", dt->DTnbytes);
                datasize += dt->DTnbytes;
                break;

            case DT_azeros:
                /* A block of zeros
                 */
                //printf("DT_azeros %d\n", dt->DTazeros);
            case_azeros:
                datasize += dt->DTazeros;
                if (dt == dtstart && !dt->DTnext && s->Sclass != SCcomdat &&
                    (s->Sseg == UNKNOWN || s->Sseg <= UDATA))
                {   /* first and only, so put in BSS segment
                     */
                    switch (ty & mTYLINK)
                    {
#if TARGET_SEGMENTED
                        case mTYfar:                    // if far data
                            s->Sseg = objmod->fardata(s->Sident,datasize,&s->Soffset);
                            s->Sfl = FLfardata;
                            break;

                        case mTYcs:
                            s->Sseg = codeseg;
                            Offset(codeseg) = _align(datasize,Offset(codeseg));
                            s->Soffset = Offset(codeseg);
                            Offset(codeseg) += datasize;
                            s->Sfl = FLcsdata;
                            break;
#endif
                        case mTYthreadData:
                            assert(config.objfmt == OBJ_MACH && I64);
                        case mTYthread:
                        {   seg_data *pseg = objmod->tlsseg_bss();
                            s->Sseg = pseg->SDseg;
                            objmod->data_start(s, datasize, pseg->SDseg);
                            if (config.objfmt == OBJ_OMF)
                                pseg->SDoffset += datasize;
                            else
                                objmod->lidata(pseg->SDseg, pseg->SDoffset, datasize);
                            s->Sfl = FLtlsdata;
                            break;
                        }
                        default:
                            s->Sseg = UDATA;
                            objmod->data_start(s,datasize,UDATA);
                            objmod->lidata(s->Sseg,s->Soffset,datasize);
                            s->Sfl = FLudata;           // uninitialized data
                            break;
                    }
                    assert(s->Sseg && s->Sseg != UNKNOWN);
                    if (s->Sclass == SCglobal || (s->Sclass == SCstatic && config.objfmt != OBJ_OMF)) // if a pubdef to be done
                        objmod->pubdefsize(s->Sseg,s,s->Soffset,datasize);   // do the definition
                    searchfixlist(s);
                    if (config.fulltypes &&
                        !(s->Sclass == SCstatic && funcsym_p)) // not local static
                        cv_outsym(s);
#if SCPP
                    out_extdef(s);
#endif
                    goto Lret;
                }
                break;
            case DT_common:
                assert(!dt->DTnext);
                outcommon(s,dt->DTazeros);
                goto Lret;

            case DT_xoff:
            {   symbol *sb = dt->DTsym;

                if (tyfunc(sb->ty()))
#if SCPP
                    nwc_mustwrite(sb);
#else
                    ;
#endif
                else if (sb->Sdt)               // if initializer for symbol
{ if (!s->Sseg) s->Sseg = DATA;
                    outdata(sb);                // write out data for symbol
}
            }
            case DT_coff:
                datasize += size(dt->Dty);
                break;
            default:
#ifdef DEBUG
                dbg_printf("dt = %p, dt = %d\n",dt,dt->dt);
#endif
                assert(0);
        }
    }
Exemplo n.º 26
0
type *TypeEnum::toCtype()
{
    if (ctype)
        return ctype;

    //printf("TypeEnum::toCtype() '%s'\n", sym->toChars());
    type *t;
    Type *tm = mutableOf();
    if (tm->ctype && tybasic(tm->ctype->Tty) == TYenum)
    {
        Symbol *s = tm->ctype->Ttag;
        assert(s);
        t = type_alloc(TYenum);
        t->Ttag = (Classsym *)s;            // enum tag name
        t->Tcount++;
        t->Tnext = tm->ctype->Tnext;
        t->Tnext->Tcount++;
        // Add modifiers
        switch (mod)
        {
            case 0:
                assert(0);
                break;
            case MODconst:
            case MODwild:
                t->Tty |= mTYconst;
                break;
            case MODimmutable:
                t->Tty |= mTYimmutable;
                break;
            case MODshared:
                t->Tty |= mTYshared;
                break;
            case MODshared | MODwild:
            case MODshared | MODconst:
                t->Tty |= mTYshared | mTYconst;
                break;
            default:
                assert(0);
        }
        ctype = t;
    }
    else if (sym->memtype && sym->memtype->toBasetype()->ty == Tint32)
    {
        t = type_enum(sym->toPrettyChars(), sym->memtype->toCtype());
        tm->ctype = t;
        ctype = t;
    }
    else if(sym->memtype)
    {
        t = ctype = sym->memtype->toCtype();
    }
    else
    {
        t = ctype = type_alloc(Tint32);
    }

    if (0 && global.params.symdebug)
        sym->toDebug();

    //printf("t = %p, Tflags = x%x\n", t, t->Tflags);
    return t;
}
Exemplo n.º 27
0
Arquivo: toir.c Projeto: dsp/dmd
/*************************************
 * Closures are implemented by taking the local variables that
 * need to survive the scope of the function, and copying them
 * into a gc allocated chuck of memory. That chunk, called the
 * closure here, is inserted into the linked list of stack
 * frames instead of the usual stack frame.
 *
 * buildClosure() inserts code just after the function prolog
 * is complete. It allocates memory for the closure, allocates
 * a local variable (sclosure) to point to it, inserts into it
 * the link to the enclosing frame, and copies into it the parameters
 * that are referred to in nested functions.
 * In VarExp::toElem and SymOffExp::toElem, when referring to a
 * variable that is in a closure, takes the offset from sclosure rather
 * than from the frame pointer.
 *
 * getEthis() and NewExp::toElem need to use sclosure, if set, rather
 * than the current frame pointer.
 */
void buildClosure(FuncDeclaration *fd, IRState *irs)
{
    if (fd->needsClosure())
    {
        // Generate closure on the heap
        // BUG: doesn't capture variadic arguments passed to this function

        /* BUG: doesn't handle destructors for the local variables.
         * The way to do it is to make the closure variables the fields
         * of a class object:
         *    class Closure {
         *        vtbl[]
         *        monitor
         *        ptr to destructor
         *        sthis
         *        ... closure variables ...
         *        ~this() { call destructor }
         *    }
         */
        //printf("FuncDeclaration::buildClosure() %s\n", toChars());

        /* Generate type name for closure struct */
        const char *name1 = "CLOSURE.";
        const char *name2 = fd->toPrettyChars();
        size_t namesize = strlen(name1)+strlen(name2)+1;
        char *closname = (char *) calloc(namesize, sizeof(char));
        strcat(strcat(closname, name1), name2);

        /* Build type for closure */
        type *Closstru = type_struct_class(closname, Target::ptrsize, 0, NULL, NULL, false, false, true);
        symbol_struct_addField(Closstru->Ttag, "__chain", Type_toCtype(Type::tvoidptr), 0);

        Symbol *sclosure;
        sclosure = symbol_name("__closptr", SCauto, type_pointer(Closstru));
        sclosure->Sflags |= SFLtrue | SFLfree;
        symbol_add(sclosure);
        irs->sclosure = sclosure;

        unsigned offset = Target::ptrsize;      // leave room for previous sthis
        for (size_t i = 0; i < fd->closureVars.dim; i++)
        {
            VarDeclaration *v = fd->closureVars[i];
            //printf("closure var %s\n", v->toChars());
            assert(v->isVarDeclaration());

            if (v->needsAutoDtor())
            {
                /* Because the value needs to survive the end of the scope!
                 */
                v->error("has scoped destruction, cannot build closure");
            }
            if (v->isargptr)
            {
                /* See Bugzilla 2479
                 * This is actually a bug, but better to produce a nice
                 * message at compile time rather than memory corruption at runtime
                 */
                v->error("cannot reference variadic arguments from closure");
            }
            /* Align and allocate space for v in the closure
             * just like AggregateDeclaration::addField() does.
             */
            unsigned memsize;
            unsigned memalignsize;
            structalign_t xalign;
            if (v->storage_class & STClazy)
            {
                /* Lazy variables are really delegates,
                 * so give same answers that TypeDelegate would
                 */
                memsize = Target::ptrsize * 2;
                memalignsize = memsize;
                xalign = STRUCTALIGN_DEFAULT;
            }
            else if (ISWIN64REF(v))
            {
                memsize = v->type->size();
                memalignsize = v->type->alignsize();
                xalign = v->alignment;
            }
            else if (ISREF(v, NULL))
            {
                // reference parameters are just pointers
                memsize = Target::ptrsize;
                memalignsize = memsize;
                xalign = STRUCTALIGN_DEFAULT;
            }
            else
            {
                memsize = v->type->size();
                memalignsize = v->type->alignsize();
                xalign = v->alignment;
            }
            AggregateDeclaration::alignmember(xalign, memalignsize, &offset);
            v->offset = offset;
            offset += memsize;

            /* Set Sscope to closure */
            Symbol *vsym = toSymbol(v);
            assert(vsym->Sscope == NULL);
            vsym->Sscope = sclosure;

            /* Add variable as closure type member */
            symbol_struct_addField(Closstru->Ttag, vsym->Sident, vsym->Stype, v->offset);
            //printf("closure field %s: memalignsize: %i, offset: %i\n", vsym->Sident, memalignsize, v->offset);

            /* Can't do nrvo if the variable is put in a closure, since
             * what the shidden points to may no longer exist.
             */
            if (fd->nrvo_can && fd->nrvo_var == v)
            {
                fd->nrvo_can = 0;
            }
        }
        // offset is now the size of the closure
        Closstru->Ttag->Sstruct->Sstructsize = offset;

        // Allocate memory for the closure
        elem *e = el_long(TYsize_t, offset);
        e = el_bin(OPcall, TYnptr, el_var(getRtlsym(RTLSYM_ALLOCMEMORY)), e);
        toTraceGC(irs, e, &fd->loc);

        // Assign block of memory to sclosure
        //    sclosure = allocmemory(sz);
        e = el_bin(OPeq, TYvoid, el_var(sclosure), e);

        // Set the first element to sthis
        //    *(sclosure + 0) = sthis;
        elem *ethis;
        if (irs->sthis)
            ethis = el_var(irs->sthis);
        else
            ethis = el_long(TYnptr, 0);
        elem *ex = el_una(OPind, TYnptr, el_var(sclosure));
        ex = el_bin(OPeq, TYnptr, ex, ethis);
        e = el_combine(e, ex);

        // Copy function parameters into closure
        for (size_t i = 0; i < fd->closureVars.dim; i++)
        {
            VarDeclaration *v = fd->closureVars[i];

            if (!v->isParameter())
                continue;
            tym_t tym = totym(v->type);
            bool win64ref = ISWIN64REF(v);
            if (win64ref)
            {
                if (v->storage_class & STClazy)
                    tym = TYdelegate;
            }
            else if (ISREF(v, NULL))
                tym = TYnptr;   // reference parameters are just pointers
            else if (v->storage_class & STClazy)
                tym = TYdelegate;
            ex = el_bin(OPadd, TYnptr, el_var(sclosure), el_long(TYsize_t, v->offset));
            ex = el_una(OPind, tym, ex);
            elem *ev = el_var(toSymbol(v));
            if (win64ref)
            {
                ev->Ety = TYnptr;
                ev = el_una(OPind, tym, ev);
                if (tybasic(ev->Ety) == TYstruct || tybasic(ev->Ety) == TYarray)
                    ev->ET = Type_toCtype(v->type);
            }
            if (tybasic(ex->Ety) == TYstruct || tybasic(ex->Ety) == TYarray)
            {
                ::type *t = Type_toCtype(v->type);
                ex->ET = t;
                ex = el_bin(OPstreq, tym, ex, ev);
                ex->ET = t;
            }
            else
                ex = el_bin(OPeq, tym, ex, ev);

            e = el_combine(e, ex);
        }

        block_appendexp(irs->blx->curblock, e);
    }
}
Exemplo n.º 28
0
type *TypeEnum::toCtype()
{
    if (ctype)
        return ctype;

    //printf("TypeEnum::toCtype() '%s'\n", sym->toChars());
    type *t;
    Type *tm = mutableOf();
    if (tm->ctype && tybasic(tm->ctype->Tty) == TYenum)
    {
        Symbol *s = tm->ctype->Ttag;
        assert(s);
        t = type_alloc(TYenum);
        t->Ttag = (Classsym *)s;            // enum tag name
        t->Tcount++;
        t->Tnext = tm->ctype->Tnext;
        t->Tnext->Tcount++;
        // Add modifiers
        switch (mod)
        {
            case 0:
                assert(0);
                break;
            case MODconst:
            case MODwild:
                t->Tty |= mTYconst;
                break;
            case MODimmutable:
                t->Tty |= mTYimmutable;
                break;
            case MODshared:
                t->Tty |= mTYshared;
                break;
            case MODshared | MODwild:
            case MODshared | MODconst:
                t->Tty |= mTYshared | mTYconst;
                break;
            default:
                assert(0);
        }
        ctype = t;
    }
    else if (sym->memtype->toBasetype()->ty == Tint32)
    {
        Symbol *s = symbol_calloc(sym->toPrettyChars());
        s->Sclass = SCenum;
        s->Senum = (enum_t *) MEM_PH_CALLOC(sizeof(enum_t));
        s->Senum->SEflags |= SENforward;        // forward reference
        slist_add(s);

        t = type_alloc(TYenum);
        t->Ttag = (Classsym *)s;            // enum tag name
        t->Tcount++;
        t->Tnext = sym->memtype->toCtype();
        t->Tnext->Tcount++;
        s->Stype = t;
        slist_add(s);
        tm->ctype = t;
        ctype = t;
    }
    else
    {
        t = ctype = sym->memtype->toCtype();
    }

    //printf("t = %p, Tflags = x%x\n", t, t->Tflags);
    return t;
}
Exemplo n.º 29
0
Arquivo: type.c Projeto: sgraf812/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",(long)tyb);
#endif
    assert(tyb < TYMAX);
    s = tysize[tyb];
    if (s == (targ_size_t) -1)
    {
        switch (tyb)
        {
            // in case program plays games with function pointers
#if TARGET_SEGMENTED
            case TYffunc:
            case TYfpfunc:
            case TYfsfunc:
            case TYf16func:
#endif
            case TYhfunc:
            case TYnfunc:       /* in case program plays games with function pointers */
            case TYnpfunc:
            case TYnsfunc:
            case TYifunc:
            case TYjfunc:
#if SCPP
            case TYmfunc:
                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;
}
Exemplo n.º 30
0
void ReturnStatement::toIR(IRState *irs)
{
    Blockx *blx = irs->blx;
    enum BC bc;

    incUsage(irs, loc);
    if (exp)
    {   elem *e;

        FuncDeclaration *func = irs->getFunc();
        assert(func);
        assert(func->type->ty == Tfunction);
        TypeFunction *tf = (TypeFunction *)(func->type);

        enum RET retmethod = tf->retStyle();
        if (retmethod == RETstack)
        {
            elem *es;

            /* If returning struct literal, write result
             * directly into return value
             */
            if (exp->op == TOKstructliteral)
            {   StructLiteralExp *se = (StructLiteralExp *)exp;
                char save[sizeof(StructLiteralExp)];
                memcpy(save, se, sizeof(StructLiteralExp));
                se->sym = irs->shidden;
                se->soffset = 0;
                se->fillHoles = 1;
                e = exp->toElemDtor(irs);
                memcpy(se, save, sizeof(StructLiteralExp));

            }
            else
                e = exp->toElemDtor(irs);
            assert(e);

            if (exp->op == TOKstructliteral ||
                (func->nrvo_can && func->nrvo_var))
            {
                // Return value via hidden pointer passed as parameter
                // Write exp; return shidden;
                es = e;
            }
            else
            {
                // Return value via hidden pointer passed as parameter
                // Write *shidden=exp; return shidden;
                int op;
                tym_t ety;

                ety = e->Ety;
                es = el_una(OPind,ety,el_var(irs->shidden));
                op = (tybasic(ety) == TYstruct) ? OPstreq : OPeq;
                es = el_bin(op, ety, es, e);
                if (op == OPstreq)
                    es->ET = exp->type->toCtype();
#if 0//DMDV2
                /* Call postBlit() on *shidden
                 */
                Type *tb = exp->type->toBasetype();
                //if (tb->ty == Tstruct) exp->dump(0);
                if (exp->isLvalue() && tb->ty == Tstruct)
                {   StructDeclaration *sd = ((TypeStruct *)tb)->sym;
                    if (sd->postblit)
                    {   FuncDeclaration *fd = sd->postblit;
                        if (fd->storage_class & STCdisable)
                        {
                            fd->toParent()->error(loc, "is not copyable because it is annotated with @disable");
                        }
                        elem *ec = el_var(irs->shidden);
                        ec = callfunc(loc, irs, 1, Type::tvoid, ec, tb->pointerTo(), fd, fd->type, NULL, NULL);
                        es = el_bin(OPcomma, ec->Ety, es, ec);
                    }
                }
#endif
            }
            e = el_var(irs->shidden);
            e = el_bin(OPcomma, e->Ety, es, e);
        }
#if DMDV2
        else if (tf->isref)
        {   // Reference return, so convert to a pointer
            Expression *ae = exp->addressOf(NULL);
            e = ae->toElemDtor(irs);
        }
#endif
        else
        {
            e = exp->toElemDtor(irs);
            assert(e);
        }
        elem_setLoc(e, loc);
        block_appendexp(blx->curblock, e);
        bc = BCretexp;
    }
    else
        bc = BCret;

    block *btry = blx->curblock->Btry;
    if (btry)
    {
        // A finally block is a successor to a return block inside a try-finally
        if (btry->numSucc() == 2)      // try-finally
        {
            block *bfinally = btry->nthSucc(1);
            assert(bfinally->BC == BC_finally);
            blx->curblock->appendSucc(bfinally);
        }
    }
    block_next(blx, bc, NULL);
}