Exemple #1
0
/***************************************
 * Put out a forward ref for structs, unions, and classes.
 * Only put out the real definitions with toDebug().
 */
idx_t cv8_fwdref(Symbol *s)
{
    assert(config.fulltypes == CV8);
//    if (s->Stypidx && !global.params.multiobj)
//      return s->Stypidx;
    struct_t *st = s->Sstruct;
    unsigned leaf;
    unsigned numidx;
    if (st->Sflags & STRunion)
    {
        leaf = LF_UNION_V3;
        numidx = 10;
    }
    else if (st->Sflags & STRclass)
    {
        leaf = LF_CLASS_V3;
        numidx = 18;
    }
    else
    {
        leaf = LF_STRUCTURE_V3;
        numidx = 18;
    }
    unsigned len = numidx + cv4_numericbytes(0);
    int idlen = strlen(s->Sident);

    if (idlen > CV8_MAX_SYMBOL_LENGTH)
        idlen = CV8_MAX_SYMBOL_LENGTH;

    debtyp_t *d = debtyp_alloc(len + idlen + 1);
    TOWORD(d->data, leaf);
    TOWORD(d->data + 2, 0);     // number of fields
    TOWORD(d->data + 4, 0x80);  // property
    TOLONG(d->data + 6, 0);     // field list
    if (leaf == LF_CLASS_V3 || leaf == LF_STRUCTURE_V3)
    {
        TOLONG(d->data + 10, 0);        // dList
        TOLONG(d->data + 14, 0);        // vshape
    }
    cv4_storenumeric(d->data + numidx, 0);
    cv_namestring(d->data + len, s->Sident, idlen);
    d->data[len + idlen] = 0;
    idx_t typidx = cv_debtyp(d);
    s->Stypidx = typidx;

    return typidx;
}
Exemple #2
0
unsigned cv4_memfunctypidx(FuncDeclaration *fd)
{   type *t;
    debtyp_t *d;
    unsigned char *p;
    AggregateDeclaration *ad;

    //printf("cv4_memfunctypidx(fd = '%s')\n", fd->toChars());
    t = fd->type->toCtype();
    ad = fd->isMember2();
    if (ad)
    {
	unsigned nparam;
	idx_t paramidx;
	idx_t thisidx;
	unsigned u;
	unsigned char call;

	// It's a member function, which gets a special type record

	if (fd->isStatic())
	    thisidx = dttab4[TYvoid];
	else
	{
	    assert(ad->handle);
	    thisidx = cv4_typidx(ad->handle->toCtype());
	}

	paramidx = cv4_arglist(t,&nparam);
	call = cv4_callconv(t);

	d = debtyp_alloc(18);
	p = d->data;
	TOWORD(p,LF_MFUNCTION);
	TOWORD(p + 2,cv4_typidx(t->Tnext));
	TOWORD(p + 4,cv4_typidx(ad->type->toCtype()));
	TOWORD(p + 6,thisidx);
	p[8] = call;
	p[9] = 0;				// reserved
	TOWORD(p + 10,nparam);
	TOWORD(p + 12,paramidx);
	TOLONG(p + 14,0);			// thisadjust

	return cv_debtyp(d);
    }
    return cv4_typidx(t);
}
Exemple #3
0
/****************************************
 * 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);
}
Exemple #4
0
/****************************************
 * Return type index for a darray of type E[]
 * Input:
 *      t       darray type
 *      etypidx type index for E
 */
