Author: zoltan
Date: 2007-12-23 17:01:31 -0500 (Sun, 23 Dec 2007)
New Revision: 91846

Added:
   trunk/mono/mono/metadata/method-builder.c
Modified:
   trunk/mono/mono/metadata/ChangeLog
   trunk/mono/mono/metadata/Makefile.am
   trunk/mono/mono/metadata/marshal.c
   trunk/mono/mono/metadata/marshal.h
Log:
2007-12-23  Zoltan Varga  <[EMAIL PROTECTED]>

        * method-builder.c: New file, extraction of the method builder 
functionality 
        from marshal.c.

        * marshal.c: Move the mb functions into method-builder.c.


Modified: trunk/mono/mono/metadata/ChangeLog
===================================================================
--- trunk/mono/mono/metadata/ChangeLog  2007-12-23 21:47:34 UTC (rev 91845)
+++ trunk/mono/mono/metadata/ChangeLog  2007-12-23 22:01:31 UTC (rev 91846)
@@ -1,5 +1,10 @@
 2007-12-23  Zoltan Varga  <[EMAIL PROTECTED]>
 
+       * method-builder.c: New file, extraction of the method builder 
functionality 
+       from marshal.c.
+
+       * marshal.c: Move the mb functions into method-builder.c.
+
        * marshal.h marshal.c: Export some mono_mb_... functions.
 
        * marshal.c: Use mono_mb_get_label () and mono_mb_patch_branch () in 
all places.

Modified: trunk/mono/mono/metadata/Makefile.am
===================================================================
--- trunk/mono/mono/metadata/Makefile.am        2007-12-23 21:47:34 UTC (rev 
91845)
+++ trunk/mono/mono/metadata/Makefile.am        2007-12-23 22:01:31 UTC (rev 
91846)
@@ -53,6 +53,7 @@
        sgen-gc.h       \
        gc.c            \
        gc-internal.h   \
+       method-builder.c \
        marshal.c       \
        marshal.h       \
        mono-mlist.c    \

Modified: trunk/mono/mono/metadata/marshal.c
===================================================================
--- trunk/mono/mono/metadata/marshal.c  2007-12-23 21:47:34 UTC (rev 91845)
+++ trunk/mono/mono/metadata/marshal.c  2007-12-23 22:01:31 UTC (rev 91846)
@@ -1204,233 +1204,6 @@
        *((gunichar2 *) dst + len) = 0;
 }
 
