[runtime] Use mono_assembly_get_object_handle instead of mono_assembly_get_object_che...
[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 (mono_class_is_ginst (res->klass))
76                         context.class_inst = mono_class_get_generic_class (res->klass)->context.class_inst;
77                 else if (mono_class_is_gtd (res->klass))
78                         context.class_inst = mono_class_get_generic_container (res->klass)->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 (!mono_class_is_gtd (vmethod->klass));
1112         g_assert (!mono_class_is_ginst (vmethod->klass) || !mono_class_get_generic_class (vmethod->klass)->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 (mono_class_is_interface (klass)) {
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 (mono_class_is_interface (cmethod->klass)) {
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 (mono_class_is_ginst (m->klass))
1612                         context.class_inst = mono_class_get_generic_class (m->klass)->context.class_inst;
1613                 else
1614                         g_assert (!mono_class_is_gtd (m->klass));
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         if (m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
1634                 m = mono_marshal_get_synchronized_wrapper (m);
1635
1636         // FIXME: This can throw exceptions
1637         addr = compiled_method = mono_compile_method_checked (m, error);
1638         mono_error_assert_ok (error);
1639         g_assert (addr);
1640
1641         addr = mini_add_method_wrappers_llvmonly (m, addr, gsharedvt, need_unbox_tramp, out_arg);
1642
1643         if (!gsharedvt && generic_virtual) {
1644                 // FIXME: This wastes memory since add_generic_virtual_invocation ignores it in a lot of cases
1645                 MonoFtnDesc *ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, out_arg);
1646
1647                 mono_method_add_generic_virtual_invocation (mono_domain_get (),
1648                                                                                                         vt, vt->vtable + slot,
1649                                                                                                         generic_virtual, ftndesc);
1650         }
1651
1652         return addr;
1653 }
1654
1655 gpointer
1656 mono_resolve_vcall_gsharedvt (MonoObject *this_obj, int slot, MonoMethod *imt_method, gpointer *out_arg)
1657 {
1658         g_assert (this_obj);
1659
1660         MonoError error;
1661         gpointer result = resolve_vcall (this_obj->vtable, slot, imt_method, out_arg, TRUE, &error);
1662         if (!is_ok (&error)) {
1663                 MonoException *ex = mono_error_convert_to_exception (&error);
1664                 mono_llvm_throw_exception ((MonoObject*)ex);
1665         }
1666         return result;
1667 }
1668
1669 /*
1670  * mono_resolve_generic_virtual_call:
1671  *
1672  *   Resolve a generic virtual call.
1673  * This function is called on a slowpath, so it doesn't need to be fast.
1674  */
1675 MonoFtnDesc*
1676 mono_resolve_generic_virtual_call (MonoVTable *vt, int slot, MonoMethod *generic_virtual)
1677 {
1678         MonoMethod *m;
1679         gpointer addr, compiled_method;
1680         gboolean need_unbox_tramp = FALSE;
1681         MonoError error;
1682         MonoGenericContext context = { NULL, NULL };
1683         MonoMethod *declaring;
1684         gpointer arg = NULL;
1685
1686         m = mono_class_get_vtable_entry (vt->klass, slot);
1687
1688         g_assert (is_generic_method_definition (m));
1689
1690         if (m->is_inflated)
1691                 declaring = mono_method_get_declaring_generic_method (m);
1692         else
1693                 declaring = m;
1694
1695         if (mono_class_is_ginst (m->klass))
1696                 context.class_inst = mono_class_get_generic_class (m->klass)->context.class_inst;
1697         else
1698                 g_assert (!mono_class_is_gtd (m->klass));
1699
1700         g_assert (generic_virtual->is_inflated);
1701         context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst;
1702
1703         m = mono_class_inflate_generic_method_checked (declaring, &context, &error);
1704         g_assert (mono_error_ok (&error));
1705
1706         if (vt->klass->valuetype)
1707                 need_unbox_tramp = TRUE;
1708
1709         // FIXME: This can throw exceptions
1710         addr = compiled_method = mono_compile_method_checked (m, &error);
1711         mono_error_assert_ok (&error);
1712         g_assert (addr);
1713
1714         addr = mini_add_method_wrappers_llvmonly (m, addr, FALSE, need_unbox_tramp, &arg);
1715
1716         /*
1717          * This wastes memory but the memory usage is bounded since
1718          * mono_method_add_generic_virtual_invocation () eventually builds an imt trampoline for
1719          * this vtable slot so we are not called any more for this instantiation.
1720          */
1721         MonoFtnDesc *ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
1722
1723         mono_method_add_generic_virtual_invocation (mono_domain_get (),
1724                                                                                                 vt, vt->vtable + slot,
1725                                                                                                 generic_virtual, ftndesc);
1726         return ftndesc;
1727 }
1728
1729 /*
1730  * mono_resolve_generic_virtual_call:
1731  *
1732  *   Resolve a generic virtual/variant iface call on interfaces.
1733  * This function is called on a slowpath, so it doesn't need to be fast.
1734  */
1735 MonoFtnDesc*
1736 mono_resolve_generic_virtual_iface_call (MonoVTable *vt, int imt_slot, MonoMethod *generic_virtual)
1737 {
1738         MonoError error;
1739         MonoMethod *m, *variant_iface;
1740         gpointer addr, aot_addr, compiled_method;
1741         gboolean need_unbox_tramp = FALSE;
1742         gboolean need_rgctx_tramp;
1743         gpointer arg = NULL;
1744         gpointer *imt;
1745
1746         imt = (gpointer*)vt - MONO_IMT_SIZE;
1747
1748         mini_resolve_imt_method (vt, imt + imt_slot, generic_virtual, &m, &aot_addr, &need_rgctx_tramp, &variant_iface, &error);
1749         if (!is_ok (&error)) {
1750                 MonoException *ex = mono_error_convert_to_exception (&error);
1751                 mono_llvm_throw_exception ((MonoObject*)ex);
1752         }
1753
1754         if (vt->klass->valuetype)
1755                 need_unbox_tramp = TRUE;
1756
1757         if (m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
1758                 m = mono_marshal_get_synchronized_wrapper (m);
1759
1760         addr = compiled_method = mono_compile_method_checked (m, &error);
1761         mono_error_raise_exception (&error);
1762         g_assert (addr);
1763
1764         addr = mini_add_method_wrappers_llvmonly (m, addr, FALSE, need_unbox_tramp, &arg);
1765
1766         /*
1767          * This wastes memory but the memory usage is bounded since
1768          * mono_method_add_generic_virtual_invocation () eventually builds an imt trampoline for
1769          * this vtable slot so we are not called any more for this instantiation.
1770          */
1771         MonoFtnDesc *ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
1772
1773         mono_method_add_generic_virtual_invocation (mono_domain_get (),
1774                                                                                                 vt, imt + imt_slot,
1775                                                                                                 variant_iface ? variant_iface : generic_virtual, ftndesc);
1776         return ftndesc;
1777 }
1778
1779 /*
1780  * mono_init_vtable_slot:
1781  *
1782  *   Initialize slot SLOT of VTABLE.
1783  * Return the contents of the vtable slot.
1784  */
1785 gpointer
1786 mono_init_vtable_slot (MonoVTable *vtable, int slot)
1787 {
1788         MonoError error;
1789         gpointer arg = NULL;
1790         gpointer addr;
1791         gpointer *ftnptr;
1792
1793         addr = resolve_vcall (vtable, slot, NULL, &arg, FALSE, &error);
1794         if (mono_error_set_pending_exception (&error))
1795                 return NULL;
1796         ftnptr = mono_domain_alloc0 (vtable->domain, 2 * sizeof (gpointer));
1797         ftnptr [0] = addr;
1798         ftnptr [1] = arg;
1799         mono_memory_barrier ();
1800
1801         vtable->vtable [slot] = ftnptr;
1802
1803         return ftnptr;
1804 }
1805
1806 /*
1807  * mono_llvmonly_init_delegate:
1808  *
1809  *   Initialize a MonoDelegate object.
1810  * Similar to mono_delegate_ctor ().
1811  */
1812 void
1813 mono_llvmonly_init_delegate (MonoDelegate *del)
1814 {
1815         MonoError error;
1816         MonoFtnDesc *ftndesc = *(MonoFtnDesc**)del->method_code;
1817
1818         /*
1819          * We store a MonoFtnDesc in del->method_code.
1820          * It would be better to store an ftndesc in del->method_ptr too,
1821          * but we don't have a a structure which could own its memory.
1822          */
1823         if (G_UNLIKELY (!ftndesc)) {
1824                 MonoMethod *m = del->method;
1825                 if (m->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
1826                         m = mono_marshal_get_synchronized_wrapper (m);
1827
1828                 gpointer addr = mono_compile_method_checked (m, &error);
1829                 if (mono_error_set_pending_exception (&error))
1830                         return;
1831
1832                 if (m->klass->valuetype && mono_method_signature (m)->hasthis)
1833                     addr = mono_aot_get_unbox_trampoline (m);
1834
1835                 gpointer arg = mini_get_delegate_arg (del->method, addr);
1836
1837                 ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
1838                 mono_memory_barrier ();
1839                 *del->method_code = (gpointer)ftndesc;
1840         }
1841         del->method_ptr = ftndesc->addr;
1842         del->extra_arg = ftndesc->arg;
1843 }
1844
1845 void
1846 mono_llvmonly_init_delegate_virtual (MonoDelegate *del, MonoObject *target, MonoMethod *method)
1847 {
1848         MonoError error;
1849
1850         g_assert (target);
1851
1852         method = mono_object_get_virtual_method (target, method);
1853
1854         if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
1855                 method = mono_marshal_get_synchronized_wrapper (method);
1856
1857         del->method = method;
1858         del->method_ptr = mono_compile_method_checked (method, &error);
1859         if (mono_error_set_pending_exception (&error))
1860                 return;
1861         if (method->klass->valuetype)
1862                 del->method_ptr = mono_aot_get_unbox_trampoline (method);
1863         del->extra_arg = mini_get_delegate_arg (del->method, del->method_ptr);
1864 }
1865
1866 MonoObject*
1867 mono_get_assembly_object (MonoImage *image)
1868 {
1869         ICALL_ENTRY();
1870         MonoObjectHandle result = MONO_HANDLE_CAST (MonoObject, mono_assembly_get_object_handle (mono_domain_get (), image->assembly, &error));
1871         ICALL_RETURN_OBJ (result);
1872 }
1873
1874 MonoObject*
1875 mono_get_method_object (MonoMethod *method)
1876 {
1877         MonoError error;
1878         MonoObject * result;
1879         result = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), method, method->klass, &error);
1880         mono_error_set_pending_exception (&error);
1881         return result;
1882 }
1883
1884 double
1885 mono_ckfinite (double d)
1886 {
1887         if (isinf (d) || isnan (d))
1888                 mono_set_pending_exception (mono_get_exception_arithmetic ());
1889         return d;
1890 }
1891
1892 /*
1893  * mono_interruption_checkpoint_from_trampoline:
1894  *
1895  *   Check whenever the thread has a pending exception, and throw it
1896  * if needed.
1897  * Architectures should move away from calling this function and
1898  * instead call mono_thread_force_interruption_checkpoint_noraise (),
1899  * rewrind to the parent frame, and throw the exception normally.
1900  */
1901 void
1902 mono_interruption_checkpoint_from_trampoline (void)
1903 {
1904         MonoException *ex;
1905
1906         ex = mono_thread_force_interruption_checkpoint_noraise ();
1907         if (ex)
1908                 mono_raise_exception (ex);
1909 }
1910
1911 void
1912 mono_throw_method_access (MonoMethod *callee, MonoMethod *caller)
1913 {
1914         char *callee_name = mono_method_full_name (callee, 1);
1915         char *caller_name = mono_method_full_name (caller, 1);
1916         MonoError error;
1917
1918         mono_error_init (&error);
1919         mono_error_set_generic_error (&error, "System", "MethodAccessException", "Method `%s' is inaccessible from method `%s'\n", callee_name, caller_name);
1920         mono_error_set_pending_exception (&error);
1921         g_free (callee_name);
1922         g_free (caller_name);
1923 }
1924
1925 void
1926 mono_dummy_jit_icall (void)
1927 {
1928 }