/// <summary> /// Renames all variables in a block to use their SSA names /// </summary> /// <param name="n">Block to rename</param> public void RenameBlock(Block n) { var wasonentry = new Dictionary <Identifier, Identifier>(rename); // Rename variables in all blocks except the starting block which // only contains dummy 'def' variables. if (n != n.Procedure.EntryBlock) { foreach (Statement stm in n.Statements) { stmCur = stm; stmCur.Instruction = stmCur.Instruction.Accept(this); } if (n == n.Procedure.ExitBlock && this.addUseInstructions) { AddUseInstructions(n); } } // Rename arguments to phi functions in successor blocks. bool [] visited = new bool[proc.ControlGraph.Blocks.Count]; foreach (Block y in n.Succ) { for (int j = 0; j < y.Pred.Count; ++j) { if (y.Pred[j] == n && !visited[ssa.RpoNumber(y)]) { visited[ssa.RpoNumber(y)] = true; // For each phi function in y... foreach (Statement stm in y.Statements.Where(s => s.Instruction is PhiAssignment)) { var newPhi = newPhiStatements.Contains(stm); stmCur = stm; PhiAssignment phi = (PhiAssignment)stmCur.Instruction; PhiFunction p = phi.Src; // replace 'n's slot with the renamed name of the variable. p.Arguments[j] = NewUse((Identifier)p.Arguments[j], stm, newPhi); } } } } foreach (Block c in ssa.DomGraph.ReversePostOrder.Keys) { if (c != proc.EntryBlock && ssa.DomGraph.ImmediateDominator(c) == n) { RenameBlock(c); } } rename = wasonentry; }
private void MarkDefined(Identifier eDef) { SsaIdentifier sid; var idDef = eDef as Identifier; if (idDef != null && ssa.Identifiers.TryGetValue(idDef, out sid)) { // If we've seen this identifier before, use its // original name. eDef = sid.OriginalIdentifier; } var dict = defVars[ssa.RpoNumber(block)]; byte bits; dict.TryGetValue(eDef, out bits); dict[eDef] = (byte)(bits | (BitDefined | BitDeadIn)); if (!inDefinitions.Contains(eDef)) { inDefinitions.Add(eDef); definitions.Add(eDef); } }
private HashSet <Statement> PlacePhiFunctions() { HashSet <Statement> phiStatements = new HashSet <Statement>(); var defVars = LocateAllDefinedVariables(AOrig); MarkTemporariesDeadIn(AOrig); // For each defined variable in block n, collect the places where it is defined foreach (var a in defVars) { // Create a worklist W of all the blocks that define a. var W = new WorkList <Block>(); foreach (Block b in SsaState.DomGraph.ReversePostOrder.Keys) { byte bits; AOrig[SsaState.RpoNumber(b)].TryGetValue(a, out bits); if ((bits & BitDefined) != 0) { W.Add(b); } } Block n; while (W.GetWorkItem(out n)) { foreach (Block y in SsaState.DomGraph.DominatorFrontier(n)) { // Only add phi functions if there is no // phi already and variable is not deadIn. var dict = AOrig[SsaState.RpoNumber(y)]; byte bits; dict.TryGetValue(a, out bits); if ((bits & (BitHasPhi | BitDeadIn)) == 0) { bits |= BitHasPhi; dict[a] = bits; var stm = InsertPhiStatement(y, a); phiStatements.Add(stm); if ((bits & BitDefined) == 0) { W.Add(y); } } } } } return(phiStatements); }
/// <summary> /// Temporary variables are never live-in, so we avoid getting phi /// functions all over the place by marking them explicitly as dead-in. /// </summary> /// <param name="def"></param> private void MarkTemporariesDeadIn(Dictionary <Expression, byte>[] def) { foreach (var block in proc.ControlGraph.Blocks) { int iBlock = SsaState.RpoNumber(block); foreach (Identifier id in proc.Frame.Identifiers.Where(id => id.Storage is TemporaryStorage)) { byte bits; if (!def[iBlock].TryGetValue(id, out bits)) { bits = 0; } def[iBlock][id] = (byte)(bits | BitDeadIn); } } }