예제 #1
0
		public void Setup()
		{
            m = new ProcedureBuilder();
            ssaState = new SsaState(m.Procedure, null);
            ssaIds = ssaState.Identifiers;
            freg = new FlagRegister("flags", 32, PrimitiveType.Word32);
		}
예제 #2
0
 protected void DumpSsaInfo(Procedure proc, SsaState ssa, TextWriter writer)
 {
     writer.WriteLine("// {0} ////////////////////////////////", proc.Name);
     DumpSsaTypes(ssa, writer);
     proc.Write(false, writer);
     writer.WriteLine();
 }
예제 #3
0
 public StrengthReduction(SsaState ssa, LinearInductionVariable liv, LinearInductionVariableContext ctx)
 {
     this.ssa = ssa;
     this.liv = liv;
     this.ctx = ctx;
     incrUses = new List<IncrementedUse>();
 }
예제 #4
0
        public ConditionCodeEliminator(SsaState ssa, IPlatform arch)
		{
            this.ssa=ssa;
			this.ssaIds = ssa.Identifiers;
            this.platform = arch;
            this.m = new ExpressionEmitter();
		}
예제 #5
0
 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);
     }
 }
예제 #6
0
파일: Coalescer.cs 프로젝트: nemerle/reko
 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);
     }
 }
예제 #7
0
 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;
 }
예제 #8
0
파일: CallRewriter.cs 프로젝트: ghmole/reko
        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);
        }
예제 #9
0
 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);
 }
예제 #10
0
        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
        }
예제 #11
0
 /// <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();
 }
예제 #12
0
 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);
 }
예제 #13
0
        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);
        }
예제 #14
0
        /// <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);
        }
예제 #15
0
 /// <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);
         }
     }
 }
예제 #16
0
        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);
                            }
                        }
                    }
                }
            }
        }
예제 #17
0
 /// <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;
 }
예제 #18
0
 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);
         }
     }
 }
예제 #19
0
        /// <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);
            }
        }
예제 #20
0
        /// <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
            }
        }
예제 #21
0
        /// <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);
        }
예제 #22
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;
                }
            }
        }
예제 #23
0
 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);
     }
 }
예제 #24
0
 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);
 }
예제 #25
0
        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);
                }
            }
        }
예제 #26
0
 public ConstDivisionImplementedByMultiplication(SsaState ssa)
 {
     this.ssa = ssa;
     this.m   = new ExpressionEmitter();
 }
예제 #27
0
 private void DumpProc(Procedure proc, SsaState ssa, TextWriter writer)
 {
     ssa.Write(writer);
     proc.Write(false, writer);
 }
예제 #28
0
 public SsaLivenessAnalysis2(SsaState ssa)
 {
     this.ssa      = ssa.Identifiers;
     visitedBlocks = new Dictionary <Block, Block>();
     interference  = new InterferenceGraph();
 }
예제 #29
0
 /// <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();
 }
예제 #30
0
        private Statement?stmCur;       //$REFACTOR: context var.

        public SequenceIdentifierGenerator(SsaTransform sst)
        {
            this.sst = sst;
            this.ssa = sst.SsaState;
        }
예제 #31
0
파일: SsaTests.cs 프로젝트: relaxar/reko
 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();
     }
 }
예제 #32
0
파일: DeadCode.cs 프로젝트: tgiphil/reko
 private DeadCode(SsaState ssa)
 {
     this.ssa     = ssa;
     this.liveIds = new WorkList <SsaIdentifier>();
 }
예제 #33
0
        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();
        }
예제 #34
0
 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());
 }
예제 #35
0
		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);
		}
예제 #36
0
		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());
		}
예제 #37
0
파일: DeadCode.cs 프로젝트: relaxar/reko
		private DeadCode(Procedure proc, SsaState ssa) 
		{
			this.proc = proc;
			this.ssa = ssa;
			this.critical = new CriticalInstruction();
		}
예제 #38
0
 public SimpleTransformer(SsaState ssa)
 {
     this.ssa = ssa;
 }
예제 #39
0
 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>();
 }
예제 #40
0
        /// <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);
        }
예제 #41
0
파일: DeadCode.cs 프로젝트: tgiphil/reko
 public static void Eliminate(SsaState ssa)
 {
     new DeadCode(ssa).Eliminate();
 }
예제 #42
0
 public UnalignedMemoryAccessFuser(SsaState ssa)
 {
     this.ssa = ssa;
 }
예제 #43
0
 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());
 }
예제 #44
0
파일: DeadCode.cs 프로젝트: relaxar/reko
		public static void Eliminate(Procedure proc, SsaState ssa)
		{
			new DeadCode(proc, ssa).Eliminate();
		}
예제 #45
0
파일: SsaMutator.cs 프로젝트: claunia/reko
 public SsaMutator(SsaState ssa)
 {
     this.ssa = ssa;
     this.m   = new ExpressionEmitter();
 }
예제 #46
0
 public IndirectCallExpander(SsaState ssa)
 {
     this.ssa = ssa;
 }
예제 #47
0
 public ProjectionPropagator(SsaState ssa, SegmentedAccessClassifier sac)
 {
     this.ssa = ssa;
     this.sac = sac;
 }
예제 #48
0
 public SsaIdentifierTransformer(SsaState ssa)
 {
     this.ssa = ssa;
     this.frame = ssa.Procedure.Frame;
     this.argumentTransformer = new ArgumentTransformer(this);
 }
예제 #49
0
 public UnSSA(SsaState ssa)
 {
     this.ssa = ssa;
 }
예제 #50
0
			public UnSSA(SsaState ssa)
			{
				this.ssa = ssa;
			}
예제 #51
0
 public SsaIdentifierTransformer(SsaState ssa)
 {
     this.ssa = ssa;
     this.frame = ssa.Procedure.Frame;
 }
예제 #52
0
파일: SsaTests.cs 프로젝트: relaxar/reko
		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();
			}
		}
예제 #53
0
파일: Coalescer.cs 프로젝트: nemerle/reko
 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;
 }
예제 #56
0
 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);
     }
 }