idx_t cv8_darray(type *t, idx_t etypidx)
{
    //printf("cv8_darray(etypidx = %x)\n", etypidx);
    /* Put out a struct:
     *    struct dArray {
     *      size_t length;
     *      E* ptr;
     *    }
     */

#if 0
    d = debtyp_alloc(18);
    TOWORD(d->data, 0x100F);
    TOWORD(d->data + 2, OEM);
    TOWORD(d->data + 4, 1);     // 1 = dynamic array
    TOLONG(d->data + 6, 2);     // count of type indices to follow
    TOLONG(d->data + 10, 0x23); // index type, T_UQUAD
    TOLONG(d->data + 14, next); // element type
    return cv_debtyp(d);
#endif

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

    static const unsigned char fl[] =
    {
        0x03, 0x12,             // LF_FIELDLIST_V2
        0x0d, 0x15,             // LF_MEMBER_V3
        0x03, 0x00,             // attribute
        0x23, 0x00, 0x00, 0x00, // size_t
        0x00, 0x00,             // offset
        'l', 'e', 'n', 'g', 't', 'h', 0x00,
        0xf3, 0xf2, 0xf1,       // align to 4-byte including length word before data
        0x0d, 0x15,
        0x03, 0x00,
        0x00, 0x00, 0x00, 0x00, // etypidx
        0x08, 0x00,
        'p', 't', 'r', 0x00,
        0xf2, 0xf1,
    };

    debtyp_t *f = debtyp_alloc(sizeof(fl));
    memcpy(f->data,fl,sizeof(fl));
    TOLONG(f->data + 6, I64 ? 0x23 : 0x22); // size_t
    TOLONG(f->data + 26, ptridx);
    TOWORD(f->data + 30, NPTRSIZE);
    idx_t fieldlist = cv_debtyp(f);

    const char *id;
    switch (t->Tnext->Tty)
    {
        case mTYimmutable | TYchar:
            id = "string";
            break;

        case mTYimmutable | TYwchar_t:
            id = "wstring";
            break;

        case mTYimmutable | TYdchar:
            id = "dstring";
            break;

        default:
            id = t->Tident ? t->Tident : "dArray";
            break;
    }

    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
    cv_namestring(d->data + 20, id, idlen);
    d->data[20 + idlen] = 0;

    idx_t top = cv_numdebtypes();
    idx_t debidx = cv_debtyp(d);
    if(top != cv_numdebtypes())
        cv8_udt(id, debidx);

    return debidx;
}
Exemple #5
0
void cv8_func_term(Symbol *sfunc)
{
    //printf("cv8_func_term(%s)\n", sfunc->Sident);

    assert(currentfuncdata.sfunc == sfunc);
    currentfuncdata.section_length = retoffset + retsize;

    funcdata->write(&currentfuncdata, sizeof(currentfuncdata));

    // Write function symbol
    assert(tyfunc(sfunc->ty()));
    idx_t typidx;
    func_t* fn = sfunc->Sfunc;
    if(fn->Fclass)
    {
        // generate member function type info
        // it would be nicer if this could be in cv4_typidx, but the function info is not available there
        unsigned nparam;
        unsigned char call = cv4_callconv(sfunc->Stype);
        idx_t paramidx = cv4_arglist(sfunc->Stype,&nparam);
        unsigned next = cv4_typidx(sfunc->Stype->Tnext);

        type* classtype = (type*)fn->Fclass;
        unsigned classidx = cv4_typidx(classtype);
        type *tp = type_allocn(TYnptr, classtype);
        unsigned thisidx = cv4_typidx(tp);  // TODO
        debtyp_t *d = debtyp_alloc(2 + 4 + 4 + 4 + 1 + 1 + 2 + 4 + 4);
        TOWORD(d->data,LF_MFUNCTION_V2);
        TOLONG(d->data + 2,next);       // return type
        TOLONG(d->data + 6,classidx);   // class type
        TOLONG(d->data + 10,thisidx);   // this type
        d->data[14] = call;
        d->data[15] = 0;                // reserved
        TOWORD(d->data + 16,nparam);
        TOLONG(d->data + 18,paramidx);
        TOLONG(d->data + 22,0);  // this adjust
        typidx = cv_debtyp(d);
    }
    else
        typidx = cv_typidx(sfunc->Stype);

    const char *id = sfunc->prettyIdent ? sfunc->prettyIdent : prettyident(sfunc);
    size_t len = strlen(id);
    if(len > CV8_MAX_SYMBOL_LENGTH)
        len = CV8_MAX_SYMBOL_LENGTH;
    /*
     *  2       length (not including these 2 bytes)
     *  2       S_GPROC_V3
     *  4       parent
     *  4       pend
     *  4       pnext
     *  4       size of function
     *  4       size of function prolog
     *  4       offset to function epilog
     *  4       type index
     *  6       seg:offset of function start
     *  1       flags
     *  n       0 terminated name string
     */
    Outbuffer *buf = currentfuncdata.f1buf;
    buf->reserve(2 + 2 + 4 * 7 + 6 + 1 + len + 1);
    buf->writeWordn( 2 + 4 * 7 + 6 + 1 + len + 1);
    buf->writeWordn(sfunc->Sclass == SCstatic ? S_LPROC_V3 : S_GPROC_V3);
    buf->write32(0);            // parent
    buf->write32(0);            // pend
    buf->write32(0);            // pnext
    buf->write32(currentfuncdata.section_length);       // size of function
    buf->write32(startoffset);          // size of prolog
    buf->write32(retoffset);                    // offset to epilog
    buf->write32(typidx);

    F1_Fixups f1f;
    f1f.s = sfunc;
    f1f.offset = buf->size();
    currentfuncdata.f1fixup->write(&f1f, sizeof(f1f));
    buf->write32(0);
    buf->writeWordn(0);

    buf->writeByte(0);
    buf->writen(id, len);
    buf->writeByte(0);

    // Write local symbol table
    bool endarg = false;
    for (SYMIDX si = 0; si < globsym.top; si++)
    {   //printf("globsym.tab[%d] = %p\n",si,globsym.tab[si]);
        symbol *sa = globsym.tab[si];
        if (endarg == false &&
            sa->Sclass != SCparameter &&
            sa->Sclass != SCfastpar &&
            sa->Sclass != SCshadowreg)
        {
            buf->writeWord(2);
            buf->writeWord(S_ENDARG);
            endarg = true;
        }
        cv8_outsym(sa);
    }

    /* Put out function return record S_RETURN
     * (VC doesn't, so we won't bother, either.)
     */

    // Write function end symbol
    buf->writeWord(2);
    buf->writeWord(S_END);

    currentfuncdata.f1buf = F1_buf;
    currentfuncdata.f1fixup = F1fixup;
}
Exemple #6
0
/****************************************
 * 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);
}
Exemple #7
0
void ClassDeclaration::toDebug()
{
    unsigned leaf;
    unsigned property;
    unsigned nfields;
    unsigned fnamelen;
    const char *id;
    targ_size_t size;
    unsigned numidx;
    debtyp_t *d,*dt;
    unsigned len;
    int i;
    int count;			// COUNT field in LF_CLASS
    unsigned char *p;
    idx_t typidx = 0;

    //printf("ClassDeclaration::toDebug('%s')\n", toChars());

    assert(config.fulltypes >= CV4);
    if (isAnonymous())
	return /*0*/;

    if (typidx)			// if reference already generated
	return /*typidx*/;	// use already existing reference

    property = 0;
    if (!members)
    {	size = 0;
	property |= 0x80;		// forward reference
    }
    else
	size = structsize;

    if (parent->isAggregateDeclaration()) // if class is nested
	property |= 8;
    if (ctor || dtors.dim)
	property |= 2;		// class has ctors and/or dtors
