示例#1
0
 protected virtual ILCondition VisitCondition(ILCondition condition)
 {
     foreach (var child in condition.GetChildren())
     {
         Visit(child);
     }
     return(condition);
 }
        bool MatchFixedInitializer(List <ILNode> body, int i, out ILVariable pinnedVar, out ILExpression initValue, out int nextPos)
        {
            if (body[i].Match(ILCode.Stloc, out pinnedVar, out initValue) && pinnedVar.IsPinned && !IsNullOrZero(initValue))
            {
                initValue = (ILExpression)body[i];
                nextPos   = i + 1;
                HandleStringFixing(pinnedVar, body, ref nextPos, ref initValue);
                return(true);
            }
            ILCondition  ifStmt = body[i] as ILCondition;
            ILExpression arrayLoadingExpr;

            if (ifStmt != null && MatchFixedArrayInitializerCondition(ifStmt.Condition, out arrayLoadingExpr))
            {
                ILVariable   arrayVariable = (ILVariable)arrayLoadingExpr.Operand;
                ILExpression trueValue;
                if (ifStmt.TrueBlock != null && ifStmt.TrueBlock.Body.Count == 1 &&
                    ifStmt.TrueBlock.Body[0].Match(ILCode.Stloc, out pinnedVar, out trueValue) &&
                    pinnedVar.IsPinned && IsNullOrZero(trueValue))
                {
                    if (ifStmt.FalseBlock != null && ifStmt.FalseBlock.Body.Count == 1 && ifStmt.FalseBlock.Body[0] is ILFixedStatement)
                    {
                        ILFixedStatement fixedStmt = (ILFixedStatement)ifStmt.FalseBlock.Body[0];
                        ILVariable       stlocVar;
                        ILExpression     falseValue;
                        if (fixedStmt.Initializers.Count == 1 && fixedStmt.BodyBlock.Body.Count == 0 &&
                            fixedStmt.Initializers[0].Match(ILCode.Stloc, out stlocVar, out falseValue) && stlocVar == pinnedVar)
                        {
                            ILVariable loadedVariable;
                            if (falseValue.Code == ILCode.Ldelema &&
                                falseValue.Arguments[0].Match(ILCode.Ldloc, out loadedVariable) && loadedVariable == arrayVariable &&
                                IsNullOrZero(falseValue.Arguments[1]))
                            {
                                // OK, we detected the pattern for fixing an array.
                                // Now check whether the loading expression was a store ot a temp. var
                                // that can be eliminated.
                                if (arrayLoadingExpr.Code == ILCode.Stloc)
                                {
                                    ILInlining inlining = new ILInlining(method);
                                    if (inlining.numLdloc.GetOrDefault(arrayVariable) == 2 &&
                                        inlining.numStloc.GetOrDefault(arrayVariable) == 1 && inlining.numLdloca.GetOrDefault(arrayVariable) == 0)
                                    {
                                        arrayLoadingExpr = arrayLoadingExpr.Arguments[0];
                                    }
                                }
                                initValue = new ILExpression(ILCode.Stloc, pinnedVar, arrayLoadingExpr);
                                nextPos   = i + 1;
                                return(true);
                            }
                        }
                    }
                }
            }
            initValue = null;
            nextPos   = -1;
            return(false);
        }
示例#3
0
        private void CompileTernaryOp(ILExpression e, ExpectType expect)
        {
            ILCondition conditionNode = new ILCondition();

            conditionNode.Condition  = e.Arguments[0];
            conditionNode.TrueBlock  = new ILBlock(e.Arguments[1]);
            conditionNode.FalseBlock = new ILBlock(e.Arguments[2]);
            CompileCondition(conditionNode, expect);

            TranslateType(resolver.Resolve(e.InferredType, thisMethod.FullGenericArguments), expect, e);
        }
        /// <summary>
        /// Reduce the nesting of conditions.
        /// It should be done on flat data that already had most gotos removed
        /// </summary>
        void ReduceIfNesting(ILNode node)
        {
            ILBlock block = node as ILBlock;

            if (block != null)
            {
                for (int i = 0; i < block.Body.Count; i++)
                {
                    ILCondition cond = block.Body[i] as ILCondition;
                    if (cond != null)
                    {
                        bool trueExits  = cond.TrueBlock.Body.LastOrDefault().IsUnconditionalControlFlow();
                        bool falseExits = cond.FalseBlock.Body.LastOrDefault().IsUnconditionalControlFlow();

                        if (trueExits)
                        {
                            // Move the false block after the condition
                            block.Body.InsertRange(i + 1, cond.FalseBlock.GetChildren());
                            cond.FalseBlock = new ILBlock();
                        }
                        else if (falseExits)
                        {
                            // Move the true block after the condition
                            block.Body.InsertRange(i + 1, cond.TrueBlock.GetChildren());
                            cond.TrueBlock = new ILBlock();
                        }

                        // Eliminate empty true block
                        if (!cond.TrueBlock.GetChildren().Any() && cond.FalseBlock.GetChildren().Any())
                        {
                            // Swap bodies
                            ILBlock tmp = cond.TrueBlock;
                            cond.TrueBlock  = cond.FalseBlock;
                            cond.FalseBlock = tmp;
                            cond.Condition  = new ILExpression(ILCode.LogicNot, null, cond.Condition);
                        }
                    }
                }
            }

            // We are changing the number of blocks so we use plain old recursion to get all blocks
            foreach (ILNode child in node.GetChildren())
            {
                if (child != null && !(child is ILExpression))
                {
                    ReduceIfNesting(child);
                }
            }
        }
示例#5
0
 public virtual void Write(ILCondition condition)
 {
     InsertLineInfo(condition);
     Write("if(");
     Write(condition.Condition); // want to make sure we are using the debug
     Write(")");
     WriteSingleLineOrBlock(condition.TrueBlock);
     if (condition.FalseBlock != null && condition.FalseBlock.Body.Count > 0)
     {
         if (this.Column > 0 && this.CurrentLine != "}")
         {
             WriteLine();
         }
         Write(" else ");
         WriteSingleLineOrBlock(condition.FalseBlock);
     }
 }
示例#6
0
        private List <ILVariable> PreprocessorCheckUninitializedLocalVarsBranch(ILBlock branch, List <ILVariable> initializedVars)
        {
            List <ILVariable> result = new List <ILVariable>(initializedVars);

            foreach (ILNode node in branch.Body)
            {
                if (node is ILExpression)
                {
                    PreprocessorCheckUninitializedLocalVarsExpression((ILExpression)node, result);
                }
                else if (node is ILBlock)
                {
                    result = PreprocessorCheckUninitializedLocalVarsBranch((ILBlock)node, result);
                }
                else if (node is ILTryCatchBlock)
                {
                    ILTryCatchBlock block = (ILTryCatchBlock)node;

                    List <ILVariable> newResult = new List <ILVariable>(result);

                    if (block.TryBlock != null)
                    {
                        newResult = newResult.Union(PreprocessorCheckUninitializedLocalVarsBranch(block.TryBlock, result)).ToList();
                    }
                    if (block.FaultBlock != null)
                    {
                        newResult = newResult.Union(PreprocessorCheckUninitializedLocalVarsBranch(block.FaultBlock, result)).ToList();
                    }
                    if (block.FinallyBlock != null)
                    {
                        newResult = newResult.Union(PreprocessorCheckUninitializedLocalVarsBranch(block.FinallyBlock, result)).ToList();
                    }
                    if (block.CatchBlocks != null)
                    {
                        foreach (ILTryCatchBlock.CatchBlock c in block.CatchBlocks)
                        {
                            newResult = newResult.Union(PreprocessorCheckUninitializedLocalVarsBranch(c, result)).ToList();
                        }
                    }

                    result = newResult;
                }
                else if (node is ILWhileLoop)
                {
                    PreprocessorCheckUninitializedLocalVarsExpression(((ILWhileLoop)node).Condition, result);
                    result = PreprocessorCheckUninitializedLocalVarsBranch(((ILWhileLoop)node).BodyBlock, result);
                }
                else if (node is ILCondition)
                {
                    ILCondition cond = (ILCondition)node;
                    PreprocessorCheckUninitializedLocalVarsExpression(cond.Condition, result);

                    List <ILVariable> fromTrue  = PreprocessorCheckUninitializedLocalVarsBranch(cond.TrueBlock, result);
                    List <ILVariable> fromFalse = PreprocessorCheckUninitializedLocalVarsBranch(cond.FalseBlock, result);

                    result = fromTrue.Union(fromFalse).ToList();
                }
                else if (node is ILSwitch)
                {
                    ILSwitch sw = (ILSwitch)node;

                    PreprocessorCheckUninitializedLocalVarsExpression(sw.Condition, result);

                    List <ILVariable> newResult = new List <ILVariable>(result);
                    foreach (var cas in sw.CaseBlocks)
                    {
                        newResult = newResult.Union(PreprocessorCheckUninitializedLocalVarsBranch(cas, result)).ToList();
                    }
                    result = newResult;
                }
            }

            return(result);
        }
