Пример #1
0
        private ExceptionHandler BeginHandler(HandlerKind kind)
        //^ requires InTryBody;
        {
            ILGeneratorLabel handlerStart = new ILGeneratorLabel(false);

            this.MarkLabel(handlerStart);
            TryBody          currentTryBody = this.tryBodyStack.Peek();
            ExceptionHandler handler        = new ExceptionHandler(kind, currentTryBody, handlerStart);

            if (currentTryBody.end == null)
            {
                currentTryBody.end = handlerStart;
            }
            else if (this.handlers.Count > 0)
            {
                for (int i = this.handlers.Count - 1; i >= 0; i--)
                {
                    if (this.handlers[i].HandlerEnd == null)
                    {
                        this.handlers[i].HandlerEnd = handlerStart;
                        break;
                    }
                }
            }
            this.handlers.Add(handler);
            return(handler);
        }
Пример #2
0
 internal ExceptionHandler(HandlerKind kind, TryBody tryBlock, ILGeneratorLabel handlerStart)
 {
     this.ExceptionType = Dummy.TypeReference;
     this.kind          = kind;
     this.HandlerStart  = handlerStart;
     this.tryBlock      = tryBlock;
 }
Пример #3
0
        /// <summary>
        /// Begins the body of a try statement.
        /// </summary>
        public void BeginTryBody()
        //^ ensures InTryBody;
        {
            ILGeneratorLabel tryBodyStart = new ILGeneratorLabel(false);

            this.MarkLabel(tryBodyStart);
            this.tryBodyStack.Push(new TryBody(tryBodyStart));
        }
Пример #4
0
        /// <summary>
        /// Begins the part of a filter handler that is invoked on the second pass if the filter condition returns true on the first pass.
        /// </summary>
        public void BeginFilterBody()
        {
            this.Emit(OperationCode.Endfilter);
            ILGeneratorLabel handlerStart = new ILGeneratorLabel(false);

            this.MarkLabel(handlerStart);
            this.handlers[handlers.Count - 1].HandlerStart = handlerStart;
        }
Пример #5
0
        /// <summary>
        /// Returns a label that represents the given offset in the original IL. This label must be marked
        /// at the corresponding location in the rewritten IL.
        /// </summary>
        protected virtual ILGeneratorLabel GetLabelFor(uint offset)
        {
            Contract.Ensures(Contract.Result <ILGeneratorLabel>() != null);

            var result = this.labelFor[offset];

            if (result == null)
            {
                this.labelFor[offset] = result = new ILGeneratorLabel();
            }
            return(result);
        }
Пример #6
0
 /// <summary>
 /// Puts the specified instruction onto the Microsoft intermediate language (MSIL) stream and leaves space to include a label when fixes are done.
 /// </summary>
 /// <param name="opcode">The Microsoft intermediate language (MSIL) instruction to be put onto the stream.</param>
 /// <param name="label">The label to which to branch from this location.</param>
 public void Emit(OperationCode opcode, ILGeneratorLabel label)
 {
     if (opcode == OperationCode.Br && this.operations.Count > 0)
     {
         Operation previousOp = this.operations[this.operations.Count - 1];
         if (previousOp.OperationCode == (OperationCode)int.MaxValue)
         {
             ILGeneratorLabel labelOfBranch = (ILGeneratorLabel)previousOp.value;
             if (labelOfBranch.mayAlias)
             {
                 labelOfBranch.alias = label;
             }
         }
     }
     this.operations.Add(new Operation(opcode, this.offset, this.GetCurrentSequencePoint(), label));
     this.offset += SizeOfOperationCode(opcode) + SizeOfOffset(opcode);
 }
Пример #7
0
 /// <summary>
 /// Ends a try body.
 /// </summary>
 public void EndTryBody()
 //^ requires InTryBody;
 {
     this.tryBodyStack.Pop();
     if (this.handlers.Count > 0)
     {
         ILGeneratorLabel handlerEnd = new ILGeneratorLabel(false);
         this.MarkLabel(handlerEnd);
         for (int i = this.handlers.Count - 1; i >= 0; i--)
         {
             if (this.handlers[i].HandlerEnd == null)
             {
                 this.handlers[i].HandlerEnd = handlerEnd;
                 break;
             }
         }
     }
 }
Пример #8
0
 /// <summary>
 /// Puts the specified instruction onto the stream of instructions.
 /// </summary>
 /// <param name="opcode">The Intermediate Language (IL) instruction to be put onto the stream.</param>
 public void Emit(OperationCode opcode)
 {
     if (opcode == OperationCode.Ret)
     {
         int i = this.operations.Count;
         while (--i >= 0)
         {
             Operation previousOp = this.operations[i];
             if (previousOp.OperationCode != (OperationCode)int.MaxValue)
             {
                 break;
             }
             ILGeneratorLabel labelOfBranch = (ILGeneratorLabel)previousOp.value;
             labelOfBranch.labelsReturnInstruction = true;
         }
     }
     this.operations.Add(new Operation(opcode, this.offset, this.GetCurrentSequencePoint(), null));
     this.offset += SizeOfOperationCode(opcode);
 }
Пример #9
0
 /// <summary>
 /// Ends a try body.
 /// </summary>
 public void EndTryBody()
 //^ requires InTryBody;
 {
     this.tryBodyStack.Pop();
     if (this.handlers.Count > 0)
     {
         ILGeneratorLabel handlerEnd = new ILGeneratorLabel(false);
         this.MarkLabel(handlerEnd);
         for (int i = this.handlers.Count - 1; i >= 0; i--)
         {
             var handler = this.handlers[i];
             if (handler.HandlerEnd == null)
             {
                 handler.HandlerEnd = handlerEnd;
                 if (i < this.handlers.Count - 1)
                 {
                     this.handlers.RemoveAt(i);
                     this.handlers.Add(handler);
                 }
                 break;
             }
         }
     }
 }
Пример #10
0
 /// <summary>
 /// Generates IL for the specified conditional.
 /// </summary>
 /// <param name="conditional">The conditional.</param>
 public override void TraverseChildren(IConditional conditional)
 {
     ILGeneratorLabel falseCase = new ILGeneratorLabel();
       ILGeneratorLabel endif = new ILGeneratorLabel();
       this.VisitBranchIfFalse(conditional.Condition, falseCase);
       this.Traverse(conditional.ResultIfTrue);
       this.generator.Emit(OperationCode.Br, endif);
       this.generator.MarkLabel(falseCase);
       this.StackSize--;
       this.Traverse(conditional.ResultIfFalse);
       this.generator.MarkLabel(endif);
 }
Пример #11
0
 /// <summary>
 ///  Marks the Microsoft intermediate language (MSIL) stream's current position with the given label.
 /// </summary>
 public void MarkLabel(ILGeneratorLabel label)
 {
     label.Offset = this.offset;
       this.operations.Add(new Operation((OperationCode)int.MaxValue, this.offset, Dummy.Location, label));
 }
Пример #12
0
        public void Compile(string fileName)
        {
            string appName = Path.GetFileNameWithoutExtension(fileName);
            string exeName = appName + ".exe";
            string src = "";
            using (TextReader file = new StreamReader(fileName))
            {
                src = file.ReadToEnd();
            }

            var nameTable = new NameTable();
            using (var host = new PeReader.DefaultHost(nameTable))
            {
                // Load Mirage types

                IModule module = host.LoadUnitFrom("Mirage.dll") as IModule;
                if (module == null || module is Dummy)
                {
                    return;
                }
                var machineType = module.GetAllTypes().First(x => x.Name.Value == "Machine");
                var inputType = module.GetAllTypes().First(x => x.Name.Value == "ConsoleInput");
                var outputType = module.GetAllTypes().First(x => x.Name.Value == "ConsoleOutput");

                // Create assembly

                var coreAssembly = host.LoadAssembly(host.CoreAssemblySymbolicIdentity);
                var assembly = new Assembly()
                {
                    Name = nameTable.GetNameFor(appName),
                    ModuleName = nameTable.GetNameFor(exeName),
                    PlatformType = host.PlatformType,
                    Kind = ModuleKind.ConsoleApplication,
                    RequiresStartupStub = host.PointerSize == 4,
                    TargetRuntimeVersion = coreAssembly.TargetRuntimeVersion,
                };
                assembly.AssemblyReferences.Add(coreAssembly);

                // Create namespace

                var rootUnitNamespace = new RootUnitNamespace();
                assembly.UnitNamespaceRoot = rootUnitNamespace;
                rootUnitNamespace.Unit = assembly;

                // Create module class

                var moduleClass = new NamespaceTypeDefinition()
                {
                    ContainingUnitNamespace = rootUnitNamespace,
                    InternFactory = host.InternFactory,
                    IsClass = true,
                    Name = nameTable.GetNameFor("<Module>"),
                };
                assembly.AllTypes.Add(moduleClass);

                // Create program class

                var programClass = new NamespaceTypeDefinition()
                {
                    ContainingUnitNamespace = rootUnitNamespace,
                    InternFactory = host.InternFactory,
                    IsClass = true,
                    IsPublic = true,
                    Methods = new List<IMethodDefinition>(1),
                    Name = nameTable.GetNameFor("Program"),
                };
                programClass.BaseClasses = new List<ITypeReference>() { host.PlatformType.SystemObject };
                rootUnitNamespace.Members.Add(programClass);

                // Add types to the assembly

                assembly.AllTypes.Add(machineType);
                foreach (var t in machineType.NestedTypes)
                {
                    assembly.AllTypes.Add(t);
                }
                assembly.AllTypes.Add(inputType);
                assembly.AllTypes.Add(outputType);
                assembly.AllTypes.Add(programClass);

                // Create main method

                var mainMethod = new MethodDefinition()
                {
                    ContainingTypeDefinition = programClass,
                    InternFactory = host.InternFactory,
                    IsCil = true,
                    IsStatic = true,
                    Name = nameTable.GetNameFor("Main"),
                    Type = host.PlatformType.SystemVoid,
                    Visibility = TypeMemberVisibility.Public,
                };
                assembly.EntryPoint = mainMethod;
                programClass.Methods.Add(mainMethod);

                // Create constructors and methods

                IMethodReference machineConstructor = new Microsoft.Cci.MethodReference(
                    host,
                    machineType,
                    CallingConvention.HasThis,
                    host.PlatformType.SystemVoid,
                    host.NameTable.Ctor,
                    0
                );

                IMethodReference inputConstructor = new Microsoft.Cci.MethodReference(
                    host,
                    inputType,
                    CallingConvention.HasThis,
                    host.PlatformType.SystemVoid,
                    host.NameTable.Ctor,
                    0
                );
                var inputCast = TypeHelper.GetMethod(inputType, nameTable.GetNameFor("op_Implicit"), inputType);

                IMethodReference outputConstructor = new Microsoft.Cci.MethodReference(
                    host,
                    outputType,
                    CallingConvention.HasThis,
                    host.PlatformType.SystemVoid,
                    host.NameTable.Ctor,
                    0
                );
                var outputCast = TypeHelper.GetMethod(outputType, nameTable.GetNameFor("op_Implicit"), outputType);

                var opIncPointers = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("IncPointers"));
                var opDecPointers = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("DecPointers"));
                var opIncHiPointer = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("IncHiPointer"));
                var opDecHiPointer = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("DecHiPointer"));
                var opReflectHiPointer = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("ReflectHiPointer"));
                var opLoadHiPointer = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("LoadHiPointer"));
                var opDragLoPointer = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("DragLoPointer"));
                var opXchPointers = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("XchPointers"));

                var opClear = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Clear"));
                var opAdd = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Add"));
                var opDec = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Dec"));
                var opNot = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Not"));
                var opAnd = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("And"));
                var opOr = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Or"));
                var opXor = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Xor"));
                var opSal = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Sal"));
                var opSar = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Sar"));

                var opLoadData = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("LoadData"), host.PlatformType.SystemString);
                var opInput = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Input"), inputCast.Type);
                var opOutput = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Output"), outputCast.Type);

                var opJz = TypeHelper.GetMethod(machineType, nameTable.GetNameFor("Jz"));

                // Create program code

                var labels = new Stack<ILGeneratorLabel>(100);

                var ilGenerator = new ILGenerator(host, mainMethod);
                ilGenerator.Emit(OperationCode.Newobj, machineConstructor);
                ilGenerator.Emit(OperationCode.Stloc_0);
                ilGenerator.Emit(OperationCode.Newobj, inputConstructor);
                ilGenerator.Emit(OperationCode.Stloc_1);
                ilGenerator.Emit(OperationCode.Newobj, outputConstructor);
                ilGenerator.Emit(OperationCode.Stloc_2);

                int pc = 0;
                while (pc < src.Length)
                {
                    char opcode = src[pc++];

                    switch (opcode)
                    {
                        case '>':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opIncPointers);
                            break;
                        case '<':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opDecPointers);
                            break;
                        case ']':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opIncHiPointer);
                            break;
                        case '[':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opDecHiPointer);
                            break;
                        case '#':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opReflectHiPointer);
                            break;
                        case '$':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opLoadHiPointer);
                            break;
                        case '=':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opDragLoPointer);
                            break;
                        case '%':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opXchPointers);
                            break;
                        case '_':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opClear);
                            break;
                        case '+':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opAdd);
                            break;
                        case '-':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opDec);
                            break;
                        case '~':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opNot);
                            break;
                        case '&':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opAnd);
                            break;
                        case '|':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opOr);
                            break;
                        case '^':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opXor);
                            break;
                        case '*':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opSal);
                            break;
                        case '/':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opSar);
                            break;
                        case '(':
                            int dataStart = pc;
                            int dataEnd = dataStart;
                            while (src[pc++] != ')')
                            {
                                dataEnd = pc;
                            }
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Ldstr, src.Substring(dataStart, dataEnd - dataStart));
                            ilGenerator.Emit(OperationCode.Callvirt, opLoadData);
                            break;
                        case '?':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Ldloc_1);
                            ilGenerator.Emit(OperationCode.Call, inputCast);
                            ilGenerator.Emit(OperationCode.Callvirt, opInput);
                            break;
                        case '!':
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Ldloc_2);
                            ilGenerator.Emit(OperationCode.Call, outputCast);
                            ilGenerator.Emit(OperationCode.Callvirt, opOutput);
                            break;
                        case '{':
                            var cycleStart = new ILGeneratorLabel();
                            var cycleEnd = new ILGeneratorLabel();
                            labels.Push(cycleStart);
                            labels.Push(cycleEnd);
                            ilGenerator.Emit(OperationCode.Br, cycleEnd);
                            ilGenerator.MarkLabel(cycleStart);
                            break;
                        case '}':
                            ilGenerator.MarkLabel(labels.Pop());
                            ilGenerator.Emit(OperationCode.Ldloc_0);
                            ilGenerator.Emit(OperationCode.Callvirt, opJz);
                            ilGenerator.Emit(OperationCode.Ldc_I4_0);
                            ilGenerator.Emit(OperationCode.Ceq);
                            ilGenerator.Emit(OperationCode.Stloc_3);
                            ilGenerator.Emit(OperationCode.Ldloc_3);
                            ilGenerator.Emit(OperationCode.Brtrue, labels.Pop());
                            break;
                        default:
                            break;
                    }
                }

                ilGenerator.Emit(OperationCode.Ret);

                mainMethod.Body = new ILGeneratorMethodBody(
                    ilGenerator,
                    true,
                    8,
                    mainMethod,
                    new List<ILocalDefinition>() {
                        new LocalDefinition() { Type = machineType },
                        new LocalDefinition() { Type = inputType },
                        new LocalDefinition() { Type = outputType },
                        new LocalDefinition() { Type = host.PlatformType.SystemInt32 },
                    },
                    Enumerable<ITypeDefinition>.Empty
                );

                using (var peStream = File.Create(exeName))
                {
                    PeWriter.WritePeToStream(assembly, host, peStream);
                }
            }
        }
