Merge pull request #2815 from lambdageek/dev/monoerror-mono_compile_method
[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 mono_helper_ldstr (MonoImage *image, guint32 idx)
1131 {
1132         return mono_ldstr (mono_domain_get (), image, idx);
1133 }
1134
1135 MonoString*
1136 mono_helper_ldstr_mscorlib (guint32 idx)
1137 {
1138         return mono_ldstr (mono_domain_get (), mono_defaults.corlib, idx);
1139 }
1140
1141 MonoObject*
1142 mono_helper_newobj_mscorlib (guint32 idx)
1143 {
1144         MonoError error;
1145         MonoClass *klass = mono_class_get_checked (mono_defaults.corlib, MONO_TOKEN_TYPE_DEF | idx, &error);
1146
1147         if (!mono_error_ok (&error)) {
1148                 mono_error_set_pending_exception (&error);
1149                 return NULL;
1150         }
1151
1152         MonoObject *obj = mono_object_new_checked (mono_domain_get (), klass, &error);
1153         if (!mono_error_ok (&error))
1154                 mono_error_set_pending_exception (&error);
1155         return obj;
1156 }
1157
1158 /*
1159  * On some architectures, gdb doesn't like encountering the cpu breakpoint instructions
1160  * in generated code. So instead we emit a call to this function and place a gdb
1161  * breakpoint here.
1162  */
1163 void
1164 mono_break (void)
1165 {
1166 }
1167
1168 MonoException *
1169 mono_create_corlib_exception_0 (guint32 token)
1170 {
1171         return mono_exception_from_token (mono_defaults.corlib, token);
1172 }
1173
1174 MonoException *
1175 mono_create_corlib_exception_1 (guint32 token, MonoString *arg)
1176 {
1177         return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg, NULL);
1178 }
1179
1180 MonoException *
1181 mono_create_corlib_exception_2 (guint32 token, MonoString *arg1, MonoString *arg2)
1182 {
1183         return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg1, arg2);
1184 }
1185
1186 MonoObject*
1187 mono_object_castclass_unbox (MonoObject *obj, MonoClass *klass)
1188 {
1189         MonoError error;
1190         MonoJitTlsData *jit_tls = NULL;
1191         MonoClass *oklass;
1192
1193         if (mini_get_debug_options ()->better_cast_details) {
1194                 jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
1195                 jit_tls->class_cast_from = NULL;
1196         }
1197
1198         if (!obj)
1199                 return NULL;
1200
1201         oklass = obj->vtable->klass;
1202         if ((klass->enumtype && oklass == klass->element_class) || (oklass->enumtype && klass == oklass->element_class))
1203                 return obj;
1204         if (mono_object_isinst_checked (obj, klass, &error))
1205                 return obj;
1206         if (mono_error_set_pending_exception (&error))
1207                 return NULL;
1208
1209         if (mini_get_debug_options ()->better_cast_details) {
1210                 jit_tls->class_cast_from = oklass;
1211                 jit_tls->class_cast_to = klass;
1212         }
1213
1214         mono_set_pending_exception (mono_exception_from_name (mono_defaults.corlib,
1215                                         "System", "InvalidCastException"));
1216
1217         return NULL;
1218 }
1219
1220 MonoObject*
1221 mono_object_castclass_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cache)
1222 {
1223         MonoError error;
1224         MonoJitTlsData *jit_tls = NULL;
1225         gpointer cached_vtable, obj_vtable;
1226
1227         if (mini_get_debug_options ()->better_cast_details) {
1228                 jit_tls = (MonoJitTlsData *)mono_native_tls_get_value (mono_jit_tls_id);
1229                 jit_tls->class_cast_from = NULL;
1230         }
1231
1232         if (!obj)
1233                 return NULL;
1234
1235         cached_vtable = *cache;
1236         obj_vtable = obj->vtable;
1237
1238         if (cached_vtable == obj_vtable)
1239                 return obj;
1240
1241         if (mono_object_isinst_checked (obj, klass, &error)) {
1242                 *cache = obj_vtable;
1243                 return obj;
1244         }
1245         if (mono_error_set_pending_exception (&error))
1246                 return NULL;
1247
1248         if (mini_get_debug_options ()->better_cast_details) {
1249                 jit_tls->class_cast_from = obj->vtable->klass;
1250                 jit_tls->class_cast_to = klass;
1251         }
1252
1253         mono_set_pending_exception (mono_exception_from_name (mono_defaults.corlib,
1254                                         "System", "InvalidCastException"));
1255
1256         return NULL;
1257 }
1258
1259 MonoObject*
1260 mono_object_isinst_with_cache (MonoObject *obj, MonoClass *klass, gpointer *cache)
1261 {
1262         MonoError error;
1263         size_t cached_vtable, obj_vtable;
1264
1265         if (!obj)
1266                 return NULL;
1267
1268         cached_vtable = (size_t)*cache;
1269         obj_vtable = (size_t)obj->vtable;
1270
1271         if ((cached_vtable & ~0x1) == obj_vtable) {
1272                 return (cached_vtable & 0x1) ? NULL : obj;
1273         }
1274
1275         if (mono_object_isinst_checked (obj, klass, &error)) {
1276                 *cache = (gpointer)obj_vtable;
1277                 return obj;
1278         } else {
1279                 if (mono_error_set_pending_exception (&error))
1280                         return NULL;
1281                 /*negative cache*/
1282                 *cache = (gpointer)(obj_vtable | 0x1);
1283                 return NULL;
1284         }
1285 }
1286
1287 gpointer
1288 mono_get_native_calli_wrapper (MonoImage *image, MonoMethodSignature *sig, gpointer func)
1289 {
1290         MonoError error;
1291         MonoMarshalSpec **mspecs;
1292         MonoMethodPInvoke piinfo;
1293         MonoMethod *m;
1294
1295         mspecs = g_new0 (MonoMarshalSpec*, sig->param_count + 1);
1296         memset (&piinfo, 0, sizeof (piinfo));
1297
1298         m = mono_marshal_get_native_func_wrapper (image, sig, &piinfo, mspecs, func);
1299
1300         gpointer compiled_ptr = mono_compile_method_checked (m, &error);
1301         mono_error_set_pending_exception (&error);
1302         return compiled_ptr;
1303 }
1304
1305 static MonoMethod*
1306 constrained_gsharedvt_call_setup (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gpointer *this_arg, MonoError *error)
1307 {
1308         MonoMethod *m;
1309         int vt_slot, iface_offset;
1310
1311         mono_error_init (error);
1312
1313         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1314                 MonoObject *this_obj;
1315
1316                 /* Have to use the receiver's type instead of klass, the receiver is a ref type */
1317                 this_obj = *(MonoObject**)mp;
1318                 g_assert (this_obj);
1319
1320                 klass = this_obj->vtable->klass;
1321         }
1322
1323         if (mono_method_signature (cmethod)->pinvoke) {
1324                 /* Object.GetType () */
1325                 m = mono_marshal_get_native_wrapper (cmethod, TRUE, FALSE);
1326         } else {
1327                 /* Lookup the virtual method */
1328                 mono_class_setup_vtable (klass);
1329                 g_assert (klass->vtable);
1330                 vt_slot = mono_method_get_vtable_slot (cmethod);
1331                 if (cmethod->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
1332                         iface_offset = mono_class_interface_offset (klass, cmethod->klass);
1333                         g_assert (iface_offset != -1);
1334                         vt_slot += iface_offset;
1335                 }
1336                 m = klass->vtable [vt_slot];
1337                 if (cmethod->is_inflated)
1338                         m = mono_class_inflate_generic_method (m, mono_method_get_context (cmethod));
1339         }
1340
1341         if (klass->valuetype && (m->klass == mono_defaults.object_class || m->klass == mono_defaults.enum_class->parent || m->klass == mono_defaults.enum_class))
1342                 /*
1343                  * Calling a non-vtype method with a vtype receiver, has to box.
1344                  */
1345                 *this_arg = mono_value_box_checked (mono_domain_get (), klass, mp, error);
1346         else if (klass->valuetype)
1347                 /*
1348                  * Calling a vtype method with a vtype receiver
1349                  */
1350                 *this_arg = mp;
1351         else
1352                 /*
1353                  * Calling a non-vtype method
1354                  */
1355                 *this_arg = *(gpointer*)mp;
1356         return m;
1357 }
1358
1359 /*
1360  * mono_gsharedvt_constrained_call:
1361  *
1362  *   Make a call to CMETHOD using the receiver MP, which is assumed to be of type KLASS. ARGS contains
1363  * the arguments to the method in the format used by mono_runtime_invoke_checked ().
1364  */
1365 MonoObject*
1366 mono_gsharedvt_constrained_call (gpointer mp, MonoMethod *cmethod, MonoClass *klass, gboolean deref_arg, gpointer *args)
1367 {
1368         MonoError error;
1369         MonoObject *o;
1370         MonoMethod *m;
1371         gpointer this_arg;
1372         gpointer new_args [16];
1373
1374         m = constrained_gsharedvt_call_setup (mp, cmethod, klass, &this_arg, &error);
1375         if (!mono_error_ok (&error)) {
1376                 mono_error_set_pending_exception (&error);
1377                 return NULL;
1378         }
1379
1380         if (!m)
1381                 return NULL;
1382         if (args && deref_arg) {
1383                 new_args [0] = *(gpointer*)args [0];
1384                 args = new_args;
1385         }
1386         if (m->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
1387                 /* Object.GetType () */
1388                 args = new_args;
1389                 args [0] = this_arg;
1390                 this_arg = NULL;
1391         }
1392
1393         o = mono_runtime_invoke_checked (m, this_arg, args, &error);
1394         if (!mono_error_ok (&error)) {
1395                 mono_error_set_pending_exception (&error);
1396                 return NULL;
1397         }
1398
1399         return o;
1400 }
1401
1402 void
1403 mono_gsharedvt_value_copy (gpointer dest, gpointer src, MonoClass *klass)
1404 {
1405         if (klass->valuetype)
1406                 mono_value_copy (dest, src, klass);
1407         else
1408         mono_gc_wbarrier_generic_store (dest, *(MonoObject**)src);
1409 }
1410
1411 void
1412 ves_icall_runtime_class_init (MonoVTable *vtable)
1413 {
1414         MONO_REQ_GC_UNSAFE_MODE;
1415         MonoError error;
1416
1417         mono_runtime_class_init_full (vtable, &error);
1418         mono_error_set_pending_exception (&error);
1419 }
1420
1421
1422 void
1423 mono_generic_class_init (MonoVTable *vtable)
1424 {
1425         MonoError error;
1426         mono_runtime_class_init_full (vtable, &error);
1427         mono_error_set_pending_exception (&error);
1428 }
1429
1430 gpointer
1431 mono_fill_class_rgctx (MonoVTable *vtable, int index)
1432 {
1433         MonoError error;
1434         gpointer res;
1435
1436         res = mono_class_fill_runtime_generic_context (vtable, index, &error);
1437         if (!mono_error_ok (&error)) {
1438                 mono_error_set_pending_exception (&error);
1439                 return NULL;
1440         }
1441         return res;
1442 }
1443
1444 gpointer
1445 mono_fill_method_rgctx (MonoMethodRuntimeGenericContext *mrgctx, int index)
1446 {
1447         MonoError error;
1448         gpointer res;
1449
1450         res = mono_method_fill_runtime_generic_context (mrgctx, index, &error);
1451         if (!mono_error_ok (&error)) {
1452                 mono_error_set_pending_exception (&error);
1453                 return NULL;
1454         }
1455         return res;
1456 }
1457
1458 /*
1459  * resolve_iface_call:
1460  *
1461  *   Return the executable code for the iface method IMT_METHOD called on THIS.
1462  * This function is called on a slowpath, so it doesn't need to be fast.
1463  * This returns an ftnptr by returning the address part, and the arg in the OUT_ARG
1464  * out parameter.
1465  */
1466 static gpointer
1467 resolve_iface_call (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, gpointer *out_arg, gboolean caller_gsharedvt)
1468 {
1469         MonoError error;
1470         MonoVTable *vt;
1471         gpointer *imt, *vtable_slot;
1472         MonoMethod *impl_method, *generic_virtual = NULL, *variant_iface = NULL;
1473         gpointer addr, compiled_method, aot_addr;
1474         gboolean need_rgctx_tramp = FALSE, need_unbox_tramp = FALSE;
1475
1476         if (!this_obj)
1477                 /* The caller will handle it */
1478                 return NULL;
1479
1480         vt = this_obj->vtable;
1481         imt = (gpointer*)vt - MONO_IMT_SIZE;
1482
1483         vtable_slot = mini_resolve_imt_method (vt, imt + imt_slot, imt_method, &impl_method, &aot_addr, &need_rgctx_tramp, &variant_iface);
1484
1485         // FIXME: This can throw exceptions
1486         addr = compiled_method = mono_compile_method_checked (impl_method, &error);
1487         mono_error_assert_ok (&error);
1488         g_assert (addr);
1489
1490         if (imt_method->is_inflated && ((MonoMethodInflated*)imt_method)->context.method_inst)
1491                 generic_virtual = imt_method;
1492
1493         if (generic_virtual || variant_iface) {
1494                 if (vt->klass->valuetype) /*FIXME is this required variant iface?*/
1495                         need_unbox_tramp = TRUE;
1496         } else {
1497                 if (impl_method->klass->valuetype)
1498                         need_unbox_tramp = TRUE;
1499         }
1500
1501         addr = mini_add_method_wrappers_llvmonly (impl_method, addr, caller_gsharedvt, need_unbox_tramp, out_arg);
1502
1503         if (generic_virtual || variant_iface) {
1504                 MonoMethod *target = generic_virtual ? generic_virtual : variant_iface;
1505
1506                 mono_method_add_generic_virtual_invocation (mono_domain_get (),
1507                                                                                                         vt, imt + imt_slot,
1508                                                                                                         target, addr);
1509         }
1510
1511         return addr;
1512 }
1513
1514 gpointer
1515 mono_resolve_iface_call_gsharedvt (MonoObject *this_obj, int imt_slot, MonoMethod *imt_method, gpointer *out_arg)
1516 {
1517         return resolve_iface_call (this_obj, imt_slot, imt_method, out_arg, TRUE);
1518 }
1519
1520 static gboolean
1521 is_generic_method_definition (MonoMethod *m)
1522 {
1523         MonoGenericContext *context;
1524         if (m->is_generic)
1525                 return TRUE;
1526         if (!m->is_inflated)
1527                 return FALSE;
1528
1529         context = mono_method_get_context (m);
1530         if (!context->method_inst)
1531                 return FALSE;
1532         if (context->method_inst == mono_method_get_generic_container (((MonoMethodInflated*)m)->declaring)->context.method_inst)
1533                 return TRUE;
1534         return FALSE;
1535 }
1536
1537 /*
1538  * resolve_vcall:
1539  *
1540  *   Return the executable code for calling vt->vtable [slot].
1541  * This function is called on a slowpath, so it doesn't need to be fast.
1542  * This returns an ftnptr by returning the address part, and the arg in the OUT_ARG
1543  * out parameter.
1544  */
1545 static gpointer
1546 resolve_vcall (MonoVTable *vt, int slot, MonoMethod *imt_method, gpointer *out_arg, gboolean gsharedvt)
1547 {
1548         MonoError error;
1549         MonoMethod *m, *generic_virtual = NULL;
1550         gpointer addr, compiled_method;
1551         gboolean need_unbox_tramp = FALSE;
1552
1553         /* Same as in common_call_trampoline () */
1554
1555         /* Avoid loading metadata or creating a generic vtable if possible */
1556         addr = mono_aot_get_method_from_vt_slot (mono_domain_get (), vt, slot);
1557         if (addr && !vt->klass->valuetype)
1558                 return mono_create_ftnptr (mono_domain_get (), addr);
1559
1560         m = mono_class_get_vtable_entry (vt->klass, slot);
1561
1562         if (is_generic_method_definition (m)) {
1563                 MonoGenericContext context = { NULL, NULL };
1564                 MonoMethod *declaring;
1565
1566                 if (m->is_inflated)
1567                         declaring = mono_method_get_declaring_generic_method (m);
1568                 else
1569                         declaring = m;
1570
1571                 if (m->klass->generic_class)
1572                         context.class_inst = m->klass->generic_class->context.class_inst;
1573                 else
1574                         g_assert (!m->klass->generic_container);
1575
1576                 generic_virtual = imt_method;
1577                 g_assert (generic_virtual);
1578                 g_assert (generic_virtual->is_inflated);
1579                 context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst;
1580
1581                 m = mono_class_inflate_generic_method_checked (declaring, &context, &error);
1582                 mono_error_assert_ok (&error); /* FIXME don't swallow the error */
1583         }
1584
1585         if (generic_virtual) {
1586                 if (vt->klass->valuetype)
1587                         need_unbox_tramp = TRUE;
1588         } else {
1589                 if (m->klass->valuetype)
1590                         need_unbox_tramp = TRUE;
1591         }
1592
1593         // FIXME: This can throw exceptions
1594         addr = compiled_method = mono_compile_method_checked (m, &error);
1595         mono_error_assert_ok (&error);
1596         g_assert (addr);
1597
1598         addr = mini_add_method_wrappers_llvmonly (m, addr, gsharedvt, need_unbox_tramp, out_arg);
1599
1600         if (!gsharedvt && generic_virtual) {
1601                 // FIXME: This wastes memory since add_generic_virtual_invocation ignores it in a lot of cases
1602                 MonoFtnDesc *ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, out_arg);
1603
1604                 mono_method_add_generic_virtual_invocation (mono_domain_get (),
1605                                                                                                         vt, vt->vtable + slot,
1606                                                                                                         generic_virtual, ftndesc);
1607         }
1608
1609         return addr;
1610 }
1611
1612 gpointer
1613 mono_resolve_vcall_gsharedvt (MonoObject *this_obj, int slot, MonoMethod *imt_method, gpointer *out_arg)
1614 {
1615         g_assert (this_obj);
1616
1617         return resolve_vcall (this_obj->vtable, slot, imt_method, out_arg, TRUE);
1618 }
1619
1620 /*
1621  * mono_resolve_generic_virtual_call:
1622  *
1623  *   Resolve a generic virtual call.
1624  * This function is called on a slowpath, so it doesn't need to be fast.
1625  */
1626 MonoFtnDesc*
1627 mono_resolve_generic_virtual_call (MonoVTable *vt, int slot, MonoMethod *generic_virtual)
1628 {
1629         MonoMethod *m;
1630         gpointer addr, compiled_method;
1631         gboolean need_unbox_tramp = FALSE;
1632         MonoError error;
1633         MonoGenericContext context = { NULL, NULL };
1634         MonoMethod *declaring;
1635         gpointer arg = NULL;
1636
1637         m = mono_class_get_vtable_entry (vt->klass, slot);
1638
1639         g_assert (is_generic_method_definition (m));
1640
1641         if (m->is_inflated)
1642                 declaring = mono_method_get_declaring_generic_method (m);
1643         else
1644                 declaring = m;
1645
1646         if (m->klass->generic_class)
1647                 context.class_inst = m->klass->generic_class->context.class_inst;
1648         else
1649                 g_assert (!m->klass->generic_container);
1650
1651         g_assert (generic_virtual->is_inflated);
1652         context.method_inst = ((MonoMethodInflated*)generic_virtual)->context.method_inst;
1653
1654         m = mono_class_inflate_generic_method_checked (declaring, &context, &error);
1655         g_assert (mono_error_ok (&error));
1656
1657         if (vt->klass->valuetype)
1658                 need_unbox_tramp = TRUE;
1659
1660         // FIXME: This can throw exceptions
1661         addr = compiled_method = mono_compile_method_checked (m, &error);
1662         mono_error_assert_ok (&error);
1663         g_assert (addr);
1664
1665         addr = mini_add_method_wrappers_llvmonly (m, addr, FALSE, need_unbox_tramp, &arg);
1666
1667         /*
1668          * This wastes memory but the memory usage is bounded since
1669          * mono_method_add_generic_virtual_invocation () eventually builds an imt thunk for
1670          * this vtable slot so we are not called any more for this instantiation.
1671          */
1672         MonoFtnDesc *ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
1673
1674         mono_method_add_generic_virtual_invocation (mono_domain_get (),
1675                                                                                                 vt, vt->vtable + slot,
1676                                                                                                 generic_virtual, ftndesc);
1677         return ftndesc;
1678 }
1679
1680 /*
1681  * mono_resolve_generic_virtual_call:
1682  *
1683  *   Resolve a generic virtual/variant iface call on interfaces.
1684  * This function is called on a slowpath, so it doesn't need to be fast.
1685  */
1686 MonoFtnDesc*
1687 mono_resolve_generic_virtual_iface_call (MonoVTable *vt, int imt_slot, MonoMethod *generic_virtual)
1688 {
1689         MonoError error;
1690         MonoMethod *m, *variant_iface;
1691         gpointer addr, aot_addr, compiled_method;
1692         gboolean need_unbox_tramp = FALSE;
1693         gboolean need_rgctx_tramp;
1694         gpointer arg = NULL;
1695         gpointer *imt;
1696
1697         imt = (gpointer*)vt - MONO_IMT_SIZE;
1698
1699         mini_resolve_imt_method (vt, imt + imt_slot, generic_virtual, &m, &aot_addr, &need_rgctx_tramp, &variant_iface);
1700
1701         if (vt->klass->valuetype)
1702                 need_unbox_tramp = TRUE;
1703
1704         // FIXME: This can throw exceptions
1705         addr = compiled_method = mono_compile_method_checked (m, &error);
1706         mono_error_assert_ok (&error);
1707         g_assert (addr);
1708
1709         addr = mini_add_method_wrappers_llvmonly (m, addr, FALSE, need_unbox_tramp, &arg);
1710
1711         /*
1712          * This wastes memory but the memory usage is bounded since
1713          * mono_method_add_generic_virtual_invocation () eventually builds an imt thunk for
1714          * this vtable slot so we are not called any more for this instantiation.
1715          */
1716         MonoFtnDesc *ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
1717
1718         mono_method_add_generic_virtual_invocation (mono_domain_get (),
1719                                                                                                 vt, imt + imt_slot,
1720                                                                                                 variant_iface ? variant_iface : generic_virtual, ftndesc);
1721         return ftndesc;
1722 }
1723
1724 /*
1725  * mono_init_vtable_slot:
1726  *
1727  *   Initialize slot SLOT of VTABLE.
1728  * Return the contents of the vtable slot.
1729  */
1730 gpointer
1731 mono_init_vtable_slot (MonoVTable *vtable, int slot)
1732 {
1733         gpointer arg = NULL;
1734         gpointer addr;
1735         gpointer *ftnptr;
1736
1737         addr = resolve_vcall (vtable, slot, NULL, &arg, FALSE);
1738         ftnptr = mono_domain_alloc0 (vtable->domain, 2 * sizeof (gpointer));
1739         ftnptr [0] = addr;
1740         ftnptr [1] = arg;
1741         mono_memory_barrier ();
1742
1743         vtable->vtable [slot] = ftnptr;
1744
1745         return ftnptr;
1746 }
1747
1748 /*
1749  * mono_llvmonly_init_delegate:
1750  *
1751  *   Initialize a MonoDelegate object.
1752  * Similar to mono_delegate_ctor ().
1753  */
1754 void
1755 mono_llvmonly_init_delegate (MonoDelegate *del)
1756 {
1757         MonoError error;
1758         MonoFtnDesc *ftndesc = *(MonoFtnDesc**)del->method_code;
1759
1760         /*
1761          * We store a MonoFtnDesc in del->method_code.
1762          * It would be better to store an ftndesc in del->method_ptr too,
1763          * but we don't have a a structure which could own its memory.
1764          */
1765         if (G_UNLIKELY (!ftndesc)) {
1766                 gpointer addr = mono_compile_method_checked (del->method, &error);
1767                 if (mono_error_set_pending_exception (&error))
1768                         return;
1769
1770                 if (del->method->klass->valuetype && mono_method_signature (del->method)->hasthis)
1771                     addr = mono_aot_get_unbox_trampoline (del->method);
1772
1773                 gpointer arg = mini_get_delegate_arg (del->method, addr);
1774
1775                 ftndesc = mini_create_llvmonly_ftndesc (mono_domain_get (), addr, arg);
1776                 mono_memory_barrier ();
1777                 *del->method_code = (gpointer)ftndesc;
1778         }
1779         del->method_ptr = ftndesc->addr;
1780         del->extra_arg = ftndesc->arg;
1781 }
1782
1783 void
1784 mono_llvmonly_init_delegate_virtual (MonoDelegate *del, MonoObject *target, MonoMethod *method)
1785 {
1786         MonoError error;
1787
1788         g_assert (target);
1789
1790         method = mono_object_get_virtual_method (target, method);
1791
1792         del->method = method;
1793         del->method_ptr = mono_compile_method_checked (method, &error);
1794         if (mono_error_set_pending_exception (&error))
1795                 return;
1796         if (method->klass->valuetype)
1797                 del->method_ptr = mono_aot_get_unbox_trampoline (method);
1798         del->extra_arg = mini_get_delegate_arg (del->method, del->method_ptr);
1799 }
1800
1801 MonoObject*
1802 mono_get_assembly_object (MonoImage *image)
1803 {
1804         MonoError error;
1805         MonoObject *result;
1806         result = (MonoObject*)mono_assembly_get_object_checked (mono_domain_get (), image->assembly, &error);
1807         if (!result)
1808                 mono_error_set_pending_exception (&error);
1809         return result;
1810 }
1811
1812 MonoObject*
1813 mono_get_method_object (MonoMethod *method)
1814 {
1815         MonoError error;
1816         MonoObject * result;
1817         result = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), method, method->klass, &error);
1818         mono_error_set_pending_exception (&error);
1819         return result;
1820 }
1821
1822 double
1823 mono_ckfinite (double d)
1824 {
1825         if (isinf (d) || isnan (d))
1826                 mono_set_pending_exception (mono_get_exception_arithmetic ());
1827         return d;
1828 }
1829
1830 /*
1831  * mono_interruption_checkpoint_from_trampoline:
1832  *
1833  *   Check whenever the thread has a pending exception, and throw it
1834  * if needed.
1835  * Architectures should move away from calling this function and
1836  * instead call mono_thread_force_interruption_checkpoint_noraise (),
1837  * rewrind to the parent frame, and throw the exception normally.
1838  */
1839 void
1840 mono_interruption_checkpoint_from_trampoline (void)
1841 {
1842         MonoException *ex;
1843
1844         ex = mono_thread_force_interruption_checkpoint_noraise ();
1845         if (ex)
1846                 mono_raise_exception (ex);
1847 }