2008-08-22 Zoltan Varga <vargaz@gmail.com>
[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  */
10
11 #include <math.h>
12 #include <limits.h>
13
14 #include "jit-icalls.h"
15
16 void*
17 mono_ldftn (MonoMethod *method)
18 {
19         gpointer addr;
20
21         MONO_ARCH_SAVE_REGS;
22
23         addr = mono_create_jump_trampoline (mono_domain_get (), method, FALSE);
24
25         return mono_create_ftnptr (mono_domain_get (), addr);
26 }
27
28 static void*
29 ldvirtfn_internal (MonoObject *obj, MonoMethod *method, gboolean gshared)
30 {
31         MonoMethod *res;
32
33         MONO_ARCH_SAVE_REGS;
34
35         if (obj == NULL)
36                 mono_raise_exception (mono_get_exception_null_reference ());
37
38         res = mono_object_get_virtual_method (obj, method);
39
40         if (gshared && method->is_inflated && mono_method_get_context (method)->method_inst) {
41                 MonoGenericContext context = { NULL, NULL };
42
43                 if (res->klass->generic_class)
44                         context.class_inst = res->klass->generic_class->context.class_inst;
45                 else if (res->klass->generic_container)
46                         context.class_inst = res->klass->generic_container->context.class_inst;
47                 context.method_inst = mono_method_get_context (method)->method_inst;
48
49                 res = mono_class_inflate_generic_method (res, &context);
50         }
51
52         /* FIXME: only do this for methods which can be shared! */
53         if (res->is_inflated && mono_method_get_context (res)->method_inst &&
54                         mono_class_generic_sharing_enabled (res->klass)) {
55                 res = mono_marshal_get_static_rgctx_invoke (res);
56         }
57
58         return mono_ldftn (res);
59 }
60
61 void*
62 mono_ldvirtfn (MonoObject *obj, MonoMethod *method) 
63 {
64         return ldvirtfn_internal (obj, method, FALSE);
65 }
66
67 void*
68 mono_ldvirtfn_gshared (MonoObject *obj, MonoMethod *method) 
69 {
70         return ldvirtfn_internal (obj, method, TRUE);
71 }
72
73 void
74 mono_helper_stelem_ref_check (MonoArray *array, MonoObject *val)
75 {
76         MONO_ARCH_SAVE_REGS;
77
78         if (val && !mono_object_isinst (val, array->obj.vtable->klass->element_class))
79                 mono_raise_exception (mono_get_exception_array_type_mismatch ());
80 }
81
82 #ifndef MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
83
84 gint64 
85 mono_llmult (gint64 a, gint64 b)
86 {
87         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
88         return a * b;
89 }
90
91 guint64  
92 mono_llmult_ovf_un (guint64 a, guint64 b)
93 {
94         guint32 al = a;
95         guint32 ah = a >> 32;
96         guint32 bl = b;
97         guint32 bh = b >> 32; 
98         guint64 res, t1;
99
100         MONO_ARCH_SAVE_REGS;
101
102         // fixme: this is incredible slow
103
104         if (ah && bh)
105                 goto raise_exception;
106
107         res = (guint64)al * (guint64)bl;
108
109         t1 = (guint64)ah * (guint64)bl + (guint64)al * (guint64)bh;
110
111         if (t1 > 0xffffffff)
112                 goto raise_exception;
113
114         res += ((guint64)t1) << 32; 
115
116         return res;
117
118  raise_exception:
119         mono_raise_exception (mono_get_exception_overflow ());
120         return 0;
121 }
122
123 guint64  
124 mono_llmult_ovf (gint64 a, gint64 b) 
125 {
126         guint32 al = a;
127         gint32 ah = a >> 32;
128         guint32 bl = b;
129         gint32 bh = b >> 32; 
130         /*
131         Use Karatsuba algorithm where:
132                 a*b is: AhBh(R^2+R)+(Ah-Al)(Bl-Bh)R+AlBl(R+1)
133                 where Ah is the "high half" (most significant 32 bits) of a and
134                 where Al is the "low half" (least significant 32 bits) of a and
135                 where  Bh is the "high half" of b and Bl is the "low half" and
136                 where R is the Radix or "size of the half" (in our case 32 bits)
137
138         Note, for the product of two 64 bit numbers to fit into a 64
139         result, ah and/or bh must be 0.  This will save us from doing
140         the AhBh term at all.
141
142         Also note that we refactor so that we don't overflow 64 bits with 
143         intermediate results. So we use [(Ah-Al)(Bl-Bh)+AlBl]R+AlBl
144         */
145
146         gint64 res, t1;
147         gint32 sign;
148
149         MONO_ARCH_SAVE_REGS;
150
151         /* need to work with absoulte values, so find out what the
152            resulting sign will be and convert any negative numbers
153            from two's complement
154         */
155         sign = ah ^ bh;
156         if (ah < 0) {
157                 if (((guint32)ah == 0x80000000) && (al == 0)) {
158                         /* This has no two's complement */
159                         if (b == 0)
160                                 return 0;
161                         else if (b == 1)
162                                 return a;
163                         else
164                                 goto raise_exception;
165                 }
166
167                 /* flip the bits and add 1 */
168                 ah ^= ~0;
169                 if (al ==  0)
170                         ah += 1;
171                 else {
172                         al ^= ~0;
173                         al +=1;
174                 }
175         }
176
177         if (bh < 0) {
178                 if (((guint32)bh == 0x80000000) && (bl == 0)) {
179                         /* This has no two's complement */
180                         if (a == 0)
181                                 return 0;
182                         else if (a == 1)
183                                 return b;
184                         else
185                                 goto raise_exception;
186                 }
187
188                 /* flip the bits and add 1 */
189                 bh ^= ~0;
190                 if (bl ==  0)
191                         bh += 1;
192                 else {
193                         bl ^= ~0;
194                         bl +=1;
195                 }
196         }
197                 
198         /* we overflow for sure if both upper halves are greater 
199            than zero because we would need to shift their 
200            product 64 bits to the left and that will not fit
201            in a 64 bit result */
202         if (ah && bh)
203                 goto raise_exception;
204         if ((gint64)((gint64)ah * (gint64)bl) > (gint64)0x80000000 || (gint64)((gint64)al * (gint64)bh) > (gint64)0x80000000)
205                 goto raise_exception;
206
207         /* do the AlBl term first */
208         t1 = (gint64)al * (gint64)bl;
209
210         res = t1;
211
212         /* now do the [(Ah-Al)(Bl-Bh)+AlBl]R term */
213         t1 += (gint64)(ah - al) * (gint64)(bl - bh);
214         /* check for overflow */
215         t1 <<= 32;
216         if (t1 > (0x7FFFFFFFFFFFFFFFLL - res))
217                 goto raise_exception;
218
219         res += t1;
220
221         if (res < 0)
222                 goto raise_exception;
223
224         if (sign < 0)
225                 return -res;
226         else
227                 return res;
228
229  raise_exception:
230         mono_raise_exception (mono_get_exception_overflow ());
231         return 0;
232 }
233
234 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_DIV)
235
236 gint32
237 mono_idiv (gint32 a, gint32 b)
238 {
239         MONO_ARCH_SAVE_REGS;
240
241 #ifdef MONO_ARCH_NEED_DIV_CHECK
242         if (!b)
243                 mono_raise_exception (mono_get_exception_divide_by_zero ());
244         else if (b == -1 && a == (0x80000000))
245                 mono_raise_exception (mono_get_exception_arithmetic ());
246 #endif
247         return a / b;
248 }
249
250 guint32
251 mono_idiv_un (guint32 a, guint32 b)
252 {
253         MONO_ARCH_SAVE_REGS;
254
255 #ifdef MONO_ARCH_NEED_DIV_CHECK
256         if (!b)
257                 mono_raise_exception (mono_get_exception_divide_by_zero ());
258 #endif
259         return a / b;
260 }
261
262 gint32
263 mono_irem (gint32 a, gint32 b)
264 {
265         MONO_ARCH_SAVE_REGS;
266
267 #ifdef MONO_ARCH_NEED_DIV_CHECK
268         if (!b)
269                 mono_raise_exception (mono_get_exception_divide_by_zero ());
270         else if (b == -1 && a == (0x80000000))
271                 mono_raise_exception (mono_get_exception_arithmetic ());
272 #endif
273
274         return a % b;
275 }
276
277 guint32
278 mono_irem_un (guint32 a, guint32 b)
279 {
280         MONO_ARCH_SAVE_REGS;
281
282 #ifdef MONO_ARCH_NEED_DIV_CHECK
283         if (!b)
284                 mono_raise_exception (mono_get_exception_divide_by_zero ());
285 #endif
286         return a % b;
287 }
288
289 #endif
290
291 #ifdef MONO_ARCH_EMULATE_MUL_DIV
292
293 gint32
294 mono_imul (gint32 a, gint32 b)
295 {
296         MONO_ARCH_SAVE_REGS;
297
298         return a * b;
299 }
300
301 gint32
302 mono_imul_ovf (gint32 a, gint32 b)
303 {
304         gint64 res;
305
306         MONO_ARCH_SAVE_REGS;
307
308         res = (gint64)a * (gint64)b;
309
310         if ((res > 0x7fffffffL) || (res < -2147483648))
311                 mono_raise_exception (mono_get_exception_overflow ());
312
313         return res;
314 }
315
316 gint32
317 mono_imul_ovf_un (guint32 a, guint32 b)
318 {
319         guint64 res;
320
321         MONO_ARCH_SAVE_REGS;
322
323         res = (guint64)a * (guint64)b;
324
325         if ((res >> 32))
326                 mono_raise_exception (mono_get_exception_overflow ());
327
328         return res;
329 }
330 #endif
331
332 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT)
333 double
334 mono_fdiv (double a, double b)
335 {
336         MONO_ARCH_SAVE_REGS;
337
338         return a / b;
339 }
340 #endif
341
342 gint64 
343 mono_lldiv (gint64 a, gint64 b)
344 {
345         MONO_ARCH_SAVE_REGS;
346
347 #ifdef MONO_ARCH_NEED_DIV_CHECK
348         if (!b)
349                 mono_raise_exception (mono_get_exception_divide_by_zero ());
350         else if (b == -1 && a == (-9223372036854775807LL - 1LL))
351                 mono_raise_exception (mono_get_exception_arithmetic ());
352 #endif
353         return a / b;
354 }
355
356 gint64 
357 mono_llrem (gint64 a, gint64 b)
358 {
359         MONO_ARCH_SAVE_REGS;
360
361 #ifdef MONO_ARCH_NEED_DIV_CHECK
362         if (!b)
363                 mono_raise_exception (mono_get_exception_divide_by_zero ());
364         else if (b == -1 && a == (-9223372036854775807LL - 1LL))
365                 mono_raise_exception (mono_get_exception_arithmetic ());
366 #endif
367         return a % b;
368 }
369
370 guint64 
371 mono_lldiv_un (guint64 a, guint64 b)
372 {
373         MONO_ARCH_SAVE_REGS;
374
375 #ifdef MONO_ARCH_NEED_DIV_CHECK
376         if (!b)
377                 mono_raise_exception (mono_get_exception_divide_by_zero ());
378 #endif
379         return a / b;
380 }
381
382 guint64 
383 mono_llrem_un (guint64 a, guint64 b)
384 {
385         MONO_ARCH_SAVE_REGS;
386
387 #ifdef MONO_ARCH_NEED_DIV_CHECK
388         if (!b)
389                 mono_raise_exception (mono_get_exception_divide_by_zero ());
390 #endif
391         return a % b;
392 }
393
394 #endif
395
396 #ifndef MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
397
398 guint64 
399 mono_lshl (guint64 a, gint32 shamt)
400 {
401         guint64 res;
402
403         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
404         res = a << shamt;
405
406         /*printf ("TESTL %lld << %d = %lld\n", a, shamt, res);*/
407
408         return res;
409 }
410
411 guint64 
412 mono_lshr_un (guint64 a, gint32 shamt)
413 {
414         guint64 res;
415
416         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
417         res = a >> shamt;
418
419         /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
420
421         return res;
422 }
423
424 gint64 
425 mono_lshr (gint64 a, gint32 shamt)
426 {
427         gint64 res;
428
429         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
430         res = a >> shamt;
431
432         /*printf ("TESTR %lld >> %d = %lld\n", a, shamt, res);*/
433
434         return res;
435 }
436
437 #endif
438
439 #ifdef MONO_ARCH_SOFT_FLOAT
440
441 double
442 mono_fsub (double a, double b)
443 {
444         return a - b;
445 }
446
447 double
448 mono_fadd (double a, double b)
449 {
450         return a + b;
451 }
452
453 double
454 mono_fmul (double a, double b)
455 {
456         return a * b;
457 }
458
459 double
460 mono_fneg (double a)
461 {
462         return -a;
463 }
464
465 double
466 mono_fconv_r4 (double a)
467 {
468         return (float)a;
469 }
470
471 double
472 mono_conv_to_r8 (int a)
473 {
474         return (double)a;
475 }
476
477 double
478 mono_conv_to_r4 (int a)
479 {
480         return (double)(float)a;
481 }
482
483 gint8
484 mono_fconv_i1 (double a)
485 {
486         return (gint8)a;
487 }
488
489 gint16
490 mono_fconv_i2 (double a)
491 {
492         return (gint16)a;
493 }
494
495 gint32
496 mono_fconv_i4 (double a)
497 {
498         return (gint32)a;
499 }
500
501 guint8
502 mono_fconv_u1 (double a)
503 {
504         return (guint8)a;
505 }
506
507 guint16
508 mono_fconv_u2 (double a)
509 {
510         return (guint16)a;
511 }
512
513 gboolean
514 mono_fcmp_eq (double a, double b)
515 {
516         return a == b;
517 }
518
519 gboolean
520 mono_fcmp_ge (double a, double b)
521 {
522         return a >= b;
523 }
524
525 gboolean
526 mono_fcmp_gt (double a, double b)
527 {
528         return a > b;
529 }
530
531 gboolean
532 mono_fcmp_le (double a, double b)
533 {
534         return a <= b;
535 }
536
537 gboolean
538 mono_fcmp_lt (double a, double b)
539 {
540         return a < b;
541 }
542
543 gboolean
544 mono_fcmp_ne_un (double a, double b)
545 {
546         return isunordered (a, b) || a != b;
547 }
548
549 gboolean
550 mono_fcmp_ge_un (double a, double b)
551 {
552         return isunordered (a, b) || a >= b;
553 }
554
555 gboolean
556 mono_fcmp_gt_un (double a, double b)
557 {
558         return isunordered (a, b) || a > b;
559 }
560
561 gboolean
562 mono_fcmp_le_un (double a, double b)
563 {
564         return isunordered (a, b) || a <= b;
565 }
566
567 gboolean
568 mono_fcmp_lt_un (double a, double b)
569 {
570         return isunordered (a, b) || a < b;
571 }
572
573 gboolean
574 mono_fceq (double a, double b)
575 {
576         return a == b;
577 }
578
579 gboolean
580 mono_fcgt (double a, double b)
581 {
582         return a > b;
583 }
584
585 gboolean
586 mono_fcgt_un (double a, double b)
587 {
588         return isunordered (a, b) || a > b;
589 }
590
591 gboolean
592 mono_fclt (double a, double b)
593 {
594         return a < b;
595 }
596
597 gboolean
598 mono_fclt_un (double a, double b)
599 {
600         return isunordered (a, b) || a < b;
601 }
602
603 double
604 mono_fload_r4 (float *ptr)
605 {
606         return *ptr;
607 }
608
609 void
610 mono_fstore_r4 (double val, float *ptr)
611 {
612         *ptr = (float)val;
613 }
614
615 /* returns the integer bitpattern that is passed in the regs or stack */
616 guint32
617 mono_fload_r4_arg (double val)
618 {
619         float v = (float)val;
620         return *(guint32*)&v;
621 }
622
623 #endif
624
625 MonoArray *
626 mono_array_new_va (MonoMethod *cm, ...)
627 {
628         MonoDomain *domain = mono_domain_get ();
629         va_list ap;
630         guint32 *lengths;
631         guint32 *lower_bounds;
632         int pcount;
633         int rank;
634         int i, d;
635
636         MONO_ARCH_SAVE_REGS;
637
638         pcount = mono_method_signature (cm)->param_count;
639         rank = cm->klass->rank;
640
641         va_start (ap, cm);
642         
643         lengths = alloca (sizeof (guint32) * pcount);
644         for (i = 0; i < pcount; ++i)
645                 lengths [i] = d = va_arg(ap, int);
646
647         if (rank == pcount) {
648                 /* Only lengths provided. */
649                 if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
650                         lower_bounds = alloca (sizeof (guint32) * rank);
651                         memset (lower_bounds, 0, sizeof (guint32) * rank);
652                 } else {
653                         lower_bounds = NULL;
654                 }
655         } else {
656                 g_assert (pcount == (rank * 2));
657                 /* lower bounds are first. */
658                 lower_bounds = lengths;
659                 lengths += rank;
660         }
661         va_end(ap);
662
663         return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
664 }
665
666 /* Specialized version of mono_array_new_va () which avoids varargs */
667 MonoArray *
668 mono_array_new_1 (MonoMethod *cm, guint32 length)
669 {
670         MonoDomain *domain = mono_domain_get ();
671         guint32 lengths [1];
672         guint32 *lower_bounds;
673         int pcount;
674         int rank;
675
676         MONO_ARCH_SAVE_REGS;
677
678         pcount = mono_method_signature (cm)->param_count;
679         rank = cm->klass->rank;
680
681         lengths [0] = length;
682
683         g_assert (rank == pcount);
684
685         if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
686                 lower_bounds = alloca (sizeof (guint32) * rank);
687                 memset (lower_bounds, 0, sizeof (guint32) * rank);
688         } else {
689                 lower_bounds = NULL;
690         }
691
692         return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
693 }
694
695 MonoArray *
696 mono_array_new_2 (MonoMethod *cm, guint32 length1, guint32 length2)
697 {
698         MonoDomain *domain = mono_domain_get ();
699         guint32 lengths [2];
700         guint32 *lower_bounds;
701         int pcount;
702         int rank;
703
704         MONO_ARCH_SAVE_REGS;
705
706         pcount = mono_method_signature (cm)->param_count;
707         rank = cm->klass->rank;
708
709         lengths [0] = length1;
710         lengths [1] = length2;
711
712         g_assert (rank == pcount);
713
714         if (cm->klass->byval_arg.type == MONO_TYPE_ARRAY) {
715                 lower_bounds = alloca (sizeof (guint32) * rank);
716                 memset (lower_bounds, 0, sizeof (guint32) * rank);
717         } else {
718                 lower_bounds = NULL;
719         }
720
721         return mono_array_new_full (domain, cm->klass, lengths, lower_bounds);
722 }
723
724 gpointer
725 mono_class_static_field_address (MonoDomain *domain, MonoClassField *field)
726 {
727         MonoVTable *vtable;
728         gpointer addr;
729         
730         MONO_ARCH_SAVE_REGS;
731
732         //printf ("SFLDA0 %s.%s::%s %d\n", field->parent->name_space, field->parent->name, field->name, field->offset, field->parent->inited);
733
734         mono_class_init (field->parent);
735
736         vtable = mono_class_vtable (domain, field->parent);
737         if (!vtable->initialized)
738                 mono_runtime_class_init (vtable);
739
740         //printf ("SFLDA1 %p\n", (char*)vtable->data + field->offset);
741
742         if (domain->special_static_fields && (addr = g_hash_table_lookup (domain->special_static_fields, field)))
743                 addr = mono_get_special_static_data (GPOINTER_TO_UINT (addr));
744         else
745                 addr = (char*)vtable->data + field->offset;
746         
747         return addr;
748 }
749
750 gpointer
751 mono_ldtoken_wrapper (MonoImage *image, int token, MonoGenericContext *context)
752 {
753         MonoClass *handle_class;
754         gpointer res;
755
756         MONO_ARCH_SAVE_REGS;
757         res = mono_ldtoken (image, token, &handle_class, context);      
758         mono_class_init (handle_class);
759
760         return res;
761 }
762
763 gpointer
764 mono_ldtoken_wrapper_generic_shared (MonoImage *image, int token, MonoMethod *method)
765 {
766         MonoMethodSignature *sig = mono_method_signature (method);
767         MonoGenericContext *generic_context;
768
769         if (sig->is_inflated) {
770                 generic_context = mono_method_get_context (method);
771         } else {
772                 MonoGenericContainer *generic_container = mono_method_get_generic_container (method);
773                 g_assert (generic_container);
774                 generic_context = &generic_container->context;
775         }
776
777         return mono_ldtoken_wrapper (image, token, generic_context);
778 }
779
780 guint64
781 mono_fconv_u8 (double v)
782 {
783         return (guint64)v;
784 }
785
786 #ifdef MONO_ARCH_EMULATE_FCONV_TO_I8
787 gint64
788 mono_fconv_i8 (double v)
789 {
790         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
791         return (gint64)v;
792 }
793 #endif
794
795 guint32
796 mono_fconv_u4 (double v)
797 {
798         /* no need, no exceptions: MONO_ARCH_SAVE_REGS;*/
799         return (guint32)v;
800 }
801
802 #ifndef HAVE_TRUNC
803 /* Solaris doesn't have trunc */
804 #ifdef HAVE_AINTL
805 extern long double aintl (long double);
806 #define trunc aintl
807 #else
808 /* FIXME: This means we will never throw overflow exceptions */
809 #define trunc(v) res
810 #endif
811 #endif /* HAVE_TRUNC */
812
813 gint64
814 mono_fconv_ovf_i8 (double v)
815 {
816         gint64 res;
817
818         MONO_ARCH_SAVE_REGS;
819
820         res = (gint64)v;
821
822         if (isnan(v) || trunc (v) != res) {
823                 mono_raise_exception (mono_get_exception_overflow ());
824         }
825         return res;
826 }
827
828 guint64
829 mono_fconv_ovf_u8 (double v)
830 {
831         guint64 res;
832
833         MONO_ARCH_SAVE_REGS;
834 /*
835  * The soft-float implementation of some ARM devices have a buggy guin64 to double
836  * conversion that it looses precision even when the integer if fully representable
837  * as a double.
838  * 
839  * This was found with 4294967295ull, converting to double and back looses one bit of precision.
840  * 
841  * To work around this issue we test for value boundaries instead. 
842  */
843 #if defined(__arm__) && MONO_ARCH_SOFT_FLOAT 
844         if (isnan (v) || !(v >= -0.5 && v <= ULLONG_MAX+0.5)) {
845                 mono_raise_exception (mono_get_exception_overflow ());
846         }
847         res = (guint64)v;
848 #else
849         res = (guint64)v;
850         if (isnan(v) || trunc (v) != res) {
851                 mono_raise_exception (mono_get_exception_overflow ());
852         }
853 #endif
854         return res;
855 }
856
857 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8
858 double
859 mono_lconv_to_r8 (gint64 a)
860 {
861         return (double)a;
862 }
863 #endif
864
865 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R4
866 float
867 mono_lconv_to_r4 (gint64 a)
868 {
869         return (float)a;
870 }
871 #endif
872
873 #ifdef MONO_ARCH_EMULATE_CONV_R8_UN
874 double
875 mono_conv_to_r8_un (guint32 a)
876 {
877         return (double)a;
878 }
879 #endif
880
881 #ifdef MONO_ARCH_EMULATE_LCONV_TO_R8_UN
882 double
883 mono_lconv_to_r8_un (guint64 a)
884 {
885         return (double)a;
886 }
887 #endif
888
889 gpointer
890 mono_helper_compile_generic_method (MonoObject *obj, MonoMethod *method, gpointer *this_arg)
891 {
892         MonoMethod *vmethod, *inflated;
893         gpointer addr;
894         MonoGenericContext *context = mono_method_get_context (method);
895
896         mono_jit_stats.generic_virtual_invocations++;
897
898         if (obj == NULL)
899                 mono_raise_exception (mono_get_exception_null_reference ());
900         vmethod = mono_object_get_virtual_method (obj, method);
901
902         /* 'vmethod' is partially inflated.  All the blanks corresponding to the type parameters of the
903            declaring class have been inflated.  We still need to fully inflate the method parameters.
904
905            FIXME: This code depends on the declaring class being fully inflated, since we inflate it twice with 
906            the same context.
907         */
908         g_assert (!vmethod->klass->generic_container);
909         g_assert (!vmethod->klass->generic_class || !vmethod->klass->generic_class->context.class_inst->is_open);
910         g_assert (!context->method_inst || !context->method_inst->is_open);
911         inflated = mono_class_inflate_generic_method (vmethod, context);
912         if (mono_class_generic_sharing_enabled (inflated->klass) &&
913                         mono_method_is_generic_sharable_impl (method, FALSE)) {
914                 /* The method is shared generic code, so it needs a
915                    MRGCTX. */
916                 inflated = mono_marshal_get_static_rgctx_invoke (inflated);
917         }
918         addr = mono_compile_method (inflated);
919
920         /* Since this is a virtual call, have to unbox vtypes */
921         if (obj->vtable->klass->valuetype)
922                 *this_arg = mono_object_unbox (obj);
923         else
924                 *this_arg = obj;
925
926         return addr;
927 }
928
929 MonoString*
930 mono_helper_ldstr (MonoImage *image, guint32 idx)
931 {
932         return mono_ldstr (mono_domain_get (), image, idx);
933 }
934
935 MonoString*
936 mono_helper_ldstr_mscorlib (guint32 idx)
937 {
938         return mono_ldstr (mono_domain_get (), mono_defaults.corlib, idx);
939 }
940
941 MonoObject*
942 mono_helper_newobj_mscorlib (guint32 idx)
943 {
944         MonoClass *klass = mono_class_get (mono_defaults.corlib, MONO_TOKEN_TYPE_DEF | idx);
945         
946         g_assert (klass);
947
948         return mono_object_new (mono_domain_get (), klass);
949 }
950
951 /*
952  * On some architectures, gdb doesn't like encountering the cpu breakpoint instructions
953  * in generated code. So instead we emit a call to this function and place a gdb
954  * breakpoint here.
955  */
956 void
957 mono_break (void)
958 {
959 }
960
961 MonoException *
962 mono_create_corlib_exception_0 (guint32 token)
963 {
964         return mono_exception_from_token (mono_defaults.corlib, token);
965 }
966
967 MonoException *
968 mono_create_corlib_exception_1 (guint32 token, MonoString *arg)
969 {
970         return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg, NULL);
971 }
972
973 MonoException *
974 mono_create_corlib_exception_2 (guint32 token, MonoString *arg1, MonoString *arg2)
975 {
976         return mono_exception_from_token_two_strings (mono_defaults.corlib, token, arg1, arg2);
977 }
978
979 MonoObject*
980 mono_object_castclass (MonoObject *obj, MonoClass *klass)
981 {
982         if (!obj)
983                 return NULL;
984
985         if (mono_object_isinst (obj, klass))
986                 return obj;
987
988         mono_raise_exception (mono_exception_from_name (mono_defaults.corlib,
989                                         "System", "InvalidCastException"));
990
991         return NULL;
992 }