Beispiel #1
0
 protected virtual ILWhileLoop VisitWhileLoop(ILWhileLoop whileLoop)
 {
     foreach (var child in whileLoop.GetChildren())
     {
         Visit(child);
     }
     return(whileLoop);
 }
Beispiel #2
0
 public virtual void Write(ILWhileLoop loop)
 {
     InsertLineInfo(loop);
     Write("while(");
     Write(loop.Condition); // want to make sure we are using the debug
     Write(")");
     WriteSingleLineOrBlock(loop.Body);
 }
Beispiel #3
0
        private void CompileLoop(ILWhileLoop node)
        {
            string labelsSufix = rnd.Next().ToString();

            string loopLabel = "loop" + labelsSufix;
            string exitLabel = "exit" + labelsSufix;

            codeGenerator.Label(loopLabel);

            if (node.Condition != null)
            {
                CompileCondition(new ILExpression(ILCode.LogicNot, null, node.Condition), exitLabel);
            }

            loopOrSwitchExitLabel.Push(exitLabel);
            loopContinueLabel.Push(loopLabel);
            CompileBlock(node.BodyBlock);
            loopOrSwitchExitLabel.Pop();
            loopContinueLabel.Pop();

            codeGenerator
            .Add(Java.OpCodes._goto, loopLabel)
            .Label(exitLabel);
        }
Beispiel #4
0
        public JSWhileLoop TranslateNode(ILWhileLoop loop)
        {
            JSExpression condition;
            if (loop.Condition != null)
                condition = TranslateNode(loop.Condition);
            else
                condition = JSLiteral.New(true);

            var result = new JSWhileLoop(condition);
            result.Label = String.Format("__loop{0}__", UnlabelledBlockCount++);
            Blocks.Push(result);

            var body = TranslateNode(loop.BodyBlock);

            Blocks.Pop();
            result.Statements.Add(body);
            return result;
        }
Beispiel #5
0
        List<ILNode> FindLoops(HashSet<ControlFlowNode> scope, ControlFlowNode entryPoint, bool excludeEntryPoint)
        {
            List<ILNode> result = new List<ILNode>();

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

                if (scope.Contains(node)
                        && node.DominanceFrontier.Contains(node)
                        && (node != entryPoint || !excludeEntryPoint))
                {
                    HashSet<ControlFlowNode> loopContents = FindDominatedNodes(scope, node);

                    ILWhileLoop loop = new ILWhileLoop();

                    ILCondition cond;
                    HashSet<ControlFlowNode> condNodes;
                    ILLabel condLabel;
                    if (TryMatchCondition(loopContents, new ControlFlowNode[]{}, node, out cond, out condNodes, out condLabel)) {
                        loopContents.ExceptWith(condNodes);
                        scope.ExceptWith(condNodes);
                        // Use loop to implement condition
                        loop.Condition      = cond.Condition;
                        loop.PreLoopLabel   = condLabel;
                        loop.PostLoopGoto   = cond.FalseBlock.EntryGoto;
                        loop.BodyBlock      = new ILBlock() { EntryGoto = cond.TrueBlock.EntryGoto };
                    } else {
                        // Give the block some explicit entry point
                        ILLabel entryLabel  = new ILLabel() { Name = "Loop_" + (nextBlockIndex++) };
                        loop.BodyBlock      = new ILBlock() { EntryGoto = new ILExpression(ILCode.Br, entryLabel) };
                        ((ILBasicBlock)node.UserData).Body.Insert(0, entryLabel);
                    }
                    loop.BodyBlock.Body = FindLoops(loopContents, node, true);

                    // Move the content into loop block
                    scope.ExceptWith(loopContents);
                    result.Add(loop);
                }

                // 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 scope) {
                result.Add((ILNode)node.UserData);
            }

            return result;
        }
