root/trunk/src/tocvdebug.c

Revision 520, 20.9 kB (checked in by walter, 2 years ago)

some cleanup

  • Property svn:eol-style set to native
Line 
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 }
Note: See TracBrowser for help on using the browser.