public LocaVariableSymbolCollectionTreeNode( InstructionBlock block )
     : base( TreeViewImage.Folder, null )
 {
     this.block = block;
     this.Text = "Symbols";
     this.EnableLatePopulate();
 }
 private static InstructionBlock[] AddBlock(InstructionBlock block, InstructionBlock[] blocks)
 {
     InstructionBlock[] destinationArray = new InstructionBlock[blocks.Length + 1];
     Array.Copy(blocks, destinationArray, blocks.Length);
     destinationArray[destinationArray.Length - 1] = block;
     return destinationArray;
 }
        /// <summary>
        /// Weaves the specified context.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="block">The block.</param>
        public void Weave(WeavingContext context, InstructionBlock block)
        {
            LocalVariableSymbol parameters = block.DefineLocalVariable(context.Method.Module.FindType(typeof(ParameterDictionary), BindingOptions.Default), NameGenerator.Generate("parameters"));

            InstructionSequence entrySequence = context.Method.MethodBody.CreateInstructionSequence();
            block.AddInstructionSequence(entrySequence, NodePosition.Before, null);

            InstructionWriter writer = context.InstructionWriter;
            writer.AttachInstructionSequence(entrySequence);
            writer.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden);

            writer.EmitInstructionMethod(OpCodeNumber.Call, context.Method.Module.FindMethod(typeof(InternalHelperMethods).GetMethod("CreateParameterCollection"), BindingOptions.Default));

            IMethod add = context.Method.Module.FindMethod(typeof(ParameterDictionary).GetMethod("Add", new[] { typeof(string), typeof(object) }), BindingOptions.Default);

            short parameterIndex = context.Method.IsStatic ? (short)0 : (short)1;
            foreach (var parameter in method.Parameters)
            {
                writer.EmitInstruction(OpCodeNumber.Dup);

                writer.EmitInstructionString(OpCodeNumber.Ldstr, new LiteralString(parameter.Name));
                writer.EmitInstructionInt16(OpCodeNumber.Ldarg, parameterIndex++);

                if (parameter.ParameterType.GetSystemType(null, null).IsValueType)
                {
                    writer.EmitInstructionType(OpCodeNumber.Box, parameter.ParameterType);
                }

                writer.EmitInstructionMethod(OpCodeNumber.Callvirt, add);
            }

            writer.EmitInstructionLocalVariable(OpCodeNumber.Stloc, parameters);

            writer.DetachInstructionSequence();
        }
        public void Weave(WeavingContext context, InstructionBlock block)
        {
            InstructionSequence nextSequence = null;
            InstructionSequence sequence = null;

            sequence = context.Method.MethodBody.CreateInstructionSequence();
            block.AddInstructionSequence(sequence, NodePosition.Before, null);
            context.InstructionWriter.AttachInstructionSequence(sequence);

            context.InstructionWriter.EmitInstructionParameter(OpCodeNumber.Ldarg, this.paramDef);
            context.InstructionWriter.EmitInstructionType(OpCodeNumber.Box, this.paramDef.ParameterType);
            context.InstructionWriter.EmitInstruction(OpCodeNumber.Ldnull);
            context.InstructionWriter.EmitInstruction(OpCodeNumber.Ceq);

            nextSequence = context.Method.MethodBody.CreateInstructionSequence();

            context.InstructionWriter.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, nextSequence);
            context.InstructionWriter.EmitInstructionString(OpCodeNumber.Ldstr, this.paramDef.Name);
            context.InstructionWriter.EmitInstructionMethod(OpCodeNumber.Newobj,
                                                            context.Method.Module.FindMethod(
                                                                typeof (ArgumentNullException).GetConstructor(
                                                                    new[] {typeof (string)}),
                                                                BindingOptions.Default));
            context.InstructionWriter.EmitInstruction(OpCodeNumber.Throw);

            context.InstructionWriter.DetachInstructionSequence();
            block.AddInstructionSequence(nextSequence, NodePosition.After, sequence);
            sequence = nextSequence;
            context.InstructionWriter.AttachInstructionSequence(sequence);

            context.InstructionWriter.DetachInstructionSequence();
        }
        public void Weave(WeavingContext context, InstructionBlock block)
        {
            InstructionSequence sequence = context.Method.MethodBody.CreateInstructionSequence();
            block.AddInstructionSequence(sequence, NodePosition.After, null);
            InstructionWriter writer = context.InstructionWriter;
            writer.AttachInstructionSequence(sequence);

            context.InstructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, context.ReturnValueVariable);
            context.InstructionWriter.EmitInstructionType(OpCodeNumber.Box,
                                                          context.ReturnValueVariable.LocalVariable.Type);
            context.InstructionWriter.EmitInstruction(OpCodeNumber.Ldnull);
            context.InstructionWriter.EmitInstruction(OpCodeNumber.Ceq);

            InstructionSequence nextSequence = context.Method.MethodBody.CreateInstructionSequence();

            context.InstructionWriter.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, nextSequence);
            context.InstructionWriter.EmitInstructionString(OpCodeNumber.Ldstr, "return value is null");
            context.InstructionWriter.EmitInstructionMethod(OpCodeNumber.Newobj,
                                                            context.Method.Module.FindMethod(
                                                                typeof (ArgumentNullException).GetConstructor(new[]
                                                                                                                  {
                                                                                                                      typeof
                                                                                                                          (
                                                                                                                          string
                                                                                                                          )
                                                                                                                  }),
                                                                BindingOptions.Default));
            context.InstructionWriter.EmitInstruction(OpCodeNumber.Throw);

            block.AddInstructionSequence(nextSequence, NodePosition.After, sequence);

            writer.DetachInstructionSequence();
        }
        /// <summary>
        /// Checks whether <paramref name="theBlock"/> is a do-finally-check block.
        /// </summary>
        /// <remarks>
        /// Pattern:
        /// (nop) - sequence of nop blocks
        /// ldloc* doFinallyVariable
        /// brfalse* - branch to endfinally - this check varies between compilers
        /// original handler:
        /// ...............
        /// </remarks>
        /// <param name="theBlock"></param>
        /// <returns></returns>
        protected override bool IsFinallyCheckBlock(InstructionBlock theBlock)
        {
            Instruction currentInstruction = theBlock.First;
            while (currentInstruction.OpCode.Code == Code.Nop)
            {
                if (currentInstruction == theBlock.Last)
                {
                    return false;
                }
                currentInstruction = currentInstruction.Next;
            }

            VariableReference loadedVariable;
            if (currentInstruction == theBlock.Last ||
                !StateMachineUtilities.TryGetVariableFromInstruction(currentInstruction, methodVariables, out loadedVariable) ||
                loadedVariable != doFinallyVariable)
            {
                return false;
            }
            currentInstruction = currentInstruction.Next;

            if (currentInstruction.OpCode.Code == Code.Brfalse || currentInstruction.OpCode.Code == Code.Brfalse_S)
            {
                return true;
            }

            return IsCSharpDebugCheck(theBlock, currentInstruction) || IsVisualBasicDebugCheck(theBlock, currentInstruction);
        }
Ejemplo n.º 7
0
 public ControlFlowGraph(Mono.Cecil.Cil.MethodBody body, InstructionBlock[] blocks, Dictionary<int, InstructionData> instructionData, List<ExceptionHandlerData> exception_data, HashSet<int> exception_objects_offsets)
 {
     this.body = body;
     this.blocks = blocks;
     this.data = instructionData;
     this.exception_data = exception_data;
     this.exception_objects_offsets = exception_objects_offsets;
 }
 protected override void ImplementOnEntry(InstructionBlock block, InstructionWriter writer)
 {
     foreach (var implementation in GetOnEntryImplementations()) {
         using (var factory = implementation.CreateExport()) {
             var instance = factory.Value;
             instance.Initialize(Context);
             instance.ImplementOnEntry(block, writer);
         }
     }
 }
 public SwitchData(InstructionBlock switchBlock, InstructionBlock defaultCase, IList<InstructionBlock> orderedCases)
 {
     SwitchBlock = switchBlock;
     DefaultCase = defaultCase;
     OrderedCasesArray = new InstructionBlock[orderedCases.Count];
     for (int i = 0; i < orderedCases.Count; i++)
     {
         OrderedCasesArray[i] = orderedCases[i];
     }
 }
        public InstructionBlockTreeNode( InstructionBlock block, string name )
            : base( TreeViewImage.Namespace, block )
        {
            this.Text = name + " " + block.ToString();
            this.block = block;

            if ( this.block.HasChildrenBlocks || this.block.HasExceptionHandlers || this.block.HasLocalVariableSymbols )
            {
                this.EnableLatePopulate();
            }
        }
