diff --git a/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml b/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml
index cf3c636bce337f..ee6d7863ebd6b1 100644
--- a/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml
+++ b/src/mono/System.Private.CoreLib/src/ILLink/ILLink.Descriptors.xml
@@ -555,9 +555,9 @@
-
+
-
+
diff --git a/src/mono/mono/metadata/CMakeLists.txt b/src/mono/mono/metadata/CMakeLists.txt
index 29c420768b7d04..b3f5ecccb0f749 100644
--- a/src/mono/mono/metadata/CMakeLists.txt
+++ b/src/mono/mono/metadata/CMakeLists.txt
@@ -18,6 +18,8 @@ set(ilgen_base_sources
method-builder-ilgen-internals.h
marshal-ilgen.c
marshal-ilgen.h
+ marshal-shared.c
+ marshal-shared.h
sgen-mono-ilgen.c
sgen-mono-ilgen.h)
diff --git a/src/mono/mono/metadata/marshal-ilgen.c b/src/mono/mono/metadata/marshal-ilgen.c
index 9c391cf9ac76b7..974a5d1663dfc2 100644
--- a/src/mono/mono/metadata/marshal-ilgen.c
+++ b/src/mono/mono/metadata/marshal-ilgen.c
@@ -16,6 +16,7 @@
#include "metadata/marshal.h"
#include "metadata/marshal-internals.h"
#include "metadata/marshal-ilgen.h"
+#include "metadata/marshal-shared.h"
#include "metadata/tabledefs.h"
#include
#include
@@ -56,983 +57,33 @@ enum {
};
#undef OPDEF
-static gboolean
-is_in (const MonoType *t)
-{
- const guint32 attrs = t->attrs;
- return (attrs & PARAM_ATTRIBUTE_IN) || !(attrs & PARAM_ATTRIBUTE_OUT);
-}
-
-static gboolean
-is_out (const MonoType *t)
-{
- const guint32 attrs = t->attrs;
- return (attrs & PARAM_ATTRIBUTE_OUT) || !(attrs & PARAM_ATTRIBUTE_IN);
-}
-
-static GENERATE_GET_CLASS_WITH_CACHE (fixed_buffer_attribute, "System.Runtime.CompilerServices", "FixedBufferAttribute");
-static GENERATE_GET_CLASS_WITH_CACHE (date_time, "System", "DateTime");
-static GENERATE_TRY_GET_CLASS_WITH_CACHE (icustom_marshaler, "System.Runtime.InteropServices", "ICustomMarshaler");
-static GENERATE_TRY_GET_CLASS_WITH_CACHE (marshal, "System.Runtime.InteropServices", "Marshal");
-
-/* MonoMethod pointers to SafeHandle::DangerousAddRef and ::DangerousRelease */
-static MonoMethod *sh_dangerous_add_ref;
-static MonoMethod *sh_dangerous_release;
-
-// FIXME Consolidate the multiple functions named get_method_nofail.
-static MonoMethod*
-get_method_nofail (MonoClass *klass, const char *method_name, int num_params, int flags)
-{
- MonoMethod *method;
- ERROR_DECL (error);
- method = mono_class_get_method_from_name_checked (klass, method_name, num_params, flags, error);
- mono_error_assert_ok (error);
- g_assertf (method, "Could not lookup method %s in %s", method_name, m_class_get_name (klass));
- return method;
-}
-
-static void
-init_safe_handle (void)
-{
- mono_atomic_store_seq (&sh_dangerous_add_ref, get_method_nofail (mono_class_try_get_safehandle_class (), "DangerousAddRef", 1, 0));
- mono_atomic_store_seq (&sh_dangerous_release, get_method_nofail (mono_class_try_get_safehandle_class (), "DangerousRelease", 0, 0));
-}
-
-static MonoImage*
-get_method_image (MonoMethod *method)
-{
- return m_class_get_image (method->klass);
-}
-
-static void
-emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
-
-static void
-emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object, int offset_of_first_child_field, MonoMarshalNative string_encoding);
-
-static MonoJitICallId
-conv_to_icall (MonoMarshalConv conv, int *ind_store_type);
-
-static MonoMarshalConv
-conv_str_inverse (MonoMarshalConv conv);
-
-/**
- * mono_mb_strdup:
- * \param mb the MethodBuilder
- * \param s a string
- *
- * Creates a copy of the string \p s that can be referenced from the IL of \c mb.
- *
- * \returns a pointer to the new string which is owned by the method builder
- */
-char*
-mono_mb_strdup (MonoMethodBuilder *mb, const char *s)
-{
- char *res;
- if (!mb->dynamic)
- res = mono_image_strdup (get_method_image (mb->method), s);
- else
- res = g_strdup (s);
- return res;
-}
-
-
-
-/*
- * mono_mb_emit_exception_marshal_directive:
- *
- * This function assumes ownership of MSG, which should be malloc-ed.
- */
-static void
-mono_mb_emit_exception_marshal_directive (MonoMethodBuilder *mb, char *msg)
-{
- char *s = mono_mb_strdup (mb, msg);
- g_free (msg);
- mono_mb_emit_exception_full (mb, "System.Runtime.InteropServices", "MarshalDirectiveException", s);
-}
-
-static int
-offset_of_first_nonstatic_field (MonoClass *klass)
-{
- mono_class_setup_fields (klass);
- gpointer iter = NULL;
- MonoClassField *field;
- while ((field = mono_class_get_fields_internal (klass, &iter))) {
- if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) && !mono_field_is_deleted (field)) {
- /*
- * metadata-update: adding fields to existing structs isn't supported. In
- * newly-added structs, the "from update" field won't be set.
- */
- g_assert (!m_field_is_from_update (field));
- return m_field_get_offset (field) - MONO_ABI_SIZEOF (MonoObject);
- }
- }
-
- return 0;
-}
-
-static gboolean
-get_fixed_buffer_attr (MonoClassField *field, MonoType **out_etype, int *out_len)
-{
- ERROR_DECL (error);
- MonoCustomAttrInfo *cinfo;
- MonoCustomAttrEntry *attr;
- int aindex;
-
- cinfo = mono_custom_attrs_from_field_checked (m_field_get_parent (field), field, error);
- if (!is_ok (error))
- return FALSE;
- attr = NULL;
- if (cinfo) {
- for (aindex = 0; aindex < cinfo->num_attrs; ++aindex) {
- MonoClass *ctor_class = cinfo->attrs [aindex].ctor->klass;
- if (mono_class_has_parent (ctor_class, mono_class_get_fixed_buffer_attribute_class ())) {
- attr = &cinfo->attrs [aindex];
- break;
- }
- }
- }
- if (attr) {
- gpointer *typed_args, *named_args;
- CattrNamedArg *arginfo;
- int num_named_args;
-
- mono_reflection_create_custom_attr_data_args_noalloc (mono_defaults.corlib, attr->ctor, attr->data, attr->data_size,
- &typed_args, &named_args, &num_named_args, &arginfo, error);
- if (!is_ok (error))
- return FALSE;
- *out_etype = (MonoType*)typed_args [0];
- *out_len = *(gint32*)typed_args [1];
- g_free (typed_args [1]);
- g_free (typed_args);
- g_free (named_args);
- g_free (arginfo);
- }
- if (cinfo && !cinfo->cached)
- mono_custom_attrs_free (cinfo);
- return attr != NULL;
-}
-
-static void
-emit_fixed_buf_conv (MonoMethodBuilder *mb, MonoType *type, MonoType *etype, int len, gboolean to_object, int *out_usize)
-{
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- MonoClass *eklass = mono_class_from_mono_type_internal (etype);
- int esize;
-
- esize = mono_class_native_size (eklass, NULL);
-
- MonoMarshalNative string_encoding = m_class_is_unicode (klass) ? MONO_NATIVE_LPWSTR : MONO_NATIVE_LPSTR;
- int usize = mono_class_value_size (eklass, NULL);
- int msize = mono_class_value_size (eklass, NULL);
-
- //printf ("FIXED: %s %d %d\n", mono_type_full_name (type), em_class_is_blittable (klass), string_encoding);
-
- if (m_class_is_blittable (eklass)) {
- /* copy the elements */
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_icon (mb, len * esize);
- mono_mb_emit_byte (mb, CEE_PREFIX1);
- mono_mb_emit_byte (mb, CEE_CPBLK);
- } else {
- int index_var;
- guint32 label2, label3;
-
- /* Emit marshalling loop */
- MonoType *int_type = mono_get_int_type ();
- index_var = mono_mb_add_local (mb, int_type);
- mono_mb_emit_byte (mb, CEE_LDC_I4_0);
- mono_mb_emit_stloc (mb, index_var);
-
- /* Loop header */
- label2 = mono_mb_get_label (mb);
- mono_mb_emit_ldloc (mb, index_var);
- mono_mb_emit_icon (mb, len);
- label3 = mono_mb_emit_branch (mb, CEE_BGE);
-
- /* src/dst is already set */
-
- /* Do the conversion */
- MonoTypeEnum t = etype->type;
- switch (t) {
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
- case MONO_TYPE_I8:
- case MONO_TYPE_U8:
- case MONO_TYPE_PTR:
- case MONO_TYPE_R4:
- case MONO_TYPE_R8:
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- if (t == MONO_TYPE_CHAR && string_encoding != MONO_NATIVE_LPWSTR) {
- if (to_object) {
- mono_mb_emit_byte (mb, CEE_LDIND_U1);
- mono_mb_emit_byte (mb, CEE_STIND_I2);
- } else {
- mono_mb_emit_byte (mb, CEE_LDIND_U2);
- mono_mb_emit_byte (mb, CEE_STIND_I1);
- }
- usize = 1;
- } else {
- mono_mb_emit_byte (mb, mono_type_to_ldind (etype));
- mono_mb_emit_byte (mb, mono_type_to_stind (etype));
- }
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-
- if (to_object) {
- mono_mb_emit_add_to_local (mb, 0, usize);
- mono_mb_emit_add_to_local (mb, 1, msize);
- } else {
- mono_mb_emit_add_to_local (mb, 0, msize);
- mono_mb_emit_add_to_local (mb, 1, usize);
- }
-
- /* Loop footer */
- mono_mb_emit_add_to_local (mb, index_var, 1);
-
- mono_mb_emit_branch_label (mb, CEE_BR, label2);
-
- mono_mb_patch_branch (mb, label3);
- }
-
- *out_usize = usize * len;
-}
-
-static void
-emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec)
-{
- switch (conv) {
- case MONO_MARSHAL_CONV_BOOL_I4:
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_I4);
- mono_mb_emit_byte (mb, CEE_BRFALSE_S);
- mono_mb_emit_byte (mb, 3);
- mono_mb_emit_byte (mb, CEE_LDC_I4_1);
- mono_mb_emit_byte (mb, CEE_BR_S);
- mono_mb_emit_byte (mb, 1);
- mono_mb_emit_byte (mb, CEE_LDC_I4_0);
- mono_mb_emit_byte (mb, CEE_STIND_I1);
- break;
- case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_I2);
- mono_mb_emit_byte (mb, CEE_BRFALSE_S);
- mono_mb_emit_byte (mb, 3);
- mono_mb_emit_byte (mb, CEE_LDC_I4_1);
- mono_mb_emit_byte (mb, CEE_BR_S);
- mono_mb_emit_byte (mb, 1);
- mono_mb_emit_byte (mb, CEE_LDC_I4_0);
- mono_mb_emit_byte (mb, CEE_STIND_I1);
- break;
- case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
- MonoClass *eklass = NULL;
- int esize;
-
- if (type->type == MONO_TYPE_SZARRAY) {
- eklass = type->data.klass;
- } else {
- g_assert_not_reached ();
- }
-
- esize = mono_class_native_size (eklass, NULL);
-
- /* create a new array */
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
- mono_mb_emit_op (mb, CEE_NEWARR, eklass);
- mono_mb_emit_byte (mb, CEE_STIND_REF);
-
- if (m_class_is_blittable (eklass)) {
- /* copy the elements */
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoArray, vector));
- mono_mb_emit_byte (mb, CEE_ADD);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
- mono_mb_emit_byte (mb, CEE_PREFIX1);
- mono_mb_emit_byte (mb, CEE_CPBLK);
- }
- else {
- int array_var, src_var, dst_var, index_var;
- guint32 label2, label3;
-
- MonoType *int_type = mono_get_int_type ();
- array_var = mono_mb_add_local (mb, mono_get_object_type ());
- src_var = mono_mb_add_local (mb, int_type);
- dst_var = mono_mb_add_local (mb, int_type);
-
- /* set array_var */
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_byte (mb, CEE_LDIND_REF);
- mono_mb_emit_stloc (mb, array_var);
-
- /* save the old src pointer */
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_stloc (mb, src_var);
- /* save the old dst pointer */
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_stloc (mb, dst_var);
-
- /* Emit marshalling loop */
- index_var = mono_mb_add_local (mb, int_type);
- mono_mb_emit_byte (mb, CEE_LDC_I4_0);
- mono_mb_emit_stloc (mb, index_var);
-
- /* Loop header */
- label2 = mono_mb_get_label (mb);
- mono_mb_emit_ldloc (mb, index_var);
- mono_mb_emit_ldloc (mb, array_var);
- mono_mb_emit_byte (mb, CEE_LDLEN);
- label3 = mono_mb_emit_branch (mb, CEE_BGE);
-
- /* src is already set */
-
- /* Set dst */
- mono_mb_emit_ldloc (mb, array_var);
- mono_mb_emit_ldloc (mb, index_var);
- mono_mb_emit_op (mb, CEE_LDELEMA, eklass);
- mono_mb_emit_stloc (mb, 1);
-
- /* Do the conversion */
- emit_struct_conv (mb, eklass, TRUE);
-
- /* Loop footer */
- mono_mb_emit_add_to_local (mb, index_var, 1);
-
- mono_mb_emit_branch_label (mb, CEE_BR, label2);
-
- mono_mb_patch_branch (mb, label3);
-
- /* restore the old src pointer */
- mono_mb_emit_ldloc (mb, src_var);
- mono_mb_emit_stloc (mb, 0);
- /* restore the old dst pointer */
- mono_mb_emit_ldloc (mb, dst_var);
- mono_mb_emit_stloc (mb, 1);
- }
- break;
- }
- case MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY: {
- MonoClass *eclass = mono_defaults.char_class;
-
- /* create a new array */
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
- mono_mb_emit_op (mb, CEE_NEWARR, eclass);
- mono_mb_emit_byte (mb, CEE_STIND_REF);
-
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_byte (mb, CEE_LDIND_REF);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
- mono_mb_emit_icall (mb, mono_byvalarray_to_byte_array);
- break;
- }
- case MONO_MARSHAL_CONV_STR_BYVALSTR:
- if (mspec && mspec->native == MONO_NATIVE_BYVALTSTR && mspec->data.array_data.num_elem) {
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
- mono_mb_emit_icall (mb, mono_string_from_byvalstr);
- } else {
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_icall (mb, ves_icall_string_new_wrapper);
- }
- mono_mb_emit_byte (mb, CEE_STIND_REF);
- break;
- case MONO_MARSHAL_CONV_STR_BYVALWSTR:
- if (mspec && mspec->native == MONO_NATIVE_BYVALTSTR && mspec->data.array_data.num_elem) {
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
- mono_mb_emit_icall (mb, mono_string_from_byvalwstr);
- } else {
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_icall (mb, ves_icall_mono_string_from_utf16);
- }
- mono_mb_emit_byte (mb, CEE_STIND_REF);
- break;
-
- case MONO_MARSHAL_CONV_STR_ANSIBSTR:
- case MONO_MARSHAL_CONV_STR_TBSTR:
- case MONO_MARSHAL_CONV_STR_UTF8STR:
- case MONO_MARSHAL_CONV_STR_LPWSTR:
- case MONO_MARSHAL_CONV_STR_LPSTR:
- case MONO_MARSHAL_CONV_STR_LPTSTR:
- case MONO_MARSHAL_CONV_STR_BSTR: {
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall_id (mb, conv_to_icall (conv_str_inverse (conv), NULL));
- mono_mb_emit_byte (mb, CEE_STIND_REF);
- break;
- }
-
- case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
- MonoClass *klass = mono_class_from_mono_type_internal (type);
- int src_var, dst_var;
-
- MonoType *int_type = mono_get_int_type ();
- src_var = mono_mb_add_local (mb, int_type);
- dst_var = mono_mb_add_local (mb, int_type);
-
- /* *dst = new object */
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_op (mb, CEE_MONO_NEWOBJ, klass);
- mono_mb_emit_byte (mb, CEE_STIND_REF);
-
- /* save the old src pointer */
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_stloc (mb, src_var);
- /* save the old dst pointer */
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_stloc (mb, dst_var);
-
- /* dst = pointer to newly created object data */
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icon (mb, MONO_ABI_SIZEOF (MonoObject));
- mono_mb_emit_byte (mb, CEE_ADD);
- mono_mb_emit_stloc (mb, 1);
-
- emit_struct_conv (mb, klass, TRUE);
-
- /* restore the old src pointer */
- mono_mb_emit_ldloc (mb, src_var);
- mono_mb_emit_stloc (mb, 0);
- /* restore the old dst pointer */
- mono_mb_emit_ldloc (mb, dst_var);
- mono_mb_emit_stloc (mb, 1);
- break;
- }
- case MONO_MARSHAL_CONV_DEL_FTN: {
- MonoClass *klass = mono_class_from_mono_type_internal (type);
-
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall (mb, mono_ftnptr_to_delegate);
- mono_mb_emit_byte (mb, CEE_STIND_REF);
- break;
- }
- case MONO_MARSHAL_CONV_ARRAY_LPARRAY: {
- char *msg = g_strdup_printf ("Structure field of type %s can't be marshalled as LPArray", m_class_get_name (mono_class_from_mono_type_internal (type)));
- mono_mb_emit_exception_marshal_directive (mb, msg);
- break;
- }
-
-#ifndef DISABLE_COM
- case MONO_MARSHAL_CONV_OBJECT_INTERFACE:
- case MONO_MARSHAL_CONV_OBJECT_IUNKNOWN:
- case MONO_MARSHAL_CONV_OBJECT_IDISPATCH:
- mono_cominterop_emit_ptr_to_object_conv (mb, type, conv, mspec);
- break;
-#endif /* DISABLE_COM */
-
- case MONO_MARSHAL_CONV_SAFEHANDLE: {
- /*
- * Passing SafeHandles as ref does not allow the unmanaged code
- * to change the SafeHandle value. If the value is changed,
- * we should issue a diagnostic exception (NotSupportedException)
- * that informs the user that changes to handles in unmanaged code
- * is not supported.
- *
- * Since we currently have no access to the original
- * SafeHandle that was used during the marshalling,
- * for now we just ignore this, and ignore/discard any
- * changes that might have happened to the handle.
- */
- break;
- }
-
- case MONO_MARSHAL_CONV_HANDLEREF: {
- /*
- * Passing HandleRefs in a struct that is ref()ed does not
- * copy the values back to the HandleRef
- */
- break;
- }
-
- case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
- default: {
- char *msg = g_strdup_printf ("marshaling conversion %d not implemented", conv);
-
- mono_mb_emit_exception_marshal_directive (mb, msg);
- break;
- }
- }
-}
-
-// On legacy Mono, LPTSTR was either UTF16 or UTF8 depending on platform
-static inline MonoJitICallId
-mono_string_to_platform_unicode (void)
-{
-#ifdef TARGET_WIN32
- return MONO_JIT_ICALL_mono_marshal_string_to_utf16;
-#else
- return MONO_JIT_ICALL_mono_string_to_utf8str;
-#endif
-}
-
-static inline MonoJitICallId
-mono_string_from_platform_unicode (void)
-{
-#ifdef TARGET_WIN32
- return MONO_JIT_ICALL_ves_icall_mono_string_from_utf16;
-#else
- return MONO_JIT_ICALL_ves_icall_string_new_wrapper;
-#endif
-}
-
-static inline MonoJitICallId
-mono_string_builder_to_platform_unicode (void)
-{
-#ifdef TARGET_WIN32
- return MONO_JIT_ICALL_mono_string_builder_to_utf16;
-#else
- return MONO_JIT_ICALL_mono_string_builder_to_utf8;
-#endif
-}
-
-static inline MonoJitICallId
-mono_string_builder_from_platform_unicode (void)
-{
-#ifdef TARGET_WIN32
- return MONO_JIT_ICALL_mono_string_utf16_to_builder;
-#else
- return MONO_JIT_ICALL_mono_string_utf8_to_builder;
-#endif
-}
-
-static MonoMarshalConv
-conv_str_inverse (MonoMarshalConv conv)
-{
- switch (conv) {
- // AnsiBStr
- case MONO_MARSHAL_CONV_STR_ANSIBSTR:
- return MONO_MARSHAL_CONV_ANSIBSTR_STR;
- case MONO_MARSHAL_CONV_ANSIBSTR_STR:
- return MONO_MARSHAL_CONV_STR_ANSIBSTR;
-
- // BStr
- case MONO_MARSHAL_CONV_STR_BSTR:
- return MONO_MARSHAL_CONV_BSTR_STR;
- case MONO_MARSHAL_CONV_BSTR_STR:
- return MONO_MARSHAL_CONV_STR_BSTR;
-
- // LPStr
- case MONO_MARSHAL_CONV_STR_LPSTR:
- return MONO_MARSHAL_CONV_LPSTR_STR;
- case MONO_MARSHAL_CONV_LPSTR_STR:
- return MONO_MARSHAL_CONV_STR_LPSTR;
-
- // LPTStr
- case MONO_MARSHAL_CONV_STR_LPTSTR:
- return MONO_MARSHAL_CONV_LPTSTR_STR;
- case MONO_MARSHAL_CONV_LPTSTR_STR:
- return MONO_MARSHAL_CONV_STR_LPTSTR;
-
- // LPUTF8Str
- case MONO_MARSHAL_CONV_STR_UTF8STR:
- return MONO_MARSHAL_CONV_UTF8STR_STR;
- case MONO_MARSHAL_CONV_UTF8STR_STR:
- return MONO_MARSHAL_CONV_STR_UTF8STR;
-
- // LPWStr
- case MONO_MARSHAL_CONV_STR_LPWSTR:
- return MONO_MARSHAL_CONV_LPWSTR_STR;
- case MONO_MARSHAL_CONV_LPWSTR_STR:
- return MONO_MARSHAL_CONV_STR_LPWSTR;
-
- // TBStr
- case MONO_MARSHAL_CONV_STR_TBSTR:
- return MONO_MARSHAL_CONV_TBSTR_STR;
- case MONO_MARSHAL_CONV_TBSTR_STR:
- return MONO_MARSHAL_CONV_STR_TBSTR;
-
- default:
- g_assert_not_reached ();
- }
-}
-
-static MonoJitICallId
-conv_to_icall (MonoMarshalConv conv, int *ind_store_type)
-{
- // FIXME This or its caller might be a good place to inline some
- // of the wrapper logic. In particular, to produce
- // volatile stack-based handles. Being data-driven,
- // from icall-def.h.
-
- int dummy;
- if (!ind_store_type)
- ind_store_type = &dummy;
- *ind_store_type = CEE_STIND_I;
- switch (conv) {
- // AnsiBStr
- case MONO_MARSHAL_CONV_STR_ANSIBSTR:
- return MONO_JIT_ICALL_mono_string_to_ansibstr;
- case MONO_MARSHAL_CONV_ANSIBSTR_STR:
- *ind_store_type = CEE_STIND_REF;
- return MONO_JIT_ICALL_mono_string_from_ansibstr;
-
- // BStr
- case MONO_MARSHAL_CONV_STR_BSTR:
- return MONO_JIT_ICALL_mono_string_to_bstr;
- case MONO_MARSHAL_CONV_BSTR_STR:
- *ind_store_type = CEE_STIND_REF;
- return MONO_JIT_ICALL_mono_string_from_bstr_icall;
-
- // LPStr
- // In Mono, LPSTR was historically treated as UTF8STR
- case MONO_MARSHAL_CONV_STR_LPSTR:
- return MONO_JIT_ICALL_mono_string_to_utf8str;
- case MONO_MARSHAL_CONV_LPSTR_STR:
- *ind_store_type = CEE_STIND_REF;
- return MONO_JIT_ICALL_ves_icall_string_new_wrapper;
- case MONO_MARSHAL_CONV_SB_LPSTR:
- return MONO_JIT_ICALL_mono_string_builder_to_utf8;
- case MONO_MARSHAL_CONV_LPSTR_SB:
- *ind_store_type = CEE_STIND_REF;
- return MONO_JIT_ICALL_mono_string_utf8_to_builder;
-
- // LPTStr
- // FIXME: This is how LPTStr was handled on legacy, but it's not correct and for netcore we should implement this more properly.
- // This type is supposed to detect ANSI or UTF16 (as LPTStr can be either depending on _UNICODE) and handle it accordingly.
- // The CoreCLR test for this type only tests as LPWSTR regardless of platform.
- case MONO_MARSHAL_CONV_STR_LPTSTR:
- return mono_string_to_platform_unicode ();
- case MONO_MARSHAL_CONV_LPTSTR_STR:
- *ind_store_type = CEE_STIND_REF;
- return mono_string_from_platform_unicode ();
- case MONO_MARSHAL_CONV_SB_LPTSTR:
- return mono_string_builder_to_platform_unicode ();
- case MONO_MARSHAL_CONV_LPTSTR_SB:
- *ind_store_type = CEE_STIND_REF;
- return mono_string_builder_from_platform_unicode ();
-
- // LPUTF8Str
- case MONO_MARSHAL_CONV_STR_UTF8STR:
- return MONO_JIT_ICALL_mono_string_to_utf8str;
- case MONO_MARSHAL_CONV_UTF8STR_STR:
- *ind_store_type = CEE_STIND_REF;
- return MONO_JIT_ICALL_ves_icall_string_new_wrapper;
- case MONO_MARSHAL_CONV_SB_UTF8STR:
- return MONO_JIT_ICALL_mono_string_builder_to_utf8;
- case MONO_MARSHAL_CONV_UTF8STR_SB:
- *ind_store_type = CEE_STIND_REF;
- return MONO_JIT_ICALL_mono_string_utf8_to_builder;
-
- // LPWStr
- case MONO_MARSHAL_CONV_STR_LPWSTR:
- return MONO_JIT_ICALL_mono_marshal_string_to_utf16;
- case MONO_MARSHAL_CONV_LPWSTR_STR:
- *ind_store_type = CEE_STIND_REF;
- return MONO_JIT_ICALL_ves_icall_mono_string_from_utf16;
- case MONO_MARSHAL_CONV_SB_LPWSTR:
- return MONO_JIT_ICALL_mono_string_builder_to_utf16;
- case MONO_MARSHAL_CONV_LPWSTR_SB:
- *ind_store_type = CEE_STIND_REF;
- return MONO_JIT_ICALL_mono_string_utf16_to_builder;
-
- // TBStr
- case MONO_MARSHAL_CONV_STR_TBSTR:
- return MONO_JIT_ICALL_mono_string_to_tbstr;
- case MONO_MARSHAL_CONV_TBSTR_STR:
- *ind_store_type = CEE_STIND_REF;
- return MONO_JIT_ICALL_mono_string_from_tbstr;
-
- case MONO_MARSHAL_CONV_STR_BYVALSTR:
- return MONO_JIT_ICALL_mono_string_to_byvalstr;
- case MONO_MARSHAL_CONV_STR_BYVALWSTR:
- return MONO_JIT_ICALL_mono_string_to_byvalwstr;
-
- case MONO_MARSHAL_CONV_DEL_FTN:
- return MONO_JIT_ICALL_mono_delegate_to_ftnptr;
- case MONO_MARSHAL_CONV_FTN_DEL:
- *ind_store_type = CEE_STIND_REF;
- return MONO_JIT_ICALL_mono_ftnptr_to_delegate;
-
- case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
- return MONO_JIT_ICALL_mono_array_to_savearray;
- case MONO_MARSHAL_FREE_ARRAY:
- return MONO_JIT_ICALL_mono_marshal_free_array;
-
- case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
- return MONO_JIT_ICALL_mono_array_to_lparray;
- case MONO_MARSHAL_FREE_LPARRAY:
- return MONO_JIT_ICALL_mono_free_lparray;
-
- default:
- g_assert_not_reached ();
- }
-
- return MONO_JIT_ICALL_ZeroIsReserved;
-}
-
-static void
-emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec)
-{
- int pos;
- int stind_op;
-
- switch (conv) {
- case MONO_MARSHAL_CONV_BOOL_I4:
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_U1);
- mono_mb_emit_byte (mb, CEE_STIND_I4);
- break;
- case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_U1);
- mono_mb_emit_byte (mb, CEE_NEG);
- mono_mb_emit_byte (mb, CEE_STIND_I2);
- break;
- case MONO_MARSHAL_CONV_STR_UTF8STR:
- case MONO_MARSHAL_CONV_STR_LPWSTR:
- case MONO_MARSHAL_CONV_STR_LPSTR:
- case MONO_MARSHAL_CONV_STR_LPTSTR:
- case MONO_MARSHAL_CONV_STR_BSTR:
- case MONO_MARSHAL_CONV_STR_ANSIBSTR:
- case MONO_MARSHAL_CONV_STR_TBSTR: {
- /* free space if free == true */
- mono_mb_emit_ldloc (mb, 2);
- pos = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S);
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall (mb, g_free); // aka monoeg_g_free
- mono_mb_patch_short_branch (mb, pos);
-
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_REF);
- mono_mb_emit_icall_id (mb, conv_to_icall (conv, &stind_op));
- mono_mb_emit_byte (mb, stind_op);
- break;
- }
- case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
- case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
- case MONO_MARSHAL_CONV_DEL_FTN:
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_REF);
- mono_mb_emit_icall_id (mb, conv_to_icall (conv, &stind_op));
- mono_mb_emit_byte (mb, stind_op);
- break;
- case MONO_MARSHAL_CONV_STR_BYVALSTR:
- case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
- g_assert (mspec);
-
- mono_mb_emit_ldloc (mb, 1); /* dst */
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_REF); /* src String */
- mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
- mono_mb_emit_icall_id (mb, conv_to_icall (conv, NULL));
- break;
- }
- case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
- MonoClass *eklass = NULL;
- int esize;
-
- if (type->type == MONO_TYPE_SZARRAY) {
- eklass = type->data.klass;
- } else if (type->type == MONO_TYPE_ARRAY) {
- eklass = type->data.array->eklass;
- g_assert(m_class_is_blittable (eklass));
- } else {
- g_assert_not_reached ();
- }
-
- if (m_class_is_valuetype (eklass))
- esize = mono_class_native_size (eklass, NULL);
- else
- esize = TARGET_SIZEOF_VOID_P;
-
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_REF);
- pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
-
- if (m_class_is_blittable (eklass)) {
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_REF);
- mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoArray, vector));
- mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
- mono_mb_emit_byte (mb, CEE_PREFIX1);
- mono_mb_emit_byte (mb, CEE_CPBLK);
- } else {
- int array_var, src_var, dst_var, index_var;
- guint32 label2, label3;
-
- MonoType *int_type = mono_get_int_type ();
- MonoType *object_type = mono_get_object_type ();
- array_var = mono_mb_add_local (mb, object_type);
- src_var = mono_mb_add_local (mb, int_type);
- dst_var = mono_mb_add_local (mb, int_type);
-
- /* set array_var */
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_REF);
- mono_mb_emit_stloc (mb, array_var);
-
- /* save the old src pointer */
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_stloc (mb, src_var);
- /* save the old dst pointer */
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_stloc (mb, dst_var);
-
- /* Emit marshalling loop */
- index_var = mono_mb_add_local (mb, int_type);
- mono_mb_emit_byte (mb, CEE_LDC_I4_0);
- mono_mb_emit_stloc (mb, index_var);
-
- /* Loop header */
- label2 = mono_mb_get_label (mb);
- mono_mb_emit_ldloc (mb, index_var);
- mono_mb_emit_ldloc (mb, array_var);
- mono_mb_emit_byte (mb, CEE_LDLEN);
- label3 = mono_mb_emit_branch (mb, CEE_BGE);
-
- /* Set src */
- mono_mb_emit_ldloc (mb, array_var);
- mono_mb_emit_ldloc (mb, index_var);
- mono_mb_emit_op (mb, CEE_LDELEMA, eklass);
- mono_mb_emit_stloc (mb, 0);
-
- /* dst is already set */
-
- /* Do the conversion */
- emit_struct_conv (mb, eklass, FALSE);
-
- /* Loop footer */
- mono_mb_emit_add_to_local (mb, index_var, 1);
-
- mono_mb_emit_branch_label (mb, CEE_BR, label2);
-
- mono_mb_patch_branch (mb, label3);
-
- /* restore the old src pointer */
- mono_mb_emit_ldloc (mb, src_var);
- mono_mb_emit_stloc (mb, 0);
- /* restore the old dst pointer */
- mono_mb_emit_ldloc (mb, dst_var);
- mono_mb_emit_stloc (mb, 1);
- }
-
- mono_mb_patch_branch (mb, pos);
- break;
- }
- case MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY: {
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_REF);
- pos = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S);
-
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_REF);
- mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
- mono_mb_emit_icall (mb, mono_array_to_byte_byvalarray);
- mono_mb_patch_short_branch (mb, pos);
- break;
- }
- case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
- int src_var, dst_var;
-
- MonoType *int_type = mono_get_int_type ();
- src_var = mono_mb_add_local (mb, int_type);
- dst_var = mono_mb_add_local (mb, int_type);
-
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
-
- /* save the old src pointer */
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_stloc (mb, src_var);
- /* save the old dst pointer */
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_stloc (mb, dst_var);
-
- /* src = pointer to object data */
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icon (mb, MONO_ABI_SIZEOF (MonoObject));
- mono_mb_emit_byte (mb, CEE_ADD);
- mono_mb_emit_stloc (mb, 0);
-
- emit_struct_conv (mb, mono_class_from_mono_type_internal (type), FALSE);
-
- /* restore the old src pointer */
- mono_mb_emit_ldloc (mb, src_var);
- mono_mb_emit_stloc (mb, 0);
- /* restore the old dst pointer */
- mono_mb_emit_ldloc (mb, dst_var);
- mono_mb_emit_stloc (mb, 1);
-
- mono_mb_patch_branch (mb, pos);
- break;
- }
-
-#ifndef DISABLE_COM
- case MONO_MARSHAL_CONV_OBJECT_INTERFACE:
- case MONO_MARSHAL_CONV_OBJECT_IDISPATCH:
- case MONO_MARSHAL_CONV_OBJECT_IUNKNOWN:
- mono_cominterop_emit_object_to_ptr_conv (mb, type, conv, mspec);
- break;
-#endif /* DISABLE_COM */
-
- case MONO_MARSHAL_CONV_SAFEHANDLE: {
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
- mono_mb_emit_exception (mb, "ArgumentNullException", NULL);
- mono_mb_patch_branch (mb, pos);
-
- /* Pull the handle field from SafeHandle */
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle));
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_byte (mb, CEE_STIND_I);
- break;
- }
+static GENERATE_GET_CLASS_WITH_CACHE (date_time, "System", "DateTime");
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (icustom_marshaler, "System.Runtime.InteropServices", "ICustomMarshaler");
- case MONO_MARSHAL_CONV_HANDLEREF: {
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoHandleRef, handle));
- mono_mb_emit_byte (mb, CEE_ADD);
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_byte (mb, CEE_STIND_I);
- break;
- }
+static MonoImage*
+get_method_image (MonoMethod *method)
+{
+ return m_class_get_image (method->klass);
+}
- default: {
- g_error ("marshalling conversion %d not implemented", conv);
- }
- }
+/**
+ * mono_mb_strdup:
+ * \param mb the MethodBuilder
+ * \param s a string
+ *
+ * Creates a copy of the string \p s that can be referenced from the IL of \c mb.
+ *
+ * \returns a pointer to the new string which is owned by the method builder
+ */
+char*
+mono_mb_strdup (MonoMethodBuilder *mb, const char *s)
+{
+ char *res;
+ if (!mb->dynamic)
+ res = mono_image_strdup (get_method_image (mb->method), s);
+ else
+ res = g_strdup (s);
+ return res;
}
#ifndef DISABLE_COM
@@ -1043,7 +94,7 @@ static MonoMethod*
mono_get_Variant_Clear (void)
{
MONO_STATIC_POINTER_INIT (MonoMethod, variant_clear)
- variant_clear = get_method_nofail (mono_class_get_variant_class (), "Clear", 0, 0);
+ variant_clear = mono_marshal_shared_get_method_nofail (mono_class_get_variant_class (), "Clear", 0, 0);
MONO_STATIC_POINTER_INIT_END (MonoMethod, variant_clear)
g_assert (variant_clear);
@@ -1058,7 +109,7 @@ static MonoMethod*
mono_get_Marshal_GetObjectForNativeVariant (void)
{
MONO_STATIC_POINTER_INIT (MonoMethod, get_object_for_native_variant)
- get_object_for_native_variant = get_method_nofail (mono_defaults.marshal_class, "GetObjectForNativeVariant", 1, 0);
+ get_object_for_native_variant = mono_marshal_shared_get_method_nofail (mono_defaults.marshal_class, "GetObjectForNativeVariant", 1, 0);
MONO_STATIC_POINTER_INIT_END (MonoMethod, get_object_for_native_variant)
g_assert (get_object_for_native_variant);
@@ -1071,254 +122,13 @@ static MonoMethod*
mono_get_Marshal_GetNativeVariantForObject (void)
{
MONO_STATIC_POINTER_INIT (MonoMethod, get_native_variant_for_object)
- get_native_variant_for_object = get_method_nofail (mono_defaults.marshal_class, "GetNativeVariantForObject", 2, 0);
+ get_native_variant_for_object = mono_marshal_shared_get_method_nofail (mono_defaults.marshal_class, "GetNativeVariantForObject", 2, 0);
MONO_STATIC_POINTER_INIT_END (MonoMethod, get_native_variant_for_object)
g_assert (get_native_variant_for_object);
return get_native_variant_for_object;
}
-static void
-emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object,
- int offset_of_first_child_field, MonoMarshalNative string_encoding)
-{
- MonoMarshalType *info;
- int i;
-
- if (m_class_get_parent (klass))
- emit_struct_conv_full (mb, m_class_get_parent (klass), to_object, offset_of_first_nonstatic_field (klass), string_encoding);
-
- info = mono_marshal_load_type_info (klass);
-
- if (info->native_size == 0)
- return;
-
- if (m_class_is_blittable (klass)) {
- int usize = mono_class_value_size (klass, NULL);
- g_assert (usize == info->native_size);
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_icon (mb, usize);
- mono_mb_emit_byte (mb, CEE_PREFIX1);
- mono_mb_emit_byte (mb, CEE_CPBLK);
-
- if (to_object) {
- mono_mb_emit_add_to_local (mb, 0, usize);
- mono_mb_emit_add_to_local (mb, 1, offset_of_first_child_field);
- } else {
- mono_mb_emit_add_to_local (mb, 0, offset_of_first_child_field);
- mono_mb_emit_add_to_local (mb, 1, usize);
- }
- return;
- }
-
- if (klass != mono_class_try_get_safehandle_class ()) {
- if (mono_class_is_auto_layout (klass)) {
- char *msg = g_strdup_printf ("Type %s which is passed to unmanaged code must have a StructLayout attribute.",
- mono_type_full_name (m_class_get_byval_arg (klass)));
- mono_mb_emit_exception_marshal_directive (mb, msg);
- return;
- }
- }
-
- for (i = 0; i < info->num_fields; i++) {
- MonoMarshalNative ntype;
- MonoMarshalConv conv;
- MonoType *ftype = info->fields [i].field->type;
- int msize = 0;
- int usize = 0;
- gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
-
- if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
- continue;
-
- ntype = (MonoMarshalNative)mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, m_class_is_unicode (klass), &conv);
-
- if (last_field) {
- msize = m_class_get_instance_size (klass) - m_field_get_offset (info->fields [i].field);
- usize = info->native_size - info->fields [i].offset;
- } else {
- msize = m_field_get_offset (info->fields [i + 1].field) - m_field_get_offset (info->fields [i].field);
- usize = info->fields [i + 1].offset - info->fields [i].offset;
- }
-
- if (klass != mono_class_try_get_safehandle_class ()){
- /*
- * FIXME: Should really check for usize==0 and msize>0, but we apply
- * the layout to the managed structure as well.
- */
-
- if (mono_class_is_explicit_layout (klass) && (usize == 0)) {
- if (MONO_TYPE_IS_REFERENCE (info->fields [i].field->type) ||
- ((!last_field && MONO_TYPE_IS_REFERENCE (info->fields [i + 1].field->type))))
- g_error ("Type %s which has an [ExplicitLayout] attribute cannot have a "
- "reference field at the same offset as another field.",
- mono_type_full_name (m_class_get_byval_arg (klass)));
- }
- }
-
- switch (conv) {
- case MONO_MARSHAL_CONV_NONE: {
- int t;
-
- //XXX a byref field!?!? that's not allowed! and worse, it might miss a WB
- g_assert (!m_type_is_byref (ftype));
- if (ftype->type == MONO_TYPE_I || ftype->type == MONO_TYPE_U) {
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_byte (mb, CEE_STIND_I);
- break;
- }
-
- handle_enum:
- t = ftype->type;
- switch (t) {
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- case MONO_TYPE_BOOLEAN:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_CHAR:
- case MONO_TYPE_I8:
- case MONO_TYPE_U8:
- case MONO_TYPE_PTR:
- case MONO_TYPE_R4:
- case MONO_TYPE_R8:
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- if (t == MONO_TYPE_CHAR && ntype == MONO_NATIVE_U1 && string_encoding != MONO_NATIVE_LPWSTR) {
- if (to_object) {
- mono_mb_emit_byte (mb, CEE_LDIND_U1);
- mono_mb_emit_byte (mb, CEE_STIND_I2);
- } else {
- mono_mb_emit_byte (mb, CEE_LDIND_U2);
- mono_mb_emit_byte (mb, CEE_STIND_I1);
- }
- } else {
- mono_mb_emit_byte (mb, mono_type_to_ldind (ftype));
- mono_mb_emit_byte (mb, mono_type_to_stind (ftype));
- }
- break;
- case MONO_TYPE_GENERICINST:
- if (!mono_type_generic_inst_is_valuetype (ftype)) {
- char *msg = g_strdup_printf ("Generic type %s cannot be marshaled as field in a struct.",
- mono_type_full_name (ftype));
- mono_mb_emit_exception_marshal_directive (mb, msg);
- break;
- }
- /* fall through */
- case MONO_TYPE_VALUETYPE: {
- int src_var, dst_var;
- MonoType *etype;
- int len;
-
- if (t == MONO_TYPE_VALUETYPE && m_class_is_enumtype (ftype->data.klass)) {
- ftype = mono_class_enum_basetype_internal (ftype->data.klass);
- goto handle_enum;
- }
-
- MonoType *int_type = mono_get_int_type ();
- src_var = mono_mb_add_local (mb, int_type);
- dst_var = mono_mb_add_local (mb, int_type);
-
- /* save the old src pointer */
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_stloc (mb, src_var);
- /* save the old dst pointer */
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_stloc (mb, dst_var);
-
- if (get_fixed_buffer_attr (info->fields [i].field, &etype, &len)) {
- emit_fixed_buf_conv (mb, ftype, etype, len, to_object, &usize);
- } else {
- emit_struct_conv (mb, mono_class_from_mono_type_internal (ftype), to_object);
- }
-
- /* restore the old src pointer */
- mono_mb_emit_ldloc (mb, src_var);
- mono_mb_emit_stloc (mb, 0);
- /* restore the old dst pointer */
- mono_mb_emit_ldloc (mb, dst_var);
- mono_mb_emit_stloc (mb, 1);
- break;
- }
- case MONO_TYPE_OBJECT: {
-#ifndef DISABLE_COM
- if (to_object) {
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_managed_call (mb, mono_get_Marshal_GetObjectForNativeVariant (), NULL);
- mono_mb_emit_byte (mb, CEE_STIND_REF);
-
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_managed_call (mb, mono_get_Variant_Clear (), NULL);
- }
- else {
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_byte(mb, CEE_LDIND_REF);
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_managed_call (mb, mono_get_Marshal_GetNativeVariantForObject (), NULL);
- }
-#else
- char *msg = g_strdup_printf ("COM support was disabled at compilation time.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
-#endif
- break;
- }
-
- default:
- g_warning ("marshaling type %02x not implemented", ftype->type);
- g_assert_not_reached ();
- }
- break;
- }
- default: {
- int src_var, dst_var;
-
- MonoType *int_type = mono_get_int_type ();
- src_var = mono_mb_add_local (mb, int_type);
- dst_var = mono_mb_add_local (mb, int_type);
-
- /* save the old src pointer */
- mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_stloc (mb, src_var);
- /* save the old dst pointer */
- mono_mb_emit_ldloc (mb, 1);
- mono_mb_emit_stloc (mb, dst_var);
-
- if (to_object)
- emit_ptr_to_object_conv (mb, ftype, conv, info->fields [i].mspec);
- else
- emit_object_to_ptr_conv (mb, ftype, conv, info->fields [i].mspec);
-
- /* restore the old src pointer */
- mono_mb_emit_ldloc (mb, src_var);
- mono_mb_emit_stloc (mb, 0);
- /* restore the old dst pointer */
- mono_mb_emit_ldloc (mb, dst_var);
- mono_mb_emit_stloc (mb, 1);
- }
- }
-
- if (to_object) {
- mono_mb_emit_add_to_local (mb, 0, usize);
- mono_mb_emit_add_to_local (mb, 1, msize);
- } else {
- mono_mb_emit_add_to_local (mb, 0, msize);
- mono_mb_emit_add_to_local (mb, 1, usize);
- }
- }
-}
-
-static void
-emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
-{
- emit_struct_conv_full (mb, klass, to_object, 0, (MonoMarshalNative)-1);
-}
-
static void
emit_struct_free (MonoMethodBuilder *mb, MonoClass *klass, int struct_var)
{
@@ -1330,40 +140,6 @@ emit_struct_free (MonoMethodBuilder *mb, MonoClass *klass, int struct_var)
mono_mb_emit_icall (mb, mono_struct_delete_old);
}
-static void
-emit_thread_interrupt_checkpoint_call (MonoMethodBuilder *mb, MonoJitICallId checkpoint_icall_id)
-{
- int pos_noabort, pos_noex;
-
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_byte (mb, CEE_MONO_LDPTR_INT_REQ_FLAG);
- mono_mb_emit_no_nullcheck (mb);
- mono_mb_emit_byte (mb, CEE_LDIND_U4);
- pos_noabort = mono_mb_emit_branch (mb, CEE_BRFALSE);
-
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_byte (mb, CEE_MONO_NOT_TAKEN);
-
- mono_mb_emit_icall_id (mb, checkpoint_icall_id);
- /* Throw the exception returned by the checkpoint function, if any */
- mono_mb_emit_byte (mb, CEE_DUP);
- pos_noex = mono_mb_emit_branch (mb, CEE_BRFALSE);
-
- mono_mb_emit_byte (mb, CEE_DUP);
- mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoException, caught_in_unmanaged));
- mono_mb_emit_byte (mb, CEE_LDC_I4_1);
- mono_mb_emit_no_nullcheck (mb);
- mono_mb_emit_byte (mb, CEE_STIND_I4);
-
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_byte (mb, CEE_MONO_RETHROW);
-
- mono_mb_patch_branch (mb, pos_noex);
- mono_mb_emit_byte (mb, CEE_POP);
-
- mono_mb_patch_branch (mb, pos_noabort);
-}
-
static void
emit_thread_interrupt_checkpoint (MonoMethodBuilder *mb)
{
@@ -1371,13 +147,13 @@ emit_thread_interrupt_checkpoint (MonoMethodBuilder *mb)
if (strstr (mb->name, "mono_thread_interruption_checkpoint"))
return;
- emit_thread_interrupt_checkpoint_call (mb, MONO_JIT_ICALL_mono_thread_interruption_checkpoint);
+ mono_marshal_shared_emit_thread_interrupt_checkpoint_call (mb, MONO_JIT_ICALL_mono_thread_interruption_checkpoint);
}
static void
emit_thread_force_interrupt_checkpoint (MonoMethodBuilder *mb)
{
- emit_thread_interrupt_checkpoint_call (mb, MONO_JIT_ICALL_mono_thread_force_interruption_checkpoint_noraise);
+ mono_marshal_shared_emit_thread_interrupt_checkpoint_call (mb, MONO_JIT_ICALL_mono_thread_force_interruption_checkpoint_noraise);
}
void
@@ -1866,13 +642,6 @@ emit_runtime_invoke_dynamic_ilgen (MonoMethodBuilder *mb)
mono_mb_emit_byte (mb, CEE_RET);
}
-static void
-mono_mb_emit_auto_layout_exception (MonoMethodBuilder *mb, MonoClass *klass)
-{
- char *msg = g_strdup_printf ("The type `%s.%s' layout needs to be Sequential or Explicit", m_class_get_name_space (klass), m_class_get_name (klass));
- mono_mb_emit_exception_marshal_directive (mb, msg);
-}
-
typedef struct EmitGCSafeTransitionBuilder {
MonoMethodBuilder *mb;
gboolean func_param;
@@ -2071,7 +840,7 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi
MonoType *int_type = mono_get_int_type ();
MonoType *boolean_type = m_class_get_byval_arg (mono_defaults.boolean_class);
- /* we allocate local for use with emit_struct_conv() */
+ /* we allocate local for use with mono_marshal_shared_emit_struct_conv() */
/* allocate local 0 (pointer) src_ptr */
mono_mb_add_local (mb, int_type);
/* allocate local 1 (pointer) dst_ptr */
@@ -2151,7 +920,7 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi
// Check if SetLastError usage is valid early so we don't try to throw an exception after transitioning GC modes.
if (piinfo && (piinfo->piflags & PINVOKE_ATTRIBUTE_SUPPORTS_LAST_ERROR) && !m.runtime_marshalling_enabled)
- mono_mb_emit_exception_marshal_directive(mb, g_strdup("Setting SetLastError=true is not supported when runtime marshalling is disabled."));
+ mono_marshal_shared_mb_emit_exception_marshal_directive(mb, g_strdup("Setting SetLastError=true is not supported when runtime marshalling is disabled."));
/* we first do all conversions */
tmp_locals = g_newa (int, sig->param_count);
@@ -2499,12 +1268,12 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_ldarg (mb, argnum);
if (m_type_is_byref (t))
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall_id (mb, conv_to_icall (MONO_MARSHAL_CONV_ARRAY_LPARRAY, NULL));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_ARRAY_LPARRAY, NULL));
mono_mb_emit_stloc (mb, conv_arg);
} else {
#ifdef DISABLE_NONBLITTABLE
char *msg = g_strdup ("Non-blittable marshalling conversion is disabled");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
#else
guint32 label1, label2, label3;
int index_var, src_var, dest_ptr, esize;
@@ -2526,7 +1295,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (is_string && conv == MONO_MARSHAL_CONV_INVALID) {
char *msg = g_strdup_printf ("string/stringbuilder marshalling conversion %d not implemented", encoding);
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
break;
}
@@ -2585,7 +1354,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_ldloc (mb, src_var);
mono_mb_emit_ldloc (mb, index_var);
mono_mb_emit_byte (mb, CEE_LDELEM_REF);
- mono_mb_emit_icall_id (mb, conv_to_icall (conv, &stind_op));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, &stind_op));
mono_mb_emit_byte (mb, stind_op);
} else {
/* set the src_ptr */
@@ -2599,7 +1368,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_stloc (mb, 1);
/* emit valuetype conversion code */
- emit_struct_conv_full (mb, eklass, FALSE, 0, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
+ mono_marshal_shared_emit_struct_conv_full (mb, eklass, FALSE, 0, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
}
mono_mb_emit_add_to_local (mb, index_var, 1);
@@ -2637,7 +1406,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (m_type_is_byref (param_type) && param_type->type != MONO_TYPE_I4) {
char *msg = g_strdup ("Not implemented.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
break;
}
@@ -2710,7 +1479,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_ldloc (mb, src_ptr);
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall_id (mb, conv_to_icall (conv, NULL));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL));
if (need_free) {
/* src */
@@ -2744,7 +1513,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_stloc (mb, 1);
/* emit valuetype conversion code */
- emit_struct_conv_full (mb, eklass, TRUE, 0, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
+ mono_marshal_shared_emit_struct_conv_full (mb, eklass, TRUE, 0, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
}
if (need_free) {
@@ -2772,7 +1541,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (m_type_is_byref (t))
mono_mb_emit_byte (mb, CEE_LDIND_REF);
mono_mb_emit_ldloc (mb, conv_arg);
- mono_mb_emit_icall_id (mb, conv_to_icall (MONO_MARSHAL_FREE_LPARRAY, NULL));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_FREE_LPARRAY, NULL));
}
break;
@@ -2788,7 +1557,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
case MARSHAL_ACTION_CONV_RESULT: {
mono_mb_emit_byte (mb, CEE_POP);
char *msg = g_strdup_printf ("Cannot marshal 'return value': Invalid managed/unmanaged type combination.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
break;
}
@@ -2803,12 +1572,12 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (m_type_is_byref (t)) {
char *msg = g_strdup ("Byref array marshalling to managed code is not implemented.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
return conv_arg;
}
if (!spec) {
char *msg = g_strdup ("[MarshalAs] attribute required to marshal arrays to managed code.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
return conv_arg;
}
@@ -2819,14 +1588,14 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
#ifndef DISABLE_COM
if (spec->data.safearray_data.elem_type != MONO_VARIANT_VARIANT) {
char *msg = g_strdup ("Only SAFEARRAY(VARIANT) marshalling to managed code is implemented.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
return conv_arg;
}
return mono_cominterop_emit_marshal_safearray (m, argnum, t, spec, conv_arg, conv_arg_type, action);
#endif
default: {
char *msg = g_strdup ("Unsupported array type marshalling to managed code.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
return conv_arg;
}
}
@@ -2843,7 +1612,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (param_num == -1) {
if (num_elem <= 0) {
char *msg = g_strdup ("Either SizeConst or SizeParamIndex should be specified when marshalling arrays to managed code.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
return conv_arg;
}
}
@@ -2880,7 +1649,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (param_num != -1) {
if (param_num >= m->sig->param_count) {
char *msg = g_strdup ("Array size control parameter index is out of range.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
return conv_arg;
}
switch (m->sig->params [param_num]->type) {
@@ -2897,7 +1666,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
break;
default: {
char *msg = g_strdup ("Array size control parameter must be an integral type.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
return conv_arg;
}
}
@@ -2949,7 +1718,7 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
#ifdef DISABLE_NONBLITTABLE
else {
char *msg = g_strdup ("Non-blittable marshalling conversion is disabled");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
}
#else
/* Emit marshalling loop */
@@ -2972,12 +1741,12 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_ldloc (mb, src_ptr);
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall_id (mb, conv_to_icall (conv, NULL));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL));
mono_mb_emit_byte (mb, CEE_STELEM_REF);
}
else {
char *msg = g_strdup ("Marshalling of non-string and non-blittable arrays to managed code is not implemented.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
return conv_arg;
}
@@ -3095,12 +1864,12 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_byte (mb, CEE_LDELEM_REF);
- mono_mb_emit_icall_id (mb, conv_to_icall (conv, &stind_op));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, &stind_op));
mono_mb_emit_byte (mb, stind_op);
}
else {
char *msg = g_strdup ("Marshalling of non-string and non-blittable arrays to managed code is not implemented.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
return conv_arg;
}
@@ -3192,12 +1961,12 @@ emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_byte (mb, CEE_LDELEM_REF);
- mono_mb_emit_icall_id (mb, conv_to_icall (conv, &stind_op));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, &stind_op));
mono_mb_emit_byte (mb, stind_op);
}
else {
char *msg = g_strdup ("Marshalling of non-string arrays to managed code is not implemented.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
return conv_arg;
}
@@ -3230,7 +1999,7 @@ emit_marshal_ptr_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
/*
if (MONO_TYPE_ISSTRUCT (t->data.type) && !mono_class_from_mono_type_internal (t->data.type)->blittable) {
char *msg = g_strdup_printf ("Can not marshal 'parameter #%d': Pointers can not reference marshaled structures. Use byref instead.", argnum + 1);
- mono_mb_emit_exception_marshal_directive (m->mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (m->mb, msg);
}
*/
break;
@@ -4577,26 +3346,6 @@ emit_thunk_invoke_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethod *method, Mono
mono_mb_emit_byte (mb, CEE_RET);
}
-static void
-emit_marshal_custom_get_instance (MonoMethodBuilder *mb, MonoClass *klass, MonoMarshalSpec *spec)
-{
- MONO_STATIC_POINTER_INIT (MonoMethod, get_instance)
-
- MonoClass *Marshal = mono_class_try_get_marshal_class ();
- g_assert (Marshal);
- get_instance = get_method_nofail (Marshal, "GetCustomMarshalerInstance", 2, 0);
- g_assert (get_instance);
-
- MONO_STATIC_POINTER_INIT_END (MonoClass, get_instance)
-
- // HACK: We cannot use ldtoken in this type of wrapper.
- mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass);
- mono_mb_emit_icall (mb, mono_marshal_get_type_object);
- mono_mb_emit_ldstr (mb, g_strdup (spec->data.custom_data.cookie));
-
- mono_mb_emit_op (mb, CEE_CALL, get_instance);
-}
static int
emit_marshal_custom_ilgen_throw_exception (MonoMethodBuilder *mb, const char *exc_nspace, const char *exc_name, const char *msg, MarshalAction action)
@@ -4648,16 +3397,16 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (!klass)
return emit_marshal_custom_ilgen_throw_exception (mb, "System", "ApplicationException", g_strdup ("Current profile doesn't support ICustomMarshaler"), action);
- cleanup_native = get_method_nofail (klass, "CleanUpNativeData", 1, 0);
+ cleanup_native = mono_marshal_shared_get_method_nofail (klass, "CleanUpNativeData", 1, 0);
g_assert (cleanup_native);
- cleanup_managed = get_method_nofail (klass, "CleanUpManagedData", 1, 0);
+ cleanup_managed = mono_marshal_shared_get_method_nofail (klass, "CleanUpManagedData", 1, 0);
g_assert (cleanup_managed);
- marshal_managed_to_native = get_method_nofail (klass, "MarshalManagedToNative", 1, 0);
+ marshal_managed_to_native = mono_marshal_shared_get_method_nofail (klass, "MarshalManagedToNative", 1, 0);
g_assert (marshal_managed_to_native);
- marshal_native_to_managed = get_method_nofail (klass, "MarshalNativeToManaged", 1, 0);
+ marshal_native_to_managed = mono_marshal_shared_get_method_nofail (klass, "MarshalNativeToManaged", 1, 0);
g_assert (marshal_native_to_managed);
mono_memory_barrier ();
@@ -4710,7 +3459,7 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_byte (mb, CEE_LDIND_I);
pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
- emit_marshal_custom_get_instance (mb, mklass, spec);
+ mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec);
mono_mb_emit_ldarg (mb, argnum);
if (m_type_is_byref (t))
@@ -4740,7 +3489,7 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_OUT)) {
mono_mb_emit_ldarg (mb, argnum);
- emit_marshal_custom_get_instance (mb, mklass, spec);
+ mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec);
mono_mb_emit_byte (mb, CEE_DUP);
mono_mb_emit_ldarg (mb, argnum);
@@ -4753,13 +3502,13 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
} else if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
mono_mb_emit_ldarg (mb, argnum);
- emit_marshal_custom_get_instance (mb, mklass, spec);
+ mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec);
mono_mb_emit_ldloc (mb, conv_arg);
mono_mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed);
mono_mb_emit_byte (mb, CEE_STIND_REF);
} else if (t->attrs & PARAM_ATTRIBUTE_OUT) {
- emit_marshal_custom_get_instance (mb, mklass, spec);
+ mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec);
mono_mb_emit_ldloc (mb, conv_arg);
mono_mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed);
@@ -4770,7 +3519,7 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
// Only call cleanup_native if MARSHAL_ACTION_CONV_IN called marshal_managed_to_native.
if (!(m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT)) &&
!(!m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT) && !(t->attrs & PARAM_ATTRIBUTE_IN))) {
- emit_marshal_custom_get_instance (mb, mklass, spec);
+ mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec);
mono_mb_emit_ldloc (mb, conv_arg);
@@ -4794,7 +3543,7 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_ldloc (mb, 3);
pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
- emit_marshal_custom_get_instance (mb, mklass, spec);
+ mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec);
mono_mb_emit_ldloc (mb, 3);
mono_mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed);
@@ -4834,7 +3583,7 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_byte (mb, CEE_LDIND_I);
pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
- emit_marshal_custom_get_instance (mb, mklass, spec);
+ mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec);
mono_mb_emit_ldarg (mb, argnum);
if (m_type_is_byref (t))
@@ -4860,7 +3609,7 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_ldloc (mb, 3);
pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
- emit_marshal_custom_get_instance (mb, mklass, spec);
+ mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec);
mono_mb_emit_byte (mb, CEE_DUP);
mono_mb_emit_ldloc (mb, 3);
@@ -4882,7 +3631,7 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (m_type_is_byref (t)) {
mono_mb_emit_ldarg (mb, argnum);
- emit_marshal_custom_get_instance (mb, mklass, spec);
+ mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec);
mono_mb_emit_ldloc (mb, conv_arg);
mono_mb_emit_op (mb, CEE_CALLVIRT, marshal_managed_to_native);
@@ -4891,7 +3640,7 @@ emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
// Only call cleanup_managed if MARSHAL_ACTION_MANAGED_CONV_IN called marshal_native_to_managed.
if (!(m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT))) {
- emit_marshal_custom_get_instance (mb, mklass, spec);
+ mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec);
mono_mb_emit_ldloc (mb, conv_arg);
mono_mb_emit_op (mb, CEE_CALLVIRT, cleanup_managed);
}
@@ -4985,7 +3734,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
m->csig->params [argnum - m->csig->hasthis] = double_type;
MONO_STATIC_POINTER_INIT (MonoMethod, to_oadate)
- to_oadate = get_method_nofail (date_time_class, "ToOADate", 0, 0);
+ to_oadate = mono_marshal_shared_get_method_nofail (date_time_class, "ToOADate", 0, 0);
g_assert (to_oadate);
MONO_STATIC_POINTER_INIT_END (MonoMethod, to_oadate)
@@ -5030,7 +3779,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_stloc (mb, 1);
/* emit valuetype conversion code */
- emit_struct_conv (mb, klass, FALSE);
+ mono_marshal_shared_emit_struct_conv (mb, klass, FALSE);
}
if (m_type_is_byref (t))
@@ -5081,7 +3830,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (!((t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT))) {
MONO_STATIC_POINTER_INIT (MonoMethod, from_oadate)
- from_oadate = get_method_nofail (date_time_class, "FromOADate", 1, 0);
+ from_oadate = mono_marshal_shared_get_method_nofail (date_time_class, "FromOADate", 1, 0);
MONO_STATIC_POINTER_INIT_END (MonoMethod, from_oadate)
g_assert (from_oadate);
@@ -5111,7 +3860,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_stloc (mb, 0);
/* emit valuetype conversion code */
- emit_struct_conv (mb, klass, TRUE);
+ mono_marshal_shared_emit_struct_conv (mb, klass, TRUE);
}
}
@@ -5137,7 +3886,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_stloc (mb, 1);
/* emit valuetype conversion code */
- emit_struct_conv (mb, klass, TRUE);
+ mono_marshal_shared_emit_struct_conv (mb, klass, TRUE);
break;
case MARSHAL_ACTION_MANAGED_CONV_IN:
@@ -5166,7 +3915,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_stloc (mb, 1);
/* emit valuetype conversion code */
- emit_struct_conv (mb, klass, TRUE);
+ mono_marshal_shared_emit_struct_conv (mb, klass, TRUE);
if (m_type_is_byref (t))
mono_mb_patch_branch (mb, pos);
@@ -5191,7 +3940,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_stloc (mb, 1);
/* emit valuetype conversion code */
- emit_struct_conv (mb, klass, FALSE);
+ mono_marshal_shared_emit_struct_conv (mb, klass, FALSE);
mono_mb_patch_branch (mb, pos2);
break;
@@ -5222,7 +3971,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_stloc (mb, m->retobj_var);
/* emit valuetype conversion code */
- emit_struct_conv (mb, klass, FALSE);
+ mono_marshal_shared_emit_struct_conv (mb, klass, FALSE);
break;
default:
@@ -5231,7 +3980,7 @@ emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
return conv_arg;
}
-static inline void
+static void
emit_string_free_icall (MonoMethodBuilder *mb, MonoMarshalConv conv)
{
if (conv == MONO_MARSHAL_CONV_BSTR_STR || conv == MONO_MARSHAL_CONV_ANSIBSTR_STR || conv == MONO_MARSHAL_CONV_TBSTR_STR)
@@ -5270,9 +4019,9 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (conv == MONO_MARSHAL_CONV_INVALID) {
char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
} else {
- mono_mb_emit_icall_id (mb, conv_to_icall (conv, NULL));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL));
mono_mb_emit_stloc (mb, conv_arg);
}
@@ -5282,7 +4031,7 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
conv = mono_marshal_get_ptr_to_string_conv (m->piinfo, spec, &need_free);
if (conv == MONO_MARSHAL_CONV_INVALID) {
char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
break;
}
@@ -5290,13 +4039,13 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (!m_type_is_byref (t)) {
char *msg = g_strdup ("VBByRefStr marshalling requires a ref parameter.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
break;
}
MONO_STATIC_POINTER_INIT (MonoMethod, method)
- method = get_method_nofail (mono_defaults.string_class, "get_Length", -1, 0);
+ method = mono_marshal_shared_get_method_nofail (mono_defaults.string_class, "get_Length", -1, 0);
MONO_STATIC_POINTER_INIT_END (MonoMethod, method)
@@ -5316,7 +4065,7 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
int stind_op;
mono_mb_emit_ldarg (mb, argnum);
mono_mb_emit_ldloc (mb, conv_arg);
- mono_mb_emit_icall_id (mb, conv_to_icall (conv, &stind_op));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, &stind_op));
mono_mb_emit_byte (mb, stind_op);
need_free = TRUE;
}
@@ -5340,12 +4089,12 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
conv = mono_marshal_get_ptr_to_string_conv (m->piinfo, spec, &need_free);
if (conv == MONO_MARSHAL_CONV_INVALID) {
char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
break;
}
mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_icall_id (mb, conv_to_icall (conv, NULL));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL));
mono_mb_emit_stloc (mb, 3);
/* free the string */
@@ -5366,14 +4115,14 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
conv = mono_marshal_get_ptr_to_string_conv (m->piinfo, spec, &need_free);
if (conv == MONO_MARSHAL_CONV_INVALID) {
char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
break;
}
mono_mb_emit_ldarg (mb, argnum);
if (m_type_is_byref (t))
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall_id (mb, conv_to_icall (conv, NULL));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL));
mono_mb_emit_stloc (mb, conv_arg);
break;
@@ -5383,18 +4132,18 @@ emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
int stind_op;
mono_mb_emit_ldarg (mb, argnum);
mono_mb_emit_ldloc (mb, conv_arg);
- mono_mb_emit_icall_id (mb, conv_to_icall (conv, &stind_op));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, &stind_op));
mono_mb_emit_byte (mb, stind_op);
}
}
break;
case MARSHAL_ACTION_MANAGED_CONV_RESULT:
- if (conv_to_icall (conv, NULL) == MONO_JIT_ICALL_mono_marshal_string_to_utf16)
+ if (mono_marshal_shared_conv_to_icall (conv, NULL) == MONO_JIT_ICALL_mono_marshal_string_to_utf16)
/* We need to make a copy so the caller is able to free it */
mono_mb_emit_icall (mb, mono_marshal_string_to_utf16_copy);
else
- mono_mb_emit_icall_id (mb, conv_to_icall (conv, NULL));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL));
mono_mb_emit_stloc (mb, 3);
break;
@@ -5421,8 +4170,8 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
conv_arg = mono_mb_add_local (mb, int_type);
*conv_arg_type = int_type;
- if (!sh_dangerous_add_ref)
- init_safe_handle ();
+ if (!*mono_marshal_shared_get_sh_dangerous_add_ref())
+ mono_marshal_shared_init_safe_handle ();
mono_mb_emit_ldarg (mb, argnum);
pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
@@ -5440,7 +4189,7 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (m_type_is_byref (t)) {
int old_handle_value_slot = mono_mb_add_local (mb, int_type);
- if (!is_in (t)) {
+ if (!mono_marshal_shared_is_in (t)) {
mono_mb_emit_icon (mb, 0);
mono_mb_emit_stloc (mb, conv_arg);
} else {
@@ -5448,7 +4197,7 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_ldarg (mb, argnum);
mono_mb_emit_byte (mb, CEE_LDIND_REF);
mono_mb_emit_ldloc_addr (mb, dar_release_slot);
- mono_mb_emit_managed_call (mb, sh_dangerous_add_ref, NULL);
+ mono_mb_emit_managed_call (mb, *mono_marshal_shared_get_sh_dangerous_add_ref(), NULL);
/* Pull the handle field from SafeHandle */
mono_mb_emit_ldarg (mb, argnum);
@@ -5463,7 +4212,7 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
/* safehandle.DangerousAddRef (ref release) */
mono_mb_emit_ldarg (mb, argnum);
mono_mb_emit_ldloc_addr (mb, dar_release_slot);
- mono_mb_emit_managed_call (mb, sh_dangerous_add_ref, NULL);
+ mono_mb_emit_managed_call (mb, *mono_marshal_shared_get_sh_dangerous_add_ref(), NULL);
/* Pull the handle field from SafeHandle */
mono_mb_emit_ldarg (mb, argnum);
@@ -5487,21 +4236,21 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
int dar_release_slot = conv_arg + 1;
int label_next = 0;
- if (!sh_dangerous_release)
- init_safe_handle ();
+ if (!*mono_marshal_shared_get_sh_dangerous_release())
+ mono_marshal_shared_init_safe_handle ();
if (m_type_is_byref (t)) {
/* If there was SafeHandle on input we have to release the reference to it */
- if (is_in (t)) {
+ if (mono_marshal_shared_is_in (t)) {
mono_mb_emit_ldloc (mb, dar_release_slot);
label_next = mono_mb_emit_branch (mb, CEE_BRFALSE);
mono_mb_emit_ldarg (mb, argnum);
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_managed_call (mb, sh_dangerous_release, NULL);
+ mono_mb_emit_managed_call (mb, *mono_marshal_shared_get_sh_dangerous_release (), NULL);
mono_mb_patch_branch (mb, label_next);
}
- if (is_out (t)) {
+ if (mono_marshal_shared_is_out (t)) {
ERROR_DECL (local_error);
MonoMethod *ctor;
@@ -5509,7 +4258,7 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
* If the SafeHandle was marshalled on input we can skip the marshalling on
* output if the handle value is identical.
*/
- if (is_in (t)) {
+ if (mono_marshal_shared_is_in (t)) {
int old_handle_value_slot = dar_release_slot + 1;
mono_mb_emit_ldloc (mb, old_handle_value_slot);
mono_mb_emit_ldloc (mb, conv_arg);
@@ -5542,7 +4291,7 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_ldloc (mb, conv_arg);
mono_mb_emit_byte (mb, CEE_STIND_I);
- if (is_in (t) && label_next) {
+ if (mono_marshal_shared_is_in (t) && label_next) {
mono_mb_patch_branch (mb, label_next);
}
}
@@ -5550,7 +4299,7 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_ldloc (mb, dar_release_slot);
label_next = mono_mb_emit_branch (mb, CEE_BRFALSE);
mono_mb_emit_ldarg (mb, argnum);
- mono_mb_emit_managed_call (mb, sh_dangerous_release, NULL);
+ mono_mb_emit_managed_call (mb, *mono_marshal_shared_get_sh_dangerous_release (), NULL);
mono_mb_patch_branch (mb, label_next);
}
break;
@@ -5563,7 +4312,7 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (mono_class_is_abstract (t->data.klass)) {
mono_mb_emit_byte (mb, CEE_POP);
- mono_mb_emit_exception_marshal_directive (mb, g_strdup ("Returned SafeHandles should not be abstract"));
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, g_strdup ("Returned SafeHandles should not be abstract"));
break;
}
@@ -5607,7 +4356,6 @@ emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
return conv_arg;
}
-
static int
emit_marshal_handleref_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
MonoMarshalSpec *spec, int conv_arg,
@@ -5623,7 +4371,7 @@ emit_marshal_handleref_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (m_type_is_byref (t)) {
char *msg = g_strdup ("HandleRefs can not be returned from unmanaged code (or passed by ref)");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
break;
}
mono_mb_emit_ldarg_addr (mb, argnum);
@@ -5645,7 +4393,7 @@ emit_marshal_handleref_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
case MARSHAL_ACTION_CONV_RESULT: {
char *msg = g_strdup ("HandleRefs can not be returned from unmanaged code (or passed by ref)");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
break;
}
@@ -5666,7 +4414,6 @@ emit_marshal_handleref_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
return conv_arg;
}
-
static int
emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
MonoMarshalSpec *spec,
@@ -5687,7 +4434,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (mono_class_from_mono_type_internal (t) == mono_defaults.object_class) {
char *msg = g_strdup_printf ("Marshalling of type object is not implemented");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
break;
}
@@ -5695,13 +4442,13 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (m_type_is_byref (t)) {
if (!(t->attrs & PARAM_ATTRIBUTE_OUT)) {
char *msg = g_strdup_printf ("Byref marshalling of delegates is not implemented.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
}
mono_mb_emit_byte (mb, CEE_LDNULL);
mono_mb_emit_stloc (mb, conv_arg);
} else {
mono_mb_emit_ldarg (mb, argnum);
- mono_mb_emit_icall_id (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, NULL));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, NULL));
mono_mb_emit_stloc (mb, conv_arg);
}
} else if (klass == mono_class_try_get_stringbuilder_class ()) {
@@ -5712,7 +4459,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (m_type_is_byref (t)) {
if (!(t->attrs & PARAM_ATTRIBUTE_OUT)) {
char *msg = g_strdup_printf ("Byref marshalling of stringbuilders is not implemented.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
}
break;
}
@@ -5723,7 +4470,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (conv == MONO_MARSHAL_CONV_INVALID) {
char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding);
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
break;
}
@@ -5731,7 +4478,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
if (m_type_is_byref (t))
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall_id (mb, conv_to_icall (conv, NULL));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL));
mono_mb_emit_stloc (mb, conv_arg);
} else if (m_class_is_blittable (klass)) {
mono_mb_emit_byte (mb, CEE_LDNULL);
@@ -5792,7 +4539,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_stloc (mb, 1);
/* emit valuetype conversion code */
- emit_struct_conv (mb, klass, FALSE);
+ mono_marshal_shared_emit_struct_conv (mb, klass, FALSE);
mono_mb_patch_branch (mb, pos);
}
@@ -5836,7 +4583,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_ldarg (mb, argnum);
mono_mb_emit_ldloc (mb, conv_arg);
- mono_mb_emit_icall_id (mb, conv_to_icall (conv, NULL));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL));
}
if (need_free) {
@@ -5852,7 +4599,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass);
mono_mb_emit_ldloc (mb, conv_arg);
- mono_mb_emit_icall_id (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL));
mono_mb_emit_byte (mb, CEE_STIND_REF);
}
break;
@@ -5888,7 +4635,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_stloc (mb, 0);
/* emit valuetype conversion code */
- emit_struct_conv (mb, klass, TRUE);
+ mono_marshal_shared_emit_struct_conv (mb, klass, TRUE);
/* Free the structure returned by the native code */
emit_struct_free (mb, klass, conv_arg);
@@ -5935,12 +4682,12 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass);
mono_mb_emit_ldloc (mb, 0);
- mono_mb_emit_icall_id (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL));
mono_mb_emit_stloc (mb, 3);
} else if (klass == mono_class_try_get_stringbuilder_class ()) {
// FIXME:
char *msg = g_strdup_printf ("Return marshalling of stringbuilders is not implemented.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
} else {
/* set src */
mono_mb_emit_stloc (mb, 0);
@@ -5969,7 +4716,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_stloc (mb, 1);
/* emit conversion code */
- emit_struct_conv (mb, klass, TRUE);
+ mono_marshal_shared_emit_struct_conv (mb, klass, TRUE);
emit_struct_free (mb, klass, loc);
@@ -5989,7 +4736,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_ldarg (mb, argnum);
if (m_type_is_byref (t))
mono_mb_emit_byte (mb, CEE_LDIND_I);
- mono_mb_emit_icall_id (mb, conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL));
mono_mb_emit_stloc (mb, conv_arg);
break;
}
@@ -6053,7 +4800,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_stloc (mb, 1);
/* emit valuetype conversion code */
- emit_struct_conv (mb, klass, TRUE);
+ mono_marshal_shared_emit_struct_conv (mb, klass, TRUE);
mono_mb_patch_branch (mb, pos);
break;
@@ -6064,7 +4811,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
int stind_op;
mono_mb_emit_ldarg (mb, argnum);
mono_mb_emit_ldloc (mb, conv_arg);
- mono_mb_emit_icall_id (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, &stind_op));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, &stind_op));
mono_mb_emit_byte (mb, stind_op);
break;
}
@@ -6098,7 +4845,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_byte (mb, CEE_STIND_I);
/* emit valuetype conversion code */
- emit_struct_conv (mb, klass, FALSE);
+ mono_marshal_shared_emit_struct_conv (mb, klass, FALSE);
mono_mb_patch_branch (mb, pos2);
} else if (klass == mono_class_try_get_stringbuilder_class ()) {
@@ -6118,13 +4865,13 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_stloc (mb, 1);
/* emit valuetype conversion code */
- emit_struct_conv (mb, klass, FALSE);
+ mono_marshal_shared_emit_struct_conv (mb, klass, FALSE);
}
break;
case MARSHAL_ACTION_MANAGED_CONV_RESULT:
if (m_class_is_delegate (klass)) {
- mono_mb_emit_icall_id (mb, conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, NULL));
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, NULL));
mono_mb_emit_stloc (mb, 3);
break;
}
@@ -6158,7 +4905,7 @@ emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
mono_mb_emit_stloc (mb, 1);
mono_mb_emit_stloc (mb, 3);
- emit_struct_conv (mb, klass, FALSE);
+ mono_marshal_shared_emit_struct_conv (mb, klass, FALSE);
mono_mb_patch_branch (mb, pos2);
break;
@@ -6223,7 +4970,7 @@ emit_marshal_variant_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
case MARSHAL_ACTION_CONV_RESULT: {
char *msg = g_strdup ("Marshalling of VARIANT not supported as a return type.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
break;
}
@@ -6258,7 +5005,7 @@ emit_marshal_variant_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
case MARSHAL_ACTION_MANAGED_CONV_RESULT: {
char *msg = g_strdup ("Marshalling of VARIANT not supported as a return type.");
- mono_mb_emit_exception_marshal_directive (mb, msg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
break;
}
@@ -6587,7 +5334,7 @@ emit_struct_to_ptr_ilgen (MonoMethodBuilder *mb, MonoClass *klass)
mono_mb_emit_byte (mb, CEE_LDARG_1);
mono_mb_emit_stloc (mb, 1);
- emit_struct_conv (mb, klass, FALSE);
+ mono_marshal_shared_emit_struct_conv (mb, klass, FALSE);
}
mono_mb_emit_byte (mb, CEE_RET);
@@ -6620,7 +5367,7 @@ emit_ptr_to_struct_ilgen (MonoMethodBuilder *mb, MonoClass *klass)
mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject));
mono_mb_emit_stloc (mb, 1);
- emit_struct_conv (mb, klass, TRUE);
+ mono_marshal_shared_emit_struct_conv (mb, klass, TRUE);
}
mono_mb_emit_byte (mb, CEE_RET);
@@ -6908,7 +5655,7 @@ emit_marshal_directive_exception_ilgen (EmitMarshalContext *m, int argnum, const
else
fullmsg = g_strdup_printf("Error marshalling parameter #%d: %s", argnum, msg);
- mono_mb_emit_exception_marshal_directive (m->mb, fullmsg);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (m->mb, fullmsg);
}
static void
diff --git a/src/mono/mono/metadata/marshal-shared.c b/src/mono/mono/metadata/marshal-shared.c
new file mode 100644
index 00000000000000..9d8f37bfa86346
--- /dev/null
+++ b/src/mono/mono/metadata/marshal-shared.c
@@ -0,0 +1,1276 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+#include "metadata/marshal-shared.h"
+#include "mono/metadata/debug-helpers.h"
+#include "metadata/marshal.h"
+#include "metadata/marshal-shared.h"
+#include "metadata/method-builder-ilgen.h"
+#include "metadata/custom-attrs-internals.h"
+#include "metadata/class-init.h"
+#include "mono/metadata/class-internals.h"
+#include "metadata/reflection-internals.h"
+#include "mono/metadata/handle.h"
+
+
+#define OPDEF(a,b,c,d,e,f,g,h,i,j) \
+ a = i,
+
+enum {
+#include "mono/cil/opcode.def"
+ LAST = 0xff
+};
+#undef OPDEF
+
+static GENERATE_GET_CLASS_WITH_CACHE (fixed_buffer_attribute, "System.Runtime.CompilerServices", "FixedBufferAttribute");
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (marshal, "System.Runtime.InteropServices", "Marshal");
+
+/* MonoMethod pointers to SafeHandle::DangerousAddRef and ::DangerousRelease */
+static MonoMethod *sh_dangerous_add_ref;
+static MonoMethod *sh_dangerous_release;
+
+
+MonoMethod**
+ mono_marshal_shared_get_sh_dangerous_add_ref (void)
+{
+ return &sh_dangerous_add_ref;
+}
+
+MonoMethod** mono_marshal_shared_get_sh_dangerous_release (void)
+{
+ return &sh_dangerous_release;
+}
+
+// On legacy Mono, LPTSTR was either UTF16 or UTF8 depending on platform
+static inline MonoJitICallId
+mono_string_to_platform_unicode (void)
+{
+#ifdef TARGET_WIN32
+ return MONO_JIT_ICALL_mono_marshal_string_to_utf16;
+#else
+ return MONO_JIT_ICALL_mono_string_to_utf8str;
+#endif
+}
+
+static inline MonoJitICallId
+mono_string_from_platform_unicode (void)
+{
+#ifdef TARGET_WIN32
+ return MONO_JIT_ICALL_ves_icall_mono_string_from_utf16;
+#else
+ return MONO_JIT_ICALL_ves_icall_string_new_wrapper;
+#endif
+}
+
+static inline MonoJitICallId
+mono_string_builder_to_platform_unicode (void)
+{
+#ifdef TARGET_WIN32
+ return MONO_JIT_ICALL_mono_string_builder_to_utf16;
+#else
+ return MONO_JIT_ICALL_mono_string_builder_to_utf8;
+#endif
+}
+
+static inline MonoJitICallId
+mono_string_builder_from_platform_unicode (void)
+{
+#ifdef TARGET_WIN32
+ return MONO_JIT_ICALL_mono_string_utf16_to_builder;
+#else
+ return MONO_JIT_ICALL_mono_string_utf8_to_builder;
+#endif
+}
+
+void
+mono_marshal_shared_emit_marshal_custom_get_instance (MonoMethodBuilder *mb, MonoClass *klass, MonoMarshalSpec *spec)
+{
+ MONO_STATIC_POINTER_INIT (MonoMethod, get_instance)
+
+ MonoClass *Marshal = mono_class_try_get_marshal_class ();
+ g_assert (Marshal);
+ get_instance = mono_marshal_shared_get_method_nofail (Marshal, "GetCustomMarshalerInstance", 2, 0);
+ g_assert (get_instance);
+
+ MONO_STATIC_POINTER_INIT_END (MonoClass, get_instance)
+
+ // HACK: We cannot use ldtoken in this type of wrapper.
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass);
+ mono_mb_emit_icall (mb, mono_marshal_get_type_object);
+ mono_mb_emit_ldstr (mb, g_strdup (spec->data.custom_data.cookie));
+
+ mono_mb_emit_op (mb, CEE_CALL, get_instance);
+}
+
+void
+mono_marshal_shared_init_safe_handle (void)
+{
+ mono_atomic_store_seq (mono_marshal_shared_get_sh_dangerous_add_ref(), mono_marshal_shared_get_method_nofail (mono_class_try_get_safehandle_class (), "DangerousAddRef", 1, 0));
+ mono_atomic_store_seq (mono_marshal_shared_get_sh_dangerous_release(), mono_marshal_shared_get_method_nofail (mono_class_try_get_safehandle_class (), "DangerousRelease", 0, 0));
+}
+
+void
+mono_mb_emit_auto_layout_exception (MonoMethodBuilder *mb, MonoClass *klass)
+{
+ char *msg = g_strdup_printf ("The type `%s.%s' layout needs to be Sequential or Explicit", m_class_get_name_space (klass), m_class_get_name (klass));
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+}
+
+gboolean
+mono_marshal_shared_is_in (const MonoType *t)
+{
+ const guint32 attrs = t->attrs;
+ return (attrs & PARAM_ATTRIBUTE_IN) || !(attrs & PARAM_ATTRIBUTE_OUT);
+}
+
+gboolean
+mono_marshal_shared_is_out (const MonoType *t)
+{
+ const guint32 attrs = t->attrs;
+ return (attrs & PARAM_ATTRIBUTE_OUT) || !(attrs & PARAM_ATTRIBUTE_IN);
+}
+
+MonoMarshalConv
+mono_marshal_shared_conv_str_inverse (MonoMarshalConv conv)
+{
+ switch (conv) {
+ // AnsiBStr
+ case MONO_MARSHAL_CONV_STR_ANSIBSTR:
+ return MONO_MARSHAL_CONV_ANSIBSTR_STR;
+ case MONO_MARSHAL_CONV_ANSIBSTR_STR:
+ return MONO_MARSHAL_CONV_STR_ANSIBSTR;
+
+ // BStr
+ case MONO_MARSHAL_CONV_STR_BSTR:
+ return MONO_MARSHAL_CONV_BSTR_STR;
+ case MONO_MARSHAL_CONV_BSTR_STR:
+ return MONO_MARSHAL_CONV_STR_BSTR;
+
+ // LPStr
+ case MONO_MARSHAL_CONV_STR_LPSTR:
+ return MONO_MARSHAL_CONV_LPSTR_STR;
+ case MONO_MARSHAL_CONV_LPSTR_STR:
+ return MONO_MARSHAL_CONV_STR_LPSTR;
+
+ // LPTStr
+ case MONO_MARSHAL_CONV_STR_LPTSTR:
+ return MONO_MARSHAL_CONV_LPTSTR_STR;
+ case MONO_MARSHAL_CONV_LPTSTR_STR:
+ return MONO_MARSHAL_CONV_STR_LPTSTR;
+
+ // LPUTF8Str
+ case MONO_MARSHAL_CONV_STR_UTF8STR:
+ return MONO_MARSHAL_CONV_UTF8STR_STR;
+ case MONO_MARSHAL_CONV_UTF8STR_STR:
+ return MONO_MARSHAL_CONV_STR_UTF8STR;
+
+ // LPWStr
+ case MONO_MARSHAL_CONV_STR_LPWSTR:
+ return MONO_MARSHAL_CONV_LPWSTR_STR;
+ case MONO_MARSHAL_CONV_LPWSTR_STR:
+ return MONO_MARSHAL_CONV_STR_LPWSTR;
+
+ // TBStr
+ case MONO_MARSHAL_CONV_STR_TBSTR:
+ return MONO_MARSHAL_CONV_TBSTR_STR;
+ case MONO_MARSHAL_CONV_TBSTR_STR:
+ return MONO_MARSHAL_CONV_STR_TBSTR;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
+/*
+ * mono_marshal_shared_mb_emit_exception_marshal_directive:
+ *
+ * This function assumes ownership of MSG, which should be malloc-ed.
+ */
+void
+mono_marshal_shared_mb_emit_exception_marshal_directive (MonoMethodBuilder *mb, char *msg)
+{
+ char *s = mono_mb_strdup (mb, msg);
+ g_free (msg);
+ mono_mb_emit_exception_full (mb, "System.Runtime.InteropServices", "MarshalDirectiveException", s);
+}
+
+gboolean
+mono_marshal_shared_get_fixed_buffer_attr (MonoClassField *field, MonoType **out_etype, int *out_len)
+{
+ ERROR_DECL (error);
+ MonoCustomAttrInfo *cinfo;
+ MonoCustomAttrEntry *attr;
+ int aindex;
+
+ cinfo = mono_custom_attrs_from_field_checked (m_field_get_parent (field), field, error);
+ if (!is_ok (error))
+ return FALSE;
+ attr = NULL;
+ if (cinfo) {
+ for (aindex = 0; aindex < cinfo->num_attrs; ++aindex) {
+ MonoClass *ctor_class = cinfo->attrs [aindex].ctor->klass;
+ if (mono_class_has_parent (ctor_class, mono_class_get_fixed_buffer_attribute_class ())) {
+ attr = &cinfo->attrs [aindex];
+ break;
+ }
+ }
+ }
+ if (attr) {
+ gpointer *typed_args, *named_args;
+ CattrNamedArg *arginfo;
+ int num_named_args;
+
+ mono_reflection_create_custom_attr_data_args_noalloc (mono_defaults.corlib, attr->ctor, attr->data, attr->data_size,
+ &typed_args, &named_args, &num_named_args, &arginfo, error);
+ if (!is_ok (error))
+ return FALSE;
+ *out_etype = (MonoType*)typed_args [0];
+ *out_len = *(gint32*)typed_args [1];
+ g_free (typed_args [1]);
+ g_free (typed_args);
+ g_free (named_args);
+ g_free (arginfo);
+ }
+ if (cinfo && !cinfo->cached)
+ mono_custom_attrs_free (cinfo);
+ return attr != NULL;
+}
+
+void
+mono_marshal_shared_emit_fixed_buf_conv (MonoMethodBuilder *mb, MonoType *type, MonoType *etype, int len, gboolean to_object, int *out_usize)
+{
+ MonoClass *klass = mono_class_from_mono_type_internal (type);
+ MonoClass *eklass = mono_class_from_mono_type_internal (etype);
+ int esize;
+
+ esize = mono_class_native_size (eklass, NULL);
+
+ MonoMarshalNative string_encoding = m_class_is_unicode (klass) ? MONO_NATIVE_LPWSTR : MONO_NATIVE_LPSTR;
+ int usize = mono_class_value_size (eklass, NULL);
+ int msize = mono_class_value_size (eklass, NULL);
+
+ //printf ("FIXED: %s %d %d\n", mono_type_full_name (type), em_class_is_blittable (klass), string_encoding);
+
+ if (m_class_is_blittable (eklass)) {
+ /* copy the elements */
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_icon (mb, len * esize);
+ mono_mb_emit_byte (mb, CEE_PREFIX1);
+ mono_mb_emit_byte (mb, CEE_CPBLK);
+ } else {
+ int index_var;
+ guint32 label2, label3;
+
+ /* Emit marshalling loop */
+ MonoType *int_type = mono_get_int_type ();
+ index_var = mono_mb_add_local (mb, int_type);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_0);
+ mono_mb_emit_stloc (mb, index_var);
+
+ /* Loop header */
+ label2 = mono_mb_get_label (mb);
+ mono_mb_emit_ldloc (mb, index_var);
+ mono_mb_emit_icon (mb, len);
+ label3 = mono_mb_emit_branch (mb, CEE_BGE);
+
+ /* src/dst is already set */
+
+ /* Do the conversion */
+ MonoTypeEnum t = etype->type;
+ switch (t) {
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_R4:
+ case MONO_TYPE_R8:
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ if (t == MONO_TYPE_CHAR && string_encoding != MONO_NATIVE_LPWSTR) {
+ if (to_object) {
+ mono_mb_emit_byte (mb, CEE_LDIND_U1);
+ mono_mb_emit_byte (mb, CEE_STIND_I2);
+ } else {
+ mono_mb_emit_byte (mb, CEE_LDIND_U2);
+ mono_mb_emit_byte (mb, CEE_STIND_I1);
+ }
+ usize = 1;
+ } else {
+ mono_mb_emit_byte (mb, mono_type_to_ldind (etype));
+ mono_mb_emit_byte (mb, mono_type_to_stind (etype));
+ }
+ break;
+ default:
+ g_assert_not_reached ();
+ break;
+ }
+
+ if (to_object) {
+ mono_mb_emit_add_to_local (mb, 0, usize);
+ mono_mb_emit_add_to_local (mb, 1, msize);
+ } else {
+ mono_mb_emit_add_to_local (mb, 0, msize);
+ mono_mb_emit_add_to_local (mb, 1, usize);
+ }
+
+ /* Loop footer */
+ mono_mb_emit_add_to_local (mb, index_var, 1);
+
+ mono_mb_emit_branch_label (mb, CEE_BR, label2);
+
+ mono_mb_patch_branch (mb, label3);
+ }
+
+ *out_usize = usize * len;
+}
+
+int
+mono_marshal_shared_offset_of_first_nonstatic_field (MonoClass *klass)
+{
+ mono_class_setup_fields (klass);
+ gpointer iter = NULL;
+ MonoClassField *field;
+ while ((field = mono_class_get_fields_internal (klass, &iter))) {
+ if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) && !mono_field_is_deleted (field)) {
+ /*
+ * metadata-update: adding fields to existing structs isn't supported. In
+ * newly-added structs, the "from update" field won't be set.
+ */
+ g_assert (!m_field_is_from_update (field));
+ return m_field_get_offset (field) - MONO_ABI_SIZEOF (MonoObject);
+ }
+ }
+
+ return 0;
+}
+
+// FIXME Consolidate the multiple functions named get_method_nofail.
+MonoMethod*
+mono_marshal_shared_get_method_nofail (MonoClass *klass, const char *method_name, int num_params, int flags)
+{
+ MonoMethod *method;
+ ERROR_DECL (error);
+ method = mono_class_get_method_from_name_checked (klass, method_name, num_params, flags, error);
+ mono_error_assert_ok (error);
+ g_assertf (method, "Could not lookup method %s in %s", method_name, m_class_get_name (klass));
+ return method;
+}
+
+MonoJitICallId
+mono_marshal_shared_conv_to_icall (MonoMarshalConv conv, int *ind_store_type)
+{
+ // FIXME This or its caller might be a good place to inline some
+ // of the wrapper logic. In particular, to produce
+ // volatile stack-based handles. Being data-driven,
+ // from icall-def.h.
+
+ int dummy;
+ if (!ind_store_type)
+ ind_store_type = &dummy;
+ *ind_store_type = CEE_STIND_I;
+ switch (conv) {
+ // AnsiBStr
+ case MONO_MARSHAL_CONV_STR_ANSIBSTR:
+ return MONO_JIT_ICALL_mono_string_to_ansibstr;
+ case MONO_MARSHAL_CONV_ANSIBSTR_STR:
+ *ind_store_type = CEE_STIND_REF;
+ return MONO_JIT_ICALL_mono_string_from_ansibstr;
+
+ // BStr
+ case MONO_MARSHAL_CONV_STR_BSTR:
+ return MONO_JIT_ICALL_mono_string_to_bstr;
+ case MONO_MARSHAL_CONV_BSTR_STR:
+ *ind_store_type = CEE_STIND_REF;
+ return MONO_JIT_ICALL_mono_string_from_bstr_icall;
+
+ // LPStr
+ // In Mono, LPSTR was historically treated as UTF8STR
+ case MONO_MARSHAL_CONV_STR_LPSTR:
+ return MONO_JIT_ICALL_mono_string_to_utf8str;
+ case MONO_MARSHAL_CONV_LPSTR_STR:
+ *ind_store_type = CEE_STIND_REF;
+ return MONO_JIT_ICALL_ves_icall_string_new_wrapper;
+ case MONO_MARSHAL_CONV_SB_LPSTR:
+ return MONO_JIT_ICALL_mono_string_builder_to_utf8;
+ case MONO_MARSHAL_CONV_LPSTR_SB:
+ *ind_store_type = CEE_STIND_REF;
+ return MONO_JIT_ICALL_mono_string_utf8_to_builder;
+
+ // LPTStr
+ // FIXME: This is how LPTStr was handled on legacy, but it's not correct and for netcore we should implement this more properly.
+ // This type is supposed to detect ANSI or UTF16 (as LPTStr can be either depending on _UNICODE) and handle it accordingly.
+ // The CoreCLR test for this type only tests as LPWSTR regardless of platform.
+ case MONO_MARSHAL_CONV_STR_LPTSTR:
+ return mono_string_to_platform_unicode ();
+ case MONO_MARSHAL_CONV_LPTSTR_STR:
+ *ind_store_type = CEE_STIND_REF;
+ return mono_string_from_platform_unicode ();
+ case MONO_MARSHAL_CONV_SB_LPTSTR:
+ return mono_string_builder_to_platform_unicode ();
+ case MONO_MARSHAL_CONV_LPTSTR_SB:
+ *ind_store_type = CEE_STIND_REF;
+ return mono_string_builder_from_platform_unicode ();
+
+ // LPUTF8Str
+ case MONO_MARSHAL_CONV_STR_UTF8STR:
+ return MONO_JIT_ICALL_mono_string_to_utf8str;
+ case MONO_MARSHAL_CONV_UTF8STR_STR:
+ *ind_store_type = CEE_STIND_REF;
+ return MONO_JIT_ICALL_ves_icall_string_new_wrapper;
+ case MONO_MARSHAL_CONV_SB_UTF8STR:
+ return MONO_JIT_ICALL_mono_string_builder_to_utf8;
+ case MONO_MARSHAL_CONV_UTF8STR_SB:
+ *ind_store_type = CEE_STIND_REF;
+ return MONO_JIT_ICALL_mono_string_utf8_to_builder;
+
+ // LPWStr
+ case MONO_MARSHAL_CONV_STR_LPWSTR:
+ return MONO_JIT_ICALL_mono_marshal_string_to_utf16;
+ case MONO_MARSHAL_CONV_LPWSTR_STR:
+ *ind_store_type = CEE_STIND_REF;
+ return MONO_JIT_ICALL_ves_icall_mono_string_from_utf16;
+ case MONO_MARSHAL_CONV_SB_LPWSTR:
+ return MONO_JIT_ICALL_mono_string_builder_to_utf16;
+ case MONO_MARSHAL_CONV_LPWSTR_SB:
+ *ind_store_type = CEE_STIND_REF;
+ return MONO_JIT_ICALL_mono_string_utf16_to_builder;
+
+ // TBStr
+ case MONO_MARSHAL_CONV_STR_TBSTR:
+ return MONO_JIT_ICALL_mono_string_to_tbstr;
+ case MONO_MARSHAL_CONV_TBSTR_STR:
+ *ind_store_type = CEE_STIND_REF;
+ return MONO_JIT_ICALL_mono_string_from_tbstr;
+
+ case MONO_MARSHAL_CONV_STR_BYVALSTR:
+ return MONO_JIT_ICALL_mono_string_to_byvalstr;
+ case MONO_MARSHAL_CONV_STR_BYVALWSTR:
+ return MONO_JIT_ICALL_mono_string_to_byvalwstr;
+
+ case MONO_MARSHAL_CONV_DEL_FTN:
+ return MONO_JIT_ICALL_mono_delegate_to_ftnptr;
+ case MONO_MARSHAL_CONV_FTN_DEL:
+ *ind_store_type = CEE_STIND_REF;
+ return MONO_JIT_ICALL_mono_ftnptr_to_delegate;
+
+ case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
+ return MONO_JIT_ICALL_mono_array_to_savearray;
+ case MONO_MARSHAL_FREE_ARRAY:
+ return MONO_JIT_ICALL_mono_marshal_free_array;
+
+ case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
+ return MONO_JIT_ICALL_mono_array_to_lparray;
+ case MONO_MARSHAL_FREE_LPARRAY:
+ return MONO_JIT_ICALL_mono_free_lparray;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ return MONO_JIT_ICALL_ZeroIsReserved;
+}
+
+void
+mono_marshal_shared_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec)
+{
+ switch (conv) {
+ case MONO_MARSHAL_CONV_BOOL_I4:
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_I4);
+ mono_mb_emit_byte (mb, CEE_BRFALSE_S);
+ mono_mb_emit_byte (mb, 3);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_1);
+ mono_mb_emit_byte (mb, CEE_BR_S);
+ mono_mb_emit_byte (mb, 1);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_0);
+ mono_mb_emit_byte (mb, CEE_STIND_I1);
+ break;
+ case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_I2);
+ mono_mb_emit_byte (mb, CEE_BRFALSE_S);
+ mono_mb_emit_byte (mb, 3);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_1);
+ mono_mb_emit_byte (mb, CEE_BR_S);
+ mono_mb_emit_byte (mb, 1);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_0);
+ mono_mb_emit_byte (mb, CEE_STIND_I1);
+ break;
+ case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
+ MonoClass *eklass = NULL;
+ int esize;
+
+ if (type->type == MONO_TYPE_SZARRAY) {
+ eklass = type->data.klass;
+ } else {
+ g_assert_not_reached ();
+ }
+
+ esize = mono_class_native_size (eklass, NULL);
+
+ /* create a new array */
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
+ mono_mb_emit_op (mb, CEE_NEWARR, eklass);
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
+
+ if (m_class_is_blittable (eklass)) {
+ /* copy the elements */
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoArray, vector));
+ mono_mb_emit_byte (mb, CEE_ADD);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
+ mono_mb_emit_byte (mb, CEE_PREFIX1);
+ mono_mb_emit_byte (mb, CEE_CPBLK);
+ }
+ else {
+ int array_var, src_var, dst_var, index_var;
+ guint32 label2, label3;
+
+ MonoType *int_type = mono_get_int_type ();
+ array_var = mono_mb_add_local (mb, mono_get_object_type ());
+ src_var = mono_mb_add_local (mb, int_type);
+ dst_var = mono_mb_add_local (mb, int_type);
+
+ /* set array_var */
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ mono_mb_emit_stloc (mb, array_var);
+
+ /* save the old src pointer */
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_stloc (mb, src_var);
+ /* save the old dst pointer */
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_stloc (mb, dst_var);
+
+ /* Emit marshalling loop */
+ index_var = mono_mb_add_local (mb, int_type);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_0);
+ mono_mb_emit_stloc (mb, index_var);
+
+ /* Loop header */
+ label2 = mono_mb_get_label (mb);
+ mono_mb_emit_ldloc (mb, index_var);
+ mono_mb_emit_ldloc (mb, array_var);
+ mono_mb_emit_byte (mb, CEE_LDLEN);
+ label3 = mono_mb_emit_branch (mb, CEE_BGE);
+
+ /* src is already set */
+
+ /* Set dst */
+ mono_mb_emit_ldloc (mb, array_var);
+ mono_mb_emit_ldloc (mb, index_var);
+ mono_mb_emit_op (mb, CEE_LDELEMA, eklass);
+ mono_mb_emit_stloc (mb, 1);
+
+ /* Do the conversion */
+ mono_marshal_shared_emit_struct_conv (mb, eklass, TRUE);
+
+ /* Loop footer */
+ mono_mb_emit_add_to_local (mb, index_var, 1);
+
+ mono_mb_emit_branch_label (mb, CEE_BR, label2);
+
+ mono_mb_patch_branch (mb, label3);
+
+ /* restore the old src pointer */
+ mono_mb_emit_ldloc (mb, src_var);
+ mono_mb_emit_stloc (mb, 0);
+ /* restore the old dst pointer */
+ mono_mb_emit_ldloc (mb, dst_var);
+ mono_mb_emit_stloc (mb, 1);
+ }
+ break;
+ }
+ case MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY: {
+ MonoClass *eclass = mono_defaults.char_class;
+
+ /* create a new array */
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
+ mono_mb_emit_op (mb, CEE_NEWARR, eclass);
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
+
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
+ mono_mb_emit_icall (mb, mono_byvalarray_to_byte_array);
+ break;
+ }
+ case MONO_MARSHAL_CONV_STR_BYVALSTR:
+ if (mspec && mspec->native == MONO_NATIVE_BYVALTSTR && mspec->data.array_data.num_elem) {
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
+ mono_mb_emit_icall (mb, mono_string_from_byvalstr);
+ } else {
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_icall (mb, ves_icall_string_new_wrapper);
+ }
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
+ break;
+ case MONO_MARSHAL_CONV_STR_BYVALWSTR:
+ if (mspec && mspec->native == MONO_NATIVE_BYVALTSTR && mspec->data.array_data.num_elem) {
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
+ mono_mb_emit_icall (mb, mono_string_from_byvalwstr);
+ } else {
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_icall (mb, ves_icall_mono_string_from_utf16);
+ }
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
+ break;
+
+ case MONO_MARSHAL_CONV_STR_ANSIBSTR:
+ case MONO_MARSHAL_CONV_STR_TBSTR:
+ case MONO_MARSHAL_CONV_STR_UTF8STR:
+ case MONO_MARSHAL_CONV_STR_LPWSTR:
+ case MONO_MARSHAL_CONV_STR_LPSTR:
+ case MONO_MARSHAL_CONV_STR_LPTSTR:
+ case MONO_MARSHAL_CONV_STR_BSTR: {
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (mono_marshal_shared_conv_str_inverse (conv), NULL));
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
+ break;
+ }
+
+ case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
+ MonoClass *klass = mono_class_from_mono_type_internal (type);
+ int src_var, dst_var;
+
+ MonoType *int_type = mono_get_int_type ();
+ src_var = mono_mb_add_local (mb, int_type);
+ dst_var = mono_mb_add_local (mb, int_type);
+
+ /* *dst = new object */
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_op (mb, CEE_MONO_NEWOBJ, klass);
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
+
+ /* save the old src pointer */
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_stloc (mb, src_var);
+ /* save the old dst pointer */
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_stloc (mb, dst_var);
+
+ /* dst = pointer to newly created object data */
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_icon (mb, MONO_ABI_SIZEOF (MonoObject));
+ mono_mb_emit_byte (mb, CEE_ADD);
+ mono_mb_emit_stloc (mb, 1);
+
+ mono_marshal_shared_emit_struct_conv (mb, klass, TRUE);
+
+ /* restore the old src pointer */
+ mono_mb_emit_ldloc (mb, src_var);
+ mono_mb_emit_stloc (mb, 0);
+ /* restore the old dst pointer */
+ mono_mb_emit_ldloc (mb, dst_var);
+ mono_mb_emit_stloc (mb, 1);
+ break;
+ }
+ case MONO_MARSHAL_CONV_DEL_FTN: {
+ MonoClass *klass = mono_class_from_mono_type_internal (type);
+
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_icall (mb, mono_ftnptr_to_delegate);
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
+ break;
+ }
+ case MONO_MARSHAL_CONV_ARRAY_LPARRAY: {
+ char *msg = g_strdup_printf ("Structure field of type %s can't be marshalled as LPArray", m_class_get_name (mono_class_from_mono_type_internal (type)));
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ break;
+ }
+
+#ifndef DISABLE_COM
+ case MONO_MARSHAL_CONV_OBJECT_INTERFACE:
+ case MONO_MARSHAL_CONV_OBJECT_IUNKNOWN:
+ case MONO_MARSHAL_CONV_OBJECT_IDISPATCH:
+ mono_cominterop_emit_ptr_to_object_conv (mb, type, conv, mspec);
+ break;
+#endif /* DISABLE_COM */
+
+ case MONO_MARSHAL_CONV_SAFEHANDLE: {
+ /*
+ * Passing SafeHandles as ref does not allow the unmanaged code
+ * to change the SafeHandle value. If the value is changed,
+ * we should issue a diagnostic exception (NotSupportedException)
+ * that informs the user that changes to handles in unmanaged code
+ * is not supported.
+ *
+ * Since we currently have no access to the original
+ * SafeHandle that was used during the marshalling,
+ * for now we just ignore this, and ignore/discard any
+ * changes that might have happened to the handle.
+ */
+ break;
+ }
+
+ case MONO_MARSHAL_CONV_HANDLEREF: {
+ /*
+ * Passing HandleRefs in a struct that is ref()ed does not
+ * copy the values back to the HandleRef
+ */
+ break;
+ }
+
+ case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
+ default: {
+ char *msg = g_strdup_printf ("marshaling conversion %d not implemented", conv);
+
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ break;
+ }
+ }
+}
+
+void
+mono_marshal_shared_emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object,
+ int offset_of_first_child_field, MonoMarshalNative string_encoding)
+{
+ MonoMarshalType *info;
+ int i;
+
+ if (m_class_get_parent (klass))
+ mono_marshal_shared_emit_struct_conv_full (mb, m_class_get_parent (klass), to_object, mono_marshal_shared_offset_of_first_nonstatic_field (klass), string_encoding);
+
+ info = mono_marshal_load_type_info (klass);
+
+ if (info->native_size == 0)
+ return;
+
+ if (m_class_is_blittable (klass)) {
+ int usize = mono_class_value_size (klass, NULL);
+ g_assert (usize == info->native_size);
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_icon (mb, usize);
+ mono_mb_emit_byte (mb, CEE_PREFIX1);
+ mono_mb_emit_byte (mb, CEE_CPBLK);
+
+ if (to_object) {
+ mono_mb_emit_add_to_local (mb, 0, usize);
+ mono_mb_emit_add_to_local (mb, 1, offset_of_first_child_field);
+ } else {
+ mono_mb_emit_add_to_local (mb, 0, offset_of_first_child_field);
+ mono_mb_emit_add_to_local (mb, 1, usize);
+ }
+ return;
+ }
+
+ if (klass != mono_class_try_get_safehandle_class ()) {
+ if (mono_class_is_auto_layout (klass)) {
+ char *msg = g_strdup_printf ("Type %s which is passed to unmanaged code must have a StructLayout attribute.",
+ mono_type_full_name (m_class_get_byval_arg (klass)));
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ return;
+ }
+ }
+
+ for (i = 0; i < info->num_fields; i++) {
+ MonoMarshalNative ntype;
+ MonoMarshalConv conv;
+ MonoType *ftype = info->fields [i].field->type;
+ int msize = 0;
+ int usize = 0;
+ gboolean last_field = i < (info->num_fields -1) ? 0 : 1;
+
+ if (ftype->attrs & FIELD_ATTRIBUTE_STATIC)
+ continue;
+
+ ntype = (MonoMarshalNative)mono_type_to_unmanaged (ftype, info->fields [i].mspec, TRUE, m_class_is_unicode (klass), &conv);
+
+ if (last_field) {
+ msize = m_class_get_instance_size (klass) - m_field_get_offset (info->fields [i].field);
+ usize = info->native_size - info->fields [i].offset;
+ } else {
+ msize = m_field_get_offset (info->fields [i + 1].field) - m_field_get_offset (info->fields [i].field);
+ usize = info->fields [i + 1].offset - info->fields [i].offset;
+ }
+
+ if (klass != mono_class_try_get_safehandle_class ()){
+ /*
+ * FIXME: Should really check for usize==0 and msize>0, but we apply
+ * the layout to the managed structure as well.
+ */
+
+ if (mono_class_is_explicit_layout (klass) && (usize == 0)) {
+ if (MONO_TYPE_IS_REFERENCE (info->fields [i].field->type) ||
+ ((!last_field && MONO_TYPE_IS_REFERENCE (info->fields [i + 1].field->type))))
+ g_error ("Type %s which has an [ExplicitLayout] attribute cannot have a "
+ "reference field at the same offset as another field.",
+ mono_type_full_name (m_class_get_byval_arg (klass)));
+ }
+ }
+
+ switch (conv) {
+ case MONO_MARSHAL_CONV_NONE: {
+ int t;
+
+ //XXX a byref field!?!? that's not allowed! and worse, it might miss a WB
+ g_assert (!m_type_is_byref (ftype));
+ if (ftype->type == MONO_TYPE_I || ftype->type == MONO_TYPE_U) {
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_byte (mb, CEE_STIND_I);
+ break;
+ }
+
+ handle_enum:
+ t = ftype->type;
+ switch (t) {
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_BOOLEAN:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_CHAR:
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ case MONO_TYPE_PTR:
+ case MONO_TYPE_R4:
+ case MONO_TYPE_R8:
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ if (t == MONO_TYPE_CHAR && ntype == MONO_NATIVE_U1 && string_encoding != MONO_NATIVE_LPWSTR) {
+ if (to_object) {
+ mono_mb_emit_byte (mb, CEE_LDIND_U1);
+ mono_mb_emit_byte (mb, CEE_STIND_I2);
+ } else {
+ mono_mb_emit_byte (mb, CEE_LDIND_U2);
+ mono_mb_emit_byte (mb, CEE_STIND_I1);
+ }
+ } else {
+ mono_mb_emit_byte (mb, mono_type_to_ldind (ftype));
+ mono_mb_emit_byte (mb, mono_type_to_stind (ftype));
+ }
+ break;
+ case MONO_TYPE_GENERICINST:
+ if (!mono_type_generic_inst_is_valuetype (ftype)) {
+ char *msg = g_strdup_printf ("Generic type %s cannot be marshaled as field in a struct.",
+ mono_type_full_name (ftype));
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ break;
+ }
+ /* fall through */
+ case MONO_TYPE_VALUETYPE: {
+ int src_var, dst_var;
+ MonoType *etype;
+ int len;
+
+ if (t == MONO_TYPE_VALUETYPE && m_class_is_enumtype (ftype->data.klass)) {
+ ftype = mono_class_enum_basetype_internal (ftype->data.klass);
+ goto handle_enum;
+ }
+
+ MonoType *int_type = mono_get_int_type ();
+ src_var = mono_mb_add_local (mb, int_type);
+ dst_var = mono_mb_add_local (mb, int_type);
+
+ /* save the old src pointer */
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_stloc (mb, src_var);
+ /* save the old dst pointer */
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_stloc (mb, dst_var);
+
+ if (mono_marshal_shared_get_fixed_buffer_attr (info->fields [i].field, &etype, &len)) {
+ mono_marshal_shared_emit_fixed_buf_conv (mb, ftype, etype, len, to_object, &usize);
+ } else {
+ mono_marshal_shared_emit_struct_conv (mb, mono_class_from_mono_type_internal (ftype), to_object);
+ }
+
+ /* restore the old src pointer */
+ mono_mb_emit_ldloc (mb, src_var);
+ mono_mb_emit_stloc (mb, 0);
+ /* restore the old dst pointer */
+ mono_mb_emit_ldloc (mb, dst_var);
+ mono_mb_emit_stloc (mb, 1);
+ break;
+ }
+ case MONO_TYPE_OBJECT: {
+#ifndef DISABLE_COM
+ if (to_object) {
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_managed_call (mb, mono_get_Marshal_GetObjectForNativeVariant (), NULL);
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
+
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_managed_call (mb, mono_get_Variant_Clear (), NULL);
+ }
+ else {
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte(mb, CEE_LDIND_REF);
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_managed_call (mb, mono_get_Marshal_GetNativeVariantForObject (), NULL);
+ }
+#else
+ char *msg = g_strdup_printf ("COM support was disabled at compilation time.");
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+#endif
+ break;
+ }
+
+ default:
+ g_warning ("marshaling type %02x not implemented", ftype->type);
+ g_assert_not_reached ();
+ }
+ break;
+ }
+ default: {
+ int src_var, dst_var;
+
+ MonoType *int_type = mono_get_int_type ();
+ src_var = mono_mb_add_local (mb, int_type);
+ dst_var = mono_mb_add_local (mb, int_type);
+
+ /* save the old src pointer */
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_stloc (mb, src_var);
+ /* save the old dst pointer */
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_stloc (mb, dst_var);
+
+ if (to_object)
+ mono_marshal_shared_emit_ptr_to_object_conv (mb, ftype, conv, info->fields [i].mspec);
+ else
+ mono_marshal_shared_emit_object_to_ptr_conv (mb, ftype, conv, info->fields [i].mspec);
+
+ /* restore the old src pointer */
+ mono_mb_emit_ldloc (mb, src_var);
+ mono_mb_emit_stloc (mb, 0);
+ /* restore the old dst pointer */
+ mono_mb_emit_ldloc (mb, dst_var);
+ mono_mb_emit_stloc (mb, 1);
+ }
+ }
+
+ if (to_object) {
+ mono_mb_emit_add_to_local (mb, 0, usize);
+ mono_mb_emit_add_to_local (mb, 1, msize);
+ } else {
+ mono_mb_emit_add_to_local (mb, 0, msize);
+ mono_mb_emit_add_to_local (mb, 1, usize);
+ }
+ }
+}
+
+void
+mono_marshal_shared_emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object)
+{
+ mono_marshal_shared_emit_struct_conv_full (mb, klass, to_object, 0, (MonoMarshalNative)-1);
+}
+
+void
+mono_marshal_shared_emit_thread_interrupt_checkpoint_call (MonoMethodBuilder *mb, MonoJitICallId checkpoint_icall_id)
+{
+ int pos_noabort, pos_noex;
+
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_LDPTR_INT_REQ_FLAG);
+ mono_mb_emit_no_nullcheck (mb);
+ mono_mb_emit_byte (mb, CEE_LDIND_U4);
+ pos_noabort = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_NOT_TAKEN);
+
+ mono_mb_emit_icall_id (mb, checkpoint_icall_id);
+ /* Throw the exception returned by the checkpoint function, if any */
+ mono_mb_emit_byte (mb, CEE_DUP);
+ pos_noex = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ mono_mb_emit_byte (mb, CEE_DUP);
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoException, caught_in_unmanaged));
+ mono_mb_emit_byte (mb, CEE_LDC_I4_1);
+ mono_mb_emit_no_nullcheck (mb);
+ mono_mb_emit_byte (mb, CEE_STIND_I4);
+
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_RETHROW);
+
+ mono_mb_patch_branch (mb, pos_noex);
+ mono_mb_emit_byte (mb, CEE_POP);
+
+ mono_mb_patch_branch (mb, pos_noabort);
+}
+
+void
+mono_marshal_shared_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec)
+{
+ int pos;
+ int stind_op;
+
+ switch (conv) {
+ case MONO_MARSHAL_CONV_BOOL_I4:
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_U1);
+ mono_mb_emit_byte (mb, CEE_STIND_I4);
+ break;
+ case MONO_MARSHAL_CONV_BOOL_VARIANTBOOL:
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_U1);
+ mono_mb_emit_byte (mb, CEE_NEG);
+ mono_mb_emit_byte (mb, CEE_STIND_I2);
+ break;
+ case MONO_MARSHAL_CONV_STR_UTF8STR:
+ case MONO_MARSHAL_CONV_STR_LPWSTR:
+ case MONO_MARSHAL_CONV_STR_LPSTR:
+ case MONO_MARSHAL_CONV_STR_LPTSTR:
+ case MONO_MARSHAL_CONV_STR_BSTR:
+ case MONO_MARSHAL_CONV_STR_ANSIBSTR:
+ case MONO_MARSHAL_CONV_STR_TBSTR: {
+ /* free space if free == true */
+ mono_mb_emit_ldloc (mb, 2);
+ pos = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S);
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_icall (mb, g_free); // aka monoeg_g_free
+ mono_mb_patch_short_branch (mb, pos);
+
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, &stind_op));
+ mono_mb_emit_byte (mb, stind_op);
+ break;
+ }
+ case MONO_MARSHAL_CONV_ARRAY_SAVEARRAY:
+ case MONO_MARSHAL_CONV_ARRAY_LPARRAY:
+ case MONO_MARSHAL_CONV_DEL_FTN:
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, &stind_op));
+ mono_mb_emit_byte (mb, stind_op);
+ break;
+ case MONO_MARSHAL_CONV_STR_BYVALSTR:
+ case MONO_MARSHAL_CONV_STR_BYVALWSTR: {
+ g_assert (mspec);
+
+ mono_mb_emit_ldloc (mb, 1); /* dst */
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_REF); /* src String */
+ mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL));
+ break;
+ }
+ case MONO_MARSHAL_CONV_ARRAY_BYVALARRAY: {
+ MonoClass *eklass = NULL;
+ int esize;
+
+ if (type->type == MONO_TYPE_SZARRAY) {
+ eklass = type->data.klass;
+ } else if (type->type == MONO_TYPE_ARRAY) {
+ eklass = type->data.array->eklass;
+ g_assert(m_class_is_blittable (eklass));
+ } else {
+ g_assert_not_reached ();
+ }
+
+ if (m_class_is_valuetype (eklass))
+ esize = mono_class_native_size (eklass, NULL);
+ else
+ esize = TARGET_SIZEOF_VOID_P;
+
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ if (m_class_is_blittable (eklass)) {
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoArray, vector));
+ mono_mb_emit_icon (mb, mspec->data.array_data.num_elem * esize);
+ mono_mb_emit_byte (mb, CEE_PREFIX1);
+ mono_mb_emit_byte (mb, CEE_CPBLK);
+ } else {
+ int array_var, src_var, dst_var, index_var;
+ guint32 label2, label3;
+
+ MonoType *int_type = mono_get_int_type ();
+ MonoType *object_type = mono_get_object_type ();
+ array_var = mono_mb_add_local (mb, object_type);
+ src_var = mono_mb_add_local (mb, int_type);
+ dst_var = mono_mb_add_local (mb, int_type);
+
+ /* set array_var */
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ mono_mb_emit_stloc (mb, array_var);
+
+ /* save the old src pointer */
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_stloc (mb, src_var);
+ /* save the old dst pointer */
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_stloc (mb, dst_var);
+
+ /* Emit marshalling loop */
+ index_var = mono_mb_add_local (mb, int_type);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_0);
+ mono_mb_emit_stloc (mb, index_var);
+
+ /* Loop header */
+ label2 = mono_mb_get_label (mb);
+ mono_mb_emit_ldloc (mb, index_var);
+ mono_mb_emit_ldloc (mb, array_var);
+ mono_mb_emit_byte (mb, CEE_LDLEN);
+ label3 = mono_mb_emit_branch (mb, CEE_BGE);
+
+ /* Set src */
+ mono_mb_emit_ldloc (mb, array_var);
+ mono_mb_emit_ldloc (mb, index_var);
+ mono_mb_emit_op (mb, CEE_LDELEMA, eklass);
+ mono_mb_emit_stloc (mb, 0);
+
+ /* dst is already set */
+
+ /* Do the conversion */
+ mono_marshal_shared_emit_struct_conv (mb, eklass, FALSE);
+
+ /* Loop footer */
+ mono_mb_emit_add_to_local (mb, index_var, 1);
+
+ mono_mb_emit_branch_label (mb, CEE_BR, label2);
+
+ mono_mb_patch_branch (mb, label3);
+
+ /* restore the old src pointer */
+ mono_mb_emit_ldloc (mb, src_var);
+ mono_mb_emit_stloc (mb, 0);
+ /* restore the old dst pointer */
+ mono_mb_emit_ldloc (mb, dst_var);
+ mono_mb_emit_stloc (mb, 1);
+ }
+
+ mono_mb_patch_branch (mb, pos);
+ break;
+ }
+ case MONO_MARSHAL_CONV_ARRAY_BYVALCHARARRAY: {
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ pos = mono_mb_emit_short_branch (mb, CEE_BRFALSE_S);
+
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ mono_mb_emit_icon (mb, mspec->data.array_data.num_elem);
+ mono_mb_emit_icall (mb, mono_array_to_byte_byvalarray);
+ mono_mb_patch_short_branch (mb, pos);
+ break;
+ }
+ case MONO_MARSHAL_CONV_OBJECT_STRUCT: {
+ int src_var, dst_var;
+
+ MonoType *int_type = mono_get_int_type ();
+ src_var = mono_mb_add_local (mb, int_type);
+ dst_var = mono_mb_add_local (mb, int_type);
+
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ /* save the old src pointer */
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_stloc (mb, src_var);
+ /* save the old dst pointer */
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_stloc (mb, dst_var);
+
+ /* src = pointer to object data */
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_icon (mb, MONO_ABI_SIZEOF (MonoObject));
+ mono_mb_emit_byte (mb, CEE_ADD);
+ mono_mb_emit_stloc (mb, 0);
+
+ mono_marshal_shared_emit_struct_conv (mb, mono_class_from_mono_type_internal (type), FALSE);
+
+ /* restore the old src pointer */
+ mono_mb_emit_ldloc (mb, src_var);
+ mono_mb_emit_stloc (mb, 0);
+ /* restore the old dst pointer */
+ mono_mb_emit_ldloc (mb, dst_var);
+ mono_mb_emit_stloc (mb, 1);
+
+ mono_mb_patch_branch (mb, pos);
+ break;
+ }
+
+#ifndef DISABLE_COM
+ case MONO_MARSHAL_CONV_OBJECT_INTERFACE:
+ case MONO_MARSHAL_CONV_OBJECT_IDISPATCH:
+ case MONO_MARSHAL_CONV_OBJECT_IUNKNOWN:
+ mono_cominterop_emit_object_to_ptr_conv (mb, type, conv, mspec);
+ break;
+#endif /* DISABLE_COM */
+
+ case MONO_MARSHAL_CONV_SAFEHANDLE: {
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
+ mono_mb_emit_exception (mb, "ArgumentNullException", NULL);
+ mono_mb_patch_branch (mb, pos);
+
+ /* Pull the handle field from SafeHandle */
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle));
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_byte (mb, CEE_STIND_I);
+ break;
+ }
+
+ case MONO_MARSHAL_CONV_HANDLEREF: {
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoHandleRef, handle));
+ mono_mb_emit_byte (mb, CEE_ADD);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_byte (mb, CEE_STIND_I);
+ break;
+ }
+
+ default: {
+ g_error ("marshalling conversion %d not implemented", conv);
+ }
+ }
+}
diff --git a/src/mono/mono/metadata/marshal-shared.h b/src/mono/mono/metadata/marshal-shared.h
new file mode 100644
index 00000000000000..964b12bcda5c5f
--- /dev/null
+++ b/src/mono/mono/metadata/marshal-shared.h
@@ -0,0 +1,77 @@
+/**
+* \file
+* Functionality shared between the legacy and DisableRuntimeMarshaling marshaling subsystems.
+*
+* Licensed to the .NET Foundation under one or more agreements.
+* The .NET Foundation licenses this file to you under the MIT license.
+*/
+
+#include "mono/metadata/debug-helpers.h"
+#include "metadata/marshal.h"
+#include "metadata/method-builder-ilgen.h"
+#include "metadata/custom-attrs-internals.h"
+#include "metadata/class-init.h"
+#include "mono/metadata/class-internals.h"
+#include "metadata/reflection-internals.h"
+#include "mono/metadata/handle.h"
+
+#ifndef _MONO_METADATA_MARSHAL_SHARED_H_
+#define _MONO_METADATA_MARSHAL_SHARED_H_
+
+MonoMethod** mono_marshal_shared_get_sh_dangerous_add_ref (void);
+MonoMethod** mono_marshal_shared_get_sh_dangerous_release (void);
+
+void
+mono_marshal_shared_emit_marshal_custom_get_instance(MonoMethodBuilder *mb, MonoClass *klass, MonoMarshalSpec *spec);
+
+void
+mono_marshal_shared_init_safe_handle (void);
+
+void
+mono_mb_emit_auto_layout_exception (MonoMethodBuilder *mb, MonoClass *klass);
+
+gboolean mono_marshal_shared_is_in (const MonoType *t);
+
+gboolean mono_marshal_shared_is_out (const MonoType *t);
+
+MonoMarshalConv
+mono_marshal_shared_conv_str_inverse (MonoMarshalConv conv);
+
+void
+mono_marshal_shared_mb_emit_exception_marshal_directive (MonoMethodBuilder *mb, char *msg);
+
+void
+mono_marshal_shared_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec);
+
+gboolean
+mono_marshal_shared_get_fixed_buffer_attr (MonoClassField *field, MonoType **out_etype, int *out_len);
+
+void
+mono_marshal_shared_emit_fixed_buf_conv (MonoMethodBuilder *mb, MonoType *type, MonoType *etype, int len, gboolean to_object, int *out_usize);
+
+int
+mono_marshal_shared_offset_of_first_nonstatic_field (MonoClass *klass);
+
+MonoMethod*
+mono_marshal_shared_get_method_nofail (MonoClass *klass, const char *method_name, int num_params, int flags);
+
+MonoJitICallId
+mono_marshal_shared_conv_to_icall (MonoMarshalConv conv, int *ind_store_type);
+
+void
+mono_marshal_shared_emit_ptr_to_object_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec);
+
+void
+mono_marshal_shared_emit_struct_conv_full (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object,
+ int offset_of_first_child_field, MonoMarshalNative string_encoding);
+
+void
+mono_marshal_shared_emit_struct_conv (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
+
+void
+mono_marshal_shared_emit_thread_interrupt_checkpoint_call (MonoMethodBuilder *mb, MonoJitICallId checkpoint_icall_id);
+
+void
+mono_marshal_shared_emit_object_to_ptr_conv (MonoMethodBuilder *mb, MonoType *type, MonoMarshalConv conv, MonoMarshalSpec *mspec);
+
+#endif /* _MONO_METADATA_MARSHAL_SHARED_H_ */
\ No newline at end of file