public YieldFieldsInformation(FieldDefinition stateHolderField, FieldDefinition currentItemField,
     VariableReference returnFlagVariable)
 {
     this.stateHolderField = stateHolderField;
     this.currentItemField = currentItemField;
     this.returnFlagVariable = returnFlagVariable;
 }
		static bool AreEquivalent (VariableReference source, VariableReference target)
		{
			IList<VariableDefinition> cv = Current.Body.Variables;
			IList<VariableDefinition> tv = Target.Body.Variables;
			return cv.Count > source.Index && tv.Count > target.Index ?
				cv [source.Index].VariableType.Equals (tv [target.Index].VariableType) : false;
		}
		protected override bool CheckTheLoop(WhileStatement theWhile, VariableReference forVariable)
		{
			bool isProperForVBForLoop = base.CheckTheLoop(theWhile, forVariable) && theWhile.Condition is BinaryExpression;

			if (!isProperForVBForLoop)
			{
				return false;
			}

			ExpressionStatement incrementCandidate = theWhile.Body.Statements[theWhile.Body.Statements.Count - 1] as ExpressionStatement;
			BinaryExpression assignmentExpression = incrementCandidate.Expression as BinaryExpression;
			if (assignmentExpression != null)
			{
				BinaryExpression incrementExpression = assignmentExpression.Right as BinaryExpression;
				if (incrementExpression != null && (incrementExpression.Operator == Ast.BinaryOperator.Add || incrementExpression.Operator == Ast.BinaryOperator.Subtract))
				{
					VariableReferenceExpression incrementVariableExpression = incrementExpression.Left as VariableReferenceExpression;
					if (incrementVariableExpression != null)
					{
						if (incrementVariableExpression.Variable == forVariable)
						{
							return true;
						}
					}
				}
			}

			return false;
		}
 public ClassHierarchyNode()
 {
     this.CanAssignTo = new HashSet<ClassHierarchyNode>();
     this.ContainedNodes = new HashSet<ClassHierarchyNode>();
     this.inferedType = null;
     this.variable = null;
     this.SubTypes = new HashSet<ClassHierarchyNode>();
 }
        internal static TypeReference ResolveVariableTypeIfNeeded(MethodReference method, VariableReference variable)
        {
            var genericInstanceMethod = method as GenericInstanceMethod;
            var declaringGenericInstanceType = method.DeclaringType as GenericInstanceType;

            if (genericInstanceMethod == null && declaringGenericInstanceType == null)
                return variable.VariableType;

            return ResolveIfNeeded (genericInstanceMethod, declaringGenericInstanceType, variable.VariableType);
        }
		protected bool IsAssignToVariableExpression(BinaryExpression theAssignExpression, out VariableReference theVariable)
		{
			theVariable = null;
			bool result = theAssignExpression != null && theAssignExpression.IsAssignmentExpression &&
					 (theAssignExpression.Left.CodeNodeType == CodeNodeType.VariableReferenceExpression ||
					  theAssignExpression.Left.CodeNodeType == CodeNodeType.VariableDeclarationExpression);
			if (result)
			{
				theVariable = GetVariableReferenceFromExpression(theAssignExpression.Left);
			}
			return result;
		}
        /// <summary>
        /// Determines the type of the <paramref name="variable"/> based on its usage.
        /// </summary>
        /// <param name="instruction">The instruction that uses the variable.</param>
        /// <param name="variable">Tha variable.</param>
        /// <returns>Returns the ClassHierarchyNode for the found type.</returns>
        public TypeReference GetUseExpressionTypeNode(Instruction instruction, Expression instructionExpression, VariableReference variable)
        {
            Code instrOpCode = instruction.OpCode.Code;
            if (instrOpCode == Code.Ldobj)
            {
                TypeReference tr = instruction.Operand as TypeReference;
                return tr;
            }
            if (IsConditionalBranch(instrOpCode))
            {
                return typeSystem.Boolean;
            }
            if (instrOpCode == Code.Pop)
            {
                return null;
            }

            return GetUseExpressionTypeNode(instructionExpression, variable);
        }
 /// <summary>
 /// Determines the type which the <paramref name="variable"/> should have, according to its usage in the <paramref name="expression"/>.
 /// </summary>
 /// <param name="expression">The expression that uses the variable.</param>
 /// <param name="variable">The variable whose type is being infered.</param>
 /// <returns>Returns the ClassHierarchyNode coresponding to the infered type.</returns>
 private TypeReference GetUseExpressionTypeNode(Expression expression, VariableReference variable)
 {
     switch (expression.CodeNodeType)
     {
         case CodeNodeType.BaseCtorExpression:
         case CodeNodeType.ThisCtorExpression:
         case CodeNodeType.MethodInvocationExpression:
         case CodeNodeType.PropertyReferenceExpression:
             return GetUseInMethodInvocation(expression as MethodInvocationExpression, variable);
         case CodeNodeType.BinaryExpression:
             return GetUseInBinaryExpression(expression as BinaryExpression, variable);
         case CodeNodeType.VariableDeclarationExpression:
             VariableDeclarationExpression vdEx = expression as VariableDeclarationExpression;
             return vdEx.Variable.VariableType;
         case CodeNodeType.VariableReferenceExpression:
             VariableReferenceExpression vrEx = expression as VariableReferenceExpression;
             return vrEx.Variable == variable ? vrEx.Variable.VariableType : null;
         case CodeNodeType.CastExpression:
         case CodeNodeType.SafeCastExpression:
             return typeSystem.Object;
         case CodeNodeType.ArrayIndexerExpression:
             return GetUseInArrayIndexer(expression as ArrayIndexerExpression, variable);
         case CodeNodeType.ObjectCreationExpression:
             return GetUseInObjectCreation(expression as ObjectCreationExpression, variable);
         case CodeNodeType.ReturnExpression:
             return methodContext.Method.FixedReturnType;
         case CodeNodeType.ArrayCreationExpression:
             return GetUseInArrayCreation(expression as ArrayCreationExpression, variable);
         case CodeNodeType.UnaryExpression:
             return GetUseExpressionTypeNode((expression as UnaryExpression).Operand, variable);
         case CodeNodeType.BoxExpression:
             return (expression as BoxExpression).BoxedAs;
         case CodeNodeType.ThrowExpression:
             return null;
         case CodeNodeType.FieldReferenceExpression:
             return (expression as FieldReferenceExpression).Field.DeclaringType;
         default:
             throw new ArgumentOutOfRangeException("Expression is not evaluated to any type.");
     }
 }
        /// <summary>
        /// Tries to get the variable that is used by the specified instruction.
        /// </summary>
        /// <param name="instruction"></param>
        /// <param name="varReference"></param>
        /// <returns>Flase if the instruction does not handle variables.</returns>
        public static bool TryGetVariableFromInstruction(Instruction instruction, IList<VariableDefinition> variableCollection,
            out VariableReference varReference)
        {
            switch (instruction.OpCode.Code)
            {
                case Code.Ldloc_0:
                case Code.Stloc_0:
                    varReference = variableCollection[0];
                    break;
                case Code.Ldloc_1:
                case Code.Stloc_1:
                    varReference = variableCollection[1];
                    break;
                case Code.Ldloc_2:
                case Code.Stloc_2:
                    varReference = variableCollection[2];
                    break;
                case Code.Ldloc_3:
                case Code.Stloc_3:
                    varReference = variableCollection[3];
                    break;
                case Code.Ldloc_S:
                case Code.Ldloca_S:
                case Code.Stloc_S:
                    varReference = instruction.Operand as VariableReference ?? variableCollection[(sbyte)instruction.Operand];
                    break;
                case Code.Ldloc:
                case Code.Ldloca:
                case Code.Stloc:
                    varReference = variableCollection[(int)instruction.Operand];
                    break;
                default:
                    varReference = null;
                    return false;
            }

            return true;
        }
        protected virtual bool CheckTheLoop(WhileStatement theWhile, VariableReference forVariable)
        {
            if (theWhile == null || theWhile.Body.Statements.Count < 2)
            {
                return false;
            }

            VariableFinder variableFinder = new VariableFinder(forVariable);
            if (!variableFinder.FindVariable(theWhile.Condition))
            {
                return false;
            }

            ExpressionStatement incrementCandidate = theWhile.Body.Statements[theWhile.Body.Statements.Count - 1] as ExpressionStatement;
            VariableReference incrementVariable;
            if (incrementCandidate == null || !TryGetAssignedVariable(incrementCandidate, out incrementVariable) || forVariable != incrementVariable)
            {
                return false;
            }

            ContinueFinder continueFinder = new ContinueFinder();
            return !continueFinder.FindContinue(theWhile.Body);
        }
 private void ClearState()
 {
     insideTry = false;
     foundEnumeratorAssignment = false;
     foundWhile = false;
     foreachCollection = null;
     foreachVariable = null;
     foreachVariableInstructions.Clear();
     foreachCollectionInstructions.Clear();
     foreachBody = new BlockStatement();
     theEnumerator = null;
     theTry = null;
     @foreach = null;
     enumeratorAssignmentStatement = null;
     foreachVariableType = null;
     isEnumeratorUsedInsideForEach = false;
     foreachConditionInstructions = null;
 }
		public static bool FindVariableInExpression (VariableReference variable, Expression expression)
		{
			var matcher = new VariableMatcher (variable);
			matcher.Visit (expression);
			return matcher.Match;
		}
		VariableMatcher (VariableReference variable)
		{
			this.variable = variable;
		}
		protected string GetVariableName(VariableReference variable)
		{
			VariableDefinition variableDefinition = variable.Resolve();

			string result;
			if (!GetCurrentMethodContext().VariableDefinitionToNameMap.TryGetValue(variableDefinition, out result))
			{
				result = variableDefinition.Name;
			}

			return result;
		}
