3 * Functions for creating IL methods at runtime.
6 * Paolo Molaro (lupus@ximian.com)
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.
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"
26 /* #define DEBUG_RUNTIME_CODE */
28 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
32 #include "mono/cil/opcode.def"
37 #ifdef DEBUG_RUNTIME_CODE
39 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
41 return g_strdup (" ");
44 static MonoDisHelper marshal_dh = {
54 static MonoMethodBuilder *
55 mono_mb_new_base (MonoClass *klass, MonoWrapperType type)
57 MonoMethodBuilder *mb;
60 g_assert (klass != NULL);
62 mb = g_new0 (MonoMethodBuilder, 1);
64 mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
68 m->wrapper_type = type;
72 mb->code = (unsigned char *)g_malloc (mb->code_size);
73 mb->init_locals = TRUE;
75 /* placeholder for the wrapper always at index 1 */
76 mono_mb_add_data (mb, NULL);
82 mono_mb_new_no_dup_name (MonoClass *klass, const char *name, MonoWrapperType type)
84 MonoMethodBuilder *mb = mono_mb_new_base (klass, type);
85 mb->name = (char*)name;
86 mb->no_dup_name = TRUE;
94 mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
96 MonoMethodBuilder *mb = mono_mb_new_base (klass, type);
97 mb->name = g_strdup (name);
105 mono_mb_free (MonoMethodBuilder *mb)
110 for (l = mb->locals_list; l; l = l->next) {
111 /* Allocated in mono_mb_add_local () */
114 g_list_free (mb->locals_list);
117 if (!mb->no_dup_name)
123 if (!mb->no_dup_name)
130 * mono_mb_create_method:
131 * Create a \c MonoMethod from this method builder.
132 * \returns the newly created method.
135 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
138 MonoMethodHeader *header;
140 MonoMethodWrapper *mw;
146 g_assert (mb != NULL);
148 image = mb->method->klass->image;
153 mw = (MonoMethodWrapper*)method;
155 method->name = mb->name;
156 method->dynamic = TRUE;
158 mw->header = header = (MonoMethodHeader *)
159 g_malloc0 (MONO_SIZEOF_METHOD_HEADER + mb->locals * sizeof (MonoType *));
161 header->code = mb->code;
163 for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
164 header->locals [i] = (MonoType*)l->data;
169 /* Realloc the method info into a mempool */
171 method = (MonoMethod *)mono_image_alloc0 (image, sizeof (MonoMethodWrapper));
172 memcpy (method, mb->method, sizeof (MonoMethodWrapper));
173 mw = (MonoMethodWrapper*) method;
176 method->name = mb->name;
178 method->name = mono_image_strdup (image, mb->name);
181 mw->header = header = (MonoMethodHeader *)
182 mono_image_alloc0 (image, MONO_SIZEOF_METHOD_HEADER + mb->locals * sizeof (MonoType *));
184 header->code = (const unsigned char *)mono_image_alloc (image, mb->pos);
185 memcpy ((char*)header->code, mb->code, mb->pos);
187 for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
188 header->locals [i] = (MonoType*)l->data;
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;
199 method->signature = signature;
200 if (!signature->hasthis)
201 method->flags |= METHOD_ATTRIBUTE_STATIC;
207 header->max_stack = max_stack;
209 header->code_size = mb->pos;
210 header->num_locals = mb->locals;
211 header->init_locals = mb->init_locals;
213 header->num_clauses = mb->num_clauses;
214 header->clauses = mb->clauses;
216 method->skip_visibility = mb->skip_visibility;
219 i = g_list_length ((GList *)mw->method_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));
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);
231 for (tmp = l; tmp; tmp = tmp->next) {
232 data [i++] = tmp->data;
236 mw->method_data = data;
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);
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));
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]);
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);
273 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
275 MonoMethodWrapper *mw;
277 g_assert (mb != NULL);
279 mw = (MonoMethodWrapper *)mb->method;
281 /* one O(n) is enough */
282 mw->method_data = g_list_prepend ((GList *)mw->method_data, data);
284 return g_list_length ((GList *)mw->method_data);
293 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
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 ().
302 t = mono_metadata_type_dup (NULL, type);
304 g_assert (mb != NULL);
305 g_assert (type != NULL);
308 mb->locals_list = g_list_append (mb->locals_list, t);
315 * mono_mb_patch_addr:
318 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
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;
327 * mono_mb_patch_addr_s:
330 mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
332 *((gint8 *)(&mb->code [pos])) = value;
339 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
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);
346 mb->code [mb->pos++] = op;
350 * mono_mb_emit_ldflda:
353 mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
355 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
356 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
359 mono_mb_emit_icon (mb, offset);
360 mono_mb_emit_byte (mb, CEE_ADD);
368 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
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);
375 mono_mb_patch_addr (mb, mb->pos, data);
380 mono_mb_emit_i8 (MonoMethodBuilder *mb, gint64 data)
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);
387 mono_mb_patch_addr (mb, mb->pos, data);
388 mono_mb_patch_addr (mb, mb->pos + 4, data >> 32);
396 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
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);
403 mb->code [mb->pos] = data & 0xff;
404 mb->code [mb->pos + 1] = (data >> 8) & 0xff;
409 mono_mb_emit_op (MonoMethodBuilder *mb, guint8 op, gpointer data)
411 mono_mb_emit_byte (mb, op);
412 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, data));
416 * mono_mb_emit_ldstr:
419 mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)
421 mono_mb_emit_op (mb, CEE_LDSTR, str);
425 * mono_mb_emit_ldarg:
428 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
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);
436 mono_mb_emit_byte (mb, CEE_PREFIX1);
437 mono_mb_emit_byte (mb, CEE_LDARG);
438 mono_mb_emit_i2 (mb, argnum);
443 * mono_mb_emit_ldarg_addr:
446 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
449 mono_mb_emit_byte (mb, CEE_LDARGA_S);
450 mono_mb_emit_byte (mb, argnum);
452 mono_mb_emit_byte (mb, CEE_PREFIX1);
453 mono_mb_emit_byte (mb, CEE_LDARGA);
454 mono_mb_emit_i2 (mb, argnum);
459 * mono_mb_emit_ldloc_addr:
462 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
465 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
466 mono_mb_emit_byte (mb, locnum);
468 mono_mb_emit_byte (mb, CEE_PREFIX1);
469 mono_mb_emit_byte (mb, CEE_LDLOCA);
470 mono_mb_emit_i2 (mb, locnum);
475 * mono_mb_emit_ldloc:
478 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
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);
486 mono_mb_emit_byte (mb, CEE_PREFIX1);
487 mono_mb_emit_byte (mb, CEE_LDLOC);
488 mono_mb_emit_i2 (mb, num);
493 * mono_mb_emit_stloc:
496 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
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);
504 mono_mb_emit_byte (mb, CEE_PREFIX1);
505 mono_mb_emit_byte (mb, CEE_STLOC);
506 mono_mb_emit_i2 (mb, num);
514 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
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);
522 mono_mb_emit_byte (mb, CEE_LDC_I4);
523 mono_mb_emit_i4 (mb, value);
528 mono_mb_emit_icon8 (MonoMethodBuilder *mb, gint64 value)
530 mono_mb_emit_byte (mb, CEE_LDC_I8);
531 mono_mb_emit_i8 (mb, value);
535 mono_mb_get_label (MonoMethodBuilder *mb)
541 mono_mb_get_pos (MonoMethodBuilder *mb)
547 * mono_mb_emit_branch:
550 mono_mb_emit_branch (MonoMethodBuilder *mb, guint8 op)
553 mono_mb_emit_byte (mb, op);
555 mono_mb_emit_i4 (mb, 0);
560 mono_mb_emit_short_branch (MonoMethodBuilder *mb, guint8 op)
563 mono_mb_emit_byte (mb, op);
565 mono_mb_emit_byte (mb, 0);
571 mono_mb_emit_branch_label (MonoMethodBuilder *mb, guint8 op, guint32 label)
573 mono_mb_emit_byte (mb, op);
574 mono_mb_emit_i4 (mb, label - (mb->pos + 4));
578 mono_mb_patch_branch (MonoMethodBuilder *mb, guint32 pos)
580 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
584 mono_mb_patch_short_branch (MonoMethodBuilder *mb, guint32 pos)
586 mono_mb_patch_addr_s (mb, pos, mb->pos - (pos + 1));
590 mono_mb_emit_ptr (MonoMethodBuilder *mb, gpointer ptr)
592 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
593 mono_mb_emit_op (mb, CEE_MONO_LDPTR, ptr);
597 mono_mb_emit_calli (MonoMethodBuilder *mb, MonoMethodSignature *sig)
599 mono_mb_emit_op (mb, CEE_CALLI, sig);
603 * mono_mb_emit_managed_call:
606 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
608 mono_mb_emit_op (mb, CEE_CALL, method);
612 * mono_mb_emit_native_call:
615 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
617 mono_mb_emit_ptr (mb, func);
618 mono_mb_emit_calli (mb, sig);
622 mono_mb_emit_icall (MonoMethodBuilder *mb, gpointer func)
624 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
625 mono_mb_emit_op (mb, CEE_MONO_ICALL, func);
629 mono_mb_emit_exception_full (MonoMethodBuilder *mb, const char *exc_nspace, const char *exc_name, const char *msg)
631 MonoMethod *ctor = NULL;
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);
637 mono_mb_emit_op (mb, CEE_NEWOBJ, ctor);
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);
644 mono_mb_emit_byte (mb, CEE_THROW);
648 * mono_mb_emit_exception:
651 mono_mb_emit_exception (MonoMethodBuilder *mb, const char *exc_name, const char *msg)
653 mono_mb_emit_exception_full (mb, "System", exc_name, msg);
657 * mono_mb_emit_exception_for_error:
660 mono_mb_emit_exception_for_error (MonoMethodBuilder *mb, MonoError *error)
663 * If at some point there is need to support other types of errors,
664 * the behaviour should conform with mono_error_prepare_exception().
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));
671 * mono_mb_emit_add_to_local:
674 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
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);
683 mono_mb_set_clauses (MonoMethodBuilder *mb, int num_clauses, MonoExceptionClause *clauses)
685 mb->num_clauses = num_clauses;
686 mb->clauses = clauses;
690 * mono_mb_set_param_names:
692 * PARAM_NAMES should have length equal to the sig->param_count, the caller retains
693 * ownership of the array, and its entries.
696 mono_mb_set_param_names (MonoMethodBuilder *mb, const char **param_names)
698 mb->param_names = param_names;
701 #endif /* DISABLE_JIT */