/*************************************** * 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; }
void cvMemberCommon(Dsymbol *s, char *id, idx_t typidx) { if (!p) result = cv_stringbytes(id); switch (config.fulltypes) { case CV8: if (!p) { result += 8; result = cv_align(NULL, result); } else { TOWORD(p,LF_NESTTYPE_V3); TOWORD(p + 2,0); TOLONG(p + 4,typidx); result = 8 + cv_namestring(p + 8, id); result = cv_align(p + result, result); } break; case CV4: if (!p) { result += 4; } else { TOWORD(p,LF_NESTTYPE); TOWORD(p + 2,typidx); result = 4 + cv_namestring(p + 4, id); } break; default: assert(0); } #ifdef DEBUG if (p) { int save = result; p = NULL; cvMemberCommon(s, id, typidx); assert(result == save); } #endif }
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); }
int cvMember(unsigned char *p, char *id, idx_t typidx) { int nwritten = 0; if (!p) nwritten = cv_stringbytes(id); switch (config.fulltypes) { case CV8: if (!p) { nwritten += 8; nwritten = cv_align(NULL, nwritten); } else { TOWORD(p,LF_NESTTYPE_V3); TOWORD(p + 2,0); TOLONG(p + 4,typidx); nwritten = 8 + cv_namestring(p + 8, id); nwritten = cv_align(p + nwritten, nwritten); } break; case CV4: if (!p) { nwritten += 4; } else { TOWORD(p,LF_NESTTYPE); TOWORD(p + 2,typidx); nwritten = 4 + cv_namestring(p + 4, id); } break; default: assert(0); } #ifdef DEBUG if (p) assert(nwritten == cvMember(NULL, id, typidx)); #endif return nwritten; }
/**************************************** * 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); }
/**************************************** * 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; }
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(¤tfuncdata, 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; }
/**************************************** * 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); }
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; }
int VarDeclaration::cvMember(unsigned char *p) { int nwritten = 0; //printf("VarDeclaration::cvMember(p = %p) '%s'\n", p, toChars()); if (type->toBasetype()->ty == Ttuple) return 0; char *id = toChars(); if (!p) { if (isField()) { if (config.fulltypes == CV8) nwritten += 2; nwritten += 6 + cv_stringbytes(id); nwritten += cv4_numericbytes(offset); } else if (isStatic()) { if (config.fulltypes == CV8) nwritten += 2; nwritten += 6 + cv_stringbytes(id); } nwritten = cv_align(NULL, nwritten); } else { idx_t typidx = cv_typidx(type->toCtype()); unsigned attribute = PROTtoATTR(prot()); assert((attribute & ~3) == 0); switch (config.fulltypes) { case CV8: if (isField()) { TOWORD(p,LF_MEMBER_V3); TOWORD(p + 2,attribute); TOLONG(p + 4,typidx); cv4_storenumeric(p + 8, offset); nwritten = 8 + cv4_numericbytes( offset); nwritten += cv_namestring(p + nwritten, id); } else if (isStatic()) { TOWORD(p,LF_STMEMBER_V3); TOWORD(p + 2,attribute); TOLONG(p + 4,typidx); nwritten = 8; nwritten += cv_namestring(p + nwritten, id); } break; case CV4: if (isField()) { TOWORD(p,LF_MEMBER); TOWORD(p + 2,typidx); TOWORD(p + 4,attribute); cv4_storenumeric(p + 6, offset); nwritten = 6 + cv4_numericbytes( offset); nwritten += cv_namestring(p + nwritten, id); } else if (isStatic()) { TOWORD(p,LF_STMEMBER); TOWORD(p + 2,typidx); TOWORD(p + 4,attribute); nwritten = 6; 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; }
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; }
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); }
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; }
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; }
void visit(VarDeclaration *vd) { //printf("VarDeclaration::cvMember(p = %p) '%s'\n", p, vd->toChars()); if (vd->type->toBasetype()->ty == Ttuple) return; char *id = vd->toChars(); if (!p) { if (vd->isField()) { if (config.fulltypes == CV8) result += 2; result += 6 + cv_stringbytes(id); result += cv4_numericbytes(vd->offset); } else if (vd->isStatic()) { if (config.fulltypes == CV8) result += 2; result += 6 + cv_stringbytes(id); } result = cv_align(NULL, result); } else { idx_t typidx = cv_typidx(Type_toCtype(vd->type)); unsigned attribute = PROTtoATTR(vd->prot()); assert((attribute & ~3) == 0); switch (config.fulltypes) { case CV8: if (vd->isField()) { TOWORD(p,LF_MEMBER_V3); TOWORD(p + 2,attribute); TOLONG(p + 4,typidx); cv4_storenumeric(p + 8, vd->offset); result = 8 + cv4_numericbytes(vd->offset); result += cv_namestring(p + result, id); } else if (vd->isStatic()) { TOWORD(p,LF_STMEMBER_V3); TOWORD(p + 2,attribute); TOLONG(p + 4,typidx); result = 8; result += cv_namestring(p + result, id); } break; case CV4: if (vd->isField()) { TOWORD(p,LF_MEMBER); TOWORD(p + 2,typidx); TOWORD(p + 4,attribute); cv4_storenumeric(p + 6, vd->offset); result = 6 + cv4_numericbytes(vd->offset); result += cv_namestring(p + result, id); } else if (vd->isStatic()) { TOWORD(p,LF_STMEMBER); TOWORD(p + 2,typidx); TOWORD(p + 4,attribute); result = 6; result += cv_namestring(p + result, id); } break; default: assert(0); } result = cv_align(p + result, result); #ifdef DEBUG int save = result; result = 0; p = NULL; visit(vd); assert(result == save); #endif } }