Exemple #1
0
 protected virtual void OnPhiVariableAssigned(int instructionOffset, ClassHierarchyNode variableNode)
 {
     V_0 = this.offsetToExpression.get_Item(instructionOffset).get_ExpressionType();
     if (V_0 != null)
     {
         V_1 = this.GetTypeNode(V_0);
         V_1.AddSupertype(variableNode);
         dummyVar1 = this.resultingGraph.Add(V_1);
         return;
     }
     V_2 = this.GetVariables(instructionOffset).GetEnumerator();
     try
     {
         while (V_2.MoveNext())
         {
             V_3 = V_2.get_Current();
             V_1 = this.GetVariableNode(V_3);
             V_1.AddSupertype(variableNode);
             dummyVar0 = this.resultingGraph.Add(V_1);
         }
     }
     finally
     {
         if (V_2 != null)
         {
             V_2.Dispose();
         }
     }
     return;
 }
 protected void MergeNodes(ICollection <ClassHierarchyNode> nodeCollection)
 {
     if (nodeCollection.get_Count() <= 1)
     {
         return;
     }
     V_0 = new ClassHierarchyNode(nodeCollection);
     V_1 = V_0.get_ContainedNodes().GetEnumerator();
     try
     {
         while (V_1.MoveNext())
         {
             V_2       = V_1.get_Current();
             dummyVar0 = this.inferenceGraph.Remove(V_2);
         }
     }
     finally
     {
         if (V_1 != null)
         {
             V_1.Dispose();
         }
     }
     this.inferenceGraph.Add(V_0);
     return;
 }
        /// <summary>
        /// Handles the assignment of phi variables.
        /// </summary>
        /// <param name="instructionOffset">The offset of the instruction, that put the value on the stack.</param>
        /// <param name="variableNode">The graph node corresponding to the phi variable.</param>
        /// <param name="nodes">The graph.</param>
        protected override void OnPhiVariableAssigned(int instructionOffset, ClassHierarchyNode variableNode)
        {
            /// This key should allways be present.
            Expression instructionExpression = offsetToExpression[instructionOffset];
            /// Determine the type of the assigned value.
            TypeReference assignedType = instructionExpression.ExpressionType;

            if (instructionExpression is LiteralExpression)
            {
                int literal = (int)((instructionExpression as LiteralExpression).Value);
                if (literal == 0 || literal == 1)
                {
                    assignedType = typeSystem.Boolean;
                }
                else if (literal <= byte.MaxValue && literal >= byte.MinValue)
                {
                    assignedType = typeSystem.Byte;
                }
                else if (literal < char.MaxValue && literal >= char.MinValue)
                {
                    /// Both char and short can be used here.
                    assignedType = typeSystem.Char;
                }
            }
            /// Add the edge in the graph.
            ClassHierarchyNode supertypeNode = GetTypeNode(assignedType);

            supertypeNode.AddSupertype(variableNode);
            resultingGraph.Add(supertypeNode);
        }
        /// <summary>
        /// Handles all nodes that have single child constraint as described in <see cref="Chapter 6 Integer inference"/>
        /// in <see cref="Efficient Inference of Static Types for Java Bytecode.pdf"/>.
        /// </summary>
        private void MergeWithSingleChild()
        {
            bool merged = false;

            do
            {
                ICollection <ClassHierarchyNode> toMerge = null;
                foreach (ClassHierarchyNode node in inferenceGraph)
                {
                    if (!node.IsHardNode)
                    {
                        if (node.CanAssignTo.Count == 1 && node.SubTypes.Count == 0)
                        {
                            ClassHierarchyNode x = null;
                            //x = node.CanAssignTo.First(); w/o Linq
                            foreach (ClassHierarchyNode p in node.CanAssignTo)
                            {
                                x = p;
                                break;
                            }
                            toMerge = new ClassHierarchyNode[] { node, x };
                            merged  = true;
                            break;
                        }
                    }
                }
                if (merged)
                {
                    MergeNodes(toMerge);
                }
            } while (merged);
        }
Exemple #5
0
        /// <summary>
        /// Handles the assignment of phi variables.
        /// </summary>
        /// <param name="instructionOffset">The instruction that pushes the value on the stack.</param>
        /// <param name="variableNode">The graph node corresponding to the variable being assigned.</param>
        protected virtual void OnPhiVariableAssigned(int instructionOffset, ClassHierarchyNode variableNode)
        {
            Expression instructionExpression = offsetToExpression[instructionOffset]; // this key should allways be present
            //TypeReference assignedType = ExpressionTypeInferer.GetExpressionType(instructionExpression, context.Method.Module.TypeSystem);
            TypeReference      assignedType = instructionExpression.ExpressionType;
            ClassHierarchyNode supertypeNode;

            if (assignedType == null)
            {
                ///Then an expression, containing one or more phi variables is being assigned to another phi variable
                IEnumerable <VariableReference> usedPhiVariables = GetVariables(instructionOffset);

                //VariableReference assigningVariable = (instructionExpression as VariableReferenceExpression).Variable;
                foreach (VariableReference assigningVariable in usedPhiVariables)
                {
                    supertypeNode = GetVariableNode(assigningVariable);
                    supertypeNode.AddSupertype(variableNode);
                    resultingGraph.Add(supertypeNode);
                }
                return;
                //supertypeNode = GetVariableNode(assigningVariable);
            }
            supertypeNode = GetTypeNode(assignedType);
            supertypeNode.AddSupertype(variableNode);
            resultingGraph.Add(supertypeNode);
        }
 /// <summary>
 /// Handles the assignment of phi variables.
 /// </summary>
 /// <param name="instructionOffset">The offset of the instruction, that put the value on the stack.</param>
 /// <param name="variableNode">The graph node corresponding to the phi variable.</param>
 /// <param name="nodes">The graph.</param>
 protected override void OnPhiVariableAssigned(int instructionOffset, ClassHierarchyNode variableNode)
 {
     /// This key should allways be present.
     Expression instructionExpression = offsetToExpression[instructionOffset];
     /// Determine the type of the assigned value.
     TypeReference assignedType = instructionExpression.ExpressionType;
     if (instructionExpression is LiteralExpression)
     {
         int literal = (int)((instructionExpression as LiteralExpression).Value);
         if (literal == 0 || literal == 1)
         {
             assignedType = typeSystem.Boolean;
         }
         else if (literal <= byte.MaxValue && literal >= byte.MinValue)
         {
             assignedType = typeSystem.Byte;
         }
         else if (literal < char.MaxValue && literal >= char.MinValue)
         {
             /// Both char and short can be used here.
             assignedType = typeSystem.Char;
         }
     }
     /// Add the edge in the graph.
     ClassHierarchyNode supertypeNode = GetTypeNode(assignedType);
     supertypeNode.AddSupertype(variableNode);
     resultingGraph.Add(supertypeNode);
 }
