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

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

[dotgnu-pnet-commits] pnet ChangeLog engine/jitc.c engine/jitc.h engi...


From: Klaus Treichel
Subject: [dotgnu-pnet-commits] pnet ChangeLog engine/jitc.c engine/jitc.h engi...
Date: Sat, 22 Jul 2006 08:48:32 +0000

CVSROOT:        /sources/dotgnu-pnet
Module name:    pnet
Changes by:     Klaus Treichel <ktreichel>      06/07/22 08:48:32

Modified files:
        .              : ChangeLog 
        engine         : jitc.c jitc.h jitc_pinvoke.c lib_marshal.c 

Log message:
        2006-07-22  Kirill Kononenko  <address@hidden>
        
                * engine/jitc.c: Add additional signatures needed for pinvokes.
        
                * engine/jitc.h: Add prototype for ILJitDelegateGetClosure.
        
                * engine/jitc_pinvoke.c: Implement marshalling for pinvokes.
        
                * engine/lib_marshal.c: Call ILJitDelegateGetClosure if the 
engine is
                built with the just in time compiler.

CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/pnet/ChangeLog?cvsroot=dotgnu-pnet&r1=1.3343&r2=1.3344
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc.c?cvsroot=dotgnu-pnet&r1=1.42&r2=1.43
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc.h?cvsroot=dotgnu-pnet&r1=1.13&r2=1.14
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/jitc_pinvoke.c?cvsroot=dotgnu-pnet&r1=1.1&r2=1.2
http://cvs.savannah.gnu.org/viewcvs/pnet/engine/lib_marshal.c?cvsroot=dotgnu-pnet&r1=1.8&r2=1.9

Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/dotgnu-pnet/pnet/ChangeLog,v
retrieving revision 1.3343
retrieving revision 1.3344
diff -u -b -r1.3343 -r1.3344
--- ChangeLog   21 Jul 2006 20:30:02 -0000      1.3343
+++ ChangeLog   22 Jul 2006 08:48:32 -0000      1.3344
@@ -1,3 +1,14 @@
+2006-07-22  Kirill Kononenko  <address@hidden>
+
+       * engine/jitc.c: Add additional signatures needed for pinvokes.
+
+       * engine/jitc.h: Add prototype for ILJitDelegateGetClosure.
+
+       * engine/jitc_pinvoke.c: Implement marshalling for pinvokes.
+
+       * engine/lib_marshal.c: Call ILJitDelegateGetClosure if the engine is
+       built with the just in time compiler.
+
 2006-07-21  Radek Polak  <address@hidden>
 
        * engine/debugger.c: New command is_stopped that is used to check if

Index: engine/jitc.c
===================================================================
RCS file: /sources/dotgnu-pnet/pnet/engine/jitc.c,v
retrieving revision 1.42
retrieving revision 1.43
diff -u -b -r1.42 -r1.43
--- engine/jitc.c       3 Jul 2006 16:18:56 -0000       1.42
+++ engine/jitc.c       22 Jul 2006 08:48:32 -0000      1.43
@@ -231,16 +231,42 @@
 static ILJitType _ILJitSignature_ILRuntimeHandleManagedSafePointFlags = 0;
 
 /*
+ * char *ILStringToAnsi(ILExecThread *thread, ILString *str)
+ */
+static ILJitType _ILJitSignature_ILStringToAnsi = 0;
+
+/*
  * char *ILStringToUTF8(ILExecThread *thread, ILString *str)
  */
 static ILJitType _ILJitSignature_ILStringToUTF8 = 0;
 
 /* 
+ * char *ILStringToUTF16(ILExecThread *thread, ILString *str)
+ */
+static ILJitType _ILJitSignature_ILStringToUTF16 = 0;
+
+/* 
  * ILString *ILStringCreate(ILExecThread *thread, const char *str)
  */
 static ILJitType _ILJitSignature_ILStringCreate = 0;
 
 /*
+ * ILString *ILStringCreateUTF8(ILExecThread *thread, const char *str)
+ */
+static ILJitType _ILJitSignature_ILStringCreateUTF8 = 0;
+
+/* 
+ * ILString *ILStringWCreate(ILExecThread *thread, const ILUInt16 *str)
+ */
+static ILJitType _ILJitSignature_ILStringWCreate = 0;
+
+/*
+ * void *ILJitDelegateGetClosure(ILExecThread *thread, ILObject *delegate, 
ILType *delType)
+ */
+static ILJitType _ILJitSignature_ILJitDelegateGetClosure = 0;
+
+
+/*
  * Define offsetof macro if not present.
  */
 #ifndef offsetof
@@ -2119,6 +2145,15 @@
        args[0] = _IL_JIT_TYPE_VPTR;
        args[1] = _IL_JIT_TYPE_VPTR;
        returnType = _IL_JIT_TYPE_VPTR;
+       if(!(_ILJitSignature_ILStringToAnsi =
+               jit_type_create_signature(IL_JIT_CALLCONV_CDECL, returnType, 
args, 2, 1)))
+       {
+               return 0;
+       }
+       
+       args[0] = _IL_JIT_TYPE_VPTR;
+       args[1] = _IL_JIT_TYPE_VPTR;
+       returnType = _IL_JIT_TYPE_VPTR;
        if(!(_ILJitSignature_ILStringToUTF8 =
                jit_type_create_signature(IL_JIT_CALLCONV_CDECL, returnType, 
args, 2, 1)))
        {
@@ -2134,6 +2169,43 @@
                return 0;
        }
 
+       args[0] = _IL_JIT_TYPE_VPTR;
+       args[1] = _IL_JIT_TYPE_VPTR;
+       returnType = _IL_JIT_TYPE_VPTR;
+       if(!(_ILJitSignature_ILStringToUTF16 =
+               jit_type_create_signature(IL_JIT_CALLCONV_CDECL, returnType, 
args, 2, 1)))
+       {
+               return 0;
+       }
+       
+       args[0] = _IL_JIT_TYPE_VPTR;
+       args[1] = _IL_JIT_TYPE_VPTR;
+       returnType = _IL_JIT_TYPE_VPTR;
+       if(!(_ILJitSignature_ILStringCreateUTF8 =
+               jit_type_create_signature(IL_JIT_CALLCONV_CDECL, returnType, 
args, 2, 1)))
+       {
+               return 0;
+       }
+       
+       args[0] = _IL_JIT_TYPE_VPTR;
+       args[1] = _IL_JIT_TYPE_VPTR;
+       returnType = _IL_JIT_TYPE_VPTR;
+       if(!(_ILJitSignature_ILStringWCreate =
+               jit_type_create_signature(IL_JIT_CALLCONV_CDECL, returnType, 
args, 2, 1)))
+       {
+               return 0;
+       }
+
+       args[0] = _IL_JIT_TYPE_VPTR;
+       args[1] = _IL_JIT_TYPE_VPTR;
+       args[2] = _IL_JIT_TYPE_VPTR;
+       returnType = _IL_JIT_TYPE_VPTR;
+       if(!(_ILJitSignature_ILJitDelegateGetClosure =
+               jit_type_create_signature(IL_JIT_CALLCONV_CDECL, returnType, 
args, 3, 1)))
+       {
+               return 0;
+       }
+
        return 1;
 }
 /*
@@ -2378,7 +2450,7 @@
  */
 static ILJitType _ILJitTypeToStackType(ILJitType type)
 {
-       return jit_type_promote_int(type);;
+       return jit_type_promote_int(type);
 }
 
 /*
@@ -2516,7 +2588,7 @@
        /* otherwise we need the thread as an additional argument. */
        totalParams = numParams + 1;
 #endif
-       returnType = jit_type_get_return(signature);;
+       returnType = jit_type_get_return(signature);
 
 #ifdef IL_JIT_THREAD_IN_SIGNATURE
        if(numParams != (numArgs + 1))

Index: engine/jitc.h
===================================================================
RCS file: /sources/dotgnu-pnet/pnet/engine/jitc.h,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -b -r1.13 -r1.14
--- engine/jitc.h       18 May 2006 19:34:31 -0000      1.13
+++ engine/jitc.h       22 Jul 2006 08:48:32 -0000      1.14
@@ -218,6 +218,13 @@
 void *_ILJitExceptionHandler(int exception_type);
 
 
+/*
+ * Get the closure for a delegate.
+ */
+void *ILJitDelegateGetClosure(ILExecThread *thread,
+                                                         ILObject *delegate,
+                                                         ILType *delType);
+
 #endif  /* IL_USE_JIT */
 
 #endif /* _ENGINE_JITC_H */

Index: engine/jitc_pinvoke.c
===================================================================
RCS file: /sources/dotgnu-pnet/pnet/engine/jitc_pinvoke.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -b -r1.1 -r1.2
--- engine/jitc_pinvoke.c       18 Jun 2006 13:09:36 -0000      1.1
+++ engine/jitc_pinvoke.c       22 Jul 2006 08:48:32 -0000      1.2
@@ -1,5 +1,5 @@
 /*
- * jitc_pinvoke.c - Handle pinvokes and marshaling within the JIT.
+ * jitc_pinvoke.c - Handle marshaling within the JIT.
  *
  * Copyright (C) 2006  Southern Storm Software, Pty Ltd.
  *
@@ -18,32 +18,59 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#define MARSHAL_FIRST_LEVEL_VALUE              0
+#define MARSHAL_ITEM_OF_STRUCTURE              1
+#define MARSHAL_ITEM_OF_ARRAY                  2
+
+
+static int NeedMarshalValue(ILType *type);
+static int NeedMarshalStruct(ILType *structureILType);
+
+static ILJitValue MarshalValue(jit_function_t function, ILJitValue in, ILType 
*type, ILUInt32 current, unsigned int addressKind, jit_nint offset, ILJitValue 
outAddress);
+static ILJitValue MarshalStruct(jit_function_t function, ILJitValue inAddress, 
ILType *structureILType, ILJitValue outAddress, jit_nint offset, unsigned int 
addressKind);
+
+static ILJitValue MarshalReturnValue(jit_function_t function, ILJitValue in, 
ILType *type, unsigned int addressKind, jit_nint offset, ILJitValue outAddress);
+static ILJitValue MarshalReturnStruct(jit_function_t function, ILJitValue 
inAddress, ILType *structureILType, ILJitValue outAddress, jit_nint offset, 
unsigned int addressKind);
+
+static void MarshalByRefValue(jit_function_t function, ILJitValue in, ILType 
*type, ILUInt32 current, unsigned int addressKind, jit_nint offset, ILJitValue 
outAddress);
+static void MarshalByRefStruct(jit_function_t function, ILJitValue inAddress, 
ILType *structureILType, ILJitValue outAddress, jit_nint offset, unsigned int 
addressKind);
+
+void *ILJitDelegateGetClosure(ILExecThread *currentThread, ILObject *del, 
ILType *delType);
+
+static ILJitValue MarshalDelegateValue(jit_function_t function, ILJitValue in, 
ILType *type, ILUInt32 current, unsigned int addressKind, jit_nint offset, 
ILJitValue outAddress, ILExecThread *thread);
+static ILJitValue MarshalDelegateStruct(jit_function_t function, ILJitValue 
inAddress, ILType *structureILType, ILJitValue outAddress, jit_nint offset, 
unsigned int addressKind, ILExecThread *thread);
+
+static ILJitValue MarshalDelegateReturnValue(jit_function_t function, 
ILJitValue in, ILType *type, unsigned int addressKind, jit_nint offset, 
ILJitValue outAddress, ILExecThread *thread);
+static ILJitValue MarshalDelegateReturnStruct(jit_function_t function, 
ILJitValue inAddress, ILType *structureILType, ILJitValue outAddress, jit_nint 
offset, unsigned int addressKind, ILExecThread *thread);
+
+static void MarshalDelegateByRefValue(jit_function_t function, ILJitValue in, 
ILType *type, ILUInt32 current, unsigned int addressKind, jit_nint offset, 
ILJitValue outAddress, ILExecThread *thread);
+static void MarshalDelegateByRefStruct(jit_function_t function, ILJitValue 
inAddress, ILType *structureILType, ILJitValue outAddress, jit_nint offset, 
unsigned int addressKind, ILExecThread *thread);
+
 /*
  * On demand code generator.for functions implemented in IL code.
  */
 static int _ILJitCompilePinvoke(jit_function_t func)
 {
        ILMethod *method = (ILMethod *)jit_function_get_meta(func, 
IL_JIT_META_METHOD);
-       ILPInvoke *pinv = ILPInvokeFind(method);
-       jit_abi_t jitAbi;
 #if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) && 
defined(_IL_JIT_ENABLE_DEBUG)
        ILClass *info = ILMethod_Owner(method);
        ILClassPrivate *classPrivate = (ILClassPrivate *)info->userData;
-       ILJITCoder *jitCoder = (ILJITCoder *)(classPrivate->process->coder);
+       ILJITCoder *jitCoder = (ILJITCoder*)(classPrivate->process->coder);
        char *methodName = _ILJitFunctionGetMethodName(func);
 #endif
        ILJitMethodInfo *jitMethodInfo = (ILJitMethodInfo *)(method->userData);
+       ILType *ilSignature = ILMethod_Signature(method);
+       ILType *type;
        ILJitType signature = jit_function_get_signature(func);
+       ILPInvoke *pinv = ILPInvokeFind(method);
+       jit_abi_t jitAbi;
+       ILUInt32 numParams = jit_type_num_params(signature);
        ILJitType returnType = jit_type_get_return(signature);
-       unsigned int numParams = jit_type_num_params(signature);
-       ILJitType callSignature;
-       ILJitValue returnValue;
-       ILUInt32 current;
-#ifdef IL_JIT_THREAD_IN_SIGNATURE
-       unsigned int totalParams = numParams - 1;
-#else
-       unsigned int totalParams = numParams;
-#endif
+       ILJitValue returnValue = jit_value_create(func, jit_type_void_ptr);
+       unsigned int current;
+       unsigned int typeFlag;
+       ILJitValue newValue;
+       ILType *valueType;
 
 #if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) && 
defined(_IL_JIT_ENABLE_DEBUG)
        if(jitCoder->flags & IL_CODER_FLAG_STATS)
@@ -54,13 +81,11 @@
        }
 #endif
 
