示例#1
0
        private static Stack <StackUseDefinition> GetStackAfter(OpExpression opInfo)
        {
            var newStack = new Stack <StackUseDefinition>(
                opInfo.StackBefore ?? Enumerable.Empty <StackUseDefinition>());

            if (opInfo.InstructionPopCount == null)
            {
                newStack.Clear();
            }
            else
            {
                var popCount = opInfo.InstructionPopCount;

                //if (opInfo.IsHandlerStart)
                //    popCount--;

                for (var i = 0; i < popCount; i++)
                {
                    newStack.Pop();
                }
            }

            for (var i = 0; i < opInfo.PushCount; i++)
            {
                newStack.Push(
                    new StackUseDefinition
                {
                    Definitions = new List <Node> {
                        opInfo
                    }
                });
            }
            return(newStack);
        }
示例#2
0
        private string MakeWhereStr(OpExpression opExpression)
        {
            if (opExpression == null)
            {
                return("");
            }
            StringBuilder sb = new StringBuilder();

            switch ((int)opExpression.joinOp)
            {
            //叶子
            case 0:
                sb.Append(opExpression.Condition.key)
                .Append(GetOpStr((int)opExpression.Condition.op))
                .Append(ToSqlString(opExpression.Condition.value));
                break;

            case 1:
                sb.Append(" ( ").Append(MakeWhereStr(opExpression.Left)).Append(" And ").Append(MakeWhereStr(opExpression.Right)).Append(" ) ");
                break;

            case 2:
                sb.Append(" ( ").Append(MakeWhereStr(opExpression.Left)).Append(" Or ").Append(MakeWhereStr(opExpression.Right)).Append(" ) ");
                break;
            }
            return(sb.ToString());
        }
示例#3
0
        public JSExpression Translate(OpExpression node)
        {
            var arg  = node.Arguments.Single();
            var expr = ProcessInternal(arg);

            var argIsInt64 = arg.ResultType == context.SystemTypes.Int64 ||
                             arg.ResultType == context.SystemTypes.UInt64;

            if (node.Instruction.OpCode.Name == "conv.u8")
            {
                if (argIsInt64)
                {
                    return(expr);
                }
                else
                {
                    return(JSFactory.Call(JSFactory.Identifier("BLR", "conv_u8"), expr));
                }
            }

            if (node.Instruction.OpCode.Name == "conv.i8")
            {
                if (argIsInt64)
                {
                    return(expr);
                }
                else
                {
                    return(JSFactory.Call(JSFactory.Identifier("BLR", "conv_i8"), expr));
                }
            }

            if (argIsInt64)
            {
                if (node.Instruction.OpCode.Name == "conv.r.un")
                {
                    return(JSFactory.Call(JSFactory.Identifier("BLR", "to_number_unsigned"), expr));
                }
                else
                {
                    return(JSFactory.Call(JSFactory.Identifier("BLR", "to_number_signed"), expr));
                }
            }

            if (IsIntegerType(node.ResultType))
            {
                return(JSFactory.Truncate(expr));
            }
            else
            {
                return(expr);
            }
        }
        private static IEnumerable <span> GetExpressionSpans(Block block)
        {
            OpExpression start = null;

            OpExpression prev = null;

            foreach (var node in block.Ast)
            {
                var expr = node as OpExpression;

                if (expr == null || expr.PushCount > 1)
                {
                    start = null;
                }
                else if (expr.PushCount == 0)
                {
                    if (start != null && prev != null && start != expr)
                    {
                        yield return new span {
                                   from = start, to = expr
                        }
                    }
                    ;

                    start = null;
                }
                else if (expr.StackBefore.Count == 0)
                {
                    if (start != null && prev != null && start != prev)
                    {
                        yield return new span {
                                   from = start, to = prev
                        }
                    }
                    ;

                    start = expr;
                }

                prev = expr;
            }

            if (start != null && prev != null && start != prev)
            {
                yield return new span {
                           from = start, to = prev
                }
            }
            ;
        }
    }
}
        private void ProcessOp(OpExpression rootOp, OpExpression op)
        {
            rootOp.RequireFieldInitTypes = new List <Type>();

            var opc = op.Instruction.OpCode.Name;

            var i    = opc.IndexOf(".");
            var opc_ = i > 0 ? opc.Substring(0, i) : opc;


            switch (opc_)
            {
            case "call":
            case "callvirt":
                var mi = (MethodBase)op.Instruction.Data;

                if (mi.DeclaringType.IsInterface)
                {
                    rootOp.RequireFieldInitTypes.Add(mi.DeclaringType);
                }

                break;

            case "ldsfld":
            case "stsfld":
                rootOp.RequireFieldInitTypes.Add(((MemberInfo)op.Instruction.Data).DeclaringType);
                break;

            case "newobj":
                var t = ((MemberInfo)op.Instruction.Data).DeclaringType;

                while (t != null)
                {
                    rootOp.RequireFieldInitTypes.Add(t);
                    t = t.BaseType;
                }
                break;

            default:
                break;
            }

            foreach (var subop in op.Arguments.OfType <OpExpression>())
            {
                ProcessOp(rootOp, subop);
            }
        }