Exemple #7
0
 private void AddEdge(ClassHierarchyNode biggerTypeNode, ClassHierarchyNode smallerTypeNode)
 {
     smallerTypeNode.AddSupertype(biggerTypeNode);
     dummyVar0 = this.resultingGraph.Add(smallerTypeNode);
     dummyVar1 = this.resultingGraph.Add(biggerTypeNode);
     return;
 }
Exemple #8
0
 protected override void OnPhiVariableAssigned(int instructionOffset, ClassHierarchyNode variableNode)
 {
     V_0 = this.offsetToExpression.get_Item(instructionOffset);
     V_1 = V_0.get_ExpressionType();
     if (V_0 as LiteralExpression != null)
     {
         V_3 = (Int32)(V_0 as LiteralExpression).get_Value();
         if (V_3 == 0 || V_3 == 1)
         {
             V_1 = this.typeSystem.get_Boolean();
         }
         else
         {
             if (V_3 > 0xff || V_3 < 0)
             {
                 if (V_3 < 0xffff && V_3 >= 0)
                 {
                     V_1 = this.typeSystem.get_Char();
                 }
             }
             else
             {
                 V_1 = this.typeSystem.get_Byte();
             }
         }
     }
     V_2 = this.GetTypeNode(V_1);
     V_2.AddSupertype(variableNode);
     dummyVar0 = this.resultingGraph.Add(V_2);
     return;
 }
 /// <summary>
 /// Adds an edge from <paramref name="smallerType"/> to <paramref name="biggerType"/>.
 /// </summary>
 /// <param name="biggerTypeNode">The type the edge points to.</param>
 /// <param name="smallerTypeNode">The type the edge comes from.</param>
 private void AddEdge(ClassHierarchyNode biggerTypeNode, ClassHierarchyNode smallerTypeNode)
 {
     // smallerTypeNode can assign to BiggerTypeNode
     smallerTypeNode.AddSupertype(biggerTypeNode);
     resultingGraph.Add(smallerTypeNode);
     resultingGraph.Add(biggerTypeNode);
 }
Exemple #10
0
        /// <summary>
        /// Adds the node, representing System.Object to the graph.
        /// </summary>
        private void AddObjectClassNodeIfMIssing()
        {
            TypeReference      tr         = typeSystem.Object;
            ClassHierarchyNode objectNode = GetTypeNode(tr);

            resultingGraph.Add(objectNode);
        }
        /// <summary>
        /// Realises the logic for merging with single parent.
        /// </summary>
        /// <param name="chooseParent">Predicate that determines if the parent node is legal to merge.</param>
        /// <returns>Returns true if there was a merge.</returns>
        private bool MergeSingleParent(Func <ClassHierarchyNode, bool> chooseParentPred)
        {
            bool result = false;

            ClassHierarchyNode[] toMerge = null;
            foreach (ClassHierarchyNode childNode in inferenceGraph)
            {
                if (childNode.IsHardNode)
                {
                    continue;
                }
                if (childNode.SubTypes.Count == 1)
                {
                    ClassHierarchyNode parentNode = childNode.SubTypes.First();
                    if (chooseParentPred(parentNode))
                    {
                        result  = true;
                        toMerge = new ClassHierarchyNode[] { childNode, parentNode };
                        break;
                    }
                }
            }
            if (result)
            {
                MergeNodes(toMerge);
            }
            return(result);
        }
Exemple #12
0
        /// <summary>
        /// Handles the case of PhiVariable usages.
        /// </summary>
        /// <param name="instructionOffset">The offset of the instruction that pops the variable from the stack.</param>
        /// <param name="variableNode">The graph node for the variable.</param>
        protected virtual void OnPhiVariableUsed(int instructionOffset, ClassHierarchyNode variableNode)
        {
            ///The usages of the variable bring no value to this algorithm. In the paper they are included, because in Java Bytecode the local method variables
            ///don't have type, and can be potentionally used before being assigned. Phi variables, however, are always assigned first and used later. Thus, the
            ///information from the assignments should be enough for legal type inference.
            return;
            //Instruction instr = offsetToInstruction[instructionOffset];
            //if (instr.OpCode.Code == Code.Dup || instr.OpCode.Code == Code.Pop)
            //{
            //    return;
            //}
            //ClassHierarchyNode typeNode = GetUseExpressionTypeNode(instr, record.Variable);


            ////this should not be happening when the array support is added
            //if (typeNode == null)
            //{
            //    //only phi variables were part of the expression
            //    List<ClassHierarchyNode> phiVariableNodes = GetUsedPhiVariableNodes(instr.Offset);
            //    for (int i = 0; i < phiVariableNodes.Count; i++)
            //    {
            //        for (int j = i + 1; j < phiVariableNodes.Count; j++)
            //        {
            //            //phi1 <-> phi2
            //            phiVariableNodes[i].AddSupertype(phiVariableNodes[j]);
            //            phiVariableNodes[j].AddSupertype(phiVariableNodes[i]);
            //        }
            //    }
            //    return;
            //}

            //variableNode.AddSupertype(typeNode);
            //nodes.Add(typeNode);
        }
 /// <summary>
 /// Adds <paramref name="supertype"/> to the collection of nodes, this one can assign to.
 /// Also adds this node in <paramref name="supertype"/>'s collection of nodes, that can assign to it.
 /// </summary>
 /// <param name="supertype">The node, representing supertype of the current node.</param>
 public void AddSupertype(ClassHierarchyNode supertype)
 {
     if (!CanAssignTo.Contains(supertype))
     {
         CanAssignTo.Add(supertype);
         supertype.SubTypes.Add(this);
     }
 }
