Exemple #1
0
        public void TrashInLoop()
        {
            p.Add("main", m =>
            {
                var eax = m.Frame.EnsureRegister(Registers.eax);
                var ebx = m.Frame.EnsureRegister(Registers.ebx);
                m.Assign(eax, 1);
                m.Label("Lupe");
                m.Store(m.IAdd(ebx, eax), m.Word16(0));
                m.Assign(eax, m.IAdd(eax, 2));
                m.BranchIf(m.Le(eax, 10), "Lupe");
                m.Return();
            });

            var sExp =
                @"main eax ax al ah
const eax:<invalid>
    main_entry esp:fp
    l1 esp:fp
    l2 eax:<invalid> esp:fp
    Lupe eax:<invalid> esp:fp
    main_exit eax:<invalid> esp:fp";

            RunTest(p, sExp);
        }
        public void Pdg_LoopWithIfElse()
        {
            var m = new ProcedureBuilder();
            var c = m.Declare(PrimitiveType.Word32, "c");
            var f = m.Declare(PrimitiveType.Bool, "f");

            m.Label("loopHead");
            m.BranchIf(m.Eq(c, 0), "done");
            m.BranchIf(f, "then");
            m.Label("else");
            m.SideEffect(m.Fn("CallElse"));
            m.Jump("loopHead");
            m.Label("then");
            m.SideEffect(m.Fn("CallThen"));
            m.Jump("loopHead");
            m.Label("done");
            m.Return();

            FindPostDominators(m);

            string sExp =
                "done (6): idom ProcedureBuilder_exit (7)" + nl +
                "else (4): idom loopHead (2)" + nl +
                "l1 (3): idom loopHead (2)" + nl +
                "loopHead (2): idom done (6)" + nl +
                "ProcedureBuilder_entry (1): idom loopHead (2)" + nl +
                "ProcedureBuilder_exit (7): idom " + nl +
                "then (5): idom loopHead (2)" + nl;

            Assert.AreEqual(sExp, sw.ToString());
        }
Exemple #3
0
        public void BwJmp()
        {
            var eax  = m.Frame.EnsureRegister(Registers.eax);
            var SCZO = m.Frame.EnsureFlagGroup(Registers.eflags, (uint)(FlagM.SF | FlagM.ZF | FlagM.CF | FlagM.OF), "SCZO", PrimitiveType.Byte);
            var bw   = new Backwalker <Block, Instruction>(host, new RtlGoto(m.Mem32(m.IAdd(eax, 0x1000)), InstrClass.Transfer), expSimp);

            Assert.IsTrue(
                bw.BackwalkInstruction(
                    m.BranchIf(
                        new TestCondition(ConditionCode.UGT, SCZO),
                        "Nizze").Instruction));
            Assert.AreEqual("branch UGT", bw.Operations[0].ToString());
            Assert.AreEqual("SCZO", bw.UsedFlagIdentifier.ToString());
        }
        public void Pdg_PostdominateLoop()
        {
            ProcedureBuilder m = new ProcedureBuilder();

            m.Jump("test");
            m.Label("test");
            m.BranchIf(m.LocalBool("f"), "done");
            m.Label("body");
            m.Store(m.Int32(30), m.Int32(0));
            m.Jump("test");
            m.Label("done");
            m.Return();

            FindPostDominators(m);
            string sExp =
                "body (4): idom test (3)" + nl +
                "done (5): idom ProcedureBuilder_exit (6)" + nl +
                "l1 (2): idom test (3)" + nl +
                "ProcedureBuilder_entry (1): idom l1 (2)" + nl +
                "ProcedureBuilder_exit (6): idom " + nl +
                "test (3): idom done (5)" + nl;

            Console.WriteLine(sw.ToString());
            Assert.AreEqual(sExp, sw.ToString());
        }
        public void WriteProcedure_Max()
        {
            var m = new ProcedureBuilder("proc");
            var r1 = m.Register("r1");
            var r2 = m.Register("r2");
            var r3 = m.Register("r3");
            m.BranchIf(m.Gt(r1, r2), "greaterthan");
            m.Assign(r3,r2);
            m.Assign(r2, r1);
            m.Assign(r1, r3);
            m.Label("greaterthan");
            m.Return(r1);

            hcf.Write(m.Procedure);

            var sExp = @"<span class=""kw"">define</span>&nbsp;proc<br />
{<br />
proc_entry:<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class=""kw"">goto</span>&nbsp;l1<br />
greaterthan:<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class=""kw"">return</span>&nbsp;r1<br />
l1:<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class=""kw"">branch</span>&nbsp;r1&nbsp;&gt;&nbsp;r2&nbsp;greaterthan<br />
l2:<br />
&nbsp;&nbsp;&nbsp;&nbsp;r3&nbsp;=&nbsp;r2<br />
&nbsp;&nbsp;&nbsp;&nbsp;r2&nbsp;=&nbsp;r1<br />
&nbsp;&nbsp;&nbsp;&nbsp;r1&nbsp;=&nbsp;r3<br />
&nbsp;&nbsp;&nbsp;&nbsp;<span class=""kw"">goto</span>&nbsp;greaterthan<br />
proc_exit:<br />
}<br />
";
            Debug.Write(sb.ToString());
            Assert.AreEqual(sExp, sb.ToString());
        }
        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.Store(r, 0);
                m.Assign(r, m.ISub(r, 4));
                m.Assign(zf, m.Cond(r));
                m.BranchCc(ConditionCode.NE, "l0000");

                m.Label("l0001");
                m.Assign(r, 42);

                m.Label("l0002");
                m.Store(r, 12);
                m.Assign(r, m.ISub(r, 4));
                m.BranchIf(m.Eq0(r), "l0002");

                m.Return();
            });
            RunFileTest(b.BuildProgram(), "Analysis/VpLoop.txt");
        }
