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