view dmd/TypeInfoStructDeclaration.d @ 126:1765f3ef917d

ClassDeclarations, Arguments -> Vector
author Eldar Insafutdinov <e.insafutdinov@gmail.com>
date Fri, 03 Sep 2010 23:25:55 +0100
parents e28b18c23469
children 60bb0fe4563e
line wrap: on
line source

module dmd.TypeInfoStructDeclaration;

import dmd.common;
import dmd.Type;
import dmd.TY;
import dmd.MOD;
import dmd.Loc;
import dmd.Argument;
import dmd.STC;
import dmd.TypeStruct;
import dmd.TypeFunction;
import dmd.StructDeclaration;
import dmd.FuncDeclaration;
import dmd.Dsymbol;
import dmd.ArrayTypes;
import dmd.Scope;
import dmd.LINK;
import dmd.Id;
import dmd.TypeInfoDeclaration;
import dmd.backend.dt_t;
import dmd.backend.TYM;
import dmd.backend.Util;
import dmd.expression.Util;

import std.string : toStringz;

class TypeInfoStructDeclaration : TypeInfoDeclaration
{
	this(Type tinfo)
	{
		super(tinfo, 0);
	    type = Type.typeinfostruct.type;
	}

	override void toDt(dt_t** pdt)
	{
		//printf("TypeInfoStructDeclaration.toDt() '%s'\n", toChars());

		uint offset = Type.typeinfostruct.structsize;

		dtxoff(pdt, Type.typeinfostruct.toVtblSymbol(), 0, TYM.TYnptr); // vtbl for TypeInfo_Struct
		dtdword(pdt, 0);			    // monitor

		assert(tinfo.ty == TY.Tstruct);

		TypeStruct tc = cast(TypeStruct)tinfo;
		StructDeclaration sd = tc.sym;

		/* 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;
		 *	uint m_flags;
		 *  xgetMembers;
		 *	xdtor;
		 *	xpostblit;
		 *
		 *	name[]
		 */

		string name = sd.toPrettyChars();
		size_t namelen = name.length;
		dtdword(pdt, namelen);

		//dtabytes(pdt, TYnptr, 0, namelen + 1, name);
		dtxoff(pdt, toSymbol(), offset, TYM.TYnptr);
		offset += namelen + 1;

		// void[] init;
		dtdword(pdt, sd.structsize);	// init.length
		if (sd.zeroInit)
			dtdword(pdt, 0);		// null for 0 initialization
		else
			dtxoff(pdt, sd.toInitializer(), 0, TYM.TYnptr);	// init.ptr
		FuncDeclaration fd;
		FuncDeclaration fdx;
		TypeFunction tf;
		Type ta;
		Dsymbol s;

		static TypeFunction tftohash;
		static TypeFunction tftostring;

		if (!tftohash)
		{
			scope Scope sc = new Scope();

			tftohash = new TypeFunction(null, Type.thash_t, 0, LINK.LINKd);
			tftohash.mod = MOD.MODconst;
			tftohash = cast(TypeFunction)tftohash.semantic(Loc(0), sc);

			tftostring = new TypeFunction(null, Type.tchar.invariantOf().arrayOf(), 0, LINK.LINKd);
			tftostring = cast(TypeFunction)tftostring.semantic(Loc(0), sc);
		}

		TypeFunction tfeqptr;
		{	
			// bool opEqual(const T*) const;
			scope Scope sc = new Scope();
			auto arguments = new Arguments;
		version (STRUCTTHISREF) {
			// arg type is ref const T
			auto arg = new Argument(STC.STCref, tc.constOf(), null, null);
		} else {
			// arg type is const T*
			auto arg = new Argument(STC.STCin, tc.pointerTo(), null, null);
		}

			arguments.push(arg);
			tfeqptr = new TypeFunction(arguments, Type.tbool, 0, LINK.LINKd);
			tfeqptr.mod = MOD.MODconst;
			tfeqptr = cast(TypeFunction)tfeqptr.semantic(Loc(0), sc);
		}

		TypeFunction tfcmpptr;
		{
			scope Scope sc = new Scope();
			auto arguments = new Arguments;
		version (STRUCTTHISREF) {
			// arg type is ref const T
			auto arg = new Argument(STC.STCref, tc.constOf(), null, null);
		} else {
			// arg type is const T*
			auto arg = new Argument(STC.STCin, tc.pointerTo(), null, null);
		}

			arguments.push(arg);
			tfcmpptr = new TypeFunction(arguments, Type.tint32, 0, LINK.LINKd);
			tfcmpptr.mod = MOD.MODconst;
			tfcmpptr = cast(TypeFunction)tfcmpptr.semantic(Loc(0), sc);
		}

		s = search_function(sd, Id.tohash);
		fdx = s ? s.isFuncDeclaration() : null;
		if (fdx)
		{	
			fd = fdx.overloadExactMatch(tftohash);
			if (fd)
				dtxoff(pdt, fd.toSymbol(), 0, TYM.TYnptr);
			else
				//fdx.error("must be declared as extern (D) uint toHash()");
				dtdword(pdt, 0);
		}
		else
			dtdword(pdt, 0);

		s = search_function(sd, Id.eq);
		fdx = s ? s.isFuncDeclaration() : null;
		if (fdx)
		{
			//printf("test1 %s, %s, %s\n", fdx.toChars(), fdx.type.toChars(), tfeqptr.toChars());
			fd = fdx.overloadExactMatch(tfeqptr);
			if (fd)
				dtxoff(pdt, fd.toSymbol(), 0, TYM.TYnptr);
			else
			{   
				fd = fdx.overloadExactMatch(tfcmpptr);
				if (fd)
					fdx.error("must return bool, not int");
				//fdx.error("must be declared as extern (D) int %s(%s*)", fdx.toChars(), sd.toChars());
				dtdword(pdt, 0);
			}
		}
		else
			dtdword(pdt, 0);

		s = search_function(sd, Id.cmp);
		fdx = s ? s.isFuncDeclaration() : null;
		if (fdx)
		{
			//printf("test1 %s, %s, %s\n", fdx.toChars(), fdx.type.toChars(), tfeqptr.toChars());
			fd = fdx.overloadExactMatch(tfcmpptr);
			if (fd)
			{
				dtxoff(pdt, fd.toSymbol(), 0, TYM.TYnptr);
				//printf("test2\n");
			}
			else
				//fdx.error("must be declared as extern (D) int %s(%s*)", fdx.toChars(), sd.toChars());
				dtdword(pdt, 0);
		}
		else
			dtdword(pdt, 0);
	
		s = search_function(sd, Id.tostring);
		fdx = s ? s.isFuncDeclaration() : null;
		if (fdx)
		{	
			fd = fdx.overloadExactMatch(tftostring);
			if (fd)
				dtxoff(pdt, fd.toSymbol(), 0, TYM.TYnptr);
			else
				//fdx.error("must be declared as extern (D) char[] toString()");
				dtdword(pdt, 0);
		}
		else
			dtdword(pdt, 0);

		// uint m_flags;
		dtdword(pdt, tc.hasPointers());

version (DMDV2) {
		// xgetMembers
		FuncDeclaration sgetmembers = sd.findGetMembers();
		if (sgetmembers)
			dtxoff(pdt, sgetmembers.toSymbol(), 0, TYM.TYnptr);
		else
			dtdword(pdt, 0);			// xgetMembers

		// xdtor
		FuncDeclaration sdtor = sd.dtor;
		if (sdtor)
			dtxoff(pdt, sdtor.toSymbol(), 0, TYM.TYnptr);
		else
			dtdword(pdt, 0);			// xdtor

		// xpostblit
		FuncDeclaration spostblit = sd.postblit;
		if (spostblit)
			dtxoff(pdt, spostblit.toSymbol(), 0, TYM.TYnptr);
		else
			dtdword(pdt, 0);			// xpostblit
}
		// name[]
		dtnbytes(pdt, namelen + 1, toStringz(name));
	}
}