1 /**
2  * \file
3  * Functions for creating IL methods at runtime.
4  *
5  * Author:
6  *   Paolo Molaro (lupus@ximian.com)
7  *
8  * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
9  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
10  * Licensed under the MIT license. See LICENSE file in the project root for full license information.
11  */
12 
13 #include "config.h"
14 #include "loader.h"
15 #include "mono/metadata/abi-details.h"
16 #include "mono/metadata/method-builder.h"
17 #include "mono/metadata/tabledefs.h"
18 #include "mono/metadata/exception.h"
19 #include "mono/metadata/appdomain.h"
20 #include "mono/metadata/debug-helpers.h"
21 #include "mono/metadata/metadata-internals.h"
22 #include "mono/metadata/domain-internals.h"
23 #include <string.h>
24 #include <errno.h>
25 
26 /* #define DEBUG_RUNTIME_CODE */
27 
28 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
29 	a = i,
30 
31 enum {
32 #include "mono/cil/opcode.def"
33 	LAST = 0xff
34 };
35 #undef OPDEF
36 
37 #ifdef DEBUG_RUNTIME_CODE
38 static char*
indenter(MonoDisHelper * dh,MonoMethod * method,guint32 ip_offset)39 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
40 {
41 	return g_strdup (" ");
42 }
43 
44 static MonoDisHelper marshal_dh = {
45 	"\n",
46 	"IL_%04x: ",
47 	"IL_%04x",
48 	indenter,
49 	NULL,
50 	NULL
51 };
52 #endif
53 
54 static MonoMethodBuilder *
mono_mb_new_base(MonoClass * klass,MonoWrapperType type)55 mono_mb_new_base (MonoClass *klass, MonoWrapperType type)
56 {
57 	MonoMethodBuilder *mb;
58 	MonoMethod *m;
59 
60 	g_assert (klass != NULL);
61 
62 	mb = g_new0 (MonoMethodBuilder, 1);
63 
64 	mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
65 
66 	m->klass = klass;
67 	m->inline_info = 1;
68 	m->wrapper_type = type;
69 
70 #ifdef ENABLE_ILGEN
71 	mb->code_size = 40;
72 	mb->code = (unsigned char *)g_malloc (mb->code_size);
73 	mb->init_locals = TRUE;
74 #endif
75 	/* placeholder for the wrapper always at index 1 */
76 	mono_mb_add_data (mb, NULL);
77 
78 	return mb;
79 }
80 
81 MonoMethodBuilder *
mono_mb_new_no_dup_name(MonoClass * klass,const char * name,MonoWrapperType type)82 mono_mb_new_no_dup_name (MonoClass *klass, const char *name, MonoWrapperType type)
83 {
84 	MonoMethodBuilder *mb = mono_mb_new_base (klass, type);
85 	mb->name = (char*)name;
86 	mb->no_dup_name = TRUE;
87 	return mb;
88 }
89 
90 /**
91  * mono_mb_new:
92  */
93 MonoMethodBuilder *
mono_mb_new(MonoClass * klass,const char * name,MonoWrapperType type)94 mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
95 {
96 	MonoMethodBuilder *mb = mono_mb_new_base (klass, type);
97 	mb->name = g_strdup (name);
98 	return mb;
99 }
100 
101 /**
102  * mono_mb_free:
103  */
104 void
mono_mb_free(MonoMethodBuilder * mb)105 mono_mb_free (MonoMethodBuilder *mb)
106 {
107 #ifdef ENABLE_ILGEN
108 	GList *l;
109 
110 	for (l = mb->locals_list; l; l = l->next) {
111 		/* Allocated in mono_mb_add_local () */
112 		g_free (l->data);
113 	}
114 	g_list_free (mb->locals_list);
115 	if (!mb->dynamic) {
116 		g_free (mb->method);
117 		if (!mb->no_dup_name)
118 			g_free (mb->name);
119 		g_free (mb->code);
120 	}
121 #else
122 	g_free (mb->method);
123 	if (!mb->no_dup_name)
124 		g_free (mb->name);
125 #endif
126 	g_free (mb);
127 }
128 
129 /**
130  * mono_mb_create_method:
131  * Create a \c MonoMethod from this method builder.
132  * \returns the newly created method.
133  */
134 MonoMethod *
mono_mb_create_method(MonoMethodBuilder * mb,MonoMethodSignature * signature,int max_stack)135 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
136 {
137 #ifdef ENABLE_ILGEN
138 	MonoMethodHeader *header;
139 #endif
140 	MonoMethodWrapper *mw;
141 	MonoImage *image;
142 	MonoMethod *method;
143 	GList *l;
144 	int i;
145 
146 	g_assert (mb != NULL);
147 
148 	image = mb->method->klass->image;
149 
150 #ifdef ENABLE_ILGEN
151 	if (mb->dynamic) {
152 		method = mb->method;
153 		mw = (MonoMethodWrapper*)method;
154 
155 		method->name = mb->name;
156 		method->dynamic = TRUE;
157 
158 		mw->header = header = (MonoMethodHeader *)
159 			g_malloc0 (MONO_SIZEOF_METHOD_HEADER + mb->locals * sizeof (MonoType *));
160 
161 		header->code = mb->code;
162 
163 		for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
164 			header->locals [i] = (MonoType*)l->data;
165 		}
166 	} else
167 #endif
168 	{
169 		/* Realloc the method info into a mempool */
170 
171 		method = (MonoMethod *)mono_image_alloc0 (image, sizeof (MonoMethodWrapper));
172 		memcpy (method, mb->method, sizeof (MonoMethodWrapper));
173 		mw = (MonoMethodWrapper*) method;
174 
175 		if (mb->no_dup_name)
176 			method->name = mb->name;
177 		else
178 			method->name = mono_image_strdup (image, mb->name);
179 
180 #ifdef ENABLE_ILGEN
181 		mw->header = header = (MonoMethodHeader *)
182 			mono_image_alloc0 (image, MONO_SIZEOF_METHOD_HEADER + mb->locals * sizeof (MonoType *));
183 
184 		header->code = (const unsigned char *)mono_image_alloc (image, mb->pos);
185 		memcpy ((char*)header->code, mb->code, mb->pos);
186 
187 		for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
188 			header->locals [i] = (MonoType*)l->data;
189 		}
190 #endif
191 	}
192 
193 #ifdef ENABLE_ILGEN
194 	/* Free the locals list so mono_mb_free () doesn't free the types twice */
195 	g_list_free (mb->locals_list);
196 	mb->locals_list = NULL;
197 #endif
198 
199 	method->signature = signature;
200 	if (!signature->hasthis)
201 		method->flags |= METHOD_ATTRIBUTE_STATIC;
202 
203 #ifdef ENABLE_ILGEN
204 	if (max_stack < 8)
205 		max_stack = 8;
206 
207 	header->max_stack = max_stack;
208 
209 	header->code_size = mb->pos;
210 	header->num_locals = mb->locals;
211 	header->init_locals = mb->init_locals;
212 
213 	header->num_clauses = mb->num_clauses;
214 	header->clauses = mb->clauses;
215 
216 	method->skip_visibility = mb->skip_visibility;
217 #endif
218 
219 	i = g_list_length ((GList *)mw->method_data);
220 	if (i) {
221 		GList *tmp;
222 		void **data;
223 		l = g_list_reverse ((GList *)mw->method_data);
224 		if (method_is_dynamic (method))
225 			data = (void **)g_malloc (sizeof (gpointer) * (i + 1));
226 		else
227 			data = (void **)mono_image_alloc (image, sizeof (gpointer) * (i + 1));
228 		/* store the size in the first element */
229 		data [0] = GUINT_TO_POINTER (i);
230 		i = 1;
231 		for (tmp = l; tmp; tmp = tmp->next) {
232 			data [i++] = tmp->data;
233 		}
234 		g_list_free (l);
235 
236 		mw->method_data = data;
237 	}
238 
239 #ifdef ENABLE_ILGEN
240 	/*{
241 		static int total_code = 0;
242 		static int total_alloc = 0;
243 		total_code += mb->pos;
244 		total_alloc += mb->code_size;
245 		g_print ("code size: %d of %d (allocated: %d)\n", mb->pos, total_code, total_alloc);
246 	}*/
247 
248 #ifdef DEBUG_RUNTIME_CODE
249 	printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (method, TRUE));
250 	printf ("%s\n", mono_disasm_code (&marshal_dh, method, mb->code, mb->code + mb->pos));
251 #endif
252 
253 	if (mb->param_names) {
254 		char **param_names = (char **)mono_image_alloc0 (image, signature->param_count * sizeof (gpointer));
255 		for (i = 0; i < signature->param_count; ++i)
256 			param_names [i] = mono_image_strdup (image, mb->param_names [i]);
257 
258 		mono_image_lock (image);
259 		if (!image->wrapper_param_names)
260 			image->wrapper_param_names = g_hash_table_new (NULL, NULL);
261 		g_hash_table_insert (image->wrapper_param_names, method, param_names);
262 		mono_image_unlock (image);
263 	}
264 #endif
265 
266 	return method;
267 }
268 
269 /**
270  * mono_mb_add_data:
271  */
272 guint32
mono_mb_add_data(MonoMethodBuilder * mb,gpointer data)273 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
274 {
275 	MonoMethodWrapper *mw;
276 
277 	g_assert (mb != NULL);
278 
279 	mw = (MonoMethodWrapper *)mb->method;
280 
281 	/* one O(n) is enough */
282 	mw->method_data = g_list_prepend ((GList *)mw->method_data, data);
283 
284 	return g_list_length ((GList *)mw->method_data);
285 }
286 
287 #ifdef ENABLE_ILGEN
288 
289 /**
290  * mono_mb_add_local:
291  */
292 int
mono_mb_add_local(MonoMethodBuilder * mb,MonoType * type)293 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
294 {
295 	int res;
296 	MonoType *t;
297 
298 	/*
299 	 * Have to make a copy early since type might be sig->ret,
300 	 * which is transient, see mono_metadata_signature_dup_internal_with_padding ().
301 	 */
302 	t = mono_metadata_type_dup (NULL, type);
303 
304 	g_assert (mb != NULL);
305 	g_assert (type != NULL);
306 
307 	res = mb->locals;
308 	mb->locals_list = g_list_append (mb->locals_list, t);
309 	mb->locals++;
310 
311 	return res;
312 }
313 
314 /**
315  * mono_mb_patch_addr:
316  */
317 void
mono_mb_patch_addr(MonoMethodBuilder * mb,int pos,int value)318 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
319 {
320 	mb->code [pos] = value & 0xff;
321 	mb->code [pos + 1] = (value >> 8) & 0xff;
322 	mb->code [pos + 2] = (value >> 16) & 0xff;
323 	mb->code [pos + 3] = (value >> 24) & 0xff;
324 }
325 
326 /**
327  * mono_mb_patch_addr_s:
328  */
329 void
mono_mb_patch_addr_s(MonoMethodBuilder * mb,int pos,gint8 value)330 mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
331 {
332 	*((gint8 *)(&mb->code [pos])) = value;
333 }
334 
335 /**
336  * mono_mb_emit_byte:
337  */
338 void
mono_mb_emit_byte(MonoMethodBuilder * mb,guint8 op)339 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
340 {
341 	if (mb->pos >= mb->code_size) {
342 		mb->code_size += mb->code_size >> 1;
343 		mb->code = (unsigned char *)g_realloc (mb->code, mb->code_size);
344 	}
345 
346 	mb->code [mb->pos++] = op;
347 }
348 
349 /**
350  * mono_mb_emit_ldflda:
351  */
352 void
mono_mb_emit_ldflda(MonoMethodBuilder * mb,gint32 offset)353 mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
354 {
355         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
356         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
357 
358 	if (offset) {
359 		mono_mb_emit_icon (mb, offset);
360 		mono_mb_emit_byte (mb, CEE_ADD);
361 	}
362 }
363 
364 /**
365  * mono_mb_emit_i4:
366  */
367 void
mono_mb_emit_i4(MonoMethodBuilder * mb,gint32 data)368 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
369 {
370 	if ((mb->pos + 4) >= mb->code_size) {
371 		mb->code_size += mb->code_size >> 1;
372 		mb->code = (unsigned char *)g_realloc (mb->code, mb->code_size);
373 	}
374 
375 	mono_mb_patch_addr (mb, mb->pos, data);
376 	mb->pos += 4;
377 }
378 
379 void
mono_mb_emit_i8(MonoMethodBuilder * mb,gint64 data)380 mono_mb_emit_i8 (MonoMethodBuilder *mb, gint64 data)
381 {
382 	if ((mb->pos + 8) >= mb->code_size) {
383 		mb->code_size += mb->code_size >> 1;
384 		mb->code = (unsigned char *)g_realloc (mb->code, mb->code_size);
385 	}
386 
387 	mono_mb_patch_addr (mb, mb->pos, data);
388 	mono_mb_patch_addr (mb, mb->pos + 4, data >> 32);
389 	mb->pos += 8;
390 }
391 
392 /**
393  * mono_mb_emit_i2:
394  */
395 void
mono_mb_emit_i2(MonoMethodBuilder * mb,gint16 data)396 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
397 {
398 	if ((mb->pos + 2) >= mb->code_size) {
399 		mb->code_size += mb->code_size >> 1;
400 		mb->code = (unsigned char *)g_realloc (mb->code, mb->code_size);
401 	}
402 
403 	mb->code [mb->pos] = data & 0xff;
404 	mb->code [mb->pos + 1] = (data >> 8) & 0xff;
405 	mb->pos += 2;
406 }
407 
408 void
mono_mb_emit_op(MonoMethodBuilder * mb,guint8 op,gpointer data)409 mono_mb_emit_op (MonoMethodBuilder *mb, guint8 op, gpointer data)
410 {
411 	mono_mb_emit_byte (mb, op);
412 	mono_mb_emit_i4 (mb, mono_mb_add_data (mb, data));
413 }
414 
415 /**
416  * mono_mb_emit_ldstr:
417  */
418 void
mono_mb_emit_ldstr(MonoMethodBuilder * mb,char * str)419 mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)
420 {
421 	mono_mb_emit_op (mb, CEE_LDSTR, str);
422 }
423 
424 /**
425  * mono_mb_emit_ldarg:
426  */
427 void
mono_mb_emit_ldarg(MonoMethodBuilder * mb,guint argnum)428 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
429 {
430 	if (argnum < 4) {
431  		mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
432 	} else if (argnum < 256) {
433 		mono_mb_emit_byte (mb, CEE_LDARG_S);
434 		mono_mb_emit_byte (mb, argnum);
435 	} else {
436 		mono_mb_emit_byte (mb, CEE_PREFIX1);
437 		mono_mb_emit_byte (mb, CEE_LDARG);
438 		mono_mb_emit_i2 (mb, argnum);
439 	}
440 }
441 
442 /**
443  * mono_mb_emit_ldarg_addr:
444  */
445 void
mono_mb_emit_ldarg_addr(MonoMethodBuilder * mb,guint argnum)446 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
447 {
448 	if (argnum < 256) {
449 		mono_mb_emit_byte (mb, CEE_LDARGA_S);
450 		mono_mb_emit_byte (mb, argnum);
451 	} else {
452 		mono_mb_emit_byte (mb, CEE_PREFIX1);
453 		mono_mb_emit_byte (mb, CEE_LDARGA);
454 		mono_mb_emit_i2 (mb, argnum);
455 	}
456 }
457 
458 /**
459  * mono_mb_emit_ldloc_addr:
460  */
461 void
mono_mb_emit_ldloc_addr(MonoMethodBuilder * mb,guint locnum)462 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
463 {
464 	if (locnum < 256) {
465 		mono_mb_emit_byte (mb, CEE_LDLOCA_S);
466 		mono_mb_emit_byte (mb, locnum);
467 	} else {
468 		mono_mb_emit_byte (mb, CEE_PREFIX1);
469 		mono_mb_emit_byte (mb, CEE_LDLOCA);
470 		mono_mb_emit_i2 (mb, locnum);
471 	}
472 }
473 
474 /**
475  * mono_mb_emit_ldloc:
476  */
477 void
mono_mb_emit_ldloc(MonoMethodBuilder * mb,guint num)478 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
479 {
480 	if (num < 4) {
481  		mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
482 	} else if (num < 256) {
483 		mono_mb_emit_byte (mb, CEE_LDLOC_S);
484 		mono_mb_emit_byte (mb, num);
485 	} else {
486 		mono_mb_emit_byte (mb, CEE_PREFIX1);
487 		mono_mb_emit_byte (mb, CEE_LDLOC);
488 		mono_mb_emit_i2 (mb, num);
489 	}
490 }
491 
492 /**
493  * mono_mb_emit_stloc:
494  */
495 void
mono_mb_emit_stloc(MonoMethodBuilder * mb,guint num)496 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
497 {
498 	if (num < 4) {
499  		mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
500 	} else if (num < 256) {
501 		mono_mb_emit_byte (mb, CEE_STLOC_S);
502 		mono_mb_emit_byte (mb, num);
503 	} else {
504 		mono_mb_emit_byte (mb, CEE_PREFIX1);
505 		mono_mb_emit_byte (mb, CEE_STLOC);
506 		mono_mb_emit_i2 (mb, num);
507 	}
508 }
509 
510 /**
511  * mono_mb_emit_icon:
512  */
513 void
mono_mb_emit_icon(MonoMethodBuilder * mb,gint32 value)514 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
515 {
516 	if (value >= -1 && value < 8) {
517 		mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
518 	} else if (value >= -128 && value <= 127) {
519 		mono_mb_emit_byte (mb, CEE_LDC_I4_S);
520 		mono_mb_emit_byte (mb, value);
521 	} else {
522 		mono_mb_emit_byte (mb, CEE_LDC_I4);
523 		mono_mb_emit_i4 (mb, value);
524 	}
525 }
526 
527 void
mono_mb_emit_icon8(MonoMethodBuilder * mb,gint64 value)528 mono_mb_emit_icon8 (MonoMethodBuilder *mb, gint64 value)
529 {
530 	mono_mb_emit_byte (mb, CEE_LDC_I8);
531 	mono_mb_emit_i8 (mb, value);
532 }
533 
534 int
mono_mb_get_label(MonoMethodBuilder * mb)535 mono_mb_get_label (MonoMethodBuilder *mb)
536 {
537 	return mb->pos;
538 }
539 
540 int
mono_mb_get_pos(MonoMethodBuilder * mb)541 mono_mb_get_pos (MonoMethodBuilder *mb)
542 {
543 	return mb->pos;
544 }
545 
546 /**
547  * mono_mb_emit_branch:
548  */
549 guint32
mono_mb_emit_branch(MonoMethodBuilder * mb,guint8 op)550 mono_mb_emit_branch (MonoMethodBuilder *mb, guint8 op)
551 {
552 	guint32 res;
553 	mono_mb_emit_byte (mb, op);
554 	res = mb->pos;
555 	mono_mb_emit_i4 (mb, 0);
556 	return res;
557 }
558 
559 guint32
mono_mb_emit_short_branch(MonoMethodBuilder * mb,guint8 op)560 mono_mb_emit_short_branch (MonoMethodBuilder *mb, guint8 op)
561 {
562 	guint32 res;
563 	mono_mb_emit_byte (mb, op);
564 	res = mb->pos;
565 	mono_mb_emit_byte (mb, 0);
566 
567 	return res;
568 }
569 
570 void
mono_mb_emit_branch_label(MonoMethodBuilder * mb,guint8 op,guint32 label)571 mono_mb_emit_branch_label (MonoMethodBuilder *mb, guint8 op, guint32 label)
572 {
573 	mono_mb_emit_byte (mb, op);
574 	mono_mb_emit_i4 (mb, label - (mb->pos + 4));
575 }
576 
577 void
mono_mb_patch_branch(MonoMethodBuilder * mb,guint32 pos)578 mono_mb_patch_branch (MonoMethodBuilder *mb, guint32 pos)
579 {
580 	mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
581 }
582 
583 void
mono_mb_patch_short_branch(MonoMethodBuilder * mb,guint32 pos)584 mono_mb_patch_short_branch (MonoMethodBuilder *mb, guint32 pos)
585 {
586 	mono_mb_patch_addr_s (mb, pos, mb->pos - (pos + 1));
587 }
588 
589 void
mono_mb_emit_ptr(MonoMethodBuilder * mb,gpointer ptr)590 mono_mb_emit_ptr (MonoMethodBuilder *mb, gpointer ptr)
591 {
592 	mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
593 	mono_mb_emit_op (mb, CEE_MONO_LDPTR, ptr);
594 }
595 
596 void
mono_mb_emit_calli(MonoMethodBuilder * mb,MonoMethodSignature * sig)597 mono_mb_emit_calli (MonoMethodBuilder *mb, MonoMethodSignature *sig)
598 {
599 	mono_mb_emit_op (mb, CEE_CALLI, sig);
600 }
601 
602 /**
603  * mono_mb_emit_managed_call:
604  */
605 void
mono_mb_emit_managed_call(MonoMethodBuilder * mb,MonoMethod * method,MonoMethodSignature * opt_sig)606 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
607 {
608 	mono_mb_emit_op (mb, CEE_CALL, method);
609 }
610 
611 /**
612  * mono_mb_emit_native_call:
613  */
614 void
mono_mb_emit_native_call(MonoMethodBuilder * mb,MonoMethodSignature * sig,gpointer func)615 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
616 {
617 	mono_mb_emit_ptr (mb, func);
618 	mono_mb_emit_calli (mb, sig);
619 }
620 
621 void
mono_mb_emit_icall(MonoMethodBuilder * mb,gpointer func)622 mono_mb_emit_icall (MonoMethodBuilder *mb, gpointer func)
623 {
624 	mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
625 	mono_mb_emit_op (mb, CEE_MONO_ICALL, func);
626 }
627 
628 void
mono_mb_emit_exception_full(MonoMethodBuilder * mb,const char * exc_nspace,const char * exc_name,const char * msg)629 mono_mb_emit_exception_full (MonoMethodBuilder *mb, const char *exc_nspace, const char *exc_name, const char *msg)
630 {
631 	MonoMethod *ctor = NULL;
632 
633 	MonoClass *mme = mono_class_load_from_name (mono_defaults.corlib, exc_nspace, exc_name);
634 	mono_class_init (mme);
635 	ctor = mono_class_get_method_from_name (mme, ".ctor", 0);
636 	g_assert (ctor);
637 	mono_mb_emit_op (mb, CEE_NEWOBJ, ctor);
638 	if (msg != NULL) {
639 		mono_mb_emit_byte (mb, CEE_DUP);
640 		mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoException, message));
641 		mono_mb_emit_ldstr (mb, (char*)msg);
642 		mono_mb_emit_byte (mb, CEE_STIND_REF);
643 	}
644 	mono_mb_emit_byte (mb, CEE_THROW);
645 }
646 
647 /**
648  * mono_mb_emit_exception:
649  */
650 void
mono_mb_emit_exception(MonoMethodBuilder * mb,const char * exc_name,const char * msg)651 mono_mb_emit_exception (MonoMethodBuilder *mb, const char *exc_name, const char *msg)
652 {
653 	mono_mb_emit_exception_full (mb, "System", exc_name, msg);
654 }
655 
656 /**
657  * mono_mb_emit_exception_for_error:
658  */
659 void
mono_mb_emit_exception_for_error(MonoMethodBuilder * mb,MonoError * error)660 mono_mb_emit_exception_for_error (MonoMethodBuilder *mb, MonoError *error)
661 {
662 	/*
663 	 * If at some point there is need to support other types of errors,
664 	 * the behaviour should conform with mono_error_prepare_exception().
665 	 */
666 	g_assert (mono_error_get_error_code (error) == MONO_ERROR_GENERIC && "Unsupported error code.");
667 	mono_mb_emit_exception_full (mb, "System", mono_error_get_exception_name (error), mono_error_get_message (error));
668 }
669 
670 /**
671  * mono_mb_emit_add_to_local:
672  */
673 void
mono_mb_emit_add_to_local(MonoMethodBuilder * mb,guint16 local,gint32 incr)674 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
675 {
676 	mono_mb_emit_ldloc (mb, local);
677 	mono_mb_emit_icon (mb, incr);
678 	mono_mb_emit_byte (mb, CEE_ADD);
679 	mono_mb_emit_stloc (mb, local);
680 }
681 
682 void
mono_mb_set_clauses(MonoMethodBuilder * mb,int num_clauses,MonoExceptionClause * clauses)683 mono_mb_set_clauses (MonoMethodBuilder *mb, int num_clauses, MonoExceptionClause *clauses)
684 {
685 	mb->num_clauses = num_clauses;
686 	mb->clauses = clauses;
687 }
688 
689 /*
690  * mono_mb_set_param_names:
691  *
692  *   PARAM_NAMES should have length equal to the sig->param_count, the caller retains
693  * ownership of the array, and its entries.
694  */
695 void
mono_mb_set_param_names(MonoMethodBuilder * mb,const char ** param_names)696 mono_mb_set_param_names (MonoMethodBuilder *mb, const char **param_names)
697 {
698 	mb->param_names = param_names;
699 }
700 
701 #endif /* DISABLE_JIT */
702