-void
-mono_mb_free (MonoMethodBuilder *mb)
-{
-       g_list_free (mb->locals_list);
-       if (!mb->dynamic) {
-               g_free (mb->method);
-               if (!mb->no_dup_name)
-                       g_free (mb->name);
-               g_free (mb->code);
-       }
-       g_free (mb);
-}
-
-static MonoMethodBuilder *
-mono_mb_new_base (MonoClass *klass, MonoWrapperType type)
-{
-       MonoMethodBuilder *mb;
-       MonoMethod *m;
-
-       g_assert (klass != NULL);
-
-       mb = g_new0 (MonoMethodBuilder, 1);
-
-       mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
-
-       m->klass = klass;
-       m->inline_info = 1;
-       m->wrapper_type = type;
-
-       mb->code_size = 40;
-       mb->code = g_malloc (mb->code_size);
-       
-       return mb;
-}
-
-static MonoMethodBuilder *
-mono_mb_new_no_dup_name (MonoClass *klass, const char *name, MonoWrapperType 
type)
-{
-       MonoMethodBuilder *mb = mono_mb_new_base (klass, type);
-       mb->name = (char*)name;
-       mb->no_dup_name = TRUE;
-       return mb;
-}
-
-MonoMethodBuilder *
-mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
-{
-       MonoMethodBuilder *mb = mono_mb_new_base (klass, type);
-       mb->name = g_strdup (name);
-       return mb;
-}
-
-int
-mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
-{
-       int res;
-
-       g_assert (mb != NULL);
-       g_assert (type != NULL);
-
-       res = mb->locals;
-       mb->locals_list = g_list_append (mb->locals_list, type);
-       mb->locals++;
-
-       return res;
-}
-
-/**
- * mono_mb_create_method:
- *
- * Create a MonoMethod from this method builder.
- * Returns: the newly created method.
- *
- * LOCKING: Takes the loader lock.
- */
-MonoMethod *
-mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, 
int max_stack)
-{
-       MonoMethodHeader *header;
-       MonoMethodWrapper *mw;
-       MonoMemPool *mp;
-       MonoMethod *method;
-       GList *l;
-       int i;
-
-       g_assert (mb != NULL);
-
-       mp = mb->method->klass->image->mempool;
-
-       mono_loader_lock ();
-       if (mb->dynamic) {
-               method = mb->method;
-
-               method->name = mb->name;
-               method->dynamic = TRUE;
-
-               ((MonoMethodNormal *)method)->header = header = 
(MonoMethodHeader *) 
-                       g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * 
sizeof (MonoType *));
-
-               header->code = mb->code;
-
-               for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
-                       header->locals [i] = mono_metadata_type_dup (NULL, 
(MonoType*)l->data);
-               }
-       } else {
-               /* Realloc the method info into a mempool */
-
-               method = mono_mempool_alloc0 (mp, sizeof (MonoMethodWrapper));
-               memcpy (method, mb->method, sizeof (MonoMethodWrapper));
-
-               if (mb->no_dup_name)
-                       method->name = mb->name;
-               else
-                       method->name = mono_mempool_strdup (mp, mb->name);
-
-               ((MonoMethodNormal *)method)->header = header = 
(MonoMethodHeader *) 
-                       mono_mempool_alloc0 (mp, sizeof (MonoMethodHeader) + 
mb->locals * sizeof (MonoType *));
-
-               header->code = mono_mempool_alloc (mp, mb->pos);
-               memcpy ((char*)header->code, mb->code, mb->pos);
-
-               for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
-                       header->locals [i] = (MonoType *)l->data;
-               }
-       }
-
-       if (max_stack < 8)
-               max_stack = 8;
-
-       header->max_stack = max_stack;
-
-       method->signature = signature;
-
-       header->code_size = mb->pos;
-       header->num_locals = mb->locals;
-       header->init_locals = TRUE;
-
-       mw = (MonoMethodWrapper*) mb->method;
-       i = g_list_length (mw->method_data);
-       if (i) {
-               GList *tmp;
-               void **data;
-               l = g_list_reverse (mw->method_data);
-               if (method->dynamic)
-                       data = g_malloc (sizeof (gpointer) * (i + 1));
-               else
-                       data = mono_mempool_alloc (mp, sizeof (gpointer) * (i + 
1));
-               /* store the size in the first element */
-               data [0] = GUINT_TO_POINTER (i);
-               i = 1;
-               for (tmp = l; tmp; tmp = tmp->next) {
-                       data [i++] = tmp->data;
-               }
-               g_list_free (l);
-
-               ((MonoMethodWrapper*)method)->method_data = data;
-       }
-       /*{
-               static int total_code = 0;
-               static int total_alloc = 0;
-               total_code += mb->pos;
-               total_alloc += mb->code_size;
-               g_print ("code size: %d of %d (allocated: %d)\n", mb->pos, 
total_code, total_alloc);
-       }*/
-
-#ifdef DEBUG_RUNTIME_CODE
-       printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (method, TRUE));
-       printf ("%s\n", mono_disasm_code (&marshal_dh, method, mb->code, 
mb->code + mb->pos));
-#endif
-
-       mono_loader_unlock ();
-       return method;
-}
-
-guint32
-mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
-{
-       MonoMethodWrapper *mw;
-
-       g_assert (mb != NULL);
-
-       mw = (MonoMethodWrapper *)mb->method;
-
-       /* one O(n) is enough */
-       mw->method_data = g_list_prepend (mw->method_data, data);
-
-       return g_list_length (mw->method_data);
-}
-
-void
-mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
-{
-       mb->code [pos] = value & 0xff;
-       mb->code [pos + 1] = (value >> 8) & 0xff;
-       mb->code [pos + 2] = (value >> 16) & 0xff;
-       mb->code [pos + 3] = (value >> 24) & 0xff;
-}
-
-void
-mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
-{
-       *((gint8 *)(&mb->code [pos])) = value;
-}
-
-void
-mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
-{
-       if (mb->pos >= mb->code_size) {
-               mb->code_size += mb->code_size >> 1;
-               mb->code = g_realloc (mb->code, mb->code_size);
-       }
-
-       mb->code [mb->pos++] = op;
-}
-
-void
-mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
-{
-        mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
-        mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
-
-       if (offset) {
-               mono_mb_emit_icon (mb, offset);
-               mono_mb_emit_byte (mb, CEE_ADD);
-       }
-}
-
 static int
 mono_mb_emit_proxy_check (MonoMethodBuilder *mb, int branch_code)
 {
@@ -1464,206 +1237,7 @@
        return pos;
 }
 
