3b04c246494af2d77121e5cbbb55fbade2bb2d3b
[mono.git] / mono / metadata / method-builder.c
1 /*
2  * method-builder.c: Functions for creating IL methods at runtime.
3  * 
4  * Author:
5  *   Paolo Molaro (lupus@ximian.com)
6  *
7  * Copyright 2002-2003 Ximian, Inc (http://www.ximian.com)
8  * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
9  */
10
11 #include "config.h"
12 #include "loader.h"
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"
21 #include <string.h>
22 #include <errno.h>
23
24 /* #define DEBUG_RUNTIME_CODE */
25
26 #define OPDEF(a,b,c,d,e,f,g,h,i,j) \
27         a = i,
28
29 enum {
30 #include "mono/cil/opcode.def"
31         LAST = 0xff
32 };
33 #undef OPDEF
34
35 #ifdef DEBUG_RUNTIME_CODE
36 static char*
37 indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
38 {
39         return g_strdup (" ");
40 }
41
42 static MonoDisHelper marshal_dh = {
43         "\n",
44         "IL_%04x: ",
45         "IL_%04x",
46         indenter, 
47         NULL,
48         NULL
49 };
50 #endif 
51
52 static MonoMethodBuilder *
53 mono_mb_new_base (MonoClass *klass, MonoWrapperType type)
54 {
55         MonoMethodBuilder *mb;
56         MonoMethod *m;
57
58         g_assert (klass != NULL);
59
60         mb = g_new0 (MonoMethodBuilder, 1);
61
62         mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
63
64         m->klass = klass;
65         m->inline_info = 1;
66         m->wrapper_type = type;
67
68 #ifndef DISABLE_JIT
69         mb->code_size = 40;
70         mb->code = (unsigned char *)g_malloc (mb->code_size);
71         mb->init_locals = TRUE;
72 #endif
73         /* placeholder for the wrapper always at index 1 */
74         mono_mb_add_data (mb, NULL);
75
76         return mb;
77 }
78
79 MonoMethodBuilder *
80 mono_mb_new_no_dup_name (MonoClass *klass, const char *name, MonoWrapperType type)
81 {
82         MonoMethodBuilder *mb = mono_mb_new_base (klass, type);
83         mb->name = (char*)name;
84         mb->no_dup_name = TRUE;
85         return mb;
86 }
87
88 MonoMethodBuilder *
89 mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
90 {
91         MonoMethodBuilder *mb = mono_mb_new_base (klass, type);
92         mb->name = g_strdup (name);
93         return mb;
94 }
95
96 void
97 mono_mb_free (MonoMethodBuilder *mb)
98 {
99 #ifndef DISABLE_JIT
100         g_list_free (mb->locals_list);
101         if (!mb->dynamic) {
102                 g_free (mb->method);
103                 if (!mb->no_dup_name)
104                         g_free (mb->name);
105                 g_free (mb->code);
106         }
107 #else
108         g_free (mb->method);
109         if (!mb->no_dup_name)
110                 g_free (mb->name);
111 #endif
112         g_free (mb);
113 }
114
115 /**
116  * mono_mb_create_method:
117  *
118  * Create a MonoMethod from this method builder.
119  * Returns: the newly created method.
120  *
121  */
122 MonoMethod *
123 mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)
124 {
125 #ifndef DISABLE_JIT
126         MonoMethodHeader *header;
127 #endif
128         MonoMethodWrapper *mw;
129         MonoImage *image;
130         MonoMethod *method;
131         GList *l;
132         int i;
133
134         g_assert (mb != NULL);
135
136         image = mb->method->klass->image;
137
138 #ifndef DISABLE_JIT
139         if (mb->dynamic) {
140                 method = mb->method;
141                 mw = (MonoMethodWrapper*)method;
142
143                 method->name = mb->name;
144                 method->dynamic = TRUE;
145
146                 mw->header = header = (MonoMethodHeader *) 
147                         g_malloc0 (MONO_SIZEOF_METHOD_HEADER + mb->locals * sizeof (MonoType *));
148
149                 header->code = mb->code;
150
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);
153                 }
154         } else
155 #endif
156         {
157                 /* Realloc the method info into a mempool */
158
159                 method = (MonoMethod *)mono_image_alloc0 (image, sizeof (MonoMethodWrapper));
160                 memcpy (method, mb->method, sizeof (MonoMethodWrapper));
161                 mw = (MonoMethodWrapper*) method;
162
163                 if (mb->no_dup_name)
164                         method->name = mb->name;
165                 else
166                         method->name = mono_image_strdup (image, mb->name);
167
168 #ifndef DISABLE_JIT
169                 mw->header = header = (MonoMethodHeader *) 
170                         mono_image_alloc0 (image, MONO_SIZEOF_METHOD_HEADER + mb->locals * sizeof (MonoType *));
171
172                 header->code = (const unsigned char *)mono_image_alloc (image, mb->pos);
173                 memcpy ((char*)header->code, mb->code, mb->pos);
174
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);
177                 }
178 #endif
179         }
180
181         method->signature = signature;
182         if (!signature->hasthis)
183                 method->flags |= METHOD_ATTRIBUTE_STATIC;
184
185 #ifndef DISABLE_JIT
186         if (max_stack < 8)
187                 max_stack = 8;
188
189         header->max_stack = max_stack;
190
191         header->code_size = mb->pos;
192         header->num_locals = mb->locals;
193         header->init_locals = mb->init_locals;
194
195         header->num_clauses = mb->num_clauses;
196         header->clauses = mb->clauses;
197
198         method->skip_visibility = mb->skip_visibility;
199 #endif
200
201         i = g_list_length ((GList *)mw->method_data);
202         if (i) {
203                 GList *tmp;
204                 void **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));
208                 else
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);
212                 i = 1;
213                 for (tmp = l; tmp; tmp = tmp->next) {
214                         data [i++] = tmp->data;
215                 }
216                 g_list_free (l);
217
218                 mw->method_data = data;
219         }
220
221 #ifndef DISABLE_JIT
222         /*{
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);
228         }*/
229
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));
233 #endif
234
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]);
239
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);
245         }
246 #endif
247
248         return method;
249 }
250
251 guint32
252 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
253 {
254         MonoMethodWrapper *mw;
255
256         g_assert (mb != NULL);
257
258         mw = (MonoMethodWrapper *)mb->method;
259
260         /* one O(n) is enough */
261         mw->method_data = g_list_prepend ((GList *)mw->method_data, data);
262
263         return g_list_length ((GList *)mw->method_data);
264 }
265
266 #ifndef DISABLE_JIT
267
268 int
269 mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
270 {
271         int res;
272
273         g_assert (mb != NULL);
274         g_assert (type != NULL);
275
276         res = mb->locals;
277         mb->locals_list = g_list_append (mb->locals_list, type);
278         mb->locals++;
279
280         return res;
281 }
282
283 void
284 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
285 {
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;
290 }
291
292 void
293 mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
294 {
295         *((gint8 *)(&mb->code [pos])) = value;
296 }
297
298 void
299 mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
300 {
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);
304         }
305
306         mb->code [mb->pos++] = op;
307 }
308
309 void
310 mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
311 {
312         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
313         mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
314
315         if (offset) {
316                 mono_mb_emit_icon (mb, offset);
317                 mono_mb_emit_byte (mb, CEE_ADD);
318         }
319 }
320
321 void
322 mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
323 {
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);
327         }
328
329         mono_mb_patch_addr (mb, mb->pos, data);
330         mb->pos += 4;
331 }
332
333 void
334 mono_mb_emit_i8 (MonoMethodBuilder *mb, gint64 data)
335 {
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);
339         }
340
341         mono_mb_patch_addr (mb, mb->pos, data);
342         mono_mb_patch_addr (mb, mb->pos + 4, data >> 32);
343         mb->pos += 8;
344 }
345
346 void
347 mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
348 {
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);
352         }
353
354         mb->code [mb->pos] = data & 0xff;
355         mb->code [mb->pos + 1] = (data >> 8) & 0xff;
356         mb->pos += 2;
357 }
358
359 void
360 mono_mb_emit_op (MonoMethodBuilder *mb, guint8 op, gpointer data)
361 {
362         mono_mb_emit_byte (mb, op);
363         mono_mb_emit_i4 (mb, mono_mb_add_data (mb, data));
364 }
365
366 void
367 mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)
368 {
369         mono_mb_emit_op (mb, CEE_LDSTR, str);
370 }
371
372 void
373 mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
374 {
375         if (argnum < 4) {
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);
380         } else {
381                 mono_mb_emit_byte (mb, CEE_PREFIX1);
382                 mono_mb_emit_byte (mb, CEE_LDARG);
383                 mono_mb_emit_i2 (mb, argnum);
384         }
385 }
386
387 void
388 mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
389 {
390         if (argnum < 256) {
391                 mono_mb_emit_byte (mb, CEE_LDARGA_S);
392                 mono_mb_emit_byte (mb, argnum);
393         } else {
394                 mono_mb_emit_byte (mb, CEE_PREFIX1);
395                 mono_mb_emit_byte (mb, CEE_LDARGA);
396                 mono_mb_emit_i2 (mb, argnum);
397         }
398 }
399
400 void
401 mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
402 {
403         if (locnum < 256) {
404                 mono_mb_emit_byte (mb, CEE_LDLOCA_S);
405                 mono_mb_emit_byte (mb, locnum);
406         } else {
407                 mono_mb_emit_byte (mb, CEE_PREFIX1);
408                 mono_mb_emit_byte (mb, CEE_LDLOCA);
409                 mono_mb_emit_i2 (mb, locnum);
410         }
411 }
412
413 void
414 mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
415 {
416         if (num < 4) {
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);
421         } else {
422                 mono_mb_emit_byte (mb, CEE_PREFIX1);
423                 mono_mb_emit_byte (mb, CEE_LDLOC);
424                 mono_mb_emit_i2 (mb, num);
425         }
426 }
427
428 void
429 mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
430 {
431         if (num < 4) {
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);
436         } else {
437                 mono_mb_emit_byte (mb, CEE_PREFIX1);
438                 mono_mb_emit_byte (mb, CEE_STLOC);
439                 mono_mb_emit_i2 (mb, num);
440         }
441 }
442
443 void
444 mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
445 {
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);
451         } else {
452                 mono_mb_emit_byte (mb, CEE_LDC_I4);
453                 mono_mb_emit_i4 (mb, value);
454         }
455 }
456
457 void
458 mono_mb_emit_icon8 (MonoMethodBuilder *mb, gint64 value)
459 {
460         mono_mb_emit_byte (mb, CEE_LDC_I8);
461         mono_mb_emit_i8 (mb, value);
462 }
463
464 int
465 mono_mb_get_label (MonoMethodBuilder *mb)
466 {
467         return mb->pos;
468 }
469
470 int
471 mono_mb_get_pos (MonoMethodBuilder *mb)
472 {
473         return mb->pos;
474 }
475
476 guint32
477 mono_mb_emit_branch (MonoMethodBuilder *mb, guint8 op)
478 {
479         guint32 res;
480         mono_mb_emit_byte (mb, op);
481         res = mb->pos;
482         mono_mb_emit_i4 (mb, 0);
483         return res;
484 }
485
486 guint32
487 mono_mb_emit_short_branch (MonoMethodBuilder *mb, guint8 op)
488 {
489         guint32 res;
490         mono_mb_emit_byte (mb, op);
491         res = mb->pos;
492         mono_mb_emit_byte (mb, 0);
493
494         return res;
495 }
496
497 void
498 mono_mb_emit_branch_label (MonoMethodBuilder *mb, guint8 op, guint32 label)
499 {
500         mono_mb_emit_byte (mb, op);
501         mono_mb_emit_i4 (mb, label - (mb->pos + 4));
502 }
503
504 void
505 mono_mb_patch_branch (MonoMethodBuilder *mb, guint32 pos)
506 {
507         mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
508 }
509
510 void
511 mono_mb_patch_short_branch (MonoMethodBuilder *mb, guint32 pos)
512 {
513         mono_mb_patch_addr_s (mb, pos, mb->pos - (pos + 1));
514 }
515
516 void
517 mono_mb_emit_ptr (MonoMethodBuilder *mb, gpointer ptr)
518 {
519         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
520         mono_mb_emit_op (mb, CEE_MONO_LDPTR, ptr);
521 }
522
523 void
524 mono_mb_emit_calli (MonoMethodBuilder *mb, MonoMethodSignature *sig)
525 {
526         mono_mb_emit_op (mb, CEE_CALLI, sig);
527 }
528
529 void
530 mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)
531 {
532         mono_mb_emit_op (mb, CEE_CALL, method);
533 }
534
535 void
536 mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)
537 {
538         mono_mb_emit_ptr (mb, func);
539         mono_mb_emit_calli (mb, sig);
540 }
541
542 void
543 mono_mb_emit_icall (MonoMethodBuilder *mb, gpointer func)
544 {
545         mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
546         mono_mb_emit_op (mb, CEE_MONO_ICALL, func);
547 }
548
549 void
550 mono_mb_emit_exception_full (MonoMethodBuilder *mb, const char *exc_nspace, const char *exc_name, const char *msg)
551 {
552         MonoMethod *ctor = NULL;
553
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);
557         g_assert (ctor);
558         mono_mb_emit_op (mb, CEE_NEWOBJ, ctor);
559         if (msg != NULL) {
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);
564         }
565         mono_mb_emit_byte (mb, CEE_THROW);
566 }
567
568 void
569 mono_mb_emit_exception (MonoMethodBuilder *mb, const char *exc_name, const char *msg)
570 {
571         mono_mb_emit_exception_full (mb, "System", exc_name, msg);
572 }
573
574 void
575 mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
576 {
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); 
581 }
582
583 void
584 mono_mb_set_clauses (MonoMethodBuilder *mb, int num_clauses, MonoExceptionClause *clauses)
585 {
586         mb->num_clauses = num_clauses;
587         mb->clauses = clauses;
588 }
589
590 /*
591  * mono_mb_set_param_names:
592  *
593  *   PARAM_NAMES should have length equal to the sig->param_count, the caller retains
594  * ownership of the array, and its entries.
595  */
596 void
597 mono_mb_set_param_names (MonoMethodBuilder *mb, const char **param_names)
598 {
599         mb->param_names = param_names;
600 }
601
602 #endif /* DISABLE_JIT */