示例#7
0
        /// <summary>
        /// Get the first expression to be excecuted if the instruction pointer is at the start of the given node.
        /// Try blocks may not be entered in any way.  If possible, the try block is returned as the node to be executed.
        /// </summary>
        ILNode Enter(ILNode node, HashSet <ILNode> visitedNodes)
        {
            if (node == null)
            {
                throw new ArgumentNullException();
            }

            if (!visitedNodes.Add(node))
            {
                return(null);  // Infinite loop
            }
            ILLabel label = node as ILLabel;

            if (label != null)
            {
                return(Exit(label, visitedNodes));
            }


            ILExpression expr = node as ILExpression;

            if (expr != null)
            {
                if (expr.Code == GMCode.B)
                {
                    ILLabel target = (ILLabel)expr.Operand;
                    return(Enter(target, visitedNodes));
                }
                else if (expr.Code == GMCode.BadOp || expr.Code == GMCode.Constant || expr.Code == GMCode.Var)
                {
                    return(Exit(expr, visitedNodes));
                }
                else if (expr.Code == GMCode.LoopOrSwitchBreak)
                {
                    ILNode breakBlock = GetParents(expr).First(n => n is ILWhileLoop || n is ILSwitch || n is ILWithStatement);
                    return(Exit(breakBlock, new HashSet <ILNode>()
                    {
                        expr
                    }));
                }
                else if (expr.Code == GMCode.LoopContinue)
                {
                    ILNode continueBlock = GetParents(expr).First(n => n is ILWhileLoop || n is ILWithStatement);
                    return(Enter(continueBlock, new HashSet <ILNode>()
                    {
                        expr
                    }));
                }
                else
                {
                    return(expr);
                }
            }

            ILBlock block = node as ILBlock;

            if (block != null)
            {
                if (block.EntryGoto != null)
                {
                    return(Enter(block.EntryGoto, visitedNodes));
                }
                else if (block.Body.Count > 0)
                {
                    return(Enter(block.Body[0], visitedNodes));
                }
                else
                {
                    return(Exit(block, visitedNodes));
                }
            }

            ILCondition cond = node as ILCondition;

            if (cond != null)
            {
                return(cond.Condition);
            }

            ILWhileLoop loop = node as ILWhileLoop;

            if (loop != null)
            {
                if (loop.Condition != null)
                {
                    return(loop.Condition);
                }
                else
                {
                    return(Enter(loop.Body, visitedNodes));
                }
            }

            ILSwitch ilSwitch = node as ILSwitch;

            if (ilSwitch != null)
            {
                return(ilSwitch.Condition);
            }

            throw new NotSupportedException(node.GetType().ToString());
        }
        /// <summary>
        /// Get the first expression to be excecuted if the instruction pointer is at the start of the given node.
        /// Try blocks may not be entered in any way.  If possible, the try block is returned as the node to be executed.
        /// </summary>
        ILNode Enter(ILNode node, HashSet <ILNode> visitedNodes)
        {
            if (node == null)
            {
                throw new ArgumentNullException();
            }

            if (!visitedNodes.Add(node))
            {
                return(null);                 // Infinite loop
            }
            ILLabel label = node as ILLabel;

            if (label != null)
            {
                return(Exit(label, visitedNodes));
            }

            ILExpression expr = node as ILExpression;

            if (expr != null)
            {
                if (expr.Code == ILCode.Br || expr.Code == ILCode.Leave)
                {
                    ILLabel target = (ILLabel)expr.Operand;
                    // Early exit - same try-block
                    if (GetParents(expr).OfType <ILTryCatchBlock>().FirstOrDefault() == GetParents(target).OfType <ILTryCatchBlock>().FirstOrDefault())
                    {
                        return(Enter(target, visitedNodes));
                    }
                    // Make sure we are not entering any try-block
                    var srcTryBlocks = GetParents(expr).OfType <ILTryCatchBlock>().Reverse().ToList();
                    var dstTryBlocks = GetParents(target).OfType <ILTryCatchBlock>().Reverse().ToList();
                    // Skip blocks that we are already in
                    int i = 0;
                    while (i < srcTryBlocks.Count && i < dstTryBlocks.Count && srcTryBlocks[i] == dstTryBlocks[i])
                    {
                        i++;
                    }
                    if (i == dstTryBlocks.Count)
                    {
                        return(Enter(target, visitedNodes));
                    }
                    else
                    {
                        ILTryCatchBlock dstTryBlock = dstTryBlocks[i];
                        // Check that the goto points to the start
                        ILTryCatchBlock current = dstTryBlock;
                        while (current != null)
                        {
                            foreach (ILNode n in current.TryBlock.Body)
                            {
                                if (n is ILLabel)
                                {
                                    if (n == target)
                                    {
                                        return(dstTryBlock);
                                    }
                                }
                                else if (!n.Match(ILCode.Nop))
                                {
                                    current = n as ILTryCatchBlock;
                                    break;
                                }
                            }
                        }
                        return(null);
                    }
                }
                else if (expr.Code == ILCode.Nop)
                {
                    return(Exit(expr, visitedNodes));
                }
                else if (expr.Code == ILCode.LoopOrSwitchBreak)
                {
                    ILNode breakBlock = GetParents(expr).First(n => n is ILWhileLoop || n is ILSwitch);
                    return(Exit(breakBlock, new HashSet <ILNode>()
                    {
                        expr
                    }));
                }
                else if (expr.Code == ILCode.LoopContinue)
                {
                    ILNode continueBlock = GetParents(expr).First(n => n is ILWhileLoop);
                    return(Enter(continueBlock, new HashSet <ILNode>()
                    {
                        expr
                    }));
                }
                else
                {
                    return(expr);
                }
            }

            ILBlock block = node as ILBlock;

            if (block != null)
            {
                if (block.EntryGoto != null)
                {
                    return(Enter(block.EntryGoto, visitedNodes));
                }
                else if (block.Body.Count > 0)
                {
                    return(Enter(block.Body[0], visitedNodes));
                }
                else
                {
                    return(Exit(block, visitedNodes));
                }
            }

            ILCondition cond = node as ILCondition;

            if (cond != null)
            {
                return(cond.Condition);
            }

            ILWhileLoop loop = node as ILWhileLoop;

            if (loop != null)
            {
                if (loop.Condition != null)
                {
                    return(loop.Condition);
                }
                else
                {
                    return(Enter(loop.BodyBlock, visitedNodes));
                }
            }

            ILTryCatchBlock tryCatch = node as ILTryCatchBlock;

            if (tryCatch != null)
            {
                return(tryCatch);
            }

            ILSwitch ilSwitch = node as ILSwitch;

            if (ilSwitch != null)
            {
                return(ilSwitch.Condition);
            }

            throw new NotSupportedException(node.GetType().ToString());
        }
        void CachedDelegateInitializationWithField(ILBlock block, ref int i)
        {
            // if (logicnot(ldsfld(field))) {
            //     stsfld(field, newobj(Action::.ctor, ldnull(), ldftn(method)))
            // } else {
            // }
            // ...(..., ldsfld(field), ...)

            ILCondition c = block.Body[i] as ILCondition;

            if (c == null || c.Condition == null && c.TrueBlock == null || c.FalseBlock == null)
            {
                return;
            }
            if (!(c.TrueBlock.Body.Count == 1 && c.FalseBlock.Body.Count == 0))
            {
                return;
            }
            if (!c.Condition.Match(ILCode.LogicNot))
            {
                return;
            }
            ILExpression condition = c.Condition.Arguments.Single() as ILExpression;

            if (condition == null || condition.Code != ILCode.Ldsfld)
            {
                return;
            }
            FieldDefinition field = ((FieldReference)condition.Operand).ResolveWithinSameModule();             // field is defined in current assembly

            if (field == null || !field.IsCompilerGeneratedOrIsInCompilerGeneratedClass())
            {
                return;
            }
            ILExpression stsfld = c.TrueBlock.Body[0] as ILExpression;

            if (!(stsfld != null && stsfld.Code == ILCode.Stsfld && ((FieldReference)stsfld.Operand).ResolveWithinSameModule() == field))
            {
                return;
            }
            ILExpression newObj = stsfld.Arguments[0];

            if (!(newObj.Code == ILCode.Newobj && newObj.Arguments.Count == 2))
            {
                return;
            }
            if (newObj.Arguments[0].Code != ILCode.Ldnull)
            {
                return;
            }
            if (newObj.Arguments[1].Code != ILCode.Ldftn)
            {
                return;
            }
            MethodDefinition anonymousMethod = ((MethodReference)newObj.Arguments[1].Operand).ResolveWithinSameModule();             // method is defined in current assembly

            if (!AstServices.Transforms.DelegateConstruction.IsAnonymousMethod(context, anonymousMethod))
            {
                return;
            }

            ILNode followingNode = block.Body.ElementAtOrDefault(i + 1);

            int ldfldResolvingWithinSameMethodCount =
                followingNode
                .EnumerateSelfAndChildrenRecursive()
                .OfType <ILExpression>()
                .Count(
                    e =>
                    e.Code == ILCode.Ldsfld &&
                    ((FieldReference)e.Operand).ResolveWithinSameModule() == field);

            if (followingNode != null && ldfldResolvingWithinSameMethodCount == 1)
            {
                foreach (ILExpression parent in followingNode.EnumerateSelfAndChildrenRecursive().OfType <ILExpression>())
                {
                    for (int j = 0; j < parent.Arguments.Count; j++)
                    {
                        if (parent.Arguments[j].Code == ILCode.Ldsfld && ((FieldReference)parent.Arguments[j].Operand).ResolveWithinSameModule() == field)
                        {
                            parent.Arguments[j] = newObj;
                            block.Body.RemoveAt(i);
                            i -= new ILInlining(method).InlineInto(block.Body, i, aggressive: false);
                            return;
                        }
                    }
                }
            }
        }