Exemple #7
0
        public void CfgcJmpToBranch()
        {
            var m   = new ProcedureBuilder();
            var c   = m.Temp(PrimitiveType.Bool, "c");
            var pfn = m.Temp(PrimitiveType.Ptr32, "pfn");

            m.Label("m1");
            m.BranchIf(c, "m3");
            m.Label("m2");
            m.Goto("m3");
            m.Label("m3");
            m.SideEffect(m.Fn(pfn));
            m.Return();

            var sExp =
                #region Expected
                @"// ProcedureBuilder
// Return size: 0
void ProcedureBuilder()
ProcedureBuilder_entry:
	pfn()
	return
	// succ:  ProcedureBuilder_exit
m1:
m3:
ProcedureBuilder_exit:
";

            #endregion
            var cfgc = new ControlFlowGraphCleaner(m.Procedure);
            cfgc.Transform();
            var sw = new StringWriter();
            m.Procedure.Write(false, sw);
            Assert.AreEqual(sExp, sw.ToString());
        }
Exemple #8
0
        public void VpEquality2()
        {
            // Makes sure that
            // y = x - 2
            // if (y == 0) ...
            // doesn't get munged into
            // y = x - 2
            // if (x == 2)

            Identifier       x = Reg32("x");
            Identifier       y = Reg32("y");
            ProcedureBuilder m = new ProcedureBuilder();
            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, ssaIds, null);

            vp.Transform(stm);
            Assert.AreEqual("branch x == 0x00000002 test", stm.Instruction.ToString());
        }
Exemple #9
0
        /// <summary>
        /// Mutually recursive functions that jump into each other's bodies.
        /// </summary>
        /// <returns></returns>
        public static Program BuildProgram()
        {
            var prog = new ProgramBuilder();

            var m  = new ProcedureBuilder("even");
            var r1 = m.Register(1);

            m.BranchIf(m.Eq0(r1), "done");
            m.Assign(r1, m.ISub(r1, 1));
            m.Call("odd", 4);
            m.Assign(r1, m.Not(r1));
            m.Return();

            m.Label("done");
            m.Assign(r1, true);
            m.Return();
            prog.Add(m);

            m  = new ProcedureBuilder("odd");
            r1 = m.Register(1);
            m.BranchIf(m.Eq(r1, 1), "done");
            m.Assign(r1, m.ISub(r1, 1));
            m.Call("event", 4);
            m.Assign(r1, m.Not(r1));
            m.Return();

            m.Label("done");
            m.Assign(r1, true);
            m.Return();
            prog.Add(m);

            return(prog.BuildProgram());
        }
