[runtime] MonoError-ize mono_ldstr
[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 gpointer
1446 mono_fill_class_rgctx (MonoVTable *vtable, int index)
1447 {
1448         MonoError error;
1449         gpointer res;
1450
1451         res = mono_class_fill_runtime_generic_context (vtable, index, &error);
1452         if (!mono_error_ok (&error)) {
1453                 mono_error_set_pending_exception (&error);
1454                 return NULL;
1455         }
1456         return res;
1457 }
1458
1459 gpointer
1460 mono_fill_method_rgctx (MonoMethodRuntimeGenericContext *mrgctx, int index)
1461 {
1462         MonoError error;
1463         gpointer res;
1464
1465         res = mono_method_fill_runtime_generic_context (mrgctx, index, &error);
1466         if (!mono_error_ok (&error)) {
1467                 mono_error_set_pending_exception (&error);
1468                 return NULL;
1469         }
1470         return res;
1471 }
1472
1473 /*
1474  * resolve_iface_call:
1475  *
1476  *   Return the executable code for the iface method IMT_METHOD called on THIS.
1477  * This function is called on a slowpath, so it doesn't need to be fast.
1478  * This returns an ftnptr by returning the address part, and the arg in the OUT_ARG
1479  * out parameter.
1480  */
1481 static gpointer
1482 resolve_iface_call (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, gpointer *out_arg, gboolean caller_gsharedvt)
1483 {
1484         MonoError error;
1485         MonoVTable *vt;
1486         gpointer *imt, *vtable_slot;
1487         MonoMethod *impl_method, *generic_virtual = NULL, *variant_iface = NULL;
1488         gpointer addr, compiled_method, aot_addr;
1489         gboolean need_rgctx_tramp = FALSE, need_unbox_tramp = FALSE;
1490
1491         if (!this_obj)
1492                 /* The caller will handle it */
1493                 return NULL;
1494
1495         vt = this_obj->vtable;
1496         imt = (gpointer*)vt - MONO_IMT_SIZE;
1497
1498         vtable_slot = mini_resolve_imt_method (vt, imt + imt_slot, imt_method, &impl_method, &aot_addr, &need_rgctx_tramp, &variant_iface);
1499
1500         // FIXME: This can throw exceptions
1501         addr = compiled_method = mono_compile_method_checked (impl_method, &error);
1502         mono_error_assert_ok (&error);
1503         g_assert (addr);
1504
1505         if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst)
1506                 generic_virtual = imt_method;
1507
1508         if (generic_virtual || variant_iface) {
1509                 if (vt->klass->valuetype) /*FIXME is this required variant iface?*/
1510                         need_unbox_tramp = TRUE;
1511         } else {
1512                 if (impl_method->klass->valuetype)
1513                         need_unbox_tramp = TRUE;
1514         }
1515
1516         addr = mini_add_method_wrappers_llvmonly (impl_method, addr, caller_gsharedvt, need_unbox_tramp, out_arg);
1517
1518         if (generic_virtual || variant_iface) {
1519                 MonoMethod *target = generic_virtual ? generic_virtual : variant_iface;
1520
1521                 mono_method_add_generic_virtual_invocation (mono_domain_get (),
1522                                                                                                         vt, imt + imt_slot,
1523                                                                                                         target, addr);
1524         }
1525
1526         return addr;
1527 }
1528
1529 gpointer
1530 mono_resolve_iface_call_gsharedvt (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, gpointer *out_arg)
1531 {
1532         return resolve_iface_call (this_obj, imt_slot, imt_method, out_arg, TRUE);
1533 }
1534
1535 static gboolean
1536 is_generic_method_definition (MonoMethod *m)
1537 {
1538         MonoGenericContext *context;
1539         if (m->is_generic)
1540                 return TRUE;
1541         if (!m->is_inflated)
1542                 return FALSE;
1543
1544         context = mono_method_get_context (m);
1545         if (!context->method_inst)
1546                 return FALSE;
1547         if (context->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)m)->declaring)->context.method_inst)
1548                 return TRUE;
1549         return FALSE;
1550 }
1551
1552 /*
1553  * resolve_vcall:
1554  *
1555  *   Return the executable code for calling vt->vtable [slot].
1556  * This function is called on a slowpath, so it doesn't need to be fast.
1557  * This returns an ftnptr by returning the address part, and the arg in the OUT_ARG
1558  * out parameter.
1559  */
1560 static gpointer
1561 resolve_vcall (MonoVTable *vt, int slot, MonoMethod *imt_method, gpointer *out_arg, gboolean gsharedvt)
1562 {
1563         MonoError error;
1564         MonoMethod *m, *generic_virtual = NULL;
1565         gpointer addr, compiled_method;
1566         gboolean need_unbox_tramp = FALSE;
1567
1568         /* Same as in common_call_trampoline () */
1569
1570         /* Avoid loading metadata or creating a generic vtable if possible */
1571         addr = mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, slot);
1572         if (addr && !vt->klass->valuetype)
1573                 return mono_create_ftnptr (mono_domain_get (), addr);
1574
1575         m = mono_class_get_vtable_entry (vt->klass, slot);
1576
1577         if (is_generic_method_definition (m)) {
1578                 MonoGenericContext context = { NULL, NULL };
1579                 MonoMethod *declaring;
1580
1581                 if (m->is_inflated)
1582                         declaring = mono_method_get_declaring_generic_method (m);
1583                 else
1584                         declaring = m;
1585
1586                 if (m->klass->generic_class)
1587                         context.class_inst = m->klass->generic_class->context.class_inst;
1588                 else
1589                         g_assert (!m->klass->generic_container);
1590
1591                 generic_virtual = imt_method;
1592                 g_assert (generic_virtual);
1593                 g_assert (generic_virtual->is_inflated);
1594                 context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst;
1595
1596                 m = mono_class_inflate_generic_method_checked (declaring, &context, &error);
1597                 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
1598         }
1599
1600         if (generic_virtual) {
1601                 if (vt->klass->valuetype)
1602                         need_unbox_tramp = TRUE;
1603         } else {
1604                 if (m->klass->valuetype)
1605                         need_unbox_tramp = TRUE;
1606         }
1607
1608         // FIXME: This can throw exceptions
1609         addr = compiled_method = mono_compile_method_checked (m, &error);
1610         mono_error_assert_ok (&error);
1611         g_assert (addr);
1612
1613         addr = mini_add_method_wrappers_llvmonly (m, addr, gsharedvt, need_unbox_tramp, out_arg);
1614
1615         if (!gsharedvt && generic_virtual) {
1616                 // FIXME: This wastes memory since add_generic_virtual_invocation ignores it in a lot of cases
1617                 MonoFtnDesc *ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, out_arg);
1618
1619                 mono_method_add_generic_virtual_invocation (mono_domain_get (),
1620                                                                                                         vt, vt->vtable + slot,
1621                                                                                                         generic_virtual, ftndesc);
1622         }
1623
1624         return addr;
1625 }
1626
1627 gpointer
1628 mono_resolve_vcall_gsharedvt (MonoObject *this_obj, int slot, MonoMethod *imt_method, gpointer *out_arg)
1629 {
1630         g_assert (this_obj);
1631
1632         return resolve_vcall (this_obj->vtable, slot, imt_method, out_arg, TRUE);
1633 }
1634
1635 /*
1636  * mono_resolve_generic_virtual_call:
1637  *
1638  *   Resolve a generic virtual call.
1639  * This function is called on a slowpath, so it doesn't need to be fast.
1640  */
1641 MonoFtnDesc*
1642 mono_resolve_generic_virtual_call (MonoVTable *vt, int slot, MonoMethod *generic_virtual)
1643 {
1644         MonoMethod *m;
1645         gpointer addr, compiled_method;
1646         gboolean need_unbox_tramp = FALSE;
1647         MonoError error;
1648         MonoGenericContext context = { NULL, NULL };
1649         MonoMethod *declaring;
1650         gpointer arg = NULL;
1651
1652         m = mono_class_get_vtable_entry (vt->klass, slot);
1653
1654         g_assert (is_generic_method_definition (m));
1655
1656         if (m->is_inflated)
1657                 declaring = mono_method_get_declaring_generic_method (m);
1658         else
1659                 declaring = m;
1660
1661         if (m->klass->generic_class)
1662                 context.class_inst = m->klass->generic_class->context.class_inst;
1663         else
1664                 g_assert (!m->klass->generic_container);
1665
1666         g_assert (generic_virtual->is_inflated);
1667         context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst;
1668
1669         m = mono_class_inflate_generic_method_checked (declaring, &context, &error);
1670         g_assert (mono_error_ok (&error));
1671
1672         if (vt->klass->valuetype)
1673                 need_unbox_tramp = TRUE;
1674
1675         // FIXME: This can throw exceptions
1676         addr = compiled_method = mono_compile_method_checked (m, &error);
1677         mono_error_assert_ok (&error);
1678         g_assert (addr);
1679
1680         addr = mini_add_method_wrappers_llvmonly (m, addr, FALSE, need_unbox_tramp, &arg);
1681
1682         /*
1683          * This wastes memory but the memory usage is bounded since
1684          * mono_method_add_generic_virtual_invocation () eventually builds an imt thunk for
1685          * this vtable slot so we are not called any more for this instantiation.
1686          */
1687         MonoFtnDesc *ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
1688
1689         mono_method_add_generic_virtual_invocation (mono_domain_get (),
1690                                                                                                 vt, vt->vtable + slot,
1691                                                                                                 generic_virtual, ftndesc);
1692         return ftndesc;
1693 }
1694
1695 /*
1696  * mono_resolve_generic_virtual_call:
1697  *
1698  *   Resolve a generic virtual/variant iface call on interfaces.
1699  * This function is called on a slowpath, so it doesn't need to be fast.
1700  */
1701 MonoFtnDesc*
1702 mono_resolve_generic_virtual_iface_call (MonoVTable *vt, int imt_slot, MonoMethod *generic_virtual)
1703 {
1704         MonoError error;
1705         MonoMethod *m, *variant_iface;
1706         gpointer addr, aot_addr, compiled_method;
1707         gboolean need_unbox_tramp = FALSE;
1708         gboolean need_rgctx_tramp;
1709         gpointer arg = NULL;
1710         gpointer *imt;
1711
1712         imt = (gpointer*)vt - MONO_IMT_SIZE;
1713
1714         mini_resolve_imt_method (vt, imt + imt_slot, generic_virtual, &m, &aot_addr, &need_rgctx_tramp, &variant_iface);
1715
1716         if (vt->klass->valuetype)
1717                 need_unbox_tramp = TRUE;
1718
1719         // FIXME: This can throw exceptions
1720         addr = compiled_method = mono_compile_method_checked (m, &error);
1721         mono_error_assert_ok (&error);
1722         g_assert (addr);
1723
1724         addr = mini_add_method_wrappers_llvmonly (m, addr, FALSE, need_unbox_tramp, &arg);
1725
1726         /*
1727          * This wastes memory but the memory usage is bounded since
1728          * mono_method_add_generic_virtual_invocation () eventually builds an imt thunk for
1729          * this vtable slot so we are not called any more for this instantiation.
1730          */
1731         MonoFtnDesc *ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
1732
1733         mono_method_add_generic_virtual_invocation (mono_domain_get (),
1734                                                                                                 vt, imt + imt_slot,
1735                                                                                                 variant_iface ? variant_iface : generic_virtual, ftndesc);
1736         return ftndesc;
1737 }
1738
1739 /*
1740  * mono_init_vtable_slot:
1741  *
1742  *   Initialize slot SLOT of VTABLE.
1743  * Return the contents of the vtable slot.
1744  */
1745 gpointer
1746 mono_init_vtable_slot (MonoVTable *vtable, int slot)
1747 {
1748         gpointer arg = NULL;
1749         gpointer addr;
1750         gpointer *ftnptr;
1751
1752         addr = resolve_vcall (vtable, slot, NULL, &arg, FALSE);
1753         ftnptr = mono_domain_alloc0 (vtable->domain, 2 * sizeof (gpointer));
1754         ftnptr [0] = addr;
1755         ftnptr [1] = arg;
1756         mono_memory_barrier ();
1757
1758         vtable->vtable [slot] = ftnptr;
1759
1760         return ftnptr;
1761 }
1762
1763 /*
1764  * mono_llvmonly_init_delegate:
1765  *
1766  *   Initialize a MonoDelegate object.
1767  * Similar to mono_delegate_ctor ().
1768  */
1769 void
1770 mono_llvmonly_init_delegate (MonoDelegate *del)
1771 {
1772         MonoError error;
1773         MonoFtnDesc *ftndesc = *(MonoFtnDesc**)del->method_code;
1774
1775         /*
1776          * We store a MonoFtnDesc in del->method_code.
1777          * It would be better to store an ftndesc in del->method_ptr too,
1778          * but we don't have a a structure which could own its memory.
1779          */
1780         if (G_UNLIKELY (!ftndesc)) {
1781                 gpointer addr = mono_compile_method_checked (del->method, &error);
1782                 if (mono_error_set_pending_exception (&error))
1783                         return;
1784
1785                 if (del->method->klass->valuetype && mono_method_signature (del->method)->hasthis)
1786                     addr = mono_aot_get_unbox_trampoline (del->method);
1787
1788                 gpointer arg = mini_get_delegate_arg (del->method, addr);
1789
1790                 ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
1791                 mono_memory_barrier ();
1792                 *del->method_code = (gpointer)ftndesc;
1793         }
1794         del->method_ptr = ftndesc->addr;
1795         del->extra_arg = ftndesc->arg;
1796 }
1797
1798 void
1799 mono_llvmonly_init_delegate_virtual (MonoDelegate *del, MonoObject *target, MonoMethod *method)
1800 {
1801         MonoError error;
1802
1803         g_assert (target);
1804
1805         method = mono_object_get_virtual_method (target, method);
1806
1807         del->method = method;
1808         del->method_ptr = mono_compile_method_checked (method, &error);
1809         if (mono_error_set_pending_exception (&error))
1810                 return;
1811         if (method->klass->valuetype)
1812                 del->method_ptr = mono_aot_get_unbox_trampoline (method);
1813         del->extra_arg = mini_get_delegate_arg (del->method, del->method_ptr);
1814 }
1815
1816 MonoObject*
1817 mono_get_assembly_object (MonoImage *image)
1818 {
1819         MonoError error;
1820         MonoObject *result;
1821         result = (MonoObject*)mono_assembly_get_object_checked (mono_domain_get (), image->assembly, &error);
1822         if (!result)
1823                 mono_error_set_pending_exception (&error);
1824         return result;
1825 }
1826
1827 MonoObject*
1828 mono_get_method_object (MonoMethod *method)
1829 {
1830         MonoError error;
1831         MonoObject * result;
1832         result = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), method, method->klass, &error);
1833         mono_error_set_pending_exception (&error);
1834         return result;
1835 }
1836
1837 double
1838 mono_ckfinite (double d)
1839 {
1840         if (isinf (d) || isnan (d))
1841                 mono_set_pending_exception (mono_get_exception_arithmetic ());
1842         return d;
1843 }
1844
1845 /*
1846  * mono_interruption_checkpoint_from_trampoline:
1847  *
1848  *   Check whenever the thread has a pending exception, and throw it
1849  * if needed.
1850  * Architectures should move away from calling this function and
1851  * instead call mono_thread_force_interruption_checkpoint_noraise (),
1852  * rewrind to the parent frame, and throw the exception normally.
1853  */
1854 void
1855 mono_interruption_checkpoint_from_trampoline (void)
1856 {
1857         MonoException *ex;
1858
1859         ex = mono_thread_force_interruption_checkpoint_noraise ();
1860         if (ex)
1861                 mono_raise_exception (ex);
1862 }