Beispiel #1
0
/*
 * Convert a method reference type into a method block.
 * Returns NULL if not a method reference type.
 */
static ILMethod *MethodRefToMethod(ILType *type)
{
	if(type != 0 && ILType_IsComplex(type) &&
	   ILType_Kind(type) == IL_TYPE_COMPLEX_METHOD_REF)
	{
		return (ILMethod *)(ILType_Ref(type));
	}
	else
	{
		return 0;
	}
}
Beispiel #2
0
/*
 * Determine if a type contains unsafe pointers.
 */
static IL_INLINE int IsUnsafeType(ILType *type)
{
	if(!type || !ILType_IsComplex(type))
	{
		return 0;
	}
	else if(ILType_Kind(type) == IL_TYPE_COMPLEX_PTR)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}
Beispiel #3
0
ILProgramItem *ILProgramItemFromType(ILImage *image, ILType *type)
{
	if(!type)
	{
		return 0;
	}
	if(ILType_IsComplex(type))
	{
		switch(ILType_Kind(type))
		{
			case IL_TYPE_COMPLEX_WITH:
			case IL_TYPE_COMPLEX_ARRAY:
			case IL_TYPE_COMPLEX_ARRAY_CONTINUE:
			case IL_TYPE_COMPLEX_PTR:
			case IL_TYPE_COMPLEX_METHOD:
			case (IL_TYPE_COMPLEX_METHOD | IL_TYPE_COMPLEX_METHOD_SENTINEL):
			{
				ILTypeSpec *spec;

				spec = ILTypeSpecCreate(image, 0, type);
				return ILToProgramItem(spec);
			}
		}
	}
	else
	{
		ILClass *info;

		info = ILClassFromType(image, 0, type, 0);
		if(info)
		{
			info = ILClassImport(image, info);
		}
		return ILToProgramItem(info);
	}
	return 0;
}
Beispiel #4
0
/*
 * Determine if a stack item is assignment-compatible with
 * a particular memory slot (argument, local, field, etc).
 */
