void EnumDeclaration::toDebug() { //printf("EnumDeclaration::toDebug('%s')\n", toChars()); assert(config.fulltypes >= CV4); // If it is a member, it is handled by cvMember() if (!isMember()) { unsigned length; const char *id = toPrettyChars(); idx_t typidx = cv4_Denum(this); unsigned len = strlen(id); unsigned char *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); } }
void TypedefDeclaration::toDebug() { //printf("TypedefDeclaration::toDebug('%s')\n", toChars()); assert(config.fulltypes >= CV4); // If it is a member, it is handled by cvMember() if (!isMember()) { if (basetype->ty == Ttuple) return; const char *id = toPrettyChars(); idx_t typidx = cv4_typidx(basetype->toCtype()); if (config.fulltypes == CV8) cv8_udt(id, typidx); else { unsigned len = strlen(id); unsigned char *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); unsigned length = 2 + 2 + cgcv.sz_idx; length += cv_namestring(debsym + length,id); TOWORD(debsym,length - 2); assert(length <= 40 + len); objmod->write_bytes(SegData[DEBSYM],length,debsym); } } }
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; }
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; }
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; }
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; }
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; }
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; }