Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAleksey Kliger (λgeek) <alklig@microsoft.com>2022-08-27 03:33:35 +0300
committerGitHub <noreply@github.com>2022-08-27 03:33:35 +0300
commit06aceb7015f3bd2ff019ef5920d2354eb2ea2c92 (patch)
tree7a73cabb99e50713bfe9e901a42d596aab7f75c8
parent3f9a51ae490930f41c820b6cd23eb6d2d6a79aa2 (diff)
Revert "[MONO] Move marshal-ilgen into a component (#71203)" (#74675)v7.0.0-rc.1.22426.10
This reverts commit de32c4466489090fdd41574d1be2945fd03ab7f2.
-rw-r--r--src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props7
-rw-r--r--src/libraries/System.Diagnostics.Tracing/tests/System.Diagnostics.Tracing.Tests.csproj2
-rw-r--r--src/mono/mono.proj3
-rw-r--r--src/mono/mono/component/CMakeLists.txt53
-rw-r--r--src/mono/mono/component/marshal-ilgen-noilgen.c186
-rw-r--r--src/mono/mono/component/marshal-ilgen-noilgen.h11
-rw-r--r--src/mono/mono/component/marshal-ilgen-stub.c41
-rw-r--r--src/mono/mono/component/marshal-ilgen.c2861
-rw-r--r--src/mono/mono/metadata/CMakeLists.txt3
-rw-r--r--src/mono/mono/metadata/components.c6
-rw-r--r--src/mono/mono/metadata/components.h11
-rw-r--r--src/mono/mono/metadata/marshal-ilgen.c2830
-rw-r--r--src/mono/mono/metadata/marshal-ilgen.h (renamed from src/mono/mono/component/marshal-ilgen.h)34
-rw-r--r--src/mono/mono/metadata/marshal-lightweight.c6
-rw-r--r--src/mono/mono/metadata/marshal-lightweight.h1
-rw-r--r--src/mono/mono/metadata/marshal-noilgen.c190
-rw-r--r--src/mono/mono/metadata/marshal-noilgen.h15
-rw-r--r--src/mono/mono/metadata/marshal.c70
-rw-r--r--src/mono/mono/metadata/marshal.h57
-rw-r--r--src/mono/mono/mini/CMakeLists.txt2
-rw-r--r--src/mono/msbuild/android/build/AndroidApp.targets5
-rw-r--r--src/mono/msbuild/apple/build/AppleApp.targets6
-rw-r--r--src/mono/sample/iOS/Program.csproj4
-rw-r--r--src/mono/wasm/build/WasmApp.InTree.props1
-rw-r--r--src/mono/wasm/build/WasmApp.Native.targets3
-rw-r--r--src/mono/wasm/runtime/CMakeLists.txt1
-rw-r--r--src/tests/build.proj4
27 files changed, 3047 insertions, 3366 deletions
diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
index 61f577981d1..07d77161002 100644
--- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
+++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
@@ -205,13 +205,6 @@
<PlatformManifestFileEntry Include="libmono-component-debugger-stub-static.a" IsNative="true" />
<PlatformManifestFileEntry Include="libmono-component-debugger-static.lib" IsNative="true" />
<PlatformManifestFileEntry Include="libmono-component-debugger-stub-static.lib" IsNative="true" />
- <PlatformManifestFileEntry Include="libmono-component-marshal-ilgen.dll" IsNative="true" />
- <PlatformManifestFileEntry Include="libmono-component-marshal-ilgen.so" IsNative="true" />
- <PlatformManifestFileEntry Include="libmono-component-marshal-ilgen.dylib" IsNative="true" />
- <PlatformManifestFileEntry Include="libmono-component-marshal-ilgen-static.a" IsNative="true" />
- <PlatformManifestFileEntry Include="libmono-component-marshal-ilgen-stub-static.a" IsNative="true" />
- <PlatformManifestFileEntry Include="libmono-component-marshal-ilgen-static.lib" IsNative="true" />
- <PlatformManifestFileEntry Include="libmono-component-marshal-ilgen-stub-static.lib" IsNative="true" />
<!-- Mono WASM-specific files -->
<PlatformManifestFileEntry Include="libmono-ee-interp.a" IsNative="true" />
<PlatformManifestFileEntry Include="libmono-icall-table.a" IsNative="true" />
diff --git a/src/libraries/System.Diagnostics.Tracing/tests/System.Diagnostics.Tracing.Tests.csproj b/src/libraries/System.Diagnostics.Tracing/tests/System.Diagnostics.Tracing.Tests.csproj
index 75300d8460b..35b1a833abb 100644
--- a/src/libraries/System.Diagnostics.Tracing/tests/System.Diagnostics.Tracing.Tests.csproj
+++ b/src/libraries/System.Diagnostics.Tracing/tests/System.Diagnostics.Tracing.Tests.csproj
@@ -6,7 +6,7 @@
<IncludeRemoteExecutor>true</IncludeRemoteExecutor>
</PropertyGroup>
<PropertyGroup>
- <RuntimeComponents Condition="'$(TargetsAppleMobile)' == 'true' or '$(TargetOS)' == 'Android'">diagnostics_tracing;marshal-ilgen</RuntimeComponents>
+ <RuntimeComponents Condition="'$(TargetsAppleMobile)' == 'true' or '$(TargetOS)' == 'Android'">diagnostics_tracing</RuntimeComponents>
</PropertyGroup>
<!-- Windows only files -->
<ItemGroup Condition="'$(TargetPlatformIdentifier)' == 'windows'">
diff --git a/src/mono/mono.proj b/src/mono/mono.proj
index 26ca5545d76..38731e96866 100644
--- a/src/mono/mono.proj
+++ b/src/mono/mono.proj
@@ -733,8 +733,7 @@
<MonoAOTCMakeArgs Include="-DENABLE_ICALL_SYMBOL_MAP=1" />
<MonoAOTCMakeArgs Include="-DDISABLE_SHARED_LIBS=1" />
<MonoAOTCMakeArgs Include="-DDISABLE_LIBS=1" />
- <!-- Link in only the components neeeded for AOT compilation -->
- <MonoAOTCMakeArgs Include="-DAOT_COMPONENTS=1 -DSTATIC_COMPONENTS=1;" />
+ <MonoAOTCMakeArgs Include="-DDISABLE_COMPONENTS=1" />
<MonoAOTCMakeArgs Condition="'$(MonoAotOffsetsFile)' != ''" Include="-DAOT_OFFSETS_FILE=&quot;$(MonoAotOffsetsFile)&quot;" />
<MonoAOTCMakeArgs Condition="'$(MonoAOTEnableLLVM)' == 'true'" Include="-DLLVM_PREFIX=$(MonoAOTLLVMDir.TrimEnd('\/'))" />
<MonoAOTCMakeArgs Include="$(_MonoAOTCFLAGSOption)" />
diff --git a/src/mono/mono/component/CMakeLists.txt b/src/mono/mono/component/CMakeLists.txt
index d83c9144af0..7c864322f5f 100644
--- a/src/mono/mono/component/CMakeLists.txt
+++ b/src/mono/mono/component/CMakeLists.txt
@@ -6,12 +6,9 @@ set(MONO_EVENTPIPE_GEN_INCLUDE_PATH "${CMAKE_CURRENT_BINARY_DIR}/eventpipe")
set(MONO_HOT_RELOAD_COMPONENT_NAME "hot_reload")
set(MONO_DIAGNOSTICS_TRACING_COMPONENT_NAME "diagnostics_tracing")
set(MONO_DEBUGGER_COMPONENT_NAME "debugger")
-set(MONO_MARSHAL_ILGEN_COMPONENT_NAME "marshal-ilgen")
# a list of every component.
set(components "")
-# a list of components needed by the AOT compiler
-set(components_for_aot "")
# the sources for each individiable component define a new
# component_name-sources list for each component, and a
@@ -82,53 +79,17 @@ set(${MONO_DIAGNOSTICS_TRACING_COMPONENT_NAME}-dependencies
${MONO_DIAGNOSTICS_TRACING_COMPONENT_NAME}-gen-sources
)
-# marshal-ilgen
-list(APPEND components
- ${MONO_MARSHAL_ILGEN_COMPONENT_NAME}
-)
-list(APPEND components_for_aot
- ${MONO_MARSHAL_ILGEN_COMPONENT_NAME}
-)
-
-set(${MONO_MARSHAL_ILGEN_COMPONENT_NAME}-sources
- ${MONO_COMPONENT_PATH}/marshal-ilgen.c
- ${MONO_COMPONENT_PATH}/marshal-ilgen.h
- ${MONO_COMPONENT_PATH}/marshal-ilgen-noilgen.c
- ${MONO_COMPONENT_PATH}/marshal-ilgen-noilgen.h
-)
-
-# For every component not build into the AOT compiler, build the stub instead
-set(stubs_for_aot "")
-foreach (component IN LISTS components)
- if (NOT (component IN_LIST components_for_aot))
- list(APPEND stubs_for_aot "${component}")
- endif()
-endforeach()
-
-
-set(${MONO_MARSHAL_ILGEN_COMPONENT_NAME}-stub-sources
- ${MONO_COMPONENT_PATH}/marshal-ilgen-stub.c
-)
-
-if (AOT_COMPONENTS)
- set(components_to_build ${components_for_aot})
- set(stubs_to_build ${stubs_for_aot})
-else()
- set(components_to_build ${components})
- set(stubs_to_build ${components})
-endif()
-
# from here down, all the components are treated in the same way
#define a library for each component and component stub
function(define_component_libs)
# NOTE: keep library naming pattern in sync with RuntimeComponentManifest.targets
- if (AOT_COMPONENTS OR NOT DISABLE_LIBS )
- foreach(component IN LISTS components_to_build)
+ if (NOT DISABLE_LIBS)
+ foreach(component IN LISTS components)
add_library("mono-component-${component}-static" STATIC $<TARGET_OBJECTS:${component}-objects>)
install(TARGETS "mono-component-${component}-static" LIBRARY)
endforeach()
- foreach(component IN LISTS stubs_to_build)
+ foreach(component IN LISTS components)
add_library("mono-component-${component}-stub-static" STATIC $<TARGET_OBJECTS:${component}-stub-objects>)
install(TARGETS "mono-component-${component}-stub-static" LIBRARY)
endforeach()
@@ -142,7 +103,7 @@ target_sources(component_base INTERFACE
)
target_link_libraries(component_base INTERFACE monoapi)
-if(NOT AOT_COMPONENTS AND (DISABLE_COMPONENTS OR DISABLE_LIBS))
+if(DISABLE_COMPONENTS OR DISABLE_LIBS)
set(DISABLE_COMPONENT_OBJECTS 1)
endif()
@@ -162,7 +123,7 @@ endforeach()
if(NOT DISABLE_COMPONENTS AND NOT STATIC_COMPONENTS)
# define a shared library for each component
- foreach(component IN LISTS components_to_build)
+ foreach(component IN LISTS components)
# NOTE: keep library naming pattern in sync with RuntimeComponentManifest.targets
if(HOST_WIN32)
add_library("mono-component-${component}" SHARED "${${component}-sources}")
@@ -194,14 +155,14 @@ if(NOT DISABLE_COMPONENTS AND NOT STATIC_COMPONENTS)
#define a library for each component and component stub
define_component_libs()
-elseif(AOT_COMPONENTS OR (NOT DISABLE_COMPONENTS AND STATIC_COMPONENTS))
+elseif(NOT DISABLE_COMPONENTS AND STATIC_COMPONENTS)
#define a library for each component and component stub
define_component_libs()
# define a list of mono-components objects for mini if building a shared libmono with static-linked components
set(mono-components-objects "")
- foreach(component IN LISTS components_to_build)
+ foreach(component IN LISTS components)
list(APPEND mono-components-objects $<TARGET_OBJECTS:${component}-objects>)
endforeach()
diff --git a/src/mono/mono/component/marshal-ilgen-noilgen.c b/src/mono/mono/component/marshal-ilgen-noilgen.c
deleted file mode 100644
index 6cf9dfd5ac6..00000000000
--- a/src/mono/mono/component/marshal-ilgen-noilgen.c
+++ /dev/null
@@ -1,186 +0,0 @@
-#include "mono/component/marshal-ilgen.h"
-#include "mono/component/marshal-ilgen-noilgen.h"
-
-#ifndef ENABLE_ILGEN
-static int
-emit_marshal_array_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec,
- int conv_arg, MonoType **conv_arg_type,
- MarshalAction action)
-{
- MonoType *int_type = mono_get_int_type ();
- MonoType *object_type = mono_get_object_type ();
- switch (action) {
- case MARSHAL_ACTION_CONV_IN:
- *conv_arg_type = object_type;
- break;
- case MARSHAL_ACTION_MANAGED_CONV_IN:
- *conv_arg_type = int_type;
- break;
- }
- return conv_arg;
-}
-
-static int
-emit_marshal_ptr_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec, int conv_arg,
- MonoType **conv_arg_type, MarshalAction action)
-{
- return conv_arg;
-}
-#endif
-
-#if !defined(ENABLE_ILGEN) || defined(DISABLE_NONBLITTABLE)
-static int
-emit_marshal_vtype_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec,
- int conv_arg, MonoType **conv_arg_type,
- MarshalAction action)
-{
- return conv_arg;
-}
-
-static int
-emit_marshal_string_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec,
- int conv_arg, MonoType **conv_arg_type,
- MarshalAction action)
-{
- MonoType *int_type = mono_get_int_type ();
- switch (action) {
- case MARSHAL_ACTION_CONV_IN:
- *conv_arg_type = int_type;
- break;
- case MARSHAL_ACTION_MANAGED_CONV_IN:
- *conv_arg_type = int_type;
- break;
- }
- return conv_arg;
-}
-
-static int
-emit_marshal_safehandle_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec, int conv_arg,
- MonoType **conv_arg_type, MarshalAction action)
-{
- MonoType *int_type = mono_get_int_type ();
- if (action == MARSHAL_ACTION_CONV_IN)
- *conv_arg_type = int_type;
- return conv_arg;
-}
-
-static int
-emit_marshal_handleref_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec, int conv_arg,
- MonoType **conv_arg_type, MarshalAction action)
-{
- MonoType *int_type = mono_get_int_type ();
- if (action == MARSHAL_ACTION_CONV_IN)
- *conv_arg_type = int_type;
- return conv_arg;
-}
-
-static int
-emit_marshal_object_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec,
- int conv_arg, MonoType **conv_arg_type,
- MarshalAction action)
-{
- MonoType *int_type = mono_get_int_type ();
- if (action == MARSHAL_ACTION_CONV_IN)
- *conv_arg_type = int_type;
- return conv_arg;
-}
-
-static int
-emit_marshal_variant_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec,
- int conv_arg, MonoType **conv_arg_type,
- MarshalAction action)
-{
- g_assert_not_reached ();
-}
-
-static int
-emit_marshal_asany_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec,
- int conv_arg, MonoType **conv_arg_type,
- MarshalAction action)
-{
- return conv_arg;
-}
-
-static int
-emit_marshal_boolean_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec,
- int conv_arg, MonoType **conv_arg_type,
- MarshalAction action)
-{
- MonoType *int_type = mono_get_int_type ();
- switch (action) {
- case MARSHAL_ACTION_CONV_IN:
- if (m_type_is_byref (t))
- *conv_arg_type = int_type;
- else
- *conv_arg_type = mono_marshal_boolean_conv_in_get_local_type (spec, NULL);
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_IN: {
- MonoClass* conv_arg_class = mono_marshal_boolean_managed_conv_in_get_conv_arg_class (spec, NULL);
- if (m_type_is_byref (t))
- *conv_arg_type = m_class_get_this_arg (conv_arg_class);
- else
- *conv_arg_type = m_class_get_byval_arg (conv_arg_class);
- break;
- }
-
- }
- return conv_arg;
-}
-
-static int
-emit_marshal_char_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec, int conv_arg,
- MonoType **conv_arg_type, MarshalAction action)
-{
- return conv_arg;
-}
-
-static int
-emit_marshal_custom_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec,
- int conv_arg, MonoType **conv_arg_type,
- MarshalAction action)
-{
- MonoType *int_type = mono_get_int_type ();
- if (action == MARSHAL_ACTION_CONV_IN && t->type == MONO_TYPE_VALUETYPE)
- *conv_arg_type = int_type;
- return conv_arg;
-}
-#endif
-
-#ifndef ENABLE_ILGEN
-
-void
-mono_marshal_noilgen_init_heavyweight (void)
-{
- MonoMarshalILgenCallbacks ilgen_cb;
-
- ilgen_cb.version = MONO_MARSHAL_CALLBACKS_VERSION;
- ilgen_cb.emit_marshal_array = emit_marshal_array_noilgen;
- ilgen_cb.emit_marshal_vtype = emit_marshal_vtype_noilgen;
- ilgen_cb.emit_marshal_string = emit_marshal_string_noilgen;
- ilgen_cb.emit_marshal_safehandle = emit_marshal_safehandle_noilgen;
- ilgen_cb.emit_marshal_handleref = emit_marshal_handleref_noilgen;
- ilgen_cb.emit_marshal_object = emit_marshal_object_noilgen;
- ilgen_cb.emit_marshal_variant = emit_marshal_variant_noilgen;
- ilgen_cb.emit_marshal_asany = emit_marshal_asany_noilgen;
- ilgen_cb.emit_marshal_boolean = emit_marshal_boolean_noilgen;
- ilgen_cb.emit_marshal_custom = emit_marshal_custom_noilgen;
- ilgen_cb.emit_marshal_ptr = emit_marshal_ptr_noilgen;
-
- ilgen_cb.emit_marshal_char = emit_marshal_char_noilgen;
- mono_install_marshal_callbacks_ilgen(&ilgen_cb);
-}
-
-#endif \ No newline at end of file
diff --git a/src/mono/mono/component/marshal-ilgen-noilgen.h b/src/mono/mono/component/marshal-ilgen-noilgen.h
deleted file mode 100644
index 5e877c22383..00000000000
--- a/src/mono/mono/component/marshal-ilgen-noilgen.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * \file
- * Copyright 2022 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-#ifndef __MARSHAL_ILGEN_NOILGEN_H__
-#define __MARSHAL_ILGEN_NOILGEN_H__
-
-void mono_marshal_noilgen_init_heavyweight (void);
-
-#endif // __MARSHAL_ILGEN_NOILGEN_H__ \ No newline at end of file
diff --git a/src/mono/mono/component/marshal-ilgen-stub.c b/src/mono/mono/component/marshal-ilgen-stub.c
deleted file mode 100644
index 8182c95b7e2..00000000000
--- a/src/mono/mono/component/marshal-ilgen-stub.c
+++ /dev/null
@@ -1,41 +0,0 @@
-
-#include <mono/component/component.h>
-#include <mono/component/marshal-ilgen.h>
-#include <mono/metadata/marshal.h>
-
-static bool
-marshal_ilgen_available (void)
-{
- return false;
-}
-
-static int
-stub_emit_marshal_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec, int conv_arg,
- MonoType **conv_arg_type, MarshalAction action, MonoMarshalLightweightCallbacks* lightweigth_cb)
-{
- return 0;
-}
-
-static void
-mono_component_marshal_ilgen_stub_init(void)
-{
-}
-
-static void
-stub_mono_marshal_ilgen_install_callbacks_mono (IlgenCallbacksToMono *callbacks)
-{
-}
-
-static MonoComponentMarshalILgen component_func_table = {
- { MONO_COMPONENT_ITF_VERSION, &marshal_ilgen_available },
- mono_component_marshal_ilgen_stub_init,
- stub_emit_marshal_ilgen,
- stub_mono_marshal_ilgen_install_callbacks_mono
-};
-
-MonoComponentMarshalILgen*
-mono_component_marshal_ilgen_init (void)
-{
- return &component_func_table;
-}
diff --git a/src/mono/mono/component/marshal-ilgen.c b/src/mono/mono/component/marshal-ilgen.c
deleted file mode 100644
index e6deeea5564..00000000000
--- a/src/mono/mono/component/marshal-ilgen.c
+++ /dev/null
@@ -1,2861 +0,0 @@
-
-#include "mono/metadata/debug-helpers.h"
-#include "metadata/marshal.h"
-#include "component/marshal-ilgen.h"
-#include "mono/component/marshal-ilgen.h"
-#include "mono/component/marshal-ilgen-noilgen.h"
-#include "metadata/marshal-lightweight.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"
-#include "mono/component/component.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
-
-#define mono_mb_emit_jit_icall(mb, name) (cb_to_mono->mb_emit_icall_id ((mb), MONO_JIT_ICALL_ ## name))
-
-static GENERATE_GET_CLASS_WITH_CACHE (date_time, "System", "DateTime");
-static GENERATE_TRY_GET_CLASS_WITH_CACHE (icustom_marshaler, "System.Runtime.InteropServices", "ICustomMarshaler");
-
-static void emit_string_free_icall (MonoMethodBuilder *mb, MonoMarshalConv conv);
-
-static void mono_marshal_ilgen_legacy_init (void);
-
-static gboolean ilgen_cb_inited = FALSE;
-static MonoMarshalILgenCallbacks ilgen_marshal_cb;
-
-static IlgenCallbacksToMono *cb_to_mono;
-
-static bool
-marshal_ilgen_available (void)
-{
- return true;
-}
-
-static MonoComponentMarshalILgen component_func_table = {
- { MONO_COMPONENT_ITF_VERSION, &marshal_ilgen_available },
- &mono_marshal_ilgen_init,
- &mono_emit_marshal_ilgen,
- &mono_marshal_ilgen_install_callbacks_mono
-};
-
-
-MonoComponentMarshalILgen*
-mono_component_marshal_ilgen_init (void)
-{
- return &component_func_table;
-}
-
-void
-mono_install_marshal_callbacks_ilgen (MonoMarshalILgenCallbacks *cb)
-{
- g_assert (!ilgen_cb_inited);
- g_assert (cb->version == MONO_MARSHAL_CALLBACKS_VERSION);
- memcpy (&ilgen_marshal_cb, cb, sizeof (MonoMarshalILgenCallbacks));
- ilgen_cb_inited = TRUE;
-}
-
-void
-mono_marshal_ilgen_install_callbacks_mono (IlgenCallbacksToMono *callbacks)
-{
- cb_to_mono = callbacks;
-}
-
-static void
-emit_struct_free (MonoMethodBuilder *mb, MonoClass *klass, int struct_var)
-{
- /* Call DestroyStructure */
- /* FIXME: Only do this if needed */
- cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- cb_to_mono->mb_emit_op (mb, CEE_MONO_CLASSCONST, klass);
- cb_to_mono->mb_emit_ldloc (mb, struct_var);
- mono_mb_emit_jit_icall (mb, mono_struct_delete_old);
-}
-
-static int
-emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec,
- int conv_arg, MonoType **conv_arg_type,
- MarshalAction action)
-{
- MonoMethodBuilder *mb = m->mb;
- MonoClass *klass = mono_class_from_mono_type_internal (t);
- MonoMarshalNative encoding;
-
- encoding = cb_to_mono->get_string_encoding (m->piinfo, spec);
- MonoType *int_type = cb_to_mono->get_int_type ();
- MonoType *object_type = cb_to_mono->get_object_type ();
-
- MonoClass *eklass = m_class_get_element_class (klass);
-
- switch (action) {
- case MARSHAL_ACTION_CONV_IN:
- *conv_arg_type = object_type;
- conv_arg = cb_to_mono->mb_add_local (mb, object_type);
-
- if (m_class_is_blittable (eklass)) {
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (MONO_MARSHAL_CONV_ARRAY_LPARRAY, NULL));
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- } else {
-#ifdef DISABLE_NONBLITTABLE
- char *msg = g_strdup ("Non-blittable marshalling conversion is disabled");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
-#else
- guint32 label1, label2, label3;
- int index_var, src_var, dest_ptr, esize;
- MonoMarshalConv conv;
- gboolean is_string = FALSE;
-
- dest_ptr = cb_to_mono->mb_add_local (mb, int_type);
-
- if (eklass == cb_to_mono->mono_defaults->string_class) {
- is_string = TRUE;
- conv = cb_to_mono->get_string_to_ptr_conv (m->piinfo, spec);
- }
- else if (eklass == cb_to_mono->try_get_stringbuilder_class ()) {
- is_string = TRUE;
- conv = cb_to_mono->get_stringbuilder_to_ptr_conv (m->piinfo, spec);
- }
- else
- conv = MONO_MARSHAL_CONV_INVALID;
-
- if (is_string && conv == MONO_MARSHAL_CONV_INVALID) {
- char *msg = g_strdup_printf ("string/stringbuilder marshalling conversion %d not implemented", encoding);
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- break;
- }
-
- src_var = cb_to_mono->mb_add_local (mb, object_type);
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
- cb_to_mono->mb_emit_stloc (mb, src_var);
-
- /* Check null */
- cb_to_mono->mb_emit_ldloc (mb, src_var);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- cb_to_mono->mb_emit_ldloc (mb, src_var);
- label1 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- if (is_string)
- esize = TARGET_SIZEOF_VOID_P;
- else if (eklass == cb_to_mono->mono_defaults->char_class) /*can't call mono_marshal_type_size since it causes all sorts of asserts*/
- esize = cb_to_mono->pinvoke_is_unicode (m->piinfo) ? 2 : 1;
- else
- esize = cb_to_mono->class_native_size (eklass, NULL);
-
- /* allocate space for the native struct and store the address */
- cb_to_mono->mb_emit_icon (mb, esize);
- cb_to_mono->mb_emit_ldloc (mb, src_var);
- cb_to_mono->mb_emit_byte (mb, CEE_LDLEN);
-
- if (eklass == cb_to_mono->mono_defaults->string_class) {
- /* Make the array bigger for the terminating null */
- cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_1);
- cb_to_mono->mb_emit_byte (mb, CEE_ADD);
- }
- cb_to_mono->mb_emit_byte (mb, CEE_MUL);
- cb_to_mono->mb_emit_byte (mb, CEE_PREFIX1);
- cb_to_mono->mb_emit_byte (mb, CEE_LOCALLOC);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
-
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_stloc (mb, dest_ptr);
-
- /* Emit marshalling loop */
- index_var = cb_to_mono->mb_add_local (mb, int_type);
- cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0);
- cb_to_mono->mb_emit_stloc (mb, index_var);
- label2 = cb_to_mono->mb_get_label (mb);
- cb_to_mono->mb_emit_ldloc (mb, index_var);
- cb_to_mono->mb_emit_ldloc (mb, src_var);
- cb_to_mono->mb_emit_byte (mb, CEE_LDLEN);
- label3 = cb_to_mono->mb_emit_branch (mb, CEE_BGE);
-
- /* Emit marshalling code */
-
- if (is_string) {
- int stind_op;
- cb_to_mono->mb_emit_ldloc (mb, dest_ptr);
- cb_to_mono->mb_emit_ldloc (mb, src_var);
- cb_to_mono->mb_emit_ldloc (mb, index_var);
- cb_to_mono->mb_emit_byte (mb, CEE_LDELEM_REF);
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, &stind_op));
- cb_to_mono->mb_emit_byte (mb, GINT_TO_UINT8 (stind_op));
- } else {
- /* set the src_ptr */
- cb_to_mono->mb_emit_ldloc (mb, src_var);
- cb_to_mono->mb_emit_ldloc (mb, index_var);
- cb_to_mono->mb_emit_op (mb, CEE_LDELEMA, eklass);
- cb_to_mono->mb_emit_stloc (mb, 0);
-
- /* set dst_ptr */
- cb_to_mono->mb_emit_ldloc (mb, dest_ptr);
- cb_to_mono->mb_emit_stloc (mb, 1);
-
- /* emit valuetype conversion code */
- cb_to_mono->emit_struct_conv_full (mb, eklass, FALSE, 0, eklass == cb_to_mono->mono_defaults->char_class ? encoding : (MonoMarshalNative)-1);
- }
-
- cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1);
- cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (dest_ptr), esize);
-
- cb_to_mono->mb_emit_branch_label (mb, CEE_BR, label2);
-
- cb_to_mono->mb_patch_branch (mb, label3);
-
- if (eklass == cb_to_mono->mono_defaults->string_class) {
- /* Null terminate */
- cb_to_mono->mb_emit_ldloc (mb, dest_ptr);
- cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0);
- cb_to_mono->mb_emit_byte (mb, CEE_STIND_I);
- }
-
- cb_to_mono->mb_patch_branch (mb, label1);
-#endif
- }
-
- break;
-
- case MARSHAL_ACTION_CONV_OUT: {
-#ifndef DISABLE_NONBLITTABLE
- gboolean need_convert, need_free;
- /* Unicode character arrays are implicitly marshalled as [Out] under MS.NET */
- need_convert = ((eklass == cb_to_mono->mono_defaults->char_class) && (encoding == MONO_NATIVE_LPWSTR)) || (eklass == cb_to_mono->try_get_stringbuilder_class ()) || (t->attrs & PARAM_ATTRIBUTE_OUT);
- need_free = cb_to_mono->need_free (m_class_get_byval_arg (eklass), m->piinfo, spec);
-
- if ((t->attrs & PARAM_ATTRIBUTE_OUT) && spec && spec->native == MONO_NATIVE_LPARRAY && spec->data.array_data.param_num != -1) {
- int param_num = spec->data.array_data.param_num;
- MonoType *param_type;
-
- param_type = m->sig->params [param_num];
-
- if (m_type_is_byref (param_type) && param_type->type != MONO_TYPE_I4) {
- char *msg = g_strdup ("Not implemented.");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- break;
- }
-
- if (m_type_is_byref (t) ) {
- cb_to_mono->mb_emit_ldarg (mb, argnum);
-
- /* Create the managed array */
- cb_to_mono->mb_emit_ldarg (mb, param_num);
- if (m_type_is_byref (m->sig->params [param_num]))
- // FIXME: Support other types
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I4);
- cb_to_mono->mb_emit_byte (mb, CEE_CONV_OVF_I);
- cb_to_mono->mb_emit_op (mb, CEE_NEWARR, eklass);
- /* Store into argument */
- cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF);
- }
- }
-
- if (need_convert || need_free) {
- /* FIXME: Optimize blittable case */
- guint32 label1, label2, label3;
- int index_var, src_ptr, loc, esize;
-
- if ((eklass == cb_to_mono->try_get_stringbuilder_class ()) || (eklass == cb_to_mono->mono_defaults->string_class))
- esize = TARGET_SIZEOF_VOID_P;
- else if (eklass == cb_to_mono->mono_defaults->char_class)
- esize = cb_to_mono->pinvoke_is_unicode (m->piinfo) ? 2 : 1;
- else
- esize = cb_to_mono->class_native_size (eklass, NULL);
- src_ptr = cb_to_mono->mb_add_local (mb, int_type);
- loc = cb_to_mono->mb_add_local (mb, int_type);
-
- /* Check null */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
- label1 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_stloc (mb, src_ptr);
-
- /* Emit marshalling loop */
- index_var = cb_to_mono->mb_add_local (mb, int_type);
- cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0);
- cb_to_mono->mb_emit_stloc (mb, index_var);
- label2 = cb_to_mono->mb_get_label (mb);
- cb_to_mono->mb_emit_ldloc (mb, index_var);
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_REF);
- cb_to_mono->mb_emit_byte (mb, CEE_LDLEN);
- label3 = cb_to_mono->mb_emit_branch (mb, CEE_BGE);
-
- /* Emit marshalling code */
-
- if (eklass == cb_to_mono->try_get_stringbuilder_class ()) {
- gboolean need_free2;
- MonoMarshalConv conv = cb_to_mono->get_ptr_to_stringbuilder_conv (m->piinfo, spec, &need_free2);
-
- g_assert (conv != MONO_MARSHAL_CONV_INVALID);
-
- /* dest */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
- cb_to_mono->mb_emit_ldloc (mb, index_var);
- cb_to_mono->mb_emit_byte (mb, CEE_LDELEM_REF);
-
- /* src */
- cb_to_mono->mb_emit_ldloc (mb, src_ptr);
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
-
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, NULL));
-
- if (need_free) {
- /* src */
- cb_to_mono->mb_emit_ldloc (mb, src_ptr);
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
-
- mono_mb_emit_jit_icall (mb, mono_marshal_free);
- }
- }
- else if (eklass == cb_to_mono->mono_defaults->string_class) {
- if (need_free) {
- /* src */
- cb_to_mono->mb_emit_ldloc (mb, src_ptr);
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
-
- mono_mb_emit_jit_icall (mb, mono_marshal_free);
- }
- }
- else {
- if (need_convert) {
- /* set the src_ptr */
- cb_to_mono->mb_emit_ldloc (mb, src_ptr);
- cb_to_mono->mb_emit_stloc (mb, 0);
-
- /* set dst_ptr */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_REF);
- cb_to_mono->mb_emit_ldloc (mb, index_var);
- cb_to_mono->mb_emit_op (mb, CEE_LDELEMA, eklass);
- cb_to_mono->mb_emit_stloc (mb, 1);
-
- /* emit valuetype conversion code */
- cb_to_mono->emit_struct_conv_full (mb, eklass, TRUE, 0, eklass == cb_to_mono->mono_defaults->char_class ? encoding : (MonoMarshalNative)-1);
- }
-
- if (need_free) {
- cb_to_mono->mb_emit_ldloc (mb, src_ptr);
- cb_to_mono->mb_emit_stloc (mb, loc);
-
- emit_struct_free (mb, eklass, loc);
- }
- }
-
- cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1);
- cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (src_ptr), esize);
-
- cb_to_mono->mb_emit_branch_label (mb, CEE_BR, label2);
-
- cb_to_mono->mb_patch_branch (mb, label1);
- cb_to_mono->mb_patch_branch (mb, label3);
- }
-#endif
-
- if (m_class_is_blittable (eklass)) {
- /* free memory allocated (if any) by MONO_MARSHAL_CONV_ARRAY_LPARRAY */
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_REF);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (MONO_MARSHAL_FREE_LPARRAY, NULL));
- }
-
- break;
- }
-
- case MARSHAL_ACTION_PUSH:
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg);
- else
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- break;
-
- case MARSHAL_ACTION_CONV_RESULT: {
- cb_to_mono->mb_emit_byte (mb, CEE_POP);
- char *msg = g_strdup_printf ("Cannot marshal 'return value': Invalid managed/unmanaged type combination.");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- break;
- }
-
- case MARSHAL_ACTION_MANAGED_CONV_IN: {
- guint32 label1, label2, label3;
- int index_var, src_ptr, esize, param_num, num_elem;
- MonoMarshalConv conv;
- gboolean is_string = FALSE;
-
- conv_arg = cb_to_mono->mb_add_local (mb, object_type);
- *conv_arg_type = int_type;
-
- if (m_type_is_byref (t)) {
- char *msg = g_strdup ("Byref array marshalling to managed code is not implemented.");
- cb_to_mono->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.");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- return conv_arg;
- }
-
- switch (spec->native) {
- case MONO_NATIVE_LPARRAY:
- break;
- case MONO_NATIVE_SAFEARRAY:
-#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.");
- cb_to_mono->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.");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- return conv_arg;
- }
- }
-
- /* FIXME: t is from the method which is wrapped, not the delegate type */
- /* g_assert (t->attrs & PARAM_ATTRIBUTE_IN); */
-
- param_num = spec->data.array_data.param_num;
- num_elem = spec->data.array_data.num_elem;
- if (spec->data.array_data.elem_mult == 0)
- /* param_num is not specified */
- param_num = -1;
-
- 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.");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- return conv_arg;
- }
- }
-
- /* FIXME: Optimize blittable case */
-
-#ifndef DISABLE_NONBLITTABLE
- if (eklass == cb_to_mono->mono_defaults->string_class) {
- is_string = TRUE;
- gboolean need_free;
- conv = cb_to_mono->get_ptr_to_string_conv (m->piinfo, spec, &need_free);
- }
- else if (eklass == cb_to_mono->try_get_stringbuilder_class ()) {
- is_string = TRUE;
- gboolean need_free;
- conv = cb_to_mono->get_ptr_to_stringbuilder_conv (m->piinfo, spec, &need_free);
- }
- else
- conv = MONO_MARSHAL_CONV_INVALID;
-#endif
-
- cb_to_mono->load_type_info (eklass);
-
- if (is_string)
- esize = TARGET_SIZEOF_VOID_P;
- else
- esize = cb_to_mono->class_native_size (eklass, NULL);
- src_ptr = cb_to_mono->mb_add_local (mb, int_type);
-
- cb_to_mono->mb_emit_byte (mb, CEE_LDNULL);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
-
- /* Check param index */
- if (param_num != -1) {
- if (param_num >= m->sig->param_count) {
- char *msg = g_strdup ("Array size control parameter index is out of range.");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- return conv_arg;
- }
- switch (m->sig->params [param_num]->type) {
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I:
- case MONO_TYPE_U:
- case MONO_TYPE_I8:
- case MONO_TYPE_U8:
- break;
- default: {
- char *msg = g_strdup ("Array size control parameter must be an integral type.");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- return conv_arg;
- }
- }
- }
-
- /* Check null */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- label1 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_stloc (mb, src_ptr);
-
- /* Create managed array */
- /*
- * The LPArray marshalling spec says that sometimes param_num starts
- * from 1, sometimes it starts from 0. But MS seems to allways start
- * from 0.
- */
-
- if (param_num == -1) {
- cb_to_mono->mb_emit_icon (mb, num_elem);
- } else {
- cb_to_mono->mb_emit_ldarg (mb, param_num);
- if (num_elem > 0) {
- cb_to_mono->mb_emit_icon (mb, num_elem);
- cb_to_mono->mb_emit_byte (mb, CEE_ADD);
- }
- cb_to_mono->mb_emit_byte (mb, CEE_CONV_OVF_I);
- }
-
- cb_to_mono->mb_emit_op (mb, CEE_NEWARR, eklass);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
-
- if (m_class_is_blittable (eklass)) {
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_byte (mb, CEE_CONV_I);
- cb_to_mono->mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoArray, vector));
- cb_to_mono->mb_emit_byte (mb, CEE_ADD);
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_byte (mb, CEE_LDLEN);
- cb_to_mono->mb_emit_icon (mb, esize);
- cb_to_mono->mb_emit_byte (mb, CEE_MUL);
- cb_to_mono->mb_emit_byte (mb, CEE_PREFIX1);
- cb_to_mono->mb_emit_byte (mb, CEE_CPBLK);
- cb_to_mono->mb_patch_branch (mb, label1);
- break;
- }
-#ifdef DISABLE_NONBLITTABLE
- else {
- char *msg = g_strdup ("Non-blittable marshalling conversion is disabled");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- }
-#else
- /* Emit marshalling loop */
- index_var = cb_to_mono->mb_add_local (mb, int_type);
- cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0);
- cb_to_mono->mb_emit_stloc (mb, index_var);
- label2 = cb_to_mono->mb_get_label (mb);
- cb_to_mono->mb_emit_ldloc (mb, index_var);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_byte (mb, CEE_LDLEN);
- label3 = cb_to_mono->mb_emit_branch (mb, CEE_BGE);
-
- /* Emit marshalling code */
- if (is_string) {
- g_assert (conv != MONO_MARSHAL_CONV_INVALID);
-
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_ldloc (mb, index_var);
-
- cb_to_mono->mb_emit_ldloc (mb, src_ptr);
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
-
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, NULL));
- cb_to_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.");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- return conv_arg;
- }
-
- cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1);
- cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (src_ptr), esize);
-
- cb_to_mono->mb_emit_branch_label (mb, CEE_BR, label2);
-
- cb_to_mono->mb_patch_branch (mb, label1);
- cb_to_mono->mb_patch_branch (mb, label3);
-#endif
-
- break;
- }
- case MARSHAL_ACTION_MANAGED_CONV_OUT: {
- guint32 label1, label2, label3;
- int index_var, dest_ptr, esize, param_num, num_elem;
- MonoMarshalConv conv;
- gboolean is_string = FALSE;
-
- if (!spec)
- /* Already handled in CONV_IN */
- break;
-
- /* These are already checked in CONV_IN */
- g_assert (!m_type_is_byref (t));
- g_assert (spec->native == MONO_NATIVE_LPARRAY);
- g_assert (t->attrs & PARAM_ATTRIBUTE_OUT);
-
- param_num = spec->data.array_data.param_num;
- num_elem = spec->data.array_data.num_elem;
-
- if (spec->data.array_data.elem_mult == 0)
- /* param_num is not specified */
- param_num = -1;
-
- if (param_num == -1) {
- if (num_elem <= 0) {
- g_assert_not_reached ();
- }
- }
-
- /* FIXME: Optimize blittable case */
-
-#ifndef DISABLE_NONBLITTABLE
- if (eklass == cb_to_mono->mono_defaults->string_class) {
- is_string = TRUE;
- conv = cb_to_mono->get_string_to_ptr_conv (m->piinfo, spec);
- }
- else if (eklass == cb_to_mono->try_get_stringbuilder_class ()) {
- is_string = TRUE;
- conv = cb_to_mono->get_stringbuilder_to_ptr_conv (m->piinfo, spec);
- }
- else
- conv = MONO_MARSHAL_CONV_INVALID;
-#endif
-
- cb_to_mono->load_type_info (eklass);
-
- if (is_string)
- esize = TARGET_SIZEOF_VOID_P;
- else
- esize = cb_to_mono->class_native_size (eklass, NULL);
-
- dest_ptr = cb_to_mono->mb_add_local (mb, int_type);
-
- /* Check null */
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- label1 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_stloc (mb, dest_ptr);
-
- if (m_class_is_blittable (eklass)) {
- /* dest */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- /* src */
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_byte (mb, CEE_CONV_I);
- cb_to_mono->mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoArray, vector));
- cb_to_mono->mb_emit_byte (mb, CEE_ADD);
- /* length */
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_byte (mb, CEE_LDLEN);
- cb_to_mono->mb_emit_icon (mb, esize);
- cb_to_mono->mb_emit_byte (mb, CEE_MUL);
- cb_to_mono->mb_emit_byte (mb, CEE_PREFIX1);
- cb_to_mono->mb_emit_byte (mb, CEE_CPBLK);
- cb_to_mono->mb_patch_branch (mb, label1);
- break;
- }
-
-#ifndef DISABLE_NONBLITTABLE
- /* Emit marshalling loop */
- index_var = cb_to_mono->mb_add_local (mb, int_type);
- cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0);
- cb_to_mono->mb_emit_stloc (mb, index_var);
- label2 = cb_to_mono->mb_get_label (mb);
- cb_to_mono->mb_emit_ldloc (mb, index_var);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_byte (mb, CEE_LDLEN);
- label3 = cb_to_mono->mb_emit_branch (mb, CEE_BGE);
-
- /* Emit marshalling code */
- if (is_string) {
- int stind_op;
- g_assert (conv != MONO_MARSHAL_CONV_INVALID);
-
- /* dest */
- cb_to_mono->mb_emit_ldloc (mb, dest_ptr);
-
- /* src */
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_ldloc (mb, index_var);
-
- cb_to_mono->mb_emit_byte (mb, CEE_LDELEM_REF);
-
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, &stind_op));
- cb_to_mono->mb_emit_byte (mb, GINT_TO_UINT8 (stind_op));
- }
- else {
- char *msg = g_strdup ("Marshalling of non-string and non-blittable arrays to managed code is not implemented.");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- return conv_arg;
- }
-
- cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1);
- cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (dest_ptr), esize);
-
- cb_to_mono->mb_emit_branch_label (mb, CEE_BR, label2);
-
- cb_to_mono->mb_patch_branch (mb, label1);
- cb_to_mono->mb_patch_branch (mb, label3);
-#endif
-
- break;
- }
- case MARSHAL_ACTION_MANAGED_CONV_RESULT: {
-#ifndef DISABLE_NONBLITTABLE
- guint32 label1, label2, label3;
- int index_var, src, dest, esize;
- MonoMarshalConv conv = MONO_MARSHAL_CONV_INVALID;
- gboolean is_string = FALSE;
-
- g_assert (!m_type_is_byref (t));
-
- cb_to_mono->load_type_info (eklass);
-
- if (eklass == cb_to_mono->mono_defaults->string_class) {
- is_string = TRUE;
- conv = cb_to_mono->get_string_to_ptr_conv (m->piinfo, spec);
- }
- else {
- g_assert_not_reached ();
- }
-
- if (is_string)
- esize = TARGET_SIZEOF_VOID_P;
- else if (eklass == cb_to_mono->mono_defaults->char_class)
- esize = cb_to_mono->pinvoke_is_unicode (m->piinfo) ? 2 : 1;
- else
- esize = cb_to_mono->class_native_size (eklass, NULL);
-
- src = cb_to_mono->mb_add_local (mb, object_type);
- dest = cb_to_mono->mb_add_local (mb, int_type);
-
- cb_to_mono->mb_emit_stloc (mb, src);
- cb_to_mono->mb_emit_ldloc (mb, src);
- cb_to_mono->mb_emit_stloc (mb, 3);
-
- /* Check for null */
- cb_to_mono->mb_emit_ldloc (mb, src);
- label1 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- /* Allocate native array */
- cb_to_mono->mb_emit_icon (mb, esize);
- cb_to_mono->mb_emit_ldloc (mb, src);
- cb_to_mono->mb_emit_byte (mb, CEE_LDLEN);
-
- if (eklass == cb_to_mono->mono_defaults->string_class) {
- /* Make the array bigger for the terminating null */
- cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_1);
- cb_to_mono->mb_emit_byte (mb, CEE_ADD);
- }
- cb_to_mono->mb_emit_byte (mb, CEE_MUL);
- mono_mb_emit_jit_icall (mb, ves_icall_marshal_alloc);
- cb_to_mono->mb_emit_stloc (mb, dest);
- cb_to_mono->mb_emit_ldloc (mb, dest);
- cb_to_mono->mb_emit_stloc (mb, 3);
-
- /* Emit marshalling loop */
- index_var = cb_to_mono->mb_add_local (mb, int_type);
- cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0);
- cb_to_mono->mb_emit_stloc (mb, index_var);
- label2 = cb_to_mono->mb_get_label (mb);
- cb_to_mono->mb_emit_ldloc (mb, index_var);
- cb_to_mono->mb_emit_ldloc (mb, src);
- cb_to_mono->mb_emit_byte (mb, CEE_LDLEN);
- label3 = cb_to_mono->mb_emit_branch (mb, CEE_BGE);
-
- /* Emit marshalling code */
- if (is_string) {
- int stind_op;
- g_assert (conv != MONO_MARSHAL_CONV_INVALID);
-
- /* dest */
- cb_to_mono->mb_emit_ldloc (mb, dest);
-
- /* src */
- cb_to_mono->mb_emit_ldloc (mb, src);
- cb_to_mono->mb_emit_ldloc (mb, index_var);
-
- cb_to_mono->mb_emit_byte (mb, CEE_LDELEM_REF);
-
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, &stind_op));
- cb_to_mono->mb_emit_byte (mb, GINT_TO_UINT8 (stind_op));
- }
- else {
- char *msg = g_strdup ("Marshalling of non-string arrays to managed code is not implemented.");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- return conv_arg;
- }
-
- cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1);
- cb_to_mono->mb_emit_add_to_local (mb, GINT_TO_UINT16 (dest), esize);
-
- cb_to_mono->mb_emit_branch_label (mb, CEE_BR, label2);
-
- cb_to_mono->mb_patch_branch (mb, label3);
- cb_to_mono->mb_patch_branch (mb, label1);
-#endif
- break;
- }
- default:
- g_assert_not_reached ();
- }
- return conv_arg;
-}
-
-static gboolean
-emit_native_wrapper_validate_signature (MonoMethodBuilder *mb, MonoMethodSignature* sig, MonoMarshalSpec** mspecs)
-{
- if (mspecs) {
- for (int i = 0; i < sig->param_count; i ++) {
- if (mspecs [i + 1] && mspecs [i + 1]->native == MONO_NATIVE_CUSTOM) {
- if (!mspecs [i + 1]->data.custom_data.custom_name || *mspecs [i + 1]->data.custom_data.custom_name == '\0') {
- cb_to_mono->mb_emit_exception_full (mb, "System", "TypeLoadException", g_strdup ("Missing ICustomMarshaler type"));
- return FALSE;
- }
-
- switch (sig->params[i]->type) {
- case MONO_TYPE_CLASS:
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_STRING:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_VALUETYPE:
- break;
-
- default:
- cb_to_mono->mb_emit_exception_full (mb, "System.Runtime.InteropServices", "MarshalDirectiveException", g_strdup_printf ("custom marshalling of type %x is currently not supported", sig->params[i]->type));
- return FALSE;
- }
- }
- else if (sig->params[i]->type == MONO_TYPE_VALUETYPE) {
- MonoMarshalType *marshal_type = mono_marshal_load_type_info (mono_class_from_mono_type_internal (sig->params [i]));
- for (guint32 field_idx = 0; field_idx < marshal_type->num_fields; ++field_idx) {
- if (marshal_type->fields [field_idx].mspec && marshal_type->fields [field_idx].mspec->native == MONO_NATIVE_CUSTOM) {
- cb_to_mono->mb_emit_exception_full (mb, "System", "TypeLoadException", g_strdup ("Value type includes custom marshaled fields"));
- return FALSE;
- }
- }
- }
- }
- }
-
- return TRUE;
-}
-
-static int
-emit_marshal_ptr_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec, int conv_arg,
- MonoType **conv_arg_type, MarshalAction action)
-{
- MonoMethodBuilder *mb = m->mb;
- switch (action) {
- case MARSHAL_ACTION_CONV_IN:
- /* MS seems to allow this in some cases, ie. bxc #158 */
- /*
- 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);
- cb_to_mono->mb_emit_exception_marshal_directive (m->mb, msg);
- }
- */
- break;
-
- case MARSHAL_ACTION_PUSH:
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- break;
-
- case MARSHAL_ACTION_CONV_RESULT:
- /* no conversions necessary */
- cb_to_mono->mb_emit_stloc (mb, 3);
- break;
-
- default:
- break;
- }
- return conv_arg;
-}
-
-static int
-emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec,
- int conv_arg, MonoType **conv_arg_type,
- MarshalAction action)
-{
- MonoMethodBuilder *mb = m->mb;
- MonoType *int_type = cb_to_mono->get_int_type ();
- MonoType *boolean_type = m_class_get_byval_arg (cb_to_mono->mono_defaults->boolean_class);
-
- switch (action) {
- case MARSHAL_ACTION_CONV_IN: {
- MonoType *local_type;
- int label_false;
- guint8 ldc_op = CEE_LDC_I4_1;
-
- local_type = cb_to_mono->boolean_conv_in_get_local_type (spec, &ldc_op);
- if (m_type_is_byref (t))
- *conv_arg_type = int_type;
- else
- *conv_arg_type = local_type;
- conv_arg = cb_to_mono->mb_add_local (mb, local_type);
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I1);
- label_false = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
- cb_to_mono->mb_emit_byte (mb, ldc_op);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- cb_to_mono->mb_patch_branch (mb, label_false);
-
- break;
- }
-
- case MARSHAL_ACTION_CONV_OUT:
- {
- int label_false, label_end;
- if (!m_type_is_byref (t))
- break;
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
-
- label_false = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
- cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_1);
-
- label_end = cb_to_mono->mb_emit_branch (mb, CEE_BR);
- cb_to_mono->mb_patch_branch (mb, label_false);
- cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0);
- cb_to_mono->mb_patch_branch (mb, label_end);
-
- cb_to_mono->mb_emit_byte (mb, CEE_STIND_I1);
- break;
- }
-
- case MARSHAL_ACTION_PUSH:
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg);
- else if (conv_arg)
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- else
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- break;
-
- case MARSHAL_ACTION_CONV_RESULT:
- /* maybe we need to make sure that it fits within 8 bits */
- cb_to_mono->mb_emit_stloc (mb, 3);
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_IN: {
- MonoClass* conv_arg_class = cb_to_mono->mono_defaults->int32_class;
- guint8 ldop = CEE_LDIND_I4;
- int label_null, label_false;
-
- conv_arg_class = cb_to_mono->boolean_managed_conv_in_get_conv_arg_class (spec, &ldop);
- conv_arg = cb_to_mono->mb_add_local (mb, boolean_type);
-
- if (m_type_is_byref (t))
- *conv_arg_type = m_class_get_this_arg (conv_arg_class);
- else
- *conv_arg_type = m_class_get_byval_arg (conv_arg_class);
-
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
-
- /* Check null */
- if (m_type_is_byref (t)) {
- label_null = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_byte (mb, ldop);
- } else
- label_null = 0;
-
- label_false = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
- cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_1);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- cb_to_mono->mb_patch_branch (mb, label_false);
-
- if (m_type_is_byref (t))
- cb_to_mono->mb_patch_branch (mb, label_null);
- break;
- }
-
- case MARSHAL_ACTION_MANAGED_CONV_OUT: {
- guint8 stop = CEE_STIND_I4;
- guint8 ldc_op = CEE_LDC_I4_1;
- int label_null,label_false, label_end;
-
- if (!m_type_is_byref (t))
- break;
- if (spec) {
- switch (spec->native) {
- case MONO_NATIVE_I1:
- case MONO_NATIVE_U1:
- stop = CEE_STIND_I1;
- break;
- case MONO_NATIVE_VARIANTBOOL:
- stop = CEE_STIND_I2;
- ldc_op = CEE_LDC_I4_M1;
- break;
- default:
- break;
- }
- }
-
- /* Check null */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- label_null = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
-
- label_false = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
- cb_to_mono->mb_emit_byte (mb, ldc_op);
- label_end = cb_to_mono->mb_emit_branch (mb, CEE_BR);
-
- cb_to_mono->mb_patch_branch (mb, label_false);
- cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0);
- cb_to_mono->mb_patch_branch (mb, label_end);
-
- cb_to_mono->mb_emit_byte (mb, stop);
- cb_to_mono->mb_patch_branch (mb, label_null);
- break;
- }
-
- default:
- g_assert_not_reached ();
- }
- return conv_arg;
-}
-
-static int
-emit_marshal_char_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec, int conv_arg,
- MonoType **conv_arg_type, MarshalAction action)
-{
- MonoMethodBuilder *mb = m->mb;
-
- switch (action) {
- case MARSHAL_ACTION_PUSH:
- /* fixme: dont know how to marshal that. We cant simply
- * convert it to a one byte UTF8 character, because an
- * unicode character may need more that one byte in UTF8 */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- break;
-
- case MARSHAL_ACTION_CONV_RESULT:
- /* fixme: we need conversions here */
- cb_to_mono->mb_emit_stloc (mb, 3);
- break;
-
- default:
- break;
- }
- return conv_arg;
-}
-
-static int
-emit_marshal_custom_ilgen_throw_exception (MonoMethodBuilder *mb, const char *exc_nspace, const char *exc_name, const char *msg, MarshalAction action)
-{
- /* Throw exception and emit compensation code, if neccesary */
- switch (action) {
- case MARSHAL_ACTION_CONV_IN:
- case MARSHAL_ACTION_MANAGED_CONV_IN:
- case MARSHAL_ACTION_CONV_RESULT:
- case MARSHAL_ACTION_MANAGED_CONV_RESULT:
- if ((action == MARSHAL_ACTION_CONV_RESULT) || (action == MARSHAL_ACTION_MANAGED_CONV_RESULT))
- cb_to_mono->mb_emit_byte (mb, CEE_POP);
-
- cb_to_mono->mb_emit_exception_full (mb, exc_nspace, exc_name, msg);
-
- break;
- case MARSHAL_ACTION_PUSH:
- cb_to_mono->mb_emit_byte (mb, CEE_LDNULL);
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-static int
-emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec,
- int conv_arg, MonoType **conv_arg_type,
- MarshalAction action)
-{
- ERROR_DECL (error);
- MonoType *mtype;
- MonoClass *mklass;
- static MonoClass *ICustomMarshaler = NULL;
- static MonoMethod *cleanup_native, *cleanup_managed;
- static MonoMethod *marshal_managed_to_native, *marshal_native_to_managed;
- MonoMethodBuilder *mb = m->mb;
- MonoAssemblyLoadContext *alc = mono_alc_get_ambient ();
- guint32 loc1;
- int pos2;
-
- MonoType *int_type = cb_to_mono->get_int_type ();
- MonoType *object_type = cb_to_mono->get_object_type ();
-
- if (!ICustomMarshaler) {
- MonoClass *klass = mono_class_try_get_icustom_marshaler_class ();
- if (!klass)
- return emit_marshal_custom_ilgen_throw_exception (mb, "System", "ApplicationException", g_strdup ("Current profile doesn't support ICustomMarshaler"), action);
-
- cleanup_native = cb_to_mono->get_method_nofail (klass, "CleanUpNativeData", 1, 0);
- g_assert (cleanup_native);
-
- cleanup_managed = cb_to_mono->get_method_nofail (klass, "CleanUpManagedData", 1, 0);
- g_assert (cleanup_managed);
-
- marshal_managed_to_native = cb_to_mono->get_method_nofail (klass, "MarshalManagedToNative", 1, 0);
- g_assert (marshal_managed_to_native);
-
- marshal_native_to_managed = cb_to_mono->get_method_nofail (klass, "MarshalNativeToManaged", 1, 0);
- g_assert (marshal_native_to_managed);
-
- cb_to_mono->memory_barrier ();
- ICustomMarshaler = klass;
- }
-
- if (spec->data.custom_data.image)
- mtype = cb_to_mono->reflection_type_from_name_checked (spec->data.custom_data.custom_name, alc, spec->data.custom_data.image, error);
- else
- mtype = cb_to_mono->reflection_type_from_name_checked (spec->data.custom_data.custom_name, alc, m->image, error);
-
- if (!mtype)
- return emit_marshal_custom_ilgen_throw_exception (mb, "System", "TypeLoadException", g_strdup ("Failed to load ICustomMarshaler type"), action);
-
- mklass = mono_class_from_mono_type_internal (mtype);
- g_assert (mklass != NULL);
-
- switch (action) {
- case MARSHAL_ACTION_CONV_IN:
- switch (t->type) {
- case MONO_TYPE_CLASS:
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_STRING:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_VALUETYPE:
- break;
-
- default:
- g_warning ("custom marshalling of type %x is currently not supported", t->type);
- g_assert_not_reached ();
- break;
- }
-
- conv_arg = cb_to_mono->mb_add_local (mb, int_type);
-
- cb_to_mono->mb_emit_byte (mb, CEE_LDNULL);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
-
- if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT))
- break;
-
- /* Minic MS.NET behavior */
- if (!m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT) && !(t->attrs & PARAM_ATTRIBUTE_IN))
- break;
-
- /* Check for null */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
- pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec);
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_REF);
-
- if (t->type == MONO_TYPE_VALUETYPE) {
- /*
- * Since we can't determine the type of the argument, we
- * will assume the unmanaged function takes a pointer.
- */
- *conv_arg_type = int_type;
-
- cb_to_mono->mb_emit_op (mb, CEE_BOX, mono_class_from_mono_type_internal (t));
- }
-
- cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, marshal_managed_to_native);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
-
- cb_to_mono->mb_patch_branch (mb, pos2);
- break;
-
- case MARSHAL_ACTION_CONV_OUT:
- /* Check for null */
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_OUT)) {
- cb_to_mono->mb_emit_ldarg (mb, argnum);
-
- cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec);
- cb_to_mono->mb_emit_byte (mb, CEE_DUP);
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_REF);
- cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, cleanup_managed);
-
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed);
- cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF);
- } else if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
- cb_to_mono->mb_emit_ldarg (mb, argnum);
-
- cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec);
-
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed);
- cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF);
- } else if (t->attrs & PARAM_ATTRIBUTE_OUT) {
- cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec);
-
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed);
- /* We have nowhere to store the result */
- cb_to_mono->mb_emit_byte (mb, CEE_POP);
- }
-
- // 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))) {
- cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec);
-
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
-
- cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, cleanup_native);
- }
-
- cb_to_mono->mb_patch_branch (mb, pos2);
- break;
-
- case MARSHAL_ACTION_PUSH:
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg);
- else
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- break;
-
- case MARSHAL_ACTION_CONV_RESULT:
- cb_to_mono->mb_emit_stloc (mb, 3);
-
- /* Check for null */
- cb_to_mono->mb_emit_ldloc (mb, 3);
- pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec);
-
- cb_to_mono->mb_emit_ldloc (mb, 3);
- cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed);
- cb_to_mono->mb_emit_stloc (mb, 3);
-
- cb_to_mono->mb_patch_branch (mb, pos2);
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_IN:
- switch (t->type) {
- case MONO_TYPE_CLASS:
- case MONO_TYPE_OBJECT:
- case MONO_TYPE_STRING:
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_SZARRAY:
- case MONO_TYPE_VALUETYPE:
- case MONO_TYPE_BOOLEAN:
- break;
-
- default:
- g_warning ("custom marshalling of type %x is currently not supported", t->type);
- g_assert_not_reached ();
- break;
- }
-
- conv_arg = cb_to_mono->mb_add_local (mb, object_type);
-
- cb_to_mono->mb_emit_byte (mb, CEE_LDNULL);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
-
- if (m_type_is_byref (t) && t->attrs & PARAM_ATTRIBUTE_OUT)
- break;
-
- /* Check for null */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
- pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec);
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
-
- cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
-
- cb_to_mono->mb_patch_branch (mb, pos2);
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_RESULT:
- g_assert (!m_type_is_byref (t));
-
- loc1 = cb_to_mono->mb_add_local (mb, object_type);
-
- cb_to_mono->mb_emit_stloc (mb, 3);
-
- cb_to_mono->mb_emit_ldloc (mb, 3);
- cb_to_mono->mb_emit_stloc (mb, loc1);
-
- /* Check for null */
- cb_to_mono->mb_emit_ldloc (mb, 3);
- pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec);
- cb_to_mono->mb_emit_byte (mb, CEE_DUP);
-
- cb_to_mono->mb_emit_ldloc (mb, 3);
- cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, marshal_managed_to_native);
- cb_to_mono->mb_emit_stloc (mb, 3);
-
- cb_to_mono->mb_emit_ldloc (mb, loc1);
- cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, cleanup_managed);
-
- cb_to_mono->mb_patch_branch (mb, pos2);
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_OUT:
-
- /* Check for null */
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- if (m_type_is_byref (t)) {
- cb_to_mono->mb_emit_ldarg (mb, argnum);
-
- cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec);
-
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, marshal_managed_to_native);
- cb_to_mono->mb_emit_byte (mb, CEE_STIND_I);
- }
-
- // 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))) {
- cb_to_mono->emit_marshal_custom_get_instance (mb, mklass, spec);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_op (mb, CEE_CALLVIRT, cleanup_managed);
- }
-
- cb_to_mono->mb_patch_branch (mb, pos2);
- break;
-
- default:
- g_assert_not_reached ();
- }
- return conv_arg;
-}
-
-static int
-emit_marshal_asany_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec,
- int conv_arg, MonoType **conv_arg_type,
- MarshalAction action)
-{
- MonoMethodBuilder *mb = m->mb;
-
- MonoType *int_type = cb_to_mono->get_int_type ();
- switch (action) {
- case MARSHAL_ACTION_CONV_IN: {
- MonoMarshalNative encoding = cb_to_mono->get_string_encoding (m->piinfo, NULL);
-
- g_assert (t->type == MONO_TYPE_OBJECT);
- g_assert (!m_type_is_byref (t));
-
- conv_arg = cb_to_mono->mb_add_local (mb, int_type);
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_icon (mb, encoding);
- cb_to_mono->mb_emit_icon (mb, t->attrs);
- mono_mb_emit_jit_icall (mb, mono_marshal_asany);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- break;
- }
-
- case MARSHAL_ACTION_PUSH:
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- break;
-
- case MARSHAL_ACTION_CONV_OUT: {
- MonoMarshalNative encoding = cb_to_mono->get_string_encoding (m->piinfo, NULL);
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_icon (mb, encoding);
- cb_to_mono->mb_emit_icon (mb, t->attrs);
- mono_mb_emit_jit_icall (mb, mono_marshal_free_asany);
- break;
- }
-
- default:
- g_assert_not_reached ();
- }
- return conv_arg;
-}
-
-static int
-emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec,
- int conv_arg, MonoType **conv_arg_type,
- MarshalAction action)
-{
- MonoMethodBuilder *mb = m->mb;
- MonoClass *klass, *date_time_class;
- int pos = 0, pos2;
-
- klass = mono_class_from_mono_type_internal (t);
-
- date_time_class = mono_class_get_date_time_class ();
-
- MonoType *int_type = cb_to_mono->get_int_type ();
- MonoType *double_type = m_class_get_byval_arg (cb_to_mono->mono_defaults->double_class);
-
- switch (action) {
- case MARSHAL_ACTION_CONV_IN:
- if (klass == date_time_class) {
- /* Convert it to an OLE DATE type */
-
- conv_arg = cb_to_mono->mb_add_local (mb, double_type);
-
- if (m_type_is_byref (t)) {
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
- }
-
- if (!(m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT))) {
- if (!m_type_is_byref (t))
- m->csig->params [argnum - m->csig->hasthis] = double_type;
-
- MONO_STATIC_POINTER_INIT (MonoMethod, to_oadate)
- to_oadate = cb_to_mono->get_method_nofail (date_time_class, "ToOADate", 0, 0);
- g_assert (to_oadate);
- MONO_STATIC_POINTER_INIT_END (MonoMethod, to_oadate)
-
- cb_to_mono->mb_emit_ldarg_addr (mb, argnum);
- cb_to_mono->mb_emit_managed_call (mb, to_oadate, NULL);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- }
-
- if (m_type_is_byref (t))
- cb_to_mono->mb_patch_branch (mb, pos);
- break;
- }
-
- if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass))
- break;
-
- conv_arg = cb_to_mono->mb_add_local (mb, int_type);
-
- /* store the address of the source into local variable 0 */
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- else
- cb_to_mono->mb_emit_ldarg_addr (mb, argnum);
-
- cb_to_mono->mb_emit_stloc (mb, 0);
-
- /* allocate space for the native struct and
- * store the address into local variable 1 (dest) */
- cb_to_mono->mb_emit_icon (mb, cb_to_mono->class_native_size (klass, NULL));
- cb_to_mono->mb_emit_byte (mb, CEE_PREFIX1);
- cb_to_mono->mb_emit_byte (mb, CEE_LOCALLOC);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
-
- if (m_type_is_byref (t)) {
- cb_to_mono->mb_emit_ldloc (mb, 0);
- pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
- }
-
- if (!(m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT))) {
- /* set dst_ptr */
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_stloc (mb, 1);
-
- /* emit valuetype conversion code */
- cb_to_mono->emit_struct_conv (mb, klass, FALSE);
- }
-
- if (m_type_is_byref (t))
- cb_to_mono->mb_patch_branch (mb, pos);
- break;
-
- case MARSHAL_ACTION_PUSH:
- if (spec && spec->native == MONO_NATIVE_LPSTRUCT) {
- /* FIXME: */
- g_assert (!m_type_is_byref (t));
-
- /* Have to change the signature since the vtype is passed byref */
- m->csig->params [argnum - m->csig->hasthis] = int_type;
-
- if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass))
- cb_to_mono->mb_emit_ldarg_addr (mb, argnum);
- else
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- break;
- }
-
- if (klass == date_time_class) {
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg);
- else
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- break;
- }
-
- if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) {
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- break;
- }
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- if (!m_type_is_byref (t)) {
- cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- cb_to_mono->mb_emit_op (mb, CEE_MONO_LDNATIVEOBJ, klass);
- }
- break;
-
- case MARSHAL_ACTION_CONV_OUT:
- if (klass == date_time_class) {
- /* Convert from an OLE DATE type */
-
- if (!m_type_is_byref (t))
- break;
-
- if (!((t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT))) {
-
- MONO_STATIC_POINTER_INIT (MonoMethod, from_oadate)
- from_oadate = cb_to_mono->get_method_nofail (date_time_class, "FromOADate", 1, 0);
- MONO_STATIC_POINTER_INIT_END (MonoMethod, from_oadate)
-
- g_assert (from_oadate);
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_managed_call (mb, from_oadate, NULL);
- cb_to_mono->mb_emit_op (mb, CEE_STOBJ, date_time_class);
- }
- break;
- }
-
- if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass))
- break;
-
- if (m_type_is_byref (t)) {
- /* dst = argument */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_stloc (mb, 1);
-
- cb_to_mono->mb_emit_ldloc (mb, 1);
- pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- if (!((t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT))) {
- /* src = tmp_locals [i] */
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_stloc (mb, 0);
-
- /* emit valuetype conversion code */
- cb_to_mono->emit_struct_conv (mb, klass, TRUE);
- }
- }
-
- emit_struct_free (mb, klass, conv_arg);
-
- if (m_type_is_byref (t))
- cb_to_mono->mb_patch_branch (mb, pos);
- break;
-
- case MARSHAL_ACTION_CONV_RESULT:
- if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass)) {
- cb_to_mono->mb_emit_stloc (mb, 3);
- break;
- }
-
- /* load pointer to returned value type */
- g_assert (m->vtaddr_var);
- cb_to_mono->mb_emit_ldloc (mb, m->vtaddr_var);
- /* store the address of the source into local variable 0 */
- cb_to_mono->mb_emit_stloc (mb, 0);
- /* set dst_ptr */
- cb_to_mono->mb_emit_ldloc_addr (mb, 3);
- cb_to_mono->mb_emit_stloc (mb, 1);
-
- /* emit valuetype conversion code */
- cb_to_mono->emit_struct_conv (mb, klass, TRUE);
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_IN:
- if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) {
- conv_arg = 0;
- break;
- }
-
- conv_arg = cb_to_mono->mb_add_local (mb, m_class_get_byval_arg (klass));
-
- if (t->attrs & PARAM_ATTRIBUTE_OUT)
- break;
-
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- else
- cb_to_mono->mb_emit_ldarg_addr (mb, argnum);
- cb_to_mono->mb_emit_stloc (mb, 0);
-
- if (m_type_is_byref (t)) {
- cb_to_mono->mb_emit_ldloc (mb, 0);
- pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
- }
-
- cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg);
- cb_to_mono->mb_emit_stloc (mb, 1);
-
- /* emit valuetype conversion code */
- cb_to_mono->emit_struct_conv (mb, klass, TRUE);
-
- if (m_type_is_byref (t))
- cb_to_mono->mb_patch_branch (mb, pos);
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_OUT:
- if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass))
- break;
- if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT))
- break;
-
- /* Check for null */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- /* Set src */
- cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg);
- cb_to_mono->mb_emit_stloc (mb, 0);
-
- /* Set dest */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_stloc (mb, 1);
-
- /* emit valuetype conversion code */
- cb_to_mono->emit_struct_conv (mb, klass, FALSE);
-
- cb_to_mono->mb_patch_branch (mb, pos2);
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_RESULT:
- if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) {
- cb_to_mono->mb_emit_stloc (mb, 3);
- m->retobj_var = 0;
- break;
- }
-
- /* load pointer to returned value type */
- g_assert (m->vtaddr_var);
- cb_to_mono->mb_emit_ldloc (mb, m->vtaddr_var);
-
- /* store the address of the source into local variable 0 */
- cb_to_mono->mb_emit_stloc (mb, 0);
- /* allocate space for the native struct and
- * store the address into dst_ptr */
- m->retobj_var = cb_to_mono->mb_add_local (mb, int_type);
- m->retobj_class = klass;
- g_assert (m->retobj_var);
- cb_to_mono->mb_emit_icon (mb, cb_to_mono->class_native_size (klass, NULL));
- cb_to_mono->mb_emit_byte (mb, CEE_CONV_I);
- mono_mb_emit_jit_icall (mb, ves_icall_marshal_alloc);
- cb_to_mono->mb_emit_stloc (mb, 1);
- cb_to_mono->mb_emit_ldloc (mb, 1);
- cb_to_mono->mb_emit_stloc (mb, m->retobj_var);
-
- /* emit valuetype conversion code */
- cb_to_mono->emit_struct_conv (mb, klass, FALSE);
- break;
-
- default:
- g_assert_not_reached ();
- }
- return conv_arg;
-}
-
-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)
- mono_mb_emit_jit_icall (mb, mono_free_bstr);
- else
- mono_mb_emit_jit_icall (mb, mono_marshal_free);
-}
-
-static int
-emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec,
- int conv_arg, MonoType **conv_arg_type,
- MarshalAction action)
-{
- MonoMethodBuilder *mb = m->mb;
- MonoMarshalNative encoding = cb_to_mono->get_string_encoding (m->piinfo, spec);
- MonoMarshalConv conv = cb_to_mono->get_string_to_ptr_conv (m->piinfo, spec);
- gboolean need_free;
-
- MonoType *int_type = cb_to_mono->get_int_type ();
- MonoType *object_type = cb_to_mono->get_object_type ();
- switch (action) {
- case MARSHAL_ACTION_CONV_IN:
- *conv_arg_type = int_type;
- conv_arg = cb_to_mono->mb_add_local (mb, int_type);
-
- if (m_type_is_byref (t)) {
- if (t->attrs & PARAM_ATTRIBUTE_OUT)
- break;
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
- } else {
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- }
-
- if (conv == MONO_MARSHAL_CONV_INVALID) {
- char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- } else {
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, NULL));
-
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- }
- break;
-
- case MARSHAL_ACTION_CONV_OUT:
- conv = cb_to_mono->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);
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- break;
- }
-
- if (encoding == MONO_NATIVE_VBBYREFSTR) {
-
- if (!m_type_is_byref (t)) {
- char *msg = g_strdup ("VBByRefStr marshalling requires a ref parameter.");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- break;
- }
-
- MONO_STATIC_POINTER_INIT (MonoMethod, method)
-
- method = cb_to_mono->get_method_nofail (cb_to_mono->mono_defaults->string_class, "get_Length", -1, 0);
-
- MONO_STATIC_POINTER_INIT_END (MonoMethod, method)
-
- /*
- * Have to allocate a new string with the same length as the original, and
- * copy the contents of the buffer pointed to by CONV_ARG into it.
- */
- g_assert (m_type_is_byref (t));
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
- cb_to_mono->mb_emit_managed_call (mb, method, NULL);
- mono_mb_emit_jit_icall (mb, mono_string_new_len_wrapper);
- cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF);
- } else if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) {
- int stind_op;
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, &stind_op));
- cb_to_mono->mb_emit_byte (mb, GINT_TO_UINT8 (stind_op));
- need_free = TRUE;
- }
-
- if (need_free) {
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- emit_string_free_icall (mb, conv);
- }
- break;
-
- case MARSHAL_ACTION_PUSH:
- if (m_type_is_byref (t) && encoding != MONO_NATIVE_VBBYREFSTR)
- cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg);
- else
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- break;
-
- case MARSHAL_ACTION_CONV_RESULT:
- cb_to_mono->mb_emit_stloc (mb, 0);
-
- conv = cb_to_mono->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);
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- break;
- }
-
- cb_to_mono->mb_emit_ldloc (mb, 0);
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, NULL));
- cb_to_mono->mb_emit_stloc (mb, 3);
-
- /* free the string */
- cb_to_mono->mb_emit_ldloc (mb, 0);
- emit_string_free_icall (mb, conv);
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_IN:
- conv_arg = cb_to_mono->mb_add_local (mb, object_type);
-
- *conv_arg_type = int_type;
-
- if (m_type_is_byref (t)) {
- if (t->attrs & PARAM_ATTRIBUTE_OUT)
- break;
- }
-
- conv = cb_to_mono->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);
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- break;
- }
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, NULL));
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_OUT:
- if (m_type_is_byref (t)) {
- if (conv_arg) {
- int stind_op;
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, &stind_op));
- cb_to_mono->mb_emit_byte (mb, GINT_TO_UINT8 (stind_op));
- }
- }
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_RESULT:
- if (cb_to_mono->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_jit_icall (mb, mono_marshal_string_to_utf16_copy);
- else
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, NULL));
- cb_to_mono->mb_emit_stloc (mb, 3);
- break;
-
- default:
- g_assert_not_reached ();
- }
- return conv_arg;
-}
-
-static int
-emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec, int conv_arg,
- MonoType **conv_arg_type, MarshalAction action)
-{
- MonoMethodBuilder *mb = m->mb;
- MonoType *int_type = cb_to_mono->get_int_type ();
- MonoType *boolean_type = m_class_get_byval_arg (cb_to_mono->mono_defaults->boolean_class);
-
- switch (action){
- case MARSHAL_ACTION_CONV_IN: {
- int dar_release_slot, pos;
-
- conv_arg = cb_to_mono->mb_add_local (mb, int_type);
- *conv_arg_type = int_type;
-
- if (!*cb_to_mono->get_sh_dangerous_add_ref())
- cb_to_mono->init_safe_handle ();
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- pos = cb_to_mono->mb_emit_branch (mb, CEE_BRTRUE);
- cb_to_mono->mb_emit_exception (mb, "ArgumentNullException", NULL);
-
- cb_to_mono->mb_patch_branch (mb, pos);
-
- /* Create local to hold the ref parameter to DangerousAddRef */
- dar_release_slot = cb_to_mono->mb_add_local (mb, boolean_type);
-
- /* set release = false; */
- cb_to_mono->mb_emit_icon (mb, 0);
- cb_to_mono->mb_emit_stloc (mb, dar_release_slot);
-
- if (m_type_is_byref (t)) {
- int old_handle_value_slot = cb_to_mono->mb_add_local (mb, int_type);
-
- if (!cb_to_mono->is_in (t)) {
- cb_to_mono->mb_emit_icon (mb, 0);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- } else {
- /* safehandle.DangerousAddRef (ref release) */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_REF);
- cb_to_mono->mb_emit_ldloc_addr (mb, dar_release_slot);
- cb_to_mono->mb_emit_managed_call (mb, *cb_to_mono->get_sh_dangerous_add_ref(), NULL);
-
- /* Pull the handle field from SafeHandle */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_REF);
- cb_to_mono->mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle));
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
- cb_to_mono->mb_emit_byte (mb, CEE_DUP);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- cb_to_mono->mb_emit_stloc (mb, old_handle_value_slot);
- }
- } else {
- /* safehandle.DangerousAddRef (ref release) */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_ldloc_addr (mb, dar_release_slot);
- cb_to_mono->mb_emit_managed_call (mb, *cb_to_mono->get_sh_dangerous_add_ref(), NULL);
-
- /* Pull the handle field from SafeHandle */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle));
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- }
-
- break;
- }
-
- case MARSHAL_ACTION_PUSH:
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg);
- else
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- break;
-
- case MARSHAL_ACTION_CONV_OUT: {
- /* The slot for the boolean is the next temporary created after conv_arg, see the CONV_IN code */
- int dar_release_slot = conv_arg + 1;
- int label_next = 0;
-
- if (!*cb_to_mono->get_sh_dangerous_release())
- cb_to_mono->init_safe_handle ();
-
- if (m_type_is_byref (t)) {
- /* If there was SafeHandle on input we have to release the reference to it */
- if (cb_to_mono->is_in (t)) {
- cb_to_mono->mb_emit_ldloc (mb, dar_release_slot);
- label_next = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
- cb_to_mono->mb_emit_managed_call (mb, *cb_to_mono->get_sh_dangerous_release (), NULL);
- cb_to_mono->mb_patch_branch (mb, label_next);
- }
-
- if (cb_to_mono->is_out (t)) {
- ERROR_DECL (local_error);
- MonoMethod *ctor;
-
- /*
- * If the SafeHandle was marshalled on input we can skip the marshalling on
- * output if the handle value is identical.
- */
- if (cb_to_mono->is_in (t)) {
- int old_handle_value_slot = dar_release_slot + 1;
- cb_to_mono->mb_emit_ldloc (mb, old_handle_value_slot);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- label_next = cb_to_mono->mb_emit_branch (mb, CEE_BEQ);
- }
-
- /*
- * Create an empty SafeHandle (of correct derived type).
- *
- * FIXME: If an out-of-memory situation or exception happens here we will
- * leak the handle. We should move the allocation of the SafeHandle to the
- * input marshalling code to prevent that.
- */
- ctor = mono_class_get_method_from_name_checked (t->data.klass, ".ctor", 0, 0, local_error);
- if (ctor == NULL || !is_ok (local_error)){
- cb_to_mono->mb_emit_exception (mb, "MissingMethodException", "parameterless constructor required");
- mono_error_cleanup (local_error);
- break;
- }
-
- /* refval = new SafeHandleDerived ()*/
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_op (mb, CEE_NEWOBJ, ctor);
- cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF);
-
- /* refval.handle = returned_handle */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_REF);
- cb_to_mono->mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle));
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_byte (mb, CEE_STIND_I);
-
- if (cb_to_mono->is_in (t) && label_next) {
- cb_to_mono->mb_patch_branch (mb, label_next);
- }
- }
- } else {
- cb_to_mono->mb_emit_ldloc (mb, dar_release_slot);
- label_next = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_managed_call (mb, *cb_to_mono->get_sh_dangerous_release (), NULL);
- cb_to_mono->mb_patch_branch (mb, label_next);
- }
- break;
- }
-
- case MARSHAL_ACTION_CONV_RESULT: {
- ERROR_DECL (error);
- MonoMethod *ctor = NULL;
- int intptr_handle_slot;
-
- if (mono_class_is_abstract (t->data.klass)) {
- cb_to_mono->mb_emit_byte (mb, CEE_POP);
- cb_to_mono->mb_emit_exception_marshal_directive (mb, g_strdup ("Returned SafeHandles should not be abstract"));
- break;
- }
-
- ctor = mono_class_get_method_from_name_checked (t->data.klass, ".ctor", 0, 0, error);
- if (ctor == NULL || !is_ok (error)){
- mono_error_cleanup (error);
- cb_to_mono->mb_emit_byte (mb, CEE_POP);
- cb_to_mono->mb_emit_exception (mb, "MissingMethodException", "parameterless constructor required");
- break;
- }
- /* Store the IntPtr results into a local */
- intptr_handle_slot = cb_to_mono->mb_add_local (mb, int_type);
- cb_to_mono->mb_emit_stloc (mb, intptr_handle_slot);
-
- /* Create return value */
- cb_to_mono->mb_emit_op (mb, CEE_NEWOBJ, ctor);
- cb_to_mono->mb_emit_stloc (mb, 3);
-
- /* Set the return.handle to the value, am using ldflda, not sure if thats a good idea */
- cb_to_mono->mb_emit_ldloc (mb, 3);
- cb_to_mono->mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle));
- cb_to_mono->mb_emit_ldloc (mb, intptr_handle_slot);
- cb_to_mono->mb_emit_byte (mb, CEE_STIND_I);
- break;
- }
-
- case MARSHAL_ACTION_MANAGED_CONV_IN:
- fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_IN\n");
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_OUT:
- fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_OUT\n");
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_RESULT:
- fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_RESULT\n");
- break;
- default:
- printf ("Unhandled case for MarshalAction: %d\n", action);
- }
- return conv_arg;
-}
-
-static int
-emit_marshal_handleref_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec, int conv_arg,
- MonoType **conv_arg_type, MarshalAction action)
-{
- MonoMethodBuilder *mb = m->mb;
-
- MonoType *int_type = cb_to_mono->get_int_type ();
- switch (action){
- case MARSHAL_ACTION_CONV_IN: {
- conv_arg = cb_to_mono->mb_add_local (mb, int_type);
- *conv_arg_type = int_type;
-
- if (m_type_is_byref (t)) {
- char *msg = g_strdup ("HandleRefs can not be returned from unmanaged code (or passed by ref)");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- break;
- }
- cb_to_mono->mb_emit_ldarg_addr (mb, argnum);
- cb_to_mono->mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoHandleRef, handle));
- cb_to_mono->mb_emit_byte (mb, CEE_ADD);
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- break;
- }
-
- case MARSHAL_ACTION_PUSH:
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- break;
-
- case MARSHAL_ACTION_CONV_OUT: {
- /* no resource release required */
- break;
- }
-
- case MARSHAL_ACTION_CONV_RESULT: {
- char *msg = g_strdup ("HandleRefs can not be returned from unmanaged code (or passed by ref)");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- break;
- }
-
- case MARSHAL_ACTION_MANAGED_CONV_IN:
- fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_IN\n");
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_OUT:
- fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_OUT\n");
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_RESULT:
- fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_RESULT\n");
- break;
- default:
- fprintf (stderr, "Unhandled case for MarshalAction: %d\n", action);
- }
- return conv_arg;
-}
-
-static int
-emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec,
- int conv_arg, MonoType **conv_arg_type,
- MarshalAction action)
-{
- MonoMethodBuilder *mb = m->mb;
- MonoClass *klass = mono_class_from_mono_type_internal (t);
- int pos, pos2, loc;
-
- MonoType *int_type = cb_to_mono->get_int_type ();
- switch (action) {
- case MARSHAL_ACTION_CONV_IN:
- *conv_arg_type = int_type;
- conv_arg = cb_to_mono->mb_add_local (mb, int_type);
-
- m->orig_conv_args [argnum] = 0;
-
- if (mono_class_from_mono_type_internal (t) == cb_to_mono->mono_defaults->object_class) {
- char *msg = g_strdup_printf ("Marshalling of type object is not implemented");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- break;
- }
-
- if (m_class_is_delegate (klass)) {
- if (m_type_is_byref (t)) {
- if (!(t->attrs & PARAM_ATTRIBUTE_OUT)) {
- char *msg = g_strdup_printf ("Byref marshalling of delegates is not implemented.");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- }
- cb_to_mono->mb_emit_byte (mb, CEE_LDNULL);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- } else {
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, NULL));
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- }
- } else if (klass == cb_to_mono->try_get_stringbuilder_class ()) {
- MonoMarshalNative encoding = cb_to_mono->get_string_encoding (m->piinfo, spec);
- MonoMarshalConv conv = cb_to_mono->get_stringbuilder_to_ptr_conv (m->piinfo, spec);
-
-#if 0
- if (m_type_is_byref (t)) {
- if (!(t->attrs & PARAM_ATTRIBUTE_OUT)) {
- char *msg = g_strdup_printf ("Byref marshalling of stringbuilders is not implemented.");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- }
- break;
- }
-#endif
-
- if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT))
- break;
-
- if (conv == MONO_MARSHAL_CONV_INVALID) {
- char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding);
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- break;
- }
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
-
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, NULL));
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- } else if (m_class_is_blittable (klass)) {
- cb_to_mono->mb_emit_byte (mb, CEE_LDNULL);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject));
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
-
- cb_to_mono->mb_patch_branch (mb, pos);
- break;
- } else {
- cb_to_mono->mb_emit_byte (mb, CEE_LDNULL);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
-
- if (m_type_is_byref (t)) {
- /* we dont need any conversions for out parameters */
- if (t->attrs & PARAM_ATTRIBUTE_OUT)
- break;
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
-
- } else {
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- cb_to_mono->mb_emit_byte (mb, CEE_MONO_OBJADDR);
- }
-
- /* store the address of the source into local variable 0 */
- cb_to_mono->mb_emit_stloc (mb, 0);
- cb_to_mono->mb_emit_ldloc (mb, 0);
- pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- /* allocate space for the native struct and store the address */
- cb_to_mono->mb_emit_icon (mb, cb_to_mono->class_native_size (klass, NULL));
- cb_to_mono->mb_emit_byte (mb, CEE_PREFIX1);
- cb_to_mono->mb_emit_byte (mb, CEE_LOCALLOC);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
-
- if (m_type_is_byref (t)) {
- /* Need to store the original buffer so we can free it later */
- m->orig_conv_args [argnum] = cb_to_mono->mb_add_local (mb, int_type);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_stloc (mb, m->orig_conv_args [argnum]);
- }
-
- /* set the src_ptr */
- cb_to_mono->mb_emit_ldloc (mb, 0);
- cb_to_mono->mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject));
- cb_to_mono->mb_emit_stloc (mb, 0);
-
- /* set dst_ptr */
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_stloc (mb, 1);
-
- /* emit valuetype conversion code */
- cb_to_mono->emit_struct_conv (mb, klass, FALSE);
-
- cb_to_mono->mb_patch_branch (mb, pos);
- }
- break;
-
- case MARSHAL_ACTION_CONV_OUT:
- if (klass == cb_to_mono->try_get_stringbuilder_class ()) {
- gboolean need_free;
- MonoMarshalNative encoding;
- MonoMarshalConv conv;
-
- encoding = cb_to_mono->get_string_encoding (m->piinfo, spec);
- conv = cb_to_mono->get_ptr_to_stringbuilder_conv (m->piinfo, spec, &need_free);
-
- g_assert (encoding != -1);
-
- if (m_type_is_byref (t)) {
- //g_assert (!(t->attrs & PARAM_ATTRIBUTE_OUT));
-
- need_free = TRUE;
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
-
- switch (encoding) {
- case MONO_NATIVE_LPWSTR:
- mono_mb_emit_jit_icall (mb, mono_string_utf16_to_builder2);
- break;
- case MONO_NATIVE_LPSTR:
- mono_mb_emit_jit_icall (mb, mono_string_utf8_to_builder2);
- break;
- case MONO_NATIVE_UTF8STR:
- mono_mb_emit_jit_icall (mb, mono_string_utf8_to_builder2);
- break;
- default:
- g_assert_not_reached ();
- }
-
- cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF);
- } else if (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN)) {
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
-
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (conv, NULL));
- }
-
- if (need_free) {
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- mono_mb_emit_jit_icall (mb, mono_marshal_free);
- }
- break;
- }
-
- if (m_class_is_delegate (klass)) {
- if (m_type_is_byref (t)) {
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- cb_to_mono->mb_emit_op (mb, CEE_MONO_CLASSCONST, klass);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL));
- cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF);
- }
- break;
- }
-
- if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
- /* allocate a new object */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- cb_to_mono->mb_emit_op (mb, CEE_MONO_NEWOBJ, klass);
- cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF);
- }
-
- /* dst = *argument */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
-
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
-
- cb_to_mono->mb_emit_stloc (mb, 1);
-
- cb_to_mono->mb_emit_ldloc (mb, 1);
- pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- if (m_type_is_byref (t) || (t->attrs & PARAM_ATTRIBUTE_OUT)) {
- cb_to_mono->mb_emit_ldloc (mb, 1);
- cb_to_mono->mb_emit_icon (mb, MONO_ABI_SIZEOF (MonoObject));
- cb_to_mono->mb_emit_byte (mb, CEE_ADD);
- cb_to_mono->mb_emit_stloc (mb, 1);
-
- /* src = tmp_locals [i] */
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_stloc (mb, 0);
-
- /* emit valuetype conversion code */
- cb_to_mono->emit_struct_conv (mb, klass, TRUE);
-
- /* Free the structure returned by the native code */
- emit_struct_free (mb, klass, conv_arg);
-
- if (m->orig_conv_args [argnum]) {
- /*
- * If the native function changed the pointer, then free
- * the original structure plus the new pointer.
- */
- cb_to_mono->mb_emit_ldloc (mb, m->orig_conv_args [argnum]);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BEQ);
-
- if (!(t->attrs & PARAM_ATTRIBUTE_OUT)) {
- g_assert (m->orig_conv_args [argnum]);
-
- emit_struct_free (mb, klass, m->orig_conv_args [argnum]);
- }
-
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- mono_mb_emit_jit_icall (mb, mono_marshal_free);
-
- cb_to_mono->mb_patch_branch (mb, pos2);
- }
- }
- else
- /* Free the original structure passed to native code */
- emit_struct_free (mb, klass, conv_arg);
-
- cb_to_mono->mb_patch_branch (mb, pos);
- break;
-
- case MARSHAL_ACTION_PUSH:
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg);
- else
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- break;
-
- case MARSHAL_ACTION_CONV_RESULT:
- if (m_class_is_delegate (klass)) {
- g_assert (!m_type_is_byref (t));
- cb_to_mono->mb_emit_stloc (mb, 0);
- cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- cb_to_mono->mb_emit_op (mb, CEE_MONO_CLASSCONST, klass);
- cb_to_mono->mb_emit_ldloc (mb, 0);
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL));
- cb_to_mono->mb_emit_stloc (mb, 3);
- } else if (klass == cb_to_mono->try_get_stringbuilder_class ()) {
- // FIXME:
- char *msg = g_strdup_printf ("Return marshalling of stringbuilders is not implemented.");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- } else {
- /* set src */
- cb_to_mono->mb_emit_stloc (mb, 0);
-
- /* Make a copy since emit_conv modifies local 0 */
- loc = cb_to_mono->mb_add_local (mb, int_type);
- cb_to_mono->mb_emit_ldloc (mb, 0);
- cb_to_mono->mb_emit_stloc (mb, loc);
-
- cb_to_mono->mb_emit_byte (mb, CEE_LDNULL);
- cb_to_mono->mb_emit_stloc (mb, 3);
-
- cb_to_mono->mb_emit_ldloc (mb, 0);
- pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- /* allocate result object */
-
- cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- cb_to_mono->mb_emit_op (mb, CEE_MONO_NEWOBJ, klass);
- cb_to_mono->mb_emit_stloc (mb, 3);
-
- /* set dst */
-
- cb_to_mono->mb_emit_ldloc (mb, 3);
- cb_to_mono->mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject));
- cb_to_mono->mb_emit_stloc (mb, 1);
-
- /* emit conversion code */
- cb_to_mono->emit_struct_conv (mb, klass, TRUE);
-
- emit_struct_free (mb, klass, loc);
-
- /* Free the pointer allocated by unmanaged code */
- cb_to_mono->mb_emit_ldloc (mb, loc);
- mono_mb_emit_jit_icall (mb, mono_marshal_free);
- cb_to_mono->mb_patch_branch (mb, pos);
- }
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_IN:
- conv_arg = cb_to_mono->mb_add_local (mb, m_class_get_byval_arg (klass));
-
- if (m_class_is_delegate (klass)) {
- cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- cb_to_mono->mb_emit_op (mb, CEE_MONO_CLASSCONST, klass);
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL));
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- break;
- }
-
- if (klass == cb_to_mono->try_get_stringbuilder_class ()) {
- MonoMarshalNative encoding;
-
- encoding = cb_to_mono->get_string_encoding (m->piinfo, spec);
-
- // FIXME:
- g_assert (encoding == MONO_NATIVE_LPSTR || encoding == MONO_NATIVE_UTF8STR);
-
- g_assert (!m_type_is_byref (t));
- g_assert (encoding != -1);
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- mono_mb_emit_jit_icall (mb, mono_string_utf8_to_builder2);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- break;
- }
-
- /* The class can not have an automatic layout */
- if (mono_class_is_auto_layout (klass)) {
- cb_to_mono->mb_emit_auto_layout_exception (mb, klass);
- break;
- }
-
- if (t->attrs & PARAM_ATTRIBUTE_OUT) {
- cb_to_mono->mb_emit_byte (mb, CEE_LDNULL);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- break;
- }
-
- /* Set src */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- if (m_type_is_byref (t)) {
- /* Check for NULL and raise an exception */
- pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BRTRUE);
-
- cb_to_mono->mb_emit_exception (mb, "ArgumentNullException", NULL);
-
- cb_to_mono->mb_patch_branch (mb, pos2);
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_byte (mb, CEE_LDIND_I);
- }
-
- cb_to_mono->mb_emit_stloc (mb, 0);
-
- cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
-
- cb_to_mono->mb_emit_ldloc (mb, 0);
- pos = cb_to_mono->mb_emit_branch (mb, CEE_BRFALSE);
-
- /* Create and set dst */
- cb_to_mono->mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
- cb_to_mono->mb_emit_op (mb, CEE_MONO_NEWOBJ, klass);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject));
- cb_to_mono->mb_emit_stloc (mb, 1);
-
- /* emit valuetype conversion code */
- cb_to_mono->emit_struct_conv (mb, klass, TRUE);
-
- cb_to_mono->mb_patch_branch (mb, pos);
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_OUT:
- if (m_class_is_delegate (klass)) {
- if (m_type_is_byref (t)) {
- int stind_op;
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, &stind_op));
- cb_to_mono->mb_emit_byte (mb, GINT_TO_UINT8 (stind_op));
- break;
- }
- }
-
- if (m_type_is_byref (t)) {
- /* Check for null */
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- pos = cb_to_mono->mb_emit_branch (mb, CEE_BRTRUE);
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_byte (mb, CEE_LDC_I4_0);
- cb_to_mono->mb_emit_byte (mb, CEE_STIND_I);
- pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BR);
-
- cb_to_mono->mb_patch_branch (mb, pos);
-
- /* Set src */
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject));
- cb_to_mono->mb_emit_stloc (mb, 0);
-
- /* Allocate and set dest */
- cb_to_mono->mb_emit_icon (mb, cb_to_mono->class_native_size (klass, NULL));
- cb_to_mono->mb_emit_byte (mb, CEE_CONV_I);
- mono_mb_emit_jit_icall (mb, ves_icall_marshal_alloc);
- cb_to_mono->mb_emit_stloc (mb, 1);
-
- /* Update argument pointer */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_ldloc (mb, 1);
- cb_to_mono->mb_emit_byte (mb, CEE_STIND_I);
-
- /* emit valuetype conversion code */
- cb_to_mono->emit_struct_conv (mb, klass, FALSE);
-
- cb_to_mono->mb_patch_branch (mb, pos2);
- } else if (klass == cb_to_mono->try_get_stringbuilder_class ()) {
- // FIXME: What to do here ?
- } else {
- /* byval [Out] marshalling */
-
- /* FIXME: Handle null */
-
- /* Set src */
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject));
- cb_to_mono->mb_emit_stloc (mb, 0);
-
- /* Set dest */
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_stloc (mb, 1);
-
- /* emit valuetype conversion code */
- cb_to_mono->emit_struct_conv (mb, klass, FALSE);
- }
- break;
-
- case MARSHAL_ACTION_MANAGED_CONV_RESULT:
- if (m_class_is_delegate (klass)) {
- cb_to_mono->mb_emit_icall_id (mb, cb_to_mono->conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, NULL));
- cb_to_mono->mb_emit_stloc (mb, 3);
- break;
- }
-
- /* The class can not have an automatic layout */
- if (mono_class_is_auto_layout (klass)) {
- cb_to_mono->mb_emit_auto_layout_exception (mb, klass);
- break;
- }
-
- cb_to_mono->mb_emit_stloc (mb, 0);
- /* Check for null */
- cb_to_mono->mb_emit_ldloc (mb, 0);
- pos = cb_to_mono->mb_emit_branch (mb, CEE_BRTRUE);
- cb_to_mono->mb_emit_byte (mb, CEE_LDNULL);
- cb_to_mono->mb_emit_stloc (mb, 3);
- pos2 = cb_to_mono->mb_emit_branch (mb, CEE_BR);
-
- cb_to_mono->mb_patch_branch (mb, pos);
-
- /* Set src */
- cb_to_mono->mb_emit_ldloc (mb, 0);
- cb_to_mono->mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject));
- cb_to_mono->mb_emit_stloc (mb, 0);
-
- /* Allocate and set dest */
- cb_to_mono->mb_emit_icon (mb, cb_to_mono->class_native_size (klass, NULL));
- cb_to_mono->mb_emit_byte (mb, CEE_CONV_I);
- mono_mb_emit_jit_icall (mb, ves_icall_marshal_alloc);
- cb_to_mono->mb_emit_byte (mb, CEE_DUP);
- cb_to_mono->mb_emit_stloc (mb, 1);
- cb_to_mono->mb_emit_stloc (mb, 3);
-
- cb_to_mono->emit_struct_conv (mb, klass, FALSE);
-
- cb_to_mono->mb_patch_branch (mb, pos2);
- break;
-
- default:
- g_assert_not_reached ();
- }
- return conv_arg;
-}
-
-static int
-emit_marshal_variant_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec,
- int conv_arg, MonoType **conv_arg_type,
- MarshalAction action)
-{
-#ifndef DISABLE_COM
- MonoMethodBuilder *mb = m->mb;
- MonoType *variant_type = m_class_get_byval_arg (mono_class_get_variant_class ());
- MonoType *variant_type_byref = mono_class_get_byref_type (mono_class_get_variant_class ());
- MonoType *object_type = cb_to_mono->get_object_type ();
-
- switch (action) {
- case MARSHAL_ACTION_CONV_IN: {
- conv_arg = cb_to_mono->mb_add_local (mb, variant_type);
-
- if (m_type_is_byref (t))
- *conv_arg_type = variant_type_byref;
- else
- *conv_arg_type = variant_type;
-
- if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && t->attrs & PARAM_ATTRIBUTE_OUT)
- break;
-
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_byte(mb, CEE_LDIND_REF);
- cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg);
- cb_to_mono->mb_emit_managed_call (mb, mono_get_Marshal_GetNativeVariantForObject (), NULL);
- break;
- }
-
- case MARSHAL_ACTION_CONV_OUT: {
- if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) {
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg);
- cb_to_mono->mb_emit_managed_call (mb, mono_get_Marshal_GetObjectForNativeVariant (), NULL);
- cb_to_mono->mb_emit_byte (mb, CEE_STIND_REF);
- }
-
- cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg);
- cb_to_mono->mb_emit_managed_call (mb, mono_get_Variant_Clear (), NULL);
- break;
- }
-
- case MARSHAL_ACTION_PUSH:
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_ldloc_addr (mb, conv_arg);
- else
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- break;
-
- case MARSHAL_ACTION_CONV_RESULT: {
- char *msg = g_strdup ("Marshalling of VARIANT not supported as a return type.");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- break;
- }
-
- case MARSHAL_ACTION_MANAGED_CONV_IN: {
- conv_arg = cb_to_mono->mb_add_local (mb, object_type);
-
- if (m_type_is_byref (t))
- *conv_arg_type = variant_type_byref;
- else
- *conv_arg_type = variant_type;
-
- if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && t->attrs & PARAM_ATTRIBUTE_OUT)
- break;
-
- if (m_type_is_byref (t))
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- else
- cb_to_mono->mb_emit_ldarg_addr (mb, argnum);
- cb_to_mono->mb_emit_managed_call (mb, mono_get_Marshal_GetObjectForNativeVariant (), NULL);
- cb_to_mono->mb_emit_stloc (mb, conv_arg);
- break;
- }
-
- case MARSHAL_ACTION_MANAGED_CONV_OUT: {
- if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) {
- cb_to_mono->mb_emit_ldloc (mb, conv_arg);
- cb_to_mono->mb_emit_ldarg (mb, argnum);
- cb_to_mono->mb_emit_managed_call (mb, mono_get_Marshal_GetNativeVariantForObject (), NULL);
- }
- break;
- }
-
- case MARSHAL_ACTION_MANAGED_CONV_RESULT: {
- char *msg = g_strdup ("Marshalling of VARIANT not supported as a return type.");
- cb_to_mono->mb_emit_exception_marshal_directive (mb, msg);
- break;
- }
-
- default:
- g_assert_not_reached ();
- }
-#endif /* DISABLE_COM */
-
- return conv_arg;
-}
-
-
-static MonoMarshalILgenCallbacks *
-get_marshal_cb (void)
-{
- if (G_UNLIKELY (!ilgen_cb_inited)) {
-#ifdef ENABLE_ILGEN
- mono_marshal_ilgen_init ();
-#else
- mono_marshal_noilgen_init_heavyweight ();
-#endif
- }
- return &ilgen_marshal_cb;
-}
-
-int
-mono_emit_marshal_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec, int conv_arg,
- MonoType **conv_arg_type, MarshalAction action, MonoMarshalLightweightCallbacks* lightweigth_cb)
-{
- if (spec && spec->native == MONO_NATIVE_CUSTOM)
- return get_marshal_cb ()->emit_marshal_custom (m, argnum, t, spec, conv_arg, conv_arg_type, action);
-
- if (spec && spec->native == MONO_NATIVE_ASANY)
- return get_marshal_cb ()->emit_marshal_asany (m, argnum, t, spec, conv_arg, conv_arg_type, action);
-
- switch (t->type) {
- case MONO_TYPE_VALUETYPE:
- if (t->data.klass == cb_to_mono->class_try_get_handleref_class ())
- return get_marshal_cb ()->emit_marshal_handleref (m, argnum, t, spec, conv_arg, conv_arg_type, action);
-
- return get_marshal_cb ()->emit_marshal_vtype (m, argnum, t, spec, conv_arg, conv_arg_type, action);
- case MONO_TYPE_STRING:
- return get_marshal_cb ()->emit_marshal_string (m, argnum, t, spec, conv_arg, conv_arg_type, action);
- case MONO_TYPE_CLASS:
- case MONO_TYPE_OBJECT:
-#if !defined(DISABLE_COM)
- if (spec && spec->native == MONO_NATIVE_STRUCT)
- return get_marshal_cb ()->emit_marshal_variant (m, argnum, t, spec, conv_arg, conv_arg_type, action);
-#endif
-
-#if !defined(DISABLE_COM)
- if ((spec && (spec->native == MONO_NATIVE_IUNKNOWN ||
- spec->native == MONO_NATIVE_IDISPATCH ||
- spec->native == MONO_NATIVE_INTERFACE)) ||
- (t->type == MONO_TYPE_CLASS && mono_cominterop_is_interface(t->data.klass)))
- return mono_cominterop_emit_marshal_com_interface (m, argnum, t, spec, conv_arg, conv_arg_type, action);
- if (spec && (spec->native == MONO_NATIVE_SAFEARRAY) &&
- (spec->data.safearray_data.elem_type == MONO_VARIANT_VARIANT) &&
- ((action == MARSHAL_ACTION_CONV_OUT) || (action == MARSHAL_ACTION_CONV_IN) || (action == MARSHAL_ACTION_PUSH)))
- return mono_cominterop_emit_marshal_safearray (m, argnum, t, spec, conv_arg, conv_arg_type, action);
-#endif
-
- if (cb_to_mono->try_get_safehandle_class () != NULL && t->data.klass &&
- cb_to_mono->is_subclass_of_internal (t->data.klass, cb_to_mono->try_get_safehandle_class (), FALSE))
- return get_marshal_cb ()->emit_marshal_safehandle (m, argnum, t, spec, conv_arg, conv_arg_type, action);
-
- return get_marshal_cb ()->emit_marshal_object (m, argnum, t, spec, conv_arg, conv_arg_type, action);
- case MONO_TYPE_ARRAY:
- case MONO_TYPE_SZARRAY:
- return get_marshal_cb ()->emit_marshal_array (m, argnum, t, spec, conv_arg, conv_arg_type, action);
- case MONO_TYPE_BOOLEAN:
- return get_marshal_cb ()->emit_marshal_boolean (m, argnum, t, spec, conv_arg, conv_arg_type, action);
- case MONO_TYPE_PTR:
- return get_marshal_cb ()->emit_marshal_ptr (m, argnum, t, spec, conv_arg, conv_arg_type, action);
- case MONO_TYPE_CHAR:
- return get_marshal_cb ()->emit_marshal_char (m, argnum, t, spec, conv_arg, conv_arg_type, action);
- case MONO_TYPE_I1:
- case MONO_TYPE_U1:
- case MONO_TYPE_I2:
- case MONO_TYPE_U2:
- case MONO_TYPE_I4:
- case MONO_TYPE_U4:
- case MONO_TYPE_I:
- case MONO_TYPE_U:
- case MONO_TYPE_R4:
- case MONO_TYPE_R8:
- case MONO_TYPE_I8:
- case MONO_TYPE_U8:
- case MONO_TYPE_FNPTR:
- return lightweigth_cb->emit_marshal_scalar (m, argnum, t, spec, conv_arg, conv_arg_type, action);
- case MONO_TYPE_GENERICINST:
- if (mono_type_generic_inst_is_valuetype (t))
- return get_marshal_cb ()->emit_marshal_vtype (m, argnum, t, spec, conv_arg, conv_arg_type, action);
- else
- return get_marshal_cb ()->emit_marshal_object (m, argnum, t, spec, conv_arg, conv_arg_type, action);
- default:
- return conv_arg;
- }
-}
-
-void
-mono_marshal_ilgen_init (void)
-{
- MonoMarshalILgenCallbacks cb;
- cb.version = MONO_MARSHAL_CALLBACKS_VERSION;
- cb.emit_marshal_array = emit_marshal_array_ilgen;
- cb.emit_marshal_ptr = emit_marshal_ptr_ilgen;
- cb.emit_marshal_char = emit_marshal_char_ilgen;
- cb.emit_marshal_vtype = emit_marshal_vtype_ilgen;
- cb.emit_marshal_string = emit_marshal_string_ilgen;
- cb.emit_marshal_variant = emit_marshal_variant_ilgen;
- cb.emit_marshal_safehandle = emit_marshal_safehandle_ilgen;
- cb.emit_marshal_object = emit_marshal_object_ilgen;
- cb.emit_marshal_boolean = emit_marshal_boolean_ilgen;
- cb.emit_marshal_custom = emit_marshal_custom_ilgen;
- cb.emit_marshal_asany = emit_marshal_asany_ilgen;
- cb.emit_marshal_handleref = emit_marshal_handleref_ilgen;
-
-#ifdef DISABLE_NONBLITTABLE
- mono_marshal_noilgen_init_blittable (&cb);
-#endif
- mono_install_marshal_callbacks_ilgen (&cb);
-}
-
-
diff --git a/src/mono/mono/metadata/CMakeLists.txt b/src/mono/mono/metadata/CMakeLists.txt
index 69394f0aba1..3eb15313804 100644
--- a/src/mono/mono/metadata/CMakeLists.txt
+++ b/src/mono/mono/metadata/CMakeLists.txt
@@ -16,6 +16,8 @@ set(ilgen_base_sources
method-builder-ilgen.c
method-builder-ilgen.h
method-builder-ilgen-internals.h
+ marshal-ilgen.c
+ marshal-ilgen.h
marshal-lightweight.c
marshal-lightweight.h
marshal-shared.c
@@ -95,7 +97,6 @@ set(metadata_common_sources
marshal.h
marshal-internals.h
marshal-noilgen.c
- marshal-noilgen.h
mempool.c
mempool.h
mempool-internals.h
diff --git a/src/mono/mono/metadata/components.c b/src/mono/mono/metadata/components.c
index 204c3d9c462..f6f94a0b507 100644
--- a/src/mono/mono/metadata/components.c
+++ b/src/mono/mono/metadata/components.c
@@ -43,9 +43,6 @@ typedef struct _MonoComponentEntry {
#define DEBUGGER_LIBRARY_NAME "debugger"
#define DEBUGGER_COMPONENT_NAME DEBUGGER_LIBRARY_NAME
-#define MARSHAL_ILGEN_LIBRARY_NAME "marshal-ilgen"
-#define MARSHAL_ILGEN_COMPONENT_NAME "marshal_ilgen"
-
MonoComponentHotReload *mono_component_hot_reload_private_ptr = NULL;
MonoComponentDebugger *mono_component_debugger_private_ptr = NULL;
@@ -53,8 +50,6 @@ MonoComponentDebugger *mono_component_debugger_private_ptr = NULL;
MonoComponentEventPipe *mono_component_event_pipe_private_ptr = NULL;
MonoComponentDiagnosticsServer *mono_component_diagnostics_server_private_ptr = NULL;
-MonoComponentMarshalILgen* mono_component_marshal_ilgen_private_ptr = NULL;
-
// DiagnosticsServer/EventPipe components currently hosted by diagnostics_tracing library.
#define DIAGNOSTICS_TRACING_LIBRARY_NAME "diagnostics_tracing"
#define EVENT_PIPE_COMPONENT_NAME "event_pipe"
@@ -66,7 +61,6 @@ MonoComponentEntry components[] = {
{ HOT_RELOAD_LIBRARY_NAME, HOT_RELOAD_COMPONENT_NAME, COMPONENT_INIT_FUNC (hot_reload), (MonoComponent**)&mono_component_hot_reload_private_ptr, NULL },
{ DIAGNOSTICS_TRACING_LIBRARY_NAME, EVENT_PIPE_COMPONENT_NAME, COMPONENT_INIT_FUNC (event_pipe), (MonoComponent**)&mono_component_event_pipe_private_ptr, NULL },
{ DIAGNOSTICS_TRACING_LIBRARY_NAME, DIAGNOSTICS_SERVER_COMPONENT_NAME, COMPONENT_INIT_FUNC (diagnostics_server), (MonoComponent**)&mono_component_diagnostics_server_private_ptr, NULL },
- { MARSHAL_ILGEN_LIBRARY_NAME, MARSHAL_ILGEN_COMPONENT_NAME, COMPONENT_INIT_FUNC (marshal_ilgen), (MonoComponent**)&mono_component_marshal_ilgen_private_ptr, NULL }
};
#ifndef STATIC_COMPONENTS
diff --git a/src/mono/mono/metadata/components.h b/src/mono/mono/metadata/components.h
index f6b8696d194..aba03174589 100644
--- a/src/mono/mono/metadata/components.h
+++ b/src/mono/mono/metadata/components.h
@@ -8,7 +8,6 @@
#include <mono/component/component.h>
#include <mono/component/hot_reload.h>
#include <mono/component/event_pipe.h>
-#include <mono/component/marshal-ilgen.h>
#include <mono/component/diagnostics_server.h>
#include <mono/component/debugger.h>
@@ -25,7 +24,6 @@ extern MonoComponentHotReload *mono_component_hot_reload_private_ptr;
extern MonoComponentEventPipe *mono_component_event_pipe_private_ptr;
extern MonoComponentDiagnosticsServer *mono_component_diagnostics_server_private_ptr;
extern MonoComponentDebugger *mono_component_debugger_private_ptr;
-extern MonoComponentMarshalILgen *mono_component_marshal_ilgen_private_ptr;
/* Declare each component's getter function here */
static inline
@@ -56,11 +54,4 @@ mono_component_debugger (void)
return mono_component_debugger_private_ptr;
}
-static inline
-MonoComponentMarshalILgen*
-mono_component_marshal_ilgen (void)
-{
- return mono_component_marshal_ilgen_private_ptr;
-}
-
-#endif/*_MONO_METADATA_COMPONENTS_H*/ \ No newline at end of file
+#endif/*_MONO_METADATA_COMPONENTS_H*/
diff --git a/src/mono/mono/metadata/marshal-ilgen.c b/src/mono/mono/metadata/marshal-ilgen.c
new file mode 100644
index 00000000000..ceceb70149f
--- /dev/null
+++ b/src/mono/mono/metadata/marshal-ilgen.c
@@ -0,0 +1,2830 @@
+#include "mono/metadata/debug-helpers.h"
+#include "metadata/marshal.h"
+#include "metadata/marshal-ilgen.h"
+#include "metadata/marshal-lightweight.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 (date_time, "System", "DateTime");
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (icustom_marshaler, "System.Runtime.InteropServices", "ICustomMarshaler");
+
+static void emit_string_free_icall (MonoMethodBuilder *mb, MonoMarshalConv conv);
+
+// TODO: Does this need to loose the mono_ prefix?
+static void mono_marshal_ilgen_legacy_init (void);
+
+static gboolean ilgen_cb_inited = FALSE;
+static MonoMarshalIlgenCallbacks ilgen_marshal_cb;
+
+void
+mono_install_marshal_callbacks_ilgen (MonoMarshalIlgenCallbacks *cb)
+{
+ g_assert (!ilgen_cb_inited);
+ g_assert (cb->version == MONO_MARSHAL_CALLBACKS_VERSION);
+ memcpy (&ilgen_marshal_cb, cb, sizeof (MonoMarshalIlgenCallbacks));
+ ilgen_cb_inited = TRUE;
+}
+
+
+static void
+emit_struct_free (MonoMethodBuilder *mb, MonoClass *klass, int struct_var)
+{
+ /* Call DestroyStructure */
+ /* FIXME: Only do this if needed */
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass);
+ mono_mb_emit_ldloc (mb, struct_var);
+ mono_mb_emit_icall (mb, mono_struct_delete_old);
+}
+
+static int
+emit_marshal_array_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec,
+ int conv_arg, MonoType **conv_arg_type,
+ MarshalAction action)
+{
+ MonoMethodBuilder *mb = m->mb;
+ MonoClass *klass = mono_class_from_mono_type_internal (t);
+ MonoMarshalNative encoding;
+
+ encoding = mono_marshal_get_string_encoding (m->piinfo, spec);
+ MonoType *int_type = mono_get_int_type ();
+ MonoType *object_type = mono_get_object_type ();
+
+ MonoClass *eklass = m_class_get_element_class (klass);
+
+ switch (action) {
+ case MARSHAL_ACTION_CONV_IN:
+ *conv_arg_type = object_type;
+ conv_arg = mono_mb_add_local (mb, object_type);
+
+ if (m_class_is_blittable (eklass)) {
+ 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, 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_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+#else
+ guint32 label1, label2, label3;
+ int index_var, src_var, dest_ptr, esize;
+ MonoMarshalConv conv;
+ gboolean is_string = FALSE;
+
+ dest_ptr = mono_mb_add_local (mb, int_type);
+
+ if (eklass == mono_defaults.string_class) {
+ is_string = TRUE;
+ conv = mono_marshal_get_string_to_ptr_conv (m->piinfo, spec);
+ }
+ else if (eklass == mono_class_try_get_stringbuilder_class ()) {
+ is_string = TRUE;
+ conv = mono_marshal_get_stringbuilder_to_ptr_conv (m->piinfo, spec);
+ }
+ else
+ conv = MONO_MARSHAL_CONV_INVALID;
+
+ if (is_string && conv == MONO_MARSHAL_CONV_INVALID) {
+ char *msg = g_strdup_printf ("string/stringbuilder marshalling conversion %d not implemented", encoding);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ break;
+ }
+
+ src_var = mono_mb_add_local (mb, object_type);
+ mono_mb_emit_ldarg (mb, argnum);
+ if (m_type_is_byref (t))
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_stloc (mb, src_var);
+
+ /* Check null */
+ mono_mb_emit_ldloc (mb, src_var);
+ mono_mb_emit_stloc (mb, conv_arg);
+ mono_mb_emit_ldloc (mb, src_var);
+ label1 = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ if (is_string)
+ esize = TARGET_SIZEOF_VOID_P;
+ else if (eklass == mono_defaults.char_class) /*can't call mono_marshal_type_size since it causes all sorts of asserts*/
+ esize = mono_pinvoke_is_unicode (m->piinfo) ? 2 : 1;
+ else
+ esize = mono_class_native_size (eklass, NULL);
+
+ /* allocate space for the native struct and store the address */
+ mono_mb_emit_icon (mb, esize);
+ mono_mb_emit_ldloc (mb, src_var);
+ mono_mb_emit_byte (mb, CEE_LDLEN);
+
+ if (eklass == mono_defaults.string_class) {
+ /* Make the array bigger for the terminating null */
+ mono_mb_emit_byte (mb, CEE_LDC_I4_1);
+ mono_mb_emit_byte (mb, CEE_ADD);
+ }
+ mono_mb_emit_byte (mb, CEE_MUL);
+ mono_mb_emit_byte (mb, CEE_PREFIX1);
+ mono_mb_emit_byte (mb, CEE_LOCALLOC);
+ mono_mb_emit_stloc (mb, conv_arg);
+
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_stloc (mb, dest_ptr);
+
+ /* 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);
+ label2 = mono_mb_get_label (mb);
+ mono_mb_emit_ldloc (mb, index_var);
+ mono_mb_emit_ldloc (mb, src_var);
+ mono_mb_emit_byte (mb, CEE_LDLEN);
+ label3 = mono_mb_emit_branch (mb, CEE_BGE);
+
+ /* Emit marshalling code */
+
+ if (is_string) {
+ int stind_op;
+ mono_mb_emit_ldloc (mb, dest_ptr);
+ 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, mono_marshal_shared_conv_to_icall (conv, &stind_op));
+ mono_mb_emit_byte (mb, GINT_TO_UINT8 (stind_op));
+ } else {
+ /* set the src_ptr */
+ mono_mb_emit_ldloc (mb, src_var);
+ mono_mb_emit_ldloc (mb, index_var);
+ mono_mb_emit_op (mb, CEE_LDELEMA, eklass);
+ mono_mb_emit_stloc (mb, 0);
+
+ /* set dst_ptr */
+ mono_mb_emit_ldloc (mb, dest_ptr);
+ mono_mb_emit_stloc (mb, 1);
+
+ /* emit valuetype conversion code */
+ 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, GINT_TO_UINT16 (index_var), 1);
+ mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (dest_ptr), esize);
+
+ mono_mb_emit_branch_label (mb, CEE_BR, label2);
+
+ mono_mb_patch_branch (mb, label3);
+
+ if (eklass == mono_defaults.string_class) {
+ /* Null terminate */
+ mono_mb_emit_ldloc (mb, dest_ptr);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_0);
+ mono_mb_emit_byte (mb, CEE_STIND_I);
+ }
+
+ mono_mb_patch_branch (mb, label1);
+#endif
+ }
+
+ break;
+
+ case MARSHAL_ACTION_CONV_OUT: {
+#ifndef DISABLE_NONBLITTABLE
+ gboolean need_convert, need_free;
+ /* Unicode character arrays are implicitly marshalled as [Out] under MS.NET */
+ need_convert = ((eklass == mono_defaults.char_class) && (encoding == MONO_NATIVE_LPWSTR)) || (eklass == mono_class_try_get_stringbuilder_class ()) || (t->attrs & PARAM_ATTRIBUTE_OUT);
+ need_free = mono_marshal_need_free (m_class_get_byval_arg (eklass), m->piinfo, spec);
+
+ if ((t->attrs & PARAM_ATTRIBUTE_OUT) && spec && spec->native == MONO_NATIVE_LPARRAY && spec->data.array_data.param_num != -1) {
+ int param_num = spec->data.array_data.param_num;
+ MonoType *param_type;
+
+ param_type = m->sig->params [param_num];
+
+ if (m_type_is_byref (param_type) && param_type->type != MONO_TYPE_I4) {
+ char *msg = g_strdup ("Not implemented.");
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ break;
+ }
+
+ if (m_type_is_byref (t) ) {
+ mono_mb_emit_ldarg (mb, argnum);
+
+ /* Create the managed array */
+ mono_mb_emit_ldarg (mb, param_num);
+ if (m_type_is_byref (m->sig->params [param_num]))
+ // FIXME: Support other types
+ mono_mb_emit_byte (mb, CEE_LDIND_I4);
+ mono_mb_emit_byte (mb, CEE_CONV_OVF_I);
+ mono_mb_emit_op (mb, CEE_NEWARR, eklass);
+ /* Store into argument */
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
+ }
+ }
+
+ if (need_convert || need_free) {
+ /* FIXME: Optimize blittable case */
+ guint32 label1, label2, label3;
+ int index_var, src_ptr, loc, esize;
+
+ if ((eklass == mono_class_try_get_stringbuilder_class ()) || (eklass == mono_defaults.string_class))
+ esize = TARGET_SIZEOF_VOID_P;
+ else if (eklass == mono_defaults.char_class)
+ esize = mono_pinvoke_is_unicode (m->piinfo) ? 2 : 1;
+ else
+ esize = mono_class_native_size (eklass, NULL);
+ src_ptr = mono_mb_add_local (mb, int_type);
+ loc = mono_mb_add_local (mb, int_type);
+
+ /* Check null */
+ mono_mb_emit_ldarg (mb, argnum);
+ if (m_type_is_byref (t))
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ label1 = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_stloc (mb, src_ptr);
+
+ /* 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);
+ label2 = mono_mb_get_label (mb);
+ mono_mb_emit_ldloc (mb, index_var);
+ mono_mb_emit_ldarg (mb, argnum);
+ if (m_type_is_byref (t))
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ mono_mb_emit_byte (mb, CEE_LDLEN);
+ label3 = mono_mb_emit_branch (mb, CEE_BGE);
+
+ /* Emit marshalling code */
+
+ if (eklass == mono_class_try_get_stringbuilder_class ()) {
+ gboolean need_free2;
+ MonoMarshalConv conv = mono_marshal_get_ptr_to_stringbuilder_conv (m->piinfo, spec, &need_free2);
+
+ g_assert (conv != MONO_MARSHAL_CONV_INVALID);
+
+ /* dest */
+ mono_mb_emit_ldarg (mb, argnum);
+ if (m_type_is_byref (t))
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_ldloc (mb, index_var);
+ mono_mb_emit_byte (mb, CEE_LDELEM_REF);
+
+ /* src */
+ mono_mb_emit_ldloc (mb, src_ptr);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL));
+
+ if (need_free) {
+ /* src */
+ mono_mb_emit_ldloc (mb, src_ptr);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+
+ mono_mb_emit_icall (mb, mono_marshal_free);
+ }
+ }
+ else if (eklass == mono_defaults.string_class) {
+ if (need_free) {
+ /* src */
+ mono_mb_emit_ldloc (mb, src_ptr);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+
+ mono_mb_emit_icall (mb, mono_marshal_free);
+ }
+ }
+ else {
+ if (need_convert) {
+ /* set the src_ptr */
+ mono_mb_emit_ldloc (mb, src_ptr);
+ mono_mb_emit_stloc (mb, 0);
+
+ /* set dst_ptr */
+ mono_mb_emit_ldarg (mb, argnum);
+ if (m_type_is_byref (t))
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ mono_mb_emit_ldloc (mb, index_var);
+ mono_mb_emit_op (mb, CEE_LDELEMA, eklass);
+ mono_mb_emit_stloc (mb, 1);
+
+ /* emit valuetype conversion code */
+ mono_marshal_shared_emit_struct_conv_full (mb, eklass, TRUE, 0, eklass == mono_defaults.char_class ? encoding : (MonoMarshalNative)-1);
+ }
+
+ if (need_free) {
+ mono_mb_emit_ldloc (mb, src_ptr);
+ mono_mb_emit_stloc (mb, loc);
+
+ emit_struct_free (mb, eklass, loc);
+ }
+ }
+
+ mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1);
+ mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (src_ptr), esize);
+
+ mono_mb_emit_branch_label (mb, CEE_BR, label2);
+
+ mono_mb_patch_branch (mb, label1);
+ mono_mb_patch_branch (mb, label3);
+ }
+#endif
+
+ if (m_class_is_blittable (eklass)) {
+ /* free memory allocated (if any) by MONO_MARSHAL_CONV_ARRAY_LPARRAY */
+
+ mono_mb_emit_ldarg (mb, argnum);
+ 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, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_FREE_LPARRAY, NULL));
+ }
+
+ break;
+ }
+
+ case MARSHAL_ACTION_PUSH:
+ if (m_type_is_byref (t))
+ mono_mb_emit_ldloc_addr (mb, conv_arg);
+ else
+ mono_mb_emit_ldloc (mb, conv_arg);
+ break;
+
+ 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_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ break;
+ }
+
+ case MARSHAL_ACTION_MANAGED_CONV_IN: {
+ guint32 label1, label2, label3;
+ int index_var, src_ptr, esize, param_num, num_elem;
+ MonoMarshalConv conv;
+ gboolean is_string = FALSE;
+
+ conv_arg = mono_mb_add_local (mb, object_type);
+ *conv_arg_type = int_type;
+
+ if (m_type_is_byref (t)) {
+ char *msg = g_strdup ("Byref array marshalling to managed code is not implemented.");
+ 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_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ return conv_arg;
+ }
+
+ switch (spec->native) {
+ case MONO_NATIVE_LPARRAY:
+ break;
+ case MONO_NATIVE_SAFEARRAY:
+#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_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_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ return conv_arg;
+ }
+ }
+
+ /* FIXME: t is from the method which is wrapped, not the delegate type */
+ /* g_assert (t->attrs & PARAM_ATTRIBUTE_IN); */
+
+ param_num = spec->data.array_data.param_num;
+ num_elem = spec->data.array_data.num_elem;
+ if (spec->data.array_data.elem_mult == 0)
+ /* param_num is not specified */
+ param_num = -1;
+
+ 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_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ return conv_arg;
+ }
+ }
+
+ /* FIXME: Optimize blittable case */
+
+#ifndef DISABLE_NONBLITTABLE
+ if (eklass == mono_defaults.string_class) {
+ is_string = TRUE;
+ gboolean need_free;
+ conv = mono_marshal_get_ptr_to_string_conv (m->piinfo, spec, &need_free);
+ }
+ else if (eklass == mono_class_try_get_stringbuilder_class ()) {
+ is_string = TRUE;
+ gboolean need_free;
+ conv = mono_marshal_get_ptr_to_stringbuilder_conv (m->piinfo, spec, &need_free);
+ }
+ else
+ conv = MONO_MARSHAL_CONV_INVALID;
+#endif
+
+ mono_marshal_load_type_info (eklass);
+
+ if (is_string)
+ esize = TARGET_SIZEOF_VOID_P;
+ else
+ esize = mono_class_native_size (eklass, NULL);
+ src_ptr = mono_mb_add_local (mb, int_type);
+
+ mono_mb_emit_byte (mb, CEE_LDNULL);
+ mono_mb_emit_stloc (mb, conv_arg);
+
+ /* Check param index */
+ 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_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ return conv_arg;
+ }
+ switch (m->sig->params [param_num]->type) {
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ break;
+ default: {
+ char *msg = g_strdup ("Array size control parameter must be an integral type.");
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ return conv_arg;
+ }
+ }
+ }
+
+ /* Check null */
+ mono_mb_emit_ldarg (mb, argnum);
+ label1 = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_stloc (mb, src_ptr);
+
+ /* Create managed array */
+ /*
+ * The LPArray marshalling spec says that sometimes param_num starts
+ * from 1, sometimes it starts from 0. But MS seems to always start
+ * from 0.
+ */
+
+ if (param_num == -1) {
+ mono_mb_emit_icon (mb, num_elem);
+ } else {
+ mono_mb_emit_ldarg (mb, param_num);
+ if (num_elem > 0) {
+ mono_mb_emit_icon (mb, num_elem);
+ mono_mb_emit_byte (mb, CEE_ADD);
+ }
+ mono_mb_emit_byte (mb, CEE_CONV_OVF_I);
+ }
+
+ mono_mb_emit_op (mb, CEE_NEWARR, eklass);
+ mono_mb_emit_stloc (mb, conv_arg);
+
+ if (m_class_is_blittable (eklass)) {
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_byte (mb, CEE_CONV_I);
+ mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoArray, vector));
+ mono_mb_emit_byte (mb, CEE_ADD);
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_byte (mb, CEE_LDLEN);
+ mono_mb_emit_icon (mb, esize);
+ mono_mb_emit_byte (mb, CEE_MUL);
+ mono_mb_emit_byte (mb, CEE_PREFIX1);
+ mono_mb_emit_byte (mb, CEE_CPBLK);
+ mono_mb_patch_branch (mb, label1);
+ break;
+ }
+#ifdef DISABLE_NONBLITTABLE
+ else {
+ char *msg = g_strdup ("Non-blittable marshalling conversion is disabled");
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ }
+#else
+ /* 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);
+ label2 = mono_mb_get_label (mb);
+ mono_mb_emit_ldloc (mb, index_var);
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_byte (mb, CEE_LDLEN);
+ label3 = mono_mb_emit_branch (mb, CEE_BGE);
+
+ /* Emit marshalling code */
+ if (is_string) {
+ g_assert (conv != MONO_MARSHAL_CONV_INVALID);
+
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_ldloc (mb, index_var);
+
+ mono_mb_emit_ldloc (mb, src_ptr);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+
+ 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_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ return conv_arg;
+ }
+
+ mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1);
+ mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (src_ptr), esize);
+
+ mono_mb_emit_branch_label (mb, CEE_BR, label2);
+
+ mono_mb_patch_branch (mb, label1);
+ mono_mb_patch_branch (mb, label3);
+#endif
+
+ break;
+ }
+ case MARSHAL_ACTION_MANAGED_CONV_OUT: {
+ guint32 label1, label2, label3;
+ int index_var, dest_ptr, esize, param_num, num_elem;
+ MonoMarshalConv conv;
+ gboolean is_string = FALSE;
+
+ if (!spec)
+ /* Already handled in CONV_IN */
+ break;
+
+ /* These are already checked in CONV_IN */
+ g_assert (!m_type_is_byref (t));
+ g_assert (spec->native == MONO_NATIVE_LPARRAY);
+ g_assert (t->attrs & PARAM_ATTRIBUTE_OUT);
+
+ param_num = spec->data.array_data.param_num;
+ num_elem = spec->data.array_data.num_elem;
+
+ if (spec->data.array_data.elem_mult == 0)
+ /* param_num is not specified */
+ param_num = -1;
+
+ if (param_num == -1) {
+ if (num_elem <= 0) {
+ g_assert_not_reached ();
+ }
+ }
+
+ /* FIXME: Optimize blittable case */
+
+#ifndef DISABLE_NONBLITTABLE
+ if (eklass == mono_defaults.string_class) {
+ is_string = TRUE;
+ conv = mono_marshal_get_string_to_ptr_conv (m->piinfo, spec);
+ }
+ else if (eklass == mono_class_try_get_stringbuilder_class ()) {
+ is_string = TRUE;
+ conv = mono_marshal_get_stringbuilder_to_ptr_conv (m->piinfo, spec);
+ }
+ else
+ conv = MONO_MARSHAL_CONV_INVALID;
+#endif
+
+ mono_marshal_load_type_info (eklass);
+
+ if (is_string)
+ esize = TARGET_SIZEOF_VOID_P;
+ else
+ esize = mono_class_native_size (eklass, NULL);
+
+ dest_ptr = mono_mb_add_local (mb, int_type);
+
+ /* Check null */
+ mono_mb_emit_ldloc (mb, conv_arg);
+ label1 = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_stloc (mb, dest_ptr);
+
+ if (m_class_is_blittable (eklass)) {
+ /* dest */
+ mono_mb_emit_ldarg (mb, argnum);
+ /* src */
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_byte (mb, CEE_CONV_I);
+ mono_mb_emit_icon (mb, MONO_STRUCT_OFFSET (MonoArray, vector));
+ mono_mb_emit_byte (mb, CEE_ADD);
+ /* length */
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_byte (mb, CEE_LDLEN);
+ mono_mb_emit_icon (mb, esize);
+ mono_mb_emit_byte (mb, CEE_MUL);
+ mono_mb_emit_byte (mb, CEE_PREFIX1);
+ mono_mb_emit_byte (mb, CEE_CPBLK);
+ mono_mb_patch_branch (mb, label1);
+ break;
+ }
+
+#ifndef DISABLE_NONBLITTABLE
+ /* 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);
+ label2 = mono_mb_get_label (mb);
+ mono_mb_emit_ldloc (mb, index_var);
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_byte (mb, CEE_LDLEN);
+ label3 = mono_mb_emit_branch (mb, CEE_BGE);
+
+ /* Emit marshalling code */
+ if (is_string) {
+ int stind_op;
+ g_assert (conv != MONO_MARSHAL_CONV_INVALID);
+
+ /* dest */
+ mono_mb_emit_ldloc (mb, dest_ptr);
+
+ /* src */
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_ldloc (mb, index_var);
+
+ mono_mb_emit_byte (mb, CEE_LDELEM_REF);
+
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, &stind_op));
+ mono_mb_emit_byte (mb, GINT_TO_UINT8 (stind_op));
+ }
+ else {
+ char *msg = g_strdup ("Marshalling of non-string and non-blittable arrays to managed code is not implemented.");
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ return conv_arg;
+ }
+
+ mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1);
+ mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (dest_ptr), esize);
+
+ mono_mb_emit_branch_label (mb, CEE_BR, label2);
+
+ mono_mb_patch_branch (mb, label1);
+ mono_mb_patch_branch (mb, label3);
+#endif
+
+ break;
+ }
+ case MARSHAL_ACTION_MANAGED_CONV_RESULT: {
+#ifndef DISABLE_NONBLITTABLE
+ guint32 label1, label2, label3;
+ int index_var, src, dest, esize;
+ MonoMarshalConv conv = MONO_MARSHAL_CONV_INVALID;
+ gboolean is_string = FALSE;
+
+ g_assert (!m_type_is_byref (t));
+
+ mono_marshal_load_type_info (eklass);
+
+ if (eklass == mono_defaults.string_class) {
+ is_string = TRUE;
+ conv = mono_marshal_get_string_to_ptr_conv (m->piinfo, spec);
+ }
+ else {
+ g_assert_not_reached ();
+ }
+
+ if (is_string)
+ esize = TARGET_SIZEOF_VOID_P;
+ else if (eklass == mono_defaults.char_class)
+ esize = mono_pinvoke_is_unicode (m->piinfo) ? 2 : 1;
+ else
+ esize = mono_class_native_size (eklass, NULL);
+
+ src = mono_mb_add_local (mb, object_type);
+ dest = mono_mb_add_local (mb, int_type);
+
+ mono_mb_emit_stloc (mb, src);
+ mono_mb_emit_ldloc (mb, src);
+ mono_mb_emit_stloc (mb, 3);
+
+ /* Check for null */
+ mono_mb_emit_ldloc (mb, src);
+ label1 = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ /* Allocate native array */
+ mono_mb_emit_icon (mb, esize);
+ mono_mb_emit_ldloc (mb, src);
+ mono_mb_emit_byte (mb, CEE_LDLEN);
+
+ if (eklass == mono_defaults.string_class) {
+ /* Make the array bigger for the terminating null */
+ mono_mb_emit_byte (mb, CEE_LDC_I4_1);
+ mono_mb_emit_byte (mb, CEE_ADD);
+ }
+ mono_mb_emit_byte (mb, CEE_MUL);
+ mono_mb_emit_icall (mb, ves_icall_marshal_alloc);
+ mono_mb_emit_stloc (mb, dest);
+ mono_mb_emit_ldloc (mb, dest);
+ mono_mb_emit_stloc (mb, 3);
+
+ /* 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);
+ label2 = mono_mb_get_label (mb);
+ mono_mb_emit_ldloc (mb, index_var);
+ mono_mb_emit_ldloc (mb, src);
+ mono_mb_emit_byte (mb, CEE_LDLEN);
+ label3 = mono_mb_emit_branch (mb, CEE_BGE);
+
+ /* Emit marshalling code */
+ if (is_string) {
+ int stind_op;
+ g_assert (conv != MONO_MARSHAL_CONV_INVALID);
+
+ /* dest */
+ mono_mb_emit_ldloc (mb, dest);
+
+ /* src */
+ mono_mb_emit_ldloc (mb, src);
+ mono_mb_emit_ldloc (mb, index_var);
+
+ mono_mb_emit_byte (mb, CEE_LDELEM_REF);
+
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, &stind_op));
+ mono_mb_emit_byte (mb, GINT_TO_UINT8 (stind_op));
+ }
+ else {
+ char *msg = g_strdup ("Marshalling of non-string arrays to managed code is not implemented.");
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ return conv_arg;
+ }
+
+ mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (index_var), 1);
+ mono_mb_emit_add_to_local (mb, GINT_TO_UINT16 (dest), esize);
+
+ mono_mb_emit_branch_label (mb, CEE_BR, label2);
+
+ mono_mb_patch_branch (mb, label3);
+ mono_mb_patch_branch (mb, label1);
+#endif
+ break;
+ }
+ default:
+ g_assert_not_reached ();
+ }
+ return conv_arg;
+}
+
+static gboolean
+emit_native_wrapper_validate_signature (MonoMethodBuilder *mb, MonoMethodSignature* sig, MonoMarshalSpec** mspecs)
+{
+ if (mspecs) {
+ for (int i = 0; i < sig->param_count; i ++) {
+ if (mspecs [i + 1] && mspecs [i + 1]->native == MONO_NATIVE_CUSTOM) {
+ if (!mspecs [i + 1]->data.custom_data.custom_name || *mspecs [i + 1]->data.custom_data.custom_name == '\0') {
+ mono_mb_emit_exception_full (mb, "System", "TypeLoadException", g_strdup ("Missing ICustomMarshaler type"));
+ return FALSE;
+ }
+
+ switch (sig->params[i]->type) {
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_VALUETYPE:
+ break;
+
+ default:
+ mono_mb_emit_exception_full (mb, "System.Runtime.InteropServices", "MarshalDirectiveException", g_strdup_printf ("custom marshalling of type %x is currently not supported", sig->params[i]->type));
+ return FALSE;
+ }
+ }
+ else if (sig->params[i]->type == MONO_TYPE_VALUETYPE) {
+ MonoMarshalType *marshal_type = mono_marshal_load_type_info (mono_class_from_mono_type_internal (sig->params [i]));
+ for (guint32 field_idx = 0; field_idx < marshal_type->num_fields; ++field_idx) {
+ if (marshal_type->fields [field_idx].mspec && marshal_type->fields [field_idx].mspec->native == MONO_NATIVE_CUSTOM) {
+ mono_mb_emit_exception_full (mb, "System", "TypeLoadException", g_strdup ("Value type includes custom marshaled fields"));
+ return FALSE;
+ }
+ }
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+static int
+emit_marshal_ptr_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec, int conv_arg,
+ MonoType **conv_arg_type, MarshalAction action)
+{
+ MonoMethodBuilder *mb = m->mb;
+ switch (action) {
+ case MARSHAL_ACTION_CONV_IN:
+ /* MS seems to allow this in some cases, ie. bxc #158 */
+ /*
+ 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_marshal_shared_mb_emit_exception_marshal_directive (m->mb, msg);
+ }
+ */
+ break;
+
+ case MARSHAL_ACTION_PUSH:
+ mono_mb_emit_ldarg (mb, argnum);
+ break;
+
+ case MARSHAL_ACTION_CONV_RESULT:
+ /* no conversions necessary */
+ mono_mb_emit_stloc (mb, 3);
+ break;
+
+ default:
+ break;
+ }
+ return conv_arg;
+}
+
+static int
+emit_marshal_boolean_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec,
+ int conv_arg, MonoType **conv_arg_type,
+ MarshalAction action)
+{
+ MonoMethodBuilder *mb = m->mb;
+ MonoType *int_type = mono_get_int_type ();
+ MonoType *boolean_type = m_class_get_byval_arg (mono_defaults.boolean_class);
+
+ switch (action) {
+ case MARSHAL_ACTION_CONV_IN: {
+ MonoType *local_type;
+ int label_false;
+ guint8 ldc_op = CEE_LDC_I4_1;
+
+ local_type = mono_marshal_boolean_conv_in_get_local_type (spec, &ldc_op);
+ if (m_type_is_byref (t))
+ *conv_arg_type = int_type;
+ else
+ *conv_arg_type = local_type;
+ conv_arg = mono_mb_add_local (mb, local_type);
+
+ mono_mb_emit_ldarg (mb, argnum);
+ if (m_type_is_byref (t))
+ mono_mb_emit_byte (mb, CEE_LDIND_I1);
+ label_false = mono_mb_emit_branch (mb, CEE_BRFALSE);
+ mono_mb_emit_byte (mb, ldc_op);
+ mono_mb_emit_stloc (mb, conv_arg);
+ mono_mb_patch_branch (mb, label_false);
+
+ break;
+ }
+
+ case MARSHAL_ACTION_CONV_OUT:
+ {
+ int label_false, label_end;
+ if (!m_type_is_byref (t))
+ break;
+
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldloc (mb, conv_arg);
+
+ label_false = mono_mb_emit_branch (mb, CEE_BRFALSE);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_1);
+
+ label_end = mono_mb_emit_branch (mb, CEE_BR);
+ mono_mb_patch_branch (mb, label_false);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_0);
+ mono_mb_patch_branch (mb, label_end);
+
+ mono_mb_emit_byte (mb, CEE_STIND_I1);
+ break;
+ }
+
+ case MARSHAL_ACTION_PUSH:
+ if (m_type_is_byref (t))
+ mono_mb_emit_ldloc_addr (mb, conv_arg);
+ else if (conv_arg)
+ mono_mb_emit_ldloc (mb, conv_arg);
+ else
+ mono_mb_emit_ldarg (mb, argnum);
+ break;
+
+ case MARSHAL_ACTION_CONV_RESULT:
+ /* maybe we need to make sure that it fits within 8 bits */
+ mono_mb_emit_stloc (mb, 3);
+ break;
+
+ case MARSHAL_ACTION_MANAGED_CONV_IN: {
+ MonoClass* conv_arg_class = mono_defaults.int32_class;
+ guint8 ldop = CEE_LDIND_I4;
+ int label_null, label_false;
+
+ conv_arg_class = mono_marshal_boolean_managed_conv_in_get_conv_arg_class (spec, &ldop);
+ conv_arg = mono_mb_add_local (mb, boolean_type);
+
+ if (m_type_is_byref (t))
+ *conv_arg_type = m_class_get_this_arg (conv_arg_class);
+ else
+ *conv_arg_type = m_class_get_byval_arg (conv_arg_class);
+
+
+ mono_mb_emit_ldarg (mb, argnum);
+
+ /* Check null */
+ if (m_type_is_byref (t)) {
+ label_null = mono_mb_emit_branch (mb, CEE_BRFALSE);
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_byte (mb, ldop);
+ } else
+ label_null = 0;
+
+ label_false = mono_mb_emit_branch (mb, CEE_BRFALSE);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_1);
+ mono_mb_emit_stloc (mb, conv_arg);
+ mono_mb_patch_branch (mb, label_false);
+
+ if (m_type_is_byref (t))
+ mono_mb_patch_branch (mb, label_null);
+ break;
+ }
+
+ case MARSHAL_ACTION_MANAGED_CONV_OUT: {
+ guint8 stop = CEE_STIND_I4;
+ guint8 ldc_op = CEE_LDC_I4_1;
+ int label_null,label_false, label_end;
+
+ if (!m_type_is_byref (t))
+ break;
+ if (spec) {
+ switch (spec->native) {
+ case MONO_NATIVE_I1:
+ case MONO_NATIVE_U1:
+ stop = CEE_STIND_I1;
+ break;
+ case MONO_NATIVE_VARIANTBOOL:
+ stop = CEE_STIND_I2;
+ ldc_op = CEE_LDC_I4_M1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Check null */
+ mono_mb_emit_ldarg (mb, argnum);
+ label_null = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldloc (mb, conv_arg);
+
+ label_false = mono_mb_emit_branch (mb, CEE_BRFALSE);
+ mono_mb_emit_byte (mb, ldc_op);
+ label_end = mono_mb_emit_branch (mb, CEE_BR);
+
+ mono_mb_patch_branch (mb, label_false);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_0);
+ mono_mb_patch_branch (mb, label_end);
+
+ mono_mb_emit_byte (mb, stop);
+ mono_mb_patch_branch (mb, label_null);
+ break;
+ }
+
+ default:
+ g_assert_not_reached ();
+ }
+ return conv_arg;
+}
+
+static int
+emit_marshal_char_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec, int conv_arg,
+ MonoType **conv_arg_type, MarshalAction action)
+{
+ MonoMethodBuilder *mb = m->mb;
+
+ switch (action) {
+ case MARSHAL_ACTION_PUSH:
+ /* fixme: dont know how to marshal that. We cant simply
+ * convert it to a one byte UTF8 character, because an
+ * unicode character may need more that one byte in UTF8 */
+ mono_mb_emit_ldarg (mb, argnum);
+ break;
+
+ case MARSHAL_ACTION_CONV_RESULT:
+ /* fixme: we need conversions here */
+ mono_mb_emit_stloc (mb, 3);
+ break;
+
+ default:
+ break;
+ }
+ return conv_arg;
+}
+
+static int
+emit_marshal_custom_ilgen_throw_exception (MonoMethodBuilder *mb, const char *exc_nspace, const char *exc_name, const char *msg, MarshalAction action)
+{
+ /* Throw exception and emit compensation code, if necessary */
+ switch (action) {
+ case MARSHAL_ACTION_CONV_IN:
+ case MARSHAL_ACTION_MANAGED_CONV_IN:
+ case MARSHAL_ACTION_CONV_RESULT:
+ case MARSHAL_ACTION_MANAGED_CONV_RESULT:
+ if ((action == MARSHAL_ACTION_CONV_RESULT) || (action == MARSHAL_ACTION_MANAGED_CONV_RESULT))
+ mono_mb_emit_byte (mb, CEE_POP);
+
+ mono_mb_emit_exception_full (mb, exc_nspace, exc_name, msg);
+
+ break;
+ case MARSHAL_ACTION_PUSH:
+ mono_mb_emit_byte (mb, CEE_LDNULL);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int
+emit_marshal_custom_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec,
+ int conv_arg, MonoType **conv_arg_type,
+ MarshalAction action)
+{
+ ERROR_DECL (error);
+ MonoType *mtype;
+ MonoClass *mklass;
+ static MonoClass *ICustomMarshaler = NULL;
+ static MonoMethod *cleanup_native, *cleanup_managed;
+ static MonoMethod *marshal_managed_to_native, *marshal_native_to_managed;
+ MonoMethodBuilder *mb = m->mb;
+ MonoAssemblyLoadContext *alc = mono_alc_get_ambient ();
+ guint32 loc1;
+ int pos2;
+
+ MonoType *int_type = mono_get_int_type ();
+ MonoType *object_type = mono_get_object_type ();
+
+ if (!ICustomMarshaler) {
+ MonoClass *klass = mono_class_try_get_icustom_marshaler_class ();
+ if (!klass)
+ return emit_marshal_custom_ilgen_throw_exception (mb, "System", "ApplicationException", g_strdup ("Current profile doesn't support ICustomMarshaler"), action);
+
+ cleanup_native = mono_marshal_shared_get_method_nofail (klass, "CleanUpNativeData", 1, 0);
+ g_assert (cleanup_native);
+
+ cleanup_managed = mono_marshal_shared_get_method_nofail (klass, "CleanUpManagedData", 1, 0);
+ g_assert (cleanup_managed);
+
+ marshal_managed_to_native = mono_marshal_shared_get_method_nofail (klass, "MarshalManagedToNative", 1, 0);
+ g_assert (marshal_managed_to_native);
+
+ marshal_native_to_managed = mono_marshal_shared_get_method_nofail (klass, "MarshalNativeToManaged", 1, 0);
+ g_assert (marshal_native_to_managed);
+
+ mono_memory_barrier ();
+ ICustomMarshaler = klass;
+ }
+
+ if (spec->data.custom_data.image)
+ mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, alc, spec->data.custom_data.image, error);
+ else
+ mtype = mono_reflection_type_from_name_checked (spec->data.custom_data.custom_name, alc, m->image, error);
+
+ if (!mtype)
+ return emit_marshal_custom_ilgen_throw_exception (mb, "System", "TypeLoadException", g_strdup ("Failed to load ICustomMarshaler type"), action);
+
+ mklass = mono_class_from_mono_type_internal (mtype);
+ g_assert (mklass != NULL);
+
+ switch (action) {
+ case MARSHAL_ACTION_CONV_IN:
+ switch (t->type) {
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_VALUETYPE:
+ break;
+
+ default:
+ g_warning ("custom marshalling of type %x is currently not supported", t->type);
+ g_assert_not_reached ();
+ break;
+ }
+
+ conv_arg = mono_mb_add_local (mb, int_type);
+
+ mono_mb_emit_byte (mb, CEE_LDNULL);
+ mono_mb_emit_stloc (mb, conv_arg);
+
+ if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT))
+ break;
+
+ /* Minic MS.NET behavior */
+ if (!m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT) && !(t->attrs & PARAM_ATTRIBUTE_IN))
+ break;
+
+ /* Check for null */
+ mono_mb_emit_ldarg (mb, argnum);
+ if (m_type_is_byref (t))
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec);
+
+ mono_mb_emit_ldarg (mb, argnum);
+ if (m_type_is_byref (t))
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+
+ if (t->type == MONO_TYPE_VALUETYPE) {
+ /*
+ * Since we can't determine the type of the argument, we
+ * will assume the unmanaged function takes a pointer.
+ */
+ *conv_arg_type = int_type;
+
+ mono_mb_emit_op (mb, CEE_BOX, mono_class_from_mono_type_internal (t));
+ }
+
+ mono_mb_emit_op (mb, CEE_CALLVIRT, marshal_managed_to_native);
+ mono_mb_emit_stloc (mb, conv_arg);
+
+ mono_mb_patch_branch (mb, pos2);
+ break;
+
+ case MARSHAL_ACTION_CONV_OUT:
+ /* Check for null */
+ mono_mb_emit_ldloc (mb, conv_arg);
+ pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_OUT)) {
+ mono_mb_emit_ldarg (mb, argnum);
+
+ mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec);
+ mono_mb_emit_byte (mb, CEE_DUP);
+
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ mono_mb_emit_op (mb, CEE_CALLVIRT, cleanup_managed);
+
+ 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 (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
+ mono_mb_emit_ldarg (mb, argnum);
+
+ 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) {
+ 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);
+ /* We have nowhere to store the result */
+ mono_mb_emit_byte (mb, CEE_POP);
+ }
+
+ // 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))) {
+ 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_native);
+ }
+
+ mono_mb_patch_branch (mb, pos2);
+ break;
+
+ case MARSHAL_ACTION_PUSH:
+ if (m_type_is_byref (t))
+ mono_mb_emit_ldloc_addr (mb, conv_arg);
+ else
+ mono_mb_emit_ldloc (mb, conv_arg);
+ break;
+
+ case MARSHAL_ACTION_CONV_RESULT:
+ mono_mb_emit_stloc (mb, 3);
+
+ /* Check for null */
+ mono_mb_emit_ldloc (mb, 3);
+ pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ 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);
+ mono_mb_emit_stloc (mb, 3);
+
+ mono_mb_patch_branch (mb, pos2);
+ break;
+
+ case MARSHAL_ACTION_MANAGED_CONV_IN:
+ switch (t->type) {
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_OBJECT:
+ case MONO_TYPE_STRING:
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_SZARRAY:
+ case MONO_TYPE_VALUETYPE:
+ case MONO_TYPE_BOOLEAN:
+ break;
+
+ default:
+ g_warning ("custom marshalling of type %x is currently not supported", t->type);
+ g_assert_not_reached ();
+ break;
+ }
+
+ conv_arg = mono_mb_add_local (mb, object_type);
+
+ mono_mb_emit_byte (mb, CEE_LDNULL);
+ mono_mb_emit_stloc (mb, conv_arg);
+
+ if (m_type_is_byref (t) && t->attrs & PARAM_ATTRIBUTE_OUT)
+ break;
+
+ /* Check for null */
+ mono_mb_emit_ldarg (mb, argnum);
+ if (m_type_is_byref (t))
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec);
+
+ mono_mb_emit_ldarg (mb, argnum);
+ if (m_type_is_byref (t))
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+
+ mono_mb_emit_op (mb, CEE_CALLVIRT, marshal_native_to_managed);
+ mono_mb_emit_stloc (mb, conv_arg);
+
+ mono_mb_patch_branch (mb, pos2);
+ break;
+
+ case MARSHAL_ACTION_MANAGED_CONV_RESULT:
+ g_assert (!m_type_is_byref (t));
+
+ loc1 = mono_mb_add_local (mb, object_type);
+
+ mono_mb_emit_stloc (mb, 3);
+
+ mono_mb_emit_ldloc (mb, 3);
+ mono_mb_emit_stloc (mb, loc1);
+
+ /* Check for null */
+ mono_mb_emit_ldloc (mb, 3);
+ pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ mono_marshal_shared_emit_marshal_custom_get_instance (mb, mklass, spec);
+ mono_mb_emit_byte (mb, CEE_DUP);
+
+ mono_mb_emit_ldloc (mb, 3);
+ mono_mb_emit_op (mb, CEE_CALLVIRT, marshal_managed_to_native);
+ mono_mb_emit_stloc (mb, 3);
+
+ mono_mb_emit_ldloc (mb, loc1);
+ mono_mb_emit_op (mb, CEE_CALLVIRT, cleanup_managed);
+
+ mono_mb_patch_branch (mb, pos2);
+ break;
+
+ case MARSHAL_ACTION_MANAGED_CONV_OUT:
+
+ /* Check for null */
+ mono_mb_emit_ldloc (mb, conv_arg);
+ pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ if (m_type_is_byref (t)) {
+ mono_mb_emit_ldarg (mb, argnum);
+
+ 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);
+ mono_mb_emit_byte (mb, CEE_STIND_I);
+ }
+
+ // 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))) {
+ 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);
+ }
+
+ mono_mb_patch_branch (mb, pos2);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+ return conv_arg;
+}
+
+static int
+emit_marshal_asany_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec,
+ int conv_arg, MonoType **conv_arg_type,
+ MarshalAction action)
+{
+ MonoMethodBuilder *mb = m->mb;
+
+ MonoType *int_type = mono_get_int_type ();
+ switch (action) {
+ case MARSHAL_ACTION_CONV_IN: {
+ MonoMarshalNative encoding = mono_marshal_get_string_encoding (m->piinfo, NULL);
+
+ g_assert (t->type == MONO_TYPE_OBJECT);
+ g_assert (!m_type_is_byref (t));
+
+ conv_arg = mono_mb_add_local (mb, int_type);
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_icon (mb, encoding);
+ mono_mb_emit_icon (mb, t->attrs);
+ mono_mb_emit_icall (mb, mono_marshal_asany);
+ mono_mb_emit_stloc (mb, conv_arg);
+ break;
+ }
+
+ case MARSHAL_ACTION_PUSH:
+ mono_mb_emit_ldloc (mb, conv_arg);
+ break;
+
+ case MARSHAL_ACTION_CONV_OUT: {
+ MonoMarshalNative encoding = mono_marshal_get_string_encoding (m->piinfo, NULL);
+
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_icon (mb, encoding);
+ mono_mb_emit_icon (mb, t->attrs);
+ mono_mb_emit_icall (mb, mono_marshal_free_asany);
+ break;
+ }
+
+ default:
+ g_assert_not_reached ();
+ }
+ return conv_arg;
+}
+
+static int
+emit_marshal_vtype_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec,
+ int conv_arg, MonoType **conv_arg_type,
+ MarshalAction action)
+{
+ MonoMethodBuilder *mb = m->mb;
+ MonoClass *klass, *date_time_class;
+ int pos = 0, pos2;
+
+ klass = mono_class_from_mono_type_internal (t);
+
+ date_time_class = mono_class_get_date_time_class ();
+
+ MonoType *int_type = mono_get_int_type ();
+ MonoType *double_type = m_class_get_byval_arg (mono_defaults.double_class);
+
+ switch (action) {
+ case MARSHAL_ACTION_CONV_IN:
+ if (klass == date_time_class) {
+ /* Convert it to an OLE DATE type */
+
+ conv_arg = mono_mb_add_local (mb, double_type);
+
+ if (m_type_is_byref (t)) {
+ mono_mb_emit_ldarg (mb, argnum);
+ pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
+ }
+
+ if (!(m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT))) {
+ if (!m_type_is_byref (t))
+ m->csig->params [argnum - m->csig->hasthis] = double_type;
+
+ MONO_STATIC_POINTER_INIT (MonoMethod, to_oadate)
+ 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)
+
+ mono_mb_emit_ldarg_addr (mb, argnum);
+ mono_mb_emit_managed_call (mb, to_oadate, NULL);
+ mono_mb_emit_stloc (mb, conv_arg);
+ }
+
+ if (m_type_is_byref (t))
+ mono_mb_patch_branch (mb, pos);
+ break;
+ }
+
+ if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass))
+ break;
+
+ conv_arg = mono_mb_add_local (mb, int_type);
+
+ /* store the address of the source into local variable 0 */
+ if (m_type_is_byref (t))
+ mono_mb_emit_ldarg (mb, argnum);
+ else
+ mono_mb_emit_ldarg_addr (mb, argnum);
+
+ mono_mb_emit_stloc (mb, 0);
+
+ /* allocate space for the native struct and
+ * store the address into local variable 1 (dest) */
+ mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
+ mono_mb_emit_byte (mb, CEE_PREFIX1);
+ mono_mb_emit_byte (mb, CEE_LOCALLOC);
+ mono_mb_emit_stloc (mb, conv_arg);
+
+ if (m_type_is_byref (t)) {
+ mono_mb_emit_ldloc (mb, 0);
+ pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
+ }
+
+ if (!(m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT))) {
+ /* set dst_ptr */
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_stloc (mb, 1);
+
+ /* emit valuetype conversion code */
+ mono_marshal_shared_emit_struct_conv (mb, klass, FALSE);
+ }
+
+ if (m_type_is_byref (t))
+ mono_mb_patch_branch (mb, pos);
+ break;
+
+ case MARSHAL_ACTION_PUSH:
+ if (spec && spec->native == MONO_NATIVE_LPSTRUCT) {
+ /* FIXME: */
+ g_assert (!m_type_is_byref (t));
+
+ /* Have to change the signature since the vtype is passed byref */
+ m->csig->params [argnum - m->csig->hasthis] = int_type;
+
+ if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass))
+ mono_mb_emit_ldarg_addr (mb, argnum);
+ else
+ mono_mb_emit_ldloc (mb, conv_arg);
+ break;
+ }
+
+ if (klass == date_time_class) {
+ if (m_type_is_byref (t))
+ mono_mb_emit_ldloc_addr (mb, conv_arg);
+ else
+ mono_mb_emit_ldloc (mb, conv_arg);
+ break;
+ }
+
+ if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) {
+ mono_mb_emit_ldarg (mb, argnum);
+ break;
+ }
+ mono_mb_emit_ldloc (mb, conv_arg);
+ if (!m_type_is_byref (t)) {
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_op (mb, CEE_MONO_LDNATIVEOBJ, klass);
+ }
+ break;
+
+ case MARSHAL_ACTION_CONV_OUT:
+ if (klass == date_time_class) {
+ /* Convert from an OLE DATE type */
+
+ if (!m_type_is_byref (t))
+ break;
+
+ if (!((t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT))) {
+
+ MONO_STATIC_POINTER_INIT (MonoMethod, from_oadate)
+ 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);
+
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_managed_call (mb, from_oadate, NULL);
+ mono_mb_emit_op (mb, CEE_STOBJ, date_time_class);
+ }
+ break;
+ }
+
+ if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass))
+ break;
+
+ if (m_type_is_byref (t)) {
+ /* dst = argument */
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_stloc (mb, 1);
+
+ mono_mb_emit_ldloc (mb, 1);
+ pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ if (!((t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT))) {
+ /* src = tmp_locals [i] */
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_stloc (mb, 0);
+
+ /* emit valuetype conversion code */
+ mono_marshal_shared_emit_struct_conv (mb, klass, TRUE);
+ }
+ }
+
+ emit_struct_free (mb, klass, conv_arg);
+
+ if (m_type_is_byref (t))
+ mono_mb_patch_branch (mb, pos);
+ break;
+
+ case MARSHAL_ACTION_CONV_RESULT:
+ if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass)) {
+ mono_mb_emit_stloc (mb, 3);
+ break;
+ }
+
+ /* load pointer to returned value type */
+ g_assert (m->vtaddr_var);
+ mono_mb_emit_ldloc (mb, m->vtaddr_var);
+ /* store the address of the source into local variable 0 */
+ mono_mb_emit_stloc (mb, 0);
+ /* set dst_ptr */
+ mono_mb_emit_ldloc_addr (mb, 3);
+ mono_mb_emit_stloc (mb, 1);
+
+ /* emit valuetype conversion code */
+ mono_marshal_shared_emit_struct_conv (mb, klass, TRUE);
+ break;
+
+ case MARSHAL_ACTION_MANAGED_CONV_IN:
+ if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) {
+ conv_arg = 0;
+ break;
+ }
+
+ conv_arg = mono_mb_add_local (mb, m_class_get_byval_arg (klass));
+
+ if (t->attrs & PARAM_ATTRIBUTE_OUT)
+ break;
+
+ if (m_type_is_byref (t))
+ mono_mb_emit_ldarg (mb, argnum);
+ else
+ mono_mb_emit_ldarg_addr (mb, argnum);
+ mono_mb_emit_stloc (mb, 0);
+
+ if (m_type_is_byref (t)) {
+ mono_mb_emit_ldloc (mb, 0);
+ pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
+ }
+
+ mono_mb_emit_ldloc_addr (mb, conv_arg);
+ mono_mb_emit_stloc (mb, 1);
+
+ /* emit valuetype conversion code */
+ mono_marshal_shared_emit_struct_conv (mb, klass, TRUE);
+
+ if (m_type_is_byref (t))
+ mono_mb_patch_branch (mb, pos);
+ break;
+
+ case MARSHAL_ACTION_MANAGED_CONV_OUT:
+ if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass))
+ break;
+ if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_IN) && !(t->attrs & PARAM_ATTRIBUTE_OUT))
+ break;
+
+ /* Check for null */
+ mono_mb_emit_ldarg (mb, argnum);
+ pos2 = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ /* Set src */
+ mono_mb_emit_ldloc_addr (mb, conv_arg);
+ mono_mb_emit_stloc (mb, 0);
+
+ /* Set dest */
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_stloc (mb, 1);
+
+ /* emit valuetype conversion code */
+ mono_marshal_shared_emit_struct_conv (mb, klass, FALSE);
+
+ mono_mb_patch_branch (mb, pos2);
+ break;
+
+ case MARSHAL_ACTION_MANAGED_CONV_RESULT:
+ if (mono_class_is_explicit_layout (klass) || m_class_is_blittable (klass) || m_class_is_enumtype (klass)) {
+ mono_mb_emit_stloc (mb, 3);
+ m->retobj_var = 0;
+ break;
+ }
+
+ /* load pointer to returned value type */
+ g_assert (m->vtaddr_var);
+ mono_mb_emit_ldloc (mb, m->vtaddr_var);
+
+ /* store the address of the source into local variable 0 */
+ mono_mb_emit_stloc (mb, 0);
+ /* allocate space for the native struct and
+ * store the address into dst_ptr */
+ m->retobj_var = mono_mb_add_local (mb, int_type);
+ m->retobj_class = klass;
+ g_assert (m->retobj_var);
+ mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
+ mono_mb_emit_byte (mb, CEE_CONV_I);
+ mono_mb_emit_icall (mb, ves_icall_marshal_alloc);
+ mono_mb_emit_stloc (mb, 1);
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_stloc (mb, m->retobj_var);
+
+ /* emit valuetype conversion code */
+ mono_marshal_shared_emit_struct_conv (mb, klass, FALSE);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+ return conv_arg;
+}
+
+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)
+ mono_mb_emit_icall (mb, mono_free_bstr);
+ else
+ mono_mb_emit_icall (mb, mono_marshal_free);
+}
+
+static int
+emit_marshal_string_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec,
+ int conv_arg, MonoType **conv_arg_type,
+ MarshalAction action)
+{
+ MonoMethodBuilder *mb = m->mb;
+ MonoMarshalNative encoding = mono_marshal_get_string_encoding (m->piinfo, spec);
+ MonoMarshalConv conv = mono_marshal_get_string_to_ptr_conv (m->piinfo, spec);
+ gboolean need_free;
+
+ MonoType *int_type = mono_get_int_type ();
+ MonoType *object_type = mono_get_object_type ();
+ switch (action) {
+ case MARSHAL_ACTION_CONV_IN:
+ *conv_arg_type = int_type;
+ conv_arg = mono_mb_add_local (mb, int_type);
+
+ if (m_type_is_byref (t)) {
+ if (t->attrs & PARAM_ATTRIBUTE_OUT)
+ break;
+
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ } else {
+ mono_mb_emit_ldarg (mb, argnum);
+ }
+
+ if (conv == MONO_MARSHAL_CONV_INVALID) {
+ char *msg = g_strdup_printf ("string marshalling conversion %d not implemented", encoding);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ } else {
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL));
+
+ mono_mb_emit_stloc (mb, conv_arg);
+ }
+ break;
+
+ case MARSHAL_ACTION_CONV_OUT:
+ 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_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ break;
+ }
+
+ if (encoding == MONO_NATIVE_VBBYREFSTR) {
+
+ if (!m_type_is_byref (t)) {
+ char *msg = g_strdup ("VBByRefStr marshalling requires a ref parameter.");
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ break;
+ }
+
+ MONO_STATIC_POINTER_INIT (MonoMethod, method)
+
+ method = mono_marshal_shared_get_method_nofail (mono_defaults.string_class, "get_Length", -1, 0);
+
+ MONO_STATIC_POINTER_INIT_END (MonoMethod, method)
+
+ /*
+ * Have to allocate a new string with the same length as the original, and
+ * copy the contents of the buffer pointed to by CONV_ARG into it.
+ */
+ g_assert (m_type_is_byref (t));
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_managed_call (mb, method, NULL);
+ mono_mb_emit_icall (mb, mono_string_new_len_wrapper);
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
+ } else if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) {
+ int stind_op;
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, &stind_op));
+ mono_mb_emit_byte (mb, GINT_TO_UINT8 (stind_op));
+ need_free = TRUE;
+ }
+
+ if (need_free) {
+ mono_mb_emit_ldloc (mb, conv_arg);
+ emit_string_free_icall (mb, conv);
+ }
+ break;
+
+ case MARSHAL_ACTION_PUSH:
+ if (m_type_is_byref (t) && encoding != MONO_NATIVE_VBBYREFSTR)
+ mono_mb_emit_ldloc_addr (mb, conv_arg);
+ else
+ mono_mb_emit_ldloc (mb, conv_arg);
+ break;
+
+ case MARSHAL_ACTION_CONV_RESULT:
+ mono_mb_emit_stloc (mb, 0);
+
+ 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_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ break;
+ }
+
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL));
+ mono_mb_emit_stloc (mb, 3);
+
+ /* free the string */
+ mono_mb_emit_ldloc (mb, 0);
+ emit_string_free_icall (mb, conv);
+ break;
+
+ case MARSHAL_ACTION_MANAGED_CONV_IN:
+ conv_arg = mono_mb_add_local (mb, object_type);
+
+ *conv_arg_type = int_type;
+
+ if (m_type_is_byref (t)) {
+ if (t->attrs & PARAM_ATTRIBUTE_OUT)
+ break;
+ }
+
+ 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_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, mono_marshal_shared_conv_to_icall (conv, NULL));
+ mono_mb_emit_stloc (mb, conv_arg);
+ break;
+
+ case MARSHAL_ACTION_MANAGED_CONV_OUT:
+ if (m_type_is_byref (t)) {
+ if (conv_arg) {
+ int stind_op;
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, &stind_op));
+ mono_mb_emit_byte (mb, GINT_TO_UINT8 (stind_op));
+ }
+ }
+ break;
+
+ case MARSHAL_ACTION_MANAGED_CONV_RESULT:
+ 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, mono_marshal_shared_conv_to_icall (conv, NULL));
+ mono_mb_emit_stloc (mb, 3);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+ return conv_arg;
+}
+
+static int
+emit_marshal_safehandle_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec, int conv_arg,
+ MonoType **conv_arg_type, MarshalAction action)
+{
+ MonoMethodBuilder *mb = m->mb;
+ MonoType *int_type = mono_get_int_type ();
+ MonoType *boolean_type = m_class_get_byval_arg (mono_defaults.boolean_class);
+
+ switch (action){
+ case MARSHAL_ACTION_CONV_IN: {
+ int dar_release_slot, pos;
+
+ conv_arg = mono_mb_add_local (mb, int_type);
+ *conv_arg_type = int_type;
+
+ 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);
+ mono_mb_emit_exception (mb, "ArgumentNullException", NULL);
+
+ mono_mb_patch_branch (mb, pos);
+
+ /* Create local to hold the ref parameter to DangerousAddRef */
+ dar_release_slot = mono_mb_add_local (mb, boolean_type);
+
+ /* set release = false; */
+ mono_mb_emit_icon (mb, 0);
+ mono_mb_emit_stloc (mb, dar_release_slot);
+
+ if (m_type_is_byref (t)) {
+ int old_handle_value_slot = mono_mb_add_local (mb, int_type);
+
+ if (!mono_marshal_shared_is_in (t)) {
+ mono_mb_emit_icon (mb, 0);
+ mono_mb_emit_stloc (mb, conv_arg);
+ } else {
+ /* safehandle.DangerousAddRef (ref release) */
+ 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, *mono_marshal_shared_get_sh_dangerous_add_ref(), NULL);
+
+ /* Pull the handle field from SafeHandle */
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle));
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_byte (mb, CEE_DUP);
+ mono_mb_emit_stloc (mb, conv_arg);
+ mono_mb_emit_stloc (mb, old_handle_value_slot);
+ }
+ } else {
+ /* 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, *mono_marshal_shared_get_sh_dangerous_add_ref(), NULL);
+
+ /* Pull the handle field from SafeHandle */
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle));
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ mono_mb_emit_stloc (mb, conv_arg);
+ }
+
+ break;
+ }
+
+ case MARSHAL_ACTION_PUSH:
+ if (m_type_is_byref (t))
+ mono_mb_emit_ldloc_addr (mb, conv_arg);
+ else
+ mono_mb_emit_ldloc (mb, conv_arg);
+ break;
+
+ case MARSHAL_ACTION_CONV_OUT: {
+ /* The slot for the boolean is the next temporary created after conv_arg, see the CONV_IN code */
+ int dar_release_slot = conv_arg + 1;
+ int label_next = 0;
+
+ 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 (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, *mono_marshal_shared_get_sh_dangerous_release (), NULL);
+ mono_mb_patch_branch (mb, label_next);
+ }
+
+ if (mono_marshal_shared_is_out (t)) {
+ ERROR_DECL (local_error);
+ MonoMethod *ctor;
+
+ /*
+ * If the SafeHandle was marshalled on input we can skip the marshalling on
+ * output if the handle value is identical.
+ */
+ 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);
+ label_next = mono_mb_emit_branch (mb, CEE_BEQ);
+ }
+
+ /*
+ * Create an empty SafeHandle (of correct derived type).
+ *
+ * FIXME: If an out-of-memory situation or exception happens here we will
+ * leak the handle. We should move the allocation of the SafeHandle to the
+ * input marshalling code to prevent that.
+ */
+ ctor = mono_class_get_method_from_name_checked (t->data.klass, ".ctor", 0, 0, local_error);
+ if (ctor == NULL || !is_ok (local_error)){
+ mono_mb_emit_exception (mb, "MissingMethodException", "parameterless constructor required");
+ mono_error_cleanup (local_error);
+ break;
+ }
+
+ /* refval = new SafeHandleDerived ()*/
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_op (mb, CEE_NEWOBJ, ctor);
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
+
+ /* refval.handle = returned_handle */
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_byte (mb, CEE_LDIND_REF);
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle));
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_byte (mb, CEE_STIND_I);
+
+ if (mono_marshal_shared_is_in (t) && label_next) {
+ mono_mb_patch_branch (mb, label_next);
+ }
+ }
+ } else {
+ 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, *mono_marshal_shared_get_sh_dangerous_release (), NULL);
+ mono_mb_patch_branch (mb, label_next);
+ }
+ break;
+ }
+
+ case MARSHAL_ACTION_CONV_RESULT: {
+ ERROR_DECL (error);
+ MonoMethod *ctor = NULL;
+ int intptr_handle_slot;
+
+ if (mono_class_is_abstract (t->data.klass)) {
+ mono_mb_emit_byte (mb, CEE_POP);
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, g_strdup ("Returned SafeHandles should not be abstract"));
+ break;
+ }
+
+ ctor = mono_class_get_method_from_name_checked (t->data.klass, ".ctor", 0, 0, error);
+ if (ctor == NULL || !is_ok (error)){
+ mono_error_cleanup (error);
+ mono_mb_emit_byte (mb, CEE_POP);
+ mono_mb_emit_exception (mb, "MissingMethodException", "parameterless constructor required");
+ break;
+ }
+ /* Store the IntPtr results into a local */
+ intptr_handle_slot = mono_mb_add_local (mb, int_type);
+ mono_mb_emit_stloc (mb, intptr_handle_slot);
+
+ /* Create return value */
+ mono_mb_emit_op (mb, CEE_NEWOBJ, ctor);
+ mono_mb_emit_stloc (mb, 3);
+
+ /* Set the return.handle to the value, am using ldflda, not sure if thats a good idea */
+ mono_mb_emit_ldloc (mb, 3);
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoSafeHandle, handle));
+ mono_mb_emit_ldloc (mb, intptr_handle_slot);
+ mono_mb_emit_byte (mb, CEE_STIND_I);
+ break;
+ }
+
+ case MARSHAL_ACTION_MANAGED_CONV_IN:
+ fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_IN\n");
+ break;
+
+ case MARSHAL_ACTION_MANAGED_CONV_OUT:
+ fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_OUT\n");
+ break;
+
+ case MARSHAL_ACTION_MANAGED_CONV_RESULT:
+ fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_RESULT\n");
+ break;
+ default:
+ printf ("Unhandled case for MarshalAction: %d\n", action);
+ }
+ return conv_arg;
+}
+
+static int
+emit_marshal_handleref_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec, int conv_arg,
+ MonoType **conv_arg_type, MarshalAction action)
+{
+ MonoMethodBuilder *mb = m->mb;
+
+ MonoType *int_type = mono_get_int_type ();
+ switch (action){
+ case MARSHAL_ACTION_CONV_IN: {
+ conv_arg = mono_mb_add_local (mb, int_type);
+ *conv_arg_type = int_type;
+
+ if (m_type_is_byref (t)) {
+ char *msg = g_strdup ("HandleRefs can not be returned from unmanaged code (or passed by ref)");
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ break;
+ }
+ mono_mb_emit_ldarg_addr (mb, argnum);
+ 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_stloc (mb, conv_arg);
+ break;
+ }
+
+ case MARSHAL_ACTION_PUSH:
+ mono_mb_emit_ldloc (mb, conv_arg);
+ break;
+
+ case MARSHAL_ACTION_CONV_OUT: {
+ /* no resource release required */
+ break;
+ }
+
+ case MARSHAL_ACTION_CONV_RESULT: {
+ char *msg = g_strdup ("HandleRefs can not be returned from unmanaged code (or passed by ref)");
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ break;
+ }
+
+ case MARSHAL_ACTION_MANAGED_CONV_IN:
+ fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_IN\n");
+ break;
+
+ case MARSHAL_ACTION_MANAGED_CONV_OUT:
+ fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_OUT\n");
+ break;
+
+ case MARSHAL_ACTION_MANAGED_CONV_RESULT:
+ fprintf (stderr, "mono/marshal: SafeHandles missing MANAGED_CONV_RESULT\n");
+ break;
+ default:
+ fprintf (stderr, "Unhandled case for MarshalAction: %d\n", action);
+ }
+ return conv_arg;
+}
+
+static int
+emit_marshal_object_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec,
+ int conv_arg, MonoType **conv_arg_type,
+ MarshalAction action)
+{
+ MonoMethodBuilder *mb = m->mb;
+ MonoClass *klass = mono_class_from_mono_type_internal (t);
+ int pos, pos2, loc;
+
+ MonoType *int_type = mono_get_int_type ();
+ switch (action) {
+ case MARSHAL_ACTION_CONV_IN:
+ *conv_arg_type = int_type;
+ conv_arg = mono_mb_add_local (mb, int_type);
+
+ m->orig_conv_args [argnum] = 0;
+
+ 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_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ break;
+ }
+
+ if (m_class_is_delegate (klass)) {
+ 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_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, 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 ()) {
+ MonoMarshalNative encoding = mono_marshal_get_string_encoding (m->piinfo, spec);
+ MonoMarshalConv conv = mono_marshal_get_stringbuilder_to_ptr_conv (m->piinfo, spec);
+
+#if 0
+ 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_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ }
+ break;
+ }
+#endif
+
+ if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && (t->attrs & PARAM_ATTRIBUTE_OUT))
+ break;
+
+ if (conv == MONO_MARSHAL_CONV_INVALID) {
+ char *msg = g_strdup_printf ("stringbuilder marshalling conversion %d not implemented", encoding);
+ 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, 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);
+ mono_mb_emit_stloc (mb, conv_arg);
+
+ mono_mb_emit_ldarg (mb, argnum);
+ pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject));
+ mono_mb_emit_stloc (mb, conv_arg);
+
+ mono_mb_patch_branch (mb, pos);
+ break;
+ } else {
+ mono_mb_emit_byte (mb, CEE_LDNULL);
+ mono_mb_emit_stloc (mb, conv_arg);
+
+ if (m_type_is_byref (t)) {
+ /* we dont need any conversions for out parameters */
+ if (t->attrs & PARAM_ATTRIBUTE_OUT)
+ break;
+
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+
+ } else {
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
+ }
+
+ /* store the address of the source into local variable 0 */
+ mono_mb_emit_stloc (mb, 0);
+ mono_mb_emit_ldloc (mb, 0);
+ pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ /* allocate space for the native struct and store the address */
+ mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
+ mono_mb_emit_byte (mb, CEE_PREFIX1);
+ mono_mb_emit_byte (mb, CEE_LOCALLOC);
+ mono_mb_emit_stloc (mb, conv_arg);
+
+ if (m_type_is_byref (t)) {
+ /* Need to store the original buffer so we can free it later */
+ m->orig_conv_args [argnum] = mono_mb_add_local (mb, int_type);
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_stloc (mb, m->orig_conv_args [argnum]);
+ }
+
+ /* set the src_ptr */
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject));
+ mono_mb_emit_stloc (mb, 0);
+
+ /* set dst_ptr */
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_stloc (mb, 1);
+
+ /* emit valuetype conversion code */
+ mono_marshal_shared_emit_struct_conv (mb, klass, FALSE);
+
+ mono_mb_patch_branch (mb, pos);
+ }
+ break;
+
+ case MARSHAL_ACTION_CONV_OUT:
+ if (klass == mono_class_try_get_stringbuilder_class ()) {
+ gboolean need_free;
+ MonoMarshalNative encoding;
+ MonoMarshalConv conv;
+
+ encoding = mono_marshal_get_string_encoding (m->piinfo, spec);
+ conv = mono_marshal_get_ptr_to_stringbuilder_conv (m->piinfo, spec, &need_free);
+
+ g_assert (encoding != -1);
+
+ if (m_type_is_byref (t)) {
+ //g_assert (!(t->attrs & PARAM_ATTRIBUTE_OUT));
+
+ need_free = TRUE;
+
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldloc (mb, conv_arg);
+
+ switch (encoding) {
+ case MONO_NATIVE_LPWSTR:
+ mono_mb_emit_icall (mb, mono_string_utf16_to_builder2);
+ break;
+ case MONO_NATIVE_LPSTR:
+ mono_mb_emit_icall (mb, mono_string_utf8_to_builder2);
+ break;
+ case MONO_NATIVE_UTF8STR:
+ mono_mb_emit_icall (mb, mono_string_utf8_to_builder2);
+ break;
+ default:
+ g_assert_not_reached ();
+ }
+
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
+ } else if (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN)) {
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldloc (mb, conv_arg);
+
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (conv, NULL));
+ }
+
+ if (need_free) {
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_icall (mb, mono_marshal_free);
+ }
+ break;
+ }
+
+ if (m_class_is_delegate (klass)) {
+ if (m_type_is_byref (t)) {
+ mono_mb_emit_ldarg (mb, argnum);
+ 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, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL));
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
+ }
+ break;
+ }
+
+ if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT)) {
+ /* allocate a new object */
+ mono_mb_emit_ldarg (mb, argnum);
+ 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);
+ }
+
+ /* dst = *argument */
+ mono_mb_emit_ldarg (mb, argnum);
+
+ if (m_type_is_byref (t))
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+
+ mono_mb_emit_stloc (mb, 1);
+
+ mono_mb_emit_ldloc (mb, 1);
+ pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ if (m_type_is_byref (t) || (t->attrs & PARAM_ATTRIBUTE_OUT)) {
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_icon (mb, MONO_ABI_SIZEOF (MonoObject));
+ mono_mb_emit_byte (mb, CEE_ADD);
+ mono_mb_emit_stloc (mb, 1);
+
+ /* src = tmp_locals [i] */
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_stloc (mb, 0);
+
+ /* emit valuetype conversion code */
+ mono_marshal_shared_emit_struct_conv (mb, klass, TRUE);
+
+ /* Free the structure returned by the native code */
+ emit_struct_free (mb, klass, conv_arg);
+
+ if (m->orig_conv_args [argnum]) {
+ /*
+ * If the native function changed the pointer, then free
+ * the original structure plus the new pointer.
+ */
+ mono_mb_emit_ldloc (mb, m->orig_conv_args [argnum]);
+ mono_mb_emit_ldloc (mb, conv_arg);
+ pos2 = mono_mb_emit_branch (mb, CEE_BEQ);
+
+ if (!(t->attrs & PARAM_ATTRIBUTE_OUT)) {
+ g_assert (m->orig_conv_args [argnum]);
+
+ emit_struct_free (mb, klass, m->orig_conv_args [argnum]);
+ }
+
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_icall (mb, mono_marshal_free);
+
+ mono_mb_patch_branch (mb, pos2);
+ }
+ }
+ else
+ /* Free the original structure passed to native code */
+ emit_struct_free (mb, klass, conv_arg);
+
+ mono_mb_patch_branch (mb, pos);
+ break;
+
+ case MARSHAL_ACTION_PUSH:
+ if (m_type_is_byref (t))
+ mono_mb_emit_ldloc_addr (mb, conv_arg);
+ else
+ mono_mb_emit_ldloc (mb, conv_arg);
+ break;
+
+ case MARSHAL_ACTION_CONV_RESULT:
+ if (m_class_is_delegate (klass)) {
+ g_assert (!m_type_is_byref (t));
+ mono_mb_emit_stloc (mb, 0);
+ 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, 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_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ } else {
+ /* set src */
+ mono_mb_emit_stloc (mb, 0);
+
+ /* Make a copy since emit_conv modifies local 0 */
+ loc = mono_mb_add_local (mb, int_type);
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_stloc (mb, loc);
+
+ mono_mb_emit_byte (mb, CEE_LDNULL);
+ mono_mb_emit_stloc (mb, 3);
+
+ mono_mb_emit_ldloc (mb, 0);
+ pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ /* allocate result object */
+
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_op (mb, CEE_MONO_NEWOBJ, klass);
+ mono_mb_emit_stloc (mb, 3);
+
+ /* set dst */
+
+ mono_mb_emit_ldloc (mb, 3);
+ mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject));
+ mono_mb_emit_stloc (mb, 1);
+
+ /* emit conversion code */
+ mono_marshal_shared_emit_struct_conv (mb, klass, TRUE);
+
+ emit_struct_free (mb, klass, loc);
+
+ /* Free the pointer allocated by unmanaged code */
+ mono_mb_emit_ldloc (mb, loc);
+ mono_mb_emit_icall (mb, mono_marshal_free);
+ mono_mb_patch_branch (mb, pos);
+ }
+ break;
+
+ case MARSHAL_ACTION_MANAGED_CONV_IN:
+ conv_arg = mono_mb_add_local (mb, m_class_get_byval_arg (klass));
+
+ if (m_class_is_delegate (klass)) {
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_op (mb, CEE_MONO_CLASSCONST, klass);
+ 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, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_FTN_DEL, NULL));
+ mono_mb_emit_stloc (mb, conv_arg);
+ break;
+ }
+
+ if (klass == mono_class_try_get_stringbuilder_class ()) {
+ MonoMarshalNative encoding;
+
+ encoding = mono_marshal_get_string_encoding (m->piinfo, spec);
+
+ // FIXME:
+ g_assert (encoding == MONO_NATIVE_LPSTR || encoding == MONO_NATIVE_UTF8STR);
+
+ g_assert (!m_type_is_byref (t));
+ g_assert (encoding != -1);
+
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_icall (mb, mono_string_utf8_to_builder2);
+ mono_mb_emit_stloc (mb, conv_arg);
+ break;
+ }
+
+ /* The class can not have an automatic layout */
+ if (mono_class_is_auto_layout (klass)) {
+ mono_mb_emit_auto_layout_exception (mb, klass);
+ break;
+ }
+
+ if (t->attrs & PARAM_ATTRIBUTE_OUT) {
+ mono_mb_emit_byte (mb, CEE_LDNULL);
+ mono_mb_emit_stloc (mb, conv_arg);
+ break;
+ }
+
+ /* Set src */
+ mono_mb_emit_ldarg (mb, argnum);
+ if (m_type_is_byref (t)) {
+ /* Check for NULL and raise an exception */
+ pos2 = mono_mb_emit_branch (mb, CEE_BRTRUE);
+
+ mono_mb_emit_exception (mb, "ArgumentNullException", NULL);
+
+ mono_mb_patch_branch (mb, pos2);
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_byte (mb, CEE_LDIND_I);
+ }
+
+ mono_mb_emit_stloc (mb, 0);
+
+ mono_mb_emit_byte (mb, CEE_LDC_I4_0);
+ mono_mb_emit_stloc (mb, conv_arg);
+
+ mono_mb_emit_ldloc (mb, 0);
+ pos = mono_mb_emit_branch (mb, CEE_BRFALSE);
+
+ /* Create and set dst */
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_op (mb, CEE_MONO_NEWOBJ, klass);
+ mono_mb_emit_stloc (mb, conv_arg);
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject));
+ mono_mb_emit_stloc (mb, 1);
+
+ /* emit valuetype conversion code */
+ mono_marshal_shared_emit_struct_conv (mb, klass, TRUE);
+
+ mono_mb_patch_branch (mb, pos);
+ break;
+
+ case MARSHAL_ACTION_MANAGED_CONV_OUT:
+ if (m_class_is_delegate (klass)) {
+ if (m_type_is_byref (t)) {
+ int stind_op;
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_icall_id (mb, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, &stind_op));
+ mono_mb_emit_byte (mb, GINT_TO_UINT8 (stind_op));
+ break;
+ }
+ }
+
+ if (m_type_is_byref (t)) {
+ /* Check for null */
+ mono_mb_emit_ldloc (mb, conv_arg);
+ pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_byte (mb, CEE_LDC_I4_0);
+ mono_mb_emit_byte (mb, CEE_STIND_I);
+ pos2 = mono_mb_emit_branch (mb, CEE_BR);
+
+ mono_mb_patch_branch (mb, pos);
+
+ /* Set src */
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject));
+ mono_mb_emit_stloc (mb, 0);
+
+ /* Allocate and set dest */
+ mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
+ mono_mb_emit_byte (mb, CEE_CONV_I);
+ mono_mb_emit_icall (mb, ves_icall_marshal_alloc);
+ mono_mb_emit_stloc (mb, 1);
+
+ /* Update argument pointer */
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldloc (mb, 1);
+ mono_mb_emit_byte (mb, CEE_STIND_I);
+
+ /* emit valuetype conversion code */
+ mono_marshal_shared_emit_struct_conv (mb, klass, FALSE);
+
+ mono_mb_patch_branch (mb, pos2);
+ } else if (klass == mono_class_try_get_stringbuilder_class ()) {
+ // FIXME: What to do here ?
+ } else {
+ /* byval [Out] marshalling */
+
+ /* FIXME: Handle null */
+
+ /* Set src */
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject));
+ mono_mb_emit_stloc (mb, 0);
+
+ /* Set dest */
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_stloc (mb, 1);
+
+ /* emit valuetype conversion code */
+ 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, mono_marshal_shared_conv_to_icall (MONO_MARSHAL_CONV_DEL_FTN, NULL));
+ mono_mb_emit_stloc (mb, 3);
+ break;
+ }
+
+ /* The class can not have an automatic layout */
+ if (mono_class_is_auto_layout (klass)) {
+ mono_mb_emit_auto_layout_exception (mb, klass);
+ break;
+ }
+
+ mono_mb_emit_stloc (mb, 0);
+ /* Check for null */
+ mono_mb_emit_ldloc (mb, 0);
+ pos = mono_mb_emit_branch (mb, CEE_BRTRUE);
+ mono_mb_emit_byte (mb, CEE_LDNULL);
+ mono_mb_emit_stloc (mb, 3);
+ pos2 = mono_mb_emit_branch (mb, CEE_BR);
+
+ mono_mb_patch_branch (mb, pos);
+
+ /* Set src */
+ mono_mb_emit_ldloc (mb, 0);
+ mono_mb_emit_ldflda (mb, MONO_ABI_SIZEOF (MonoObject));
+ mono_mb_emit_stloc (mb, 0);
+
+ /* Allocate and set dest */
+ mono_mb_emit_icon (mb, mono_class_native_size (klass, NULL));
+ mono_mb_emit_byte (mb, CEE_CONV_I);
+ mono_mb_emit_icall (mb, ves_icall_marshal_alloc);
+ mono_mb_emit_byte (mb, CEE_DUP);
+ mono_mb_emit_stloc (mb, 1);
+ mono_mb_emit_stloc (mb, 3);
+
+ mono_marshal_shared_emit_struct_conv (mb, klass, FALSE);
+
+ mono_mb_patch_branch (mb, pos2);
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+ return conv_arg;
+}
+
+static int
+emit_marshal_variant_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec,
+ int conv_arg, MonoType **conv_arg_type,
+ MarshalAction action)
+{
+#ifndef DISABLE_COM
+ MonoMethodBuilder *mb = m->mb;
+ MonoType *variant_type = m_class_get_byval_arg (mono_class_get_variant_class ());
+ MonoType *variant_type_byref = mono_class_get_byref_type (mono_class_get_variant_class ());
+ MonoType *object_type = mono_get_object_type ();
+
+ switch (action) {
+ case MARSHAL_ACTION_CONV_IN: {
+ conv_arg = mono_mb_add_local (mb, variant_type);
+
+ if (m_type_is_byref (t))
+ *conv_arg_type = variant_type_byref;
+ else
+ *conv_arg_type = variant_type;
+
+ if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && t->attrs & PARAM_ATTRIBUTE_OUT)
+ break;
+
+ mono_mb_emit_ldarg (mb, argnum);
+ if (m_type_is_byref (t))
+ mono_mb_emit_byte(mb, CEE_LDIND_REF);
+ mono_mb_emit_ldloc_addr (mb, conv_arg);
+ mono_mb_emit_managed_call (mb, mono_get_Marshal_GetNativeVariantForObject (), NULL);
+ break;
+ }
+
+ case MARSHAL_ACTION_CONV_OUT: {
+ if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) {
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_ldloc_addr (mb, conv_arg);
+ mono_mb_emit_managed_call (mb, mono_get_Marshal_GetObjectForNativeVariant (), NULL);
+ mono_mb_emit_byte (mb, CEE_STIND_REF);
+ }
+
+ mono_mb_emit_ldloc_addr (mb, conv_arg);
+ mono_mb_emit_managed_call (mb, mono_get_Variant_Clear (), NULL);
+ break;
+ }
+
+ case MARSHAL_ACTION_PUSH:
+ if (m_type_is_byref (t))
+ mono_mb_emit_ldloc_addr (mb, conv_arg);
+ else
+ mono_mb_emit_ldloc (mb, conv_arg);
+ break;
+
+ case MARSHAL_ACTION_CONV_RESULT: {
+ char *msg = g_strdup ("Marshalling of VARIANT not supported as a return type.");
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ break;
+ }
+
+ case MARSHAL_ACTION_MANAGED_CONV_IN: {
+ conv_arg = mono_mb_add_local (mb, object_type);
+
+ if (m_type_is_byref (t))
+ *conv_arg_type = variant_type_byref;
+ else
+ *conv_arg_type = variant_type;
+
+ if (m_type_is_byref (t) && !(t->attrs & PARAM_ATTRIBUTE_IN) && t->attrs & PARAM_ATTRIBUTE_OUT)
+ break;
+
+ if (m_type_is_byref (t))
+ mono_mb_emit_ldarg (mb, argnum);
+ else
+ mono_mb_emit_ldarg_addr (mb, argnum);
+ mono_mb_emit_managed_call (mb, mono_get_Marshal_GetObjectForNativeVariant (), NULL);
+ mono_mb_emit_stloc (mb, conv_arg);
+ break;
+ }
+
+ case MARSHAL_ACTION_MANAGED_CONV_OUT: {
+ if (m_type_is_byref (t) && (t->attrs & PARAM_ATTRIBUTE_OUT || !(t->attrs & PARAM_ATTRIBUTE_IN))) {
+ mono_mb_emit_ldloc (mb, conv_arg);
+ mono_mb_emit_ldarg (mb, argnum);
+ mono_mb_emit_managed_call (mb, mono_get_Marshal_GetNativeVariantForObject (), NULL);
+ }
+ break;
+ }
+
+ case MARSHAL_ACTION_MANAGED_CONV_RESULT: {
+ char *msg = g_strdup ("Marshalling of VARIANT not supported as a return type.");
+ mono_marshal_shared_mb_emit_exception_marshal_directive (mb, msg);
+ break;
+ }
+
+ default:
+ g_assert_not_reached ();
+ }
+#endif /* DISABLE_COM */
+
+ return conv_arg;
+}
+
+static MonoMarshalIlgenCallbacks *
+get_marshal_cb (void)
+{
+ if (G_UNLIKELY (!ilgen_cb_inited)) {
+#ifdef ENABLE_ILGEN
+ mono_marshal_ilgen_init ();
+#else
+ mono_marshal_noilgen_init_heavyweight ();
+#endif
+ }
+ return &ilgen_marshal_cb;
+}
+
+int
+mono_emit_marshal_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec, int conv_arg,
+ MonoType **conv_arg_type, MarshalAction action, MonoMarshalLightweightCallbacks* lightweigth_cb)
+{
+ if (spec && spec->native == MONO_NATIVE_CUSTOM)
+ return get_marshal_cb ()->emit_marshal_custom (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+
+ if (spec && spec->native == MONO_NATIVE_ASANY)
+ return get_marshal_cb ()->emit_marshal_asany (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+
+ switch (t->type) {
+ case MONO_TYPE_VALUETYPE:
+ if (t->data.klass == mono_class_try_get_handleref_class ())
+ return get_marshal_cb ()->emit_marshal_handleref (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+
+ return get_marshal_cb ()->emit_marshal_vtype (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+ case MONO_TYPE_STRING:
+ return get_marshal_cb ()->emit_marshal_string (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+ case MONO_TYPE_CLASS:
+ case MONO_TYPE_OBJECT:
+#if !defined(DISABLE_COM)
+ if (spec && spec->native == MONO_NATIVE_STRUCT)
+ return get_marshal_cb ()->emit_marshal_variant (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+#endif
+
+#if !defined(DISABLE_COM)
+ if ((spec && (spec->native == MONO_NATIVE_IUNKNOWN ||
+ spec->native == MONO_NATIVE_IDISPATCH ||
+ spec->native == MONO_NATIVE_INTERFACE)) ||
+ (t->type == MONO_TYPE_CLASS && mono_cominterop_is_interface(t->data.klass)))
+ return mono_cominterop_emit_marshal_com_interface (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+ if (spec && (spec->native == MONO_NATIVE_SAFEARRAY) &&
+ (spec->data.safearray_data.elem_type == MONO_VARIANT_VARIANT) &&
+ ((action == MARSHAL_ACTION_CONV_OUT) || (action == MARSHAL_ACTION_CONV_IN) || (action == MARSHAL_ACTION_PUSH)))
+ return mono_cominterop_emit_marshal_safearray (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+#endif
+
+ if (mono_class_try_get_safehandle_class () != NULL && t->data.klass &&
+ mono_class_is_subclass_of_internal (t->data.klass, mono_class_try_get_safehandle_class (), FALSE))
+ return get_marshal_cb ()->emit_marshal_safehandle (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+
+ return get_marshal_cb ()->emit_marshal_object (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+ case MONO_TYPE_ARRAY:
+ case MONO_TYPE_SZARRAY:
+ return get_marshal_cb ()->emit_marshal_array (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+ case MONO_TYPE_BOOLEAN:
+ return get_marshal_cb ()->emit_marshal_boolean (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+ case MONO_TYPE_PTR:
+ return get_marshal_cb ()->emit_marshal_ptr (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+ case MONO_TYPE_CHAR:
+ return get_marshal_cb ()->emit_marshal_char (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+ case MONO_TYPE_I1:
+ case MONO_TYPE_U1:
+ case MONO_TYPE_I2:
+ case MONO_TYPE_U2:
+ case MONO_TYPE_I4:
+ case MONO_TYPE_U4:
+ case MONO_TYPE_I:
+ case MONO_TYPE_U:
+ case MONO_TYPE_R4:
+ case MONO_TYPE_R8:
+ case MONO_TYPE_I8:
+ case MONO_TYPE_U8:
+ case MONO_TYPE_FNPTR:
+ return lightweigth_cb->emit_marshal_scalar (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+ case MONO_TYPE_GENERICINST:
+ if (mono_type_generic_inst_is_valuetype (t))
+ return get_marshal_cb ()->emit_marshal_vtype (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+ else
+ return get_marshal_cb ()->emit_marshal_object (m, argnum, t, spec, conv_arg, conv_arg_type, action);
+ default:
+ return conv_arg;
+ }
+}
+
+void
+mono_marshal_ilgen_init (void)
+{
+ MonoMarshalIlgenCallbacks cb;
+ cb.version = MONO_MARSHAL_CALLBACKS_VERSION;
+ cb.emit_marshal_array = emit_marshal_array_ilgen;
+ cb.emit_marshal_ptr = emit_marshal_ptr_ilgen;
+ cb.emit_marshal_char = emit_marshal_char_ilgen;
+ cb.emit_marshal_vtype = emit_marshal_vtype_ilgen;
+ cb.emit_marshal_string = emit_marshal_string_ilgen;
+ cb.emit_marshal_variant = emit_marshal_variant_ilgen;
+ cb.emit_marshal_safehandle = emit_marshal_safehandle_ilgen;
+ cb.emit_marshal_object = emit_marshal_object_ilgen;
+ cb.emit_marshal_boolean = emit_marshal_boolean_ilgen;
+ cb.emit_marshal_custom = emit_marshal_custom_ilgen;
+ cb.emit_marshal_asany = emit_marshal_asany_ilgen;
+ cb.emit_marshal_handleref = emit_marshal_handleref_ilgen;
+
+#ifdef DISABLE_NONBLITTABLE
+ mono_marshal_noilgen_init_blittable (&cb);
+#endif
+ mono_install_marshal_callbacks_ilgen (&cb);
+}
+
+
diff --git a/src/mono/mono/component/marshal-ilgen.h b/src/mono/mono/metadata/marshal-ilgen.h
index 08768a37448..1b3914588fb 100644
--- a/src/mono/mono/component/marshal-ilgen.h
+++ b/src/mono/mono/metadata/marshal-ilgen.h
@@ -1,24 +1,9 @@
-/**
- * \file
- * Copyright 2022 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
+
#ifndef __MARSHAL_ILGEN_H__
#define __MARSHAL_ILGEN_H__
#include "metadata/marshal-lightweight.h"
#include "metadata/marshal.h"
-#include "mono/component/component.h"
-
-typedef struct MonoComponentMarshalILgen {
- MonoComponent component;
- void (*ilgen_init) (void);
- int (*emit_marshal_ilgen) (EmitMarshalContext *m, int argnum, MonoType *t,
- MonoMarshalSpec *spec, int conv_arg,
- MonoType **conv_arg_type, MarshalAction action, MonoMarshalLightweightCallbacks* lightweigth_cb);
- void (*install_callbacks_mono) (IlgenCallbacksToMono *callbacks);
-
-} MonoComponentMarshalILgen;
typedef struct {
int version;
@@ -34,23 +19,24 @@ typedef struct {
int (*emit_marshal_custom) (EmitMarshalContext *m, int argnum, MonoType *t, MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action);
int (*emit_marshal_asany) (EmitMarshalContext *m, int argnum, MonoType *t, MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action);
int (*emit_marshal_handleref) (EmitMarshalContext *m, int argnum, MonoType *t, MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action);
-} MonoMarshalILgenCallbacks;
-
-MONO_COMPONENT_EXPORT_ENTRYPOINT
-MonoComponentMarshalILgen* mono_component_marshal_ilgen_init (void);
+} MonoMarshalIlgenCallbacks;
void
-mono_install_marshal_callbacks_ilgen (MonoMarshalILgenCallbacks *cb);
+mono_install_marshal_callbacks_ilgen (MonoMarshalIlgenCallbacks *cb);
+
MONO_API void
mono_marshal_ilgen_init (void);
+void
+mono_marshal_noilgen_init_heavyweight (void);
+
+void
+mono_marshal_noilgen_init_lightweight (void);
+
int
mono_emit_marshal_ilgen (EmitMarshalContext *m, int argnum, MonoType *t,
MonoMarshalSpec *spec, int conv_arg,
MonoType **conv_arg_type, MarshalAction action, MonoMarshalLightweightCallbacks* lightweigth_cb);
-void
-mono_marshal_ilgen_install_callbacks_mono (IlgenCallbacksToMono *callbacks);
-
#endif // __MARSHAL_ILGEN_H__ \ No newline at end of file
diff --git a/src/mono/mono/metadata/marshal-lightweight.c b/src/mono/mono/metadata/marshal-lightweight.c
index 0c9a5258063..70a8ee0ede2 100644
--- a/src/mono/mono/metadata/marshal-lightweight.c
+++ b/src/mono/mono/metadata/marshal-lightweight.c
@@ -8,13 +8,14 @@
#include <alloca.h>
#endif
-#include "mono/metadata/method-builder-ilgen.h"
-#include "mono/metadata/method-builder-ilgen-internals.h"
+#include "metadata/method-builder-ilgen.h"
+#include "metadata/method-builder-ilgen-internals.h"
#include <mono/metadata/object.h>
#include <mono/metadata/loader.h>
#include "cil-coff.h"
#include "metadata/marshal.h"
#include "metadata/marshal-internals.h"
+#include "metadata/marshal-ilgen.h"
#include "metadata/marshal-lightweight.h"
#include "metadata/marshal-shared.h"
#include "metadata/tabledefs.h"
@@ -23,7 +24,6 @@
#include "mono/metadata/abi-details.h"
#include "mono/metadata/class-abi-details.h"
#include "mono/metadata/class-init.h"
-#include "mono/metadata/components.h"
#include "mono/metadata/debug-helpers.h"
#include "mono/metadata/threads.h"
#include "mono/metadata/monitor.h"
diff --git a/src/mono/mono/metadata/marshal-lightweight.h b/src/mono/mono/metadata/marshal-lightweight.h
index b25d9cc9f2a..8dfd4803a96 100644
--- a/src/mono/mono/metadata/marshal-lightweight.h
+++ b/src/mono/mono/metadata/marshal-lightweight.h
@@ -5,7 +5,6 @@
*/
#ifndef __MONO_MARSHAL_LIGHTWEIGHT_H__
#define __MONO_MARSHAL_LIGHTWEIGHT_H__
-#include <mono/utils/mono-publib.h>
MONO_API void
mono_marshal_lightweight_init (void);
diff --git a/src/mono/mono/metadata/marshal-noilgen.c b/src/mono/mono/metadata/marshal-noilgen.c
index 8d6f75981cd..ae073fcaf7f 100644
--- a/src/mono/mono/metadata/marshal-noilgen.c
+++ b/src/mono/mono/metadata/marshal-noilgen.c
@@ -1,13 +1,38 @@
#include "config.h"
+
#include <mono/metadata/attrdefs.h>
-#include <mono/metadata/marshal-internals.h>
-#include <mono/metadata/marshal.h>
-#include <mono/metadata/marshal-noilgen.h>
+#include "metadata/marshal-internals.h"
+#include "metadata/marshal.h"
+#include "metadata/marshal-ilgen.h"
#include "utils/mono-compiler.h"
#ifndef ENABLE_ILGEN
+static int
+emit_marshal_array_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec,
+ int conv_arg, MonoType **conv_arg_type,
+ MarshalAction action)
+{
+ MonoType *int_type = mono_get_int_type ();
+ MonoType *object_type = mono_get_object_type ();
+ switch (action) {
+ case MARSHAL_ACTION_CONV_IN:
+ *conv_arg_type = object_type;
+ break;
+ case MARSHAL_ACTION_MANAGED_CONV_IN:
+ *conv_arg_type = int_type;
+ break;
+ }
+ return conv_arg;
+}
-
+static int
+emit_marshal_ptr_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec, int conv_arg,
+ MonoType **conv_arg_type, MarshalAction action)
+{
+ return conv_arg;
+}
static int
emit_marshal_scalar_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
@@ -18,6 +43,136 @@ emit_marshal_scalar_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
}
#endif
+#if !defined(ENABLE_ILGEN) || defined(DISABLE_NONBLITTABLE)
+static int
+emit_marshal_boolean_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec,
+ int conv_arg, MonoType **conv_arg_type,
+ MarshalAction action)
+{
+ MonoType *int_type = mono_get_int_type ();
+ switch (action) {
+ case MARSHAL_ACTION_CONV_IN:
+ if (m_type_is_byref (t))
+ *conv_arg_type = int_type;
+ else
+ *conv_arg_type = mono_marshal_boolean_conv_in_get_local_type (spec, NULL);
+ break;
+
+ case MARSHAL_ACTION_MANAGED_CONV_IN: {
+ MonoClass* conv_arg_class = mono_marshal_boolean_managed_conv_in_get_conv_arg_class (spec, NULL);
+ if (m_type_is_byref (t))
+ *conv_arg_type = m_class_get_this_arg (conv_arg_class);
+ else
+ *conv_arg_type = m_class_get_byval_arg (conv_arg_class);
+ break;
+ }
+
+ }
+ return conv_arg;
+}
+
+static int
+emit_marshal_char_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec, int conv_arg,
+ MonoType **conv_arg_type, MarshalAction action)
+{
+ return conv_arg;
+}
+
+static int
+emit_marshal_custom_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec,
+ int conv_arg, MonoType **conv_arg_type,
+ MarshalAction action)
+{
+ MonoType *int_type = mono_get_int_type ();
+ if (action == MARSHAL_ACTION_CONV_IN && t->type == MONO_TYPE_VALUETYPE)
+ *conv_arg_type = int_type;
+ return conv_arg;
+}
+
+static int
+emit_marshal_asany_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec,
+ int conv_arg, MonoType **conv_arg_type,
+ MarshalAction action)
+{
+ return conv_arg;
+}
+
+static int
+emit_marshal_vtype_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec,
+ int conv_arg, MonoType **conv_arg_type,
+ MarshalAction action)
+{
+ return conv_arg;
+}
+
+static int
+emit_marshal_string_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec,
+ int conv_arg, MonoType **conv_arg_type,
+ MarshalAction action)
+{
+ MonoType *int_type = mono_get_int_type ();
+ switch (action) {
+ case MARSHAL_ACTION_CONV_IN:
+ *conv_arg_type = int_type;
+ break;
+ case MARSHAL_ACTION_MANAGED_CONV_IN:
+ *conv_arg_type = int_type;
+ break;
+ }
+ return conv_arg;
+}
+
+static int
+emit_marshal_safehandle_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec, int conv_arg,
+ MonoType **conv_arg_type, MarshalAction action)
+{
+ MonoType *int_type = mono_get_int_type ();
+ if (action == MARSHAL_ACTION_CONV_IN)
+ *conv_arg_type = int_type;
+ return conv_arg;
+}
+
+
+static int
+emit_marshal_handleref_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec, int conv_arg,
+ MonoType **conv_arg_type, MarshalAction action)
+{
+ MonoType *int_type = mono_get_int_type ();
+ if (action == MARSHAL_ACTION_CONV_IN)
+ *conv_arg_type = int_type;
+ return conv_arg;
+}
+
+static int
+emit_marshal_object_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec,
+ int conv_arg, MonoType **conv_arg_type,
+ MarshalAction action)
+{
+ MonoType *int_type = mono_get_int_type ();
+ if (action == MARSHAL_ACTION_CONV_IN)
+ *conv_arg_type = int_type;
+ return conv_arg;
+}
+
+static int
+emit_marshal_variant_noilgen (EmitMarshalContext *m, int argnum, MonoType *t,
+ MonoMarshalSpec *spec,
+ int conv_arg, MonoType **conv_arg_type,
+ MarshalAction action)
+{
+ g_assert_not_reached ();
+}
+#endif
+
#ifndef ENABLE_ILGEN
static void
emit_managed_wrapper_noilgen (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, MonoGCHandle target_handle, MonoError *error)
@@ -251,13 +406,38 @@ mono_marshal_noilgen_init_lightweight (void)
}
+void
+mono_marshal_noilgen_init_heavyweight (void)
+{
+ MonoMarshalIlgenCallbacks ilgen_cb;
+
+ ilgen_cb.version = MONO_MARSHAL_CALLBACKS_VERSION;
+ ilgen_cb.emit_marshal_array = emit_marshal_array_noilgen;
+ ilgen_cb.emit_marshal_vtype = emit_marshal_vtype_noilgen;
+ ilgen_cb.emit_marshal_string = emit_marshal_string_noilgen;
+ ilgen_cb.emit_marshal_safehandle = emit_marshal_safehandle_noilgen;
+ ilgen_cb.emit_marshal_handleref = emit_marshal_handleref_noilgen;
+ ilgen_cb.emit_marshal_object = emit_marshal_object_noilgen;
+ ilgen_cb.emit_marshal_variant = emit_marshal_variant_noilgen;
+ ilgen_cb.emit_marshal_asany = emit_marshal_asany_noilgen;
+ ilgen_cb.emit_marshal_boolean = emit_marshal_boolean_noilgen;
+ ilgen_cb.emit_marshal_custom = emit_marshal_custom_noilgen;
+ ilgen_cb.emit_marshal_ptr = emit_marshal_ptr_noilgen;
+
+ ilgen_cb.emit_marshal_char = emit_marshal_char_noilgen;
+ mono_install_marshal_callbacks_ilgen(&ilgen_cb);
+}
+
#else
void
mono_marshal_noilgen_init_lightweight (void)
{
}
-
+void
+mono_marshal_noilgen_init_heavyweight (void)
+{
+}
#endif
#ifdef DISABLE_NONBLITTABLE
diff --git a/src/mono/mono/metadata/marshal-noilgen.h b/src/mono/mono/metadata/marshal-noilgen.h
deleted file mode 100644
index c9cafee09fb..00000000000
--- a/src/mono/mono/metadata/marshal-noilgen.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/**
- * \file
- * Copyright 2022 Microsoft
- * Licensed under the MIT license. See LICENSE file in the project root for full license information.
- */
-#ifndef __MARSHAL_NOILGEN_H__
-#define __MARSHAL_NOILGEN_H__
-
-void
-mono_marshal_noilgen_init_lightweight (void);
-
-void
-mono_marshal_noilgen_init_heavyweight (void);
-
-#endif // __MARSHAL_NOILGEN_H__ \ No newline at end of file
diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c
index 47b1a66a979..6caac8e640b 100644
--- a/src/mono/mono/metadata/marshal.c
+++ b/src/mono/mono/metadata/marshal.c
@@ -32,7 +32,7 @@ MONO_PRAGMA_WARNING_POP()
#include "cil-coff.h"
#include "metadata/marshal.h"
#include "metadata/marshal-internals.h"
-#include "metadata/marshal-shared.h"
+#include "metadata/marshal-ilgen.h"
#include "metadata/marshal-lightweight.h"
#include "metadata/method-builder.h"
#include "metadata/method-builder-internals.h"
@@ -41,10 +41,8 @@ MONO_PRAGMA_WARNING_POP()
#include <mono/metadata/appdomain.h>
#include "mono/metadata/abi-details.h"
#include "mono/metadata/class-abi-details.h"
-#include "mono/metadata/components.h"
#include "mono/metadata/debug-helpers.h"
#include "mono/metadata/threads.h"
-#include "mono/metadata/marshal-noilgen.h"
#include "mono/metadata/monitor.h"
#include "mono/metadata/class-init.h"
#include "mono/metadata/class-internals.h"
@@ -129,66 +127,6 @@ static GENERATE_TRY_GET_CLASS_WITH_CACHE (unmanaged_callconv_attribute, "System.
static gboolean type_is_blittable (MonoType *type);
-static IlgenCallbacksToMono ilgenCallbacksToMono = {
- &mono_get_object_type,
- &mono_marshal_get_ptr_to_string_conv,
- &mono_class_is_subclass_of_internal,
- &mono_class_native_size,
- &mono_class_try_get_handleref_class,
- &mono_class_try_get_safehandle_class,
- &mono_class_try_get_stringbuilder_class,
- &mono_defaults,
- &mono_marshal_boolean_conv_in_get_local_type,
- &mono_marshal_boolean_managed_conv_in_get_conv_arg_class,
- &mono_marshal_get_ptr_to_stringbuilder_conv,
- &mono_marshal_get_string_encoding,
- &mono_marshal_get_string_to_ptr_conv,
- &mono_marshal_get_stringbuilder_to_ptr_conv,
- &mono_marshal_load_type_info,
- &mono_marshal_shared_conv_to_icall,
- &mono_marshal_shared_emit_marshal_custom_get_instance,
- &mono_marshal_shared_emit_struct_conv,
- &mono_marshal_shared_emit_struct_conv_full,
- &mono_marshal_shared_get_method_nofail,
- &mono_marshal_shared_get_sh_dangerous_add_ref,
- &mono_marshal_shared_get_sh_dangerous_release,
- &mono_marshal_shared_init_safe_handle,
- &mono_marshal_shared_is_in,
- &mono_marshal_shared_is_out,
- &mono_marshal_shared_mb_emit_exception_marshal_directive,
- &mono_mb_add_local,
- &mono_mb_emit_add_to_local,
- &mono_mb_emit_auto_layout_exception,
- &mono_mb_emit_branch,
- &mono_mb_emit_branch_label,
- &mono_mb_emit_byte,
- &mono_mb_emit_exception,
- &mono_mb_emit_exception_full,
- &mono_mb_emit_icall_id,
- &mono_mb_emit_icon,
- &mono_mb_emit_ldarg,
- &mono_mb_emit_ldarg_addr,
- &mono_mb_emit_ldflda,
- &mono_mb_emit_ldloc,
- &mono_mb_emit_ldloc_addr,
- &mono_mb_emit_managed_call,
- &mono_mb_emit_op,
- &mono_mb_emit_stloc,
- &mono_mb_get_label,
- &mono_mb_patch_branch,
- &mono_pinvoke_is_unicode,
- &mono_reflection_type_from_name_checked,
- &mono_memory_barrier,
- &mono_marshal_need_free,
- &mono_get_int_type
-};
-
-IlgenCallbacksToMono*
-mono_marshal_get_mono_callbacks_for_ilgen (void)
-{
- return &ilgenCallbacksToMono;
-}
-
static MonoImage*
get_method_image (MonoMethod *method)
{
@@ -3222,9 +3160,8 @@ mono_emit_marshal (EmitMarshalContext *m, int argnum, MonoType *t,
if (!m->runtime_marshalling_enabled)
return mono_emit_disabled_marshal (m, argnum, t, spec, conv_arg, conv_arg_type, action);
- mono_component_marshal_ilgen()->install_callbacks_mono(mono_marshal_get_mono_callbacks_for_ilgen());
- return mono_component_marshal_ilgen()->emit_marshal_ilgen(m, argnum, t, spec, conv_arg, conv_arg_type, action, get_marshal_cb());
-}
+ return mono_emit_marshal_ilgen(m, argnum, t, spec, conv_arg, conv_arg_type, action, get_marshal_cb());
+}
static void
mono_marshal_set_callconv_for_type(MonoType *type, MonoMethodSignature *csig, gboolean *skip_gc_trans /*out*/)
@@ -6323,6 +6260,7 @@ get_marshal_cb (void)
mono_marshal_noilgen_init_lightweight ();
#endif
}
+
return &marshal_lightweight_cb;
}
diff --git a/src/mono/mono/metadata/marshal.h b/src/mono/mono/metadata/marshal.h
index e4244ad07c7..93aeb28667d 100644
--- a/src/mono/mono/metadata/marshal.h
+++ b/src/mono/mono/metadata/marshal.h
@@ -348,60 +348,6 @@ typedef struct {
int (*emit_marshal_scalar) (EmitMarshalContext *m, int argnum, MonoType *t, MonoMarshalSpec *spec, int conv_arg, MonoType **conv_arg_type, MarshalAction action);
} MonoMarshalLightweightCallbacks;
-typedef struct {
- MonoType* (*get_object_type) (void);
- MonoMarshalConv (*get_ptr_to_string_conv) (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec, gboolean *need_free);
- gboolean (*is_subclass_of_internal) (MonoClass *klass, MonoClass *klassc, gboolean check_interfaces);
- gint32 (*class_native_size) (MonoClass *klass, guint32 *align);
- MonoClass* (*class_try_get_handleref_class) (void);
- MonoClass* (*try_get_safehandle_class) (void);
- MonoClass* (*try_get_stringbuilder_class) (void);
- MonoDefaults* mono_defaults;
- MonoType* (*boolean_conv_in_get_local_type) (MonoMarshalSpec *spec, guint8 *ldc_op /*out*/);
- MonoClass* (*boolean_managed_conv_in_get_conv_arg_class) (MonoMarshalSpec *spec, guint8 *ldop/*out*/);
- MonoMarshalConv (*get_ptr_to_stringbuilder_conv) (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec, gboolean *need_free);
- MonoMarshalNative (*get_string_encoding) (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec);
- MonoMarshalConv (*get_string_to_ptr_conv) (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec);
- MonoMarshalConv (*get_stringbuilder_to_ptr_conv) (MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec);
- MonoMarshalType* (*load_type_info) (MonoClass* klass);
- MonoJitICallId (*conv_to_icall) (MonoMarshalConv conv, int *ind_store_type);
- void (*emit_marshal_custom_get_instance) (MonoMethodBuilder *mb, MonoClass *klass, MonoMarshalSpec *spec);
- void (*emit_struct_conv) (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object);
- void (*emit_struct_conv_full) (MonoMethodBuilder *mb, MonoClass *klass, gboolean to_object, int offset_of_first_child_field, MonoMarshalNative string_encoding);
- MonoMethod* (*get_method_nofail) (MonoClass *klass, const char *method_name, int num_params, int flags);
- MonoMethod** (*get_sh_dangerous_add_ref) (void);
- MonoMethod** (*get_sh_dangerous_release) (void);
- void (*init_safe_handle) (void);
- gboolean (*is_in) (const MonoType *t);
- gboolean (*is_out) (const MonoType *t);
- void (*mb_emit_exception_marshal_directive) (MonoMethodBuilder *mb, char *msg);
- int (*mb_add_local) (MonoMethodBuilder *mb, MonoType *type);
- void (*mb_emit_add_to_local) (MonoMethodBuilder *mb, guint16 local, gint32 incr);
- void (*mb_emit_auto_layout_exception) (MonoMethodBuilder *mb, MonoClass *klass);
- guint32 (*mb_emit_branch) (MonoMethodBuilder *mb, guint8 op);
- void (*mb_emit_branch_label) (MonoMethodBuilder *mb, guint8 op, guint32 label);
- void (*mb_emit_byte) (MonoMethodBuilder *mb, guint8 op);
- void (*mb_emit_exception) (MonoMethodBuilder *mb, const char *exc_name, const char *msg);
- void (*mb_emit_exception_full) (MonoMethodBuilder *mb, const char *exc_nspace, const char *exc_name, const char *msg);
- void (*mb_emit_icall_id) (MonoMethodBuilder *mb, MonoJitICallId jit_icall_id);
- void (*mb_emit_icon) (MonoMethodBuilder *mb, gint32 value);
- void (*mb_emit_ldarg) (MonoMethodBuilder *mb, guint argnum);
- void (*mb_emit_ldarg_addr) (MonoMethodBuilder *mb, guint argnum);
- void (*mb_emit_ldflda) (MonoMethodBuilder *mb, gint32 offset);
- void (*mb_emit_ldloc) (MonoMethodBuilder *mb, guint num);
- void (*mb_emit_ldloc_addr) (MonoMethodBuilder *mb, guint argnum);
- void (*mb_emit_managed_call) (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig);
- void (*mb_emit_op) (MonoMethodBuilder *mb, guint8 op, gpointer data);
- void (*mb_emit_stloc) (MonoMethodBuilder *mb, guint num);
- int (*mb_get_label) (MonoMethodBuilder *mb);
- void (*mb_patch_branch) (MonoMethodBuilder *mb, guint32 pos);
- gboolean (*pinvoke_is_unicode) (MonoMethodPInvoke *piinfo);
- MonoType* (*reflection_type_from_name_checked) (char *name, MonoAssemblyLoadContext *alc, MonoImage *image, MonoError *error);
- void (*memory_barrier) (void);
- gboolean (*need_free) (MonoType *t, MonoMethodPInvoke *piinfo, MonoMarshalSpec *spec);
- MonoType* (*get_int_type) (void);
-} IlgenCallbacksToMono;
-
/*type of the function pointer of methods returned by mono_marshal_get_runtime_invoke*/
typedef MonoObject *(*RuntimeInvokeFunction) (MonoObject *this_obj, void **params, MonoObject **exc, void* compiled_method);
@@ -756,7 +702,4 @@ mono_mb_create_and_cache_full (GHashTable *cache, gpointer key,
MonoMethodBuilder *mb, MonoMethodSignature *sig,
int max_stack, WrapperInfo *info, gboolean *out_found);
-IlgenCallbacksToMono*
-mono_marshal_get_mono_callbacks_for_ilgen (void);
-
#endif /* __MONO_MARSHAL_H__ */
diff --git a/src/mono/mono/mini/CMakeLists.txt b/src/mono/mono/mini/CMakeLists.txt
index 6ef0ebf57b4..9e74fd9e16f 100644
--- a/src/mono/mono/mini/CMakeLists.txt
+++ b/src/mono/mono/mini/CMakeLists.txt
@@ -349,7 +349,7 @@ add_library(monosgen-static STATIC $<TARGET_OBJECTS:monosgen-objects>;$<TARGET_O
target_link_libraries (monosgen-static PRIVATE monoapi)
set_target_properties(monosgen-static PROPERTIES OUTPUT_NAME ${MONO_LIB_NAME})
-if(DISABLE_COMPONENTS OR AOT_COMPONENTS)
+if(DISABLE_COMPONENTS)
# add component fallback stubs into static mono library when components have been disabled.
target_sources(monosgen-static PRIVATE "${mono-components-stub-objects}")
endif()
diff --git a/src/mono/msbuild/android/build/AndroidApp.targets b/src/mono/msbuild/android/build/AndroidApp.targets
index 3d6024763b0..6fd26641cd1 100644
--- a/src/mono/msbuild/android/build/AndroidApp.targets
+++ b/src/mono/msbuild/android/build/AndroidApp.targets
@@ -119,13 +119,8 @@
</ItemGroup>
</Target>
-
<Target Name="_AndroidGenerateAppBundle" DependsOnTargets="_AndroidGenerateRuntimeConfig">
- <PropertyGroup>
- <RuntimeComponents Condition="'$(RuntimeComponents)' == ''" >marshal-ilgen</RuntimeComponents>
- </PropertyGroup>
-
<AndroidAppBuilderTask
RuntimeIdentifier="$(RuntimeIdentifier)"
ProjectName="$(AssemblyName)"
diff --git a/src/mono/msbuild/apple/build/AppleApp.targets b/src/mono/msbuild/apple/build/AppleApp.targets
index 12e1701223f..470a84edecb 100644
--- a/src/mono/msbuild/apple/build/AppleApp.targets
+++ b/src/mono/msbuild/apple/build/AppleApp.targets
@@ -109,15 +109,9 @@
</ItemGroup>
</Target>
-
<Target Name="_AppleGenerateAppBundle" DependsOnTargets="_AppleGenerateRuntimeConfig">
<!-- Run App bundler, it uses AOT libs (if needed), link all native bits, compile simple UI (written in ObjC)
and produce an app bundle (with xcode project) -->
-
- <PropertyGroup>
- <RuntimeComponents Condition="'$(RuntimeComponents)' == ''">marshal-ilgen</RuntimeComponents>
- </PropertyGroup>
-
<AppleAppBuilderTask
TargetOS="$(TargetOS)"
Arch="$(TargetArchitecture)"
diff --git a/src/mono/sample/iOS/Program.csproj b/src/mono/sample/iOS/Program.csproj
index 206d8f02fe8..ec1f84c354d 100644
--- a/src/mono/sample/iOS/Program.csproj
+++ b/src/mono/sample/iOS/Program.csproj
@@ -67,10 +67,6 @@
<Output TaskParameter="CompiledAssemblies" ItemName="BundleAssemblies" />
</MonoAOTCompiler>
- <PropertyGroup>
- <RuntimeComponents Condition="'$(RuntimeComponents)' == ''">marshal-ilgen</RuntimeComponents>
- </PropertyGroup>
-
<AppleAppBuilderTask
TargetOS="$(TargetOS)"
Arch="$(TargetArchitecture)"
diff --git a/src/mono/wasm/build/WasmApp.InTree.props b/src/mono/wasm/build/WasmApp.InTree.props
index 38e99c6a6cb..4949caa40e6 100644
--- a/src/mono/wasm/build/WasmApp.InTree.props
+++ b/src/mono/wasm/build/WasmApp.InTree.props
@@ -18,6 +18,5 @@
<!-- FIXME: This will exclude the diagnostics component if tracing is not on and threads are not on. Which means that if you turn on threading, you will get diagnostics. Is this what we want? -->
<_MonoRuntimeComponentDontLink Include="libmono-component-diagnostics_tracing-static.a" Condition="'$(FeatureWasmPerfTracing)' != 'true' and $(FeatureWasmThreads) != 'true'"/>
<_MonoRuntimeComponentDontLink Include="libmono-component-hot_reload-stub-static.a" />
- <_MonoRuntimeComponentDontLink Include="libmono-component-marshal-ilgen-stub-static.a" />
</ItemGroup>
</Project>
diff --git a/src/mono/wasm/build/WasmApp.Native.targets b/src/mono/wasm/build/WasmApp.Native.targets
index 14070469f0d..dfe3a169d56 100644
--- a/src/mono/wasm/build/WasmApp.Native.targets
+++ b/src/mono/wasm/build/WasmApp.Native.targets
@@ -31,9 +31,6 @@
<ItemGroup Condition="'$(Configuration)' == 'Debug' and '@(_MonoComponent->Count())' == 0">
<_MonoComponent Include="hot_reload;debugger" />
</ItemGroup>
- <ItemGroup>
- <_MonoComponent Include="marshal-ilgen" />
- </ItemGroup>
<Import Project="$(MSBuildThisFileDirectory)EmSdkRepo.Defaults.props" Condition="'$(WasmUseEMSDK_PATH)' == 'true'" />
diff --git a/src/mono/wasm/runtime/CMakeLists.txt b/src/mono/wasm/runtime/CMakeLists.txt
index 76a17f73e0c..c852a7df1df 100644
--- a/src/mono/wasm/runtime/CMakeLists.txt
+++ b/src/mono/wasm/runtime/CMakeLists.txt
@@ -19,7 +19,6 @@ target_link_libraries(dotnet
${MONO_ARTIFACTS_DIR}/libmono-component-hot_reload-static.a
${MONO_ARTIFACTS_DIR}/libmono-component-debugger-static.a
${MONO_ARTIFACTS_DIR}/libmono-component-diagnostics_tracing-stub-static.a
- ${MONO_ARTIFACTS_DIR}/libmono-component-marshal-ilgen-static.a
${MONO_ARTIFACTS_DIR}/libmono-ee-interp.a
${MONO_ARTIFACTS_DIR}/libmonosgen-2.0.a
${MONO_ARTIFACTS_DIR}/libmono-ilgen.a
diff --git a/src/tests/build.proj b/src/tests/build.proj
index e2716558b9d..37236bad271 100644
--- a/src/tests/build.proj
+++ b/src/tests/build.proj
@@ -185,7 +185,7 @@
<AppDir>$(BuildDir)\apk</AppDir>
<FinalApkPath>$(XUnitTestBinBase)$(CategoryWithSlash)\$(Category).apk</FinalApkPath>
<StripDebugSymbols>False</StripDebugSymbols>
- <RuntimeComponents>diagnostics_tracing;marshal-ilgen</RuntimeComponents>
+ <RuntimeComponents>diagnostics_tracing</RuntimeComponents>
<DiagnosticPorts>127.0.0.1:9000,nosuspend,listen</DiagnosticPorts>
<StripDebugSymbols Condition="'$(Configuration)' == 'Release'">True</StripDebugSymbols>
<MicrosoftNetCoreAppRuntimePackDir>$(ArtifactsBinDir)microsoft.netcore.app.runtime.android-$(TargetArchitecture)\$(Configuration)\runtimes\android-$(TargetArchitecture)\</MicrosoftNetCoreAppRuntimePackDir>
@@ -272,7 +272,7 @@
<XUnitWrapperDll>$(CMDDIR_GrandParent)/$(CategoryWithSlash)/$(XUnitWrapperFileName)</XUnitWrapperDll>
<BuildDir>$(IntermediateOutputPath)\iOSApps\$(Category)</BuildDir>
<FinalPath>$(XUnitTestBinBase)$(CategoryWithSlash)\$(Category).app</FinalPath>
- <RuntimeComponents>diagnostics_tracing;marshal-ilgen</RuntimeComponents>
+ <RuntimeComponents>diagnostics_tracing</RuntimeComponents>
</PropertyGroup>
<PropertyGroup>