Exemple #14
0
 public void AddSupertype(ClassHierarchyNode supertype)
 {
     if (!this.get_CanAssignTo().Contains(supertype))
     {
         this.get_CanAssignTo().Add(supertype);
         supertype.get_SubTypes().Add(this);
     }
     return;
 }
 /// <summary>
 /// Removes <paramref name="subType"/> from <paramref name="superType"/>'s collection of nodes, <paramref name="superType"/> can be assigned from.
 /// Also updates the collection of nodes <paramref name="subType"/> can assign to.
 /// </summary>
 /// <param name="superType"></param>
 /// <param name="subType"></param>
 private void RemoveSubtype(ClassHierarchyNode superType, ClassHierarchyNode subType)
 {
     if (!superType.SubTypes.Contains(subType))
     {
         throw new ArgumentOutOfRangeException(string.Format("No such relation between {0} and {1}.", this, subType));
     }
     superType.SubTypes.Remove(subType);
     subType.CanAssignTo.Remove(superType);
 }
Exemple #16
0
        private void MergeWithSingleChild()
        {
            V_0 = false;
            do
            {
                V_1 = null;
                V_2 = this.inferenceGraph.GetEnumerator();
                try
                {
                    while (V_2.MoveNext())
                    {
                        V_3 = V_2.get_Current();
                        if (V_3.get_IsHardNode() || V_3.get_CanAssignTo().get_Count() != 1 || V_3.get_SubTypes().get_Count() != 0)
                        {
                            continue;
                        }
                        V_4 = null;
                        V_5 = V_3.get_CanAssignTo().GetEnumerator();
                        try
                        {
                            if (V_5.MoveNext())
                            {
                                V_4 = V_5.get_Current();
                            }
                        }
                        finally
                        {
                            if (V_5 != null)
                            {
                                V_5.Dispose();
                            }
                        }
                        stackVariable27    = new ClassHierarchyNode[2];
                        stackVariable27[0] = V_3;
                        stackVariable27[1] = V_4;
                        V_1 = (ICollection <ClassHierarchyNode>)stackVariable27;
                        V_0 = true;
                        goto Label0;
                    }
                }
                finally
                {
                    if (V_2 != null)
                    {
                        V_2.Dispose();
                    }
                }
Label0:
                if (!V_0)
                {
                    continue;
                }
                this.MergeNodes(V_1);
            }while (V_0);
            return;
        }
Exemple #17
0
 protected override ClassHierarchyNode GetTypeNode(TypeReference assignedType)
 {
     V_0 = assignedType.get_FullName();
     if (!this.typeNameToNode.ContainsKey(V_0))
     {
         V_1 = new ClassHierarchyNode(assignedType);
         this.typeNameToNode.Add(V_0, V_1);
     }
     return(this.typeNameToNode.get_Item(V_0));
 }
Exemple #18
0
 private void RemoveBooleanAsASubtype(ClassHierarchyNode variableNode)
 {
     V_0 = this.GetTypeNode(this.typeSystem.get_Boolean());
     if (variableNode.get_SubTypes().Contains(V_0))
     {
         dummyVar0 = variableNode.get_SubTypes().Remove(V_0);
         dummyVar1 = V_0.get_CanAssignTo().Remove(variableNode);
     }
     return;
 }
 private void RemoveSubtype(ClassHierarchyNode superType, ClassHierarchyNode subType)
 {
     if (!superType.get_SubTypes().Contains(subType))
     {
         throw new ArgumentOutOfRangeException(String.Format("No such relation between {0} and {1}.", this, subType));
     }
     dummyVar0 = superType.get_SubTypes().Remove(subType);
     dummyVar1 = subType.get_CanAssignTo().Remove(superType);
     return;
 }
 /// <summary>
 /// Locates the node in the graph, holding <paramref name="assignedType"/>. If no such node exists, it's created.
 /// </summary>
 /// <param name="assignedType">The type we want to get the node for.</param>
 /// <returns>Returns the graph node.</returns>
 protected override ClassHierarchyNode GetTypeNode(TypeReference assignedType)
 {
     string typeName = assignedType.FullName;
     if (!typeNameToNode.ContainsKey(typeName))
     {
         ClassHierarchyNode typeNode = new ClassHierarchyNode(assignedType);
         typeNameToNode.Add(typeName, typeNode);
     }
     return typeNameToNode[typeName];
 }
        private void RemoveBooleanAsASubtype(ClassHierarchyNode variableNode)
        {
            ClassHierarchyNode booleanNode = GetTypeNode(typeSystem.Boolean);

            if (variableNode.SubTypes.Contains(booleanNode))
            {
                variableNode.SubTypes.Remove(booleanNode);
                booleanNode.CanAssignTo.Remove(variableNode);
            }
        }
