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; }
void addVariableReference(VariableReference v) { if (v == null) return; pushMember(v.VariableType); }
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); }