static int AssignCompatible(ILMethod *method, ILEngineStackItem *item,
							ILType *type, int unsafeAllowed)
{
	ILImage *image;
	ILClass *classInfo;
	ILClass *classInfo2;
	ILMethod *methodRef;
	ILType *objType;

	/* Check for safe and unsafe pointer assignments */
	if(item->engineType == ILEngineType_I)
	{
		methodRef = MethodRefToMethod(item->typeInfo);
		if(methodRef)
		{
			/* Assigning a method reference, obtained via "ldftn"
			   or "ldvirtftn", to a method pointer destination */
			if(ILTypeIdentical(ILMethod_Signature(methodRef), type))
			{
				return 1;
			}
		}
		else if(item->typeInfo != 0 && ILType_IsComplex(item->typeInfo))
		{
			/* May be trying to assign a method pointer to a method type */
			if(ILType_IsMethod(item->typeInfo))
			{
				if(ILTypeIdentical(item->typeInfo, type))
				{
					return 1;
				}
			}
		}
		if(unsafeAllowed)
		{
			if(type != 0 && ILType_IsComplex(type))
			{
				if((ILType_Kind(type) & IL_TYPE_COMPLEX_METHOD) != 0 ||
				   ILType_Kind(type) == IL_TYPE_COMPLEX_PTR)
				{
					return 1;
				}
			}
		}
	}

	/* Check for regular assignments */
	if(item->engineType == ILEngineType_I4 ||
	   item->engineType == ILEngineType_I)
	{
		type = ILTypeGetEnumType(type);
		switch((unsigned long)type)
		{
			case (unsigned long)ILType_Boolean:
			case (unsigned long)ILType_Int8:
			case (unsigned long)ILType_UInt8:
			case (unsigned long)ILType_Int16:
			case (unsigned long)ILType_UInt16:
			case (unsigned long)ILType_Char:
			case (unsigned long)ILType_Int32:
			case (unsigned long)ILType_UInt32:
			case (unsigned long)ILType_Int:
			case (unsigned long)ILType_UInt:	return 1;
			default: break;
		}

		if(!unsafeAllowed)
		{
			return 0;
		}

		/* Allow a native int to be assigned to a complex type */
		if(type != 0 && ILType_IsComplex(type) && 
						item->engineType == ILEngineType_I)
		{
			if(ILType_Kind(type) == IL_TYPE_COMPLEX_PTR ||
			  ILType_Kind(type) == IL_TYPE_COMPLEX_BYREF) 
			{
				return 1;
			}
		}
		return 0;
	}
	else if(item->engineType == ILEngineType_I8)
	{
		type = ILTypeGetEnumType(type);
		return (type == ILType_Int64 || type == ILType_UInt64);
	}
	else if(item->engineType == ILEngineType_F)
	{
		return (type == ILType_Float32 ||
		        type == ILType_Float64 ||
		        type == ILType_Float);
	}
	else if(item->engineType == ILEngineType_O)
	{
		if(!(item->typeInfo))
		{
			/* A "null" constant was pushed, which is
			   compatible with any object reference type */
			return IsObjectRef(type);
		}
		if(!IsObjectRef(type) || !IsObjectRef(item->typeInfo))
		{
			/* Both types must be object references */
			return 0;
		}
		/* make a copy to avoid unecessary complications */
		objType=item->typeInfo;
		if(ILType_IsArray(type) && ILType_IsArray(objType) &&
			(ILTypeGetRank(type) == ILTypeGetRank(objType)))
		{
			objType=ILTypeGetElemType(objType);
			type=ILTypeGetElemType(type);
		}
		image = ILProgramItem_Image(method);
		classInfo = ILClassResolve(ILClassFromType(image, 0, type, 0));
		classInfo2 = ILClassResolve
			(ILClassFromType(image, 0, objType, 0));
		if(classInfo && classInfo2)
		{
			/* Is the type a regular class or an interface? */
			if(!ILClass_IsInterface(classInfo))
			{
				/* Regular class: the value must inherit from the type */
				if(ILClassInheritsFrom(classInfo2, classInfo))
				{
					return 1;
				}

				/* If "classInfo2" is an interface, then the conversion
				   is OK if "type" is "System.Object", because all
				   interfaces inherit from "System.Object", even though
				   the metadata doesn't explicitly say so */
				if(ILClass_IsInterface(classInfo2))
				{
					return ILTypeIsObjectClass(type);
				}

				/* The conversion is not OK */
				return 0;
			}
			else
			{
				/* Interface which the value must implement or inherit from */
				return ILClassImplements(classInfo2, classInfo) ||
				       ILClassInheritsFrom(classInfo2, classInfo);
			}
		}
		else
		{
			return 0;
		}
	}
	else if(item->engineType == ILEngineType_MV)
	{
		/* Can only assign managed values to an exact type destination */
		return ILTypeIdentical(item->typeInfo, type);
	}
	else if(item->engineType == ILEngineType_TypedRef)
	{
		/* The type must be "typedref" */
		return (type == ILType_TypedRef);
	}
	else if(item->engineType == ILEngineType_M ||
	        item->engineType == ILEngineType_T)
	{
		/* Cannot assign managed pointers to variables or fields,
		   unless we are in "unsafe" mode */
		if(!unsafeAllowed)
		{
			return 0;
		}

		/* Allow an assignment to any pointer, reference, or native
		   destination, regardless of type.  This allows C/C++ code
		   to arbitrarily cast pointers via assignment */
		if(type != 0 && ILType_IsComplex(type))
		{
			if(ILType_Kind(type) == IL_TYPE_COMPLEX_PTR ||
			   ILType_Kind(type) == IL_TYPE_COMPLEX_BYREF ||
			   (ILType_Kind(type) & IL_TYPE_COMPLEX_METHOD) != 0)
			{
				return 1;
			}
		}
		else if(type == ILType_Int || type == ILType_UInt)
		{
			return 1;
		}
		return 0;
	}
	else
	{
		/* Invalid type: never assignment-compatible with anything */
		return 0;
	}
}
Beispiel #5
0
/*
 * Convert a type into an engine type.
 */
