dotgnu-pnet-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[dotgnu-pnet-commits] pnet/image generic_class.c generic_member.c


From: Ivan de Jesus Deras Tabora
Subject: [dotgnu-pnet-commits] pnet/image generic_class.c generic_member.c
Date: Fri, 14 Sep 2007 12:09:12 +0000

CVSROOT:        /sources/dotgnu-pnet
Module name:    pnet
Changes by:     Ivan de Jesus Deras Tabora <iderashn>   07/09/14 12:09:12

Added files:
        image          : generic_class.c generic_member.c 

Log message:
        Added missing generic_class.c and generic_member.c

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/pnet/image/generic_class.c?cvsroot=dotgnu-pnet&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/pnet/image/generic_member.c?cvsroot=dotgnu-pnet&rev=1.1

Patches:
Index: generic_class.c
===================================================================
RCS file: generic_class.c
diff -N generic_class.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ generic_class.c     14 Sep 2007 12:09:12 -0000      1.1
@@ -0,0 +1,391 @@
+/*
+ * generic_class.c - Functions related to generic class instances.
+ *
+ * Copyright (C) 2007  Southern Storm Software, Pty Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "program.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ILMethod *ILMethodCreateInstance(ILImage *image,
+                                                                ILMethod 
*method,
+                                                                ILClass 
*classInfo,
+                                                                ILType 
*classTypeArgs,
+                                                                ILType 
*methodTypeArgs);
+
+ILParameter *ILParameterCreateInstance(ILParameter *paramDef, ILMethod 
*method);
+ILMember *ILMemberCreateInstance(ILMember *memberDef, ILClass *info);
+
+ILClass *ILClassGetUnderlying(ILClass *info)
+{
+       ILType *synType = info->synthetic;
+       if(ILType_IsWith(synType) &&
+          !ILClassIsExpanded(info))
+       {
+               synType = ILTypeGetWithMain(synType);
+               return ILClassFromType(info->programItem.image, 0, synType, 0);
+       }
+       else
+       {
+               return info;
+       }
+}
+
+ILClass *ILClassGetGenericDef(ILClass *info)
+{
+       ILType *type = info->synthetic;
+       if(ILType_IsWith(type))
+       {
+               return ILType_ToClass(ILTypeGetWithMain(type));
+       }
+       else
+       {
+               return 0;
+       }
+}
+
+/*
+ * Expand a class instance.
+ */
+ILClass *ILClassExpand(ILImage *image, ILClass *classInfo,
+                                          ILType *classArgs, ILType 
*methodArgs)
+{
+       ILType *type = ILClassToType(classInfo);
+       return ILClassInstantiate(image, type, classArgs, methodArgs);
+}
+
+/*
+ * Expand the instantiations in a class.  Returns zero if out of memory.
+ */
+static int ExpandInstantiations(ILImage *image, ILClass *classInfo,
+                                                               ILType 
*classType, ILType *classParams)
+{
+       ILClass *origClass;
+       ILMember *member;
+       ILMethod *newMethod;
+       ILField *newField;
+       ILEvent *newEvent;
+       ILType *signature;
+       ILImplements *impl;
+       ILClass *tempInfo;
+
+       /* Bail out if not a "with" type, since the instantiation would
+          have already been taken care of by "ILClassFromType" */
+       if(!ILType_IsWith(classType))
+       {
+               return 1;
+       }
+
+       /* Find the original class underlying the type */
+       origClass = ILClassFromType(image, 0, ILTypeGetWithMain(classType), 0);
+       if(!origClass)
+       {
+               return 0;
+       }
+       origClass = ILClassResolve(origClass);
+
+       /* Copy across the class attributes */
+       ILClassSetAttrs(classInfo, ~((ILUInt32)0), ILClass_Attrs(origClass));
+       
+       /* Mark this class as being expanded, to deal with circularities */
+       classInfo->attributes |= IL_META_TYPEDEF_CLASS_EXPANDED;
+
+       /* Expand the parent class and interfaces */
+       if(origClass->parent)
+       {               
+               classInfo->parent = ILClassExpand
+                       (image, ILClass_Parent(origClass), classParams, 0);
+               if(!(classInfo->parent))
+               {
+                       return 0;
+               }
+       }
+       impl = 0;
+       while((impl = ILClassNextImplements(origClass, impl)) != 0)
+       {
+               tempInfo = ILImplementsGetInterface(impl);
+               tempInfo = ILClassExpand(image, tempInfo, classParams, 0);
+               if(!tempInfo)
+               {
+                       return 0;
+               }
+               if(!ILClassAddImplements(classInfo, tempInfo, 0))
+               {
+                       return 0;
+               }
+       }
+
+       /* Expand the methods and fields */
+       member = 0;
+       while((member = ILClassNextMember(origClass, member)) != 0)
+       {
+               switch(ILMemberGetKind(member))
+               {
+                       case IL_META_MEMBERKIND_METHOD:
+                       {
+                               newMethod = ILMethodCreateInstance(image, 
(ILMethod *)member,
+                                                                               
                   classInfo, classParams, 0);
+
+                               if(!newMethod)
+                               {
+                                       return 0;
+                               }
+                       }
+                       break;
+
+                       case IL_META_MEMBERKIND_FIELD:
+                       {
+                               /* Create a new field */
+                               newField = (ILField 
*)ILMemberCreateInstance(member, classInfo);
+
+                               if(!newField)
+                               {
+                                       return 0;
+                               }
+
+                               /* Copy the original field's properties */
+                               signature = ILTypeInstantiate(image->context,
+                                                                               
          ILMember_Signature(member),
+                                                                               
          classParams, 0);
+                               if(!signature)
+                               {
+                                       return 0;
+                               }
+                               else
+                               {
+                                       ILMemberSetSignature((ILMember 
*)newField, signature);
+                               }
+                       }
+                       break;
+                       
+                       case IL_META_MEMBERKIND_EVENT:
+                       {
+                               /* Create a new event */
+                               newEvent = (ILField 
*)ILMemberCreateInstance(member, classInfo);
+
+                               if(!newEvent)
+                               {
+                                       return 0;
+                               }
+
+                               /* Copy the original field's properties */
+                               signature = ILTypeInstantiate(image->context,
+                                                                               
          ILMember_Signature(member),
+                                                                               
          classParams, 0);
+                               if(!signature)
+                               {
+                                       return 0;
+                               }
+                               else
+                               {
+                                       ILMemberSetSignature((ILMember 
*)newEvent, signature);
+                               }
+                       }
+                       break;
+
+                       case IL_META_MEMBERKIND_PROPERTY:
+                       {
+                               /* TODO */
+                       }
+                       break;
+
+                       case IL_META_MEMBERKIND_OVERRIDE:
+                       {
+                               /* TODO */
+                       }
+                       break;
+
+                       case IL_META_MEMBERKIND_PINVOKE:
+                       {
+                               /* TODO */
+                       }
+                       break;
+               }               
+       }
+
+       /* Done */
+       return 1;
+}
+
+ILClass *ILClassInstantiate(ILImage *image, ILType *classType,
+                                                       ILType *classArgs, 
ILType *methodArgs)
+{
+       ILClass *classInfo;
+       ILType *type;
+
+       /* Bail out early if the type does not need instantiation */
+       if(!ILType_IsWith(classType) && !ILTypeNeedsInstantiation(classType))
+       {
+               return ILClassFromType(image, 0, classType, 0);
+       }
+
+       /* Search for a synthetic type that matches the expanded
+          form of the class type, in case we already instantiated
+          this class previously.  We do this in such a way that we
+          won't need to call "ILTypeInstantiate" unless necessary */
+       classInfo = _ILTypeToSyntheticInstantiation(image, classType, 
classArgs, methodArgs);
+       if(classInfo)
+       {
+               if((classInfo->attributes & IL_META_TYPEDEF_CLASS_EXPANDED) == 
0)
+               {
+                       classArgs = ILClassToType(classInfo);
+                       if(!ExpandInstantiations(image, classInfo, classType, 
classArgs))
+                       {
+                               return 0;
+                       }
+               }
+               return classInfo;
+       }
+
+       /* Instantiate the class type */
+       type = ILTypeInstantiate(image->context, classType, classArgs, 
methodArgs);
+       if(!type)
+       {
+               return 0;
+       }
+
+       /* Create a synthetic type for the expanded form */
+       classInfo = ILClassFromType(image, 0, type, 0);
+       if(!classInfo)
+       {
+               return 0;
+       }
+       if(!ExpandInstantiations(image, classInfo, type, type))
+       {
+               return 0;
+       }
+       return classInfo;
+}
+
+ILType *ILClassGetTypeArguments(ILClass *info)
+{
+       if((info->attributes & IL_META_TYPEDEF_CLASS_EXPANDED) != 0)
+       {
+               return info->synthetic;
+       }
+       else
+       {
+               return 0;
+       }
+}
+
+int ILClassNeedsExpansion(ILClass *info)
+{
+       ILType *type = info->synthetic;
+       if(ILType_IsWith(type) &&
+         (info->attributes & IL_META_TYPEDEF_CLASS_EXPANDED) == 0)
+       {
+               return 1;
+       }
+       else
+       {
+               return 0;
+       }
+}
+
+int ILClassIsExpanded(ILClass *info)
+{
+       return ((info->attributes & IL_META_TYPEDEF_CLASS_EXPANDED) != 0);
+}
+
+/* FIXME: Make this function more efficient. */
+ILMember *ILClassGetMemberInstance(ILClass *owner, ILMember *member)
+{
+       ILMember *memberInst = owner->firstMember;
+
+       if(!ILClass_IsGenericInstance(owner))
+       {
+               return 0;
+       }
+
+       while(memberInst != 0)
+       {
+               if(ILProgramItem_Token(memberInst) == 
ILProgramItem_Token(member))
+               {
+                       return memberInst;
+               }
+               memberInst = memberInst->nextMember;
+       }
+
+       return 0;
+}
+
+/* FIXME: Make this function more efficient. */
+ILMethod *ILClassLookupMethodInstance(ILClass *owner, const char *name,
+                                                                         
ILType *signature, ILType  *methodArgs)
+{
+       ILMember *member = 0;
+
+       while((member = ILClassNextMemberByKind(owner,
+                                                                               
    member,
+                                                                               
        IL_META_MEMBERKIND_METHOD)) != 0)
+       {
+               if(strcmp(member->name, name) != 0)
+               {
+                       continue;
+               }
+               if(!ILTypeIdentical(member->signature, signature))
+               {
+                       continue;
+               }
+               if(ILMember_IsGenericInstance(member))
+               {
+                       ILMethodInstance *methodInstance = (ILMethodInstance 
*)member;
+
+                       if 
(ILTypeIdentical(methodInstance->methodTypeArguments, methodArgs))
+                       {
+                               return (ILMethod *)member;
+                       }
+               }
+       }
+
+       return 0;
+}
+
+ILClass *ILClassResolveToInstance(ILClass *classInfo, ILMethod *methodCaller)
+{
+       ILType *classTypeArgs = 0;
+       ILType *methodTypeArgs = 0;
+       ILType *classType;
+
+       classInfo = ILClassResolve(classInfo);
+       classType = ILClass_SynType(classInfo);
+       if(!classType ||
+          (!ILTypeNeedsInstantiation(classType) &&
+          !ILClassNeedsExpansion(classInfo)))
+       {
+               return classInfo;
+       }
+       if(ILMember_IsGenericInstance(methodCaller))
+       {
+               ILMethodInstance *methodInstance = (ILMethodInstance 
*)methodCaller;
+
+               classTypeArgs = methodInstance->classTypeArguments;
+               methodTypeArgs = methodInstance->methodTypeArguments;
+       }
+       classInfo = ILClassExpand(ILClassToImage(classInfo), classInfo,
+                                                         classTypeArgs, 
methodTypeArgs);
+
+       return classInfo;
+}
+
+#ifdef __cplusplus
+};
+#endif

