Пример #1
0
        /// <summary>
        /// Recursive workhorse method for the method <see cref="GetAggregateFields"/>.
        /// </summary>
        ///
        /// <param name="aggregateType">Type of the aggregate that is being accessed.</param>
        /// <param name="offset">Offset of the access from the start of the aggregate,
        /// in bits.</param>
        /// <param name="accessType">Type of the aggregate access.</param>
        /// <param name="accessBitSize">Bit-size of the aggregate access.</param>
        /// <param name="getArrayElements">True if, and only if, the elements of
        /// a fixed-size array should be treated as separate fields of the aggregate.</param>
        /// <param name="accessSoFar">Expression that represents the access so far.</param>
        /// <param name="path">Path that contains the aggregate.</param>
        /// <returns>List of AggregateField objects, each of which represents
        /// the aggregate fields that the input aggregate access overlaps.</returns>
        private static List <AggregateField> GetAggregateFieldsHelper(AggregateType aggregateType,
                                                                      int offset, Phx.Types.Type accessType, int accessBitSize, bool getArrayElements,
                                                                      Expression accessSoFar, Path path)
        {
            Utilities.Configuration config = path.Config;
            List <AggregateField>   result = new List <AggregateField>();

            int         completedOffset    = 0;
            FieldSymbol currentFieldSymbol = aggregateType.FieldSymbolList;

            while (currentFieldSymbol != null)
            {
                /* Obtain the necessary information from the current field symbol. */
                string         fieldName        = currentFieldSymbol.ToString();
                int            fieldStartOffset = currentFieldSymbol.BitOffset;
                Phx.Types.Type fieldType        = currentFieldSymbol.Type;
                int            fieldEndOffset   = (fieldStartOffset + (int)fieldType.BitSize) - 1;

                /* Move to the next field symbol for the subsequent iteration. */
                currentFieldSymbol = currentFieldSymbol.NextFieldSymbol;
                if (fieldStartOffset < completedOffset)
                {
                    /* Skip this field if it starts at an offset in the part of
                     * the aggregate that has already been examined. */
                    continue;
                }
                else
                {
                    /* Move the completed offset pointer to the end of the field currently
                     * being examined. This indicates that, after this iteration
                     * is complete, the part of the aggregate prior to the pointer
                     * has already been examined. */
                    completedOffset = fieldEndOffset;
                }

                if (((offset <= fieldStartOffset) &&
                     (fieldStartOffset <= (offset + accessBitSize) - 1)) ||
                    ((offset > fieldStartOffset) && (offset <= fieldEndOffset)))
                {
                    /* Attach a unique identifier to each field name. */
                    string newFieldName = String.Format("{0}{1}{2}{3}",
                                                        config.IDENT_FIELD, fieldName,
                                                        config.IDENT_AGGREGATE, GetAggregateName(aggregateType));

                    /* Make an array variable Expression for the field, since we represent
                     * aggregate accesses as accesses into an array. */
                    Expression newArrayVar =
                        new Expression(OperatorStore.ArrayVariableOp, newFieldName);
                    newArrayVar.Type = Phx.Types.PointerType.New(aggregateType.TypeTable,
                                                                 Phx.Types.PointerTypeKind.UnmanagedPointer, path.Config.WORD_BITSIZE,
                                                                 fieldType, fieldType.TypeSymbol);
                    path.AddVariable(newArrayVar);

                    /* Convert the array variable Expression into the equivalent
                     * pointer Expression, represented as a dereferencing function. */
                    newArrayVar = ExpressionHelper.MakeDereferencingFunction(newArrayVar, path);

                    /* Apply the dereferencing function on the Expression generated so far. */
                    List <Expression> argExprs = new List <Expression>();
                    argExprs.Add(accessSoFar);
                    argExprs.Add(new Constant(0, config.WORD_BITSIZE));

                    Expression fieldAccessExpr =
                        ExpressionHelper.ApplyFunction(newArrayVar, argExprs, path);
                    fieldAccessExpr = ExpressionHelper.LookupAndReplaceOffset(fieldAccessExpr,
                                                                              fieldType, false, path);

                    if (fieldType.IsAggregateType)
                    {
                        /* Recurse into the field, if the field is itself an aggregate. */
                        AggregateType         innerAggregateType   = fieldType.AsAggregateType;
                        List <AggregateField> innerAggregateFields =
                            GetAggregateFieldsHelper(innerAggregateType,
                                                     Math.Max((offset - fieldStartOffset), 0),
                                                     accessType,
                                                     (accessBitSize - Math.Max(fieldStartOffset - offset, 0)),
                                                     getArrayElements, fieldAccessExpr, path);
                        foreach (AggregateField innerAggregateField in innerAggregateFields)
                        {
                            /* Include the offset of the field inside
                             * the enclosing aggregate type. */
                            innerAggregateField.StartOffset += fieldStartOffset;
                            result.Add(innerAggregateField);
                        }
                    }
                    else if (fieldType.IsUnmanagedArrayType &&
                             !ExpressionHelper.AreSameTypes(fieldType, accessType) &&
                             getArrayElements)
                    {
                        List <Pair <Expression, int> > arrayElements =
                            ExpressionHelper.GetArrayElementsInRange(fieldAccessExpr,
                                                                     Math.Max((offset - fieldStartOffset), 0),
                                                                     (accessBitSize - Math.Max(fieldStartOffset - offset, 0)),
                                                                     path);
                        foreach (Pair <Expression, int> arrayElementAndOffset in arrayElements)
                        {
                            Expression arrayElementExpr   = arrayElementAndOffset.First;
                            int        arrayElementOffset = arrayElementAndOffset.Second;

                            result.Add(new AggregateField(aggregateType,
                                                          arrayElementExpr, (fieldStartOffset + arrayElementOffset),
                                                          arrayElementExpr.BitSize));
                        }
                    }
                    else
                    {
                        result.Add(new AggregateField(aggregateType,
                                                      fieldAccessExpr, fieldStartOffset, fieldType.BitSize));
                    }
                }
            }

            Trace.Assert(result.Count > 0, "PHOENIX: Field(s) not found.");
            return(result);
        }