static ILEngineType TypeToEngineType(ILType *type)
{
	type = ILTypeGetEnumType(type);
	if(ILType_IsPrimitive(type))
	{
		switch(ILType_ToElement(type))
		{
			case IL_META_ELEMTYPE_BOOLEAN:
			case IL_META_ELEMTYPE_I1:
			case IL_META_ELEMTYPE_U1:
			case IL_META_ELEMTYPE_I2:
			case IL_META_ELEMTYPE_U2:
			case IL_META_ELEMTYPE_CHAR:
			case IL_META_ELEMTYPE_I4:
			case IL_META_ELEMTYPE_U4:		return ILEngineType_I4;

			case IL_META_ELEMTYPE_I8:
			case IL_META_ELEMTYPE_U8:		return ILEngineType_I8;

			case IL_META_ELEMTYPE_I:
			case IL_META_ELEMTYPE_U:		return ILEngineType_I;

			case IL_META_ELEMTYPE_R4:
			case IL_META_ELEMTYPE_R8:
			case IL_META_ELEMTYPE_R:		return ILEngineType_F;

			case IL_META_ELEMTYPE_TYPEDBYREF: return ILEngineType_TypedRef;
		}
		return ILEngineType_I4;
	}
	else if(ILType_IsValueType(type))
	{
		return ILEngineType_MV;
	}
	else if(ILType_IsComplex(type) && type != 0)
	{
		switch(ILType_Kind(type))
		{
			case IL_TYPE_COMPLEX_PTR:
			{
				/* Unsafe pointers are represented as native integers */
				return ILEngineType_I;
			}
			/* Not reached */

			case IL_TYPE_COMPLEX_BYREF:
			{
				/* Reference values are managed pointers */
				return ILEngineType_M;
			}
			/* Not reached */

			case IL_TYPE_COMPLEX_PINNED:
			{
				/* Pinned types are the same as their underlying type */
				return TypeToEngineType(ILType_Ref(type));
			}
			/* Not reached */

			case IL_TYPE_COMPLEX_CMOD_REQD:
			case IL_TYPE_COMPLEX_CMOD_OPT:
			{
				/* Strip the modifier and inspect the underlying type */
				return TypeToEngineType(type->un.modifier__.type__);
			}
			/* Not reached */

			case IL_TYPE_COMPLEX_METHOD:
			case IL_TYPE_COMPLEX_METHOD | IL_TYPE_COMPLEX_METHOD_SENTINEL:
			{
				/* Pass method pointers around the system as "I".  Higher
				   level code will also set the "typeInfo" field to reflect
				   the signature so that method pointers become verifiable */
				return ILEngineType_I;
			}
			/* Not reached */
		}
	}
	return ILEngineType_O;
}
Beispiel #6
0
/*
 * Get type size information.
 */