-void
-mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
-{
-       if ((mb->pos + 4) >= mb->code_size) {
-               mb->code_size += mb->code_size >> 1;
-               mb->code = g_realloc (mb->code, mb->code_size);
-       }
-
-       mono_mb_patch_addr (mb, mb->pos, data);
-       mb->pos += 4;
-}
-
-void
-mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
-{
-       if ((mb->pos + 2) >= mb->code_size) {
-               mb->code_size += mb->code_size >> 1;
-               mb->code = g_realloc (mb->code, mb->code_size);
-       }
-
-       mb->code [mb->pos] = data & 0xff;
-       mb->code [mb->pos + 1] = (data >> 8) & 0xff;
-       mb->pos += 2;
-}
-
-void
-mono_mb_emit_op (MonoMethodBuilder *mb, guint8 op, gpointer data)
-{
-       mono_mb_emit_byte (mb, op);
-       mono_mb_emit_i4 (mb, mono_mb_add_data (mb, data));
-}
-
-void
-mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)
-{
-       mono_mb_emit_op (mb, CEE_LDSTR, str);
-}
-
-void
-mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
-{
-       if (argnum < 4) {
-               mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
-       } else if (argnum < 256) {
-               mono_mb_emit_byte (mb, CEE_LDARG_S);
-               mono_mb_emit_byte (mb, argnum);
-       } else {
-               mono_mb_emit_byte (mb, CEE_PREFIX1);
-               mono_mb_emit_byte (mb, CEE_LDARG);
-               mono_mb_emit_i2 (mb, argnum);
-       }
-}
-
-void
-mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
-{
-       if (argnum < 256) {
-               mono_mb_emit_byte (mb, CEE_LDARGA_S);
-               mono_mb_emit_byte (mb, argnum);
-       } else {
-               mono_mb_emit_byte (mb, CEE_PREFIX1);
-               mono_mb_emit_byte (mb, CEE_LDARGA);
-               mono_mb_emit_i2 (mb, argnum);
-       }
-}
-
-void
-mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
-{
-       if (locnum < 256) {
-               mono_mb_emit_byte (mb, CEE_LDLOCA_S);
-               mono_mb_emit_byte (mb, locnum);
-       } else {
-               mono_mb_emit_byte (mb, CEE_PREFIX1);
-               mono_mb_emit_byte (mb, CEE_LDLOCA);
-               mono_mb_emit_i2 (mb, locnum);
-       }
-}
-
-void
-mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
-{
-       if (num < 4) {
-               mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
-       } else if (num < 256) {
-               mono_mb_emit_byte (mb, CEE_LDLOC_S);
-               mono_mb_emit_byte (mb, num);
-       } else {
-               mono_mb_emit_byte (mb, CEE_PREFIX1);
-               mono_mb_emit_byte (mb, CEE_LDLOC);
-               mono_mb_emit_i2 (mb, num);
-       }
-}
-
-void
-mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
-{
-       if (num < 4) {
-               mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
-       } else if (num < 256) {
-               mono_mb_emit_byte (mb, CEE_STLOC_S);
-               mono_mb_emit_byte (mb, num);
-       } else {
-               mono_mb_emit_byte (mb, CEE_PREFIX1);
-               mono_mb_emit_byte (mb, CEE_STLOC);
-               mono_mb_emit_i2 (mb, num);
-       }
-}
-
-void
-mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
-{
-       if (value >= -1 && value < 8) {
-               mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
-       } else if (value >= -128 && value <= 127) {
-               mono_mb_emit_byte (mb, CEE_LDC_I4_S);
-               mono_mb_emit_byte (mb, value);
-       } else {
-               mono_mb_emit_byte (mb, CEE_LDC_I4);
-               mono_mb_emit_i4 (mb, value);
-       }
-}
-
-int
-mono_mb_get_label (MonoMethodBuilder *mb)
-{
-       return mb->pos;
-}
-
-guint32
-mono_mb_emit_branch (MonoMethodBuilder *mb, guint8 op)
-{
-       guint32 res;
-       mono_mb_emit_byte (mb, op);
-       res = mb->pos;
-       mono_mb_emit_i4 (mb, 0);
-       return res;
-}
-
-guint32
-mono_mb_emit_short_branch (MonoMethodBuilder *mb, guint8 op)
-{
-       guint32 res;
-       mono_mb_emit_byte (mb, op);
-       res = mb->pos;
-       mono_mb_emit_byte (mb, 0);
-
-       return res;
-}
-
-void
-mono_mb_patch_branch (MonoMethodBuilder *mb, guint32 pos)
-{
-       mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
-}
-
-void
-mono_mb_patch_short_branch (MonoMethodBuilder *mb, guint32 pos)
-{
-       mono_mb_patch_addr_s (mb, pos, mb->pos - (pos + 1));
-}
-
 static void
