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