public Identifier InsertAssignmentNewId(Identifier idOld, Block b, int i) { Statement stm = new Statement(0, null, b); SsaIdentifier sidNew = ssaIds.Add((Identifier)ssaIds[idOld].OriginalIdentifier, stm, idOld, false); stm.Instruction = new Assignment(sidNew.Identifier, idOld); b.Statements.Insert(i, stm); return sidNew.Identifier; }
/// <summary> /// Creates a phi statement with slots for each predecessor block, then /// inserts the phi statement as the first statement of the block. /// </summary> /// <param name="b">Block into which the phi statement is inserted</param> /// <param name="v">Destination variable for the phi assignment</param> /// <returns>The inserted phi Assignment</returns> private Instruction InsertPhiStatement(Block b, Identifier v) { var stm = new Statement( 0, new PhiAssignment(v, b.Pred.Count), b); b.Statements.Insert(0, stm); return stm.Instruction; }
public void Test2() { BinaryExpression b = m.IAdd(id, m.UMul(id, 5)); Assignment ass = new Assignment(x, b); Statement stm = new Statement(0, ass, null); Add_mul_id_c_id_Rule rule = new Add_mul_id_c_id_Rule(new SsaEvaluationContext(ssaIds)); Assert.IsTrue(rule.Match(b)); ass.Src = rule.Transform(); Assert.AreEqual("x = id *u 0x00000006", ass.ToString()); }
public void Test1() { BinaryExpression b = m.Shl(m.SMul(id, 3), 2); Assignment ass = new Assignment(x, b); Statement stm = new Statement(0, ass, null); ssaIds[id].Uses.Add(stm); ssaIds[id].Uses.Add(stm); var rule = new Shl_mul_e_Rule(null); Assert.IsTrue(rule.Match(b)); ass.Src = rule.Transform(); Assert.AreEqual("x = id *s 12", ass.ToString()); }
public SsaIdentifier(Identifier id, Identifier eOrig, Statement stmDef, Expression exprDef, bool isSideEffect) { if (id == null) throw new ArgumentNullException("id"); if (eOrig == null) throw new ArgumentNullException("eOrig"); this.Identifier = id; this.OriginalIdentifier = eOrig; this.DefStatement = stmDef; this.DefExpression = exprDef; this.IsSideEffect = isSideEffect; this.Uses = new List<Statement>(); }
public bool AreConstrained(Statement def, Statement use) { SideEffectFlags defFlags = FindSideEffect(def.Instruction); int iUse = use.Block.Statements.IndexOf(use); for (int i = def.Block.Statements.IndexOf(def) + 1; i < def.Block.Statements.Count; ++i) { if (i == iUse) return false; if (Conflict(defFlags, FindSideEffect(def.Block.Statements[i].Instruction))) return true; } return true; }
private void SetDefStatement(Statement stm, SsaIdentifier sid) { List<SsaIdentifier> sids; if (defsByStatement.TryGetValue(sid.DefStatement, out sids)) { sids.Remove(sid); } if (!defsByStatement.TryGetValue(stm, out sids)) { sids = new List<SsaIdentifier>(); defsByStatement.Add(stm, sids); } sids.Add(sid); }
/// <summary> /// Rewrites CALL instructions to function applications. /// </summary> /// <remarks> /// Converts an opcode: /// <code> /// call procExpr /// </code> /// to one of: /// <code> /// ax = procExpr(bindings); /// procEexpr(bindings); /// </code> /// </remarks> /// <param name="proc">Procedure in which the CALL instruction exists</param> /// <param name="stm">The particular statement of the call instruction</param> /// <param name="call">The actuall CALL instruction.</param> /// <returns>True if the conversion was possible, false if the procedure didn't have /// a signature yet.</returns> public bool RewriteCall(Procedure proc, Statement stm, CallInstruction call) { var callee = call.Callee as ProcedureConstant; if (callee == null) return false; //$REVIEW: what happens with indirect calls? var procCallee = callee.Procedure; var sigCallee = GetProcedureSignature(procCallee); var fn = new ProcedureConstant(Program.Platform.PointerType, procCallee); if (sigCallee == null || !sigCallee.ParametersValid) return false; var ab = new ApplicationBuilder(Program.Architecture, proc.Frame, call.CallSite, fn, sigCallee, true); stm.Instruction = ab.CreateInstruction(); return true; }
public void Test1() { BinaryExpression b = m.IAdd(m.SMul(id, 4), id); Assignment ass = new Assignment(x, b); Statement stm = new Statement(0, ass, null); ssaIds[id].Uses.Add(stm); ssaIds[id].Uses.Add(stm); ctx.Statement = stm; Add_mul_id_c_id_Rule rule = new Add_mul_id_c_id_Rule(ctx); Assert.IsTrue(rule.Match(b)); Assert.AreEqual(2, ssaIds[id].Uses.Count); ass.Src = rule.Transform(); Assert.AreEqual("x = id *s 0x00000005", ass.ToString()); Assert.AreEqual(1, ssaIds[id].Uses.Count); }
public void Creation() { CallGraph g = new CallGraph(); Procedure p1 = new Procedure("p1000", null); Procedure p2 = new Procedure("p2000", null); Procedure p3 = new Procedure("p3000", null); Procedure p4 = new Procedure("p4000", null); var pc1 = new ProcedureConstant(PrimitiveType.Pointer32, p1); var pc2 = new ProcedureConstant(PrimitiveType.Pointer32, p2); var pc3 = new ProcedureConstant(PrimitiveType.Pointer32, p3); var pc4 = new ProcedureConstant(PrimitiveType.Pointer32, p4); Statement s11 = new Statement(0, CreateCall(pc2), p1.EntryBlock); Statement s12 = new Statement(0, CreateCall(pc2), p1.EntryBlock); Statement s13 = new Statement(0, CreateCall(pc3), p1.EntryBlock); p1.EntryBlock.Statements.Add(s11); p1.EntryBlock.Statements.Add(s12); p1.EntryBlock.Statements.Add(s13); Statement s21 = new Statement(0, CreateCall(pc3), p2.EntryBlock); Statement s22 = new Statement(0, CreateCall(pc4), p2.EntryBlock); p2.EntryBlock.Statements.Add(s21); p2.EntryBlock.Statements.Add(s22); Statement s31 = new Statement(0, CreateCall(pc4), p3.EntryBlock); p3.EntryBlock.Statements.Add(s31); Statement s41 = new Statement(0, CreateCall(pc4), p4.EntryBlock); g.AddEntryPoint(p1); g.AddEdge(s11, p2); g.AddEdge(s12, p2); g.AddEdge(s13, p3); g.AddEdge(s21, p3); g.AddEdge(s22, p4); g.AddEdge(s31, p4); g.AddEdge(s41, p4); // recursion! //$TODO: need Count // Assert.IsTrue(g.Callees(p1).Count == 3); // Assert.IsTrue(g.CallerStatements(p4).Count == 3); }
/// <summary> /// Chases a chain statements to locate the expression that /// defines the value of a condition code. /// </summary> /// <param name="sid"></param> /// <returns></returns> public void FindDefiningExpression(SsaIdentifier sid) { this.sid = sid; negated = false; stm = sid.DefStatement; if (stm != null) { Statement stmOld = null; defExpr = null; while (stm != null && defExpr == null) { stmOld = stm; stm = null; stmOld.Instruction.Accept(this); } } }
/// <summary> /// Inserts the instr d of the identifier v at statement S. /// </summary> /// <param name="d"></param> /// <param name="v"></param> /// <param name="S"></param> public void Insert(Instruction d, Identifier v, Statement S) { // Insert new phi-functions. foreach (var dfFode in DomGraph.DominatorFrontier(S.Block)) { // If there is no phi-function for v // create new phi-function for v. (which is an insert, so call self recursively) // All input operands of the new phi-finctions are initually assumed to be // uses of r. // Update uses sets for all uses dominated by S, or the new phi statements. // This is done by walking down the dominator tree from each def and find uses // that along wit the def match property 1. // Update each use that is a parameter of a newly created phi-function, according // to property 2. } }
public void ReplaceDefinitionsWithOutParameter(Identifier id, Identifier idOut) { this.idOut = idOut; wl = new WorkList<Identifier>(); wl.Add(id); var visited = new HashSet<Statement>(); while (wl.GetWorkItem(out id)) { ssa = ssaIds[id]; stmDef = ssa.DefStatement; if (stmDef != null && !visited.Contains(stmDef)) { visited.Add(stmDef); iStmDef = stmDef.Block.Statements.IndexOf(stmDef); stmDef.Instruction = stmDef.Instruction.Accept(this); } } }
public void Transform() { foreach (var s in ssaIds) { sidGrf = s; if (!IsLocallyDefinedFlagGroup(sidGrf)) continue; var uses = new HashSet<Statement>(); aliases = new HashSet<SsaIdentifier>(); ClosureOfUsingStatements(sidGrf, sidGrf.DefExpression, uses, aliases); if (trace.TraceInfo) Debug.WriteLine(string.Format("Tracing {0}", sidGrf.DefStatement.Instruction)); foreach (var u in uses) { useStm = u; if (trace.TraceInfo) Debug.WriteLine(string.Format(" used {0}", useStm.Instruction)); useStm.Instruction.Accept(this); if (trace.TraceInfo) Debug.WriteLine(string.Format(" now {0}", useStm.Instruction)); } } }
/// <summary> /// Tries to move the assigment as far down the block as is possible. /// </summary> /// <param name="ass"></param> /// <param name="block"></param> /// <param name="i"></param> /// <returns>true if a change was made</returns> public bool TryMoveAssignment(Statement stmDef, SsaIdentifier sidDef, Expression defExpr, Block block, int initialPosition) { SideEffectFlags flagsDef = sef.FindSideEffect(stmDef.Instruction); for (int i = initialPosition + 1; i < block.Statements.Count; ++i) { Statement stm = block.Statements[i]; if (sidDef.Uses.Contains(stm)) { if (CanCoalesce(sidDef, stmDef, stm)) { Coalesced = true; return CoalesceStatements(sidDef, defExpr, stmDef, stm); } else { return MoveAssignment(initialPosition, i, block); } } if (stm.Instruction.IsControlFlow) { return MoveAssignment(initialPosition, i, block); } SideEffectFlags flagsStm = sef.FindSideEffect(stm.Instruction); if (sef.Conflict(flagsDef, flagsStm)) { return MoveAssignment(initialPosition, i, block); } } return MoveAssignment(initialPosition, block.Statements.Count, block); }
private Block PrecedingPhiBlock(Identifier u, Statement stm) { PhiAssignment phi = stm.Instruction as PhiAssignment; if (phi == null) return null; for (int i = 0; i < phi.Src.Arguments.Length; ++i) { if (u == phi.Src.Arguments[i]) return stm.Block.Pred[i]; } return null; }
private Dictionary<SsaIdentifier,SsaIdentifier> VariablesDefinedByStatement(Statement stm) { Dictionary<SsaIdentifier,SsaIdentifier> W = new Dictionary<SsaIdentifier,SsaIdentifier>(); foreach (SsaIdentifier sid in ssa) { if (sid.DefStatement == stm) W[sid] = sid; } return W; }
public PhiFunction GetPhiFunction(Statement stm) { PhiAssignment ass = stm.Instruction as PhiAssignment; if (ass == null) return null; return ass.Src; }
// Returns true if v is also live in before executing s. public bool LiveOutAtStatement(Statement s, SsaIdentifier v) { // v is live-out at s. List<Identifier> ids = this.IdentifiersDefinedAtStatement(s); if (ids != null) { foreach (Identifier id in ids) { if (id != v.Identifier) interference.Add(id, v.Identifier); } } return (v.DefStatement != s); }
public bool IsLiveOut(Identifier id, Statement stm) { bool live = records[stm.Block].LiveOut.Contains(ssaIds[id]); for (int i = stm.Block.Statements.Count - 1; i >= 0; --i) { Statement s = stm.Block.Statements[i]; if (s == stm) return live; if (ssaIds[id].DefStatement == s) return false; if (!(s.Instruction is PhiAssignment) && ssaIds[id].Uses.Contains(s)) live = true; } return live; }
public bool IsFirstStatementInBlock(Statement stm, Block block) { return block.Statements.IndexOf(stm) == 0; }
public bool IsDefinedAtStatement(SsaIdentifier v, Statement stm) { return (v.DefStatement == stm); }
public List<Identifier> IdentifiersDefinedAtStatement(Statement stm) { if (stm == null) return null; return defined[stm]; }
/// <summary> /// Returns true if the identifer <paramref name="sid"/>, which is defined in <paramref name="def"/>, can safely /// be coalesced into <paramref name="use"/>. /// </summary> /// <param name="sid">identifier common to <paramref name="def"/> and <paramref name="use"/>.</param> /// <param name="def">Statement that defines <paramref name="sid"/>. </param> /// <param name="use">Statement that uses <paramref name="sid"/>. </param> /// <returns></returns> public bool CanCoalesce(SsaIdentifier sid, Statement def, Statement use) { if (sid.Uses.Count != 1) return false; System.Diagnostics.Debug.Assert(sid.Uses[0] == use); if (use.Instruction is PhiAssignment) return false; if (use.Instruction is UseInstruction) return false; //$PERFORMANCE: this loop might be slow and should be improved if possible. List<SsaIdentifier> sids; if (defsByStatement.TryGetValue(def, out sids)) { foreach (SsaIdentifier sidOther in sids) { if (sidOther != sid && sidOther.IsSideEffect) { if (sidOther.Uses.Contains(use)) return false; } } } return true; }
public UsedIdentifierAdjuster(Statement def, SsaIdentifierCollection ssaIds, Statement use) { this.def = def; this.use = use; this.ssaIds = ssaIds; }
/// <summary> /// Coalesces the single use and the single definition of an identifier. /// </summary> /// <param name="sid"></param> /// <param name="defExpr"></param> /// <param name="def"></param> /// <param name="use"></param> /// <returns></returns> public bool CoalesceStatements(SsaIdentifier sid, Expression defExpr, Statement def, Statement use) { PreCoalesceDump(sid, def, use); def.Instruction.Accept(new UsedIdentifierAdjuster(def, ssa.Identifiers, use)); use.Instruction.Accept(new IdentifierReplacer(ssa, use, sid.Identifier, defExpr)); List<SsaIdentifier> sids; if (defsByStatement.TryGetValue(def, out sids)) { foreach (SsaIdentifier s in sids) { if (s != sid) { s.DefStatement = use; SetDefStatement(use, s); } } } ssa.DeleteStatement(def); PostCoalesceDump(use); return true; }
private static void PreCoalesceDump(SsaIdentifier sid, Statement def, Statement use) { if (trace.TraceInfo) { Debug.WriteLineIf(trace.TraceInfo, "Coalescing on " + sid.Identifier.ToString()); Debug.Indent(); Debug.WriteLineIf(trace.TraceInfo, def.Instruction.ToString()); Debug.WriteLineIf(trace.TraceInfo, use.Instruction.ToString()); Debug.Unindent(); } }
private static void PostCoalesceDump(Statement use) { if (trace.TraceInfo) { Debug.WriteLineIf(trace.TraceInfo, " ; coalesced to"); Debug.Indent(); Debug.WriteLineIf(trace.TraceInfo, use.Instruction.ToString()); Debug.Unindent(); } }
public Statement BranchIf(Expression expr, string label) { Block b = EnsureBlock(null); branchBlock = BlockOf(label); TerminateBlock(); Statement stm = new Statement(0, new Branch(expr, branchBlock), b); b.Statements.Add(stm); return stm; }
public IdentifierReplacer(SsaState ssaIds, Statement use, Identifier idOld, Expression exprNew) { this.ssaIds = ssaIds; this.use = use; this.idOld = idOld; this.exprNew = exprNew; }