示例#6
0
        private IKVM.Reflection.Type InferBinaryArithmeticType(OpExpression op)
        {
            var int32s = new[] { types.Char, types.Sbyte, types.Int32, types.Byte, types.UInt32 };
            var int64s = new[] { types.Int64, types.UInt64 };

            var a = op.Arguments.First().ResultType;
            var b = op.Arguments.Last().ResultType;

            if (int32s.Contains(a))
            {
                a = types.Int32;
            }

            if (int32s.Contains(b))
            {
                b = types.Int32;
            }

            if (int64s.Contains(a))
            {
                a = types.Int64;
            }

            if (int64s.Contains(b))
            {
                b = types.Int64;
            }

            if (a == b)
            {
                return(a);
            }
            else if (op.Instruction.OpCode.Name.StartsWith("sh"))
            {
                return(a);
            }
            else
            {
                throw new NotSupportedException();
            }
        }
示例#7
0
        private static bool UpdateTargetStack(Stack <StackUseDefinition> newStack, OpExpression target)
        {
            var stackList = newStack.Reverse().ToList();

            var changed = false;

            if (target.StackBefore == null)
            {
                target.StackBefore = stackList
                                     .Select(
                    n => new StackUseDefinition
                {
                    Usage       = target,
                    Definitions = n.Definitions.ToList()
                })
                                     .ToList();

                changed = true;
            }
            else
            {
                // Merging stacks described in ECMA - 335, III.1.8.1.3

                for (var i = 0; i < stackList.Count; i++)
                {
                    var oldDef = target.StackBefore[i];
                    var newDef = stackList[i];

                    var beforeCount = oldDef.Definitions.Count;

                    oldDef.Definitions = oldDef.Definitions.Concat(newDef.Definitions).Distinct().ToList();

                    if (oldDef.Definitions.Count != beforeCount)
                    {
                        changed = true;
                    }
                }
            }
            return(changed);
        }
