1 #include <emscripten.h>
8 /* Disables AOT mode */
10 /* Enables normal AOT mode, equivalent to mono_jit_set_aot_only (false) */
12 /* Enables hybrid AOT mode, JIT can still be used for wrappers */
14 /* Enables full AOT mode, JIT is disabled and not allowed,
15 * equivalent to mono_jit_set_aot_only (true) */
17 /* Same as full, but use only llvm compiled code */
18 MONO_AOT_MODE_LLVMONLY
,
19 /* Uses Interpreter, JIT is disabled and not allowed,
20 * equivalent to "--full-aot --interpreter" */
22 /* Same as INTERP, but use only llvm compiled code */
23 MONO_AOT_MODE_INTERP_LLVMONLY
,
27 MONO_TYPE_END
= 0x00, /* End of List */
28 MONO_TYPE_VOID
= 0x01,
29 MONO_TYPE_BOOLEAN
= 0x02,
30 MONO_TYPE_CHAR
= 0x03,
41 MONO_TYPE_STRING
= 0x0e,
42 MONO_TYPE_PTR
= 0x0f, /* arg: <type> token */
43 MONO_TYPE_BYREF
= 0x10, /* arg: <type> token */
44 MONO_TYPE_VALUETYPE
= 0x11, /* arg: <type> token */
45 MONO_TYPE_CLASS
= 0x12, /* arg: <type> token */
46 MONO_TYPE_VAR
= 0x13, /* number */
47 MONO_TYPE_ARRAY
= 0x14, /* type, rank, boundsCount, bound1, loCount, lo1 */
48 MONO_TYPE_GENERICINST
= 0x15, /* <type> <type-arg-count> <type-1> \x{2026} <type-n> */
49 MONO_TYPE_TYPEDBYREF
= 0x16,
52 MONO_TYPE_FNPTR
= 0x1b, /* arg: full method signature */
53 MONO_TYPE_OBJECT
= 0x1c,
54 MONO_TYPE_SZARRAY
= 0x1d, /* 0-based one-dim-array */
55 MONO_TYPE_MVAR
= 0x1e, /* number */
56 MONO_TYPE_CMOD_REQD
= 0x1f, /* arg: typedef or typeref token */
57 MONO_TYPE_CMOD_OPT
= 0x20, /* optional arg: typedef or typref token */
58 MONO_TYPE_INTERNAL
= 0x21, /* CLR internal type */
60 MONO_TYPE_MODIFIER
= 0x40, /* Or with the following types */
61 MONO_TYPE_SENTINEL
= 0x41, /* Sentinel for varargs method signature */
62 MONO_TYPE_PINNED
= 0x45, /* Local var that points to pinned object */
64 MONO_TYPE_ENUM
= 0x55 /* an enumeration */
69 MONO_IMAGE_ERROR_ERRNO
,
70 MONO_IMAGE_MISSING_ASSEMBLYREF
,
71 MONO_IMAGE_IMAGE_INVALID
72 } MonoImageOpenStatus
;
74 typedef struct MonoType_ MonoType
;
75 typedef struct MonoDomain_ MonoDomain
;
76 typedef struct MonoAssembly_ MonoAssembly
;
77 typedef struct MonoMethod_ MonoMethod
;
78 typedef struct MonoException_ MonoException
;
79 typedef struct MonoString_ MonoString
;
80 typedef struct MonoClass_ MonoClass
;
81 typedef struct MonoImage_ MonoImage
;
82 typedef struct MonoObject_ MonoObject
;
83 typedef struct MonoArray_ MonoArray
;
84 typedef struct MonoThread_ MonoThread
;
85 typedef struct _MonoAssemblyName MonoAssemblyName
;
89 extern MonoObject
* mono_wasm_invoke_js_with_args (int js_handle
, MonoString
*method
, MonoArray
*args
, int *is_exception
);
90 extern MonoObject
* mono_wasm_get_object_property (int js_handle
, MonoString
*method
, int *is_exception
);
91 extern MonoObject
* mono_wasm_set_object_property (int js_handle
, MonoString
*method
, MonoObject
*value
, int createIfNotExist
, int hasOwnProperty
, int *is_exception
);
92 extern MonoObject
* mono_wasm_get_global_object (MonoString
*globalName
, int *is_exception
);
94 // Blazor specific custom routines - see dotnet_support.js for backing code
95 extern void* mono_wasm_invoke_js_marshalled (MonoString
**exceptionMessage
, void *asyncHandleLongPtr
, MonoString
*funcName
, MonoString
*argsJson
);
96 extern void* mono_wasm_invoke_js_unmarshalled (MonoString
**exceptionMessage
, MonoString
*funcName
, void* arg0
, void* arg1
, void* arg2
);
97 void mono_aot_register_module (void **aot_info
);
98 void mono_jit_set_aot_mode (MonoAotMode mode
);
99 MonoDomain
* mono_jit_init_version (const char *root_domain_name
, const char *runtime_version
);
100 void mono_ee_interp_init (const char *opts
);
101 void mono_marshal_ilgen_init (void);
102 void mono_method_builder_ilgen_init (void);
103 void mono_sgen_mono_ilgen_init (void);
104 void mono_icall_table_init (void);
105 MonoAssembly
* mono_assembly_open (const char *filename
, MonoImageOpenStatus
*status
);
106 int mono_jit_exec (MonoDomain
*domain
, MonoAssembly
*assembly
, int argc
, char *argv
[]);
107 void mono_set_assemblies_path (const char* path
);
108 int monoeg_g_setenv(const char *variable
, const char *value
, int overwrite
);
109 void mono_free (void*);
110 MonoString
* mono_string_new (MonoDomain
*domain
, const char *text
);
111 MonoDomain
* mono_domain_get (void);
112 MonoClass
* mono_class_from_name (MonoImage
*image
, const char* name_space
, const char *name
);
113 MonoMethod
* mono_class_get_method_from_name (MonoClass
*klass
, const char *name
, int param_count
);
114 MonoType
* mono_class_get_type (MonoClass
*klass
);
115 MonoClass
* mono_object_get_class (MonoObject
*obj
);
116 int mono_type_get_type (MonoType
*type
);
117 int mono_type_is_reference (MonoType
*type
);
119 MonoString
* mono_object_to_string (MonoObject
*obj
, MonoObject
**exc
);//FIXME Use MonoError variant
120 char* mono_string_to_utf8 (MonoString
*string_obj
);
121 MonoObject
* mono_runtime_invoke (MonoMethod
*method
, void *obj
, void **params
, MonoObject
**exc
);
122 void* mono_object_unbox (MonoObject
*obj
);
124 MonoImage
* mono_assembly_get_image (MonoAssembly
*assembly
);
125 MonoAssembly
* mono_assembly_load (MonoAssemblyName
*aname
, const char *basedir
, MonoImageOpenStatus
*status
);
127 MonoAssemblyName
* mono_assembly_name_new (const char *name
);
128 void mono_assembly_name_free (MonoAssemblyName
*aname
);
129 const char* mono_image_get_name (MonoImage
*image
);
130 MonoString
* mono_string_new (MonoDomain
*domain
, const char *text
);
131 void mono_add_internal_call (const char *name
, const void* method
);
132 MonoString
* mono_string_from_utf16 (char *data
);
133 MonoString
* mono_string_new (MonoDomain
*domain
, const char *text
);
134 void mono_wasm_enable_debugging (void);
135 MonoArray
* mono_array_new (MonoDomain
*domain
, MonoClass
*eclass
, int n
);
136 MonoClass
* mono_get_object_class (void);
137 int mono_class_is_delegate (MonoClass
* klass
);
138 const char* mono_class_get_name (MonoClass
*klass
);
139 const char* mono_class_get_namespace (MonoClass
*klass
);
140 MonoClass
* mono_get_byte_class (void);
141 MonoClass
* mono_get_sbyte_class (void);
142 MonoClass
* mono_get_int16_class (void);
143 MonoClass
* mono_get_uint16_class (void);
144 MonoClass
* mono_get_int32_class (void);
145 MonoClass
* mono_get_uint32_class (void);
146 MonoClass
* mono_get_single_class (void);
147 MonoClass
* mono_get_double_class (void);
148 MonoClass
* mono_class_get_element_class(MonoClass
*klass
);
149 int mono_regression_test_step (int verbose_level
, char *image
, char *method_name
);
152 #define mono_array_get(array,type,index) ( *(type*)mono_array_addr ((array), type, (index)) )
153 #define mono_array_addr(array,type,index) ((type*)(void*) mono_array_addr_with_size (array, sizeof (type), index))
154 #define mono_array_setref(array,index,value) \
156 void **__p = (void **) mono_array_addr ((array), void*, (index)); \
157 mono_gc_wbarrier_set_arrayref ((array), __p, (MonoObject*)(value)); \
158 /* *__p = (value);*/ \
162 char* mono_array_addr_with_size (MonoArray
*array
, int size
, int idx
);
163 int mono_array_length (MonoArray
*array
);
164 int mono_array_element_size(MonoClass
*klass
);
165 void mono_gc_wbarrier_set_arrayref (MonoArray
*arr
, void* slot_ptr
, MonoObject
* value
);
169 const unsigned char *data
;
171 } MonoBundledAssembly
;
173 void mono_register_bundled_assemblies (const MonoBundledAssembly
**assemblies
);
176 m_strdup (const char *str
)
181 int len
= strlen (str
) + 1;
182 char *res
= malloc (len
);
183 memcpy (res
, str
, len
);
187 static MonoDomain
*root_domain
;
190 mono_wasm_invoke_js (MonoString
*str
, int *is_exception
)
195 char *native_val
= mono_string_to_utf8 (str
);
196 char *native_res
= (char*)EM_ASM_INT ({
197 var str
= UTF8ToString ($
0);
199 var res
= eval (str
);
200 if (res
=== null
|| res
== undefined
)
202 res
= res
.toString ();
203 setValue ($
1, 0, "i32");
206 setValue ($
1, 1, "i32");
207 if (res
=== null
|| res
=== undefined
)
208 res
= "unknown exception";
210 var buff
= Module
._malloc((res
.length
+ 1) * 2);
211 stringToUTF16 (res
, buff
, (res
.length
+ 1) * 2);
213 }, (int)native_val
, is_exception
);
215 mono_free (native_val
);
217 if (native_res
== NULL
)
220 MonoString
*res
= mono_string_from_utf16 (native_res
);
226 #include "driver-gen.c"
229 typedef struct WasmAssembly_ WasmAssembly
;
231 struct WasmAssembly_
{
232 MonoBundledAssembly assembly
;
236 static WasmAssembly
*assemblies
;
237 static int assembly_count
;
239 EMSCRIPTEN_KEEPALIVE
void
240 mono_wasm_add_assembly (const char *name
, const unsigned char *data
, unsigned int size
)
242 WasmAssembly
*entry
= (WasmAssembly
*)malloc(sizeof (MonoBundledAssembly
));
243 entry
->assembly
.name
= m_strdup (name
);
244 entry
->assembly
.data
= data
;
245 entry
->assembly
.size
= size
;
246 entry
->next
= assemblies
;
251 EMSCRIPTEN_KEEPALIVE
void
252 mono_wasm_load_runtime (const char *managed_path
, int enable_debugging
)
254 monoeg_g_setenv ("MONO_LOG_LEVEL", "debug", 1);
255 monoeg_g_setenv ("MONO_LOG_MASK", "gc", 1);
258 // Defined in driver-gen.c
259 register_aot_modules ();
260 mono_jit_set_aot_mode (MONO_AOT_MODE_LLVMONLY
);
262 mono_jit_set_aot_mode (MONO_AOT_MODE_INTERP_LLVMONLY
);
263 if (enable_debugging
)
264 mono_wasm_enable_debugging ();
268 mono_ee_interp_init ("");
269 mono_marshal_ilgen_init ();
270 mono_method_builder_ilgen_init ();
271 mono_sgen_mono_ilgen_init ();
273 mono_icall_table_init ();
275 if (assembly_count
) {
276 MonoBundledAssembly
**bundle_array
= (MonoBundledAssembly
**)calloc (1, sizeof (MonoBundledAssembly
*) * (assembly_count
+ 1));
277 WasmAssembly
*cur
= assemblies
;
278 bundle_array
[assembly_count
] = NULL
;
281 bundle_array
[i
] = &cur
->assembly
;
285 mono_register_bundled_assemblies ((const MonoBundledAssembly
**)bundle_array
);
288 mono_set_assemblies_path (m_strdup (managed_path
));
289 root_domain
= mono_jit_init_version ("mono", "v4.0.30319");
291 mono_add_internal_call ("WebAssembly.Runtime::InvokeJS", mono_wasm_invoke_js
);
292 mono_add_internal_call ("WebAssembly.Runtime::InvokeJSWithArgs", mono_wasm_invoke_js_with_args
);
293 mono_add_internal_call ("WebAssembly.Runtime::GetObjectProperty", mono_wasm_get_object_property
);
294 mono_add_internal_call ("WebAssembly.Runtime::SetObjectProperty", mono_wasm_set_object_property
);
295 mono_add_internal_call ("WebAssembly.Runtime::GetGlobalObject", mono_wasm_get_global_object
);
297 // Blazor specific custom routines - see dotnet_support.js for backing code
298 mono_add_internal_call ("WebAssembly.JSInterop.InternalCalls::InvokeJSMarshalled", mono_wasm_invoke_js_marshalled
);
299 mono_add_internal_call ("WebAssembly.JSInterop.InternalCalls::InvokeJSUnmarshalled", mono_wasm_invoke_js_unmarshalled
);
303 EMSCRIPTEN_KEEPALIVE MonoAssembly
*
304 mono_wasm_assembly_load (const char *name
)
306 MonoImageOpenStatus status
;
307 MonoAssemblyName
* aname
= mono_assembly_name_new (name
);
311 MonoAssembly
*res
= mono_assembly_load (aname
, NULL
, &status
);
312 mono_assembly_name_free (aname
);
317 EMSCRIPTEN_KEEPALIVE MonoClass
*
318 mono_wasm_assembly_find_class (MonoAssembly
*assembly
, const char *namespace, const char *name
)
320 return mono_class_from_name (mono_assembly_get_image (assembly
), namespace, name
);
323 EMSCRIPTEN_KEEPALIVE MonoMethod
*
324 mono_wasm_assembly_find_method (MonoClass
*klass
, const char *name
, int arguments
)
326 return mono_class_get_method_from_name (klass
, name
, arguments
);
329 EMSCRIPTEN_KEEPALIVE MonoObject
*
330 mono_wasm_invoke_method (MonoMethod
*method
, MonoObject
*this_arg
, void *params
[], int* got_exception
)
332 MonoObject
*exc
= NULL
;
333 MonoObject
*res
= mono_runtime_invoke (method
, this_arg
, params
, &exc
);
339 MonoObject
*exc2
= NULL
;
340 res
= (MonoObject
*)mono_object_to_string (exc
, &exc2
);
342 res
= (MonoObject
*) mono_string_new (root_domain
, "Exception Double Fault");
349 EMSCRIPTEN_KEEPALIVE
char *
350 mono_wasm_string_get_utf8 (MonoString
*str
)
352 return mono_string_to_utf8 (str
); //XXX JS is responsible for freeing this
355 EMSCRIPTEN_KEEPALIVE MonoString
*
356 mono_wasm_string_from_js (const char *str
)
358 return mono_string_new (root_domain
, str
);
363 class_is_task (MonoClass
*klass
)
365 if (!strcmp ("System.Threading.Tasks", mono_class_get_namespace (klass
)) &&
366 (!strcmp ("Task", mono_class_get_name (klass
)) || !strcmp ("Task`1", mono_class_get_name (klass
))))
372 #define MARSHAL_TYPE_INT 1
373 #define MARSHAL_TYPE_FP 2
374 #define MARSHAL_TYPE_STRING 3
375 #define MARSHAL_TYPE_VT 4
376 #define MARSHAL_TYPE_DELEGATE 5
377 #define MARSHAL_TYPE_TASK 6
378 #define MARSHAL_TYPE_OBJECT 7
379 #define MARSHAL_TYPE_BOOL 8
381 // typed array marshalling
382 #define MARSHAL_ARRAY_BYTE 11
383 #define MARSHAL_ARRAY_UBYTE 12
384 #define MARSHAL_ARRAY_SHORT 13
385 #define MARSHAL_ARRAY_USHORT 14
386 #define MARSHAL_ARRAY_INT 15
387 #define MARSHAL_ARRAY_UINT 16
388 #define MARSHAL_ARRAY_FLOAT 17
389 #define MARSHAL_ARRAY_DOUBLE 18
391 EMSCRIPTEN_KEEPALIVE
int
392 mono_wasm_get_obj_type (MonoObject
*obj
)
396 MonoClass
*klass
= mono_object_get_class (obj
);
397 MonoType
*type
= mono_class_get_type (klass
);
399 switch (mono_type_get_type (type
)) {
400 // case MONO_TYPE_CHAR: prob should be done not as a number?
401 case MONO_TYPE_BOOLEAN
:
402 return MARSHAL_TYPE_BOOL
;
411 return MARSHAL_TYPE_INT
;
414 return MARSHAL_TYPE_FP
;
415 case MONO_TYPE_STRING
:
416 return MARSHAL_TYPE_STRING
;
417 case MONO_TYPE_SZARRAY
: { // simple zero based one-dim-array
418 MonoClass
*eklass
= mono_class_get_element_class(klass
);
419 MonoType
*etype
= mono_class_get_type (eklass
);
421 switch (mono_type_get_type (etype
)) {
423 return MARSHAL_ARRAY_UBYTE
;
425 return MARSHAL_ARRAY_BYTE
;
427 return MARSHAL_ARRAY_USHORT
;
429 return MARSHAL_ARRAY_SHORT
;
431 return MARSHAL_ARRAY_UINT
;
433 return MARSHAL_ARRAY_INT
;
435 return MARSHAL_ARRAY_FLOAT
;
437 return MARSHAL_ARRAY_DOUBLE
;
439 return MARSHAL_TYPE_OBJECT
;
443 if (!mono_type_is_reference (type
)) //vt
444 return MARSHAL_TYPE_VT
;
445 if (mono_class_is_delegate (klass
))
446 return MARSHAL_TYPE_DELEGATE
;
447 if (class_is_task(klass
))
448 return MARSHAL_TYPE_TASK
;
450 return MARSHAL_TYPE_OBJECT
;
455 EMSCRIPTEN_KEEPALIVE
int
456 mono_unbox_int (MonoObject
*obj
)
460 MonoType
*type
= mono_class_get_type (mono_object_get_class(obj
));
462 void *ptr
= mono_object_unbox (obj
);
463 switch (mono_type_get_type (type
)) {
465 case MONO_TYPE_BOOLEAN
:
466 return *(signed char*)ptr
;
468 return *(unsigned char*)ptr
;
472 return *(unsigned short*)ptr
;
476 return *(unsigned int*)ptr
;
477 // WASM doesn't support returning longs to JS
478 // case MONO_TYPE_I8:
479 // case MONO_TYPE_U8:
481 printf ("Invalid type %d to mono_unbox_int\n", mono_type_get_type (type
));
486 EMSCRIPTEN_KEEPALIVE
double
487 mono_wasm_unbox_float (MonoObject
*obj
)
491 MonoType
*type
= mono_class_get_type (mono_object_get_class(obj
));
493 void *ptr
= mono_object_unbox (obj
);
494 switch (mono_type_get_type (type
)) {
498 return *(double*)ptr
;
500 printf ("Invalid type %d to mono_wasm_unbox_float\n", mono_type_get_type (type
));
505 EMSCRIPTEN_KEEPALIVE
int
506 mono_wasm_array_length (MonoArray
*array
)
508 return mono_array_length (array
);
511 EMSCRIPTEN_KEEPALIVE MonoObject
*
512 mono_wasm_array_get (MonoArray
*array
, int idx
)
514 return mono_array_get (array
, MonoObject
*, idx
);
517 EMSCRIPTEN_KEEPALIVE MonoArray
*
518 mono_wasm_obj_array_new (int size
)
520 return mono_array_new (root_domain
, mono_get_object_class (), size
);
523 EMSCRIPTEN_KEEPALIVE
void
524 mono_wasm_obj_array_set (MonoArray
*array
, int idx
, MonoObject
*obj
)
526 mono_array_setref (array
, idx
, obj
);
529 // Int8Array | int8_t | byte or SByte (signed byte)
530 // Uint8Array | uint8_t | byte or Byte (unsigned byte)
531 // Uint8ClampedArray| uint8_t | byte or Byte (unsigned byte)
532 // Int16Array | int16_t | short (signed short)
533 // Uint16Array | uint16_t | ushort (unsigned short)
534 // Int32Array | int32_t | int (signed integer)
535 // Uint32Array | uint32_t | uint (unsigned integer)
536 // Float32Array | float | float
537 // Float64Array | double | double
539 EMSCRIPTEN_KEEPALIVE MonoArray
*
540 mono_wasm_typed_array_new (char *arr
, int length
, int size
, int type
)
542 MonoClass
*typeClass
= mono_get_byte_class(); // default is Byte
544 case MARSHAL_ARRAY_BYTE
:
545 typeClass
= mono_get_sbyte_class();
547 case MARSHAL_ARRAY_SHORT
:
548 typeClass
= mono_get_int16_class();
550 case MARSHAL_ARRAY_USHORT
:
551 typeClass
= mono_get_uint16_class();
553 case MARSHAL_ARRAY_INT
:
554 typeClass
= mono_get_int32_class();
556 case MARSHAL_ARRAY_UINT
:
557 typeClass
= mono_get_uint32_class();
559 case MARSHAL_ARRAY_FLOAT
:
560 typeClass
= mono_get_single_class();
562 case MARSHAL_ARRAY_DOUBLE
:
563 typeClass
= mono_get_double_class();
569 buffer
= mono_array_new (root_domain
, typeClass
, length
);
570 memcpy(mono_array_addr_with_size(buffer
, sizeof(char), 0), arr
, length
* size
);
576 EMSCRIPTEN_KEEPALIVE
void
577 mono_wasm_array_to_heap (MonoArray
*src
, char *dest
)
583 element_size
= mono_array_element_size ( mono_object_get_class((MonoObject
*)src
));
584 //DBG("mono_wasm_to_heap element size %i / length %i\n",element_size, mono_array_length(src));
586 // get our src address
587 source_addr
= mono_array_addr_with_size (src
, element_size
, 0);
588 // copy the array memory to heap via ptr dest
589 memcpy (dest
, source_addr
, mono_array_length(src
) * element_size
);
592 EMSCRIPTEN_KEEPALIVE
int
593 mono_wasm_exec_regression (int verbose_level
, char *image
)
595 return mono_regression_test_step (verbose_level
, image
, NULL
) ? 0 : 1;