示例#10
0
        private void ProcessMethodDecencies(InterMethod method, ILNode node, List <InterGenericArgument> genericArgs)
        {
            if (node is ILBlock)
            {
                ILBlock block = node as ILBlock;

                foreach (ILNode n in block.Body)
                {
                    ProcessMethodDecencies(method, n, genericArgs);
                }
            }
            else if (node is ILBasicBlock)
            {
                ILBasicBlock block = node as ILBasicBlock;

                foreach (ILNode n in block.Body)
                {
                    ProcessMethodDecencies(method, n, genericArgs);
                }
            }
            else if (node is ILTryCatchBlock)
            {
                ILTryCatchBlock block = node as ILTryCatchBlock;

                foreach (ILNode n in block.TryBlock.Body)
                {
                    ProcessMethodDecencies(method, n, genericArgs);
                }
                if (block.FaultBlock != null)
                {
                    foreach (ILNode n in block.FaultBlock.Body)
                    {
                        ProcessMethodDecencies(method, n, genericArgs);
                    }
                }
                if (block.FinallyBlock != null)
                {
                    foreach (ILNode n in block.FinallyBlock.Body)
                    {
                        ProcessMethodDecencies(method, n, genericArgs);
                    }
                }
                foreach (var catchBlock in block.CatchBlocks)
                {
                    ((IResolver)this).Resolve(catchBlock.ExceptionType, genericArgs);
                    ProcessMethodDecencies(method, catchBlock, genericArgs);
                }
            }
            else if (node is ILExpression)
            {
                ILExpression e = node as ILExpression;

                foreach (var n in e.Arguments)
                {
                    ProcessMethodDecencies(method, n, genericArgs);
                }

                if ((e.Code == ILCode.Mkrefany) || (e.Code == ILCode.Refanyval))
                {
                    ((IResolver)this).Resolve(ClassNames.SystemTypedReference.ClassName);
                }

                if (e.Code == ILCode.Refanytype)
                {
                    ((IResolver)this).Resolve(ClassNames.SystemTypedReference.ClassName);
                    ((IResolver)this).Resolve(ClassNames.SystemRuntimeTypeHandle.ClassName);
                }

                if (e.Code == ILCode.Arglist)
                {
                    ((IResolver)this).Resolve(ClassNames.SystemRuntimeArgumentHandle.ClassName);
                }

                if (e.Code.IsExternalRealization())
                {
                    ((IResolver)this).Resolve(ClassNames.CIL2JavaVESInstructions.ClassName);
                }

                if (e.Code == ILCode.Ldc_Decimal)
                {
                    ((IResolver)this).Resolve(ClassNames.SystemDecimal.ClassNames);
                }

                if (e.Code == ILCode.Ldtoken)
                {
                    if (e.Operand is TypeReference)
                    {
                        ((IResolver)this).Resolve(ClassNames.SystemRuntimeTypeHandle.ClassName);
                    }
                    else if (e.Operand is FieldReference)
                    {
                        ((IResolver)this).Resolve(ClassNames.SystemRuntimeFieldHandle.ClassName);
                    }
                    else if (e.Operand is MethodReference)
                    {
                        ((IResolver)this).Resolve(ClassNames.SystemRuntimeMethodHandle.ClassName);
                    }
                }

                if (e.Operand is ILVariable)
                {
                    ((IResolver)this).Resolve(((ILVariable)e.Operand).Type, genericArgs);
                }
                if (e.Operand is TypeReference)
                {
                    ((IResolver)this).Resolve((TypeReference)e.Operand, genericArgs);
                }
                if (e.Operand is MethodReference)
                {
                    ((IResolver)this).Resolve((MethodReference)e.Operand, genericArgs);
                }
                if (e.Operand is FieldReference)
                {
                    InterField fld          = ((IResolver)this).Resolve((FieldReference)e.Operand, genericArgs);
                    bool       needAccessor = false;

                    if ((fld.IsPrivate) && (fld.DeclaringType != method.DeclaringType))
                    {
                        needAccessor = true;
                    }
                    else if ((fld.IsProtected) && (fld.DeclaringType != method.DeclaringType) &&
                             (!method.DeclaringType.IsSuper(fld.DeclaringType)))
                    {
                        needAccessor = true;
                    }

                    if (needAccessor)
                    {
                        switch (e.Code)
                        {
                        case ILCode.Ldflda:
                        case ILCode.Ldsflda:
                            if (fld.FieldType.IsValueType)
                            {
                                fld.DeclaringType.AddFieldAccessor(new FieldAccessor(FieldAccessorType.Getter, fld));
                            }
                            break;

                        case ILCode.Ldfld:
                        case ILCode.Ldsfld:
                            fld.DeclaringType.AddFieldAccessor(new FieldAccessor(FieldAccessorType.Getter, fld));
                            break;

                        case ILCode.Stfld:
                        case ILCode.Stsfld:
                            fld.DeclaringType.AddFieldAccessor(new FieldAccessor(FieldAccessorType.Setter, fld));
                            break;
                        }
                    }
                }

                InterType expected = null;
                InterType inferred = null;

                if (e.ExpectedType != null)
                {
                    expected = ((IResolver)this).Resolve(e.ExpectedType, genericArgs);
                }
                if (e.InferredType != null)
                {
                    inferred = ((IResolver)this).Resolve(e.InferredType, genericArgs);
                }

                if ((expected != null) && (expected.IsInterface) && (inferred != null) && (inferred.IsArray))
                {
                    ((IResolver)this).Resolve(ClassNames.ArraysInterfaceAdapterTypeName,
                                              new List <InterGenericArgument>()
                    {
                        new InterGenericArgument(GenericArgumentOwnerType.Type, 0, inferred.ElementType)
                    });
                }
            }
            else if (node is ILWhileLoop)
            {
                ILWhileLoop loop = node as ILWhileLoop;
                ProcessMethodDecencies(method, loop.Condition, genericArgs);
                ProcessMethodDecencies(method, loop.BodyBlock, genericArgs);
            }
            else if (node is ILCondition)
            {
                ILCondition cond = node as ILCondition;
                ProcessMethodDecencies(method, cond.Condition, genericArgs);
                ProcessMethodDecencies(method, cond.TrueBlock, genericArgs);
                ProcessMethodDecencies(method, cond.FalseBlock, genericArgs);
            }
            else if (node is ILSwitch)
            {
                ILSwitch sw = node as ILSwitch;
                ProcessMethodDecencies(method, sw.Condition, genericArgs);
                foreach (var c in sw.CaseBlocks)
                {
                    ProcessMethodDecencies(method, c, genericArgs);
                }
            }
            else if (node is ILFixedStatement)
            {
                ILFixedStatement fs = node as ILFixedStatement;
                foreach (var n in fs.Initializers)
                {
                    ProcessMethodDecencies(method, n, genericArgs);
                }
                ProcessMethodDecencies(method, fs.BodyBlock, genericArgs);
            }
        }
示例#11
0
        List<ILNode> FindConditions(HashSet<ControlFlowNode> nodes, ControlFlowNode entryNode)
        {
            List<ILNode> result = new List<ILNode>();

            Queue<ControlFlowNode> agenda  = new Queue<ControlFlowNode>();
            agenda.Enqueue(entryNode);
            while(agenda.Count > 0) {
                ControlFlowNode node = agenda.Dequeue();

                // Find a block that represents a simple condition
                if (nodes.Contains(node)) {

                    ILMoveableBlock block = node.UserData as ILMoveableBlock;

                    if (block != null && block.Body.Count == 3) {

                        ILLabel      label      = block.Body[0] as ILLabel;
                        ILExpression condBranch = block.Body[1] as ILExpression;
                        ILExpression statBranch = block.Body[2] as ILExpression;

                        // Switch
                        if (label != null &&
                            condBranch != null && condBranch.Operand is ILLabel[] && condBranch.Arguments.Count > 0 &&
                            statBranch != null && statBranch.Operand is ILLabel   && statBranch.Arguments.Count == 0)
                        {
                            ILSwitch ilSwitch = new ILSwitch() { Condition = condBranch };

                            // Replace the two branches with a conditional structure - this preserves the node label
                            block.Body.Remove(condBranch);
                            block.Body.Remove(statBranch);
                            block.Body.Add(ilSwitch);

                            ControlFlowNode statTarget = null;
                            labelToCfNode.TryGetValue((ILLabel)statBranch.Operand, out statTarget);

                            // Pull in the conditional code
                            HashSet<ControlFlowNode> frontiers = new HashSet<ControlFlowNode>();

                            if (statTarget != null)
                                frontiers.UnionWith(statTarget.DominanceFrontier);

                            foreach(ILLabel condLabel in (ILLabel[])condBranch.Operand) {
                                ControlFlowNode condTarget = null;
                                labelToCfNode.TryGetValue(condLabel, out condTarget);

                                if (condTarget != null)
                                    frontiers.UnionWith(condTarget.DominanceFrontier);
                            }

                            foreach(ILLabel condLabel in (ILLabel[])condBranch.Operand) {
                                ControlFlowNode condTarget = null;
                                labelToCfNode.TryGetValue(condLabel, out condTarget);

                                ILBlock caseBlock = new ILBlock() { EntryPoint = condLabel };
                                if (condTarget != null && !frontiers.Contains(condTarget)) {
                                    HashSet<ControlFlowNode> content = FindDominatedNodes(nodes, condTarget);
                                    nodes.ExceptWith(content);
                                    caseBlock.Body.AddRange(FindConditions(content, condTarget));
                                }
                                ilSwitch.CaseBlocks.Add(caseBlock);
                            }

                            // The labels will not be used - kill them
                            condBranch.Operand = null;

                            result.Add(block);
                            nodes.Remove(node);
                        }

                        // Two-way branch
                        if (label != null &&
                            condBranch != null && condBranch.Operand is ILLabel && condBranch.Arguments.Count > 0 &&
                            statBranch != null && statBranch.Operand is ILLabel && statBranch.Arguments.Count == 0)
                        {
                            ControlFlowNode statTarget = null;
                            labelToCfNode.TryGetValue((ILLabel)statBranch.Operand, out statTarget);
                            ControlFlowNode condTarget = null;
                            labelToCfNode.TryGetValue((ILLabel)condBranch.Operand, out condTarget);

                            ILCondition condition = new ILCondition() {
                                Condition  = condBranch,
                                TrueBlock  = new ILBlock() { EntryPoint = (ILLabel)condBranch.Operand },
                                FalseBlock = new ILBlock() { EntryPoint = (ILLabel)statBranch.Operand }
                            };

                            // Replace the two branches with a conditional structure - this preserves the node label
                            block.Body.Remove(condBranch);
                            block.Body.Remove(statBranch);
                            block.Body.Add(condition);

                            // Pull in the conditional code
                            HashSet<ControlFlowNode> frontiers = new HashSet<ControlFlowNode>();
                            if (statTarget != null)
                                frontiers.UnionWith(statTarget.DominanceFrontier);
                            if (condTarget != null)
                                frontiers.UnionWith(condTarget.DominanceFrontier);

                            if (condTarget != null && !frontiers.Contains(condTarget)) {
                                HashSet<ControlFlowNode> content = FindDominatedNodes(nodes, condTarget);
                                nodes.ExceptWith(content);
                                condition.TrueBlock.Body.AddRange(FindConditions(content, condTarget));
                            }
                            if (statTarget != null && !frontiers.Contains(statTarget)) {
                                HashSet<ControlFlowNode> content = FindDominatedNodes(nodes, statTarget);
                                nodes.ExceptWith(content);
                                condition.FalseBlock.Body.AddRange(FindConditions(content, statTarget));
                            }

                            // The label will not be used - kill it
                            condBranch.Operand = null;

                            result.Add(block);
                            nodes.Remove(node);
                        }
                    }

                    // Add the node now so that we have good ordering
                    if (nodes.Contains(node)) {
                        result.Add((ILNode)node.UserData);
                        nodes.Remove(node);
                    }
                }

                // Using the dominator tree should ensure we find the the widest loop first
                foreach(var child in node.DominatorTreeChildren) {
                    agenda.Enqueue(child);
                }
            }

            // Add whatever is left
            foreach(var node in nodes) {
                result.Add((ILNode)node.UserData);
            }

            return result;
        }
示例#12
0
        protected bool TranslateCallSiteConstruction(ILCondition condition, out JSStatement result)
        {
            var cond = condition.Condition;
            if (
                (cond.Code == ILCode.LogicNot) &&
                (cond.Arguments.Count > 0) &&
                (cond.Arguments[0].Code == ILCode.GetCallSite) &&
                (condition.TrueBlock != null) &&
                (condition.TrueBlock.Body.Count == 1) &&
                (condition.TrueBlock.Body[0] is ILExpression)
            ) {
                var callSiteExpression = (ILExpression)condition.TrueBlock.Body[0];
                var callSiteType = callSiteExpression.Arguments[0].ExpectedType;
                var binderExpression = callSiteExpression.Arguments[0].Arguments[0];
                var binderMethod = (MethodReference)binderExpression.Operand;
                var arguments = Translate(binderExpression.Arguments);
                var targetType = ((IGenericInstance)callSiteType).GenericArguments[0];

                DynamicCallSites.InitializeCallSite(
                    (FieldReference)cond.Arguments[0].Operand,
                    binderMethod.Name,
                    targetType,
                    arguments
                );

                result = new JSNullStatement();
                return true;
            }

            result = null;
            return false;
        }
