public void SrtReg685() { var m = new SsaProcedureBuilder(nameof(SrtReg685)); var i_1 = m.Reg32("i_1"); var i_2 = m.Reg32("i_2"); var i_3 = m.Reg32("i_3"); m.Assign(i_1, m.Int32(0)); m.Label("m1"); m.Phi(i_2, i_1, i_3); m.SideEffect(m.Fn("foo", i_2)); m.SideEffect(m.Fn("foo", m.IAdd(i_2, 1))); m.Assign(i_3, m.IAdd(i_2, 2)); m.BranchIf(m.Eq(i_3, 10), "m1"); m.Label("m2"); m.Return(); var dom = m.Procedure.CreateBlockDominatorGraph(); var lif = new LinearInductionVariableFinder(m.Procedure, m.Ssa.Identifiers, dom); lif.Find(); Assert.AreEqual("(0 0x00000002 0x0000000C)", lif.InductionVariables[0].ToString()); var ctx = lif.Contexts[lif.InductionVariables[0]]; var str = new StrengthReduction(m.Ssa, lif.InductionVariables[0], ctx); str.ClassifyUses(); Assert.AreEqual(2, str.IncrementedUses.Count); str.ModifyUses(); }
public void VpCopyPropagate() { var x = m.Reg32("x"); var y = m.Reg32("y"); var z = m.Reg32("z"); var w = m.Reg32("w"); var stmX = m.Assign(x, m.Mem32(Constant.Word32(0x10004000))); var stmY = m.Assign(y, x); var stmZ = m.Assign(z, m.IAdd(y, Constant.Word32(2))); var stmW = m.Assign(w, y); Assert.AreEqual("x = Mem4[0x10004000<32>:word32]", stmX.ToString()); Assert.AreEqual("y = x", stmY.ToString()); Assert.AreEqual("z = y + 2<32>", stmZ.ToString()); Assert.AreEqual("w = y", stmW.ToString()); RunValuePropagator(); Assert.AreEqual("x = Mem4[0x10004000<32>:word32]", stmX.ToString()); Assert.AreEqual("y = x", stmY.ToString()); Assert.AreEqual("z = x + 2<32>", stmZ.ToString()); Assert.AreEqual("w = x", stmW.ToString()); Assert.AreEqual(3, m.Ssa.Identifiers[x].Uses.Count); Assert.AreEqual(0, m.Ssa.Identifiers[y].Uses.Count); }
public void CoaCallCallee() { var r2 = m.Reg32("r2"); var r3 = m.Reg32("r3"); m.Assign(r3, m.Fn(r2)); var uses = new Identifier[] { r2 }; var defines = new Identifier[] { }; m.Call(m.IAdd(r3, 4), 4, uses, defines); RunCoalescer(); var expected = @" call r2() + 4<32> (retsize: 4;) uses: r2:r2 "; AssertProcedureCode(expected); }
public void CoaDoNotCoalesceInvalidConstant() { var a = m.Reg32("a"); var b = m.Reg32("b"); m.Assign(a, Constant.Invalid); m.Assign(b, m.IAdd(a, 4)); RunCoalescer(); var expected = @" a = <invalid> b = a + 0x00000004 "; AssertProcedureCode(expected); }
public void Spbp_LinearProcedure() { var m = new SsaProcedureBuilder(nameof(Spbp_LinearProcedure)); var fp = m.Ssa.Identifiers.Add(m.Frame.FramePointer, null, null, false).Identifier; Given_StackPointer(m); var sp_1 = m.Reg("sp_1", m.Architecture.StackRegister); var sp_2 = m.Reg("sp_2", m.Architecture.StackRegister); var sp_3 = m.Reg("sp_3", m.Architecture.StackRegister); m.AddDefToEntryBlock(fp); m.Assign(sp_1, m.ISub(fp, m.Int32(4))); // Indirect call = hell node var ci = m.Call(m.Mem32(m.Word32(0x2)), 4, new[] { sp_1 }, new[] { sp_2 }); m.Assign(sp_3, m.IAdd(sp_2, m.Int32(4))); m.Return(); m.AddUseToExitBlock(sp_3); RunTest(m.Ssa); var sExp = #region Expected @"Spbp_LinearProcedure_entry: def fp l1: sp_1 = fp - 4 call Mem4[0x00000002:word32] (retsize: 4;) uses: sp:sp_1 sp_2 = fp - 4 sp_3 = fp return Spbp_LinearProcedure_exit: use sp_3 "; #endregion AssertStringsEqual(sExp, m.Ssa); }
public void VpCopyPropagate() { var x = m.Reg32("x"); var y = m.Reg32("y"); var z = m.Reg32("z"); var w = m.Reg32("w"); m.Assign(x, m.Mem32(Constant.Word32(0x10004000))); var stmX = m.Block.Statements.Last(); m.Assign(y, x); var stmY = m.Block.Statements.Last(); m.Assign(z, m.IAdd(y, Constant.Word32(2))); var stmZ = m.Block.Statements.Last(); m.Assign(w, y); var stmW = m.Block.Statements.Last(); Assert.AreEqual("x = Mem4[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()); var vp = new ValuePropagator(segmentMap, m.Ssa, listener); vp.Transform(stmX); vp.Transform(stmY); vp.Transform(stmZ); vp.Transform(stmW); Assert.AreEqual("x = Mem4[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, m.Ssa.Identifiers[x].Uses.Count); Assert.AreEqual(0, m.Ssa.Identifiers[y].Uses.Count); }
public void Cab_GuessStackParameter() { var m = new SsaProcedureBuilder(nameof(Cab_Sequence)); var sp = m.Reg("sp", m.Procedure.Architecture.StackRegister); m.AddDefToEntryBlock(sp); var r2_1 = m.Reg("r2_1", reg2); var r3_2 = m.Reg("r3_2", reg3); m.MStore(sp, m.Word32(0x0001234)); m.MStore(m.IAdd(sp, 4), m.Word32(0x5678ABCD)); var sigCallee = FunctionType.Action( new Identifier("arg04", PrimitiveType.Word32, new StackArgumentStorage(4, PrimitiveType.Word32)), new Identifier("arg08", PrimitiveType.Word32, new StackArgumentStorage(8, PrimitiveType.Word32))); sigCallee.ReturnAddressOnStack = 4; var callee = new ProcedureConstant( PrimitiveType.Ptr32, new ExternalProcedure("callee", sigCallee)); var stmCall = m.Call(callee, 0, new Identifier[] { sp }, new Identifier[] { }); m.Return(); var cab = new CallApplicationBuilder( m.Ssa, stmCall, (CallInstruction)stmCall.Instruction, callee, true); var instr = cab.CreateInstruction(sigCallee, null); Assert.AreEqual("callee(Mem4[sp:word32], Mem4[sp + 4<i32>:word32])", instr.ToString()); m.Ssa.Validate(s => Assert.Fail(s)); }
public void UfuserMipsLittleEndianUnalignedWordLoad() { var r4 = m.Reg32("r4"); var r8 = m.Reg32("r8"); __lwl(r8, m.Mem32(m.IAdd(r4, 0x2B))); __lwr(r8, m.Mem32(m.IAdd(r4, 0x28))); var ssa = RunTest(m); var sExp = #region Expected @"r8:r8 def: def r8 uses: r8_3 = r8 r4:r4 def: def r4 uses: r8_5 = Mem3[r4 + 0x00000028:word32] Mem2:Global memory def: def Mem2 r8_3: orig: r8 def: r8_3 = r8 Mem3:Global memory def: def Mem3 uses: r8_5 = Mem3[r4 + 0x00000028:word32] r8_5: orig: r8 def: r8_5 = Mem3[r4 + 0x00000028:word32] // SsaProcedureBuilder // Return size: 0 void SsaProcedureBuilder() SsaProcedureBuilder_entry: def r8 def r4 def Mem2 def Mem3 // succ: l1 l1: r8_5 = Mem3[r4 + 0x00000028:word32] SsaProcedureBuilder_exit: "; #endregion AssertStringsEqual(sExp, ssa); }
public void Spbp_SpaceOnStack() { var m = new SsaProcedureBuilder(nameof(Spbp_SpaceOnStack)); var fp = m.Ssa.Identifiers.Add(m.Frame.FramePointer, null, null, false).Identifier; Given_StackPointer(m); var sp_1 = m.Reg("sp_1", sp); var sp_2 = m.Reg("sp_2", sp); var sp_3 = m.Reg("sp_3", sp); var sp_4 = m.Reg("sp_4", sp); var sp_5 = m.Reg("sp_5", sp); var sp_6 = m.Reg("sp_6", sp); var sp_7 = m.Reg("sp_7", sp); var sp_8 = m.Reg("sp_8", sp); var a = m.Reg("a", new RegisterStorage("a", 1, 0, PrimitiveType.Word32)); var b = m.Reg("b", new RegisterStorage("b", 2, 0, PrimitiveType.Word32)); var a_1 = m.Reg("a_1", (RegisterStorage)a.Storage); var b_1 = m.Reg("b_1", (RegisterStorage)b.Storage); m.AddDefToEntryBlock(fp); m.Assign(sp_2, m.ISub(fp, 4)); // space for a m.MStore(sp_2, a); m.Assign(sp_3, m.ISub(fp, 4)); // space for b m.MStore(sp_3, b); m.Assign(sp_4, m.ISub(fp, 40)); // 40 bytes of stack space m.MStore(sp_4, m.Word32(0xDEADBABE)); m.Call(m.Mem32(m.Word32(0x00123400)), 4, new[] { sp_4 }, new[] { sp_5 }); m.Assign(sp_6, m.IAdd(sp_5, 40)); m.Assign(b_1, m.Mem32(sp_6)); m.Assign(sp_7, m.IAdd(sp_6, 4)); m.Assign(a_1, m.Mem32(sp_7)); m.Assign(sp_8, m.IAdd(sp_7, 4)); m.Return(); m.AddUseToExitBlock(sp_8); RunTest(m.Ssa); var sExp = #region Expected @"Spbp_SpaceOnStack_entry: def fp l1: sp_2 = fp - 0x00000004 Mem13[sp_2:word32] = a sp_3 = fp - 0x00000004 Mem14[sp_3:word32] = b sp_4 = fp - 0x00000028 Mem15[sp_4:word32] = 0xDEADBABE call Mem16[0x00123400:word32] (retsize: 4;) uses: sp:sp_4 sp_5 = fp - 48 sp_6 = fp - 8 b_1 = Mem17[sp_6:word32] sp_7 = fp - 4 a_1 = Mem18[sp_7:word32] sp_8 = fp return Spbp_SpaceOnStack_exit: use sp_8 "; #endregion this.AssertStringsEqual(sExp, m.Ssa); }
public void Spbp_TwoExits() { var m = new SsaProcedureBuilder(nameof(Spbp_TwoExits)); Given_FramePointer(m); Given_StackPointer(m); var sp_1 = m.Reg("sp_1", m.Architecture.StackRegister); var sp_2 = m.Reg("sp_2", m.Architecture.StackRegister); var sp_3 = m.Reg("sp_3", m.Architecture.StackRegister); var sp_4 = m.Reg("sp_4", m.Architecture.StackRegister); var sp_5 = m.Reg("sp_5", m.Architecture.StackRegister); var sp_6 = m.Reg("sp_6", m.Architecture.StackRegister); m.AddDefToEntryBlock(fp); m.Assign(sp_1, m.ISub(fp, m.Int32(4))); m.BranchIf(m.Eq0(m.Mem32(m.Word32(0x1))), "m_eq0"); m.Label("m_ne0"); // Indirect call = hell node m.Call(m.Mem32(m.Word32(0x4)), 4, new[] { sp_1 }, new[] { sp_2 }); m.Assign(sp_3, m.IAdd(sp_2, m.Int32(4))); m.Return(); m.Label("m_eq0"); // Indirect call = hell node m.Call(m.Mem32(m.Word32(0x8)), 4, new[] { sp_1 }, new[] { sp_4 }); m.Assign(sp_5, m.IAdd(sp_4, m.Int32(4))); m.Return(); m.AddPhiToExitBlock(sp_6, (sp_3, "m_ne0"), (sp_5, "m_eq0")); m.AddUseToExitBlock(sp_6); RunTest(m.Ssa); var sExp = #region Expected @"Spbp_TwoExits_entry: def fp l1: sp_1 = fp - 4 branch Mem7[0x00000001:word32] == 0x00000000 m_eq0 goto m_ne0 m_eq0: call Mem9[0x00000008:word32] (retsize: 4;) uses: sp:sp_1 sp_4 = fp - 4 sp_5 = fp return m_ne0: call Mem8[0x00000004:word32] (retsize: 4;) uses: sp:sp_1 sp_2 = fp - 4 sp_3 = fp return Spbp_TwoExits_exit: sp_6 = PHI((sp_3, m_ne0), (sp_5, m_eq0)) use sp_6 "; #endregion AssertStringsEqual(sExp, m.Ssa); }