Пример #13
0
 /// <summary>
 /// Begins the part of a filter handler that is invoked on the second pass if the filter condition returns true on the first pass.
 /// </summary>
 public void BeginFilterBody()
 {
     this.Emit(OperationCode.Endfilter);
       ILGeneratorLabel handlerStart = new ILGeneratorLabel(false);
       this.MarkLabel(handlerStart);
       this.handlers[handlers.Count-1].HandlerStart = handlerStart;
 }
Пример #14
0
 /// <summary>
 /// Puts the specified instruction onto the Microsoft intermediate language (MSIL) stream and leaves space to include a label when fixes are done.
 /// </summary>
 /// <param name="opcode">The Microsoft intermediate language (MSIL) instruction to be put onto the stream.</param>
 /// <param name="label">The label to which to branch from this location.</param>
 public void Emit(OperationCode opcode, ILGeneratorLabel label)
 {
     if (opcode == OperationCode.Br && this.operations.Count > 0) {
     Operation previousOp = this.operations[this.operations.Count-1];
     if (previousOp.OperationCode == (OperationCode)int.MaxValue) {
       ILGeneratorLabel labelOfBranch = (ILGeneratorLabel)previousOp.value;
       if (labelOfBranch.mayAlias) labelOfBranch.alias = label;
     }
       }
       this.operations.Add(new Operation(opcode, this.offset, this.GetCurrentSequencePoint(), label));
       this.offset += SizeOfOperationCode(opcode)+SizeOfOffset(opcode);
 }
 private ILGeneratorLabel GetLabelFor(uint offset) {
   var result = this.labelFor[offset];
   if (result == null)
     this.labelFor[offset] = result = new ILGeneratorLabel();
   return result;
 }
Пример #16
0
 internal ExceptionHandler(HandlerKind kind, TryBody tryBlock, ILGeneratorLabel handlerStart)
 {
     this.ExceptionType = Dummy.TypeReference;
       this.kind = kind;
       this.HandlerStart = handlerStart;
       this.tryBlock = tryBlock;
 }
Пример #17
0
        private void GenerateDownLevelLockStatement(ILockStatement lockStatement)
        {
            var systemThreading = new NestedUnitNamespaceReference(this.host.PlatformType.SystemObject.ContainingUnitNamespace,
            this.host.NameTable.GetNameFor("Threading"));
              var systemThreadingMonitor = new NamespaceTypeReference(this.host, systemThreading, this.host.NameTable.GetNameFor("Monitor"), 0,
            isEnum: false, isValueType: false, typeCode: PrimitiveTypeCode.NotPrimitive);
              var parameters = new IParameterTypeInformation[2];
              var monitorEnter = new MethodReference(this.host, systemThreadingMonitor, CallingConvention.Default, this.host.PlatformType.SystemVoid,
            this.host.NameTable.GetNameFor("Enter"), 0, this.host.PlatformType.SystemObject);
              var monitorExit = new MethodReference(this.host, systemThreadingMonitor, CallingConvention.Default, this.host.PlatformType.SystemVoid,
            this.host.NameTable.GetNameFor("Exit"), 0, this.host.PlatformType.SystemObject);

              this.EmitSequencePoint(lockStatement.Locations);
              var guardObject = new TemporaryVariable(lockStatement.Guard.Type, this.method);
              this.Traverse(lockStatement.Guard);
              this.generator.Emit(OperationCode.Dup); this.StackSize++;
              this.VisitAssignmentTo(guardObject);
              this.generator.Emit(OperationCode.Call, monitorEnter);
              this.StackSize--;
              //try
              var savedCurrentTryCatch = this.currentTryCatch;
              this.currentTryCatch = lockStatement;
              var savedCurrentTryCatchFinallyEnd = this.currentTryCatchFinallyEnd;
              this.currentTryCatchFinallyEnd = new ILGeneratorLabel();
              this.generator.BeginTryBody();
              this.Traverse(lockStatement.Body);
              if (!this.lastStatementWasUnconditionalTransfer)
            this.generator.Emit(OperationCode.Leave, this.currentTryCatchFinallyEnd);
              //finally
              this.generator.BeginFinallyBlock();
              //if (status)
              this.LoadLocal(guardObject);
              this.generator.Emit(OperationCode.Call, monitorExit);
              this.StackSize--;
              //monitor exit
              this.generator.Emit(OperationCode.Endfinally);
              this.generator.EndTryBody();
              this.generator.MarkLabel(this.currentTryCatchFinallyEnd);
              this.currentTryCatchFinallyEnd = savedCurrentTryCatchFinallyEnd;
              this.currentTryCatch = savedCurrentTryCatch;
              this.lastStatementWasUnconditionalTransfer = false;
        }
Пример #18
0
 internal bool LabelIsOutsideCurrentExceptionBlock(ILGeneratorLabel label)
 {
     IStatement tryCatchContainingTarget = null;
       this.mostNestedTryCatchFor.TryGetValue(label, out tryCatchContainingTarget);
       return this.currentTryCatch != tryCatchContainingTarget;
 }
