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