Exemple #22
0
 protected virtual ClassHierarchyNode MergeWithVariableTypeIfNeeded(VariableReference variable, ClassHierarchyNode variableNode)
 {
     /// The node should be merget with its type in the normal inference.
     if (variable.VariableType != null)
     {
         ClassHierarchyNode variableTypeNode = GetTypeNode(variable.VariableType);
         variableNode = new ClassHierarchyNode(new ClassHierarchyNode[] { variableNode, variableTypeNode });
     }
     return(variableNode);
 }
        /// <summary>
        /// Handles the usage of phi variables.
        /// </summary>
        /// <param name="instructionOffset">The offset of the instruction, that pops the phi variable from the stack.</param>
        /// <param name="record">The VariableDefineUseRecord associated with the instruction.</param>
        /// <param name="variableNode">The node in the craph corresponding to the phi variable.</param>
        /// <param name="nodes"> The graph. </param>
        protected override void OnPhiVariableUsed(int instructionOffset, ClassHierarchyNode variableNode)
        {
            Instruction instr = offsetToInstruction[instructionOffset];

            if (instr.OpCode.Code == Code.Dup || instr.OpCode.Code == Code.Pop)
            {
                ///No information regarding the type of the phi variable can be extracted from pop/dup instructions
                return;
            }
            ///Get the use type of the phi variable.
            ClassHierarchyNode typeNode = GetUseExpressionTypeNode(instr, variableNode.Variable);

            if (instr.OpCode.Code == Code.Switch)
            {
                variableNode.AddSupertype(typeNode);
                resultingGraph.Add(typeNode);
                return;
            }

            ///It is possible, that a phi variable is being used with another one. This case needs special care.
            if (typeNode.NodeType.FullName == "System.Int32" && OnlyPhiVariablesUsed(offsetToExpression[instr.Offset]))
            {
                ///Only phi variables were part of the expression.
                List <ClassHierarchyNode> phiVariableNodes = GetUsedPhiVariableNodes(instr.Offset);
                for (int i = 0; i < phiVariableNodes.Count; i++)
                {
                    for (int j = i + 1; j < phiVariableNodes.Count; j++)
                    {
                        ///Add edge between the phi variables.
                        phiVariableNodes[i].AddSupertype(phiVariableNodes[j]);
                        phiVariableNodes[j].AddSupertype(phiVariableNodes[i]);
                    }
                }

                if (IsArithmeticOperation(instr.OpCode.Code))
                {
                    for (int i = 0; i < phiVariableNodes.Count; i++)
                    {
                        notPossibleBooleanNodes.Add(phiVariableNodes[i]);

                        ClassHierarchyNode integerTypeNode = GetTypeNode(typeSystem.Int32);
                        if (!integerTypeNode.CanAssignTo.Contains(phiVariableNodes[i]))
                        {
                            integerTypeNode.CanAssignTo.Add(phiVariableNodes[i]);
                            phiVariableNodes[i].SubTypes.Add(integerTypeNode);
                        }
                    }
                }

                return;
            }

            variableNode.AddSupertype(typeNode);
            resultingGraph.Add(typeNode);
        }
        /// <summary>
        /// Locates the node in the graph, holding <paramref name="assignedType"/>. If no such node exists, it's created.
        /// </summary>
        /// <param name="assignedType">The type we want to get the node for.</param>
        /// <returns>Returns the graph node.</returns>
        protected override ClassHierarchyNode GetTypeNode(TypeReference assignedType)
        {
            string typeName = assignedType.FullName;

            if (!typeNameToNode.ContainsKey(typeName))
            {
                ClassHierarchyNode typeNode = new ClassHierarchyNode(assignedType);
                typeNameToNode.Add(typeName, typeNode);
            }
            return(typeNameToNode[typeName]);
        }
        /// <summary>
        /// Handles the usage of phi variables.
        /// </summary>
        /// <param name="instructionOffset">The offset of the instruction, that pops the phi variable from the stack.</param>
        /// <param name="record">The VariableDefineUseRecord associated with the instruction.</param>
        /// <param name="variableNode">The node in the craph corresponding to the phi variable.</param>
        /// <param name="nodes"> The graph. </param>
        protected override void OnPhiVariableUsed(int instructionOffset, ClassHierarchyNode variableNode)
        {
            Instruction instr = offsetToInstruction[instructionOffset];
            if (instr.OpCode.Code == Code.Dup || instr.OpCode.Code == Code.Pop)
            {
                ///No information regarding the type of the phi variable can be extracted from pop/dup instructions
                return;
            }
            ///Get the use type of the phi variable.
            ClassHierarchyNode typeNode = GetUseExpressionTypeNode(instr, variableNode.Variable);

            if (instr.OpCode.Code == Code.Switch)
            {
                variableNode.AddSupertype(typeNode);
                resultingGraph.Add(typeNode);
                return;
            }

            ///It is possible, that a phi variable is being used with another one. This case needs special care.
            if (typeNode.NodeType.FullName == "System.Int32" && OnlyPhiVariablesUsed(offsetToExpression[instr.Offset]))
            {
                ///Only phi variables were part of the expression.
                List<ClassHierarchyNode> phiVariableNodes = GetUsedPhiVariableNodes(instr.Offset);
                for (int i = 0; i < phiVariableNodes.Count; i++)
                {
                    for (int j = i + 1; j < phiVariableNodes.Count; j++)
                    {
                        ///Add edge between the phi variables.
                        phiVariableNodes[i].AddSupertype(phiVariableNodes[j]);
                        phiVariableNodes[j].AddSupertype(phiVariableNodes[i]);
                    }
                }

                if (IsArithmeticOperation(instr.OpCode.Code))
                {
                    for (int i = 0; i < phiVariableNodes.Count; i++)
                    {
                        notPossibleBooleanNodes.Add(phiVariableNodes[i]);

                        ClassHierarchyNode integerTypeNode = GetTypeNode(typeSystem.Int32);
                        if (!integerTypeNode.CanAssignTo.Contains(phiVariableNodes[i]))
                        {
                            integerTypeNode.CanAssignTo.Add(phiVariableNodes[i]);
                            phiVariableNodes[i].SubTypes.Add(integerTypeNode);
                        }
                    }
                }

                return;
            }

            variableNode.AddSupertype(typeNode);
            resultingGraph.Add(typeNode);
        }
Exemple #26
0
        /// <summary>
        /// Finds the ClassHierarchyNode corresponding to the <paramref name="variable"/>. If no such node exists, it's created.
        /// </summary>
        /// <param name="variable">The variable we search the node for.</param>
        /// <returns>Returns the corresponding node in the graph.</returns>
        protected ClassHierarchyNode GetVariableNode(VariableReference variable)
        {
            string variableName = variable.Name;

            if (!variableNameToNode.ContainsKey(variableName))
            {
                ClassHierarchyNode variableNode = new ClassHierarchyNode(variable);
                variableNode = MergeWithVariableTypeIfNeeded(variable, variableNode);
                variableNameToNode.Add(variableName, variableNode);
            }
            return(variableNameToNode[variableName]);
        }
Exemple #27
0
 protected virtual ClassHierarchyNode MergeWithVariableTypeIfNeeded(VariableReference variable, ClassHierarchyNode variableNode)
 {
     if (variable.get_VariableType() != null)
     {
         V_0               = this.GetTypeNode(variable.get_VariableType());
         stackVariable8    = new ClassHierarchyNode[2];
         stackVariable8[0] = variableNode;
         stackVariable8[1] = V_0;
         variableNode      = new ClassHierarchyNode(stackVariable8);
     }
     return(variableNode);
 }