Пример #2
0
        /// <summary>
        /// Finds the conditions along a path.
        /// </summary>
        ///
        /// <param name="functionUnit">Phoenix function unit.</param>
        /// <param name="config">Configuration object that contains GameTime
        /// configuration information.</param>
        /// <param name="projectConfig">ProjectConfiguration object that
        /// contains project configuration information.</param>
        public static void FindPathConditions(Phx.FunctionUnit functionUnit,
                                              Utilities.Configuration config, ProjectConfiguration projectConfig)
        {
            Console.Out.WriteLine("PHOENIX: Finding the conditions and " +
                                  "assignments along a path...");

            Console.Out.WriteLine("PHOENIX: Reading in the DAG...");

            /* Read in the DAG and deduce associated information. The DAG is in DOT file format. */
            string dagFileName =
                System.IO.Path.Combine(projectConfig.locationTempDir, config.TEMP_DAG);
            TextReader dagReader = new StreamReader(dagFileName);

            /* Ignore the first line. */
            dagReader.ReadLine();
            /* Read in the nodes and the edges of the graph. */
            HashSet <string> dagNodes = new HashSet <string>();
            HashSet <Pair <string, string> > dagEdges = new HashSet <Pair <string, string> >();
            string dagEdge = null;

            while ((dagEdge = dagReader.ReadLine()) != null)
            {
                dagEdge = dagEdge.Replace("{", "");
                dagEdge = dagEdge.Replace("}", "");
                dagEdge.Trim();
                if (dagEdge.Length != 0)
                {
                    /* Ignore the semicolon. */
                    dagEdge = dagEdge.Trim(';');
                    /* Split at the arrow. */
                    dagEdge = dagEdge.Replace("->", ">");
                    string[] edgeNodes = dagEdge.Split('>');
                    /* Find the nodes incident to the edge. */
                    edgeNodes[0] = edgeNodes[0].Trim();
                    edgeNodes[1] = edgeNodes[1].Trim();
                    /* Add the nodes and the edge. */
                    dagNodes.Add(edgeNodes[0]);
                    dagNodes.Add(edgeNodes[1]);
                    dagEdges.Add(new Pair <string, string>(edgeNodes[0], edgeNodes[1]));
                }
            }

            dagReader.Close();

            uint numNodes = (uint)dagNodes.Count;
            uint numEdges = (uint)dagEdges.Count;

            Console.Out.WriteLine("PHOENIX: DAG has " + numNodes + " nodes and " +
                                  numEdges + " edges.");
            Console.Out.WriteLine("PHOENIX: There are at most " +
                                  (numEdges - numNodes + 2) + " basis paths.");

            /* How many nodes are there in the original DAG, without the fake
             * intermediate nodes? */
            uint actualNumNodes = (numNodes / 2);
            uint actualNumEdges = (numEdges - actualNumNodes - 1);

            /* Get the successors of the nodes that existed in the
             * original DAG (without the fake intermediate nodes). */
            Dictionary <uint, uint> nodeSuccessors = new Dictionary <uint, uint>();

            foreach (Pair <string, string> edge in dagEdges)
            {
                uint sourceNodeId = Convert.ToUInt32(edge.First);
                uint sinkNodeId   = Convert.ToUInt32(edge.Second);

                /* Yes, there can be more than one successor for any given node.
                 * However, we are guaranteed that for the nodes in the original
                 * DAG, there is exactly one (fake) successor node. We are only
                 * concerned about these nodes. There is no great way to programatically
                 * determine these successor nodes. */
                if (sourceNodeId <= actualNumNodes)
                {
                    nodeSuccessors.Add(sourceNodeId, sinkNodeId);
                }
            }

            Console.Out.WriteLine("PHOENIX: Finished reading and processing the DAG.");

            Console.Out.WriteLine("PHOENIX: Reading the block ID map...");

            /* Read and store the mapping between "adjusted" block IDs and "actual"
             * block IDs. Also, store the reverse mapping for quick conversion
             * in the other direction. */
            Dictionary <uint, uint> adjustedToActual = new Dictionary <uint, uint>();
            Dictionary <uint, uint> actualToAdjusted = new Dictionary <uint, uint>();

            string idMapFileName =
                System.IO.Path.Combine(projectConfig.locationTempDir, config.TEMP_DAG_ID_MAP);

            string[] idMappings = File.ReadAllLines(idMapFileName);
            foreach (string idMapping in idMappings)
            {
                string[] idMappingArray = idMapping.Split(' ');

                uint adjustedBlockId = Convert.ToUInt32(idMappingArray[0]);
                uint actualBlockId   = Convert.ToUInt32(idMappingArray[1]);

                adjustedToActual.Add(adjustedBlockId, actualBlockId);
                actualToAdjusted.Add(actualBlockId, adjustedBlockId);
            }

            Console.Out.WriteLine("PHOENIX: Finished reading and processing the ID map.");
            Console.Out.WriteLine();

            Console.Out.WriteLine("PHOENIX: Reading in the candidate path...");

            /* Read in the candidate path. */
            string pathNodesFileName =
                System.IO.Path.Combine(projectConfig.locationTempDir, config.TEMP_PATH_NODES);
            TextReader pathNodesReader = new StreamReader(pathNodesFileName);

            string[] pathNodesArray = pathNodesReader.ReadLine().Split(' ');
            pathNodesReader.Close();

            List <uint> pathNodes = new List <uint>();

            foreach (string pathNode in pathNodesArray)
            {
                if (pathNode != "")
                {
                    pathNodes.Add(Convert.ToUInt32(pathNode));
                }
            }

            /* Convert the adjusted block IDs in the candidate path to the actual block IDs. */
            Phx.Graphs.FlowGraph         flowGraph  = functionUnit.FlowGraph;
            List <Phx.Graphs.BasicBlock> pathBlocks = new List <Phx.Graphs.BasicBlock>();
            int position = 0;

            while (position < pathNodes.Count)
            {
                uint adjustedBlockId = pathNodes[position];
                uint actualBlockId   = adjustedToActual[adjustedBlockId];

                Phx.Graphs.BasicBlock actualBlock =
                    flowGraph.Node(actualBlockId) as Phx.Graphs.BasicBlock;
                pathBlocks.Add(actualBlock);

                /* Skip over the "fake" intermediate nodes. */
                position = position + 2;
            }

            Path path = new Path(pathBlocks, config, projectConfig);

            Console.Out.WriteLine("PHOENIX: Finished reading and processing the candidate path.");

            /* Generate the conditions and the assignments along the path. */
            Console.Out.WriteLine("PHOENIX: Generating the conditions and " +
                                  "assignments along the path...");
            Console.Out.WriteLine();
            path.GenerateConditionsAndAssignments();
            Console.Out.WriteLine("PHOENIX: Finished generating the conditions and assignments.");

            if (path.ProjectConfig.debugConfig.DUMP_PATH)
            {
                path.Dump();
                Console.Out.WriteLine();
            }

            List <Pair <Expression, uint> >       conditions      = path.Conditions;
            HashSet <Expression>                  arrayVariables  = path.ArrayVariables;
            Dictionary <Expression, List <uint> > arrayDimensions = path.ArrayDimensions;

            Console.Out.WriteLine("PHOENIX: Writing information about the path " +
                                  "to temporary files...");

            Console.Out.WriteLine("PHOENIX: Writing the conditions and assignments...");

            string pathConditionsFileName =
                System.IO.Path.Combine(projectConfig.locationTempDir, config.TEMP_PATH_CONDITIONS);
            StreamWriter pathConditionsWriter = new StreamWriter(pathConditionsFileName, false);

            pathConditionsWriter.AutoFlush = true;

            List <Expression> conditionExprs = new List <Expression>();

            foreach (Pair <Expression, uint> conditionPair in conditions)
            {
                Expression condition = conditionPair.First;
                pathConditionsWriter.WriteLine(condition);
                conditionExprs.Add(condition);
            }

            pathConditionsWriter.Close();

            Console.Out.WriteLine("PHOENIX: Writing completed.");

            Console.Out.WriteLine("PHOENIX: Writing line numbers...");
            path.DumpLineNumbers();
            Console.Out.WriteLine("PHOENIX: Writing completed.");

            Console.Out.WriteLine("PHOENIX: Writing the edges that correspond to " +
                                  "conditions and assignments...");

            /* The actual source node that corresponds to a constraint (condition
            * or assignment) is the dummy node after the adjusted source node. */
            path.DumpConditionEdges(sourceNodeId => nodeSuccessors[actualToAdjusted[sourceNodeId]],
                                    sinkNodeId => actualToAdjusted[sinkNodeId]);
            Console.Out.WriteLine("PHOENIX: Writing completed.");

            Console.Out.WriteLine("PHOENIX: Writing the line numbers and truth values of " +
                                  "the conditional points..");
            path.DumpConditionTruths();
            Console.Out.WriteLine("PHOENIX: Writing completed.");

            Console.Out.WriteLine("PHOENIX: Writing information about array and " +
                                  "aggregate accesses...");
            path.DumpAccesses();
            Console.Out.WriteLine("PHOENIX: Writing completed.");

            if (path.ProjectConfig.debugConfig.DUMP_ALL_PATHS)
            {
                string allPathsFileName =
                    System.IO.Path.Combine(projectConfig.locationTempDir, config.TEMP_PATH_ALL);
                StreamWriter allPathsWriter = new StreamWriter(allPathsFileName, true);
                allPathsWriter.AutoFlush = true;
                allPathsWriter.Write("*** CANDIDATE PATH ***");
                allPathsWriter.WriteLine(path.ToString());
                allPathsWriter.Close();
            }

            Console.Out.WriteLine("PHOENIX: Path information written to temporary files.");

            Console.Out.WriteLine("PHOENIX: Writing the corresponding SMT query to " +
                                  "a temporary file...");

            string smtQueryFileName =
                System.IO.Path.Combine(projectConfig.locationTempDir,
                                       config.TEMP_PATH_QUERY + ".smt");
            StreamWriter smtQueryWriter = new StreamWriter(smtQueryFileName, false);

            smtQueryWriter.AutoFlush = true;
            smtQueryWriter.Write(SmtHelper.ConvertToSmtLib2Query(path));
            smtQueryWriter.Close();

            Console.Out.WriteLine("PHOENIX: Writing completed.");
        }
