Edit

Share via


ControlFlowBuilder Class

Definition

Emits branches and exception blocks in a method body.

public ref class ControlFlowBuilder sealed
public sealed class ControlFlowBuilder
type ControlFlowBuilder = class
Public NotInheritable Class ControlFlowBuilder
Inheritance
ControlFlowBuilder

Examples

This example shows how to emit a method body with the exception handler using ControlFlowBuilder:

// The following code emits method body similar to this C# code:

/* public static void ExceptionBlockTest(int x, int y)
   {
      try
      {
         Console.WriteLine(x / y);
      }
      catch (DivideByZeroException)
      {
         Console.WriteLine("Error: division by zero");
      }
   }
*/

public static InstructionEncoder ControlFlowBuilderDemo(MetadataBuilder metadata, 
    AssemblyReferenceHandle corlibAssemblyRef)
{
    var codeBuilder = new BlobBuilder();
    var flowBuilder = new ControlFlowBuilder();
    var encoder = new InstructionEncoder(codeBuilder, flowBuilder);

    // Get reference to System.Console
    AssemblyReferenceHandle systemConsoleAssemblyRef = metadata.AddAssemblyReference(
        name: metadata.GetOrAddString("System.Console"),
        version: new Version(4, 0, 0, 0),
        culture: default(StringHandle),
        publicKeyOrToken: default(BlobHandle),
        flags: default(AssemblyFlags),
        hashValue: default(BlobHandle));
    
    TypeReferenceHandle consoleTypeRefHandle = metadata.AddTypeReference(
        systemConsoleAssemblyRef,
        metadata.GetOrAddString("System"),
        metadata.GetOrAddString("Console"));

    // Get reference to void System.Console::WriteLine(int32)
    var methodSignature = new BlobBuilder();

    new BlobEncoder(methodSignature).
        MethodSignature(isInstanceMethod: false).
        Parameters(1, returnType => returnType.Void(), parameters => parameters.AddParameter().Type().Int32());

    BlobHandle sigBlobIndex1 = metadata.GetOrAddBlob(methodSignature);

    MemberReferenceHandle refWriteLineInt32 = metadata.AddMemberReference(
        consoleTypeRefHandle,
        metadata.GetOrAddString("WriteLine"),
        sigBlobIndex1);

    // Get reference to void System.Console::WriteLine(string)
    methodSignature = new BlobBuilder();

    new BlobEncoder(methodSignature).
        MethodSignature(isInstanceMethod: false).
        Parameters(1, returnType => returnType.Void(), parameters => parameters.AddParameter().Type().String());

    BlobHandle sigBlobIndex2 = metadata.GetOrAddBlob(methodSignature);

    MemberReferenceHandle refWriteLineString = metadata.AddMemberReference(
        consoleTypeRefHandle,
        metadata.GetOrAddString("WriteLine"),
        sigBlobIndex2);

    // Get reference to System.DivideByZeroException
    TypeReferenceHandle exceptionTypeRefHandle = metadata.AddTypeReference(
        corlibAssemblyRef,
        metadata.GetOrAddString("System"),
        metadata.GetOrAddString("DivideByZeroException"));
    
    LabelHandle labelTryStart = encoder.DefineLabel();
    LabelHandle labelTryEnd = encoder.DefineLabel();
    LabelHandle labelCatchStart = encoder.DefineLabel();
    LabelHandle labelCatchEnd = encoder.DefineLabel();
    LabelHandle labelExit = encoder.DefineLabel();

    flowBuilder.AddCatchRegion(labelTryStart, labelTryEnd, labelCatchStart, labelCatchEnd,
        exceptionTypeRefHandle);

    // .try {
    encoder.MarkLabel(labelTryStart);

    // ldarg.0
    encoder.OpCode(ILOpCode.Ldarg_0);

    // ldarg.1
    encoder.OpCode(ILOpCode.Ldarg_1);

    // div
    encoder.OpCode(ILOpCode.Div);

    // call void [System.Console]System.Console::WriteLine(int32)
    encoder.Call(refWriteLineInt32);

    // leave.s EXIT            
    encoder.Branch(ILOpCode.Leave_s, labelExit);
    encoder.MarkLabel(labelTryEnd);

    // } 
    // catch [System.Runtime]System.DivideByZeroException {
    encoder.MarkLabel(labelCatchStart);

    // pop
    encoder.OpCode(ILOpCode.Pop);
    
    // ldstr "Error: division by zero"
    encoder.LoadString(metadata.GetOrAddUserString("Error: division by zero"));

    // call void [System.Console]System.Console::WriteLine(string)
    encoder.Call(refWriteLineString);

    // leave.s EXIT            
    encoder.Branch(ILOpCode.Leave_s, labelExit);
    encoder.MarkLabel(labelCatchEnd);

    // } EXIT: ret
    encoder.MarkLabel(labelExit);
    encoder.OpCode(ILOpCode.Ret);
    
    return encoder;
}

Remarks

The ControlFlowBuilder class is used to create branches and exception blocks in a method body encoded by InstructionEncoder. For more information about emitting .NET assemblies, see the MetadataBuilder class documentation.

Constructors

ControlFlowBuilder()

Methods

AddCatchRegion(LabelHandle, LabelHandle, LabelHandle, LabelHandle, EntityHandle)

Adds catch region.

AddFaultRegion(LabelHandle, LabelHandle, LabelHandle, LabelHandle)

Adds fault region.

AddFilterRegion(LabelHandle, LabelHandle, LabelHandle, LabelHandle, LabelHandle)

Adds catch region.

AddFinallyRegion(LabelHandle, LabelHandle, LabelHandle, LabelHandle)

Adds finally region.

Clear()

Clears the object's internal state, allowing the same instance to be reused.

Equals(Object)

Determines whether the specified object is equal to the current object.

(Inherited from Object)
GetHashCode()

Serves as the default hash function.

(Inherited from Object)
GetType()

Gets the Type of the current instance.

(Inherited from Object)
MemberwiseClone()

Creates a shallow copy of the current Object.

(Inherited from Object)
ToString()

Returns a string that represents the current object.

(Inherited from Object)

Applies to