-mono_mb_emit_ptr (MonoMethodBuilder *mb, gpointer ptr)
-{
-       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
-       mono_mb_emit_op (mb, CEE_MONO_LDPTR, ptr);
-}
-
-void
-mono_mb_emit_calli (MonoMethodBuilder *mb, MonoMethodSignature *sig)
-{
-       mono_mb_emit_op (mb, CEE_CALLI, sig);
-}
-
-void
-mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, 
MonoMethodSignature *opt_sig)
-{
-       mono_mb_emit_op (mb, CEE_CALL, method);
-}
-
-void
-mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, 
gpointer func)
-{
-       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
-       mono_mb_emit_byte (mb, CEE_MONO_SAVE_LMF);
-       mono_mb_emit_ptr (mb, func);
-       mono_mb_emit_calli (mb, sig);
-       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
-       mono_mb_emit_byte (mb, CEE_MONO_RESTORE_LMF);
-}
-
-void
-mono_mb_emit_icall (MonoMethodBuilder *mb, gpointer func)
-{
-       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
-       mono_mb_emit_op (mb, CEE_MONO_ICALL, func);
-}
-
-static void
 mono_mb_emit_cominterop_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, 
MonoMethod* method)
 {
        // get function pointer from 1st arg, the COM interface pointer
@@ -1678,46 +1252,12 @@
        mono_mb_emit_byte (mb, CEE_MONO_RESTORE_LMF);
 }
 
-void
-mono_mb_emit_exception_full (MonoMethodBuilder *mb, const char *exc_nspace, 
const char *exc_name, const char *msg)
-{
-       MonoMethod *ctor = NULL;
-
-       MonoClass *mme = mono_class_from_name (mono_defaults.corlib, 
exc_nspace, exc_name);
-       mono_class_init (mme);
-       ctor = mono_class_get_method_from_name (mme, ".ctor", 0);
-       g_assert (ctor);
-       mono_mb_emit_op (mb, CEE_NEWOBJ, ctor);
-       if (msg != NULL) {
-               mono_mb_emit_byte (mb, CEE_DUP);
-               mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoException, 
message));
-               mono_mb_emit_ldstr (mb, (char*)msg);
-               mono_mb_emit_byte (mb, CEE_STIND_REF);
-       }
-       mono_mb_emit_byte (mb, CEE_THROW);
-}
-
-void
-mono_mb_emit_exception (MonoMethodBuilder *mb, const char *exc_name, const 
char *msg)
-{
-       mono_mb_emit_exception_full (mb, "System", exc_name, msg);
-}
-
 static void
 mono_mb_emit_exception_marshal_directive (MonoMethodBuilder *mb, const char 
*msg)
 {
        mono_mb_emit_exception_full (mb, "System.Runtime.InteropServices", 
"MarshalDirectiveException", msg);
 }
 
-void
-mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
-{
-       mono_mb_emit_ldloc (mb, local); 
-       mono_mb_emit_icon (mb, incr);
-       mono_mb_emit_byte (mb, CEE_ADD);
-       mono_mb_emit_stloc (mb, local); 
-}
-
 guint
 mono_type_to_ldind (MonoType *type)
 {

Modified: trunk/mono/mono/metadata/marshal.h
===================================================================
--- trunk/mono/mono/metadata/marshal.h  2007-12-23 21:47:34 UTC (rev 91845)
+++ trunk/mono/mono/metadata/marshal.h  2007-12-23 22:01:31 UTC (rev 91846)
@@ -95,13 +95,16 @@
 
 /* method builder functions */
 
-void
-mono_mb_free (MonoMethodBuilder *mb) MONO_INTERNAL;
-
 MonoMethodBuilder *
 mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type) 
MONO_INTERNAL;
 
