mono-api-dynamic-codegen.html

## Internal: Dynamic Code Generation

The dynamic code generation interface inside the Mono runtime is similar to the API exposed by System.Reflection.Emit.

This interface is used by Mono internally to generate code on the flight in a cross-platform fashion. For example, P/Invoke marshalling in Mono is implemented in terms of this interface, but it is also used in various other parts of the runtime.

Unlike Reflection.Emit, the dynamic code generation interface does not start with an assembly builder. The code generation interface starts directly at the method level, which is represented by a pointer to the MonoMethodBuilder structure.

To JIT this method, the process is this:

- Create a `MonoMethodBuilder` object using the `mono_mb_new` method. The method's class is specified as the first argument.
- Create the method signature, using `mono_metadata_signature_alloc`. The call takes the number of arguments that the method takes. Then you must initialize the types for each one of the parameters.
- Emit the CIL code, using one of the `mono_mb_emit_*` functions. There are some helper routines that you can use.
- Create the `MonoMethod` from the `MethodBuilder` using `mono_mb_create_method`.
- Release the `MonoMethodBuilder` resources using mono_mb_free.

The result of this process is a `MonoMethod` which can be called using `mono_create_jit_trampoline` routine or can be passed to any other functions that require the MonoMethod.

Example:

    MonoMethod *adder ()
    {
        MonoMethodBuilder *mb;
        MonoMethodSignature *sig;
        MonoMethod *method;

        mb = mono_mb_new (mono_defaults.object_class, "adder", MONO_WRAPPER_NONE);

        /* Setup method signature */
        sig = mono_metadata_signature_alloc (2);
        sig->ret = &mono_get_int32_class ()->byval_arg;
        sig->params [0] = &mono_get_int32_class ()->byval_arg;
        sig->params [1] = &mono_defaults.int32_class->byval_arg;

        /* Emit CIL code */
        mono_mb_emit_ldarg (mb, 0);
        mono_mb_emit_ldarg (mb, 1);
        mono_mb_emit_byte (mb, CEE_ADD);
        mono_mb_emit_byte (mb, CEE_RET);

        /* Get the method */
        method = mono_mb_create_method (mb, sig, max_stack);

        /* Cleanup */
        mono_mb-free (mb);
        return method;
    }

`mono_mb_new`
Syntax
MonoMethodBuilder* mono_mb_new (MonoClass *klass, const char *name, MonoWrapperType type)

The possible values for the type argument are:

            MONO_WRAPPER_NONE
            MONO_WRAPPER_DELEGATE_INVOKE
            MONO_WRAPPER_DELEGATE_BEGIN_INVOKE
            MONO_WRAPPER_DELEGATE_END_INVOKE
            MONO_WRAPPER_RUNTIME_INVOKE
            MONO_WRAPPER_NATIVE_TO_MANAGED
            MONO_WRAPPER_MANAGED_TO_NATIVE
            MONO_WRAPPER_REMOTING_INVOKE
            MONO_WRAPPER_REMOTING_INVOKE_WITH_CHECK
            MONO_WRAPPER_XDOMAIN_INVOKE
            MONO_WRAPPER_XDOMAIN_DISPATCH
            MONO_WRAPPER_LDFLD
            MONO_WRAPPER_STFLD
            MONO_WRAPPER_LDFLD_REMOTE
            MONO_WRAPPER_STFLD_REMOTE
            MONO_WRAPPER_SYNCHRONIZED
            MONO_WRAPPER_DYNAMIC_METHOD
            MONO_WRAPPER_ISINST
            MONO_WRAPPER_CASTCLASS
            MONO_WRAPPER_PROXY_ISINST
            MONO_WRAPPER_STELEMREF
            MONO_WRAPPER_UNBOX
            MONO_WRAPPER_LDFLDA
            MONO_WRAPPER_UNKNOWN

### Emitting IL

Functions that can be used to generate IL on the flight, similar in spirit to System.Reflection.Emit.ILGenerator.
`mono_mb_emit_add_to_local`
Syntax
void mono_mb_emit_add_to_local (MonoMethodBuilder *mb, guint16 local, gint32 incr)

