2 * method-builder.c: Functions for creating IL methods at runtime.
5 * Paolo Molaro (lupus@ximian.com)
7 * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
8 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 #include "mono/metadata/abi-details.h"
14 #include "mono/metadata/method-builder.h"
15 #include "mono/metadata/tabledefs.h"
16 #include "mono/metadata/exception.h"
17 #include "mono/metadata/appdomain.h"
18 #include "mono/metadata/debug-helpers.h"
19 #include "mono/metadata/metadata-internals.h"
20 #include "mono/metadata/domain-internals.h"
24 /* #define DEBUG_RUNTIME_CODE */
26 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
30 #include "mono/cil/opcode.def"
35 #ifdef DEBUG_RUNTIME_CODE
37 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
39 return g_strdup (" ");
42 static MonoDisHelper marshal_dh = {
52 static MonoMethodBuilder *
53 mono_mb_new_base (MonoClass *klass, MonoWrapperType type)
55 MonoMethodBuilder *mb;
58 g_assert (klass != NULL);
60 mb = g_new0 (MonoMethodBuilder, 1);
62 mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
66 m->wrapper_type = type;
70 mb->code = (unsigned char *)g_malloc (mb->code_size);
71 mb->init_locals = TRUE;
73 /* placeholder for the wrapper always at index 1 */
74 mono_mb_add_data (mb, NULL);
80 mono_mb_new_no_dup_name (MonoClass *klass, const char *name, MonoWrapperType type)
82 MonoMethodBuilder *mb = mono_mb_new_base (klass, type);
83 mb->name = (char*)name;
84 mb->no_dup_name = TRUE;
89 mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
91 MonoMethodBuilder *mb = mono_mb_new_base (klass, type);
92 mb->name = g_strdup (name);
97 mono_mb_free (MonoMethodBuilder *mb)
100 g_list_free (mb->locals_list);
103 if (!mb->no_dup_name)
109 if (!mb->no_dup_name)
116 * mono_mb_create_method:
118 * Create a MonoMethod from this method builder.
119 * Returns: the newly created method.
123 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
126 MonoMethodHeader *header;
128 MonoMethodWrapper *mw;
134 g_assert (mb != NULL);
136 image = mb->method->klass->image;
141 mw = (MonoMethodWrapper*)method;
143 method->name = mb->name;
144 method->dynamic = TRUE;
146 mw->header = header = (MonoMethodHeader *)
147 g_malloc0 (MONO_SIZEOF_METHOD_HEADER + mb->locals * sizeof (MonoType *));
149 header->code = mb->code;
151 for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
152 header->locals [i] = mono_metadata_type_dup (NULL, (MonoType*)l->data);
157 /* Realloc the method info into a mempool */
159 method = (MonoMethod *)mono_image_alloc0 (image, sizeof (MonoMethodWrapper));
160 memcpy (method, mb->method, sizeof (MonoMethodWrapper));
161 mw = (MonoMethodWrapper*) method;
164 method->name = mb->name;
166 method->name = mono_image_strdup (image, mb->name);
169 mw->header = header = (MonoMethodHeader *)
170 mono_image_alloc0 (image, MONO_SIZEOF_METHOD_HEADER + mb->locals * sizeof (MonoType *));
172 header->code = (const unsigned char *)mono_image_alloc (image, mb->pos);
173 memcpy ((char*)header->code, mb->code, mb->pos);
175 for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
176 header->locals [i] = mono_metadata_type_dup (NULL, (MonoType*)l->data);
181 method->signature = signature;
182 if (!signature->hasthis)
183 method->flags |= METHOD_ATTRIBUTE_STATIC;
189 header->max_stack = max_stack;
191 header->code_size = mb->pos;
192 header->num_locals = mb->locals;
193 header->init_locals = mb->init_locals;
195 header->num_clauses = mb->num_clauses;
196 header->clauses = mb->clauses;
198 method->skip_visibility = mb->skip_visibility;
201 i = g_list_length ((GList *)mw->method_data);
205 l = g_list_reverse ((GList *)mw->method_data);
206 if (method_is_dynamic (method))
207 data = (void **)g_malloc (sizeof (gpointer) * (i + 1));
209 data = (void **)mono_image_alloc (image, sizeof (gpointer) * (i + 1));
210 /* store the size in the first element */
211 data [0] = GUINT_TO_POINTER (i);
213 for (tmp = l; tmp; tmp = tmp->next) {
214 data [i++] = tmp->data;
218 mw->method_data = data;
223 static int total_code = 0;
224 static int total_alloc = 0;
225 total_code += mb->pos;
226 total_alloc += mb->code_size;
227 g_print ("code size: %d of %d (allocated: %d)\n", mb->pos, total_code, total_alloc);
230 #ifdef DEBUG_RUNTIME_CODE
231 printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (method, TRUE));
232 printf ("%s\n", mono_disasm_code (&marshal_dh, method, mb->code, mb->code + mb->pos));
235 if (mb->param_names) {
236 char **param_names = (char **)mono_image_alloc0 (image, signature->param_count * sizeof (gpointer));
237 for (i = 0; i < signature->param_count; ++i)
238 param_names [i] = mono_image_strdup (image, mb->param_names [i]);
240 mono_image_lock (image);
241 if (!image->wrapper_param_names)
242 image->wrapper_param_names = g_hash_table_new (NULL, NULL);
243 g_hash_table_insert (image->wrapper_param_names, method, param_names);
244 mono_image_unlock (image);
252 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
254 MonoMethodWrapper *mw;
256 g_assert (mb != NULL);
258 mw = (MonoMethodWrapper *)mb->method;
260 /* one O(n) is enough */
261 mw->method_data = g_list_prepend ((GList *)mw->method_data, data);
263 return g_list_length ((GList *)mw->method_data);
269 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
273 g_assert (mb != NULL);
274 g_assert (type != NULL);
277 mb->locals_list = g_list_append (mb->locals_list, type);
284 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
286 mb->code [pos] = value & 0xff;
287 mb->code [pos + 1] = (value >> 8) & 0xff;
288 mb->code [pos + 2] = (value >> 16) & 0xff;
289 mb->code [pos + 3] = (value >> 24) & 0xff;
293 mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
295 *((gint8 *)(&mb->code [pos])) = value;
299 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
301 if (mb->pos >= mb->code_size) {
302 mb->code_size += mb->code_size >> 1;
303 mb->code = (unsigned char *)g_realloc (mb->code, mb->code_size);
306 mb->code [mb->pos++] = op;
310 mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
312 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
313 mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
316 mono_mb_emit_icon (mb, offset);
317 mono_mb_emit_byte (mb, CEE_ADD);
322 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
324 if ((mb->pos + 4) >= mb->code_size) {
325 mb->code_size += mb->code_size >> 1;
326 mb->code = (unsigned char *)g_realloc (mb->code, mb->code_size);
329 mono_mb_patch_addr (mb, mb->pos, data);
334 mono_mb_emit_i8 (MonoMethodBuilder *mb, gint64 data)
336 if ((mb->pos + 8) >= mb->code_size) {
337 mb->code_size += mb->code_size >> 1;
338 mb->code = (unsigned char *)g_realloc (mb->code, mb->code_size);
341 mono_mb_patch_addr (mb, mb->pos, data);
342 mono_mb_patch_addr (mb, mb->pos + 4, data >> 32);
347 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
349 if ((mb->pos + 2) >= mb->code_size) {
350 mb->code_size += mb->code_size >> 1;
351 mb->code = (unsigned char *)g_realloc (mb->code, mb->code_size);
354 mb->code [mb->pos] = data & 0xff;
355 mb->code [mb->pos + 1] = (data >> 8) & 0xff;
360 mono_mb_emit_op (MonoMethodBuilder *mb, guint8 op, gpointer data)
362 mono_mb_emit_byte (mb, op);
363 mono_mb_emit_i4 (mb, mono_mb_add_data (mb, data));
367 mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)
369 mono_mb_emit_op (mb, CEE_LDSTR, str);
373 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
376 mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
377 } else if (argnum < 256) {
378 mono_mb_emit_byte (mb, CEE_LDARG_S);
379 mono_mb_emit_byte (mb, argnum);
381 mono_mb_emit_byte (mb, CEE_PREFIX1);
382 mono_mb_emit_byte (mb, CEE_LDARG);
383 mono_mb_emit_i2 (mb, argnum);
388 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
391 mono_mb_emit_byte (mb, CEE_LDARGA_S);
392 mono_mb_emit_byte (mb, argnum);
394 mono_mb_emit_byte (mb, CEE_PREFIX1);
395 mono_mb_emit_byte (mb, CEE_LDARGA);
396 mono_mb_emit_i2 (mb, argnum);
401 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
404 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
405 mono_mb_emit_byte (mb, locnum);
407 mono_mb_emit_byte (mb, CEE_PREFIX1);
408 mono_mb_emit_byte (mb, CEE_LDLOCA);
409 mono_mb_emit_i2 (mb, locnum);
414 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
417 mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
418 } else if (num < 256) {
419 mono_mb_emit_byte (mb, CEE_LDLOC_S);
420 mono_mb_emit_byte (mb, num);
422 mono_mb_emit_byte (mb, CEE_PREFIX1);
423 mono_mb_emit_byte (mb, CEE_LDLOC);
424 mono_mb_emit_i2 (mb, num);
429 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
432 mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
433 } else if (num < 256) {
434 mono_mb_emit_byte (mb, CEE_STLOC_S);
435 mono_mb_emit_byte (mb, num);
437 mono_mb_emit_byte (mb, CEE_PREFIX1);
438 mono_mb_emit_byte (mb, CEE_STLOC);
439 mono_mb_emit_i2 (mb, num);
444 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
446 if (value >= -1 && value < 8) {
447 mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
448 } else if (value >= -128 && value <= 127) {
449 mono_mb_emit_byte (mb, CEE_LDC_I4_S);
450 mono_mb_emit_byte (mb, value);
452 mono_mb_emit_byte (mb, CEE_LDC_I4);
453 mono_mb_emit_i4 (mb, value);
458 mono_mb_emit_icon8 (MonoMethodBuilder *mb, gint64 value)
460 mono_mb_emit_byte (mb, CEE_LDC_I8);
461 mono_mb_emit_i8 (mb, value);
465 mono_mb_get_label (MonoMethodBuilder *mb)
471 mono_mb_get_pos (MonoMethodBuilder *mb)
477 mono_mb_emit_branch (MonoMethodBuilder *mb, guint8 op)
480 mono_mb_emit_byte (mb, op);
482 mono_mb_emit_i4 (mb, 0);
487 mono_mb_emit_short_branch (MonoMethodBuilder *mb, guint8 op)
490 mono_mb_emit_byte (mb, op);
492 mono_mb_emit_byte (mb, 0);
498 mono_mb_emit_branch_label (MonoMethodBuilder *mb, guint8 op, guint32 label)
500 mono_mb_emit_byte (mb, op);
501 mono_mb_emit_i4 (mb, label - (mb->pos + 4));
505 mono_mb_patch_branch (MonoMethodBuilder *mb, guint32 pos)
507 mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
511 mono_mb_patch_short_branch (MonoMethodBuilder *mb, guint32 pos)
513 mono_mb_patch_addr_s (mb, pos, mb->pos - (pos + 1));
517 mono_mb_emit_ptr (MonoMethodBuilder *mb, gpointer ptr)
519 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
520 mono_mb_emit_op (mb, CEE_MONO_LDPTR, ptr);
524 mono_mb_emit_calli (MonoMethodBuilder *mb, MonoMethodSignature *sig)
526 mono_mb_emit_op (mb, CEE_CALLI, sig);
530 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
532 mono_mb_emit_op (mb, CEE_CALL, method);
536 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
538 mono_mb_emit_ptr (mb, func);
539 mono_mb_emit_calli (mb, sig);
543 mono_mb_emit_icall (MonoMethodBuilder *mb, gpointer func)
545 mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
546 mono_mb_emit_op (mb, CEE_MONO_ICALL, func);
550 mono_mb_emit_exception_full (MonoMethodBuilder *mb, const char *exc_nspace, const char *exc_name, const char *msg)
552 MonoMethod *ctor = NULL;
554 MonoClass *mme = mono_class_load_from_name (mono_defaults.corlib, exc_nspace, exc_name);
555 mono_class_init (mme);
556 ctor = mono_class_get_method_from_name (mme, ".ctor", 0);
558 mono_mb_emit_op (mb, CEE_NEWOBJ, ctor);
560 mono_mb_emit_byte (mb, CEE_DUP);
561 mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoException, message));
562 mono_mb_emit_ldstr (mb, (char*)msg);
563 mono_mb_emit_byte (mb, CEE_STIND_REF);
565 mono_mb_emit_byte (mb, CEE_THROW);
569 mono_mb_emit_exception (MonoMethodBuilder *mb, const char *exc_name, const char *msg)
571 mono_mb_emit_exception_full (mb, "System", exc_name, msg);
575 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
577 mono_mb_emit_ldloc (mb, local);
578 mono_mb_emit_icon (mb, incr);
579 mono_mb_emit_byte (mb, CEE_ADD);
580 mono_mb_emit_stloc (mb, local);
584 mono_mb_set_clauses (MonoMethodBuilder *mb, int num_clauses, MonoExceptionClause *clauses)
586 mb->num_clauses = num_clauses;
587 mb->clauses = clauses;
591 * mono_mb_set_param_names:
593 * PARAM_NAMES should have length equal to the sig->param_count, the caller retains
594 * ownership of the array, and its entries.
597 mono_mb_set_param_names (MonoMethodBuilder *mb, const char **param_names)
599 mb->param_names = param_names;
602 #endif /* DISABLE_JIT */