示例#13
0
        List<ILNode> FindConditions(HashSet<ControlFlowNode> scope, ControlFlowNode entryNode)
        {
            List<ILNode> result = new List<ILNode>();

            // Do not modify entry data
            scope = new HashSet<ControlFlowNode>(scope);

            HashSet<ControlFlowNode> agenda  = new HashSet<ControlFlowNode>();
            agenda.Add(entryNode);
            while(agenda.Any()) {
                ControlFlowNode node = agenda.First();
                // Attempt for a good order
                while(agenda.Contains(node.ImmediateDominator)) {
                    node = node.ImmediateDominator;
                }
                agenda.Remove(node);

                // Find a block that represents a simple condition
                if (scope.Contains(node)) {

                    ILBasicBlock block = node.UserData as ILBasicBlock;

                    if (block != null && block.Body.Count == 1) {

                        ILExpression condBranch = block.Body[0] as ILExpression;

                        // Switch
                        if (condBranch != null && condBranch.Operand is ILLabel[] && condBranch.Arguments.Count > 0) {

                            ILLabel[] caseLabels = (ILLabel[])condBranch.Operand;

                            // The labels will not be used - kill them
                            condBranch.Operand = null;

                            ILSwitch ilSwitch = new ILSwitch() {
                                Condition = condBranch,
                                DefaultGoto = block.FallthoughGoto
                            };
                            result.Add(new ILBasicBlock() {
                                EntryLabel = block.EntryLabel,  // Keep the entry label
                                Body = { ilSwitch }
                            });

                            // Remove the item so that it is not picked up as content
                            if (!scope.Remove(node))
                                throw new Exception("Item is not in set");

                            // Pull in code of cases
                            ControlFlowNode fallTarget = null;
                            labelToCfNode.TryGetValue((ILLabel)block.FallthoughGoto.Operand, out fallTarget);

                            HashSet<ControlFlowNode> frontiers = new HashSet<ControlFlowNode>();
                            if (fallTarget != null)
                                frontiers.UnionWith(fallTarget.DominanceFrontier);

                            foreach(ILLabel condLabel in caseLabels) {
                                ControlFlowNode condTarget = null;
                                labelToCfNode.TryGetValue(condLabel, out condTarget);
                                if (condTarget != null)
                                    frontiers.UnionWith(condTarget.DominanceFrontier);
                            }

                            foreach(ILLabel condLabel in caseLabels) {
                                ControlFlowNode condTarget = null;
                                labelToCfNode.TryGetValue(condLabel, out condTarget);

                                ILBlock caseBlock = new ILBlock() {
                                    EntryGoto = new ILExpression(ILCode.Br, condLabel)
                                };
                                if (condTarget != null && !frontiers.Contains(condTarget)) {
                                    HashSet<ControlFlowNode> content = FindDominatedNodes(scope, condTarget);
                                    scope.ExceptWith(content);
                                    caseBlock.Body.AddRange(FindConditions(content, condTarget));
                                }
                                ilSwitch.CaseBlocks.Add(caseBlock);
                            }
                        }

                        // Two-way branch
                        ILExpression branchExpr = null;
                        ILLabel trueLabel = null;
                        ILLabel falseLabel = null;
                        if(IsConditionalBranch(block, ref branchExpr, ref trueLabel, ref falseLabel)) {

                            // The branch label will not be used - kill it
                            branchExpr.Operand = null;

                            // Convert the basic block to ILCondition
                            ILCondition ilCond = new ILCondition() {
                                Condition  = branchExpr,
                                TrueBlock  = new ILBlock() { EntryGoto = new ILExpression(ILCode.Br, trueLabel) },
                                FalseBlock = new ILBlock() { EntryGoto = new ILExpression(ILCode.Br, falseLabel) }
                            };
                            result.Add(new ILBasicBlock() {
                                    EntryLabel = block.EntryLabel,  // Keep the entry label
                                    Body = { ilCond }
                            });

                            // Remove the item immediately so that it is not picked up as content
                            if (!scope.Remove(node))
                                throw new Exception("Item is not in set");

                            ControlFlowNode trueTarget = null;
                            labelToCfNode.TryGetValue(trueLabel, out trueTarget);
                            ControlFlowNode falseTarget = null;
                            labelToCfNode.TryGetValue(falseLabel, out falseTarget);

                            // Pull in the conditional code
                            HashSet<ControlFlowNode> frontiers = new HashSet<ControlFlowNode>();
                            if (trueTarget != null)
                                frontiers.UnionWith(trueTarget.DominanceFrontier);
                            if (falseTarget != null)
                                frontiers.UnionWith(falseTarget.DominanceFrontier);

                            if (trueTarget != null && !frontiers.Contains(trueTarget)) {
                                HashSet<ControlFlowNode> content = FindDominatedNodes(scope, trueTarget);
                                scope.ExceptWith(content);
                                ilCond.TrueBlock.Body.AddRange(FindConditions(content, trueTarget));
                            }
                            if (falseTarget != null && !frontiers.Contains(falseTarget)) {
                                HashSet<ControlFlowNode> content = FindDominatedNodes(scope, falseTarget);
                                scope.ExceptWith(content);
                                ilCond.FalseBlock.Body.AddRange(FindConditions(content, falseTarget));
                            }

                            if (scope.Count == 0) {
                                // We have removed the whole scope - eliminte one of the condition bodies
                                int trueSize = ilCond.TrueBlock.GetSelfAndChildrenRecursive<ILNode>().Count();
                                int falseSize = ilCond.FalseBlock.GetSelfAndChildrenRecursive<ILNode>().Count();

                                // The block are protected
                                Debug.Assert(ilCond.TrueBlock.EntryGoto != null);
                                Debug.Assert(ilCond.FalseBlock.EntryGoto != null);

                                if (falseSize > trueSize) {
                                    // Move the false body out
                                    result.AddRange(ilCond.FalseBlock.Body);
                                    ilCond.FalseBlock.Body.Clear();
                                } else {
                                    // Move the true body out
                                    result.AddRange(ilCond.TrueBlock.Body);
                                    ilCond.TrueBlock.Body.Clear();
                                }
                            }

                            // If true body is empty, swap bodies.
                            // Might happend because there was not any to start with or we moved it out.
                            if (ilCond.TrueBlock.Body.Count == 0 && ilCond.FalseBlock.Body.Count > 0) {
                                ILBlock tmp = ilCond.TrueBlock;
                                ilCond.TrueBlock = ilCond.FalseBlock;
                                ilCond.FalseBlock = tmp;
                                ilCond.Condition = new ILExpression(ILCode.LogicNot, null, ilCond.Condition);
                            }
                        }
                    }

                    // Add the node now so that we have good ordering
                    if (scope.Contains(node)) {
                        result.Add((ILNode)node.UserData);
                        scope.Remove(node);
                    }
                }

                // Using the dominator tree should ensure we find the the widest loop first
                foreach(var child in node.DominatorTreeChildren) {
                    agenda.Add(child);
                }
            }

            // Add whatever is left
            foreach(var node in scope) {
                result.Add((ILNode)node.UserData);
            }

            return result;
        }
