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