示例#8
0
        private static void UpdateTargets(Stack <OpExpression> processStack, OpExpression opInfo, Stack <StackUseDefinition> newStack)
        {
            foreach (var target in opInfo.Targets)
            {
                if (target.IsHandlerStart)
                {
                    newStack.Push(new StackUseDefinition {
                        Definitions = new List <Node> {
                            new ExceptionNode()
                        }
                    });
                }

                if (UpdateTargetStack(newStack, target))
                {
                    processStack.Push(target);
                }

                if (target.IsHandlerStart)
                {
                    newStack.Pop();
                }
            }
        }
        private List <OpExpression> CreateOpInfos(CilMethod method)
        {
            var ilOps    = new OpInstructionReader(method.MethodBody.GetILAsByteArray(), method.Resolver);
            var opInfos  = new List <OpExpression>();
            var prefixes = new List <OpInstruction>();

            foreach (var op in ilOps.Process())
            {
                if (op.OpCode.OpCodeType == OpCodeType.Prefix)
                {
                    prefixes.Add(op);
                    continue;
                }

                OpExpression opx;

                if (op.OpCode.Name.StartsWith("call"))
                {
                    opx = new CallNode(op, prefixes, GetPopCount(method, op), GetPushCount(method, op), context.LookupMethod((MethodBase)op.Data));
                }
                else if (op.OpCode.Name.StartsWith("ldftn"))
                {
                    opx = new LoadFunctionNode(op, prefixes, GetPopCount(method, op), GetPushCount(method, op), context.LookupMethod((MethodBase)op.Data));
                }
                else
                {
                    opx = new OpExpression(op, prefixes, GetPopCount(method, op), GetPushCount(method, op));
                }

                opInfos.Add(opx);

                prefixes = new List <OpInstruction>();
            }

            foreach (var pairs in opInfos.Zip(opInfos.Skip(1), (current, next) => new { current, next }))
            {
                pairs.current.Next = pairs.next;
            }

            foreach (var pairs in opInfos.Zip(opInfos.Skip(1), (prev, current) => new { current, prev }))
            {
                pairs.current.Prev = pairs.prev;
            }

            var body     = method.MethodBody;
            var handlers = body != null ? body.ExceptionHandlingClauses : new List <ExceptionHandlingClause>();

            // Create targets
            foreach (var opInfo in opInfos)
            {
                if (opInfo.Instruction.OpCode.Name == "switch")
                {
                    var i = opInfo.Instruction;
                    var switchEndPosition = 1 + i.Position + i.Size;
                    var target            = opInfos.First(p => p.Position == switchEndPosition);
                    opInfo.Targets.Add(target);

                    foreach (var targetOffset in (int[])i.Data)
                    {
                        var targetPosition = 1 + i.Position + i.Size + targetOffset;
                        target = opInfos.First(f2 => f2.Position == targetPosition);
                        opInfo.Targets.Add(target);
                    }
                }
                else if (opInfo.Instruction.OpCode.FlowControl == FlowControl.Branch)
                {
                    var position = GetTargetPosition(opInfo.Instruction);
                    opInfo.Targets = new List <OpExpression>
                    {
                        opInfos.First(i => i.Position == position)
                    };
                }
                else if (opInfo.Instruction.OpCode.FlowControl == FlowControl.Cond_Branch)
                {
                    var position = GetTargetPosition(opInfo.Instruction);
                    opInfo.Targets = new List <OpExpression>
                    {
                        opInfos.First(i => i.Position == position)
                    };

                    if (opInfo.Next != null)
                    {
                        opInfo.Targets.Add(opInfo.Next);
                    }
                }
                else if (opInfo.Instruction.OpCode.FlowControl == FlowControl.Throw)
                {
                    // nothing
                }
                else
                {
                    if (opInfo.Next != null)
                    {
                        opInfo.Targets.Add(opInfo.Next);
                    }
                }

                if (opInfo.Next != null)
                {
                    foreach (var handler in handlers.Where(t => t.TryOffset == opInfo.Next.Position))
                    {
                        if (handler.Flags != ExceptionHandlingClauseOptions.Clause &&
                            handler.Flags != ExceptionHandlingClauseOptions.Finally)
                        {
                            continue;
                        }

                        var handlerStart = opInfos.First(i => i.Position == handler.HandlerOffset);

                        opInfo.Targets.Add(handlerStart);
                    }
                }

                foreach (var target in opInfo.Targets)
                {
                    target.Targeting.Add(opInfo);
                }
            }

            foreach (var handler in handlers)
            {
                if (handler.Flags != ExceptionHandlingClauseOptions.Clause)
                {
                    continue;
                }

                var handlerStart = opInfos.First(i => i.Position == handler.HandlerOffset);
                handlerStart.IsHandlerStart = true;
            }
            return(opInfos);
        }