//    if (st->Sopoverload)
//	property |= 4;		// class has overloaded operators
//    if (st->Scastoverload)
//	property |= 0x40;		// class has casting methods
//    if (st->Sopeq && !(st->Sopeq->Sfunc->Fflags & Fnodebug))
//	property |= 0x20;		// class has overloaded assignment

    id = toPrettyChars();
    numidx = isUnionDeclaration() ? 8 : 12;
    len = numidx + cv4_numericbytes(size);
    d = debtyp_alloc(len + cv_stringbytes(id));
    cv4_storenumeric(d->data + numidx,size);
    len += cv_namestring(d->data + len,id);

    leaf = LF_CLASS;
    TOWORD(d->data + 8,0);		// dList

    if (1)
    {   debtyp_t *vshape;
	unsigned n;
	unsigned char descriptor;

	n = vtbl.dim;			// number of virtual functions
	if (n == 0)
	{
	    TOWORD(d->data + 10,0);             // vshape is 0
	}
	else
	{   int i;

	    vshape = debtyp_alloc(4 + (n + 1) / 2);
	    TOWORD(vshape->data,LF_VTSHAPE);
	    TOWORD(vshape->data + 2,1);

	    n = 0;
	    descriptor = 0;
	    for (i = 0; i < vtbl.dim; i++)
	    {   FuncDeclaration *fd = (FuncDeclaration *)vtbl.data[i];
		tym_t ty;

		//if (intsize == 4)
		    descriptor |= 5;
		vshape->data[4 + n / 2] = descriptor;
		descriptor <<= 4;
		n++;
	    }
	    TOWORD(d->data + 10,cv_debtyp(vshape));     // vshape
	}
    }
    else
	TOWORD(d->data + 10,0);		// vshape is 0 (no virtual functions)

    TOWORD(d->data,leaf);

    // Assign a number to prevent infinite recursion if a struct member
    // references the same struct.
    d->length = 0;			// so cv_debtyp() will allocate new
    typidx = cv_debtyp(d);
    d->length = len;		// restore length

    if (!members)			// if reference only
    {
	TOWORD(d->data + 2,0);		// count: number of fields is 0
	TOWORD(d->data + 4,0);		// field list is 0
	TOWORD(d->data + 6,property);
	return /*typidx*/;
    }

    // Compute the number of fields, and the length of the fieldlist record
    nfields = 0;
    fnamelen = 2;

    // Add in base classes
    for (i = 0; i < baseclasses.dim; i++)
    {	BaseClass *bc = (BaseClass *)baseclasses.data[i];

	nfields++;
	fnamelen += 6 + cv4_numericbytes(bc->offset);
    }

    count = nfields;
    for (i = 0; i < members->dim; i++)
    {	Dsymbol *s = (Dsymbol *)members->data[i];
	int nwritten;

	nwritten = s->cvMember(NULL);
	if (nwritten)
	{
	    fnamelen += nwritten;
	    nfields++;
	    count++;
	}
    }

    TOWORD(d->data + 2,count);
    TOWORD(d->data + 6,property);

    // Generate fieldlist type record
    dt = debtyp_alloc(fnamelen);
    p = dt->data;

    // And fill it in
    TOWORD(p,LF_FIELDLIST);
    p += 2;

    // Add in base classes
    for (i = 0; i < baseclasses.dim; i++)
    {	BaseClass *bc = (BaseClass *)baseclasses.data[i];
	idx_t typidx;
	unsigned attribute;

        typidx = cv4_typidx(bc->base->type->toCtype()->Tnext);

	attribute = PROTtoATTR(bc->protection);

        TOWORD(p,LF_BCLASS);
	TOWORD(p + 2,typidx);
	TOWORD(p + 4,attribute);
	p += 6;

        cv4_storenumeric(p, bc->offset);
        p += cv4_numericbytes(bc->offset);
    }



    for (i = 0; i < members->dim; i++)
    {	Dsymbol *s = (Dsymbol *)members->data[i];

	p += s->cvMember(p);
    }

    //dbg_printf("fnamelen = %d, p-dt->data = %d\n",fnamelen,p-dt->data);
    assert(p - dt->data == fnamelen);
    TOWORD(d->data + 4,cv_debtyp(dt));

//    cv4_outsym(s);

    unsigned char *debsym;
    unsigned length;

    len = strlen(id);
    debsym = (unsigned char *) alloca(39 + IDOHD + len);

    // Output a 'user-defined type' for the tag name
    TOWORD(debsym + 2,S_UDT);
    TOIDX(debsym + 4,typidx);
    length = 2 + 2 + cgcv.sz_idx;
    length += cv_namestring(debsym + length,id);
    TOWORD(debsym,length - 2);

    assert(length <= 40 + len);
    obj_write_bytes(SegData[DEBSYM],length,debsym);