Пример #19
0
        // creates a method for a given method CFG (IMPORTANT: it updates the operations
        // and exception handlers of the existing method, does not create a new method)
        public void createMethodFromCfg(MethodCfg methodCfg) {

            // list of basic blocks that belong together logically (i.e. BB2 lies directly behind BB1 because it reaches it without a branch)
            IList<BasicBlockUnion> basicBlockUnions = new List<BasicBlockUnion>();

            // first step: create basic block unions
            // create first basic block union starting from the start basic block
            BasicBlockUnion firstBasicBlockUnion = new BasicBlockUnion();
            this.createRecursivelyBasicBlockUnion(basicBlockUnions, firstBasicBlockUnion, methodCfg.startBasicBlock);
            basicBlockUnions.Add(firstBasicBlockUnion);

            // create basic block unions for the rest of the basic blocks
            foreach (BasicBlock tempBB in methodCfg.basicBlocks) {

                // create a basic block union (if basic block is not contained by another existing basic block union)
                BasicBlockUnion basicBlockUnion = new BasicBlockUnion();
                this.createRecursivelyBasicBlockUnion(basicBlockUnions, basicBlockUnion, tempBB);

                // if the newly created basic block union contains basic blocks
                // => add to list of basic block unions
                if (basicBlockUnion.basicBlocks.Count() != 0) {
                    basicBlockUnions.Add(basicBlockUnion);
                }
            }


            // step two: merge basic block unions with respect to the exception handler
            foreach (OperationExceptionInformation exceptionHandler in methodCfg.method.Body.OperationExceptionInformation) {

                // create a temporary object to reorder the basic block unions with respect to the exception handler
                BasicBlockUnionExceptionHandlerOrder tempNewOrder = new BasicBlockUnionExceptionHandlerOrder();
                tempNewOrder.exceptionHandler = exceptionHandler;

                // find all basic blocks that are connected to the current exception handler
                foreach (BasicBlockUnion basicBlockUnion in basicBlockUnions) {
                    foreach (BasicBlock basicBlock in basicBlockUnion.basicBlocks) {

                        // ignore all basic blocks that do not have any try/catch/finally handler in it
                        if (basicBlock.tryBlocks.Count() == 0 && basicBlock.handlerBlocks.Count() == 0) {
                            continue;
                        }

                        // find the try block that is connected to the current exception handler
                        foreach (TryBlock tryBlock in basicBlock.tryBlocks) {

                            // ignore try blocks that do not belong to the current exception handler
                            if (tryBlock.exceptionHandler != exceptionHandler) {
                                continue;
                            }

                            // check if basic block union already resides in try body
                            // if not => add to try body
                            if (!tempNewOrder.tryBody.Contains(basicBlockUnion)) {
                                tempNewOrder.tryBody.Add(basicBlockUnion);
                            }

                            // check if the basic block starts the try block
                            if (tryBlock.firstBasicBlockOfTryBlock) {
                                tempNewOrder.tryStart = basicBlockUnion;
                            }

                            // check if the basic block ends the try block
                            if (tryBlock.lastBasicBlockOfTryBlock) {
                                tempNewOrder.tryEnd = basicBlockUnion;
                            }
                        }

                        // find the handler block that is connected to the current exception handler
                        foreach (HandlerBlock handlerBlock in basicBlock.handlerBlocks) {

                            // ignore handler blocks that do not belong to the current exception handler
                            if (handlerBlock.exceptionHandler != exceptionHandler) {
                                continue;
                            }

                            // check if basic block union already resides in handler body
                            // if not => add to handler body
                            if (!tempNewOrder.handlerBody.Contains(basicBlockUnion)) {
                                tempNewOrder.handlerBody.Add(basicBlockUnion);
                            }

                            // check if the basic block starts the handler block
                            if (handlerBlock.firstBasicBlockOfHandlerBlock) {
                                tempNewOrder.handlerStart = basicBlockUnion;
                            }

                            // check if the basic block ends the handler block
                            if (handlerBlock.lastBasicBlockOfHandlerBlock) {
                                tempNewOrder.handlerEnd = basicBlockUnion;
                            }
                        }
                    }
                }
                if (tempNewOrder.tryStart == null
                    || tempNewOrder.tryEnd == null
                    || tempNewOrder.handlerStart == null
                    || tempNewOrder.handlerEnd == null) {
                        throw new ArgumentException("Could not find all try/catch beginnings/ends.");
                }



                // merge basic block unions with respect to the current exception handler

                // check if the complete exception handling is done in only one basic block union
                // => ignore it
                if (tempNewOrder.tryStart == tempNewOrder.tryEnd
                    && tempNewOrder.handlerStart == tempNewOrder.handlerEnd
                    && tempNewOrder.tryStart == tempNewOrder.handlerStart) {
                    continue;
                }

                // if not everything lies in the same basic block union
                // extend the basic block union that starts the try block
                BasicBlockUnion extendedUnion = tempNewOrder.tryStart;

                // if try block start and end are the same => nothing to merge
                // else merge the basic block unions
                if (tempNewOrder.tryStart != tempNewOrder.tryEnd) {
                    foreach (BasicBlockUnion tryBodyBasicBlockUnion in tempNewOrder.tryBody) {

                        // ignore the basic block union that starts the try block (already in extended union)
                        // and ignore the basic block union that ends the try block (is added last)
                        if (tryBodyBasicBlockUnion == tempNewOrder.tryStart
                            || tryBodyBasicBlockUnion == tempNewOrder.tryEnd) {
                            continue;
                        }

                        // extend first basic block union with the basic block union of the
                        // try block body and remove the added one from the list of basic block unions
                        extendedUnion.basicBlocks.AddRange(tryBodyBasicBlockUnion.basicBlocks);
                        basicBlockUnions.Remove(tryBodyBasicBlockUnion);
                    }

                    // extend first basic block union with the basic block union of the
                    // try block end and remove the added one from the list of basic block unions
                    extendedUnion.basicBlocks.AddRange(tempNewOrder.tryEnd.basicBlocks);
                    basicBlockUnions.Remove(tempNewOrder.tryEnd);
                }

                // if the try block end and the handler block start are not the same basic block union
                // => merge the union of the handler block start to the current basic block union
                if (tempNewOrder.tryEnd != tempNewOrder.handlerStart) {
                    extendedUnion.basicBlocks.AddRange(tempNewOrder.handlerStart.basicBlocks);
                    basicBlockUnions.Remove(tempNewOrder.handlerStart);
                }

                // if handler block start and end are the same => nothing to merge
                // else merge the basic block unions
                if (tempNewOrder.handlerStart != tempNewOrder.handlerEnd) {
                    foreach (BasicBlockUnion handlerBodyBasicBlockUnion in tempNewOrder.handlerBody) {

                        // ignore the basic block union that starts the handler block (already in extended union)
                        // and ignore the basic block union that ends the handler block (is added last)
                        if (handlerBodyBasicBlockUnion == tempNewOrder.handlerStart
                            || handlerBodyBasicBlockUnion == tempNewOrder.handlerEnd) {
                            continue;
                        }

                        // add basic block union of the handler block body to the extended basic block union 
                        // and remove the added one from the list of basic block unions
                        extendedUnion.basicBlocks.AddRange(handlerBodyBasicBlockUnion.basicBlocks);
                        basicBlockUnions.Remove(handlerBodyBasicBlockUnion);
                    }

                    // extend the extended basic block union with the basic block union of the
                    // handler block end and remove the added one from the list of basic block unions
                    extendedUnion.basicBlocks.AddRange(tempNewOrder.handlerEnd.basicBlocks);
                    basicBlockUnions.Remove(tempNewOrder.handlerEnd);
                }
            }


            // step three: create one list of operations and modify jump offsets
            // create a list of operations from the basic blocks,
            // update basic block start/end indices accordingly
            // and update the offsets of the operations (needed to update branch operations)
            IList<IOperation> methodOperations = new List<IOperation>();
            int operationIdx = 0;
            uint currentOffset = 0;
            foreach (BasicBlockUnion basicBlockUnion in basicBlockUnions) {
                foreach (BasicBlock basicBlock in basicBlockUnion.basicBlocks) {
                    basicBlock.startIdx = operationIdx;
                    //foreach (IOperation operation in basicBlock.operations) {
                    for (int opIdx = 0; opIdx < basicBlock.operations.Count(); opIdx++) {
                        IOperation operation = basicBlock.operations.ElementAt(opIdx);

                        // a new operation object is needed because the old operations
                        // are read only due to cci
                        InternalOperation newOperation = new InternalOperation();

                        // exchange every short instruction with its larger one
                        switch (operation.OperationCode) {
                            case OperationCode.Beq_S:
                                newOperation.OperationCode = OperationCode.Beq;
                                break;
                            case OperationCode.Bge_S:
                                newOperation.OperationCode = OperationCode.Bge;
                                break;
                            case OperationCode.Bge_Un_S:
                                newOperation.OperationCode = OperationCode.Bge_Un;
                                break;
                            case OperationCode.Bgt_S:
                                newOperation.OperationCode = OperationCode.Bgt;
                                break;
                            case OperationCode.Bgt_Un_S:
                                newOperation.OperationCode = OperationCode.Bgt_Un;
                                break;
                            case OperationCode.Ble_S:
                                newOperation.OperationCode = OperationCode.Ble;
                                break;
                            case OperationCode.Ble_Un_S:
                                newOperation.OperationCode = OperationCode.Ble_Un;
                                break;
                            case OperationCode.Blt_S:
                                newOperation.OperationCode = OperationCode.Blt;
                                break;
                            case OperationCode.Blt_Un_S:
                                newOperation.OperationCode = OperationCode.Blt_Un;
                                break;
                            case OperationCode.Bne_Un_S:
                                newOperation.OperationCode = OperationCode.Bne_Un;
                                break;
                            case OperationCode.Br_S:
                                newOperation.OperationCode = OperationCode.Br;
                                break;
                            case OperationCode.Brfalse_S:
                                newOperation.OperationCode = OperationCode.Brfalse;
                                break;
                            case OperationCode.Brtrue_S:
                                newOperation.OperationCode = OperationCode.Brtrue;
                                break;
                            case OperationCode.Ldarg_S:
                                newOperation.OperationCode = OperationCode.Ldarg;
                                break;
                            case OperationCode.Ldarga_S:
                                newOperation.OperationCode = OperationCode.Ldarga;
                                break;
                            case OperationCode.Ldc_I4_S:
                                newOperation.OperationCode = OperationCode.Ldc_I4;
                                break;
                            case OperationCode.Ldloc_S:
                                newOperation.OperationCode = OperationCode.Ldloc;
                                break;
                            case OperationCode.Ldloca_S:
                                newOperation.OperationCode = OperationCode.Ldloca;
                                break;
                            case OperationCode.Leave_S:
                                newOperation.OperationCode = OperationCode.Leave;
                                break;
                            case OperationCode.Starg_S:
                                newOperation.OperationCode = OperationCode.Starg;
                                break;
                            case OperationCode.Stloc_S:
                                newOperation.OperationCode = OperationCode.Stloc;
                                break;
                            default:
                                newOperation.OperationCode = operation.OperationCode;
                                break;
                        }
                        newOperation.Value = operation.Value;
                        newOperation.Location = operation.Location;
                        newOperation.Offset = currentOffset;
                        methodOperations.Add(newOperation);

                        // replace old operation in basic block with newly created one
                        basicBlock.operations[opIdx] = newOperation;

                        operationIdx++;
                        currentOffset += CfgBuilder.getSizeOfOperation(newOperation);
                    }
                    basicBlock.endIdx = operationIdx - 1;
                }
            }


            // step four: update branches with new target offsets
            foreach (BasicBlock tempBB in methodCfg.basicBlocks) {
                InternalOperation branchOperation = (InternalOperation)methodOperations.ElementAt(tempBB.endIdx);

                // check which kind of exit branch is used by this basic block and update its operation accordingly
                if (tempBB.exitBranch as NoBranchTarget != null) {
                    continue;
                }
                else if (tempBB.exitBranch as TryBlockTarget != null) {
                    continue;
                }
                else if (tempBB.exitBranch as ConditionalBranchTarget != null) {
                    ConditionalBranchTarget tempExitBranch = (tempBB.exitBranch as ConditionalBranchTarget);

                    // check if the branch is done by a branch operation
                    if (!CfgBuilder.isBranchOperation(branchOperation)) {
                        throw new ArgumentException("Branch is not done by a valid branch operation.");
                    }

                    // get index of the branch target
                    int targetBranchIdx = tempExitBranch.takenTarget.startIdx;

                    // update offset of the taken branch
                    branchOperation.Value = methodOperations.ElementAt(targetBranchIdx).Offset;
                }
                else if (tempBB.exitBranch as SwitchBranchTarget != null) {
                    SwitchBranchTarget tempExitBranch = (tempBB.exitBranch as SwitchBranchTarget);

                    // check if the branch is done by a branch operation
                    if (!CfgBuilder.isBranchOperation(branchOperation)) {
                        throw new ArgumentException("Branch is not done by a valid branch operation.");
                    }

                    // update all switch branches
                    for (int switchIdx = 0; switchIdx < tempExitBranch.takenTarget.Count(); switchIdx++) {

                        // get index of the branch target
                        int targetBranchIdx = tempExitBranch.takenTarget.ElementAt(switchIdx).startIdx;

                        // update offset of the taken branch
                        ((uint[])branchOperation.Value)[switchIdx] = methodOperations.ElementAt(targetBranchIdx).Offset;
                    }
                }
                else if (tempBB.exitBranch as UnconditionalBranchTarget != null) {
                    UnconditionalBranchTarget tempExitBranch = (tempBB.exitBranch as UnconditionalBranchTarget);

                    // check if the branch is done by a branch operation
                    if (!CfgBuilder.isBranchOperation(branchOperation)) {
                        throw new ArgumentException("Branch is not done by a valid branch operation.");
                    }

                    // get index of the branch target
                    int targetBranchIdx = tempExitBranch.takenTarget.startIdx;

                    // update offset of the taken branch
                    branchOperation.Value = methodOperations.ElementAt(targetBranchIdx).Offset;
                }
                else if (tempBB.exitBranch as ExitBranchTarget != null) {
                    continue;
                }
                else if (tempBB.exitBranch as ThrowBranchTarget != null) {
                    continue;
                }
                else if (tempBB.exitBranch as ExceptionBranchTarget != null) {
                    ExceptionBranchTarget tempExitBranch = (tempBB.exitBranch as ExceptionBranchTarget);

                    // check if the branch is done by a branch operation
                    if (!CfgBuilder.isBranchOperation(branchOperation)) {
                        throw new ArgumentException("Branch is not done by a valid branch operation.");
                    }

                    // get index of the branch target
                    int targetBranchIdx = tempExitBranch.exitTarget.startIdx;

                    // update offset of the taken branch
                    branchOperation.Value = methodOperations.ElementAt(targetBranchIdx).Offset;
                }
                else {
                    throw new ArgumentException("Do not know how to handle exit branch.");
                }
            }


            // step five: create new exception handler with updated offsets and
            // create new method body of the cci method
            MethodDefinition method = methodCfg.method;
            var ilGenerator = new ILGenerator(this.host, method);
            // emit all operations to the new body
            foreach (IOperation operation in methodOperations) {
                ilGenerator.Emit(operation.OperationCode, operation.Value);
            }

            // list that is used to replace the pointer to the old exception handler in the basic blocks to the new exception handler
            List<OldExceptionHandlerMapping> oldExceptionHandlerMappings = new List<OldExceptionHandlerMapping>();
            
            // create for each old exception handler a new one with updated data
            foreach (IOperationExceptionInformation exceptionHandler in method.Body.OperationExceptionInformation) {

                // create mapping object for old exception handler
                OldExceptionHandlerMapping oldExceptionHandlerMapping = new OldExceptionHandlerMapping();
                oldExceptionHandlerMapping.oldExceptionHandler = exceptionHandler;
                oldExceptionHandlerMappings.Add(oldExceptionHandlerMapping);

                ILGeneratorLabel tryStart = new ILGeneratorLabel();
                ILGeneratorLabel tryEnd = new ILGeneratorLabel();
                ILGeneratorLabel handlerStart = new ILGeneratorLabel();
                ILGeneratorLabel handlerEnd = new ILGeneratorLabel();
                ILGeneratorLabel filterStart = new ILGeneratorLabel();

                // search for the basic blocks that start/end the try block and handler block
                foreach (BasicBlock tempBB in methodCfg.basicBlocks) {

                    foreach (TryBlock tempTryBlock in tempBB.tryBlocks) {

                        // ignore try blocks that do not belong to the current exception handler
                        if (tempTryBlock.exceptionHandler != exceptionHandler) {
                            continue;
                        }

                        // get offset of the instruction that starts the try block
                        if (tempTryBlock.firstBasicBlockOfTryBlock) {
                            tryStart.Offset = tempBB.operations.ElementAt(0).Offset;
                            oldExceptionHandlerMapping.tryStartOffset = tryStart.Offset;
                        }

                        // get offset of the instruction that ends the try block (always the last instruction of the basic block)
                        if (tempTryBlock.lastBasicBlockOfTryBlock) {
                            tryEnd.Offset = tempBB.operations.ElementAt(tempBB.operations.Count() - 1).Offset;
                            // exception handler object needs offset of the end of the instruction (not the beginning)
                            tryEnd.Offset += CfgBuilder.getSizeOfOperation(tempBB.operations.ElementAt(tempBB.operations.Count() - 1));
                            oldExceptionHandlerMapping.tryEndOffset = tryEnd.Offset;
                        }
                    }

                    foreach (HandlerBlock tempHandlerBlock in tempBB.handlerBlocks) {

                        // ignore handler blocks that do not belong to the current exception handler
                        if (tempHandlerBlock.exceptionHandler != exceptionHandler) {
                            continue;
                        }

                        // get offset ot the instruction that starts the handler block
                        if (tempHandlerBlock.firstBasicBlockOfHandlerBlock) {
                            handlerStart.Offset = tempBB.operations.ElementAt(0).Offset;
                            oldExceptionHandlerMapping.handlerStartOffset = handlerStart.Offset;
                        }

                        // get offset of the instruction that ends the handler block
                        if (tempHandlerBlock.lastBasicBlockOfHandlerBlock) {
                            handlerEnd.Offset = tempBB.operations.ElementAt(tempBB.operations.Count() - 1).Offset;
                            // exception handler object needs offset of the end of the instruction (not the beginning)
                            handlerEnd.Offset += CfgBuilder.getSizeOfOperation(tempBB.operations.ElementAt(tempBB.operations.Count() - 1));
                            oldExceptionHandlerMapping.handlerEndOffset = handlerEnd.Offset;
                        }
                    }
                }

                // copy the exception handler filter
                filterStart.Offset = exceptionHandler.FilterDecisionStartOffset;
                oldExceptionHandlerMapping.filterStartOffset = filterStart.Offset;

                // add new exception handler
                oldExceptionHandlerMapping.exceptionType = exceptionHandler.ExceptionType;
                oldExceptionHandlerMapping.handlerKind = exceptionHandler.HandlerKind;
                ilGenerator.AddExceptionHandlerInformation(exceptionHandler.HandlerKind, exceptionHandler.ExceptionType, tryStart, tryEnd, handlerStart, handlerEnd, filterStart);
            }

            // create the body
            List<ILocalDefinition> variableListCopy = new List<ILocalDefinition>(method.Body.LocalVariables);
            List<ITypeDefinition> privateHelperTypesListCopy = new List<ITypeDefinition>(method.Body.PrivateHelperTypes);
            var newBody = new ILGeneratorMethodBody(ilGenerator, method.Body.LocalsAreZeroed, 8, method, variableListCopy, privateHelperTypesListCopy); // TODO dynamic max stack size?
            method.Body = newBody;


            // step six: replace pointer to the old exception handler with the new exception handler

            // map all old exception handler to the new objects
            foreach (IOperationExceptionInformation exceptionHandler in method.Body.OperationExceptionInformation) {

                // search for the new exception handler object to get the mapping to the old one
                bool found = false;
                foreach (OldExceptionHandlerMapping oldExceptionHandlerMapping in oldExceptionHandlerMappings) {
                    if (oldExceptionHandlerMapping.exceptionType == exceptionHandler.ExceptionType
                        && oldExceptionHandlerMapping.handlerKind == exceptionHandler.HandlerKind
                        && oldExceptionHandlerMapping.filterStartOffset == exceptionHandler.FilterDecisionStartOffset
                        && oldExceptionHandlerMapping.tryStartOffset == exceptionHandler.TryStartOffset
                        && oldExceptionHandlerMapping.tryEndOffset == exceptionHandler.TryEndOffset
                        && oldExceptionHandlerMapping.handlerStartOffset == exceptionHandler.HandlerStartOffset
                        && oldExceptionHandlerMapping.handlerEndOffset == exceptionHandler.HandlerEndOffset) {
                        oldExceptionHandlerMapping.newExceptionHandler = exceptionHandler;
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    throw new ArgumentException("Not able to map old exception handler to new one.");
                }
            }

            // replace all old exception handler in the basic blocks with the new exception handler
            foreach (BasicBlock tempBB in methodCfg.basicBlocks) {

                // replace all exception handler in the try blocks
                foreach (TryBlock tryBlock in tempBB.tryBlocks) {
                    foreach (OldExceptionHandlerMapping oldExceptionHandlerMapping in oldExceptionHandlerMappings) {
                        if (tryBlock.exceptionHandler == oldExceptionHandlerMapping.oldExceptionHandler) {
                            tryBlock.exceptionHandler = oldExceptionHandlerMapping.newExceptionHandler;
                            break;
                        }
                    }
                }

                // replace all exception handler in the handler blocks
                foreach (HandlerBlock handlerBlock in tempBB.handlerBlocks) {
                    foreach (OldExceptionHandlerMapping oldExceptionHandlerMapping in oldExceptionHandlerMappings) {
                        if (handlerBlock.exceptionHandler == oldExceptionHandlerMapping.oldExceptionHandler) {
                            handlerBlock.exceptionHandler = oldExceptionHandlerMapping.newExceptionHandler;
                            break;
                        }
                    }
                }
            }

            
            // TODO
            // DEBUG
            /*
            // sanitize method name to store it as a file
            String invalidChars = System.Text.RegularExpressions.Regex.Escape(new string(System.IO.Path.GetInvalidFileNameChars()));
            String invalidRegStr = string.Format(@"([{0}]*\.+$)|([{0}]+)", invalidChars);
            String fileName = System.Text.RegularExpressions.Regex.Replace(methodCfg.method.ToString(), invalidRegStr, "_");
            fileName = fileName.Length >= 230 ? fileName.Substring(0, 230) : fileName;

            // dump cfg created from the exit branches
            System.IO.StreamWriter dotFile = new System.IO.StreamWriter("e:\\" + "\\BBUnion_" + fileName + ".dot");

            // start .dot file graph
            dotFile.WriteLine("digraph G {");

            for (int bbuidx = 0; bbuidx < basicBlockUnions.Count(); bbuidx++) {
                BasicBlockUnion basicBlockUnion = basicBlockUnions.ElementAt(bbuidx);
                    // write all basic blocks to .dot file
                    for (int idx = 0; idx < basicBlockUnion.basicBlocks.Count(); idx++) {

                        BasicBlock currentBasicBlock = basicBlockUnion.basicBlocks.ElementAt(idx);

                        // write the current basic block to the file and all its instructions
                        dotFile.WriteLine("BB" + bbuidx.ToString() + "_" + idx.ToString() + " [shape=record]");
                        bool first = true;
                        for (int opIdx = 0; opIdx < currentBasicBlock.operations.Count(); opIdx++) {
                            var operation = currentBasicBlock.operations.ElementAt(opIdx);
                            if (first) {
                                dotFile.Write("BB" + bbuidx.ToString() + "_" + idx.ToString() + " [label=\"{");
                                first = false;
                            }
                            else {
                                dotFile.Write("|");
                            }

                            // insert try block beginnings
                            foreach (var tryBlock in currentBasicBlock.tryBlocks) {
                                if (tryBlock.firstBasicBlockOfTryBlock && opIdx == 0) {
                                    dotFile.Write("TRY START (" + tryBlock.exceptionHandler.ExceptionType.ToString() + ")|");
                                }
                            }

                            // insert catch block beginnings
                            foreach (var handlerBlock in currentBasicBlock.handlerBlocks) {
                                if (handlerBlock.firstBasicBlockOfHandlerBlock && opIdx == 0) {
                                    if (handlerBlock.typeOfHandler == HandlerKind.Catch) {
                                        dotFile.Write("CATCH START (" + handlerBlock.exceptionHandler.ExceptionType.ToString() + ")|");
                                    }
                                    else if (handlerBlock.typeOfHandler == HandlerKind.Finally) {
                                        dotFile.Write("FINALLY START (" + handlerBlock.exceptionHandler.ExceptionType.ToString() + ")|");
                                    }
                                    else {
                                        throw new ArgumentException("Do not know how to handle handler.");
                                    }
                                }
                            }

                            // check if instruction has an argument
                            if (operation.Value != null) {
                                dotFile.Write(operation.OperationCode.ToString() + " " + operation.Value.ToString());
                            }
                            else {
                                dotFile.Write(operation.OperationCode.ToString());
                            }

                            // insert try block endings
                            foreach (var tryBlock in currentBasicBlock.tryBlocks) {
                                if (tryBlock.lastBasicBlockOfTryBlock && (currentBasicBlock.operations.Count() - 1) == opIdx) {
                                    dotFile.Write("|TRY END (" + tryBlock.exceptionHandler.ExceptionType.ToString() + ")");
                                }
                            }

                            // insert catch block endings
                            foreach (var handlerBlock in currentBasicBlock.handlerBlocks) {
                                if (handlerBlock.lastBasicBlockOfHandlerBlock && (currentBasicBlock.operations.Count() - 1) == opIdx) {
                                    if (handlerBlock.typeOfHandler == HandlerKind.Catch) {
                                        dotFile.Write("|CATCH END (" + handlerBlock.exceptionHandler.ExceptionType.ToString() + ")");
                                    }
                                    else if (handlerBlock.typeOfHandler == HandlerKind.Finally) {
                                        dotFile.Write("|FINALLY END (" + handlerBlock.exceptionHandler.ExceptionType.ToString() + ")");
                                    }
                                    else {
                                        throw new ArgumentException("Do not know how to handle handler.");
                                    }
                                }
                            }
                        }
                        dotFile.WriteLine("}\"]");


                        if ((idx + 1) < basicBlockUnion.basicBlocks.Count()) {
                            dotFile.WriteLine("BB" + bbuidx.ToString() + "_" + idx.ToString() + " -> BB" + bbuidx.ToString() + "_" + (idx + 1).ToString() + "[ color=\"blue\" ]");
                        }

                    }
                }


            // finish graph
            dotFile.WriteLine("}");

            dotFile.Close();
            */
        }
Пример #20
0
 private void GenerateSwitchInstruction(IEnumerable<ISwitchCase> switchCases, uint maxValue)
 {
     ILGeneratorLabel[] labels = new ILGeneratorLabel[maxValue+1];
       ILGeneratorLabel defaultLabel = new ILGeneratorLabel();
       for (uint i = 0; i <= maxValue; i++) labels[i] = defaultLabel;
       Dictionary<ISwitchCase, ILGeneratorLabel> labelFor = new Dictionary<ISwitchCase, ILGeneratorLabel>();
       bool foundDefault = false;
       foreach (ISwitchCase switchCase in switchCases) {
     if (switchCase.IsDefault) {
       labelFor.Add(switchCase, defaultLabel);
       foundDefault = true;
     } else {
       ILGeneratorLabel caseLabel = new ILGeneratorLabel();
       uint i = (uint)((IConvertible)switchCase.Expression.Value).ToUInt64(null);
       labels[i] = caseLabel;
       labelFor.Add(switchCase, caseLabel);
     }
       }
       this.generator.Emit(OperationCode.Switch, labels);
       this.generator.Emit(OperationCode.Br, defaultLabel);
       ILGeneratorLabel savedCurrentBreakTarget = this.currentBreakTarget;
       if (!foundDefault)
     this.currentBreakTarget = defaultLabel;
       else
     this.currentBreakTarget = new ILGeneratorLabel();
       if (this.currentTryCatch != null)
     this.mostNestedTryCatchFor.Add(this.currentBreakTarget, this.currentTryCatch);
       foreach (ISwitchCase switchCase in switchCases) {
     this.generator.MarkLabel(labelFor[switchCase]);
     this.Traverse(switchCase);
       }
       this.generator.MarkLabel(this.currentBreakTarget);
       this.currentBreakTarget = savedCurrentBreakTarget;
 }
Пример #21
0
        /// <summary>
        /// Generates IL for the specified for statement.
        /// </summary>
        /// <param name="forStatement">For statement.</param>
        public override void TraverseChildren(IForStatement forStatement)
        {
            ILGeneratorLabel savedCurrentBreakTarget = this.currentBreakTarget;
              ILGeneratorLabel savedCurrentContinueTarget = this.currentContinueTarget;
              this.currentBreakTarget = new ILGeneratorLabel();
              this.currentContinueTarget = new ILGeneratorLabel();
              if (this.currentTryCatch != null) {
            this.mostNestedTryCatchFor.Add(this.currentBreakTarget, this.currentTryCatch);
            this.mostNestedTryCatchFor.Add(this.currentContinueTarget, this.currentTryCatch);
              }
              ILGeneratorLabel conditionCheck = new ILGeneratorLabel();
              ILGeneratorLabel loopStart = new ILGeneratorLabel();

              this.Traverse(forStatement.InitStatements);
              this.generator.Emit(OperationCode.Br, conditionCheck);
              this.generator.MarkLabel(loopStart);
              this.Traverse(forStatement.Body);
              this.generator.MarkLabel(this.currentContinueTarget);
              this.Traverse(forStatement.IncrementStatements);
              this.generator.MarkLabel(conditionCheck);
              this.EmitSequencePoint(forStatement.Condition.Locations);
              this.VisitBranchIfTrue(forStatement.Condition, loopStart);
              this.generator.MarkLabel(this.currentBreakTarget);

              this.currentBreakTarget = savedCurrentBreakTarget;
              this.currentContinueTarget = savedCurrentContinueTarget;
              this.lastStatementWasUnconditionalTransfer = false;
        }
Пример #22
0
        /// <summary>
        /// Generates IL for the specified do until statement.
        /// </summary>
        /// <param name="doUntilStatement">The do until statement.</param>
        public override void TraverseChildren(IDoUntilStatement doUntilStatement)
        {
            ILGeneratorLabel savedCurrentBreakTarget = this.currentBreakTarget;
              ILGeneratorLabel savedCurrentContinueTarget = this.currentContinueTarget;
              this.currentBreakTarget = new ILGeneratorLabel();
              this.currentContinueTarget = new ILGeneratorLabel();
              if (this.currentTryCatch != null) {
            this.mostNestedTryCatchFor.Add(this.currentBreakTarget, this.currentTryCatch);
            this.mostNestedTryCatchFor.Add(this.currentContinueTarget, this.currentTryCatch);
              }

              this.generator.MarkLabel(this.currentContinueTarget);
              this.Traverse(doUntilStatement.Body);
              this.EmitSequencePoint(doUntilStatement.Condition.Locations);
              this.VisitBranchIfFalse(doUntilStatement.Condition, this.currentContinueTarget);
              this.generator.MarkLabel(this.currentBreakTarget);

              this.currentBreakTarget = savedCurrentBreakTarget;
              this.currentContinueTarget = savedCurrentContinueTarget;
              this.lastStatementWasUnconditionalTransfer = false;
        }
Пример #23
0
 /// <summary>
 /// Generates IL for the specified conditional statement.
 /// </summary>
 /// <param name="conditionalStatement">The conditional statement.</param>
 public override void TraverseChildren(IConditionalStatement conditionalStatement)
 {
     this.EmitSequencePoint(conditionalStatement.Condition.Locations);
       ILGeneratorLabel/*?*/ endif = null;
       if (conditionalStatement.TrueBranch is IBreakStatement && !this.LabelIsOutsideCurrentExceptionBlock(this.currentBreakTarget))
     this.VisitBranchIfTrue(conditionalStatement.Condition, this.currentBreakTarget);
       else if (conditionalStatement.TrueBranch is IContinueStatement &&  !this.LabelIsOutsideCurrentExceptionBlock(this.currentContinueTarget))
     this.VisitBranchIfTrue(conditionalStatement.Condition, this.currentContinueTarget);
       else {
     ILGeneratorLabel falseCase = new ILGeneratorLabel();
     this.VisitBranchIfFalse(conditionalStatement.Condition, falseCase);
     this.Traverse(conditionalStatement.TrueBranch);
     if (!this.lastStatementWasUnconditionalTransfer) {
       endif = new ILGeneratorLabel();
       this.generator.Emit(OperationCode.Br, endif);
     } else {
     }
     this.generator.MarkLabel(falseCase);
       }
       this.Traverse(conditionalStatement.FalseBranch);
       if (endif != null)
     this.generator.MarkLabel(endif);
       this.lastStatementWasUnconditionalTransfer = false;
 }
Пример #24
0
 /// <summary>
 /// Generates IL for the specified logical not.
 /// </summary>
 /// <param name="logicalNot">The logical not.</param>
 public override void TraverseChildren(ILogicalNot logicalNot)
 {
     if (logicalNot.Operand.Type.IsValueType) {
     //The type should be a primitive integer, a boolean or an enum.
     this.Traverse(logicalNot.Operand);
     var opsize = TypeHelper.SizeOfType(logicalNot.Operand.Type);
     if (opsize == 1 || opsize == 2 || opsize == 4) {
       this.generator.Emit(OperationCode.Ldc_I4_0);
       this.StackSize++;
       this.generator.Emit(OperationCode.Ceq);
       this.StackSize--;
     } else if (opsize == 8) {
       this.generator.Emit(OperationCode.Ldc_I4_0);
       this.StackSize++;
       this.generator.Emit(OperationCode.Conv_I8);
       this.generator.Emit(OperationCode.Ceq);
       this.StackSize--;
     } else {
       Contract.Assert(opsize == 0); //If not, the CodeModel is invalid.
       //the type is an unresolved reference, typically an enum, so we just don't know what size it is (at compile time, that is).
       var trueCase = new ILGeneratorLabel();
       var done = new ILGeneratorLabel();
       this.generator.Emit(OperationCode.Brtrue_S, trueCase);
       this.generator.Emit(OperationCode.Ldc_I4_0);
       this.generator.Emit(OperationCode.Br_S, done);
       this.generator.MarkLabel(trueCase);
       this.generator.Emit(OperationCode.Ldc_I4_1);
       this.generator.MarkLabel(done);
     }
       } else {
     //pointer non null test
     this.Traverse(logicalNot.Operand);
     this.generator.Emit(OperationCode.Ldnull);
     this.StackSize++;
     this.generator.Emit(OperationCode.Ceq);
     this.StackSize--;
       }
 }
Пример #25
0
        /// <summary>
        /// Generates IL code for the given for each statement for the special case where the collection is known
        /// to be vector type.
        /// </summary>
        /// <param name="forEachStatement">The foreach statement to visit.</param>
        /// <param name="arrayType">The vector type of the collection.</param>
        public virtual void VisitForeachArrayElement(IForEachStatement forEachStatement, IArrayTypeReference arrayType)
        {
            Contract.Requires(arrayType.IsVector);
              ILGeneratorLabel savedCurrentBreakTarget = this.currentBreakTarget;
              ILGeneratorLabel savedCurrentContinueTarget = this.currentContinueTarget;
              this.currentBreakTarget = new ILGeneratorLabel();
              this.currentContinueTarget = new ILGeneratorLabel();
              if (this.currentTryCatch != null) {
            this.mostNestedTryCatchFor.Add(this.currentBreakTarget, this.currentTryCatch);
            this.mostNestedTryCatchFor.Add(this.currentContinueTarget, this.currentTryCatch);
              }
              ILGeneratorLabel conditionCheck = new ILGeneratorLabel();
              ILGeneratorLabel loopStart = new ILGeneratorLabel();

              this.EmitSequencePoint(forEachStatement.Variable.Locations);
              this.Traverse(forEachStatement.Collection);
              this.generator.Emit(OperationCode.Dup);
              var array = new TemporaryVariable(arrayType, this.method);
              this.VisitAssignmentTo(array);
              var length = new TemporaryVariable(this.host.PlatformType.SystemInt32, this.method);
              this.generator.Emit(OperationCode.Ldlen);
              this.generator.Emit(OperationCode.Conv_I4);
              this.VisitAssignmentTo(length);
              var counter = new TemporaryVariable(this.host.PlatformType.SystemInt32, this.method);
              this.generator.Emit(OperationCode.Ldc_I4_0);
              this.StackSize++;
              this.VisitAssignmentTo(counter);
              this.generator.Emit(OperationCode.Br, conditionCheck);
              this.generator.MarkLabel(loopStart);
              this.LoadLocal(array);
              this.LoadLocal(counter);
              this.LoadVectorElement(arrayType.ElementType);
              this.VisitAssignmentTo(forEachStatement.Variable);
              this.Traverse(forEachStatement.Body);
              this.generator.MarkLabel(this.currentContinueTarget);
              this.LoadLocal(counter);
              this.generator.Emit(OperationCode.Ldc_I4_1);
              this.StackSize++;
              this.generator.Emit(OperationCode.Add);
              this.StackSize--;
              this.VisitAssignmentTo(counter);
              this.generator.MarkLabel(conditionCheck);
              this.EmitSequencePoint(forEachStatement.Collection.Locations);
              this.LoadLocal(counter);
              this.LoadLocal(length);
              this.generator.Emit(OperationCode.Blt, loopStart);
              this.generator.MarkLabel(this.currentBreakTarget);

              this.currentBreakTarget = savedCurrentBreakTarget;
              this.currentContinueTarget = savedCurrentContinueTarget;
        }
    private void InstrumentBlock(BasicBlock<Instruction> block) {
      var blockOffset = block.Instructions[0].Operation.Offset;
      this.ilGenerator.MarkLabel(this.GetLabelFor(blockOffset));
      for (int i = 0, n = block.Instructions.Count-1; i < n; i++) {
        var operation = block.Instructions[i].Operation;
        this.EmitDebugInformationFor(operation);
        this.ilGenerator.Emit(operation.OperationCode, operation.Value);
      }

      var lastOperation = block.Instructions[block.Instructions.Count-1].Operation;
      this.EmitDebugInformationFor(lastOperation);
      switch (lastOperation.OperationCode) {
        case OperationCode.Beq:
        case OperationCode.Beq_S:
        case OperationCode.Bge:
        case OperationCode.Bge_S:
        case OperationCode.Bge_Un:
        case OperationCode.Bge_Un_S:
        case OperationCode.Bgt:
        case OperationCode.Bgt_S:
        case OperationCode.Bgt_Un:
        case OperationCode.Bgt_Un_S:
        case OperationCode.Ble:
        case OperationCode.Ble_S:
        case OperationCode.Ble_Un:
        case OperationCode.Ble_Un_S:
        case OperationCode.Blt:
        case OperationCode.Blt_S:
        case OperationCode.Blt_Un:
        case OperationCode.Blt_Un_S:
        case OperationCode.Bne_Un:
        case OperationCode.Bne_Un_S:
        case OperationCode.Brfalse:
        case OperationCode.Brfalse_S:
        case OperationCode.Brtrue:
        case OperationCode.Brtrue_S:
          var unconditionalBranch = new ILGeneratorLabel();
          var fallThrough = new ILGeneratorLabel();
          this.ilGenerator.Emit(lastOperation.OperationCode, unconditionalBranch);
          this.ilGenerator.Emit(OperationCode.Br_S, fallThrough);
          this.ilGenerator.MarkLabel(unconditionalBranch);
          this.EmitCounterIncrement(lastOperation.Offset);
          this.ilGenerator.Emit(OperationCode.Br, this.GetLabelFor((uint)lastOperation.Value));
          this.ilGenerator.MarkLabel(fallThrough);
          this.EmitCounterIncrement(lastOperation.Offset+1);
          break;

        case OperationCode.Br:
        case OperationCode.Br_S:
          this.EmitCounterIncrement(lastOperation.Offset);
          this.ilGenerator.Emit(OperationCode.Br, this.GetLabelFor((uint)lastOperation.Value));
          break;

        case OperationCode.Leave:
        case OperationCode.Leave_S:
          this.EmitCounterIncrement(lastOperation.Offset);
          this.ilGenerator.Emit(OperationCode.Leave, this.GetLabelFor((uint)lastOperation.Value));
          break;

        case OperationCode.Endfilter:
        case OperationCode.Endfinally:
        case OperationCode.Jmp:
        case OperationCode.Ret:
        case OperationCode.Rethrow:
        case OperationCode.Throw:
          //No need to count the outgoing edge. Its count is the same as the number of times this block executes.
          this.ilGenerator.Emit(lastOperation.OperationCode, lastOperation.Value);
          break;

        case OperationCode.Switch:
          fallThrough = new ILGeneratorLabel();
          uint[] targets = (uint[])lastOperation.Value;
          ILGeneratorLabel[] counters = new ILGeneratorLabel[targets.Length];
          for (int i = 0, n = counters.Length; i < n; i++) counters[i] = new ILGeneratorLabel();
          this.ilGenerator.Emit(OperationCode.Switch, counters);
          this.EmitCounterIncrement(lastOperation.Offset);
          this.ilGenerator.Emit(OperationCode.Br, fallThrough);
          for (int i = 0, n = counters.Length; i < n; i++) {
            var counterLabel = counters[i];
            this.ilGenerator.MarkLabel(counterLabel);
            this.EmitCounterIncrement(lastOperation.Offset+1+(uint)i);
            this.ilGenerator.Emit(OperationCode.Br, this.GetLabelFor(targets[i]));
          }
          this.ilGenerator.MarkLabel(fallThrough);
          break;

        default:
          this.ilGenerator.Emit(lastOperation.OperationCode, lastOperation.Value);
          this.EmitCounterIncrement(lastOperation.Offset);
          break;
      }
    }
Пример #27
0
    /// <summary>
    /// Returns a label that represents the given offset in the original IL. This label must be marked
    /// at the corresponding location in the rewritten IL.
    /// </summary>
    protected virtual ILGeneratorLabel GetLabelFor(uint offset) {
      Contract.Ensures(Contract.Result<ILGeneratorLabel>() != null);

      var result = this.labelFor[offset];
      if (result == null)
        this.labelFor[offset] = result = new ILGeneratorLabel();
      return result;
    }    
    private void ProcessOperations(IMethodBody methodBody) {

      List<IOperation> operations = ((methodBody.Operations == null) ? new List<IOperation>(): new List<IOperation>(methodBody.Operations));
      int count = operations.Count;

      ILGenerator generator = new ILGenerator(this.host, methodBody.MethodDefinition);
      if (this.pdbReader != null) {
        foreach (var ns in this.pdbReader.GetNamespaceScopes(methodBody)) {
          foreach (var uns in ns.UsedNamespaces)
            generator.UseNamespace(uns.NamespaceName.Value);
        }
      }

      this.currentGenerator = generator;
      this.scopeEnumerator = this.pdbReader == null ? null : this.pdbReader.GetLocalScopes(methodBody).GetEnumerator();
      this.scopeEnumeratorIsValid = this.scopeEnumerator != null && this.scopeEnumerator.MoveNext();

      var methodName = MemberHelper.GetMemberSignature(methodBody.MethodDefinition, NameFormattingOptions.SmartTypeName);

      #region Record all offsets that appear as part of an exception handler
      Dictionary<uint, bool> offsetsUsedInExceptionInformation = new Dictionary<uint, bool>();
      foreach (var exceptionInfo in methodBody.OperationExceptionInformation??Enumerable<IOperationExceptionInformation>.Empty) {
        uint x = exceptionInfo.TryStartOffset;
        if (!offsetsUsedInExceptionInformation.ContainsKey(x)) offsetsUsedInExceptionInformation.Add(x, true);
        x = exceptionInfo.TryEndOffset;
        if (!offsetsUsedInExceptionInformation.ContainsKey(x)) offsetsUsedInExceptionInformation.Add(x, true);
        x = exceptionInfo.HandlerStartOffset;
        if (!offsetsUsedInExceptionInformation.ContainsKey(x)) offsetsUsedInExceptionInformation.Add(x, true);
        x = exceptionInfo.HandlerEndOffset;
        if (!offsetsUsedInExceptionInformation.ContainsKey(x)) offsetsUsedInExceptionInformation.Add(x, true);
        if (exceptionInfo.HandlerKind == HandlerKind.Filter) {
          x = exceptionInfo.FilterDecisionStartOffset;
          if (!offsetsUsedInExceptionInformation.ContainsKey(x)) offsetsUsedInExceptionInformation.Add(x, true);
        }
      }
      #endregion Record all offsets that appear as part of an exception handler

      Dictionary<uint, ILGeneratorLabel> offset2Label = new Dictionary<uint, ILGeneratorLabel>();
      #region Pass 1: Make a label for each branch target
      for (int i = 0; i < count; i++) {
        IOperation op = operations[i];
        switch (op.OperationCode) {
          case OperationCode.Beq:
          case OperationCode.Bge:
          case OperationCode.Bge_Un:
          case OperationCode.Bgt:
          case OperationCode.Bgt_Un:
          case OperationCode.Ble:
          case OperationCode.Ble_Un:
          case OperationCode.Blt:
          case OperationCode.Blt_Un:
          case OperationCode.Bne_Un:
          case OperationCode.Br:
          case OperationCode.Brfalse:
          case OperationCode.Brtrue:
          case OperationCode.Leave:
          case OperationCode.Beq_S:
          case OperationCode.Bge_S:
          case OperationCode.Bge_Un_S:
          case OperationCode.Bgt_S:
          case OperationCode.Bgt_Un_S:
          case OperationCode.Ble_S:
          case OperationCode.Ble_Un_S:
          case OperationCode.Blt_S:
          case OperationCode.Blt_Un_S:
          case OperationCode.Bne_Un_S:
          case OperationCode.Br_S:
          case OperationCode.Brfalse_S:
          case OperationCode.Brtrue_S:
          case OperationCode.Leave_S:
            uint x = (uint)op.Value;
            if (!offset2Label.ContainsKey(x))
              offset2Label.Add(x, new ILGeneratorLabel());
            break;
          case OperationCode.Switch:
            uint[] offsets = op.Value as uint[];
            foreach (var offset in offsets) {
              if (!offset2Label.ContainsKey(offset))
                offset2Label.Add(offset, new ILGeneratorLabel());
            }
            break;
          default:
            break;
        }
      }
      #endregion Pass 1: Make a label for each branch target

      #region Pass 2: Emit each operation, along with labels
      for (int i = 0; i < count; i++) {
        IOperation op = operations[i];
        ILGeneratorLabel label;
        this.EmitDebugInformationFor(op);
        #region Mark operation if it is a label for a branch
        if (offset2Label.TryGetValue(op.Offset, out label)) {
          generator.MarkLabel(label);
        }
        #endregion Mark operation if it is a label for a branch

        #region Mark operation if it is pointed to by an exception handler
        bool ignore;
        uint offset = op.Offset;
        if (offsetsUsedInExceptionInformation.TryGetValue(offset, out ignore)) {
          foreach (var exceptionInfo in methodBody.OperationExceptionInformation) {
            if (offset == exceptionInfo.TryStartOffset)
              generator.BeginTryBody();

            // Never need to do anthing when offset == exceptionInfo.TryEndOffset because
            // we pick up an EndTryBody from the HandlerEndOffset below
            //  generator.EndTryBody();

            if (offset == exceptionInfo.HandlerStartOffset) {
              switch (exceptionInfo.HandlerKind) {
                case HandlerKind.Catch:
                  generator.BeginCatchBlock(exceptionInfo.ExceptionType);
                  break;
                case HandlerKind.Fault:
                  generator.BeginFaultBlock();
                  break;
                case HandlerKind.Filter:
                  generator.BeginFilterBody();
                  break;
                case HandlerKind.Finally:
                  generator.BeginFinallyBlock();
                  break;
              }
            }
            if (exceptionInfo.HandlerKind == HandlerKind.Filter && offset == exceptionInfo.FilterDecisionStartOffset) {
              generator.BeginFilterBlock();
            }
            if (offset == exceptionInfo.HandlerEndOffset)
              generator.EndTryBody();
          }
        }
        #endregion Mark operation if it is pointed to by an exception handler

        #region Emit operation along with any injection
        switch (op.OperationCode) {
          #region Branches
          case OperationCode.Beq:
          case OperationCode.Bge:
          case OperationCode.Bge_Un:
          case OperationCode.Bgt:
          case OperationCode.Bgt_Un:
          case OperationCode.Ble:
          case OperationCode.Ble_Un:
          case OperationCode.Blt:
          case OperationCode.Blt_Un:
          case OperationCode.Bne_Un:
          case OperationCode.Br:
          case OperationCode.Brfalse:
          case OperationCode.Brtrue:
          case OperationCode.Leave:
          case OperationCode.Beq_S:
          case OperationCode.Bge_S:
          case OperationCode.Bge_Un_S:
          case OperationCode.Bgt_S:
          case OperationCode.Bgt_Un_S:
          case OperationCode.Ble_S:
          case OperationCode.Ble_Un_S:
          case OperationCode.Blt_S:
          case OperationCode.Blt_Un_S:
          case OperationCode.Bne_Un_S:
          case OperationCode.Br_S:
          case OperationCode.Brfalse_S:
          case OperationCode.Brtrue_S:
          case OperationCode.Leave_S:
            generator.Emit(ILGenerator.LongVersionOf(op.OperationCode), offset2Label[(uint)op.Value]);
            break;
          case OperationCode.Switch:
            uint[] offsets = op.Value as uint[];
            ILGeneratorLabel[] labels = new ILGeneratorLabel[offsets.Length];
            for (int j = 0, n = offsets.Length; j < n; j++) {
              labels[j] = offset2Label[offsets[j]];
            }
            generator.Emit(OperationCode.Switch, labels);
            break;
          #endregion Branches
          #region Everything else
          case OperationCode.Stloc_0:
          case OperationCode.Stloc_1:
          case OperationCode.Stloc_2:
          case OperationCode.Stloc_3:
            generator.Emit(op.OperationCode);
            EmitStoreLocal(generator, op);
            break;
          case OperationCode.Stloc:
          case OperationCode.Stloc_S:
            generator.Emit(op.OperationCode, op.Value);
            EmitStoreLocal(generator, op);
            break;
          default:
            if (op.Value == null) {
              generator.Emit(op.OperationCode);
              break;
            }
            var typeCode = System.Convert.GetTypeCode(op.Value);
            switch (typeCode) {
              case TypeCode.Byte:
                generator.Emit(op.OperationCode, (byte)op.Value);
                break;
              case TypeCode.Double:
                generator.Emit(op.OperationCode, (double)op.Value);
                break;
              case TypeCode.Int16:
                generator.Emit(op.OperationCode, (short)op.Value);
                break;
              case TypeCode.Int32:
                generator.Emit(op.OperationCode, (int)op.Value);
                break;
              case TypeCode.Int64:
                generator.Emit(op.OperationCode, (long)op.Value);
                break;
              case TypeCode.Object:
                IFieldReference fieldReference = op.Value as IFieldReference;
                if (fieldReference != null) {
                  generator.Emit(op.OperationCode, this.Rewrite(fieldReference));
                  break;
                }
                ILocalDefinition localDefinition = op.Value as ILocalDefinition;
                if (localDefinition != null) {
                  generator.Emit(op.OperationCode, localDefinition);
                  break;
                }
                IMethodReference methodReference = op.Value as IMethodReference;
                if (methodReference != null) {
                  generator.Emit(op.OperationCode, this.Rewrite(methodReference));
                  break;
                }
                IParameterDefinition parameterDefinition = op.Value as IParameterDefinition;
                if (parameterDefinition != null) {
                  generator.Emit(op.OperationCode, parameterDefinition);
                  break;
                }
                ISignature signature = op.Value as ISignature;
                if (signature != null) {
                  generator.Emit(op.OperationCode, signature);
                  break;
                }
                ITypeReference typeReference = op.Value as ITypeReference;
                if (typeReference != null) {
                  generator.Emit(op.OperationCode, this.Rewrite(typeReference));
                  break;
                }
                throw new ILMutatorException("Should never get here: no other IOperation argument types should exist");
              case TypeCode.SByte:
                generator.Emit(op.OperationCode, (sbyte)op.Value);
                break;
              case TypeCode.Single:
                generator.Emit(op.OperationCode, (float)op.Value);
                break;
              case TypeCode.String:
                generator.Emit(op.OperationCode, (string)op.Value);
                break;
              default:
                // The other cases are the other enum values that TypeCode has.
                // But no other argument types should be in the Operations. ILGenerator cannot handle anything else,
                // so such IOperations should never exist.
                //case TypeCode.Boolean:
                //case TypeCode.Char:
                //case TypeCode.DateTime:
                //case TypeCode.DBNull:
                //case TypeCode.Decimal:
                //case TypeCode.Empty: // this would be the value for null, but the case when op.Value is null is handled before the switch statement
                //case TypeCode.UInt16:
                //case TypeCode.UInt32:
                //case TypeCode.UInt64:
                throw new ILMutatorException("Should never get here: no other IOperation argument types should exist");
            }
            break;
          #endregion Everything else
        }
        #endregion Emit operation along with any injection

      }
      while (generator.InTryBody)
        generator.EndTryBody();
      while (this.scopeStack.Count > 0) {
        this.currentGenerator.EndScope();
        this.scopeStack.Pop();
      }
      #endregion Pass 2: Emit each operation, along with labels

    }
    /// <summary>
    /// This method is called for all labels.
    /// </summary>
    /// <param name="op">The Microsoft intermediate language (MSIL) instruction that is marked as being a label.</param>
    /// <param name="label">A label that can be used to designate locations in MSIL where an instruction may jump.</param>
    protected virtual void RewriteLabel(IOperation op, ILGeneratorLabel label) {
      Contract.Requires(this.generator != null);
      Contract.Requires(op != null);
      Contract.Requires(label != null);

      this.generator.MarkLabel(label);
    }
Пример #30
0
 internal TryBody(ILGeneratorLabel start)
 {
     this.start = start;
 }
Пример #31
0
 /// <summary>
 /// Generates IL for the specified try catch filter finally statement.
 /// </summary>
 /// <param name="tryCatchFilterFinallyStatement">The try catch filter finally statement.</param>
 public override void TraverseChildren(ITryCatchFinallyStatement tryCatchFilterFinallyStatement)
 {
     var savedCurrentTryCatch = this.currentTryCatch;
       this.currentTryCatch = tryCatchFilterFinallyStatement;
       ILGeneratorLabel/*?*/ savedCurrentTryCatchFinallyEnd = this.currentTryCatchFinallyEnd;
       this.currentTryCatchFinallyEnd = new ILGeneratorLabel();
       this.generator.BeginTryBody();
       this.Traverse(tryCatchFilterFinallyStatement.TryBody);
       if (!this.lastStatementWasUnconditionalTransfer)
     this.generator.Emit(OperationCode.Leave, this.currentTryCatchFinallyEnd);
       this.Traverse(tryCatchFilterFinallyStatement.CatchClauses);
       if (tryCatchFilterFinallyStatement.FinallyBody != null) {
     this.generator.BeginFinallyBlock();
     this.Traverse(tryCatchFilterFinallyStatement.FinallyBody);
     this.generator.Emit(OperationCode.Endfinally);
       }
       if (tryCatchFilterFinallyStatement.FaultBody != null) {
     this.generator.BeginFaultBlock();
     this.Traverse(tryCatchFilterFinallyStatement.FaultBody);
     this.generator.Emit(OperationCode.Endfinally);
       }
       this.generator.EndTryBody();
       this.generator.MarkLabel(this.currentTryCatchFinallyEnd);
       this.currentTryCatchFinallyEnd = savedCurrentTryCatchFinallyEnd;
       this.currentTryCatch = savedCurrentTryCatch;
       this.lastStatementWasUnconditionalTransfer = false;
 }
Пример #32
0
 //^ ensures InTryBody;
 /// <summary>
 /// Begins the body of a try statement.
 /// </summary>
 public void BeginTryBody()
 {
     ILGeneratorLabel tryBodyStart = new ILGeneratorLabel(false);
       this.MarkLabel(tryBodyStart);
       this.tryBodyStack.Push(new TryBody(tryBodyStart));
 }
Пример #33
0
        /// <summary>
        /// Generates IL for the specified resource use statement.
        /// </summary>
        /// <param name="resourceUseStatement">The resource use statement.</param>
        public override void TraverseChildren(IResourceUseStatement resourceUseStatement)
        {
            this.EmitSequencePoint(resourceUseStatement.Locations);
              var systemIDisposable = new NamespaceTypeReference(this.host, this.host.PlatformType.SystemObject.ContainingUnitNamespace,
            this.host.NameTable.GetNameFor("IDisposable"), 0, isEnum: false, isValueType: false, typeCode: PrimitiveTypeCode.NotPrimitive);
              var dispose = new MethodReference(this.host, systemIDisposable, CallingConvention.Default, this.host.PlatformType.SystemVoid,
            this.host.NameTable.GetNameFor("Dispose"), 0, Enumerable<IParameterTypeInformation>.Empty);

              //Get resource into a local
              ILocalDefinition resourceLocal;
              var localDeclaration = resourceUseStatement.ResourceAcquisitions as ILocalDeclarationStatement;
              if (localDeclaration != null) {
            resourceLocal = localDeclaration.LocalVariable;
            this.Traverse(localDeclaration.InitialValue);
              } else {
            var expressionStatement = (IExpressionStatement)resourceUseStatement.ResourceAcquisitions;
            this.Traverse(expressionStatement.Expression);
            resourceLocal = new TemporaryVariable(systemIDisposable, this.method);
              }
              this.VisitAssignmentTo(resourceLocal);

              //try
              var savedCurrentTryCatch = this.currentTryCatch;
              this.currentTryCatch = resourceUseStatement;
              var savedCurrentTryCatchFinallyEnd = this.currentTryCatchFinallyEnd;
              this.currentTryCatchFinallyEnd = new ILGeneratorLabel();
              this.generator.BeginTryBody();
              this.Traverse(resourceUseStatement.Body);
              if (!this.lastStatementWasUnconditionalTransfer)
            this.generator.Emit(OperationCode.Leave, this.currentTryCatchFinallyEnd);

              //finally
              this.generator.BeginFinallyBlock();
              var endOfFinally = new ILGeneratorLabel();
              if (!resourceLocal.Type.IsValueType) {
            this.generator.Emit(OperationCode.Ldloc, resourceLocal);
            this.generator.Emit(OperationCode.Brfalse_S, endOfFinally);
              }
              this.generator.Emit(OperationCode.Ldloc, resourceLocal);
              this.generator.Emit(OperationCode.Callvirt, dispose);
              this.generator.MarkLabel(endOfFinally);
              this.generator.Emit(OperationCode.Endfinally);
              this.generator.EndTryBody();
              this.generator.MarkLabel(this.currentTryCatchFinallyEnd);
              this.currentTryCatchFinallyEnd = savedCurrentTryCatchFinallyEnd;
              this.currentTryCatch = savedCurrentTryCatch;
              this.lastStatementWasUnconditionalTransfer = false;
        }
Пример #34
0
 //^ requires InTryBody;
 /// <summary>
 /// Ends a try body.
 /// </summary>
 public void EndTryBody()
 {
     this.tryBodyStack.Pop();
       if (this.handlers.Count > 0) {
     ILGeneratorLabel handlerEnd = new ILGeneratorLabel(false);
     this.MarkLabel(handlerEnd);
     for (int i = this.handlers.Count-1; i >= 0; i--) {
       var handler = this.handlers[i];
       if (handler.HandlerEnd == null) {
     handler.HandlerEnd = handlerEnd;
     if (i < this.handlers.Count-1) {
       this.handlers.RemoveAt(i);
       this.handlers.Add(handler);
     }
     break;
       }
     }
       }
 }
Пример #35
0
        /// <summary>
        /// Performs one or more extra passes over the list of operations, changing long branches to short if possible and short branches to
        /// long branches if necessary.
        /// </summary>
        /// <remarks>If any long branches in this.operations could have been short, they are adjusted to be short.
        /// This can result in an updated version of this.operations where some branches that had to be long in the previous
        /// version can now be short as well. Consequently, the adjustment process iterates until no further changes are possible.
        /// Note that all decisions are made based on the offsets at the start of an iteration. </remarks>
        public void AdjustBranchSizesToBestFit()
        {
            int  adjustment;
            uint numberOfAdjustments;

            do
            {
                adjustment          = 0;
                numberOfAdjustments = 0;
                for (int i = 0, n = this.operations.Count; i < n; i++)
                {
                    Operation operation = this.operations[i];
                    uint      oldOffset = operation.offset;
                    uint      newOffset = (uint)(((int)oldOffset) + adjustment);
                    operation.offset = newOffset;
                    ILGeneratorLabel /*?*/ label = operation.value as ILGeneratorLabel;
                    if (label != null)
                    {
                        if (operation.OperationCode == (OperationCode)int.MaxValue)
                        {
                            //Dummy operation that serves as label definition.
                            label.Offset = operation.offset;
                            continue;
                        }
                        // REVIEW: Do we really want to do this? Should it be an optimization that is made upstream?
                        if (label.labelsReturnInstruction && (operation.OperationCode == OperationCode.Br || operation.OperationCode == OperationCode.Br_S))
                        {
                            numberOfAdjustments++;
                            adjustment        -= (operation.OperationCode == OperationCode.Br ? 4 : 1);
                            this.operations[i] = new Operation(OperationCode.Ret, operation.offset, label.locationOfReturnInstruction, null);
                            continue;
                        }
                        //For backward branches, this test will compare the new offset of the label with the old offset of the current
                        //instruction. This is OK, because the new offset of the label will be less than or equal to its old offset.
                        bool isForwardBranch = label.Offset >= oldOffset;
                        // Short offsets are calculated from the start of the instruction *after* the current instruction, which takes up 2 bytes
                        // (1 for the opcode and 1 for the signed byte).
                        bool          shortOffsetOk = isForwardBranch ? label.Offset - oldOffset <= 129 : newOffset - label.Offset <= 126;
                        OperationCode oldOpCode     = operation.OperationCode;
                        if (shortOffsetOk)
                        {
                            operation.operationCode = ShortVersionOf(operation.OperationCode);
                            if (operation.operationCode != oldOpCode)
                            {
                                numberOfAdjustments++; adjustment -= 3;
                            }
                        }
                        else
                        {
                            if (operation.operationCode != LongVersionOf(operation.operationCode))
                            {
                                throw new InvalidOperationException(); //A short branch was specified for an offset that is long.
                            }
                            //The test for isForwardBranch depends on label offsets only decreasing, so it is not an option to replace the short branch with a long one.
                        }
                        if (operation.OperationCode == OperationCode.Br_S && operation.offset + 2 == label.Offset)
                        {
                            //eliminate branch to the next instruction
                            operation.operationCode            = (OperationCode)int.MaxValue;
                            numberOfAdjustments++; adjustment -= 2;
                        }
                    }
                }
            } while (numberOfAdjustments > 0);
        }
Пример #36
0
 //^ requires InTryBody;
 private ExceptionHandler BeginHandler(HandlerKind kind)
 {
     ILGeneratorLabel handlerStart = new ILGeneratorLabel(false);
       this.MarkLabel(handlerStart);
       TryBody currentTryBody = this.tryBodyStack.Peek();
       ExceptionHandler handler = new ExceptionHandler(kind, currentTryBody, handlerStart);
       if (currentTryBody.end == null)
     currentTryBody.end = handlerStart;
       else if (this.handlers.Count > 0) {
     for (int i = this.handlers.Count-1; i >= 0; i--) {
       if (this.handlers[i].HandlerEnd == null) {
     this.handlers[i].HandlerEnd = handlerStart;
     break;
       }
     }
       }
       this.handlers.Add(handler);
       return handler;
 }
Пример #37
0
        /// <summary>
        /// Emits the given operation at the current position of the new IL stream. Also tracks any referenced local definitions,
        /// so that this.localVariables will contain the exact list of locals used in the new method body.
        /// </summary>
        /// <param name="operation"></param>
        protected virtual void EmitOperation(IOperation operation)
        {
            Contract.Requires(operation != null);

            var operationCode = operation.OperationCode;
            var value         = operation.Value;

            switch (operationCode)
            {
            case OperationCode.Beq:
            case OperationCode.Bge:
            case OperationCode.Bge_Un:
            case OperationCode.Bgt:
            case OperationCode.Bgt_Un:
            case OperationCode.Ble:
            case OperationCode.Ble_Un:
            case OperationCode.Blt:
            case OperationCode.Blt_Un:
            case OperationCode.Bne_Un:
            case OperationCode.Br:
            case OperationCode.Br_S:
            case OperationCode.Brfalse:
            case OperationCode.Brtrue:
            case OperationCode.Leave:
            case OperationCode.Beq_S:
            case OperationCode.Bge_S:
            case OperationCode.Bge_Un_S:
            case OperationCode.Bgt_S:
            case OperationCode.Bgt_Un_S:
            case OperationCode.Ble_S:
            case OperationCode.Ble_Un_S:
            case OperationCode.Blt_S:
            case OperationCode.Blt_Un_S:
            case OperationCode.Bne_Un_S:
            case OperationCode.Brfalse_S:
            case OperationCode.Brtrue_S:
            case OperationCode.Leave_S:
                operationCode = ILGenerator.LongVersionOf(operationCode);
                Contract.Assume(operation.Value is uint);
                value = this.GetLabelFor(+(uint)operation.Value);
                break;

            case OperationCode.Switch:
                uint[] offsets = operation.Value as uint[];
                Contract.Assume(offsets != null);
                var n = offsets.Length;
                ILGeneratorLabel[] labels = new ILGeneratorLabel[n];
                for (int i = 0; i < n; i++)
                {
                    var offset = offsets[i];
                    labels[i] = this.GetLabelFor(offset);
                }
                value = labels;
                break;

            //Avoid the short forms because the locals can get reordered.
            case OperationCode.Ldloc_0:
            case OperationCode.Ldloc_1:
            case OperationCode.Ldloc_2:
            case OperationCode.Ldloc_3:
            case OperationCode.Ldloc_S:
                operationCode = OperationCode.Ldloc;
                break;

            case OperationCode.Ldloca_S:
                operationCode = OperationCode.Ldloca;
                break;

            case OperationCode.Stloc_0:
            case OperationCode.Stloc_1:
            case OperationCode.Stloc_2:
            case OperationCode.Stloc_3:
            case OperationCode.Stloc_S:
                operationCode = OperationCode.Stloc;
                break;
            }
            this.generator.Emit(operationCode, value);
        }
Пример #38
0
    /// <summary>
    /// Emits the given operation at the current position of the new IL stream. Also tracks any referenced local definitions,
    /// so that this.localVariables will contain the exact list of locals used in the new method body.
    /// </summary>
    /// <param name="operation"></param>
    protected virtual void EmitOperation(IOperation operation) {
      Contract.Requires(operation != null);

      var operationCode = operation.OperationCode;
      var value = operation.Value;
      switch (operationCode) {
        case OperationCode.Beq:
        case OperationCode.Bge:
        case OperationCode.Bge_Un:
        case OperationCode.Bgt:
        case OperationCode.Bgt_Un:
        case OperationCode.Ble:
        case OperationCode.Ble_Un:
        case OperationCode.Blt:
        case OperationCode.Blt_Un:
        case OperationCode.Bne_Un:
        case OperationCode.Br:
        case OperationCode.Br_S:
        case OperationCode.Brfalse:
        case OperationCode.Brtrue:
        case OperationCode.Leave:
        case OperationCode.Beq_S:
        case OperationCode.Bge_S:
        case OperationCode.Bge_Un_S:
        case OperationCode.Bgt_S:
        case OperationCode.Bgt_Un_S:
        case OperationCode.Ble_S:
        case OperationCode.Ble_Un_S:
        case OperationCode.Blt_S:
        case OperationCode.Blt_Un_S:
        case OperationCode.Bne_Un_S:
        case OperationCode.Brfalse_S:
        case OperationCode.Brtrue_S:
        case OperationCode.Leave_S:
          operationCode = ILGenerator.LongVersionOf(operationCode);
          Contract.Assume(operation.Value is uint);
          value = this.GetLabelFor(+(uint)operation.Value);
          break;
        case OperationCode.Switch:
          uint[] offsets = operation.Value as uint[];
          Contract.Assume(offsets != null);
          var n = offsets.Length;
          ILGeneratorLabel[] labels = new ILGeneratorLabel[n];
          for (int i = 0; i < n; i++) {
            var offset = offsets[i];
            labels[i] = this.GetLabelFor(offset);
          }
          value = labels;
          break;

        //Avoid the short forms because the locals can get reordered.
        case OperationCode.Ldloc_0:
        case OperationCode.Ldloc_1:
        case OperationCode.Ldloc_2:
        case OperationCode.Ldloc_3:
        case OperationCode.Ldloc_S:
          operationCode = OperationCode.Ldloc;
          break;

        case OperationCode.Ldloca_S:
          operationCode = OperationCode.Ldloca;
          break;

        case OperationCode.Stloc_0:
        case OperationCode.Stloc_1:
        case OperationCode.Stloc_2:
        case OperationCode.Stloc_3:
        case OperationCode.Stloc_S:
          operationCode = OperationCode.Stloc;
          break;
      }
      this.generator.Emit(operationCode, value);
    }
Пример #39
0
 private void VisitBranchIfTrue(IExpression expression, ILGeneratorLabel targetLabel)
 {
     OperationCode branchOp = OperationCode.Brtrue;
       IBinaryOperation/*?*/ binaryOperation = expression as IBinaryOperation;
       bool signedPrimitive = binaryOperation != null && TypeHelper.IsSignedPrimitive(binaryOperation.LeftOperand.Type);
       if (binaryOperation is IEquality) {
     branchOp = OperationCode.Beq;
     if (ExpressionHelper.IsIntegralZero(binaryOperation.LeftOperand) || ExpressionHelper.IsNullLiteral(binaryOperation.LeftOperand) ||
       binaryOperation.LeftOperand is IDefaultValue || ExpressionHelper.IsZeroIntPtr(binaryOperation.LeftOperand)) {
       branchOp = OperationCode.Brfalse;
       expression = binaryOperation.RightOperand;
     } else if (ExpressionHelper.IsIntegralZero(binaryOperation.RightOperand) || ExpressionHelper.IsNullLiteral(binaryOperation.RightOperand) ||
       binaryOperation.RightOperand is IDefaultValue || ExpressionHelper.IsZeroIntPtr(binaryOperation.RightOperand)) {
       branchOp = OperationCode.Brfalse;
       expression = binaryOperation.LeftOperand;
     }
       } else if (binaryOperation is INotEquality) {
     branchOp = OperationCode.Bne_Un;
     if (ExpressionHelper.IsIntegralZero(binaryOperation.LeftOperand) || ExpressionHelper.IsNullLiteral(binaryOperation.LeftOperand) ||
       binaryOperation.LeftOperand is IDefaultValue || ExpressionHelper.IsZeroIntPtr(binaryOperation.LeftOperand)) {
       branchOp = OperationCode.Brtrue;
       expression = binaryOperation.RightOperand;
     } else if (ExpressionHelper.IsIntegralZero(binaryOperation.RightOperand) || ExpressionHelper.IsNullLiteral(binaryOperation.RightOperand) ||
       binaryOperation.RightOperand is IDefaultValue || ExpressionHelper.IsZeroIntPtr(binaryOperation.RightOperand)) {
       branchOp = OperationCode.Brtrue;
       expression = binaryOperation.LeftOperand;
     }
       } else if (binaryOperation is ILessThan) branchOp = ((ILessThan)binaryOperation).IsUnsignedOrUnordered ? OperationCode.Blt_Un : OperationCode.Blt;
       else if (binaryOperation is ILessThanOrEqual) branchOp = ((ILessThanOrEqual)binaryOperation).IsUnsignedOrUnordered ? OperationCode.Ble_Un : OperationCode.Ble;
       else if (binaryOperation is IGreaterThan) branchOp = ((IGreaterThan)binaryOperation).IsUnsignedOrUnordered ? OperationCode.Bgt_Un : OperationCode.Bgt;
       else if (binaryOperation is IGreaterThanOrEqual) branchOp = ((IGreaterThanOrEqual)binaryOperation).IsUnsignedOrUnordered ? OperationCode.Bge_Un : OperationCode.Bge;
       else {
     IConditional/*?*/ conditional = expression as IConditional;
     if (conditional != null) {
       ICompileTimeConstant/*?*/ resultIfFalse = conditional.ResultIfFalse as ICompileTimeConstant;
       if (resultIfFalse != null && (ExpressionHelper.IsIntegralZero(resultIfFalse) || (resultIfFalse.Value is bool && !((bool)resultIfFalse.Value)))) {
     //conditional.Condition && conditional.ResultIfTrue
     ILGeneratorLabel fallThrough = new ILGeneratorLabel();
     this.VisitBranchIfFalse(conditional.Condition, fallThrough);
     this.VisitBranchIfTrue(conditional.ResultIfTrue, targetLabel);
     this.generator.MarkLabel(fallThrough);
     return;
       }
       ICompileTimeConstant/*?*/ resultIfTrue = conditional.ResultIfTrue as ICompileTimeConstant;
       if (resultIfTrue != null && (ExpressionHelper.IsIntegralOne(resultIfTrue) || (resultIfTrue.Value is bool && (bool)resultIfTrue.Value))) {
     //conditional.Condition || conditional.ResultIfFalse
     this.VisitBranchIfTrue(conditional.Condition, targetLabel);
     this.VisitBranchIfTrue(conditional.ResultIfFalse, targetLabel);
     return;
       }
     }
     IMethodCall/*?*/ methodCall = expression as IMethodCall;
     if (methodCall != null) {
       int mkey = methodCall.MethodToCall.Name.UniqueKey;
       if ((mkey == this.host.NameTable.OpEquality.UniqueKey || mkey == this.host.NameTable.OpInequality.UniqueKey) &&
     TypeHelper.TypesAreEquivalent(methodCall.MethodToCall.ContainingType, methodCall.Type.PlatformType.SystemMulticastDelegate)) {
     List<IExpression> operands = new List<IExpression>(methodCall.Arguments);
     if (operands.Count == 2) {
       if (ExpressionHelper.IsNullLiteral(operands[0]))
         expression = operands[1];
       else if (ExpressionHelper.IsNullLiteral(operands[1]))
         expression = operands[0];
       if (expression != methodCall)
         branchOp = methodCall.MethodToCall.Name.UniqueKey == this.host.NameTable.OpEquality.UniqueKey ? OperationCode.Brfalse : OperationCode.Brtrue;
     }
       }
     } else {
       ILogicalNot/*?*/ logicalNot = expression as ILogicalNot;
       if (logicalNot != null) {
     this.VisitBranchIfFalse(logicalNot.Operand, targetLabel);
     return;
       }
     }
       }
       if (branchOp == OperationCode.Brfalse || branchOp == OperationCode.Brtrue) {
     this.Traverse(expression);
     this.StackSize--;
       } else {
     this.Traverse(binaryOperation.LeftOperand);
     this.Traverse(binaryOperation.RightOperand);
     this.StackSize-=2;
       }
       this.generator.Emit(branchOp, targetLabel);
 }
Пример #40
0
		/// <summary>
		/// Emits the specified number of operations from the original method body.
		/// </summary>
		/// <param name="count"></param>
		public void EmitOperations(int count)
		{
			for (int i = 0; i < count; i++)
			{
				IOperation op = operations[0];
				operations.RemoveAt(0);
				ILGeneratorLabel label;
				if (op.Location is IILLocation)
					MarkSequencePoint(op.Location);

				// Mark operation if it is a label for a branch
				if (offset2Label.TryGetValue(op.Offset, out label))
					MarkLabel(label);

				// Mark operation if it is pointed to by an exception handler
				bool ignore;
				uint offset = op.Offset;
				if (offsetsUsedInExceptionInformation.TryGetValue(offset, out ignore))
				{
					foreach (var exceptionInfo in methodBody.OperationExceptionInformation)
					{
						if (offset == exceptionInfo.TryStartOffset)
							BeginTryBody();

						// Never need to do anthing when offset == exceptionInfo.TryEndOffset because
						// we pick up an EndTryBody from the HandlerEndOffset below
						//  EndTryBody();

						if (offset == exceptionInfo.HandlerStartOffset)
						{
							switch (exceptionInfo.HandlerKind)
							{
								case HandlerKind.Catch:
									BeginCatchBlock(exceptionInfo.ExceptionType);
									break;
								case HandlerKind.Fault:
									BeginFaultBlock();
									break;
								case HandlerKind.Filter:
									BeginFilterBody();
									break;
								case HandlerKind.Finally:
									BeginFinallyBlock();
									break;
							}
						}

						if (exceptionInfo.HandlerKind == HandlerKind.Filter && offset == exceptionInfo.FilterDecisionStartOffset)
							BeginFilterBlock();

						if (offset == exceptionInfo.HandlerEndOffset)
							EndTryBody();
					}
				}

				// Emit operation along with any injection
				switch (op.OperationCode)
				{
					// Branches
					case OperationCode.Beq:
					case OperationCode.Bge:
					case OperationCode.Bge_Un:
					case OperationCode.Bgt:
					case OperationCode.Bgt_Un:
					case OperationCode.Ble:
					case OperationCode.Ble_Un:
					case OperationCode.Blt:
					case OperationCode.Blt_Un:
					case OperationCode.Bne_Un:
					case OperationCode.Br:
					case OperationCode.Brfalse:
					case OperationCode.Brtrue:
					case OperationCode.Leave:
					case OperationCode.Beq_S:
					case OperationCode.Bge_S:
					case OperationCode.Bge_Un_S:
					case OperationCode.Bgt_S:
					case OperationCode.Bgt_Un_S:
					case OperationCode.Ble_S:
					case OperationCode.Ble_Un_S:
					case OperationCode.Blt_S:
					case OperationCode.Blt_Un_S:
					case OperationCode.Bne_Un_S:
					case OperationCode.Br_S:
					case OperationCode.Brfalse_S:
					case OperationCode.Brtrue_S:
					case OperationCode.Leave_S:
						Emit(ILGenerator.LongVersionOf(op.OperationCode), offset2Label[(uint)op.Value]);
						break;
					case OperationCode.Switch:
						uint[] offsets = op.Value as uint[];
						ILGeneratorLabel[] labels = new ILGeneratorLabel[offsets.Length];
						for (int j = 0, n = offsets.Length; j < n; j++)
						{
							labels[j] = offset2Label[offsets[j]];
						}
						Emit(OperationCode.Switch, labels);
						break;

					// Everything else
					default:
						if (op.Value == null)
						{
							Emit(op.OperationCode);
							break;
						}
						var typeCode = System.Convert.GetTypeCode(op.Value);
						switch (typeCode)
						{
							case TypeCode.Byte:
								Emit(op.OperationCode, (byte)op.Value);
								break;
							case TypeCode.Double:
								Emit(op.OperationCode, (double)op.Value);
								break;
							case TypeCode.Int16:
								Emit(op.OperationCode, (short)op.Value);
								break;
							case TypeCode.Int32:
								Emit(op.OperationCode, (int)op.Value);
								break;
							case TypeCode.Int64:
								Emit(op.OperationCode, (long)op.Value);
								break;
							case TypeCode.Object:
								IFieldReference fieldReference = op.Value as IFieldReference;
								if (fieldReference != null)
								{
									Emit(op.OperationCode, fieldReference);
									break;
								}
								ILocalDefinition localDefinition = op.Value as ILocalDefinition;
								if (localDefinition != null)
								{
									Emit(op.OperationCode, localDefinition);
									break;
								}
								IMethodReference methodReference = op.Value as IMethodReference;
								if (methodReference != null)
								{
									Emit(op.OperationCode, methodReference);
									break;
								}
								IParameterDefinition parameterDefinition = op.Value as IParameterDefinition;
								if (parameterDefinition != null)
								{
									Emit(op.OperationCode, parameterDefinition);
									break;
								}
								ISignature signature = op.Value as ISignature;
								if (signature != null)
								{
									Emit(op.OperationCode, signature);
									break;
								}
								ITypeReference typeReference = op.Value as ITypeReference;
								if (typeReference != null)
								{
									Emit(op.OperationCode, typeReference);
									break;
								}
								throw new Exception("Should never get here: no other IOperation argument types should exist");
							case TypeCode.SByte:
								Emit(op.OperationCode, (sbyte)op.Value);
								break;
							case TypeCode.Single:
								Emit(op.OperationCode, (float)op.Value);
								break;
							case TypeCode.String:
								Emit(op.OperationCode, (string)op.Value);
								break;
							default:
								throw new Exception("Should never get here: no other IOperation argument types should exist");
						}
						break;
				}
			}
		}
Пример #41
0
 /// <summary>
 ///  Marks the Microsoft intermediate language (MSIL) stream's current position with the given label.
 /// </summary>
 public void MarkLabel(ILGeneratorLabel label)
 {
     label.Offset = this.offset;
     this.operations.Add(new Operation((OperationCode)int.MaxValue, this.offset, Dummy.Location, label));
 }
    /// <summary>
    /// This method is called for all opcodes related to branches:
    ///    OperationCode.Beq:
    ///    OperationCode.Bge:
    ///    OperationCode.Bge_Un:
    ///    OperationCode.Bgt:
    ///    OperationCode.Bgt_Un:
    ///    OperationCode.Ble:
    ///    OperationCode.Ble_Un:
    ///    OperationCode.Blt:
    ///    OperationCode.Blt_Un:
    ///    OperationCode.Bne_Un:
    ///    OperationCode.Br:
    ///    OperationCode.Brfalse:
    ///    OperationCode.Brtrue:
    ///    OperationCode.Leave:
    ///    OperationCode.Beq_S:
    ///    OperationCode.Bge_S:
    ///    OperationCode.Bge_Un_S:
    ///    OperationCode.Bgt_S:
    ///    OperationCode.Bgt_Un_S:
    ///    OperationCode.Ble_S:
    ///    OperationCode.Ble_Un_S:
    ///    OperationCode.Blt_S:
    ///    OperationCode.Blt_Un_S:
    ///    OperationCode.Bne_Un_S:
    ///    OperationCode.Br_S:
    ///    OperationCode.Brfalse_S:
    ///    OperationCode.Brtrue_S:
    ///    OperationCode.Leave_S:
    /// </summary>
    /// <param name="op">The Microsoft intermediate language (MSIL) instruction to be copied.</param>
    protected virtual void RewriteBranch(IOperation op) {
      Contract.Requires(this.generator != null);
      Contract.Requires(op != null);

      // handle branches
      switch (op.OperationCode) {
        // Branches
        case OperationCode.Beq:
        case OperationCode.Bge:
        case OperationCode.Bge_Un:
        case OperationCode.Bgt:
        case OperationCode.Bgt_Un:
        case OperationCode.Ble:
        case OperationCode.Ble_Un:
        case OperationCode.Blt:
        case OperationCode.Blt_Un:
        case OperationCode.Bne_Un:
        case OperationCode.Br:
        case OperationCode.Brfalse:
        case OperationCode.Brtrue:
        case OperationCode.Leave:
        case OperationCode.Beq_S:
        case OperationCode.Bge_S:
        case OperationCode.Bge_Un_S:
        case OperationCode.Bgt_S:
        case OperationCode.Bgt_Un_S:
        case OperationCode.Ble_S:
        case OperationCode.Ble_Un_S:
        case OperationCode.Blt_S:
        case OperationCode.Blt_Un_S:
        case OperationCode.Bne_Un_S:
        case OperationCode.Br_S:
        case OperationCode.Brfalse_S:
        case OperationCode.Brtrue_S:
        case OperationCode.Leave_S:
          this.generator.Emit(ILGenerator.LongVersionOf(op.OperationCode),
            this.offset2Label[(uint)op.Value]);
          break;
        case OperationCode.Switch:
          uint[] offsets = op.Value as uint[];
          ILGeneratorLabel[] labels = new ILGeneratorLabel[offsets.Length];
          for (int j = 0, n = offsets.Length; j < n; j++) {
            labels[j] = offset2Label[offsets[j]];
          }
          this.generator.Emit(OperationCode.Switch, labels);
          break;
        default:
          throw new Exception("Only branches should be handled here");
      }
    }
Пример #43
0
 internal TryBody(ILGeneratorLabel start)
 {
     this.start = start;
 }