Ejemplo n.º 11
0
 public static void MarkBlocksDeadIfNeeded(InstructionBlock[] instructionBlocks)
 {
     if (Enumerable.Count<InstructionBlock>(instructionBlocks) != 1)
     {
         foreach (InstructionBlock block in instructionBlocks)
         {
             block.MarkIsDead();
         }
         instructionBlocks[0].MarkIsAliveRecursive();
     }
 }
        public void Weave(WeavingContext context, InstructionBlock block)
        {
            InstructionSequence sequence = null;

            sequence = context.Method.MethodBody.CreateInstructionSequence();
            block.AddInstructionSequence(sequence, NodePosition.After, null);
            context.InstructionWriter.AttachInstructionSequence(sequence);

            context.InstructionWriter.EmitInstructionMethod(OpCodeNumber.Call, context.Method.Module.FindMethod(m_type.Methods.GetOneByName("get_Instance").GetReflectionWrapper(new Type[]{},new Type[]{}),BindingOptions.Default));
            context.InstructionWriter.DetachInstructionSequence();
        }
 public ControlFlowGraph(
     MethodBody body, 
     InstructionBlock[] blocks, 
     Dictionary<int, InstructionBlock> instructiontoBlockMapping,
     Dictionary<InstructionBlock, SwitchData> switchBlocksInformation, 
     Dictionary<int, Instruction> offsetToInstruction)
 {
     this.MethodBody = body;
     this.Blocks = blocks;
     this.InstructionToBlockMapping = instructiontoBlockMapping;
     this.SwitchBlocksInformation = switchBlocksInformation;
     this.OffsetToInstruction = offsetToInstruction;
 }
        public static void AddPropertyGuard(PropertyDeclaration property, MethodBodyTransformationContext context, InstructionBlock block, InstructionWriter writer)
        {
            var propertyType = property.PropertyType;
            var methodBody = block.MethodBody;

            var sequence = block.AddInstructionSequence(null, NodePosition.After, null);
            if (sequence == null) return;

            var oldValueVariable =
                block.DefineLocalVariable(propertyType, string.Format("old{0}Value", property.Name));
            var assets = GetTransformationAssets(property.Module);

            writer.AttachInstructionSequence(sequence);
            var isLocationBinding = CheckIfIsLocationBinding(methodBody,assets);
            if (isLocationBinding) {
                writer.AssignValue_LocalVariable(oldValueVariable
                    , () => writer.Call_MethodOnTarget(property.GetGetter()
                        ,
                        () => {
                            //Load the instance parameter of the SetValue method
                            //and convert it to the type
                            writer.EmitInstruction(OpCodeNumber.Ldarg_1);
                            //writer.EmitInstructionLoadIndirect(Assets.ObjectTypeSignature);
                            writer.EmitInstructionType(OpCodeNumber.Ldobj, assets.ObjectTypeSignature);
                            writer.EmitConvertFromObject(property.Parent);
                        }
                    )
                );
                //On the location binding the value parameter is at psotion 3
                writer.EmitInstruction(OpCodeNumber.Ldarg_3);
            } else {
                writer.AssignValue_LocalVariable(oldValueVariable,
                                                    () => writer.Get_PropertyValue(property));
                //For a normal property the value parameter is at position 1
                writer.EmitInstruction(OpCodeNumber.Ldarg_1);
            }
            if (propertyType.IsStruct()) {
                writer.EmitInstructionType(OpCodeNumber.Box, propertyType);
            }
            writer.Box_LocalVariableIfNeeded(oldValueVariable);
            var isPrimitive = propertyType.IsPrimitive();
            if (isPrimitive) {
                writer.Compare_Primitives();
            } else {
                //TODO: Try and use the equality operator when present
                writer.Compare_Objects(assets.ObjectEqualsMethod);
            }
            //writer.Leave_IfTrue(_context.LeaveBranchTarget);
            writer.Leave_IfTrue(context.LeaveBranchTarget);
            writer.DetachInstructionSequence();
        }
Ejemplo n.º 15
0
        public void Weave(WeavingContext context, InstructionBlock block)
        {
            InstructionSequence entrySequence = context.Method.MethodBody.CreateInstructionSequence();
            block.AddInstructionSequence(entrySequence, NodePosition.Before, null);

            InstructionWriter writer = context.InstructionWriter;

            writer.AttachInstructionSequence(entrySequence);
            writer.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden);

            Weave(context, writer);

            writer.DetachInstructionSequence();
        }
Ejemplo n.º 16
0
        public void Weave( WeavingContext context, InstructionBlock block )
        {
            switch ( context.JoinPoint.JoinPointKind )
            {
                case JoinPointKinds.BeforeMethodBody:
                    this.WeaveEntry( context, block );
                    break;

                case JoinPointKinds.AfterMethodBodySuccess:
                    this.WeaveExit( context, block );
                    break;

                default:
                    throw new ArgumentException(string.Format( "Unexpected join point kind: {0}", context.JoinPoint.JoinPointKind ) );
            }
        }
Ejemplo n.º 17
0
        void ProcessBlock(InstructionBlock block)
        {
            if (WasProcessed(block))
            {
                return;
            }

            var previous_block = current_block;

            current_block = block;

            MarkProcessed(block);

            ProcessInstructions(block);

            current_block = previous_block;
        }
        /// <summary>
        /// Checks whether the specified block contains assignment of the state variable.
        /// </summary>
        /// <param name="theBlock"></param>
        /// <returns></returns>
        private bool ContainsStateVariableSet(InstructionBlock theBlock)
        {
            VariableReference varReference;
            Instruction       currentInstruction = theBlock.First;

            while (currentInstruction != theBlock.Last)
            {
                if (IsStloc(currentInstruction) && TryGetVariableFromInstruction(currentInstruction, out varReference) && varReference == this.stateVariable)
                {
                    return(true);
                }

                currentInstruction = currentInstruction.Next;
            }

            return(false);
        }
        public void Weave(WeavingContext context, InstructionBlock block)
        {
            InstructionSequence nextSequence = null;
            InstructionSequence sequence = null;

            sequence = context.Method.MethodBody.CreateInstructionSequence();
            block.AddInstructionSequence(sequence, NodePosition.Before, null);
            context.InstructionWriter.AttachInstructionSequence(sequence);

            IMethod isNullOrEmpty = context.Method.Module.FindMethod(typeof (string).GetMethod("IsNullOrEmpty"),
                                                                     BindingOptions.Default);

            // Checks if not empty

            context.InstructionWriter.EmitInstructionParameter(OpCodeNumber.Ldarg, paramDef);
            context.InstructionWriter.EmitInstructionMethod(OpCodeNumber.Call, isNullOrEmpty);

            nextSequence = context.Method.MethodBody.CreateInstructionSequence();

            context.InstructionWriter.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, nextSequence);
            context.InstructionWriter.EmitInstructionString(OpCodeNumber.Ldstr, "Parameter is null or empty.");
            context.InstructionWriter.EmitInstructionString(OpCodeNumber.Ldstr, this.paramDef.Name);
            context.InstructionWriter.EmitInstructionMethod(OpCodeNumber.Newobj,
                                                            context.Method.Module.FindMethod(
                                                                typeof (ArgumentException).GetConstructor(new[]
                                                                                                              {
                                                                                                                  typeof
                                                                                                                      (
                                                                                                                      string
                                                                                                                      ),
                                                                                                                  typeof
                                                                                                                      (
                                                                                                                      string
                                                                                                                      )
                                                                                                              }),
                                                                BindingOptions.Default));
            context.InstructionWriter.EmitInstruction(OpCodeNumber.Throw);

            context.InstructionWriter.DetachInstructionSequence();
            block.AddInstructionSequence(nextSequence, NodePosition.After, sequence);
            sequence = nextSequence;
            context.InstructionWriter.AttachInstructionSequence(sequence);

            context.InstructionWriter.DetachInstructionSequence();
        }
        /// <summary>
        /// Performs stack analysis on single block.
        /// </summary>
        /// <param name="block">The block to be analysed.</param>
        private void ComputeStackUsage(InstructionBlock block)
        {
            List <int> currentStack = new List <int>(blockToInitialStackMap[block.Index]);

            /// Analyse the stack usage for each instruction.
            foreach (Instruction instruction in block)
            {
                if (instruction.OpCode.Code == Code.Dup)
                {
                    if (currentStack.Count == 0)
                    {
                        throw new Exception("Invalid evaluation stack");
                    }
                    currentStack.Add(currentStack[currentStack.Count - 1]);
                    continue;
                }

                uint popDelta  = GetPopDelta((uint)currentStack.Count, instruction);
                uint pushDelta = GetPushDelta(instruction);

                List <int> instructionPopStack = new List <int>();
                for (int i = 0; i < popDelta; i++)
                {
                    int last = currentStack.Count - 1;
                    instructionPopStack.Add(currentStack[last]);
                    currentStack.RemoveAt(last);
                }

                if (pushDelta > 0)
                {
                    stackVariableInstructionsSet.Add(instruction.Offset);
                }

                /// Push entries on the evaluation stack as they will be pushed by the instruction.
                for (int i = 0; i < pushDelta; i++)
                {
                    currentStack.Add(instruction.Offset);
                }

                /// Update the records for the instruction.
                instructionOffsetToUsedInstructionsMap[instruction.Offset] = new Stack <int>(instructionPopStack);
            }

            blockToExitStackMap[block.Index] = currentStack.ToArray();
        }
        void GetReachableBlocks(IEnumerable <InstructionBlock> startBlocks)
        {
            reachableBlocks.UnionWith(startBlocks);
            Queue <InstructionBlock> traversalQueue = new Queue <InstructionBlock>(startBlocks);

            while (traversalQueue.Count > 0)
            {
                InstructionBlock currentBlock = traversalQueue.Dequeue();

                foreach (InstructionBlock successor in currentBlock.Successors)
                {
                    if (reachableBlocks.Add(successor))
                    {
                        traversalQueue.Enqueue(successor);
                    }
                }
            }
        }
