예제 #1
0
파일: objc_glue.c 프로젝트: Angeldude/dmd
Symbol *objc_getMsgSend(Type *ret, bool hasHiddenArg)
{
    if (hasHiddenArg)
    {
        if (!objc_smsgSend_stret)
            objc_smsgSend_stret = symbol_name("_objc_msgSend_stret", SCglobal, type_fake(TYhfunc));
        return objc_smsgSend_stret;
    }
    // not sure if DMD can handle this
    else if (ret->ty == Tcomplex80)
    {
         if (!objc_smsgSend_fp2ret)
             objc_smsgSend_fp2ret = symbol_name("_objc_msgSend_fp2ret", SCglobal, type_fake(TYnfunc));
         return objc_smsgSend_fp2ret;
    }
    else if (ret->ty == Tfloat80)
    {
        if (!objc_smsgSend_fpret)
            objc_smsgSend_fpret = symbol_name("_objc_msgSend_fpret", SCglobal, type_fake(TYnfunc));
        return objc_smsgSend_fpret;
    }
    else
    {
        if (!objc_smsgSend)
            objc_smsgSend = symbol_name("_objc_msgSend", SCglobal, type_fake(TYnfunc));
        return objc_smsgSend;
    }
    assert(0);
    return NULL;
}
예제 #2
0
파일: rtlsym.c 프로젝트: 9rnsr/dmd
void rtlsym_init()
{
    static int inited;

    if (!inited)
    {   inited++;

        //printf("rtlsym_init(%s)\n", regm_str(FREGSAVED));

#if MARS
        type *t = type_fake(TYnfunc);
        t->Tmangle = mTYman_c;
        t->Tcount++;

        // Variadic function
        type *tv = type_fake(TYnfunc);
        tv->Tmangle = mTYman_c;
        tv->Tcount++;
#endif

        // Only used by dmd1 for RTLSYM_THROW
        type *tw = NULL;

#undef SYMBOL_Z
#define SYMBOL_Z(e, fl, regsaved, n, flags, t) \
        rtlsym[RTLSYM_##e] = symbolz(n, t, fl, flags, regsaved);

        RTLSYMS
    }
예제 #3
0
파일: rtlsym.c 프로젝트: ckamm/dmd
void rtlsym_init()
{
    static int inited;

    if (!inited)
    {   inited++;

        //printf("rtlsym_init(%s)\n", regm_str(FREGSAVED));

        for (int i = 0; i < RTLSYM_MAX; i++)
        {
            rtlsym[i] = &rtlsym2[i];
#ifdef DEBUG
            rtlsym[i]->id = IDsymbol;
#endif
            rtlsym[i]->Stype = tsclib;
            rtlsym[i]->Ssymnum = -1;
            rtlsym[i]->Sclass = SCextern;
            rtlsym[i]->Sfl = FLfunc;
#if ELFOBJ || MACHOBJ
            rtlsym[i]->obj_si = (unsigned)-1;
            rtlsym[i]->dwarf_off = (unsigned)-1;
#endif
            rtlsym[i]->Sregsaved = FREGSAVED;
        }

#if MARS
        type *t = type_fake(LARGECODE ? TYffunc : TYnfunc);
        t->Tmangle = mTYman_c;
        t->Tcount++;

        // Variadic function
        type *tv = type_fake(LARGECODE ? TYffunc : TYnfunc);
        tv->Tmangle = mTYman_c;
        tv->Tcount++;
#endif

#if MACHOBJ
        type *tw = type_fake(TYnpfunc);
        tw->Tmangle = mTYman_sys;
        tw->Tcount++;
#else
        type *tw = NULL;
#endif

#undef SYMBOL_Z
#define SYMBOL_Z(e, fl, saved, n, flags, ty)                            \
        if (ty) rtlsym[RTLSYM_##e]->Stype = ty;                         \
        if (fl != FLfunc) rtlsym[RTLSYM_##e]->Sfl = fl;                 \
        if (flags) rtlsym[RTLSYM_##e]->Sflags = flags;                  \
        if (saved != FREGSAVED) rtlsym[RTLSYM_##e]->Sregsaved = saved;  \
        strcpy(rtlsym[RTLSYM_##e]->Sident, n);                          \

        RTLSYMS
    }
예제 #4
0
파일: glue.c 프로젝트: Geod24/dnet
elem *Module::toEfilename()
{   elem *efilename;

    if (!sfilename)
    {
	dt_t *dt = NULL;
	char *id;
	int len;

	id = srcfile->toChars();
	len = strlen(id);
	dtdword(&dt, len);
	dtabytes(&dt,TYnptr, 0, len + 1, id);

	sfilename = symbol_generate(SCstatic,type_fake(TYdarray));
	sfilename->Sdt = dt;
	sfilename->Sfl = FLdata;
#if ELFOBJ
	sfilename->Sseg = CDATA;
#endif
#if MACHOBJ
	// Because of PIC and CDATA being in the _TEXT segment, cannot
	// have pointers in CDATA
	sfilename->Sseg = DATA;
#endif
	outdata(sfilename);
    }

    efilename = el_var(sfilename);
    return efilename;
}
예제 #5
0
파일: objc_glue.c 프로젝트: Angeldude/dmd
Symbol *objc_getMethVarRef(const char *s, size_t len)
{
    objc_hasSymbols = true;

    StringValue *sv = objc_smethVarRefTable->update(s, len);
    Symbol *refsymbol = (Symbol *) sv->ptrvalue;
    if (refsymbol == NULL)
    {
        // create data
        dt_t *dt = NULL;
        Symbol *sselname = objc_getMethVarName(s, len);
        dtxoff(&dt, sselname, 0, TYnptr);

        // find segment
        int seg = objc_getSegment(SEGselrefs);

        // create symbol
        static size_t selcount = 0;
        char namestr[42];
        sprintf(namestr, "L_OBJC_SELECTOR_REFERENCES_%lu", selcount);
        refsymbol = symbol_name(namestr, SCstatic, type_fake(TYnptr));

        refsymbol->Sdt = dt;
        refsymbol->Sseg = seg;
        outdata(refsymbol);
        sv->ptrvalue = refsymbol;

        ++selcount;
    }
    return refsymbol;
}
예제 #6
0
파일: glue.c 프로젝트: abhishekkumar-/dmd
void Module::genhelpers(bool iscomdat)
{

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

        if (ma)
        {
            elem *elinnum;

            localgot = NULL;

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

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

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

                elinnum = el_var(sp);
            }

            elem *efilename = toEfilename(this);

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

            block *b = block_calloc();
            b->BC = bc;
            b->Belem = e;
            ma->Sfunc->Fstartline.Sfilename = arg;
            ma->Sfunc->Fstartblock = b;
            ma->Sclass = iscomdat ? SCcomdat : SCglobal;
            ma->Sfl = 0;
            ma->Sflags |= rtlsym[rt]->Sflags & SFLexit;
            writefunc(ma);
        }
    }
}
예제 #7
0
파일: toctype.c 프로젝트: ZHANITEST/pspemu
type *Type::toCtype()
{
    if (!ctype)
    {   ctype = type_fake(totym());
        ctype->Tcount++;
    }
    return ctype;
}
예제 #8
0
파일: msc.c 프로젝트: 1100110/dmd
symbol *symboldata(targ_size_t offset,tym_t ty)
{
    symbol *s = symbol_generate(SClocstat, type_fake(ty));
    s->Sfl = FLdata;
    s->Soffset = offset;
    symbol_keep(s);             // keep around
    return s;
}
예제 #9
0
static void genhelpers(Module *m)
{
    // If module assert
    for (int i = 0; i < 3; i++)
    {
        Symbol *ma;
        unsigned rt;
        unsigned bc;
        switch (i)
        {
            case 0:     ma = toModuleArray(m);    rt = RTLSYM_DARRAY;     bc = BCexit; break;
            case 1:     ma = toModuleAssert(m);   rt = RTLSYM_DASSERT;    bc = BCexit; break;
            case 2:     ma = toModuleUnittest(m); rt = RTLSYM_DUNITTEST;  bc = BCret;  break;
            default:    assert(0);
        }

        if (!ma)
            continue;


        localgot = NULL;

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

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

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

        elem *elinnum = el_var(sp);


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

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

        block *b = block_calloc();
        b->BC = bc;
        b->Belem = e;
        ma->Sfunc->Fstartline.Sfilename = m->arg;
        ma->Sfunc->Fstartblock = b;
        ma->Sclass = SCglobal;
        ma->Sfl = 0;
        ma->Sflags |= getRtlsym(rt)->Sflags & SFLexit;
        writefunc(ma);
    }
}
예제 #10
0
파일: toctype.c 프로젝트: ZHANITEST/pspemu
type *TypeAArray::toCtype()
{   type *t;

    if (ctype)
        return ctype;

    if (0 && global.params.symdebug)
    {
        /* An associative array is represented by:
         *      struct AArray { size_t length; void* ptr; }
         */

        static Symbol *s;

        if (!s)
        {
            s = symbol_calloc("_AArray");
            s->Sclass = SCstruct;
            s->Sstruct = struct_calloc();
            s->Sstruct->Sflags |= 0;
            s->Sstruct->Salignsize = alignsize();
            s->Sstruct->Sstructalign = global.structalign;
            s->Sstruct->Sstructsize = size(0);
            slist_add(s);

            Symbol *s1 = symbol_name("length", SCmember, Type::tsize_t->toCtype());
            list_append(&s->Sstruct->Sfldlst, s1);

            Symbol *s2 = symbol_name("data", SCmember, Type::tvoidptr->toCtype());
            s2->Smemoff = Type::tsize_t->size();
            list_append(&s->Sstruct->Sfldlst, s2);
        }

        t = type_alloc(TYstruct);
        t->Ttag = (Classsym *)s;                // structure tag name
        t->Tcount++;
        s->Stype = t;
    }
    else
    {
        if (global.params.symdebug == 1)
        {
            /* Generate D symbolic debug info, rather than C
             *   Tnext: element type
             *   Tkey: key type
             */
            t = type_allocn(TYaarray, next->toCtype());
            t->Tkey = index->toCtype();
            t->Tkey->Tcount++;
        }
        else
            t = type_fake(TYaarray);
    }
    t->Tcount++;
    ctype = t;
    return t;
}
예제 #11
0
파일: toctype.c 프로젝트: ZHANITEST/pspemu
type *TypeDelegate::toCtype()
{   type *t;

    if (ctype)
        return ctype;

    if (0 && global.params.symdebug)
    {
        /* A delegate consists of:
         *    _Delegate { void* frameptr; Function *funcptr; }
         */

        static Symbol *s;

        if (!s)
        {
            s = symbol_calloc("_Delegate");
            s->Sclass = SCstruct;
            s->Sstruct = struct_calloc();
            s->Sstruct->Sflags |= 0;
            s->Sstruct->Salignsize = alignsize();
            s->Sstruct->Sstructalign = global.structalign;
            s->Sstruct->Sstructsize = size(0);
            slist_add(s);

            Symbol *s1 = symbol_name("frameptr", SCmember, Type::tvoidptr->toCtype());
            list_append(&s->Sstruct->Sfldlst, s1);

            Symbol *s2 = symbol_name("funcptr", SCmember, Type::tvoidptr->toCtype());
            s2->Smemoff = Type::tvoidptr->size();
            list_append(&s->Sstruct->Sfldlst, s2);
        }

        t = type_alloc(TYstruct);
        t->Ttag = (Classsym *)s;                // structure tag name
        t->Tcount++;
        s->Stype = t;
    }
    else
    {
        if (global.params.symdebug == 1)
        {
            // Generate D symbolic debug info, rather than C
            t = type_allocn(TYdelegate, next->toCtype());
        }
        else
            t = type_fake(TYdelegate);
    }

    t->Tcount++;
    ctype = t;
    return t;
}
예제 #12
0
파일: toctype.c 프로젝트: ZHANITEST/pspemu
type *TypeDArray::toCtype()
{   type *t;

    if (ctype)
        return ctype;

    if (0 && global.params.symdebug)
    {
        /* Create a C type out of:
         *      struct _Array_T { size_t length; T* data; }
         */
        Symbol *s;
        char *id;

        assert(next->deco);
        id = (char *) alloca(7 + strlen(next->deco) + 1);
        sprintf(id, "_Array_%s", next->deco);
        s = symbol_calloc(id);
        s->Sclass = SCstruct;
        s->Sstruct = struct_calloc();
        s->Sstruct->Sflags |= 0;
        s->Sstruct->Salignsize = alignsize();
        s->Sstruct->Sstructalign = global.structalign;
        s->Sstruct->Sstructsize = size(0);
        slist_add(s);

        Symbol *s1 = symbol_name("length", SCmember, Type::tsize_t->toCtype());
        list_append(&s->Sstruct->Sfldlst, s1);

        Symbol *s2 = symbol_name("data", SCmember, next->pointerTo()->toCtype());
        s2->Smemoff = Type::tsize_t->size();
        list_append(&s->Sstruct->Sfldlst, s2);

        t = type_alloc(TYstruct);
        t->Ttag = (Classsym *)s;                // structure tag name
        t->Tcount++;
        s->Stype = t;
    }
    else
    {
        if (global.params.symdebug == 1)
        {
            // Generate D symbolic debug info, rather than C
            t = type_allocn(TYdarray, next->toCtype());
        }
        else
            t = type_fake(TYdarray);
    }
    t->Tcount++;
    ctype = t;
    return t;
}
예제 #13
0
파일: toobj.c 프로젝트: bitwise-github/dmd
        /**
         * Creates the data symbol for a TLS variable for Mach-O.
         *
         * Input:
         *      vd  the variable declaration for the symbol
         *      s   the regular symbol for the variable
         *
         * Returns: the newly create symbol
         */
        Symbol *createTLVDataSymbol(VarDeclaration *vd, Symbol *s)
        {
            assert(config.objfmt == OBJ_MACH && I64 && (s->ty() & mTYLINK) == mTYthread);

            OutBuffer buffer;
            buffer.writestring(s->Sident);
            buffer.write("$tlv$init", 9);

            const char *tlvInitName = buffer.extractString();
            Symbol *tlvInit = symbol_name(tlvInitName, SCstatic, type_fake(vd->type->ty));
            tlvInit->Sdt = NULL;
            tlvInit->Salignment = type_alignsize(s->Stype);

            type_setty(&tlvInit->Stype, tlvInit->Stype->Tty | mTYthreadData);
            type_setmangle(&tlvInit->Stype, mangle(vd, tlvInit));

            return tlvInit;
        }
예제 #14
0
파일: glue.c 프로젝트: abhishekkumar-/dmd
elem *toEfilename(Module *m)
{
    elem *efilename;
    if (!m->sfilename)
    {
        dt_t *dt = NULL;
        char *id = m->srcfile->toChars();
        size_t len = strlen(id);
        dtsize_t(&dt, len);
        dtabytes(&dt,TYnptr, 0, len + 1, id);

        m->sfilename = symbol_generate(SCstatic,type_fake(TYdarray));
        m->sfilename->Sdt = dt;
        m->sfilename->Sfl = FLdata;
        out_readonly(m->sfilename);
        outdata(m->sfilename);
    }

    efilename = (config.exe == EX_WIN64) ? el_ptr(m->sfilename) : el_var(m->sfilename);
    return efilename;
}
예제 #15
0
파일: toobj.c 프로젝트: Cauterite/dmd
        /**
         * Creates the data symbol used to initialize a TLS variable for Mach-O.
         *
         * Params:
         *      vd = the variable declaration for the symbol
         *      s = the back end symbol corresponding to vd
         *
         * Returns: the newly created symbol
         */
        Symbol *createTLVDataSymbol(VarDeclaration *vd, Symbol *s)
        {
            assert(config.objfmt == OBJ_MACH && I64 && (s->ty() & mTYLINK) == mTYthread);

            // Compute identifier for tlv symbol
            OutBuffer buffer;
            buffer.writestring(s->Sident);
            buffer.write("$tlv$init", 9);
            const char *tlvInitName = buffer.peekString();

            // Compute type for tlv symbol
            type *t = type_fake(vd->type->ty);
            type_setty(&t, t->Tty | mTYthreadData);
            type_setmangle(&t, mangle(vd));

            Symbol *tlvInit = symbol_name(tlvInitName, SCstatic, t);
            tlvInit->Sdt = NULL;
            tlvInit->Salignment = type_alignsize(s->Stype);
            if (vd->linkage == LINKcpp)
                tlvInit->Sflags |= SFLpublic;

            return tlvInit;
        }
예제 #16
0
파일: toctype.c 프로젝트: ZHANITEST/pspemu
type *TypePointer::toCtype()
{   type *tn;
    type *t;

    //printf("TypePointer::toCtype() %s\n", toChars());
    if (ctype)
        return ctype;

    if (1 || global.params.symdebug)
    {   /* Need to always do this, otherwise C++ name mangling
         * goes awry.
         */
        t = type_alloc(TYnptr);
        ctype = t;
        tn = next->toCtype();
        t->Tnext = tn;
        tn->Tcount++;
    }
    else
        t = type_fake(totym());
    t->Tcount++;
    ctype = t;
    return t;
}
예제 #17
0
파일: glue.c 프로젝트: greeeen/dmd
elem *Module::toEfilename()
{   elem *efilename;

    if (!sfilename)
    {
        dt_t *dt = NULL;
        char *id;
        int len;

        id = srcfile->toChars();
        len = strlen(id);
        dtsize_t(&dt, len);
        dtabytes(&dt,TYnptr, 0, len + 1, id);

        sfilename = symbol_generate(SCstatic,type_fake(TYdarray));
        sfilename->Sdt = dt;
        sfilename->Sfl = FLdata;
        out_readonly(sfilename);
        outdata(sfilename);
    }

    efilename = el_var(sfilename);
    return efilename;
}
예제 #18
0
파일: tocsym.c 프로젝트: MrPhil/ShortHike
Symbol *VarDeclaration::toSymbol()
{
    //printf("VarDeclaration::toSymbol(%s)\n", toChars());
    //if (needThis()) *(char*)0=0;
    assert(!needThis());
    if (!csym)
    {	Symbol *s;
	TYPE *t;
	const char *id;
	mangle_t m = 0;

	if (isDataseg())
	    id = mangle();
	else
	    id = ident->toChars();
	s = symbol_calloc(id);

	if (storage_class & STCout)
	    t = type_fake(TYnptr);
	else if (isParameter())
	    t = type->toCParamtype();
	else
	    t = type->toCtype();
	t->Tcount++;

	if (isDataseg())
	{
	    s->Sclass = SCextern;
	    s->Sfl = FLextern;
	    slist_add(s);
	}
	else
	{
	    s->Sclass = SCauto;
	    s->Sfl = FLauto;

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

	    if (storage_class & STCconst)
		tym |= mTYconst;
	    type_setcv(&t, tym);
	}
	switch (linkage)
	{
	    case LINKwindows:
		m = mTYman_std;
		break;

	    case LINKpascal:
		m = mTYman_pas;
		break;

	    case LINKc:
		m = mTYman_c;
		break;

	    case LINKd:
		m = mTYman_d;
		break;

	    case LINKcpp:
		m = mTYman_cpp;
		break;

	    default:
		printf("linkage = %d\n", linkage);
		assert(0);
	}
	type_setmangle(&t, m);
	s->Stype = t;

	csym = s;
    }
    return csym;
}
예제 #19
0
파일: type.c 프로젝트: michelf/dmd
void type_init()
{   int i;

    tsbool    = type_allocbasic(TYbool);
    tswchar_t = type_allocbasic(TYwchar_t);
    tsdchar   = type_allocbasic(TYdchar);
    tsvoid    = type_allocbasic(TYvoid);
    tsnullptr = type_allocbasic(TYnullptr);
    tschar16  = type_allocbasic(TYchar16);
    tsuchar   = type_allocbasic(TYuchar);
    tsschar   = type_allocbasic(TYschar);
    tschar    = type_allocbasic(TYchar);
    tsshort   = type_allocbasic(TYshort);
    tsushort  = type_allocbasic(TYushort);
    tsint     = type_allocbasic(TYint);
    tsuns     = type_allocbasic(TYuint);
    tslong    = type_allocbasic(TYlong);
    tsulong   = type_allocbasic(TYulong);
    tsllong   = type_allocbasic(TYllong);
    tsullong  = type_allocbasic(TYullong);
    tsfloat   = type_allocbasic(TYfloat);
    tsdouble  = type_allocbasic(TYdouble);
    tsifloat   = type_allocbasic(TYifloat);
    tsidouble  = type_allocbasic(TYidouble);
    tscfloat   = type_allocbasic(TYcfloat);
    tscdouble  = type_allocbasic(TYcdouble);
#if TX86
    tsreal64  = type_allocbasic(TYdouble_alias);
    tsldouble  = type_allocbasic(TYldouble);
    tsildouble  = type_allocbasic(TYildouble);
    tscldouble  = type_allocbasic(TYcldouble);
#else
    tsldouble = type_allocbasic(TYldouble);
    tscomp = type_allocbasic(TYcomp);
    chartype = tschar;                          /* default is signed chars */
#endif
    if (I64)
    {
        TYptrdiff = TYllong;
        TYsize = TYullong;
        tsptrdiff = tsllong;
        tssize = tsullong;
    }
    else
    {
        TYptrdiff = TYint;
        TYsize = TYuint;
        tsptrdiff = tsint;
        tssize = tsuns;
    }

#if TX86
    chartype = (config.flags3 & CFG3ju) ? tsuchar : tschar;

    // Type of far library function
    tsclib =    type_fake(LARGECODE ? TYfpfunc : TYnpfunc);
    tsclib->Tmangle = mTYman_c;
    tsclib->Tcount++;

    // Type of trace function
    tstrace =   type_fake(I16 ? TYffunc : TYnfunc);
    tstrace->Tmangle = mTYman_c;
    tstrace->Tcount++;

    tspvoid = type_allocn(pointertype,tsvoid);
    tspvoid->Tmangle = mTYman_c;
    tspvoid->Tcount++;

    // Type of far library function
    tsjlib =    type_fake(TYjfunc);
    tsjlib->Tmangle = mTYman_c;
    tsjlib->Tcount++;

    tsdlib = tsjlib;

#if SCPP
    tspcvoid = type_alloc(mTYconst | TYvoid);
    tspcvoid = newpointer(tspcvoid);
    tspcvoid->Tmangle = mTYman_c;
    tspcvoid->Tcount++;
#endif

    // Type of logical expression
    tslogical = (config.flags4 & CFG4bool) ? tsbool : tsint;

    for (i = 0; i < TYMAX; i++)
    {
        if (tstypes[i])
        {   tsptr2types[i] = type_allocn(pointertype,tstypes[i]);
            tsptr2types[i]->Tcount++;
        }
    }
#else
    type_list = NULL;
    tsclib = type_fake( TYffunc );
    tsclib->Tmangle = mTYman_c;
    tsclib->Tcount++;
#ifdef DEBUG
    type_num = 0;
    type_max = 0;
#endif /* DEBUG */
#endif /* TX86 */
}
예제 #20
0
파일: cv8.c 프로젝트: jasonwhite/dmd
/****************************************
 * Return type index for a aarray of type Value[Key]
 * Input:
 *      t          associative array type
 *      keyidx     key type
 *      validx     value type
 */
idx_t cv8_daarray(type *t, idx_t keyidx, idx_t validx)
{
    //printf("cv8_daarray(keyidx = %x, validx = %x)\n", keyidx, validx);
    /* Put out a struct:
     *    struct dAssocArray {
     *      void* ptr;
     *      typedef key-type __key_t;
     *      typedef val-type __val_t;
     *    }
     */

#if 0
    debtyp_t *d = debtyp_alloc(18);
    TOWORD(d->data, 0x100F);
    TOWORD(d->data + 2, OEM);
    TOWORD(d->data + 4, 2);     // 2 = associative array
    TOLONG(d->data + 6, 2);     // count of type indices to follow
    TOLONG(d->data + 10, keyidx);  // key type
    TOLONG(d->data + 14, validx);  // element type
#else
    type *tv = type_fake(TYnptr);
    tv->Tcount++;
    idx_t pvidx = cv4_typidx(tv);
    type_free(tv);

    static const unsigned char fl[] =
    {
        0x03, 0x12,             // LF_FIELDLIST_V2
        0x0d, 0x15,             // LF_MEMBER_V3
        0x03, 0x00,             // attribute
        0x00, 0x00, 0x00, 0x00, // void*
        0x00, 0x00,             // offset
        'p','t','r',0,          // "ptr"
        0xf2, 0xf1,             // align to 4-byte including field id
        // offset 18
        0x10, 0x15,             // LF_NESTTYPE_V3
        0x00, 0x00,             // padding
        0x00, 0x00, 0x00, 0x00, // key type
        '_','_','k','e','y','_','t',0,  // "__key_t"
        // offset 34
        0x10, 0x15,             // LF_NESTTYPE_V3
        0x00, 0x00,             // padding
        0x00, 0x00, 0x00, 0x00, // value type
        '_','_','v','a','l','_','t',0,  // "__val_t"
    };

    debtyp_t *f = debtyp_alloc(sizeof(fl));
    memcpy(f->data,fl,sizeof(fl));
    TOLONG(f->data + 6, pvidx);
    TOLONG(f->data + 22, keyidx);
    TOLONG(f->data + 38, validx);
    idx_t fieldlist = cv_debtyp(f);

    const char *id = "dAssocArray";
    int idlen = strlen(id);
    if (idlen > CV8_MAX_SYMBOL_LENGTH)
        idlen = CV8_MAX_SYMBOL_LENGTH;

    debtyp_t *d = debtyp_alloc(20 + idlen + 1);
    TOWORD(d->data, LF_STRUCTURE_V3);
    TOWORD(d->data + 2, 1);     // count
    TOWORD(d->data + 4, 0);     // property
    TOLONG(d->data + 6, fieldlist);
    TOLONG(d->data + 10, 0);    // dList
    TOLONG(d->data + 14, 0);    // vtshape
    TOWORD(d->data + 18, NPTRSIZE);   // size
    memcpy(d->data + 20, id, idlen);
    d->data[20 + idlen] = 0;

#endif
    return cv_debtyp(d);
}
예제 #21
0
파일: cv8.c 프로젝트: jasonwhite/dmd
/****************************************
 * Return type index for a delegate
 * Input:
 *      t          delegate type
 *      functypidx type index for pointer to function
 */
idx_t cv8_ddelegate(type *t, idx_t functypidx)
{
    //printf("cv8_ddelegate(functypidx = %x)\n", functypidx);
    /* Put out a struct:
     *    struct dDelegate {
     *      void* ptr;
     *      function* funcptr;
     *    }
     */

    type *tv = type_fake(TYnptr);
    tv->Tcount++;
    idx_t pvidx = cv4_typidx(tv);
    type_free(tv);

    type *tp = type_pointer(t->Tnext);
    idx_t ptridx = cv4_typidx(tp);
    type_free(tp);

#if 0
    debtyp_t *d = debtyp_alloc(18);
    TOWORD(d->data, 0x100F);
    TOWORD(d->data + 2, OEM);
    TOWORD(d->data + 4, 3);     // 3 = delegate
    TOLONG(d->data + 6, 2);     // count of type indices to follow
    TOLONG(d->data + 10, key);  // void* type
    TOLONG(d->data + 14, functypidx); // function type
#else
    static const unsigned char fl[] =
    {
        0x03, 0x12,             // LF_FIELDLIST_V2
        0x0d, 0x15,             // LF_MEMBER_V3
        0x03, 0x00,             // attribute
        0x00, 0x00, 0x00, 0x00, // void*
        0x00, 0x00,             // offset
        'p','t','r',0,          // "ptr"
        0xf2, 0xf1,             // align to 4-byte including length word before data
        0x0d, 0x15,
        0x03, 0x00,
        0x00, 0x00, 0x00, 0x00, // ptrtypidx
        0x08, 0x00,
        'f', 'u','n','c','p','t','r', 0,        // "funcptr"
        0xf2, 0xf1,
    };

    debtyp_t *f = debtyp_alloc(sizeof(fl));
    memcpy(f->data,fl,sizeof(fl));
    TOLONG(f->data + 6, pvidx);
    TOLONG(f->data + 22, ptridx);
    TOWORD(f->data + 26, NPTRSIZE);
    idx_t fieldlist = cv_debtyp(f);

    const char *id = "dDelegate";
    int idlen = strlen(id);
    if (idlen > CV8_MAX_SYMBOL_LENGTH)
        idlen = CV8_MAX_SYMBOL_LENGTH;

    debtyp_t *d = debtyp_alloc(20 + idlen + 1);
    TOWORD(d->data, LF_STRUCTURE_V3);
    TOWORD(d->data + 2, 2);     // count
    TOWORD(d->data + 4, 0);     // property
    TOLONG(d->data + 6, fieldlist);
    TOLONG(d->data + 10, 0);    // dList
    TOLONG(d->data + 14, 0);    // vtshape
    TOWORD(d->data + 18, 2 * NPTRSIZE);   // size
    memcpy(d->data + 20, id, idlen);
    d->data[20 + idlen] = 0;
#endif
    return cv_debtyp(d);
}
예제 #22
0
파일: toctype.c 프로젝트: CyberShadow/dmd
    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);
    }
예제 #23
0
파일: glue.c 프로젝트: Geod24/dnet
void Module::genobjfile(int multiobj)
{
    //EEcontext *ee = env->getEEcontext();

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

    lastmname = srcfile->toChars();

    obj_initfile(lastmname, NULL, toPrettyChars());

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

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

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

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

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

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

	free(covb);
	covb = NULL;

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

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

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

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

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

	static char moddeco[] = "FZv";

	if (eictor)
	{
	    localgot = ictorlocalgot;

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

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

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

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

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

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

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

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

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

	if (doppelganger)
	    genmoduleinfo();
    }

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

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

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

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

	    localgot = NULL;

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

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

		elinnum = el_var(sp);
	    }

	    efilename = toEmodulename();

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

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

#if 1
    // Always generate module info, because of templates and -cov
    if (1 || needModuleInfo())
	genmoduleinfo();
#endif
    
    obj_termfile();
}
예제 #24
0
파일: tocsym.c 프로젝트: andralex/dmd
Symbol *VarDeclaration::toSymbol()
{
    //printf("VarDeclaration::toSymbol(%s)\n", toChars());
    //if (needThis()) *(char*)0=0;
    assert(!needThis());
    if (!csym)
    {
        TYPE *t;
        const char *id;

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

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

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

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

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

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

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

            case LINKpascal:
                m = mTYman_pas;
                break;

            case LINKc:
                m = mTYman_c;
                break;

            case LINKd:
                m = mTYman_d;
                break;

            case LINKcpp:
            {
                m = mTYman_cpp;

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

        csym = s;
    }
    return csym;
}
예제 #25
0
파일: glue.c 프로젝트: AlexBezzubenko/dmd
void genObjFile(Module *m, bool multiobj)
{
    //EEcontext *ee = env->getEEcontext();

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

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

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

        global.params.verbose = v;
        return;
    }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    genhelpers(m, false);

    objmod->termfile();
}
예제 #26
0
파일: toctype.c 프로젝트: CyberShadow/dmd
 void visit(Type *t)
 {
     t->ctype = type_fake(totym(t));
     t->ctype->Tcount++;
 }
예제 #27
0
파일: glue.c 프로젝트: alexrp/dmd
void Module::genobjfile(int multiobj)
{
    //EEcontext *ee = env->getEEcontext();

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

    lastmname = srcfile->toChars();

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

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

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

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

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

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

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

        free(covb);
        covb = NULL;

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

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

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

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

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

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

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

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

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

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

        if (doppelganger)
            genmoduleinfo();
    }

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

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

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

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

        if (ma)
        {
            elem *elinnum;

            localgot = NULL;

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

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

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

                elinnum = el_var(sp);
            }

            elem *efilename = el_ptr(toSymbol());

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

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

    objmod->termfile();
}
예제 #28
0
파일: glue.c 프로젝트: iteratif/dmd
void Module::genobjfile(int multiobj)
{
    //EEcontext *ee = env->getEEcontext();

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

    lastmname = srcfile->toChars();

    obj_initfile(lastmname, NULL, toPrettyChars());

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

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

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

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

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

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

        free(covb);
        covb = NULL;

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

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

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

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

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

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

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

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

        if (doppelganger)
            genmoduleinfo();
    }

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

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

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

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

        if (ma)
        {
            elem *elinnum;

            localgot = NULL;

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

                elinnum = el_var(sp);
            }

            elem *efilename = el_ptr(toSymbol());

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

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

    obj_termfile();
}
예제 #29
0
파일: s2ir.c 프로젝트: Faianca/dmd
    void visit(TryCatchStatement *s)
    {
        Blockx *blx = irs->blx;

#if SEH
        if (!global.params.is64bit)
            nteh_declarvars(blx);
#endif

        IRState mystate(irs, s);

        block *tryblock = block_goto(blx,BCgoto,NULL);

        int previndex = blx->scope_index;
        tryblock->Blast_index = previndex;
        blx->scope_index = tryblock->Bscope_index = blx->next_index++;

        // Set the current scope index
        setScopeIndex(blx,tryblock,tryblock->Bscope_index);

        // This is the catch variable
        tryblock->jcatchvar = symbol_genauto(type_fake(mTYvolatile | TYnptr));

        blx->tryblock = tryblock;
        block *breakblock = block_calloc(blx);
        block_goto(blx,BC_try,NULL);
        if (s->_body)
        {
            Statement_toIR(s->_body, &mystate);
        }
        blx->tryblock = tryblock->Btry;

        // break block goes here
        block_goto(blx, BCgoto, breakblock);

        setScopeIndex(blx,blx->curblock, previndex);
        blx->scope_index = previndex;

        // create new break block that follows all the catches
        breakblock = block_calloc(blx);

        blx->curblock->appendSucc(breakblock);
        block_next(blx,BCgoto,NULL);

        assert(s->catches);
        for (size_t i = 0 ; i < s->catches->dim; i++)
        {
            Catch *cs = (*s->catches)[i];
            if (cs->var)
                cs->var->csym = tryblock->jcatchvar;
            block *bcatch = blx->curblock;
            if (cs->type)
                bcatch->Bcatchtype = toSymbol(cs->type->toBasetype());
            tryblock->appendSucc(bcatch);
            block_goto(blx, BCjcatch, NULL);
            if (cs->handler != NULL)
            {
                IRState catchState(irs, s);

                /* Append to block:
                 *   *(sclosure + cs.offset) = cs;
                 */
                if (cs->var && cs->var->offset)
                {
                    tym_t tym = totym(cs->var->type);
                    elem *ex = el_var(irs->sclosure);
                    ex = el_bin(OPadd, TYnptr, ex, el_long(TYsize_t, cs->var->offset));
                    ex = el_una(OPind, tym, ex);
                    ex = el_bin(OPeq, tym, ex, el_var(toSymbol(cs->var)));
                    block_appendexp(catchState.blx->curblock, ex);
                }
                Statement_toIR(cs->handler, &catchState);
            }
            blx->curblock->appendSucc(breakblock);
            block_next(blx, BCgoto, NULL);
        }

        block_next(blx,(enum BC)blx->curblock->BC, breakblock);
    }
예제 #30
0
파일: s2ir.c 프로젝트: Faianca/dmd
    void visit(SwitchStatement *s)
    {
        int string;
        Blockx *blx = irs->blx;

        //printf("SwitchStatement::toIR()\n");
        IRState mystate(irs,s);

        mystate.switchBlock = blx->curblock;

        /* Block for where "break" goes to
         */
        mystate.breakBlock = block_calloc(blx);

        /* Block for where "default" goes to.
         * If there is a default statement, then that is where default goes.
         * If not, then do:
         *   default: break;
         * by making the default block the same as the break block.
         */
        mystate.defaultBlock = s->sdefault ? block_calloc(blx) : mystate.breakBlock;

        size_t numcases = 0;
        if (s->cases)
            numcases = s->cases->dim;

        incUsage(irs, s->loc);
        elem *econd = toElemDtor(s->condition, &mystate);
        if (s->hasVars)
        {   /* Generate a sequence of if-then-else blocks for the cases.
             */
            if (econd->Eoper != OPvar)
            {
                elem *e = exp2_copytotemp(econd);
                block_appendexp(mystate.switchBlock, e);
                econd = e->E2;
            }

            for (size_t i = 0; i < numcases; i++)
            {   CaseStatement *cs = (*s->cases)[i];

                elem *ecase = toElemDtor(cs->exp, &mystate);
                elem *e = el_bin(OPeqeq, TYbool, el_copytree(econd), ecase);
                block *b = blx->curblock;
                block_appendexp(b, e);
                Label *clabel = getLabel(irs, blx, cs);
                block_next(blx, BCiftrue, NULL);
                b->appendSucc(clabel->lblock);
                b->appendSucc(blx->curblock);
            }

            /* The final 'else' clause goes to the default
             */
            block *b = blx->curblock;
            block_next(blx, BCgoto, NULL);
            b->appendSucc(mystate.defaultBlock);

            Statement_toIR(s->_body, &mystate);

            /* Have the end of the switch body fall through to the block
             * following the switch statement.
             */
            block_goto(blx, BCgoto, mystate.breakBlock);
            return;
        }

        if (s->condition->type->isString())
        {
            // Number the cases so we can unscramble things after the sort()
            for (size_t i = 0; i < numcases; i++)
            {   CaseStatement *cs = (*s->cases)[i];
                cs->index = i;
            }

            s->cases->sort();

            /* Create a sorted array of the case strings, and si
             * will be the symbol for it.
             */
            dt_t *dt = NULL;
            Symbol *si = symbol_generate(SCstatic,type_fake(TYdarray));
            dtsize_t(&dt, numcases);
            dtxoff(&dt, si, Target::ptrsize * 2, TYnptr);

            for (size_t i = 0; i < numcases; i++)
            {   CaseStatement *cs = (*s->cases)[i];

                if (cs->exp->op != TOKstring)
                {   s->error("case '%s' is not a string", cs->exp->toChars()); // BUG: this should be an assert
                }
                else
                {
                    StringExp *se = (StringExp *)(cs->exp);
                    Symbol *si = toStringSymbol((char *)se->string, se->len, se->sz);
                    dtsize_t(&dt, se->len);
                    dtxoff(&dt, si, 0);
                }
            }

            si->Sdt = dt;
            si->Sfl = FLdata;
            outdata(si);

            /* Call:
             *      _d_switch_string(string[] si, string econd)
             */
            if (config.exe == EX_WIN64)
                econd = addressElem(econd, s->condition->type, true);
            elem *eparam = el_param(econd, (config.exe == EX_WIN64) ? el_ptr(si) : el_var(si));
            switch (s->condition->type->nextOf()->ty)
            {
                case Tchar:
                    econd = el_bin(OPcall, TYint, el_var(getRtlsym(RTLSYM_SWITCH_STRING)), eparam);
                    break;
                case Twchar:
                    econd = el_bin(OPcall, TYint, el_var(getRtlsym(RTLSYM_SWITCH_USTRING)), eparam);
                    break;
                case Tdchar:        // BUG: implement
                    econd = el_bin(OPcall, TYint, el_var(getRtlsym(RTLSYM_SWITCH_DSTRING)), eparam);
                    break;
                default:
                    assert(0);
            }
            elem_setLoc(econd, s->loc);
            string = 1;
        }
        else
            string = 0;
        block_appendexp(mystate.switchBlock, econd);
        block_next(blx,BCswitch,NULL);

        // Corresponding free is in block_free
        targ_llong *pu = (targ_llong *) ::malloc(sizeof(*pu) * (numcases + 1));
        mystate.switchBlock->BS.Bswitch = pu;
        /* First pair is the number of cases, and the default block
         */
        *pu++ = numcases;
        mystate.switchBlock->appendSucc(mystate.defaultBlock);

        /* Fill in the first entry in each pair, which is the case value.
         * CaseStatement::toIR() will fill in
         * the second entry for each pair with the block.
         */
        for (size_t i = 0; i < numcases; i++)
        {
            CaseStatement *cs = (*s->cases)[i];
            if (string)
            {
                pu[cs->index] = i;
            }
            else
            {
                pu[i] = cs->exp->toInteger();
            }
        }

        Statement_toIR(s->_body, &mystate);

        /* Have the end of the switch body fall through to the block
         * following the switch statement.
         */
        block_goto(blx, BCgoto, mystate.breakBlock);
    }