806 changes: 414 additions & 392 deletions src/typinf.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,12 @@
#include "import.h"
#include "aggregate.h"
#include "target.h"
#include "visitor.h"

#include "dt.h"

Parameters *Parameters_create();

/*
* Used in TypeInfo*::toDt to verify the runtime TypeInfo sizes
*/
void verifyStructSize(ClassDeclaration *typeclass, size_t expected)
{
if (typeclass->structsize != expected)
{
#ifdef DEBUG
printf("expected = x%x, %s.structsize = x%x\n", expected,
typeclass->toChars(), typeclass->structsize);
#endif
error(typeclass->loc, "mismatch between compiler and object.d or object.di found. Check installation and import paths with -v compiler switch.");
fatal();
}
}

/*******************************************
* Get a canonicalized form of the TypeInfo for use with the internal
* runtime library routines. Canonicalized in that static arrays are
Expand Down Expand Up @@ -251,476 +236,513 @@ TypeInfoDeclaration *TypeTuple::getTypeInfoDeclaration()
/****************************************************
*/

void TypeInfoDeclaration::toDt(dt_t **pdt)
{
//printf("TypeInfoDeclaration::toDt() %s\n", toChars());
verifyStructSize(Type::dtypeinfo, 2 * Target::ptrsize);

dtxoff(pdt, Type::dtypeinfo->toVtblSymbol(), 0); // vtbl for TypeInfo
dtsize_t(pdt, 0); // monitor
}

void TypeInfoConstDeclaration::toDt(dt_t **pdt)
{
//printf("TypeInfoConstDeclaration::toDt() %s\n", toChars());
verifyStructSize(Type::typeinfoconst, 3 * Target::ptrsize);

dtxoff(pdt, Type::typeinfoconst->toVtblSymbol(), 0); // vtbl for TypeInfo_Const
dtsize_t(pdt, 0); // monitor
Type *tm = tinfo->mutableOf();
tm = tm->merge();
tm->getTypeInfo(NULL);
dtxoff(pdt, tm->vtinfo->toSymbol(), 0);
}

void TypeInfoInvariantDeclaration::toDt(dt_t **pdt)
class TypeInfoDtVisitor : public Visitor
{
//printf("TypeInfoInvariantDeclaration::toDt() %s\n", toChars());
verifyStructSize(Type::typeinfoinvariant, 3 * Target::ptrsize);

dtxoff(pdt, Type::typeinfoinvariant->toVtblSymbol(), 0); // vtbl for TypeInfo_Invariant
dtsize_t(pdt, 0); // monitor
Type *tm = tinfo->mutableOf();
tm = tm->merge();
tm->getTypeInfo(NULL);
dtxoff(pdt, tm->vtinfo->toSymbol(), 0);
}

void TypeInfoSharedDeclaration::toDt(dt_t **pdt)
{
//printf("TypeInfoSharedDeclaration::toDt() %s\n", toChars());
verifyStructSize(Type::typeinfoshared, 3 * Target::ptrsize);

dtxoff(pdt, Type::typeinfoshared->toVtblSymbol(), 0); // vtbl for TypeInfo_Shared
dtsize_t(pdt, 0); // monitor
Type *tm = tinfo->unSharedOf();
tm = tm->merge();
tm->getTypeInfo(NULL);
dtxoff(pdt, tm->vtinfo->toSymbol(), 0);
}

void TypeInfoWildDeclaration::toDt(dt_t **pdt)
{
//printf("TypeInfoWildDeclaration::toDt() %s\n", toChars());
verifyStructSize(Type::typeinfowild, 3 * Target::ptrsize);

dtxoff(pdt, Type::typeinfowild->toVtblSymbol(), 0); // vtbl for TypeInfo_Wild
dtsize_t(pdt, 0); // monitor
Type *tm = tinfo->mutableOf();
tm = tm->merge();
tm->getTypeInfo(NULL);
dtxoff(pdt, tm->vtinfo->toSymbol(), 0);
}
private:
dt_t **pdt;

/*
* Used in TypeInfo*::toDt to verify the runtime TypeInfo sizes
*/
static void verifyStructSize(ClassDeclaration *typeclass, size_t expected)
{
if (typeclass->structsize != expected)
{
#ifdef DEBUG
printf("expected = x%x, %s.structsize = x%x\n", expected,
typeclass->toChars(), typeclass->structsize);
#endif
error(typeclass->loc, "mismatch between compiler and object.d or object.di found. Check installation and import paths with -v compiler switch.");
fatal();
}
}

