Add Code to the Method Bodies

CCI Metadata

To this point, HelloIL has been working entirely with metadata. To complete the assembly, you must add some code. CCI Metadata adds code to the assembly as a flat list of MSIL instruction, which is usually suitable only for creating short simple code blocks. Another approach is to use the CCI Code Model API, which is easier to use if you want generate large or complex code blocks.

The complete HelloIL Main method is:
.method public static void Main() cil managed
{
    .entrypoint
    .maxstack 8
    L_0000: ldstr "hello"
    L_0005: call void [mscorlib]System.Console::WriteLine(string)
    L_000a: ret 
}

The Microsoft.Cci.ILGenerator object handles the task of creating a method body and adding MSIL.
The following example from HelloIL creates a new ILGenerator object.
ILGenerator ilGenerator = new ILGenerator(host);

Note: You must pass the host object to ILGenerator, which depends on the host for application policy information.
For details, see The ILGenerator Object.

Create the Method Body

Method bodies are represented by Microsoft.Cci.ILGeneratorMethodBody objects. The following example shows how HelloIL creates the Main method body.
ILGeneratorMethodBody body = new ILGeneratorMethodBody(ilGenerator, true, 1);
body.MethodDefinition = mainMethod;
mainMethod.Body = body;

The ILGeneratorMethodBody constructor has three parameters:
  1. The ILGenerator object, which ILGeneratorMethodBody uses to construct the method body’s information.
  2. A Boolean value that specifies whether to zero the stack on method entry. Set this parameter to true to zero the stack.
  3. The maximum number of elements on the evaluation stack during method execution.
The last two lines in the example establish a link between the method body and its metadata by assigning the Main method’s MethodDefinition object to ILGeneratorMethodBody.MethodDefinition, and assigning the ILGeneratorMethodBody object to MethodDefinition.Body.

Create Type and Method Definitions

You must next create definition objects for members to be called and their types. CCI Metadata includes helper objects that create an appropriate definition object and return its immutable representation. For more discussion of immutable representations, see Mutable and Immutable Representations.

Hello.exe calls one method, System.Console.WriteLine. HelloIL creates the type definition object as follows.
INamedTypeDefinition systemConsole = UnitHelper.FindType(nameTable,
                                                         coreAssembly,
                                                         "System.Console");

Microsoft.Cci.UnitHelper.FindType creates a NamedTypeDefinition object for specified type and returns its immutable Microsoft.Cci.INamedTypeDefinition interface.
FindType has three parameters:
  1. The NameTable object.
  2. The assembly that contains the method, the .NET core assembly in this case.
  3. The fully-qualified type name, as an ordinary string.
HelloIL creates the WriteLine method definition object as follows.
IMethodDefinition writeLine = TypeHelper.GetMethod(systemConsole,
                                                   nameTable.GetNameFor("WriteLine"),
                                                   host.PlatformType.SystemString);

Microsoft.Cci.TypeHelper.GetMethod creates a MethodDefinition object for WriteLine and returns the object’s immutable IMethodDefinition interface. GetMethod has three parameters:
  1. The type definition object from the previous example.
  2. An IName interface for the method name, created in the usual way.
  3. A list of the method’s parameter types, in order. In this case, the method has a single string parameter.

Add MSIL to the Method Body

The final step is to add MSIL to the method body by calling ILGenerator.Emit once for each line of code. HelloIL adds the WriteLine command, as follows:
ilGenerator.Emit(OperationCode.Ldstr, "hello");
ilGenerator.Emit(OperationCode.Call, writeLine);
ilGenerator.Emit(OperationCode.Ret);

The Emit call puts the specified instructions into the method body in the same order. Microsoft.Cci.OperationCode is an enumeration that contains all CLI Common Intermediate Language the operation codes.

Next: Write the Assembly to a File
Return to Beginning

Last edited Dec 18, 2009 at 9:15 PM by Guy_Smith, version 1

Comments

No comments yet.