/// <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); }
/// <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."); }
/// <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(); }
/// <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); }