Ejemplo n.º 22
0
        /// <summary>
        /// Gets the first control flow block that is not marked for removal.
        /// </summary>
        /// <remarks>
        /// The search for the first block follows the control flow. This method is used only when creating fake switch data, which means
        /// that there are no controller blocks in the method. This means that only some simple blocks should have been marked for removal
        /// (e.g. nop blocks, unconditional branch blocks). That's why we presume that there will be no branches during the search, which means
        /// that a simple while will suffice for the algorithm.
        /// If we reach a block that is marked for removal but has more than one successor then the method fails (returns false).
        /// </remarks>
        /// <param name="methodEntry"></param>
        /// <returns></returns>
        private bool GetMethodEntry(out InstructionBlock methodEntry)
        {
            InstructionBlock current = theCFG.Blocks[0];

            while (toBeRemoved.Contains(current))
            {
                if (current.Successors.Length != 1)
                {
                    methodEntry = null;
                    return(false);
                }

                current = current.Successors[0];
            }

            methodEntry = current;
            return(true);
        }
Ejemplo n.º 23
0
        void MoveStatementsToBlock(InstructionBlock start, InstructionBlock limit, BlockStatement block)
        {
            for (int i = start.Index; i < limit.Index; i++)
            {
                ProcessBlock(cfg.Blocks [i]);

                var list = this.statements [i];

                if (list == null)
                {
                    continue;
                }

                AddRangeToBlock(block, list);

                list.Clear();
            }
        }
 private void ReattachDefaultSuccessor(InstructionBlock initialBlock, InstructionBlock currentBlock)
 {
     if (InstructionBlock.op_Inequality(initialBlock, currentBlock))
     {
         this.RedirectNonControllerPredecessors(initialBlock, currentBlock);
         this.SwapCFGBlocks(initialBlock.get_Index(), currentBlock.get_Index());
         V_0 = 0;
         while (V_0 < (int)this.stateToStartBlock.Length)
         {
             if (InstructionBlock.op_Equality(this.stateToStartBlock[V_0], initialBlock))
             {
                 this.stateToStartBlock[V_0] = currentBlock;
             }
             V_0 = V_0 + 1;
         }
     }
     return;
 }
        private void UpdateCurrentStackVariables(InstructionBlock parent, InstructionBlock successor)
        {
            int[] parentExitStack     = blockToExitStackMap[parent.Index];
            int[] successorEntryStack = blockToInitialStackMap[successor.Index];

            if (parentExitStack.Length != successorEntryStack.Length)
            {
                /// This coveres the case, when single block can be entered with stacks of different size.
                /// As this is not allowed by standarts, an exception is thrown.
                /// No real code has been seen, that has this behavior. Only test that reproduces it is written by hand.
                throw new ArgumentException("Two paths with different stack states encountered.");
            }

            for (int i = 0; i < parentExitStack.Length; i++)
            {
                unionFinder.Union(successorEntryStack[i], parentExitStack[i]);
            }
        }
        bool TryProcessBreak(InstructionBlock block)
        {
            var data = PeekLoopData();

            if (data == null)
            {
                return(false);
            }

            if (block.Successors [0].Index == data.Body.End.Index)
            {
                store.RemoveAttotation(block.Last, Annotation.Skip);
                Annotate(block.Last, Annotation.Break);
                return(true);
            }

            return(false);
        }
        protected bool IsConditionExpression(InstructionBlock block)
        {
            var last = block.Last;

            if (!IsConditionalBranch(last))
            {
                return(false);
            }

            var child = GetFirstCommonChild(block.Successors [0], block.Successors [1]);

            if (child == null)
            {
                return(false);
            }

            return(GetStackBefore(child.First) > 0);
        }
 private bool CheckForIsCompletedCall(InstructionBlock theBlock)
 {
     V_0 = theBlock.get_First();
     while ((object)V_0 != (object)theBlock.get_Last())
     {
         if (V_0.get_OpCode().get_Code() == 39 || V_0.get_OpCode().get_Code() == 110 && String.op_Equality(((MethodReference)V_0.get_Operand()).get_Name(), "get_IsCompleted"))
         {
             if (!StateMachineUtilities.TryGetVariableFromInstruction(V_0.get_Previous(), this.moveNextMethodContext.get_Body().get_Variables(), out V_2))
             {
                 return(false);
             }
             dummyVar0 = this.awaiterVariables.Add(V_2);
             return(true);
         }
         V_0 = V_0.get_Next();
     }
     return(false);
 }
 private bool BFSRemoveBlocks()
 {
     V_0 = new Queue <InstructionBlock>();
     V_1 = this.toBeRemoved.GetEnumerator();
     try
     {
         while (V_1.MoveNext())
         {
             V_2 = V_1.get_Current();
             if (V_2.get_Predecessors().get_Count() != 0)
             {
                 continue;
             }
             V_0.Enqueue(V_2);
         }
     }
     finally
     {
         ((IDisposable)V_1).Dispose();
     }
     while (V_0.get_Count() > 0)
     {
         V_3 = V_0.Dequeue();
         if (V_3.get_Index() == -1)
         {
             continue;
         }
         stackVariable22 = V_3.get_Successors();
         this.theCFG.RemoveBlockAt(V_3.get_Index());
         V_4 = stackVariable22;
         V_5 = 0;
         while (V_5 < (int)V_4.Length)
         {
             V_6 = V_4[V_5];
             if (V_6.get_Predecessors().get_Count() == 0 && InstructionBlock.op_Inequality(V_6, this.newEntryBlock))
             {
                 V_0.Enqueue(V_6);
             }
             V_5 = V_5 + 1;
         }
         dummyVar0 = this.toBeRemoved.Remove(V_3);
     }
     return(this.toBeRemoved.get_Count() == 0);
 }