void TypeInfoTypedefDeclaration::toDt(dt_t **pdt)
{
//printf("TypeInfoTypedefDeclaration::toDt() %s\n", toChars());
verifyStructSize(Type::typeinfotypedef, 7 * Target::ptrsize);
public:
TypeInfoDtVisitor(dt_t **pdt)
: pdt(pdt)
{
}

dtxoff(pdt, Type::typeinfotypedef->toVtblSymbol(), 0); // vtbl for TypeInfo_Typedef
dtsize_t(pdt, 0); // monitor
void visit(TypeInfoDeclaration *d)
{
//printf("TypeInfoDeclaration::toDt() %s\n", toChars());
verifyStructSize(Type::dtypeinfo, 2 * Target::ptrsize);

assert(tinfo->ty == Ttypedef);
dtxoff(pdt, Type::dtypeinfo->toVtblSymbol(), 0); // vtbl for TypeInfo
dtsize_t(pdt, 0); // monitor
}

TypeTypedef *tc = (TypeTypedef *)tinfo;
TypedefDeclaration *sd = tc->sym;
//printf("basetype = %s\n", sd->basetype->toChars());
void visit(TypeInfoConstDeclaration *d)
{
//printf("TypeInfoConstDeclaration::toDt() %s\n", toChars());
verifyStructSize(Type::typeinfoconst, 3 * Target::ptrsize);

dtxoff(pdt, Type::typeinfoconst->toVtblSymbol(), 0); // vtbl for TypeInfo_Const
dtsize_t(pdt, 0); // monitor
Type *tm = d->tinfo->mutableOf();
tm = tm->merge();
tm->getTypeInfo(NULL);
dtxoff(pdt, tm->vtinfo->toSymbol(), 0);
}

/* Put out:
* TypeInfo base;
* char[] name;
* void[] m_init;
*/
void visit(TypeInfoInvariantDeclaration *d)
{
//printf("TypeInfoInvariantDeclaration::toDt() %s\n", toChars());
verifyStructSize(Type::typeinfoinvariant, 3 * Target::ptrsize);

dtxoff(pdt, Type::typeinfoinvariant->toVtblSymbol(), 0); // vtbl for TypeInfo_Invariant
dtsize_t(pdt, 0); // monitor
Type *tm = d->tinfo->mutableOf();
tm = tm->merge();
tm->getTypeInfo(NULL);
dtxoff(pdt, tm->vtinfo->toSymbol(), 0);
}

sd->basetype = sd->basetype->merge();
sd->basetype->getTypeInfo(NULL); // generate vtinfo
assert(sd->basetype->vtinfo);
dtxoff(pdt, sd->basetype->vtinfo->toSymbol(), 0); // TypeInfo for basetype

const char *name = sd->toPrettyChars();
size_t namelen = strlen(name);
dtsize_t(pdt, namelen);
dtabytes(pdt, 0, namelen + 1, name);

// void[] init;
if (tinfo->isZeroInit() || !sd->init)
{ // 0 initializer, or the same as the base type
dtsize_t(pdt, 0); // init.length
dtsize_t(pdt, 0); // init.ptr
void visit(TypeInfoSharedDeclaration *d)
{
//printf("TypeInfoSharedDeclaration::toDt() %s\n", toChars());
verifyStructSize(Type::typeinfoshared, 3 * Target::ptrsize);

dtxoff(pdt, Type::typeinfoshared->toVtblSymbol(), 0); // vtbl for TypeInfo_Shared
dtsize_t(pdt, 0); // monitor
Type *tm = d->tinfo->unSharedOf();
tm = tm->merge();
tm->getTypeInfo(NULL);
dtxoff(pdt, tm->vtinfo->toSymbol(), 0);
}
else

void visit(TypeInfoWildDeclaration *d)
{
dtsize_t(pdt, sd->type->size()); // init.length
dtxoff(pdt, sd->toInitializer(), 0); // init.ptr
//printf("TypeInfoWildDeclaration::toDt() %s\n", toChars());
verifyStructSize(Type::typeinfowild, 3 * Target::ptrsize);

dtxoff(pdt, Type::typeinfowild->toVtblSymbol(), 0); // vtbl for TypeInfo_Wild
dtsize_t(pdt, 0); // monitor
Type *tm = d->tinfo->mutableOf();
tm = tm->merge();
tm->getTypeInfo(NULL);
dtxoff(pdt, tm->vtinfo->toSymbol(), 0);
}
}

void TypeInfoEnumDeclaration::toDt(dt_t **pdt)
{
//printf("TypeInfoEnumDeclaration::toDt()\n");
verifyStructSize(Type::typeinfoenum, 7 * Target::ptrsize);
void visit(TypeInfoTypedefDeclaration *d)
{
//printf("TypeInfoTypedefDeclaration::toDt() %s\n", toChars());
verifyStructSize(Type::typeinfotypedef, 7 * Target::ptrsize);

dtxoff(pdt, Type::typeinfoenum->toVtblSymbol(), 0); // vtbl for TypeInfo_Enum
dtsize_t(pdt, 0); // monitor
dtxoff(pdt, Type::typeinfotypedef->toVtblSymbol(), 0); // vtbl for TypeInfo_Typedef
dtsize_t(pdt, 0); // monitor

assert(tinfo->ty == Tenum);
assert( d->tinfo->ty == Ttypedef);

TypeEnum *tc = (TypeEnum *)tinfo;
EnumDeclaration *sd = tc->sym;
TypeTypedef *tc = (TypeTypedef *)d->tinfo;
TypedefDeclaration *sd = tc->sym;
//printf("basetype = %s\n", sd->basetype->toChars());

/* Put out:
* TypeInfo base;
* char[] name;
* void[] m_init;
*/
/* Put out:
* TypeInfo base;
* char[] name;
* void[] m_init;
*/

if (sd->memtype)
{ sd->memtype->getTypeInfo(NULL);
dtxoff(pdt, sd->memtype->vtinfo->toSymbol(), 0); // TypeInfo for enum members
}
else
dtsize_t(pdt, 0);

const char *name = sd->toPrettyChars();
size_t namelen = strlen(name);
dtsize_t(pdt, namelen);
dtabytes(pdt, 0, namelen + 1, name);

// void[] init;
if (!sd->members || tinfo->isZeroInit())
{ // 0 initializer, or the same as the base type
dtsize_t(pdt, 0); // init.length
dtsize_t(pdt, 0); // init.ptr
sd->basetype = sd->basetype->merge();
sd->basetype->getTypeInfo(NULL); // generate vtinfo
assert(sd->basetype->vtinfo);
dtxoff(pdt, sd->basetype->vtinfo->toSymbol(), 0); // TypeInfo for basetype

const char *name = sd->toPrettyChars();
size_t namelen = strlen(name);
dtsize_t(pdt, namelen);
dtabytes(pdt, 0, namelen + 1, name);

// void[] init;
if (d->tinfo->isZeroInit() || !sd->init)
{
// 0 initializer, or the same as the base type
dtsize_t(pdt, 0); // init.length
dtsize_t(pdt, 0); // init.ptr
}
else
{
dtsize_t(pdt, sd->type->size()); // init.length
dtxoff(pdt, sd->toInitializer(), 0); // init.ptr
}
}
else

void visit(TypeInfoEnumDeclaration *d)
{
dtsize_t(pdt, sd->type->size()); // init.length
dtxoff(pdt, sd->toInitializer(), 0); // init.ptr
}
}
//printf("TypeInfoEnumDeclaration::toDt()\n");
verifyStructSize(Type::typeinfoenum, 7 * Target::ptrsize);

void TypeInfoPointerDeclaration::toDt(dt_t **pdt)
{
//printf("TypeInfoPointerDeclaration::toDt()\n");
verifyStructSize(Type::typeinfopointer, 3 * Target::ptrsize);
dtxoff(pdt, Type::typeinfoenum->toVtblSymbol(), 0); // vtbl for TypeInfo_Enum
dtsize_t(pdt, 0); // monitor

dtxoff(pdt, Type::typeinfopointer->toVtblSymbol(), 0); // vtbl for TypeInfo_Pointer
dtsize_t(pdt, 0); // monitor
assert(d->tinfo->ty == Tenum);

assert(tinfo->ty == Tpointer);
TypeEnum *tc = (TypeEnum *)d->tinfo;
EnumDeclaration *sd = tc->sym;

TypePointer *tc = (TypePointer *)tinfo;
/* Put out:
* TypeInfo base;
* char[] name;
* void[] m_init;
*/

tc->next->getTypeInfo(NULL);
dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0); // TypeInfo for type being pointed to
}
if (sd->memtype)
{
sd->memtype->getTypeInfo(NULL);
dtxoff(pdt, sd->memtype->vtinfo->toSymbol(), 0); // TypeInfo for enum members
}
else
dtsize_t(pdt, 0);

void TypeInfoArrayDeclaration::toDt(dt_t **pdt)
{
//printf("TypeInfoArrayDeclaration::toDt()\n");
verifyStructSize(Type::typeinfoarray, 3 * Target::ptrsize);
const char *name = sd->toPrettyChars();
size_t namelen = strlen(name);
dtsize_t(pdt, namelen);
dtabytes(pdt, 0, namelen + 1, name);

dtxoff(pdt, Type::typeinfoarray->toVtblSymbol(), 0); // vtbl for TypeInfo_Array
dtsize_t(pdt, 0); // monitor
// void[] init;
if (!sd->members || d->tinfo->isZeroInit())
{
// 0 initializer, or the same as the base type
dtsize_t(pdt, 0); // init.length
dtsize_t(pdt, 0); // init.ptr
}
else
{
dtsize_t(pdt, sd->type->size()); // init.length
dtxoff(pdt, sd->toInitializer(), 0); // init.ptr
}
}

assert(tinfo->ty == Tarray);
void visit(TypeInfoPointerDeclaration *d)
{
//printf("TypeInfoPointerDeclaration::toDt()\n");
verifyStructSize(Type::typeinfopointer, 3 * Target::ptrsize);

TypeDArray *tc = (TypeDArray *)tinfo;
dtxoff(pdt, Type::typeinfopointer->toVtblSymbol(), 0); // vtbl for TypeInfo_Pointer
dtsize_t(pdt, 0); // monitor

tc->next->getTypeInfo(NULL);
dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0); // TypeInfo for array of type
}
assert(d->tinfo->ty == Tpointer);

