Exemplo n.º 1
0
        /// <summary>
        /// Creates and adds a new node to the collection of data flow nodes.
        /// </summary>
        /// <param name="id">The unique identifier of the node.</param>
        /// <param name="contents">The contents of the node.</param>
        /// <returns>The created node.</returns>
        public DataFlowNode <TContents> Add(long id, TContents contents)
        {
            var node = new DataFlowNode <TContents>(id, contents);

            Add(node);
            return(node);
        }
Exemplo n.º 2
0
        private void CollectStackDependencies(
            BasicBlock <Statement <TInstruction> > block,
            DataFlowNode <TInstruction> dataFlowNode,
            Span <IVariable> buffer,
            ref int phiStatementCount)
        {
            var stackDependencies = dataFlowNode.StackDependencies;

            for (int i = 0; i < stackDependencies.Count; i++)
            {
                var sources = stackDependencies[i];
                if (sources.Count == 1)
                {
                    // If the dependency only has 1 possible data source, we can simply
                    // create a stack slot and an assignment to that slot.
                    buffer[i] = GetStackSlot(sources.First());
                }
                else
                {
                    // If we have more than 1 possible data source, we
                    // will add a "phi" node. This basically means
                    // that the result of the "phi function" will return
                    // the value based on prior control flow.
                    var phi   = CreatePhiSlot();
                    var slots = sources
                                .Select(source => new VariableExpression <TInstruction>(GetStackSlot(source)))
                                .ToArray();

                    block.Instructions.Insert(phiStatementCount++, new PhiStatement <TInstruction>(phi, slots));
                    buffer[i] = phi;
                }
            }
        }
Exemplo n.º 3
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="symbol">ISymbol</param>
 /// <param name="dfgNode">DataFlowNode</param>
 internal SymbolDefinition(ISymbol symbol, DataFlowNode dfgNode)
 {
     this.DataFlowNode = dfgNode;
     this.Symbol = symbol;
     this.CandidateTypes = new HashSet<ITypeSymbol>();
     this.Kind = symbol.Kind;
     this.Name = $"[{this.DataFlowNode.Id},{this.Kind}]::{this.Symbol.Name}";
 }
Exemplo n.º 4
0
        public void AddNodeToGraphShouldSetParentGraph()
        {
            var dfg  = new DataFlowGraph <int>(IntArchitecture.Instance);
            var node = new DataFlowNode <int>(1, 2);

            dfg.Nodes.Add(node);
            Assert.Same(dfg, node.ParentGraph);
        }
Exemplo n.º 5
0
 /// <inheritdoc />
 public bool Contains(DataFlowNode <TContents> item)
 {
     if (item == null)
     {
         return(false);
     }
     return(_nodes.TryGetValue(item.Id, out var node) && node == item);
 }
Exemplo n.º 6
0
        public void RemoveNodeFromGraphShouldUnsetParentGraph()
        {
            var dfg  = new DataFlowGraph <int>(IntArchitecture.Instance);
            var node = new DataFlowNode <int>(1, 2);

            dfg.Nodes.Add(node);
            dfg.Nodes.Remove(node);
            Assert.Null(node.ParentGraph);
        }
Exemplo n.º 7
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="dfgNode">DataFlowNode</param>
 /// <param name="context">AnalysisContext</param>
 internal DataFlowInfo(DataFlowNode dfgNode, AnalysisContext context)
 {
     this.AnalysisContext = context;
     this.DataFlowNode = dfgNode;
     this.GeneratedDefinitions = new HashSet<SymbolDefinition>();
     this.KilledDefinitions = new HashSet<SymbolDefinition>();
     this.InputDefinitions = new HashSet<SymbolDefinition>();
     this.OutputDefinitions = new HashSet<SymbolDefinition>();
     this.TaintedDefinitions = new Dictionary<SymbolDefinition, ISet<SymbolDefinition>>();
 }