Exemple #10
0
        public void Rl_TestFlags()
        {
            var grf = f.EnsureFlagGroup(program.Architecture.GetFlagGroup(0x7));
            var edx = f.EnsureRegister(Registers.edx);
            var tmp = f.CreateTemporary("tmp", PrimitiveType.Bool);

            m.BranchIf(m.Test(ConditionCode.EQ, grf), "somewhere").Instruction.Accept(rl);
            Assert.AreEqual(" SCZ", Dump(rl.IdentifierLiveness));
        }
        /// <summary>
        /// Builds a strongly connected component corresponding to:
        /// a1 = 0
        /// a2 = phi(a1, a3)
        /// while (a2 != 10)
        /// {
        ///    a3 = a2 + 4
        /// }
        /// </summary>
        private List <SsaIdentifier> BuildScc()
        {
            var        m = new ProcedureBuilder("test");
            Identifier a = new Identifier("a", PrimitiveType.Word32, null);

            m.Label("b1");
            m.Assign(a, Constant.Word32(0));
            m.Label("b2");
            m.Assign(a, m.IAdd(a, 4));
            m.BranchIf(m.Ne(a, 10), "b2");
            m.Label("b3");
            m.Return();
            this.dom = m.Procedure.CreateBlockDominatorGraph();
            var ssa = new SsaTransform(
                new ProgramDataFlow(),
                m.Procedure,
                null,
                dom,
                new HashSet <RegisterStorage>());

            /*
             *
             * proc = new Procedure("test", new Frame(PrimitiveType.Word32));
             *          Block b1 = proc.AddBlock("b1");
             *          Block b2 = proc.AddBlock("b2");
             *
             *          Identifier a2 = new Identifier("a2", PrimitiveType.Word32, null);
             *          Identifier a3 = new Identifier("a3", PrimitiveType.Word32, null);
             *          PhiFunction phi = new PhiFunction(a1.DataType, new Expression [] { a1, a3 });
             *
             *          Statement stm_a1 = new Statement(0, new Assignment(a1, Constant.Word32(0)), null);
             *          Statement stm_a2 = new Statement(0, new PhiAssignment(a2, new PhiFunction(a1.DataType,  a1, a3 )), null);
             *          Statement stm_ex = new Statement(0, new Branch(new BinaryExpression(Operator.Ne, PrimitiveType.Bool, a2, Constant.Word32(10)), b2), null);
             *          Statement stm_a3 = new Statement(0, new Assignment(a3, new BinaryExpression(Operator.IAdd, a3.DataType, a2, Constant.Word32(4))), null);
             *          b1.Statements.Add(stm_a1);
             *
             *          b2.Statements.Add(stm_a2);
             *          b2.Statements.Add(stm_a3);
             *
             *          SsaIdentifier sid_a1 = new SsaIdentifier(a1, a1, stm_a1, ((Assignment)stm_a1.Instruction).Src, false);
             * SsaIdentifier sid_a2 = new SsaIdentifier(a2, a2, stm_a2, ((PhiAssignment) stm_a2.Instruction).Src, false);
             * SsaIdentifier sid_a3 = new SsaIdentifier(a3, a3, stm_a3, ((Assignment) stm_a3.Instruction).Src, false);
             *          sid_a1.Uses.Add(stm_a2);
             *          ssaIds = new SsaIdentifierCollection();
             *          ssaIds.Add(a1, sid_a1);
             *          ssaIds.Add(a2, sid_a2);
             *          ssaIds.Add(a3, sid_a3);
             */
            ssaIds = ssa.SsaState.Identifiers;
            List <SsaIdentifier> list = new List <SsaIdentifier> {
                ssaIds.Where(i => i.Identifier.Name == "a_0").Single(),
                ssaIds.Where(i => i.Identifier.Name == "a_1").Single(),
                ssaIds.Where(i => i.Identifier.Name == "a_2").Single(),
            };

            return(list);
        }
        public void CceEqId()
        {
            Identifier r = Reg32("r");
            Identifier z = FlagGroup("z");  // is a condition code.
            Identifier y = FlagGroup("y");  // is a condition code.

            m.Assign(z, new ConditionOf(r));
            ssaIds[z].DefStatement = m.Block.Statements.Last;
            m.Assign(y, z);
            ssaIds[y].DefStatement = m.Block.Statements.Last;
            ssaIds[z].Uses.Add(m.Block.Statements.Last);
            var stmBr = m.BranchIf(m.Test(ConditionCode.EQ, y), "foo");

            ssaIds[y].Uses.Add(stmBr);

            Given_ConditionCodeEliminator();
            cce.Transform();
            Assert.AreEqual("branch r == 0x00000000 foo", stmBr.Instruction.ToString());
        }
        public void ProcStr_IfThen()
        {
            var r1 = m.Reg32("r1");

            m.Label("head");
            m.BranchIf(m.Le(r1, 0), "tail");
            m.Label("doit");
            m.Assign(r1, 0);
            m.Label("tail");
            m.Return(r1);

            var sExp =
                @"    if (r1 > 0x00000000)
        r1 = 0x00000000;
    return r1;
";

            RunTest(sExp, m.Procedure);
        }