void TypeInfoStaticArrayDeclaration::toDt(dt_t **pdt)
{
//printf("TypeInfoStaticArrayDeclaration::toDt()\n");
verifyStructSize(Type::typeinfostaticarray, 4 * Target::ptrsize);
TypePointer *tc = (TypePointer *)d->tinfo;

tc->next->getTypeInfo(NULL);
dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0); // TypeInfo for type being pointed to
}

dtxoff(pdt, Type::typeinfostaticarray->toVtblSymbol(), 0); // vtbl for TypeInfo_StaticArray
dtsize_t(pdt, 0); // monitor
void visit(TypeInfoArrayDeclaration *d)
{
//printf("TypeInfoArrayDeclaration::toDt()\n");
verifyStructSize(Type::typeinfoarray, 3 * Target::ptrsize);

assert(tinfo->ty == Tsarray);
dtxoff(pdt, Type::typeinfoarray->toVtblSymbol(), 0); // vtbl for TypeInfo_Array
dtsize_t(pdt, 0); // monitor

TypeSArray *tc = (TypeSArray *)tinfo;
assert(d->tinfo->ty == Tarray);

tc->next->getTypeInfo(NULL);
dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0); // TypeInfo for array of type
TypeDArray *tc = (TypeDArray *)d->tinfo;