示例#10
0
        private IKVM.Reflection.Type InferType(CilMethod method, OpExpression op)
        {
            var opc = op.Instruction.OpCode.Name;

            var i    = opc.IndexOf(".");
            var opc_ = i > 0 ? opc.Substring(0, i) : opc;

            var methodBody = method.MethodBody;

            switch (opc_)
            {
            case "add":
            case "and":
                return(InferBinaryArithmeticType(op));

            case "box":
                return(types.Object);

            case "call":
            case "callvirt":
            {
                var mb = ((MethodBase)op.Instruction.Data);

                var mi = mb as MethodInfo;

                if (mi != null)
                {
                    return(mi.ReturnType);
                }

                return(null);
            }

            case "castclass":
                return((IKVM.Reflection.Type)op.Instruction.Data);

            case "ceq":
            case "cgt":
            case "clt":
                return(types.Boolean);    // err... should this be int?

            case "conv":
                var t =
                    opc == "conv.i1" ? types.Int32 :
                    opc == "conv.i2" ? types.Int32 :
                    opc == "conv.i4" ? types.Int32 :
                    opc == "conv.i8" ? types.Int64 :
                    opc == "conv.r4" ? types.Single :
                    opc == "conv.r8" ? types.Double :
                    opc == "conv.u1" ? types.UInt32 :
                    opc == "conv.u2" ? types.UInt32 :
                    opc == "conv.u4" ? types.UInt32 :
                    opc == "conv.u8" ? types.UInt64 :
                    opc == "conv.i" ? types.Int32 :
                    opc == "conv.u" ? types.Int32 :
                    opc == "conv.r.un" ? types.Single : null;

                return(t);

            case "div":
            case "div.un":
                return(InferBinaryArithmeticType(op));

            case "dup":
                return(op.Targeting.First().ResultType);

            case "endfinally":
                return(null);

            case "initobj":
                return((Type)op.Instruction.Data);

            case "isinst":
                return((Type)op.Instruction.Data);

            case "ldarg":
            {
                var id = "";
                if (op.Instruction.Data != null)
                {
                    id = op.Instruction.Data.ToString();
                }
                else
                {
                    id = opc.Replace(".s", ".").Replace(".", "").Substring("ldarg".Length);
                }

                var idx = int.Parse(id);

                if (false == method.ReflectionMethod.IsStatic)
                {
                    if (idx == 0)
                    {
                        if (method.ReflectionMethod.DeclaringType.IsValueType)
                        {
                            return(types.ManagedPointer.MakeGenericType(method.ReflectionMethod.DeclaringType));
                        }
                        else
                        {
                            return(method.ReflectionMethod.DeclaringType);
                        }
                    }
                    else
                    {
                        idx -= 1;
                    }
                }

                return(method.ReflectionMethod.GetParameters()[idx].ParameterType);
            }

            case "ldarga":
            {
                var idxStr = "";

                if (op.Instruction.Data != null)
                {
                    idxStr = op.Instruction.Data.ToString();
                }

                idxStr = opc.Replace(".s", ".").Replace(".", "").Substring("ldarga".Length) + idxStr;

                var idx = int.Parse(idxStr);

                if (method.ReflectionMethod.IsStatic == false)
                {
                    idx--;
                }

                var args = method.ReflectionMethod.GetParameters();
                var type = args[idx].ParameterType;
                return(types.ManagedPointer.MakeGenericType(type));
            }

            case "ldc":
                if (opc.StartsWith("ldc.i4"))
                {
                    return(types.Int32);
                }
                else if (opc.StartsWith("ldc.i8"))
                {
                    return(types.Int64);
                }
                else if (opc.StartsWith("ldc.r8"))
                {
                    return(types.Double);
                }
                else
                {
                    return(types.Single);
                }

            case "ldelem":
                switch (opc)
                {
                case "ldelem":
                    return((Type)op.Instruction.Data);

                case "ldelem.ref":
                    return(op.Arguments.First().ResultType.GetElementType());

                //throw new NotImplementedException(); // array element type
                case "ldelem.i1":
                    return(types.Sbyte);

                case "ldelem.i2":
                    return(types.Int16);

                case "ldelem.i4":
                    return(types.Int32);

                case "ldelem.i8":
                    return(types.Int64);

                case "ldelem.u1":
                    return(types.Byte);

                case "ldelem.u2":
                    return(types.UInt16);

                case "ldelem.u4":
                    return(types.UInt32);

                case "ldelem.u8":
                    return(types.UInt64);

                case "ldelem.r4":
                    return(types.Single);

                case "ldelem.r8":
                    return(types.Double);

                case "ldelem.i":
                    return(types.Int32);

                default:
                    throw new NotSupportedException();
                }

            case "ldelema":
            {
                var type = (Type)op.Instruction.Data;
                return(types.ManagedPointer.MakeGenericType(type));
            }

            case "ldfld":
                return(((FieldInfo)op.Instruction.Data).FieldType);

            case "ldftn":
                return(types.IntPtr);

            case "ldlen":
                return(types.UInt32);

            case "ldloc":
            {
                var id = "";
                if (op.Instruction.Data != null)
                {
                    id = op.Instruction.Data.ToString();
                }
                id = opc.Substring(5).Replace(".s", ".").Replace(".", "") + id;

                return(methodBody.LocalVariables[int.Parse(id)].LocalType);
            }

            case "ldloca":
            {
                var id = "";
                if (op.Instruction.Data != null)
                {
                    id = op.Instruction.Data.ToString();
                }

                var idx = int.Parse(opc.Substring(5).Replace("a.", ".").Replace(".s", ".").Replace(".", "") + id);

                var type = methodBody.LocalVariables[idx].LocalType;
                return(types.ManagedPointer.MakeGenericType(type));
            }

            case "ldnull":
                return(types.Null);

            case "ldobj":
                return((Type)op.Instruction.Data);

            case "ldsfld":
                return(((FieldInfo)op.Instruction.Data).FieldType);

            case "ldflda":
            {
                var fieldType = ((FieldInfo)op.Instruction.Data).FieldType;
                return(types.ManagedPointer.MakeGenericType(fieldType));
            }

            case "ldstr":
                return(types.String);

            case "ldtoken":
                return(types.Object);    //universe.GetType("System.Reflection.MemberInfo");

            case "mul":
                return(InferBinaryArithmeticType(op));

            case "neg":
                return(op.Arguments.First().ResultType);

            case "newarr":
                return(((Type)op.Instruction.Data).MakeArrayType());

            case "newobj":
                return(((ConstructorInfo)op.Instruction.Data).DeclaringType);

            case "nop":
                return(null);

            case "or":
                return(InferBinaryArithmeticType(op));

            case "pop":
                return(null);

            case "rem":
            case "rem.un":
                return(InferBinaryArithmeticType(op));

            case "ret":
                return(null);

            case "shl":
            case "shr":
            case "shr.un":
                return(InferBinaryArithmeticType(op));

            case "stelem":
            case "stind":
            case "stloc":
            case "stfld":
            case "stsfld":
                return(null);

            case "sub":
                return(InferBinaryArithmeticType(op));

            case "throw":
                return(null);

            case "unbox":
                return((Type)op.Instruction.Data);

            default:
                return(null);
            }
        }