Exemple #14
0
        public void BwReg_00121()
        {
            var d0    = m.Reg32("d0", 0);
            var d3    = m.Reg32("d3", 3);
            var a5    = m.Reg32("a5", 5);
            var v38   = m.Temp(PrimitiveType.Word16, "v38");
            var v39   = m.Temp(PrimitiveType.Byte, "v39");
            var v40   = m.Temp(PrimitiveType.Word16, "v40");
            var VZN   = m.Flags("VZN");
            var ZN    = m.Flags("ZN");
            var C     = m.Flags("C");
            var V     = m.Flags("V");
            var CVZN  = m.Flags("CVZN");
            var CVZNX = m.Flags("CVZNX");

            m.Assign(d0, d3);
            m.Assign(CVZN, m.Cond(d0));
            m.Assign(v38, m.And(m.Cast(PrimitiveType.Word16, d0), 0xF0));
            m.Assign(d0, m.Dpb(d0, v38, 0));
            m.Assign(ZN, m.Cond(v38));
            m.Assign(C, false);
            m.Assign(V, false);
            m.Assign(v39, m.Shl(m.Cast(PrimitiveType.Byte, d0), 2));
            m.Assign(d0, m.Dpb(d0, v39, 0));
            m.Assign(CVZNX, m.Cond(v39));
            m.Assign(v40, m.ISub(m.Cast(PrimitiveType.Word16, d0), 44));
            m.Assign(CVZN, m.Cond(v40));
            m.BranchIf(m.Test(ConditionCode.GT, VZN), "lDefault");
            m.Assign(a5, m.Mem32(m.IAdd(Address.Ptr32(0x0000C046), d0)));
            var xfer = new RtlCall(a5, 4, RtlClass.Transfer);

            var bw = new Backwalker <Block, Instruction>(host, xfer, expSimp);

            Assert.IsTrue(bw.CanBackwalk());
            Assert.AreEqual("a5", bw.Index.Name);
            bw.BackWalk(m.Block);
            Assert.AreEqual("v40", bw.IndexExpression.ToString());
        }