dtsize_t(pdt, tc->dim->toInteger()); // length
}
tc->next->getTypeInfo(NULL);
dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0); // TypeInfo for array of type
}

void TypeInfoVectorDeclaration::toDt(dt_t **pdt)
{
//printf("TypeInfoVectorDeclaration::toDt()\n");
verifyStructSize(Type::typeinfovector, 3 * Target::ptrsize);
void visit(TypeInfoStaticArrayDeclaration *d)
{
//printf("TypeInfoStaticArrayDeclaration::toDt()\n");
verifyStructSize(Type::typeinfostaticarray, 4 * Target::ptrsize);

dtxoff(pdt, Type::typeinfovector->toVtblSymbol(), 0); // vtbl for TypeInfo_Vector
dtsize_t(pdt, 0); // monitor
dtxoff(pdt, Type::typeinfostaticarray->toVtblSymbol(), 0); // vtbl for TypeInfo_StaticArray
dtsize_t(pdt, 0); // monitor

assert(tinfo->ty == Tvector);
assert(d->tinfo->ty == Tsarray);

TypeVector *tc = (TypeVector *)tinfo;
TypeSArray *tc = (TypeSArray *)d->tinfo;

tc->basetype->getTypeInfo(NULL);
dtxoff(pdt, tc->basetype->vtinfo->toSymbol(), 0); // TypeInfo for equivalent static array
}
tc->next->getTypeInfo(NULL);
dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0); // TypeInfo for array of type

void TypeInfoAssociativeArrayDeclaration::toDt(dt_t **pdt)
{
//printf("TypeInfoAssociativeArrayDeclaration::toDt()\n");
verifyStructSize(Type::typeinfoassociativearray, 5 * Target::ptrsize);
dtsize_t(pdt, tc->dim->toInteger()); // length
}

