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