+MonoMethodBuilder *
+mono_mb_new_no_dup_name (MonoClass *klass, const char *name, MonoWrapperType 
type) MONO_INTERNAL;
+
 void
+mono_mb_free (MonoMethodBuilder *mb) MONO_INTERNAL;
+
+void
 mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value) MONO_INTERNAL;
 
 void
@@ -120,6 +123,9 @@
 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data) MONO_INTERNAL;
 
 void
+mono_mb_emit_ptr (MonoMethodBuilder *mb, gpointer ptr) MONO_INTERNAL;
+
+void
 mono_mb_emit_calli (MonoMethodBuilder *mb, MonoMethodSignature *sig) 
MONO_INTERNAL;
 
 void

Added: trunk/mono/mono/metadata/method-builder.c
===================================================================
--- trunk/mono/mono/metadata/method-builder.c   2007-12-23 21:47:34 UTC (rev 
91845)
+++ trunk/mono/mono/metadata/method-builder.c   2007-12-23 22:01:31 UTC (rev 
91846)
@@ -0,0 +1,528 @@
+/*
+ * method-builder.c: Functions for creating IL methods at runtime.
+ * 
+ * Author:
+ *   Paolo Molaro ([EMAIL PROTECTED])
+ *
+ * (C) 2002 Ximian, Inc.  http://www.ximian.com
+ *
+ */
+
+#include "config.h"
+#include "object.h"
+#include "loader.h"
+#include "metadata/marshal.h"
+#include "metadata/tabledefs.h"
+#include "metadata/exception.h"
+#include "metadata/appdomain.h"
+#include "mono/metadata/debug-helpers.h"
+#include "mono/metadata/threadpool.h"
+#include "mono/metadata/threads.h"
+#include "mono/metadata/monitor.h"
+#include "mono/metadata/metadata-internals.h"
+#include "mono/metadata/domain-internals.h"
+#include "mono/metadata/gc-internal.h"
+#include "mono/metadata/threads-types.h"
+#include "mono/metadata/string-icalls.h"
+#include <mono/os/gc_wrapper.h>
+#include <string.h>
+#include <errno.h>
+
+/* #define DEBUG_RUNTIME_CODE */
+
+#define OPDEF(a,b,c,d,e,f,g,h,i,j) \
+       a = i,
+
+enum {
+#include "mono/cil/opcode.def"
+       LAST = 0xff
+};
+#undef OPDEF
+
+struct _MonoMethodBuilder {
+       MonoMethod *method;
+       char *name;
+       GList *locals_list;
+       int locals;
+       gboolean dynamic;
+       gboolean no_dup_name;
+       guint32 code_size, pos;
+       unsigned char *code;
+};
+
+#ifdef DEBUG_RUNTIME_CODE
+static char*
+indenter (MonoDisHelper *dh, MonoMethod *method, guint32 ip_offset)
+{
+       return g_strdup (" ");
+}
+
+static MonoDisHelper marshal_dh = {
+       "\n",
+       "IL_%04x: ",
+       "IL_%04x",
+       indenter, 
+       NULL,
+       NULL
+};
+#endif 
+
+static MonoMethodBuilder *
+mono_mb_new_base (MonoClass *klass, MonoWrapperType type)
+{
+       MonoMethodBuilder *mb;
+       MonoMethod *m;
+
+       g_assert (klass != NULL);
+
+       mb = g_new0 (MonoMethodBuilder, 1);
+
+       mb->method = m = (MonoMethod *)g_new0 (MonoMethodWrapper, 1);
+
+       m->klass = klass;
+       m->inline_info = 1;
+       m->wrapper_type = type;
+
+       mb->code_size = 40;
+       mb->code = g_malloc (mb->code_size);
+       
+       return mb;
+}
+
+MonoMethodBuilder *
+mono_mb_new_no_dup_name (MonoClass *klass, const char *name, MonoWrapperType 
type)
+{
+       MonoMethodBuilder *mb = mono_mb_new_base (klass, type);
+       mb->name = (char*)name;
+       mb->no_dup_name = TRUE;
+       return mb;
+}
+
+MonoMethodBuilder *
+mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)
+{
+       MonoMethodBuilder *mb = mono_mb_new_base (klass, type);
+       mb->name = g_strdup (name);
+       return mb;
+}
+
+void
+mono_mb_free (MonoMethodBuilder *mb)
+{
+       g_list_free (mb->locals_list);
+       if (!mb->dynamic) {
+               g_free (mb->method);
+               if (!mb->no_dup_name)
+                       g_free (mb->name);
+               g_free (mb->code);
+       }
+       g_free (mb);
+}
+
+int
+mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)
+{
+       int res;
+
+       g_assert (mb != NULL);
+       g_assert (type != NULL);
+
+       res = mb->locals;
+       mb->locals_list = g_list_append (mb->locals_list, type);
+       mb->locals++;
+
+       return res;
+}
+
+/**
+ * mono_mb_create_method:
+ *
+ * Create a MonoMethod from this method builder.
+ * Returns: the newly created method.
+ *
+ * LOCKING: Takes the loader lock.
+ */
+MonoMethod *
+mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, 
int max_stack)
+{
+       MonoMethodHeader *header;
+       MonoMethodWrapper *mw;
+       MonoMemPool *mp;
+       MonoMethod *method;
+       GList *l;
+       int i;
+
+       g_assert (mb != NULL);
+
+       mp = mb->method->klass->image->mempool;
+
+       mono_loader_lock ();
+       if (mb->dynamic) {
+               method = mb->method;
+
+               method->name = mb->name;
+               method->dynamic = TRUE;
+
+               ((MonoMethodNormal *)method)->header = header = 
(MonoMethodHeader *) 
+                       g_malloc0 (sizeof (MonoMethodHeader) + mb->locals * 
sizeof (MonoType *));
+
+               header->code = mb->code;
+
+               for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
+                       header->locals [i] = mono_metadata_type_dup (NULL, 
(MonoType*)l->data);
+               }
+       } else {
+               /* Realloc the method info into a mempool */
+
+               method = mono_mempool_alloc0 (mp, sizeof (MonoMethodWrapper));
+               memcpy (method, mb->method, sizeof (MonoMethodWrapper));
+
+               if (mb->no_dup_name)
+                       method->name = mb->name;
+               else
+                       method->name = mono_mempool_strdup (mp, mb->name);
+
+               ((MonoMethodNormal *)method)->header = header = 
(MonoMethodHeader *) 
+                       mono_mempool_alloc0 (mp, sizeof (MonoMethodHeader) + 
mb->locals * sizeof (MonoType *));
+
+               header->code = mono_mempool_alloc (mp, mb->pos);
+               memcpy ((char*)header->code, mb->code, mb->pos);
+
+               for (i = 0, l = mb->locals_list; l; l = l->next, i++) {
+                       header->locals [i] = (MonoType *)l->data;
+               }
+       }
+
+       if (max_stack < 8)
+               max_stack = 8;
+
+       header->max_stack = max_stack;
+
+       method->signature = signature;
+
+       header->code_size = mb->pos;
+       header->num_locals = mb->locals;
+       header->init_locals = TRUE;
+
+       mw = (MonoMethodWrapper*) mb->method;
+       i = g_list_length (mw->method_data);
+       if (i) {
+               GList *tmp;
+               void **data;
+               l = g_list_reverse (mw->method_data);
+               if (method->dynamic)
+                       data = g_malloc (sizeof (gpointer) * (i + 1));
+               else
+                       data = mono_mempool_alloc (mp, sizeof (gpointer) * (i + 
1));
+               /* store the size in the first element */
+               data [0] = GUINT_TO_POINTER (i);
+               i = 1;
+               for (tmp = l; tmp; tmp = tmp->next) {
+                       data [i++] = tmp->data;
+               }
+               g_list_free (l);
+
+               ((MonoMethodWrapper*)method)->method_data = data;
+       }
+       /*{
+               static int total_code = 0;
+               static int total_alloc = 0;
+               total_code += mb->pos;
+               total_alloc += mb->code_size;
+               g_print ("code size: %d of %d (allocated: %d)\n", mb->pos, 
total_code, total_alloc);
+       }*/
+
+#ifdef DEBUG_RUNTIME_CODE
+       printf ("RUNTIME CODE FOR %s\n", mono_method_full_name (method, TRUE));
+       printf ("%s\n", mono_disasm_code (&marshal_dh, method, mb->code, 
mb->code + mb->pos));
+#endif
+
+       mono_loader_unlock ();
+       return method;
+}
+
+guint32
+mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)
+{
+       MonoMethodWrapper *mw;
+
+       g_assert (mb != NULL);
+
+       mw = (MonoMethodWrapper *)mb->method;
+
+       /* one O(n) is enough */
+       mw->method_data = g_list_prepend (mw->method_data, data);
+
+       return g_list_length (mw->method_data);
+}
+
+void
+mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)
+{
+       mb->code [pos] = value & 0xff;
+       mb->code [pos + 1] = (value >> 8) & 0xff;
+       mb->code [pos + 2] = (value >> 16) & 0xff;
+       mb->code [pos + 3] = (value >> 24) & 0xff;
+}
+
+void
+mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)
+{
+       *((gint8 *)(&mb->code [pos])) = value;
+}
+
+void
+mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)
+{
+       if (mb->pos >= mb->code_size) {
+               mb->code_size += mb->code_size >> 1;
+               mb->code = g_realloc (mb->code, mb->code_size);
+       }
+
+       mb->code [mb->pos++] = op;
+}
+
+void
+mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)
+{
+        mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+        mono_mb_emit_byte (mb, CEE_MONO_OBJADDR);
+
+       if (offset) {
+               mono_mb_emit_icon (mb, offset);
+               mono_mb_emit_byte (mb, CEE_ADD);
+       }
+}
+
+void
+mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)
+{
+       if ((mb->pos + 4) >= mb->code_size) {
+               mb->code_size += mb->code_size >> 1;
+               mb->code = g_realloc (mb->code, mb->code_size);
+       }
+
+       mono_mb_patch_addr (mb, mb->pos, data);
+       mb->pos += 4;
+}
+
+void
+mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)
+{
+       if ((mb->pos + 2) >= mb->code_size) {
+               mb->code_size += mb->code_size >> 1;
+               mb->code = g_realloc (mb->code, mb->code_size);
+       }
+
+       mb->code [mb->pos] = data & 0xff;
+       mb->code [mb->pos + 1] = (data >> 8) & 0xff;
+       mb->pos += 2;
+}
+
+void
+mono_mb_emit_op (MonoMethodBuilder *mb, guint8 op, gpointer data)
+{
+       mono_mb_emit_byte (mb, op);
+       mono_mb_emit_i4 (mb, mono_mb_add_data (mb, data));
+}
+
+void
+mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)
+{
+       mono_mb_emit_op (mb, CEE_LDSTR, str);
+}
+
+void
+mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)
+{
+       if (argnum < 4) {
+               mono_mb_emit_byte (mb, CEE_LDARG_0 + argnum);
+       } else if (argnum < 256) {
+               mono_mb_emit_byte (mb, CEE_LDARG_S);
+               mono_mb_emit_byte (mb, argnum);
+       } else {
+               mono_mb_emit_byte (mb, CEE_PREFIX1);
+               mono_mb_emit_byte (mb, CEE_LDARG);
+               mono_mb_emit_i2 (mb, argnum);
+       }
+}
+
+void
+mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)
+{
+       if (argnum < 256) {
+               mono_mb_emit_byte (mb, CEE_LDARGA_S);
+               mono_mb_emit_byte (mb, argnum);
+       } else {
+               mono_mb_emit_byte (mb, CEE_PREFIX1);
+               mono_mb_emit_byte (mb, CEE_LDARGA);
+               mono_mb_emit_i2 (mb, argnum);
+       }
+}
+
+void
+mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)
+{
+       if (locnum < 256) {
+               mono_mb_emit_byte (mb, CEE_LDLOCA_S);
+               mono_mb_emit_byte (mb, locnum);
+       } else {
+               mono_mb_emit_byte (mb, CEE_PREFIX1);
+               mono_mb_emit_byte (mb, CEE_LDLOCA);
+               mono_mb_emit_i2 (mb, locnum);
+       }
+}
+
+void
+mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)
+{
+       if (num < 4) {
+               mono_mb_emit_byte (mb, CEE_LDLOC_0 + num);
+       } else if (num < 256) {
+               mono_mb_emit_byte (mb, CEE_LDLOC_S);
+               mono_mb_emit_byte (mb, num);
+       } else {
+               mono_mb_emit_byte (mb, CEE_PREFIX1);
+               mono_mb_emit_byte (mb, CEE_LDLOC);
+               mono_mb_emit_i2 (mb, num);
+       }
+}
+
+void
+mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)
+{
+       if (num < 4) {
+               mono_mb_emit_byte (mb, CEE_STLOC_0 + num);
+       } else if (num < 256) {
+               mono_mb_emit_byte (mb, CEE_STLOC_S);
+               mono_mb_emit_byte (mb, num);
+       } else {
+               mono_mb_emit_byte (mb, CEE_PREFIX1);
+               mono_mb_emit_byte (mb, CEE_STLOC);
+               mono_mb_emit_i2 (mb, num);
+       }
+}
+
+void
+mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)
+{
+       if (value >= -1 && value < 8) {
+               mono_mb_emit_byte (mb, CEE_LDC_I4_0 + value);
+       } else if (value >= -128 && value <= 127) {
+               mono_mb_emit_byte (mb, CEE_LDC_I4_S);
+               mono_mb_emit_byte (mb, value);
+       } else {
+               mono_mb_emit_byte (mb, CEE_LDC_I4);
+               mono_mb_emit_i4 (mb, value);
+       }
+}
+
+int
+mono_mb_get_label (MonoMethodBuilder *mb)
+{
+       return mb->pos;
+}
+
+guint32
+mono_mb_emit_branch (MonoMethodBuilder *mb, guint8 op)
+{
+       guint32 res;
+       mono_mb_emit_byte (mb, op);
+       res = mb->pos;
+       mono_mb_emit_i4 (mb, 0);
+       return res;
+}
+
+guint32
+mono_mb_emit_short_branch (MonoMethodBuilder *mb, guint8 op)
+{
+       guint32 res;
+       mono_mb_emit_byte (mb, op);
+       res = mb->pos;
+       mono_mb_emit_byte (mb, 0);
+
+       return res;
+}
+
+void
+mono_mb_patch_branch (MonoMethodBuilder *mb, guint32 pos)
+{
+       mono_mb_patch_addr (mb, pos, mb->pos - (pos + 4));
+}
+
+void
+mono_mb_patch_short_branch (MonoMethodBuilder *mb, guint32 pos)
+{
+       mono_mb_patch_addr_s (mb, pos, mb->pos - (pos + 1));
+}
+
+void
+mono_mb_emit_ptr (MonoMethodBuilder *mb, gpointer ptr)
+{
+       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+       mono_mb_emit_op (mb, CEE_MONO_LDPTR, ptr);
+}
+
+void
+mono_mb_emit_calli (MonoMethodBuilder *mb, MonoMethodSignature *sig)
+{
+       mono_mb_emit_op (mb, CEE_CALLI, sig);
+}
+
+void
+mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, 
MonoMethodSignature *opt_sig)
+{
+       mono_mb_emit_op (mb, CEE_CALL, method);
+}
+
+void
+mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, 
gpointer func)
+{
+       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+       mono_mb_emit_byte (mb, CEE_MONO_SAVE_LMF);
+       mono_mb_emit_ptr (mb, func);
+       mono_mb_emit_calli (mb, sig);
+       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+       mono_mb_emit_byte (mb, CEE_MONO_RESTORE_LMF);
+}
+
+void
+mono_mb_emit_icall (MonoMethodBuilder *mb, gpointer func)
+{
+       mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+       mono_mb_emit_op (mb, CEE_MONO_ICALL, func);
+}
+
+void
+mono_mb_emit_exception_full (MonoMethodBuilder *mb, const char *exc_nspace, 
const char *exc_name, const char *msg)
+{
+       MonoMethod *ctor = NULL;
+
+       MonoClass *mme = mono_class_from_name (mono_defaults.corlib, 
exc_nspace, exc_name);
+       mono_class_init (mme);
+       ctor = mono_class_get_method_from_name (mme, ".ctor", 0);
+       g_assert (ctor);
+       mono_mb_emit_op (mb, CEE_NEWOBJ, ctor);
+       if (msg != NULL) {
+               mono_mb_emit_byte (mb, CEE_DUP);
+               mono_mb_emit_ldflda (mb, G_STRUCT_OFFSET (MonoException, 
message));
+               mono_mb_emit_ldstr (mb, (char*)msg);
+               mono_mb_emit_byte (mb, CEE_STIND_REF);
+       }
+       mono_mb_emit_byte (mb, CEE_THROW);
+}
+
+void
+mono_mb_emit_exception (MonoMethodBuilder *mb, const char *exc_name, const 
char *msg)
+{
+       mono_mb_emit_exception_full (mb, "System", exc_name, msg);
+}
+
+void
+mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)
+{
+       mono_mb_emit_ldloc (mb, local); 
+       mono_mb_emit_icon (mb, incr);
+       mono_mb_emit_byte (mb, CEE_ADD);
+       mono_mb_emit_stloc (mb, local); 
+}

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to