1 From 60a2bf694f1166ca012fcb0a3fb8c092a1afd26b Mon Sep 17 00:00:00 2001
2 From: Leandro Lucarella <llucax@gmail.com>
3 Date: Wed, 28 Jul 2010 18:05:37 -0300
4 Subject: [PATCH] Create pointer map bitmask to allow precise heap scanning
6 This is the patch[1] published in D's bug #3463[2], written by Vincent
7 Lang (AKA wm4) based on David Simcha's idea.
9 Here are some interesting comments in the bug report about the patch
10 (completely rephrased by me to group the information *I* found interesting
13 All user programs will make use of the precise scanning; no
14 modifications required.
16 The dmd patch makes dmd generate an additional field in
17 TypeInfo_Struct and ClassInfo. These fields point to pointer
18 bitmasks for the referenced type. The patch is written in such
19 a way, that it won't break unpatched Tango or Phobos1 runtimes. In
20 particular, this means the patched compiler should be usable with
23 The patch should be able to handle all D types. The internal nodes
24 for associative arrays are still scanned conservatively.
26 I also wanted to make scanning of AA nodes precise, but it turned
27 out the compiler never passes the TypeInfo of AA values to the
28 runtime functions. I guess I could hack the compiler to fix this,
31 The idea I wanted to implement was to dynamically allocate & build
32 a PointerMap for the aaA type each time an associative array is
33 instantiated. As an alternative solution, one could expose the aaA
34 type to the compiler (would have to move aaA to object.d), and
35 then let the compiler put a PointerMap into
36 TypeInfo_AssociativeArray.
38 Note that the bitmask format is a bitmap, where each bit
39 represents an aligned, pointer sized chunk of memory.
41 [1] http://d.puremagic.com/issues/attachment.cgi?id=700
42 [2] http://d.puremagic.com/issues/show_bug.cgi?id=3463
44 src/aggregate.h | 7 ++-
45 src/attrib.c | 14 ++++
47 src/declaration.c | 7 ++
48 src/declaration.h | 1 +
53 src/mtype.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++--
54 src/mtype.h | 50 ++++++++++++++
55 src/template.c | 10 +++
57 src/toobj.c | 45 ++++++++++---
58 src/typinf.c | 66 ++++++++++++++++++
59 15 files changed, 387 insertions(+), 20 deletions(-)
61 diff --git a/src/aggregate.h b/src/aggregate.h
62 index bd4aa0f..871876d 100644
65 @@ -188,7 +188,12 @@ struct BaseClass
67 #define CLASSINFO_SIZE (0x3C+16+4) // value of ClassInfo.size
69 -#define CLASSINFO_SIZE (0x3C+12+4) // value of ClassInfo.size
70 + // warning: if the user's object.d contains a ClassInfo.pointermap field,
71 + // CLASSINFO_SIZE grows by an additonal 2 words - this is handled
72 + // dynamically in ClassDeclaration::toObjFile
73 + //now, the ONLY purpose of this is for the object.d incompatibility warning
74 +#define CLASSINFO_SIZE_1 (0x3C+12+4) // value of ClassInfo.size
75 +#define CLASSINFO_SIZE_2 (0x3C+12+4+8) // value of ClassInfo.size
78 struct ClassDeclaration : AggregateDeclaration
79 diff --git a/src/attrib.c b/src/attrib.c
80 index 18d4385..684932f 100644
83 @@ -277,6 +277,20 @@ int AttribDeclaration::hasPointers()
87 +void AttribDeclaration::fillPointerMap(PointerMap *pm, size_t offset)
89 + Array *d = include(NULL, NULL);
93 + for (size_t i = 0; i < d->dim; i++)
95 + Dsymbol *s = (Dsymbol *)d->data[i];
96 + s->fillPointerMap(pm, offset);
101 const char *AttribDeclaration::kind()
104 diff --git a/src/attrib.h b/src/attrib.h
105 index 1747f5b..b4f2718 100644
108 @@ -23,6 +23,7 @@ struct LabelDsymbol;
116 @@ -51,6 +52,7 @@ struct AttribDeclaration : Dsymbol
118 int oneMember(Dsymbol **ps);
120 + void fillPointerMap(PointerMap *pm, size_t offset);
121 void checkCtorConstInit();
122 void addLocalClass(ClassDeclarations *);
123 void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
124 diff --git a/src/declaration.c b/src/declaration.c
125 index 64d6c3a..e58ad92 100644
126 --- a/src/declaration.c
127 +++ b/src/declaration.c
128 @@ -1377,6 +1377,13 @@ int VarDeclaration::hasPointers()
129 return (!isDataseg() && type->hasPointers());
132 +void VarDeclaration::fillPointerMap(PointerMap *pm, size_t a_offset)
134 + //printf("VarDeclaration::fillPointerMap() %s, ty = %d, offs=%d\n", toChars(), type->ty, (int)offset);
136 + type->fillPointerMap(pm, offset + a_offset);
139 /******************************************
140 * If a variable has an auto destructor call, return call for it.
141 * Otherwise, return NULL.
142 diff --git a/src/declaration.h b/src/declaration.h
143 index c558630..d8922ca 100644
144 --- a/src/declaration.h
145 +++ b/src/declaration.h
146 @@ -279,6 +279,7 @@ struct VarDeclaration : Declaration
150 + void fillPointerMap(PointerMap *pm, size_t offset);
152 int canTakeAddressOf();
154 diff --git a/src/dsymbol.c b/src/dsymbol.c
155 index dd47434..f619fc1 100644
158 @@ -148,6 +148,10 @@ int Dsymbol::hasPointers()
162 +void Dsymbol::fillPointerMap(PointerMap *pm, size_t offset)
166 char *Dsymbol::toChars()
168 return ident ? ident->toChars() : (char *)"__anonymous";
169 diff --git a/src/dsymbol.h b/src/dsymbol.h
170 index 68d261b..18813b0 100644
173 @@ -70,6 +70,7 @@ struct DeleteDeclaration;
181 @@ -180,6 +181,7 @@ struct Dsymbol : Object
182 virtual int oneMember(Dsymbol **ps);
183 static int oneMembers(Array *members, Dsymbol **ps);
184 virtual int hasPointers();
185 + virtual void fillPointerMap(PointerMap *pm, size_t offset);
186 virtual void addLocalClass(ClassDeclarations *) { }
187 virtual void checkCtorConstInit() { }
189 diff --git a/src/idgen.c b/src/idgen.c
190 index 46bc269..6714824 100644
193 @@ -91,6 +91,10 @@ Msgtable msgtable[] =
197 + // check for PointerMap-aware runtime
198 + { "pointermap" }, //ClassInfo.pointermap
199 + { "m_pointermap" }, //TypeInfo_Struct.m_pointermap
201 { "LINE", "__LINE__" },
202 { "FILE", "__FILE__" },
203 { "DATE", "__DATE__" },
204 diff --git a/src/mars.c b/src/mars.c
205 index fbb4f74..15b9248 100644
208 @@ -394,6 +394,8 @@ int main(int argc, char *argv[])
212 + VersionCondition::addPredefinedGlobalIdent("D_HavePointerMap");
214 VersionCondition::addPredefinedGlobalIdent("LittleEndian");
215 //VersionCondition::addPredefinedGlobalIdent("D_Bits");
217 diff --git a/src/mtype.c b/src/mtype.c
218 index ce959ff..6386ff0 100644
221 @@ -833,7 +833,14 @@ Expression *Type::toExpression()
223 int Type::hasPointers()
226 + //fprintf(stderr, "Type::hasPointers(): '%s'\n", toChars());
230 +void Type::fillPointerMap(PointerMap *pm, size_t offset)
232 + //fprintf(stderr, "Type::fillPointerMap(): '%s'\n", toChars());
236 /* ============================= TypeError =========================== */
237 @@ -1584,6 +1591,29 @@ TypeBasic *TypeBasic::isTypeBasic()
238 return (TypeBasic *)this;
241 +int TypeBasic::hasPointers()
246 +void TypeBasic::fillPointerMap(PointerMap *pm, size_t offset)
248 + // special case: static void arrays inside structs/classes
249 + // justification: union { void[8] a; void[] b; } (often used for variants)
250 + // should just be fully scanned, instead of only b.ptr
251 + // [dynamic void[] arrays are handled by TypeInfo_v.flags() (that's why
252 + // hasPointers() is not special cased for Tvoid?)]
255 + if (offset + PTRSIZE <= pm->size())
256 + pm->maybepointer(offset);
260 + pm->nopointer(offset, Type::size());
264 /***************************** TypeArray *****************************/
266 TypeArray::TypeArray(TY ty, Type *next)
267 @@ -2060,6 +2090,18 @@ int TypeSArray::hasPointers()
268 return next->hasPointers();
271 +void TypeSArray::fillPointerMap(PointerMap *pm, size_t offset)
273 + // for all array items
274 + // static arrays of size 0 produce nothing
275 + size_t d = dim->toInteger();
276 + size_t s = next->size();
277 + for (size_t n = 0; n < d; n++)
279 + next->fillPointerMap(pm, offset + n * s);
283 /***************************** TypeDArray *****************************/
285 TypeDArray::TypeDArray(Type *t)
286 @@ -2209,6 +2251,13 @@ int TypeDArray::hasPointers()
290 +void TypeDArray::fillPointerMap(PointerMap *pm, size_t offset)
292 + // like struct Array { size_t length; byte* data; }
293 + pm->nopointer(offset, PTRSIZE);
294 + pm->pointer(offset + PTRSIZE);
297 /***************************** TypeAArray *****************************/
299 TypeAArray::TypeAArray(Type *t, Type *index)
300 @@ -2451,6 +2500,12 @@ int TypeAArray::hasPointers()
304 +void TypeAArray::fillPointerMap(PointerMap *pm, size_t offset)
306 + // a pointer to the internal AA struct
307 + pm->pointer(offset);
310 /***************************** TypePointer *****************************/
312 TypePointer::TypePointer(Type *t)
313 @@ -2559,6 +2614,11 @@ int TypePointer::hasPointers()
317 +void TypePointer::fillPointerMap(PointerMap *pm, size_t offset)
319 + pm->pointer(offset);
323 /***************************** TypeReference *****************************/
325 @@ -3187,6 +3247,15 @@ int TypeDelegate::hasPointers()
329 +void TypeDelegate::fillPointerMap(PointerMap *pm, size_t offset)
331 + // ABI: .ptr followed by .funcptr
332 + // assume .funcptr always points to static data (code)
333 + // thus, only .ptr needs to be scanned
334 + pm->pointer(offset);
335 + pm->nopointer(offset + PTRSIZE, PTRSIZE);
340 /***************************** TypeQualified *****************************/
341 @@ -4098,6 +4167,11 @@ int TypeEnum::hasPointers()
342 return toBasetype()->hasPointers();
345 +void TypeEnum::fillPointerMap(PointerMap *pm, size_t offset)
347 + toBasetype()->fillPointerMap(pm, offset);
350 /***************************** TypeTypedef *****************************/
352 TypeTypedef::TypeTypedef(TypedefDeclaration *sym)
353 @@ -4306,6 +4380,11 @@ int TypeTypedef::hasPointers()
354 return toBasetype()->hasPointers();
357 +void TypeTypedef::fillPointerMap(PointerMap *pm, size_t offset)
359 + toBasetype()->fillPointerMap(pm, offset);
362 /***************************** TypeStruct *****************************/
364 TypeStruct::TypeStruct(StructDeclaration *sym)
365 @@ -4637,18 +4716,27 @@ int TypeStruct::hasPointers()
366 StructDeclaration *s = sym;
368 sym->size(0); // give error for forward references
370 + for (size_t i = 0; i < s->fields.dim; i++)
372 - for (size_t i = 0; i < s->members->dim; i++)
374 - Dsymbol *sm = (Dsymbol *)s->members->data[i];
375 - if (sm->hasPointers())
378 + Dsymbol *sm = (Dsymbol *)s->fields.data[i];
379 + if (sm->hasPointers())
385 +void TypeStruct::fillPointerMap(PointerMap *pm, size_t offset)
387 + StructDeclaration *s = sym;
389 + sym->size(0); // give error for forward references
390 + //NOTE: using s->members instead of s->fields would call fillPointerMap on TypeTuple
391 + for (size_t i = 0; i < s->fields.dim; i++)
393 + Dsymbol *sm = (Dsymbol *)s->fields.data[i];
394 + sm->fillPointerMap(pm, offset);
398 /***************************** TypeClass *****************************/
400 @@ -5064,6 +5152,11 @@ int TypeClass::hasPointers()
404 +void TypeClass::fillPointerMap(PointerMap *pm, size_t offset)
406 + pm->pointer(offset);
409 /***************************** TypeTuple *****************************/
411 TypeTuple::TypeTuple(Parameters *arguments)
412 @@ -5201,6 +5294,16 @@ Expression *TypeTuple::getProperty(Loc loc, Identifier *ident)
416 +int TypeTuple::hasPointers()
421 +void TypeTuple::fillPointerMap(PointerMap *pm, size_t offset)
426 /***************************** TypeSlice *****************************/
428 /* This is so we can slice a TypeTuple */
429 @@ -5568,3 +5671,75 @@ Parameter *Parameter::getNth(Parameters *args, size_t nth, size_t *pn)
435 +PointerMap::PointerMap()
442 +PointerMap::~PointerMap()
448 + * Set size in bytes and reinit all bits to 0.
450 +void PointerMap::setSize(size_t bytes)
454 + m_dlen = m_size / PTRSIZE;
455 + m_data = (ubyte*)mem.calloc(m_dlen, 1);
460 +size_t PointerMap::size()
466 + * Mark position at offset as pointer.
467 + * Actually does nothing if the offset isn't aligned.
469 +void PointerMap::pointer(size_t offset)
472 + assert(offset < m_size);
473 + //reject unaligned pointers
474 + if ((offset & (PTRSIZE - 1)) != 0)
476 + size_t elem = offset / PTRSIZE;
477 + assert(elem < m_dlen);
478 + m_data[elem] |= PTR;
481 +void PointerMap::nopointer(size_t offset, size_t size)
486 + assert(offset < m_size);
487 + assert(offset + size <= m_size);
488 + size_t pos = offset & ~(PTRSIZE - 1); //align down to cover all words
489 + for (; pos < offset + size; pos += PTRSIZE)
491 + //when m_size is unaligned, the last bytes will be in elem==m_dlen
492 + if (pos >= (m_size & ~(PTRSIZE - 1)))
494 + size_t elem = pos / PTRSIZE;
495 + assert(elem < m_dlen);
496 + m_data[elem] |= NOPTR;
500 +void PointerMap::maybepointer(size_t offset)
503 + nopointer(offset, PTRSIZE);
505 diff --git a/src/mtype.h b/src/mtype.h
506 index ab87f81..e28f81c 100644
509 @@ -38,6 +38,7 @@ enum LINK;
517 @@ -246,6 +247,7 @@ struct Type : Object
518 virtual Type *reliesOnTident();
519 virtual Expression *toExpression();
520 virtual int hasPointers();
521 + virtual void fillPointerMap(PointerMap *pm, size_t offset);
523 Type *nextOf() { return next; }
525 @@ -325,6 +327,8 @@ struct TypeBasic : Type
526 Expression *defaultInit(Loc loc);
527 int isZeroInit(Loc loc);
528 int builtinTypeInfo();
530 + void fillPointerMap(PointerMap *pm, size_t offset);
532 // For eliminating dynamic_cast
533 TypeBasic *isTypeBasic();
534 @@ -362,6 +366,7 @@ struct TypeSArray : TypeArray
535 TypeInfoDeclaration *getTypeInfoDeclaration();
536 Expression *toExpression();
538 + void fillPointerMap(PointerMap *pm, size_t offset);
541 type *toCParamtype();
542 @@ -386,6 +391,7 @@ struct TypeDArray : TypeArray
543 int builtinTypeInfo();
544 TypeInfoDeclaration *getTypeInfoDeclaration();
546 + void fillPointerMap(PointerMap *pm, size_t offset);
550 @@ -409,6 +415,7 @@ struct TypeAArray : TypeArray
552 TypeInfoDeclaration *getTypeInfoDeclaration();
554 + void fillPointerMap(PointerMap *pm, size_t offset);
557 Symbol *aaGetSymbol(const char *func, int flags);
558 @@ -429,6 +436,7 @@ struct TypePointer : Type
559 int isZeroInit(Loc loc);
560 TypeInfoDeclaration *getTypeInfoDeclaration();
562 + void fillPointerMap(PointerMap *pm, size_t offset);
566 @@ -489,6 +497,7 @@ struct TypeDelegate : Type
567 TypeInfoDeclaration *getTypeInfoDeclaration();
568 Expression *dotExp(Scope *sc, Expression *e, Identifier *ident);
570 + void fillPointerMap(PointerMap *pm, size_t offset);
574 @@ -577,6 +586,7 @@ struct TypeStruct : Type
575 MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
576 TypeInfoDeclaration *getTypeInfoDeclaration();
578 + void fillPointerMap(PointerMap *pm, size_t offset);
582 @@ -607,6 +617,7 @@ struct TypeEnum : Type
583 MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
584 TypeInfoDeclaration *getTypeInfoDeclaration();
586 + void fillPointerMap(PointerMap *pm, size_t offset);
588 void toCppMangle(OutBuffer *buf, CppMangleState *cms);
590 @@ -646,6 +657,7 @@ struct TypeTypedef : Type
591 MATCH deduceType(Scope *sc, Type *tparam, TemplateParameters *parameters, Objects *dedtypes);
592 TypeInfoDeclaration *getTypeInfoDeclaration();
594 + void fillPointerMap(PointerMap *pm, size_t offset);
597 type *toCParamtype();
598 @@ -674,6 +686,7 @@ struct TypeClass : Type
600 TypeInfoDeclaration *getTypeInfoDeclaration();
602 + void fillPointerMap(PointerMap *pm, size_t offset);
603 int builtinTypeInfo();
605 Type *toHeadMutable();
606 @@ -702,6 +715,8 @@ struct TypeTuple : Type
607 void toDecoBuffer(OutBuffer *buf);
608 Expression *getProperty(Loc loc, Identifier *ident);
609 TypeInfoDeclaration *getTypeInfoDeclaration();
611 + void fillPointerMap(PointerMap *pm, size_t offset);
614 struct TypeSlice : Type
615 @@ -750,4 +765,39 @@ extern int Tptrdiff_t;
617 int arrayTypeCompatible(Loc loc, Type *t1, Type *t2);
619 +//"abstracted" because we might want to support other representations
620 +//e.g. a list of offsets
623 + typedef unsigned char ubyte;
625 + static const ubyte PTR = 1;
626 + static const ubyte NOPTR = 2;
628 + //each ubyte represents a word; bitmask of PTR and NOPTR
629 + //PTR|NOPTR means non-moveable
631 + size_t m_dlen; //length of m_data
632 + size_t m_size; //size of the type
637 + void setSize(size_t bytes);
640 + //if both pointer and nopointer are called for the same word, the word is
641 + //registered as non-moveable pointer
642 + void pointer(size_t offset);
643 + void nopointer(size_t offset, size_t size);
644 + //pointer-aligned field that may or may not be a pointer
645 + void maybepointer(size_t offset);
647 + //write a PointerMap instance as described in object_.d
648 + void toDt(dt_t **pdt);
650 + //write an "invalid" PointerMap instance
651 + static void toDtInvalid(dt_t **pdt);
654 #endif /* DMD_MTYPE_H */
655 diff --git a/src/template.c b/src/template.c
656 index a3b5b6a..7f87730 100644
659 @@ -4812,6 +4812,16 @@ int TemplateMixin::hasPointers()
663 +void TemplateMixin::fillPointerMap(PointerMap *pm, size_t offset)
665 + for (size_t i = 0; i < members->dim; i++)
667 + Dsymbol *s = (Dsymbol *)members->data[i];
668 + //printf(" s = %s %s\n", s->kind(), s->toChars());
669 + s->fillPointerMap(pm, offset);
673 char *TemplateMixin::toChars()
676 diff --git a/src/template.h b/src/template.h
677 index 2f9b834..992b731 100644
680 @@ -36,6 +36,7 @@ struct Expression;
681 struct AliasDeclaration;
682 struct FuncDeclaration;
687 struct Tuple : Object
688 @@ -337,6 +338,7 @@ struct TemplateMixin : TemplateInstance
690 int oneMember(Dsymbol **ps);
692 + void fillPointerMap(PointerMap *pm, size_t offset);
694 void toCBuffer(OutBuffer *buf, HdrGenState *hgs);
696 diff --git a/src/toobj.c b/src/toobj.c
697 index 0b16044..7db76a2 100644
700 @@ -351,10 +351,14 @@ void ClassDeclaration::toObjFile(int multiobj)
704 + assert(classinfo != NULL);
705 + size_t CLASSINFO_SIZE = classinfo->structsize;
706 + bool have_pointer_map = classinfo->search(NULL, Id::pointermap, 0);
707 offset = CLASSINFO_SIZE; // must be ClassInfo.size
710 - if (classinfo->structsize != CLASSINFO_SIZE)
711 + if ((!have_pointer_map && (classinfo->structsize != CLASSINFO_SIZE_1))
712 + || (have_pointer_map && (classinfo->structsize != CLASSINFO_SIZE_2)))
714 error("mismatch between dmd and object.d or object.di found. Check installation and import paths with -v compiler switch.");
716 @@ -464,6 +468,26 @@ void ClassDeclaration::toObjFile(int multiobj)
717 dtxoff(&dt, type->vtinfo->toSymbol(), 0, TYnptr); // typeinfo
720 + // pointermap - only with pointermap-aware runtime
721 + if (have_pointer_map)
724 + pm.setSize(structsize);
725 + for (ClassDeclaration *cd = this; cd; cd = cd->baseClass)
729 + for (size_t i = 0; i < cd->members->dim; i++)
731 + Dsymbol *sm = (Dsymbol *)cd->members->data[i];
732 + //printf("sm = %s %s\n", sm->kind(), sm->toChars());
733 + sm->fillPointerMap(&pm, 0);
740 //////////////////////////////////////////////
742 // Put out vtblInterfaces->data[]. Must immediately follow csym, because
743 @@ -717,7 +741,8 @@ unsigned ClassDeclaration::baseVtblOffset(BaseClass *bc)
746 //printf("ClassDeclaration::baseVtblOffset('%s', bc = %p)\n", toChars(), bc);
747 - csymoffset = CLASSINFO_SIZE;
748 + assert(classinfo != NULL);
749 + csymoffset = classinfo->structsize;
750 csymoffset += vtblInterfaces->dim * (4 * PTRSIZE);
752 for (i = 0; i < vtblInterfaces->dim; i++)
753 @@ -841,6 +866,7 @@ void InterfaceDeclaration::toObjFile(int multiobj)
754 const(MemberInfo[]) function(string) xgetMembers; // module getMembers() function
757 + PointerMap pointermap; //optional!
761 @@ -869,15 +895,8 @@ void InterfaceDeclaration::toObjFile(int multiobj)
762 dtdword(&dt, vtblInterfaces->dim);
763 if (vtblInterfaces->dim)
767 - if (classinfo->structsize != CLASSINFO_SIZE)
769 - error("mismatch between dmd and object.d or object.di found. Check installation and import paths with -v compiler switch.");
773 - offset = CLASSINFO_SIZE;
774 + assert(classinfo != NULL);
775 + offset = classinfo->structsize;
776 dtxoff(&dt, csym, offset, TYnptr); // (*)
779 @@ -913,6 +932,10 @@ void InterfaceDeclaration::toObjFile(int multiobj)
781 dtxoff(&dt, type->vtinfo->toSymbol(), 0, TYnptr); // typeinfo
783 + bool have_pointer_map = classinfo->search(NULL, Id::pointermap, 0);
784 + if (have_pointer_map)
785 + PointerMap::toDtInvalid(&dt);
787 //////////////////////////////////////////////
789 // Put out vtblInterfaces->data[]. Must immediately follow csym, because
790 diff --git a/src/typinf.c b/src/typinf.c
791 index 53a8648..8852c31 100644
794 @@ -573,6 +573,15 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt)
796 dtdword(pdt, tc->hasPointers());
798 + // m_pointermap - only with pointermap-aware runtime
799 + if (Type::typeinfostruct->search(NULL, Id::m_pointermap, 0))
802 + pm.setSize(sd->structsize);
803 + tc->fillPointerMap(&pm, 0);
809 FuncDeclaration *sgetmembers = sd->findGetMembers();
810 @@ -599,6 +608,63 @@ void TypeInfoStructDeclaration::toDt(dt_t **pdt)
811 dtnbytes(pdt, namelen + 1, name);
814 +//set the n-th bit in bits[0..length*PTRSIZE]
815 +//bits is an array of target size_t
816 +static void setbit(unsigned char *bits, size_t bits_length, size_t bit)
818 + //TODO: this probably only works on little endian machines
819 + // the generated program reads this bit array as size_t[]
820 + size_t bitpos = bit % 8;
821 + size_t npos = bit / 8;
822 + assert(npos < bits_length * PTRSIZE);
823 + bits[npos] |= 1 << bitpos;
826 +void PointerMap::toDt(dt_t **pdt)
828 + size_t BITS = PTRSIZE * 8;
830 + size_t nelem = (m_dlen + BITS - 1) / BITS; //number of bitmap elements needed for mwords
831 + size_t data_len = 1 + nelem * 2; //length of the final bitmask array (header + 2 bitmaps)
832 + ubyte *data = (ubyte *)mem.calloc(data_len, PTRSIZE);
835 + //number of pointer-sized words in type
836 + uinteger_t target_len = m_dlen;
837 + assert(PTRSIZE <= sizeof(target_len));
838 + //TODO: this only works on little endian machines
839 + memcpy(data, &target_len, PTRSIZE);
841 + ubyte *p_bits = data + PTRSIZE; //bitmap for all pointers
842 + ubyte *m_bits = data + PTRSIZE * (1 + nelem); //bitmap for moveable pointers
844 + for (size_t cur = 0; cur < m_dlen; cur++)
846 + ubyte p = m_data[cur];
849 + setbit(p_bits, nelem, cur);
852 + setbit(m_bits, nelem, cur);
857 + //length (inline size field + bits)
858 + dtdword(pdt, data_len);
860 + dtabytes(pdt, TYnptr, 0, data_len * PTRSIZE, (char*)data);
865 +void PointerMap::toDtInvalid(dt_t **pdt) {
871 void TypeInfoClassDeclaration::toDt(dt_t **pdt)
873 //printf("TypeInfoClassDeclaration::toDt() %s\n", tinfo->toChars());