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