Added/Updated .gitignore files
[mono.git] / mono / mini / jit-icalls.c
blob2f650cb59b2d5916d4100b37e6c6fb68e4f3a3f3
1 /*
2 * jit-icalls.c: internal calls used by the JIT
4 * Author:
5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
8 * (C) 2002 Ximian, Inc.
9 */
10 #include <config.h>
11 #include <math.h>
12 #include <limits.h>
13 #ifdef HAVE_ALLOCA_H
14 #include <alloca.h>
15 #endif
17 #include "jit-icalls.h"
19 void*
20 mono_ldftn (MonoMethod *method)
22 gpointer addr;
24 MONO_ARCH_SAVE_REGS;
26 addr = mono_create_jump_trampoline (mono_domain_get (), method, FALSE);
28 return mono_create_ftnptr (mono_domain_get (), addr);
31 static void*
32 ldvirtfn_internal (MonoObject *obj, MonoMethod *method, gboolean gshared)
34 MonoMethod *res;
36 MONO_ARCH_SAVE_REGS;
38 if (obj == NULL)
39 mono_raise_exception (mono_get_exception_null_reference ());
41 res = mono_object_get_virtual_method (obj, method);
43 if (gshared && method->is_inflated && mono_method_get_context (method)->method_inst) {
44 MonoGenericContext context = { NULL, NULL };
46 if (res->klass->generic_class)
47 context.class_inst = res->klass->generic_class->context.class_inst;
48 else if (res->klass->generic_container)
49 context.class_inst = res->klass->generic_container->context.class_inst;
50 context.method_inst = mono_method_get_context (method)->method_inst;
52 res = mono_class_inflate_generic_method (res, &context);
55 /* An rgctx wrapper is added by the trampolines no need to do it here */
57 return mono_ldftn (res);
60 void*
61 mono_ldvirtfn (MonoObject *obj, MonoMethod *method)
63 return ldvirtfn_internal (obj, method, FALSE);
66 void*
67 mono_ldvirtfn_gshared (MonoObject *obj, MonoMethod *method)
69 return ldvirtfn_internal (obj, method, TRUE);
72 void
73 mono_helper_stelem_ref_check (MonoArray *array, MonoObject *val)
75 MONO_ARCH_SAVE_REGS;
77 if (val && !mono_object_isinst (val, array->obj.vtable->klass->element_class))
78 mono_raise_exception (mono_get_exception_array_type_mismatch ());
81 #ifndef MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
83 gint64
84 mono_llmult (gint64 a, gint64 b)
86 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
87 return a * b;
90 guint64
91 mono_llmult_ovf_un (guint64 a, guint64 b)
93 guint32 al = a;
94 guint32 ah = a >> 32;
95 guint32 bl = b;
96 guint32 bh = b >> 32;
97 guint64 res, t1;
99 MONO_ARCH_SAVE_REGS;
101 // fixme: this is incredible slow
103 if (ah && bh)
104 goto raise_exception;
106 res = (guint64)al * (guint64)bl;
108 t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
110 if (t1 > 0xffffffff)
111 goto raise_exception;
113 res += ((guint64)t1) << 32;
115 return res;
117 raise_exception:
118 mono_raise_exception (mono_get_exception_overflow ());
119 return 0;
122 guint64
123 mono_llmult_ovf (gint64 a, gint64 b)
125 guint32 al = a;
126 gint32 ah = a >> 32;
127 guint32 bl = b;
128 gint32 bh = b >> 32;
130 Use Karatsuba algorithm where:
131 a*b is: AhBh(R^2+R)+(Ah-Al)(Bl-Bh)R+AlBl(R+1)
132 where Ah is the "high half" (most significant 32 bits) of a and
133 where Al is the "low half" (least significant 32 bits) of a and
134 where Bh is the "high half" of b and Bl is the "low half" and
135 where R is the Radix or "size of the half" (in our case 32 bits)
137 Note, for the product of two 64 bit numbers to fit into a 64
138 result, ah and/or bh must be 0. This will save us from doing
139 the AhBh term at all.
141 Also note that we refactor so that we don't overflow 64 bits with
142 intermediate results. So we use [(Ah-Al)(Bl-Bh)+AlBl]R+AlBl
145 gint64 res, t1;
146 gint32 sign;
148 MONO_ARCH_SAVE_REGS;
150 /* need to work with absoulte values, so find out what the
151 resulting sign will be and convert any negative numbers
152 from two's complement
154 sign = ah ^ bh;
155 if (ah < 0) {
156 if (((guint32)ah == 0x80000000) && (al == 0)) {
157 /* This has no two's complement */
158 if (b == 0)
159 return 0;
160 else if (b == 1)
161 return a;
162 else
163 goto raise_exception;
166 /* flip the bits and add 1 */
167 ah ^= ~0;
168 if (al == 0)
169 ah += 1;
170 else {
171 al ^= ~0;
172 al +=1;
176 if (bh < 0) {
177 if (((guint32)bh == 0x80000000) && (bl == 0)) {
178 /* This has no two's complement */
179 if (a == 0)
180 return 0;
181 else if (a == 1)
182 return b;
183 else
184 goto raise_exception;
187 /* flip the bits and add 1 */
188 bh ^= ~0;
189 if (bl == 0)
190 bh += 1;
191 else {
192 bl ^= ~0;
193 bl +=1;
197 /* we overflow for sure if both upper halves are greater
198 than zero because we would need to shift their
199 product 64 bits to the left and that will not fit
200 in a 64 bit result */
201 if (ah && bh)
202 goto raise_exception;
203 if ((gint64)((gint64)ah * (gint64)bl) > (gint64)0x80000000 || (gint64)((gint64)al * (gint64)bh) > (gint64)0x80000000)
204 goto raise_exception;
206 /* do the AlBl term first */
207 t1 = (gint64)al * (gint64)bl;
209 res = t1;
211 /* now do the [(Ah-Al)(Bl-Bh)+AlBl]R term */
212 t1 += (gint64)(ah - al) * (gint64)(bl - bh);
213 /* check for overflow */
214 t1 <<= 32;
215 if (t1 > (0x7FFFFFFFFFFFFFFFLL - res))
216 goto raise_exception;
218 res += t1;
220 if (res < 0)
221 goto raise_exception;
223 if (sign < 0)
224 return -res;
225 else
226 return res;
228 raise_exception:
229 mono_raise_exception (mono_get_exception_overflow ());
230 return 0;
233 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
235 gint32
236 mono_idiv (gint32 a, gint32 b)
238 MONO_ARCH_SAVE_REGS;
240 #ifdef MONO_ARCH_NEED_DIV_CHECK
241 if (!b)
242 mono_raise_exception (mono_get_exception_divide_by_zero ());
243 else if (b == -1 && a == (0x80000000))
244 mono_raise_exception (mono_get_exception_arithmetic ());
245 #endif
246 return a / b;
249 guint32
250 mono_idiv_un (guint32 a, guint32 b)
252 MONO_ARCH_SAVE_REGS;
254 #ifdef MONO_ARCH_NEED_DIV_CHECK
255 if (!b)
256 mono_raise_exception (mono_get_exception_divide_by_zero ());
257 #endif
258 return a / b;
261 gint32
262 mono_irem (gint32 a, gint32 b)
264 MONO_ARCH_SAVE_REGS;
266 #ifdef MONO_ARCH_NEED_DIV_CHECK
267 if (!b)
268 mono_raise_exception (mono_get_exception_divide_by_zero ());
269 else if (b == -1 && a == (0x80000000))
270 mono_raise_exception (mono_get_exception_arithmetic ());
271 #endif
273 return a % b;
276 guint32
277 mono_irem_un (guint32 a, guint32 b)
279 MONO_ARCH_SAVE_REGS;
281 #ifdef MONO_ARCH_NEED_DIV_CHECK
282 if (!b)
283 mono_raise_exception (mono_get_exception_divide_by_zero ());
284 #endif
285 return a % b;
288 #endif
290 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF)
292 gint32
293 mono_imul (gint32 a, gint32 b)
295 MONO_ARCH_SAVE_REGS;
297 return a * b;
300 gint32
301 mono_imul_ovf (gint32 a, gint32 b)
303 gint64 res;
305 MONO_ARCH_SAVE_REGS;
307 res = (gint64)a * (gint64)b;
309 if ((res > 0x7fffffffL) || (res < -2147483648LL))
310 mono_raise_exception (mono_get_exception_overflow ());
312 return res;
315 gint32
316 mono_imul_ovf_un (guint32 a, guint32 b)
318 guint64 res;
320 MONO_ARCH_SAVE_REGS;
322 res = (guint64)a * (guint64)b;
324 if ((res >> 32))
325 mono_raise_exception (mono_get_exception_overflow ());
327 return res;
329 #endif
331 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT)
332 double
333 mono_fdiv (double a, double b)
335 MONO_ARCH_SAVE_REGS;
337 return a / b;
339 #endif
341 gint64
342 mono_lldiv (gint64 a, gint64 b)
344 MONO_ARCH_SAVE_REGS;
346 #ifdef MONO_ARCH_NEED_DIV_CHECK
347 if (!b)
348 mono_raise_exception (mono_get_exception_divide_by_zero ());
349 else if (b == -1 && a == (-9223372036854775807LL - 1LL))
350 mono_raise_exception (mono_get_exception_arithmetic ());
351 #endif
352 return a / b;
355 gint64
356 mono_llrem (gint64 a, gint64 b)
358 MONO_ARCH_SAVE_REGS;
360 #ifdef MONO_ARCH_NEED_DIV_CHECK
361 if (!b)
362 mono_raise_exception (mono_get_exception_divide_by_zero ());
363 else if (b == -1 && a == (-9223372036854775807LL - 1LL))
364 mono_raise_exception (mono_get_exception_arithmetic ());
365 #endif
366 return a % b;
369 guint64
370 mono_lldiv_un (guint64 a, guint64 b)
372 MONO_ARCH_SAVE_REGS;
374 #ifdef MONO_ARCH_NEED_DIV_CHECK
375 if (!b)
376 mono_raise_exception (mono_get_exception_divide_by_zero ());
377 #endif
378 return a / b;
381 guint64
382 mono_llrem_un (guint64 a, guint64 b)
384 MONO_ARCH_SAVE_REGS;
386 #ifdef MONO_ARCH_NEED_DIV_CHECK
387 if (!b)
388 mono_raise_exception (mono_get_exception_divide_by_zero ());
389 #endif
390 return a % b;
393 #endif
395 #ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
397 guint64
398 mono_lshl (guint64 a, gint32 shamt)
400 guint64 res;
402 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
403 res = a << shamt;
405 /*printf ("TESTL %lld << %d = %lld\n", a, shamt, res);*/
407 return res;
410 guint64
411 mono_lshr_un (guint64 a, gint32 shamt)
413 guint64 res;
415 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
416 res = a >> shamt;
418 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
420 return res;
423 gint64
424 mono_lshr (gint64 a, gint32 shamt)
426 gint64 res;
428 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
429 res = a >> shamt;
431 /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
433 return res;
436 #endif
438 #ifdef MONO_ARCH_SOFT_FLOAT
440 double
441 mono_fsub (double a, double b)
443 return a - b;
446 double
447 mono_fadd (double a, double b)
449 return a + b;
452 double
453 mono_fmul (double a, double b)
455 return a * b;
458 double
459 mono_fneg (double a)
461 return -a;
464 double
465 mono_fconv_r4 (double a)
467 return (float)a;
470 double
471 mono_conv_to_r8 (int a)
473 return (double)a;
476 double
477 mono_conv_to_r4 (int a)
479 return (double)(float)a;
482 gint8
483 mono_fconv_i1 (double a)
485 return (gint8)a;
488 gint16
489 mono_fconv_i2 (double a)
491 return (gint16)a;
494 gint32
495 mono_fconv_i4 (double a)
497 return (gint32)a;
500 guint8
501 mono_fconv_u1 (double a)
503 return (guint8)a;
506 guint16
507 mono_fconv_u2 (double a)
509 return (guint16)a;
512 gboolean
513 mono_fcmp_eq (double a, double b)
515 return a == b;
518 gboolean
519 mono_fcmp_ge (double a, double b)
521 return a >= b;
524 gboolean
525 mono_fcmp_gt (double a, double b)
527 return a > b;
530 gboolean
531 mono_fcmp_le (double a, double b)
533 return a <= b;
536 gboolean
537 mono_fcmp_lt (double a, double b)
539 return a < b;
542 gboolean
543 mono_fcmp_ne_un (double a, double b)
545 return isunordered (a, b) || a != b;
548 gboolean
549 mono_fcmp_ge_un (double a, double b)
551 return isunordered (a, b) || a >= b;
554 gboolean
555 mono_fcmp_gt_un (double a, double b)
557 return isunordered (a, b) || a > b;
560 gboolean
561 mono_fcmp_le_un (double a, double b)
563 return isunordered (a, b) || a <= b;
566 gboolean
567 mono_fcmp_lt_un (double a, double b)
569 return isunordered (a, b) || a < b;
572 gboolean
573 mono_fceq (double a, double b)
575 return a == b;
578 gboolean
579 mono_fcgt (double a, double b)
581 return a > b;
584 gboolean
585 mono_fcgt_un (double a, double b)
587 return isunordered (a, b) || a > b;
590 gboolean
591 mono_fclt (double a, double b)
593 return a < b;
596 gboolean
597 mono_fclt_un (double a, double b)
599 return isunordered (a, b) || a < b;
602 gboolean
603 mono_isfinite (double a)
605 #ifdef HAVE_ISFINITE
606 return isfinite (a);
607 #else
608 g_assert_not_reached ();
609 return TRUE;
610 #endif
613 double
614 mono_fload_r4 (float *ptr)
616 return *ptr;
619 void
620 mono_fstore_r4 (double val, float *ptr)
622 *ptr = (float)val;
625 /* returns the integer bitpattern that is passed in the regs or stack */
626 guint32
627 mono_fload_r4_arg (double val)
629 float v = (float)val;
630 return *(guint32*)&v;
633 #endif
635 MonoArray *
636 mono_array_new_va (MonoMethod *cm, ...)
638 MonoDomain *domain = mono_domain_get ();
639 va_list ap;
640 guint32 *lengths;
641 guint32 *lower_bounds;
642 int pcount;
643 int rank;
644 int i, d;
646 MONO_ARCH_SAVE_REGS;
648 pcount = mono_method_signature (cm)->param_count;
649 rank = cm->klass->rank;
651 va_start (ap, cm);
653 lengths = alloca (sizeof (guint32) * pcount);
654 for (i = 0; i < pcount; ++i)
655 lengths [i] = d = va_arg(ap, int);
657 if (rank == pcount) {
658 /* Only lengths provided. */
659 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
660 lower_bounds = alloca (sizeof (guint32) * rank);
661 memset (lower_bounds, 0, sizeof (guint32) * rank);
662 } else {
663 lower_bounds = NULL;
665 } else {
666 g_assert (pcount == (rank * 2));
667 /* lower bounds are first. */
668 lower_bounds = lengths;
669 lengths += rank;
671 va_end(ap);
673 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
676 /* Specialized version of mono_array_new_va () which avoids varargs */
677 MonoArray *
678 mono_array_new_1 (MonoMethod *cm, guint32 length)
680 MonoDomain *domain = mono_domain_get ();
681 guint32 lengths [1];
682 guint32 *lower_bounds;
683 int pcount;
684 int rank;
686 MONO_ARCH_SAVE_REGS;
688 pcount = mono_method_signature (cm)->param_count;
689 rank = cm->klass->rank;
691 lengths [0] = length;
693 g_assert (rank == pcount);
695 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
696 lower_bounds = alloca (sizeof (guint32) * rank);
697 memset (lower_bounds, 0, sizeof (guint32) * rank);
698 } else {
699 lower_bounds = NULL;
702 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
705 MonoArray *
706 mono_array_new_2 (MonoMethod *cm, guint32 length1, guint32 length2)
708 MonoDomain *domain = mono_domain_get ();
709 guint32 lengths [2];
710 guint32 *lower_bounds;
711 int pcount;
712 int rank;
714 MONO_ARCH_SAVE_REGS;
716 pcount = mono_method_signature (cm)->param_count;
717 rank = cm->klass->rank;
719 lengths [0] = length1;
720 lengths [1] = length2;
722 g_assert (rank == pcount);
724 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
725 lower_bounds = alloca (sizeof (guint32) * rank);
726 memset (lower_bounds, 0, sizeof (guint32) * rank);
727 } else {
728 lower_bounds = NULL;
731 return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
734 gpointer
735 mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
737 MonoVTable *vtable;
738 gpointer addr;
740 MONO_ARCH_SAVE_REGS;
742 //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
744 mono_class_init (field->parent);
746 vtable = mono_class_vtable_full (domain, field->parent, TRUE);
747 if (!vtable->initialized)
748 mono_runtime_class_init (vtable);
750 //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
752 if (domain->special_static_fields && (addr = g_hash_table_lookup (domain->special_static_fields, field)))
753 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
754 else
755 addr = (char*)vtable->data + field->offset;
757 return addr;
760 gpointer
761 mono_ldtoken_wrapper (MonoImage *image, int token, MonoGenericContext *context)
763 MonoClass *handle_class;
764 gpointer res;
766 MONO_ARCH_SAVE_REGS;
767 res = mono_ldtoken (image, token, &handle_class, context);
768 mono_class_init (handle_class);
770 return res;
773 gpointer
774 mono_ldtoken_wrapper_generic_shared (MonoImage *image, int token, MonoMethod *method)
776 MonoMethodSignature *sig = mono_method_signature (method);
777 MonoGenericContext *generic_context;
779 if (sig->is_inflated) {
780 generic_context = mono_method_get_context (method);
781 } else {
782 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
783 g_assert (generic_container);
784 generic_context = &generic_container->context;
787 return mono_ldtoken_wrapper (image, token, generic_context);
790 guint64
791 mono_fconv_u8 (double v)
793 return (guint64)v;
796 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
797 gint64
798 mono_fconv_i8 (double v)
800 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
801 return (gint64)v;
803 #endif
805 guint32
806 mono_fconv_u4 (double v)
808 /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
809 return (guint32)v;
812 #ifndef HAVE_TRUNC
813 /* Solaris doesn't have trunc */
814 #ifdef HAVE_AINTL
815 extern long double aintl (long double);
816 #define trunc aintl
817 #else
818 /* FIXME: This means we will never throw overflow exceptions */
819 #define trunc(v) res
820 #endif
821 #endif /* HAVE_TRUNC */
823 gint64
824 mono_fconv_ovf_i8 (double v)
826 gint64 res;
828 MONO_ARCH_SAVE_REGS;
830 res = (gint64)v;
832 if (isnan(v) || trunc (v) != res) {
833 mono_raise_exception (mono_get_exception_overflow ());
835 return res;
838 guint64
839 mono_fconv_ovf_u8 (double v)
841 guint64 res;
843 MONO_ARCH_SAVE_REGS;
845 * The soft-float implementation of some ARM devices have a buggy guin64 to double
846 * conversion that it looses precision even when the integer if fully representable
847 * as a double.
849 * This was found with 4294967295ull, converting to double and back looses one bit of precision.
851 * To work around this issue we test for value boundaries instead.
853 #if defined(__arm__) && MONO_ARCH_SOFT_FLOAT
854 if (isnan (v) || !(v >= -0.5 && v <= ULLONG_MAX+0.5)) {
855 mono_raise_exception (mono_get_exception_overflow ());
857 res = (guint64)v;
858 #else
859 res = (guint64)v;
860 if (isnan(v) || trunc (v) != res) {
861 mono_raise_exception (mono_get_exception_overflow ());
863 #endif
864 return res;
867 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
868 double
869 mono_lconv_to_r8 (gint64 a)
871 return (double)a;
873 #endif
875 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
876 float
877 mono_lconv_to_r4 (gint64 a)
879 return (float)a;
881 #endif
883 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
884 double
885 mono_conv_to_r8_un (guint32 a)
887 return (double)a;
889 #endif
891 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
892 double
893 mono_lconv_to_r8_un (guint64 a)
895 return (double)a;
897 #endif
899 gpointer
900 mono_helper_compile_generic_method (MonoObject *obj, MonoMethod *method, gpointer *this_arg)
902 MonoMethod *vmethod;
903 gpointer addr;
904 MonoGenericContext *context = mono_method_get_context (method);
906 mono_jit_stats.generic_virtual_invocations++;
908 if (obj == NULL)
909 mono_raise_exception (mono_get_exception_null_reference ());
910 vmethod = mono_object_get_virtual_method (obj, method);
911 g_assert (!vmethod->klass->generic_container);
912 g_assert (!vmethod->klass->generic_class || !vmethod->klass->generic_class->context.class_inst->is_open);
913 g_assert (!context->method_inst || !context->method_inst->is_open);
915 addr = mono_compile_method (vmethod);
917 if (mono_method_needs_static_rgctx_invoke (vmethod, FALSE))
918 addr = mono_create_static_rgctx_trampoline (vmethod, addr);
920 /* Since this is a virtual call, have to unbox vtypes */
921 if (obj->vtable->klass->valuetype)
922 *this_arg = mono_object_unbox (obj);
923 else
924 *this_arg = obj;
926 return addr;
929 MonoString*
930 mono_helper_ldstr (MonoImage *image, guint32 idx)
932 return mono_ldstr (mono_domain_get (), image, idx);
935 MonoString*
936 mono_helper_ldstr_mscorlib (guint32 idx)
938 return mono_ldstr (mono_domain_get (), mono_defaults.corlib, idx);
941 MonoObject*
942 mono_helper_newobj_mscorlib (guint32 idx)
944 MonoClass *klass = mono_class_get (mono_defaults.corlib, MONO_TOKEN_TYPE_DEF | idx);
946 g_assert (klass);
948 return mono_object_new (mono_domain_get (), klass);
952 * On some architectures, gdb doesn't like encountering the cpu breakpoint instructions
953 * in generated code. So instead we emit a call to this function and place a gdb
954 * breakpoint here.
956 void
957 mono_break (void)
961 MonoException *
962 mono_create_corlib_exception_0 (guint32 token)
964 return mono_exception_from_token (mono_defaults.corlib, token);
967 MonoException *
968 mono_create_corlib_exception_1 (guint32 token, MonoString *arg)
970 return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg, NULL);
973 MonoException *
974 mono_create_corlib_exception_2 (guint32 token, MonoString *arg1, MonoString *arg2)
976 return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg1, arg2);
979 MonoObject*
980 mono_object_castclass (MonoObject *obj, MonoClass *klass)
982 if (!obj)
983 return NULL;
985 if (mono_object_isinst (obj, klass))
986 return obj;
988 mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
989 "System", "InvalidCastException"));
991 return NULL;
994 gpointer
995 mono_get_native_calli_wrapper (MonoImage *image, MonoMethodSignature *sig, gpointer func)
997 MonoMarshalSpec **mspecs;
998 MonoMethodPInvoke piinfo;
999 MonoMethod *m;
1001 mspecs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
1002 memset (&piinfo, 0, sizeof (piinfo));
1004 m = mono_marshal_get_native_func_wrapper (image, sig, &piinfo, mspecs, func);
1006 return mono_compile_method (m);