Exemple #28
0
        /// <summary>
        /// The entry point of the class.
        /// </summary>
        /// <returns>Returns a collection of all nodes in the built graph.</returns>
        internal ICollection <ClassHierarchyNode> BuildHierarchy(HashSet <VariableReference> resolvedVariables)
        {
            StackUsageData stackData = methodContext.StackData;

            foreach (KeyValuePair <VariableDefinition, StackVariableDefineUseInfo> pair in stackData.VariableToDefineUseInfo)
            {
                VariableDefinition variableDef = pair.Key;
                if (resolvedVariables.Contains(variableDef))
                {
                    continue;
                }
                ///As this method is shared with IntegerTypesHierarchyByilder here is where the check if the phi variable should be used comes in place.
                ///For the purposes of TypeInferer all variables that don't have type yet should be considered.
                ///for the purposes of IntegerTypeInferer only variabless assigned Int32 as their type should be considered.
                if (!ShouldConsiderVariable(variableDef))
                {
                    continue;
                }

                ///Add a node for each variable and process all its appearances in the code.

                ClassHierarchyNode variableNode = GetVariableNode(variableDef);
                resultingGraph.Add(variableNode);

                foreach (int defineOffset in pair.Value.DefinedAt)
                {
                    OnPhiVariableAssigned(defineOffset, variableNode);
                }

                foreach (int usageOffset in pair.Value.UsedAt)
                {
                    OnPhiVariableUsed(usageOffset, variableNode);
                }
            }

            RemoveImpossibleEdges();

            HashSet <ClassHierarchyNode> hardNodes = new HashSet <ClassHierarchyNode>();

            foreach (ClassHierarchyNode node in resultingGraph)
            {
                if (node.IsHardNode)
                {
                    hardNodes.Add(node);
                }
            }

            BuildUpHardNodesHierarchy(hardNodes);

            return(resultingGraph);
        }
Exemple #29
0
 protected override void OnPhiVariableUsed(int instructionOffset, ClassHierarchyNode variableNode)
 {
     V_0 = this.offsetToInstruction.get_Item(instructionOffset);
     if (V_0.get_OpCode().get_Code() == 36 || V_0.get_OpCode().get_Code() == 37)
     {
         return;
     }
     V_1 = this.GetUseExpressionTypeNode(V_0, variableNode.get_Variable());
     if (V_0.get_OpCode().get_Code() == 68)
     {
         variableNode.AddSupertype(V_1);
         dummyVar0 = this.resultingGraph.Add(V_1);
         return;
     }
     if (!String.op_Equality(V_1.get_NodeType().get_FullName(), "System.Int32") || !this.OnlyPhiVariablesUsed(this.offsetToExpression.get_Item(V_0.get_Offset())))
     {
         variableNode.AddSupertype(V_1);
         dummyVar2 = this.resultingGraph.Add(V_1);
         return;
     }
     V_3 = this.GetUsedPhiVariableNodes(V_0.get_Offset());
     V_4 = 0;
     while (V_4 < V_3.get_Count())
     {
         V_5 = V_4 + 1;
         while (V_5 < V_3.get_Count())
         {
             V_3.get_Item(V_4).AddSupertype(V_3.get_Item(V_5));
             V_3.get_Item(V_5).AddSupertype(V_3.get_Item(V_4));
             V_5 = V_5 + 1;
         }
         V_4 = V_4 + 1;
     }
     if (this.IsArithmeticOperation(V_0.get_OpCode().get_Code()))
     {
         V_6 = 0;
         while (V_6 < V_3.get_Count())
         {
             dummyVar1 = this.notPossibleBooleanNodes.Add(V_3.get_Item(V_6));
             V_7       = this.GetTypeNode(this.typeSystem.get_Int32());
             if (!V_7.get_CanAssignTo().Contains(V_3.get_Item(V_6)))
             {
                 V_7.get_CanAssignTo().Add(V_3.get_Item(V_6));
                 V_3.get_Item(V_6).get_SubTypes().Add(V_7);
             }
             V_6 = V_6 + 1;
         }
     }
     return;
 }
 private void RecursiveDfs(ClassHierarchyNode node)
 {
     this.preorderNumber = this.preorderNumber + 1;
     this.used.Add(node, this.preorderNumber);
     this.s.Push(node);
     this.p.Push(node);
     V_0 = node.get_CanAssignTo().GetEnumerator();
     try
     {
         while (V_0.MoveNext())
         {
             V_1 = V_0.get_Current();
             if (this.used.ContainsKey(V_1))
             {
                 if (this.nodeToComponent.ContainsKey(V_1))
                 {
                     continue;
                 }
                 V_2 = this.used.get_Item(V_1);
                 while (V_2 < this.used.get_Item(this.p.Peek()))
                 {
                     dummyVar0 = this.p.Pop();
                 }
             }
             else
             {
                 this.RecursiveDfs(V_1);
             }
         }
     }
     finally
     {
         if (V_0 != null)
         {
             V_0.Dispose();
         }
     }
     if (this.p.Peek() == node)
     {
         while (this.s.Peek() != node)
         {
             V_3 = this.s.Pop();
             this.nodeToComponent.Add(V_3, this.componentCount);
         }
         this.nodeToComponent.Add(this.p.Pop(), this.componentCount);
         dummyVar1           = this.s.Pop();
         this.componentCount = this.componentCount + 1;
     }
     return;
 }
Exemple #31
0
 protected virtual ClassHierarchyNode GetTypeNode(TypeReference type)
 {
     V_0 = type.get_FullName();
     if (String.op_Equality(V_0, "System.Byte") || String.op_Equality(V_0, "System.SByte") || String.op_Equality(V_0, "System.Char") || String.op_Equality(V_0, "System.Int16") || String.op_Equality(V_0, "System.UInt16") || String.op_Equality(V_0, "System.Boolean"))
     {
         V_0 = "System.Int32";
     }
     if (!this.typeNameToNode.ContainsKey(V_0))
     {
         V_1 = new ClassHierarchyNode(type);
         this.typeNameToNode.Add(V_0, V_1);
     }
     return(this.typeNameToNode.get_Item(V_0));
 }
        /// <summary>
        /// As integer values can be ordered depending on their size, the graph algorithm used in TypeInferer isn't needed here.
        /// Instead, we might use the indexes to determine which is the smallest type big enough to contain every type provided in
        /// <paramref name="typeNodes"/>.
        /// </summary>
        /// <param name="typeNodes">The list of types.</param>
        /// <returns>The common parent node.</returns>
        protected override ClassHierarchyNode FindLowestCommonAncestor(ICollection <ClassHierarchyNode> typeNodes)
        {
            ClassHierarchyNode result = null;
            int maxIndex = Int32.MinValue;

            foreach (ClassHierarchyNode node in typeNodes)
            {
                int currentIndex = ExpressionTypeInferer.GetTypeIndex(node.NodeType);
                if (currentIndex > maxIndex)
                {
                    maxIndex = currentIndex;
                    result   = node;
                }
            }
            return(result);
        }
