示例#1
0
        private BlockScope(IScope parent, BaseControlFlowGraph cfg)
        {
            _parent   = parent.AssertNotNull();
            _localCfg = cfg;

            var offspringsRecursive = new Dictionary <ControlFlowBlock, Offspring>();

            this.Hierarchy().ForEach(s => s.Offsprings.ForEach(off => offspringsRecursive.Add(off.Root, off)));
            var pivotsRecursive = new Dictionary <ControlFlowBlock, IScope>();

            this.Parents().Reverse().ForEach(p => p.Pivots.ForEach(cfb => pivotsRecursive[cfb] = p));

            var cflow    = _localCfg.Cflow().Except(cfg.Start).ToReadOnly();
            var todo     = cflow.ToList();
            var expected = todo.First();

            while (todo.IsNotEmpty())
            {
                var curr = todo.First();
                (expected == curr).AssertTrue();
                todo.Remove(curr);

                var offspring = offspringsRecursive.GetOrDefault(curr);
                if (offspring != null)
                {
                    var parentCfg = offspring.Scope.Parent.LocalCfg;
                    (parentCfg.Vedges(curr, null).Count() == 2).AssertTrue();
                    (parentCfg.BackVedges(null, curr).Count() == 0).AssertTrue();
                    var localEdge = cfg.Vedges(curr, null).AssertSingle();
                    localEdge.IsConditional.AssertTrue();
                    expected = localEdge.Target;

                    _block.AddElements(curr.BalancedCode);
                    var test = curr.Residue.AssertSingle();
                    test = localEdge.Condition == PredicateType.IsTrue ? Operator.Not(test) :
                           localEdge.Condition == PredicateType.IsFalse ? test :
                           ((Func <Expression>)(() => { throw AssertionHelper.Fail(); }))();
                    _block.AddElements(new If(test, ComplexScope.Decompile(this, offspring).Hir));
                }
                else
                {
                    if (_localCfg.BackVedges(null, curr).IsNotEmpty())
                    {
                        var loop = LoopScope.Decompile(this, curr);
                        todo.RemoveElements(loop.Test, loop.Continue);
                        todo.RemoveElements(loop.Body.Vertices);
                        todo.RemoveElements(loop.Offsprings.SelectMany(off => off.Body));

                        _block.AddElements(loop.Hir);
                        expected = loop.Conv;
                    }
                    else if (_localCfg.Vedges(curr, null).Count() >= 2)
                    {
                        (_localCfg.TreeVedges(curr, null).Count() == 2).AssertTrue();
                        (_localCfg.BackVedges(curr, null).Count() == 0).AssertTrue();

                        var @if = IfScope.Decompile(this, curr);
                        todo.RemoveElements(@if.Test);
                        todo.RemoveElements(@if.IfTrue.Vertices);
                        todo.RemoveElements(@if.IfFalse.Vertices);
                        todo.RemoveElements(@if.Offsprings.SelectMany(off => off.Body));

                        _block.AddElements(@if.Hir);
                        expected = @if.Conv;
                    }
                    else
                    {
                        (_localCfg.TreeVedges(curr, null).Count() <= 1).AssertTrue();
                        (_localCfg.BackVedges(curr, null).Count() == 0).AssertTrue();
                        var e_next = _localCfg.TreeVedges(curr, null).SingleOrDefault();
                        (e_next == null).AssertEquiv(todo.IsEmpty());
                        expected = e_next == null ? null : e_next.Target;

                        var isPivot = pivotsRecursive.ContainsKey(curr);
                        isPivot.AssertImplies(e_next == null);
                        if (!isPivot)
                        {
                            _block.AddElements(curr.BalancedCode);
                            if (curr.Residue.IsNotEmpty())
                            {
                                var nextIsRetOf = pivotsRecursive.GetOrDefault(expected) as LambdaScope;
                                (nextIsRetOf != null && nextIsRetOf.Return == expected).AssertTrue();
                                _block.Add(curr.Residue.AssertSingle());
                            }
                        }
                        else
                        {
                            var scope = pivotsRecursive[curr];
                            if (scope is LambdaScope)
                            {
                                var lambda = scope.AssertCast <LambdaScope>();
                                if (curr == lambda.Return)
                                {
                                    var i_curr            = cflow.IndexOf(curr).AssertThat(i => i != -1);
                                    var prev              = cflow.NthOrDefault(i_curr - 1);
                                    var prevWasExpression = _block.LastOrDefault() is Expression;
                                    var prevHasResidue    = prev != null && prev.Residue.IsNotEmpty();

                                    if (prevWasExpression && prevHasResidue)
                                    {
                                        var valueToRet = _block.Last().AssertCast <Expression>();
                                        _block.RemoveLast();
                                        _block.Add(new Return(valueToRet.DeepClone()));
                                    }
                                    else
                                    {
                                        var complex       = parent as ComplexScope;
                                        var global        = complex == null ? null : complex.Parent as LambdaScope;
                                        var canOmitReturn = global != null && global.Return == curr;
                                        if (!canOmitReturn)
                                        {
                                            _block.Add(new Return());
                                        }
                                    }
                                }
                                else
                                {
                                    throw AssertionHelper.Fail();
                                }
                            }
                            else if (scope is LoopScope)
                            {
                                var loop = scope.AssertCast <LoopScope>();
                                (loop == this.Parents().OfType <LoopScope>().First()).AssertTrue();
                                if (curr == loop.Continue)
                                {
                                    _block.Add(new Continue());
                                }
                                else if (curr == loop.Conv)
                                {
                                    _block.Add(new Break());
                                }
                                else
                                {
                                    throw AssertionHelper.Fail();
                                }
                            }
                            else
                            {
                                throw AssertionHelper.Fail();
                            }
                        }
                    }
                }
            }
        }
示例#2
0
 private void BanChangesToLocalsWhenFrozen(Object sender, ListChangeEventArgs args)
 {
     throw AssertionHelper.Fail();
 }
示例#3
0
        // todo. when outputting HTML, also inject the "$(document).ready(function(){window.log.server(<actual log>});"
        private void Complete(Object result = null)
        {
            if (result == null)
            {
                Native.End();
            }

            var result_ex = result as Exception;

            if (result_ex != null)
            {
                Native.Clear();

                // note. why there's no line info in the stack trace?
                // see http://stackoverflow.com/questions/2673623/iis-not-giving-line-numbers-in-stack-trace-even-though-pdb-present
                var message = (CallStack.Enabled ? result_ex.ToString() : result_ex.Message).ToHtml();
                var trace   = (Debug.Enabled ? Log.Message : null).ToHtml();

                var is_json = Native.ContentType == "application/json";
                if (is_json)
                {
                    this["Content-Type"] = "application/json";
                    var lowlevel_result = new Json(new { success = true, result = message, trace = trace });
                    Write(Hints.Prettyprint ? lowlevel_result.ToPrettyString() : lowlevel_result.ToCompactString());
                    Native.End();
                }
                else
                {
                    this["Content-Type"] = "text/html";
                    // note. trace will be written by Gateway.cs
                    // note. no need to dump exception, since it's already included into trace
                    Native.End();
                }
            }

            var result_json = result as Json;

            if (result_json != null)
            {
                (this.Text() == null || this.Text().IsEmpty()).AssertTrue();
                this["Content-Type"] = Hints.Prettyprint ? "text/html" : "application/json";
                var lowlevel_result = new Json(new { success = true, result = result_json, trace = (Debug.Enabled ? Log.Message : null).ToHtml() });
                Write(Hints.Prettyprint ? lowlevel_result.ToPrettyString() : lowlevel_result.ToCompactString());
                Native.End();
            }

            var result_string = result as String;

            if (result_string != null)
            {
                // todo. if this is HTML, inject log into it and show via javascript upon hotkey press
                (this.Text() == null || this.Text().IsEmpty()).AssertTrue();
                Write(result_string);
                Native.End();
            }

            var result_bytes = result as byte[];

            if (result_bytes != null)
            {
                (this.Bytes() == null || this.Bytes().IsEmpty()).AssertTrue();
                BinaryWrite(result_bytes);
                Native.End();
            }

            var result_stream = result as Stream;

            if (result_stream != null)
            {
                (this.Bytes() == null || this.Bytes().IsEmpty()).AssertTrue();
                StreamWrite(result_stream);
                Native.End();
            }

            throw AssertionHelper.Fail();
        }
示例#4
0
        protected override void TraverseOperator(Operator op)
        {
            var lhs  = op.Args.FirstOrDefault();
            var rhs  = op.Args.SecondOrDefault();
            var targ = op.Args.FirstOrDefault();

            var opt = op.OperatorType;

            if (opt.IsAssign())
            {
                // todo. implement this with the use of SafeExpandOpAssign
                var equiv = op.UnsafeExpandOpAssign();
                Traverse(equiv);
            }
            else if (opt == OperatorType.AndAlso)
            {
                var equiv = new Conditional(lhs, rhs, new Const(false));
                Traverse(equiv);
            }
            else if (opt == OperatorType.OrElse)
            {
                var equiv = new Conditional(lhs, new Const(true), rhs);
                Traverse(equiv);
            }
            else
            {
                op.Args.ForEach(Traverse);

                switch (opt)
                {
                case OperatorType.Add:
                    il.add();
                    break;

                case OperatorType.And:
                    il.and();
                    break;

                case OperatorType.Divide:
                    il.div();
                    break;

                case OperatorType.Equal:
                    il.ceq();
                    break;

                case OperatorType.GreaterThan:
                    il.cgt();
                    break;

                case OperatorType.GreaterThanOrEqual:
                    il.cge();
                    break;

                case OperatorType.LeftShift:
                    il.shl();
                    break;

                case OperatorType.LessThan:
                    il.clt();
                    break;

                case OperatorType.LessThanOrEqual:
                    il.cle();
                    break;

                case OperatorType.Modulo:
                    il.rem();
                    break;

                case OperatorType.Multiply:
                    il.mul();
                    break;

                case OperatorType.Negate:
                    il.neg();
                    break;

                case OperatorType.Not:
                    var is_bool = targ.Type() == typeof(bool);
                    if (is_bool)
                    {
                        il.ldc_i4(0).ceq();
                    }
                    else
                    {
                        il.not();
                    }
                    break;

                case OperatorType.NotEqual:
                    il.cne();
                    break;

                case OperatorType.Or:
                    il.or();
                    break;

                case OperatorType.RightShift:
                    il.shr();
                    break;

                case OperatorType.Subtract:
                    il.sub();
                    break;

                case OperatorType.Xor:
                    il.xor();
                    break;

                default:
                    throw AssertionHelper.Fail();
                }
            }
        }
