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