示例#11
0
        public JSExpression Translate(OpExpression node)
        {
            var opc = node.Instruction.OpCode.Name;

            var i    = opc.IndexOf(".");
            var opc_ = i > 0 ? opc.Substring(0, i) : opc;

            var isUnsigned = opc.Contains(".un");

            switch (opc_)
            {
            case "ceq":
                if (IsUInt64Operation(node) || IsInt64Operation(node))
                {
                    return(CreateXInt64BinaryOperation(node, "XInt64_Equality"));
                }
                else
                {
                    return(new JSConditionalExpression
                    {
                        Condition = new JSBinaryExpression
                        {
                            Left = ProcessInternal(node.Arguments.First()),
                            Right = ProcessInternal(node.Arguments.Last()),
                            Operator = "==="
                        },
                        TrueValue = new JSNumberLiteral {
                            Value = 1
                        },
                        FalseValue = new JSNumberLiteral {
                            Value = 0
                        }
                    });
                }

            case "cgt":
                if (opc == "cgt.un" && node.Arguments.Last().ResultType == context.SystemTypes.Null)
                {
                    // we should consider using Number(0) instead of 'null'

                    return(new JSConditionalExpression
                    {
                        Condition = new JSBinaryExpression
                        {
                            Left = ProcessInternal(node.Arguments.First()),
                            Right = ProcessInternal(node.Arguments.Last()),
                            Operator = "!=="
                        },
                        TrueValue = new JSNumberLiteral {
                            Value = 1
                        },
                        FalseValue = new JSNumberLiteral {
                            Value = 0
                        }
                    });
                }
                else
                {
                    if (IsUInt64Operation(node))
                    {
                        return(CreateXInt64BinaryOperation(node, "UInt64_GreaterThan"));
                    }
                    else if (IsInt64Operation(node))
                    {
                        return(CreateXInt64BinaryOperation(node, "Int64_GreaterThan"));
                    }
                    else
                    {
                        return(new JSConditionalExpression
                        {
                            Condition = new JSBinaryExpression
                            {
                                Left = WrapInUnsigned(isUnsigned, ProcessInternal(node.Arguments.First())),
                                Right = WrapInUnsigned(isUnsigned, ProcessInternal(node.Arguments.Last())),
                                Operator = ">"
                            },
                            TrueValue = new JSNumberLiteral {
                                Value = 1
                            },
                            FalseValue = new JSNumberLiteral {
                                Value = 0
                            }
                        });
                    }
                }

            case "clt":
                if (IsUInt64Operation(node))
                {
                    return(CreateXInt64BinaryOperation(node, "UInt64_LessThan"));
                }
                else if (IsInt64Operation(node))
                {
                    return(CreateXInt64BinaryOperation(node, "Int64_LessThan"));
                }
                else
                {
                    return(new JSConditionalExpression
                    {
                        Condition = new JSBinaryExpression
                        {
                            Left = WrapInUnsigned(isUnsigned, ProcessInternal(node.Arguments.First())),
                            Right = WrapInUnsigned(isUnsigned, ProcessInternal(node.Arguments.Last())),
                            Operator = "<"
                        },
                        TrueValue = new JSNumberLiteral {
                            Value = 1
                        },
                        FalseValue = new JSNumberLiteral {
                            Value = 0
                        }
                    });
                }

            default:
                throw new NotSupportedException(node.Instruction.OpCode.Name);
            }
        }