Exemplo n.º 8
0
        public void DisconnectNodeShouldRemoveEdge(DataDependencyType edgeType, bool removeSourceNode)
        {
            var variable = new DummyVariable("var");

            var graph = new DataFlowGraph <int>(IntArchitecture.Instance);

            var n1 = new DataFlowNode <int>(0, 0);

            n1.StackDependencies.Add(new DataDependency <int>());
            n1.VariableDependencies.Add(variable, new DataDependency <int>());

            var n2 = new DataFlowNode <int>(1, 1);

            graph.Nodes.AddRange(new[]
            {
                n1,
                n2
            });

            switch (edgeType)
            {
            case DataDependencyType.Stack:
                n1.StackDependencies[0].Add(new DataSource <int>(n2));
                break;

            case DataDependencyType.Variable:
                n1.VariableDependencies[variable].Add(new DataSource <int>(n2));
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(edgeType), edgeType, null);
            }

            if (removeSourceNode)
            {
                n1.Disconnect();
            }
            else
            {
                n2.Disconnect();
            }

            Assert.Empty(n1.StackDependencies[0]);
            Assert.Empty(n1.VariableDependencies[variable]);
            Assert.Empty(n2.GetDependants());
        }
Exemplo n.º 9
0
        /// <inheritdoc />
        public void Add(DataFlowNode <TContents> item)
        {
            if (item.ParentGraph == _owner)
            {
                return;
            }
            if (item.ParentGraph != null)
            {
                throw new ArgumentException("Cannot add a node from another graph.");
            }
            if (_nodes.ContainsKey(item.Id))
            {
                throw new ArgumentException($"A node with identifier 0x{item.Id:X8} was already added to the graph.");
            }

            _nodes.Add(item.Id, item);
            item.ParentGraph = _owner;
        }
Exemplo n.º 10
0
        /// <summary>
        /// Collects all dependency nodes recursively, and sorts them in a topological order such that the final collection
        /// of nodes can be executed sequentially.
        /// </summary>
        /// <param name="node">The node to find all dependencies for.</param>
        /// <param name="flags">Flags that influence the behaviour of the algorithm.</param>
        /// <typeparam name="T">The type of contents that each node contains.</typeparam>
        /// <returns>The topological ordering of all dependencies of the node.</returns>
        /// <exception cref="CyclicDependencyException">Occurs when there is a cyclic dependency in the graph.</exception>
        public static IEnumerable <DataFlowNode <T> > GetOrderedDependencies <T>(this DataFlowNode <T> node, DependencyCollectionFlags flags)
        {
            try
            {
                var topologicalSorting = new TopologicalSorter <DataFlowNode <T> >(GetSortedOutgoingEdges);
                return(topologicalSorting.GetTopologicalSorting(node));
            }
            catch (CycleDetectedException ex)
            {
                throw new CyclicDependencyException("Cyclic dependency was detected.", ex);
            }

            IReadOnlyList <DataFlowNode <T> > GetSortedOutgoingEdges(DataFlowNode <T> n)
            {
                var result = new List <DataFlowNode <T> >();

                // Prioritize stack dependencies over variable dependencies.
                if ((flags & DependencyCollectionFlags.IncludeStackDependencies) != 0)
                {
                    foreach (var dependency in n.StackDependencies)
                    {
                        if (dependency.HasKnownDataSources)
                        {
                            result.Add(dependency.First().Node);
                        }
                    }
                }

                if ((flags & DependencyCollectionFlags.IncludeVariableDependencies) != 0)
                {
                    foreach (var entry in n.VariableDependencies)
                    {
                        if (entry.Value.HasKnownDataSources)
                        {
                            result.Add(entry.Value.First().Node);
                        }
                    }
                }

                return(result);
            }
        }
Exemplo n.º 11
0
 /// <summary>
 /// Creates a new stack data source, referencing a stack value produced by the provided node.
 /// </summary>
 /// <param name="node">The node producing the value.</param>
 /// <param name="slotIndex">The index of the stack value that was produced by the node.</param>
 public StackDataSource(DataFlowNode <TContents> node, int slotIndex)
     : base(node)
 {
     SlotIndex = slotIndex;
 }
Exemplo n.º 12
0
 /// <summary>
 /// Creates a new stack data source, referencing the first stack value produced by the provided node.
 /// </summary>
 /// <param name="node">The node producing the value.</param>
 public StackDataSource(DataFlowNode <TContents> node)
     : base(node)
 {
 }
