Exemplo n.º 1
0
        private QurasCode _Convert1by1(Pure.VM.OpCode code, OpCode src, NeoMethod to, byte[] data = null)
        {
            QurasCode _code     = new QurasCode();
            int       startaddr = addr;

            _code.addr = addr;
            if (src != null)
            {
                addrconv[src.addr] = addr;
                _code.debugcode    = src.debugcode;
                _code.debugline    = src.debugline;
                _code.debugILAddr  = src.addr;
                _code.debugILCode  = src.code.ToString();
            }


            addr++;

            _code.code = code;

            if (data != null)
            {
                _code.bytes = data;
                addr       += _code.bytes.Length;
            }
            to.body_Codes[startaddr] = _code;
            return(_code);
        }
Exemplo n.º 2
0
        private int _ConvertNewObj(OpCode src, NeoMethod to)
        {
            var _type = (src.tokenUnknown as Mono.Cecil.MethodReference);

            if (_type.FullName == "System.Void System.Numerics.BigInteger::.ctor(System.Byte[])")
            {
                return(0);//donothing;
            }
            else if (_type.DeclaringType.FullName.Contains("Exception"))
            {
                _Convert1by1(Pure.VM.OpCode.NOP, src, to);//空白
                var pcount = _type.Parameters.Count;
                for (var i = 0; i < pcount; i++)
                {
                    _Insert1(Pure.VM.OpCode.DROP, "", to);
                }
                return(0);
            }
            var type = _type.Resolve();

            //如果构造函数上有一个[OpCode],替换New Array操作
            foreach (var m in type.DeclaringType.Methods)
            {
                if (m.IsConstructor && m.HasCustomAttributes)
                {
                    foreach (var attr in m.CustomAttributes)
                    {
                        if (attr.AttributeType.Name == "OpCodeAttribute")
                        {
                            //var _type = attr.ConstructorArguments[0].Type;
                            var            value = (byte)attr.ConstructorArguments[0].Value;
                            Pure.VM.OpCode v     = (Pure.VM.OpCode)value;
                            _Insert1(v, null, to);
                            return(0);
                        }
                    }
                }
            }
            _Convert1by1(Pure.VM.OpCode.NOP, src, to);               //空白
            _ConvertPush(type.DeclaringType.Fields.Count, null, to); //插入个数量
            if (type.DeclaringType.IsValueType)
            {
                _Insert1(Pure.VM.OpCode.NEWSTRUCT, null, to);
            }
            else
            {
                _Insert1(Pure.VM.OpCode.NEWARRAY, null, to);
            }
            return(0);
        }