Example #15
0
 void addVariableReference(VariableReference v)
 {
     if (v == null)
         return;
     pushMember(v.VariableType);
 }
Example #16
0
 public SsaVariable GetOriginalVariable(VariableReference variable)
 {
     return locals[variable.Index];
 }
        /// <summary>
        /// Determines if the use of <paramref name="variable"/> in <paramref name="useExpression"/> requires a cast.
        /// </summary>
        /// <param name="useExpression">The expression being checked.</param>
        /// <param name="variable">The variable that might need to be casted.</param>
        private void AddCastIfNeeded(Expression useExpression, VariableReference variable)
        {
            switch (useExpression.CodeNodeType)
            {
                case CodeNodeType.MethodInvocationExpression:
                    MethodInvocationExpression miEx = useExpression as MethodInvocationExpression;
                    Expression argument = miEx.Arguments.FirstOrDefault(x => x.CodeNodeType == CodeNodeType.VariableReferenceExpression &&
                                                                                    (x as VariableReferenceExpression).Variable == variable);
                    if (argument != null)
                    {
                        ///The variable is passed as argument to the method.
                        int argumentIndex = miEx.Arguments.IndexOf(argument);
                        TypeReference argumentType = miEx.MethodExpression.Method.Parameters[argumentIndex].ResolveParameterType(miEx.MethodExpression.Method);
                        if (!IsSubtype(argumentType, variable.VariableType))
                        {
                            if (argumentType.IsPrimitive && variable.VariableType.IsPrimitive)
                            {
                                ///Integer values are not in inheritance relations. Some of them, however, can be expanded to bigger types
                                ///automatically, without the addition of a cast, i.e. Byte variable can be passed as int parameter without the
                                ///need to include a cast.
                                TypeReference containingType = ExpressionTypeInferer.GetContainingType(argumentType.Resolve(), variable.VariableType.Resolve());
                                if (containingType.FullName == argumentType.FullName)
                                {
                                    ///Then the type of the argument contains the type of the variable, thus no cast is needed.
                                    return;
                                }
                            }

                            ///Then a cast is needed.
                            miEx.Arguments[argumentIndex] = new CastExpression(argument, argumentType, null);
                            ///This should be enough to update the expression everywhere it is seen.
                        }
                    }
                    else
                    {
                        /// Then the variable is the object from which the method is called
                        /// variable.SomeMethod(...);
                        Expression target = miEx.MethodExpression.Target;
                        if (target.CodeNodeType == CodeNodeType.VariableReferenceExpression && (target as VariableReferenceExpression).Variable == variable)
                        {
                            TypeReference targetType = miEx.MethodExpression.Method.DeclaringType;
                            if (!IsSubtype(targetType, variable.VariableType))
                            {
                                miEx.MethodExpression.Target = new CastExpression(target, targetType, null);
                            }
                        }
                        else
                        {
                            ///This should not be reachable, but anyway.
                            AddCastIfNeeded(target, variable);
                        }

                    }
                    break;
                case CodeNodeType.BinaryExpression:
                    BinaryExpression binEx = useExpression as BinaryExpression;
                    if (binEx.Operator == BinaryOperator.Assign)
                    {
                        if (binEx.Right.CodeNodeType == CodeNodeType.VariableReferenceExpression &&
                            (binEx.Right as VariableReferenceExpression).Variable == variable)
                        {
                            TypeReference assignedAs = binEx.Left.ExpressionType;
                            ///binex.Right should be VariableReferenceExpression to 'variable'.
                            if (!IsSubtype(assignedAs, variable.VariableType))
                            {
                                binEx.Right = new CastExpression(binEx.Right, assignedAs, null);
                            }
                        }
                    }
                    break;
                //default:
                //throw new NotSupportedException("Not supported cast expression.");
            }
        }
		private void PushVariableReference (VariableReference variable)
		{
			Push (new VariableReferenceExpression (variable));
		}
        private bool IsEnumeratorAssignment(Expression expression)
        {
            BinaryExpression assignment = expression as BinaryExpression;
            if (assignment == null || !assignment.IsAssignmentExpression)
            {
                return false;
            }
            Expression right = assignment.Right;
            MethodInvocationExpression supposedGetEnumerator;
            if (right is MethodInvocationExpression)
            {
                supposedGetEnumerator = right as MethodInvocationExpression;
                if (IsGetEnumerator(supposedGetEnumerator))
                {
                    if (assignment.Left as VariableReferenceExpression == null)
                    {
                        return false;
                    }

                    foreachCollectionInstructions.Clear();
                    foreachCollectionInstructions.AddRange(assignment.Left.UnderlyingSameMethodInstructions);
                    foreachCollectionInstructions.AddRange(assignment.MappedInstructions);
                    foreachCollectionInstructions.AddRange(supposedGetEnumerator.InvocationInstructions);
                    theEnumerator = (assignment.Left as VariableReferenceExpression).Variable;
                    return true;
                }
            }
            return false;
        }
 public GetCurrentFixer(VariableReference enumerator, VariableReference foreachVariable)
 {
     this.enumerator = enumerator;
     this.foreachVariable = foreachVariable;
 }
 protected override ClassHierarchyNode MergeWithVariableTypeIfNeeded(VariableReference variable, ClassHierarchyNode variableNode)
 {
     /// The variable node should not be merged with its type in integer inference, because
     /// that will efectively assume all phi variables are integers.
     return variableNode;
 }
 /// <summary>
 /// Checks if the type of <paramref name="variableReference"/> needs to be infered.
 /// </summary>
 /// <param name="variableReference">The variable in question.</param>
 /// <returns>Returns true, if the type of <paramref name="variableReference"/> needs to be infered.</returns>
 protected override bool ShouldConsiderVariable(VariableReference variableReference)
 {
     ///All phi variables, that were assigned Int32 at the total type inference might possibly have toghter types
     ///and thus need to be included.
     return variableReference.VariableType.FullName == "System.Int32";
 }
 private bool IsStackVariable(VariableReference varRef)
 {
     return methodContext.StackData.VariableToDefineUseInfo.ContainsKey(varRef.Resolve());
 }
        public Unit VisitInlineVar(Instruction instruction, VariableReference operand)
        {
            MarkLabel(instruction);

            var local = _locals[operand];
            _generator.Emit(_opCodeMapper.Map(instruction.OpCode), local);
            return Unit.Value;
        }
 public ForeachElementTypeFinder(VariableReference theEnumerator)
 {
     this.theEnumerator = theEnumerator;
 }
 public VariableReferenceExpression(VariableReference variable)
 {
     _variable = variable;
 }
 public IsEnumeratorUsedVisitor(VariableReference enumerator)
 {
     this.enumerator = enumerator;
     this.IsEnumeratorUsed = false;
 }
 public VariableFinder(VariableReference variable)
 {
     this.variable = variable;
 }
		private void PushVariableAssignement (VariableReference variable)
		{
			PushVariableAssignement (variable.Index);
		}
		void RemoveVariable (VariableReference reference)
		{
			RemoveVariable ((VariableDefinition) reference);
		}