Beispiel #6
0
		List<ILNode> FindLoops(HashSet<ControlFlowNode> scope, ControlFlowNode entryPoint, bool excludeEntryPoint)
		{
			List<ILNode> result = new List<ILNode>();
			
			// Do not modify entry data
			scope = new HashSet<ControlFlowNode>(scope);
			
			Queue<ControlFlowNode> agenda  = new Queue<ControlFlowNode>();
			agenda.Enqueue(entryPoint);
			while(agenda.Count > 0) {
				ControlFlowNode node = agenda.Dequeue();
				
				// If the node is a loop header
				if (scope.Contains(node)
				    && node.DominanceFrontier.Contains(node)
				    && (node != entryPoint || !excludeEntryPoint))
				{
					HashSet<ControlFlowNode> loopContents = FindLoopContent(scope, node);
					
					// If the first expression is a loop condition
					ILBasicBlock basicBlock = (ILBasicBlock)node.UserData;
					ILExpression condExpr;
					ILLabel trueLabel;
					ILLabel falseLabel;
					// It has to be just brtrue - any preceding code would introduce goto
					if(basicBlock.MatchSingleAndBr(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel))
					{
						ControlFlowNode trueTarget;
						labelToCfNode.TryGetValue(trueLabel, out trueTarget);
						ControlFlowNode falseTarget;
						labelToCfNode.TryGetValue(falseLabel, out falseTarget);
						
						// If one point inside the loop and the other outside
						if ((!loopContents.Contains(trueTarget) && loopContents.Contains(falseTarget)) ||
						    (loopContents.Contains(trueTarget) && !loopContents.Contains(falseTarget)) )
						{
							loopContents.RemoveOrThrow(node);
							scope.RemoveOrThrow(node);
							
							// If false means enter the loop
							if (loopContents.Contains(falseTarget) || falseTarget == node)
							{
								// Negate the condition
								condExpr = new ILExpression(ILCode.LogicNot, null, condExpr);
								ILLabel tmp = trueLabel;
								trueLabel = falseLabel;
								falseLabel = tmp;
							}
							
							ControlFlowNode postLoopTarget;
							labelToCfNode.TryGetValue(falseLabel, out postLoopTarget);
							if (postLoopTarget != null) {
								// Pull more nodes into the loop
								HashSet<ControlFlowNode> postLoopContents = FindDominatedNodes(scope, postLoopTarget);
								var pullIn = scope.Except(postLoopContents).Where(n => node.Dominates(n));
								loopContents.UnionWith(pullIn);
							}
							
							// Use loop to implement the brtrue
							var tail = basicBlock.Body.RemoveTail(ILCode.Brtrue, ILCode.Br);
							ILWhileLoop whileLoop;
							basicBlock.Body.Add(whileLoop = new ILWhileLoop() {
								Condition = condExpr,
								BodyBlock = new ILBlock() {
									EntryGoto = new ILExpression(ILCode.Br, trueLabel),
									Body = FindLoops(loopContents, node, false)
								}
							});
							if (context.CalculateILRanges) {
								whileLoop.ILRanges.AddRange(tail[0].ILRanges);  // no recursive add
								tail[1].AddSelfAndChildrenRecursiveILRanges(whileLoop.ILRanges);
							}
							basicBlock.Body.Add(new ILExpression(ILCode.Br, falseLabel));
							result.Add(basicBlock);
							
							scope.ExceptWith(loopContents);
						}
					}
					
					// Fallback method: while(true)
					if (scope.Contains(node)) {
						result.Add(new ILBasicBlock() {
							Body = new List<ILNode>() {
								new ILLabel() { Name = "Loop_" + (nextLabelIndex++).ToString() },
								new ILWhileLoop() {
									BodyBlock = new ILBlock() {
										EntryGoto = new ILExpression(ILCode.Br, (ILLabel)basicBlock.Body.First()),
										Body = FindLoops(loopContents, node, true)
									}
								},
							},
						});
						
						scope.ExceptWith(loopContents);
					}
				}

				// 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 scope) {
				result.Add((ILNode)node.UserData);
			}
			scope.Clear();
			
			return result;
		}
Beispiel #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());
        }
        List<ILNode> FindLoops(HashSet<ControlFlowNode> scope, ControlFlowNode entryPoint, bool excludeEntryPoint)
        {
            List<ILNode> result = new List<ILNode>();

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

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

                if (scope.Contains(node)
                    && node.DominanceFrontier.Contains(node)
                    && (node != entryPoint || !excludeEntryPoint))
                {
                    HashSet<ControlFlowNode> loopContents = FindLoopContent(scope, node);

                    ILWhileLoop loop = new ILWhileLoop();

                    ILBasicBlock basicBlock = node.UserData as ILBasicBlock;
                    ILExpression branchExpr = null;
                    ILLabel trueLabel = null;
                    ILLabel falseLabel = null;
                    if(basicBlock != null && IsConditionalBranch(basicBlock, ref branchExpr, ref trueLabel, ref falseLabel)) {
                        loopContents.Remove(node);
                        scope.Remove(node);
                        branchExpr.Operand = null;  // Do not keep label alive

                        // Use loop to implement condition
                        loop.Condition      = branchExpr;
                        loop.PreLoopLabel   = basicBlock.EntryLabel;
                        loop.PostLoopGoto   = new ILExpression(ILCode.Br, falseLabel);
                        loop.BodyBlock      = new ILBlock() { EntryGoto = new ILExpression(ILCode.Br, trueLabel) };
                    } else {
                        // Give the block some explicit entry point
                        ILLabel entryLabel  = new ILLabel() { Name = "Loop_" + (nextBlockIndex++) };
                        loop.BodyBlock      = new ILBlock() { EntryGoto = new ILExpression(ILCode.Br, entryLabel) };
                        ((ILBasicBlock)node.UserData).Body.Insert(0, entryLabel);
                    }
                    loop.BodyBlock.Body = FindLoops(loopContents, node, true);

                    // Move the content into loop block
                    scope.ExceptWith(loopContents);
                    result.Add(loop);
                }

                // 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 scope) {
                result.Add((ILNode)node.UserData);
            }
            scope.Clear();

            return result;
        }
Beispiel #10
0
 protected virtual ILWhileLoop VisitWhileLoop(ILWhileLoop whileLoop)
 {
     foreach (var child in whileLoop.GetChildren())
         Visit(child);
     return whileLoop;
 }
Beispiel #11
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);
            }
        }