Exemplo n.º 3
0
        private QurasCode _Insert1(Pure.VM.OpCode code, string comment, NeoMethod to, byte[] data = null)
        {
            QurasCode _code     = new QurasCode();
            int       startaddr = addr;

            _code.addr = addr;
            {
                _code.debugcode = comment;
                _code.debugline = 0;
            }

            addr++;

            _code.code = code;

            if (data != null)
            {
                _code.bytes = data;
                addr       += _code.bytes.Length;
            }
            to.body_Codes[startaddr] = _code;
            return(_code);
        }
        private int _ConvertCall(JavaMethod method, OpCode src, NeoMethod to)
        {
            _Convert1by1(Pure.VM.OpCode.NOP, src, to);
            var cc   = method.DeclaringType.classfile.constantpool;
            var c    = cc[src.arg1] as javaloader.ClassFile.ConstantPoolItemMethodref;
            var name = c.Class + "::" + c.Name;

            List <string> paramTypes = new List <string>();
            string        returntype;

            JavaMethod.scanTypes(c.Signature, out returntype, paramTypes);


            JavaClass  javaclass   = null;
            JavaMethod _javamethod = null;

            if (this.srcModule.classes.ContainsKey(c.Class))
            {
                javaclass = this.srcModule.classes[c.Class];
                if (javaclass.methods.ContainsKey(c.Name + c.Signature))
                {
                    _javamethod = javaclass.methods[c.Name + c.Signature];
                }
                else
                {
                    while (javaclass != null)
                    {
                        if (this.srcModule.classes.ContainsKey(javaclass.superClass))
                        {
                            javaclass = this.srcModule.classes[javaclass.superClass];
                            if (javaclass.methods.ContainsKey(c.Name + c.Signature))
                            {
                                _javamethod = javaclass.methods[c.Name + c.Signature];
                                break;
                            }
                        }
                        else
                        {
                            javaclass = null;
                        }
                    }
                }
            }
            int    calltype = 0;
            string callname = "";

            byte[]         callhash = null;
            Pure.VM.OpCode callcode = Pure.VM.OpCode.NOP;
            if (IsNonCall(_javamethod))
            {
                return(0);
            }
            else if (IsOpCall(_javamethod, src, out callname))
            {
                if (System.Enum.TryParse <Pure.VM.OpCode>(callname, out callcode))
                {
                    calltype = 2;
                }
                else
                {
                    throw new Exception("Can not find OpCall:" + callname);
                }
            }
            else if (IsSysCall(_javamethod, src, out callname))
            {
                calltype = 3;
            }
            else if (IsAppCall(_javamethod, src, out callhash))
            {
                calltype = 4;
            }
            else if (this.outModule.mapMethods.ContainsKey(c.Class + "::" + c.Name + c.Signature))
            {//this is a call
                calltype = 1;
            }
            else
            {
                if (name == "java.io.PrintStream::println")
                {//drop 1;
                    Console.WriteLine("logstr.");
                    _Convert1by1(Pure.VM.OpCode.DROP, src, to);
                    return(0);
                }
                else if (name == "java.math.BigInteger::<init>")
                {//do nothing
                    if (c.Signature == "([B)V")
                    {
                        return(0);
                    }
                    else if (c.Signature == "(Ljava/lang/String;)V")
                    {
                        throw new Exception("not support new BigInteger(string)");
                    }
                }
                else if (name == "java.math.BigInteger::add")
                {
                    _Convert1by1(Pure.VM.OpCode.ADD, src, to);
                    return(0);
                }
                else if (name == "java.math.BigInteger::subtract")
                {
                    _Convert1by1(Pure.VM.OpCode.SUB, src, to);
                    return(0);
                }
                else if (name == "java.math.BigInteger::multiply")
                {
                    _Convert1by1(Pure.VM.OpCode.MUL, src, to);
                    return(0);
                }
                else if (name == "java.math.BigInteger::divide")
                {
                    _Convert1by1(Pure.VM.OpCode.DIV, src, to);
                    return(0);
                }
                else if (name == "java.math.BigInteger::mod")
                {
                    _Convert1by1(Pure.VM.OpCode.MOD, src, to);
                    return(0);
                }
                else if (name == "java.math.BigInteger::compareTo")
                {
                    //need parse
                    _Convert1by1(Pure.VM.OpCode.SUB, src, to);
                    _Convert1by1(Pure.VM.OpCode.SIGN, null, to);
                    //_Convert1by1(Pure.VM.OpCode.DEC, src, to);
                    return(0);
                }
                // todo: what about java.lang.String::contentEquals?
                else if (name == "java.math.BigInteger::equals" ||
                         name == "java.lang.String::equals" ||
                         name == "kotlin.jvm.internal.Intrinsics::areEqual")
                {
                    _Convert1by1(Pure.VM.OpCode.NUMEQUAL, src, to);
                    //_Convert1by1(Pure.VM.OpCode.DEC, src, to);
                    return(0);
                }
                else if (name == "java.math.BigInteger::valueOf" ||
                         name == "java.math.BigInteger::intValue" ||
                         name == "java.lang.Boolean::valueOf" ||
                         name == "java.lang.Character::valueOf" ||
                         name == "java.lang.String::valueOf" ||
                         name == "java.lang.Long::valueOf" ||
                         name == "java.lang.Integer::valueOf" ||
                         name == "java.lang.Byte::valueOf" ||
                         name == "java.math.BigInteger::toByteArray")
                {
                    //donothing
                    return(0);
                }
                else if (name == "java.lang.Boolean::booleanValue" ||
                         name == "java.lang.Integer::integerValue" ||
                         name == "java.lang.Long::longValue" ||
                         name == "java.math.BigInteger::longValue")
                {
                    _Convert1by1(Pure.VM.OpCode.NOP, src, to);
                    return(0);
                }
                else if (name == "java.lang.String::hashCode")
                {
                    //java switch 的编译方式很奇怪
                    return(0);
                }
                else if (name == "java.lang.String::charAt")
                {
                    _ConvertPush(1, src, to);
                    _Convert1by1(Pure.VM.OpCode.SUBSTR, null, to);
                    return(0);
                }
                else if (name == "java.lang.String::length")
                {
                    _Convert1by1(Pure.VM.OpCode.SIZE, null, to);
                    return(0);
                }
                else if (c.Class == "java.lang.StringBuilder")
                {
                    return(_ConvertStringBuilder(c.Name, null, to));
                }
                else if (name == "java.util.Arrays::equals" ||
                         name == "kotlin.jvm.internal.Intrinsics::areEqual")
                {
                    _Convert1by1(Pure.VM.OpCode.EQUAL, null, to);
                    return(0);
                }
                else if (name == "kotlin.jvm.internal.Intrinsics::checkParameterIsNotNull")
                {
                    _Convert1by1(Pure.VM.OpCode.DROP, null, to);
                    _Convert1by1(Pure.VM.OpCode.DROP, null, to);
                    return(0);
                }
                else if (name == "kotlin.jvm.internal.Intrinsics::throwNpe")
                {
                    _Convert1by1(Pure.VM.OpCode.THROW, src, to);
                    return(0);
                }
            }

            if (calltype == 0)
            {
                throw new Exception("unknown call:" + name);
            }
            var pcount = paramTypes.Count;

            if (calltype == 2)
            {
                //opcode call
            }
            else
            {//翻转参数入栈顺序
                _Convert1by1(Pure.VM.OpCode.NOP, src, to);
                if (pcount <= 1)
                {
                }
                else if (pcount == 2)
                {
                    _Insert1(Pure.VM.OpCode.SWAP, "swap 2 param", to);
                }
                else if (pcount == 3)
                {
                    _InsertPush(2, "swap 0 and 2 param", to);
                    _Insert1(Pure.VM.OpCode.XSWAP, "", to);
                }
                else
                {
                    for (var i = 0; i < pcount / 2; i++)
                    {
                        int saveto = (pcount - 1 - i);
                        _InsertPush(saveto, "load" + saveto, to);
                        _Insert1(Pure.VM.OpCode.PICK, "", to);

                        _InsertPush(i + 1, "load" + i + 1, to);
                        _Insert1(Pure.VM.OpCode.PICK, "", to);


                        _InsertPush(saveto + 2, "save to" + saveto + 2, to);
                        _Insert1(Pure.VM.OpCode.XSWAP, "", to);
                        _Insert1(Pure.VM.OpCode.DROP, "", to);

                        _InsertPush(i + 1, "save to" + i + 1, to);
                        _Insert1(Pure.VM.OpCode.XSWAP, "", to);
                        _Insert1(Pure.VM.OpCode.DROP, "", to);
                    }
                }
            }
            if (calltype == 1)
            {
                var _c = _Convert1by1(Pure.VM.OpCode.CALL, null, to, new byte[] { 5, 0 });
                _c.needfixfunc = true;
                _c.srcfunc     = name + c.Signature;
                return(0);
            }
            else if (calltype == 2)
            {
                _Convert1by1(callcode, null, to);
                return(0);
            }
            else if (calltype == 3)
            {
                var bytes = Encoding.UTF8.GetBytes(callname);
                if (bytes.Length > 252)
                {
                    throw new Exception("string is too long");
                }
                byte[] outbytes = new byte[bytes.Length + 1];
                outbytes[0] = (byte)bytes.Length;
                Array.Copy(bytes, 0, outbytes, 1, bytes.Length);
                //bytes.Prepend 函数在 dotnet framework 4.6 编译不过
                _Convert1by1(Pure.VM.OpCode.SYSCALL, null, to, outbytes);
                return(0);
            }
            else if (calltype == 4)
            {
                _Convert1by1(Pure.VM.OpCode.APPCALL, null, to, callhash);
            }

            return(0);
        }