-       /* TODO */
        if(!pinv)
        {
                /* The pinvoke record could not be found. */
                return JIT_RESULT_COMPILE_ERROR;
        }
-
        /* determine which calling convention to use. */
        switch(pinv->member.attributes & IL_META_PINVOKE_CALL_CONV_MASK)
        {
@@ -96,44 +121,68 @@
                }
        }
 
-       if(totalParams > 0)
-       {
+
                ILJitType paramType;
-               ILJitType jitParamTypes[totalParams];
-               ILJitValue jitParams[totalParams];
+       ILJitType jitParamTypes[numParams + 1];
+       ILJitValue jitParams[numParams + 1];
+       ILJitValue tempParams[numParams + 1];
                ILUInt32 param = 0;
 
-#ifdef IL_JIT_THREAD_IN_SIGNATURE
                for(current = 1; current < numParams; ++current)
-#else
-               for(current = 0; current < numParams; ++current)
-#endif
                {
+
                        paramType = jit_type_get_param(signature, current);
-                       jitParams[param] = jit_value_get_param(func, current);
+               valueType = ILTypeGetParam(ilSignature, current);
+               valueType = ILTypeGetEnumType(valueType);
+               tempParams[param] = jit_insn_dup(func, 
jit_value_get_param(func, current));
+               jitParams[param] = (ILJitValue)MarshalValue(func, 
tempParams[param], valueType, current, 0, 0, 0);
                        jitParamTypes[param] = paramType;
                        ++param;
                }
-               callSignature = jit_type_create_signature(jitAbi,
+       ILJitType callSignature = jit_type_create_signature(jitAbi,
                                                                                
                  returnType,
                                                                                
                  jitParamTypes,
-                                                                               
                  totalParams, 1);
-
+                                                                  numParams - 
1, 1);
+       if(numParams > 1)
+       {                                                                       
                                           
+               type = ILTypeGetEnumType(ILTypeGetReturn(ilSignature));
                returnValue = jit_insn_call_native(func, 0, 
jitMethodInfo->fnInfo.func,
                                                                                
   callSignature,
-                                                                               
   jitParams, totalParams, 0);
+                                                                jitParams, 
numParams - 1, 0);
+               jit_insn_store(func, returnValue, 
(ILJitValue)MarshalReturnValue(func, jit_insn_dup(func, returnValue), type, 0, 
0, 0));
+               param = 0;
+               for(current = 1; current < numParams; ++current)
+               {
+                       newValue = jit_insn_dup(func, jitParams[param]);
+                       type = ILTypeGetParam(ilSignature, current);
+                       type = ILTypeGetEnumType(type);
+
+                       if(type!=0 && ILType_IsSimpleArray(type))
+                       {
+                               MarshalByRefValue(func, newValue, type, 
current, 0, 0, tempParams[param]);
        }
-       else
+                       else if(type!=0 && ILType_IsComplex(type))
        {
-               callSignature = jit_type_create_signature(jitAbi,
-                                                                               
                  returnType,
-                                                                               
                  0, 0, 1);
+                               typeFlag = ILType_Kind(type);
+                               if(typeFlag==IL_TYPE_COMPLEX_BYREF || typeFlag 
== IL_TYPE_COMPLEX_PTR)
+                               {
+                                       MarshalByRefValue(func, newValue, type,
+                                                                   current, 0,
+                                                                   0, 
tempParams[param]);
+                               }
+                       }
+                       ++param;
+               }
+               jit_insn_return(func, returnValue);
 
-               returnValue = jit_insn_call_native(func, 0, 
jitMethodInfo->fnInfo.func,
+       }
+       else
+       {
+               jit_insn_call_native(func, 0, jitMethodInfo->fnInfo.func,
                                                                                
   callSignature, 0, 0, 0);
+               jit_insn_return(func, 0);
        }
        jit_type_free(callSignature);
-       jit_insn_return(func, returnValue);     
 
 #if !defined(IL_CONFIG_REDUCE_CODE) && !defined(IL_WITHOUT_TOOLS) && 
defined(_IL_JIT_ENABLE_DEBUG)
 #ifdef _IL_JIT_DUMP_FUNCTION
@@ -160,3 +209,2540 @@
        return JIT_RESULT_OK;
 }
 
