Merge pull request #2770 from lambdageek/dev/monoerror-object_isinst_mbyref
[mono.git] / mono / mini / jit-icalls.c
1 /*
2  * jit-icalls.c: internal calls used by the JIT
3  *
4  * Author:
5  *   Dietmar Maurer (dietmar@ximian.com)
6  *   Paolo Molaro (lupus@ximian.com)
7  *
8  * (C) 2002 Ximian, Inc.
9  * Copyright 2003-2011 Novell Inc (http://www.novell.com)
10  * Copyright 2011 Xamarin Inc (http://www.xamarin.com)
11  */
12 #include <config.h>
13 #include <math.h>
14 #include <limits.h>
15 #ifdef HAVE_ALLOCA_H
16 #include <alloca.h>
17 #endif
18
19 #include "jit-icalls.h"
20 #include <mono/utils/mono-error-internals.h>
21 #include <mono/metadata/threads-types.h>
22 #include <mono/metadata/reflection-internals.h>
23
24 #ifdef ENABLE_LLVM
25 #include "mini-llvm-cpp.h"
26 #endif
27
28 void*
29 mono_ldftn (MonoMethod *method)
30 {
31         gpointer addr;
32         MonoError error;
33
34         if (mono_llvm_only) {
35                 // FIXME: No error handling
36
37                 addr = mono_compile_method (method);
38                 g_assert (addr);
39
40                 if (mono_method_needs_static_rgctx_invoke (method, FALSE))
41                         /* The caller doesn't pass it */
42                         g_assert_not_reached ();
43
44                 addr = mini_add_method_trampoline (method, addr, mono_method_needs_static_rgctx_invoke (method, FALSE), FALSE);
45                 return addr;
46         }
47
48         addr = mono_create_jump_trampoline (mono_domain_get (), method, FALSE, &error);
49         if (!mono_error_ok (&error)) {
50                 mono_error_set_pending_exception (&error);
51                 return NULL;
52         }
53         return mono_create_ftnptr (mono_domain_get (), addr);
54 }
55
56 static void*
57 ldvirtfn_internal (MonoObject *obj, MonoMethod *method, gboolean gshared)
58 {
59         MonoError error;
60         MonoMethod *res;
61
62         if (obj == NULL) {
63                 mono_set_pending_exception (mono_get_exception_null_reference ());
64                 return NULL;
65         }
66
67         res = mono_object_get_virtual_method (obj, method);
68
69         if (gshared && method->is_inflated && mono_method_get_context (method)->method_inst) {
70                 MonoGenericContext context = { NULL, NULL };
71
72                 if (res->klass->generic_class)
73                         context.class_inst = res->klass->generic_class->context.class_inst;
74                 else if (res->klass->generic_container)
75                         context.class_inst = res->klass->generic_container->context.class_inst;
76                 context.method_inst = mono_method_get_context (method)->method_inst;
77
78                 res = mono_class_inflate_generic_method_checked (res, &context, &error);
79                 if (!mono_error_ok (&error)) {
80                         mono_error_set_pending_exception (&error);
81                         return NULL;
82                 }
83         }
84
85         /* An rgctx wrapper is added by the trampolines no need to do it here */
86
87         return mono_ldftn (res);
88 }
89
90 void*
91 mono_ldvirtfn (MonoObject *obj, MonoMethod *method) 
92 {
93         return ldvirtfn_internal (obj, method, FALSE);
94 }
95
96 void*
97 mono_ldvirtfn_gshared (MonoObject *obj, MonoMethod *method) 
98 {
99         return ldvirtfn_internal (obj, method, TRUE);
100 }
101
102 void
103 mono_helper_stelem_ref_check (MonoArray *array, MonoObject *val)
104 {
105         MonoError error;
106         if (!array) {
107                 mono_set_pending_exception (mono_get_exception_null_reference ());
108                 return;
109         }
110         if (val && !mono_object_isinst_checked (val, array->obj.vtable->klass->element_class, &error)) {
111                 if (mono_error_set_pending_exception (&error))
112                         return;
113                 mono_set_pending_exception (mono_get_exception_array_type_mismatch ());
114                 return;
115         }
116 }
117
118 #if !defined(MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS) || defined(MONO_ARCH_EMULATE_LONG_MUL_OVF_OPTS)
119
120 gint64 
121 mono_llmult (gint64 a, gint64 b)
122 {
123         return a * b;
124 }
125
126 guint64  
127 mono_llmult_ovf_un (guint64 a, guint64 b)
128 {
129         guint32 al = a;
130         guint32 ah = a >> 32;
131         guint32 bl = b;
132         guint32 bh = b >> 32; 
133         guint64 res, t1;
134
135         // fixme: this is incredible slow
136
137         if (ah && bh)
138                 goto raise_exception;
139
140         res = (guint64)al * (guint64)bl;
141
142         t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
143
144         if (t1 > 0xffffffff)
145                 goto raise_exception;
146
147         res += ((guint64)t1) << 32; 
148
149         return res;
150
151  raise_exception:
152         mono_set_pending_exception (mono_get_exception_overflow ());
153         return 0;
154 }
155
156 guint64  
157 mono_llmult_ovf (gint64 a, gint64 b) 
158 {
159         guint32 al = a;
160         gint32 ah = a >> 32;
161         guint32 bl = b;
162         gint32 bh = b >> 32; 
163         /*
164         Use Karatsuba algorithm where:
165                 a*b is: AhBh(R^2+R)+(Ah-Al)(Bl-Bh)R+AlBl(R+1)
166                 where Ah is the "high half" (most significant 32 bits) of a and
167                 where Al is the "low half" (least significant 32 bits) of a and
168                 where  Bh is the "high half" of b and Bl is the "low half" and
169                 where R is the Radix or "size of the half" (in our case 32 bits)
170
171         Note, for the product of two 64 bit numbers to fit into a 64
172         result, ah and/or bh must be 0.  This will save us from doing
173         the AhBh term at all.
174
175         Also note that we refactor so that we don't overflow 64 bits with 
176         intermediate results. So we use [(Ah-Al)(Bl-Bh)+AlBl]R+AlBl
177         */
178
179         gint64 res, t1;
180         gint32 sign;
181
182         /* need to work with absoulte values, so find out what the
183            resulting sign will be and convert any negative numbers
184            from two's complement
185         */
186         sign = ah ^ bh;
187         if (ah < 0) {
188                 if (((guint32)ah == 0x80000000) && (al == 0)) {
189                         /* This has no two's complement */
190                         if (b == 0)
191                                 return 0;
192                         else if (b == 1)
193                                 return a;
194                         else
195                                 goto raise_exception;
196                 }
197
198                 /* flip the bits and add 1 */
199                 ah ^= ~0;
200                 if (al ==  0)
201                         ah += 1;
202                 else {
203                         al ^= ~0;
204                         al +=1;
205                 }
206         }
207
208         if (bh < 0) {
209                 if (((guint32)bh == 0x80000000) && (bl == 0)) {
210                         /* This has no two's complement */
211                         if (a == 0)
212                                 return 0;
213                         else if (a == 1)
214                                 return b;
215                         else
216                                 goto raise_exception;
217                 }
218
219                 /* flip the bits and add 1 */
220                 bh ^= ~0;
221                 if (bl ==  0)
222                         bh += 1;
223                 else {
224                         bl ^= ~0;
225                         bl +=1;
226                 }
227         }
228                 
229         /* we overflow for sure if both upper halves are greater 
230            than zero because we would need to shift their 
231            product 64 bits to the left and that will not fit
232            in a 64 bit result */
233         if (ah && bh)
234                 goto raise_exception;
235         if ((gint64)((gint64)ah * (gint64)bl) > (gint64)0x80000000 || (gint64)((gint64)al * (gint64)bh) > (gint64)0x80000000)
236                 goto raise_exception;
237
238         /* do the AlBl term first */
239         t1 = (gint64)al * (gint64)bl;
240
241         res = t1;
242
243         /* now do the [(Ah-Al)(Bl-Bh)+AlBl]R term */
244         t1 += (gint64)(ah - al) * (gint64)(bl - bh);
245         /* check for overflow */
246         t1 <<= 32;
247         if (t1 > (0x7FFFFFFFFFFFFFFFLL - res))
248                 goto raise_exception;
249
250         res += t1;
251
252         if (res < 0)
253                 goto raise_exception;
254
255         if (sign < 0)
256                 return -res;
257         else
258                 return res;
259
260  raise_exception:
261         mono_set_pending_exception (mono_get_exception_overflow ());
262         return 0;
263 }
264
265 gint64 
266 mono_lldiv (gint64 a, gint64 b)
267 {
268 #ifdef MONO_ARCH_NEED_DIV_CHECK
269         if (!b) {
270                 mono_set_pending_exception (mono_get_exception_divide_by_zero ());
271                 return 0;
272         }
273         else if (b == -1 && a == (-9223372036854775807LL - 1LL)) {
274                 mono_set_pending_exception (mono_get_exception_arithmetic ());
275                 return 0;
276         }
277 #endif
278         return a / b;
279 }
280
281 gint64 
282 mono_llrem (gint64 a, gint64 b)
283 {
284 #ifdef MONO_ARCH_NEED_DIV_CHECK
285         if (!b) {
286                 mono_set_pending_exception (mono_get_exception_divide_by_zero ());
287                 return 0;
288         }
289         else if (b == -1 && a == (-9223372036854775807LL - 1LL)) {
290                 mono_set_pending_exception (mono_get_exception_arithmetic ());
291                 return 0;
292         }
293 #endif
294         return a % b;
295 }
296
297 guint64 
298 mono_lldiv_un (guint64 a, guint64 b)
299 {
300 #ifdef MONO_ARCH_NEED_DIV_CHECK
301         if (!b) {
302                 mono_set_pending_exception (mono_get_exception_divide_by_zero ());
303                 return 0;
304         }
305 #endif
306         return a / b;
307 }
308
309 guint64 
310 mono_llrem_un (guint64 a, guint64 b)
311 {
312 #ifdef MONO_ARCH_NEED_DIV_CHECK
313         if (!b) {
314                 mono_set_pending_exception (mono_get_exception_divide_by_zero ());
315                 return 0;
316         }
317 #endif
318         return a % b;
319 }
320
321 #endif
322
323 #ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
324
325 guint64 
326 mono_lshl (guint64 a, gint32 shamt)
327 {
328         guint64 res;
329
330         res = a << (shamt & 0x7f);
331
332         /*printf ("TESTL %lld << %d = %lld\n", a, shamt, res);*/
333
334         return res;
335 }
336
337 guint64 
338 mono_lshr_un (guint64 a, gint32 shamt)
339 {
340         guint64 res;
341
342         res = a >> (shamt & 0x7f);
343
344         /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
345
346         return res;
347 }
348
349 gint64 
350 mono_lshr (gint64 a, gint32 shamt)
351 {
352         gint64 res;
353
354         res = a >> (shamt & 0x7f);
355
356         /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
357
358         return res;
359 }
360
361 #endif
362
363 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
364
365 gint32
366 mono_idiv (gint32 a, gint32 b)
367 {
368 #ifdef MONO_ARCH_NEED_DIV_CHECK
369         if (!b) {
370                 mono_set_pending_exception (mono_get_exception_divide_by_zero ());
371                 return 0;
372         }
373         else if (b == -1 && a == (0x80000000)) {
374                 mono_set_pending_exception (mono_get_exception_overflow ());
375                 return 0;
376         }
377 #endif
378         return a / b;
379 }
380
381 guint32
382 mono_idiv_un (guint32 a, guint32 b)
383 {
384 #ifdef MONO_ARCH_NEED_DIV_CHECK
385         if (!b) {
386                 mono_set_pending_exception (mono_get_exception_divide_by_zero ());
387                 return 0;
388         }
389 #endif
390         return a / b;
391 }
392
393 gint32
394 mono_irem (gint32 a, gint32 b)
395 {
396 #ifdef MONO_ARCH_NEED_DIV_CHECK
397         if (!b) {
398                 mono_set_pending_exception (mono_get_exception_divide_by_zero ());
399                 return 0;
400         }
401         else if (b == -1 && a == (0x80000000)) {
402                 mono_set_pending_exception (mono_get_exception_overflow ());
403                 return 0;
404         }
405 #endif
406         return a % b;
407 }
408
409 guint32
410 mono_irem_un (guint32 a, guint32 b)
411 {
412 #ifdef MONO_ARCH_NEED_DIV_CHECK
413         if (!b) {
414                 mono_set_pending_exception (mono_get_exception_divide_by_zero ());
415                 return 0;
416         }
417 #endif
418         return a % b;
419 }
420
421 #endif
422
423 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF)
424
425 gint32
426 mono_imul (gint32 a, gint32 b)
427 {
428         return a * b;
429 }
430
431 gint32
432 mono_imul_ovf (gint32 a, gint32 b)
433 {
434         gint64 res;
435
436         res = (gint64)a * (gint64)b;
437
438         if ((res > 0x7fffffffL) || (res < -2147483648LL)) {
439                 mono_set_pending_exception (mono_get_exception_overflow ());
440                 return 0;
441         }
442
443         return res;
444 }
445
446 gint32
447 mono_imul_ovf_un (guint32 a, guint32 b)
448 {
449         guint64 res;
450
451         res = (guint64)a * (guint64)b;
452
453         if (res >> 32) {
454                 mono_set_pending_exception (mono_get_exception_overflow ());
455                 return 0;
456         }
457
458         return res;
459 }
460 #endif
461
462 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
463 double
464 mono_fdiv (double a, double b)
465 {
466         return a / b;
467 }
468 #endif
469
470 #ifdef MONO_ARCH_SOFT_FLOAT_FALLBACK
471
472 double
473 mono_fsub (double a, double b)
474 {
475         return a - b;
476 }
477
478 double
479 mono_fadd (double a, double b)
480 {
481         return a + b;
482 }
483
484 double
485 mono_fmul (double a, double b)
486 {
487         return a * b;
488 }
489
490 double
491 mono_fneg (double a)
492 {
493         return -a;
494 }
495
496 double
497 mono_fconv_r4 (double a)
498 {
499         return (float)a;
500 }
501
502 double
503 mono_conv_to_r8 (int a)
504 {
505         return (double)a;
506 }
507
508 double
509 mono_conv_to_r4 (int a)
510 {
511         return (double)(float)a;
512 }
513
514 gint8
515 mono_fconv_i1 (double a)
516 {
517         return (gint8)a;
518 }
519
520 gint16
521 mono_fconv_i2 (double a)
522 {
523         return (gint16)a;
524 }
525
526 gint32
527 mono_fconv_i4 (double a)
528 {
529         return (gint32)a;
530 }
531
532 guint8
533 mono_fconv_u1 (double a)
534 {
535         return (guint8)a;
536 }
537
538 guint16
539 mono_fconv_u2 (double a)
540 {
541         return (guint16)a;
542 }
543
544 gboolean
545 mono_fcmp_eq (double a, double b)
546 {
547         return a == b;
548 }
549
550 gboolean
551 mono_fcmp_ge (double a, double b)
552 {
553         return a >= b;
554 }
555
556 gboolean
557 mono_fcmp_gt (double a, double b)
558 {
559         return a > b;
560 }
561
562 gboolean
563 mono_fcmp_le (double a, double b)
564 {
565         return a <= b;
566 }
567
568 gboolean
569 mono_fcmp_lt (double a, double b)
570 {
571         return a < b;
572 }
573
574 gboolean
575 mono_fcmp_ne_un (double a, double b)
576 {
577         return isunordered (a, b) || a != b;
578 }
579
580 gboolean
581 mono_fcmp_ge_un (double a, double b)
582 {
583         return isunordered (a, b) || a >= b;
584 }
585
586 gboolean
587 mono_fcmp_gt_un (double a, double b)
588 {
589         return isunordered (a, b) || a > b;
590 }
591
592 gboolean
593 mono_fcmp_le_un (double a, double b)
594 {
595         return isunordered (a, b) || a <= b;
596 }
597
598 gboolean
599 mono_fcmp_lt_un (double a, double b)
600 {
601         return isunordered (a, b) || a < b;
602 }
603
604 gboolean
605 mono_fceq (double a, double b)
606 {
607         return a == b;
608 }
609
610 gboolean
611 mono_fcgt (double a, double b)
612 {
613         return a > b;
614 }
615
616 gboolean
617 mono_fcgt_un (double a, double b)
618 {
619         return isunordered (a, b) || a > b;
620 }
621
622 gboolean
623 mono_fclt (double a, double b)
624 {
625         return a < b;
626 }
627
628 gboolean
629 mono_fclt_un (double a, double b)
630 {
631         return isunordered (a, b) || a < b;
632 }
633
634 gboolean
635 mono_isfinite (double a)
636 {
637 #ifdef HAVE_ISFINITE
638         return isfinite (a);
639 #else
640         g_assert_not_reached ();
641         return TRUE;
642 #endif
643 }
644
645 double
646 mono_fload_r4 (float *ptr)
647 {
648         return *ptr;
649 }
650
651 void
652 mono_fstore_r4 (double val, float *ptr)
653 {
654         *ptr = (float)val;
655 }
656
657 /* returns the integer bitpattern that is passed in the regs or stack */
658 guint32
659 mono_fload_r4_arg (double val)
660 {
661         float v = (float)val;
662         return *(guint32*)&v;
663 }
664
665 #endif
666
667 MonoArray *
668 mono_array_new_va (MonoMethod *cm, ...)
669 {
670         MonoError error;
671         MonoArray *arr;
672         MonoDomain *domain = mono_domain_get ();
673         va_list ap;
674         uintptr_t *lengths;
675         intptr_t *lower_bounds;
676         int pcount;
677         int rank;
678         int i, d;
679
680         pcount = mono_method_signature (cm)->param_count;
681         rank = cm->klass->rank;
682
683         va_start (ap, cm);
684         
685         lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
686         for (i = 0; i < pcount; ++i)
687                 lengths [i] = d = va_arg(ap, int);
688
689         if (rank == pcount) {
690                 /* Only lengths provided. */
691                 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
692                         lower_bounds = (intptr_t *)alloca (sizeof (intptr_t) * rank);
693                         memset (lower_bounds, 0, sizeof (intptr_t) * rank);
694                 } else {
695                         lower_bounds = NULL;
696                 }
697         } else {
698                 g_assert (pcount == (rank * 2));
699                 /* lower bounds are first. */
700                 lower_bounds = (intptr_t*)lengths;
701                 lengths += rank;
702         }
703         va_end(ap);
704
705         arr = mono_array_new_full_checked (domain, cm->klass, lengths, lower_bounds, &error);
706
707         if (!mono_error_ok (&error)) {
708                 mono_error_set_pending_exception (&error);
709                 return NULL;
710         }
711
712         return arr;
713 }
714
715 /* Specialized version of mono_array_new_va () which avoids varargs */
716 MonoArray *
717 mono_array_new_1 (MonoMethod *cm, guint32 length)
718 {
719         MonoError error;
720         MonoArray *arr;
721         MonoDomain *domain = mono_domain_get ();
722         uintptr_t lengths [1];
723         intptr_t *lower_bounds;
724         int pcount;
725         int rank;
726
727         pcount = mono_method_signature (cm)->param_count;
728         rank = cm->klass->rank;
729
730         lengths [0] = length;
731
732         g_assert (rank == pcount);
733
734         if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
735                 lower_bounds = (intptr_t *)alloca (sizeof (intptr_t) * rank);
736                 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
737         } else {
738                 lower_bounds = NULL;
739         }
740
741         arr = mono_array_new_full_checked (domain, cm->klass, lengths, lower_bounds, &error);
742
743         if (!mono_error_ok (&error)) {
744                 mono_error_set_pending_exception (&error);
745                 return NULL;
746         }
747
748         return arr;
749 }
750
751 MonoArray *
752 mono_array_new_2 (MonoMethod *cm, guint32 length1, guint32 length2)
753 {
754         MonoError error;
755         MonoArray *arr;
756         MonoDomain *domain = mono_domain_get ();
757         uintptr_t lengths [2];
758         intptr_t *lower_bounds;
759         int pcount;
760         int rank;
761
762         pcount = mono_method_signature (cm)->param_count;
763         rank = cm->klass->rank;
764
765         lengths [0] = length1;
766         lengths [1] = length2;
767
768         g_assert (rank == pcount);
769
770         if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
771                 lower_bounds = (intptr_t *)alloca (sizeof (intptr_t) * rank);
772                 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
773         } else {
774                 lower_bounds = NULL;
775         }
776
777         arr = mono_array_new_full_checked (domain, cm->klass, lengths, lower_bounds, &error);
778
779         if (!mono_error_ok (&error)) {
780                 mono_error_set_pending_exception (&error);
781                 return NULL;
782         }
783
784         return arr;
785 }
786
787 MonoArray *
788 mono_array_new_3 (MonoMethod *cm, guint32 length1, guint32 length2, guint32 length3)
789 {
790         MonoError error;
791         MonoArray *arr;
792         MonoDomain *domain = mono_domain_get ();
793         uintptr_t lengths [3];
794         intptr_t *lower_bounds;
795         int pcount;
796         int rank;
797
798         pcount = mono_method_signature (cm)->param_count;
799         rank = cm->klass->rank;
800
801         lengths [0] = length1;
802         lengths [1] = length2;
803         lengths [2] = length3;
804
805         g_assert (rank == pcount);
806
807         if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
808                 lower_bounds = (intptr_t *)alloca (sizeof (intptr_t) * rank);
809                 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
810         } else {
811                 lower_bounds = NULL;
812         }
813
814         arr = mono_array_new_full_checked (domain, cm->klass, lengths, lower_bounds, &error);
815
816         if (!mono_error_ok (&error)) {
817                 mono_error_set_pending_exception (&error);
818                 return NULL;
819         }
820
821         return arr;
822 }
823
824 MonoArray *
825 mono_array_new_4 (MonoMethod *cm, guint32 length1, guint32 length2, guint32 length3, guint32 length4)
826 {
827         MonoError error;
828         MonoArray *arr;
829         MonoDomain *domain = mono_domain_get ();
830         uintptr_t lengths [4];
831         intptr_t *lower_bounds;
832         int pcount;
833         int rank;
834
835         pcount = mono_method_signature (cm)->param_count;
836         rank = cm->klass->rank;
837
838         lengths [0] = length1;
839         lengths [1] = length2;
840         lengths [2] = length3;
841         lengths [3] = length4;
842
843         g_assert (rank == pcount);
844
845         if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
846                 lower_bounds = (intptr_t *)alloca (sizeof (intptr_t) * rank);
847                 memset (lower_bounds, 0, sizeof (intptr_t) * rank);
848         } else {
849                 lower_bounds = NULL;
850         }
851
852         arr = mono_array_new_full_checked (domain, cm->klass, lengths, lower_bounds, &error);
853
854         if (!mono_error_ok (&error)) {
855                 mono_error_set_pending_exception (&error);
856                 return NULL;
857         }
858
859         return arr;
860 }
861
862 gpointer
863 mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
864 {
865         MonoError error;
866         MonoVTable *vtable;
867         gpointer addr;
868         
869         //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
870
871         mono_class_init (field->parent);
872
873         vtable = mono_class_vtable_full (domain, field->parent, &error);
874         if (!is_ok (&error)) {
875                 mono_error_set_pending_exception (&error);
876                 return NULL;
877         }
878         if (!vtable->initialized) {
879                 if (!mono_runtime_class_init_full (vtable, &error)) {
880                         mono_error_set_pending_exception (&error);
881                         return NULL;
882                 }
883         }
884
885         //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
886
887         if (domain->special_static_fields && (addr = g_hash_table_lookup (domain->special_static_fields, field)))
888                 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
889         else
890                 addr = (char*)mono_vtable_get_static_field_data (vtable) + field->offset;
891         
892         return addr;
893 }
894
895 gpointer
896 mono_ldtoken_wrapper (MonoImage *image, int token, MonoGenericContext *context)
897 {
898         MonoError error;
899         MonoClass *handle_class;
900         gpointer res;
901
902         res = mono_ldtoken_checked (image, token, &handle_class, context, &error);
903         if (!mono_error_ok (&error)) {
904                 mono_error_set_pending_exception (&error);
905                 return NULL;
906         }
907         mono_class_init (handle_class);
908
909         return res;
910 }
911
912 gpointer
913 mono_ldtoken_wrapper_generic_shared (MonoImage *image, int token, MonoMethod *method)
914 {
915         MonoMethodSignature *sig = mono_method_signature (method);
916         MonoGenericContext *generic_context;
917
918         if (sig->is_inflated) {
919                 generic_context = mono_method_get_context (method);
920         } else {
921                 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
922                 g_assert (generic_container);
923                 generic_context = &generic_container->context;
924         }
925
926         return mono_ldtoken_wrapper (image, token, generic_context);
927 }
928
929 guint64
930 mono_fconv_u8 (double v)
931 {
932         return (guint64)v;
933 }
934
935 guint64
936 mono_rconv_u8 (float v)
937 {
938         return (guint64)v;
939 }
940
941 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
942 gint64
943 mono_fconv_i8 (double v)
944 {
945         return (gint64)v;
946 }
947 #endif
948
949 guint32
950 mono_fconv_u4 (double v)
951 {
952         /* MS.NET behaves like this for some reason */
953 #ifdef HAVE_ISINF
954         if (isinf (v) || isnan (v))
955                 return 0;
956 #endif
957
958         return (guint32)v;
959 }
960
961 #ifndef HAVE_TRUNC
962 /* Solaris doesn't have trunc */
963 #ifdef HAVE_AINTL
964 extern long double aintl (long double);
965 #define trunc aintl
966 #else
967 /* FIXME: This means we will never throw overflow exceptions */
968 #define trunc(v) res
969 #endif
970 #endif /* HAVE_TRUNC */
971
972 gint64
973 mono_fconv_ovf_i8 (double v)
974 {
975         gint64 res;
976
977         res = (gint64)v;
978
979         if (isnan(v) || trunc (v) != res) {
980                 mono_set_pending_exception (mono_get_exception_overflow ());
981                 return 0;
982         }
983         return res;
984 }
985
986 guint64
987 mono_fconv_ovf_u8 (double v)
988 {
989         guint64 res;
990
991 /*
992  * The soft-float implementation of some ARM devices have a buggy guin64 to double
993  * conversion that it looses precision even when the integer if fully representable
994  * as a double.
995  * 
996  * This was found with 4294967295ull, converting to double and back looses one bit of precision.
997  * 
998  * To work around this issue we test for value boundaries instead. 
999  */
1000 #if defined(__arm__) && defined(MONO_ARCH_SOFT_FLOAT_FALLBACK)
1001         if (isnan (v) || !(v >= -0.5 && v <= ULLONG_MAX+0.5)) {
1002                 mono_set_pending_exception (mono_get_exception_overflow ());
1003                 return 0;
1004         }
1005         res = (guint64)v;
1006 #else
1007         res = (guint64)v;
1008         if (isnan(v) || trunc (v) != res) {
1009                 mono_set_pending_exception (mono_get_exception_overflow ());
1010                 return 0;
1011         }
1012 #endif
1013         return res;
1014 }
1015
1016 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
1017 gint64
1018 mono_rconv_i8 (float v)
1019 {
1020         return (gint64)v;
1021 }
1022 #endif
1023
1024 gint64
1025 mono_rconv_ovf_i8 (float v)
1026 {
1027         gint64 res;
1028
1029         res = (gint64)v;
1030
1031         if (isnan(v) || trunc (v) != res) {
1032                 mono_set_pending_exception (mono_get_exception_overflow ());
1033                 return 0;
1034         }
1035         return res;
1036 }
1037
1038 guint64
1039 mono_rconv_ovf_u8 (float v)
1040 {
1041         guint64 res;
1042
1043         res = (guint64)v;
1044         if (isnan(v) || trunc (v) != res) {
1045                 mono_set_pending_exception (mono_get_exception_overflow ());
1046                 return 0;
1047         }
1048         return res;
1049 }
1050
1051 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
1052 double
1053 mono_lconv_to_r8 (gint64 a)
1054 {
1055         return (double)a;
1056 }
1057 #endif
1058
1059 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
1060 float
1061 mono_lconv_to_r4 (gint64 a)
1062 {
1063         return (float)a;
1064 }
1065 #endif
1066
1067 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
1068 double
1069 mono_conv_to_r8_un (guint32 a)
1070 {
1071         return (double)a;
1072 }
1073 #endif
1074
1075 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
1076 double
1077 mono_lconv_to_r8_un (guint64 a)
1078 {
1079         return (double)a;
1080 }
1081 #endif
1082
1083 #if defined(__native_client_codegen__) || defined(__native_client__)
1084 /* When we cross-compile to Native Client we can't directly embed calls */
1085 /* to the math library on the host. This will use the fmod on the target*/
1086 double
1087 mono_fmod(double a, double b)
1088 {
1089         return fmod(a, b);
1090 }
1091 #endif
1092
1093 gpointer
1094 mono_helper_compile_generic_method (MonoObject *obj, MonoMethod *method, gpointer *this_arg)
1095 {
1096         MonoMethod *vmethod;
1097         gpointer addr;
1098         MonoGenericContext *context = mono_method_get_context (method);
1099
1100         mono_jit_stats.generic_virtual_invocations++;
1101
1102         if (obj == NULL) {
1103                 mono_set_pending_exception (mono_get_exception_null_reference ());
1104                 return NULL;
1105         }
1106         vmethod = mono_object_get_virtual_method (obj, method);
1107         g_assert (!vmethod->klass->generic_container);
1108         g_assert (!vmethod->klass->generic_class || !vmethod->klass->generic_class->context.class_inst->is_open);
1109         g_assert (!context->method_inst || !context->method_inst->is_open);
1110
1111         addr = mono_compile_method (vmethod);
1112
1113         addr = mini_add_method_trampoline (vmethod, addr, mono_method_needs_static_rgctx_invoke (vmethod, FALSE), FALSE);
1114
1115         /* Since this is a virtual call, have to unbox vtypes */
1116         if (obj->vtable->klass->valuetype)
1117                 *this_arg = mono_object_unbox (obj);
1118         else
1119                 *this_arg = obj;
1120
1121         return addr;
1122 }
1123
1124 MonoString*
1125 mono_helper_ldstr (MonoImage *image, guint32 idx)
1126 {
1127         return mono_ldstr (mono_domain_get (), image, idx);
1128 }
1129
1130 MonoString*
1131 mono_helper_ldstr_mscorlib (guint32 idx)
1132 {
1133         return mono_ldstr (mono_domain_get (), mono_defaults.corlib, idx);
1134 }
1135
1136 MonoObject*
1137 mono_helper_newobj_mscorlib (guint32 idx)
1138 {
1139         MonoError error;
1140         MonoClass *klass = mono_class_get_checked (mono_defaults.corlib, MONO_TOKEN_TYPE_DEF | idx, &error);
1141
1142         if (!mono_error_ok (&error)) {
1143                 mono_error_set_pending_exception (&error);
1144                 return NULL;
1145         }
1146
1147         MonoObject *obj = mono_object_new_checked (mono_domain_get (), klass, &error);
1148         if (!mono_error_ok (&error))
1149                 mono_error_set_pending_exception (&error);
1150         return obj;
1151 }
1152
1153 /*
1154  * On some architectures, gdb doesn't like encountering the cpu breakpoint instructions
1155  * in generated code. So instead we emit a call to this function and place a gdb
1156  * breakpoint here.
1157  */
1158 void
1159 mono_break (void)
1160 {
1161 }
1162
1163 MonoException *
1164 mono_create_corlib_exception_0 (guint32 token)
1165 {
1166         return mono_exception_from_token (mono_defaults.corlib, token);
1167 }
1168
1169 MonoException *
1170 mono_create_corlib_exception_1 (guint32 token, MonoString *arg)
1171 {
1172         return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg, NULL);
1173 }
1174
1175 MonoException *
1176 mono_create_corlib_exception_2 (guint32 token, MonoString *arg1, MonoString *arg2)
1177 {
1178         return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg1, arg2);
1179 }
1180
1181 MonoObject*
1182 mono_object_castclass_unbox (MonoObject *obj, MonoClass *klass)
1183 {
1184         MonoError error;
1185         MonoJitTlsData *jit_tls = NULL;
1186         MonoClass *oklass;
1187
1188         if (mini_get_debug_options ()->better_cast_details) {
1189                 jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
1190                 jit_tls->class_cast_from = NULL;
1191         }
1192
1193         if (!obj)
1194                 return NULL;
1195
1196         oklass = obj->vtable->klass;
1197         if ((klass->enumtype && oklass == klass->element_class) || (oklass->enumtype && klass == oklass->element_class))
1198                 return obj;
1199         if (mono_object_isinst_checked (obj, klass, &error))
1200                 return obj;
1201         if (mono_error_set_pending_exception (&error))
1202                 return NULL;
1203
1204         if (mini_get_debug_options ()->better_cast_details) {
1205                 jit_tls->class_cast_from = oklass;
1206                 jit_tls->class_cast_to = klass;
1207         }
1208
1209         mono_set_pending_exception (mono_exception_from_name (mono_defaults.corlib,
1210                                         "System", "InvalidCastException"));
1211
1212         return NULL;
1213 }
1214
1215 MonoObject*
1216 mono_object_castclass_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cache)
1217 {
1218         MonoError error;
1219         MonoJitTlsData *jit_tls = NULL;
1220         gpointer cached_vtable, obj_vtable;
1221
1222         if (mini_get_debug_options ()->better_cast_details) {
1223                 jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
1224                 jit_tls->class_cast_from = NULL;
1225         }
1226
1227         if (!obj)
1228                 return NULL;
1229
1230         cached_vtable = *cache;
1231         obj_vtable = obj->vtable;
1232
1233         if (cached_vtable == obj_vtable)
1234                 return obj;
1235
1236         if (mono_object_isinst_checked (obj, klass, &error)) {
1237                 *cache = obj_vtable;
1238                 return obj;
1239         }
1240         if (mono_error_set_pending_exception (&error))
1241                 return NULL;
1242
1243         if (mini_get_debug_options ()->better_cast_details) {
1244                 jit_tls->class_cast_from = obj->vtable->klass;
1245                 jit_tls->class_cast_to = klass;
1246         }
1247
1248         mono_set_pending_exception (mono_exception_from_name (mono_defaults.corlib,
1249                                         "System", "InvalidCastException"));
1250
1251         return NULL;
1252 }
1253
1254 MonoObject*
1255 mono_object_isinst_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cache)
1256 {
1257         MonoError error;
1258         size_t cached_vtable, obj_vtable;
1259
1260         if (!obj)
1261                 return NULL;
1262
1263         cached_vtable = (size_t)*cache;
1264         obj_vtable = (size_t)obj->vtable;
1265
1266         if ((cached_vtable & ~0x1) == obj_vtable) {
1267                 return (cached_vtable & 0x1) ? NULL : obj;
1268         }
1269
1270         if (mono_object_isinst_checked (obj, klass, &error)) {
1271                 *cache = (gpointer)obj_vtable;
1272                 return obj;
1273         } else {
1274                 if (mono_error_set_pending_exception (&error))
1275                         return NULL;
1276                 /*negative cache*/
1277                 *cache = (gpointer)(obj_vtable | 0x1);
1278                 return NULL;
1279         }
1280 }
1281
1282 gpointer
1283 mono_get_native_calli_wrapper (MonoImage *image, MonoMethodSignature *sig, gpointer func)
1284 {
1285         MonoMarshalSpec **mspecs;
1286         MonoMethodPInvoke piinfo;
1287         MonoMethod *m;
1288
1289         mspecs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
1290         memset (&piinfo, 0, sizeof (piinfo));
1291
1292         m = mono_marshal_get_native_func_wrapper (image, sig, &piinfo, mspecs, func);
1293
1294         return mono_compile_method (m);
1295 }
1296
1297 static MonoMethod*
1298 constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gpointer *this_arg, MonoError *error)
1299 {
1300         MonoMethod *m;
1301         int vt_slot, iface_offset;
1302
1303         mono_error_init (error);
1304
1305         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1306                 MonoObject *this_obj;
1307
1308                 /* Have to use the receiver's type instead of klass, the receiver is a ref type */
1309                 this_obj = *(MonoObject**)mp;
1310                 g_assert (this_obj);
1311
1312                 klass = this_obj->vtable->klass;
1313         }
1314
1315         if (mono_method_signature (cmethod)->pinvoke) {
1316                 /* Object.GetType () */
1317                 m = mono_marshal_get_native_wrapper (cmethod, TRUE, FALSE);
1318         } else {
1319                 /* Lookup the virtual method */
1320                 mono_class_setup_vtable (klass);
1321                 g_assert (klass->vtable);
1322                 vt_slot = mono_method_get_vtable_slot (cmethod);
1323                 if (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1324                         iface_offset = mono_class_interface_offset (klass, cmethod->klass);
1325                         g_assert (iface_offset != -1);
1326                         vt_slot += iface_offset;
1327                 }
1328                 m = klass->vtable [vt_slot];
1329                 if (cmethod->is_inflated)
1330                         m = mono_class_inflate_generic_method (m, mono_method_get_context (cmethod));
1331         }
1332
1333         if (klass->valuetype && (m->klass == mono_defaults.object_class || m->klass == mono_defaults.enum_class->parent || m->klass == mono_defaults.enum_class))
1334                 /*
1335                  * Calling a non-vtype method with a vtype receiver, has to box.
1336                  */
1337                 *this_arg = mono_value_box_checked (mono_domain_get (), klass, mp, error);
1338         else if (klass->valuetype)
1339                 /*
1340                  * Calling a vtype method with a vtype receiver
1341                  */
1342                 *this_arg = mp;
1343         else
1344                 /*
1345                  * Calling a non-vtype method
1346                  */
1347                 *this_arg = *(gpointer*)mp;
1348         return m;
1349 }
1350
1351 /*
1352  * mono_gsharedvt_constrained_call:
1353  *
1354  *   Make a call to CMETHOD using the receiver MP, which is assumed to be of type KLASS. ARGS contains
1355  * the arguments to the method in the format used by mono_runtime_invoke_checked ().
1356  */
1357 MonoObject*
1358 mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gboolean deref_arg, gpointer *args)
1359 {
1360         MonoError error;
1361         MonoObject *o;
1362         MonoMethod *m;
1363         gpointer this_arg;
1364         gpointer new_args [16];
1365
1366         m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg, &error);
1367         if (!mono_error_ok (&error)) {
1368                 mono_error_set_pending_exception (&error);
1369                 return NULL;
1370         }
1371
1372         if (!m)
1373                 return NULL;
1374         if (args && deref_arg) {
1375                 new_args [0] = *(gpointer*)args [0];
1376                 args = new_args;
1377         }
1378         if (m->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
1379                 /* Object.GetType () */
1380                 args = new_args;
1381                 args [0] = this_arg;
1382                 this_arg = NULL;
1383         }
1384
1385         o = mono_runtime_invoke_checked (m, this_arg, args, &error);
1386         if (!mono_error_ok (&error)) {
1387                 mono_error_set_pending_exception (&error);
1388                 return NULL;
1389         }
1390
1391         return o;
1392 }
1393
1394 void
1395 mono_gsharedvt_value_copy (gpointer dest, gpointer src, MonoClass *klass)
1396 {
1397         if (klass->valuetype)
1398                 mono_value_copy (dest, src, klass);
1399         else
1400         mono_gc_wbarrier_generic_store (dest, *(MonoObject**)src);
1401 }
1402
1403 void
1404 ves_icall_runtime_class_init (MonoVTable *vtable)
1405 {
1406         MONO_REQ_GC_UNSAFE_MODE;
1407         MonoError error;
1408
1409         mono_runtime_class_init_full (vtable, &error);
1410         mono_error_set_pending_exception (&error);
1411 }
1412
1413
1414 void
1415 mono_generic_class_init (MonoVTable *vtable)
1416 {
1417         MonoError error;
1418         mono_runtime_class_init_full (vtable, &error);
1419         mono_error_set_pending_exception (&error);
1420 }
1421
1422 gpointer
1423 mono_fill_class_rgctx (MonoVTable *vtable, int index)
1424 {
1425         MonoError error;
1426         gpointer res;
1427
1428         res = mono_class_fill_runtime_generic_context (vtable, index, &error);
1429         if (!mono_error_ok (&error)) {
1430                 mono_error_set_pending_exception (&error);
1431                 return NULL;
1432         }
1433         return res;
1434 }
1435
1436 gpointer
1437 mono_fill_method_rgctx (MonoMethodRuntimeGenericContext *mrgctx, int index)
1438 {
1439         MonoError error;
1440         gpointer res;
1441
1442         res = mono_method_fill_runtime_generic_context (mrgctx, index, &error);
1443         if (!mono_error_ok (&error)) {
1444                 mono_error_set_pending_exception (&error);
1445                 return NULL;
1446         }
1447         return res;
1448 }
1449
1450 /*
1451  * resolve_iface_call:
1452  *
1453  *   Return the executable code for the iface method IMT_METHOD called on THIS.
1454  * This function is called on a slowpath, so it doesn't need to be fast.
1455  * This returns an ftnptr by returning the address part, and the arg in the OUT_ARG
1456  * out parameter.
1457  */
1458 static gpointer
1459 resolve_iface_call (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, gpointer *out_arg, gboolean caller_gsharedvt)
1460 {
1461         MonoVTable *vt;
1462         gpointer *imt, *vtable_slot;
1463         MonoMethod *impl_method, *generic_virtual = NULL, *variant_iface = NULL;
1464         gpointer addr, compiled_method, aot_addr;
1465         gboolean need_rgctx_tramp = FALSE, need_unbox_tramp = FALSE;
1466
1467         if (!this_obj)
1468                 /* The caller will handle it */
1469                 return NULL;
1470
1471         vt = this_obj->vtable;
1472         imt = (gpointer*)vt - MONO_IMT_SIZE;
1473
1474         vtable_slot = mini_resolve_imt_method (vt, imt + imt_slot, imt_method, &impl_method, &aot_addr, &need_rgctx_tramp, &variant_iface);
1475
1476         // FIXME: This can throw exceptions
1477         addr = compiled_method = mono_compile_method (impl_method);
1478         g_assert (addr);
1479
1480         if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst)
1481                 generic_virtual = imt_method;
1482
1483         if (generic_virtual || variant_iface) {
1484                 if (vt->klass->valuetype) /*FIXME is this required variant iface?*/
1485                         need_unbox_tramp = TRUE;
1486         } else {
1487                 if (impl_method->klass->valuetype)
1488                         need_unbox_tramp = TRUE;
1489         }
1490
1491         addr = mini_add_method_wrappers_llvmonly (impl_method, addr, caller_gsharedvt, need_unbox_tramp, out_arg);
1492
1493         if (generic_virtual || variant_iface) {
1494                 MonoMethod *target = generic_virtual ? generic_virtual : variant_iface;
1495
1496                 mono_method_add_generic_virtual_invocation (mono_domain_get (),
1497                                                                                                         vt, imt + imt_slot,
1498                                                                                                         target, addr);
1499         }
1500
1501         return addr;
1502 }
1503
1504 gpointer
1505 mono_resolve_iface_call_gsharedvt (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, gpointer *out_arg)
1506 {
1507         return resolve_iface_call (this_obj, imt_slot, imt_method, out_arg, TRUE);
1508 }
1509
1510 static gboolean
1511 is_generic_method_definition (MonoMethod *m)
1512 {
1513         MonoGenericContext *context;
1514         if (m->is_generic)
1515                 return TRUE;
1516         if (!m->is_inflated)
1517                 return FALSE;
1518
1519         context = mono_method_get_context (m);
1520         if (!context->method_inst)
1521                 return FALSE;
1522         if (context->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)m)->declaring)->context.method_inst)
1523                 return TRUE;
1524         return FALSE;
1525 }
1526
1527 /*
1528  * resolve_vcall:
1529  *
1530  *   Return the executable code for calling vt->vtable [slot].
1531  * This function is called on a slowpath, so it doesn't need to be fast.
1532  * This returns an ftnptr by returning the address part, and the arg in the OUT_ARG
1533  * out parameter.
1534  */
1535 static gpointer
1536 resolve_vcall (MonoVTable *vt, int slot, MonoMethod *imt_method, gpointer *out_arg, gboolean gsharedvt)
1537 {
1538         MonoMethod *m, *generic_virtual = NULL;
1539         gpointer addr, compiled_method;
1540         gboolean need_unbox_tramp = FALSE;
1541
1542         /* Same as in common_call_trampoline () */
1543
1544         /* Avoid loading metadata or creating a generic vtable if possible */
1545         addr = mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, slot);
1546         if (addr && !vt->klass->valuetype)
1547                 return mono_create_ftnptr (mono_domain_get (), addr);
1548
1549         m = mono_class_get_vtable_entry (vt->klass, slot);
1550
1551         if (is_generic_method_definition (m)) {
1552                 MonoError error;
1553                 MonoGenericContext context = { NULL, NULL };
1554                 MonoMethod *declaring;
1555
1556                 if (m->is_inflated)
1557                         declaring = mono_method_get_declaring_generic_method (m);
1558                 else
1559                         declaring = m;
1560
1561                 if (m->klass->generic_class)
1562                         context.class_inst = m->klass->generic_class->context.class_inst;
1563                 else
1564                         g_assert (!m->klass->generic_container);
1565
1566                 generic_virtual = imt_method;
1567                 g_assert (generic_virtual);
1568                 g_assert (generic_virtual->is_inflated);
1569                 context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst;
1570
1571                 m = mono_class_inflate_generic_method_checked (declaring, &context, &error);
1572                 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
1573         }
1574
1575         if (generic_virtual) {
1576                 if (vt->klass->valuetype)
1577                         need_unbox_tramp = TRUE;
1578         } else {
1579                 if (m->klass->valuetype)
1580                         need_unbox_tramp = TRUE;
1581         }
1582
1583         // FIXME: This can throw exceptions
1584         addr = compiled_method = mono_compile_method (m);
1585         g_assert (addr);
1586
1587         addr = mini_add_method_wrappers_llvmonly (m, addr, gsharedvt, need_unbox_tramp, out_arg);
1588
1589         if (!gsharedvt && generic_virtual) {
1590                 // FIXME: This wastes memory since add_generic_virtual_invocation ignores it in a lot of cases
1591                 MonoFtnDesc *ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, out_arg);
1592
1593                 mono_method_add_generic_virtual_invocation (mono_domain_get (),
1594                                                                                                         vt, vt->vtable + slot,
1595                                                                                                         generic_virtual, ftndesc);
1596         }
1597
1598         return addr;
1599 }
1600
1601 gpointer
1602 mono_resolve_vcall_gsharedvt (MonoObject *this_obj, int slot, MonoMethod *imt_method, gpointer *out_arg)
1603 {
1604         g_assert (this_obj);
1605
1606         return resolve_vcall (this_obj->vtable, slot, imt_method, out_arg, TRUE);
1607 }
1608
1609 /*
1610  * mono_resolve_generic_virtual_call:
1611  *
1612  *   Resolve a generic virtual call.
1613  * This function is called on a slowpath, so it doesn't need to be fast.
1614  */
1615 MonoFtnDesc*
1616 mono_resolve_generic_virtual_call (MonoVTable *vt, int slot, MonoMethod *generic_virtual)
1617 {
1618         MonoMethod *m;
1619         gpointer addr, compiled_method;
1620         gboolean need_unbox_tramp = FALSE;
1621         MonoError error;
1622         MonoGenericContext context = { NULL, NULL };
1623         MonoMethod *declaring;
1624         gpointer arg = NULL;
1625
1626         m = mono_class_get_vtable_entry (vt->klass, slot);
1627
1628         g_assert (is_generic_method_definition (m));
1629
1630         if (m->is_inflated)
1631                 declaring = mono_method_get_declaring_generic_method (m);
1632         else
1633                 declaring = m;
1634
1635         if (m->klass->generic_class)
1636                 context.class_inst = m->klass->generic_class->context.class_inst;
1637         else
1638                 g_assert (!m->klass->generic_container);
1639
1640         g_assert (generic_virtual->is_inflated);
1641         context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst;
1642
1643         m = mono_class_inflate_generic_method_checked (declaring, &context, &error);
1644         g_assert (mono_error_ok (&error));
1645
1646         if (vt->klass->valuetype)
1647                 need_unbox_tramp = TRUE;
1648
1649         // FIXME: This can throw exceptions
1650         addr = compiled_method = mono_compile_method (m);
1651         g_assert (addr);
1652
1653         addr = mini_add_method_wrappers_llvmonly (m, addr, FALSE, need_unbox_tramp, &arg);
1654
1655         /*
1656          * This wastes memory but the memory usage is bounded since
1657          * mono_method_add_generic_virtual_invocation () eventually builds an imt thunk for
1658          * this vtable slot so we are not called any more for this instantiation.
1659          */
1660         MonoFtnDesc *ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
1661
1662         mono_method_add_generic_virtual_invocation (mono_domain_get (),
1663                                                                                                 vt, vt->vtable + slot,
1664                                                                                                 generic_virtual, ftndesc);
1665         return ftndesc;
1666 }
1667
1668 /*
1669  * mono_resolve_generic_virtual_call:
1670  *
1671  *   Resolve a generic virtual/variant iface call on interfaces.
1672  * This function is called on a slowpath, so it doesn't need to be fast.
1673  */
1674 MonoFtnDesc*
1675 mono_resolve_generic_virtual_iface_call (MonoVTable *vt, int imt_slot, MonoMethod *generic_virtual)
1676 {
1677         MonoMethod *m, *variant_iface;
1678         gpointer addr, aot_addr, compiled_method;
1679         gboolean need_unbox_tramp = FALSE;
1680         gboolean need_rgctx_tramp;
1681         gpointer arg = NULL;
1682         gpointer *imt;
1683
1684         imt = (gpointer*)vt - MONO_IMT_SIZE;
1685
1686         mini_resolve_imt_method (vt, imt + imt_slot, generic_virtual, &m, &aot_addr, &need_rgctx_tramp, &variant_iface);
1687
1688         if (vt->klass->valuetype)
1689                 need_unbox_tramp = TRUE;
1690
1691         // FIXME: This can throw exceptions
1692         addr = compiled_method = mono_compile_method (m);
1693         g_assert (addr);
1694
1695         addr = mini_add_method_wrappers_llvmonly (m, addr, FALSE, need_unbox_tramp, &arg);
1696
1697         /*
1698          * This wastes memory but the memory usage is bounded since
1699          * mono_method_add_generic_virtual_invocation () eventually builds an imt thunk for
1700          * this vtable slot so we are not called any more for this instantiation.
1701          */
1702         MonoFtnDesc *ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
1703
1704         mono_method_add_generic_virtual_invocation (mono_domain_get (),
1705                                                                                                 vt, imt + imt_slot,
1706                                                                                                 variant_iface ? variant_iface : generic_virtual, ftndesc);
1707         return ftndesc;
1708 }
1709
1710 /*
1711  * mono_init_vtable_slot:
1712  *
1713  *   Initialize slot SLOT of VTABLE.
1714  * Return the contents of the vtable slot.
1715  */
1716 gpointer
1717 mono_init_vtable_slot (MonoVTable *vtable, int slot)
1718 {
1719         gpointer arg = NULL;
1720         gpointer addr;
1721         gpointer *ftnptr;
1722
1723         addr = resolve_vcall (vtable, slot, NULL, &arg, FALSE);
1724         ftnptr = mono_domain_alloc0 (vtable->domain, 2 * sizeof (gpointer));
1725         ftnptr [0] = addr;
1726         ftnptr [1] = arg;
1727         mono_memory_barrier ();
1728
1729         vtable->vtable [slot] = ftnptr;
1730
1731         return ftnptr;
1732 }
1733
1734 /*
1735  * mono_llvmonly_init_delegate:
1736  *
1737  *   Initialize a MonoDelegate object.
1738  * Similar to mono_delegate_ctor ().
1739  */
1740 void
1741 mono_llvmonly_init_delegate (MonoDelegate *del)
1742 {
1743         MonoFtnDesc *ftndesc = *(MonoFtnDesc**)del->method_code;
1744
1745         /*
1746          * We store a MonoFtnDesc in del->method_code.
1747          * It would be better to store an ftndesc in del->method_ptr too,
1748          * but we don't have a a structure which could own its memory.
1749          */
1750         if (G_UNLIKELY (!ftndesc)) {
1751                 gpointer addr = mono_compile_method (del->method);
1752
1753                 if (del->method->klass->valuetype && mono_method_signature (del->method)->hasthis)
1754                     addr = mono_aot_get_unbox_trampoline (del->method);
1755
1756                 gpointer arg = mini_get_delegate_arg (del->method, addr);
1757
1758                 ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
1759                 mono_memory_barrier ();
1760                 *del->method_code = (gpointer)ftndesc;
1761         }
1762         del->method_ptr = ftndesc->addr;
1763         del->extra_arg = ftndesc->arg;
1764 }
1765
1766 void
1767 mono_llvmonly_init_delegate_virtual (MonoDelegate *del, MonoObject *target, MonoMethod *method)
1768 {
1769         g_assert (target);
1770
1771         method = mono_object_get_virtual_method (target, method);
1772
1773         del->method = method;
1774         del->method_ptr = mono_compile_method (method);
1775         if (method->klass->valuetype)
1776                 del->method_ptr = mono_aot_get_unbox_trampoline (method);
1777         del->extra_arg = mini_get_delegate_arg (del->method, del->method_ptr);
1778 }
1779
1780 MonoObject*
1781 mono_get_assembly_object (MonoImage *image)
1782 {
1783         MonoError error;
1784         MonoObject *result;
1785         result = (MonoObject*)mono_assembly_get_object_checked (mono_domain_get (), image->assembly, &error);
1786         if (!result)
1787                 mono_error_set_pending_exception (&error);
1788         return result;
1789 }
1790
1791 MonoObject*
1792 mono_get_method_object (MonoMethod *method)
1793 {
1794         MonoError error;
1795         MonoObject * result;
1796         result = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), method, method->klass, &error);
1797         mono_error_set_pending_exception (&error);
1798         return result;
1799 }
1800
1801 double
1802 mono_ckfinite (double d)
1803 {
1804         if (isinf (d) || isnan (d))
1805                 mono_set_pending_exception (mono_get_exception_arithmetic ());
1806         return d;
1807 }
1808
1809 /*
1810  * mono_interruption_checkpoint_from_trampoline:
1811  *
1812  *   Check whenever the thread has a pending exception, and throw it
1813  * if needed.
1814  * Architectures should move away from calling this function and
1815  * instead call mono_thread_force_interruption_checkpoint_noraise (),
1816  * rewrind to the parent frame, and throw the exception normally.
1817  */
1818 void
1819 mono_interruption_checkpoint_from_trampoline (void)
1820 {
1821         MonoException *ex;
1822
1823         ex = mono_thread_force_interruption_checkpoint_noraise ();
1824         if (ex)
1825                 mono_raise_exception (ex);
1826 }