Index: generic_member.c
===================================================================
RCS file: generic_member.c
diff -N generic_member.c
--- /dev/null   1 Jan 1970 00:00:00 -0000
+++ generic_member.c    14 Sep 2007 12:09:12 -0000      1.1
@@ -0,0 +1,493 @@
+/*
+ * generic_member.c - Functions related to generic class members.
+ *
+ * Copyright (C) 2007  Southern Storm Software, Pty Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include "program.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ILMember *ILClassGetMemberInstance(ILClass *owner, ILMember *member);
+
+/*
+ * Function for creating members instances and attaching them to a class.
+ */
+ILMember *ILMemberCreateInstance(ILMember *memberDef,
+                                                                ILClass *info)
+{
+       ILImage *image = memberDef->programItem.image;
+       ILMember *member;
+       unsigned size;
+
+       if(ILMember_IsMethod(memberDef))
+       {
+               size = sizeof(ILMethodInstance);
+       }
+       else if(ILMember_IsField(memberDef))
+       {
+               size = sizeof(ILField);
+       }
+       else if(ILMember_IsProperty(memberDef))
+       {
+               size = sizeof(ILProperty);
+       }
+       else if(ILMember_IsEvent(memberDef))
+       {
+               size = sizeof(ILEvent);
+       }
+       else if(ILMember_IsOverride(memberDef))
+       {
+               size = sizeof(ILOverride);
+       }
+       else if(ILMember_IsPInvoke(memberDef))
+       {
+               size = sizeof(ILPInvoke);
+       }
+       else
+       {
+               /* Unknown */
+               return 0;
+       }
+
+       /* Allocate space for the member from the memory stack */
+       member = (ILMember *)ILMemStackAllocItem(&(image->memStack), size);
+       if(!member)
+       {
+               return 0;
+       }
+
+       /* Attach the member to its owning class */     
+       member->owner = info;
+       member->nextMember = 0;
+       if(info->lastMember)
+               info->lastMember->nextMember = member;
+       else
+               info->firstMember = member;
+       info->lastMember = member;
+
+       /* Copy the other member fields from the member definition */
+       member->name = memberDef->name;
+       member->programItem.image = image;
+       member->programItem.token = memberDef->programItem.token;
+       member->kind = memberDef->kind;
+       member->attributes = memberDef->attributes;
+       member->signature = 0;
+       member->signatureBlob = 0;
+
+       return member;
+}
+
+
+/*
+ * Function for creating parameter instances and attaching them to a method.
+ */
+ILParameter *ILParameterCreateInstance(ILParameter *paramDef,
+                                                                          
ILMethod *method)
+{
+       ILImage *image = paramDef->programItem.image;
+       ILParameter *param;
+       ILParameter *current;
+       ILParameter *prev;
+
+       /* Allocate space for the parameter from the memory stack */
+       param = ILMemStackAlloc(&(image->memStack), ILParameter);
+       if(!param)
+       {
+               return 0;
+       }
+
+       /* Set the parameter fields */
+       param->name = paramDef->name;
+       param->programItem.image = image;
+       param->attributes = paramDef->attributes;
+       param->paramNum = paramDef->paramNum;
+
+       /* Attach the parameter to the method */
+       current = method->parameters;
+       prev = 0;
+       while(current != 0 && current->paramNum < param->paramNum)
+       {
+               prev = current;
+               current = current->next;
+       }
+       param->next = current;
+       if(prev)
+       {
+               prev->next = param;
+       }
+       else
+       {
+               method->parameters = param;
+       }
+
+       /* Return the parameter to the caller */
+       return param;
+}
+
+/*
+ * Create a method instance and attach it to a class.
+ */
+ILMethod *ILMethodCreateInstance(ILImage *image,
+                                                                ILMethod 
*method,
+                                                                ILClass 
*classInfo,
+                                                                ILType 
*classTypeArgs,
+                                                                ILType 
*methodTypeArgs)
+{
+       ILParameter *origParam;
+       ILMethod *newMethod;
+       ILType *signature;
+       ILMethodInstance *methodInstance;
+
+       signature = ILTypeInstantiate(image->context,
+                                                                 
ILMethod_Signature(method),
+                                                                 classTypeArgs,
+                                                                 
methodTypeArgs);
+       if(!signature)
+       {
+               return 0;
+       }
+       newMethod = 0;
+       if(ILClassIsExpanded(classInfo))
+       {
+               newMethod = ILClassLookupMethodInstance(classInfo, 
ILMethod_Name(method),
+                                                                               
                signature, methodTypeArgs);
+       }
+       if(!newMethod)
+       {
+               /* Create a new method */
+               newMethod = (ILMethod *)ILMemberCreateInstance((ILMember 
*)method, classInfo);
+
+               if(!newMethod)
+               {
+                       return 0;
+               }       
+
+               /* Copy the original method's properties */
+               ILMemberSetSignature((ILMember *)newMethod, signature);
+               ILMethodSetImplAttrs(newMethod, ~((ILUInt32)0),
+                                                        
ILMethod_ImplAttrs(method));
+               ILMethodSetCallConv(newMethod, ILMethod_CallConv(method));
+               ILMethodSetRVA(newMethod, ILMethod_RVA(method));
+               newMethod->callingConventions |= IL_META_CALLCONV_INSTANTIATION;
+               newMethod->userData = 0;
+               methodInstance = (ILMethodInstance *)newMethod;
+               methodInstance->genMethod = method;
+               methodInstance->classTypeArguments = classTypeArgs;
+               methodInstance->methodTypeArguments = methodTypeArgs;
+               
+               /* Copy the original method's parameter blocks */
+               origParam = 0;
+               while((origParam = ILMethodNextParam(method, origParam)) != 0)
+               {
+                       if(!ILParameterCreateInstance(origParam, newMethod))
+                       {
+                               return 0;
+                       }
+               }
+       }
+
+       return newMethod;
+}
+
+static int UpdateMethodVTable(ILMethod *method, ILMethod *virtualAncestor)
+{
+       ILClass *owner = ILMethod_Owner(method);
+       ILImage *image;
+       ILMethodVTable *parentVTable;
+       ILMethodVTable *vtable;
+
+       if(method->vtable == 0)
+       {
+               return 0;
+       }
+       parentVTable = virtualAncestor->vtable;
+       if(!parentVTable)
+       {
+               return 0;
+       }
+       image = ILProgramItem_Image(method);
+       vtable = method->vtable;
+       while(vtable->numSlots < parentVTable->numSlots)
+       {
+               ILMethodInstance *methodInstance = (ILMethodInstance 
*)ILMethodGetInstance(virtualAncestor, vtable->numSlots);
+               ILMethod *newMethod = ILMethodCreateInstance(image,
+                                                                               
                         method,
+                                                                               
                         owner, 
+                                                                               
                         ILClassGetTypeArguments(owner),
+                                                                               
                         methodInstance->methodTypeArguments);
+               if(!newMethod)
+               {
+                       return 0;
+               }
+               if(!ILMethodAddInstance(method, newMethod))
+               {
+                       return 0;
+               }
+       }
+
+       return 1;
+}
+
+static int InitVTable(ILMethod *method)
+{
+       ILImage *image = ILProgramItem_Image(method);
+
+       method->vtable = ILMemStackAlloc(&(image->memStack), ILMethodVTable);
+       if(!method->vtable)
+       {
+               return 0;
+       }
+       method->vtable->numSlots = 0;
+       method->vtable->numItems = 1;
+       method->vtable->lastItem = &method->vtable->firstItem;
+
+       return 1;
+}
+
+/*
+ * Set the method ancestor and initialize the vtable.
+ */
+int ILMethodSetVirtualAncestor(ILMethod *method, ILMethod *virtualAncestor)
+{
+       if(!ILMethod_IsVirtualGeneric(method))
+       {
+               return 1;
+       }       
+       if(method->vtable == 0)
+       {
+               if(!InitVTable(method))
+               {
+                       return 0;
+               }
+       }
+       method->vtable->virtualAncestor = virtualAncestor;
+
+       return 1;
+}
+
+ILMethod *ILMethodGetInstance(ILMethod *method, int index)
+{
+       ILMethodVTableItem *item;
+       ILMethodVTable     *vtable;
+       ILMethod                   *ancestor;
+       int itemIndex;
+       int indexInItem;
+
+       if(method->vtable == 0)
+       {
+               return 0;
+       }
+       /* Let's find the top virtual ancestor. */
+       ancestor = method->vtable->virtualAncestor;
+       if(ancestor != 0)
+       {
+               while(ancestor->vtable->virtualAncestor != 0)
+               {
+                       ancestor = ancestor->vtable->virtualAncestor;
+               }
+
+               /* Ensure that the vtable is up-to-date. */
+               if(!UpdateMethodVTable(method, ancestor))
+               {
+                       return 0;
+               }
+       }
+       vtable = method->vtable;
+       if(index >= vtable->numSlots)
+       {
+               return 0;
+       }
+       item = &(vtable->firstItem);
+       itemIndex = index / METHOD_VTABLE_ITEM_COUNT;
+       indexInItem = index % METHOD_VTABLE_ITEM_COUNT;
+       while(itemIndex-- > 0)
+       {
+               item = item->nextItem;
+       }
+       
+       return item->data[indexInItem];
+}
+
+int ILMethodAddInstance(ILMethod *method, ILMethod *methodInstance)
+{
+       ILImage  *image = ILProgramItem_Image(method);
+       ILMethodVTableItem *item;
+       int             indexInItem;
+       int             lastItemCount;
+
+       /* The method vtable should have been initialized when laying out the 
class */
+       if(method->vtable == 0)
+       {
+               return 0;
+       }
+       lastItemCount = (method->vtable->numItems * METHOD_VTABLE_ITEM_COUNT) - 
method->vtable->numSlots;
+       if(lastItemCount == 0)
+       {               
+               item = ILMemStackAlloc(&(image->memStack), ILMethodVTableItem);
+               if(!item)
+               {
+                       return 0;
+               }
+               method->vtable->numItems++;
+               method->vtable->lastItem->nextItem = item;
+               method->vtable->lastItem = item;
+       }
+       else
+       {
+               item = method->vtable->lastItem;
+       }
+       methodInstance->index = method->vtable->numSlots;
+       method->vtable->numSlots++;
+       indexInItem = methodInstance->index % METHOD_VTABLE_ITEM_COUNT;
+       item->data[indexInItem] = methodInstance;
+
+       return 1;
+}
+
+ILMember *ILMemberResolveToInstance(ILMember *member, ILMethod *methodCaller)
+{
+       ILClass *owner;
+
+       owner = ILClassResolveToInstance(member->owner, methodCaller);
+       if(owner == 0)
+       {
+               return 0;
+       }
+       member = ILMemberResolve(member);
+       if(member->owner != owner)
+       {
+               member = ILClassGetMemberInstance(owner, member);
+       }
+
+       return member;
+}
+
+int ILMemberIsGenericInstance(ILMember *member)
+{
+       if(!member->owner)
+       {
+               return 0;
+       }
+       if(ILClass_IsGenericInstance(member->owner))
+       {
+               return 1;
+       }
+
+       if(ILMember_IsMethod(member))
+       {
+               return ((ILMethod_CallConv((ILMethod *)member) & 
IL_META_CALLCONV_INSTANTIATION) != 0);
+       }
+       
+       return 0;
+}
+
+ILMethod *ILMethodSpecToMethod(ILMethodSpec *mspec, ILMethod *methodCaller)
+{
+       ILType *classTypeArgs = 0;
+       ILType *methodTypeArgs = 0;
+       ILMethod *newMethod;
+       ILMethod *genMethod;
+       ILMethod *virtAncestor;
+       ILType *mspecTypeArgs;
+       ILClass *owner;
+       ILImage *image;
+
+       if(ILMember_IsGenericInstance((ILMember *)methodCaller))
+       {
+               ILMethodInstance *methodInstance = (ILMethodInstance 
*)methodCaller;
+
+               classTypeArgs = methodInstance->classTypeArguments;
+               methodTypeArgs = methodInstance->methodTypeArguments;
+       }
+
+       image = ILProgramItem_Image(mspec);
+       mspecTypeArgs = ILTypeInstantiate(ILImageToContext(image),
+                                                                         
ILMethodSpec_Type(mspec),
+                                                                         
classTypeArgs,
+                                                                         
methodTypeArgs);
+       if(!mspecTypeArgs)
+       {
+               return 0;
+       }
+       genMethod = (ILMethod *)ILMemberResolveToInstance(mspec->method, 
methodCaller);
+       if(!genMethod)
+       {
+               return 0;
+       }
+       virtAncestor = genMethod;
+       if(ILMethod_IsVirtualGeneric(genMethod))
+       {               
+               while(virtAncestor->vtable->virtualAncestor != 0)
+               {
+                       virtAncestor = virtAncestor->vtable->virtualAncestor;
+               }
+       }
+       newMethod = ILMethodCreateInstance(image, 
+                                                                          
virtAncestor,
+                                                                          
ILMethod_Owner(virtAncestor),
+                                                                          
classTypeArgs,
+                                                                          
mspecTypeArgs);
+       if(!newMethod)
+       {
+               return 0;
+       }
+       if(ILMethod_IsVirtualGeneric(virtAncestor))
+       {
+               if(!ILMethodAddInstance(virtAncestor, newMethod))
+               {
+                       return 0;
+               }
+               newMethod = ILMethodGetInstance(genMethod, newMethod->index);
+               if(!newMethod)
+               {
+                       return 0;
+               }
+       }
+
+       return newMethod;
+}
+
+ILType *ILMethodGetClassTypeArguments(ILMethod *method)
+{
+       if(ILMember_IsGenericInstance(method))
+       {
+               return ((ILMethodInstance*)method)->classTypeArguments;
+       }
+       else
+       {
+               return 0;
+       }
+}
+
+ILType *ILMethodGetMethodTypeArguments(ILMethod *method)
+{
+       if(ILMember_IsGenericInstance(method))
+       {
+               return ((ILMethodInstance*)method)->methodTypeArguments;
+       }
+       else
+       {
+               return 0;
+       }
+}
+
+#ifdef __cplusplus
+};
+#endif




reply via email to

[Prev in Thread] Current Thread [Next in Thread]