static void GetTypeSize(ILSizeInfo *info, ILType *type)
{
	unsigned long num;
	unsigned long posn;

	/* Only complex types have a non-zero memory size */
	if(type == 0 || !ILType_IsComplex(type))
	{
		return;
	}

	/* Account for the size of the complex type header */
	info->loadedMeta += sizeof(ILType);

	/* Account for element information */
	switch(ILType_Kind(type))
	{
		case IL_TYPE_COMPLEX_BYREF:
		case IL_TYPE_COMPLEX_PTR:
		case IL_TYPE_COMPLEX_PINNED:
		{
			GetTypeSize(info, ILType_Ref(type));
		}
		break;

		case IL_TYPE_COMPLEX_ARRAY:
		case IL_TYPE_COMPLEX_ARRAY_CONTINUE:
		{
			GetTypeSize(info, ILType_ElemType(type));
		}
		break;

		case IL_TYPE_COMPLEX_CMOD_REQD:
		case IL_TYPE_COMPLEX_CMOD_OPT:
		{
			GetTypeSize(info, type->un.modifier__.type__);
		}
		break;

		case IL_TYPE_COMPLEX_LOCALS:
		{
			num = ILTypeNumLocals(type);
			for(posn = 0; posn < num; ++posn)
			{
				GetTypeSize(info, ILTypeGetLocalWithPrefixes(type, posn));
			}
		}
		break;

		case IL_TYPE_COMPLEX_WITH:
		{
			num = ILTypeNumWithParams(type);
			GetTypeSize(info, ILTypeGetWithMainWithPrefixes(type));
			for(posn = 1; posn <= num; ++posn)
			{
				GetTypeSize(info, ILTypeGetWithParamWithPrefixes(type, posn));
			}
		}
		break;

		case IL_TYPE_COMPLEX_PROPERTY:
		case IL_TYPE_COMPLEX_METHOD:
		case IL_TYPE_COMPLEX_METHOD | IL_TYPE_COMPLEX_METHOD_SENTINEL:
		{
			num = ILTypeNumParams(type);
			GetTypeSize(info, ILTypeGetReturnWithPrefixes(type));
			for(posn = 1; posn <= num; ++posn)
			{
				GetTypeSize(info, ILTypeGetParamWithPrefixes(type, posn));
			}
		}
		break;
	}
}
Beispiel #7
0
/*
 * Pack the parameters for a delegate closure call onto the CVM stack.
 */