示例#14
0
        List <ILNode> FindConditions(HashSet <ControlFlowNode> scope, ControlFlowNode entryNode)
        {
            List <ILNode> result = new List <ILNode>();

            // Do not modify entry data
            scope = new HashSet <ControlFlowNode>(scope);

            Stack <ControlFlowNode> agenda = new Stack <ControlFlowNode>();

            agenda.Push(entryNode);
            while (agenda.Count > 0)
            {
                ControlFlowNode node = agenda.Pop();

                // Find a block that represents a simple condition
                if (scope.Contains(node))
                {
                    ILBasicBlock block = (ILBasicBlock)node.UserData;

                    {
                        // Switch
                        ILLabel[]    caseLabels;
                        ILExpression switchArg;
                        ILLabel      fallLabel;
                        if (block.MatchLastAndBr(ILCode.Switch, out caseLabels, out switchArg, out fallLabel))
                        {
                            // Replace the switch code with ILSwitch
                            ILSwitch ilSwitch = new ILSwitch()
                            {
                                Condition = switchArg
                            };
                            block.Body.RemoveTail(ILCode.Switch, ILCode.Br);
                            block.Body.Add(ilSwitch);
                            block.Body.Add(new ILExpression(ILCode.Br, fallLabel));
                            result.Add(block);

                            // Remove the item so that it is not picked up as content
                            scope.RemoveOrThrow(node);

                            // Find the switch offset
                            int addValue = 0;
                            List <ILExpression> subArgs;
                            if (ilSwitch.Condition.Match(ILCode.Sub, out subArgs) && subArgs[1].Match(ILCode.Ldc_I4, out addValue))
                            {
                                ilSwitch.Condition = subArgs[0];
                            }

                            // Pull in code of cases
                            ControlFlowNode fallTarget = null;
                            labelToCfNode.TryGetValue(fallLabel, out fallTarget);

                            HashSet <ControlFlowNode> frontiers = new HashSet <ControlFlowNode>();
                            if (fallTarget != null)
                            {
                                frontiers.UnionWith(fallTarget.DominanceFrontier.Except(new [] { fallTarget }));
                            }

                            foreach (ILLabel condLabel in caseLabels)
                            {
                                ControlFlowNode condTarget = null;
                                labelToCfNode.TryGetValue(condLabel, out condTarget);
                                if (condTarget != null)
                                {
                                    frontiers.UnionWith(condTarget.DominanceFrontier.Except(new [] { condTarget }));
                                }
                            }

                            for (int i = 0; i < caseLabels.Length; i++)
                            {
                                ILLabel condLabel = caseLabels[i];

                                // Find or create new case block
                                ILSwitch.CaseBlock caseBlock = ilSwitch.CaseBlocks.FirstOrDefault(b => b.EntryGoto.Operand == condLabel);
                                if (caseBlock == null)
                                {
                                    caseBlock = new ILSwitch.CaseBlock()
                                    {
                                        Values    = new List <int>(),
                                        EntryGoto = new ILExpression(ILCode.Br, condLabel)
                                    };
                                    ilSwitch.CaseBlocks.Add(caseBlock);

                                    ControlFlowNode condTarget = null;
                                    labelToCfNode.TryGetValue(condLabel, out condTarget);
                                    if (condTarget != null && !frontiers.Contains(condTarget))
                                    {
                                        HashSet <ControlFlowNode> content = FindDominatedNodes(scope, condTarget);
                                        scope.ExceptWith(content);
                                        caseBlock.Body.AddRange(FindConditions(content, condTarget));
                                        // Add explicit break which should not be used by default, but the goto removal might decide to use it
                                        caseBlock.Body.Add(new ILBasicBlock()
                                        {
                                            Body =
                                            {
                                                new ILLabel()
                                                {
                                                    Name = "SwitchBreak_" + (nextLabelIndex++)
                                                },
                                                new ILExpression(ILCode.LoopOrSwitchBreak, null)
                                            }
                                        });
                                    }
                                }
                                caseBlock.Values.Add(i + addValue);
                            }

                            // Heuristis to determine if we want to use fallthough as default case
                            if (fallTarget != null && !frontiers.Contains(fallTarget))
                            {
                                HashSet <ControlFlowNode> content = FindDominatedNodes(scope, fallTarget);
                                if (content.Any())
                                {
                                    var caseBlock = new ILSwitch.CaseBlock()
                                    {
                                        EntryGoto = new ILExpression(ILCode.Br, fallLabel)
                                    };
                                    ilSwitch.CaseBlocks.Add(caseBlock);
                                    block.Body.RemoveTail(ILCode.Br);

                                    scope.ExceptWith(content);
                                    caseBlock.Body.AddRange(FindConditions(content, fallTarget));
                                    // Add explicit break which should not be used by default, but the goto removal might decide to use it
                                    caseBlock.Body.Add(new ILBasicBlock()
                                    {
                                        Body =
                                        {
                                            new ILLabel()
                                            {
                                                Name = "SwitchBreak_" + (nextLabelIndex++)
                                            },
                                            new ILExpression(ILCode.LoopOrSwitchBreak, null)
                                        }
                                    });
                                }
                            }
                        }

                        // Two-way branch
                        ILExpression condExpr;
                        ILLabel      trueLabel;
                        ILLabel      falseLabel;
                        if (block.MatchLastAndBr(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel))
                        {
                            // Swap bodies since that seems to be the usual C# order
                            ILLabel temp = trueLabel;
                            trueLabel  = falseLabel;
                            falseLabel = temp;
                            condExpr   = new ILExpression(ILCode.LogicNot, null, condExpr);

                            // Convert the brtrue to ILCondition
                            ILCondition ilCond = new ILCondition()
                            {
                                Condition = condExpr,
                                TrueBlock = new ILBlock()
                                {
                                    EntryGoto = new ILExpression(ILCode.Br, trueLabel)
                                },
                                FalseBlock = new ILBlock()
                                {
                                    EntryGoto = new ILExpression(ILCode.Br, falseLabel)
                                }
                            };
                            block.Body.RemoveTail(ILCode.Brtrue, ILCode.Br);
                            block.Body.Add(ilCond);
                            result.Add(block);

                            // Remove the item immediately so that it is not picked up as content
                            scope.RemoveOrThrow(node);

                            ControlFlowNode trueTarget = null;
                            labelToCfNode.TryGetValue(trueLabel, out trueTarget);
                            ControlFlowNode falseTarget = null;
                            labelToCfNode.TryGetValue(falseLabel, out falseTarget);

                            // Pull in the conditional code
                            if (trueTarget != null && HasSingleEdgeEnteringBlock(trueTarget))
                            {
                                HashSet <ControlFlowNode> content = FindDominatedNodes(scope, trueTarget);
                                scope.ExceptWith(content);
                                ilCond.TrueBlock.Body.AddRange(FindConditions(content, trueTarget));
                            }
                            if (falseTarget != null && HasSingleEdgeEnteringBlock(falseTarget))
                            {
                                HashSet <ControlFlowNode> content = FindDominatedNodes(scope, falseTarget);
                                scope.ExceptWith(content);
                                ilCond.FalseBlock.Body.AddRange(FindConditions(content, falseTarget));
                            }
                        }
                    }

                    // Add the node now so that we have good ordering
                    if (scope.Contains(node))
                    {
                        result.Add((ILNode)node.UserData);
                        scope.Remove(node);
                    }
                }

                // depth-first traversal of dominator tree
                for (int i = node.DominatorTreeChildren.Count - 1; i >= 0; i--)
                {
                    agenda.Push(node.DominatorTreeChildren[i]);
                }
            }

            // Add whatever is left
            foreach (var node in scope)
            {
                result.Add((ILNode)node.UserData);
            }

            return(result);
        }
示例#15
0
        private void CompileCondition(ILCondition node, ExpectType expectType)
        {
            ILExpression condition = node.Condition;

            while (condition != null)
            {
                if (condition.Code == ILCode.Call)
                {
                    InterMethod callMethod = resolver.Resolve((MethodReference)condition.Operand, thisMethod.FullGenericArguments);

                    if (callMethod.DeclaringType.Fullname == ClassNames.Intrinsics.ClassName)
                    {
                        if (callMethod.Name == ClassNames.Intrinsics.IsCILBoxing)
                        {
                            if (Program.BoxType == BoxingType.Cil)
                            {
                                CompileBlock(node.TrueBlock);
                            }
                            return;
                        }

                        if (callMethod.Name == ClassNames.Intrinsics.IsJavaBoxing)
                        {
                            if (Program.BoxType == BoxingType.Java)
                            {
                                CompileBlock(node.TrueBlock);
                            }
                            return;
                        }
                    }
                    break;
                }

                condition = condition.Arguments.FirstOrDefault();
            }

            string labelsSufix = rnd.Next().ToString();
            string falseLabel  = "false" + labelsSufix;
            string exitLabel   = "exit" + labelsSufix;

            if (node.FalseBlock.Body.Count == 0)
            {
                falseLabel = exitLabel;
            }
            CompileCondition(new ILExpression(ILCode.LogicNot, null, node.Condition), falseLabel);

            //CompileExpression(node.Condition, ExpectType.Primitive);

            //Java.OpCodes branchInstr = Java.OpCodes.ifeq;
            //TranslateToBool(node.Condition.InferredType, ref branchInstr, node);

            //codeGenerator.Add(branchInstr, falseLabel, node);
            CompileBlock(node.TrueBlock, expectType);

            if (node.FalseBlock.Body.Count > 0)
            {
                codeGenerator.Add(Java.OpCodes._goto, exitLabel, node)
                .Label(falseLabel);
                CompileBlock(node.FalseBlock, expectType);
            }

            codeGenerator.Label(exitLabel);
        }
示例#16
0
 protected virtual ILCondition VisitCondition(ILCondition condition)
 {
     foreach (var child in condition.GetChildren())
         Visit(child);
     return condition;
 }
示例#17
0
        bool TryMatchCondition(HashSet<ControlFlowNode> scope, IEnumerable<ControlFlowNode> scopeExcept, ControlFlowNode head, out ILCondition condition, out HashSet<ControlFlowNode> matchedNodes, out ILLabel entryLabel)
        {
            condition = null;
            matchedNodes = null;
            entryLabel = null;
            if (!scope.Contains(head) || scopeExcept.Contains(head))
                return false;

            ILBasicBlock basicBlock = head.UserData as ILBasicBlock;

            if (basicBlock == null || basicBlock.Body.Count != 1)
                return false;

            ILExpression condBranch = basicBlock.Body[0] as ILExpression;

            if (condBranch != null && condBranch.Operand is ILLabel && condBranch.Arguments.Count > 0) {

                // We have found a two-way condition
                condition = new ILCondition() {
                    Condition  = condBranch,
                    TrueBlock  = new ILBlock() { EntryGoto = new ILExpression(ILCode.Br, condBranch.Operand) },
                    FalseBlock = new ILBlock() { EntryGoto = new ILExpression(ILCode.Br, basicBlock.FallthoughGoto.Operand) }
                };
                // We are done with the node so "remove" it from scope
                scopeExcept  = scopeExcept.Union(new[] {head});
                matchedNodes = new HashSet<ControlFlowNode>() { head };
                entryLabel   = basicBlock.EntryLabel;

                // Optimize short-circut expressions
                while(true) {

                    // Consider condition.TrueBlock
                    {
                        ILLabel nextLabel = (ILLabel)condition.TrueBlock.EntryGoto.Operand;
                        ControlFlowNode nextTarget;
                        labelToCfNode.TryGetValue(nextLabel, out nextTarget);
                        ILCondition nextCond;
                        HashSet<ControlFlowNode> nextMatchedNodes;
                        ILLabel nextEnteryLabel;
                        if (nextTarget != null &&
                            TryMatchCondition(scope, scopeExcept, nextTarget, out nextCond, out nextMatchedNodes, out nextEnteryLabel) &&
                            labelRefCount[nextEnteryLabel] == 1)
                        {
                            if (condition.FalseBlock.EntryGoto.Operand == nextCond.FalseBlock.EntryGoto.Operand) {
                                    condition.Condition  = new ILExpression(ILCode.LogicAnd, null, condition.Condition, nextCond.Condition);
                                    condition.TrueBlock  = nextCond.TrueBlock;
                                    condition.FalseBlock = nextCond.FalseBlock;
                                    scopeExcept = scopeExcept.Union(nextMatchedNodes);
                                    matchedNodes.UnionWith(nextMatchedNodes);
                                    continue;
                            }

                            if (condition.FalseBlock.EntryGoto.Operand == nextCond.TrueBlock.EntryGoto.Operand) {
                                condition.Condition  = new ILExpression(ILCode.LogicOr, null, new ILExpression(ILCode.LogicNot, null, condition.Condition), nextCond.Condition);
                                    condition.TrueBlock  = nextCond.TrueBlock;
                                    condition.FalseBlock = nextCond.FalseBlock;
                                    scopeExcept = scopeExcept.Union(nextMatchedNodes);
                                    matchedNodes.UnionWith(nextMatchedNodes);
                                    continue;
                            }
                        }
                    }

                    // Consider condition.FalseBlock
                    {
                        ILLabel nextLabel = (ILLabel)condition.FalseBlock.EntryGoto.Operand;
                        ControlFlowNode nextTarget;
                        labelToCfNode.TryGetValue(nextLabel, out nextTarget);
                        ILCondition nextCond;
                        HashSet<ControlFlowNode> nextMatchedNodes;
                        ILLabel nextEnteryLabel;
                        if (nextTarget != null &&
                            TryMatchCondition(scope, scopeExcept, nextTarget, out nextCond, out nextMatchedNodes, out nextEnteryLabel) &&
                            labelRefCount[nextEnteryLabel] == 1)
                        {
                            if (condition.TrueBlock.EntryGoto.Operand == nextCond.FalseBlock.EntryGoto.Operand) {
                                condition.Condition  = new ILExpression(ILCode.LogicAnd, null, new ILExpression(ILCode.LogicNot, null, condition.Condition), nextCond.Condition);
                                    condition.TrueBlock  = nextCond.TrueBlock;
                                    condition.FalseBlock = nextCond.FalseBlock;
                                    scopeExcept = scopeExcept.Union(nextMatchedNodes);
                                    matchedNodes.UnionWith(nextMatchedNodes);
                                    continue;
                            }

                            if (condition.TrueBlock.EntryGoto.Operand == nextCond.TrueBlock.EntryGoto.Operand) {
                                condition.Condition  = new ILExpression(ILCode.LogicOr, null, condition.Condition, nextCond.Condition);
                                    condition.TrueBlock  = nextCond.TrueBlock;
                                    condition.FalseBlock = nextCond.FalseBlock;
                                    scopeExcept = scopeExcept.Union(nextMatchedNodes);
                                    matchedNodes.UnionWith(nextMatchedNodes);
                                    continue;
                            }
                        }
                    }
                    break;
                }
                return true;
            }
            return false;
        }