Exemplo n.º 13
0
 /// <summary>
 /// Collects all dependency nodes recursively, and sorts them in a topological order such that the final collection
 /// of nodes can be executed sequentially.
 /// </summary>
 /// <param name="node">The node to find all dependencies for.</param>
 /// <typeparam name="T">The type of contents that each node contains.</typeparam>
 /// <returns>The topological ordering of all dependencies of the node.</returns>
 /// <exception cref="CyclicDependencyException">Occurs when there is a cyclic dependency in the graph.</exception>
 public static IEnumerable <DataFlowNode <T> > GetOrderedDependencies <T>(this DataFlowNode <T> node) =>
 GetOrderedDependencies(node, DependencyCollectionFlags.IncludeAllDependencies);
Exemplo n.º 14
0
 internal VariableDependencyCollection(DataFlowNode <TContents> owner)
 {
     _owner = owner ?? throw new ArgumentNullException(nameof(owner));
 }
Exemplo n.º 15
0
 /// <inheritdoc />
 public bool Remove(DataFlowNode <TContents> item) =>
 item != null && Remove(item.Id);
Exemplo n.º 16
0
        private void CollectVariableDependencies(
            BasicBlock <Statement <TInstruction> > block,
            DataFlowNode <TInstruction> dataFlowNode,
            Span <IVariable> buffer,
            ref int phiStatementCount)
        {
            int index = 0;
            var variableDependencies = dataFlowNode.VariableDependencies;

            foreach (var pair in variableDependencies)
            {
                var variable   = pair.Key;
                var dependency = pair.Value;

                if (dependency.Count <= 1)
                {
                    // If the dependency has only 1 possible source we just simply
                    // get the variable. But since the AST utilizes SSA, all of the
                    // variables are versioned. This is good because everything is
                    // "immutable". One "real" variable will have a new versioned
                    // variable created every time it is assigned to.
                    int version  = _context.GetVariableVersion(variable);
                    var snapshot = new VariableSnapshot(variable, version);

                    buffer[index++] = _context.GetVersionedVariable(snapshot);
                    continue;
                }

                // Otherwise (>0), we will get the list of versioned(!) variables
                // that could reach the instruction and create a "phi" statement
                // like in the stack dependencies.
                var sources = CollectVariables();

                if (_context.VariableSourcesToPhiVariable.TryGetValue(sources, out var phi))
                {
                    // If a phi slot already exists for the list of variables,
                    // reuse the same phi slot.
                    buffer[index++] = phi;
                }
                else
                {
                    // Otherwise, create a new phi slot for the list of variables
                    // and save it if we encounter the same variables again.
                    phi = CreatePhiSlot();
                    var slots = sources
                                .Select(source => new VariableExpression <TInstruction>(source))
                                .ToArray();

                    _context.VariableSourcesToPhiVariable.Add(sources, phi);
                    block.Instructions.Insert(phiStatementCount++, new PhiStatement <TInstruction>(phi, slots));
                    buffer[index++] = phi;
                }

                List <AstVariable> CollectVariables()
                {
                    var result = new List <AstVariable>();

                    foreach (var instruction in dependency.Select(dep => dep.Node.Contents))
                    {
                        if (_context.VariableStates.TryGetValue(instruction, out var versions))
                        {
                            // If we already have a dictionary for the instruction, we will
                            // just get the versioned variable from the existing dictionary.
                            var snapshot = new VariableSnapshot(variable, versions[variable]);
                            result.Add(_context.VersionedVariables[snapshot]);
                        }
                        else
                        {
                            // Otherwise, we will create a new dictionary for the instruction.
                            var snapshot = new VariableSnapshot(variable, 0);
                            var slot     = _context.GetVersionedVariable(snapshot);

                            _context.VariableStates.Add(instruction, new Dictionary <IVariable, int>
                            {
                                [variable] = 0
                            });

                            result.Add(slot);
                        }
                    }

                    return(result);
                }
            }
        }
Exemplo n.º 17
0
 /// <summary>
 /// Creates a new symbolic value with a single data source.
 /// </summary>
 /// <param name="dataSource">The data source of the symbolic value.</param>
 public SymbolicValue(DataFlowNode <T> dataSource)
     : this(new DataSource <T>(dataSource, 0))
 {
 }
Exemplo n.º 18
0
        public void ConstructorShouldSetContents()
        {
            var node = new DataFlowNode <int>(1, 2);

            Assert.Equal(2, node.Contents);
        }