Ejemplo n.º 30
0
        public void TestWrongDeclaration()
        {
            var v = new Variable(new Range(new StringLocation(0), new StringLocation(1)), "f");

            var x = new VariableDeclaration(
                new Range(new StringLocation(0), new StringLocation(1)),
                IntType.Instance,
                "f",
                null);

            var fc = new FunctionCall(
                new Range(new StringLocation(0), new StringLocation(1)),
                "f",
                new List <Expression>());

            var instructionBlock = new InstructionBlock(
                new Range(new StringLocation(0), new StringLocation(1)),
                new List <Expression> {
                v, x, fc
            });
            var f = new FunctionDeclaration(
                new Range(new StringLocation(0), new StringLocation(1)),
                "f",
                UnitType.Instance,
                new List <VariableDeclaration>(),
                instructionBlock,
                false);

            var diagnosticsMock = new Moq.Mock <IDiagnostics>();
            var diagnostics     = diagnosticsMock.Object;

            var functions = new List <FunctionDeclaration> {
                f
            };
            var root = new Program(
                new Range(new StringLocation(0), new StringLocation(1)),
                new List <StructDeclaration>(),
                functions);

            Assert.ThrowsException <NameResolverException>(() => this.nameResolver.Run(root, diagnostics));
            MockDiagnostics.Verify(
                diagnosticsMock,
                NameResolver.IdentifierNotFoundDiagnostic);
        }
        public void Weave(WeavingContext context, InstructionBlock block)
        {
            IList<ParameterDeclaration> args = new List<ParameterDeclaration>();
            foreach(ParameterDeclaration p in context.Method.Parameters)
            {
                foreach (CustomAttributeDeclaration c in p.CustomAttributes)
                {
                    object obj = c.ConstructRuntimeObject();
                    if (obj is NonNullAttribute)
                    {
                        args.Add(p);
                    }
                }
            }

            InstructionSequence nextSequence = null;
            InstructionSequence sequence = null;

            sequence = context.Method.MethodBody.CreateInstructionSequence();
            block.AddInstructionSequence(sequence, NodePosition.Before, null);
            context.InstructionWriter.AttachInstructionSequence(sequence);

            foreach (ParameterDeclaration p in args)
            {
                context.InstructionWriter.EmitInstructionParameter(OpCodeNumber.Ldarg, p);
                context.InstructionWriter.EmitInstructionType(OpCodeNumber.Box, p.ParameterType);
                context.InstructionWriter.EmitInstruction(OpCodeNumber.Ldnull);
                context.InstructionWriter.EmitInstruction(OpCodeNumber.Ceq);

                nextSequence = context.Method.MethodBody.CreateInstructionSequence();

                context.InstructionWriter.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, nextSequence);
                context.InstructionWriter.EmitInstructionString(OpCodeNumber.Ldstr, (LiteralString)p.Name);
                context.InstructionWriter.EmitInstructionMethod(OpCodeNumber.Newobj, context.Method.Module.FindMethod(typeof(ArgumentNullException).GetConstructor(new Type[] { typeof(string) }), BindingOptions.Default));
                context.InstructionWriter.EmitInstruction(OpCodeNumber.Throw);

                context.InstructionWriter.DetachInstructionSequence();
                block.AddInstructionSequence(nextSequence, NodePosition.After, sequence);
                sequence = nextSequence;
                context.InstructionWriter.AttachInstructionSequence(sequence);
            }

            context.InstructionWriter.DetachInstructionSequence();
        }
Ejemplo n.º 32
0
        /// <summary>
        /// Checks whether the specified block is a dummy controller block.
        /// </summary>
        /// <remarks>
        /// This block looks like a state controller block with the difference that it ends with two pop instructions.
        /// Generated by the C# compiler in release mode.
        /// Update: With C# 6.0 the structure of the dummy state controller blocks has changed. The new one is load
        /// of the state variable, followed by pop and nop instructions.
        /// </remarks>
        /// <param name="theBlock"></param>
        /// <returns></returns>
        private bool IsDummyStateControllerBlock(InstructionBlock theBlock)
        {
            if (this.version == AsyncStateMachineVersion.V1)
            {
                if (!ContainsStateFieldLoad(theBlock))
                {
                    return(false);
                }

                Instruction currentInstruction = theBlock.Last;
                for (int i = 0; i < 2; i++)
                {
                    if (currentInstruction == theBlock.First || currentInstruction.OpCode.Code != Code.Pop)
                    {
                        return(false);
                    }
                    currentInstruction = currentInstruction.Previous;
                }

                toBeRemoved.Add(theBlock);
                return(true);
            }
            else
            {
                Instruction       current = theBlock.First;
                VariableReference variable;
                if (!TryGetVariableFromInstruction(current, out variable) || variable != stateVariable)
                {
                    return(false);
                }

                if (current.Next.OpCode.Code != Code.Pop || current.Next.Next.OpCode.Code != Code.Nop)
                {
                    return(false);
                }

                if (current.Next.Next != theBlock.Last)
                {
                    return(false);
                }

                return(true);
            }
        }
Ejemplo n.º 33
0
        public void TestUnapplication()
        {
            var names = new List <string> {
                "a"
            };
            var functions      = new List <FunctionDeclaration>();
            var unapplications = new List <UnApplication>();

            foreach (var id in names)
            {
                var unapplication = new UnApplication(
                    new Range(new StringLocation(0), new StringLocation(1)),
                    "a");
                var body = new InstructionBlock(
                    new Range(new StringLocation(0), new StringLocation(1)),
                    new List <Expression> {
                    unapplication
                });
                var fun = new FunctionDeclaration(
                    new Range(new StringLocation(0), new StringLocation(1)),
                    id,
                    UnitType.Instance,
                    new List <VariableDeclaration>(),
                    body,
                    false);
                unapplications.Add(unapplication);
                functions.Add(fun);
            }

            var root = new Program(
                new Range(new StringLocation(0), new StringLocation(1)),
                new List <StructDeclaration>(),
                functions);
            var resolver = new NameResolver();

            resolver.Run(root, null);
            var aDeclaration = functions[0];
            var expected     = new List <FunctionDeclaration> {
                aDeclaration
            };

            CollectionAssert.AreEqual(expected, unapplications[0].Candidates.ToList());
        }
Ejemplo n.º 34
0
        private void ReplaceOperator(TypeDefDeclaration enhancedType, MethodDefDeclaration equalityMethodDef,
                                     bool negate)
        {
            InstructionBlock originalCode = equalityMethodDef.MethodBody.RootInstructionBlock;

            originalCode.Detach();

            InstructionBlock root = equalityMethodDef.MethodBody.CreateInstructionBlock();

            equalityMethodDef.MethodBody.RootInstructionBlock = root;
            var newSequence = root.AddInstructionSequence();

            using (var writer = InstructionWriter.GetInstance())
            {
                writer.AttachInstructionSequence(newSequence);

                if (enhancedType.IsValueType())
                {
                    var canonicalType = enhancedType.GetCanonicalGenericInstance();
                    writer.EmitInstruction(OpCodeNumber.Ldarg_0);
                    writer.EmitInstructionType(OpCodeNumber.Box, canonicalType);
                    writer.EmitInstruction(OpCodeNumber.Ldarg_1);
                    writer.EmitInstructionType(OpCodeNumber.Box, canonicalType);
                }
                else
                {
                    writer.EmitInstruction(OpCodeNumber.Ldarg_0);
                    writer.EmitInstruction(OpCodeNumber.Ldarg_1);
                }

                writer.EmitInstructionMethod(OpCodeNumber.Call, this.staticEqualsMethod);

                if (negate)
                {
                    writer.EmitInstruction(OpCodeNumber.Ldc_I4_0);
                    writer.EmitInstruction(OpCodeNumber.Ceq);
                }

                writer.EmitInstruction(OpCodeNumber.Ret);

                writer.DetachInstructionSequence();
            }
        }
        /// <summary>
        /// Checks whether the specified block is a disposing-check block.
        /// </summary>
        /// <remarks>
        /// Pattern:
        /// ldarg.0
        /// ldfld disposingField
        /// ..........
        /// conditional branch
        /// </remarks>
        /// <param name="theBlock"></param>
        /// <returns></returns>
        private bool IsDisposingBlock(InstructionBlock theBlock)
        {
            Instruction currentInstruction = theBlock.First;
            if (currentInstruction.OpCode.Code != Code.Ldarg_0 || currentInstruction == theBlock.Last)
            {
                return false;
            }

            currentInstruction = currentInstruction.Next;
            if (currentInstruction.OpCode.Code != Code.Ldfld || ((FieldReference)currentInstruction.Operand).Resolve() != disposingField ||
                currentInstruction == theBlock.Last)
            {
                return false;
            }

            Instruction lastInstruction = theBlock.Last;
            return lastInstruction.OpCode.Code == Code.Brfalse || lastInstruction.OpCode.Code == Code.Brfalse_S ||
                lastInstruction.OpCode.Code == Code.Brtrue || lastInstruction.OpCode.Code == Code.Brtrue_S;
        }
 protected override bool IsFinallyCheckBlock(InstructionBlock finallyEntry)
 {
     V_0 = finallyEntry.get_First();
     if (!StateMachineUtilities.TryGetVariableFromInstruction(V_0, this.methodVariables, out V_1) || (object)V_1 != (object)this.stateVariable)
     {
         return(false);
     }
     V_0 = V_0.get_Next();
     if (V_0.get_OpCode().get_Code() != 22)
     {
         return(false);
     }
     V_0 = V_0.get_Next();
     if (V_0.get_OpCode().get_Code() != 59 && V_0.get_OpCode().get_Code() != 46)
     {
         return(false);
     }
     return(true);
 }