dtxoff(pdt, Type::typeinfoassociativearray->toVtblSymbol(), 0); // vtbl for TypeInfo_AssociativeArray
dtsize_t(pdt, 0); // monitor
void visit(TypeInfoVectorDeclaration *d)
{
//printf("TypeInfoVectorDeclaration::toDt()\n");
verifyStructSize(Type::typeinfovector, 3 * Target::ptrsize);

assert(tinfo->ty == Taarray);
dtxoff(pdt, Type::typeinfovector->toVtblSymbol(), 0); // vtbl for TypeInfo_Vector
dtsize_t(pdt, 0); // monitor

TypeAArray *tc = (TypeAArray *)tinfo;
assert(d->tinfo->ty == Tvector);

tc->next->getTypeInfo(NULL);
dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0); // TypeInfo for array of type
TypeVector *tc = (TypeVector *)d->tinfo;

tc->index->getTypeInfo(NULL);
dtxoff(pdt, tc->index->vtinfo->toSymbol(), 0); // TypeInfo for array of type
tc->basetype->getTypeInfo(NULL);
dtxoff(pdt, tc->basetype->vtinfo->toSymbol(), 0); // TypeInfo for equivalent static array
}

tc->getImpl()->type->getTypeInfo(NULL);
dtxoff(pdt, tc->getImpl()->type->vtinfo->toSymbol(), 0); // impl
}
void visit(TypeInfoAssociativeArrayDeclaration *d)
{
//printf("TypeInfoAssociativeArrayDeclaration::toDt()\n");
verifyStructSize(Type::typeinfoassociativearray, 5 * Target::ptrsize);

void TypeInfoFunctionDeclaration::toDt(dt_t **pdt)
{
//printf("TypeInfoFunctionDeclaration::toDt()\n");
verifyStructSize(Type::typeinfofunction, 5 * Target::ptrsize);
dtxoff(pdt, Type::typeinfoassociativearray->toVtblSymbol(), 0); // vtbl for TypeInfo_AssociativeArray
dtsize_t(pdt, 0); // monitor

dtxoff(pdt, Type::typeinfofunction->toVtblSymbol(), 0); // vtbl for TypeInfo_Function
dtsize_t(pdt, 0); // monitor
assert(d->tinfo->ty == Taarray);

assert(tinfo->ty == Tfunction);
TypeAArray *tc = (TypeAArray *)d->tinfo;

TypeFunction *tc = (TypeFunction *)tinfo;
tc->next->getTypeInfo(NULL);
dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0); // TypeInfo for array of type

tc->next->getTypeInfo(NULL);
dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0); // TypeInfo for function return value
tc->index->getTypeInfo(NULL);
dtxoff(pdt, tc->index->vtinfo->toSymbol(), 0); // TypeInfo for array of type

const char *name = tinfo->deco;
assert(name);
size_t namelen = strlen(name);
dtsize_t(pdt, namelen);
dtabytes(pdt, 0, namelen + 1, name);
}
tc->getImpl()->type->getTypeInfo(NULL);
dtxoff(pdt, tc->getImpl()->type->vtinfo->toSymbol(), 0); // impl
}

void TypeInfoDelegateDeclaration::toDt(dt_t **pdt)
{
//printf("TypeInfoDelegateDeclaration::toDt()\n");
verifyStructSize(Type::typeinfodelegate, 5 * Target::ptrsize);
void visit(TypeInfoFunctionDeclaration *d)
{
//printf("TypeInfoFunctionDeclaration::toDt()\n");
verifyStructSize(Type::typeinfofunction, 5 * Target::ptrsize);

dtxoff(pdt, Type::typeinfodelegate->toVtblSymbol(), 0); // vtbl for TypeInfo_Delegate
dtsize_t(pdt, 0); // monitor
dtxoff(pdt, Type::typeinfofunction->toVtblSymbol(), 0); // vtbl for TypeInfo_Function
dtsize_t(pdt, 0); // monitor

assert(tinfo->ty == Tdelegate);
assert(d->tinfo->ty == Tfunction);

TypeDelegate *tc = (TypeDelegate *)tinfo;
TypeFunction *tc = (TypeFunction *)d->tinfo;

tc->next->nextOf()->getTypeInfo(NULL);
dtxoff(pdt, tc->next->nextOf()->vtinfo->toSymbol(), 0); // TypeInfo for delegate return value
tc->next->getTypeInfo(NULL);
dtxoff(pdt, tc->next->vtinfo->toSymbol(), 0); // TypeInfo for function return value

const char *name = tinfo->deco;
assert(name);
size_t namelen = strlen(name);
dtsize_t(pdt, namelen);
dtabytes(pdt, 0, namelen + 1, name);
}
const char *name = d->tinfo->deco;
assert(name);
size_t namelen = strlen(name);
dtsize_t(pdt, namelen);
dtabytes(pdt, 0, namelen + 1, name);
}

