| 1 |
// Copyright (c) 2004-2009 by Digital Mars |
|---|
| 2 |
// All Rights Reserved |
|---|
| 3 |
// written by Walter Bright |
|---|
| 4 |
// http://www.digitalmars.com |
|---|
| 5 |
|
|---|
| 6 |
#include <stdio.h> |
|---|
| 7 |
#include <stddef.h> |
|---|
| 8 |
#include <time.h> |
|---|
| 9 |
#include <assert.h> |
|---|
| 10 |
|
|---|
| 11 |
#include "mars.h" |
|---|
| 12 |
#include "module.h" |
|---|
| 13 |
#include "mtype.h" |
|---|
| 14 |
#include "declaration.h" |
|---|
| 15 |
#include "statement.h" |
|---|
| 16 |
#include "enum.h" |
|---|
| 17 |
#include "aggregate.h" |
|---|
| 18 |
#include "init.h" |
|---|
| 19 |
#include "attrib.h" |
|---|
| 20 |
#include "id.h" |
|---|
| 21 |
#include "import.h" |
|---|
| 22 |
#include "template.h" |
|---|
| 23 |
|
|---|
| 24 |
#include "rmem.h" |
|---|
| 25 |
#include "cc.h" |
|---|
| 26 |
#include "global.h" |
|---|
| 27 |
#include "oper.h" |
|---|
| 28 |
#include "code.h" |
|---|
| 29 |
#include "type.h" |
|---|
| 30 |
#include "dt.h" |
|---|
| 31 |
#include "cv4.h" |
|---|
| 32 |
#include "cgcv.h" |
|---|
| 33 |
#include "outbuf.h" |
|---|
| 34 |
#include "irstate.h" |
|---|
| 35 |
|
|---|
| 36 |
/* The CV4 debug format is defined in: |
|---|
| 37 |
* "CV4 Symbolic Debug Information Specification" |
|---|
| 38 |
* rev 3.1 March 5, 1993 |
|---|
| 39 |
* Languages Business Unit |
|---|
| 40 |
* Microsoft |
|---|
| 41 |
*/ |
|---|
| 42 |
|
|---|
| 43 |
/****************************** |
|---|
| 44 |
* CV4 pg. 25 |
|---|
| 45 |
* Convert D protection attribute to cv attribute. |
|---|
| 46 |
*/ |
|---|
| 47 |
|
|---|
| 48 |
unsigned PROTtoATTR(enum PROT prot) |
|---|
| 49 |
{ |
|---|
| 50 |
unsigned attribute; |
|---|
| 51 |
|
|---|
| 52 |
switch (prot) |
|---|
| 53 |
{ |
|---|
| 54 |
case PROTprivate: attribute = 1; break; |
|---|
| 55 |
case PROTpackage: attribute = 2; break; |
|---|
| 56 |
case PROTprotected: attribute = 2; break; |
|---|
| 57 |
case PROTpublic: attribute = 3; break; |
|---|
| 58 |
case PROTexport: attribute = 3; break; |
|---|
| 59 |
|
|---|
| 60 |
case PROTundefined: |
|---|
| 61 |
case PROTnone: |
|---|
| 62 |
default: |
|---|
| 63 |
//printf("prot = %d\n", prot); |
|---|
| 64 |
assert(0); |
|---|
| 65 |
} |
|---|
| 66 |
return attribute; |
|---|
| 67 |
} |
|---|
| 68 |
|
|---|
| 69 |
unsigned cv4_memfunctypidx(FuncDeclaration *fd) |
|---|
| 70 |
{ type *t; |
|---|
| 71 |
debtyp_t *d; |
|---|
| 72 |
unsigned char *p; |
|---|
| 73 |
AggregateDeclaration *ad; |
|---|
| 74 |
|
|---|
| 75 |
//printf("cv4_memfunctypidx(fd = '%s')\n", fd->toChars()); |
|---|
| 76 |
t = fd->type->toCtype(); |
|---|
| 77 |
ad = fd->isMember2(); |
|---|
| 78 |
if (ad) |
|---|
| 79 |
{ |
|---|
| 80 |
unsigned nparam; |
|---|
| 81 |
idx_t paramidx; |
|---|
| 82 |
idx_t thisidx; |
|---|
| 83 |
unsigned u; |
|---|
| 84 |
unsigned char call; |
|---|
| 85 |
|
|---|
| 86 |
// It's a member function, which gets a special type record |
|---|
| 87 |
|
|---|
| 88 |
if (fd->isStatic()) |
|---|
| 89 |
thisidx = dttab4[TYvoid]; |
|---|
| 90 |
else |
|---|
| 91 |
{ |
|---|
| 92 |
assert(ad->handle); |
|---|
| 93 |
thisidx = cv4_typidx(ad->handle->toCtype()); |
|---|
| 94 |
} |
|---|
| 95 |
|
|---|
| 96 |
paramidx = cv4_arglist(t,&nparam); |
|---|
| 97 |
call = cv4_callconv(t); |
|---|
| 98 |
|
|---|
| 99 |
d = debtyp_alloc(18); |
|---|
| 100 |
p = d->data; |
|---|
| 101 |
TOWORD(p,LF_MFUNCTION); |
|---|
| 102 |
TOWORD(p + 2,cv4_typidx(t->Tnext)); |
|---|
| 103 |
TOWORD(p + 4,cv4_typidx(ad->type->toCtype())); |
|---|
| 104 |
TOWORD(p + 6,thisidx); |
|---|
| 105 |
p[8] = call; |
|---|
| 106 |
p[9] = 0; // reserved |
|---|
| 107 |
TOWORD(p + 10,nparam); |
|---|
| 108 |
TOWORD(p + 12,paramidx); |
|---|
| 109 |
TOLONG(p + 14,0); // thisadjust |
|---|
| 110 |
|
|---|
| 111 |
return cv_debtyp(d); |
|---|
| 112 |
} |
|---|
| 113 |
return cv4_typidx(t); |
|---|
| 114 |
} |
|---|
| 115 |
|
|---|
| 116 |
unsigned cv4_Denum(EnumDeclaration *e) |
|---|
| 117 |
{ |
|---|
| 118 |
debtyp_t *d,*dt; |
|---|
| 119 |
unsigned nfields,fnamelen; |
|---|
| 120 |
unsigned len; |
|---|
| 121 |
unsigned property; |
|---|
| 122 |
unsigned attribute; |
|---|
| 123 |
int i; |
|---|
| 124 |
const char *id; |
|---|
| 125 |
idx_t typidx; |
|---|
| 126 |
|
|---|
| 127 |
//dbg_printf("cv4_Denum(%s)\n", e->toChars()); |
|---|
| 128 |
property = 0; |
|---|
| 129 |
if (!e->members || !e->memtype) |
|---|
| 130 |
property |= 0x80; // enum is forward referenced |
|---|
| 131 |
|
|---|
| 132 |
id = e->toPrettyChars(); |
|---|
| 133 |
len = 10; |
|---|
| 134 |
d = debtyp_alloc(len + cv_stringbytes(id)); |
|---|
| 135 |
TOWORD(d->data,LF_ENUM); |
|---|
| 136 |
TOWORD(d->data + 4,e->memtype ? cv4_typidx(e->memtype->toCtype()) : 0); |
|---|
| 137 |
TOWORD(d->data + 8,property); |
|---|
| 138 |
len += cv_namestring(d->data + len,id); |
|---|
| 139 |
|
|---|
| 140 |
d->length = 0; // so cv_debtyp() will allocate new |
|---|
| 141 |
typidx = cv_debtyp(d); |
|---|
| 142 |
d->length = len; // restore length |
|---|
| 143 |
|
|---|
| 144 |
// Compute the number of fields, and the length of the fieldlist record |
|---|
| 145 |
nfields = 0; |
|---|
| 146 |
fnamelen = 2; |
|---|
| 147 |
if (e->members) |
|---|
| 148 |
{ |
|---|
| 149 |
for (i = 0; i < e->members->dim; i++) |
|---|
| 150 |
{ EnumMember *sf = ((Dsymbol *)e->members->data[i])->isEnumMember(); |
|---|
| 151 |
dinteger_t value; |
|---|
| 152 |
|
|---|
| 153 |
if (sf) |
|---|
| 154 |
{ |
|---|
| 155 |
value = sf->value->toInteger(); |
|---|
| 156 |
unsigned fnamelen1 = fnamelen; |
|---|
| 157 |
fnamelen += 4 + cv4_numericbytes(value) + cv_stringbytes(sf->toPrettyChars()); |
|---|
| 158 |
|
|---|
| 159 |
/* Optlink dies on longer ones, so just truncate |
|---|
| 160 |
*/ |
|---|
| 161 |
if (fnamelen > 0xB000) // 0xB000 found by trial and error |
|---|
| 162 |
{ fnamelen = fnamelen1; // back up |
|---|
| 163 |
break; // and skip the rest |
|---|
| 164 |
} |
|---|
| 165 |
|
|---|
| 166 |
nfields++; |
|---|
| 167 |
} |
|---|
| 168 |
} |
|---|
| 169 |
} |
|---|
| 170 |
|
|---|
| 171 |
TOWORD(d->data + 2,nfields); |
|---|
| 172 |
|
|---|
| 173 |
// If forward reference, then field list is 0 |
|---|
| 174 |
if (!e->members) |
|---|
| 175 |
{ |
|---|
| 176 |
TOWORD(d->data + 6,0); |
|---|
| 177 |
return typidx; |
|---|
| 178 |
} |
|---|
| 179 |
|
|---|
| 180 |
// Generate fieldlist type record |
|---|
| 181 |
dt = debtyp_alloc(fnamelen); |
|---|
| 182 |
TOWORD(dt->data,LF_FIELDLIST); |
|---|
| 183 |
|
|---|
| 184 |
// And fill it in |
|---|
| 185 |
int j = 2; |
|---|
| 186 |
int fieldi = 0; |
|---|
| 187 |
for (i = 0; i < e->members->dim; i++) |
|---|
| 188 |
{ EnumMember *sf = ((Dsymbol *)e->members->data[i])->isEnumMember(); |
|---|
| 189 |
dinteger_t value; |
|---|
| 190 |
|
|---|
| 191 |
if (sf) |
|---|
| 192 |
{ |
|---|
| 193 |
fieldi++; |
|---|
| 194 |
if (fieldi > nfields) |
|---|
| 195 |
break; // chop off the rest |
|---|
| 196 |
|
|---|
| 197 |
value = sf->value->toInteger(); |
|---|
| 198 |
TOWORD(dt->data + j,LF_ENUMERATE); |
|---|
| 199 |
attribute = 0; |
|---|
| 200 |
TOWORD(dt->data + j + 2,attribute); |
|---|
| 201 |
cv4_storenumeric(dt->data + j + 4,value); |
|---|
| 202 |
j += 4 + cv4_numericbytes(value); |
|---|
| 203 |
j += cv_namestring(dt->data + j, sf->toPrettyChars()); |
|---|
| 204 |
|
|---|
| 205 |
// If enum is not a member of a class, output enum members as constants |
|---|
| 206 |
// if (!isclassmember(s)) |
|---|
| 207 |
// { |
|---|
| 208 |
// cv4_outsym(sf); |
|---|
| 209 |
// } |
|---|
| 210 |
} |
|---|
| 211 |
} |
|---|
| 212 |
assert(j == fnamelen); |
|---|
| 213 |
TOWORD(d->data + 6,cv_debtyp(dt)); |
|---|
| 214 |
|
|---|
| 215 |
// cv4_outsym(s); |
|---|
| 216 |
return typidx; |
|---|
| 217 |
} |
|---|
| 218 |
|
|---|
| 219 |
/* ==================================================================== */ |
|---|
| 220 |
|
|---|
| 221 |
/**************************** |
|---|
| 222 |
* Emit symbolic debug info in CV format. |
|---|
| 223 |
*/ |
|---|
| 224 |
|
|---|
| 225 |
void TypedefDeclaration::toDebug() |
|---|
| 226 |
{ |
|---|
| 227 |
//printf("TypedefDeclaration::toDebug('%s')\n", toChars()); |
|---|
| 228 |
|
|---|
| 229 |
assert(config.fulltypes >= CV4); |
|---|
| 230 |
|
|---|
| 231 |
// If it is a member, it is handled by cvMember() |
|---|
| 232 |
if (!isMember()) |
|---|
| 233 |
{ |
|---|
| 234 |
if (basetype->ty == Ttuple) |
|---|
| 235 |
return; |
|---|
| 236 |
|
|---|
| 237 |
unsigned length; |
|---|
| 238 |
const char *id = toPrettyChars(); |
|---|
| 239 |
idx_t typidx = cv4_typidx(basetype->toCtype()); |
|---|
| 240 |
unsigned len = strlen(id); |
|---|
| 241 |
unsigned char *debsym = (unsigned char *) alloca(39 + IDOHD + len); |
|---|
| 242 |
|
|---|
| 243 |
// Output a 'user-defined type' for the tag name |
|---|
| 244 |
TOWORD(debsym + 2,S_UDT); |
|---|
| 245 |
TOIDX(debsym + 4,typidx); |
|---|
| 246 |
length = 2 + 2 + cgcv.sz_idx; |
|---|
| 247 |
length += cv_namestring(debsym + length,id); |
|---|
| 248 |
TOWORD(debsym,length - 2); |
|---|
| 249 |
|
|---|
| 250 |
assert(length <= 40 + len); |
|---|
| 251 |
obj_write_bytes(SegData[DEBSYM],length,debsym); |
|---|
| 252 |
} |
|---|
| 253 |
} |
|---|
| 254 |
|
|---|
| 255 |
|
|---|
| 256 |
void EnumDeclaration::toDebug() |
|---|
| 257 |
{ |
|---|
| 258 |
//printf("EnumDeclaration::toDebug('%s')\n", toChars()); |
|---|
| 259 |
|
|---|
| 260 |
assert(config.fulltypes >= CV4); |
|---|
| 261 |
|
|---|
| 262 |
// If it is a member, it is handled by cvMember() |
|---|
| 263 |
if (!isMember()) |
|---|
| 264 |
{ |
|---|
| 265 |
unsigned length; |
|---|
| 266 |
const char *id = toPrettyChars(); |
|---|
| 267 |
idx_t typidx = cv4_Denum(this); |
|---|
| 268 |
unsigned len = strlen(id); |
|---|
| 269 |
unsigned char *debsym = (unsigned char *) alloca(39 + IDOHD + len); |
|---|
| 270 |
|
|---|
| 271 |
// Output a 'user-defined type' for the tag name |
|---|
| 272 |
TOWORD(debsym + 2,S_UDT); |
|---|
| 273 |
TOIDX(debsym + 4,typidx); |
|---|
| 274 |
length = 2 + 2 + cgcv.sz_idx; |
|---|
| 275 |
length += cv_namestring(debsym + length,id); |
|---|
| 276 |
TOWORD(debsym,length - 2); |
|---|
| 277 |
|
|---|
| 278 |
assert(length <= 40 + len); |
|---|
| 279 |
obj_write_bytes(SegData[DEBSYM],length,debsym); |
|---|
| 280 |
} |
|---|
| 281 |
} |
|---|
| 282 |
|
|---|
| 283 |
|
|---|
| 284 |
void StructDeclaration::toDebug() |
|---|
| 285 |
{ |
|---|
| 286 |
unsigned leaf; |
|---|
| 287 |
unsigned property; |
|---|
| 288 |
unsigned nfields; |
|---|
| 289 |
unsigned fnamelen; |
|---|
| 290 |
const char *id; |
|---|
| 291 |
targ_size_t size; |
|---|
| 292 |
unsigned numidx; |
|---|
| 293 |
debtyp_t *d,*dt; |
|---|
| 294 |
unsigned len; |
|---|
| 295 |
int i; |
|---|
| 296 |
int count; // COUNT field in LF_CLASS |
|---|
| 297 |
unsigned char *p; |
|---|
| 298 |
idx_t typidx = 0; |
|---|
| 299 |
|
|---|
| 300 |
//printf("StructDeclaration::toDebug('%s')\n", toChars()); |
|---|
| 301 |
|
|---|
| 302 |
assert(config.fulltypes >= CV4); |
|---|
| 303 |
if (isAnonymous()) |
|---|
| 304 |
return /*0*/; |
|---|
| 305 |
|
|---|
| 306 |
if (typidx) // if reference already generated |
|---|
| 307 |
return /*typidx*/; // use already existing reference |
|---|
| 308 |
|
|---|
| 309 |
property = 0; |
|---|
| 310 |
if (!members) |
|---|
| 311 |
{ size = 0; |
|---|
| 312 |
property |= 0x80; // forward reference |
|---|
| 313 |
} |
|---|
| 314 |
else |
|---|
| 315 |
size = structsize; |
|---|
| 316 |
|
|---|
| 317 |
if (parent->isAggregateDeclaration()) // if class is nested |
|---|
| 318 |
property |= 8; |
|---|
| 319 |
// if (st->Sctor || st->Sdtor) |
|---|
| 320 |
// property |= 2; // class has ctors and/or dtors |
|---|
| 321 |
// if (st->Sopoverload) |
|---|
| 322 |
// property |= 4; // class has overloaded operators |
|---|
| 323 |
// if (st->Scastoverload) |
|---|
| 324 |
// property |= 0x40; // class has casting methods |
|---|
| 325 |
// if (st->Sopeq && !(st->Sopeq->Sfunc->Fflags & Fnodebug)) |
|---|
| 326 |
// property |= 0x20; // class has overloaded assignment |
|---|
| 327 |
|
|---|
| 328 |
id = toPrettyChars(); |
|---|
| 329 |
numidx = isUnionDeclaration() ? 8 : 12; |
|---|
| 330 |
len = numidx + cv4_numericbytes(size); |
|---|
| 331 |
d = debtyp_alloc(len + cv_stringbytes(id)); |
|---|
| 332 |
cv4_storenumeric(d->data + numidx,size); |
|---|
| 333 |
len += cv_namestring(d->data + len,id); |
|---|
| 334 |
|
|---|
| 335 |
leaf = isUnionDeclaration() ? LF_UNION : LF_STRUCTURE; |
|---|
| 336 |
if (!isUnionDeclaration()) |
|---|
| 337 |
{ |
|---|
| 338 |
TOWORD(d->data + 8,0); // dList |
|---|
| 339 |
TOWORD(d->data + 10,0); // vshape is 0 (no virtual functions) |
|---|
| 340 |
} |
|---|
| 341 |
TOWORD(d->data,leaf); |
|---|
| 342 |
|
|---|
| 343 |
// Assign a number to prevent infinite recursion if a struct member |
|---|
| 344 |
// references the same struct. |
|---|
| 345 |
d->length = 0; // so cv_debtyp() will allocate new |
|---|
| 346 |
typidx = cv_debtyp(d); |
|---|
| 347 |
d->length = len; // restore length |
|---|
| 348 |
|
|---|
| 349 |
if (!members) // if reference only |
|---|
| 350 |
{ |
|---|
| 351 |
TOWORD(d->data + 2,0); // count: number of fields is 0 |
|---|
| 352 |
TOWORD(d->data + 4,0); // field list is 0 |
|---|
| 353 |
TOWORD(d->data + 6,property); |
|---|
| 354 |
return /*typidx*/; |
|---|
| 355 |
} |
|---|
| 356 |
|
|---|
| 357 |
// Compute the number of fields, and the length of the fieldlist record |
|---|
| 358 |
nfields = 0; |
|---|
| 359 |
fnamelen = 2; |
|---|
| 360 |
|
|---|
| 361 |
count = nfields; |
|---|
| 362 |
for (i = 0; i < members->dim; i++) |
|---|
| 363 |
{ Dsymbol *s = (Dsymbol *)members->data[i]; |
|---|
| 364 |
int nwritten; |
|---|
| 365 |
|
|---|
| 366 |
nwritten = s->cvMember(NULL); |
|---|
| 367 |
if (nwritten) |
|---|
| 368 |
{ |
|---|
| 369 |
fnamelen += nwritten; |
|---|
| 370 |
nfields++; |
|---|
| 371 |
count++; |
|---|
| 372 |
} |
|---|
| 373 |
} |
|---|
| 374 |
|
|---|
| 375 |
TOWORD(d->data + 2,count); |
|---|
| 376 |
TOWORD(d->data + 6,property); |
|---|
| 377 |
|
|---|
| 378 |
// Generate fieldlist type record |
|---|
| 379 |
dt = debtyp_alloc(fnamelen); |
|---|
| 380 |
p = dt->data; |
|---|
| 381 |
|
|---|
| 382 |
// And fill it in |
|---|
| 383 |
TOWORD(p,LF_FIELDLIST); |
|---|
| 384 |
p += 2; |
|---|
| 385 |
for (i = 0; i < members->dim; i++) |
|---|
| 386 |
{ Dsymbol *s = (Dsymbol *)members->data[i]; |
|---|
| 387 |
|
|---|
| 388 |
p += s->cvMember(p); |
|---|
| 389 |
} |
|---|
| 390 |
|
|---|
| 391 |
//dbg_printf("fnamelen = %d, p-dt->data = %d\n",fnamelen,p-dt->data); |
|---|
| 392 |
assert(p - dt->data == fnamelen); |
|---|
| 393 |
TOWORD(d->data + 4,cv_debtyp(dt)); |
|---|
| 394 |
|
|---|
| 395 |
// cv4_outsym(s); |
|---|
| 396 |
|
|---|
| 397 |
unsigned char *debsym; |
|---|
| 398 |
unsigned length; |
|---|
| 399 |
|
|---|
| 400 |
len = strlen(id); |
|---|
| 401 |
debsym = (unsigned char *) alloca(39 + IDOHD + len); |
|---|
| 402 |
|
|---|
| 403 |
// Output a 'user-defined type' for the tag name |
|---|
| 404 |
TOWORD(debsym + 2,S_UDT); |
|---|
| 405 |
TOIDX(debsym + 4,typidx); |
|---|
| 406 |
length = 2 + 2 + cgcv.sz_idx; |
|---|
| 407 |
length += cv_namestring(debsym + length,id); |
|---|
| 408 |
TOWORD(debsym,length - 2); |
|---|
| 409 |
|
|---|
| 410 |
assert(length <= 40 + len); |
|---|
| 411 |
obj_write_bytes(SegData[DEBSYM],length,debsym); |
|---|
| 412 |
|
|---|
| 413 |
// return typidx; |
|---|
| 414 |
} |
|---|
| 415 |
|
|---|
| 416 |
|
|---|
| 417 |
void ClassDeclaration::toDebug() |
|---|
| 418 |
{ |
|---|
| 419 |
unsigned leaf; |
|---|
| 420 |
unsigned property; |
|---|
| 421 |
unsigned nfields; |
|---|
| 422 |
unsigned fnamelen; |
|---|
| 423 |
const char *id; |
|---|
| 424 |
targ_size_t size; |
|---|
| 425 |
unsigned numidx; |
|---|
| 426 |
debtyp_t *d,*dt; |
|---|
| 427 |
unsigned len; |
|---|
| 428 |
int i; |
|---|
| 429 |
int count; // COUNT field in LF_CLASS |
|---|
| 430 |
unsigned char *p; |
|---|
| 431 |
idx_t typidx = 0; |
|---|
| 432 |
|
|---|
| 433 |
//printf("ClassDeclaration::toDebug('%s')\n", toChars()); |
|---|
| 434 |
|
|---|
| 435 |
assert(config.fulltypes >= CV4); |
|---|
| 436 |
if (isAnonymous()) |
|---|
| 437 |
return /*0*/; |
|---|
| 438 |
|
|---|
| 439 |
if (typidx) // if reference already generated |
|---|
| 440 |
return /*typidx*/; // use already existing reference |
|---|
| 441 |
|
|---|
| 442 |
property = 0; |
|---|
| 443 |
if (!members) |
|---|
| 444 |
{ size = 0; |
|---|
| 445 |
property |= 0x80; // forward reference |
|---|
| 446 |
} |
|---|
| 447 |
else |
|---|
| 448 |
size = structsize; |
|---|
| 449 |
|
|---|
| 450 |
if (parent->isAggregateDeclaration()) // if class is nested |
|---|
| 451 |
property |= 8; |
|---|
| 452 |
if (ctor || dtors.dim) |
|---|
| 453 |
property |= 2; // class has ctors and/or dtors |
|---|
| 454 |
// if (st->Sopoverload) |
|---|
| 455 |
// property |= 4; // class has overloaded operators |
|---|
| 456 |
// if (st->Scastoverload) |
|---|
| 457 |
// property |= 0x40; // class has casting methods |
|---|
| 458 |
// if (st->Sopeq && !(st->Sopeq->Sfunc->Fflags & Fnodebug)) |
|---|
| 459 |
// property |= 0x20; // class has overloaded assignment |
|---|
| 460 |
|
|---|
| 461 |
id = toPrettyChars(); |
|---|
| 462 |
numidx = isUnionDeclaration() ? 8 : 12; |
|---|
| 463 |
len = numidx + cv4_numericbytes(size); |
|---|
| 464 |
d = debtyp_alloc(len + cv_stringbytes(id)); |
|---|
| 465 |
cv4_storenumeric(d->data + numidx,size); |
|---|
| 466 |
len += cv_namestring(d->data + len,id); |
|---|
| 467 |
|
|---|
| 468 |
leaf = LF_CLASS; |
|---|
| 469 |
TOWORD(d->data + 8,0); // dList |
|---|
| 470 |
|
|---|
| 471 |
if (1) |
|---|
| 472 |
{ debtyp_t *vshape; |
|---|
| 473 |
unsigned n; |
|---|
| 474 |
unsigned char descriptor; |
|---|
| 475 |
|
|---|
| 476 |
n = vtbl.dim; // number of virtual functions |
|---|
| 477 |
if (n == 0) |
|---|
| 478 |
{ |
|---|
| 479 |
TOWORD(d->data + 10,0); // vshape is 0 |
|---|
| 480 |
} |
|---|
| 481 |
else |
|---|
| 482 |
{ int i; |
|---|
| 483 |
|
|---|
| 484 |
vshape = debtyp_alloc(4 + (n + 1) / 2); |
|---|
| 485 |
TOWORD(vshape->data,LF_VTSHAPE); |
|---|
| 486 |
TOWORD(vshape->data + 2,1); |
|---|
| 487 |
|
|---|
| 488 |
n = 0; |
|---|
| 489 |
descriptor = 0; |
|---|
| 490 |
for (i = 0; i < vtbl.dim; i++) |
|---|
| 491 |
{ FuncDeclaration *fd = (FuncDeclaration *)vtbl.data[i]; |
|---|
| 492 |
tym_t ty; |
|---|
| 493 |
|
|---|
| 494 |
//if (intsize == 4) |
|---|
| 495 |
descriptor |= 5; |
|---|
| 496 |
vshape->data[4 + n / 2] = descriptor; |
|---|
| 497 |
descriptor <<= 4; |
|---|
| 498 |
n++; |
|---|
| 499 |
} |
|---|
| 500 |
TOWORD(d->data + 10,cv_debtyp(vshape)); // vshape |
|---|
| 501 |
} |
|---|
| 502 |
} |
|---|
| 503 |
else |
|---|
| 504 |
TOWORD(d->data + 10,0); // vshape is 0 (no virtual functions) |
|---|
| 505 |
|
|---|
| 506 |
TOWORD(d->data,leaf); |
|---|
| 507 |
|
|---|
| 508 |
// Assign a number to prevent infinite recursion if a struct member |
|---|
| 509 |
// references the same struct. |
|---|
| 510 |
d->length = 0; // so cv_debtyp() will allocate new |
|---|
| 511 |
typidx = cv_debtyp(d); |
|---|
| 512 |
d->length = len; // restore length |
|---|
| 513 |
|
|---|
| 514 |
if (!members) // if reference only |
|---|
| 515 |
{ |
|---|
| 516 |
TOWORD(d->data + 2,0); // count: number of fields is 0 |
|---|
| 517 |
TOWORD(d->data + 4,0); // field list is 0 |
|---|
| 518 |
TOWORD(d->data + 6,property); |
|---|
| 519 |
return /*typidx*/; |
|---|
| 520 |
} |
|---|
| 521 |
|
|---|
| 522 |
// Compute the number of fields, and the length of the fieldlist record |
|---|
| 523 |
nfields = 0; |
|---|
| 524 |
fnamelen = 2; |
|---|
| 525 |
|
|---|
| 526 |
// Add in base classes |
|---|
| 527 |
for (i = 0; i < baseclasses->dim; i++) |
|---|
| 528 |
{ BaseClass *bc = (BaseClass *)baseclasses->data[i]; |
|---|
| 529 |
|
|---|
| 530 |
nfields++; |
|---|
| 531 |
fnamelen += 6 + cv4_numericbytes(bc->offset); |
|---|
| 532 |
} |
|---|
| 533 |
|
|---|
| 534 |
count = nfields; |
|---|
| 535 |
for (i = 0; i < members->dim; i++) |
|---|
| 536 |
{ Dsymbol *s = (Dsymbol *)members->data[i]; |
|---|
| 537 |
int nwritten; |
|---|
| 538 |
|
|---|
| 539 |
nwritten = s->cvMember(NULL); |
|---|
| 540 |
if (nwritten) |
|---|
| 541 |
{ |
|---|
| 542 |
fnamelen += nwritten; |
|---|
| 543 |
nfields++; |
|---|
| 544 |
count++; |
|---|
| 545 |
} |
|---|
| 546 |
} |
|---|
| 547 |
|
|---|
| 548 |
TOWORD(d->data + 2,count); |
|---|
| 549 |
TOWORD(d->data + 6,property); |
|---|
| 550 |
|
|---|
| 551 |
// Generate fieldlist type record |
|---|
| 552 |
dt = debtyp_alloc(fnamelen); |
|---|
| 553 |
p = dt->data; |
|---|
| 554 |
|
|---|
| 555 |
// And fill it in |
|---|
| 556 |
TOWORD(p,LF_FIELDLIST); |
|---|
| 557 |
p += 2; |
|---|
| 558 |
|
|---|
| 559 |
// Add in base classes |
|---|
| 560 |
for (i = 0; i < baseclasses->dim; i++) |
|---|
| 561 |
{ BaseClass *bc = (BaseClass *)baseclasses->data[i]; |
|---|
| 562 |
idx_t typidx; |
|---|
| 563 |
unsigned attribute; |
|---|
| 564 |
|
|---|
| 565 |
typidx = cv4_typidx(bc->base->type->toCtype()->Tnext); |
|---|
| 566 |
|
|---|
| 567 |
attribute = PROTtoATTR(bc->protection); |
|---|
| 568 |
|
|---|
| 569 |
TOWORD(p,LF_BCLASS); |
|---|
| 570 |
TOWORD(p + 2,typidx); |
|---|
| 571 |
TOWORD(p + 4,attribute); |
|---|
| 572 |
p += 6; |
|---|
| 573 |
|
|---|
| 574 |
cv4_storenumeric(p, bc->offset); |
|---|
| 575 |
p += cv4_numericbytes(bc->offset); |
|---|
| 576 |
} |
|---|
| 577 |
|
|---|
| 578 |
|
|---|
| 579 |
|
|---|
| 580 |
for (i = 0; i < members->dim; i++) |
|---|
| 581 |
{ Dsymbol *s = (Dsymbol *)members->data[i]; |
|---|
| 582 |
|
|---|
| 583 |
p += s->cvMember(p); |
|---|
| 584 |
} |
|---|
| 585 |
|
|---|
| 586 |
//dbg_printf("fnamelen = %d, p-dt->data = %d\n",fnamelen,p-dt->data); |
|---|
| 587 |
assert(p - dt->data == fnamelen); |
|---|
| 588 |
TOWORD(d->data + 4,cv_debtyp(dt)); |
|---|
| 589 |
|
|---|
| 590 |
// cv4_outsym(s); |
|---|
| 591 |
|
|---|
| 592 |
unsigned char *debsym; |
|---|
| 593 |
unsigned length; |
|---|
| 594 |
|
|---|
| 595 |
len = strlen(id); |
|---|
| 596 |
debsym = (unsigned char *) alloca(39 + IDOHD + len); |
|---|
| 597 |
|
|---|
| 598 |
// Output a 'user-defined type' for the tag name |
|---|
| 599 |
TOWORD(debsym + 2,S_UDT); |
|---|
| 600 |
TOIDX(debsym + 4,typidx); |
|---|
| 601 |
length = 2 + 2 + cgcv.sz_idx; |
|---|
| 602 |
length += cv_namestring(debsym + length,id); |
|---|
| 603 |
TOWORD(debsym,length - 2); |
|---|
| 604 |
|
|---|
| 605 |
assert(length <= 40 + len); |
|---|
| 606 |
obj_write_bytes(SegData[DEBSYM],length,debsym); |
|---|
| 607 |
|
|---|
| 608 |
// return typidx; |
|---|
| 609 |
} |
|---|
| 610 |
|
|---|
| 611 |
|
|---|
| 612 |
/* ===================================================================== */ |
|---|
| 613 |
|
|---|
| 614 |
/***************************************** |
|---|
| 615 |
* Insert CV info into *p. |
|---|
| 616 |
* Returns: |
|---|
| 617 |
* number of bytes written, or that would be written if p==NULL |
|---|
| 618 |
*/ |
|---|
| 619 |
|
|---|
| 620 |
int Dsymbol::cvMember(unsigned char *p) |
|---|
| 621 |
{ |
|---|
| 622 |
return 0; |
|---|
| 623 |
} |
|---|
| 624 |
|
|---|
| 625 |
|
|---|
| 626 |
int TypedefDeclaration::cvMember(unsigned char *p) |
|---|
| 627 |
{ |
|---|
| 628 |
char *id; |
|---|
| 629 |
idx_t typidx; |
|---|
| 630 |
unsigned attribute; |
|---|
| 631 |
int nwritten = 0; |
|---|
| 632 |
debtyp_t *d; |
|---|
| 633 |
|
|---|
| 634 |
//printf("TypedefDeclaration::cvMember() '%s'\n", toChars()); |
|---|
| 635 |
id = toChars(); |
|---|
| 636 |
|
|---|
| 637 |
if (!p) |
|---|
| 638 |
{ |
|---|
| 639 |
nwritten = 4 + cv_stringbytes(id); |
|---|
| 640 |
} |
|---|
| 641 |
else |
|---|
| 642 |
{ |
|---|
| 643 |
TOWORD(p,LF_NESTTYPE); |
|---|
| 644 |
typidx = cv4_typidx(basetype->toCtype()); |
|---|
| 645 |
TOWORD(p + 2,typidx); |
|---|
| 646 |
nwritten = 4 + cv_namestring(p + 4, id); |
|---|
| 647 |
} |
|---|
| 648 |
return nwritten; |
|---|
| 649 |
} |
|---|
| 650 |
|
|---|
| 651 |
|
|---|
| 652 |
int EnumDeclaration::cvMember(unsigned char *p) |
|---|
| 653 |
{ |
|---|
| 654 |
char *id; |
|---|
| 655 |
idx_t typidx; |
|---|
| 656 |
unsigned attribute; |
|---|
| 657 |
int nwritten = 0; |
|---|
| 658 |
debtyp_t *d; |
|---|
| 659 |
|
|---|
| 660 |
//printf("EnumDeclaration::cvMember() '%s'\n", toChars()); |
|---|
| 661 |
id = toChars(); |
|---|
| 662 |
|
|---|
| 663 |
if (!p) |
|---|
| 664 |
{ |
|---|
| 665 |
nwritten = 4 + cv_stringbytes(id); |
|---|
| 666 |
} |
|---|
| 667 |
else |
|---|
| 668 |
{ |
|---|
| 669 |
TOWORD(p,LF_NESTTYPE); |
|---|
| 670 |
typidx = cv4_Denum(this); |
|---|
| 671 |
TOWORD(p + 2,typidx); |
|---|
| 672 |
nwritten = 4 + cv_namestring(p + 4, id); |
|---|
| 673 |
} |
|---|
| 674 |
return nwritten; |
|---|
| 675 |
} |
|---|
| 676 |
|
|---|
| 677 |
|
|---|
| 678 |
int FuncDeclaration::cvMember(unsigned char *p) |
|---|
| 679 |
{ |
|---|
| 680 |
char *id; |
|---|
| 681 |
idx_t typidx; |
|---|
| 682 |
unsigned attribute; |
|---|
| 683 |
int nwritten = 0; |
|---|
| 684 |
debtyp_t *d; |
|---|
| 685 |
|
|---|
| 686 |
//printf("FuncDeclaration::cvMember() '%s'\n", toChars()); |
|---|
| 687 |
|
|---|
| 688 |
if (!type) // if not compiled in, |
|---|
| 689 |
return 0; // skip it |
|---|
| 690 |
|
|---|
| 691 |
id = toChars(); |
|---|
| 692 |
|
|---|
| 693 |
if (!p) |
|---|
| 694 |
{ |
|---|
| 695 |
nwritten = 6 + cv_stringbytes(id); |
|---|
| 696 |
} |
|---|
| 697 |
else |
|---|
| 698 |
{ |
|---|
| 699 |
int count; |
|---|
| 700 |
int mlen; |
|---|
| 701 |
unsigned char *q; |
|---|
| 702 |
|
|---|
| 703 |
count = 0; |
|---|
| 704 |
mlen = 2; |
|---|
| 705 |
{ |
|---|
| 706 |
if (introducing) |
|---|
| 707 |
mlen += 4; |
|---|
| 708 |
mlen += cgcv.sz_idx * 2; |
|---|
| 709 |
count++; |
|---|
| 710 |
} |
|---|
| 711 |
|
|---|
| 712 |
// Allocate and fill it in |
|---|
| 713 |
d = debtyp_alloc(mlen); |
|---|
| 714 |
q = d->data; |
|---|
| 715 |
TOWORD(q,LF_METHODLIST); |
|---|
| 716 |
q += 2; |
|---|
| 717 |
// for (s = sf; s; s = s->Sfunc->Foversym) |
|---|
| 718 |
{ |
|---|
| 719 |
attribute = PROTtoATTR(prot()); |
|---|
| 720 |
|
|---|
| 721 |
/* 0*4 vanilla method |
|---|
| 722 |
* 1*4 virtual method |
|---|
| 723 |
* 2*4 static method |
|---|
| 724 |
* 3*4 friend method |
|---|
| 725 |
* 4*4 introducing virtual method |
|---|
| 726 |
* 5*4 pure virtual method |
|---|
| 727 |
* 6*4 pure introducing virtual method |
|---|
| 728 |
* 7*4 reserved |
|---|
| 729 |
*/ |
|---|
| 730 |
|
|---|
| 731 |
if (isStatic()) |
|---|
| 732 |
attribute |= 2*4; |
|---|
| 733 |
else if (isVirtual()) |
|---|
| 734 |
{ |
|---|
| 735 |
if (introducing) |
|---|
| 736 |
{ |
|---|
| 737 |
if (isAbstract()) |
|---|
| 738 |
attribute |= 6*4; |
|---|
| 739 |
else |
|---|
| 740 |
attribute |= 4*4; |
|---|
| 741 |
} |
|---|
| 742 |
else |
|---|
| 743 |
{ |
|---|
| 744 |
if (isAbstract()) |
|---|
| 745 |
attribute |= 5*4; |
|---|
| 746 |
else |
|---|
| 747 |
attribute |= 1*4; |
|---|
| 748 |
} |
|---|
| 749 |
} |
|---|
| 750 |
else |
|---|
| 751 |
attribute |= 0*4; |
|---|
| 752 |
|
|---|
| 753 |
TOIDX(q,attribute); |
|---|
| 754 |
q += cgcv.sz_idx; |
|---|
| 755 |
TOIDX(q, cv4_memfunctypidx(this)); |
|---|
| 756 |
q += cgcv.sz_idx; |
|---|
| 757 |
if (introducing) |
|---|
| 758 |
{ TOLONG(q, vtblIndex * PTRSIZE); |
|---|
| 759 |
q += 4; |
|---|
| 760 |
} |
|---|
| 761 |
} |
|---|
| 762 |
assert(q - d->data == mlen); |
|---|
| 763 |
|
|---|
| 764 |
typidx = cv_debtyp(d); |
|---|
| 765 |
if (typidx) |
|---|
| 766 |
{ |
|---|
| 767 |
TOWORD(p,LF_METHOD); |
|---|
| 768 |
TOWORD(p + 2,count); |
|---|
| 769 |
nwritten = 4; |
|---|
| 770 |
TOIDX(p + nwritten, typidx); |
|---|
| 771 |
nwritten += cgcv.sz_idx; |
|---|
| 772 |
nwritten += cv_namestring(p + nwritten, id); |
|---|
| 773 |
} |
|---|
| 774 |
} |
|---|
| 775 |
return nwritten; |
|---|
| 776 |
} |
|---|
| 777 |
|
|---|
| 778 |
int VarDeclaration::cvMember(unsigned char *p) |
|---|
| 779 |
{ |
|---|
| 780 |
char *id; |
|---|
| 781 |
idx_t typidx; |
|---|
| 782 |
unsigned attribute; |
|---|
| 783 |
int nwritten = 0; |
|---|
| 784 |
|
|---|
| 785 |
//printf("VarDeclaration::cvMember(p = %p) '%s'\n", p, toChars()); |
|---|
| 786 |
|
|---|
| 787 |
if (type->toBasetype()->ty == Ttuple) |
|---|
| 788 |
return 0; |
|---|
| 789 |
|
|---|
| 790 |
id = toChars(); |
|---|
| 791 |
|
|---|
| 792 |
if (!p) |
|---|
| 793 |
{ |
|---|
| 794 |
if (storage_class & STCfield) |
|---|
| 795 |
{ |
|---|
| 796 |
nwritten += 6 + |
|---|
| 797 |
cv4_numericbytes(offset) + cv_stringbytes(id); |
|---|
| 798 |
} |
|---|
| 799 |
else if (isStatic()) |
|---|
| 800 |
{ |
|---|
| 801 |
nwritten += 6 + cv_stringbytes(id); |
|---|
| 802 |
} |
|---|
| 803 |
} |
|---|
| 804 |
else if (storage_class & STCfield) |
|---|
| 805 |
{ |
|---|
| 806 |
TOWORD(p,LF_MEMBER); |
|---|
| 807 |
typidx = cv_typidx(type->toCtype()); |
|---|
| 808 |
attribute = PROTtoATTR(prot()); |
|---|
| 809 |
assert((attribute & ~3) == 0); |
|---|
| 810 |
TOWORD(p + 2,typidx); |
|---|
| 811 |
TOWORD(p + 4,attribute); |
|---|
| 812 |
cv4_storenumeric(p + 6, offset); |
|---|
| 813 |
nwritten = 6 + cv4_numericbytes( offset); |
|---|
| 814 |
nwritten += cv_namestring(p + nwritten, id); |
|---|
| 815 |
} |
|---|
| 816 |
else if (isStatic()) |
|---|
| 817 |
{ |
|---|
| 818 |
TOWORD(p,LF_STMEMBER); |
|---|
| 819 |
typidx = cv_typidx(type->toCtype()); |
|---|
| 820 |
attribute = PROTtoATTR(prot()); |
|---|
| 821 |
assert((attribute & ~3) == 0); |
|---|
| 822 |
TOWORD(p + 2,typidx); |
|---|
| 823 |
TOWORD(p + 4,attribute); |
|---|
| 824 |
nwritten = 6 + cv_namestring(p + 6, id); |
|---|
| 825 |
} |
|---|
| 826 |
return nwritten; |
|---|
| 827 |
} |
|---|