Ejemplo n.º 37
0
        public BooleanExpressionCoder Or <T>(T[] collection, Func <BooleanExpressionCoder, T, int, object> code)
        {
            if (collection == null || collection.Length == 0)
            {
                return(this);
            }

            code(this, collection[0], 0);
            InstructionBlock.CastOrBoxValues(this.instructions, BuilderTypes.Boolean);

            for (int i = 1; i < collection.Length; i++)
            {
                code(this, collection[i], i);
                InstructionBlock.CastOrBoxValues(this.instructions, BuilderTypes.Boolean);
                this.instructions.Emit(OpCodes.Or);
            }

            return(this);
        }
Ejemplo n.º 38
0
        /// <summary>
        /// Process each CFG block to determine which cases lead to try/finally construct.
        /// </summary>
        private void DetermineExceptionHandlingStatesFromCFGBlocks()
        {
            foreach (InstructionBlock block in theDisposeCFG.Blocks)
            {
                int state;
                if ((!IsBeqInstruction(block.Last) && !IsBneUnInstruction(block.Last)) ||
                    !StateMachineUtilities.TryGetOperandOfLdc(block.Last.Previous, out state))
                {
                    continue;
                }

                Instruction branchTargetInstruction = null;
                if (IsBeqInstruction(block.Last))
                {
                    branchTargetInstruction = block.Last.Operand as Instruction;
                }
                else // bne.un*
                {
                    branchTargetInstruction = block.Last.Next as Instruction;
                }

                if (branchTargetInstruction == null)
                {
                    throw new Exception("branchTargetInstruction cannot be null.");
                }

                InstructionBlock targetBlock = SkipSingleNopInstructionBlock(theDisposeCFG.InstructionToBlockMapping[branchTargetInstruction.Offset]);
                ExceptionHandler theHandler;
                if (!TryGetExceptionHandler(targetBlock, out theHandler))
                {
                    continue;
                }

                //We've found an exception handler.

                if (!this.handlerToStatesMap.ContainsKey(theHandler))
                {
                    this.handlerToStatesMap.Add(theHandler, new HashSet <int>());
                }

                this.handlerToStatesMap[theHandler].Add(state);
            }
        }
Ejemplo n.º 39
0
        /// <summary>
        /// Checks whether the specified block contains a call of the get_IsCompleted method.
        /// </summary>
        /// <remarks>
        /// Saves the target variable of the call.
        /// </remarks>
        /// <param name="theBlock"></param>
        /// <returns></returns>
        private bool CheckForIsCompletedCall(InstructionBlock theBlock)
        {
            for (Instruction current = theBlock.First; current != theBlock.Last; current = current.Next)
            {
                if ((current.OpCode.Code == Code.Call || current.OpCode.Code == Code.Callvirt) &&
                    ((MethodReference)current.Operand).Name == "get_IsCompleted")
                {
                    VariableReference awaiterVariable;
                    if (StateMachineUtilities.TryGetVariableFromInstruction(current.Previous, moveNextMethodContext.Body.Variables, out awaiterVariable))
                    {
                        awaiterVariables.Add(awaiterVariable);
                        return(true);
                    }
                    return(false);
                }
            }

            return(false);
        }
Ejemplo n.º 40
0
        void ProcessBlock(InstructionBlock block)
        {
            switch (block.Successors.Length)
            {
            case 0:
            case 1:
                ProcessSimpleBlock(block);
                break;

            case 2:
                ProcessTwoWayBlock(block);
                break;

            default:
                throw new ArgumentException("n-way block not supported", "block");
            }

            MarkProcessed(block);
        }
Ejemplo n.º 41
0
        /// <summary>
        /// Removes the blocks that save the state and then exit the method.
        /// </summary>
        /// <remarks>
        /// We search for the state saving blocks by starting from the last block in the CFG, which should be a block that contains only the ret instruction
        /// (and some nops when compiled in debug). This block has two predecessors that are not state saving blocks: the second to last block that is used to set
        /// the result when the state machine terminates (i.e. return in the original code) and the body of the catch clause that is part of the try/catch construct
        /// that encloses the logic of the state machine. All other predecessors should be state saving blocks.
        /// We detach the final return block (and we mark it for removal) from these two block in order to avoid creating an unneeded goto from the catch block.
        /// </remarks>
        /// <returns></returns>
        private bool RemoveStateSavingBlocks()
        {
            InstructionBlock lastBlock = theCFG.Blocks[theCFG.Blocks.Length - 1];

            Instruction currentInstruction = lastBlock.First;

            while (currentInstruction.OpCode.Code == Code.Nop && currentInstruction != lastBlock.Last)
            {
                currentInstruction = currentInstruction.Next;
            }

            if (currentInstruction.OpCode.Code != Code.Ret)
            {
                return(false);
            }

            int detachedPredecessorsCount           = 0;
            HashSet <InstructionBlock> predecessors = new HashSet <InstructionBlock>(lastBlock.Predecessors);

            foreach (InstructionBlock predecessor in predecessors)
            {
                if (predecessor.Successors.Length > 1)
                {
                    return(false);
                }

                if (predecessor.Predecessors.Count == 1 && theCFG.Blocks[theCFG.Blocks.Length - 2] != predecessor)
                {
                    if (!CheckForStateFieldSet(predecessor) || !TryRemoveStateSavingBlock(predecessor))
                    {
                        return(false);
                    }
                }
                else
                {
                    predecessor.Successors = new InstructionBlock[0];
                    detachedPredecessorsCount++;
                }
            }

            toBeRemoved.Add(lastBlock);
            return(detachedPredecessorsCount == 2);
        }
