Merge pull request #3144 from Unity-Technologies/fix-recursive-property-call
[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, MonoError *error)
1500 {
1501         MonoVTable *vt;
1502         gpointer *imt, *vtable_slot;
1503         MonoMethod *impl_method, *generic_virtual = NULL, *variant_iface = NULL;
1504         gpointer addr, compiled_method, aot_addr;
1505         gboolean need_rgctx_tramp = FALSE, need_unbox_tramp = FALSE;
1506
1507         mono_error_init (error);
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, error);
1516         return_val_if_nok (error, NULL);
1517
1518         // FIXME: This can throw exceptions
1519         addr = compiled_method = mono_compile_method_checked (impl_method, error);
1520         mono_error_assert_ok (error);
1521         g_assert (addr);
1522
1523         if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst)
1524                 generic_virtual = imt_method;
1525
1526         if (generic_virtual || variant_iface) {
1527                 if (vt->klass->valuetype) /*FIXME is this required variant iface?*/
1528                         need_unbox_tramp = TRUE;
1529         } else {
1530                 if (impl_method->klass->valuetype)
1531                         need_unbox_tramp = TRUE;
1532         }
1533
1534         addr = mini_add_method_wrappers_llvmonly (impl_method, addr, caller_gsharedvt, need_unbox_tramp, out_arg);
1535
1536         if (generic_virtual || variant_iface) {
1537                 MonoMethod *target = generic_virtual ? generic_virtual : variant_iface;
1538
1539                 mono_method_add_generic_virtual_invocation (mono_domain_get (),
1540                                                                                                         vt, imt + imt_slot,
1541                                                                                                         target, addr);
1542         }
1543
1544         return addr;
1545 }
1546
1547 gpointer
1548 mono_resolve_iface_call_gsharedvt (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, gpointer *out_arg)
1549 {
1550         MonoError error;
1551         gpointer res = resolve_iface_call (this_obj, imt_slot, imt_method, out_arg, TRUE, &error);
1552         if (!is_ok (&error)) {
1553                 MonoException *ex = mono_error_convert_to_exception (&error);
1554                 mono_llvm_throw_exception ((MonoObject*)ex);
1555         }
1556         return res;
1557 }
1558
1559 static gboolean
1560 is_generic_method_definition (MonoMethod *m)
1561 {
1562         MonoGenericContext *context;
1563         if (m->is_generic)
1564                 return TRUE;
1565         if (!m->is_inflated)
1566                 return FALSE;
1567
1568         context = mono_method_get_context (m);
1569         if (!context->method_inst)
1570                 return FALSE;
1571         if (context->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)m)->declaring)->context.method_inst)
1572                 return TRUE;
1573         return FALSE;
1574 }
1575
1576 /*
1577  * resolve_vcall:
1578  *
1579  *   Return the executable code for calling vt->vtable [slot].
1580  * This function is called on a slowpath, so it doesn't need to be fast.
1581  * This returns an ftnptr by returning the address part, and the arg in the OUT_ARG
1582  * out parameter.
1583  */
1584 static gpointer
1585 resolve_vcall (MonoVTable *vt, int slot, MonoMethod *imt_method, gpointer *out_arg, gboolean gsharedvt, MonoError *error)
1586 {
1587         MonoMethod *m, *generic_virtual = NULL;
1588         gpointer addr, compiled_method;
1589         gboolean need_unbox_tramp = FALSE;
1590
1591         mono_error_init (error);
1592         /* Same as in common_call_trampoline () */
1593
1594         /* Avoid loading metadata or creating a generic vtable if possible */
1595         addr = mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, slot, error);
1596         return_val_if_nok (error, NULL);
1597         if (addr && !vt->klass->valuetype)
1598                 return mono_create_ftnptr (mono_domain_get (), addr);
1599
1600         m = mono_class_get_vtable_entry (vt->klass, slot);
1601
1602         if (is_generic_method_definition (m)) {
1603                 MonoGenericContext context = { NULL, NULL };
1604                 MonoMethod *declaring;
1605
1606                 if (m->is_inflated)
1607                         declaring = mono_method_get_declaring_generic_method (m);
1608                 else
1609                         declaring = m;
1610
1611                 if (m->klass->generic_class)
1612                         context.class_inst = m->klass->generic_class->context.class_inst;
1613                 else
1614                         g_assert (!m->klass->generic_container);
1615
1616                 generic_virtual = imt_method;
1617                 g_assert (generic_virtual);
1618                 g_assert (generic_virtual->is_inflated);
1619                 context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst;
1620
1621                 m = mono_class_inflate_generic_method_checked (declaring, &context, error);
1622                 mono_error_assert_ok (error); /* FIXME don't swallow the error */
1623         }
1624
1625         if (generic_virtual) {
1626                 if (vt->klass->valuetype)
1627                         need_unbox_tramp = TRUE;
1628         } else {
1629                 if (m->klass->valuetype)
1630                         need_unbox_tramp = TRUE;
1631         }
1632
1633         // FIXME: This can throw exceptions
1634         addr = compiled_method = mono_compile_method_checked (m, error);
1635         mono_error_assert_ok (error);
1636         g_assert (addr);
1637
1638         addr = mini_add_method_wrappers_llvmonly (m, addr, gsharedvt, need_unbox_tramp, out_arg);
1639
1640         if (!gsharedvt && generic_virtual) {
1641                 // FIXME: This wastes memory since add_generic_virtual_invocation ignores it in a lot of cases
1642                 MonoFtnDesc *ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, out_arg);
1643
1644                 mono_method_add_generic_virtual_invocation (mono_domain_get (),
1645                                                                                                         vt, vt->vtable + slot,
1646                                                                                                         generic_virtual, ftndesc);
1647         }
1648
1649         return addr;
1650 }
1651
1652 gpointer
1653 mono_resolve_vcall_gsharedvt (MonoObject *this_obj, int slot, MonoMethod *imt_method, gpointer *out_arg)
1654 {
1655         g_assert (this_obj);
1656
1657         MonoError error;
1658         gpointer result = resolve_vcall (this_obj->vtable, slot, imt_method, out_arg, TRUE, &error);
1659         if (!is_ok (&error)) {
1660                 MonoException *ex = mono_error_convert_to_exception (&error);
1661                 mono_llvm_throw_exception ((MonoObject*)ex);
1662         }
1663         return result;
1664 }
1665
1666 /*
1667  * mono_resolve_generic_virtual_call:
1668  *
1669  *   Resolve a generic virtual call.
1670  * This function is called on a slowpath, so it doesn't need to be fast.
1671  */
1672 MonoFtnDesc*
1673 mono_resolve_generic_virtual_call (MonoVTable *vt, int slot, MonoMethod *generic_virtual)
1674 {
1675         MonoMethod *m;
1676         gpointer addr, compiled_method;
1677         gboolean need_unbox_tramp = FALSE;
1678         MonoError error;
1679         MonoGenericContext context = { NULL, NULL };
1680         MonoMethod *declaring;
1681         gpointer arg = NULL;
1682
1683         m = mono_class_get_vtable_entry (vt->klass, slot);
1684
1685         g_assert (is_generic_method_definition (m));
1686
1687         if (m->is_inflated)
1688                 declaring = mono_method_get_declaring_generic_method (m);
1689         else
1690                 declaring = m;
1691
1692         if (m->klass->generic_class)
1693                 context.class_inst = m->klass->generic_class->context.class_inst;
1694         else
1695                 g_assert (!m->klass->generic_container);
1696
1697         g_assert (generic_virtual->is_inflated);
1698         context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst;
1699
1700         m = mono_class_inflate_generic_method_checked (declaring, &context, &error);
1701         g_assert (mono_error_ok (&error));
1702
1703         if (vt->klass->valuetype)
1704                 need_unbox_tramp = TRUE;
1705
1706         // FIXME: This can throw exceptions
1707         addr = compiled_method = mono_compile_method_checked (m, &error);
1708         mono_error_assert_ok (&error);
1709         g_assert (addr);
1710
1711         addr = mini_add_method_wrappers_llvmonly (m, addr, FALSE, need_unbox_tramp, &arg);
1712
1713         /*
1714          * This wastes memory but the memory usage is bounded since
1715          * mono_method_add_generic_virtual_invocation () eventually builds an imt thunk for
1716          * this vtable slot so we are not called any more for this instantiation.
1717          */
1718         MonoFtnDesc *ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
1719
1720         mono_method_add_generic_virtual_invocation (mono_domain_get (),
1721                                                                                                 vt, vt->vtable + slot,
1722                                                                                                 generic_virtual, ftndesc);
1723         return ftndesc;
1724 }
1725
1726 /*
1727  * mono_resolve_generic_virtual_call:
1728  *
1729  *   Resolve a generic virtual/variant iface call on interfaces.
1730  * This function is called on a slowpath, so it doesn't need to be fast.
1731  */
1732 MonoFtnDesc*
1733 mono_resolve_generic_virtual_iface_call (MonoVTable *vt, int imt_slot, MonoMethod *generic_virtual)
1734 {
1735         MonoError error;
1736         MonoMethod *m, *variant_iface;
1737         gpointer addr, aot_addr, compiled_method;
1738         gboolean need_unbox_tramp = FALSE;
1739         gboolean need_rgctx_tramp;
1740         gpointer arg = NULL;
1741         gpointer *imt;
1742
1743         imt = (gpointer*)vt - MONO_IMT_SIZE;
1744
1745         mini_resolve_imt_method (vt, imt + imt_slot, generic_virtual, &m, &aot_addr, &need_rgctx_tramp, &variant_iface, &error);
1746         if (!is_ok (&error)) {
1747                 MonoException *ex = mono_error_convert_to_exception (&error);
1748                 mono_llvm_throw_exception ((MonoObject*)ex);
1749         }
1750
1751         if (vt->klass->valuetype)
1752                 need_unbox_tramp = TRUE;
1753
1754         // FIXME: This can throw exceptions
1755         addr = compiled_method = mono_compile_method_checked (m, &error);
1756         mono_error_assert_ok (&error);
1757         g_assert (addr);
1758
1759         addr = mini_add_method_wrappers_llvmonly (m, addr, FALSE, need_unbox_tramp, &arg);
1760
1761         /*
1762          * This wastes memory but the memory usage is bounded since
1763          * mono_method_add_generic_virtual_invocation () eventually builds an imt thunk for
1764          * this vtable slot so we are not called any more for this instantiation.
1765          */
1766         MonoFtnDesc *ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
1767
1768         mono_method_add_generic_virtual_invocation (mono_domain_get (),
1769                                                                                                 vt, imt + imt_slot,
1770                                                                                                 variant_iface ? variant_iface : generic_virtual, ftndesc);
1771         return ftndesc;
1772 }
1773
1774 /*
1775  * mono_init_vtable_slot:
1776  *
1777  *   Initialize slot SLOT of VTABLE.
1778  * Return the contents of the vtable slot.
1779  */
1780 gpointer
1781 mono_init_vtable_slot (MonoVTable *vtable, int slot)
1782 {
1783         MonoError error;
1784         gpointer arg = NULL;
1785         gpointer addr;
1786         gpointer *ftnptr;
1787
1788         addr = resolve_vcall (vtable, slot, NULL, &arg, FALSE, &error);
1789         if (mono_error_set_pending_exception (&error))
1790                 return NULL;
1791         ftnptr = mono_domain_alloc0 (vtable->domain, 2 * sizeof (gpointer));
1792         ftnptr [0] = addr;
1793         ftnptr [1] = arg;
1794         mono_memory_barrier ();
1795
1796         vtable->vtable [slot] = ftnptr;
1797
1798         return ftnptr;
1799 }
1800
1801 /*
1802  * mono_llvmonly_init_delegate:
1803  *
1804  *   Initialize a MonoDelegate object.
1805  * Similar to mono_delegate_ctor ().
1806  */
1807 void
1808 mono_llvmonly_init_delegate (MonoDelegate *del)
1809 {
1810         MonoError error;
1811         MonoFtnDesc *ftndesc = *(MonoFtnDesc**)del->method_code;
1812
1813         /*
1814          * We store a MonoFtnDesc in del->method_code.
1815          * It would be better to store an ftndesc in del->method_ptr too,
1816          * but we don't have a a structure which could own its memory.
1817          */
1818         if (G_UNLIKELY (!ftndesc)) {
1819                 gpointer addr = mono_compile_method_checked (del->method, &error);
1820                 if (mono_error_set_pending_exception (&error))
1821                         return;
1822
1823                 if (del->method->klass->valuetype && mono_method_signature (del->method)->hasthis)
1824                     addr = mono_aot_get_unbox_trampoline (del->method);
1825
1826                 gpointer arg = mini_get_delegate_arg (del->method, addr);
1827
1828                 ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
1829                 mono_memory_barrier ();
1830                 *del->method_code = (gpointer)ftndesc;
1831         }
1832         del->method_ptr = ftndesc->addr;
1833         del->extra_arg = ftndesc->arg;
1834 }
1835
1836 void
1837 mono_llvmonly_init_delegate_virtual (MonoDelegate *del, MonoObject *target, MonoMethod *method)
1838 {
1839         MonoError error;
1840
1841         g_assert (target);
1842
1843         method = mono_object_get_virtual_method (target, method);
1844
1845         del->method = method;
1846         del->method_ptr = mono_compile_method_checked (method, &error);
1847         if (mono_error_set_pending_exception (&error))
1848                 return;
1849         if (method->klass->valuetype)
1850                 del->method_ptr = mono_aot_get_unbox_trampoline (method);
1851         del->extra_arg = mini_get_delegate_arg (del->method, del->method_ptr);
1852 }
1853
1854 MonoObject*
1855 mono_get_assembly_object (MonoImage *image)
1856 {
1857         MonoError error;
1858         MonoObject *result;
1859         result = (MonoObject*)mono_assembly_get_object_checked (mono_domain_get (), image->assembly, &error);
1860         if (!result)
1861                 mono_error_set_pending_exception (&error);
1862         return result;
1863 }
1864
1865 MonoObject*
1866 mono_get_method_object (MonoMethod *method)
1867 {
1868         MonoError error;
1869         MonoObject * result;
1870         result = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), method, method->klass, &error);
1871         mono_error_set_pending_exception (&error);
1872         return result;
1873 }
1874
1875 double
1876 mono_ckfinite (double d)
1877 {
1878         if (isinf (d) || isnan (d))
1879                 mono_set_pending_exception (mono_get_exception_arithmetic ());
1880         return d;
1881 }
1882
1883 /*
1884  * mono_interruption_checkpoint_from_trampoline:
1885  *
1886  *   Check whenever the thread has a pending exception, and throw it
1887  * if needed.
1888  * Architectures should move away from calling this function and
1889  * instead call mono_thread_force_interruption_checkpoint_noraise (),
1890  * rewrind to the parent frame, and throw the exception normally.
1891  */
1892 void
1893 mono_interruption_checkpoint_from_trampoline (void)
1894 {
1895         MonoException *ex;
1896
1897         ex = mono_thread_force_interruption_checkpoint_noraise ();
1898         if (ex)
1899                 mono_raise_exception (ex);
1900 }
1901
1902 void
1903 mono_throw_method_access (MonoMethod *callee, MonoMethod *caller)
1904 {
1905         char *callee_name = mono_method_full_name (callee, 1);
1906         char *caller_name = mono_method_full_name (caller, 1);
1907         MonoError error;
1908
1909         mono_error_init (&error);
1910         mono_error_set_generic_error (&error, "System", "MethodAccessException", "Method `%s' is inaccessible from method `%s'\n", callee_name, caller_name);
1911         mono_error_set_pending_exception (&error);
1912         g_free (callee_name);
1913         g_free (caller_name);
1914 }