Exemple #33
0
        /// <summary>
        /// Builds the hierarchy between the hard nodes.
        /// </summary>
        /// <param name="hardNodes">Collection of the hard nodes.</param>
        protected virtual void BuildUpHardNodesHierarchy(IEnumerable <ClassHierarchyNode> hardNodes)
        {
            Queue <ClassHierarchyNode>   queuedNodes    = new Queue <ClassHierarchyNode>(hardNodes);
            HashSet <ClassHierarchyNode> processedNodes = new HashSet <ClassHierarchyNode>();

            while (queuedNodes.Count > 0)
            {
                ClassHierarchyNode currentType = queuedNodes.Dequeue();
                processedNodes.Add(currentType);
                resultingGraph.Add(currentType);
                TypeDefinition currentNodeType = currentType.NodeType.Resolve();
                TypeReference  baseTypeRef     = null;
                if (currentNodeType == null)
                {
                    continue;
                }
                baseTypeRef = currentNodeType.BaseType;
                if (baseTypeRef != null)
                {
                    ClassHierarchyNode baseType = GetTypeNode(baseTypeRef);
                    currentType.AddSupertype(baseType);
                    if (!processedNodes.Contains(baseType))
                    {
                        queuedNodes.Enqueue(baseType);
                    }
                }

                if (currentNodeType.IsInterface)
                {
                    ClassHierarchyNode objectNode = GetTypeNode(typeSystem.Object);
                    currentType.AddSupertype(objectNode);
                }

                IEnumerable <TypeReference> interfaces = currentType.NodeType.Resolve().Interfaces;
                foreach (TypeReference interfaceRef in interfaces)
                {
                    ClassHierarchyNode implementedInterface = GetTypeNode(interfaceRef);
                    currentType.AddSupertype(implementedInterface);
                    if (!processedNodes.Contains(implementedInterface))
                    {
                        queuedNodes.Enqueue(implementedInterface);
                    }
                }
            }

            AddObjectClassNodeIfMIssing();
        }
        /// <summary>
        /// Replaces multiple parent dependencies as described in <see cref="Chapter 6 Integer inference"/>
        /// in <see cref="Efficient Inference of Static Types for Java Bytecode.pdf"/>.
        /// </summary>
        private void ReplaceMultipleParentDependencies()
        {
            bool merged = false;
            do
            {
                merged = false;
                ICollection<ClassHierarchyNode> toMerge = null;
                foreach (ClassHierarchyNode node in inferenceGraph)
                {
                    bool flag = true;
                    if (!node.IsHardNode)
                    {
                        foreach (ClassHierarchyNode subtype in node.SubTypes)
                        {
                            if (!subtype.IsHardNode)
                            {
                                flag = false;
                                break;
                            }
                        }
                        if (!flag || node.SubTypes.Count == 0)
                        {
                            continue;
                        }

                        merged = true;
                        ClassHierarchyNode type = FindLowestCommonAncestor(node.SubTypes);
                        toMerge = new ClassHierarchyNode[] { node, type };
                        break;
                    }
                }
                if (merged)
                {
                    MergeNodes(toMerge);
                }
            } while (merged);
        }
 /// <summary>
 /// Replaces multiple child constraints as described in <see cref="Chapter 6 Integer inference"/>
 /// in <see cref="Efficient Inference of Static Types for Java Bytecode.pdf"/>.
 /// </summary>
 private void ReplaceMultipleChildConstraints()
 {
     bool merged = false;
     do
     {
         merged = false;
         ICollection<ClassHierarchyNode> toMerge = null;
         foreach (ClassHierarchyNode node in inferenceGraph)
         {
             if (!node.IsHardNode)
             {
                 bool flag = true;
                 foreach (ClassHierarchyNode canAssignTo in node.CanAssignTo)
                 {
                     if (!canAssignTo.IsHardNode)
                     {
                         flag = false;
                         break;
                     }
                 }
                 if (!flag || node.CanAssignTo.Count == 0)
                 {
                     continue;
                 }
                 ///Now it's sure the node has only type predecessors.
                 ///Now find the smallest type it can assign to and assign it to the node.
                 merged = true;
                 ClassHierarchyNode type = FindGreatestCommonDescendant(node.CanAssignTo);
                 toMerge = new ClassHierarchyNode[] { node, type };
                 break;
             }
         }
         if (merged)
         {
             MergeNodes(toMerge);
         }
     } while (merged);
 }
 /// <summary>
 /// Adds an edge from <paramref name="smallerType"/> to <paramref name="biggerType"/>.
 /// </summary>
 /// <param name="biggerTypeNode">The type the edge points to.</param>
 /// <param name="smallerTypeNode">The type the edge comes from.</param>
 private void AddEdge(ClassHierarchyNode biggerTypeNode, ClassHierarchyNode smallerTypeNode)
 {
     // smallerTypeNode can assign to BiggerTypeNode
     smallerTypeNode.AddSupertype(biggerTypeNode);
     resultingGraph.Add(smallerTypeNode);
     resultingGraph.Add(biggerTypeNode);
 }
 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>
 /// Adds <paramref name="supertype"/> to the collection of nodes, this one can assign to.
 /// Also adds this node in <paramref name="supertype"/>'s collection of nodes, that can assign to it.
 /// </summary>
 /// <param name="supertype">The node, representing supertype of the current node.</param>
 public void AddSupertype(ClassHierarchyNode supertype)
 {
     if (!CanAssignTo.Contains(supertype))
     {
         CanAssignTo.Add(supertype);
         supertype.SubTypes.Add(this);
     }
 }
 /// <summary>
 /// Merges nodes with LowestCommonAncestor constraints as described in <see cref="Single Constraints (page 11)"/> 
 /// in <see cref="Efficient Inference of Static Types for Java Bytecode.pdf"/>.
 /// </summary>
 /// <returns>Returns true if a merge was made.</returns>
 private bool MergeWithLowestCommonAncestor()
 {
     bool shouldMerge = false;
     ClassHierarchyNode[] toMerge = null;
     foreach (ClassHierarchyNode node in inferenceGraph)
     {
         if (node.IsHardNode)
         {
             continue;
         }
         shouldMerge = true;
         HashSet<ClassHierarchyNode> classNodes = new HashSet<ClassHierarchyNode>();
         foreach (ClassHierarchyNode childNode in node.SubTypes)
         {
             ///Only class nodes should be able to assign to the type of the current node.
             if (!childNode.IsClassNode)
             {
                 shouldMerge = false;
                 break;
             }
             classNodes.Add(childNode);
         }
         if (shouldMerge)
         {
             ClassHierarchyNode lcaNode = FindLowestCommonAncestor(classNodes);
             if (lcaNode == null || lcaNode == node)
             {
                 shouldMerge = false;
                 continue;
             }
             toMerge = new ClassHierarchyNode[] { lcaNode, node };
             break;
         }
     }
     if (shouldMerge)
     {
         MergeNodes(toMerge);
     }
     return shouldMerge;
 }
 /// <summary>
 /// Merges Single Child constraints as described in <see cref="Single Constraints (page 11)"/> in <see cref="Efficient Inference of Static Types for Java Bytecode.pdf"/>.
 /// </summary>
 private void MergeSingleChildConstraints()
 {
     bool changed = true;
     while (changed)
     {
         ClassHierarchyNode[] toMerge = null;
         changed = false;
         foreach (ClassHierarchyNode node in inferenceGraph)
         {
             if (node.SubTypes.Count == 1 && !node.IsHardNode)
             {
                 ClassHierarchyNode childNode = node.SubTypes.First();
                 toMerge = new ClassHierarchyNode[] { node, childNode };
                 changed = true;
                 break;
             }
         }
         if (changed)
         {
             MergeNodes(toMerge);
         }
     }
 }
 /// <summary>
 /// Locates the graph node corresponding to the supplied <paramref name="type"/>. If it doesn't exist, it's created.
 /// </summary>
 /// <param name="type">A type whose graph node is being searched.</param>
 /// <returns>Returns the graph node.</returns>
 protected virtual ClassHierarchyNode GetTypeNode(TypeReference type)
 {
     string typeName = type.FullName;
     ///All types, smaller than 4 bytes are represented by Int32 at this point.
     if (typeName == "System.Byte" || typeName == "System.SByte" || typeName == "System.Char" ||
         typeName == "System.Int16" || typeName == "System.UInt16" || typeName == "System.Boolean")
     {
         typeName = "System.Int32";
     }
     if (!typeNameToNode.ContainsKey(typeName))
     {
         ClassHierarchyNode typeNode = new ClassHierarchyNode(type);
         typeNameToNode.Add(typeName, typeNode);
     }
     return typeNameToNode[typeName];
 }
        /// <summary>
        /// Finds the ClassHierarchyNode corresponding to the <paramref name="variable"/>. If no such node exists, it's created.
        /// </summary>
        /// <param name="variable">The variable we search the node for.</param>
        /// <returns>Returns the corresponding node in the graph.</returns>
        protected ClassHierarchyNode GetVariableNode(VariableReference variable)
        {
            string variableName = variable.Name;
            if (!variableNameToNode.ContainsKey(variableName))
            {
                ClassHierarchyNode variableNode = new ClassHierarchyNode(variable);
                variableNode = MergeWithVariableTypeIfNeeded(variable, variableNode);
                variableNameToNode.Add(variableName, variableNode);

            }
            return variableNameToNode[variableName];
        }
 protected virtual ClassHierarchyNode MergeWithVariableTypeIfNeeded(VariableReference variable, ClassHierarchyNode variableNode)
 {
     /// The node should be merget with its type in the normal inference.
     if (variable.VariableType != null)
     {
         ClassHierarchyNode variableTypeNode = GetTypeNode(variable.VariableType);
         variableNode = new ClassHierarchyNode(new ClassHierarchyNode[] { variableNode, variableTypeNode });
     }
     return variableNode;
 }
 /// <summary>
 /// Handles all nodes that have single child constraint as described in <see cref="Chapter 6 Integer inference"/>
 /// in <see cref="Efficient Inference of Static Types for Java Bytecode.pdf"/>.
 /// </summary>
 private void MergeWithSingleChild()
 {
     bool merged = false;
     do
     {
         ICollection<ClassHierarchyNode> toMerge = null;
         foreach (ClassHierarchyNode node in inferenceGraph)
         {
             if (!node.IsHardNode)
             {
                 if (node.CanAssignTo.Count == 1 && node.SubTypes.Count == 0)
                 {
                     ClassHierarchyNode x = null;
                     //x = node.CanAssignTo.First(); w/o Linq
                     foreach (ClassHierarchyNode p in node.CanAssignTo)
                     {
                         x = p; 
                         break;
                     }
                     toMerge = new ClassHierarchyNode[]{node,x};
                     merged = true;
                     break;
                 }
             }
         }
         if (merged)
         {
             MergeNodes(toMerge);
         }
     } while (merged);
 }
        /// <summary>
        /// Handles the assignment of phi variables.
        /// </summary>
        /// <param name="instructionOffset">The instruction that pushes the value on the stack.</param>
        /// <param name="variableNode">The graph node corresponding to the variable being assigned.</param>
        protected virtual void OnPhiVariableAssigned(int instructionOffset, ClassHierarchyNode variableNode)
        {
            Expression instructionExpression = offsetToExpression[instructionOffset]; // this key should allways be present
            //TypeReference assignedType = ExpressionTypeInferer.GetExpressionType(instructionExpression, context.Method.Module.TypeSystem);
            TypeReference assignedType = instructionExpression.ExpressionType;
            ClassHierarchyNode supertypeNode;
            if (assignedType == null)
            {
                ///Then an expression, containing one or more phi variables is being assigned to another phi variable
                IEnumerable<VariableReference> usedPhiVariables = GetVariables(instructionOffset);

                //VariableReference assigningVariable = (instructionExpression as VariableReferenceExpression).Variable;
                foreach (VariableReference assigningVariable in usedPhiVariables)
                {
                    supertypeNode = GetVariableNode(assigningVariable);
                    supertypeNode.AddSupertype(variableNode);
                    resultingGraph.Add(supertypeNode);
                }
                return;
                //supertypeNode = GetVariableNode(assigningVariable);
            }
            supertypeNode = GetTypeNode(assignedType);
            supertypeNode.AddSupertype(variableNode);
            resultingGraph.Add(supertypeNode);
        }
        /// <summary>
        /// Merges the nodes in <paramref name="nodeCollection"/> in one node and attaches the result to the graph.
        /// </summary>
        /// <param name="nodeCollection">The collection of nodes to be merged.</param>
        protected void MergeNodes(ICollection<ClassHierarchyNode> nodeCollection)
        {
            if (nodeCollection.Count <= 1)
            {
                return;
            }

            ///Merge component.
            ClassHierarchyNode mergedNode = new ClassHierarchyNode(nodeCollection);

            ///Attach the merged node.
            foreach (ClassHierarchyNode oldNode in mergedNode.ContainedNodes)
            {
                inferenceGraph.Remove(oldNode);
            }
            inferenceGraph.Add(mergedNode);
        }
 private void RemoveBooleanAsASubtype(ClassHierarchyNode variableNode)
 {
     ClassHierarchyNode booleanNode = GetTypeNode(typeSystem.Boolean);
     if (variableNode.SubTypes.Contains(booleanNode))
     {
         variableNode.SubTypes.Remove(booleanNode);
         booleanNode.CanAssignTo.Remove(variableNode);
     }
 }
 /// <summary>
 /// Realises the logic for merging with single parent.
 /// </summary>
 /// <param name="chooseParent">Predicate that determines if the parent node is legal to merge.</param>
 /// <returns>Returns true if there was a merge.</returns>
 private bool MergeSingleParent(Func<ClassHierarchyNode, bool> chooseParentPred)
 {
     bool result = false;
     ClassHierarchyNode[] toMerge = null;
     foreach (ClassHierarchyNode childNode in inferenceGraph)
     {
         if (childNode.IsHardNode)
         {
             continue;
         }
         if (childNode.SubTypes.Count == 1)
         {
             ClassHierarchyNode parentNode = childNode.SubTypes.First();
             if (chooseParentPred(parentNode))
             {
                 result = true;
                 toMerge = new ClassHierarchyNode[] { childNode, parentNode };
                 break;
             }
         }
     }
     if (result)
     {
         MergeNodes(toMerge);
     }
     return result;
 }
        /// <summary>
        /// Handles the case of PhiVariable usages.
        /// </summary>
        /// <param name="instructionOffset">The offset of the instruction that pops the variable from the stack.</param>
        /// <param name="variableNode">The graph node for the variable.</param>
        protected virtual void OnPhiVariableUsed(int instructionOffset, ClassHierarchyNode variableNode)
        {
            ///The usages of the variable bring no value to this algorithm. In the paper they are included, because in Java Bytecode the local method variables 
            ///don't have type, and can be potentionally used before being assigned. Phi variables, however, are always assigned first and used later. Thus, the
            ///information from the assignments should be enough for legal type inference.
            return;
            //Instruction instr = offsetToInstruction[instructionOffset];
            //if (instr.OpCode.Code == Code.Dup || instr.OpCode.Code == Code.Pop)
            //{
            //    return;
            //}
            //ClassHierarchyNode typeNode = GetUseExpressionTypeNode(instr, record.Variable);


            ////this should not be happening when the array support is added
            //if (typeNode == null)
            //{
            //    //only phi variables were part of the expression
            //    List<ClassHierarchyNode> phiVariableNodes = GetUsedPhiVariableNodes(instr.Offset);
            //    for (int i = 0; i < phiVariableNodes.Count; i++)
            //    {
            //        for (int j = i + 1; j < phiVariableNodes.Count; j++)
            //        {
            //            //phi1 <-> phi2
            //            phiVariableNodes[i].AddSupertype(phiVariableNodes[j]);
            //            phiVariableNodes[j].AddSupertype(phiVariableNodes[i]);
            //        }
            //    }
            //    return;
            //}

            //variableNode.AddSupertype(typeNode);
            //nodes.Add(typeNode);
        }
 /// <summary>
 /// Removes <paramref name="subType"/> from <paramref name="superType"/>'s collection of nodes, <paramref name="superType"/> can be assigned from.
 /// Also updates the collection of nodes <paramref name="subType"/> can assign to.
 /// </summary>
 /// <param name="superType"></param>
 /// <param name="subType"></param>
 private void RemoveSubtype(ClassHierarchyNode superType, ClassHierarchyNode subType)
 {
     if (!superType.SubTypes.Contains(subType))
     {
         throw new ArgumentOutOfRangeException(string.Format("No such relation between {0} and {1}.", this, subType));
     }
     superType.SubTypes.Remove(subType);
     subType.CanAssignTo.Remove(superType);
 }
 /// <summary>
 /// Realises the steps from 1 to 4 as described above.
 /// </summary>
 /// <param name="node">The node which connected component is to be found.</param>
 private void RecursiveDfs(ClassHierarchyNode node)
 {
     preorderNumber++;
     used.Add(node, preorderNumber);
     s.Push(node);
     p.Push(node);
     foreach (ClassHierarchyNode supernode in node.CanAssignTo)
     {
         if (!used.ContainsKey(supernode))
         {
             RecursiveDfs(supernode);
         }
         else
         {
             if (!nodeToComponent.ContainsKey(supernode))
             {
                 int supernodeNumber = used[supernode];
                 while (supernodeNumber < used[p.Peek()])
                 {
                     p.Pop();
                 }
             }
         }
     }
     if (p.Peek() == node)
     {
         while (s.Peek() != node)
         {
             ClassHierarchyNode componentMember = s.Pop();
             nodeToComponent.Add(componentMember, componentCount);
         }
         nodeToComponent.Add(p.Pop(), componentCount);
         s.Pop();
         componentCount++;
     }
 }