`mono_mb_emit_branch`
Syntax
guint32 mono_mb_emit_branch (MonoMethodBuilder *mb, guint8 op)

`mono_mb_emit_byte`
Syntax
void mono_mb_emit_byte (MonoMethodBuilder *mb, guint8 op)

`mono_mb_emit_exception`
Syntax
void mono_mb_emit_exception (MonoMethodBuilder *mb, const char *exc_name, const char *msg)

`mono_mb_emit_i2`
Syntax
void mono_mb_emit_i2 (MonoMethodBuilder *mb, gint16 data)

`mono_mb_emit_i4`
Syntax
void mono_mb_emit_i4 (MonoMethodBuilder *mb, gint32 data)

`mono_mb_emit_icon`
Syntax
void mono_mb_emit_icon (MonoMethodBuilder *mb, gint32 value)

`mono_mb_emit_ldarg_addr`
Syntax
void mono_mb_emit_ldarg_addr (MonoMethodBuilder *mb, guint argnum)

`mono_mb_emit_ldarg`
Syntax
void mono_mb_emit_ldarg (MonoMethodBuilder *mb, guint argnum)

`mono_mb_emit_ldflda`
Syntax
void mono_mb_emit_ldflda (MonoMethodBuilder *mb, gint32 offset)

`mono_mb_emit_ldloc_addr`
Syntax
void mono_mb_emit_ldloc_addr (MonoMethodBuilder *mb, guint locnum)

`mono_mb_emit_ldloc`
Syntax
void mono_mb_emit_ldloc (MonoMethodBuilder *mb, guint num)

`mono_mb_emit_ldstr`
Syntax
void mono_mb_emit_ldstr (MonoMethodBuilder *mb, char *str)

`mono_mb_emit_managed_call`
Syntax
void mono_mb_emit_managed_call (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *opt_sig)

`mono_mb_emit_native_call`
Syntax
void mono_mb_emit_native_call (MonoMethodBuilder *mb, MonoMethodSignature *sig, gpointer func)

`mono_mb_emit_stloc`
Syntax
void mono_mb_emit_stloc (MonoMethodBuilder *mb, guint num)

### Local variables and Methods

`mono_mb_create_method`
Syntax
MonoMethod* mono_mb_create_method (MonoMethodBuilder *mb, MonoMethodSignature *signature, int max_stack)

Return value
the newly created method.
Description
Create a `MonoMethod` from this method builder.
`mono_mb_add_data`
Syntax
guint32 mono_mb_add_data (MonoMethodBuilder *mb, gpointer data)

`mono_mb_add_local`
Syntax
int mono_mb_add_local (MonoMethodBuilder *mb, MonoType *type)

`mono_mb_free`
Syntax
void mono_mb_free (MonoMethodBuilder *mb)

### Patching Addresses

`mono_mb_patch_addr`
Syntax
void mono_mb_patch_addr (MonoMethodBuilder *mb, int pos, int value)

`mono_mb_patch_addr_s`
Syntax
void mono_mb_patch_addr_s (MonoMethodBuilder *mb, int pos, gint8 value)

### Method Signatures

`mono_metadata_signature_alloc`
Syntax
MonoMethodSignature* mono_metadata_signature_alloc (MonoImage *m, guint32 nparams)

Parameters

image | metadata context
nparams | number of parameters in the signature

Return value
the new `MonoMethodSignature` structure.
Description

Allocate a `MonoMethodSignature` structure with the specified number of params. The return type and the params types need to be filled later. This is a Mono runtime internal function.

LOCKING: Assumes the loader lock is held.

`mono_metadata_signature_dup`
Syntax
MonoMethodSignature* mono_metadata_signature_dup (MonoMethodSignature *sig)

Parameters

sig | method signature

Return value
the new `MonoMethodSignature` structure.
Description

Duplicate an existing `MonoMethodSignature` so it can be modified. This is a Mono runtime internal function.