Пример #3
0
        /// <summary>
        /// Dumps the DOT representation of the control-flow graph of the input function unit
        /// in a file (a DAG file labeled with the name of the function unit) that will be
        /// further processed by the GameTime Python scripts.
        /// </summary>
        ///
        /// <param name="functionUnit">Phoenix function unit whose control-flow graph is
        /// to be dumped.</param>
        /// <param name="sourceNodeId">ID of the BasicBlock in the control-flow
        /// graph to start the analysis from.</param>
        /// <param name="sinkNodeId">ID of the BasicBlock in the control-flow
        /// graph to end the analysis at.</param>
        /// <param name="config">Configuration object that contains
        /// GameTime configuration information.</param>
        /// <param name="projectConfig">ProjectConfiguration object that contains
        /// project configuration information.</param>
        public static void DumpCfgToFile(Phx.FunctionUnit functionUnit,
                                         uint sourceNodeId, uint sinkNodeId, Utilities.Configuration config,
                                         ProjectConfiguration projectConfig)
        {
            Console.Out.WriteLine("PHOENIX: Dumping a DOT representation of the " +
                                  "control-flow graph...");

            string funcName = GetFunctionName(functionUnit);

            Phx.Graphs.FlowGraph flowGraph = functionUnit.FlowGraph;
            Phx.Lifetime         lifetime  = functionUnit.Lifetime;

            if (projectConfig.debugConfig.DUMP_IR)
            {
                Console.Out.WriteLine("PHOENIX: Dumping IR...");

                string irFileName =
                    System.IO.Path.Combine(projectConfig.locationTempDir,
                                           config.TEMP_PHX_IR);
                StreamWriter irWriter = new StreamWriter(irFileName, true);
                irWriter.AutoFlush = true;

                foreach (Phx.Graphs.BasicBlock block in flowGraph.BasicBlocks)
                {
                    irWriter.WriteLine("*** BASIC BLOCK " + block.Id + " ***");
                    foreach (Phx.IR.Instruction instruction in block.Instructions)
                    {
                        irWriter.WriteLine(instruction);
                    }
                }

                irWriter.Close();
            }


            /* Perform a reachability analysis from the source node: determine
             * what nodes and edges can be reached from the source node. */
            Phx.BitVector.Sparse blocksVisitedFromSource = Phx.BitVector.Sparse.New(lifetime);
            Phx.BitVector.Sparse blocksToVisitFromSource = Phx.BitVector.Sparse.New(lifetime);
            Phx.BitVector.Sparse edgesVisitedFromSource  = Phx.BitVector.Sparse.New(lifetime);

            blocksToVisitFromSource.SetBit(sourceNodeId);
            /* TODO: Make more efficient. */
            while (!blocksToVisitFromSource.IsEmpty)
            {
                uint blockToVisitId = blocksToVisitFromSource.RemoveFirstBit();
                blocksVisitedFromSource.SetBit(blockToVisitId);

                Phx.Graphs.BasicBlock blockToVisit =
                    flowGraph.Node(blockToVisitId) as Phx.Graphs.BasicBlock;
                foreach (Phx.Graphs.FlowEdge edge in blockToVisit.SuccessorEdges)
                {
                    Phx.Graphs.BasicBlock successor = edge.SuccessorNode;

                    uint succId = successor.Id;
                    uint edgeId = edge.Id;

                    if (!blocksVisitedFromSource.GetBit(succId))
                    {
                        blocksToVisitFromSource.SetBit(succId);
                        edgesVisitedFromSource.SetBit(edgeId);
                    }
                }
            }

            /* Perform a backward reachability analysis from the sink node: determine
             * what nodes and edges can be reached from the sink node. */
            Phx.BitVector.Sparse blocksVisitedFromSink = Phx.BitVector.Sparse.New(lifetime);
            Phx.BitVector.Sparse blocksToVisitFromSink = Phx.BitVector.Sparse.New(lifetime);
            Phx.BitVector.Sparse edgesVisitedFromSink  = Phx.BitVector.Sparse.New(lifetime);

            blocksToVisitFromSink.SetBit(sinkNodeId);

            while (!blocksToVisitFromSink.IsEmpty)
            {
                uint blockToVisitId = blocksToVisitFromSink.RemoveFirstBit();
                blocksVisitedFromSink.SetBit(blockToVisitId);

                Phx.Graphs.BasicBlock blockToVisit =
                    flowGraph.Node(blockToVisitId) as Phx.Graphs.BasicBlock;
                foreach (Phx.Graphs.FlowEdge edge in blockToVisit.PredecessorEdges)
                {
                    Phx.Graphs.BasicBlock predecessor = edge.PredecessorNode;

                    uint predId = predecessor.Id;
                    uint edgeId = edge.Id;

                    if (!blocksVisitedFromSink.GetBit(predId))
                    {
                        blocksToVisitFromSink.SetBit(predId);
                        edgesVisitedFromSink.SetBit(edgeId);
                    }
                }
            }

            /* Determine which blocks and edges in the control-flow graph can be reached from
             * *both* the source and the sink: this is the section of the control-flow graph
             * that we are interested in. */
            blocksVisitedFromSource.And(blocksVisitedFromSink);
            edgesVisitedFromSource.And(edgesVisitedFromSink);

            uint numNodes = (uint)blocksVisitedFromSource.GetBitCount();
            uint numEdges = (uint)edgesVisitedFromSource.GetBitCount();

            uint numNewNodes = numNodes + numNodes;
            uint numNewEdges = numEdges + numNodes + 1;

            /* Mapping between old block IDs and new block IDs. */
            Dictionary <uint, uint> idMap = new Dictionary <uint, uint>();

            /* Create a writer to write the DAG in DOT format to a file. */
            string dagFileName =
                System.IO.Path.Combine(projectConfig.locationTempDir, config.TEMP_DAG);
            StreamWriter dagWriter = new StreamWriter(dagFileName);

            dagWriter.AutoFlush = true;

            /* Qualify the DAG. */
            dagWriter.WriteLine("digraph " + funcName + " {");

            uint newMappedBlockId = 1;
            uint newFakeBlockId   = numNodes + 1;

            foreach (Phx.Graphs.BasicBlock basicBlock in flowGraph.BasicBlocks)
            {
                uint blockId = basicBlock.Id;

                /* Is the block in the portion of the control-flow graph
                 * we are concerned about? */
                if (blocksVisitedFromSource.GetBit(blockId))
                {
                    uint mappedBlockId;
                    if (idMap.ContainsKey(blockId))
                    {
                        mappedBlockId = idMap[blockId];
                    }
                    else
                    {
                        idMap.Add(blockId, newMappedBlockId);
                        mappedBlockId = newMappedBlockId++;
                    }

                    /* Keep track of the edges that may be added to the resulting DAG. */
                    List <Pair <uint, uint> > edges = new List <Pair <uint, uint> >();

                    /* First edge that may be added to the DAG: it will be added
                     * if there are successors. */
                    edges.Add(new Pair <uint, uint>(mappedBlockId, newFakeBlockId));

                    List <Phx.Graphs.FlowEdge> reverseSuccessorList = new List <Phx.Graphs.FlowEdge>();
                    foreach (Phx.Graphs.FlowEdge edge in basicBlock.SuccessorEdges)
                    {
                        reverseSuccessorList.Add(edge);
                    }
                    reverseSuccessorList.Reverse();

                    foreach (Phx.Graphs.FlowEdge edge in reverseSuccessorList)
                    {
                        /* Is the block in the portion of the control-flow graph
                         * we are concerned about? */
                        Phx.Graphs.BasicBlock successor = edge.SuccessorNode;
                        uint succId = successor.Id;

                        if (blocksVisitedFromSource.GetBit(succId))
                        {
                            uint mappedSuccId;
                            if (idMap.ContainsKey(succId))
                            {
                                mappedSuccId = idMap[succId];
                            }
                            else
                            {
                                idMap.Add(succId, newMappedBlockId);
                                mappedSuccId = newMappedBlockId++;
                            }

                            /* Replace each BasicBlock with two edges,
                             * separated by a new, "fake" node. */
                            edges.Add(new Pair <uint, uint>(newFakeBlockId, mappedSuccId));
                        }
                    }

                    if (edges.Count > 1)
                    {
                        /* This node has successors in the "snipped" CFG. */
                        foreach (Pair <uint, uint> edge in edges)
                        {
                            dagWriter.WriteLine("  " + edge.First + " -> " + edge.Second + ";");
                        }

                        /* Generate the ID of a "fake" node corresponding to
                         * the next node, if any. */
                        newFakeBlockId++;
                    }
                }
            }

            /* Add a "dummy" edge from the sink. */
            dagWriter.WriteLine("  " + idMap[sinkNodeId] + " -> " + numNewNodes + ";");

            dagWriter.WriteLine("}");
            dagWriter.Close();

            /* Copy the mappings to a file. */
            string blockIdMapFile =
                System.IO.Path.Combine(projectConfig.locationTempDir, config.TEMP_DAG_ID_MAP);
            StreamWriter blockIdMapWriter = new StreamWriter(blockIdMapFile);

            blockIdMapWriter.AutoFlush = true;

            foreach (uint key in idMap.Keys)
            {
                uint blockVisitedId = key;
                uint newBlockId     = idMap[key];

                blockIdMapWriter.WriteLine(newBlockId + " " + blockVisitedId);
            }

            blockIdMapWriter.Close();
        }