Exemple #15
0
        public void StrAnls_Issue_529()
        {
            var m    = new ProcedureBuilder();
            var fp   = m.Frame.FramePointer;
            var sp   = m.Frame.EnsureRegister(m.Architecture.StackRegister);
            var puts = new ExternalProcedure("puts", new FunctionType());

            m.Label("m4E2");
            m.Goto("m4F7");

            m.Label("m4E4");
            m.SideEffect(m.Fn(puts, Constant.String("Hello", StringType.NullTerminated(PrimitiveType.Byte))));
            m.Return();

            m.Label("m4F7");
            m.BranchIf(m.Eq0(m.Mem32(m.Word32(0x0808A0A4))), "m502");
            m.Label("m500");
            m.Goto("m50D");

            m.Label("m502");
            m.BranchIf(m.Eq0(m.Mem32(m.Word32(0x0808A0A8))), "m4E4");
            m.Goto("m50D");
            m.Label("m50D");
            m.SideEffect(m.Fn(puts, Constant.String("Goodbye", StringType.NullTerminated(PrimitiveType.Byte))));
            m.Goto("m4E4");

            var sExp =
                #region Expected
                @"    if (Mem0[0x0808A0A4:word32] != 0x00 || Mem0[0x0808A0A8:word32] != 0x00)
        puts(""Goodbye"");
    puts(""Hello"");
    return;
";

            #endregion
            Given_CompoundConditionCoalescer(m.Procedure);
            RunTest(sExp, m.Procedure);
        }
        public void Pdg_PostDominateIfElse()
        {
            ProcedureBuilder m = new ProcedureBuilder();

            m.BranchIf(m.Local32("a"), "then");
            m.Assign(m.Local32("b"), m.Int32(0));
            m.Jump("join");
            m.Label("then");
            m.Assign(m.Local32("c"), m.Int32(0));
            m.Label("join");
            m.Return();

            FindPostDominators(m);
        }
        public void Pdg_InfiniteLoop()
        {
            ProcedureBuilder m = new ProcedureBuilder();

            m.Label("Infinity");
            m.BranchIf(m.Eq(m.LoadW(m.Word16(0x1234)), 0), "hop");
            m.SideEffect(m.Fn("foo"));
            m.Label("hop");
            m.BranchIf(m.Eq(m.LoadW(m.Word16(0x5123)), 1), "Infinity");
            m.SideEffect(m.Fn("bar"));
            m.Jump("Infinity");
            m.Return();

            FindPostDominators(m);
            string sExp =
                "hop (4): idom ProcedureBuilder_exit (6)" + nl +
                "Infinity (2): idom hop (4)" + nl +
                "l1 (3): idom hop (4)" + nl +
                "l2 (5): idom ProcedureBuilder_exit (6)" + nl +
                "ProcedureBuilder_entry (1): idom Infinity (2)" + nl +
                "ProcedureBuilder_exit (6): idom " + nl;

            Assert.AreEqual(sExp, sw.ToString());
        }
Exemple #18
0
        private Procedure BuildSimpleLoop()
        {
            ProcedureBuilder m = new ProcedureBuilder();
            Identifier       p = m.Local32("p");

            m.Assign(p, 0);

            m.Label("loop");
            m.BranchIf(m.Eq(p, 0x4000), "done");
            m.Store(m.IAdd(p, 0x3000), m.Int32(0));
            m.Assign(p, m.IAdd(p, 4));
            m.Jump("loop");

            m.Label("done");
            m.Return();
            return(m.Procedure);
        }
Exemple #19
0
        public void SsaSwitchWithSharedBranches()
        {
            var m = new ProcedureBuilder("SsaSwitchWithSharedBranches");

            var sp  = m.Frame.EnsureRegister(m.Architecture.StackRegister);
            var r1  = m.Reg32("r1", 1);
            var r2  = m.Reg32("r2", 2);
            var foo = new ExternalProcedure("foo", new FunctionType(
                                                new Identifier("", VoidType.Instance, null),
                                                new Identifier("arg1", PrimitiveType.Int32, new StackArgumentStorage(4, PrimitiveType.Int32))));

            m.Assign(sp, m.Frame.FramePointer);
            m.Assign(r1, m.Mem32(m.IAdd(sp, 4)));
            m.BranchIf(m.Ugt(r1, m.Word32(0x5)), "m4_default");
            m.Label("m1");
            m.Switch(r1,
                     "m2", "m2", "m3", "m3", "m2", "m3");
            m.Label("m2");
            m.Assign(sp, m.ISub(sp, 4));
            m.MStore(sp, m.Word32(0x42));
            m.Call(foo, 4);
            m.Assign(sp, m.IAdd(sp, 4));
            // fall through
            m.Label("m3");
            m.Assign(sp, m.ISub(sp, 4));
            m.MStore(sp, m.Word32(42));
            m.Call(foo, 4);
            m.Assign(sp, m.IAdd(sp, 4));
            // fall through
            m.Label("m4_default");
            m.Assign(sp, m.ISub(sp, 4));
            m.MStore(sp, m.Word32(0));
            m.Call(foo, 4);
            m.Assign(sp, m.IAdd(sp, 4));

            m.Return();

            RunUnitTest(m, "Analysis/SsaSwitchWithSharedBranches.txt");
        }