示例#12
0
 public bool Contains(OpExpression frame)
 {
     return(frame.Instruction.Position < To &&
            frame.Position >= From);
 }
示例#13
0
        private IEnumerable <Type> FindTypes(CilMethod method, OpExpression op)
        {
            if (method.ReflectionMethod == method.ReflectionMethod.DeclaringType.Assembly.EntryPoint)
            {
                yield return(context.SystemTypes.ValueType);
            }

            var opc = op.Instruction.OpCode.Name;

            var i    = opc.IndexOf(".");
            var opc_ = i > 0 ? opc.Substring(0, i) : opc;

            switch (opc_)
            {
            case "castclass":
            case "initobj":
            case "isinst":
            case "newarr":
            case "box":
                var d = (Type)op.Instruction.Data;
                yield return(d);

                break;

            case "call":
            case "callvirt":
                var mi = (MethodBase)op.Instruction.Data;
                if (mi.IsGenericMethod)
                {
                    foreach (var g in mi.GetGenericArguments())
                    {
                        yield return(g);
                    }
                }

                if (mi.DeclaringType.IsInterface)
                {
                    yield return(mi.DeclaringType);
                }

                break;

            case "ldtoken":
                var type = op.Instruction.Data as Type;
                if (type != null)
                {
                    yield return(type);
                }
                yield break;

            case "ldsfld":
            case "stsfld":
            case "newobj":
                yield return(((MemberInfo)op.Instruction.Data).DeclaringType);

                break;

            default:
                break;
            }
        }