void TypeInfoStructDeclaration::toDt(dt_t **pdt)
{
//printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars());
if (global.params.is64bit)
verifyStructSize(Type::typeinfostruct, 17 * Target::ptrsize);
else
verifyStructSize(Type::typeinfostruct, 15 * Target::ptrsize);

dtxoff(pdt, Type::typeinfostruct->toVtblSymbol(), 0); // vtbl for TypeInfo_Struct
dtsize_t(pdt, 0); // monitor

assert(tinfo->ty == Tstruct);

TypeStruct *tc = (TypeStruct *)tinfo;
StructDeclaration *sd = tc->sym;

if (!sd->members)
return;

/* Put out:
* char[] name;
* void[] init;
* hash_t function(in void*) xtoHash;
* bool function(in void*, in void*) xopEquals;
* int function(in void*, in void*) xopCmp;
* string function(const(void)*) xtoString;
* StructFlags m_flags;
* //xgetMembers;
* xdtor;
* xpostblit;
* uint m_align;
* version (X86_64)
* TypeInfo m_arg1;
* TypeInfo m_arg2;
* xgetRTInfo
*/
void visit(TypeInfoDelegateDeclaration *d)
{
//printf("TypeInfoDelegateDeclaration::toDt()\n");
verifyStructSize(Type::typeinfodelegate, 5 * Target::ptrsize);

const char *name = sd->toPrettyChars();
size_t namelen = strlen(name);
dtsize_t(pdt, namelen);
dtabytes(pdt, 0, namelen + 1, name);
dtxoff(pdt, Type::typeinfodelegate->toVtblSymbol(), 0); // vtbl for TypeInfo_Delegate
dtsize_t(pdt, 0); // monitor

// void[] init;
dtsize_t(pdt, sd->structsize); // init.length
if (sd->zeroInit)
dtsize_t(pdt, 0); // NULL for 0 initialization
else
dtxoff(pdt, sd->toInitializer(), 0); // init.ptr
assert(d->tinfo->ty == Tdelegate);

if (FuncDeclaration *fd = search_toHash(sd))
TypeDelegate *tc = (TypeDelegate *)d->tinfo;

tc->next->nextOf()->getTypeInfo(NULL);
dtxoff(pdt, tc->next->nextOf()->vtinfo->toSymbol(), 0); // TypeInfo for delegate return value

const char *name = d->tinfo->deco;
assert(name);
size_t namelen = strlen(name);
dtsize_t(pdt, namelen);
dtabytes(pdt, 0, namelen + 1, name);
}

void visit(TypeInfoStructDeclaration *d)
{
dtxoff(pdt, fd->toSymbol(), 0);
TypeFunction *tf = (TypeFunction *)fd->type;
assert(tf->ty == Tfunction);
/* I'm a little unsure this is the right way to do it. Perhaps a better
* way would to automatically add these attributes to any struct member
* function with the name "toHash".
* So I'm leaving this here as an experiment for the moment.
//printf("TypeInfoStructDeclaration::toDt() '%s'\n", toChars());
if (global.params.is64bit)
verifyStructSize(Type::typeinfostruct, 17 * Target::ptrsize);
else
verifyStructSize(Type::typeinfostruct, 15 * Target::ptrsize);

dtxoff(pdt, Type::typeinfostruct->toVtblSymbol(), 0); // vtbl for TypeInfo_Struct
dtsize_t(pdt, 0); // monitor

assert(d->tinfo->ty == Tstruct);

TypeStruct *tc = (TypeStruct *)d->tinfo;
StructDeclaration *sd = tc->sym;

if (!sd->members)
return;

/* Put out:
* char[] name;
* void[] init;
* hash_t function(in void*) xtoHash;
* bool function(in void*, in void*) xopEquals;
* int function(in void*, in void*) xopCmp;
* string function(const(void)*) xtoString;
* StructFlags m_flags;
* //xgetMembers;
* xdtor;
* xpostblit;
* uint m_align;
* version (X86_64)
* TypeInfo m_arg1;
* TypeInfo m_arg2;
* xgetRTInfo
*/
if (!tf->isnothrow || tf->trust == TRUSTsystem /*|| tf->purity == PUREimpure*/)
warning(fd->loc, "toHash() must be declared as extern (D) size_t toHash() const nothrow @safe, not %s", tf->toChars());
}
else
dtsize_t(pdt, 0);

if (sd->xeq)
dtxoff(pdt, sd->xeq->toSymbol(), 0);
else
dtsize_t(pdt, 0);
const char *name = sd->toPrettyChars();
size_t namelen = strlen(name);
dtsize_t(pdt, namelen);
dtabytes(pdt, 0, namelen + 1, name);

if (sd->xcmp)
dtxoff(pdt, sd->xcmp->toSymbol(), 0);
else
dtsize_t(pdt, 0);
// void[] init;
dtsize_t(pdt, sd->structsize); // init.length
if (sd->zeroInit)
dtsize_t(pdt, 0); // NULL for 0 initialization
else
dtxoff(pdt, sd->toInitializer(), 0); // init.ptr

if (FuncDeclaration *fd = search_toString(sd))
{
dtxoff(pdt, fd->toSymbol(), 0);
}
else
dtsize_t(pdt, 0);
if (FuncDeclaration *fd = search_toHash(sd))
{
dtxoff(pdt, fd->toSymbol(), 0);
TypeFunction *tf = (TypeFunction *)fd->type;
assert(tf->ty == Tfunction);
/* I'm a little unsure this is the right way to do it. Perhaps a better
* way would to automatically add these attributes to any struct member
* function with the name "toHash".
* So I'm leaving this here as an experiment for the moment.
*/
if (!tf->isnothrow || tf->trust == TRUSTsystem /*|| tf->purity == PUREimpure*/)
warning(fd->loc, "toHash() must be declared as extern (D) size_t toHash() const nothrow @safe, not %s", tf->toChars());
}
else
dtsize_t(pdt, 0);

// StructFlags m_flags;
StructFlags::Type m_flags = 0;
if (tc->hasPointers()) m_flags |= StructFlags::hasPointers;
dtsize_t(pdt, m_flags);
if (sd->xeq)
dtxoff(pdt, sd->xeq->toSymbol(), 0);
else
dtsize_t(pdt, 0);

#if 0
// xgetMembers
FuncDeclaration *sgetmembers = sd->findGetMembers();
if (sgetmembers)
dtxoff(pdt, sgetmembers->toSymbol(), 0);
else
dtsize_t(pdt, 0); // xgetMembers
#endif
if (sd->xcmp)
dtxoff(pdt, sd->xcmp->toSymbol(), 0);
else
dtsize_t(pdt, 0);

// xdtor
FuncDeclaration *sdtor = sd->dtor;
if (sdtor)
dtxoff(pdt, sdtor->toSymbol(), 0);
else
dtsize_t(pdt, 0); // xdtor
if (FuncDeclaration *fd = search_toString(sd))
{
dtxoff(pdt, fd->toSymbol(), 0);
}
else
dtsize_t(pdt, 0);

// StructFlags m_flags;
StructFlags::Type m_flags = 0;
if (tc->hasPointers()) m_flags |= StructFlags::hasPointers;
dtsize_t(pdt, m_flags);

#if 0
// xgetMembers
FuncDeclaration *sgetmembers = sd->findGetMembers();
if (sgetmembers)
dtxoff(pdt, sgetmembers->toSymbol(), 0);
else
dtsize_t(pdt, 0); // xgetMembers
#endif

// xpostblit
FuncDeclaration *spostblit = sd->postblit;
if (spostblit && !(spostblit->storage_class & STCdisable))
dtxoff(pdt, spostblit->toSymbol(), 0);
else
dtsize_t(pdt, 0); // xpostblit
// xdtor
FuncDeclaration *sdtor = sd->dtor;
if (sdtor)
dtxoff(pdt, sdtor->toSymbol(), 0);
else
dtsize_t(pdt, 0); // xdtor

// xpostblit
FuncDeclaration *spostblit = sd->postblit;
if (spostblit && !(spostblit->storage_class & STCdisable))
dtxoff(pdt, spostblit->toSymbol(), 0);
else
dtsize_t(pdt, 0); // xpostblit

// uint m_align;
dtsize_t(pdt, tc->alignsize());
// uint m_align;
dtsize_t(pdt, tc->alignsize());

if (global.params.is64bit)
{
Type *t = sd->arg1type;
for (int i = 0; i < 2; i++)
if (global.params.is64bit)
{
// m_argi
if (t)
Type *t = sd->arg1type;
for (int i = 0; i < 2; i++)
{
t->getTypeInfo(NULL);
dtxoff(pdt, t->vtinfo->toSymbol(), 0);
}
else
dtsize_t(pdt, 0);
// m_argi
if (t)
{
t->getTypeInfo(NULL);
dtxoff(pdt, t->vtinfo->toSymbol(), 0);
}
else
dtsize_t(pdt, 0);

t = sd->arg2type;
t = sd->arg2type;
}
}

// xgetRTInfo
if (sd->getRTInfo)
sd->getRTInfo->toDt(pdt);
else if (m_flags & StructFlags::hasPointers)
dtsize_t(pdt, 1);
else
dtsize_t(pdt, 0);
}