//    return typidx;
}
Exemple #8
0
int FuncDeclaration::cvMember(unsigned char *p)
{
    char *id;
    idx_t typidx;
    unsigned attribute;
    int nwritten = 0;
    debtyp_t *d;

    //printf("FuncDeclaration::cvMember() '%s'\n", toChars());

    if (!type)			// if not compiled in,
	return 0;		// skip it

    id = toChars();

    if (!p)
    {
	nwritten = 6 + cv_stringbytes(id);
    }
    else
    {
	int count;
	int mlen;
	unsigned char *q;

	count = 0;
	mlen = 2;
	{
	    if (introducing)
		mlen += 4;
	    mlen += cgcv.sz_idx * 2;
	    count++;
	}

	// Allocate and fill it in
	d = debtyp_alloc(mlen);
	q = d->data;
	TOWORD(q,LF_METHODLIST);
	q += 2;
//	for (s = sf; s; s = s->Sfunc->Foversym)
	{
	    attribute = PROTtoATTR(prot());

	    /* 0*4 vanilla method
	     * 1*4 virtual method
	     * 2*4 static method
	     * 3*4 friend method
	     * 4*4 introducing virtual method
	     * 5*4 pure virtual method
	     * 6*4 pure introducing virtual method
	     * 7*4 reserved
	     */

	    if (isStatic())
		attribute |= 2*4;
	    else if (isVirtual())
	    {
		if (introducing)
		{
		    if (isAbstract())
			attribute |= 6*4;
		    else
			attribute |= 4*4;
		}
		else
		{
		    if (isAbstract())
			attribute |= 5*4;
		    else
			attribute |= 1*4;
		}
	    }
	    else
		attribute |= 0*4;

	    TOIDX(q,attribute);
	    q += cgcv.sz_idx;
	    TOIDX(q, cv4_memfunctypidx(this));
	    q += cgcv.sz_idx;
	    if (introducing)
	    {   TOLONG(q, vtblIndex * PTRSIZE);
		q += 4;
	    }
	}
	assert(q - d->data == mlen);

	typidx = cv_debtyp(d);
	if (typidx)
	{
	    TOWORD(p,LF_METHOD);
	    TOWORD(p + 2,count);
	    nwritten = 4;
	    TOIDX(p + nwritten, typidx);
	    nwritten += cgcv.sz_idx;
	    nwritten += cv_namestring(p + nwritten, id);
	}
    }
    return nwritten;
}
Exemple #9
0
unsigned cv4_Denum(EnumDeclaration *e)
{
    debtyp_t *d,*dt;
    unsigned nfields,fnamelen;
    unsigned len;
    unsigned property;
    unsigned attribute;
    int i;
    const char *id;
    idx_t typidx;

    //dbg_printf("cv4_Denum(%s)\n", e->toChars());
    property = 0;
    if (!e->members || !e->memtype)
	property |= 0x80;		// enum is forward referenced

    id = e->toPrettyChars();
    len = 10;
    d = debtyp_alloc(len + cv_stringbytes(id));
    TOWORD(d->data,LF_ENUM);
    TOWORD(d->data + 4,e->memtype ? cv4_typidx(e->memtype->toCtype()) : 0);
    TOWORD(d->data + 8,property);
    len += cv_namestring(d->data + len,id);

    d->length = 0;			// so cv_debtyp() will allocate new
    typidx = cv_debtyp(d);
    d->length = len;			// restore length

    // Compute the number of fields, and the length of the fieldlist record
    nfields = 0;
    fnamelen = 2;
    if (e->members)
    {
	for (i = 0; i < e->members->dim; i++)
	{   EnumMember *sf = ((Dsymbol *)e->members->data[i])->isEnumMember();
	    dinteger_t value;

	    if (sf)
	    {
		value = sf->value->toInteger();
		unsigned fnamelen1 = fnamelen;
		fnamelen += 4 + cv4_numericbytes(value) + cv_stringbytes(sf->toPrettyChars());

		/* Optlink dies on longer ones, so just truncate
		 */
		if (fnamelen > 0xB000)		// 0xB000 found by trial and error
		{   fnamelen = fnamelen1;	// back up
		    break;			// and skip the rest
		}

		nfields++;
	    }
	}
    }

    TOWORD(d->data + 2,nfields);

    // If forward reference, then field list is 0
    if (!e->members)
    {
	TOWORD(d->data + 6,0);
	return typidx;
    }

    // Generate fieldlist type record
    dt = debtyp_alloc(fnamelen);
    TOWORD(dt->data,LF_FIELDLIST);

    // And fill it in
    int j = 2;
    int fieldi = 0;
    for (i = 0; i < e->members->dim; i++)
    {   EnumMember *sf = ((Dsymbol *)e->members->data[i])->isEnumMember();
	dinteger_t value;

	if (sf)
	{
	    fieldi++;
	    if (fieldi > nfields)
		break;			// chop off the rest

	    value = sf->value->toInteger();
	    TOWORD(dt->data + j,LF_ENUMERATE);
	    attribute = 0;
	    TOWORD(dt->data + j + 2,attribute);
	    cv4_storenumeric(dt->data + j + 4,value);
	    j += 4 + cv4_numericbytes(value);
	    j += cv_namestring(dt->data + j, sf->toPrettyChars());

	    // If enum is not a member of a class, output enum members as constants
//	    if (!isclassmember(s))
//	    {
//		cv4_outsym(sf);
//	    }
	}
    }
    assert(j == fnamelen);
    TOWORD(d->data + 6,cv_debtyp(dt));

//    cv4_outsym(s);
    return typidx;
}
Exemple #10
0
void StructDeclaration::toDebug()
{
    unsigned leaf;
    unsigned property;
    unsigned nfields;
    unsigned fnamelen;
    const char *id;
    targ_size_t size;
    unsigned numidx;
    debtyp_t *d,*dt;
    unsigned len;
    int i;
    int count;			// COUNT field in LF_CLASS
    unsigned char *p;
    idx_t typidx = 0;

    //printf("StructDeclaration::toDebug('%s')\n", toChars());

    assert(config.fulltypes >= CV4);
    if (isAnonymous())
	return /*0*/;

    if (typidx)			// if reference already generated
	return /*typidx*/;	// use already existing reference

    property = 0;
    if (!members)
    {	size = 0;
	property |= 0x80;		// forward reference
    }
    else
	size = structsize;

    if (parent->isAggregateDeclaration()) // if class is nested
	property |= 8;
//    if (st->Sctor || st->Sdtor)
//	property |= 2;		// class has ctors and/or dtors
//    if (st->Sopoverload)
//	property |= 4;		// class has overloaded operators
//    if (st->Scastoverload)
//	property |= 0x40;		// class has casting methods
//    if (st->Sopeq && !(st->Sopeq->Sfunc->Fflags & Fnodebug))
//	property |= 0x20;		// class has overloaded assignment

    id = toPrettyChars();
    numidx = isUnionDeclaration() ? 8 : 12;
    len = numidx + cv4_numericbytes(size);
    d = debtyp_alloc(len + cv_stringbytes(id));
    cv4_storenumeric(d->data + numidx,size);
    len += cv_namestring(d->data + len,id);

    leaf = isUnionDeclaration() ? LF_UNION : LF_STRUCTURE;
    if (!isUnionDeclaration())
    {
	TOWORD(d->data + 8,0);		// dList
	TOWORD(d->data + 10,0);		// vshape is 0 (no virtual functions)
    }
    TOWORD(d->data,leaf);

    // Assign a number to prevent infinite recursion if a struct member
    // references the same struct.
    d->length = 0;			// so cv_debtyp() will allocate new
    typidx = cv_debtyp(d);
    d->length = len;		// restore length

    if (!members)			// if reference only
    {
	TOWORD(d->data + 2,0);		// count: number of fields is 0
	TOWORD(d->data + 4,0);		// field list is 0
	TOWORD(d->data + 6,property);
	return /*typidx*/;
    }

    // Compute the number of fields, and the length of the fieldlist record
    nfields = 0;
    fnamelen = 2;

    count = nfields;
    for (i = 0; i < members->dim; i++)
    {	Dsymbol *s = (Dsymbol *)members->data[i];
	int nwritten;

	nwritten = s->cvMember(NULL);
	if (nwritten)
	{
	    fnamelen += nwritten;
	    nfields++;
	    count++;
	}
    }

    TOWORD(d->data + 2,count);
    TOWORD(d->data + 6,property);

    // Generate fieldlist type record
    dt = debtyp_alloc(fnamelen);
    p = dt->data;

    // And fill it in
    TOWORD(p,LF_FIELDLIST);
    p += 2;
    for (i = 0; i < members->dim; i++)
    {	Dsymbol *s = (Dsymbol *)members->data[i];

	p += s->cvMember(p);
    }

    //dbg_printf("fnamelen = %d, p-dt->data = %d\n",fnamelen,p-dt->data);
    assert(p - dt->data == fnamelen);
    TOWORD(d->data + 4,cv_debtyp(dt));

//    cv4_outsym(s);

    unsigned char *debsym;
    unsigned length;

    len = strlen(id);
    debsym = (unsigned char *) alloca(39 + IDOHD + len);

    // Output a 'user-defined type' for the tag name
    TOWORD(debsym + 2,S_UDT);
    TOIDX(debsym + 4,typidx);
    length = 2 + 2 + cgcv.sz_idx;
    length += cv_namestring(debsym + length,id);
    TOWORD(debsym,length - 2);

    assert(length <= 40 + len);
    obj_write_bytes(SegData[DEBSYM],length,debsym);

//    return typidx;
}
Exemple #11
0
int FuncDeclaration::cvMember(unsigned char *p)
{
    int nwritten = 0;

    //printf("FuncDeclaration::cvMember() '%s'\n", toChars());

    if (!type)                  // if not compiled in,
        return 0;               // skip it

    char *id = toChars();

    if (!p)
    {
        nwritten = 2 + 2 + cgcv.sz_idx + cv_stringbytes(id);
        nwritten = cv_align(NULL, nwritten);
        return nwritten;
    }
    else
    {
        int count = 0;
        int mlen = 2;
        {
            if (introducing)
                mlen += 4;
            mlen += cgcv.sz_idx * 2;
            count++;
        }

        // Allocate and fill it in
        debtyp_t *d = debtyp_alloc(mlen);
        unsigned char *q = d->data;
        TOWORD(q,config.fulltypes == CV8 ? LF_METHODLIST_V2 : LF_METHODLIST);
        q += 2;
//      for (s = sf; s; s = s->Sfunc->Foversym)
        {
            unsigned attribute = PROTtoATTR(prot());

            /* 0*4 vanilla method
             * 1*4 virtual method
             * 2*4 static method
             * 3*4 friend method
             * 4*4 introducing virtual method
             * 5*4 pure virtual method
             * 6*4 pure introducing virtual method
             * 7*4 reserved
             */

            if (isStatic())
                attribute |= 2*4;
            else if (isVirtual())
            {
                if (introducing)
                {
                    if (isAbstract())
                        attribute |= 6*4;
                    else
                        attribute |= 4*4;
                }
                else
                {
                    if (isAbstract())
                        attribute |= 5*4;
                    else
                        attribute |= 1*4;
                }
            }
            else
                attribute |= 0*4;

            TOIDX(q,attribute);
            q += cgcv.sz_idx;
            TOIDX(q, cv4_memfunctypidx(this));
            q += cgcv.sz_idx;
            if (introducing)
            {   TOLONG(q, vtblIndex * Target::ptrsize);
                q += 4;
            }
        }
        assert(q - d->data == mlen);

        idx_t typidx = cv_debtyp(d);
        if (typidx)
        {
            switch (config.fulltypes)
            {
                case CV8:
                    TOWORD(p,LF_METHOD_V3);
                    goto Lmethod;
                case CV4:
                    TOWORD(p,LF_METHOD);
                Lmethod:
                    TOWORD(p + 2,count);
                    nwritten = 4;
                    TOIDX(p + nwritten, typidx);
                    nwritten += cgcv.sz_idx;
                    nwritten += cv_namestring(p + nwritten, id);
                    break;

                default:
                    assert(0);
            }
        }
        nwritten = cv_align(p + nwritten, nwritten);
#ifdef DEBUG
        assert(nwritten == cvMember(NULL));
#endif
    }
    return nwritten;
}
Exemple #12
0
unsigned cv4_memfunctypidx(FuncDeclaration *fd)
{
    //printf("cv4_memfunctypidx(fd = '%s')\n", fd->toChars());

    type *t = fd->type->toCtype();
    AggregateDeclaration *ad = fd->isMember2();
    if (ad)
    {
        // It's a member function, which gets a special type record

        idx_t thisidx;
        if (fd->isStatic())
            thisidx = dttab4[TYvoid];
        else
        {
            assert(ad->handle);
            thisidx = cv4_typidx(ad->handle->toCtype());
        }

        unsigned nparam;
        idx_t paramidx = cv4_arglist(t,&nparam);

        unsigned char call = cv4_callconv(t);

        debtyp_t *d;
        switch (config.fulltypes)
        {
            case CV4:
            {
                d = debtyp_alloc(18);
                unsigned char *p = d->data;
                TOWORD(p,LF_MFUNCTION);
                TOWORD(p + 2,cv4_typidx(t->Tnext));
                TOWORD(p + 4,cv4_typidx(ad->type->toCtype()));
                TOWORD(p + 6,thisidx);
                p[8] = call;
                p[9] = 0;                               // reserved
                TOWORD(p + 10,nparam);
                TOWORD(p + 12,paramidx);
                TOLONG(p + 14,0);                       // thisadjust
                break;
            }
            case CV8:
            {
                d = debtyp_alloc(26);
                unsigned char *p = d->data;
                TOWORD(p,0x1009);
                TOLONG(p + 2,cv4_typidx(t->Tnext));
                TOLONG(p + 6,cv4_typidx(ad->type->toCtype()));
                TOLONG(p + 10,thisidx);
                p[14] = call;
                p[15] = 0;                               // reserved
                TOWORD(p + 16,nparam);
                TOLONG(p + 18,paramidx);
                TOLONG(p + 22,0);                       // thisadjust
                break;
            }
            default:
                assert(0);
        }
        return cv_debtyp(d);
    }
    return cv4_typidx(t);
}
Exemple #13
0
void ClassDeclaration::toDebug()
{
    idx_t typidx = 0;

    //printf("ClassDeclaration::toDebug('%s')\n", toChars());

    assert(config.fulltypes >= CV4);
    if (isAnonymous())
        return /*0*/;

    if (typidx)                 // if reference already generated
        return /*typidx*/;      // use already existing reference

    targ_size_t size;
    unsigned property = 0;
    if (!members)
    {   size = 0;
        property |= 0x80;               // forward reference
    }
    else
        size = structsize;

    if (parent->isAggregateDeclaration()) // if class is nested
        property |= 8;
    if (ctor || dtors.dim)
        property |= 2;          // class has ctors and/or dtors
//    if (st->Sopoverload)
//      property |= 4;          // class has overloaded operators
//    if (st->Scastoverload)
//      property |= 0x40;               // class has casting methods
//    if (st->Sopeq && !(st->Sopeq->Sfunc->Fflags & Fnodebug))
//      property |= 0x20;               // class has overloaded assignment

#if DMDV1
    const char *id = toPrettyChars();
#else
    const char *id = isCPPinterface() ? ident->toChars() : toPrettyChars();
#endif
    unsigned leaf = config.fulltypes == CV8 ? LF_CLASS_V3 : LF_CLASS;

    unsigned numidx = (leaf == LF_CLASS_V3) ? 18 : 12;
    unsigned len = numidx + cv4_numericbytes(size);
    debtyp_t *d = debtyp_alloc(len + cv_stringbytes(id));
    cv4_storenumeric(d->data + numidx,size);
    len += cv_namestring(d->data + len,id);

    idx_t vshapeidx = 0;
    if (1)
    {
        size_t n = vtbl.dim;                   // number of virtual functions
        if (n)
        {   // 4 bits per descriptor
            debtyp_t *vshape = debtyp_alloc(4 + (n + 1) / 2);
            TOWORD(vshape->data,LF_VTSHAPE);
            TOWORD(vshape->data + 2,n);

            n = 0;
            unsigned char descriptor = 0;
            for (size_t i = 0; i < vtbl.dim; i++)
            {   FuncDeclaration *fd = (FuncDeclaration *)vtbl[i];

                //if (intsize == 4)
                    descriptor |= 5;
                vshape->data[4 + n / 2] = descriptor;
                descriptor <<= 4;
                n++;
            }
            vshapeidx = cv_debtyp(vshape);
        }
    }
    if (leaf == LF_CLASS)
    {
        TOWORD(d->data + 8,0);          // dList
        TOWORD(d->data + 10,vshapeidx);
    }
    else if (leaf == LF_CLASS_V3)
    {
        TOLONG(d->data + 10,0);         // dList
        TOLONG(d->data + 14,vshapeidx);
    }
    TOWORD(d->data,leaf);

    // Assign a number to prevent infinite recursion if a struct member
    // references the same struct.
    unsigned length_save = d->length;
    d->length = 0;                      // so cv_debtyp() will allocate new
    typidx = cv_debtyp(d);
    d->length = length_save;            // restore length

    if (!members)                       // if reference only
    {
        if (leaf == LF_CLASS_V3)
        {
            TOWORD(d->data + 2,0);          // count: number of fields is 0
            TOLONG(d->data + 6,0);          // field list is 0
            TOWORD(d->data + 4,property);
        }
        else
        {
            TOWORD(d->data + 2,0);          // count: number of fields is 0
            TOWORD(d->data + 4,0);          // field list is 0
            TOWORD(d->data + 6,property);
        }
        return /*typidx*/;
    }

    // Compute the number of fields (nfields), and the length of the fieldlist record (fnamelen)
    CvMemberCount mc;
    mc.nfields = 0;
    mc.fnamelen = 2;

    /* Adding in the base classes causes VS 2010 debugger to refuse to display any
     * of the fields. I have not been able to determine why.
     * (Could it be because the base class is "forward referenced"?)
     * It does work with VS 2012.
     */
    bool addInBaseClasses = true;
    if (addInBaseClasses)
    {
        // Add in base classes
        for (size_t i = 0; i < baseclasses->dim; i++)
        {   BaseClass *bc = (*baseclasses)[i];

            mc.nfields++;
            unsigned elementlen = 4 + cgcv.sz_idx + cv4_numericbytes(bc->offset);
            elementlen = cv_align(NULL, elementlen);
            mc.fnamelen += elementlen;
        }
    }

    for (size_t i = 0; i < members->dim; i++)
    {   Dsymbol *s = (*members)[i];
        s->apply(&cv_mem_count, &mc);
    }
    unsigned nfields = mc.nfields;
    unsigned fnamelen = mc.fnamelen;

    int count = nfields;
    TOWORD(d->data + 2,count);

    // Generate fieldlist type record
    debtyp_t *dt = debtyp_alloc(fnamelen);
    unsigned char *p = dt->data;

    // And fill it in
    TOWORD(p,config.fulltypes == CV8 ? LF_FIELDLIST_V2 : LF_FIELDLIST);
    p += 2;

    if (addInBaseClasses)
    {
        // Add in base classes
        for (size_t i = 0; i < baseclasses->dim; i++)
        {   BaseClass *bc = (*baseclasses)[i];

            idx_t typidx = cv4_typidx(bc->base->type->toCtype()->Tnext);
            unsigned attribute = PROTtoATTR(bc->protection);

            unsigned elementlen;
            switch (config.fulltypes)
            {
                case CV8:
                    TOWORD(p, LF_BCLASS_V2);
                    TOWORD(p + 2,attribute);
                    TOLONG(p + 4,typidx);
                    elementlen = 8;
                    break;

                case CV4:
                    TOWORD(p, LF_BCLASS);
                    TOWORD(p + 2,typidx);
                    TOWORD(p + 4,attribute);
                    elementlen = 6;
                    break;
            }

            cv4_storenumeric(p + elementlen, bc->offset);
            elementlen += cv4_numericbytes(bc->offset);
            elementlen = cv_align(p + elementlen, elementlen);
            p += elementlen;
        }
    }

    for (size_t i = 0; i < members->dim; i++)
    {   Dsymbol *s = (*members)[i];
        s->apply(&cv_mem_p, &p);
    }

    //dbg_printf("fnamelen = %d, p-dt->data = %d\n",fnamelen,p-dt->data);
    assert(p - dt->data == fnamelen);
    idx_t fieldlist = cv_debtyp(dt);

    TOWORD(d->data + 2,count);
    if (config.fulltypes == CV8)
    {
        TOWORD(d->data + 4,property);
        TOLONG(d->data + 6,fieldlist);
    }
    else
    {
        TOWORD(d->data + 4,fieldlist);
        TOWORD(d->data + 6,property);
    }

//    cv4_outsym(s);

    if (config.fulltypes == CV8)
        cv8_udt(id, typidx);
    else
    {
        size_t idlen = strlen(id);
        unsigned char *debsym = (unsigned char *) alloca(39 + IDOHD + idlen);

        // Output a 'user-defined type' for the tag name
        TOWORD(debsym + 2,S_UDT);
        TOIDX(debsym + 4,typidx);
        unsigned length = 2 + 2 + cgcv.sz_idx;
        length += cv_namestring(debsym + length,id);
        TOWORD(debsym,length - 2);

        assert(length <= 40 + idlen);
        objmod->write_bytes(SegData[DEBSYM],length,debsym);
    }

//    return typidx;
}
Exemple #14
0
void StructDeclaration::toDebug()
{
    idx_t typidx = 0;

    //printf("StructDeclaration::toDebug('%s')\n", toChars());

    assert(config.fulltypes >= CV4);
    if (isAnonymous())
        return /*0*/;

    if (typidx)                 // if reference already generated
        return /*typidx*/;      // use already existing reference

    targ_size_t size;
    unsigned property = 0;
    if (!members)
    {   size = 0;
        property |= 0x80;               // forward reference
    }
    else
        size = structsize;

    if (parent->isAggregateDeclaration()) // if class is nested
        property |= 8;
//    if (st->Sctor || st->Sdtor)
//      property |= 2;          // class has ctors and/or dtors
//    if (st->Sopoverload)
//      property |= 4;          // class has overloaded operators
//    if (st->Scastoverload)
//      property |= 0x40;               // class has casting methods
//    if (st->Sopeq && !(st->Sopeq->Sfunc->Fflags & Fnodebug))
//      property |= 0x20;               // class has overloaded assignment

    const char *id = toPrettyChars();

    unsigned leaf = isUnionDeclaration() ? LF_UNION : LF_STRUCTURE;
    if (config.fulltypes == CV8)
        leaf = leaf == LF_UNION ? LF_UNION_V3 : LF_STRUCTURE_V3;

    unsigned numidx;
    switch (leaf)
    {
        case LF_UNION:        numidx = 8;       break;
        case LF_UNION_V3:     numidx = 10;      break;
        case LF_STRUCTURE:    numidx = 12;      break;
        case LF_STRUCTURE_V3: numidx = 18;      break;
    }

    unsigned len = numidx + cv4_numericbytes(size);
    debtyp_t *d = debtyp_alloc(len + cv_stringbytes(id));
    cv4_storenumeric(d->data + numidx,size);
    len += cv_namestring(d->data + len,id);

    if (leaf == LF_STRUCTURE)
    {
        TOWORD(d->data + 8,0);          // dList
        TOWORD(d->data + 10,0);         // vshape is 0 (no virtual functions)
    }
    else if (leaf == LF_STRUCTURE_V3)
    {
        TOLONG(d->data + 10,0);         // dList
        TOLONG(d->data + 14,0);         // vshape is 0 (no virtual functions)
    }
    TOWORD(d->data,leaf);

    // Assign a number to prevent infinite recursion if a struct member
    // references the same struct.
    unsigned length_save = d->length;
    d->length = 0;                      // so cv_debtyp() will allocate new
    typidx = cv_debtyp(d);
    d->length = length_save;            // restore length

    if (!members)                       // if reference only
    {
        if (config.fulltypes == CV8)
        {
            TOWORD(d->data + 2,0);          // count: number of fields is 0
            TOLONG(d->data + 6,0);          // field list is 0
            TOWORD(d->data + 4,property);
        }
        else
        {
            TOWORD(d->data + 2,0);          // count: number of fields is 0
            TOWORD(d->data + 4,0);          // field list is 0
            TOWORD(d->data + 6,property);
        }
        return /*typidx*/;
    }

    // Compute the number of fields (nfields), and the length of the fieldlist record (fnamelen)
    CvMemberCount mc;
    mc.nfields = 0;
    mc.fnamelen = 2;
    for (size_t i = 0; i < members->dim; i++)
    {   Dsymbol *s = (*members)[i];
        s->apply(&cv_mem_count, &mc);
    }
    unsigned nfields = mc.nfields;
    unsigned fnamelen = mc.fnamelen;

    int count = nfields;                  // COUNT field in LF_CLASS

    // Generate fieldlist type record
    debtyp_t *dt = debtyp_alloc(fnamelen);
    unsigned char *p = dt->data;

    // And fill it in
    TOWORD(p,config.fulltypes == CV8 ? LF_FIELDLIST_V2 : LF_FIELDLIST);
    p += 2;
    for (size_t i = 0; i < members->dim; i++)
    {   Dsymbol *s = (*members)[i];
        s->apply(&cv_mem_p, &p);
    }

    //dbg_printf("fnamelen = %d, p-dt->data = %d\n",fnamelen,p-dt->data);
    assert(p - dt->data == fnamelen);
    idx_t fieldlist = cv_debtyp(dt);

    TOWORD(d->data + 2,count);
    if (config.fulltypes == CV8)
    {
        TOWORD(d->data + 4,property);
        TOLONG(d->data + 6,fieldlist);
    }
    else
    {
        TOWORD(d->data + 4,fieldlist);
        TOWORD(d->data + 6,property);
    }

//    cv4_outsym(s);

    if (config.fulltypes == CV8)
        cv8_udt(id, typidx);
    else
    {
        size_t idlen = strlen(id);
        unsigned char *debsym = (unsigned char *) alloca(39 + IDOHD + idlen);

        // Output a 'user-defined type' for the tag name
        TOWORD(debsym + 2,S_UDT);
        TOIDX(debsym + 4,typidx);
        unsigned length = 2 + 2 + cgcv.sz_idx;
        length += cv_namestring(debsym + length,id);
        TOWORD(debsym,length - 2);

        assert(length <= 40 + idlen);
        objmod->write_bytes(SegData[DEBSYM],length,debsym);
    }

//    return typidx;
}
Exemple #15
0
unsigned cv4_Denum(EnumDeclaration *e)
{
    //dbg_printf("cv4_Denum(%s)\n", e->toChars());
    unsigned property = 0;
        if (!e->members || !e->memtype || !e->memtype->isintegral())
        property |= 0x80;               // enum is forward referenced or non-integer

    // Compute the number of fields, and the length of the fieldlist record
    unsigned nfields = 0;
    unsigned fnamelen = 2;
    if (!property)
    {
        for (size_t i = 0; i < e->members->dim; i++)
        {   EnumMember *sf = (*e->members)[i]->isEnumMember();
            if (sf)
            {
                dinteger_t value = sf->value->toInteger();
                unsigned fnamelen1 = fnamelen;

                // store only member's simple name
                fnamelen += 4 + cv4_numericbytes(value) + cv_stringbytes(sf->toChars());

                if (config.fulltypes != CV8)
                {
                    /* Optlink dies on longer ones, so just truncate
                     */
                    if (fnamelen > 0xB000)          // 0xB000 found by trial and error
                    {   fnamelen = fnamelen1;       // back up
                        break;                      // and skip the rest
                    }
                }

                nfields++;
            }
        }
    }

    const char *id = e->toPrettyChars();
    unsigned len;
    debtyp_t *d;
    unsigned memtype = e->memtype ? cv4_typidx(e->memtype->toCtype()) : 0;
    switch (config.fulltypes)
    {
        case CV8:
            len = 14;
            d = debtyp_alloc(len + cv_stringbytes(id));
            TOWORD(d->data,LF_ENUM_V3);
            TOLONG(d->data + 6,memtype);
            TOWORD(d->data + 4,property);
            len += cv_namestring(d->data + len,id);
            break;

        case CV4:
            len = 10;
            d = debtyp_alloc(len + cv_stringbytes(id));
            TOWORD(d->data,LF_ENUM);
            TOWORD(d->data + 4,memtype);
            TOWORD(d->data + 8,property);
            len += cv_namestring(d->data + len,id);
            break;

        default:
            assert(0);
    }
    unsigned length_save = d->length;
    d->length = 0;                      // so cv_debtyp() will allocate new
    idx_t typidx = cv_debtyp(d);
    d->length = length_save;            // restore length

    TOWORD(d->data + 2,nfields);

    unsigned fieldlist = 0;
    if (!property)                      // if forward reference, then fieldlist is 0
    {
        // Generate fieldlist type record
        debtyp_t *dt = debtyp_alloc(fnamelen);
        TOWORD(dt->data,(config.fulltypes == CV8) ? LF_FIELDLIST_V2 : LF_FIELDLIST);

        // And fill it in
        unsigned j = 2;
        unsigned fieldi = 0;
        for (size_t i = 0; i < e->members->dim; i++)
        {   EnumMember *sf = (*e->members)[i]->isEnumMember();

            if (sf)
            {
                fieldi++;
                if (fieldi > nfields)
                    break;                  // chop off the rest

                dinteger_t value = sf->value->toInteger();
                TOWORD(dt->data + j,(config.fulltypes == CV8) ? LF_ENUMERATE_V3 : LF_ENUMERATE);
                unsigned attribute = 0;
                TOWORD(dt->data + j + 2,attribute);
                cv4_storenumeric(dt->data + j + 4,value);
                j += 4 + cv4_numericbytes(value);
                // store only member's simple name
                j += cv_namestring(dt->data + j, sf->toChars());

                // If enum is not a member of a class, output enum members as constants
    //          if (!isclassmember(s))
    //          {
    //              cv4_outsym(sf);
    //          }
            }
        }
        assert(j == fnamelen);
        fieldlist = cv_debtyp(dt);
    }

    if (config.fulltypes == CV8)
        TOLONG(d->data + 10,fieldlist);
    else
        TOWORD(d->data + 6,fieldlist);

//    cv4_outsym(s);
    return typidx;
}