public void Setup() { m = new ProcedureBuilder(); ssaState = new SsaState(m.Procedure, null); ssaIds = ssaState.Identifiers; freg = new FlagRegister("flags", 32, PrimitiveType.Word32); }
protected void DumpSsaInfo(Procedure proc, SsaState ssa, TextWriter writer) { writer.WriteLine("// {0} ////////////////////////////////", proc.Name); DumpSsaTypes(ssa, writer); proc.Write(false, writer); writer.WriteLine(); }
public StrengthReduction(SsaState ssa, LinearInductionVariable liv, LinearInductionVariableContext ctx) { this.ssa = ssa; this.liv = liv; this.ctx = ctx; incrUses = new List<IncrementedUse>(); }
public ConditionCodeEliminator(SsaState ssa, IPlatform arch) { this.ssa=ssa; this.ssaIds = ssa.Identifiers; this.platform = arch; this.m = new ExpressionEmitter(); }
protected void DumpSsaTypes(SsaState ssa, TextWriter writer) { foreach (SsaIdentifier id in ssa.Identifiers) { if (id.Identifier.TypeVariable != null) writer.WriteLine("{0}: {1}", id.Identifier, id.Identifier.TypeVariable); } }
public Coalescer(Procedure proc, SsaState ssa) { this.proc = proc; this.ssa = ssa; this.sef = new SideEffectFinder(); this.defsByStatement = new Dictionary<Statement, List<SsaIdentifier>>(); foreach (SsaIdentifier sid in ssa.Identifiers) { if (sid.DefStatement != null) SetDefStatement(sid.DefStatement, sid); } }
public IndirectCallRewriter( Program program, SsaState ssa, DecompilerEventListener eventListener) { this.program = program; this.proc = ssa.Procedure; this.ssa = ssa; this.asc = new IndirectCallTypeAscender(program); this.expander = new IndirectCallExpander(ssa); this.ssaIdTransformer = new SsaIdentifierTransformer(ssa); this.eventListener = eventListener; }
private void InsertOutArgumentAssignment( SsaState ssa, Identifier parameter, Expression e, Block block, int insertPos) { var iAddr = block.Statements[insertPos].LinearAddress; var stm = block.Statements.Insert( insertPos, iAddr, new Store(parameter, e)); ssa.AddUses(stm); }
public IndirectCallRewriter( Program program, SsaState ssa, DecompilerEventListener eventListener) { this.program = program; this.proc = ssa.Procedure; this.ssa = ssa; this.asc = new IndirectCallTypeAscender(program); this.expander = new IndirectCallExpander(ssa); this.ssaIdTransformer = new SsaIdentifierTransformer(ssa); this.eventListener = eventListener; this.ssam = new SsaMutator(ssa); }
public void DumpWatchedProcedure(string phase, string caption, SsaState ssa) { DumpWatchedProcedure(phase, caption, ssa.Procedure); #if FIND_BUGS // This is currently disabled because of hard-to-fix problems with the UnalignedMemoryAccessFuser ssa.Validate(s => { Console.WriteLine("== SSA validation failure; {0} {1}", caption, ssa.Procedure.Name, s); Console.WriteLine(" {0}", s); ssa.Write(Console.Out); ssa.Procedure.Write(false, Console.Out); }); #endif }
/// <summary> /// Walks the dominator tree, renaming the different definitions of variables /// (including phi-functions). /// </summary> /// <param name="ssa">SSA identifiers</param> /// <param name="p">procedure to rename</param> public VariableRenamer(SsaTransform ssaXform) { this.programFlow = ssaXform.programFlow; this.ssa = ssaXform.SsaState; this.renameFrameAccess = ssaXform.RenameFrameAccesses; this.addUseInstructions = ssaXform.AddUseInstructions; this.proc = ssaXform.proc; this.rename = new Dictionary <Identifier, Identifier>(); this.stmCur = null; this.existingDefs = proc.EntryBlock.Statements .Select(s => s.Instruction as DefInstruction) .Where(d => d != null) .Select(d => d.Expression) .ToHashSet(); }
public ValuePropagator( SegmentMap segmentMap, SsaState ssa, CallGraph callGraph, IImportResolver importResolver, DecompilerEventListener eventListener) { this.ssa = ssa; this.callGraph = callGraph; this.arch = ssa.Procedure.Architecture; this.eventListener = eventListener; this.ssaIdTransformer = new SsaIdentifierTransformer(ssa); this.evalCtx = new SsaEvaluationContext(arch, ssa.Identifiers, importResolver); this.eval = new ExpressionSimplifier(segmentMap, evalCtx, eventListener); }
private Statement?stmCur; //$REFACTOR: try to make this a context paramter. public ValuePropagator( SegmentMap segmentMap, SsaState ssa, CallGraph callGraph, IDynamicLinker dynamicLinker, DecompilerEventListener eventListener) { this.ssa = ssa; this.callGraph = callGraph; this.arch = ssa.Procedure.Architecture; this.eventListener = eventListener; this.ssam = new SsaMutator(ssa); this.evalCtx = new SsaEvaluationContext(arch, ssa.Identifiers, dynamicLinker); this.eval = new ExpressionSimplifier(segmentMap, evalCtx, eventListener); }
/// <summary> // Statements of the form: // call <ssaCaller-operand> // become redefined to // ret = <ssaCaller-operand>(bindings) // where ret is the return register (if any) and the // bindings are the bindings of the procedure. /// </summary> /// <param name="ssaCeller">SSA state of the calling procedure.</param> /// <returns>The number of calls that couldn't be converted</returns> public int RewriteCalls(SsaState ssaCaller) { int unConverted = 0; foreach (Statement stm in ssaCaller.Procedure.Statements.ToList()) { if (stm.Instruction is CallInstruction ci) { if (!RewriteCall(ssaCaller, stm, ci)) { ++unConverted; } } } return(unConverted); }
/// <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); } } }
private void PlacePhiFunctions() { 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; InsertPhiStatement(y, a); if ((bits & BitDefined) == 0) { W.Add(y); } } } } } }
/// <summary> /// Walks the dominator tree, renaming the different definitions of variables /// (including phi-functions). /// </summary> /// <param name="ssa">SSA identifiers</param> /// <param name="newPhiStatements"> /// Phi statements added during current pass of SsaTransform. Used /// to avoid extra use of identifiers in existing phi assignments /// </param> public VariableRenamer(SsaTransform ssaXform, HashSet <Statement> newPhiStatements) { this.programFlow = ssaXform.programFlow; this.ssa = ssaXform.SsaState; this.implicitRegs = ssaXform.implicitRegs; this.renameFrameAccess = ssaXform.RenameFrameAccesses; this.addUseInstructions = ssaXform.AddUseInstructions; this.proc = ssaXform.proc; this.importResolver = ssaXform.importResolver; this.rename = new Dictionary <Identifier, Identifier>(); this.stmCur = null; this.existingDefs = proc.EntryBlock.Statements .Select(s => s.Instruction as DefInstruction) .Where(d => d != null) .Select(d => d.Identifier) .ToHashSet(); this.newPhiStatements = newPhiStatements; }
public void Transform(Procedure proc) { this.ssa = new SsaState(proc, null); this.asta = new AliasState(); this.currentDef = new Dictionary <Block, Dictionary <Storage, SsaIdentifier> >(); this.incompletePhis = new Dictionary <Block, Dictionary <Storage, SsaIdentifier> >(); this.sealedBlocks = new HashSet <Block>(); foreach (Block b in new DfsIterator <Block>(proc.ControlGraph).PreOrder()) { this.block = b; this.currentDef.Add(block, new Dictionary <Storage, SsaIdentifier>()); // new StorageEquality())); foreach (var s in b.Statements.ToList()) { this.stm = s; stm.Instruction = stm.Instruction.Accept(this); } } }
/// <summary> /// Remove any Use instruction that uses identifiers /// that are marked as preserved. /// </summary> /// <param name="ssa"></param> private void RemovePreservedUseInstructions(SsaState ssa) { var flow = this.flow[ssa.Procedure]; var deadStms = new List <Statement>(); foreach (var stm in ssa.Procedure.ExitBlock.Statements) { if (stm.Instruction is UseInstruction u && u.Expression is Identifier id && flow.Preserved.Contains(id.Storage)) { deadStms.Add(stm); } } foreach (var stm in deadStms) { ssa.DeleteStatement(stm); } }
/// <summary> /// Rewrites CALL instructions to function applications. /// </summary> /// <remarks> /// Converts an instruction: /// <code> /// call procExpr /// </code> /// to one of: /// <code> /// ax = procExpr(bindings); /// procEexpr(bindings); /// </code> /// </remarks> /// <param name="ssaCaller">SSA state of the 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> public bool RewriteCall(SsaState ssaCaller, Statement stm, CallInstruction call) { if (call.Callee is ProcedureConstant callee) { var procCallee = callee.Procedure; var sigCallee = procCallee.Signature; var fn = new ProcedureConstant(platform.PointerType, procCallee); if (sigCallee == null || !sigCallee.ParametersValid) { return(false); } if (stm.LinearAddress == 0x000000000001e32) { stm.ToString(); //$DEBUG } ApplicationBuilder ab = CreateApplicationBuilder(ssaCaller, stm, call, fn); var instr = ab.CreateInstruction(sigCallee, procCallee.Characteristics); var instrOld = stm.Instruction; stm.Instruction = instr; var ssam = new SsaMutator(ssaCaller); ssam.AdjustSsa(stm, call); return(true); } else { return(false); #if NOT_READY_YET //$TODO // We have an indirect call with an unknown signature. // Use the guessed `uses` and `defs` to construct a signature. // It's likely going to be wrong, but it can be overridden with // user-provided metadata. var sigCallee = MakeSignature(ssaCaller, call.Uses, call.Definitions); var ab = CreateApplicationBuilder(ssaCaller, stm, call, call.Callee); var instr = ab.CreateInstruction(sigCallee, Core.Serialization.DefaultProcedureCharacteristics.Instance); stm.Instruction = instr; var ssam = new SsaMutator(ssaCaller); ssam.AdjustSsa(stm, call); return(true); #endif } }
/// <summary> /// From the call instruction <paramref name="ci"/>, in statement <paramref name="stmCall"/>, /// removes those 'use's that have been marked as dead in <paramref name="deadStgs"/>. /// </summary> private bool RemoveDeadCallUses(SsaState ssa, Statement stmCall, CallInstruction ci, HashSet <Storage> deadStgs) { //$REVIEW: this code is similar to DeadCode.AdjustCallWithDeadDefinitions // Move it to SsaState? Somewhere else? int cRemoved = ci.Uses.RemoveWhere(use => { if (use.Expression is Identifier id) { if (deadStgs.Contains(id.Storage)) { var sidUse = ssa.Identifiers[id]; sidUse.Uses.Remove(stmCall); return(true); } } return(false); }); return(cRemoved > 0); }
/// <summary> /// Having identified the return variable -- if any -- rewrite all /// return statements to return that variable. /// </summary> /// <param name="ssa"></param> public void RewriteReturns(SsaState ssa) { // For each basic block reaching the exit block, get all reaching // definitions and then either replace the return expression or // inject out variable assignments as Stores. var reachingBlocks = ssa.PredecessorPhiIdentifiers(ssa.Procedure.ExitBlock); var sig = ssa.Procedure.Signature; foreach (var reachingBlock in reachingBlocks) { var block = reachingBlock.Key; var idRet = sig.ReturnValue; if (idRet != null && !(idRet.DataType is VoidType)) { var idStg = reachingBlock.Value .Where(cb => cb.Storage.Covers(idRet.Storage)) .FirstOrDefault(); SetReturnExpression(ssa, block, idRet, idStg); } int insertPos = block.Statements.FindIndex(s => s.Instruction is ReturnInstruction); Debug.Assert(insertPos >= 0); foreach (var p in sig.Parameters.Where(p => p.Storage is OutArgumentStorage)) { var outStg = (OutArgumentStorage)p.Storage; var idStg = reachingBlock.Value .Where(cb => cb.Storage == outStg.OriginalIdentifier.Storage) .FirstOrDefault(); InsertOutArgumentAssignment( ssa, p, idStg?.Expression ?? Constant.Invalid, block, insertPos); ++insertPos; } } }
public BitRange Classify( SsaState ssa, SsaIdentifier sid, Storage storage, bool ignoreUseInstructions) { this.procFlow = flow[ssa.Procedure]; this.ssa = ssa; this.useLiveness = ignoreUseInstructions; if (storage is RegisterStorage || storage is StackArgumentStorage || storage is FpuStackStorage || storage is FlagGroupStorage || storage is SequenceStorage) { var n = Classify(sid); return(n); } else { return(BitRange.Empty); } }
private bool IsStackStorageOfPreservedRegister( SsaState ssa, HashSet <RegisterStorage> trashedRegisters, CallBinding use) { if (!(use.Storage is StackStorage)) { return(false); } if (!(use.Expression is Identifier id)) { return(false); } if (!(ssa.Identifiers[id].IsOriginal)) { return(false); } if (!IsPreservedRegister(trashedRegisters, id.Storage)) { return(false); } return(true); }
private void SetReturnExpression( SsaState ssa, Block block, Identifier idRet, CallBinding idStg) { var e = idStg?.Expression ?? Constant.Invalid; for (int i = block.Statements.Count - 1; i >= 0; --i) { var stm = block.Statements[i]; if (stm.Instruction is ReturnInstruction ret) { if (idRet.DataType.BitSize < e.DataType.BitSize) { int offset = idStg !.Storage.OffsetOf(idRet.Storage); e = new Slice(idRet.DataType, e, offset); } ret.Expression = e; ssa.AddUses(stm); } } }
public ConstDivisionImplementedByMultiplication(SsaState ssa) { this.ssa = ssa; this.m = new ExpressionEmitter(); }
private void DumpProc(Procedure proc, SsaState ssa, TextWriter writer) { ssa.Write(writer); proc.Write(false, writer); }
public SsaLivenessAnalysis2(SsaState ssa) { this.ssa = ssa.Identifiers; visitedBlocks = new Dictionary <Block, Block>(); interference = new InterferenceGraph(); }
/// <summary> /// Walks the dominator tree, renaming the different definitions of variables /// (including phi-functions). /// </summary> /// <param name="ssa">SSA identifiers</param> /// <param name="p">procedure to rename</param> public VariableRenamer(SsaTransform ssaXform) { this.programFlow = ssaXform.programFlow; this.ssa = ssaXform.SsaState; this.renameFrameAccess = ssaXform.RenameFrameAccesses; this.addUseInstructions = ssaXform.AddUseInstructions; this.proc = ssaXform.proc; this.rename = new Dictionary<Identifier, Identifier>(); this.stmCur = null; this.existingDefs = proc.EntryBlock.Statements .Select(s => s.Instruction as DefInstruction) .Where(d => d != null) .Select(d => d.Expression) .ToHashSet(); }
private Statement?stmCur; //$REFACTOR: context var. public SequenceIdentifierGenerator(SsaTransform sst) { this.sst = sst; this.ssa = sst.SsaState; }
private void RunUnitTest(ProcedureBuilder m, string outfile) { var proc = m.Procedure; var sst = new SsaTransform( new ProgramDataFlow(), proc, null, proc.CreateBlockDominatorGraph(), new HashSet<RegisterStorage>()); ssa = sst.SsaState; using (var fut = new FileUnitTester(outfile)) { ssa.Write(fut.TextWriter); proc.Write(false, fut.TextWriter); fut.AssertFilesEqual(); } }
private DeadCode(SsaState ssa) { this.ssa = ssa; this.liveIds = new WorkList <SsaIdentifier>(); }
private void Build(Procedure proc, IProcessorArchitecture arch) { var platform = new DefaultPlatform(null, arch); this.proc = proc; Aliases alias = new Aliases(proc, arch); alias.Transform(); SsaTransform sst = new SsaTransform(new ProgramDataFlow(), proc, proc.CreateBlockDominatorGraph()); ssa = sst.SsaState; ConditionCodeEliminator cce = new ConditionCodeEliminator(ssa.Identifiers, platform); cce.Transform(); ValuePropagator vp = new ValuePropagator(arch, ssa.Identifiers, proc); vp.Transform(); DeadCode.Eliminate(proc, ssa); Coalescer coa = new Coalescer(proc, ssa); coa.Transform(); DeadCode.Eliminate(proc, ssa); sla = new SsaLivenessAnalysis(proc, ssa.Identifiers); sla2 = new SsaLivenessAnalysis2(proc, ssa.Identifiers); sla2.Analyze(); }
public void VpPhiWithConstants() { Constant c1 = Constant.Word16(0x4711); Constant c2 = Constant.Word16(0x4711); Identifier r1 = Reg16("r1"); Identifier r2 = Reg16("r2"); Identifier r3 = Reg16("r3"); var stm1 = new Statement(1, new Assignment(r1, c1), null); var stm2 = new Statement(2, new Assignment(r2, c2), null); var proc = new Procedure("foo", arch.CreateFrame()); var ssa = new SsaState(proc, null); var r1Sid = ssa.Identifiers.Add(r1, null, null, false); var r2Sid = ssa.Identifiers.Add(r2, null, null, false); r1Sid.DefStatement = stm1; r2Sid.DefStatement = stm2; var vp = new ValuePropagator(arch, ssa); Instruction instr = new PhiAssignment(r3, new PhiFunction(r1.DataType, r1, r2)); instr = instr.Accept(vp); Assert.AreEqual("r3 = 0x4711", instr.ToString()); }
public void VpCopyPropagate() { var ssa = new SsaState(new Procedure("foo", new Frame(PrimitiveType.Pointer32)), null); ssaIds = ssa.Identifiers; Identifier x = Reg32("x"); Identifier y = Reg32("y"); Identifier z = Reg32("z"); Identifier w = Reg32("w"); Statement stmX = new Statement(0, new Assignment(x, new MemoryAccess(MemoryIdentifier.GlobalMemory, Constant.Word32(0x10004000), PrimitiveType.Word32)), null); Statement stmY = new Statement(1, new Assignment(y, x), null); Statement stmZ = new Statement(2, new Assignment(z, new BinaryExpression(Operator.IAdd, PrimitiveType.Word32, y, Constant.Word32(2))), null); Statement stmW = new Statement(3, new Assignment(w, y), null); ssaIds[x].DefStatement = stmX; ssaIds[y].DefStatement = stmY; ssaIds[z].DefStatement = stmZ; ssaIds[w].DefStatement = stmW; ssaIds[x].Uses.Add(stmY); ssaIds[y].Uses.Add(stmZ); ssaIds[y].Uses.Add(stmW); Assert.AreEqual("x = Mem0[0x10004000:word32]", stmX.Instruction.ToString()); Assert.AreEqual("y = x", stmY.Instruction.ToString()); Assert.AreEqual("z = y + 0x00000002", stmZ.Instruction.ToString()); Assert.AreEqual("w = y", stmW.Instruction.ToString()); ValuePropagator vp = new ValuePropagator(arch, ssa); vp.Transform(stmX); vp.Transform(stmY); vp.Transform(stmZ); vp.Transform(stmW); Assert.AreEqual("x = Mem0[0x10004000:word32]", stmX.Instruction.ToString()); Assert.AreEqual("y = x", stmY.Instruction.ToString()); Assert.AreEqual("z = x + 0x00000002", stmZ.Instruction.ToString()); Assert.AreEqual("w = x", stmW.Instruction.ToString()); Assert.AreEqual(3, ssaIds[x].Uses.Count); Assert.AreEqual(0, ssaIds[y].Uses.Count); }
public void VpEquality2() { // Makes sure that // y = x - 2 // if (y == 0) ... // doesn't get munged into // y = x - 2 // if (x == 2) ProcedureBuilder m = new ProcedureBuilder(); var ssa = new SsaState(m.Procedure, null); this.ssaIds = ssa.Identifiers; Identifier x = Reg32("x"); Identifier y = Reg32("y"); var stmX = m.Assign(x, m.LoadDw(Constant.Word32(0x1000300))); ssaIds[x].DefStatement = m.Block.Statements.Last; var stmY = m.Assign(y, m.ISub(x, 2)); ssaIds[y].DefStatement = m.Block.Statements.Last; var stm = m.BranchIf(m.Eq(y, 0), "test"); Assert.AreEqual("x = Mem0[0x01000300:word32]", stmX.ToString()); Assert.AreEqual("y = x - 0x00000002", stmY.ToString()); Assert.AreEqual("branch y == 0x00000000 test", stm.ToString()); var vp = new ValuePropagator(arch, ssa); vp.Transform(stm); Assert.AreEqual("branch x == 0x00000002 test", stm.Instruction.ToString()); }
private DeadCode(Procedure proc, SsaState ssa) { this.proc = proc; this.ssa = ssa; this.critical = new CriticalInstruction(); }
public SimpleTransformer(SsaState ssa) { this.ssa = ssa; }
public LocateDefinedVariables(SsaTransform ssaXform, Dictionary<Expression, byte>[] defOrig) { this.programFlow = ssaXform.programFlow; this.proc = ssaXform.proc; this.ssa = ssaXform.SsaState; this.frameVariables = ssaXform.RenameFrameAccesses; this.defVars = defOrig; this.definitions = new List<Identifier>(); this.inDefinitions = new HashSet<Identifier>(); }
/// <summary> /// Make a function signature based on the procedure flow <paramref name="flow"/>. /// </summary> /// <returns>A valid function signature.</returns> public FunctionType MakeSignature(SsaState ssa, IStorageBinder frame, ProcedureFlow flow) { var allLiveOut = flow.BitsLiveOut; var sb = new SignatureBuilder(frame, platform.Architecture); var implicitRegs = platform.CreateImplicitArgumentRegisters(); var liveOutFlagGroups = flow.grfLiveOut.Select(de => platform.Architecture.GetFlagGroup(de.Key, de.Value) !); AddModifiedFlags(frame, liveOutFlagGroups, sb); var mayUseSeqs = flow.BitsUsed.Keys.OfType <SequenceStorage>().ToHashSet(); var seqRegs = mayUseSeqs.SelectMany(s => s.Elements).Distinct().ToHashSet(); //$BUG: should be sorted by ABI register order. foreach (var seq in mayUseSeqs.OrderBy(r => r.Name)) { sb.AddSequenceArgument(seq); } var mayUseRegs = flow.BitsUsed .Select(de => (Key: de.Key as RegisterStorage, de.Value)) .Where(b => { return(b.Key is RegisterStorage reg && !implicitRegs.Contains(reg)); }) .Select(MakeRegisterParameter) .ToDictionary(de => de.Item1, de => de.Item2); //$BUG: should be sorted by ABI register order. Need a new method // IPlatform.CreateAbiRegisterCollator(). foreach (var reg in mayUseRegs.OrderBy(r => r.Key.Number)) { if (!IsSubRegisterOfRegisters(reg.Key, mayUseRegs) && !seqRegs.Contains(reg.Key)) { sb.AddRegisterArgument(reg.Key); } } foreach (var id in GetSortedStackArguments((Frame)frame, flow.BitsUsed)) { sb.AddInParam(id.Item2); } foreach (var oFpu in flow.BitsUsed .Where(f => f.Key is FpuStackStorage) .OrderBy(r => ((FpuStackStorage)r.Key).FpuStackOffset)) { var fpu = (FpuStackStorage)oFpu.Key; var id = frame.EnsureFpuStackVariable(fpu.FpuStackOffset, fpu.DataType); sb.AddFpuStackArgument(fpu.FpuStackOffset, id); } var liveOut = allLiveOut .Select(de => (Key: de.Key as RegisterStorage, de.Value)) .Where(de => { return(de.Key != null && !implicitRegs.Contains(de.Key)); }) .Select(MakeRegisterParameter) .ToDictionary(de => de.Item1, de => de.Item2); // Sort the names in a stable way to avoid regression tests failing. foreach (var r in liveOut.OrderBy(r => r.Key.Number).ThenBy(r => r.Key.BitAddress)) { if (!IsSubRegisterOfRegisters(r.Key, liveOut)) { var regOut = sb.AddOutParam(frame.EnsureRegister(r.Key)); if (regOut.Storage is OutArgumentStorage && !ssa.Identifiers.TryGetValue(regOut, out var sidOut)) { // Ensure there are SSA identifiers for 'out' registers. ssa.Identifiers.Add(regOut, null, null, false); } } } foreach (var fpu in allLiveOut.Keys.OfType <FpuStackStorage>().OrderBy(r => r.FpuStackOffset)) { sb.AddOutParam(frame.EnsureFpuStackVariable(fpu.FpuStackOffset, fpu.DataType)); } var sig = sb.BuildSignature(); return(sig); }
public static void Eliminate(SsaState ssa) { new DeadCode(ssa).Eliminate(); }
public UnalignedMemoryAccessFuser(SsaState ssa) { this.ssa = ssa; }
public void VpPhiLoops() { var m = new ProcedureBuilder(); var ssa = new SsaState(m.Procedure, null); ssaIds = ssa.Identifiers; var fp = Reg16("fp"); var a = Reg16("a"); var b = Reg16("b"); var c = Reg16("c"); var d = Reg16("d"); var x = Reg16("x"); var y = Reg16("y"); var z = Reg16("z"); m.Emit(m.Assign(y, m.IAdd(x, 4))); m.Emit(m.Assign(z, m.ISub(x, 8))); m.Emit(m.Assign(a, m.ISub(fp, 12))); m.Emit(m.Assign(b, m.ISub(fp, 12))); m.Emit(m.Assign(c, m.ISub(y, 4))); m.Emit(m.Assign(d, m.IAdd(z, 8))); var phiStm = m.Phi(x, a, b, c, d); var stms = m.Procedure.EntryBlock.Succ[0].Statements; stms.ForEach(stm => { var ass = stm.Instruction as Assignment; if (ass != null) ssaIds[ass.Dst].DefStatement = stm; var phiAss = stm.Instruction as PhiAssignment; if (phiAss != null) ssaIds[phiAss.Dst].DefStatement = stm; }); var vp = new ValuePropagator(arch, ssa); vp.Transform(); Assert.AreEqual("x = fp - 0x000C", phiStm.Instruction.ToString()); }
public static void Eliminate(Procedure proc, SsaState ssa) { new DeadCode(proc, ssa).Eliminate(); }
public SsaMutator(SsaState ssa) { this.ssa = ssa; this.m = new ExpressionEmitter(); }
public IndirectCallExpander(SsaState ssa) { this.ssa = ssa; }
public ProjectionPropagator(SsaState ssa, SegmentedAccessClassifier sac) { this.ssa = ssa; this.sac = sac; }
public SsaIdentifierTransformer(SsaState ssa) { this.ssa = ssa; this.frame = ssa.Procedure.Frame; this.argumentTransformer = new ArgumentTransformer(this); }
public UnSSA(SsaState ssa) { this.ssa = ssa; }
public SsaIdentifierTransformer(SsaState ssa) { this.ssa = ssa; this.frame = ssa.Procedure.Frame; }
protected override void RunTest(Program prog, TextWriter writer) { var flow = new ProgramDataFlow(prog); var eventListener = new FakeDecompilerEventListener(); var importResolver = MockRepository.GenerateStub<IImportResolver>(); importResolver.Replay(); var trf = new TrashedRegisterFinder(prog, prog.Procedures.Values, flow, eventListener); trf.Compute(); trf.RewriteBasicBlocks(); Dump(prog.CallGraph); RegisterLiveness.Compute(prog, flow, eventListener); GlobalCallRewriter.Rewrite(prog, flow, eventListener); foreach (Procedure proc in prog.Procedures.Values) { Aliases alias = new Aliases(proc, prog.Architecture); alias.Transform(); var gr = proc.CreateBlockDominatorGraph(); SsaTransform sst = new SsaTransform( flow, proc, importResolver, gr, new HashSet<RegisterStorage>()); ssa = sst.SsaState; ssa.Write(writer); proc.Write(false, true, writer); writer.WriteLine(); } }
public IdentifierReplacer(SsaState ssaIds, Statement use, Identifier idOld, Expression exprNew) { this.ssaIds = ssaIds; this.use = use; this.idOld = idOld; this.exprNew = exprNew; }
public ConstDivisionImplementedByMultiplication(SsaState ssa) { this.ssa = ssa; }
public StackPointerBackpropagator(SsaState ssa, DecompilerEventListener listener) { this.ssa = ssa; this.m = new ExpressionEmitter(); this.listener = listener; }
private void AssertStringsEqual(string sExp, SsaState ssa) { var sw = new StringWriter(); ssa.Write(sw); ssa.Procedure.Write(false, sw); var sActual = sw.ToString(); if (sExp != sActual) { Debug.Print("{0}", sActual); Assert.AreEqual(sExp, sActual); } }