+static int NeedMarshalValue(ILType *type)
+{
+    type = ILTypeGetEnumType(type);
+    if(ILType_IsPrimitive(type))
+    {
+       switch(ILType_ToElement(type))
+       {
+               case IL_META_ELEMTYPE_VOID:
+               {
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_BOOLEAN:
+               {
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_I1:
+               {
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_U1:
+               {
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_I2:
+               {
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_U2:
+               {
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_CHAR:
+               {
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_I4:
+               {
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_U4:
+               {
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_I8:
+               {
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_U8:
+               {
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_R4:
+               {
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_R8:
+               {
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_I:
+               {
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_U:
+               {
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_TYPEDBYREF:
+               {
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_OBJECT:
+               {       
+                       return 0;
+               }
+               break;
+               default: break;
+       }                       
+    }
+    else if(ILType_IsValueType(type))
+    {  
+           return NeedMarshalStruct(type);
+    }
+    else if(ILTypeIsStringClass(type))
+    {
+           return 1;
+    }
+    else if(ILTypeIsDelegateSubClass(type))
+    {
+           return 1;
+    }
+    else if(ILType_IsClass(type))
+    {
+           return 0;
+    }
+    else if(type !=0 && ILType_IsComplex(type))
+    {
+           
+           switch(ILType_Kind(type))
+           {
+                   case IL_TYPE_COMPLEX_PTR:
+                   case IL_TYPE_COMPLEX_BYREF:
+                   {
+                           return 1;
+                   }
+                   break;
+                   default:
+                   {
+
+                   }
+                   break;
+           }
+    }
+
+    if(ILType_IsSimpleArray(type))
+    {
+           return 1;
+    }
+    else if(ILType_IsArray(type))
+    {
+           return 1;
+    }
+
+    return 1;
+}
+
+static int NeedMarshalStruct(ILType *structureILType)
+{
+       ILClass *classInfo = 
ILClassResolve(ILType_ToValueType(structureILType));
+       ILField *field = 0;
+       ILType *type;
+
+       while((field = (ILField *)ILClassNextMemberByKind
+                       (classInfo, (ILMember *)field, 
IL_META_MEMBERKIND_FIELD)) != 0)
+       {
+               if(!ILField_IsStatic(field))
+               {
+                       type = ILTypeGetEnumType(ILField_Type(field));
+                       if(NeedMarshalValue(type))return 1;
+               }
+       }
+       return 0;
+}
+
+
+static ILJitValue MarshalValue(jit_function_t function, ILJitValue in, ILType 
*type, ILUInt32 current, unsigned int addressKind, jit_nint offset, ILJitValue 
outAddress)
+{
+    ILJitValue outAddressValue = outAddress;
+    ILJitValue temp = jit_value_create(function, _IL_JIT_TYPE_VPTR);
+    ILJitValue ptr, valuePtr;
+    ILType *refType;
+    ILJitValue srcArray = jit_value_create(function, _IL_JIT_TYPE_VPTR);
+    ILJitValue args[3];
+    ILJitValue srcElemSize;
+    ILType *elemType;
+    ILExecThread *thread;
+    ILJitValue newElemSize, newArraySize;
+    ILJitValue newArray = jit_value_create(function, _IL_JIT_TYPE_VPTR);
+    jit_label_t startLoop = jit_label_undefined;
+    jit_label_t endLoop = jit_label_undefined;
+    jit_label_t endLabel = jit_label_undefined;
+    ILJitValue srcElemAddress;
+    ILJitValue newElemAddress;
+    ILJitValue counter;
+    ILJitValue arraySize;
+    ILUInt32 marshalType;
+    char *customName;
+    int customNameLen;
+    char *customCookie;
+    int customCookieLen;
+    ILMethod *method = (ILMethod *)jit_function_get_meta(function, 
IL_JIT_META_METHOD);
+    ILPInvoke *pinv = ILPInvokeFind(method);
+    marshalType = ILPInvokeGetMarshalType(pinv, method, current, &customName, 
&customNameLen,
+                                                       &customCookie,  
&customCookieLen, type);
+    if(marshalType==IL_META_MARSHAL_DIRECT && 
addressKind==MARSHAL_FIRST_LEVEL_VALUE) 
+    {
+       return in;
+    }
+    else if(marshalType==IL_META_MARSHAL_CUSTOM)
+    {
+           fprintf(stderr, "Custom marshaling not yet supported\n");
+           return 0;
+    }
+
+    if(!NeedMarshalValue(type) && addressKind==MARSHAL_FIRST_LEVEL_VALUE)
+    {
+           return in;
+    }    
+    type = ILTypeGetEnumType(type);
+    if(addressKind==MARSHAL_ITEM_OF_ARRAY || addressKind == 
MARSHAL_ITEM_OF_STRUCTURE) outAddressValue = outAddress;
+    else if(addressKind!=MARSHAL_FIRST_LEVEL_VALUE && 
addressKind!=MARSHAL_ITEM_OF_STRUCTURE)
+    {
+           fprintf(stderr, "addressKind has an invalid value of %d\n", 
addressKind);
+           return 0;
+    }
+    if(ILType_IsPrimitive(type))
+    {
+       switch(ILType_ToElement(type))
+       {
+               case IL_META_ELEMTYPE_VOID:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_BOOLEAN:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_BYTE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I1:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_SBYTE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U1:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_BYTE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I2:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_INT16);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U2:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_UINT16);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_CHAR:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_CHAR);                         
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I4:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_INT32);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U4:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_UINT32);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I8:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_INT64);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U8:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_UINT64);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;                    
+               }
+               break;
+               case IL_META_ELEMTYPE_R4:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_SINGLE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_R8:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_DOUBLE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I:
+               {                       
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_NINT);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_NUINT);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;                    
+               }
+               break;
+               case IL_META_ELEMTYPE_TYPEDBYREF:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) temp = in;
+                       else temp = jit_insn_load_relative(function, in, 
offset, _ILJitTypedRef);
+                       ptr = jit_insn_address_of(function, temp);              
        
+                       valuePtr = jit_insn_load_relative(function, 
+                                                               ptr,
+                                                               
offsetof(ILTypedRef, value),
+                                                               
_IL_JIT_TYPE_VPTR);
+                       refType = ILType_Ref(type);
+                       switch(addressKind)
+                       {
+                               case MARSHAL_ITEM_OF_ARRAY:
+                               {
+                                       return 
(ILJitValue)MarshalStruct(function, valuePtr, refType, outAddressValue, offset, 
MARSHAL_ITEM_OF_ARRAY);
+                               }
+                               break;
+                               case MARSHAL_ITEM_OF_STRUCTURE:
+                               {
+                                       return 
(ILJitValue)MarshalStruct(function, valuePtr, refType, outAddressValue, offset, 
MARSHAL_ITEM_OF_STRUCTURE);
+                               }
+                               break;
+                               default:
+                               {
+                                       return 
(ILJitValue)MarshalStruct(function, valuePtr, refType, 0, 0, 
MARSHAL_FIRST_LEVEL_VALUE);
+                               }
+                               break;
+                       }
+               }
+               break;
+               case IL_META_ELEMTYPE_OBJECT:
+               {       
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               default:  break;
+       }                       
+    }
+    else if (ILType_IsValueType(type))
+    {
+           switch(addressKind)
+           {
+                   case MARSHAL_ITEM_OF_STRUCTURE:
+                   case MARSHAL_ITEM_OF_ARRAY:
+                   {
+                           return (ILJitValue)MarshalStruct(function, in, 
type, outAddressValue, offset, MARSHAL_ITEM_OF_ARRAY);
+                   }
+                   break;
+                   default:
+                   {
+                           return (ILJitValue)MarshalStruct(function, 
jit_insn_address_of(function, in), type, 0, 0, MARSHAL_FIRST_LEVEL_VALUE);
+                   }
+                   break;
+           }
+    }
+    else if(ILTypeIsStringClass(type))
+    {
+           args[0] = _ILJitFunctionGetThread(function);
+           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) args[1] = in;
+           else args[1] = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+
+           switch(marshalType)
+           {
+                       case IL_META_MARSHAL_ANSI_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringToAnsi",
+                                                   ILStringToAnsi,
+                                                   
_ILJitSignature_ILStringToAnsi,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+                       case IL_META_MARSHAL_UTF8_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringToUTF8",
+                                                   ILStringToUTF8,
+                                                   
_ILJitSignature_ILStringToUTF8,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+                       case IL_META_MARSHAL_UTF16_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringToUTF16",
+                                                   ILStringToUTF16,
+                                                   
_ILJitSignature_ILStringToUTF16,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+                       default:
+                       {
+                               fprintf(stderr, "Unsupported string char set in 
marshaling\n");
+                               return 0;
+                       };
+           }
+
+           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                   jit_insn_store_relative(function, outAddressValue, offset, 
temp);
+           return temp;
+    }
+
+    else if(type!=0 && ILTypeIsDelegate(type))
+    {
+           temp = jit_insn_dup(function, in);
+           if(addressKind!=MARSHAL_FIRST_LEVEL_VALUE)
+           {
+               temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+           }
+           ILJitValue closure = jit_insn_load_relative(function, temp, 
offsetof(System_Delegate, closure), _IL_JIT_TYPE_VPTR);
+           jit_insn_branch_if(function, jit_insn_to_bool(function, closure), 
&endLabel);
+           args[0] = _ILJitFunctionGetThread(function);
+           args[1] = jit_insn_dup(function, temp);
+           args[2] = jit_value_create_nint_constant(function, 
_IL_JIT_TYPE_VPTR, (jit_nint)type);
+           jit_insn_store(function, closure, jit_insn_call_native(function,
+                                           "ILJitDelegateGetClosure",
+                                           ILJitDelegateGetClosure,
+                                           
_ILJitSignature_ILJitDelegateGetClosure,
+                                           args, 3, JIT_CALL_NOTHROW));
+           jit_insn_label(function, &endLabel);
+           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                   jit_insn_store_relative(function, outAddressValue, offset, 
closure);
+           return closure; 
+    }
+    else if(type!=0 && ILType_IsComplex(type))
+    {
+           switch(ILType_Kind(type))
+           {
+                   case IL_TYPE_COMPLEX_PTR:
+                   {
+                           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return 
in;
+                           temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+                           jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                           return temp;
+                   }
+                   break;
+                   case IL_TYPE_COMPLEX_BYREF:
+                   {
+                           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                                   jit_insn_store(function, srcArray, 
jit_insn_load_relative(function, in, offset, _IL_JIT_TYPE_VPTR));
+                           else jit_insn_store(function, srcArray, in);
+                           elemType = ILType_Ref(type);
+                           if(NeedMarshalValue(elemType))
+                           {
+                                       MarshalValue(function, 
jit_insn_dup(function, srcArray),
+                                                           elemType, 0, 
+                                                           
MARSHAL_ITEM_OF_STRUCTURE,
+                                                           0,
+                                                           
jit_insn_dup(function, srcArray));
+                           }
+                           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY) 
+                               jit_insn_store_relative(function, 
outAddressValue, offset, srcArray);
+                           return srcArray;
+                   }
+                   break;
+                   default: break;
+                   }
+
+                   if(ILType_IsSimpleArray(type))
+                   {
+                           srcArray = in;
+                           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                                   srcArray = jit_insn_load_relative(function, 
srcArray, offset, _IL_JIT_TYPE_VPTR);
+                           elemType = ILType_ElemType(type);
+                           if(!NeedMarshalValue(elemType))
+                           {
+                                   jit_insn_store(function, newArray, 
srcArray);
+                                   if(addressKind==MARSHAL_FIRST_LEVEL_VALUE)
+                                   {
+                                           jit_insn_store(function, newArray, 
jit_insn_add_relative(function,
+                                                                               
newArray,
+                                                                               
(jit_nint)(sizeof(ILUInt32))));
+                                   }
+                                   if(addressKind==MARSHAL_ITEM_OF_STRUCTURE 
|| addressKind==MARSHAL_ITEM_OF_ARRAY)
+                                           jit_insn_store_relative(function, 
outAddressValue, offset, newArray);
+                                   return newArray;
+                           }
+
+                           // The size of a simple array can be known only on 
run-time.
+                           arraySize = jit_insn_load_relative(function, 
srcArray, 0, _IL_JIT_TYPE_UINT32);
+                           thread = ILExecThreadCurrent();
+                           srcElemSize = 
jit_value_create_nint_constant(function,
+                                                                               
_IL_JIT_TYPE_INT32,
+                                                                               
(jit_nint)(ILSizeOfType(thread, elemType)));
+                           newElemSize = 
jit_value_create_nint_constant(function,
+                                                                               
_IL_JIT_TYPE_INT32,
+                                                                               
(jit_nint)(ILSizeOfType(thread, elemType)));
+                           newArraySize = jit_insn_mul(function, arraySize, 
newElemSize);
+                           newArraySize = jit_insn_add_relative(function, 
newArraySize, (jit_nint)sizeof(ILUInt32));
+                           args[0] = newArraySize;
+                           jit_insn_store(function, newArray, 
jit_insn_call_native(function, "_ILMalloc",
+                                                                       
ILGCAlloc,
+                                                                       
_ILJitSignature_malloc,
+                                                                       args, 
1, 0));
+
+                           jit_insn_branch_if(function,
+                                               jit_insn_eq(function, arraySize,
+                                                                       
jit_value_create_nint_constant
+                                                                               
(function, _IL_JIT_TYPE_UINT32, 0)),
+                                                                               
&endLoop);
+                           srcElemAddress = jit_insn_add_relative(function,
+                                                                       
srcArray,
+                                                                       
(jit_nint)(sizeof(ILUInt32)));
+                           newElemAddress = jit_insn_dup(function, newArray);
+                           counter = arraySize;
+                           jit_insn_label(function, &startLoop);
+                           jit_insn_store(function, counter, 
jit_insn_sub(function, counter,
+                                                                               
        jit_value_create_nint_constant(function,
+                                                                               
        _IL_JIT_TYPE_INT32,
+                                                                               
        1)));
+                           MarshalValue(function, jit_insn_dup(function, 
srcElemAddress),
+                                                       elemType, 0,
+                                                       MARSHAL_ITEM_OF_ARRAY,
+                                                       0,
+                                                       jit_insn_dup(function, 
newElemAddress));
+                           jit_insn_store(function, srcElemAddress,
+                                                           
jit_insn_add(function,
+                                                           srcElemAddress, 
srcElemSize));
+                           jit_insn_store(function, newElemAddress,
+                                                       jit_insn_add(function,
+                                                       newElemAddress, 
newElemSize));
+                           jit_insn_branch_if(function,
+                                               jit_insn_to_bool(function, 
counter),
+                                               &(startLoop));
+                           jit_insn_label(function, &endLoop);
+                           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                                       jit_insn_store_relative(function, 
outAddressValue, offset, newArray);
+                           return newArray;
+                   }
+                   else if (ILType_IsArray(type))
+                   {
+                           fprintf(stderr, "Multidimential arrays are not 
supported for marshaling\n");
+                           return 0;
+                   }
+    }
+
+    if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+    temp = jit_insn_load_relative(function, in, offset, _IL_JIT_TYPE_VPTR);
+    jit_insn_store_relative(function, outAddressValue, offset, temp);
+    return temp;
+}
+
+static ILJitValue MarshalStruct(jit_function_t function, ILJitValue inAddress, 
ILType *structureILType, ILJitValue outAddress, jit_nint offset, unsigned int 
addressKind)
+{
+        ILClass *classInfo = 
ILClassResolve(ILType_ToValueType(structureILType));
+       ILExecThread *thread = ILExecThreadCurrent();
+        unsigned int structSize = ILSizeOfType(thread, structureILType);
+       ILField *field = 0;
+       ILType *type;
+
+       switch(addressKind)
+       {
+               case MARSHAL_FIRST_LEVEL_VALUE:
+               {
+                       ILJitValue sizeValue = 
jit_value_create_nint_constant(function, _IL_JIT_TYPE_UINT32, structSize);
+                       outAddress = jit_insn_call_native(function, "_ILMalloc",
+                                                                   ILGCAlloc,
+                                                                   
_ILJitSignature_malloc,
+                                                                   &sizeValue, 
1, 0);
+               }
+               break;
+               case MARSHAL_ITEM_OF_STRUCTURE:
+               case MARSHAL_ITEM_OF_ARRAY:
+               {           
+                       
+               }
+               break;
+               default:
+               {
+                       fprintf(stderr, "addressKind is an invalid value of 
%d\n", addressKind);
+                       return 0;
+               }
+               break;
+       }
+
+       while((field = (ILField *)ILClassNextMemberByKind
+                       (classInfo, (ILMember *)field, 
IL_META_MEMBERKIND_FIELD)) != 0)
+       {
+               if(!ILField_IsStatic(field))
+               {
+                       type = ILTypeGetEnumType(ILField_Type(field));
+                       switch(addressKind)
+                       {
+                               case MARSHAL_FIRST_LEVEL_VALUE:
+                               {
+                                       MarshalValue(function, inAddress, type, 
0, MARSHAL_ITEM_OF_STRUCTURE, field->offset + offset, outAddress);
+                               }
+                               break;
+                               case MARSHAL_ITEM_OF_STRUCTURE:
+                               {
+                                       MarshalValue(function, inAddress, type, 
0, MARSHAL_ITEM_OF_STRUCTURE, field->offset + offset, outAddress);
+                               }
+                               break;
+                               default:
+                               {
+                                       MarshalValue(function, inAddress, type, 
0, MARSHAL_ITEM_OF_ARRAY, field->offset + offset, outAddress);
+                               }
+                               break;
+                       }
+               }
+       }
+       
+       return outAddress;
+}
+
+
+static ILJitValue MarshalReturnValue(jit_function_t function, ILJitValue in, 
ILType *type, unsigned int addressKind, jit_nint offset, ILJitValue outAddress)
+{
+    ILJitValue retValue;    
+    ILJitValue outAddressValue = outAddress;
+    ILJitValue temp = jit_value_create(function, _IL_JIT_TYPE_VPTR);
+    ILJitValue args[3];
+    ILJitValue srcArray = jit_value_create(function, _IL_JIT_TYPE_VPTR);
+    ILUInt32 marshalType;
+    char *customName;
+    int customNameLen;
+    char *customCookie;
+    int customCookieLen;
+    ILMethod *method = (ILMethod *)jit_function_get_meta(function, 
IL_JIT_META_METHOD);
+    ILPInvoke *pinv = ILPInvokeFind(method);
+    marshalType = ILPInvokeGetMarshalType(pinv, method, 1, &customName, 
&customNameLen,
+                                                       &customCookie,  
&customCookieLen, type);
+    if(marshalType == IL_META_MARSHAL_DIRECT && 
addressKind==MARSHAL_FIRST_LEVEL_VALUE)
+    {
+           return in;
+    }
+    else if(marshalType == IL_META_MARSHAL_CUSTOM)
+    {
+           fprintf(stderr, "custom marshaling of return value is not 
supported\n");
+           return 0;
+    }
+    type = ILTypeGetEnumType(type);
+
+    if(addressKind==MARSHAL_FIRST_LEVEL_VALUE && !NeedMarshalValue(type))
+    {
+           return in;
+    }
+
+    switch(addressKind)
+    {    
+           case MARSHAL_FIRST_LEVEL_VALUE:
+           case MARSHAL_ITEM_OF_STRUCTURE:
+           case MARSHAL_ITEM_OF_ARRAY:
+           {
+           }
+           break;
+           default:
+           {
+                   fprintf(stderr, "addressKind has an invalid %d value\n", 
addressKind);
+                   return 0;
+           }
+           break;
+    }
+
+    if(ILType_IsPrimitive(type))
+    {
+       switch(ILType_ToElement(type))
+       {
+               case IL_META_ELEMTYPE_VOID:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_BOOLEAN:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_BYTE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I1:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_SBYTE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U1:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_BYTE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I2:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_INT16);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U2:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_UINT16);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_CHAR:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_CHAR);                         
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I4:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_INT32);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U4:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_UINT32);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I8:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_INT64);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U8:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_UINT64);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_R4:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_SINGLE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_R8:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_DOUBLE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_NINT);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_NUINT);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_TYPEDBYREF:
+               {       
+                       fprintf(stderr, "Marshaling of TypedByRef as a return 
value is not supported\n");
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_OBJECT:
+               {       
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               default: break;
+       }                       
+    }
+    else if(ILType_IsValueType(type))
+    {
+           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return 
(ILJitValue)MarshalReturnStruct(function, jit_insn_address_of(function, in), 
type, 0, 0, MARSHAL_FIRST_LEVEL_VALUE);
+           temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+           retValue = (ILJitValue)MarshalReturnStruct(function, temp, type, 
outAddressValue, offset, MARSHAL_ITEM_OF_STRUCTURE);
+           jit_insn_store_relative(function, outAddressValue, offset, 
retValue);
+           return retValue;
+    }
+    else if(ILTypeIsStringClass(type))
+    {
+           args[0] = _ILJitFunctionGetThread(function);
+           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) args[1] = in;
+           else args[1] = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+           switch(marshalType)
+           {
+                       case IL_META_MARSHAL_ANSI_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringCreate",
+                                                   ILStringCreate,
+                                                   
_ILJitSignature_ILStringCreate,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+                       case IL_META_MARSHAL_UTF8_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringCreateUTF8",
+                                                   ILStringCreateUTF8,
+                                                   
_ILJitSignature_ILStringCreateUTF8,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+                       case IL_META_MARSHAL_UTF16_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringWCreate",
+                                                   ILStringWCreate,
+                                                   
_ILJitSignature_ILStringWCreate,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+           }
+           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                   jit_insn_store_relative(function, outAddressValue, offset, 
temp);
+           return temp;
+    }
+    else if(ILTypeIsDelegateSubClass(type))
+    {
+           fprintf(stderr, "Marshaling of a delegate as a return value is not 
supported\n");
+           return 0;
+    }
+    else if(ILType_IsClass(type))
+    {
+           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+           temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+           jit_insn_store_relative(function, outAddressValue, offset, temp);
+           retValue = temp;
+           return retValue;
+    }
+    else if(type !=0 && ILType_IsComplex(type))
+    {
+           switch(ILType_Kind(type))
+           {
+                   case IL_TYPE_COMPLEX_PTR:
+                   {
+                           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE)return in;
+                           temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+                           jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                           return temp;
+                   };
+                   break;
+                   case IL_TYPE_COMPLEX_BYREF:
+                   {
+                           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                                   jit_insn_store(function, srcArray, 
jit_insn_load_relative(function, in, offset, _IL_JIT_TYPE_VPTR));
+                           else jit_insn_store(function, srcArray, in);
+                           ILType *elemType = ILType_Ref(type);
+                           if(NeedMarshalValue(elemType))
+                           {
+                                   MarshalReturnValue(function, 
jit_insn_dup(function, srcArray),
+                                                                   elemType,
+                                                                   
MARSHAL_ITEM_OF_STRUCTURE,
+                                                                   0,
+                                                                   
jit_insn_dup(function, srcArray));
+                           }
+                           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                                   jit_insn_store_relative(function, 
outAddressValue, offset, srcArray);
+                           return srcArray;
+                   }
+                   break;
+                   default: break;
+           }
+
+           if(ILType_IsSimpleArray(type))
+           {
+                       // The size of a simple array can be known only on 
run-time 
+                       // and we cannot use the same return memory as it is 
allocated in C code.
+                       fprintf(stderr, "Simple arrays not supported for 
marshaling as a return value");
+                       return 0;
+                       
+           }
+           else if(ILType_IsArray(type))
+           {
+                   fprintf(stderr, "Multidimential arrays are not supported 
for marshaling as a return value\n");
+                   return 0;
+           }
+
+    }
+
+    // Do something smart.
+    if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+    temp = jit_insn_load_relative(function, in, offset, _IL_JIT_TYPE_VPTR);
+    jit_insn_store_relative(function, outAddressValue, offset, temp);
+    return temp;
+}
+
+static ILJitValue MarshalReturnStruct(jit_function_t function, ILJitValue 
inAddress, ILType *structureILType, ILJitValue outAddress, jit_nint offset, 
unsigned int addressKind)
+{
+    ILClass *classInfo = ILClassResolve(ILType_ToValueType(structureILType));
+    ILExecThread *thread = ILExecThreadCurrent();
+    unsigned int structSize = ILSizeOfType(thread, structureILType);
+    ILField *field = 0;
+    ILJitValue newStruct = 0;
+    ILType *type;
+    ILJitType structType;      
+
+    if(addressKind==MARSHAL_FIRST_LEVEL_VALUE)
+    {
+           structType = jit_type_create_struct(0, 0, 0);
+           jit_type_set_size_and_alignment(structType, structSize, 0);
+           newStruct = jit_value_create(function, structType);
+           outAddress = jit_insn_address_of(function, newStruct);
+    }
+
+    while((field = (ILField *)ILClassNextMemberByKind
+               (classInfo, (ILMember *)field, IL_META_MEMBERKIND_FIELD)) != 0)
+    {
+           if(!ILField_IsStatic(field))
+           {
+                   type = ILTypeGetEnumType(ILField_Type(field));
+                   MarshalReturnValue(function, inAddress, type, 
MARSHAL_ITEM_OF_STRUCTURE, field->offset, outAddress);
+           }
+    }
+    return jit_insn_dup(function, newStruct);
+}
+
+static void MarshalByRefValue(jit_function_t function, ILJitValue in, ILType 
*type, ILUInt32 current, unsigned int addressKind, jit_nint offset, ILJitValue 
outAddress)
+{
+    ILJitValue outAddressValue = outAddress;
+    ILJitValue temp = jit_value_create(function, _IL_JIT_TYPE_VPTR);
+    ILJitValue args[3];
+    ILJitValue srcArray = jit_value_create(function, _IL_JIT_TYPE_VPTR);
+    ILJitValue srcElemSize;
+    ILType *elemType;
+    ILExecThread *thread;
+    ILJitValue newElemSize;
+    ILJitValue newArray;
+    jit_label_t startLoop = jit_label_undefined;
+    jit_label_t endLoop = jit_label_undefined;
+    ILJitValue srcElemAddress;
+    ILJitValue newElemAddress;
+    ILJitValue counter;
+    ILJitValue arraySize;    
+    ILUInt32 marshalType;
+    char *customName;
+    int customNameLen;
+    char *customCookie;
+    int customCookieLen;
+    ILMethod *method = (ILMethod *)jit_function_get_meta(function, 
IL_JIT_META_METHOD);
+    ILPInvoke *pinv = ILPInvokeFind(method);
+    marshalType = ILPInvokeGetMarshalType(pinv, method, current, &customName, 
&customNameLen,
+                                                       &customCookie,  
&customCookieLen, type);
+       
+    if(marshalType == IL_META_MARSHAL_DIRECT && 
addressKind==MARSHAL_FIRST_LEVEL_VALUE)
+    {
+           return;
+    }
+    type = ILTypeGetEnumType(type);
+
+    if(!NeedMarshalValue(type)) return;
+
+    switch(addressKind)
+    {    
+           case MARSHAL_FIRST_LEVEL_VALUE:
+           case MARSHAL_ITEM_OF_STRUCTURE:
+           case MARSHAL_ITEM_OF_ARRAY:
+           {
+                   outAddressValue = outAddress;
+           }
+           break;
+           default:
+           {
+                   fprintf(stderr, "addressKind has an invalid %d value\n", 
addressKind);
+                   return;
+           }
+           break;
+    }
+
+    if(ILType_IsPrimitive(type))
+    {
+       switch(ILType_ToElement(type))
+       {
+               case IL_META_ELEMTYPE_VOID:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_BOOLEAN:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_I1:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_U1:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_I2:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_U2:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_CHAR:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_I4:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_U4:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_I8:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_U8:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_R4:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_R8:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_I:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_U:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_TYPEDBYREF:
+               {       
+                       fprintf(stderr, "Marshaling of TypedByRef as a byref is 
not supported\n");
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_OBJECT:
+               {       
+                       return;
+               }
+               break;
+               default: break;
+       }                       
+    }
+    else if(ILType_IsValueType(type))
+    {  
+           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE)
+           {
+                   MarshalByRefStruct(function, jit_insn_address_of(function, 
in), type, jit_insn_address_of(function, in), 0, MARSHAL_ITEM_OF_STRUCTURE);
+                   return;
+           }
+           temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+           MarshalByRefStruct(function, temp, type, temp, offset, 
MARSHAL_ITEM_OF_STRUCTURE);
+           return;
+    }
+    else if(ILTypeIsStringClass(type))
+    {     
+           args[0] = _ILJitFunctionGetThread(function);
+           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) args[1] = in;
+           else args[1] = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+           switch(marshalType)
+           {
+                       case IL_META_MARSHAL_ANSI_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringCreate",
+                                                   ILStringCreate,
+                                                   
_ILJitSignature_ILStringCreate,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+                       case IL_META_MARSHAL_UTF8_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringCreateUTF8",
+                                                   ILStringCreateUTF8,
+                                                   
_ILJitSignature_ILStringCreateUTF8,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+                       case IL_META_MARSHAL_UTF16_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringWCreate",
+                                                   ILStringWCreate,
+                                                   
_ILJitSignature_ILStringWCreate,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+           }
+           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                   jit_insn_store_relative(function, in, offset, temp);
+           return;
+    }
+    else if(ILTypeIsDelegate(type))
+    {
+           return;
+    }
+    else if(ILType_IsClass(type))
+    {
+           return;
+    }
+    else if(type !=0 && ILType_IsComplex(type))
+    {
+           switch(ILType_Kind(type))
+           {
+                   case IL_TYPE_COMPLEX_PTR:
+                   {
+                           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE)return;
+                           temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+                           jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                           return;
+                   };
+                   break;
+                   case IL_TYPE_COMPLEX_BYREF:
+                   {
+                           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                           {
+                                   jit_insn_store(function, srcArray, 
jit_insn_load_relative(function, in, offset, _IL_JIT_TYPE_VPTR));
+                           }
+                           else jit_insn_store(function, srcArray, in);
+                           ILType *elemType = ILType_Ref(type);
+                           if(NeedMarshalValue(elemType))
+                           {
+                                   if(addressKind==MARSHAL_ITEM_OF_STRUCTURE 
|| addressKind==MARSHAL_ITEM_OF_ARRAY)
+                                   {
+                                   
+                                           MarshalByRefValue(function, 
jit_insn_dup(function, srcArray),
+                                                                               
    elemType, current,
+                                                                               
    MARSHAL_ITEM_OF_STRUCTURE,
+                                                                               
    0,
+                                                                               
    jit_insn_load_relative(function, outAddressValue, offset, 
_IL_JIT_TYPE_VPTR));
+                                   }
+                                   else MarshalByRefValue(function, 
jit_insn_dup(function, srcArray),
+                                                                               
    elemType, current,
+                                                                               
    MARSHAL_ITEM_OF_STRUCTURE,
+                                                                               
    0,
+                                                                               
    srcArray);
+                           }
+                           return;
+                   }
+                   break;
+                   default: break;
+           }
+
+           if(ILType_IsSimpleArray(type))
+           {
+                           srcArray = in;
+                           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                                   srcArray = jit_insn_load_relative(function, 
srcArray, offset, _IL_JIT_TYPE_VPTR);
+                           elemType = ILType_ElemType(type);
+
+                           if(!NeedMarshalValue(elemType))
+                           {
+                                   return;
+                           }
+
+                           // The size of a simple array can be known only on 
run-time.
+                           arraySize = jit_insn_load_relative(function, 
outAddressValue, 0, _IL_JIT_TYPE_UINT32);
+                           thread = ILExecThreadCurrent();
+                           srcElemSize = 
jit_value_create_nint_constant(function,
+                                                                               
_IL_JIT_TYPE_INT32,
+                                                                               
(jit_nint)(ILSizeOfType(thread, elemType)));
+                           newElemSize = 
jit_value_create_nint_constant(function,
+                                                                               
_IL_JIT_TYPE_INT32,
+                                                                               
(jit_nint)(ILSizeOfType(thread, elemType)));
+
+                           newArray = jit_insn_add_relative(function, 
outAddressValue, (jit_nint)(sizeof(ILUInt32)));
+                           jit_insn_branch_if(function,
+                                               jit_insn_eq(function, arraySize,
+                                                                       
jit_value_create_nint_constant
+                                                                               
(function, _IL_JIT_TYPE_UINT32, 0)),
+                                                                               
&endLoop);
+                           srcElemAddress = jit_insn_dup(function, srcArray);
+                           newElemAddress = jit_insn_dup(function, newArray);
+                           counter = arraySize;
+                           jit_insn_label(function, &startLoop);
+                           jit_insn_store(function, counter, 
jit_insn_sub(function, counter,
+                                                                               
        jit_value_create_nint_constant(function,
+                                                                               
        _IL_JIT_TYPE_INT32,
+                                                                               
        1)));
+                           MarshalByRefValue(function, srcElemAddress,
+                                                               elemType, 
current,
+                                                               
MARSHAL_ITEM_OF_ARRAY,
+                                                               0,
+                                                               newElemAddress);
+                           jit_insn_store(function, srcElemAddress,
+                                                           
jit_insn_add(function,
+                                                           srcElemAddress, 
srcElemSize));
+                           jit_insn_store(function, newElemAddress,
+                                                       jit_insn_add(function,
+                                                       newElemAddress, 
newElemSize));
+                           jit_insn_branch_if(function,
+                                               jit_insn_to_bool(function, 
counter),
+                                               &(startLoop));
+                           jit_insn_label(function, &endLoop);
+                           return;
+           }
+           else if(ILType_IsArray(type))
+           {
+                   fprintf(stderr, "Multidimential arrays are not supported 
for marshaling as a return value\n");
+                   return;
+           }
+
+    }
+    // Should not reach here but, make the compiler happy.
+    return;
+}
+
+static void MarshalByRefStruct(jit_function_t function, ILJitValue inAddress, 
ILType *structureILType, ILJitValue outAddress, jit_nint offset, unsigned int 
addressKind)
+{
+    ILClass *classInfo = ILClassResolve(ILType_ToValueType(structureILType));
+    ILField *field = 0;
+    ILType *type;
+
+    while((field = (ILField *)ILClassNextMemberByKind
+               (classInfo, (ILMember *)field, IL_META_MEMBERKIND_FIELD)) != 0)
+    {
+           if(!ILField_IsStatic(field))
+           {
+                   type = ILTypeGetEnumType(ILField_Type(field));
+                   MarshalByRefValue(function, inAddress, type, 1, 
MARSHAL_ITEM_OF_STRUCTURE, field->offset + offset, outAddress);
+           }
+    }
+    return;
+}
+
+
+
+void *ILJitDelegateGetClosure(ILExecThread *currentThread, ILObject *del, 
ILType *delType)
+{
+       ILType *invokeSignature = 
ILMethod_Signature(((System_Delegate*)del)->methodInfo);
+       int paramCount = ILTypeNumParams(invokeSignature);
+       ILType *returnILType = ILTypeGetReturn(invokeSignature);
+       ILJitType returnType = _ILJitGetReturnType(returnILType, 
ILExecThreadGetProcess(currentThread));
+       ILJitType jitParamTypes[paramCount];
+       ILJitType jitInvokeTypes[paramCount + 2];
+       ILJitValue jitParams[paramCount + 2];
+       int current;
+       ILJitType newSignature;
+       ILType *valueType;      
+       ILJitType delInvokeSignature;
+       ILJitFunction function;
+       ILMethod *method;
+       ILClass *info;
+       ILClassPrivate *classPrivate;
+       ILJITCoder *jitCoder;
+       ILJitFunction delFunction;
+       ILJitValue returnValue = 0;
+       ILJitValue tempParams[paramCount + 2];
+       unsigned int typeFlag;
+       ILType *type;
+       ILJitValue newValue;
+       for(current = 0; current < paramCount; ++current)
+       {
+               valueType = ILTypeGetParam(invokeSignature, current + 1);
+               jitParamTypes[current] = _ILJitGetArgType(valueType, 
ILExecThreadGetProcess(currentThread));
+               jitInvokeTypes[current + 2] = jitParamTypes[current];
+       }
+       newSignature = jit_type_create_signature(jit_abi_cdecl,
+                                                   returnType,
+                                                   jitParamTypes,
+                                                   paramCount, 1);
+       jitInvokeTypes[0] = jit_type_void_ptr;
+       jitInvokeTypes[1] = jit_type_void_ptr;
+       delInvokeSignature = jit_type_create_signature(jit_abi_cdecl,
+                                                       returnType,
+                                                       jitInvokeTypes,
+                                                       paramCount + 2, 1);
+       method = ILTypeGetDelegateMethod(delType);
+       info = ILMethod_Owner(method);
+       classPrivate = (ILClassPrivate *)info->userData;
+       jitCoder = (ILJITCoder *)(classPrivate->process->coder);
+
+       function = jit_function_create(jitCoder->context, newSignature);
+       delFunction = ILJitFunctionFromILMethod(method);
+
+       jit_function_set_meta(function, IL_JIT_META_METHOD, method, 0, 0);
+
+       for(current = 0; current < paramCount; ++current)
+       {
+               tempParams[current] = jit_value_get_param(function, current);
+               jitParams[current + 2] = 
(ILJitValue)MarshalDelegateValue(function, jit_value_get_param(function, 
current), ILTypeGetParam(invokeSignature, current + 1), current + 1, 0, 0, 0, 
currentThread);
+       }
+
+       jitParams[0] = jit_value_create_nint_constant(function, 
jit_type_void_ptr, (jit_nint)currentThread);
+       jitParams[1] = jit_value_create_nint_constant(function, 
jit_type_void_ptr, (jit_nint)del);
+       if(returnType==jit_type_void) jit_insn_call(function, 
"callDelegatePinvokeMethod", delFunction, delInvokeSignature, jitParams, 
paramCount + 2, JIT_CALL_NOTHROW);
+       else
+       {
+               returnValue = jit_insn_call(function, 
"callDelegatePinvokeMethod", delFunction, delInvokeSignature, jitParams, 
paramCount + 2, JIT_CALL_NOTHROW);
+               returnValue = (ILJitValue)MarshalDelegateReturnValue(function, 
returnValue, returnILType, 0, 0, 0, currentThread);
+       }
+       for(current = 0; current < paramCount; ++current)
+       {
+               newValue = jitParams[current + 2];
+               type = ILTypeGetParam(invokeSignature, current + 1);
+               type = ILTypeGetEnumType(type);
+
+               if(type!=0 && ILType_IsSimpleArray(type))
+               {
+                       MarshalDelegateByRefValue(function, newValue, type, 
current + 1, 0, 0, tempParams[current], currentThread);
+               }
+               else if(type!=0 && ILType_IsComplex(type))
+               {
+                       typeFlag = ILType_Kind(type);
+                       if(typeFlag==IL_TYPE_COMPLEX_BYREF || 
typeFlag==IL_TYPE_COMPLEX_PTR)
+                       {
+                               MarshalDelegateByRefValue(function, newValue, 
type, current + 1, 0, 0, tempParams[current], currentThread);
+                       }
+               }
+       }
+       if(returnType==jit_type_void)jit_insn_return(function, 0);
+       else jit_insn_return(function, returnValue);
+       jit_function_compile(function);
+       ((System_Delegate*)del)->closure = jit_function_to_closure(function);
+       return ((System_Delegate*)del)->closure;
+}
+
+
+static ILJitValue MarshalDelegateValue(jit_function_t function, ILJitValue in, 
ILType *type, ILUInt32 current, unsigned int addressKind, jit_nint offset, 
ILJitValue outAddress, ILExecThread *thread)
+{
+    ILJitValue retValue;
+    ILJitValue outAddressValue = outAddress;
+    ILJitValue temp = jit_value_create(function, _IL_JIT_TYPE_VPTR);
+    ILJitValue args[3];
+    ILJitValue srcArray = jit_value_create(function, _IL_JIT_TYPE_VPTR);
+    ILJitValue srcElemSize;
+    ILType *elemType;
+    ILJitValue newElemSize, newArraySize;
+    ILJitValue newArray;
+    jit_label_t startLoop = jit_label_undefined;
+    jit_label_t endLoop = jit_label_undefined;
+    ILJitValue srcElemAddress;
+    ILJitValue newElemAddress;
+    ILJitValue counter;
+    ILJitValue arraySize;    
+    ILUInt32 marshalType;
+    char *customName;
+    int customNameLen;
+    char *customCookie;
+    int customCookieLen;
+    ILMethod *method = (ILMethod *)jit_function_get_meta(function, 
IL_JIT_META_METHOD);
+    ILPInvoke *pinv = ILPInvokeFind(method);
+    marshalType = ILPInvokeGetMarshalType(pinv, method, current, &customName, 
&customNameLen,
+                                                       &customCookie,  
&customCookieLen, type);
+    if(marshalType == IL_META_MARSHAL_DIRECT && 
addressKind==MARSHAL_FIRST_LEVEL_VALUE)
+    {
+           return in;
+    }
+    else if(marshalType == IL_META_MARSHAL_CUSTOM)
+    {
+           fprintf(stderr, "Custom marshaling not supported in delegate 
value\n");
+           return 0;
+    }
+    type = ILTypeGetEnumType(type);
+
+    switch(addressKind)
+    {    
+           case MARSHAL_FIRST_LEVEL_VALUE:
+           case MARSHAL_ITEM_OF_STRUCTURE:
+           case MARSHAL_ITEM_OF_ARRAY:
+           {
+                   outAddressValue = outAddress;
+           }
+           break;
+           default:
+           {
+                   fprintf(stderr, "addressKind has an invalid %d value\n", 
addressKind);
+                   return 0;
+           }
+           break;
+    }
+
+    if(ILType_IsPrimitive(type))
+    {
+       switch(ILType_ToElement(type))
+       {
+               case IL_META_ELEMTYPE_VOID:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_BOOLEAN:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_BYTE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I1:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_SBYTE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U1:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_BYTE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I2:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_INT16);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U2:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_UINT16);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_CHAR:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_CHAR);                         
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I4:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_INT32);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U4:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_UINT32);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I8:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_INT64);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U8:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_UINT64);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_R4:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_SINGLE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_R8:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_DOUBLE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_NINT);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_NUINT);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_TYPEDBYREF:
+               {       
+                       fprintf(stderr, "Marshaling of TypedByRef as a value is 
not supported");
+                       return 0;
+               }
+               break;
+               case IL_META_ELEMTYPE_OBJECT:
+               {       
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               default: break;
+       }                       
+    }
+    else if(ILType_IsValueType(type))
+    {  
+           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return 
(ILJitValue)MarshalDelegateStruct(function, jit_insn_address_of(function, in), 
type, 0, 0, MARSHAL_FIRST_LEVEL_VALUE, thread);
+           retValue = (ILJitValue)MarshalDelegateStruct(function, in, type, 
outAddressValue, offset, MARSHAL_ITEM_OF_STRUCTURE, thread);
+           jit_insn_store_relative(function, outAddressValue, offset, 
retValue);
+           return retValue;
+    }
+    else if(ILTypeIsStringClass(type))
+    {
+           args[0] = jit_value_create_nint_constant(function, 
_IL_JIT_TYPE_VPTR, (jit_nint)thread);
+           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) args[1] = in;
+           else args[1] = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+           switch(marshalType)
+           {
+                       case IL_META_MARSHAL_ANSI_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringCreate",
+                                                   ILStringCreate,
+                                                   
_ILJitSignature_ILStringCreate,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+                       case IL_META_MARSHAL_UTF8_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringCreateUTF8",
+                                                   ILStringCreateUTF8,
+                                                   
_ILJitSignature_ILStringCreateUTF8,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+                       case IL_META_MARSHAL_UTF16_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringWCreate",
+                                                   ILStringWCreate,
+                                                   
_ILJitSignature_ILStringWCreate,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+           }
+           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                   jit_insn_store_relative(function, outAddressValue, offset, 
temp);
+           return temp;
+    }
+    else if(ILTypeIsDelegateSubClass(type))
+    {
+           fprintf(stderr, "Marshaling in a delegate of a delegate as a value 
is not supported\n");
+           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+           temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+           jit_insn_store_relative(function, outAddressValue, offset, temp);
+           return temp;
+    }
+    else if(ILType_IsClass(type))
+    {
+           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+           temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+           jit_insn_store_relative(function, outAddressValue, offset, temp);
+           retValue = temp;
+           return retValue;
+    }
+    else if(type !=0 && ILType_IsComplex(type))
+    {
+           switch(ILType_Kind(type))
+           {
+                   case IL_TYPE_COMPLEX_PTR:
+                   {
+                           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE)return in;
+                           temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+                           jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                           return temp;
+                   };
+                   break;
+                   case IL_TYPE_COMPLEX_BYREF:
+                   {
+                           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                                   jit_insn_store(function, srcArray, 
jit_insn_load_relative(function, in, offset, _IL_JIT_TYPE_VPTR));
+                           else jit_insn_store(function, srcArray, in);
+                           ILType *elemType = ILType_Ref(type);
+                           if(NeedMarshalValue(elemType))
+                           {
+                                   jit_insn_store(function, temp, 
MarshalDelegateStruct(function, jit_insn_dup(function, srcArray),
+                                                                           
elemType,
+                                                                           0,
+                                                                           0,
+                                                                           
MARSHAL_FIRST_LEVEL_VALUE,
+                                                                           
thread));
+                           }
+                           else jit_insn_store(function, temp, srcArray);
+                           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                                   jit_insn_store_relative(function, 
outAddressValue, offset, srcArray);
+                           return srcArray;
+                   }
+                   break;
+                   case IL_TYPE_COMPLEX_PINNED:
+                   {
+                           fprintf(stderr, "Marshaling in a delegate a 
COMPLEX_PINNED type is not yet supported\n");
+                           return 0;
+                   }
+                   break;
+                   default: break;
+           }
+
+           if(ILType_IsSimpleArray(type))
+           {
+                           srcArray = in;
+                           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                                   srcArray = jit_insn_load_relative(function, 
srcArray, offset, _IL_JIT_TYPE_VPTR);
+                           elemType = ILType_ElemType(type);
+
+                           // The size of a simple array can be known only on 
run-time.
+                           arraySize = jit_insn_load_relative(function, 
srcArray, 0, _IL_JIT_TYPE_UINT32);
+                           srcElemSize = 
jit_value_create_nint_constant(function,
+                                                                               
_IL_JIT_TYPE_INT32,
+                                                                               
(jit_nint)(ILSizeOfType(thread, elemType)));
+                           newElemSize = 
jit_value_create_nint_constant(function,
+                                                                               
_IL_JIT_TYPE_INT32,
+                                                                               
(jit_nint)(ILSizeOfType(thread, elemType)));
+                           newArraySize = jit_insn_mul(function, arraySize, 
newElemSize);
+                           newArraySize = jit_insn_add_relative(function, 
newArraySize, (jit_nint)(sizeof(ILUInt32)));
+                           args[0] = newArraySize;
+                           newArray = jit_insn_call_native(function, 
"_ILMalloc",
+                                                                       
ILGCAlloc,
+                                                                       
_ILJitSignature_malloc,
+                                                                       args, 
1, 0);
+                           jit_insn_store_relative(function, newArray, 0, 
arraySize);
+                           newArray = jit_insn_add_relative(function, 
newArray, (jit_nint)(sizeof(ILUInt32)));
+                           jit_insn_branch_if(function,
+                                               jit_insn_eq(function, arraySize,
+                                                                       
jit_value_create_nint_constant
+                                                                               
(function, _IL_JIT_TYPE_UINT32, 0)),
+                                                                               
&endLoop);
+                           srcElemAddress = jit_insn_add(function,
+                                                               srcArray,
+                                                               
jit_value_create_nint_constant(function,
+                                                                               
                _IL_JIT_TYPE_INT32,
+                                                                               
                (jit_nint)(sizeof(ILUInt32))));
+                           newElemAddress = jit_insn_dup(function, newArray);
+                           counter = arraySize;
+                           jit_insn_label(function, &startLoop);
+                           jit_insn_store(function, counter, 
jit_insn_sub(function, counter,
+                                                                               
        jit_value_create_nint_constant(function,
+                                                                               
        _IL_JIT_TYPE_INT32,
+                                                                               
        1)));
+                           MarshalDelegateValue(function, srcElemAddress,
+                                                       elemType, current,
+                                                       MARSHAL_ITEM_OF_ARRAY,
+                                                       0,
+                                                       newElemAddress,
+                                                       thread);
+                           jit_insn_store(function, srcElemAddress,
+                                                           
jit_insn_add(function,
+                                                           srcElemAddress, 
srcElemSize));
+                           jit_insn_store(function, newElemAddress,
+                                                       jit_insn_add(function,
+                                                       newElemAddress, 
newElemSize));
+                           jit_insn_branch_if(function,
+                                               jit_insn_to_bool(function, 
counter),
+                                               &(startLoop));
+                           jit_insn_label(function, &endLoop);
+                           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                                       jit_insn_store_relative(function, 
outAddressValue, offset, newArray);
+                           return newArray;
+           }
+           else if(ILType_IsArray(type))
+           {
+                   fprintf(stderr, "Multidimential arrays are not supported 
for marshaling in delegates as a value\n");
+                   return 0;
+           }
+
+    }
+
+    // Should not reach here if all every case is above, however do something 
smart.
+    if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+    temp = jit_insn_load_relative(function, in, offset, _IL_JIT_TYPE_VPTR);
+    jit_insn_store_relative(function, outAddressValue, offset, temp);
+    return temp;
+}
+
+ILJitValue MarshalDelegateStruct(jit_function_t function, ILJitValue 
inAddress, ILType *structureILType, ILJitValue outAddress, jit_nint offset, 
unsigned int addressKind, ILExecThread *thread)
+{
+    ILClass *classInfo = ILClassResolve(ILType_ToValueType(structureILType));
+    unsigned int structSize = ILSizeOfType(thread, structureILType);
+    ILField *field = 0;
+    ILJitValue newStruct = 0;
+    ILType *type;
+    ILJitType structType;      
+
+    if(addressKind==MARSHAL_FIRST_LEVEL_VALUE)
+    {
+           structType = jit_type_create_struct(0, 0, 0);
+           jit_type_set_size_and_alignment(structType, structSize, 0);
+           newStruct = jit_value_create(function, structType);
+           outAddress = jit_insn_address_of(function, newStruct);
+    }
+
+    while((field = (ILField *)ILClassNextMemberByKind
+               (classInfo, (ILMember *)field, IL_META_MEMBERKIND_FIELD)) != 0)
+    {
+           if(!ILField_IsStatic(field))
+           {
+                   type = ILTypeGetEnumType(ILField_Type(field));
+                   MarshalDelegateValue(function, inAddress, type, 1, 
MARSHAL_ITEM_OF_STRUCTURE, field->offset, outAddress, thread);
+           }
+    }
+    return jit_insn_dup(function, newStruct);
+}
+       
+
+static ILJitValue MarshalDelegateReturnValue(jit_function_t function, 
ILJitValue in, ILType *type, unsigned int addressKind, jit_nint offset, 
ILJitValue outAddress, ILExecThread *thread)
+{
+    ILJitValue outAddressValue = outAddress;
+    ILJitValue temp = jit_value_create(function, _IL_JIT_TYPE_VPTR);
+    ILJitValue ptr, valuePtr;
+    ILType *refType;
+    ILJitValue args[3];
+    ILType *elemType;
+    jit_label_t endLabel = jit_label_undefined;
+    ILJitValue srcArray = jit_value_create(function, _IL_JIT_TYPE_VPTR);    
+    ILUInt32 marshalType;
+    char *customName;
+    int customNameLen;
+    char *customCookie;
+    int customCookieLen;
+    ILMethod *method = (ILMethod *)jit_function_get_meta(function, 
IL_JIT_META_METHOD);
+    ILPInvoke *pinv = ILPInvokeFind(method);
+    marshalType = ILPInvokeGetMarshalType(pinv, method, 1, &customName, 
&customNameLen,
+                                                       &customCookie,  
&customCookieLen, type);
+
+    if(marshalType == IL_META_MARSHAL_DIRECT && 
addressKind==MARSHAL_FIRST_LEVEL_VALUE)
+    {
+           return in;
+    }    
+    else if(marshalType == IL_META_MARSHAL_CUSTOM)
+    {
+           fprintf(stderr, "Custom marshaling not supported in return 
value\n");
+           return 0;
+    }
+    type = ILTypeGetEnumType(type);
+
+    if(addressKind==MARSHAL_FIRST_LEVEL_VALUE)
+    {
+           if(!NeedMarshalValue(type))return in;
+    }
+
+    if(addressKind==MARSHAL_ITEM_OF_ARRAY || addressKind == 
MARSHAL_ITEM_OF_STRUCTURE) outAddressValue = outAddress;
+    else if(addressKind!=MARSHAL_FIRST_LEVEL_VALUE && 
addressKind!=MARSHAL_ITEM_OF_STRUCTURE)
+    {
+           fprintf(stderr, "addressKind has an invalid value of %d\n", 
addressKind);
+           return 0;
+    }
+
+    if(ILType_IsPrimitive(type))
+    {
+       switch(ILType_ToElement(type))
+       {
+               case IL_META_ELEMTYPE_VOID:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_BOOLEAN:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_BYTE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I1:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_SBYTE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U1:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_BYTE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I2:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_INT16);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U2:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_UINT16);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_CHAR:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_CHAR);                         
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I4:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_INT32);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U4:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_UINT32);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I8:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_INT64);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U8:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_UINT64);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;                    
+               }
+               break;
+               case IL_META_ELEMTYPE_R4:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_SINGLE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_R8:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_DOUBLE);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_I:
+               {                       
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_NINT);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               case IL_META_ELEMTYPE_U:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_NUINT);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;                    
+               }
+               break;
+               case IL_META_ELEMTYPE_TYPEDBYREF:
+               {
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) temp = in;
+                       else temp = jit_insn_load_relative(function, in, 
offset, _ILJitTypedRef);
+                       ptr = jit_insn_address_of(function, temp);              
        