示例#5
0
        private static void InferFromOpcode(OpCodeKb kb)
        {
            if (kb.OpCode.FlowControl == FlowControl.Meta)
            {
                kb.Tags.Add("Prefix");

                if (kb.Family == "unaligned")
                {
                    (kb.OpCode.OperandType == OperandType.ShortInlineI).AssertTrue();

                    var p = kb.EnsureProperty("Alignment", typeof(Byte));
                    kb.Meta["ValueProp"] = p.Name;
                    p.Getter             = "_alignment";

                    var f = kb.EnsureField("_alignment", typeof(Byte));
                    f.Initializer = "ReadU1(reader)";
                }
                else if (kb.Family == "constrained")
                {
                    (kb.OpCode.OperandType == OperandType.InlineType).AssertTrue();

                    var p_Token = kb.EnsureProperty("TypeToken", typeof(Int32));
                    p_Token.Getter = "_typeToken;";

                    var p_Type = kb.EnsureProperty("Type", typeof(Type));
                    p_Type.Getter = "TypeFromToken(_typeToken);";

                    var f = kb.EnsureField("_typeToken", typeof(Int32));
                    f.Initializer = "ReadMetadataToken(reader)";
                }
                else
                {
                    (kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue();
                }
            }
            else if (kb.Family == "endfinally" || kb.Family == "endfilter")
            {
                (kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue();

//                kb.Tags.Add("Ignore");
                // todo. uncomment the line above and perform all necessary fixups
            }
            else if (kb.Family == "switch")
            {
                var f       = kb.EnsureField("_targetOffsets", typeof(ReadOnlyCollection <Tuple <Int32, Int32> >));
                var buffer1 = new StringBuilder();
                buffer1.AppendLine(String.Format("(({0})(() => ",
                                                 typeof(Func <ReadOnlyCollection <Tuple <Int32, Int32> > >).GetCSharpRef(ToCSharpOptions.ForCodegen)));
                buffer1.AppendLine("{");
                buffer1.AppendLine("var n = ReadI4(reader);".Indent());
                buffer1.AppendLine(String.Format("var pivot = ({0})reader.BaseStream.Position + sizeof({0}) * n;",
                                                 typeof(Int32).GetCSharpRef(ToCSharpOptions.ForCodegen)).Indent());
                buffer1.AppendLine();
                buffer1.Append(String.Format("return {0}.ToReadOnly(",
                                             typeof(EnumerableExtensions).GetCSharpRef(ToCSharpOptions.ForCodegen)).Indent());
                buffer1.AppendLine(String.Format("{0}.Select(",
                                                 typeof(Enumerable).GetCSharpRef(ToCSharpOptions.ForCodegen)));
                buffer1.AppendLine(String.Format("{0}.Range(1, n), _ => ",
                                                 typeof(Enumerable).GetCSharpRef(ToCSharpOptions.ForCodegen)).Indent().Indent());
                buffer1.AppendLine("{".Indent().Indent());
                buffer1.AppendLine("var relative = ReadI4(reader);".Indent().Indent().Indent());
                buffer1.AppendLine("var absolute = pivot + relative;".Indent().Indent().Indent());
                buffer1.AppendLine(String.Format("return {0}.Create(relative, absolute);",
                                                 typeof(Tuple).GetCSharpRef(ToCSharpOptions.ForCodegen)).Indent().Indent().Indent());
                buffer1.AppendLine("}));".Indent().Indent());
                buffer1.Append("}))()");
                f.Initializer = buffer1.ToString();

                var p_RelativeTargetOffsets = kb.EnsureProperty("RelativeTargetOffsets", typeof(ReadOnlyCollection <Int32>));
                p_RelativeTargetOffsets.Getter = String.Format(
                    "{0}.ToReadOnly({1}.Select(_targetOffsets, t => t.Item2))",
                    typeof(EnumerableExtensions).GetCSharpRef(ToCSharpOptions.ForCodegen),
                    typeof(Enumerable).GetCSharpRef(ToCSharpOptions.ForCodegen));

                var p_AbsoluteTargetOffsets = kb.EnsureProperty("AbsoluteTargetOffsets", typeof(ReadOnlyCollection <Int32>));
                p_AbsoluteTargetOffsets.Getter = String.Format(
                    "{0}.ToReadOnly({1}.Select(_targetOffsets, t => t.Item2))",
                    typeof(EnumerableExtensions).GetCSharpRef(ToCSharpOptions.ForCodegen),
                    typeof(Enumerable).GetCSharpRef(ToCSharpOptions.ForCodegen));

                var p_Targets = kb.EnsureProperty("Targets", typeof(ReadOnlyCollection <ILOp>));
                var buffer2   = new StringBuilder();
                buffer2.Append(String.Format("var resolved = {0}.Select(",
                                             typeof(Enumerable).GetCSharpRef(ToCSharpOptions.ForCodegen)));
                buffer2.AppendLine("AbsoluteTargetOffsets, offset => ResolveReference(offset));");
                buffer2.Append(String.Format("return {0}.ToReadOnly(resolved);",
                                             typeof(EnumerableExtensions).GetCSharpRef(ToCSharpOptions.ForCodegen)));
                p_Targets.Getter = buffer2.ToString();
            }
            else if (kb.OpCode.FlowControl == FlowControl.Branch ||
                     kb.OpCode.FlowControl == FlowControl.Cond_Branch)
            {
                (kb.OpCode.OperandType == OperandType.InlineBrTarget ||
                 kb.OpCode.OperandType == OperandType.ShortInlineBrTarget).AssertTrue();

                var p_target = kb.EnsureProperty("Target", typeof(IILOp));
                p_target.Getter = "ResolveReference(_absoluteTargetOffset)";

                var p_rto = kb.EnsureProperty("RelativeTargetOffset", typeof(Int32));
                p_rto.Getter = "_relativeTargetOffset";

                var p_ato = kb.EnsureProperty("AbsoluteTargetOffset", typeof(Int32));
                p_ato.Getter = "_absoluteTargetOffset";

                // relative offset === operand of the opcode
                var f_rto = kb.EnsureField("_relativeTargetOffset", typeof(Int32));
                f_rto.SetLazyInitializer(_ => String.Format(
                                             "Read" + TypeSpecFromSpec(kb).Capitalize() + "(reader)",
                                             typeof(Int32).GetCSharpRef(ToCSharpOptions.ForCodegen)));

                // absolute offset === exact offset that can be resolved into target
                var f_ato = kb.EnsureField("_absoluteTargetOffset", typeof(Int32));
                f_ato.SetLazyInitializer(_ => String.Format(
                                             "({0})origPos + sizeof({1}) + _relativeTargetOffset",
                                             typeof(Int32).GetCSharpRef(ToCSharpOptions.ForCodegen),
                                             TypeFromSpec(kb).AssertNotNull().GetCSharpRef(ToCSharpOptions.ForCodegen)));
            }
            else if (kb.Family == "ldarg" || kb.Family == "ldarga" || kb.Family == "starg")
            {
                (kb.OpCode.OperandType == OperandType.InlineVar ||
                 kb.OpCode.OperandType == OperandType.ShortInlineVar ||
                 kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue();

                var p_Index = kb.EnsureProperty("Index", typeof(int));
                p_Index.Getter = "_value";

                var p_Arg = kb.EnsureProperty("Arg", typeof(ParameterInfo));
                p_Arg.Getter =
                    "if (Source.Method == null || Source.Args == null)" + Environment.NewLine +
                    "{" + Environment.NewLine +
                    "    return null;" + Environment.NewLine +
                    "}" + Environment.NewLine +
                    "else" + Environment.NewLine +
                    "{" + Environment.NewLine +
                    "    if (Source.Method.IsStatic)" + Environment.NewLine +
                    "    {" + Environment.NewLine +
                    "        return Source.Args[_value];" + Environment.NewLine +
                    "    }" + Environment.NewLine +
                    "    else" + Environment.NewLine +
                    "    {" + Environment.NewLine +
                    "        return _value == 0 ? null : Source.Args[_value - 1];" + Environment.NewLine +
                    "    }" + Environment.NewLine +
                    "}";

                var f_value         = kb.EnsureField("_value", typeof(Int32));
                var f_useConstValue = kb.EnsureField("_useConstValue", typeof(bool));
                var f_constValue    = kb.EnsureField("_constValue", typeof(Int32?));
                f_value.SetLazyInitializer(_ => f_useConstValue.Name + " ? " +
                                           f_constValue.Name + ".Value : Read" + TypeSpecFromSpec(kb).Capitalize() + "(reader)");
            }
            else if (kb.Family == "ldloc" || kb.Family == "ldloca" || kb.Family == "stloc")
            {
                (kb.OpCode.OperandType == OperandType.InlineVar ||
                 kb.OpCode.OperandType == OperandType.ShortInlineVar ||
                 kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue();

                var p_Index = kb.EnsureProperty("Index", typeof(int));
                p_Index.Getter = "_value";

                var p_Loc = kb.EnsureProperty("Loc", typeof(ILocalVar));
                p_Loc.Getter =
                    "if (Source.Method == null || Source.Locals == null)" + Environment.NewLine +
                    "{" + Environment.NewLine +
                    "    return null;" + Environment.NewLine +
                    "}" + Environment.NewLine +
                    "else" + Environment.NewLine +
                    "{" + Environment.NewLine +
                    "    return Source.Locals[_value];" + Environment.NewLine +
                    "}";

                var f_value         = kb.EnsureField("_value", typeof(Int32));
                var f_useConstValue = kb.EnsureField("_useConstValue", typeof(bool));
                var f_constValue    = kb.EnsureField("_constValue", typeof(Int32?));
                f_value.SetLazyInitializer(_ => f_useConstValue.Name + " ? " +
                                           f_constValue.Name + ".Value : Read" + TypeSpecFromSpec(kb).Capitalize() + "(reader)");
            }
            else if (kb.Family == "ldc")
            {
                (kb.OpCode.OperandType == OperandType.InlineI ||
                 kb.OpCode.OperandType == OperandType.InlineI8 ||
                 kb.OpCode.OperandType == OperandType.InlineR ||
                 kb.OpCode.OperandType == OperandType.ShortInlineI ||
                 kb.OpCode.OperandType == OperandType.ShortInlineR ||
                 kb.OpCode.OperandType == OperandType.InlineString ||
                 kb.OpCode.OperandType == OperandType.InlineTok ||
                 kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue();

                var p = kb.EnsureProperty("Value", typeof(Object));
                p.Getter = "_value";

                var f_value         = kb.EnsureField("_value", typeof(Object));
                var f_useConstValue = kb.EnsureField("_useConstValue", typeof(bool));
                var f_constValue    = kb.EnsureField("_constValue", typeof(Object));
                var cast            = kb.OpCode.Name == "ldc.i4.s" ? String.Format("({0})",
                                                                                   typeof(int).GetCSharpRef(ToCSharpOptions.Informative)) : String.Empty;
                f_value.SetLazyInitializer(_ => f_useConstValue.Name + " ? " +
                                           f_constValue.Name + " : " + cast + "Read" + TypeSpecFromSpec(kb).Capitalize() + "(reader)");
            }
            else if (kb.Family == "isinst" || kb.Family == "sizeof" ||
                     kb.Family == "initobj" || kb.Family == "stobj" || kb.Family == "ldobj" || kb.Family == "cpobj" ||
                     kb.Family == "mkrefany" || kb.Family == "refanyval")
            {
                (kb.OpCode.OperandType == OperandType.InlineType).AssertTrue();

                var p_Token = kb.EnsureProperty("TypeToken", typeof(Int32));
                p_Token.Getter = "_typeToken;";

                var p_Type = kb.EnsureProperty("Type", typeof(Type));
                p_Type.Getter = "TypeFromToken(_typeToken);";

                var f = kb.EnsureField("_typeToken", typeof(Int32));
                f.Initializer = "ReadMetadataToken(reader)";
            }
            else if (kb.Family == "ldelem" || kb.Family == "ldelema" || kb.Family == "stelem")
            {
                (kb.OpCode.OperandType == OperandType.InlineType ||
                 kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue();

                if (kb.OpCode.OperandType == OperandType.InlineType)
                {
                    var p_Token = kb.EnsureProperty("TypeToken", typeof(Int32));
                    p_Token.Getter = "_typeToken;";

                    var p_Type = kb.EnsureProperty("Type", typeof(Type));
                    p_Type.Getter = "TypeFromToken(_typeToken);";

                    var f = kb.EnsureField("_typeToken", typeof(Int32));
                    f.Initializer = "ReadMetadataToken(reader)";
                }
                else
                {
                    // InferFromTag will take care of XXXelemYYY.TYPE (see below)
                }
            }
            else if (kb.Family == "ldind" || kb.Family == "stind")
            {
                (kb.OpCode.OperandType == OperandType.InlineType ||
                 kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue();

                if (kb.OpCode.OperandType == OperandType.InlineType)
                {
                    var p_Token = kb.EnsureProperty("TypeToken", typeof(Int32));
                    p_Token.Getter = "_typeToken;";

                    var p_Type = kb.EnsureProperty("Type", typeof(Type));
                    p_Type.Getter = "TypeFromToken(_typeToken);";

                    var f = kb.EnsureField("_typeToken", typeof(Int32));
                    f.Initializer = "ReadMetadataToken(reader)";
                }
                else
                {
                    // InferFromTag will take care of XXXind.TYPE (see below)
                }

                kb.EnsurePrefix("IsVolatile", typeof(bool), "volatile");
                kb.EnsurePrefix("IsUnaligned", typeof(bool), "unaligned");
                var p_IsAligned = kb.EnsureProperty("IsAligned", typeof(bool));
                p_IsAligned.Getter = "!IsUnaligned";
                var p_Alignment = kb.EnsureProperty("Alignment", typeof(byte));
                var buf         = new StringBuilder();
                buf.AppendLine(String.Format(
                                   "var unaligned = {0}.SingleOrDefault({0}.OfType<{1}>(Prefixes));",
                                   typeof(Enumerable), "Unaligned"));
                buf.AppendLine(String.Format(
                                   "var defaultAlignment = (({0})(() => {{ throw new {1}(); }}))();",
                                   typeof(Func <byte>).GetCSharpRef(ToCSharpOptions.ForCodegen),
                                   typeof(NotImplementedException).GetCSharpRef(ToCSharpOptions.ForCodegen)));
                buf.Append("return unaligned != null ? unaligned.Alignment : defaultAlignment");
                p_Alignment.Getter = buf.ToString();
            }
            else if (kb.Family == "cast")
            {
                (kb.OpCode.OperandType == OperandType.InlineType ||
                 kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue();

                if (kb.OpCode.OperandType == OperandType.InlineType)
                {
                    var p_Token = kb.EnsureProperty("TypeToken", typeof(Int32));
                    p_Token.Getter = "_typeToken;";

                    var p_Type = kb.EnsureProperty("Type", typeof(Type));
                    p_Type.Getter = kb.OpCode.Name == "box" ?
                                    String.Format("typeof({0})", typeof(Object).GetCSharpRef(ToCSharpOptions.ForCodegen)) :
                                    "TypeFromToken(_typeToken);";

                    var f = kb.EnsureField("_typeToken", typeof(Int32));
                    f.Initializer = "ReadMetadataToken(reader)";
                }
            }
            else if (kb.Family == "new")
            {
                (kb.OpCode.OperandType == OperandType.InlineType ||
                 kb.OpCode.OperandType == OperandType.InlineMethod).AssertTrue();

                var f_ctorToken = kb.EnsureField("_ctorToken", typeof(Int32?));
                var p_ctorToken = kb.EnsureProperty("CtorToken", typeof(Int32?));
                p_ctorToken.Getter = "_ctorToken;";

                var f_typeToken = kb.EnsureField("_typeToken", typeof(Int32?));
                var p_typeToken = kb.EnsureProperty("TypeToken", typeof(Int32?));
                p_typeToken.Getter = "_typeToken;";

                var p_ctor = kb.EnsureProperty("Ctor", typeof(ConstructorInfo));
                if (kb.OpCode == OpCodes.Newobj)
                {
                    p_ctor.Getter = String.Format("CtorFromToken({0}.AssertValue({1}))", typeof(AssertionHelper).GetCSharpRef(ToCSharpOptions.ForCodegen), f_ctorToken.Name);
                }
                else if (kb.OpCode == OpCodes.Newarr)
                {
                    p_ctor.Getter = String.Format("Type != null ? {0}.AssertSingle(Type.GetConstructors()) : null", typeof(AssertionHelper).GetCSharpRef(ToCSharpOptions.ForCodegen));
                }
                else
                {
                    throw AssertionHelper.Fail();
                }

                var p_type = kb.EnsureProperty("Type", typeof(Type));
                if (kb.OpCode == OpCodes.Newobj)
                {
                    p_type.Getter = "Ctor != null ? Ctor.DeclaringType : null";
                }
                else if (kb.OpCode == OpCodes.Newarr)
                {
                    p_type.Getter =
                        String.Format("var elementType = TypeFromToken({0}.AssertValue({1}));", typeof(AssertionHelper).GetCSharpRef(ToCSharpOptions.ForCodegen), f_typeToken.Name) + Environment.NewLine +
                        "return elementType != null ? elementType.MakeArrayType() : null;";
                }
                else
                {
                    throw AssertionHelper.Fail();
                }
            }
            else if (kb.Family == "ldftn" || kb.Family == "jmp")
            {
                (kb.OpCode.OperandType == OperandType.InlineMethod).AssertTrue();

                var p_Token = kb.EnsureProperty("MethodToken", typeof(Int32));
                p_Token.Getter = "_methodToken;";

                var p_Method = kb.EnsureProperty("Method", typeof(MethodBase));
                p_Method.Getter = "MethodBaseFromToken(_methodToken);";

                var f = kb.EnsureField("_methodToken", typeof(Int32));
                f.Initializer = "ReadMetadataToken(reader)";
            }
            else if (kb.Family == "call")
            {
                (kb.OpCode.OperandType == OperandType.InlineMethod ||
                 kb.OpCode.OperandType == OperandType.InlineSig).AssertTrue();

                var p_Method = kb.EnsureProperty("Method", typeof(MethodBase));
                if (kb.OpCode.OperandType == OperandType.InlineMethod)
                {
                    p_Method.Getter = "MethodBaseFromToken(_methodToken);";
                }
                else if (kb.OpCode.OperandType == OperandType.InlineSig)
                {
                    p_Method.Getter = "MethodBaseFromSignature(SignatureFromToken(_signatureToken));";
                }
                else
                {
                    throw AssertionHelper.Fail();
                }

                var p_MethodToken = kb.EnsureProperty("MethodToken", typeof(Int32));
                if (kb.OpCode.OperandType == OperandType.InlineMethod)
                {
                    p_MethodToken.Getter = "_methodToken;";
                }
                else if (kb.OpCode.OperandType == OperandType.InlineSig)
                {
                    p_MethodToken.Getter = null;
                }
                else
                {
                    throw AssertionHelper.Fail();
                }

                var f_MethodToken = kb.EnsureField("_methodToken", typeof(Int32));
                if (kb.OpCode.OperandType == OperandType.InlineMethod)
                {
                    f_MethodToken.Initializer = "ReadMetadataToken(reader)";
                }
                else if (kb.OpCode.OperandType == OperandType.InlineSig)
                {
                    f_MethodToken.Initializer = null;
                }
                else
                {
                    throw AssertionHelper.Fail();
                }

                var p_Signature = kb.EnsureProperty("Signature", typeof(byte[]));
                if (kb.OpCode.OperandType == OperandType.InlineMethod)
                {
                    p_Signature.Getter = null;
                }
                else if (kb.OpCode.OperandType == OperandType.InlineSig)
                {
                    p_Signature.Getter = "SignatureFromToken(_signatureToken);";
                }
                else
                {
                    throw AssertionHelper.Fail();
                }

                var p_SignatureToken = kb.EnsureProperty("SignatureToken", typeof(Int32));
                if (kb.OpCode.OperandType == OperandType.InlineMethod)
                {
                    p_SignatureToken.Getter = null;
                }
                else if (kb.OpCode.OperandType == OperandType.InlineSig)
                {
                    p_SignatureToken.Getter = "_signatureToken;";
                }
                else
                {
                    throw AssertionHelper.Fail();
                }

                var f_SignatureToken = kb.EnsureField("_signatureToken", typeof(Int32));
                if (kb.OpCode.OperandType == OperandType.InlineMethod)
                {
                    f_SignatureToken.Initializer = null;
                }
                else if (kb.OpCode.OperandType == OperandType.InlineSig)
                {
                    f_SignatureToken.Initializer = "ReadMetadataToken(reader)";
                }
                else
                {
                    throw AssertionHelper.Fail();
                }

                var pfx_constrained = kb.EnsurePrefix("Constraint", typeof(Type), "constrained");
                pfx_constrained.Getter = "Type";
                kb.EnsurePrefix("IsTail", typeof(bool), "tail");
            }
            else if (kb.Family == "ldfld" || kb.Family == "ldflda" || kb.Family == "stfld")
            {
                (kb.OpCode.OperandType == OperandType.InlineField).AssertTrue();

                var p_Token = kb.EnsureProperty("FieldToken", typeof(Int32));
                p_Token.Getter = "_fieldToken;";

                var p_Fld = kb.EnsureProperty("Field", typeof(FieldInfo));
                p_Fld.Getter = "FieldFromToken(_fieldToken);";

                var f = kb.EnsureField("_fieldToken", typeof(Int32));
                f.Initializer = "ReadMetadataToken(reader)";

                kb.EnsurePrefix("IsVolatile", typeof(bool), "volatile");
                var pfx_Unaligned = kb.EnsurePrefix("IsUnaligned", typeof(bool), "unaligned");
                if (kb.Family == "ldfld")
                {
                    pfx_Unaligned.Filter = "OpSpec.OpCode.Value != 0x7e /* ldsfld */";
                }
                if (kb.Family == "stfld")
                {
                    pfx_Unaligned.Filter = "OpSpec.OpCode.Value != 0x80 /* stsfld */";
                }

                var p_IsAligned = kb.EnsureProperty("IsAligned", typeof(bool));
                p_IsAligned.Getter = "!IsUnaligned";
                var p_Alignment = kb.EnsureProperty("Alignment", typeof(byte));
                var buf         = new StringBuilder();
                buf.AppendLine(String.Format(
                                   "var unaligned = {0}.SingleOrDefault({0}.OfType<{1}>(Prefixes));",
                                   typeof(Enumerable), "Unaligned"));
                buf.AppendLine(String.Format(
                                   "var defaultAlignment = (({0})(() => {{ throw new {1}(); }}))();",
                                   typeof(Func <byte>).GetCSharpRef(ToCSharpOptions.ForCodegen),
                                   typeof(NotImplementedException).GetCSharpRef(ToCSharpOptions.ForCodegen)));
                buf.Append("return unaligned != null ? unaligned.Alignment : defaultAlignment");
                p_Alignment.Getter = buf.ToString();
            }
            else if (kb.Family == "initblk" || kb.Family == "cpblk")
            {
                kb.EnsurePrefix("IsVolatile", typeof(bool), "volatile");
                kb.EnsurePrefix("IsUnaligned", typeof(bool), "unaligned");
                var p_IsAligned = kb.EnsureProperty("IsAligned", typeof(bool));
                p_IsAligned.Getter = "!IsUnaligned";
                var p_Alignment = kb.EnsureProperty("Alignment", typeof(byte));
                var buf         = new StringBuilder();
                buf.AppendLine(String.Format(
                                   "var unaligned = {0}.SingleOrDefault({0}.OfType<{1}>(Prefixes));",
                                   typeof(Enumerable).GetCSharpRef(ToCSharpOptions.ForCodegen),
                                   "Unaligned"));
                buf.AppendLine(String.Format(
                                   "var defaultAlignment = ({0}){1}.SizeOf(typeof({2}));",
                                   typeof(byte).GetCSharpRef(ToCSharpOptions.ForCodegen),
                                   typeof(Marshal).GetCSharpRef(ToCSharpOptions.ForCodegen),
                                   typeof(IntPtr).GetCSharpRef(ToCSharpOptions.ForCodegen)));
                buf.Append("return unaligned != null ? unaligned.Alignment : defaultAlignment");
                p_Alignment.Getter   = buf.ToString();
                p_Alignment.IsUnsafe = true;
            }
            else
            {
                // so that we never miss any other instructions with arguments
                (kb.OpCode.OperandType == OperandType.InlineNone).AssertTrue();
            }
        }
        public static void DoDecompileComplexConditions(ControlFlowGraph cfg)
        {
            var flow = cfg.Cflow(cfg.Start);

            while (true)
            {
                var vs = flow.FirstOrDefault(v =>
                                             v.Residue.Count() == 1 &&
                                             cfg.Vedges(v, null).Count() == 2 &&
                                             cfg.Vedges(v, null).All(e => e.Target.BalancedCode.IsEmpty() && e.Target.Residue.Count() == 1));
                if (vs == null)
                {
                    break;
                }

                var conv = cfg.ConvStrict(vs);
                var ass  = conv.BalancedCode.AssertFirst().AssertCast <Assign>();
                (ass.Lhs is Ref && ass.Rhs is Loophole).AssertTrue();

                var parts      = cfg.Cflow(vs, conv);
                var innerEdges = cfg.Edges(parts, parts).ToList();
                cfg.Edges(null, parts).Except(innerEdges).AssertEach(e => e.Target == vs);
                cfg.Edges(parts, null).Except(innerEdges).AssertEach(e => e.Source == vs || e.Source == conv);

                while (true)
                {
                    var somethingWasChanged = false;
                    foreach (var pivot in parts)
                    {
                        var pivot_inEdges = cfg.Vedges(null, pivot);
                        if (pivot_inEdges.Count() != 1)
                        {
                            continue;
                        }

                        var e_pred2pivot  = pivot_inEdges.AssertSingle();
                        var pred          = e_pred2pivot.Source;
                        var pred_outEdges = cfg.Vedges(pred, null);
                        if (pred_outEdges.Count() != 2)
                        {
                            continue;
                        }

                        var e_pred2target1  = pred_outEdges.AssertSingle(e => e.Target != pivot);
                        var target1         = e_pred2target1.Target;
                        var e_pivot2target1 = cfg.Vedge(pivot, target1);
                        if (e_pivot2target1 == null)
                        {
                            continue;
                        }

                        var pivot_outEdges = cfg.Vedges(pivot, null);
                        if (pivot_outEdges.Count() != 2)
                        {
                            continue;
                        }
                        var e_pivot2target2 = pivot_outEdges.AssertSingle(e => e.Target != target1);
                        var target2         = e_pivot2target2.Target;

                        var @operator = e_pred2target1.Condition == PredicateType.IsTrue ? OperatorType.OrElse :
                                        e_pred2target1.Condition == PredicateType.IsFalse ? OperatorType.AndAlso :
                                        ((Func <OperatorType>)(() => { throw AssertionHelper.Fail(); }))();
                        var clause_left  = pred.Residue.AssertSingle();
                        var clause_right = pivot.Residue.AssertSingle();
                        var negate_rhs   = e_pred2target1.Condition != e_pivot2target1.Condition;
                        if (negate_rhs)
                        {
                            clause_right = Operator.Not(clause_right);
                        }
                        var junction = Operator.Create(@operator, clause_left, clause_right);

                        cfg.RemoveVertex(pivot);
                        cfg.AddEdge(new ControlFlowEdge(pred, target2, e_pred2target1.Condition.Negate()));
                        pred.Residue.SetElements(junction);
                        somethingWasChanged |= true;
                    }

                    if (!somethingWasChanged)
                    {
                        break;
                    }
                }

                parts = cfg.Cflow(vs, conv);
                (parts.Count() == 4).AssertTrue();
                var @const = parts.Except(vs, conv).AssertSingle(v => v.Residue.AssertSingle() is Const);
                var vnext  = parts.Except(vs, conv, @const).AssertSingle();
                (cfg.Vedge(@const, vnext) == null && cfg.Vedge(vnext, @const) == null).AssertTrue();
                cfg.Vedge(vs, vnext).IsConditional.AssertTrue();
                cfg.Vedge(vs, @const).IsConditional.AssertTrue();
                cfg.Vedge(vnext, conv).IsUnconditional.AssertTrue();
                cfg.Vedge(@const, conv).IsUnconditional.AssertTrue();

                var estart     = vs.Residue.AssertSingle();
                var enext      = vnext.Residue.AssertSingle();
                var cond_const = @const.Residue.AssertSingle().AssertCast <Const>().Value.AssertCast <int>();
                var cond_edge  = cfg.Vedge(vs, @const).Condition;
                var val_const  = cond_const == 1 ? true :
                                 cond_const == 0 ? false :
                                 ((Func <bool>)(() => { throw AssertionHelper.Fail(); }))();
                var val_edge = cond_edge == PredicateType.IsTrue ? true :
                               cond_edge == PredicateType.IsFalse ? false :
                               ((Func <bool>)(() => { throw AssertionHelper.Fail(); }))();

                var operator1     = val_const ? OperatorType.OrElse : OperatorType.AndAlso;
                var clause_left1  = val_edge && val_const ? estart : Operator.Not(estart);
                var clause_right1 = !val_edge && !val_const?Operator.Not(enext) : enext;

                var junction1 = Operator.Create(operator1, clause_left1, clause_right1);

                var conv_outEdges = cfg.Vedges(conv, null);
                var conv_inEdges  = cfg.Vedges(null, conv).Except(cfg.Vedges(parts, conv));
                cfg.RemoveVertices(@const, vnext, conv);
                conv_outEdges.ForEach(e => cfg.AddEdge(new ControlFlowEdge(vs, e.Target, e.Tag)));
                conv_inEdges.ForEach(e => cfg.AddEdge(new ControlFlowEdge(e.Source, vs, e.Tag)));

                vs.BalancedCode.Add(new Assign(ass.Lhs, junction1));
                vs.BalancedCode.AddElements(conv.BalancedCode.Skip(1));
                vs.Residue.SetElements(conv.Residue);
            }

            cfg.Edges().AssertEach(e => e.Tag.Arity() <= 1);
            cfg.Vertices.Where(v => v.Residue.IsNotEmpty()).AssertEach(v => v.Residue.Count() == 1);
            cfg.Vertices.AssertNone(v => v.Residue.IsNotEmpty() &&
                                    cfg.Vedges(v, null).Any(e => e.IsUnconditional && e.Target != cfg.Finish));
        }
示例#7
0
        public static String ResolveShellPathAsFileSystemPath(this String shellPath, ShellBrowser shellBrowser)
        {
            try
            {
                String resolved;
                if (Path.IsPathRooted(shellPath))
                {
                    resolved = shellPath;
                }
                else
                {
                    var parent = shellBrowser.CurrentDirectory;
                    parent.AssertNotNull();

                    Func <ShellItem, String> reallyRealPath = si =>
                    {
                        var realPath = ShellItem.GetRealPath(si);
                        Func <Func <String>, String> neverFail = f => { try { return(f()); } catch { return(null); } };
                        realPath = neverFail(() => Path.GetFullPath(realPath));

                        if (realPath == null)
                        {
                            var desktop = shellBrowser.ShellBrowserComponent.DesktopItem;
                            if (si == desktop)
                            {
                                realPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
                            }
                            else if (si.Text == shellBrowser.ShellBrowserComponent.MyComputerName)
                            {
                                realPath = Environment.GetFolderPath(Environment.SpecialFolder.MyComputer);
                            }
                            else
                            {
                                // todo. possibly map other bizarre folders
                                AssertionHelper.Fail();
                            }
                        }

                        realPath.AssertNotNull();
                        return(realPath);
                    };

                    // strategy 1. match children of current parent with the fpath
                    var match = parent.Cast <ShellItem>().SingleOrDefaultDontCrash(si => si.Text == shellPath);
                    if (match != null)
                    {
                        match.IsFileSystem.AssertTrue();
                        match.IsLink.AssertFalse();
                        resolved = reallyRealPath(match);
                    }
                    // strategy 2. resolve fpath as [parent's real path] + fpath
                    else
                    {
                        var parentResolved = reallyRealPath(parent);
                        resolved = Path.Combine(parentResolved, shellPath);
                    }
                }

                resolved.AssertNotNull();
                Path.IsPathRooted(resolved).AssertTrue();

                // canonicalize the path
                resolved = Path.GetFullPath(resolved);
                return(resolved);
            }
            catch (Exception)
            {
                // i know this is bad, but in this case user experience >> robustness
                return(null);
            }
        }
示例#8
0
        protected override void TraverseEval(Eval eval)
        {
            var m    = eval.InvokedMethod();
            var args = eval.InvocationArgsInfo();

            if (m.DeclaringType == typeof(Ctm) && m.Name == "Malloc")
            {
                throw AssertionHelper.Fail();
            }
            else if (m.DeclaringType.IsArray || m.DeclaringType == typeof(Array))
            {
                var @this = args.First().Item1;
                if (m.Name == "GetLength")
                {
                    var e_dim = args.Skip(1).AssertSingle().Item1;
                    var dim   = e_dim.AssertCast <Const>().Value.AssertCoerce <int>();
                    _ptx.ld(@this).arrdim(dim);
                }
                else if (m.IsArrayGetter())
                {
                    _ptx.ld(@this);
                    args.Skip(1).ForEach(idx => _ptx.ld(idx.Item1));
                    _ptx.arrget(m);
                }
                else if (m.IsArraySetter())
                {
                    _ptx.ld(@this);
                    args.Skip(1).ForEach(idx => _ptx.ld(idx.Item1));
                    _ptx.arrset(m);
                }
                else
                {
                    throw AssertionHelper.Fail();
                }
            }
            else
            {
                var a_ptx = m.AttrOrNull <PtxAttribute>();
                if (a_ptx == null)
                {
                    var p_m = m.EnclosingProperty();
                    if (p_m != null)
                    {
                        a_ptx = p_m.AttrOrNull <PtxAttribute>();
                    }
                }

                a_ptx.AssertNotNull();
                (a_ptx.Version <= _cfg.Version).AssertTrue();
                (a_ptx.Target <= _cfg.Target).AssertTrue();

                var s_code     = a_ptx.Code.Trim();
                var is_literal = !s_code.Contains(" ");
                is_literal.AssertEquiv(args.IsEmpty());

                if (is_literal)
                {
                    _ptx.op(s_code);
                }
                else
                {
                    var splits = s_code.Split(" ".MkArray(), StringSplitOptions.RemoveEmptyEntries);
                    splits.AssertThat(seq => seq.Count() >= 3);

                    var cop = splits.AssertFirst();
                    splits.AssertSecond().AssertThat(s => s == "%");
                    splits.Skip(2).ForEach(s_arg =>
                    {
                        if (!s_arg.StartsWith("%"))
                        {
                            _ptx.ld(s_arg);
                        }
                        else
                        {
                            var p_name = s_arg.AssertExtract("$%(?<name>.*)^");
                            var p      = m.GetParameters().AssertSingle(p1 => p1.Name == p_name);
                            _ptx.ld(args[p]);
                        }
                    });

                    _ptx.op(cop);
                }
            }
        }
示例#9
0
        private Expression Expand(Expression expr)
        {
            if (expr == null)
            {
                return(null);
            }
            else if (expr is Addr)
            {
                var addr   = (Addr)expr;
                var target = Expand(addr.Target);
                return(new Addr(target));
            }
            else if (expr is Assign)
            {
                var ass = (Assign)expr;

                var prop = ass.InvokedProp();
                if (prop != null)
                {
                    return(Expand(prop));
                }
                else
                {
                    var rhs = Expand(ass.Rhs);
                    var lhs = Expand(ass.Lhs);
                    return(new Assign(lhs, rhs));
                }
            }
            else if (expr is Operator)
            {
                var op = (Operator)expr;
                if (op.OperatorType.IsAssign())
                {
                    var prop = op.Children.AssertFirst().InvokedProp();
                    if (prop != null)
                    {
                        return(Expand(prop));
                    }
                    else
                    {
                        // todo. implement this with the use of SafeExpandOpAssign
                        var args = op.Args.Select(arg => Expand(arg));
                        return(Operator.Create(op.OperatorType, args));
                    }
                }
                else
                {
                    var args = op.Args.Select(arg => Expand(arg));
                    return(Operator.Create(op.OperatorType, args));
                }
            }
            else if (expr is Conditional)
            {
                var cond    = (Conditional)expr;
                var test    = Expand(cond.Test);
                var iftrue  = Expand(cond.IfTrue);
                var iffalse = Expand(cond.IfFalse);
                return(new Conditional(test, iftrue, iffalse));
            }
            else if (expr is Const)
            {
                // do nothing - nowhere to drill into
                return(expr);
            }
            else if (expr is Convert)
            {
                var cvt    = (Convert)expr;
                var source = Expand(cvt.Source);
                return(new Convert(cvt.Type, source));
            }
            else if (expr is Deref)
            {
                var deref  = (Deref)expr;
                var target = Expand(deref.Target);
                return(new Deref(target));
            }
            else if (expr is Fld)
            {
                var fld   = (Fld)expr;
                var @this = Expand(fld.This);
                return(new Fld(fld.Field, @this));
            }
            else if (expr is Prop)
            {
                // basic investigations
                var prop        = (Prop)expr;
                var is_instance = prop.Property.IsInstance();
                var parent      = prop.Parent;
                var app         = parent as Apply;
                var is_indexer  = app != null && app.Callee == prop;
                if (is_indexer)
                {
                    parent = parent.Parent;
                }

                // we have 5 different cases:
                // 1) foo.P;
                // 2) foo.P = bar;
                // 3) qux = (foo.P = bar);
                // 4) foo.P += bar;
                // 4') foo.P++;
                // 5) qux = (foo.P += bar);
                // 5') qux = (foo.P++);
                var ass           = parent as Assign;
                var is_assigned   = ass != null && (ass.Lhs == prop || ass.Lhs == app);
                var op            = parent as Operator;
                var is_opassigned = op != null && op.OperatorType.IsAssign();
                is_assigned |= is_opassigned;
                var is_rhs_reused = is_assigned && parent.Parent is Expression;

                if (!is_assigned)
                {
                    var impl         = prop.Property.GetGetMethod(true);
                    var this_args    = is_instance ? prop.This.MkArray() : Seq.Empty <Expression>();
                    var indexer_args = is_indexer ? app.Args : Seq.Empty <Expression>();
                    var args         = Seq.Concat(this_args, indexer_args).ToReadOnly();
                    var style        = prop.InvokedAsVirtual ? InvocationStyle.Virtual : InvocationStyle.NonVirtual;
                    return(Expand(new Eval(new Apply(new Lambda(impl, style), args))));
                }
                else
                {
                    // abstract away the root
                    // todo. implement this with the use of SafeExpandOpAssign
                    var root = prop.This;
                    if (is_opassigned && !root.IsLvalue())
                    {
                        var opassroot = DeclareLocal("$opassroot", prop.This.Type());
                        Emit(new Assign(opassroot, prop.This));
                        root = opassroot;
                    }

                    // abstract away the RHS
                    var rhs = null as Expression;
                    if (ass != null)
                    {
                        rhs = ass.Rhs;
                    }
                    if (is_opassigned)
                    {
                        if (op.IsUnary())
                        {
                            rhs = new Const(1);
                        }
                        else if (op.IsBinary())
                        {
                            rhs = op.Children.AssertSecond().AssertCast <Expression>();
                        }
                        else
                        {
                            throw AssertionHelper.Fail();
                        }
                    }

                    // abstract away the equivalence transform
                    Func <Expression> equiv = () =>
                    {
                        Func <Expression> equivGetter = () =>
                        {
                            var impl         = prop.Property.GetGetMethod(true);
                            var this_args    = is_instance ? root.MkArray() : Seq.Empty <Expression>();
                            var indexer_args = is_indexer ? app.Args : Seq.Empty <Expression>();
                            var args         = Seq.Concat(this_args, indexer_args).ToReadOnly();
                            var style        = prop.InvokedAsVirtual ? InvocationStyle.Virtual : InvocationStyle.NonVirtual;
                            return(new Eval(new Apply(new Lambda(impl, style), args)));
                        };

                        Func <Expression, Expression> equivSetter = assigned_value =>
                        {
                            var impl         = prop.Property.GetSetMethod(true);
                            var this_args    = is_instance ? root.MkArray() : Seq.Empty <Expression>();
                            var indexer_args = is_indexer ? app.Args : Seq.Empty <Expression>();
                            var args         = Seq.Concat(this_args, indexer_args, assigned_value.MkArray()).ToReadOnly();
                            var style        = prop.InvokedAsVirtual ? InvocationStyle.Virtual : InvocationStyle.NonVirtual;
                            return(new Eval(new Apply(new Lambda(impl, style), args)));
                        };

                        if (is_opassigned)
                        {
                            return(equivSetter(Operator.Create(op.OperatorType, equivGetter(), rhs)));
                        }
                        else
                        {
                            return(equivSetter(rhs));
                        }
                    };

                    // final transform
                    if (is_rhs_reused)
                    {
                        var cached_rhs = DeclareLocal("$opassrhs", rhs.Type());
                        Emit(new Assign(cached_rhs, rhs));
                        rhs = cached_rhs;
                        Emit(equiv());
                        return(cached_rhs);
                    }
                    else
                    {
                        return(Expand(equiv()));
                    }
                }
            }
            else if (expr is Ref)
            {
                var @ref = (Ref)expr;
                var env  = Env.GetOrDefault(@ref.Sym);
                return(Expand(env) ?? @ref);
            }
            else if (expr is SizeOf)
            {
                // do nothing - nowhere to drill into
                return(expr);
            }
            else if (expr is TypeAs)
            {
                var typeAs = (TypeAs)expr;
                var target = Expand(typeAs.Target);
                return(new TypeAs(typeAs.Type, target));
            }
            else if (expr is TypeIs)
            {
                var typeIs = (TypeIs)expr;
                var target = Expand(typeIs.Target);
                return(new TypeAs(typeIs.Type, target));
            }
            else if (expr is Default)
            {
                // do nothing - nowhere to drill into
                return(expr);
            }
            else if (expr is CollectionInit)
            {
                var ci = (CollectionInit)expr;
                if (ci.Elements.IsEmpty())
                {
                    return(Expand(ci.Ctor));
                }
                else
                {
                    var ctor_coll = ci.InvokedMethod().AssertThat(mb => mb.IsConstructor());
                    var t_coll    = ctor_coll.DeclaringType;

                    var l_coll = DeclareLocal("$", t_coll);
                    Emit(new Assign(l_coll, ci.Ctor));
                    ci.Elements.ForEach((el, i) =>
                    {
                        if (t_coll.IsArray)
                        {
                            (t_coll.GetArrayRank() == 1).AssertTrue();
                            var m_set = t_coll.ArraySetter().AssertNotNull();
                            Emit(new Eval(new Apply(new Lambda(m_set), l_coll, new Const(i), el)));
                        }
                        else
                        {
                            var m_add = t_coll.GetMethods(BF.All).AssertSingle(m => m.Name == "Add");
                            Emit(new Eval(new Apply(new Lambda(m_add), l_coll, el)));
                        }
                    });

                    return(l_coll);
                }
            }
            else if (expr is ObjectInit)
            {
                var oi = (ObjectInit)expr;
                if (oi.Members.IsEmpty())
                {
                    return(Expand(oi.Ctor));
                }
                else
                {
                    var ctor_obj = oi.InvokedMethod().AssertThat(mb => mb.IsConstructor());
                    var t_obj    = ctor_obj.DeclaringType;

                    var l_obj = DeclareLocal("$", t_obj);
                    Emit(new Assign(l_obj, oi.Ctor));
                    foreach (var mi in oi.Members)
                    {
                        if (mi is FieldInfo)
                        {
                            var fi = mi as FieldInfo;
                            Emit(new Assign(new Fld(fi, l_obj), oi.MemberInits[mi]));
                        }
                        else if (mi is PropertyInfo)
                        {
                            var pi = mi as PropertyInfo;
                            // todo. what about virtuality?!
                            Emit(new Assign(new Prop(pi, l_obj), oi.MemberInits[mi]));
                        }
                        else
                        {
                            throw AssertionHelper.Fail();
                        }
                    }

                    return(l_obj);
                }
            }
            else if (expr is Eval)
            {
                var eval      = (Eval)expr;
                var lam       = eval.InvokedLambda();
                var m         = eval.InvokedMethod();
                var child_ctx = Ctx.SpinOff(m);

                var status = Codebase.Classify(m);
                (status != MethodStatus.MustNotBeExecutedOnDevice).AssertTrue();
                var is_redirected = status == MethodStatus.IsRedirected;
                if (is_redirected)
                {
                    var redir = Codebase.Redirect(eval);
                    if (redir == null)
                    {
                        return(null);
                    }
                    else
                    {
                        var m_redir = redir.InvokedMethod();
                        if (m_redir.HasBody())
                        {
                            var raw_body = m_redir.ParseBody().Where(op => !(op is CilNop)).ToReadOnly();
                            if (raw_body.Count() == 2)
                            {
                                var first  = raw_body.First() as CilNew;
                                var second = raw_body.Second() as CilThrow;

                                var tni_ctor = typeof(NotImplementedException).GetConstructor(Type.EmptyTypes);
                                if (first != null && first.Ctor == tni_ctor && second != null)
                                {
                                    throw AssertionHelper.Fail();
                                }
                            }
                        }

                        return(Expand(redir));
                    }
                }
                else
                {
                    var needsExpansion      = status == MethodStatus.CanBeExecutedOnDevice;
                    var doesntNeedExpansion = status == MethodStatus.HasSpecialSemantics;
                    (needsExpansion ^ doesntNeedExpansion).AssertTrue();
                    if (needsExpansion)
                    {
                        // todo. think about what we can do here
                        (lam.InvocationStyle == InvocationStyle.Virtual).AssertFalse();
                        m.DeclaringType.IsInterface.AssertFalse();
                    }

                    var md = m.Decompile();
                    needsExpansion.AssertImplies(m.HasBody());
                    var p_ret = Seq.Empty <ParameterInfo>();
                    var mi    = m as MethodInfo;
                    if (mi != null)
                    {
                        p_ret = mi.ReturnParameter.MkArray();
                    }
                    m.GetParameters().Concat(p_ret).ForEach(pi => pi.IsOptional.AssertFalse());

                    var args = eval.InvocationArgs();
                    var args_include_this = !lam.InvokedAsCtor && m.IsInstance();
                    var @params           = m.GetParameters().AsEnumerable();
                    var p_fakethis        = null as ParameterInfo;
                    if (args_include_this)
                    {
                        @params = p_fakethis.Concat(@params).ToReadOnly();
                    }

                    var l_args = @params.Zip(args, (p, actual_arg) =>
                    {
                        var p_sig  = p == null ? md.Sig.Params.First() : md.Sig.Params.AssertSingle(p1 => p1.Metadata == p);
                        var p_type = p_sig.Type;

                        Func <Expression, Expression> expand_arg = null;
                        expand_arg = arg =>
                        {
                            Func <Expression, String, Expression> default_expand1 = (e, postfix) =>
                            {
                                var prefix    = (m.IsConstructor() ? m.DeclaringType.Name : m.Name).ToLower();
                                var name      = p_sig.Name + (postfix == null ? null : ("_" + postfix.ToLower()));
                                var full_name = String.Format("${0}_{1}", prefix, name);

                                var l_stub = DeclareLocal(full_name, p_type);
                                Emit(new Assign(l_stub, Expand(arg)));
                                return(l_stub);
                            };
                            Func <Expression, Expression> default_expand = e => default_expand1(e, null);

                            if (doesntNeedExpansion)
                            {
                                if (p_type.IsArray && p.IsVarargs())
                                {
                                    var ctor = arg.InvokedCtor();
                                    if (ctor != null && ctor.DeclaringType.IsArray)
                                    {
                                        var arg_eval = arg as Eval;
                                        if (arg_eval != null)
                                        {
                                            var rank = ctor.DeclaringType.GetArrayRank();
                                            if (rank == 1)
                                            {
                                                var sole_arg = arg.InvocationArgs().AssertSingle() as Const;
                                                if (sole_arg != null &&
                                                    sole_arg.Value is int && (int)sole_arg.Value == 0)
                                                {
                                                    return(arg);
                                                }
                                            }
                                        }

                                        var arg_ci = arg as CollectionInit;
                                        if (arg_ci != null)
                                        {
                                            p_type.IsArray().AssertTrue();
                                            (p_type.GetArrayRank() == 1).AssertTrue();

                                            try
                                            {
                                                p_type  = p_type.GetElementType();
                                                var els = arg_ci.Elements.Select(expand_arg).ToReadOnly();
                                                return(new CollectionInit(arg_ci.Ctor, els));
                                            }
                                            finally
                                            {
                                                p_type = p_type.MakeArrayType();
                                            }
                                        }
                                    }
                                }

                                var needs_expansion = arg.Family().Any(c =>
                                                                       c is Eval || c is Apply || c is Lambda || c is Prop || c is CollectionInit || c is ObjectInit);
                                if (!needs_expansion)
                                {
                                    return(arg);
                                }
                                else
                                {
                                    // todo. the stuff below works incorrectly in general case
                                    // since it might disrupt evaluation order of parameters
                                    //
                                    // however for now I trade off introducing a potential bug
                                    // for the ease of debugging and looking at traces

                                    var old_stmtc = Stmts.Count();
                                    var expanded  = default_expand(arg).AssertCast <Ref>();
                                    var new_stmtc = Stmts.Count();
                                    (new_stmtc > old_stmtc).AssertTrue();

                                    // todo. fix possible semantic disruption at the next line
                                    if (new_stmtc - old_stmtc > 1)
                                    {
                                        return(expanded);
                                    }
                                    else
                                    {
                                        var ass = Stmts.Last().AssertCast <Assign>();
                                        ass.Lhs.Equiv(expanded).AssertTrue();
                                        Stmts.RemoveLast();
                                        RemoveLocal(expanded);
                                        return(ass.Rhs);
                                    }
                                }
                            }
                            else
                            {
                                var p_reads = md.Body.Family().OfType <Ref>().Where(r => r.Sym == p_sig.Sym).ToReadOnly();
                                var p_asses = md.Body.Family().OfType <Assign>().Select(ass =>
                                {
                                    var r_lhs    = ass.Lhs as Ref;
                                    var is_write = r_lhs != null && r_lhs.Sym == p_sig.Sym;
                                    return(is_write ? ass : null);
                                }).Where(ass => ass != null).ToReadOnly();
                                var p_byref = md.Body.Family().OfType <Apply>().Select(app =>
                                {
                                    var passes_byref = app.ArgsInfo.Zip((e, pi) =>
                                    {
                                        var e_ref    = e as Ref;
                                        var is_read  = e_ref != null && e_ref.Sym == p_sig.Sym;
                                        var is_byref = pi.Type.IsByRef;
                                        return(is_read && is_byref);
                                    }).Any();
                                    return(passes_byref ? app : null);
                                }).Where(app => app != null).ToReadOnly();
                                var p_writes = Seq.Concat(p_asses.Cast <Expression>(), p_byref.Cast <Expression>()).ToReadOnly();
                                var p_usages = Seq.Concat(p_reads.Cast <Expression>(), p_writes.Cast <Expression>()).ToReadOnly();

                                // todo. below we might disrupt evaluation order
                                // by totally inlining an arg expression if it has a single usage
                                // strictly speaking, before doing that
                                // we need perform additional checks that eval-order is preserved
                                //
                                // note. this semi-correct solution is introduced
                                // solely for the convenience of the back-end
                                // and for the convenience of reading the resulting traces

                                var passed_by_ref = p == null || p.PassedByRef();
                                if (passed_by_ref)
                                {
                                    var @ref = arg as Ref;
                                    if (@ref != null)
                                    {
                                        return(arg);
                                    }

                                    var fld = arg as Fld;
                                    if (fld != null)
                                    {
                                        fld.Field.IsInstance().AssertTrue();

                                        // todo. fix possible semantic disruption at the next line
                                        if (p_usages.Count() <= 1)
                                        {
                                            return(arg);
                                        }
                                        else
                                        {
                                            var root    = fld.This;
                                            var is_atom = root is Ref || root is Const;
                                            if (is_atom)
                                            {
                                                return(arg);
                                            }
                                            else
                                            {
                                                var root_expanded = default_expand1(root, "root");
                                                return(new Fld(fld.Field, root_expanded));
                                            }
                                        }
                                    }

                                    var eval1 = arg as Eval;
                                    if (eval1 != null)
                                    {
                                        var m1 = eval1.InvokedMethod();
                                        m1.IsArrayGetter().AssertTrue();
                                        var args1 = eval1.InvocationArgs();
                                        var lam1  = eval1.InvokedLambda();

                                        var r_ee = eval1.Expand(Ctx.SpinOff(m1));
                                        r_ee.Stmts.ForEach(Stmts.Add);
                                        var ee = r_ee.Result.AssertCast <Eval>().AssertNotNull();

                                        // todo. fix possible semantic disruption at the next line
                                        if (p_usages.Count() <= 1)
                                        {
                                            return(ee);
                                        }
                                        else
                                        {
                                            var root = ee.Callee.Callee;
                                            Func <Expression, bool> is_atom = e => e is Ref || e is Const;
                                            if (is_atom(root) && ee.Callee.Args.All(is_atom))
                                            {
                                                return(ee);
                                            }
                                            else
                                            {
                                                var root_expanded = default_expand1(root, "root");
                                                return(new Eval(new Apply(new Lambda(m1, lam1.InvocationStyle), root_expanded.Concat(args1))));
                                            }
                                        }
                                    }

                                    // arg isn't an lvalue, so it can't be passed by reference
                                    throw AssertionHelper.Fail();
                                }
                                else
                                {
                                    if (p_writes.IsEmpty())
                                    {
                                        // todo. fix possible semantic disruption at the next line
                                        if (p_usages.Count() <= 1)
                                        {
                                            return(arg);
                                        }
                                        else
                                        {
                                            var is_atom = arg is Ref || arg is Const;
                                            if (is_atom)
                                            {
                                                var is_value_type = p_type.IsValueType;
                                                var is_primitive  = p_type.IsPrimitive;
                                                var needs_copying = is_value_type && !is_primitive;
                                                return(needs_copying ? default_expand(arg) : arg);
                                            }
                                            else
                                            {
                                                return(default_expand(arg));
                                            }
                                        }
                                    }
                                    else
                                    {
                                        return(default_expand(arg));
                                    }
                                }
                            }
                        };

                        var preprocessed_arg = actual_arg.Transform((Ref @ref) =>
                        {
                            var env = Env.GetOrDefault(@ref.Sym);
                            return(env ?? @ref);
                        }).AssertCast <Expression>();
                        var expanded_arg = expand_arg(preprocessed_arg);
                        expanded_arg     = expanded_arg.Transform((Ref @ref) =>
                        {
                            var env = Env.GetOrDefault(@ref.Sym);
                            return(env ?? @ref);
                        }).AssertCast <Expression>();

                        if (needsExpansion)
                        {
                            child_ctx.Env.Add(p_sig.Sym, expanded_arg);
                        }
                        return(expanded_arg);
                    }).ToReadOnly();

                    if (needsExpansion)
                    {
                        var env_locals = lam.Body.LocalsRecursive().ToDictionary(l => l as Sym, l =>
                        {
                            var frames    = Stack.Reverse().Skip(1).Concat(m);
                            var qualifier = frames.Select(sf => sf.Name.ToLower()).StringJoin("_");
                            var full_name = String.Format("${0}_{1}", qualifier, l.Name);
                            return(DeclareLocal(full_name, l.Type) as Expression);
                        }).ToReadOnly();
                        child_ctx.Env.AddElements(env_locals);

                        Action <Block> import_locals = blk =>
                        {
                            foreach (var local in blk.Locals.ToArray())
                            {
                                var env_ref = env_locals.GetOrDefault(local) as Ref;
                                var env     = env_ref == null ? null : (Local)env_ref.Sym;
                                if (env != null)
                                {
                                    blk.Locals.Remove(local);
                                    blk.Locals.Add(env);
                                }
                                else
                                {
                                    Scope.Locals.Add(local);
                                }
                            }

                            // todo. also import locals from embedded blocks
                            // here we need to take inlined stuff into account
                        };

                        if (lam.InvokedAsCtor)
                        {
                            var l_this = DeclareLocal(String.Format("${0}_this", m.DeclaringType.Name.ToLower()), m.DeclaringType);
                            child_ctx.Env.Add(lam.Sig.Syms[0], l_this);

                            var malloc      = typeof(Ctm).GetMethod("Malloc", new [] { typeof(Type) }).AssertNotNull();
                            var malloc_type = new Const(m.DeclaringType);
                            Emit(new Assign(l_this, new Eval(new Apply(new Lambda(malloc), malloc_type))));

                            var body = lam.Body.Expand(child_ctx);
                            import_locals(body);

                            if (body.IsEmpty())
                            {
                                var last_stmt    = Stmts.Last() as Assign;
                                var last_invoked = last_stmt == null ? null : last_stmt.Rhs.InvokedMethod();
                                (last_invoked == malloc).AssertTrue();

                                RemoveLocal(l_this);
                                Stmts.RemoveLast();
                                return(last_stmt.Rhs);
                            }
                            else
                            {
                                body.ForEach(Stmts.Add);
                                return(l_this);
                            }
                        }
                        else if (m.Ret() == typeof(void))
                        {
                            var body = lam.Body.Expand(child_ctx).AssertNotEmpty();
                            import_locals(body);

                            if (body.IsNotEmpty())
                            {
                                body.ForEach(Stmts.Add);
                            }
                            return(null);
                        }
                        else
                        {
                            (m.Ret().IsByRef || m.Ret().IsPointer).AssertFalse();

                            var name  = String.Format("${0}_ret", m.Name.ToLower());
                            var l_ret = DeclareLocal(name, m.Ret());
                            child_ctx.Ret = l_ret;

                            var body = lam.Body.Expand(child_ctx).AssertNotEmpty();
                            import_locals(body);

                            var body_last = body.LastOrDefault();
                            if (body_last is Label)
                            {
                                body.ForEach(Stmts.Add);
                                return(l_ret);
                            }
                            else
                            {
                                var ass = body.AssertLast().AssertCast <Assign>();
                                ass.Lhs.Equiv(l_ret).AssertTrue();

                                RemoveLocal(l_ret);
                                body.SkipLast(1).ForEach(Stmts.Add);
                                return(ass.Rhs);
                            }
                        }
                    }
                    else
                    {
                        return(new Eval(new Apply(lam, l_args.Cast <Expression>())));
                    }
                }
            }
            else
            {
                var app      = expr as Apply;
                var app_prop = app == null ? null : app.Callee as Prop;
                if (app_prop != null)
                {
                    return(Expand(app_prop));
                }

                // todo. also support indirect calls and partial applications
                // i.e. process cases when Apply/Lambda nodes ain't wrapped in an Eval
                throw AssertionHelper.Fail();
            }
        }
        private ReadOnlyCollection <Node> FixupEvaluationOrder(ReadOnlyCollection <Node> seq)
        {
            var q_evalOrders = new Dictionary <Node, ReadOnlyCollection <IILOp> >();

            seq.ForEach(q => q_evalOrders[q] = q.CSharpEvaluationOrder().Where(n => n != null)
                                               .Select(n => _map.GetOrDefault(n)).Where(op => op != null).ToReadOnly());
            var evalOrder = q_evalOrders.SelectMany(kvp => kvp.Value).ToReadOnly();

            var violatedDeps = new Dictionary <IILOp, ReadOnlyCollection <IILOp> >();

            evalOrder.ForEach((op, i_op) => violatedDeps.Add(op, evalOrder.Where(
                                                                 (oop, i_oop) => i_op > i_oop && op.Offset < oop.Offset).ToReadOnly()));
            violatedDeps.RemoveElements(kvp => kvp.Value.IsEmpty());

            if (violatedDeps.IsEmpty())
            {
                return(seq);
            }
            else
            {
                var fixt = seq.ToList();

                foreach (var op in violatedDeps.Keys)
                {
                    if (op is Call)
                    {
                        var call = op.AssertCast <Call>();
                        if (call.Method.IsGetter()) /* implemented */
                        {
                        }
                        else if (call.Method.IsSetter())
                        {
                            throw AssertionHelper.Fail();
                        }
                        else
                        {
                            throw AssertionHelper.Fail();
                        }
                    }
                    else if (op is New) /* presume that ctors are stateless */
                    {
                    }
                    else if (op is Ldloc) /* implemented */
                    {
                    }
                    else if (op is Ldarg) /* implemented */
                    {
                    }
                    else if (op is Ldelem)
                    {
                        throw AssertionHelper.Fail();
                    }
                    else if (op is Ldfld) /* implemented */
                    {
                    }
                    else if (op is Ldloca) /* implemented */
                    {
                    }
                    else if (op is Ldarga) /* implemented */
                    {
                    }
                    else if (op is Ldelema)
                    {
                        throw AssertionHelper.Fail();
                    }
                    else if (op is Ldflda) /* implemented */
                    {
                    }
                    else if (op is Ldind)
                    {
                        throw AssertionHelper.Fail();
                    }
                    else if (op is Ldftn)
                    {
                        throw AssertionHelper.Fail();
                    }
                    else if (op is Stloc)
                    {
                        throw AssertionHelper.Fail();
                    }
                    else if (op is Starg)
                    {
                        throw AssertionHelper.Fail();
                    }
                    else if (op is Stelem)
                    {
                        throw AssertionHelper.Fail();
                    }
                    else if (op is Stfld)
                    {
                        throw AssertionHelper.Fail();
                    }
                    else if (op is Stind)
                    {
                        throw AssertionHelper.Fail();
                    }
                    // ops that neither read nor write from anywhere except stack
                    // can be freely skipped so we have to consider only a dozen of ops
                    else
                    {
                        continue;
                    }

                    if (op is Ldloc || op is Ldloca)
                    {
                        var ldloc  = op as Ldloc;
                        var ldloca = op as Ldloca;
                        var loc_il = ldloc != null ? ldloc.Loc :
                                     ldloca != null ? ldloca.Loc : ((Func <ILocalVar>)(() => { throw AssertionHelper.Fail(); }))();

                        var violations = violatedDeps[op];
                        if (violations.OfType <Stloc>().Any(stloc => stloc.Index == loc_il.Index))
                        {
                            var loc_sym    = _symbols.ResolveLocal(loc_il.Index);
                            var expr_ldloc = _mapOp(op).AssertCast <Ref>();
                            (expr_ldloc.Sym == loc_sym).AssertTrue();

                            var locName = loc_il.Source.DebugInfo == null ? ("loc" + loc_il.Index) :
                                          !loc_il.Source.DebugInfo.LocalNames.ContainsKey(loc_il.Index) ? ("loc" + loc_il.Index) :
                                          loc_il.Source.DebugInfo.LocalNames[loc_il.Index];
                            var bufLocName = Seq.Nats.Select(i => locName + "__CF$" + i.ToString("0000")).First(name1 => _symbols.Locals.None(loc1 => loc1.Name == name1));
                            var bufLoc     = _symbols.IntroduceLocal(bufLocName, loc_il.Type);

                            var startOfViolations = q_evalOrders.Keys.First(q => Set.Intersect(q_evalOrders[q], violations).IsNotEmpty());
                            q_evalOrders[startOfViolations].Except(violations).AssertEmpty();
                            var insertionPoint = fixt.IndexOf(startOfViolations);
                            fixt.Insert(insertionPoint, new Assign(new Ref(bufLoc), new Ref(loc_sym)));
                            expr_ldloc.Parent.Children.ReplaceElements(expr_ldloc, new Ref(bufLoc));
                        }
                    }

                    if (op is Ldarg || op is Ldarga)
                    {
                        var ldarg  = op as Ldarg;
                        var ldarga = op as Ldarga;
                        var arg_il = ldarg != null ? ldarg.Arg :
                                     ldarga != null ? ldarga.Arg : ((Func <ParameterInfo>)(() => { throw AssertionHelper.Fail(); }))();
                        var arg_index = ldarg != null ? ldarg.Index :
                                        ldarga != null ? ldarga.Index : ((Func <int>)(() => { throw AssertionHelper.Fail(); }))();

                        var violations = violatedDeps[op];
                        if (violations.OfType <Starg>().Any(starg => starg.Index == arg_index))
                        {
                            var arg_sym    = _symbols.ResolveParam(arg_index);
                            var expr_ldarg = _mapOp(op).AssertCast <Ref>();
                            (expr_ldarg.Sym == arg_sym).AssertTrue();

                            var argName    = arg_sym.Name;
                            var bufLocName = Seq.Nats.Select(i => argName + "__CF$" + i.ToString("0000")).First(name1 => _symbols.Locals.None(loc => loc.Name == name1));
                            var bufLoc     = _symbols.IntroduceLocal(bufLocName, null);

                            var startOfViolations = q_evalOrders.Keys.First(q => Set.Intersect(q_evalOrders[q], violations).IsNotEmpty());
                            q_evalOrders[startOfViolations].Except(violations).AssertEmpty();
                            var insertionPoint = fixt.IndexOf(startOfViolations);
                            fixt.Insert(insertionPoint, new Assign(new Ref(bufLoc), new Ref(arg_sym)));
                            expr_ldarg.Children.ReplaceElements(expr_ldarg, new Ref(bufLoc));
                        }
                    }

                    if (op is Ldfld || op is Ldflda)
                    {
                        var ldfld  = op as Ldfld;
                        var ldflda = op as Ldflda;
                        var fld    = ldfld != null ? ldfld.Field :
                                     ldflda != null ? ldflda.Field : ((Func <FieldInfo>)(() => { throw AssertionHelper.Fail(); }))();

                        var violations = violatedDeps[op];
                        if (violations.OfType <Stfld>().Any(stfld => stfld.Field == fld &&
                                                            ((Func <bool>)(() =>
                        {
                            var stfld_fld = _mapOp(stfld).AssertCast <Assign>().Lhs.AssertCast <Fld>();
                            var ldfld_fld = _mapOp(op).AssertCast <Fld>();
                            return(stfld_fld.This.Equiv(ldfld_fld.This));
                        }))()))
                        {
                            var expr_ldfld = _mapOp(op).AssertCast <Fld>();
                            (expr_ldfld.Field == fld).AssertTrue();

                            var fldName    = fld.Name;
                            var bufLocName = Seq.Nats.Select(i => fldName + "__CF$" + i.ToString("0000")).First(name1 => _symbols.Locals.None(loc => loc.Name == name1));
                            var bufLoc     = _symbols.IntroduceLocal(bufLocName, null);

                            var startOfViolations = q_evalOrders.Keys.First(q => Set.Intersect(q_evalOrders[q], violations).IsNotEmpty());
                            q_evalOrders[startOfViolations].Except(violations).AssertEmpty();
                            var insertionPoint = fixt.IndexOf(startOfViolations);
                            fixt.Insert(insertionPoint, new Assign(new Ref(bufLoc), new Fld(fld, expr_ldfld.This)));
                            expr_ldfld.Children.ReplaceElements(expr_ldfld, new Ref(bufLoc));
                        }
                    }

                    if (op is Call)
                    {
                        var callGet = op.AssertCast <Call>();
                        callGet.Method.IsGetter().AssertTrue();
                        var violations = violatedDeps[callGet];
                        if (violations.OfType <Call>().Any(callSet =>
                        {
                            if (!callSet.Method.IsSetter())
                            {
                                return(false);
                            }
                            if (!(callSet.Method.EnclosingProperty() == callGet.Method.EnclosingProperty()))
                            {
                                return(false);
                            }

                            // todo. verify that both calls reference the same property
                            // and have the same This (use Dump comparison and add a todo)
                            throw new NotImplementedException();
                        }))
                        {
                            var prop         = callGet.Method.EnclosingProperty().AssertNotNull();
                            var expr_callGet = _mapOp(callGet);
                            // todo. verify that it references the "prop" property

                            var rawName    = callGet.Method.Name;
                            var bufLocName = Seq.Nats.Select(i => rawName + "__CF$" + i.ToString("0000")).First(name1 => _symbols.Locals.None(loc => loc.Name == name1));
                            var bufLoc     = _symbols.IntroduceLocal(bufLocName, null);

                            var startOfViolations = q_evalOrders.Keys.First(q => Set.Intersect(q_evalOrders[q], violations).IsNotEmpty());
                            q_evalOrders[startOfViolations].Except(violations).AssertEmpty();
                            var insertionPoint = fixt.IndexOf(startOfViolations);
                            fixt.Insert(insertionPoint, ((Func <Expression>)(() =>
                            {
                                throw new NotImplementedException();
                            }))());
                            expr_callGet.Children.ReplaceElements(expr_callGet, new Ref(bufLoc));
                        }
                    }
                }

                return(fixt.ToReadOnly());
            }
        }
示例#11
0
        protected override void TraverseOperator(Operator op)
        {
            var lhs  = op.Args.FirstOrDefault();
            var rhs  = op.Args.SecondOrDefault();
            var targ = op.Args.FirstOrDefault();

            var opt = op.OperatorType;

            if (opt.IsAssign())
            {
                var equiv = op.UnsafeExpandOpAssign();
                _ptx.ld(equiv);
            }
            else if (opt == OperatorType.AndAlso)
            {
                var equiv = new Conditional(lhs, rhs, new Const(false));
                _ptx.ld(equiv);
            }
            else if (opt == OperatorType.OrElse)
            {
                var equiv = new Conditional(lhs, new Const(true), rhs);
                _ptx.ld(equiv);
            }
            else
            {
                op.Args.ForEach(arg => _ptx.ld(arg));

                switch (opt)
                {
                case OperatorType.Add:
                    _ptx.op("add");
                    break;

                case OperatorType.And:
                    _ptx.op("and");
                    break;

                case OperatorType.Divide:
                    _ptx.op("div");
                    break;

                case OperatorType.Equal:
                    _ptx.op("setp.eq");
                    break;

                case OperatorType.GreaterThan:
                    _ptx.op("setp.gt");
                    break;

                case OperatorType.GreaterThanOrEqual:
                    _ptx.op("setp.ge");
                    break;

                case OperatorType.LeftShift:
                    _ptx.op("shl");
                    break;

                case OperatorType.LessThan:
                    _ptx.op("setp.lt");
                    break;

                case OperatorType.LessThanOrEqual:
                    _ptx.op("setp.le");
                    break;

                case OperatorType.Modulo:
                    _ptx.op("rem");
                    break;

                case OperatorType.Multiply:
                    var t = _ptx.peek_expr().Type;
                    _ptx.op(t.is_int() ? "mul.lo" : "mul");
                    break;

                case OperatorType.Negate:
                    _ptx.op("neg");
                    break;

                case OperatorType.Not:
                    _ptx.ld("not");
                    break;

                case OperatorType.NotEqual:
                    _ptx.op("setp.ne");
                    break;

                case OperatorType.Or:
                    _ptx.op("or");
                    break;

                case OperatorType.RightShift:
                    _ptx.op("shr");
                    break;

                case OperatorType.Subtract:
                    _ptx.op("sub");
                    break;

                case OperatorType.Xor:
                    _ptx.op("xor");
                    break;

                default:
                    throw AssertionHelper.Fail();
                }
            }
        }
示例#12
0
        internal String OperatorTypeToString(OperatorType?t)
        {
            if (t == null)
            {
                return(null);
            }

            switch (t.Value)
            {
            case OperatorType.Add:
                return("add");

            case OperatorType.And:
                return("and");

            case OperatorType.Divide:
                return("div");

            case OperatorType.Equal:
                return("eq");

            case OperatorType.GreaterThan:
                return("gt");

            case OperatorType.GreaterThanOrEqual:
                return("ge");

            case OperatorType.LeftShift:
                return("shl");

            case OperatorType.LessThan:
                return("lt");

            case OperatorType.LessThanOrEqual:
                return("le");

            case OperatorType.NotEqual:
                return("ne");

            case OperatorType.Modulo:
                return("rem");

            case OperatorType.Multiply:
                return("mul");

            case OperatorType.Negate:
                return("neg");

            case OperatorType.Not:
                return("not");

            case OperatorType.Or:
                return("or");

            case OperatorType.RightShift:
                return("shr");

            case OperatorType.Subtract:
                return("sub");

            case OperatorType.Xor:
                return("xor");

            default:
                throw AssertionHelper.Fail();
            }
        }
示例#13
0
 // this is a fake method required for Ldc to compile successfully
 internal String ReadToken(BinaryReader reader)
 {
     throw AssertionHelper.Fail();
 }
示例#14
0
        public Object Deserialize(MemberInfo descriptor)
        {
            var mi = descriptor ?? ((Func <MemberInfo>)(() => { throw AssertionHelper.Fail(); }))();
            var pi = mi as PropertyInfo;
            var t  = mi is Type ? (Type)mi : (mi is PropertyInfo ? ((PropertyInfo)mi).PropertyType : ((Func <Type>)(() => { throw AssertionHelper.Fail(); }))());

            var engine = pi.Config().Engine ?? t.Config().Engine ?? (Engine) new DefaultEngine();

            if (engine is TypeEngine && !(mi is Type))
            {
                mi = mi.Type();
            }
            var value = engine.Deserialize(mi, this);

            value = t.Config().Adapters.Fold(value, (curr, adapter) => adapter.AfterDeserialize(t, curr));
            value = pi.Config().Adapters.Fold(value, (curr, adapter) => adapter.AfterDeserialize(pi, curr));
            t.Config().Validators.ForEach(validator => validator.Validate(t, value));
            pi.Config().Validators.ForEach(validator => validator.Validate(pi, value));

            return(value);
        }
示例#15
0
        public void DoRewrite()
        {
            _status.InProgress.AssertTrue();

            using (_status)
            {
                Func <byte[]> m_ILStream  = () => _il.Get("m_ILStream").AssertCast <byte[]>();
                var           typeBuilder = _dest.Get("m_containingType").AssertCast <TypeBuilder>();
                var           module      = typeBuilder.Get("m_module").AssertCast <ModuleBuilder>();
                Func <int>    get_length  = () => _il.Get("m_length").AssertCast <int>();
                Action <int>  set_length  = v => _il.Set("m_length", v);

                // Stage 1: Write rewritten ops according to _logic
                // So far we don't care about branches being fix't up
                var rawIl_BeforeStage1 = _src.ParseBody().RawIL;
                TraceRawIl(rawIl_BeforeStage1, 0);

                foreach (var op in _body)
                {
                    _curr = op;
                    _logic(op, this);
                }

                // Stage 2: Replace short branches with regular ones
                // since fixups (see below) might overflow the 1-byte offset storage
                _rewrittenIL = m_ILStream().Take(get_length()).ToArray();
                TraceRawIl(_rewrittenIL, 1);
                set_length(0);

                var fixupUpdates          = new List <Action>();
                var branchExpansionPoints = new Dictionary <int, int>();
                foreach (var rop in _rewrittenIL.ParseRawIL(module))
                {
                    var rop1 = rop;
                    if (rop1 is Branch)
                    {
                        var br = rop1.AssertCast <Branch>();
                        if (rop1.OpSpec.OperandType == OperandType.ShortInlineBrTarget)
                        {
                            // rewrite short branch to normal form
                            var opcode_sig = rop1.OpSpec.OpCode.Value + 0x0d;
                            var allOpcodes = typeof(OpCodes).GetFields(BF.PublicStatic).Select(f => f.GetValue(null).AssertCast <OpCode>());
                            var opcode     = allOpcodes.Single(oc => oc.Value == opcode_sig);
                            _il.raw(opcode, BitConverter.GetBytes(br.RelativeTargetOffset));

                            // update fixup of the next operation
                            // fixup = translate from original offsets to after-stage-2 ones
                            var preImage = _off2op[RewrittenToNearestOrig(rop1.Offset)];
                            if (preImage.Next != null)
                            {
                                fixupUpdates.Add(() => _fixups[preImage.Next] += 3);
                            }

                            // update the map that memorizes BEPs in after-stage-1 coordinates
                            fixupUpdates.Add(() => branchExpansionPoints[rop1.Offset] = 3);

                            // also be careful to fixup _offsetsModeChangeLog => lazily!
                            // fixup = translate from after-stage-1 to after-stage-2 coordinates
                            foreach (var entry in _offsetsModeChangeLog)
                            {
                                (rop1.Offset < entry.Offset && entry.Offset < rop1.OffsetOfNextOp).AssertFalse();

                                var entry1 = entry;
                                var fixup  = rop1.Offset >= entry1.Offset ? 0 : 3;
                                fixupUpdates.Add(() => entry1.Offset += fixup);
                            }
                        }
                        else
                        {
                            _il.clone(rop1);
                        }
                    }
                    else
                    {
                        _il.clone(rop1);
                    }
                }

                // we defer updates so that they won't f**k up _fixups in process
                fixupUpdates.RunEach();

                // Stage 3: Fixup branches since their offsets are most likely invalid now
                // todo. also fixup switches and protected regions
                //
                // note. this works as follows:
                // 1) if an instruction was emitted during OffsetsMode.Original,
                //    i.e. (if EnterXXXMode wasn't called) during Clone
                //    it needs a fixup and uses the main fixup log, i.e. _fixups.
                // 2) if an instruction was emitted during OffsetsMode.Rewritten,
                //    i.e. (if EnterXXXMode wasn't called) during Clone
                //    it ain't need a fixup due to rewriting,
                //    but does need a fixup to compensate for short branches expansion (see above)
                //    and thusly uses the branchExpansionFixups log
                _rewrittenIL = m_ILStream().Take(get_length()).ToArray();
                TraceRawIl(_rewrittenIL, 2);
                foreach (var rop in _rewrittenIL.ParseRawIL(module))
                {
                    // note #1.
                    // we can't use Target here since offsets are most likely broken at the moment
                    // at best it'll return null, and at worst it'll crash

                    // note #2.
                    // we can't use AbsoluteTargetOffset either since it positions at after-stage-2 IL
                    // but not to before-stage-1 IL (i.e. original)

                    // note #3.
                    // neither we can use RewrittenToOrig(rop.Offset)
                    // since, even if we're at OffsetsMode.Original, the rop might've been issued during r/w

                    if (rop is Branch)
                    {
                        var br    = rop.AssertCast <Branch>();
                        var pivot = br.OffsetOfNextOp;

                        Action <int> rewriteRelOffset = newRelOffset =>
                        {
                            var addrOfOperand = rop.OffsetOfOperand;
                            var fixedUp       = BitConverter.GetBytes(newRelOffset);
                            fixedUp.ForEach((b, i) => m_ILStream()[i + addrOfOperand] = b);
                        };

                        var mode = GetOffsetsMode(br.Offset);
                        // see section #1 of the above comment
                        if (mode == OffsetsMode.Original)
                        {
                            // note. important: original offsets mode here
                            // doesn't mean that the op processed has a corresponding preimage (see also n0te #3 above)
                            // it only means that the relative offset works in original mode

                            // step 1. find out orig_relOffset (note: trick here!)
                            var r_r_relOffset  = br.RelativeTargetOffset;
                            var nearestOrig    = _off2op[RewrittenToNearestOrig(br.Offset)];
                            var r_off2op       = _rewrittenIL.ParseRawIL(module).ToDictionary(op => op.Offset, op => op);
                            var r_nearestOrig  = r_off2op[OrigToRewritten(nearestOrig.Offset)];
                            var orig_relOffset = r_r_relOffset + (br.Offset - r_nearestOrig.Offset);

                            // step 2. restore the op that orig_relOffset references
                            var orig_pivot     = nearestOrig.OffsetOfNextOp;
                            var orig_absOffset = orig_pivot + orig_relOffset;

                            // step 3. find out the r_pivot (note: trick here!)
                            var r_pivot = br.OffsetOfNextOp;

                            // step 4. calculate the r_relOffset
                            var r_absOffset = OrigToRewritten(orig_absOffset);
                            var r_relOffset = r_absOffset - r_pivot;

                            rewriteRelOffset(r_relOffset);
                        }
                        // see section #2 of the above comment
                        else if (mode == OffsetsMode.Rewritten)
                        {
                            // we can't use relOffset here
                            // because the "where" condition will become really complex
                            // since we need to take into account both negative and positive rels
                            var absOffset = br.AbsoluteTargetOffset;
                            branchExpansionPoints
                            .Where(kvp => kvp.Key < br.AbsoluteTargetOffset)
                            .ForEach(kvp => absOffset += kvp.Value);

                            rewriteRelOffset(absOffset - pivot);
                        }
                        else
                        {
                            throw AssertionHelper.Fail();
                        }
                    }
                    else if (rop is Switch)
                    {
                        throw AssertionHelper.Fail();
                    }
                    else
                    {
                        // do nothing - this op ain't eligible for fixup
                    }
                }

                // Finalizing the operations
                // fill in the RewrittenOps
                _rewrittenIL = m_ILStream().Take(get_length()).ToArray();
                TraceRawIl(_rewrittenIL, 3);
                var opsAfterRewriting = _rewrittenIL.ParseRawIL(module).ToDictionary(op => op.Offset, op => op);
                foreach (var rop in _rewrittenOps.Keys.ToArray())
                {
                    var startOffset = OrigToRewritten(rop.Offset);
                    var endOffset   = rop.Next == null ? int.MaxValue : OrigToRewritten(rop.Next.Offset);
                    var imageOps    = opsAfterRewriting
                                      .Where(kvp2 => startOffset <= kvp2.Key && kvp2.Key < endOffset)
                                      .Select(kvp2 => kvp2.Value);

                    _rewrittenOps[rop] = imageOps.ToReadOnly();
                }
            }
        }
示例#16
0
        private MemoryAllocator()
        {
            // infer allocation hints for fields
            var fai       = new Dictionary <FieldInfo, MemoryTier>();
            var t_kernel  = CudaRuntime.Current.TKernel;
            var hierarchy = t_kernel.Hierarchy().TakeWhile(t =>
                                                           t.Assembly != typeof(Kernel <,>).Assembly && !t.Name.StartsWith("Kernel`"));
            var fields = hierarchy.SelectMany(t => t.GetFields(BF.AllInstance | BF.DeclOnly)).ToReadOnly();

            fields.ForEach(f => fai.Add(f, f.HasAttr <PrivateAttribute>() ? MemoryTier.Private :
                                        f.HasAttr <LocalAttribute>() ? MemoryTier.Shared :
                                        f.HasAttr <GlobalAttribute>() ? MemoryTier.Global :
                                        /* otherwise, default to mem_global */ MemoryTier.Global));
            // todo. we don't support non-global fields to be consistent with CPU runtime
            fai.AssertNone(kvp => kvp.Value != MemoryTier.Global);

            // infer allocation hints for locals
            var sai    = new Dictionary <Sym, MemoryTier>();
            var locals = _hir.LocalsRecursive();

            locals.ForEach(local => sai.Add(local, 0));

            var evals = _hir.Family().OfType <Eval>().ToReadOnly();

            foreach (var eval in evals)
            {
                var m = eval.InvokedMethod();
                var t = m == null ? null : m.DeclaringType;
                if (t != null && t.DeclaringType == typeof(Hints))
                {
                    // todo. support other hints as well
                    (t == typeof(Hints.SharingHint)).AssertTrue();
                    var mem = m == t.GetMethod("Private") ? MemoryTier.Private :
                              m == t.GetMethod("Local") ? MemoryTier.Shared :
                              // todo. we don't support global sharing for locals to be consistent with CPU runtime
                              m == t.GetMethod("Global") ? ((Func <MemoryTier>)(() => { throw AssertionHelper.Fail(); }))() :
                              ((Func <MemoryTier>)(() => { throw AssertionHelper.Fail(); }))();

                    var args = eval.Callee.Args.AsEnumerable();
                    args = args.Skip(1.AssertThat(_ => m.IsInstance()));
                    m.IsVarargs().AssertTrue();
                    args = args.AssertSingle().AssertCast <CollectionInit>().Elements;

                    foreach (var arg in args)
                    {
                        // todo. we don't support hints for fields to be consistent with CPU runtime
                        var @ref = arg.AssertCast <Ref>();
                        var sym  = @ref.Sym.AssertThat(s => s.IsLocal());
                        (sai[sym] == 0).AssertTrue();
                        sai[sym] = mem;
                    }
                }
            }

            // if no memory model has been explicitly specified for the local, we default to mem_private
            locals.Where(local => sai[local] == 0).ForEach(local => sai[local] = MemoryTier.Private);
            _allocs = new AllocationScheme(fai, sai);
        }
示例#17
0
        public static ILGenerator clone(this ILGenerator il, IILOp op)
        {
            // todo #1. also take into account that we need to update stacksize
            // todo #2. what is RecordTokenFixup()?

            // load some internals
            var methodBuilder = il.Get("m_methodBuilder").AssertCast <MethodBuilder>();
            var typeBuilder   = methodBuilder.Get("m_containingType").AssertCast <TypeBuilder>();
            var ilModule      = typeBuilder.Get("m_module").AssertCast <ModuleBuilder>();

            // if op has some prefixes, clone them first
            op.Prefixes.ForEach(prefix => il.clone(prefix));

            // hello, Shlemiel the Painter...
            var operand = op.BytesOfOperand.ToArray();

            // fixup metadata tokens
            // 1. if op doesn't have a module specified, we just crash
            // 2. if op references a module builder, we verify that ilgen references it too
            //    since as of .NET 3.5 you cannot resolve a token in module builder
            // 3. if op has a regular module, we proceed to fixup
            var opModule = op.Get("Module").AssertCast <Module>();

            opModule.AssertNotNull();

            if (opModule is ModuleBuilder)
            {
                (opModule == ilModule).AssertTrue();
            }
            else
            {
                int newToken;

                // prepare to process ldtokens
                var ldc        = op as Ldc;
                var ldc_value  = ldc == null ? null : ldc.Value;
                var ldc_member = null as MemberInfo;
                if (ldc_value != null)
                {
                    if (ldc_value is RuntimeTypeHandle)
                    {
                        var rth = (RuntimeTypeHandle)ldc_value;
                        ldc_member = Type.GetTypeFromHandle(rth);
                    }
                    else if (ldc_value is RuntimeMethodHandle)
                    {
                        var rmh = (RuntimeMethodHandle)ldc_value;
                        ldc_member = MethodBase.GetMethodFromHandle(rmh);
                    }
                    else if (ldc_value is RuntimeFieldHandle)
                    {
                        var rfh = (RuntimeFieldHandle)ldc_value;
                        ldc_member = FieldInfo.GetFieldFromHandle(rfh);
                    }
                }

                // process special case - ldtoken
                var operandType = op.OpSpec.OperandType;
                if (operandType == OperandType.InlineTok)
                {
                    ldc_member.AssertNotNull();
                    if (ldc_member is Type)
                    {
                        operandType = OperandType.InlineType;
                    }
                    else if (ldc_member is MethodBase)
                    {
                        operandType = OperandType.InlineMethod;
                    }
                    else if (ldc_member is FieldInfo)
                    {
                        operandType = OperandType.InlineField;
                    }
                    else
                    {
                        throw AssertionHelper.Fail();
                    }
                }

                // process all other cases
                switch (operandType)
                {
                case OperandType.InlineType:
                    var type = (ldc_member ?? op.GetOrDefault("Type") ?? op.GetOrDefault("Resolved")).AssertCast <Type>();
                    if (op.OpSpec.OpCode == OpCodes.Newarr)
                    {
                        type = type.GetElementType();
                    }
                    newToken = ilModule.GetTypeToken(type).Token;
                    operand  = BitConverter.GetBytes(newToken);
                    break;

                case OperandType.InlineField:
                    var field = (ldc_member ?? op.GetOrDefault("Field") ?? op.GetOrDefault("Resolved")).AssertCast <FieldInfo>();
                    newToken = ilModule.GetFieldToken(field).Token;
                    operand  = BitConverter.GetBytes(newToken);
                    break;

                case OperandType.InlineMethod:
                    // note 1. Module::GetMethodToken won't work here
                    // since it returns index of an entry in the MemberRef metadata table (0x0a)
                    // closed generic methods are stored a separate metadata table (MethodSpec, 0x2b)

                    var method         = (ldc_member ?? op.GetOrDefault("Method") ?? op.GetOrDefault("Ctor") ?? op.GetOrDefault("Resolved")).AssertCast <MethodBase>();
                    var getMethodToken = typeof(ILGenerator).GetMethod("GetMethodToken", BF.PrivateInstance);
                    newToken = (int)getMethodToken.Invoke(il, new Object[] { method, null, false });
                    operand  = BitConverter.GetBytes(newToken);
                    break;

                case OperandType.InlineString:
                    var @string = (op.GetOrDefault("Value") ?? op.GetOrDefault("Resolved")).AssertCast <String>();
                    newToken = ilModule.GetStringConstant(@string).Token;
                    operand  = BitConverter.GetBytes(newToken);
                    break;

                case OperandType.InlineSig:
                    // todo. implement this
                    throw AssertionHelper.Fail();

                case OperandType.InlineBrTarget:
                case OperandType.InlineI:
                case OperandType.InlineI8:
                case OperandType.InlineNone:
#pragma warning disable 612, 618
                case OperandType.InlinePhi:
#pragma warning restore 612, 618
                case OperandType.InlineR:
                case OperandType.InlineSwitch:
                case OperandType.InlineVar:
                case OperandType.ShortInlineBrTarget:
                case OperandType.ShortInlineI:
                case OperandType.ShortInlineR:
                case OperandType.ShortInlineVar:
                    // do nothing - operand ain't needs a fixup
                    break;

                default:
                    throw AssertionHelper.Fail();
                }
            }

            // write the op to the output stream
            return(il.raw(op.OpSpec.OpCode, operand));
        }
示例#18
0
        public override void BuildDialogControls(IVaultDialog dialog, IVaultDialogTab tab)
        {
            // File dialog emulation

            var shellBrowser = new ShellBrowser();

            shellBrowser.Dock              = DockStyle.Fill;
            shellBrowser.ListViewMode      = View.List;
            shellBrowser.Multiselect       = false;
            shellBrowser.ShowFolders       = true;
            shellBrowser.ShowFoldersButton = false;
            shellBrowser.browseSplitter.Panel2Collapsed = true; // hack!

            var lbFolderName = new Label {
                Text = Resources.Dialogs_BrowseForFolder_FolderNameLabel, Padding = new Padding(2, 7, 5, 3)
            };
            var tbFolderName = new TextBox()
            {
                Dock = DockStyle.Fill
            };
            var pn1 = new Panel()
            {
                Dock = DockStyle.Left
            };

            pn1.Controls.Add(lbFolderName);
            pn1.Width = 70;
            var pn2 = new Panel()
            {
                Dock = DockStyle.Fill, Padding = new Padding(5, 5, 2, 5)
            };

            pn2.Controls.Add(tbFolderName);

            var pnFolderName = new Panel()
            {
                Dock = DockStyle.Bottom
            };

            pnFolderName.Controls.Add(pn2);
            pnFolderName.Controls.Add(pn1);
            pnFolderName.Height = tbFolderName.Height + 10;
            var pnShellBrowser = new Panel()
            {
                Dock = DockStyle.Fill
            };

            pnShellBrowser.Controls.Add(shellBrowser);
            tab.TabPage.Controls.Add(pnShellBrowser);
            tab.TabPage.Controls.Add(pnFolderName);

            shellBrowser.HandleCreated += (o, e) =>
            {
                // loads startup dir from appdomain-wide history
                var startupDir = (String)AppDomain.CurrentDomain.GetData(this.GetType().FullName);
                if (!Directory.Exists(startupDir))
                {
                    startupDir = null;
                }
                startupDir = startupDir ?? shellBrowser.ShellBrowserComponent.MyDocumentsPath;
                shellBrowser.SelectPath(startupDir, false);

                // remember all changes of current directory
                Action storeCurrentDirInAppDomain = () =>
                {
                    var currentDir = ".".ResolveShellPathAsFileSystemPath(shellBrowser);
                    AppDomain.CurrentDomain.SetData(this.GetType().FullName, currentDir);
                };

                shellBrowser.FileView.SelectedIndexChanged += (o1, e1) => storeCurrentDirInAppDomain();
                shellBrowser.FolderView.AfterSelect        += (o1, e1) => storeCurrentDirInAppDomain();
            };

            Action refreshTextBox = () =>
            {
                var shellItem = shellBrowser.CurrentDirectory;
                tbFolderName.Text = shellItem == null ? String.Empty : ".";
            };

            shellBrowser.FileView.SelectedIndexChanged += (o, e) => refreshTextBox();
            shellBrowser.FolderView.AfterSelect        += (o, e) => refreshTextBox();

            // Ensuring consistent OK button availability

            Action refreshOkAvailability = () =>
            {
                var shellItem  = shellBrowser.CurrentDirectory; // hack
                var folderName = tbFolderName.Text;

                if (folderName == (shellItem == null ? String.Empty : shellItem.Text) ||
                    folderName == (shellItem == null ? String.Empty : shellItem.Path))
                {
                    // foldername in the text box corresponds to selected file/dir
                    dialog.OkButton.Enabled = shellItem != null && shellItem.IsFileSystem && shellItem.IsFolder && !shellItem.IsLink;
                }
                else
                {
                    dialog.OkButton.Enabled = folderName.IsNeitherNullNorEmpty();
                }
            };

            dialog.TabActivated      += (o, e) => refreshOkAvailability();
            tbFolderName.TextChanged += (o, e) => refreshOkAvailability();

            // Processing folder selection: via OK, via ENTER, or via double-click on a folder in the tree

            Action <String> processSelectFolder = path =>
            {
                var resolved = path.ResolveShellPathAsFileSystemPath(shellBrowser);
                if (resolved == null)
                {
                    MessageBox.Show(
                        Resources.Dialogs_BrowseForFolder_NotAFileSystemLocation_Message,
                        Resources.Dialogs_BrowseForFolder_NotAFileSystemLocation_Title,
                        MessageBoxButtons.OK,
                        MessageBoxIcon.Error);
                }
                else
                {
                    // the logic below only accepts full paths
                    Path.IsPathRooted(resolved).AssertTrue();

                    if (File.Exists(resolved))
                    {
                        MessageBox.Show(
                            Resources.Dialogs_BrowseForFolder_FileIsNotValidHere_Message,
                            Resources.Dialogs_BrowseForFolder_FileIsNotValidHere_Title,
                            MessageBoxButtons.OK,
                            MessageBoxIcon.Error);
                    }
                    else
                    {
                        // remember the selection
                        AppDomain.CurrentDomain.SetData(this.GetType().FullName, resolved);

                        if (dialog.Action == VaultAction.Create ||
                            dialog.Action == VaultAction.Export)
                        {
                            if (ApproveSavingToUri(resolved))
                            {
                                resolved.EnsureDirectoryExists();
                                var vault = OpenCore(resolved, true);

                                if (vault != null)
                                {
                                    dialog.EndDialog(vault);
                                }
                            }
                        }
                        else if (dialog.Action == VaultAction.Open ||
                                 dialog.Action == VaultAction.Import)
                        {
                            if (ApproveOpeningFromUri(resolved))
                            {
                                var vault = OpenCore(resolved, false);
                                if (vault != null)
                                {
                                    dialog.EndDialog(vault);
                                }
                            }
                        }
                        else
                        {
                            AssertionHelper.Fail();
                        }
                    }
                }
            };

            // disabled on purpose:
            // general guideline is having expand/collapse on double click
            // and even Windows' system browse for folder dialog respects this behaviour

//            shellBrowser.folderView.NodeMouseDoubleClick += (o, e) =>
//            {
//                refreshOkAvailability();
//                if (dialog.OkButton.Enabled)
//                {
//                    processSelectShellItem();
//                }
//            };

            dialog.OkButton.Click += (o, e) =>
            {
                if (dialog.ActiveTab == tab)
                {
                    processSelectFolder(tbFolderName.Text);
                }
            };

            tbFolderName.KeyDown += (o, e) =>
            {
                if (e.KeyCode == Keys.Enter && !e.Alt && !e.Shift && !e.Control)
                {
                    processSelectFolder(tbFolderName.Text);
                }
            };
        }
示例#19
0
 public override IEnumerable <String> GetDynamicMemberNames()
 {
     throw AssertionHelper.Fail();
 }
示例#20
0
        public static int Arity(this OperatorType opType)
        {
            switch (opType)
            {
            case OperatorType.Add:
                return(2);

            case OperatorType.And:
                return(2);

            case OperatorType.Divide:
                return(2);

            case OperatorType.Equal:
                return(2);

            case OperatorType.GreaterThan:
                return(2);

            case OperatorType.GreaterThanOrEqual:
                return(2);

            case OperatorType.LeftShift:
                return(2);

            case OperatorType.LessThan:
                return(2);

            case OperatorType.LessThanOrEqual:
                return(2);

            case OperatorType.NotEqual:
                return(2);

            case OperatorType.Modulo:
                return(2);

            case OperatorType.Multiply:
                return(2);

            case OperatorType.Negate:
                return(1);

            case OperatorType.Not:
                return(1);

            case OperatorType.Or:
                return(2);

            case OperatorType.RightShift:
                return(2);

            case OperatorType.Subtract:
                return(2);

            case OperatorType.Xor:
                return(2);

            default:
                throw AssertionHelper.Fail();
            }
        }
示例#21
0
        protected override void TraverseAssign(Assign ass)
        {
            if (ass.Parent is Expression)
            {
                throw new NotImplementedException();
            }
            else
            {
                if (ass.Lhs is Ref)
                {
                    var sym = ((Ref)ass.Lhs).Sym;
                    if (sym.IsLocal())
                    {
                        Traverse(ass.Rhs);
                        il.stloc(locals[(Local)sym]);
                    }
                    else if (sym.IsParam())
                    {
                        throw new NotImplementedException();
                    }
                    else
                    {
                        throw AssertionHelper.Fail();
                    }
                }
                else if (ass.Lhs is Fld)
                {
                    var fld = (Fld)ass.Lhs;
                    if (fld.This != null)
                    {
                        Traverse(fld.This);
                    }
                    Traverse(ass.Rhs);
                    il.stfld(fld.Field);
                }
                else
                {
                    var p = ass.InvokedProperty();
                    if (p != null)
                    {
                        var prop   = ass.InvokedProp();
                        var setter = prop.Property.GetSetMethod(true);
                        var @this  = prop.Property.IsInstance() ? prop.This.MkArray() : Seq.Empty <Expression>();
                        var args   = (ass.InvocationIndexers() ?? Seq.Empty <Expression>()).Concat(ass.Rhs);
                        var style  = prop.InvokedAsVirtual ? InvocationStyle.Virtual : InvocationStyle.NonVirtual;
                        var equiv  = new Eval(new Apply(new Lambda(setter, style), @this.Concat(args)));
                        Traverse(equiv);
                    }
                    else
                    {
                        // todo. we've really got to consider array-getter an lvalue
                        // currently I don't have time for that
                        // but this needs to be propagated through the entire code

                        var m = ass.Lhs.InvokedMethod();
                        if (m.IsArrayGetter())
                        {
                            var setter = m.DeclaringType.ArraySetter();
                            var args   = ass.Lhs.InvocationArgs().Concat(ass.Rhs);
                            var equiv  = new Eval(new Apply(new Lambda(setter), args));
                            Traverse(equiv);
                        }
                        else
                        {
                            throw AssertionHelper.Fail();
                        }
                    }
                }
            }
        }
示例#22
0
        public static String ToCSharpSymbol(this OperatorType opType)
        {
            switch (opType)
            {
            case OperatorType.Add:
                return("+");

            case OperatorType.And:
                return("&&");

            case OperatorType.Divide:
                return("/");

            case OperatorType.Equal:
                return("==");

            case OperatorType.GreaterThan:
                return(">");

            case OperatorType.GreaterThanOrEqual:
                return(">=");

            case OperatorType.LeftShift:
                return("<<");

            case OperatorType.LessThan:
                return("<");

            case OperatorType.LessThanOrEqual:
                return("<=");

            case OperatorType.NotEqual:
                return("!=");

            case OperatorType.Modulo:
                return("%");

            case OperatorType.Multiply:
                return("*");

            case OperatorType.Negate:
                return("-");

            case OperatorType.Not:
                return("!");

            case OperatorType.Or:
                return("||");

            case OperatorType.RightShift:
                return(">>");

            case OperatorType.Subtract:
                return("-");

            case OperatorType.Xor:
                return("^");

            default:
                throw AssertionHelper.Fail();
            }
        }
示例#23
0
        private static ReadOnlyDictionary <String, String> ParseUrl(String url, String template)
        {
            var buffer = new StringBuilder();
            Func <char, bool> isSpecial = c => ".?+*{}^$[](){}\\".IndexOf(c) != -1;

            var state = 0;
            var name  = String.Empty;
            var keys  = new List <String>();

            for (var i = 0; i < template.Length; ++i)
            {
                var curr = template[i];
                var next = i == template.Length - 1 ? '\0' : template[i + 1];

                if (state == 0)
                {
                    if (curr == '{' && next != '{')
                    {
                        name  = String.Empty;
                        state = 1;
                    }
                    else
                    {
                        if (isSpecial(curr))
                        {
                            buffer.Append("\\");
                        }
                        buffer.Append(curr);
                    }
                }
                else if (state == 1)
                {
                    if (curr == '}' && next != '}')
                    {
                        buffer.AppendFormat("(?<{0}>.*?)", name);
                        keys.Add(name);
                        state = 0;
                    }
                    else
                    {
                        if (isSpecial(curr))
                        {
                            name += "\\";
                        }
                        name += curr;
                    }
                }
                else
                {
                    throw AssertionHelper.Fail();
                }
            }

            (state == 0).AssertTrue();
            var regex = String.Format("^{0}$", buffer);

            if (url == null)
            {
                return(null);
            }
            var match = Regex.Match(url, regex, RegexOptions.Singleline | RegexOptions.IgnoreCase);

            if (match.Success)
            {
                return(keys.ToDictionary(key => key, key => match.Result("${" + key + "}")).ToReadOnly());
            }
            else
            {
                return(null);
            }
        }
示例#24
0
 /// <summary>
 /// Signals an unconditional assertion failure with a particular message.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Use <see cref="AssertionHelper.Verify" /> and <see cref="AssertionHelper.Fail" />
 /// instead when implementing custom assertions.
 /// </para>
 /// </remarks>
 /// <param name="messageFormat">The format of the assertion failure message.</param>
 /// <param name="messageArgs">The arguments for the assertion failure message format string.</param>
 /// <exception cref="AssertionException">Thrown unless the current <see cref="AssertionContext.AssertionFailureBehavior" /> indicates otherwise.</exception>
 public static void Fail(string messageFormat, params object[] messageArgs)
 {
     AssertionHelper.Fail(new AssertionFailureBuilder("An assertion failed.")
                          .SetMessage(messageFormat, messageArgs)
                          .ToAssertionFailure());
 }
示例#25
0
        private static void InferFromTag(OpCodeKb kb, String tag)
        {
            if (tag == "ovf")
            {
                var p = kb.EnsureProperty("FailsOnOverflow", typeof(bool));
                p.Getter = "true";
            }
            else if (tag == "un")
            {
                var p = kb.EnsureProperty("ExpectsUn", typeof(bool));
                p.Getter = "true";
            }
            else if (tag == "s")
            {
                // just ignore this
            }
            else if (tag == "virt")
            {
                var p = kb.EnsureProperty("IsVirtual", typeof(bool));
                p.Getter = "true";
            }
            else if (tag.StartsWith("expects.") || tag.StartsWith("yields."))
            {
                var p = kb.EnsureProperty(CapitalizeAfterPeriods(tag), typeof(bool));
                p.Getter = "true";
            }
            else if (tag.StartsWith("predicate."))
            {
                var p         = kb.EnsureProperty("PredicateType", typeof(PredicateType?));
                var predicate = PredicateFromPredicateSpec(tag);
                p.Getter = typeof(PredicateType).GetCSharpRef(ToCSharpOptions.ForCodegen) + "." + predicate;
            }
            else if (tag.StartsWith("operator."))
            {
                var p         = kb.EnsureProperty("OperatorType", typeof(OperatorType));
                var @operator = OperatorFromOperatorSpec(tag);
                p.Getter = typeof(OperatorType).GetCSharpRef(ToCSharpOptions.ForCodegen) + "." + @operator;
            }
            else if (tag.StartsWith("instantiates."))
            {
                var f_ctor = kb.Fields["_ctorToken"];
                var f_type = kb.Fields["_typeToken"];

                var what = tag.Substring("instantiates.".Length);
                if (what == "obj")
                {
                    f_ctor.Initializer = "ReadMetadataToken(reader)";
                }
                else if (what == "arr")
                {
                    f_type.Initializer = "ReadMetadataToken(reader)";
                }
                else
                {
                    AssertionHelper.Fail();
                }
            }
            else if (tag == "br" || tag == "leave")
            {
                // this will be processed elsewhere
            }
            else if (tag == String.Empty)
            {
                // empty string after dot in prefix ops
                kb.Tags.Remove(String.Empty);
                kb.Tags.Add(".");
            }
            else
            {
                // all this hassle is solely for Ldstr/Ldtoken instructions
                // since they need both type and const semantics

                var type   = TypeFromTypeSpec(tag);
                var @const = ValueFromConstSpec(tag);

                if (type != null)
                {
                    kb.Meta["Type"] = tag;

                    kb.Props.ContainsKey("Type").AssertFalse();
                    var p = kb.EnsureProperty("Type", typeof(Type));
                    if (tag != "token")
                    {
                        p.Getter = "typeof(" + type.GetCSharpRef(ToCSharpOptions.ForCodegen) + ")";
                    }
                    else
                    {
                        p.Getter = "_constValue.GetType()";
                    }
                }

                if (@const != null)
                {
                    var f_constValue    = kb.Fields["_constValue"];
                    var f_useConstValue = kb.Fields["_useConstValue"];

                    f_constValue.Initializer    = @const.ToInvariantString();
                    f_useConstValue.Initializer = "true";
                }

                if (@type == null && @const == null)
                {
                    // so that we never miss an instruction with an unknown part
                    AssertionHelper.Fail();
                }
            }
        }
示例#26
0
        public override int GetHashCode()
        {
            var state   = IsPrimitive ? 1 : IsArray ? 2 : IsObject ? 3 : IsComplex ? 4 : ((Func <int>)(() => { throw AssertionHelper.Fail(); }))();
            var ordered = (_complex ?? new OrderedDictionary <String, Json>()).OrderBy(kvp => IsArray ? (Object)int.Parse(kvp.Key) : kvp.Key);

            return(ordered.Fold(state, (curr, kvp) => curr ^ kvp.GetHashCode()));
        }
示例#27
0
 T ICloneable2.ShallowClone <T>()
 {
     throw AssertionHelper.Fail();
 }
示例#28
0
        private void CopyHtoD()
        {
            if (_type.IsCudaPrimitive())
            {
                if (_type.IsInteger())
                {
                    (_type == typeof(int) || _type == typeof(uint)).AssertTrue();
                    (Direction == ParameterDirection.In).AssertTrue();
                }
                else if (_type.IsFloatingPoint())
                {
                    (_type == typeof(float)).AssertTrue();
                    (Direction == ParameterDirection.In).AssertTrue();
                }
                else
                {
                    throw AssertionHelper.Fail();
                }
            }
            else if (_type.IsCudaVector())
            {
                (Direction == ParameterDirection.In).AssertTrue();
            }
            else
            {
                if (_type.IsValueType)
                {
                    (Direction == ParameterDirection.In).AssertTrue();
                }
                else if (_type.IsClass)
                {
                    if (_type.IsArray())
                    {
                        var array = _value.AssertCast <Array>();
                        var t_el  = _type.GetElementType();
                        t_el.IsValueType.AssertTrue();

                        // allocate memory in VRAM
                        var sizeOfAlloc = (uint)(array.Dims().Product() * Marshal.SizeOf(t_el));
                        _devicePtr = nvcuda.cuMemAlloc(sizeOfAlloc);

                        // copy data if necessary
                        if (Direction == ParameterDirection.In ||
                            Direction == ParameterDirection.InOut)
                        {
                            using (var rawmem = _value.Pin())
                            {
                                nvcuda.cuMemcpyHtoD(_devicePtr, rawmem, sizeOfAlloc);
                            }
                        }
                        else if (Direction == ParameterDirection.Out)
                        {
                            // do nothing
                        }
                        else
                        {
                            throw AssertionHelper.Fail();
                        }
                    }
                    else
                    {
                        throw AssertionHelper.Fail();
                    }
                }
            }
        }
示例#29
0
        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();
            }
        }
示例#30
0
        private static void DetectEnclaves(String s, out HashSet <int> strings, out HashSet <int> comments)
        {
            strings  = new HashSet <int>();
            comments = new HashSet <int>();

            const int normal = 0, squo = 1, dquo = 2, sline = 3, mline = 4;
            var       escape = false;
            var       state  = normal;

            for (var i = 0; i < s.Length; ++i)
            {
                var p = i == 0 ? '\0' : s[i - 1];
                var c = s[i];
                var n = i == s.Length - 1 ? '\0' : s[i + 1];

                if (state == normal)
                {
                    if (c == '\'')
                    {
                        state  = squo;
                        escape = false;
                        strings.Add(i);
                    }
                    else if (c == '\"')
                    {
                        state  = dquo;
                        escape = false;
                        strings.Add(i);
                    }
                    else if (c == '/' && n == '/')
                    {
                        state  = sline;
                        escape = false;
                        comments.Add(i);
                        i++;
                        comments.Add(i);
                    }
                    else if (c == '/' && n == '*')
                    {
                        state  = mline;
                        escape = false;
                        comments.Add(i);
                        i++;
                        comments.Add(i);
                    }
                    else
                    {
                        state = normal;
                    }
                }
                else if (state == squo)
                {
                    if (escape)
                    {
                        state  = squo;
                        escape = false;
                        strings.Add(i);
                    }
                    else
                    {
                        if (c == '\'')
                        {
                            state  = normal;
                            escape = false;
                            strings.Add(i);
                        }
                        else if (c == '\\')
                        {
                            state  = squo;
                            escape = true;
                            strings.Add(i);
                        }
                        else
                        {
                            state = squo;
                            strings.Add(i);
                        }
                    }
                }
                else if (state == dquo)
                {
                    if (escape)
                    {
                        state  = dquo;
                        escape = false;
                        strings.Add(i);
                    }
                    else
                    {
                        if (c == '\"')
                        {
                            state  = normal;
                            escape = false;
                            strings.Add(i);
                        }
                        else if (c == '\\')
                        {
                            state  = dquo;
                            escape = true;
                            strings.Add(i);
                        }
                        else
                        {
                            state = dquo;
                            strings.Add(i);
                        }
                    }
                }
                else if (state == sline)
                {
                    if (c == '\n')
                    {
                        state = normal;
                    }
                    else
                    {
                        state = sline;
                        comments.Add(i);
                    }
                }
                else if (state == mline)
                {
                    if (c == '*' && n == '/')
                    {
                        state  = normal;
                        escape = false;
                        comments.Add(i);
                        i++;
                        comments.Add(i);
                    }
                    else
                    {
                        state = mline;
                        comments.Add(i);
                    }
                }
                else
                {
                    throw AssertionHelper.Fail();
                }
            }
        }