示例#14
0
        public JSExpression Translate(OpExpression node)
        {
            var opc = node.Instruction.OpCode.Name;

            var i    = opc.IndexOf(".");
            var opc_ = i > 0 ? opc.Substring(0, i) : opc;

            switch (opc_)
            {
            case "add":
                if (node.ResultType == context.SystemTypes.UInt64 ||
                    node.ResultType == context.SystemTypes.Int64)
                {
                    return(JSFactory.Call(
                               JSFactory.Identifier("asm0", "XInt64_Addition"),
                               ProcessInternal(node.Arguments.First()),
                               ProcessInternal(node.Arguments.Last())));
                }
                else
                {
                    var expr = new JSBinaryExpression
                    {
                        Left     = ProcessInternal(node.Arguments.First()),
                        Right    = ProcessInternal(node.Arguments.Last()),
                        Operator = "+"
                    } as JSExpression;

                    if (IsIntegerType(node.ResultType))
                    {
                        expr = JSFactory.Truncate(expr);
                    }

                    return(expr);
                }

            case "and":
                if (node.ResultType == context.SystemTypes.UInt64 ||
                    node.ResultType == context.SystemTypes.Int64)
                {
                    return(JSFactory.Call(
                               JSFactory.Identifier("asm0", "XInt64_BitwiseAnd"),
                               ProcessInternal(node.Arguments.First()),
                               ProcessInternal(node.Arguments.Last())));
                }
                else
                {
                    return(new JSBinaryExpression
                    {
                        Left = ProcessInternal(node.Arguments.First()),
                        Right = ProcessInternal(node.Arguments.Last()),
                        Operator = "&"
                    });
                }

            case "div":
            case "div.un":
                if (IsUInt64Operation(node))
                {
                    return(CreateXInt64BinaryOperation(node, "UInt64_Division"));
                }
                else if (IsInt64Operation(node))
                {
                    return(CreateXInt64BinaryOperation(node, "Int64_Division"));
                }
                else
                {
                    var divExpression =
                        new JSBinaryExpression
                    {
                        Left     = ProcessInternal(node.Arguments.First()),
                        Right    = ProcessInternal(node.Arguments.Last()),
                        Operator = "/"
                    };
                    if (IsIntegerType(node.ResultType))
                    {
                        return(JSFactory.Truncate(divExpression));
                    }
                    else
                    {
                        return(divExpression);
                    }
                }

            case "mul":
                if (IsUInt64Operation(node) || IsInt64Operation(node))
                {
                    return(CreateXInt64BinaryOperation(node, "XInt64_Multiplication"));
                }
                else
                {
                    return(new JSBinaryExpression
                    {
                        Left = ProcessInternal(node.Arguments.First()),
                        Right = ProcessInternal(node.Arguments.Last()),
                        Operator = "*"
                    });
                }

            case "neg":
                if (node.ResultType == context.SystemTypes.Int64)
                {
                    return(JSFactory.Call(
                               JSFactory.Identifier("asm0", "Int64_UnaryNegation"),
                               ProcessInternal(node.Arguments.First())));
                }
                else
                {
                    return(new JSUnaryExpression
                    {
                        Operator = "-",
                        Operand = ProcessInternal(node.Arguments.Single())
                    });
                }

            case "not":
                if (node.ResultType == context.SystemTypes.Int64)
                {
                    return(JSFactory.Call(
                               JSFactory.Identifier("asm0", "XInt64_OnesComplement"),
                               ProcessInternal(node.Arguments.First())));
                }
                else
                {
                    return(new JSUnaryExpression
                    {
                        Operator = "~",
                        Operand = ProcessInternal(node.Arguments.Single())
                    });
                }

            case "or":
                if (IsUInt64Operation(node) || IsInt64Operation(node))
                {
                    return(CreateXInt64BinaryOperation(node, "XInt64_BitwiseOr"));
                }
                else
                {
                    return(new JSBinaryExpression
                    {
                        Left = ProcessInternal(node.Arguments.First()),
                        Right = ProcessInternal(node.Arguments.Last()),
                        Operator = "|"
                    });
                }

            case "rem":
            case "rem.un":
                if (IsUInt64Operation(node))
                {
                    return(CreateXInt64BinaryOperation(node, "UInt64_Modulus"));
                }
                else if (IsInt64Operation(node))
                {
                    return(CreateXInt64BinaryOperation(node, "Int64_Modulus"));
                }
                else
                {
                    return(new JSBinaryExpression
                    {
                        Left = ProcessInternal(node.Arguments.First()),
                        Right = ProcessInternal(node.Arguments.Last()),
                        Operator = "%"
                    });
                }

            case "shl":
                if (IsUInt64Operation(node) || IsInt64Operation(node))
                {
                    return(CreateXInt64BinaryOperation(node, "XInt64_LeftShift"));
                }
                else
                {
                    return(new JSBinaryExpression
                    {
                        Left = ProcessInternal(node.Arguments.First()),
                        Right = ProcessInternal(node.Arguments.Last()),
                        Operator = "<<"
                    });
                }

            case "shr":
                if (IsUInt64Operation(node))
                {
                    return(CreateXInt64BinaryOperation(node, "UInt64_RightShift"));
                }
                else if (IsInt64Operation(node))
                {
                    return(CreateXInt64BinaryOperation(node, "Int64_RightShift"));
                }
                else
                {
                    return(new JSBinaryExpression
                    {
                        Left = ProcessInternal(node.Arguments.First()),
                        Right = ProcessInternal(node.Arguments.Last()),
                        Operator = ">>"
                    });
                }

            case "shr.un":
                return(new JSBinaryExpression
                {
                    Left = ProcessInternal(node.Arguments.First()),
                    Right = ProcessInternal(node.Arguments.Last()),
                    Operator = ">>>"
                });

            case "sub":
                if (IsUInt64Operation(node) || IsInt64Operation(node))
                {
                    return(CreateXInt64BinaryOperation(node, "XInt64_Subtraction"));
                }
                else
                {
                    var expr = new JSBinaryExpression
                    {
                        Left     = ProcessInternal(node.Arguments.First()),
                        Right    = ProcessInternal(node.Arguments.Last()),
                        Operator = "-"
                    } as JSExpression;

                    if (IsIntegerType(node.ResultType))
                    {
                        expr = JSFactory.Truncate(expr);
                    }

                    return(expr);
                }

            case "xor":
                if (IsUInt64Operation(node) || IsInt64Operation(node))
                {
                    return(CreateXInt64BinaryOperation(node, "XInt64_ExclusiveOr"));
                }
                else
                {
                    var expr = new JSBinaryExpression
                    {
                        Left     = ProcessInternal(node.Arguments.First()),
                        Right    = ProcessInternal(node.Arguments.Last()),
                        Operator = "^"
                    } as JSExpression;

                    return(expr);
                }

            default:
                throw new NotSupportedException(node.Instruction.OpCode.Name);
            }
        }
 protected void MarkTargetForUpdate(OpExpression target)
 {
     processStack.Push(target);
 }
 protected virtual void Process(OpExpression opInfo)
 {
 }