Пример #4
0
        /// <summary>
        /// Private helper workhorse function for <see cref="Execute"/>.
        /// </summary>
        ///
        /// <param name="moduleUnit">The moduleUnit to process.</param>
        /// <returns>True if successful; false otherwise.</returns>
        private bool ExecuteHelper(Phx.ModuleUnit moduleUnit)
        {
            Console.Out.WriteLine();

            Phx.Graphs.CallGraph callGraph = moduleUnit.CallGraph;
            if (callGraph == null)
            {
                Console.Out.WriteLine("PHOENIX: Call graph is null.");
                Console.Out.WriteLine("Exiting GameTime.");
                Environment.Exit(1);
                return(false);
            }

            /* Load GameTime configuration. */
            string configFile = Console.ReadLine();

            Console.Out.WriteLine("PHOENIX: Configuring this GameTime session with " +
                                  configFile + "...");
            Utilities.Configuration config = Utilities.Configuration.ReadConfigFile(configFile);
            Console.Out.WriteLine("PHOENIX: Successfully configured this session.");

            /* Load the project configuration. */
            string projectConfigFile = Console.ReadLine();

            Console.Out.WriteLine("PHOENIX: Loading project configuration from " +
                                  projectConfigFile + "...");
            ProjectConfiguration projectConfig =
                ProjectConfiguration.ReadProjectConfigFile(projectConfigFile, config);

            Console.Out.WriteLine("PHOENIX: Successfully loaded the project for this session.");

            /* Determine the current GameTime operation mode. */
            string currentMode = Console.ReadLine();

            mode = (currentMode.Equals(config.TEMP_PHX_CREATE_DAG)) ?
                   MODES.CREATE_DAG : MODES.FIND_CONDITIONS;
            Console.Out.WriteLine("PHOENIX: GameTime operation mode is: " +
                                  ((mode == MODES.CREATE_DAG) ? "Create DAG." : "Find path conditions."));

            /* Find the function to analyze. */
            string funcToProcess = projectConfig.func;

            Console.Out.WriteLine("PHOENIX: Preprocessing " + funcToProcess + "...");
            Console.Out.WriteLine();

            Console.Out.WriteLine("PHOENIX: Finding the corresponding function unit...");

            /* Find the function unit corresponding to the function to be analyzed. */
            FunctionUnit functionUnitToProcess = null;

            /* Traverse the graph in post-order (top-down order). */
            Phx.Graphs.NodeFlowOrder nodeOrder = Phx.Graphs.NodeFlowOrder.New(callGraph.Lifetime);
            nodeOrder.Build(callGraph, Phx.Graphs.Order.PostOrder);
            Phx.Targets.Runtimes.Runtime runtime = moduleUnit.Runtime;
            uint functionCount = 0;

            for (uint i = 1; i <= nodeOrder.NodeCount; ++i)
            {
                Phx.Graphs.CallNode node = nodeOrder.Node(i).AsCallNode;
                if ((node == callGraph.UnknownCallerNode) ||
                    (node == callGraph.UnknownCalleeNode))
                {
                    continue;
                }
                if (node.FunctionSymbol != null)
                {
                    /* Is this LTCG mode? */
                    bool isLTCG = false;
                    try
                    {
                        IDictionary env = Environment.GetEnvironmentVariables();
                        if (env.Contains("LINK_TIME_CODE_GENERATION"))
                        {
                            isLTCG = true;
                        }
                    }
                    catch (ArgumentNullException) { }

                    /* Only perform the check when the LTCG mode is off. */
                    if (isLTCG || moduleUnit.IsPEModuleUnit)
                    {
                        moduleUnit = node.FunctionSymbol.CompilationUnitParentSymbol.Unit.AsModuleUnit;
                    }

                    /* Create the corresponding function unit. */
                    Phx.Lifetime     lifetime     = Phx.Lifetime.New(Phx.LifetimeKind.Function, null);
                    Phx.FunctionUnit functionUnit = Phx.FunctionUnit.New(lifetime,
                                                                         node.FunctionSymbol, Phx.CodeGenerationMode.Native,
                                                                         moduleUnit.TypeTable, runtime.Architecture, runtime,
                                                                         moduleUnit, functionCount++);

                    /* Attach debugging info. */
                    Phx.Debug.Info.New(functionUnit.Lifetime, functionUnit);

                    node.FunctionSymbol.FunctionUnit = functionUnit;
                    this.PhaseConfiguration.PhaseList.DoPhaseList(functionUnit);
                    functionUnit.Context.PopUnit();

                    string funcName = FunctionUnitHelper.GetFunctionName(functionUnit);
                    if (funcName == funcToProcess)
                    {
                        functionUnitToProcess = functionUnit;
                        break;
                    }
                }
            }

            if (functionUnitToProcess == null)
            {
                Console.Out.WriteLine("PHOENIX: Cannot find function named " + funcToProcess + ".");
                Console.Out.WriteLine("PHOENIX: Exiting GameTime...");
                Environment.Exit(1);
                return(false);
            }
            else
            {
                Console.Out.WriteLine("PHOENIX: Function unit found.");
            }

            Console.Out.WriteLine("PHOENIX: Preprocessing the function unit...");
            FunctionUnitHelper.Preprocess(functionUnitToProcess);
            Console.Out.WriteLine("PHOENIX: Function unit preprocessing complete.");
            Console.Out.WriteLine();

            Console.Out.WriteLine("PHOENIX: Building the flow graph...");
            functionUnitToProcess.BuildFlowGraphWithoutEH();
            Phx.Graphs.FlowGraph graph = functionUnitToProcess.FlowGraph;
            Console.Out.WriteLine("PHOENIX: Flow graph built.");

            Console.Out.WriteLine("PHOENIX: Snipping the relevant portion of the flow graph...");

            uint sourceBlockId = 1;
            uint sinkBlockId   = graph.NodeCount;

            if (projectConfig.startLabel != "")
            {
                Phx.Graphs.BasicBlock sourceBlock =
                    FunctionUnitHelper.SplitAtUserLabel(functionUnitToProcess,
                                                        projectConfig.startLabel);
                sourceBlockId = sourceBlock.Id;
            }
            if (projectConfig.endLabel != "")
            {
                Phx.Graphs.BasicBlock sinkBlock =
                    FunctionUnitHelper.SplitAtUserLabel(functionUnitToProcess,
                                                        projectConfig.endLabel);

                /* Correct the sink block: we want the block just before the block
                 * we receive from SplitAtUserLabel. */
                Phx.Graphs.FlowEdge edgeToSink = sinkBlock.PredecessorEdgeList;
                sinkBlock   = edgeToSink.PredecessorNode;
                sinkBlockId = sinkBlock.Id;
            }

            Console.Out.WriteLine("PHOENIX: Relevant portion snipped.");
            Console.Out.WriteLine();

            Console.Out.WriteLine("PHOENIX: Starting analysis...");

            switch (mode)
            {
            case MODES.CREATE_DAG:
                FunctionUnitHelper.DumpCfgToFile(functionUnitToProcess,
                                                 sourceBlockId, sinkBlockId, config, projectConfig);
                break;

            case MODES.FIND_CONDITIONS:
                FunctionUnitHelper.FindPathConditions(functionUnitToProcess,
                                                      config, projectConfig);
                break;
            }

            Console.Out.WriteLine("PHOENIX: Analysis successful.");
            Console.Out.WriteLine();

            Environment.Exit(0);
            return(true);
        }