Exemple #20
0
        public void CceEqId()
        {
            Identifier r = Reg32("r");
            Identifier z = FlagGroup("z");  // is a condition code.
            Identifier y = FlagGroup("y");  // is a condition code.

            ProcedureBuilder m = new ProcedureBuilder();

            m.Assign(z, new ConditionOf(r));
            ssaIds[z].DefStatement = m.Block.Statements.Last;
            m.Assign(y, z);
            ssaIds[y].DefStatement = m.Block.Statements.Last;
            ssaIds[z].Uses.Add(m.Block.Statements.Last);
            var stmBr = m.BranchIf(m.Test(ConditionCode.EQ, y), "foo");

            ssaIds[y].Uses.Add(stmBr);

            var arch = new FakeArchitecture();
            var cce  = new ConditionCodeEliminator(ssaIds, new DefaultPlatform(null, arch));

            cce.Transform();
            Assert.AreEqual("branch r == 0x00000000 foo", stmBr.Instruction.ToString());
        }
Exemple #21
0
        public void CrwManyPredecessorsToExitBlock()
        {
            var m   = new ProcedureBuilder("CrwManyPredecessorsToExitBlock");
            var eax = m.Frame.EnsureRegister(Registers.eax);

            m.BranchIf(m.Ge0(eax), "m2Ge");

            m.Label("m1Lt");
            m.Assign(eax, -1);
            m.Return();

            m.Label("m2Ge");
            m.BranchIf(m.Ne0(eax), "m4Gt");

            m.Label("m3Eq");
            m.Return();

            m.Label("m4Gt");
            m.Assign(eax, 1);
            m.Return();

            var flow = new ProgramDataFlow(program);
            var sst  = new SsaTransform(program, m.Procedure, new HashSet <Procedure>(), null, new ProgramDataFlow());

            sst.Transform();
            sst.AddUsesToExitBlock();
            sst.SsaState.Procedure.Signature = FunctionType.Func(
                new Identifier("", PrimitiveType.Word32, Registers.eax),
                new Identifier("eax", PrimitiveType.Word32, Registers.eax));

            var crw = new CallRewriter(this.platform, flow, new FakeDecompilerEventListener());

            crw.RewriteReturns(sst.SsaState);
            crw.RemoveStatementsFromExitBlock(sst.SsaState);

            var sExp =
                #region Expected
                @"eax:eax
    def:  def eax
    uses: branch eax >= 0<32> m2Ge
          branch eax != 0<32> m4Gt
          return eax
eax_2: orig: eax
    def:  eax_2 = 1<32>
    uses: return eax_2
eax_3: orig: eax
    def:  eax_3 = 0xFFFFFFFF<32>
    uses: return eax_3
eax_4: orig: eax
// CrwManyPredecessorsToExitBlock
// Return size: 0
word32 CrwManyPredecessorsToExitBlock(word32 eax)
CrwManyPredecessorsToExitBlock_entry:
	def eax
	// succ:  l1
l1:
	branch eax >= 0<32> m2Ge
	// succ:  m1Lt m2Ge
m1Lt:
	eax_3 = 0xFFFFFFFF<32>
	return eax_3
	// succ:  CrwManyPredecessorsToExitBlock_exit
m2Ge:
	branch eax != 0<32> m4Gt
	// succ:  m3Eq m4Gt
m3Eq:
	return eax
	// succ:  CrwManyPredecessorsToExitBlock_exit
m4Gt:
	eax_2 = 1<32>
	return eax_2
	// succ:  CrwManyPredecessorsToExitBlock_exit
CrwManyPredecessorsToExitBlock_exit:
";

            #endregion
            AssertExpected(sExp, sst.SsaState);
        }
Exemple #22
0
        public void StrAnls_DoNoCleanProcedureCall()
        {
            m.Label("head");
            m.BranchIf(m.Fn("someCheck"), "failed");
            m.Goto("exit");
            m.Label("failed");
            m.Label("exit");
            m.Return();

            var sExp =
                @"    someCheck();
    return;
";

            RunTest(sExp, m.Procedure);
        }