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