Exemplo n.º 5
0
        private int _ConvertCall(OpCode src, NeoMethod to)
        {
            Mono.Cecil.MethodReference refs = src.tokenUnknown as Mono.Cecil.MethodReference;

            int    calltype   = 0;
            string callname   = "";
            int    callpcount = 0;

            byte[]         callhash = null;
            Pure.VM.OpCode callcode = Pure.VM.OpCode.NOP;

            Mono.Cecil.MethodDefinition defs = null;
            try
            {
                defs = refs.Resolve();
            }
            catch
            {
            }

            if (IsNonCall(defs))
            {
                return(0);
            }
            else if (IsNotifyCall(defs, refs, to, out callname))
            {
                calltype = 5;
            }
            else if (to.lastparam >= 0)
            {
                callpcount   = to.lastparam;
                calltype     = 6;
                to.lastparam = -1;
            }
            else if (IsOpCall(defs, out callname))
            {
                if (System.Enum.TryParse <Pure.VM.OpCode>(callname, out callcode))
                {
                    calltype = 2;
                }
                else
                {
                    throw new Exception("Can not find OpCall:" + callname);
                }
            }
            else if (IsSysCall(defs, out callname))
            {
                calltype = 3;
            }
            else if (IsAppCall(defs, out callhash))
            {
                calltype = 4;
            }
            else if (this.outModule.mapMethods.ContainsKey(src.tokenMethod))
            {//this is a call
                calltype = 1;
            }
            else
            {//maybe a syscall // or other
                if (src.tokenMethod.Contains("::op_Explicit(") || src.tokenMethod.Contains("::op_Implicit("))
                {
                    //各类显示隐示转换都忽略
                    //有可能有一些会特殊处理,故还保留独立判断
                    if (src.tokenMethod == "System.Int32 System.Numerics.BigInteger::op_Explicit(System.Numerics.BigInteger)")
                    {
                        //donothing
                        return(0);
                    }
                    else if (src.tokenMethod == "System.Int64 System.Numerics.BigInteger::op_Explicit(System.Numerics.BigInteger)")
                    {
                        //donothing
                        return(0);
                    }
                    else if (src.tokenMethod == "System.Numerics.BigInteger System.Numerics.BigInteger::op_Implicit(System.Int32)")//int->bignumber
                    {
                        //donothing
                        return(0);
                    }
                    else if (src.tokenMethod == "System.Numerics.BigInteger System.Numerics.BigInteger::op_Implicit(System.Int64)")
                    {
                        return(0);
                    }

                    return(0);
                }
                else if (src.tokenMethod == "System.Void System.Diagnostics.Debugger::Break()")
                {
                    _Convert1by1(Pure.VM.OpCode.NOP, src, to);

                    return(0);
                }
                else if (src.tokenMethod.Contains("::op_Equality(") || src.tokenMethod.Contains("::Equals("))
                {
                    var _ref = src.tokenUnknown as Mono.Cecil.MethodReference;

                    if (_ref.DeclaringType.FullName == "System.Boolean" ||
                        _ref.DeclaringType.FullName == "System.Int32" ||
                        _ref.DeclaringType.FullName == "System.Numerics.BigInteger")
                    {
                        _Convert1by1(Pure.VM.OpCode.NUMEQUAL, src, to);
                    }
                    else
                    {
                        _Convert1by1(Pure.VM.OpCode.EQUAL, src, to);
                    }
                    //各类==指令
                    //有可能有一些会特殊处理,故还保留独立判断
                    //if (src.tokenMethod == "System.Boolean System.String::op_Equality(System.String,System.String)")
                    //{
                    //    _Convert1by1(Pure.VM.OpCode.EQUAL, src, to);
                    //    return 0;
                    //}
                    //else if (src.tokenMethod == "System.Boolean System.Object::Equals(System.Object)")
                    //{
                    //    _Convert1by1(Pure.VM.OpCode.EQUAL, src, to);
                    //    return 0;
                    //}
                    //_Convert1by1(Pure.VM.OpCode.EQUAL, src, to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::op_Inequality("))
                {
                    var _ref = src.tokenUnknown as Mono.Cecil.MethodReference;
                    if (_ref.DeclaringType.FullName == "System.Boolean" ||
                        _ref.DeclaringType.FullName == "System.Int32" ||
                        _ref.DeclaringType.FullName == "System.Numerics.BigInteger")
                    {
                        _Convert1by1(Pure.VM.OpCode.NUMNOTEQUAL, src, to);
                    }
                    else
                    {
                        _Convert1by1(Pure.VM.OpCode.INVERT, src, to);
                        _Insert1(Pure.VM.OpCode.EQUAL, "", to);
                    }
                    ////各类!=指令
                    ////有可能有一些会特殊处理,故还保留独立判断
                    //if (src.tokenMethod == "System.Boolean System.Numerics.BigInteger::op_Inequality(System.Numerics.BigInteger,System.Numerics.BigInteger)")
                    //{
                    //    _Convert1by1(Pure.VM.OpCode.INVERT, src, to);
                    //    _Insert1(Pure.VM.OpCode.EQUAL, "", to);
                    //    return 0;
                    //}
                    //_Convert1by1(Pure.VM.OpCode.INVERT, src, to);
                    //_Insert1(Pure.VM.OpCode.EQUAL, "", to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::op_Addition("))
                {
                    //各类+指令
                    //有可能有一些会特殊处理,故还保留独立判断
                    if (src.tokenMethod == "System.Numerics.BigInteger System.Numerics.BigInteger::op_Addition(System.Numerics.BigInteger,System.Numerics.BigInteger)")
                    {
                        _Convert1by1(Pure.VM.OpCode.ADD, src, to);
                        return(0);
                    }
                    _Convert1by1(Pure.VM.OpCode.ADD, src, to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::op_Subtraction("))
                {
                    //各类-指令
                    //有可能有一些会特殊处理,故还保留独立判断
                    if (src.tokenMethod == "System.Numerics.BigInteger System.Numerics.BigInteger::op_Subtraction(System.Numerics.BigInteger,System.Numerics.BigInteger)")
                    {
                        _Convert1by1(Pure.VM.OpCode.SUB, src, to);
                        return(0);
                    }
                    _Convert1by1(Pure.VM.OpCode.SUB, src, to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::op_Multiply("))
                {
                    //各类*指令
                    //有可能有一些会特殊处理,故还保留独立判断
                    if (src.tokenMethod == "System.Numerics.BigInteger System.Numerics.BigInteger::op_Multiply(System.Numerics.BigInteger,System.Numerics.BigInteger)")
                    {
                        _Convert1by1(Pure.VM.OpCode.MUL, src, to);
                        return(0);
                    }
                    _Convert1by1(Pure.VM.OpCode.MUL, src, to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::op_Division("))
                {
                    //各类/指令
                    //有可能有一些会特殊处理,故还保留独立判断
                    if (src.tokenMethod == "System.Numerics.BigInteger System.Numerics.BigInteger::op_Division(System.Numerics.BigInteger, System.Numerics.BigInteger)")
                    {
                        _Convert1by1(Pure.VM.OpCode.DIV, src, to);
                        return(0);
                    }
                    _Convert1by1(Pure.VM.OpCode.DIV, src, to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::op_Modulus("))
                {
                    //各类%指令
                    //有可能有一些会特殊处理,故还保留独立判断
                    if (src.tokenMethod == "System.Numerics.BigInteger System.Numerics.BigInteger::op_Modulus(System.Numerics.BigInteger,System.Numerics.BigInteger)")
                    {
                        _Convert1by1(Pure.VM.OpCode.MOD, src, to);
                        return(0);
                    }
                    _Convert1by1(Pure.VM.OpCode.MOD, src, to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::op_LessThan("))
                {
                    //各类<指令
                    //有可能有一些会特殊处理,故还保留独立判断
                    _Convert1by1(Pure.VM.OpCode.LT, src, to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::op_GreaterThan("))
                {
                    //各类>指令
                    //有可能有一些会特殊处理,故还保留独立判断
                    _Convert1by1(Pure.VM.OpCode.GT, src, to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::op_LessThanOrEqual("))
                {
                    //各类<=指令
                    //有可能有一些会特殊处理,故还保留独立判断
                    _Convert1by1(Pure.VM.OpCode.LTE, src, to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::op_GreaterThanOrEqual("))
                {
                    //各类>=指令
                    //有可能有一些会特殊处理,故还保留独立判断
                    _Convert1by1(Pure.VM.OpCode.GTE, src, to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::get_Length("))
                {
                    //各类.Length指令
                    //"System.Int32 System.String::get_Length()"
                    _Convert1by1(Pure.VM.OpCode.SIZE, src, to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::Concat("))
                {
                    //各类.Concat
                    //"System.String System.String::Concat(System.String,System.String)"
                    _Convert1by1(Pure.VM.OpCode.CAT, src, to);
                    return(0);
                }

                else if (src.tokenMethod == "System.String System.String::Substring(System.Int32,System.Int32)")
                {
                    _Convert1by1(Pure.VM.OpCode.SUBSTR, src, to);
                    return(0);
                }
                else if (src.tokenMethod == "System.Char System.String::get_Chars(System.Int32)")
                {
                    _ConvertPush(1, src, to);
                    _Convert1by1(Pure.VM.OpCode.SUBSTR, null, to);
                    return(0);
                }
                else if (src.tokenMethod == "System.String System.String::Substring(System.Int32)")
                {
                    throw new Exception("neomachine cant use this call,please use  .SubString(1,2) with 2 params.");
                }
                else if (src.tokenMethod == "System.String System.Char::ToString()")
                {
                    return(0);
                }
                else if (src.tokenMethod == "System.Byte[] System.Numerics.BigInteger::ToByteArray()")
                {
                    return(0);
                }
                else if (src.tokenMethod == "System.Void System.Numerics.BigInteger::.ctor(System.Byte[])")
                {
                    _Convert1by1(Pure.VM.OpCode.DUPFROMALTSTACK, src, to);
                    _ConvertPush(2, null, to);
                    _Convert1by1(Pure.VM.OpCode.ROLL, null, to);
                    _ConvertPush(2, null, to);
                    _Convert1by1(Pure.VM.OpCode.ROLL, null, to);
                    _Convert1by1(Pure.VM.OpCode.SETITEM, null, to);
                    return(0);
                }
                else if (src.tokenMethod == "System.UInt32 <PrivateImplementationDetails>::ComputeStringHash(System.String)")
                {
                    throw new Exception("not supported on neovm now.");
                    // 需要neo.vm nuget更新以后,这个才可以放开,就可以处理 string switch了。");

                    //_Convert1by1(Pure.VM.OpCode.CSHARPSTRHASH32, src, to);
                    //return 0;
                }
                else
                {
                }
            }

            if (calltype == 0)
            {
                //之前的所有尝试都无效,那也不一定是个不存在的函数,有可能在别的模块里
                if (TryInsertMethod(outModule, defs))
                {
                    calltype = 1;
                    //ILModule module = new ILModule();
                    //module.LoadModule
                    //ILType type =new ILType()
                    //ILMethod method = new ILMethod(defs)
                }
                else
                {
                    throw new Exception("unknown call: " + src.tokenMethod + "\r\n   in: " + to.name + "\r\n");
                }
            }
            var  md       = src.tokenUnknown as Mono.Cecil.MethodReference;
            var  pcount   = md.Parameters.Count;
            bool havethis = md.HasThis;

            if (calltype == 2)
            {
                //opcode call
            }
            else
            {//翻转参数顺序
                //如果是syscall 并且有this的,翻转范围加一
                if (calltype == 3 && havethis)
                {
                    pcount++;
                }

                _Convert1by1(Pure.VM.OpCode.NOP, src, to);
                if (pcount <= 1)
                {
                }
                else if (pcount == 2)
                {
                    _Insert1(Pure.VM.OpCode.SWAP, "swap 2 param", to);
                }
                else if (pcount == 3)
                {
                    _InsertPush(2, "swap 0 and 2 param", to);
                    _Insert1(Pure.VM.OpCode.XSWAP, "", to);
                }
                else
                {
                    for (var i = 0; i < pcount / 2; i++)
                    {
                        int saveto = (pcount - 1 - i);
                        _InsertPush(saveto, "load" + saveto, to);
                        _Insert1(Pure.VM.OpCode.PICK, "", to);

                        _InsertPush(i + 1, "load" + i + 1, to);
                        _Insert1(Pure.VM.OpCode.PICK, "", to);


                        _InsertPush(saveto + 2, "save to" + saveto + 2, to);
                        _Insert1(Pure.VM.OpCode.XSWAP, "", to);
                        _Insert1(Pure.VM.OpCode.DROP, "", to);

                        _InsertPush(i + 1, "save to" + i + 1, to);
                        _Insert1(Pure.VM.OpCode.XSWAP, "", to);
                        _Insert1(Pure.VM.OpCode.DROP, "", to);
                    }
                }
            }
            if (calltype == 1)
            {
                var c = _Convert1by1(Pure.VM.OpCode.CALL, null, to, new byte[] { 5, 0 });
                c.needfixfunc = true;
                c.srcfunc     = src.tokenMethod;
                return(0);
            }
            else if (calltype == 2)
            {
                _Convert1by1(callcode, src, to);
                return(0);
            }
            else if (calltype == 3)
            {
                var bytes = Encoding.UTF8.GetBytes(callname);
                if (bytes.Length > 252)
                {
                    throw new Exception("string is to long");
                }
                byte[] outbytes = new byte[bytes.Length + 1];
                outbytes[0] = (byte)bytes.Length;
                Array.Copy(bytes, 0, outbytes, 1, bytes.Length);
                //bytes.Prepend 函数在 dotnet framework 4.6 编译不过
                _Convert1by1(Pure.VM.OpCode.SYSCALL, null, to, outbytes);
                return(0);
            }
            else if (calltype == 4)
            {
                _Convert1by1(Pure.VM.OpCode.APPCALL, null, to, callhash);
            }
            else if (calltype == 5)
            {
                //把name参数推进去
                var callp = Encoding.UTF8.GetBytes(callname);
                _ConvertPush(callp, src, to);

                //参数打包成array
                _ConvertPush(pcount + 1, null, to);
                _Convert1by1(Pure.VM.OpCode.PACK, null, to);

                //a syscall
                {
                    var    bytes    = Encoding.UTF8.GetBytes("Module.Runtime.Notify");
                    byte[] outbytes = new byte[bytes.Length + 1];
                    outbytes[0] = (byte)bytes.Length;
                    Array.Copy(bytes, 0, outbytes, 1, bytes.Length);
                    //bytes.Prepend 函数在 dotnet framework 4.6 编译不过
                    _Convert1by1(Pure.VM.OpCode.SYSCALL, null, to, outbytes);
                }
            }
            else if (calltype == 6)
            {
                _ConvertPush(callpcount, src, to);
                _Convert1by1(Pure.VM.OpCode.ROLL, null, to);
                byte[] nullhash = new byte[20];
                //dyn appcall
                _Convert1by1(Pure.VM.OpCode.APPCALL, null, to, nullhash);
            }
            return(0);
        }