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