示例#18
0
        List<ILNode> FindConditions(HashSet<ControlFlowNode> scope, ControlFlowNode entryNode)
        {
            List<ILNode> result = new List<ILNode>();

            // Do not modify entry data
            scope = new HashSet<ControlFlowNode>(scope);

            Stack<ControlFlowNode> agenda = new Stack<ControlFlowNode>();
            agenda.Push(entryNode);
            while (agenda.Count > 0)
            {
                ControlFlowNode node = agenda.Pop();

                // Find a block that represents a simple condition
                if (scope.Contains(node))
                {

                    ILBasicBlock block = (ILBasicBlock)node.UserData;
                   
                    {
                        IList<ILExpression> conditions;
                        ILLabel fallLabel;
                        // Switch
                        FakeSwitch fswitch;
                        if (block.MatchLastAndBr(GMCode.Switch, out fswitch, out conditions, out fallLabel))
                        {
                            ILSwitch ilSwitch = new ILSwitch() { Condition = fswitch.SwitchExpression };
                            block.Body[block.Body.Count - 2] = ilSwitch; // replace it, nothing else needs to be done!
                            result.Add(block); // except add it to the result, DOLT
                           
                            scope.RemoveOrThrow(node);// Remove the item so that it is not picked up as content

                            // Pull in code of cases
                            ControlFlowNode fallTarget = null;
                            labelToCfNode.TryGetValue(fallLabel, out fallTarget);

                            HashSet<ControlFlowNode> frontiers = new HashSet<ControlFlowNode>();
                            if (fallTarget != null)
                                frontiers.UnionWith(fallTarget.DominanceFrontier.Except(new[] { fallTarget }));

                            foreach (ILLabel condLabel in fswitch.CaseExpressions.Select(x => x.Value))
                            {
                                ControlFlowNode condTarget = null;
                                labelToCfNode.TryGetValue(condLabel, out condTarget);
                                if (condTarget != null)
                                    frontiers.UnionWith(condTarget.DominanceFrontier.Except(new[] { condTarget }));
                            }
                            for (int i = 0; i < fswitch.CaseExpressions.Count; i++)
                            {
                                ILLabel condLabel = fswitch.CaseExpressions[i].Value;

                                // Find or create new case block
                                ILSwitch.ILCase caseBlock = ilSwitch.Cases.FirstOrDefault(b => b.EntryGoto.Operand == condLabel);
                                if (caseBlock == null)
                                {
                                    caseBlock = new ILSwitch.ILCase()
                                    {
                                        Values = new List<ILExpression>(),
                                        EntryGoto = new ILExpression(GMCode.B, condLabel)
                                    };
                                    ilSwitch.Cases.Add(caseBlock);

                                    ControlFlowNode condTarget = null;
                                    labelToCfNode.TryGetValue(condLabel, out condTarget);
                                    if (condTarget != null && !frontiers.Contains(condTarget))
                                    {
                                        HashSet<ControlFlowNode> content = FindDominatedNodes(scope, condTarget);
                                        scope.ExceptWith(content);
                                        foreach (var con in FindConditions(content, condTarget)) caseBlock.Body.Add(con);
                                        //   caseBlock.Body.AddRange(FindConditions(content, condTarget));
                                        // Add explicit break which should not be used by default, but the goto removal might decide to use it
                                        caseBlock.Body.Add(new ILBasicBlock()
                                        {
                                            Body = {
                                                ILLabel.Generate("SwitchBreak" ,(int)nextLabelIndex++),
                                                new ILExpression(GMCode.LoopOrSwitchBreak, null)
                                            }
                                        });
                                    }
                                }
                                caseBlock.Values.Add(fswitch.CaseExpressions[i].Key);
                            }

                            // Heuristis to determine if we want to use fallthough as default case
                            if (fallTarget != null && !frontiers.Contains(fallTarget))
                            {
                                HashSet<ControlFlowNode> content = FindDominatedNodes(scope, fallTarget);
                                if (content.Any())
                                {
                                    var caseBlock = new ILSwitch.ILCase() { EntryGoto = new ILExpression(GMCode.B, fallLabel) };
                                    ilSwitch.Cases.Add(caseBlock);
                                    block.Body.RemoveTail(GMCode.B);

                                    scope.ExceptWith(content);
                                    foreach (var con in FindConditions(content, fallTarget)) caseBlock.Body.Add(con);
                                    
                                    // Add explicit break which should not be used by default, but the goto removal might decide to use it
                                    caseBlock.Body.Add(new ILBasicBlock()
                                    { 
                                        Body = {
                                            ILLabel.Generate("SwitchBreak" ,(int)nextLabelIndex++),
                                            new ILExpression(GMCode.LoopOrSwitchBreak, null)
                                        }
                                    });
                                }
                            }
                        }
                     //   Debug.Assert((block.Body.First() as ILLabel).Name != "L1938");
                        // Two-way branch
                        ILLabel trueLabel;
                        ILLabel falseLabel;
                        IList<ILExpression> condExprs;
                        if (block.MatchLastAndBr(GMCode.Bt, out trueLabel, out condExprs, out falseLabel) // be sure to invert this condition
                            && condExprs.Count > 0)  // its resolved
                        {
 
                            ILExpression condExpr = condExprs[0];
                            IList<ILNode> body = block.Body;
                            // this is a simple condition, skip anything short curiket for now
                            // Match a condition patern
                            // Convert the brtrue to ILCondition
                            ILCondition ilCond = new ILCondition()
                            {
                                Condition = condExpr, //code == GMCode.Bf ? condExpr : condExpr.NegateCondition(),
                                TrueBlock = new ILBlock() { EntryGoto = new ILExpression(GMCode.B, trueLabel) },
                                FalseBlock = new ILBlock() { EntryGoto = new ILExpression(GMCode.B, falseLabel) }
                            };
                            block.Body.RemoveTail(GMCode.Bt, GMCode.B);
                            block.Body.Add(ilCond);
                            result.Add(block);

                            // Remove the item immediately so that it is not picked up as content
                            scope.RemoveOrThrow(node);

                            ControlFlowNode trueTarget = null;
                            labelToCfNode.TryGetValue(trueLabel, out trueTarget);
                            ControlFlowNode falseTarget = null;
                            labelToCfNode.TryGetValue(falseLabel, out falseTarget);
   
                            // Pull in the conditional code
                            if (trueTarget != null && HasSingleEdgeEnteringBlock(trueTarget))
                            {
                                HashSet<ControlFlowNode> content = FindDominatedNodes(scope, trueTarget);
                                scope.ExceptWith(content);
                                foreach (var con in FindConditions(content, trueTarget)) ilCond.TrueBlock.Body.Add(con);
                            }
                            if (falseTarget != null && HasSingleEdgeEnteringBlock(falseTarget))
                            {
                                HashSet<ControlFlowNode> content = FindDominatedNodes(scope, falseTarget);
                                scope.ExceptWith(content);
                                foreach (var con in FindConditions(content, falseTarget)) ilCond.FalseBlock.Body.Add(con);
                            }
                       


                        }
                    }

                    // Add the node now so that we have good ordering
                    if (scope.Contains(node))
                    {
                        result.Add((ILNode)node.UserData);
                        scope.Remove(node);
                    }
                }

                // depth-first traversal of dominator tree
                for (int i = node.DominatorTreeChildren.Count - 1; i >= 0; i--)
                {
                    agenda.Push(node.DominatorTreeChildren[i]);
                }
            }

            // Add whatever is left
            foreach (var node in scope)
            {
                result.Add((ILNode)node.UserData);
            }

            return result;
        }
示例#19
0
        public JSStatement TranslateNode(ILCondition condition)
        {
            JSStatement result = null;
            if (TranslateCallSiteConstruction(condition, out result))
                return result;

            JSStatement falseBlock = null;
            if ((condition.FalseBlock != null) && (condition.FalseBlock.Body.Count > 0))
                falseBlock = TranslateNode(condition.FalseBlock);

            result = new JSIfStatement(
                TranslateNode(condition.Condition),
                TranslateNode(condition.TrueBlock),
                falseBlock
            );

            return result;
        }
        bool HandleStringFixing(ILVariable pinnedVar, List <ILNode> body, ref int pos, ref ILExpression fixedStmtInitializer)
        {
            // fixed (stloc(pinnedVar, ldloc(text))) {
            //   var1 = var2 = conv.i(ldloc(pinnedVar))
            //   if (logicnot(logicnot(var1))) {
            //     var2 = add(var1, call(RuntimeHelpers::get_OffsetToStringData))
            //   }
            //   stloc(ptrVar, var2)
            //   ...

            if (pos >= body.Count)
            {
                return(false);
            }

            ILVariable   var1, var2;
            ILExpression varAssignment, ptrInitialization;

            if (!(body[pos].Match(ILCode.Stloc, out var1, out varAssignment) && varAssignment.Match(ILCode.Stloc, out var2, out ptrInitialization)))
            {
                return(false);
            }
            if (!(var1.IsGenerated && var2.IsGenerated))
            {
                return(false);
            }
            if (ptrInitialization.Code == ILCode.Conv_I || ptrInitialization.Code == ILCode.Conv_U)
            {
                ptrInitialization = ptrInitialization.Arguments[0];
            }
            if (!ptrInitialization.MatchLdloc(pinnedVar))
            {
                return(false);
            }

            ILCondition ifStmt = body[pos + 1] as ILCondition;

            if (!(ifStmt != null && ifStmt.TrueBlock != null && ifStmt.TrueBlock.Body.Count == 1 && (ifStmt.FalseBlock == null || ifStmt.FalseBlock.Body.Count == 0)))
            {
                return(false);
            }
            if (!UnpackDoubleNegation(ifStmt.Condition).MatchLdloc(var1))
            {
                return(false);
            }
            ILVariable   assignedVar;
            ILExpression assignedExpr;

            if (!(ifStmt.TrueBlock.Body[0].Match(ILCode.Stloc, out assignedVar, out assignedExpr) && assignedVar == var2 && assignedExpr.Code == ILCode.Add))
            {
                return(false);
            }
            MethodReference calledMethod;

            if (!(assignedExpr.Arguments[0].MatchLdloc(var1)))
            {
                return(false);
            }
            if (!(assignedExpr.Arguments[1].Match(ILCode.Call, out calledMethod) || assignedExpr.Arguments[1].Match(ILCode.CallGetter, out calledMethod)))
            {
                return(false);
            }
            if (!(calledMethod.Name == "get_OffsetToStringData" && calledMethod.DeclaringType.FullName == "System.Runtime.CompilerServices.RuntimeHelpers"))
            {
                return(false);
            }

            ILVariable pointerVar;

            if (body[pos + 2].Match(ILCode.Stloc, out pointerVar, out assignedExpr) && assignedExpr.MatchLdloc(var2))
            {
                pos += 3;
                fixedStmtInitializer.Operand = pointerVar;
                return(true);
            }
            return(false);
        }
