public void VpLoop() { var b = new ProgramBuilder(); b.Add("main", m => { var r = m.Reg32("r0", 0); var zf = m.Flags("Z"); m.Label("l0000"); m.MStore(r, m.Word32(0)); m.Assign(r, m.ISub(r, 4)); m.Assign(zf, m.Cond(r)); m.BranchIf(m.Test(ConditionCode.NE, zf), "l0000"); m.Label("l0001"); m.Assign(r, 42); m.Label("l0002"); m.MStore(r, m.Word32(12)); m.Assign(r, m.ISub(r, 4)); m.BranchIf(m.Eq0(r), "l0002"); m.Return(); }); RunFileTest(b.BuildProgram(), "Analysis/VpLoop.txt"); }
public void Cab_Sequence_MkSequence() { var m = new SsaProcedureBuilder(nameof(Cab_Sequence)); var r2_1 = m.Reg("r2_1", reg2); var r3_2 = m.Reg("r3_2", reg3); m.Assign(r2_1, 0x0001234); m.Assign(r3_2, 0x5678ABCD); var sigCallee = FunctionType.Action( new Identifier("r2_r3", PrimitiveType.Word64, new SequenceStorage(PrimitiveType.Word64, reg2, reg3))); var callee = new ProcedureConstant( PrimitiveType.Ptr32, new ExternalProcedure("callee", sigCallee)); var stmCall = m.Call(callee, 0, new Identifier[] { r3_2, r2_1 }, new Identifier[] { }); m.Return(); var cab = new CallApplicationBuilder( m.Ssa, stmCall, (CallInstruction)stmCall.Instruction, callee); var instr = cab.CreateInstruction(sigCallee, null); Assert.AreEqual("callee(SEQ(r2_1, r3_2))", instr.ToString()); m.Ssa.Validate(s => Assert.Fail(s)); }
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 Urb_Remove_many_blocks() { var m = new SsaProcedureBuilder(name: nameof(Urb_Remove_many_blocks)); var r1_1 = m.Reg32("r1_1"); var r1_2 = m.Reg32("r1_2"); var r1_3 = m.Reg32("r1_3"); var r1_4 = m.Reg32("r1_4"); var r2 = m.Reg32("r2"); m.AddDefToEntryBlock(r2); m.BranchIf(Constant.False(), "m2"); m.Label("m1"); m.Assign(r1_1, 1); m.Goto("m4"); m.Label("m2"); // dead code m.BranchIf(m.Eq0(r2), "m3"); m.Label("m2a"); m.Assign(r1_2, 2); m.Goto("m4"); m.Label("m3"); m.Assign(r1_3, 3); // end of dead code. m.Label("m4"); m.Phi(r1_4, (r1_1, "m1"), (r1_2, "m2a"), (r1_3, "m3")); m.Return(r1_4); var sExp = #region @"// Urb_Remove_many_blocks // Return size: 0 define Urb_Remove_many_blocks Urb_Remove_many_blocks_entry: def r2 // succ: l1 l1: // succ: m1 m1: r1_1 = 1<32> // succ: m4 m4: r1_4 = r1_1 return r1_4 // succ: Urb_Remove_many_blocks_exit Urb_Remove_many_blocks_exit: "; #endregion RunTest(sExp, m); }
public void DeadCallDefinition() { var sExp = #region Expected @"// ProcedureBuilder // Return size: 0 define ProcedureBuilder ProcedureBuilder_entry: def r1 // succ: l1 l1: call foo (retsize: 4;) uses: r1:r1 defs: r1:r1_2 Mem4[0x00123400<p32>:word32] = r1_2 return // succ: ProcedureBuilder_exit ProcedureBuilder_exit: "; #endregion RunTest(sExp, m => { var _r1 = new RegisterStorage("r1", 1, 0, PrimitiveType.Word32); var _r2 = new RegisterStorage("r2", 2, 0, PrimitiveType.Word32); var foo = Given_Procedure_With_Flow(m, "foo", new Storage[] { _r1 }, new Storage[] { _r1, _r2 }); var r1 = m.Frame.EnsureRegister(_r1); var r2 = m.Frame.EnsureRegister(_r2); var call = m.Call(foo, 4); m.MStore(m.Ptr32(0x123400), r1); m.Return(); }); }
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 Urb_Remove_false() { var m = new SsaProcedureBuilder(name: nameof(Urb_Remove_false)); var r1_1 = m.Reg32("r1_1"); var r1_2 = m.Reg32("r1_2"); var r1_3 = m.Reg32("r1_3"); m.BranchIf(Constant.False(), "m2"); m.Label("m1"); m.Assign(r1_1, 1); m.Goto("m3"); m.Label("m2"); // dead code m.Assign(r1_2, 2); m.Label("m3"); m.Phi(r1_3, (r1_1, "m1"), (r1_2, "m2")); m.Return(r1_3); var sExp = #region @"// Urb_Remove_false // Return size: 0 define Urb_Remove_false Urb_Remove_false_entry: // succ: l1 l1: // succ: m1 m1: r1_1 = 1<32> // succ: m3 m3: r1_3 = r1_1 return r1_3 // succ: Urb_Remove_false_exit Urb_Remove_false_exit: "; #endregion RunTest(sExp, m); }
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 UfuserLittleEndianSequence() { var r8 = m.Reg32("r8"); var r14 = m.Reg32("r14"); var r13 = m.Reg32("r13"); var r9 = m.Reg32("r9"); var r4 = m.Reg32("r4"); __swl(m.Mem32(m.IAdd(r8, 0x13)), r14); __swl(m.Mem32(m.IAdd(r8, 0x17)), r13); __swl(m.Mem32(m.IAdd(r8, 0x1B)), m.Word32(0x00)); __swl(m.Mem32(m.IAdd(r8, 0x1F)), m.Word32(0x00)); __swl(m.Mem32(m.IAdd(r8, 0x2B)), m.Word32(0x00)); __swl(m.Mem32(m.IAdd(r8, 0x2F)), r9); __swl(m.Mem32(m.IAdd(r8, 0x33)), m.Word32(0x00)); m.Assign(r4, m.IAdd(r8, 0x0010)); __swr(m.Mem32(m.IAdd(r8, 0x10)), r14); __swr(m.Mem32(m.IAdd(r8, 0x14)), r13); __swr(m.Mem32(m.IAdd(r8, 0x18)), m.Word32(0x00)); __swr(m.Mem32(m.IAdd(r8, 0x1C)), m.Word32(0x00)); __swr(m.Mem32(m.IAdd(r8, 0x28)), m.Word32(0x00)); __swr(m.Mem32(m.IAdd(r8, 44)), r9); __swr(m.Mem32(m.IAdd(r8, 0x30)), m.Word32(0x00)); m.Return(); var ssa = RunTest(m); var sExp = #region Expected @"r8:r8 def: def r8 uses: r4_18 = r8 + 0x00000010 Mem20[r8 + 0x00000010:word32] = r14 Mem22[r8 + 0x00000014:word32] = r13 Mem24[r8 + 0x00000018:word32] = 0x00000000 Mem26[r8 + 0x0000001C:word32] = 0x00000000 Mem28[r8 + 0x00000028:word32] = 0x00000000 Mem30[r8 + 0x0000002C:word32] = r9 Mem32[r8 + 0x00000030:word32] = 0x00000000 Mem5:Global memory def: def Mem5 r14:r14 def: def r14 uses: Mem20[r8 + 0x00000010:word32] = r14 Mem3: orig: Mem5 Mem6:Global memory def: def Mem6 r13:r13 def: def r13 uses: Mem22[r8 + 0x00000014:word32] = r13 Mem6: orig: Mem6 Mem7:Global memory def: def Mem7 Mem8: orig: Mem7 Mem8:Global memory def: def Mem8 Mem10: orig: Mem8 Mem9:Global memory def: def Mem9 Mem12: orig: Mem9 Mem10:Global memory def: def Mem10 r9:r9 def: def r9 uses: Mem30[r8 + 0x0000002C:word32] = r9 Mem15: orig: Mem10 Mem11:Global memory def: def Mem11 Mem17: orig: Mem11 r4_18: orig: r4 def: r4_18 = r8 + 0x00000010 Mem12:Global memory def: def Mem12 Mem20: orig: Mem12 def: Mem20[r8 + 0x00000010:word32] = r14 Mem13:Global memory def: def Mem13 Mem22: orig: Mem13 def: Mem22[r8 + 0x00000014:word32] = r13 Mem14:Global memory def: def Mem14 Mem24: orig: Mem14 def: Mem24[r8 + 0x00000018:word32] = 0x00000000 Mem15:Global memory def: def Mem15 Mem26: orig: Mem15 def: Mem26[r8 + 0x0000001C:word32] = 0x00000000 Mem16:Global memory def: def Mem16 Mem28: orig: Mem16 def: Mem28[r8 + 0x00000028:word32] = 0x00000000 Mem17:Global memory def: def Mem17 Mem30: orig: Mem17 def: Mem30[r8 + 0x0000002C:word32] = r9 Mem18:Global memory def: def Mem18 Mem32: orig: Mem18 def: Mem32[r8 + 0x00000030:word32] = 0x00000000 // SsaProcedureBuilder // Return size: 0 void SsaProcedureBuilder() SsaProcedureBuilder_entry: def r8 def Mem5 def r14 def Mem6 def r13 def Mem7 def Mem8 def Mem9 def Mem10 def r9 def Mem11 def Mem12 def Mem13 def Mem14 def Mem15 def Mem16 def Mem17 def Mem18 // succ: l1 l1: r4_18 = r8 + 0x00000010 Mem20[r8 + 0x00000010:word32] = r14 Mem22[r8 + 0x00000014:word32] = r13 Mem24[r8 + 0x00000018:word32] = 0x00000000 Mem26[r8 + 0x0000001C:word32] = 0x00000000 Mem28[r8 + 0x00000028:word32] = 0x00000000 Mem30[r8 + 0x0000002C:word32] = r9 Mem32[r8 + 0x00000030:word32] = 0x00000000 return // succ: SsaProcedureBuilder_exit 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); }