Ejemplo n.º 42
0
 private bool IsDisposingBlock(InstructionBlock theBlock)
 {
     V_0 = theBlock.get_First();
     if (V_0.get_OpCode().get_Code() != 2 || (object)V_0 == (object)theBlock.get_Last())
     {
         return(false);
     }
     V_0 = V_0.get_Next();
     if (V_0.get_OpCode().get_Code() != 120 || (object)((FieldReference)V_0.get_Operand()).Resolve() != (object)this.disposingField || (object)V_0 == (object)theBlock.get_Last())
     {
         return(false);
     }
     V_1 = theBlock.get_Last();
     if (V_1.get_OpCode().get_Code() == 56 || V_1.get_OpCode().get_Code() == 43 || V_1.get_OpCode().get_Code() == 57)
     {
         return(true);
     }
     return(V_1.get_OpCode().get_Code() == 44);
 }
        private TypeDefDeclaration CreateContainingType()
        {
            string uniqueName = this.module.Types.GetUniqueName(
                DebuggerSpecialNames.GetDeclarationSpecialName("LoggingImplementationDetails{0}"));

            TypeDefDeclaration logCategoriesType = new TypeDefDeclaration
            {
                Name       = uniqueName,
                Attributes = TypeAttributes.NotPublic | TypeAttributes.Sealed | TypeAttributes.Abstract,
                BaseType   = ((IType)this.module.Cache.GetType("System.Object, mscorlib"))
            };

            this.module.Types.Add(logCategoriesType);

            // Add [CompilerGenerated] and [DebuggerNonUserCode] to the type
            this.weavingHelper.AddCompilerGeneratedAttribute(logCategoriesType.CustomAttributes);
            this.weavingHelper.AddDebuggerNonUserCodeAttribute(logCategoriesType.CustomAttributes);

            MethodDefDeclaration staticConstructor = new MethodDefDeclaration
            {
                Name       = ".cctor",
                Attributes = MethodAttributes.Private | MethodAttributes.Static | MethodAttributes.RTSpecialName |
                             MethodAttributes.SpecialName | MethodAttributes.HideBySig,
            };

            logCategoriesType.Methods.Add(staticConstructor);

            staticConstructor.ReturnParameter = new ParameterDeclaration
            {
                Attributes    = ParameterAttributes.Retval,
                ParameterType = this.module.Cache.GetIntrinsic(IntrinsicType.Void)
            };

            this.constructorBlock = staticConstructor.MethodBody.RootInstructionBlock = staticConstructor.MethodBody.CreateInstructionBlock();
            this.returnSequence   = staticConstructor.MethodBody.RootInstructionBlock.AddInstructionSequence(null, NodePosition.After, null);

            this.writer.AttachInstructionSequence(this.returnSequence);
            this.writer.EmitInstruction(OpCodeNumber.Ret);
            this.writer.DetachInstructionSequence();

            return(logCategoriesType);
        }
Ejemplo n.º 44
0
            private FunctionDeclaration FunctionDeclarationToAst(Brunch <KjuAlphabet> branch)
            {
                var              parameters = new List <VariableDeclaration>();
                string           identifier = null;
                DataType         type       = null;
                InstructionBlock body       = null;
                bool             isForeign  = false;

                foreach (var child in branch.Children)
                {
                    switch (child.Category)
                    {
                    case KjuAlphabet.FunctionParameter:
                        parameters.Add(this.FunctionParameterToAst((Brunch <KjuAlphabet>)child));
                        break;

                    case KjuAlphabet.VariableFunctionIdentifier:
                        identifier = ((Token <KjuAlphabet>)child).Text;
                        break;

                    case KjuAlphabet.TypeDeclaration:
                        type = this.TypeDeclarationAst((Brunch <KjuAlphabet>)child);
                        break;

                    case KjuAlphabet.Block:
                        body = this.BlockToAst((Brunch <KjuAlphabet>)child);
                        break;

                    case KjuAlphabet.Import:
                        isForeign = true;
                        break;
                    }
                }

                return(new FunctionDeclaration(
                           branch.InputRange,
                           identifier,
                           type,
                           parameters,
                           body,
                           isForeign));
            }
        /// <summary>
        /// The method that does the actual analysis.
        /// </summary>
        /// <param name="graphEntry">The entry point of the decompiled method.</param>
        private void AnalyzeStackUsage()
        {
            this.traversed = new bool[controlFlowGraph.Blocks.Length];

            /// This should pass through all the blocks of the method, missing only the exception handlers.
            RecursiveDfs(controlFlowGraph.Blocks[0], new int[0]);

            /// Pass through all the exception handlers.
            foreach (ExceptionHandler handler in exceptionHandlers)
            {
                InstructionBlock handlerBlock = controlFlowGraph.InstructionToBlockMapping[handler.HandlerStart.Offset];

                if (handler.HandlerType == ExceptionHandlerType.Fault || handler.HandlerType == ExceptionHandlerType.Finally)
                {
                    RecursiveDfs(handlerBlock, new int[0]);
                }
                else
                {
                    if (handler.HandlerType == ExceptionHandlerType.Filter)
                    {
                        InstructionBlock filterBlock = controlFlowGraph.InstructionToBlockMapping[handler.FilterStart.Offset];
                        RecursiveDfs(filterBlock, new int[] { -handler.FilterStart.Offset });
                        instructionOffsetToVariableDefinitionMap[-handler.FilterStart.Offset] =
                            new VariableDefinition(ExceptionVariablePrefix + exceptionVariableCount++, Utilities.GetCorlibTypeReference(typeof(Exception), methodContext.Method.Module));
                        exceptionVariableInstructionsSet.Add(-handler.FilterStart.Offset);
                    }
                    RecursiveDfs(handlerBlock, new int[] { -handler.HandlerStart.Offset });
                    instructionOffsetToVariableDefinitionMap[-handler.HandlerStart.Offset] =
                        new VariableDefinition(ExceptionVariablePrefix + exceptionVariableCount++,
                                               handler.CatchType ?? Utilities.GetCorlibTypeReference(typeof(Exception), methodContext.Method.Module));
                    exceptionVariableInstructionsSet.Add(-handler.HandlerStart.Offset);
                }
            }

            for (int i = 0; i < controlFlowGraph.Blocks.Length; i++)
            {
                if (!traversed[i])
                {
                    throw new Exception("Unreachable block found");
                }
            }
        }
        /// <summary>
        /// Creates the controller switch data using the information gathered during the traversal of the state controller blocks.
        /// </summary>
        private void CreateControllerSwitchData()
        {
            int index = GetIndexOfLastNonNullElement(stateToStartBlock);

            InstructionBlock[] finalCasesArray = new InstructionBlock[++index];
            //Trim the excess elements of the cases array.
            for (int i = 0; i < index; i++)
            {
                if (stateToStartBlock[i] == null)
                {
                    finalCasesArray[i] = defaultStateEntry;
                }
                else
                {
                    finalCasesArray[i] = stateToStartBlock[i];
                }
            }

            this.switchData = new SwitchData(null, defaultStateEntry, finalCasesArray);
        }
Ejemplo n.º 47
0
        /// <summary>
        /// Process each switch block to determine which cases lead to try/finally constructs.
        /// </summary>
        /// <param name="switchBlockInfo"></param>
        private bool DetermineExceptionHandlingStatesFromSwitchData(SwitchData switchBlockInfo)
        {
            //Since the first try/finally that this switch covers can start at state 20, the complier will optimize this by subtracting 20 from the value of
            //the state field.
            int         stateOffset        = 0;
            Instruction currentInstruction = switchBlockInfo.SwitchBlock.Last.Previous;

            if (currentInstruction.OpCode.Code == Code.Sub)
            {
                currentInstruction = currentInstruction.Previous;
                if (!StateMachineUtilities.TryGetOperandOfLdc(currentInstruction, out stateOffset))
                {
                    return(false);
                }

                currentInstruction = currentInstruction.Previous;
            }

            InstructionBlock[] orderedCases = switchBlockInfo.OrderedCasesArray;
            for (int i = 0; i < orderedCases.Length; i++)
            {
                InstructionBlock currentCase = GetActualCase(orderedCases[i]);

                ExceptionHandler theHandler;
                if (!TryGetExceptionHandler(currentCase, out theHandler))
                {
                    continue;
                }

                //We've found an exception handler.

                if (!this.handlerToStatesMap.ContainsKey(theHandler))
                {
                    this.handlerToStatesMap.Add(theHandler, new HashSet <int>());
                }

                this.handlerToStatesMap[theHandler].Add(i + stateOffset);
            }

            return(true);
        }
        /// <summary>
        /// Sets the true and false CFG successors of the construct.
        /// </summary>
        /// <param name="cfgConditionBlock"></param>
        private void SetTrueAndFalseSuccessors(CFGBlockLogicalConstruct cfgConditionBlock)
        {
            InstructionBlock block = cfgConditionBlock.TheBlock;

            //The successor at the last index is the near successor (by design). The ExpressionDecompilerStep ensures that the far successor will be
            //the true successor and the near successor will be the false successor.
            InstructionBlock trueSuccessorBlock  = block.Successors[0]; //The far successor
            InstructionBlock falseSuccessorBlock = block.Successors[1]; //The near successor

            foreach (CFGBlockLogicalConstruct cfgSuccessor in cfgConditionBlock.CFGSuccessors)
            {
                if (cfgSuccessor.TheBlock == trueSuccessorBlock)
                {
                    this.TrueCFGSuccessor = cfgSuccessor;
                }
                if (cfgSuccessor.TheBlock == falseSuccessorBlock)
                {
                    this.FalseCFGSuccessor = cfgSuccessor;
                }
            }
        }
