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