Expand Up
@@ -26,22 +26,11 @@
#include "enum.h"
#include "import.h"
#include "aggregate.h"
#include "target.h"
#include "visitor.h"
#include "dt.h"
Symbol * toSymbol (Dsymbol * s );
dt_t * * Expression_toDt (Expression * e , dt_t * * pdt );
void toObjFile (Dsymbol * ds , bool multiobj );
Symbol * toVtblSymbol (ClassDeclaration * cd );
Symbol * toInitializer (AggregateDeclaration * ad );
Symbol * toInitializer (EnumDeclaration * ed );
TypeInfoDeclaration * getTypeInfoDeclaration (Type * t );
static bool builtinTypeInfo (Type * t );
FuncDeclaration * search_toString (StructDeclaration * sd );
/****************************************************
* Get the exact TypeInfo.
*/
Expand Down
Expand Up
@@ -135,496 +124,6 @@ TypeInfoDeclaration *getTypeInfoDeclaration(Type *t)
}
}
/****************************************************
*/
class TypeInfoDtVisitor : public Visitor
{
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" , (unsigned )expected ,
typeclass -> toChars (), (unsigned )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 ();
}
}
public:
TypeInfoDtVisitor (dt_t * * pdt )
: pdt (pdt )
{
}
void visit (TypeInfoDeclaration * d )
{
//printf("TypeInfoDeclaration::toDt() %s\n", toChars());
verifyStructSize(Type ::dtypeinfo , 2 * Target ::ptrsize );
dtxoff (pdt , toVtblSymbol (Type ::dtypeinfo ), 0 ); // vtbl for TypeInfo
dtsize_t (pdt , 0 ); // monitor
}
void visit (TypeInfoConstDeclaration * d )
{
//printf("TypeInfoConstDeclaration::toDt() %s\n", toChars());
verifyStructSize(Type ::typeinfoconst , 3 * Target ::ptrsize );
dtxoff (pdt , toVtblSymbol (Type ::typeinfoconst ), 0 ); // vtbl for TypeInfo_Const
dtsize_t (pdt , 0 ); // monitor
Type * tm = d -> tinfo -> mutableOf ();
tm = tm -> merge ();
genTypeInfo (tm , NULL );
dtxoff (pdt , toSymbol (tm -> vtinfo ), 0 );
}
void visit (TypeInfoInvariantDeclaration * d )
{
//printf("TypeInfoInvariantDeclaration::toDt() %s\n", toChars());
verifyStructSize(Type ::typeinfoinvariant , 3 * Target ::ptrsize );
dtxoff (pdt , toVtblSymbol (Type ::typeinfoinvariant ), 0 ); // vtbl for TypeInfo_Invariant
dtsize_t (pdt , 0 ); // monitor
Type * tm = d -> tinfo -> mutableOf ();
tm = tm -> merge ();
genTypeInfo (tm , NULL );
dtxoff (pdt , toSymbol (tm -> vtinfo ), 0 );
}
void visit (TypeInfoSharedDeclaration * d )
{
//printf("TypeInfoSharedDeclaration::toDt() %s\n", toChars());
verifyStructSize(Type ::typeinfoshared , 3 * Target ::ptrsize );
dtxoff (pdt , toVtblSymbol (Type ::typeinfoshared ), 0 ); // vtbl for TypeInfo_Shared
dtsize_t (pdt , 0 ); // monitor
Type * tm = d -> tinfo -> unSharedOf ();
tm = tm -> merge ();
genTypeInfo (tm , NULL );
dtxoff (pdt , toSymbol (tm -> vtinfo ), 0 );
}
void visit (TypeInfoWildDeclaration * d )
{
//printf("TypeInfoWildDeclaration::toDt() %s\n", toChars());
verifyStructSize(Type ::typeinfowild , 3 * Target ::ptrsize );
dtxoff (pdt , toVtblSymbol (Type ::typeinfowild ), 0 ); // vtbl for TypeInfo_Wild
dtsize_t (pdt , 0 ); // monitor
Type * tm = d -> tinfo -> mutableOf ();
tm = tm -> merge ();
genTypeInfo (tm , NULL );
dtxoff (pdt , toSymbol (tm -> vtinfo ), 0 );
}
void visit (TypeInfoEnumDeclaration * d )
{
//printf("TypeInfoEnumDeclaration::toDt()\n");
verifyStructSize(Type ::typeinfoenum , 7 * Target ::ptrsize );
dtxoff (pdt , toVtblSymbol (Type ::typeinfoenum ), 0 ); // vtbl for TypeInfo_Enum
dtsize_t (pdt , 0 ); // monitor
assert (d -> tinfo -> ty == Tenum );
TypeEnum * tc = (TypeEnum * )d -> tinfo ;
EnumDeclaration * sd = tc -> sym ;
/* Put out:
* TypeInfo base;
* char[] name;
* void[] m_init;
*/
if (sd -> memtype )
{
genTypeInfo (sd -> memtype , NULL );
dtxoff (pdt , toSymbol (sd -> memtype -> vtinfo ), 0 ); // TypeInfo for enum members
}
else
dtsize_t (pdt , 0 );
const char * name = sd -> toPrettyChars ();
size_t namelen = strlen (name );
dtsize_t (pdt , namelen );
dtxoff (pdt , d -> csym , Type ::typeinfoenum -> structsize );
// 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 , toInitializer (sd ), 0 ); // init.ptr
}
// Put out name[] immediately following TypeInfo_Enum
dtnbytes (pdt , namelen + 1 , name );
}
void visit (TypeInfoPointerDeclaration * d )
{
//printf("TypeInfoPointerDeclaration::toDt()\n");
verifyStructSize(Type ::typeinfopointer , 3 * Target ::ptrsize );
dtxoff (pdt , toVtblSymbol (Type ::typeinfopointer ), 0 ); // vtbl for TypeInfo_Pointer
dtsize_t (pdt , 0 ); // monitor
assert (d -> tinfo -> ty == Tpointer );
TypePointer * tc = (TypePointer * )d -> tinfo ;
genTypeInfo (tc -> next , NULL );
dtxoff (pdt , toSymbol (tc -> next -> vtinfo ), 0 ); // TypeInfo for type being pointed to
}
void visit (TypeInfoArrayDeclaration * d )
{
//printf("TypeInfoArrayDeclaration::toDt()\n");
verifyStructSize(Type ::typeinfoarray , 3 * Target ::ptrsize );
dtxoff (pdt , toVtblSymbol (Type ::typeinfoarray ), 0 ); // vtbl for TypeInfo_Array
dtsize_t (pdt , 0 ); // monitor
assert (d -> tinfo -> ty == Tarray );
TypeDArray * tc = (TypeDArray * )d -> tinfo ;
genTypeInfo (tc -> next , NULL );
dtxoff (pdt , toSymbol (tc -> next -> vtinfo ), 0 ); // TypeInfo for array of type
}
void visit (TypeInfoStaticArrayDeclaration * d )
{
//printf("TypeInfoStaticArrayDeclaration::toDt()\n");
verifyStructSize(Type ::typeinfostaticarray , 4 * Target ::ptrsize );
dtxoff (pdt , toVtblSymbol (Type ::typeinfostaticarray ), 0 ); // vtbl for TypeInfo_StaticArray
dtsize_t (pdt , 0 ); // monitor
assert (d -> tinfo -> ty == Tsarray );
TypeSArray * tc = (TypeSArray * )d -> tinfo ;
genTypeInfo (tc -> next , NULL );
dtxoff (pdt , toSymbol (tc -> next -> vtinfo ), 0 ); // TypeInfo for array of type
dtsize_t (pdt , tc -> dim -> toInteger ()); // length
}
void visit (TypeInfoVectorDeclaration * d )
{
//printf("TypeInfoVectorDeclaration::toDt()\n");
verifyStructSize(Type ::typeinfovector , 3 * Target ::ptrsize );
dtxoff (pdt , toVtblSymbol (Type ::typeinfovector ), 0 ); // vtbl for TypeInfo_Vector
dtsize_t (pdt , 0 ); // monitor
assert (d -> tinfo -> ty == Tvector );
TypeVector * tc = (TypeVector * )d -> tinfo ;
genTypeInfo (tc -> basetype , NULL );
dtxoff (pdt , toSymbol (tc -> basetype -> vtinfo ), 0 ); // TypeInfo for equivalent static array
}
void visit (TypeInfoAssociativeArrayDeclaration * d )
{
//printf("TypeInfoAssociativeArrayDeclaration::toDt()\n");
verifyStructSize(Type ::typeinfoassociativearray , 4 * Target ::ptrsize );
dtxoff (pdt , toVtblSymbol (Type ::typeinfoassociativearray ), 0 ); // vtbl for TypeInfo_AssociativeArray
dtsize_t (pdt , 0 ); // monitor
assert (d -> tinfo -> ty == Taarray );
TypeAArray * tc = (TypeAArray * )d -> tinfo ;
genTypeInfo (tc -> next , NULL );
dtxoff (pdt , toSymbol (tc -> next -> vtinfo ), 0 ); // TypeInfo for array of type
genTypeInfo (tc -> index , NULL );
dtxoff (pdt , toSymbol (tc -> index -> vtinfo ), 0 ); // TypeInfo for array of type
}
void visit (TypeInfoFunctionDeclaration * d )
{
//printf("TypeInfoFunctionDeclaration::toDt()\n");
verifyStructSize(Type ::typeinfofunction , 5 * Target ::ptrsize );
dtxoff (pdt , toVtblSymbol (Type ::typeinfofunction ), 0 ); // vtbl for TypeInfo_Function
dtsize_t (pdt , 0 ); // monitor
assert (d -> tinfo -> ty == Tfunction );
TypeFunction * tc = (TypeFunction * )d -> tinfo ;
genTypeInfo (tc -> next , NULL );
dtxoff (pdt , toSymbol (tc -> next -> vtinfo ), 0 ); // TypeInfo for function return value
const char * name = d -> tinfo -> deco ;
assert (name );
size_t namelen = strlen (name );
dtsize_t (pdt , namelen );
dtxoff (pdt , d -> csym , Type ::typeinfofunction -> structsize );
// Put out name[] immediately following TypeInfo_Function
dtnbytes (pdt , namelen + 1 , name );
}
void visit (TypeInfoDelegateDeclaration * d )
{
//printf("TypeInfoDelegateDeclaration::toDt()\n");
verifyStructSize(Type ::typeinfodelegate , 5 * Target ::ptrsize );
dtxoff (pdt , toVtblSymbol (Type ::typeinfodelegate ), 0 ); // vtbl for TypeInfo_Delegate
dtsize_t (pdt , 0 ); // monitor
assert (d -> tinfo -> ty == Tdelegate );
TypeDelegate * tc = (TypeDelegate * )d -> tinfo ;
genTypeInfo (tc -> next -> nextOf (), NULL );
dtxoff (pdt , toSymbol (tc -> next -> nextOf ()-> vtinfo ), 0 ); // TypeInfo for delegate return value
const char * name = d -> tinfo -> deco ;
assert (name );
size_t namelen = strlen (name );
dtsize_t (pdt , namelen );
dtxoff (pdt , d -> csym , Type ::typeinfodelegate -> structsize );
// Put out name[] immediately following TypeInfo_Delegate
dtnbytes (pdt , namelen + 1 , name );
}
void visit (TypeInfoStructDeclaration * d )
{
//printf("TypeInfoStructDeclaration::toDt() '%s'\n", d->toChars());
if (global .params .is64bit )
verifyStructSize (Type ::typeinfostruct , 17 * Target ::ptrsize );
else
verifyStructSize (Type ::typeinfostruct , 15 * Target ::ptrsize );
dtxoff (pdt , toVtblSymbol (Type ::typeinfostruct ), 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 ;
if (TemplateInstance * ti = sd -> isInstantiated ())
{
/* Bugzilla 14425: TypeInfo_Struct would refer the members of
* struct (e.g. opEquals via xopEquals field), so if it's instantiated
* in speculative context, TypeInfo creation should also be
* stopped to avoid 'unresolved symbol' linker errors.
*/
if (!ti -> needsCodegen () && !ti -> minst )
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
*/
const char * name = sd -> toPrettyChars ();
size_t namelen = strlen (name );
dtsize_t (pdt , namelen );
dtxoff (pdt , d -> csym , Type ::typeinfostruct -> structsize );
// void[] init;
dtsize_t (pdt , sd -> structsize ); // init.length
if (sd -> zeroInit )
dtsize_t (pdt , 0 ); // NULL for 0 initialization
else
dtxoff (pdt , toInitializer (sd ), 0 ); // init.ptr
if (FuncDeclaration * fd = sd -> xhash )
{
dtxoff (pdt , toSymbol (fd ), 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 );
if (sd -> xeq )
dtxoff (pdt , toSymbol (sd -> xeq ), 0 );
else
dtsize_t (pdt , 0 );
if (sd -> xcmp )
dtxoff (pdt , toSymbol (sd -> xcmp ), 0 );
else
dtsize_t (pdt , 0 );
if (FuncDeclaration * fd = search_toString (sd ))
{
dtxoff (pdt , toSymbol (fd ), 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 , toSymbol (sgetmembers ), 0 );
else
dtsize_t (pdt , 0 ); // xgetMembers
#endif
// xdtor
FuncDeclaration * sdtor = sd -> dtor ;
if (sdtor )
dtxoff (pdt , toSymbol (sdtor ), 0 );
else
dtsize_t (pdt , 0 ); // xdtor
// xpostblit
FuncDeclaration * spostblit = sd -> postblit ;
if (spostblit && !(spostblit -> storage_class & STCdisable ))
dtxoff (pdt , toSymbol (spostblit ), 0 );
else
dtsize_t (pdt , 0 ); // xpostblit
// uint m_align;
dtsize_t (pdt , tc -> alignsize ());
if (global .params .is64bit )
{
Type * t = sd -> arg1type ;
for (int i = 0 ; i < 2 ; i ++ )
{
// m_argi
if (t )
{
genTypeInfo (t , NULL );
dtxoff (pdt , toSymbol (t -> vtinfo ), 0 );
}
else
dtsize_t (pdt , 0 );
t = sd -> arg2type ;
}
}
// xgetRTInfo
if (sd -> getRTInfo )
Expression_toDt (sd -> getRTInfo , pdt );
else if (m_flags & StructFlags ::hasPointers )
dtsize_t (pdt , 1 );
else
dtsize_t (pdt , 0 );
// Put out name[] immediately following TypeInfo_Struct
dtnbytes (pdt , namelen + 1 , name );
}
void visit (TypeInfoClassDeclaration * d )
{
//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 );
dtxoff (pdt , toVtblSymbol (Type ::typeinfointerface ), 0 ); // vtbl for TypeInfoInterface
dtsize_t (pdt , 0 ); // monitor
assert (d -> tinfo -> ty == Tclass );
TypeClass * tc = (TypeClass * )d -> tinfo ;
Symbol * s ;
if (!tc -> sym -> vclassinfo )
tc -> sym -> vclassinfo = TypeInfoClassDeclaration ::create (tc );
s = toSymbol (tc -> sym -> vclassinfo );
dtxoff (pdt , s , 0 ); // ClassInfo for tinfo
}
void visit (TypeInfoTupleDeclaration * d )
{
//printf("TypeInfoTupleDeclaration::toDt() %s\n", tinfo->toChars());
verifyStructSize(Type ::typeinfotypelist , 4 * Target ::ptrsize );
dtxoff (pdt , toVtblSymbol (Type ::typeinfotypelist ), 0 ); // vtbl for TypeInfoInterface
dtsize_t (pdt , 0 ); // monitor
assert (d -> tinfo -> ty == Ttuple );
TypeTuple * tu = (TypeTuple * )d -> tinfo ;
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 ];
genTypeInfo (arg -> type , NULL );
Symbol * s = toSymbol (arg -> type -> vtinfo );
dtxoff (& dt , s , 0 );
}
dtdtoff (pdt , dt , 0 ); // elements.ptr
}
};
void TypeInfo_toDt (dt_t * * pdt , TypeInfoDeclaration * d )
{
TypeInfoDtVisitor v (pdt );
d -> accept (& v );
}
/* ========================================================================= */
/* These decide if there's an instance for them already in std.typeinfo,
Expand Down