static int PackDelegateParams(ILExecThread *thread, ILMethod *method,
					          int isCtor, void *_this, void *userData)
{
	void **args = ((PackDelegateUserData *)userData)->args;
	ILMethod *pinvokeInfo = ((PackDelegateUserData *)userData)->pinvokeInfo;
	ILType *signature = ILMethod_Signature(method);
	CVMWord *stacktop, *stacklimit;
	ILUInt32 param, numParams;
	ILType *paramType;
	void *ptr;
	ILUInt32 size, sizeInWords;
	ILNativeFloat tempFloat;
	ILUInt32 marshalType;
	char *customName;
	int customNameLen;
	char *customCookie;
	int customCookieLen;
	char *strValue;

	/* Get the top and extent of the stack */
	stacktop = thread->stackTop;
	stacklimit = thread->stackLimit;

	/* Push the arguments onto the evaluation stack */
	if(ILType_HasThis(signature))
	{
		/* Push the "this" argument */
		CHECK_SPACE(1);
		if(((PackDelegateUserData *)userData)->needThis)
		{
			/* We get the "this" value from the incoming arguments */
			stacktop->ptrValue = *((void **)(*args));
			++args;
		}
		else
		{
			/* We get the "this" value from the delegate object */
			stacktop->ptrValue = _this;
		}
		++stacktop;
	}
	numParams = ILTypeNumParams(signature);
	for(param = 1; param <= numParams; ++param)
	{
		/* Marshal parameters that need special handling */
		marshalType = ILPInvokeGetMarshalType(0, pinvokeInfo, param,
											  &customName, &customNameLen,
											  &customCookie, &customCookieLen,
											  ILTypeGetParam(signature, param));
		if(marshalType != IL_META_MARSHAL_DIRECT)
		{
			switch(marshalType)
			{
				case IL_META_MARSHAL_ANSI_STRING:
				{
					/* Marshal an ANSI string from the native world */
					CHECK_SPACE(1);
					strValue = *((char **)(*args));
					if(strValue)
					{
						stacktop->ptrValue = ILStringCreate(thread, strValue);

						/* Free the native string */
						ILFreeNativeString(strValue);

						if(!(stacktop->ptrValue))
						{
							return 1;
						}
					}
					else
					{
						stacktop->ptrValue = 0;
					}
					++args;
					++stacktop;
				}
				continue;

				case IL_META_MARSHAL_UTF8_STRING:
				{
					/* Marshal a UTF-8 string from the native world */
					CHECK_SPACE(1);
					strValue = *((char **)(*args));
					if(strValue)
					{
						stacktop->ptrValue =
							ILStringCreateUTF8(thread, strValue);

						/* Free the native string */
						ILFreeNativeString(strValue);

						if(!(stacktop->ptrValue))
						{
							return 1;
						}
					}
					else
					{
						stacktop->ptrValue = 0;
					}
					++args;
					++stacktop;
				}
				continue;

				case IL_META_MARSHAL_UTF16_STRING:
				{
					/* Marshal a UTF-16 string from the native world */
					CHECK_SPACE(1);
					strValue = *((char **)(*args));
					if(strValue)
					{
						stacktop->ptrValue =
							ILStringWCreate(thread, (ILUInt16 *)strValue);

						/* Free the native string */
						ILFreeNativeString(strValue);
					
						if(!(stacktop->ptrValue))
						{
							return 1;
						}
					}
					else
					{
						stacktop->ptrValue = 0;
					}
					++args;
					++stacktop;
				}
				continue;

				case IL_META_MARSHAL_CUSTOM:
				{
					/* Marshal a custom value from the native world */
					CHECK_SPACE(1);
					stacktop->ptrValue = _ILCustomToObject
						(thread, *((void **)(*args)),
						 customName, customNameLen,
						 customCookie, customCookieLen);
					if(_ILExecThreadHasException(thread))
					{
						return 1;
					}
					++args;
					++stacktop;
				}
				continue;
			}
		}

		/* Marshal the parameter directly */
		paramType = ILTypeGetEnumType(ILTypeGetParam(signature, param));
		if(ILType_IsPrimitive(paramType))
		{
			/* Process a primitive value */
			switch(ILType_ToElement(paramType))
			{
				case IL_META_ELEMTYPE_VOID:		break;

				case IL_META_ELEMTYPE_BOOLEAN:
				case IL_META_ELEMTYPE_I1:
				case IL_META_ELEMTYPE_U1:
				case IL_META_ELEMTYPE_I2:
				case IL_META_ELEMTYPE_U2:
				case IL_META_ELEMTYPE_CHAR:
				case IL_META_ELEMTYPE_I4:
				case IL_META_ELEMTYPE_U4:
			#ifdef IL_NATIVE_INT32
				case IL_META_ELEMTYPE_I:
				case IL_META_ELEMTYPE_U:
			#endif
				{
					CHECK_SPACE(1);
					stacktop->intValue = *((ILInt32 *)(*args));
					++args;
					++stacktop;
				}
				break;

				case IL_META_ELEMTYPE_I8:
				case IL_META_ELEMTYPE_U8:
			#ifdef IL_NATIVE_INT64
				case IL_META_ELEMTYPE_I:
				case IL_META_ELEMTYPE_U:
			#endif
				{
					CHECK_SPACE(CVM_WORDS_PER_LONG);
					ILMemCpy(stacktop, *args, sizeof(ILInt64));
					++args;
					stacktop += CVM_WORDS_PER_LONG;
				}
				break;

				case IL_META_ELEMTYPE_R4:
				{
					CHECK_SPACE(CVM_WORDS_PER_NATIVE_FLOAT);
					tempFloat = (ILNativeFloat)(*((ILFloat *)(*args)));
					ILMemCpy(stacktop, &tempFloat, sizeof(ILNativeFloat));
					++args;
					stacktop += CVM_WORDS_PER_NATIVE_FLOAT;
				}
				break;

				case IL_META_ELEMTYPE_R8:
				{
					CHECK_SPACE(CVM_WORDS_PER_NATIVE_FLOAT);
					tempFloat = (ILNativeFloat)(*((ILDouble *)(*args)));
					ILMemCpy(stacktop, &tempFloat, sizeof(ILNativeFloat));
					++args;
					stacktop += CVM_WORDS_PER_NATIVE_FLOAT;
				}
				break;

				case IL_META_ELEMTYPE_R:
				{
					CHECK_SPACE(CVM_WORDS_PER_NATIVE_FLOAT);
					ILMemCpy(stacktop, *args, sizeof(ILNativeFloat));
					++args;
					stacktop += CVM_WORDS_PER_NATIVE_FLOAT;
				}
				break;

				case IL_META_ELEMTYPE_TYPEDBYREF:
				{
					CHECK_SPACE(CVM_WORDS_PER_TYPED_REF);
					ILMemCpy(stacktop, *args, sizeof(ILTypedRef));
					++args;
					stacktop += CVM_WORDS_PER_TYPED_REF;
				}
				break;
			}
		}
		else if(ILType_IsClass(paramType))
		{
			/* Process an object reference */
			CHECK_SPACE(1);
			stacktop->ptrValue = *((void **)(*args));
			++args;
			++stacktop;
		}
		else if(ILType_IsValueType(paramType))
		{
			/* Process a value type which was passed by value */
			ptr = *args;
			++args;
			size = ILSizeOfType(thread, paramType);
			sizeInWords = ((size + sizeof(CVMWord) - 1) / sizeof(CVMWord));
			CHECK_SPACE(sizeInWords);
			ILMemCpy(stacktop, ptr, size);
			stacktop += sizeInWords;
		}
		else if(paramType != 0 && ILType_IsComplex(paramType) &&
				(ILType_Kind(paramType) == IL_TYPE_COMPLEX_BYREF || 
				 ILType_Kind(paramType) == IL_TYPE_COMPLEX_PTR))
		{
			/* Process a value that is being passed by reference */
			CHECK_SPACE(1);
			stacktop->ptrValue = *((void **)(*args));
			++args;
			++stacktop;
		}
		else
		{
			/* Assume that everything else is an object reference */
			CHECK_SPACE(1);
			stacktop->ptrValue = *args;
			++args;
			++stacktop;
		}
	}

	/* Update the stack top */
	thread->stackTop = stacktop;
	return 0;
}
ILUInt32 ILPInvokeGetMarshalType(ILPInvoke *pinvoke, ILMethod *method,
								 unsigned long param, char **customName,
								 int *customNameLen, char **customCookie,
								 int *customCookieLen, ILType *type)
{
	ILParameter *parameter;
	ILFieldMarshal *marshal;
	const unsigned char *nativeType;
	unsigned long nativeTypeLen;
	int nativeTypeCode;

	/* Find the parameter information block */
	if(method)
	{
		if(!(method->parameters))
		{
			_ILMethodLoadParams(method);
		}
		parameter = method->parameters;
		while(parameter != 0 && parameter->paramNum != param)
		{
			parameter = parameter->next;
		}
	}
	else
	{
		parameter = 0;
	}

	/* See if we have native type information for the parameter */
	nativeType = 0;
	nativeTypeLen = 0;
	nativeTypeCode = IL_META_NATIVETYPE_END;
	if(parameter != 0)
	{
		marshal = ILFieldMarshalGetFromOwner(&(parameter->programItem));
		if(marshal != 0)
		{
			nativeType = (const unsigned char *)
				ILFieldMarshalGetType(marshal, &nativeTypeLen);
			if(nativeTypeLen > 0)
			{
				nativeTypeCode = (int)(nativeType[0]);
			}
		}
	}

	/* Initialize the custom name return information to nothing */
	*customName = 0;
	*customNameLen = 0;
	*customCookie = 0;
	*customCookieLen = 0;

	/* If the native type is "interface", then always marshal directly.
	   This is normally used to force strings, delegates, and arrays
	   to be passed as objects */
	if(nativeTypeCode == IL_META_NATIVETYPE_INTF)
	{
		return IL_META_MARSHAL_DIRECT;
	}

	/* Check for custom marshalling */
	if(nativeTypeCode == IL_META_NATIVETYPE_CUSTOMMARSHALER &&
	   ILTypeIsReference(type))
	{
		ILMetaDataRead reader;
		reader.data = nativeType + 1;
		reader.len = nativeTypeLen - 1;
		reader.error = 0;
		ExtractCustomString(customName, customNameLen);	/* Unused GUID */
		ExtractCustomString(customName, customNameLen);	/* Unused native name */
		ExtractCustomString(customName, customNameLen);
		ExtractCustomString(customCookie, customCookieLen);
		if(*customNameLen > 0)
		{
			return IL_META_MARSHAL_CUSTOM;
		}
		else
		{
			return IL_META_MARSHAL_DIRECT;
		}
	}

	/* Determine what to do based on the parameter type */
	if(ILTypeIsStringClass(type))
	{
		/* Value string type */
		if(nativeTypeCode == IL_META_NATIVETYPE_LPWSTR)
		{
		#ifdef IL_WIN32_PLATFORM
			return IL_META_MARSHAL_UTF16_STRING;
		#else
			return IL_META_MARSHAL_UTF8_STRING;
		#endif
		}
		else if(nativeTypeCode == IL_META_NATIVETYPE_LPSTR)
		{
			return IL_META_MARSHAL_ANSI_STRING;
		}
		else
		{
			return ILPInvokeGetCharSet(pinvoke, method);
		}
	}
	else if(ILTypeIsDelegateSubClass(type))
	{
		/* Delegate type */
		return IL_META_MARSHAL_FNPTR;
	}
	else if(ILType_IsSimpleArray(type))
	{
		if(ILTypeIsStringClass(ILTypeGetElemType(type)))
		{
			/* Array of strings, passed as "char **" */
			switch(ILPInvokeGetCharSet(pinvoke, method))
			{
				case IL_META_MARSHAL_UTF8_STRING:
				{
					return IL_META_MARSHAL_UTF8_ARRAY;
				}
				/* not reached */
	
				case IL_META_MARSHAL_UTF16_STRING:
				{
					return IL_META_MARSHAL_UTF16_ARRAY;
				}
				/* not reached */

				default:
				{
					return IL_META_MARSHAL_ANSI_ARRAY;
				}
				/* not reached */
			}
		}
		else
		{
			/* Array type, passed in by pointer to the first element */
			return IL_META_MARSHAL_ARRAY;
		}
	}
	else if(type != 0 && ILType_IsComplex(type) &&
			ILType_Kind(type) == IL_TYPE_COMPLEX_BYREF)
	{
		/* Check for "ref String[]", which is used by Gtk# when
		   calling the "gtk_init" function */
		if(ILType_IsSimpleArray(ILType_Ref(type)) &&
		   ILTypeIsStringClass(ILTypeGetElemType(ILType_Ref(type))))
		{
			switch(ILPInvokeGetCharSet(pinvoke, method))
			{
				case IL_META_MARSHAL_UTF8_STRING:
				{
					return IL_META_MARSHAL_REF_UTF8_ARRAY;
				}
				/* not reached */
	
				case IL_META_MARSHAL_UTF16_STRING:
				{
					return IL_META_MARSHAL_REF_UTF16_ARRAY;
				}
				/* not reached */

				default:
				{
					return IL_META_MARSHAL_REF_ANSI_ARRAY;
				}
				/* not reached */
			}
			return IL_META_MARSHAL_REF_ANSI_ARRAY;
		}
	}

	/* Marshal the parameter directly */
	return IL_META_MARSHAL_DIRECT;
}