+                       valuePtr = jit_insn_load_relative(function, 
+                                                               ptr,
+                                                               
offsetof(ILTypedRef, value),
+                                                               
_IL_JIT_TYPE_VPTR);
+                       refType = ILType_Ref(type);
+                       switch(addressKind)
+                       {
+                               case MARSHAL_ITEM_OF_ARRAY:
+                               {
+                                       return 
(ILJitValue)MarshalDelegateReturnStruct(function, valuePtr, refType, 
outAddressValue, offset, MARSHAL_ITEM_OF_ARRAY, thread);
+                               }
+                               break;
+                               case MARSHAL_ITEM_OF_STRUCTURE:
+                               {
+                                       return 
(ILJitValue)MarshalDelegateReturnStruct(function, valuePtr, refType, 
outAddressValue, offset, MARSHAL_ITEM_OF_STRUCTURE, thread);
+                               }
+                               break;
+                               default:
+                               {
+                                       return 
(ILJitValue)MarshalDelegateReturnStruct(function, valuePtr, refType, 0, 0, 
MARSHAL_FIRST_LEVEL_VALUE, thread);
+                               }
+                               break;
+                       }
+               }
+               break;
+               case IL_META_ELEMTYPE_OBJECT:
+               {       
+                       if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+                       temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+                       jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                       return temp;
+               }
+               break;
+               default:  break;
+       }                       
+    }
+    else if (ILType_IsValueType(type))
+    {
+           switch(addressKind)
+           {
+                   case MARSHAL_ITEM_OF_STRUCTURE:
+                   case MARSHAL_ITEM_OF_ARRAY:
+                   {
+                           return 
(ILJitValue)MarshalDelegateReturnStruct(function, in, type, outAddressValue, 
offset, MARSHAL_ITEM_OF_ARRAY, thread);
+                   }
+                   break;
+                   default:
+                   {
+                           return 
(ILJitValue)MarshalDelegateReturnStruct(function, jit_insn_address_of(function, 
in), type, outAddressValue, 0, MARSHAL_FIRST_LEVEL_VALUE, thread);
+                   }
+                   break;
+           }
+    }
+    else if(ILTypeIsStringClass(type))
+    {
+           args[0] = jit_value_create_nint_constant(function, 
_IL_JIT_TYPE_VPTR, (jit_nint)thread);
+           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) args[1] = in;
+           else args[1] = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+           switch(marshalType)
+           {
+                       case IL_META_MARSHAL_ANSI_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringToAnsi",
+                                                   ILStringToAnsi,
+                                                   
_ILJitSignature_ILStringToAnsi,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+                       case IL_META_MARSHAL_UTF8_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringToUTF8",
+                                                   ILStringToUTF8,
+                                                   
_ILJitSignature_ILStringToUTF8,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+                       case IL_META_MARSHAL_UTF16_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringToUTF16",
+                                                   ILStringToUTF16,
+                                                   
_ILJitSignature_ILStringToUTF16,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+           }
+           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                   jit_insn_store_relative(function, outAddressValue, offset, 
temp);
+           return temp;
+    }
+    else if(ILTypeIsDelegateSubClass(type))
+    {
+           temp = jit_insn_dup(function, in);
+           if(addressKind!=MARSHAL_FIRST_LEVEL_VALUE) temp = 
jit_insn_load_relative(function, in, offset, _IL_JIT_TYPE_VPTR);
+           ILJitValue closure = jit_insn_load_relative(function, temp, 
offsetof(System_Delegate, closure), _IL_JIT_TYPE_VPTR);
+           jit_insn_branch_if(function, jit_insn_to_bool(function, closure), 
&endLabel);
+           args[0] = jit_value_create_nint_constant(function, 
_IL_JIT_TYPE_VPTR, (jit_nint)thread);
+           args[1] = jit_insn_dup(function, temp);
+           args[2] = jit_value_create_nint_constant(function, 
_IL_JIT_TYPE_VPTR, (jit_nint)type);
+           jit_insn_store(function, closure, jit_insn_call_native(function,
+                                           "ILJitDelegateGetClosure",
+                                           ILJitDelegateGetClosure,
+                                           
_ILJitSignature_ILJitDelegateGetClosure,
+                                           args, 3, JIT_CALL_NOTHROW));
+           jit_insn_label(function, &endLabel);
+           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                   jit_insn_store_relative(function, outAddressValue, offset, 
closure);
+           return(closure);
+
+    }
+    else if(type!=0 && ILType_IsComplex(type))
+    {
+           switch(ILType_Kind(type))
+           {
+                   case IL_TYPE_COMPLEX_PTR:
+                   {
+                           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE)return in;
+                           temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+                           jit_insn_store_relative(function, outAddressValue, 
offset, temp);
+                           return temp;
+                   }
+                   break;
+                   case IL_TYPE_COMPLEX_BYREF:
+                   {
+                           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                                   jit_insn_store(function, srcArray, 
jit_insn_load_relative(function, srcArray, offset, _IL_JIT_TYPE_VPTR));
+                           else jit_insn_store(function, srcArray, in);
+                           elemType = ILType_Ref(type);
+                           if(NeedMarshalValue(elemType))
+                           {
+                                   MarshalDelegateReturnValue(function, 
jit_insn_dup(function, srcArray),
+                                                               elemType,
+                                                               
MARSHAL_ITEM_OF_ARRAY,
+                                                               0,
+                                                               
jit_insn_dup(function, srcArray),
+                                                               thread);
+                           }
+                           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                                   jit_insn_store_relative(function, 
outAddressValue, offset, srcArray);
+                           return srcArray;
+                   }
+                   break;
+                   default: break;
+                   }
+
+                   if(ILType_IsSimpleArray(type))
+                   {
+                           // The size of a simple array can be known only on 
run-time and we
+                           // cannot use the same memory as it is used in the 
C code.
+                           fprintf(stderr, "Simple arrays are not supported 
for marshaling as a return value\n");
+                           return 0;
+                   }
+                   else if (ILType_IsArray(type))
+                   {
+                           fprintf(stderr, "Multidimential arrays are not 
supported for marshaling as a return value\n");
+                           return 0;
+                   }
+    }
+
+    if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) return in;
+    temp = jit_insn_load_relative(function, in, offset, _IL_JIT_TYPE_VPTR);
+    jit_insn_store_relative(function, outAddressValue, offset, temp);
+    return temp;
+}
+
+static ILJitValue MarshalDelegateReturnStruct(jit_function_t function, 
ILJitValue inAddress, ILType *structureILType, ILJitValue outAddress, jit_nint 
offset, unsigned int addressKind, ILExecThread *thread)
+{
+        ILClass *classInfo = 
ILClassResolve(ILType_ToValueType(structureILType));
+        unsigned int structSize = ILSizeOfType(thread, structureILType);
+       ILField *field = 0;
+       ILType *type;
+
+       switch(addressKind)
+       {
+               case MARSHAL_FIRST_LEVEL_VALUE:
+               {
+                       ILJitValue sizeValue = 
jit_value_create_nint_constant(function, _IL_JIT_TYPE_UINT32, structSize);
+                       outAddress = jit_insn_call_native(function, "_ILMalloc",
+                                                                   ILGCAlloc,
+                                                                   
_ILJitSignature_malloc,
+                                                                   &sizeValue, 
1, 0);
+               }
+               break;
+               case MARSHAL_ITEM_OF_STRUCTURE:
+               case MARSHAL_ITEM_OF_ARRAY:
+               {           
+                       
+               }
+               break;
+               default:
+               {
+                       fprintf(stderr, "addressKind is an invalid value of 
%d\n", addressKind);
+                       return 0;
+               }
+               break;
+       }
+
+       while((field = (ILField *)ILClassNextMemberByKind
+                       (classInfo, (ILMember *)field, 
IL_META_MEMBERKIND_FIELD)) != 0)
+       {
+               if(!ILField_IsStatic(field))
+               {
+                       type = ILTypeGetEnumType(ILField_Type(field));
+                       switch(addressKind)
+                       {
+                               case MARSHAL_FIRST_LEVEL_VALUE:
+                               {
+                                       MarshalDelegateReturnValue(function, 
inAddress, type, MARSHAL_ITEM_OF_STRUCTURE, field->offset + offset, outAddress, 
thread);
+                               }
+                               break;
+                               case MARSHAL_ITEM_OF_STRUCTURE:
+                               {
+                                       MarshalDelegateReturnValue(function, 
inAddress, type, MARSHAL_ITEM_OF_STRUCTURE, field->offset + offset, outAddress, 
thread);
+                               }
+                               break;
+                               default:
+                               {
+                                       MarshalDelegateReturnValue(function, 
inAddress, type, MARSHAL_ITEM_OF_ARRAY, field->offset + offset, outAddress, 
thread);
+                               }
+                               break;
+                       }
+               }
+       }
+       
+       return outAddress;
+}
+
+static void MarshalDelegateByRefValue(jit_function_t function, ILJitValue in, 
ILType *type, ILUInt32 current, unsigned int addressKind, jit_nint offset, 
ILJitValue outAddress, ILExecThread *thread)
+{
+    ILJitValue outAddressValue;
+    ILJitValue temp = jit_value_create(function, _IL_JIT_TYPE_VPTR);
+    ILJitValue args[3];
+    ILJitValue srcArray = jit_value_create(function, _IL_JIT_TYPE_VPTR);
+    ILJitValue srcElemSize;
+    ILType *elemType;
+    ILJitValue newElemSize;
+    jit_label_t startLoop = jit_label_undefined;
+    jit_label_t endLoop = jit_label_undefined;
+    ILJitValue srcElemAddress;
+    ILJitValue newElemAddress;
+    ILJitValue counter;
+    ILJitValue arraySize;    
+    ILUInt32 marshalType;
+    char *customName;
+    int customNameLen;
+    char *customCookie;
+    int customCookieLen;
+    ILMethod *method = (ILMethod *)jit_function_get_meta(function, 
IL_JIT_META_METHOD);
+    ILPInvoke *pinv = ILPInvokeFind(method);
+    marshalType = ILPInvokeGetMarshalType(pinv, method, current, &customName, 
&customNameLen,
+                                                       &customCookie,  
&customCookieLen, type);
+    if(marshalType == IL_META_MARSHAL_DIRECT && 
addressKind==MARSHAL_FIRST_LEVEL_VALUE)
+    {
+           return;
+    }
+    else if(marshalType == IL_META_MARSHAL_CUSTOM)
+    {
+           fprintf(stderr, "Custom marshaling not supported in delegate by ref 
value\n");
+           return;
+    }
+    type = ILTypeGetEnumType(type);
+
+    if(addressKind==MARSHAL_FIRST_LEVEL_VALUE)
+    {
+           if(!NeedMarshalValue(type))return;
+    }
+
+    switch(addressKind)
+    {    
+           case MARSHAL_FIRST_LEVEL_VALUE:
+           case MARSHAL_ITEM_OF_STRUCTURE:
+           case MARSHAL_ITEM_OF_ARRAY:
+           {
+                   outAddressValue = outAddress;
+           }
+           break;
+           default:
+           {
+                   fprintf(stderr, "addressKind has an invalid %d value\n", 
addressKind);
+                   return;
+           }
+           break;
+    }
+
+    if(ILType_IsPrimitive(type))
+    {
+       switch(ILType_ToElement(type))
+       {
+               case IL_META_ELEMTYPE_VOID:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_BOOLEAN:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_I1:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_U1:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_I2:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_U2:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_CHAR:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_I4:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_U4:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_I8:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_U8:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_R4:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_R8:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_I:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_U:
+               {
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_TYPEDBYREF:
+               {       
+                       fprintf(stderr, "Marshaling of TypedByRef as a ref 
value in delegate is not supported\n");
+                       return;
+               }
+               break;
+               case IL_META_ELEMTYPE_OBJECT:
+               {       
+                       return;
+               }
+               break;
+               default: break;
+       }                       
+    }
+    else if(ILType_IsValueType(type))
+    {
+           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE)
+           {
+                   MarshalDelegateByRefStruct(function, 
jit_insn_address_of(function, in), type, jit_insn_address_of(function, in), 0, 
MARSHAL_ITEM_OF_STRUCTURE, thread);
+                   return;
+           }
+           temp = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+           MarshalDelegateByRefStruct(function, temp, type, temp, 0, 
MARSHAL_ITEM_OF_STRUCTURE, thread);
+           return;
+    }
+    else if(ILTypeIsDelegateSubClass(type))
+    {
+           return;
+    }
+    else if(ILTypeIsStringClass(type))
+    {
+           args[0] = jit_value_create_nint_constant(function, 
_IL_JIT_TYPE_VPTR, (jit_nint)thread);
+           if(addressKind==MARSHAL_FIRST_LEVEL_VALUE) args[1] = in;
+           else args[1] = jit_insn_load_relative(function, in, offset, 
_IL_JIT_TYPE_VPTR);
+           switch(marshalType)
+           {
+                       case IL_META_MARSHAL_ANSI_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringToAnsi",
+                                                   ILStringToAnsi,
+                                                   
_ILJitSignature_ILStringToAnsi,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+                       case IL_META_MARSHAL_UTF8_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringToUTF8",
+                                                   ILStringToUTF8,
+                                                   
_ILJitSignature_ILStringToUTF8,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+                       case IL_META_MARSHAL_UTF16_STRING:
+                       {
+                                   jit_insn_store(function, temp, 
jit_insn_call_native(function,
+                                                   "ILStringToUTF16",
+                                                   ILStringToUTF16,
+                                                   
_ILJitSignature_ILStringToUTF16,
+                                                   args, 2, JIT_CALL_NOTHROW));
+                       }
+                       break;
+           }
+           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                   jit_insn_store_relative(function, in, offset, temp);
+           return;
+    }
+    else if(ILType_IsClass(type))
+    {
+           return;
+    }
+    else if(type !=0 && ILType_IsComplex(type))
+    {
+           switch(ILType_Kind(type))
+           {
+                   case IL_TYPE_COMPLEX_PTR:
+                   case IL_TYPE_COMPLEX_BYREF:
+                   {
+                           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                                   jit_insn_store(function, srcArray, 
jit_insn_load_relative(function, in, offset, _IL_JIT_TYPE_VPTR));
+                           else jit_insn_store(function, srcArray, in);
+                           ILType *elemType = ILType_Ref(type);
+                           if(NeedMarshalValue(elemType))
+                           {
+                                   if(addressKind==MARSHAL_ITEM_OF_STRUCTURE 
|| addressKind==MARSHAL_ITEM_OF_ARRAY)
+                                   {
+                                           MarshalDelegateByRefValue(function, 
jit_insn_dup(function, srcArray),
+                                                                               
    elemType, current,
+                                                                               
    MARSHAL_ITEM_OF_STRUCTURE,
+                                                                               
    0,
+                                                                               
    jit_insn_load_relative(function, outAddressValue, offset, 
_IL_JIT_TYPE_VPTR),
+                                                                               
    thread);
+                                   }
+                                   else MarshalDelegateByRefValue(function, 
jit_insn_dup(function, srcArray),
+                                                                               
    elemType, current,
+                                                                               
    MARSHAL_ITEM_OF_STRUCTURE,
+                                                                               
    0,
+                                                                               
    srcArray,
+                                                                               
    thread);
+                           }
+                           return;
+                   }
+                   break;
+                   case IL_TYPE_COMPLEX_PINNED:
+                   {
+                           fprintf(stderr, "Marshaling a COMPLEX_PINNED type 
is not yet supported for marshaling as a return byref value\n");
+                           return;
+                   }
+                   break;
+                   default: break;
+           }
+
+           if(ILType_IsSimpleArray(type))
+           {
+                           srcArray = in;
+                           if(addressKind==MARSHAL_ITEM_OF_STRUCTURE || 
addressKind==MARSHAL_ITEM_OF_ARRAY)
+                                   srcArray = jit_insn_load_relative(function, 
srcArray, offset, _IL_JIT_TYPE_VPTR);
+                           elemType = ILType_ElemType(type);
+
+                           if(!NeedMarshalValue(elemType))
+                           {
+                                   return;
+                           }
+
+                           // The size of a simple array can be known only on 
run-time.
+                           arraySize = jit_insn_load_relative(function, 
srcArray, 0, _IL_JIT_TYPE_UINT32);
+                           srcElemSize = 
jit_value_create_nint_constant(function,
+                                                                               
_IL_JIT_TYPE_INT32,
+                                                                               
(jit_nint)(ILSizeOfType(thread, elemType)));
+                           newElemSize = 
jit_value_create_nint_constant(function,
+                                                                               
_IL_JIT_TYPE_INT32,
+                                                                               
(jit_nint)(ILSizeOfType(thread, elemType)));
+
+                           jit_insn_branch_if(function,
+                                               jit_insn_eq(function, arraySize,
+                                                                       
jit_value_create_nint_constant
+                                                                               
(function, _IL_JIT_TYPE_UINT32, 0)),
+                                                                               
&endLoop);
+                           newElemAddress = jit_insn_dup(function, 
outAddressValue);
+                           srcElemAddress = jit_insn_add_relative(function, 
srcArray, (jit_nint)(sizeof(ILUInt32)));
+                           counter = arraySize;
+                           jit_insn_label(function, &startLoop);
+                           jit_insn_store(function, counter, 
jit_insn_sub(function, counter,
+                                                                               
        jit_value_create_nint_constant(function,
+                                                                               
        _IL_JIT_TYPE_INT32,
+                                                                               
        1)));
+                           MarshalDelegateByRefValue(function, srcElemAddress,
+                                                       elemType, current,
+                                                       MARSHAL_ITEM_OF_ARRAY,
+                                                       0,
+                                                       newElemAddress,
+                                                       thread);
+                           jit_insn_store(function, srcElemAddress,
+                                                           
jit_insn_add(function,
+                                                           srcElemAddress, 
srcElemSize));
+                           jit_insn_store(function, newElemAddress,
+                                                       jit_insn_add(function,
+                                                       newElemAddress, 
newElemSize));
+                           jit_insn_branch_if(function,
+                                               jit_insn_to_bool(function, 
counter),
+                                               &(startLoop));
+                           jit_insn_label(function, &endLoop);
+                           return;
+           }
+           else if(ILType_IsArray(type))
+           {
+                   fprintf(stderr, "Multidimential arrays are not supported 
for marshaling as a return byref value\n");
+                   return;
+           }
+
+    }
+
+    // Should not reach here, but make the compiler happy.
+    return;
+}
+
+static void MarshalDelegateByRefStruct(jit_function_t function, ILJitValue 
inAddress, ILType *structureILType, ILJitValue outAddress, jit_nint offset, 
unsigned int addressKind, ILExecThread *thread)
+{
+    ILClass *classInfo = ILClassResolve(ILType_ToValueType(structureILType));
+    ILField *field = 0;
+    ILType *type;
+
+    while((field = (ILField *)ILClassNextMemberByKind
+               (classInfo, (ILMember *)field, IL_META_MEMBERKIND_FIELD)) != 0)
+    {
+           if(!ILField_IsStatic(field))
+           {
+                   type = ILTypeGetEnumType(ILField_Type(field));
+                   MarshalDelegateByRefValue(function, inAddress, type, 1, 
MARSHAL_ITEM_OF_STRUCTURE, field->offset + offset, outAddress, thread);
+           }
+    }
+    return;
+}

Index: engine/lib_marshal.c
===================================================================
RCS file: /sources/dotgnu-pnet/pnet/engine/lib_marshal.c,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- engine/lib_marshal.c        23 Aug 2005 10:45:52 -0000      1.8
+++ engine/lib_marshal.c        22 Jul 2006 08:48:32 -0000      1.9
@@ -642,8 +642,13 @@
                /* TODO: convert other kinds of fields, not just delegates */
                if(marshalType == IL_META_MARSHAL_FNPTR)
                {
+           #ifdef IL_USE_JIT
+                       *((void **)ptr) = ILJitDelegateGetClosure
+                               (thread, *((ILObject **)ptr), type);
+           #else
                        *((void **)ptr) = _ILDelegateGetClosure
                                (thread, *((ILObject **)ptr));
+           #endif
                }
        }
 }




reply via email to

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