protected override void TraverseLoop(Loop loop) { Func<Type, Type> safeType = t => t.IsRectMdArray() ? typeof(Object) : t; loop.Locals.ForEach(l => locals.Add(l, il.DeclareLocal(safeType(l.Type.AssertNotNull())))); var test = il.DefineLabel(); var @continue = il.DefineLabel(); var body = il.DefineLabel(); var @break = il.DefineLabel(); continues.Add(loop, @continue); breaks.Add(loop, @break); Traverse(loop.Init); if (loop.IsDoWhile) il.br(body); il.label(test); Traverse(loop.Test); il.brfalse(@break); il.label(body); Traverse(loop.Body); il.label(@continue); Traverse(loop.Iter); il.br(test); il.label(@break); }
protected internal virtual void TraverseLoop(Loop loop) { loop.Unsupported(); }
private void Expand(Node node) { if (node is Expression) { var expr = (Expression)node; var inlined = expr.Expand(Ctx); inlined.Stmts.ForEach(Stmts.Add); if (inlined.Result != null) Stmts.Add(inlined.Result); } else if (node is Block) { var block = (Block)node; Stmts.Add(block.Expand(Ctx.SpinOff())); } else if (node is Break) { Stmts.Add(node); } else if (node is Continue) { Stmts.Add(node); } else if (node is Goto) { Stmts.Add(node); } else if (node is Label) { Stmts.Add(node); } else if (node is If) { var @if = (If)node; var test = @if.Test.Expand(Ctx); test.Stmts.ForEach(Stmts.Add); test.Result.AssertNotNull(); var if_true = @if.IfTrue.Expand(Ctx.SpinOff()); var if_false = @if.IfFalse.Expand(Ctx.SpinOff()); var expanded = new If(test.Result, if_true, if_false); Stmts.Add(expanded); } else if (node is Loop) { var loop = (Loop)node; var test = loop.Test.Expand(Ctx); test.Result.AssertNotNull(); var init = loop.Init.Expand(Ctx.SpinOff()); var iter = loop.Iter.Expand(Ctx.SpinOff()); var body = loop.Body.Expand(Ctx.SpinOff()); var prepend_test = loop.IsWhileDo && test.Stmts.IsNotEmpty(); if (init.IsNotEmpty() && prepend_test) { Stmts.Add(init); init = new Block(); } if (prepend_test) test.Stmts.ForEach(Stmts.Add); test.Stmts.ForEach(iter.Add); var xloop = new Loop(test.Result, body, loop.IsWhileDo){Init = init, Iter = iter}; var cloned_locals = loop.Locals.Select(l => l.DeepClone()); cloned_locals.ForEach(local => xloop.Locals.Add(local)); Stmts.Add(xloop); } else if (node is Return) { var ret = (Return)node; (ret.Value == null).AssertEquiv(Ret == null); if (ret.Value != null) Expand(new Assign(Ret, ret.Value)); Stmts.Add(new Goto(RetLabel)); } else if (node is Try || node is Clause || node is Throw || node is Using || node is Iter) { // todo. implement support for non-linear control flow // this is only possible when we fully implement decompilation of tries // until now I leave this marked as "to be implemented" throw AssertionHelper.Fail(); } else { throw AssertionHelper.Fail(); } }
protected internal override void TraverseLoop(Loop loop) { Dispatch(loop); }
protected internal override Node TransformLoop(Loop loop) { return Dispatch(loop); }
protected internal override void TraverseLoop(Loop loop) { Traverse(loop.Init); Traverse(loop.Test); Traverse(loop.Body); Traverse(loop.Iter); Types.Add(loop, null); }
protected override void TraverseLoop(Loop loop) { var loop_id = Guid.NewGuid().ToString().Slice(0, 4); var test = _ptx.def_label("$loop_test_" + loop_id); var @continue = _ptx.def_label("$loop_continue_" + loop_id); var body = _ptx.def_label("$loop_body_" + loop_id); var @break = _ptx.def_label("$loop_break_" + loop_id); _continues.Add(loop, @continue); _breaks.Add(loop, @break); _ptx.emit(loop.Init); if (loop.IsDoWhile) _ptx.bra(body); _ptx.label(test) .comment(Environment.NewLine) .comment(loop.Test.ToDebugString_WithoutParentInfo()) .bra(Operator.Not(loop.Test), @break) .label(body) .emit(loop.Body) .label(@continue) .emit(loop.Iter) .bra(test) .label(@break); }
protected internal override void TraverseLoop(Loop loop) { Action dumpHeader = () => { var initIsNotEmpty = loop.Init.IsNeitherNullNorEmpty(); var iterIsNotEmpty = loop.Iter.IsNeitherNullNorEmpty(); ; if (initIsNotEmpty || iterIsNotEmpty) _writer.Write("for ("); else _writer.Write("while ("); if (initIsNotEmpty || iterIsNotEmpty) { (loop.Init ?? new Block()).ForEach((c, i) => { var ass = c as Assign; var lhs = ass == null ? null : ass.Lhs as Ref; if (lhs != null && loop.Locals.Contains(lhs.Sym as Local)) _writer.Write("var "); Traverse(c.AssertCast<Expression>()); if (i != loop.Init.Count() - 1) _writer.Write(", "); }); _writer.Write(";"); if (initIsNotEmpty) _writer.Write(" "); } Traverse(loop.Test); if (initIsNotEmpty || iterIsNotEmpty) { _writer.Write(";"); if (iterIsNotEmpty) _writer.Write(" "); (loop.Iter ?? new Block()).ForEach((c, i) => { Traverse(c.AssertCast<Expression>()); if (i != loop.Iter.Count() - 1) _writer.Write(", "); }); } _writer.WriteLine(")"); }; if (loop.IsWhileDo) { dumpHeader(); Traverse(loop.Body); } else { _writer.WriteLine("do"); Traverse(loop.Body); dumpHeader(); } }
// todo. verify that init and iter can live outside the thread loop (when insideThreadLoop is false) private void TransformLoop(Loop loop, Block xregion, bool insideThreadLoop) { var x_init = new Block(); TransformBlock(loop.Init, x_init, true); var x_test = TransformExpression(loop.Test, insideThreadLoop); var x_body = new Block(); TransformBlock(loop.Body, x_body, insideThreadLoop); var x_iter = new Block(); TransformBlock(loop.Iter, x_iter, true); var x_loop = new Loop(x_test, x_body); x_loop.Locals.SetElements(loop.Locals); x_loop.Init = new Block(x_init.Children); x_loop.Iter = new Block(x_iter.Children); xregion.Add(x_loop); }
protected internal virtual Node TransformLoop(Loop loop) { return loop.AcceptTransformer(this, true); }