// xgetRTInfo
if (sd->getRTInfo)
sd->getRTInfo->toDt(pdt);
else if (m_flags & StructFlags::hasPointers)
dtsize_t(pdt, 1);
else
dtsize_t(pdt, 0);
}
void visit(TypeInfoClassDeclaration *d)
{
//printf("TypeInfoClassDeclaration::toDt() %s\n", tinfo->toChars());
assert(0);
}

void TypeInfoClassDeclaration::toDt(dt_t **pdt)
{
//printf("TypeInfoClassDeclaration::toDt() %s\n", tinfo->toChars());
assert(0);
}
void visit(TypeInfoInterfaceDeclaration *d)
{
//printf("TypeInfoInterfaceDeclaration::toDt() %s\n", tinfo->toChars());
verifyStructSize(Type::typeinfointerface, 3 * Target::ptrsize);

void TypeInfoInterfaceDeclaration::toDt(dt_t **pdt)
{
//printf("TypeInfoInterfaceDeclaration::toDt() %s\n", tinfo->toChars());
verifyStructSize(Type::typeinfointerface, 3 * Target::ptrsize);
dtxoff(pdt, Type::typeinfointerface->toVtblSymbol(), 0); // vtbl for TypeInfoInterface
dtsize_t(pdt, 0); // monitor

dtxoff(pdt, Type::typeinfointerface->toVtblSymbol(), 0); // vtbl for TypeInfoInterface
dtsize_t(pdt, 0); // monitor
assert(d->tinfo->ty == Tclass);

assert(tinfo->ty == Tclass);
TypeClass *tc = (TypeClass *)d->tinfo;
Symbol *s;

TypeClass *tc = (TypeClass *)tinfo;
Symbol *s;
if (!tc->sym->vclassinfo)
tc->sym->vclassinfo = TypeInfoClassDeclaration::create(tc);
s = tc->sym->vclassinfo->toSymbol();
dtxoff(pdt, s, 0); // ClassInfo for tinfo
}

if (!tc->sym->vclassinfo)
tc->sym->vclassinfo = TypeInfoClassDeclaration::create(tc);
s = tc->sym->vclassinfo->toSymbol();
dtxoff(pdt, s, 0); // ClassInfo for tinfo
}
void visit(TypeInfoTupleDeclaration *d)
{
//printf("TypeInfoTupleDeclaration::toDt() %s\n", tinfo->toChars());
verifyStructSize(Type::typeinfotypelist, 4 * Target::ptrsize);

void TypeInfoTupleDeclaration::toDt(dt_t **pdt)
{
//printf("TypeInfoTupleDeclaration::toDt() %s\n", tinfo->toChars());
verifyStructSize(Type::typeinfotypelist, 4 * Target::ptrsize);
dtxoff(pdt, Type::typeinfotypelist->toVtblSymbol(), 0); // vtbl for TypeInfoInterface
dtsize_t(pdt, 0); // monitor

dtxoff(pdt, Type::typeinfotypelist->toVtblSymbol(), 0); // vtbl for TypeInfoInterface
dtsize_t(pdt, 0); // monitor
assert(d->tinfo->ty == Ttuple);

assert(tinfo->ty == Ttuple);
TypeTuple *tu = (TypeTuple *)d->tinfo;

TypeTuple *tu = (TypeTuple *)tinfo;
size_t dim = tu->arguments->dim;
dtsize_t(pdt, dim); // elements.length

size_t dim = tu->arguments->dim;
dtsize_t(pdt, dim); // elements.length
dt_t *dt = NULL;
for (size_t i = 0; i < dim; i++)
{ Parameter *arg = (*tu->arguments)[i];
Expression *e = arg->type->getTypeInfo(NULL);
e = e->optimize(WANTvalue);
e->toDt(&dt);
}

dt_t *d = NULL;
for (size_t i = 0; i < dim; i++)
{ Parameter *arg = (*tu->arguments)[i];
Expression *e = arg->type->getTypeInfo(NULL);
e = e->optimize(WANTvalue);
e->toDt(&d);
dtdtoff(pdt, dt, 0); // elements.ptr
}

dtdtoff(pdt, d, 0); // elements.ptr
};

void TypeInfo_toDt(dt_t **pdt, TypeInfoDeclaration *d)
{
TypeInfoDtVisitor v(pdt);
d->accept(&v);
}

/* ========================================================================= */
Expand Down