public void Setup() { // identifiers.json holds sample tree constructed from V1 urls var identifiersJson = System.IO.File.ReadAllText("identifiers.json"); var tree = System.Text.Json.JsonSerializer.Deserialize <IDTree>(identifiersJson); idReplacer = new IdentifierReplacer(tree); }
public override void Process() { var movedBlocks = new HashSet<Block>(); var stack = new Stack<IEnumerator<Block>>(); stack.Push(new Block[] { Block }.Cast<Block>().GetEnumerator()); var replacer = new IdentifierReplacer(ProcNew.Frame); while (stack.Count != 0) { DumpBlocks(Block.Procedure); var e = stack.Peek(); if (!e.MoveNext()) { stack.Pop(); continue; } var b = e.Current; if (b.Procedure == ProcNew || b == b.Procedure.ExitBlock || b.Procedure.EntryBlock.Succ[0] == b) continue; Debug.Print("PromoteBlock visiting block {0}", b.Name); b.Procedure.RemoveBlock(b); ProcNew.AddBlock(b); b.Procedure = ProcNew; movedBlocks.Add(b); foreach (var stm in b.Statements) { stm.Instruction = replacer.ReplaceIdentifiers(stm.Instruction); } if (b.Succ.Count > 0) stack.Push(b.Succ.GetEnumerator()); } foreach (var b in movedBlocks) { FixExitEdges(b); FixInboundEdges(b); FixOutboundEdges(b); } }
/// <summary> /// Remove temporary assignment from the result. That is, removing /// assignment "t1 = x" where t1 is a temporary variable. This kind /// of assginment can be safely removed, but now all nodes that /// connect to "t1" should re-connect to "x". For example, "a = t1" /// now should be updated to "a = x". /// </summary> /// <param name="result"></param> /// <returns></returns> public static NodeToCodeResult ConstantPropagationForTemp(NodeToCodeResult result, IEnumerable <string> outputVariables) { var tempVars = new HashSet <string>( result.OutputMap.Where(p => p.Key.StartsWith(Constants.kTempVarForNonAssignment)) .Select(p => p.Value)); var nonTempAsts = new List <AssociativeNode>(); var tempAssignments = new List <Tuple <IdentifierNode, AssociativeNode> >(); foreach (var ast in result.AstNodes) { var expr = ast as BinaryExpressionNode; if (expr == null || expr.Optr != Operator.assign) { nonTempAsts.Add(ast); continue; } var lhs = expr.LeftNode as IdentifierNode; var rhs = expr.RightNode; if (lhs == null || !tempVars.Contains(lhs.Value) || outputVariables.Contains(lhs.Value) || !(rhs.IsLiteral || rhs is IdentifierNode)) { nonTempAsts.Add(ast); continue; } IdentifierFinder finder = new IdentifierFinder(lhs.Value, false); bool isReferenced = result.AstNodes.Any(n => n.Accept(finder)); bool isRhsDefined = false; if (rhs is IdentifierNode) { var defFinder = new IdentifierFinder((rhs as IdentifierNode).Value, true); isRhsDefined = result.AstNodes.Any(n => n.Accept(defFinder)); } if (isReferenced || isRhsDefined) { tempAssignments.Add(Tuple.Create(lhs, rhs)); } else { nonTempAsts.Add(ast); } } foreach (var pair in tempAssignments) { // Update the map. var keys = result.OutputMap.Keys.ToList(); for (int i = 0; i < keys.Count; ++i) { var value = result.OutputMap[keys[i]]; if (value.Equals(pair.Item1.Value)) { var rhs = pair.Item2 as IdentifierNode; if (rhs != null) { result.OutputMap[keys[i]] = rhs.Value; } } } // Update ASTs. IdentifierReplacer replacer = new IdentifierReplacer(pair.Item1.Value, pair.Item2); foreach (var ast in nonTempAsts) { ast.Accept(replacer); } } return(new NodeToCodeResult(nonTempAsts, result.InputMap, result.OutputMap)); }