示例#21
0
        public Dictionary <int, EventRegistration[]> DecompileEventMappings(string fullTypeName)
        {
            var            result = new Dictionary <int, EventRegistration[]>();
            TypeDefinition type   = this.assembly.MainModule.GetType(fullTypeName);

            if (type == null)
            {
                return(result);
            }

            MethodDefinition def = null;

            foreach (var method in type.Methods)
            {
                if (method.Name == "System.Windows.Markup.IComponentConnector.Connect")
                {
                    def = method;
                    break;
                }
            }

            if (def == null)
            {
                return(result);
            }

            // decompile method and optimize the switch
            ILBlock      ilMethod   = new ILBlock();
            ILAstBuilder astBuilder = new ILAstBuilder();

            ilMethod.Body = astBuilder.Build(def, true);
            ILAstOptimizer optimizer = new ILAstOptimizer();
            var            context   = new DecompilerContext(type.Module)
            {
                CurrentMethod = def, CurrentType = type
            };

            optimizer.Optimize(context, ilMethod, ILAstOptimizationStep.RemoveRedundantCode3);

            ILSwitch    ilSwitch  = ilMethod.Body.OfType <ILSwitch>().FirstOrDefault();
            ILCondition condition = ilMethod.Body.OfType <ILCondition>().FirstOrDefault();

            if (ilSwitch != null)
            {
                foreach (var caseBlock in ilSwitch.CaseBlocks)
                {
                    if (caseBlock.Values == null)
                    {
                        continue;
                    }
                    var events = FindEvents(caseBlock);
                    foreach (int id in caseBlock.Values)
                    {
                        result.Add(id, events);
                    }
                }
            }
            else if (condition != null)
            {
                result.Add(1, FindEvents(condition.FalseBlock));
            }

            return(result);
        }