Ejemplo n.º 49
0
        void ProcessExpressionBlock(InstructionBlock block, bool skip_first)
        {
            MarkProcessed(block);

            var current = current_block;

            current_block = block;

            foreach (var instruction in block)
            {
                if (skip_first && instruction == block.First)
                {
                    continue;
                }

                expression_decompiler.Visit(instruction);
                TryProcessExpression(instruction);
            }

            current_block = current;
        }
		private InstructionBlock FindMostDistantSuccessor(InstructionBlock currentBlock)
		{
			InstructionBlock mostDistantSuccessor = null;
			foreach (InstructionBlock successor in currentBlock.Successors)
			{
				if (mostDistantSuccessor == null)
				{
					if (successor.Index > currentBlock.Index)
					{
						mostDistantSuccessor = successor;
					}
				}
				else
				{
					if (successor.Index > mostDistantSuccessor.Index)	
					{
						mostDistantSuccessor = successor;
					}
				}
			}
			return mostDistantSuccessor;
		}
        protected override bool IsFinallyCheckBlock(InstructionBlock finallyEntry)
        {
            Instruction current = finallyEntry.First;
            VariableReference loadedVariable;
            if (!StateMachineUtilities.TryGetVariableFromInstruction(current, methodVariables, out loadedVariable) ||
                loadedVariable != this.stateVariable)
            {
                return false;
            }

            current = current.Next;
            if (current.OpCode.Code != Code.Ldc_I4_0)
            {
                return false;
            }

            current = current.Next;
            if (current.OpCode.Code != Code.Bge && current.OpCode.Code != Code.Bge_S)
            {
                return false;
            }

            return true;
        }
        private void WeaveSuccess(WeavingContext context, InstructionBlock block)
        {
            LogLevel level = this.attribute.ExitLevel;
              string text = this.attribute.ExitText;

              this.EmitCheckingAndTemplateLogging(context, block, level, text);
        }
        private void WeaveException(WeavingContext context, InstructionBlock block)
        {
            LogLevel level = this.attribute.ExceptionLevel;
              string text = this.attribute.ExceptionText;

              // Inject the logging code only if the logging is turned on.
              if (this.attribute.ExceptionLevel != LogLevel.None)
              {
            // Method being woven and the type the method is declared in.
            MethodDefDeclaration wovenMethod = context.Method;
            TypeDefDeclaration wovenType = wovenMethod.DeclaringType;

            // Objects that contain required methods, fields, etc.
            LogLevelSupportItem supportItem = this.parent.GetSupportItem(level);
            PerTypeLoggingData perTypeLoggingData = this.parent.GetPerTypeLoggingData(wovenType);

            // Get the tokens for the message template.
            StringBuilder messageFormatString = new StringBuilder();
            List<IMessageToken> nonStaticTokens = new List<IMessageToken>();
            List<IMessageToken> messageParts = TemplateParser.Tokenize(text, wovenMethod, attribute.IncludeParamName);
            MakeFormatString(messageParts, messageFormatString, nonStaticTokens);

            // As log4net does not provide an overload for the LogXXX() methods which would accept
            // both exception and array of arguments for a format string, disallow usage of dynamic
            // tokens in the template.
            if (nonStaticTokens.Count > 0)
            {
              throw new FormatException("Message for logging exception can contain only placeholders whose value can be expanded at weaving time.");
            }

            // Variable that stores the reference to the thrown exception.
            LocalVariableSymbol exception = block.DefineLocalVariable(context.Method.Module.FindType(typeof(Exception), BindingOptions.Default), "~ex~{0}");

            // Sequence that contains code that checks if the logging is enabled and logs the message.
            InstructionSequence logExceptionSequence = context.Method.MethodBody.CreateInstructionSequence();
            block.AddInstructionSequence(logExceptionSequence, NodePosition.Before, null);
            // Sequence that contains code that is executed after logging.
            InstructionSequence afterLoggingSequence = context.Method.MethodBody.CreateInstructionSequence();
            block.AddInstructionSequence(afterLoggingSequence, NodePosition.After, logExceptionSequence);

            // Emit code that checks if the logging is enabled and logs the message.
            context.InstructionWriter.AttachInstructionSequence(logExceptionSequence);
            context.InstructionWriter.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden);
            context.InstructionWriter.EmitInstructionLocalVariable(OpCodeNumber.Stloc_S, exception);
            EmitLoggingEnabledCheck(context.InstructionWriter, supportItem, perTypeLoggingData, afterLoggingSequence);
            EmitLogStringException(context.InstructionWriter, perTypeLoggingData.Log, supportItem.LogStringExceptionMethod, messageFormatString.ToString(), exception);
            context.InstructionWriter.DetachInstructionSequence();

            // After logging is finished (or skipped), rethrow the exception.
            context.InstructionWriter.AttachInstructionSequence(afterLoggingSequence);
            context.InstructionWriter.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden);
            context.InstructionWriter.EmitInstruction(OpCodeNumber.Rethrow);
            context.InstructionWriter.DetachInstructionSequence();
              }
              else
              {
            // Logging is turned off, just rethrow the exception.
            InstructionSequence rethrowSequence = context.Method.MethodBody.CreateInstructionSequence();
            block.AddInstructionSequence(rethrowSequence, NodePosition.Before, null);
            context.InstructionWriter.AttachInstructionSequence(rethrowSequence);
            context.InstructionWriter.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden);
            context.InstructionWriter.EmitInstruction(OpCodeNumber.Rethrow);
            context.InstructionWriter.DetachInstructionSequence();
              }
        }
        /// <summary>
        /// Emits the MSIL that creates local variable and initializes it with array of objects representing the specified tokens.
        /// </summary>
        /// <param name="context">Context for the weaving.</param>
        /// <param name="block">Block where the code has to be injected.</param>
        /// <param name="nonStaticTokens">List of tokens that the object array is created for.</param>
        /// <returns>Local variable that stores the reference to the array.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="context"/>, <paramref name="block"/> or <paramref name="nonStaticTokens"/> is <see langword="null"/>.</exception>
        /// <remarks>
        /// <para>Code emitted by this method makes no assumptions on the state of the evaluation stack 
        /// and it leaves the stack unmodified.</para>
        /// </remarks>
        private LocalVariableSymbol EmitCreateFormatArgumentArray(WeavingContext context, InstructionBlock block, IList<IMessageToken> nonStaticTokens)
        {
            if (context == null)
              {
            throw new ArgumentNullException("context");
              }
              if (block == null)
              {
            throw new ArgumentNullException("block");
              }
              if (nonStaticTokens == null)
              {
            throw new ArgumentNullException("nonStaticTokens");
              }

              InstructionWriter emitter = context.InstructionWriter;

              // Array that store arguments for the formatting.
              LocalVariableSymbol args = block.DefineLocalVariable(context.Method.Module.FindType(typeof(object[]), BindingOptions.Default), "~args~{0}");

              // Create the array for storing agruments for formatting (contains only dyncamic tokens).
              emitter.EmitInstructionInt32(OpCodeNumber.Ldc_I4, nonStaticTokens.Count);
              emitter.EmitInstructionType(OpCodeNumber.Newarr, this.parent.ObjectType);
              // Save the array into the local variable because it will be used multiple times.
              emitter.EmitInstructionLocalVariable(OpCodeNumber.Stloc, args);

              // Fill the array with the data.
              for (int index = 0; index < nonStaticTokens.Count; index++)
              {
            // Array to store the data in.
            emitter.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, args);
            // Position in the array to store the data at.
            emitter.EmitInstructionInt32(OpCodeNumber.Ldc_I4, index);
            // Let the token generate the IL that pushes the argument onto the stack.
            nonStaticTokens[index].Emit(context);
            // Finally: store the generated object into the array at the given position.
            emitter.EmitInstruction(OpCodeNumber.Stelem_Ref);
              }

              return args;
        }
        /// <summary>
        /// Emits the MSIL which checks if the logging is enabled and logs the message.
        /// </summary>
        /// <param name="context">Weaving context.</param>
        /// <param name="block">Block where the code has to be injected.</param>
        /// <param name="level">Level for the message.</param>
        /// <param name="template">Template that will be tokenized in order to get message text.</param>
        /// <exception cref="ArgumentNullException"><paramref name="context"/>, <paramref name="block"/> or <paramref name="template"/> is <see langword="null"/>.</exception>
        /// <exception cref="FormatException">Template is not valid.</exception>
        /// <remarks>
        /// <para>If the <paramref name="level"/> is set to <see cref="LogLevel.None"/>, the method emits no code.</para>
        /// </remarks>
        private void EmitCheckingAndTemplateLogging(WeavingContext context, InstructionBlock block, LogLevel level, string template)
        {
            if (context == null)
              {
            throw new ArgumentNullException("context");
              }
              if (block == null)
              {
            throw new ArgumentNullException("block");
              }
              if (template == null)
              {
            throw new ArgumentNullException("template");
              }

              if (level != LogLevel.None)
              {
            // Method being woven and the type the method is declared in.
            MethodDefDeclaration wovenMethod = context.Method;
            TypeDefDeclaration wovenType = wovenMethod.DeclaringType;

            // Objects that contain required methods, fields, etc.
            LogLevelSupportItem supportItem = this.parent.GetSupportItem(level);
            PerTypeLoggingData perTypeLoggingData = this.parent.GetPerTypeLoggingData(wovenType);

            // Get the tokens for the message template.
            StringBuilder messageFormatString = new StringBuilder();
            List<IMessageToken> nonStaticTokens = new List<IMessageToken>();
            List<IMessageToken> messageParts = TemplateParser.Tokenize(template, wovenMethod, attribute.IncludeParamName);
            MakeFormatString(messageParts, messageFormatString, nonStaticTokens);

            // Sequence that contains the logging check and the logging itself.
            InstructionSequence logEntrySequence = wovenMethod.MethodBody.CreateInstructionSequence();
            block.AddInstructionSequence(logEntrySequence, NodePosition.Before, null);

            // Sequence that follows the logging code.
            InstructionSequence afterLoggingSequence = wovenMethod.MethodBody.CreateInstructionSequence();
            block.AddInstructionSequence(afterLoggingSequence, NodePosition.After, logEntrySequence);

            // Check if logging is enabled and log the message.
            context.InstructionWriter.AttachInstructionSequence(logEntrySequence);
            context.InstructionWriter.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden);
            EmitLoggingEnabledCheck(context.InstructionWriter, supportItem, perTypeLoggingData, afterLoggingSequence);
            if (nonStaticTokens.Count == 0)
            {
              // There are no dynamic tokens, use the faster logging method.
              EmitLogString(context.InstructionWriter, perTypeLoggingData.Log, supportItem.LogStringMethod, messageFormatString.ToString());
            }
            else
            {
              // There are dynamic tokens, prepare log message at run-time.
              LocalVariableSymbol args = this.EmitCreateFormatArgumentArray(context, block, nonStaticTokens);
              EmitLogProviderStringArgs(context.InstructionWriter, perTypeLoggingData.Log, supportItem.LogCultureStringArgsMethod, this.parent.InvariantCultureGetter, messageFormatString.ToString(), args);
            }
            context.InstructionWriter.DetachInstructionSequence();

            // Logging is finished (or skipped), do nothing.
            context.InstructionWriter.AttachInstructionSequence(afterLoggingSequence);
            context.InstructionWriter.EmitSymbolSequencePoint(SymbolSequencePoint.Hidden);
            context.InstructionWriter.EmitInstruction(OpCodeNumber.Nop);
            context.InstructionWriter.DetachInstructionSequence();
              }
        }
 public void Weave(WeavingContext context, InstructionBlock block)
 {
     switch (context.JoinPoint.JoinPointKind)
       {
       case JoinPointKinds.AfterMethodBodyException:
     this.WeaveException(context, block);
     break;
       case JoinPointKinds.AfterMethodBodySuccess:
     this.WeaveSuccess(context, block);
     break;
       case JoinPointKinds.BeforeMethodBody:
     this.WeaveEnter(context, block);
     break;
       }
 }
                private void EmitMessage(InstructionBlock block, InstructionWriter writer, MethodDefDeclaration targetMethod, string messageFormatString)
                {
                    // TODO: nested types
                    string category = targetMethod.DeclaringType.Name;
                    ILoggingCategoryBuilder builder = this.backendInstance.GetCategoryBuilder(category);

                    InstructionSequence sequence = block.AddInstructionSequence(null, NodePosition.After, null);
                    writer.AttachInstructionSequence(sequence);

                    if (builder.SupportsIsEnabled)
                    {
                        builder.EmitGetIsEnabled(writer, LogSeverity.Trace);
                        InstructionSequence branchSequence = block.AddInstructionSequence(null, NodePosition.After, sequence);
                        writer.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, branchSequence);
                    }

                    int parameterCount = Context.MethodMapping.MethodSignature.ParameterCount;
                    bool hasThis = Context.MethodMapping.MethodSignature.CallingConvention == CallingConvention.HasThis;

                    builder.EmitWrite(writer, block, messageFormatString, parameterCount, LogSeverity.Trace, null,
                                      (i, instructionWriter) =>
                                      {
                                          instructionWriter.EmitInstructionInt16(OpCodeNumber.Ldarg, (short)(hasThis ? i + 1 : i));
                                          instructionWriter.EmitConvertToObject(
                                              this.Context.MethodMapping.MethodSignature.GetParameterType(i));
                                      });

                    writer.DetachInstructionSequence();
                }
                protected override void ImplementOnSuccess(InstructionBlock block, InstructionWriter writer)
                {
                    MethodDefDeclaration targetMethod = Context.TargetElement as MethodDefDeclaration;
                    if (targetMethod == null)
                    {
                        return;
                    }

                    string messageFormatString = this.CreateMessageFormatString(this.onSuccessOptions, targetMethod);

                    this.EmitMessage(block, writer, targetMethod, "Leaving: " + messageFormatString);
                }
 protected override void ImplementOnExit(InstructionBlock block, InstructionWriter writer)
 {
 }
                protected override void ImplementOnException(InstructionBlock block, ITypeSignature exceptionType, InstructionWriter writer)
                {
                    MethodDefDeclaration targetMethod = this.transformationInstance.AspectWeaverInstance.TargetElement as MethodDefDeclaration;
                    if (targetMethod == null)
                    {
                        return;
                    }

                    // TODO: nested types
                    string category = targetMethod.DeclaringType.Name;
                    ILoggingCategoryBuilder builder = this.backendInstance.GetCategoryBuilder(category);
                    InstructionSequence sequence = block.AddInstructionSequence(null, NodePosition.After, null);
                    writer.AttachInstructionSequence(sequence);

                    LocalVariableSymbol exceptionLocal = block.MethodBody.RootInstructionBlock.DefineLocalVariable(
                        exceptionType, DebuggerSpecialNames.GetVariableSpecialName("ex"));

                    LogSeverity logSeverity = LogSeverity.Warning;
                    if (builder.SupportsIsEnabled)
                    {
                        builder.EmitGetIsEnabled(writer, logSeverity);
                        InstructionSequence branchSequence = block.AddInstructionSequence(null, NodePosition.After, sequence);
                        writer.EmitBranchingInstruction(OpCodeNumber.Brfalse_S, branchSequence);
                    }

                    builder.EmitWrite(writer, block, "An exception occurred:\n{0}", 1, logSeverity,
                                      w => w.EmitInstructionLocalVariable(OpCodeNumber.Stloc, exceptionLocal),
                                      (i, w) => w.EmitInstructionLocalVariable(OpCodeNumber.Ldloc, exceptionLocal));

                    writer.EmitInstruction(OpCodeNumber.Rethrow);
                    writer.DetachInstructionSequence();
                }