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