示例#22
0
        List <ILNode> FindConditions(HashSet <ControlFlowNode> scope, ControlFlowNode entryNode)
        {
            List <ILNode> result = new List <ILNode>();

            // Do not modify entry data
            scope = new HashSet <ControlFlowNode>(scope);

            Stack <ControlFlowNode> agenda = new Stack <ControlFlowNode>();

            agenda.Push(entryNode);
            while (agenda.Count > 0)
            {
                ControlFlowNode node = agenda.Pop();

                // Find a block that represents a simple condition
                if (scope.Contains(node))
                {
                    ILBasicBlock block = (ILBasicBlock)node.UserData;

                    {
                        IList <ILExpression> conditions;
                        ILLabel fallLabel;
                        // Switch
                        FakeSwitch fswitch;
                        if (block.MatchLastAndBr(GMCode.Switch, out fswitch, out conditions, out fallLabel))
                        {
                            ILSwitch ilSwitch = new ILSwitch()
                            {
                                Condition = fswitch.SwitchExpression
                            };
                            block.Body[block.Body.Count - 2] = ilSwitch; // replace it, nothing else needs to be done!
                            result.Add(block);                           // except add it to the result, DOLT

                            scope.RemoveOrThrow(node);                   // Remove the item so that it is not picked up as content

                            // Pull in code of cases
                            ControlFlowNode fallTarget = null;
                            labelToCfNode.TryGetValue(fallLabel, out fallTarget);

                            HashSet <ControlFlowNode> frontiers = new HashSet <ControlFlowNode>();
                            if (fallTarget != null)
                            {
                                frontiers.UnionWith(fallTarget.DominanceFrontier.Except(new[] { fallTarget }));
                            }

                            foreach (ILLabel condLabel in fswitch.CaseExpressions.Select(x => x.Value))
                            {
                                ControlFlowNode condTarget = null;
                                labelToCfNode.TryGetValue(condLabel, out condTarget);
                                if (condTarget != null)
                                {
                                    frontiers.UnionWith(condTarget.DominanceFrontier.Except(new[] { condTarget }));
                                }
                            }
                            for (int i = 0; i < fswitch.CaseExpressions.Count; i++)
                            {
                                ILLabel condLabel = fswitch.CaseExpressions[i].Value;

                                // Find or create new case block
                                ILSwitch.ILCase caseBlock = ilSwitch.Cases.FirstOrDefault(b => b.EntryGoto.Operand == condLabel);
                                if (caseBlock == null)
                                {
                                    caseBlock = new ILSwitch.ILCase()
                                    {
                                        Values    = new List <ILExpression>(),
                                        EntryGoto = new ILExpression(GMCode.B, condLabel)
                                    };
                                    ilSwitch.Cases.Add(caseBlock);

                                    ControlFlowNode condTarget = null;
                                    labelToCfNode.TryGetValue(condLabel, out condTarget);
                                    if (condTarget != null && !frontiers.Contains(condTarget))
                                    {
                                        HashSet <ControlFlowNode> content = FindDominatedNodes(scope, condTarget);
                                        scope.ExceptWith(content);
                                        foreach (var con in FindConditions(content, condTarget))
                                        {
                                            caseBlock.Body.Add(con);
                                        }
                                        //   caseBlock.Body.AddRange(FindConditions(content, condTarget));
                                        // Add explicit break which should not be used by default, but the goto removal might decide to use it
                                        caseBlock.Body.Add(new ILBasicBlock()
                                        {
                                            Body =
                                            {
                                                ILLabel.Generate("SwitchBreak",            (int)nextLabelIndex++),
                                                new ILExpression(GMCode.LoopOrSwitchBreak, null)
                                            }
                                        });
                                    }
                                }
                                caseBlock.Values.Add(fswitch.CaseExpressions[i].Key);
                            }

                            // Heuristis to determine if we want to use fallthough as default case
                            if (fallTarget != null && !frontiers.Contains(fallTarget))
                            {
                                HashSet <ControlFlowNode> content = FindDominatedNodes(scope, fallTarget);
                                if (content.Any())
                                {
                                    var caseBlock = new ILSwitch.ILCase()
                                    {
                                        EntryGoto = new ILExpression(GMCode.B, fallLabel)
                                    };
                                    ilSwitch.Cases.Add(caseBlock);
                                    block.Body.RemoveTail(GMCode.B);

                                    scope.ExceptWith(content);
                                    foreach (var con in FindConditions(content, fallTarget))
                                    {
                                        caseBlock.Body.Add(con);
                                    }

                                    // Add explicit break which should not be used by default, but the goto removal might decide to use it
                                    caseBlock.Body.Add(new ILBasicBlock()
                                    {
                                        Body =
                                        {
                                            ILLabel.Generate("SwitchBreak",            (int)nextLabelIndex++),
                                            new ILExpression(GMCode.LoopOrSwitchBreak, null)
                                        }
                                    });
                                }
                            }
                        }
                        //   Debug.Assert((block.Body.First() as ILLabel).Name != "L1938");
                        // Two-way branch
                        ILLabel trueLabel;
                        ILLabel falseLabel;
                        IList <ILExpression> condExprs;
                        if (block.MatchLastAndBr(GMCode.Bt, out trueLabel, out condExprs, out falseLabel) && // be sure to invert this condition
                            condExprs.Count > 0)     // its resolved
                        {
                            ILExpression   condExpr = condExprs[0];
                            IList <ILNode> body     = block.Body;
                            // this is a simple condition, skip anything short curiket for now
                            // Match a condition patern
                            // Convert the brtrue to ILCondition
                            ILCondition ilCond = new ILCondition()
                            {
                                Condition = condExpr, //code == GMCode.Bf ? condExpr : condExpr.NegateCondition(),
                                TrueBlock = new ILBlock()
                                {
                                    EntryGoto = new ILExpression(GMCode.B, trueLabel)
                                },
                                FalseBlock = new ILBlock()
                                {
                                    EntryGoto = new ILExpression(GMCode.B, falseLabel)
                                }
                            };
                            block.Body.RemoveTail(GMCode.Bt, GMCode.B);
                            block.Body.Add(ilCond);
                            result.Add(block);

                            // Remove the item immediately so that it is not picked up as content
                            scope.RemoveOrThrow(node);

                            ControlFlowNode trueTarget = null;
                            labelToCfNode.TryGetValue(trueLabel, out trueTarget);
                            ControlFlowNode falseTarget = null;
                            labelToCfNode.TryGetValue(falseLabel, out falseTarget);

                            // Pull in the conditional code
                            if (trueTarget != null && HasSingleEdgeEnteringBlock(trueTarget))
                            {
                                HashSet <ControlFlowNode> content = FindDominatedNodes(scope, trueTarget);
                                scope.ExceptWith(content);
                                foreach (var con in FindConditions(content, trueTarget))
                                {
                                    ilCond.TrueBlock.Body.Add(con);
                                }
                            }
                            if (falseTarget != null && HasSingleEdgeEnteringBlock(falseTarget))
                            {
                                HashSet <ControlFlowNode> content = FindDominatedNodes(scope, falseTarget);
                                scope.ExceptWith(content);
                                foreach (var con in FindConditions(content, falseTarget))
                                {
                                    ilCond.FalseBlock.Body.Add(con);
                                }
                            }
                        }
                    }

                    // Add the node now so that we have good ordering
                    if (scope.Contains(node))
                    {
                        result.Add((ILNode)node.UserData);
                        scope.Remove(node);
                    }
                }

                // depth-first traversal of dominator tree
                for (int i = node.DominatorTreeChildren.Count - 1; i >= 0; i--)
                {
                    agenda.Push(node.DominatorTreeChildren[i]);
                }
            }

            // Add whatever is left
            foreach (var node in scope)
            {
                result.Add((ILNode)node.UserData);
            }

            return(result);
        }
		List<ILNode> FindConditions(HashSet<ControlFlowNode> scope, ControlFlowNode entryNode)
		{
			List<ILNode> result = new List<ILNode>();
			
			// Do not modify entry data
			scope = new HashSet<ControlFlowNode>(scope);
			
			Stack<ControlFlowNode> agenda  = new Stack<ControlFlowNode>();
			agenda.Push(entryNode);
			while(agenda.Count > 0) {
				ControlFlowNode node = agenda.Pop();
				
				// Find a block that represents a simple condition
				if (scope.Contains(node)) {
					
					ILBasicBlock block = (ILBasicBlock)node.UserData;
					
					{
						// Switch
						ILLabel[] caseLabels;
						ILExpression switchArg;
						ILLabel fallLabel;
						if (block.MatchLastAndBr(ILCode.Switch, out caseLabels, out switchArg, out fallLabel)) {
							
							// Replace the switch code with ILSwitch
							ILSwitch ilSwitch = new ILSwitch() { Condition = switchArg };
							block.Body.RemoveTail(ILCode.Switch, ILCode.Br);
							block.Body.Add(ilSwitch);
							block.Body.Add(new ILExpression(ILCode.Br, fallLabel));
							result.Add(block);

							// Remove the item so that it is not picked up as content
							scope.RemoveOrThrow(node);
							
							// Find the switch offset
							int addValue = 0;
							List<ILExpression> subArgs;
							if (ilSwitch.Condition.Match(ILCode.Sub, out subArgs) && subArgs[1].Match(ILCode.Ldc_I4, out addValue)) {
								ilSwitch.Condition = subArgs[0];
							}
							
							// Pull in code of cases
							ControlFlowNode fallTarget = null;
							labelToCfNode.TryGetValue(fallLabel, out fallTarget);
							
							HashSet<ControlFlowNode> frontiers = new HashSet<ControlFlowNode>();
							if (fallTarget != null)
								frontiers.UnionWith(fallTarget.DominanceFrontier.Except(new [] { fallTarget }));
							
							foreach(ILLabel condLabel in caseLabels) {
								ControlFlowNode condTarget = null;
								labelToCfNode.TryGetValue(condLabel, out condTarget);
								if (condTarget != null)
									frontiers.UnionWith(condTarget.DominanceFrontier.Except(new [] { condTarget }));
							}
							
							for (int i = 0; i < caseLabels.Length; i++) {
								ILLabel condLabel = caseLabels[i];
								
								// Find or create new case block
								ILSwitch.CaseBlock caseBlock = ilSwitch.CaseBlocks.FirstOrDefault(b => b.EntryGoto.Operand == condLabel);
								if (caseBlock == null) {
									caseBlock = new ILSwitch.CaseBlock() {
										Values = new List<int>(),
										EntryGoto = new ILExpression(ILCode.Br, condLabel)
									};
									ilSwitch.CaseBlocks.Add(caseBlock);
									
									ControlFlowNode condTarget = null;
									labelToCfNode.TryGetValue(condLabel, out condTarget);
									if (condTarget != null && !frontiers.Contains(condTarget)) {
										HashSet<ControlFlowNode> content = FindDominatedNodes(scope, condTarget);
										scope.ExceptWith(content);
										caseBlock.Body.AddRange(FindConditions(content, condTarget));
										// Add explicit break which should not be used by default, but the goto removal might decide to use it
										caseBlock.Body.Add(new ILBasicBlock() {
											Body = {
												new ILLabel() { Name = "SwitchBreak_" + (nextLabelIndex++) },
												new ILExpression(ILCode.LoopOrSwitchBreak, null)
											}
										});
									}
								}
								caseBlock.Values.Add(i + addValue);
							}
							
							// Heuristis to determine if we want to use fallthough as default case
							if (fallTarget != null && !frontiers.Contains(fallTarget)) {
								HashSet<ControlFlowNode> content = FindDominatedNodes(scope, fallTarget);
								if (content.Any()) {
									var caseBlock = new ILSwitch.CaseBlock() { EntryGoto = new ILExpression(ILCode.Br, fallLabel) };
									ilSwitch.CaseBlocks.Add(caseBlock);
									block.Body.RemoveTail(ILCode.Br);
									
									scope.ExceptWith(content);
									caseBlock.Body.AddRange(FindConditions(content, fallTarget));
									// Add explicit break which should not be used by default, but the goto removal might decide to use it
									caseBlock.Body.Add(new ILBasicBlock() {
										Body = {
											new ILLabel() { Name = "SwitchBreak_" + (nextLabelIndex++) },
											new ILExpression(ILCode.LoopOrSwitchBreak, null)
										}
									});
								}
							}
						}
						
						// Two-way branch
						ILExpression condExpr;
						ILLabel trueLabel;
						ILLabel falseLabel;
						if(block.MatchLastAndBr(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel)) {
							
							// Swap bodies since that seems to be the usual C# order
							ILLabel temp = trueLabel;
							trueLabel = falseLabel;
							falseLabel = temp;
							condExpr = new ILExpression(ILCode.LogicNot, null, condExpr);
							
							// Convert the brtrue to ILCondition
							ILCondition ilCond = new ILCondition() {
								Condition  = condExpr,
								TrueBlock  = new ILBlock() { EntryGoto = new ILExpression(ILCode.Br, trueLabel) },
								FalseBlock = new ILBlock() { EntryGoto = new ILExpression(ILCode.Br, falseLabel) }
							};
							block.Body.RemoveTail(ILCode.Brtrue, ILCode.Br);
							block.Body.Add(ilCond);
							result.Add(block);
							
							// Remove the item immediately so that it is not picked up as content
							scope.RemoveOrThrow(node);
							
							ControlFlowNode trueTarget = null;
							labelToCfNode.TryGetValue(trueLabel, out trueTarget);
							ControlFlowNode falseTarget = null;
							labelToCfNode.TryGetValue(falseLabel, out falseTarget);
							
							// Pull in the conditional code
							if (trueTarget != null && HasSingleEdgeEnteringBlock(trueTarget)) {
								HashSet<ControlFlowNode> content = FindDominatedNodes(scope, trueTarget);
								scope.ExceptWith(content);
								ilCond.TrueBlock.Body.AddRange(FindConditions(content, trueTarget));
							}
							if (falseTarget != null && HasSingleEdgeEnteringBlock(falseTarget)) {
								HashSet<ControlFlowNode> content = FindDominatedNodes(scope, falseTarget);
								scope.ExceptWith(content);
								ilCond.FalseBlock.Body.AddRange(FindConditions(content, falseTarget));
							}
						}
					}
					
					// Add the node now so that we have good ordering
					if (scope.Contains(node)) {
						result.Add((ILNode)node.UserData);
						scope.Remove(node);
					}
				}

				// depth-first traversal of dominator tree
				for (int i = node.DominatorTreeChildren.Count - 1; i >= 0; i--) {
					agenda.Push(node.DominatorTreeChildren[i]);
				}
			}
			
			// Add whatever is left
			foreach(var node in scope) {
				result.Add((ILNode)node.UserData);
			}
			
			return result;
		}
        void CachedDelegateInitializationWithLocal(ILBlock block, ref int i)
        {
            // if (logicnot(ldloc(v))) {
            //     stloc(v, newobj(Action::.ctor, ldloc(displayClass), ldftn(method)))
            // } else {
            // }
            // ...(..., ldloc(v), ...)

            ILCondition c = block.Body[i] as ILCondition;

            if (c == null || c.Condition == null && c.TrueBlock == null || c.FalseBlock == null)
            {
                return;
            }
            if (!(c.TrueBlock.Body.Count == 1 && c.FalseBlock.Body.Count == 0))
            {
                return;
            }
            if (!c.Condition.Match(ILCode.LogicNot))
            {
                return;
            }
            ILExpression condition = c.Condition.Arguments.Single() as ILExpression;

            if (condition == null || condition.Code != ILCode.Ldloc)
            {
                return;
            }
            ILVariable   v     = (ILVariable)condition.Operand;
            ILExpression stloc = c.TrueBlock.Body[0] as ILExpression;

            if (!(stloc != null && stloc.Code == ILCode.Stloc && (ILVariable)stloc.Operand == v))
            {
                return;
            }
            ILExpression newObj = stloc.Arguments[0];

            if (!(newObj.Code == ILCode.Newobj && newObj.Arguments.Count == 2))
            {
                return;
            }
            if (newObj.Arguments[0].Code != ILCode.Ldloc)
            {
                return;
            }
            if (newObj.Arguments[1].Code != ILCode.Ldftn)
            {
                return;
            }
            MethodDefinition anonymousMethod = ((MethodReference)newObj.Arguments[1].Operand).ResolveWithinSameModule();             // method is defined in current assembly

            if (!AstServices.Transforms.DelegateConstruction.IsAnonymousMethod(context, anonymousMethod))
            {
                return;
            }

            ILNode followingNode     = block.Body.ElementAtOrDefault(i + 1);
            int    ldlocOperandCount =
                followingNode
                .EnumerateSelfAndChildrenRecursive()
                .OfType <ILExpression>()
                .Count(
                    e =>
                    e.Code == ILCode.Ldloc &&
                    (ILVariable)e.Operand == v);

            if (followingNode != null && ldlocOperandCount == 1)
            {
                ILInlining inlining = new ILInlining(method);
                if (!(inlining.numLdloc.GetOrDefault(v) == 2 && inlining.numStloc.GetOrDefault(v) == 2 && inlining.numLdloca.GetOrDefault(v) == 0))
                {
                    return;
                }

                // Find the store instruction that initializes the local to null:
                foreach (ILBlock storeBlock in method.EnumerateSelfAndChildrenRecursive().OfType <ILBlock>())
                {
                    for (int j = 0; j < storeBlock.Body.Count; j++)
                    {
                        ILVariable   storedVar;
                        ILExpression storedExpr;
                        if (storeBlock.Body[j].Match(ILCode.Stloc, out storedVar, out storedExpr) && storedVar == v && storedExpr.Match(ILCode.Ldnull))
                        {
                            // Remove the instruction
                            storeBlock.Body.RemoveAt(j);
                            if (storeBlock == block && j < i)
                            {
                                i--;
                            }
                            break;
                        }
                    }
                }

                block.Body[i] = stloc;                 // remove the 'if (v==null)'
                inlining      = new ILInlining(method);
                inlining.InlineIfPossible(block.Body, ref i);
            }
        }