Esempio n. 1
0
        private NeoCode _Convert1by1(Lux.Core.OpCode code, OpCode src, NeoMethod to, byte[] data = null)
        {
            NeoCode _code     = new NeoCode();
            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);
        }
Esempio n. 2
0
        private NeoCode _Insert1(Lux.Core.OpCode code, string comment, NeoMethod to, byte[] data = null)
        {
            NeoCode _code     = new NeoCode();
            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(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;
            Lux.Core.OpCode callcode = Lux.Core.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;
            }
            else if (IsOpCall(defs, out callname))
            {
                if (System.Enum.TryParse <Lux.Core.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(Lux.Core.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(Lux.Core.OpCode.NUMEQUAL, src, to);
                    }
                    else
                    {
                        _Convert1by1(Lux.Core.OpCode.EQUAL, src, to);
                    }
                    //各类==指令
                    //有可能有一些会特殊处理,故还保留独立判断
                    //if (src.tokenMethod == "System.Boolean System.String::op_Equality(System.String,System.String)")
                    //{
                    //    _Convert1by1(Lux.Core.OpCode.EQUAL, src, to);
                    //    return 0;
                    //}
                    //else if (src.tokenMethod == "System.Boolean System.Object::Equals(System.Object)")
                    //{
                    //    _Convert1by1(Lux.Core.OpCode.EQUAL, src, to);
                    //    return 0;
                    //}
                    //_Convert1by1(Lux.Core.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(Lux.Core.OpCode.NUMNOTEQUAL, src, to);
                    }
                    else
                    {
                        _Convert1by1(Lux.Core.OpCode.INVERT, src, to);
                        _Insert1(Lux.Core.OpCode.EQUAL, "", to);
                    }
                    ////各类!=指令
                    ////有可能有一些会特殊处理,故还保留独立判断
                    //if (src.tokenMethod == "System.Boolean System.Numerics.BigInteger::op_Inequality(System.Numerics.BigInteger,System.Numerics.BigInteger)")
                    //{
                    //    _Convert1by1(Lux.Core.OpCode.INVERT, src, to);
                    //    _Insert1(Lux.Core.OpCode.EQUAL, "", to);
                    //    return 0;
                    //}
                    //_Convert1by1(Lux.Core.OpCode.INVERT, src, to);
                    //_Insert1(Lux.Core.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(Lux.Core.OpCode.ADD, src, to);
                        return(0);
                    }
                    _Convert1by1(Lux.Core.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(Lux.Core.OpCode.SUB, src, to);
                        return(0);
                    }
                    _Convert1by1(Lux.Core.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(Lux.Core.OpCode.MUL, src, to);
                        return(0);
                    }
                    _Convert1by1(Lux.Core.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(Lux.Core.OpCode.DIV, src, to);
                        return(0);
                    }
                    _Convert1by1(Lux.Core.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(Lux.Core.OpCode.MOD, src, to);
                        return(0);
                    }
                    _Convert1by1(Lux.Core.OpCode.MOD, src, to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::op_LessThan("))
                {
                    //各类<指令
                    //有可能有一些会特殊处理,故还保留独立判断
                    _Convert1by1(Lux.Core.OpCode.LT, src, to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::op_GreaterThan("))
                {
                    //各类>指令
                    //有可能有一些会特殊处理,故还保留独立判断
                    _Convert1by1(Lux.Core.OpCode.GT, src, to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::op_LessThanOrEqual("))
                {
                    //各类<=指令
                    //有可能有一些会特殊处理,故还保留独立判断
                    _Convert1by1(Lux.Core.OpCode.LTE, src, to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::op_GreaterThanOrEqual("))
                {
                    //各类>=指令
                    //有可能有一些会特殊处理,故还保留独立判断
                    _Convert1by1(Lux.Core.OpCode.GTE, src, to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::get_Length("))
                {
                    //各类.Length指令
                    //"System.Int32 System.String::get_Length()"
                    _Convert1by1(Lux.Core.OpCode.SIZE, src, to);
                    return(0);
                }
                else if (src.tokenMethod.Contains("::Concat("))
                {
                    //各类.Concat
                    //"System.String System.String::Concat(System.String,System.String)"
                    _Convert1by1(Lux.Core.OpCode.CAT, src, to);
                    return(0);
                }

                else if (src.tokenMethod == "System.String System.String::Substring(System.Int32,System.Int32)")
                {
                    _Convert1by1(Lux.Core.OpCode.SUBSTR, src, to);
                    return(0);
                }
                else if (src.tokenMethod == "System.Char System.String::get_Chars(System.Int32)")
                {
                    _ConvertPush(1, src, to);
                    _Convert1by1(Lux.Core.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(Lux.Core.OpCode.DUPFROMALTSTACK, src, to);
                    _ConvertPush(2, null, to);
                    _Convert1by1(Lux.Core.OpCode.ROLL, null, to);
                    _ConvertPush(2, null, to);
                    _Convert1by1(Lux.Core.OpCode.ROLL, null, to);
                    _Convert1by1(Lux.Core.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(Lux.Core.OpCode.CSHARPSTRHASH32, src, to);
                    //return 0;
                }
                else
                {
                }
            }

            if (calltype == 0)
            {
                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(Lux.Core.OpCode.NOP, src, to);
                if (pcount <= 1)
                {
                }
                else if (pcount == 2)
                {
                    _Insert1(Lux.Core.OpCode.SWAP, "swap 2 param", to);
                }
                else if (pcount == 3)
                {
                    _InsertPush(2, "swap 0 and 2 param", to);
                    _Insert1(Lux.Core.OpCode.XSWAP, "", to);
                }
                else
                {
                    for (var i = 0; i < pcount / 2; i++)
                    {
                        int saveto = (pcount - 1 - i);
                        _InsertPush(saveto, "load" + saveto, to);
                        _Insert1(Lux.Core.OpCode.PICK, "", to);

                        _InsertPush(i + 1, "load" + i + 1, to);
                        _Insert1(Lux.Core.OpCode.PICK, "", to);


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

                        _InsertPush(i + 1, "save to" + i + 1, to);
                        _Insert1(Lux.Core.OpCode.XSWAP, "", to);
                        _Insert1(Lux.Core.OpCode.DROP, "", to);
                    }
                }
            }
            if (calltype == 1)
            {
                var c = _Convert1by1(Lux.Core.OpCode.CALL, null, to, new byte[] { 5, 0 });
                c.needfixfunc = true;
                c.srcfunc     = src.tokenMethod;
                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 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(Lux.Core.OpCode.SYSCALL, null, to, outbytes);
                return(0);
            }
            else if (calltype == 4)
            {
                _Convert1by1(Lux.Core.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(Lux.Core.OpCode.PACK, null, to);

                //a syscall
                {
                    var    bytes    = Encoding.UTF8.GetBytes("Neo.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(Lux.Core.OpCode.SYSCALL, null, to, outbytes);
                }
            }
            else if (calltype == 6)
            {
                _ConvertPush(callpcount, src, to);
                _Convert1by1(Lux.Core.OpCode.ROLL, null, to);
                byte[] nullhash = new byte[20];
                //dyn appcall
                _Convert1by1(Lux.Core.OpCode.APPCALL, null, to, nullhash);
            }
            return(0);
        }