Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Type Convert #196

Merged
merged 12 commits into from
Mar 11, 2020
70 changes: 43 additions & 27 deletions src/Neo.Compiler.MSIL/MSIL/Conv_Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,29 @@ private NeoCode _Convert1by1(VM.OpCode code, OpCode src, NeoMethod to, byte[] da
return _code;
}

private NeoCode _ConvertPush(byte[] data, OpCode src, NeoMethod to)
private void _ConvertPushNumber(System.Numerics.BigInteger i, OpCode src, NeoMethod to)
{
if (i == 0) _Convert1by1(VM.OpCode.PUSH0, src, to);
else if (i == -1) _Convert1by1(VM.OpCode.PUSHM1, src, to);
else if (i > 0 && i <= 16) _Convert1by1(VM.OpCode.PUSH0 + (byte)i, src, to);
else
{
_ConvertPushDataArray(i.ToByteArray(), src, to);
_Insert1(VM.OpCode.CONVERT, "", to, new byte[1] { (byte)VM.Types.StackItemType.Integer });
}
}

private void _ConvertPushBoolean(bool b, OpCode src, NeoMethod to)
{
if (!b)
_Convert1by1(VM.OpCode.PUSH0, src, to);
else
_Convert1by1(VM.OpCode.PUSH1, src, to);
_Insert1(VM.OpCode.CONVERT, "", to, new byte[1] { (byte)VM.Types.StackItemType.Boolean });
shargon marked this conversation as resolved.
Show resolved Hide resolved
}

private void _ConvertPushDataArray(byte[] data, OpCode src, NeoMethod to)
{
if (data.Length == 0) return _Convert1by1(VM.OpCode.PUSH0, src, to);
byte prefixLen;
VM.OpCode code;
if (data.Length <= byte.MaxValue)
Expand All @@ -116,15 +136,13 @@ private NeoCode _ConvertPush(byte[] data, OpCode src, NeoMethod to)
byte[] bytes = new byte[data.Length + prefixLen];
Buffer.BlockCopy(BitConverter.GetBytes(data.Length), 0, bytes, 0, prefixLen);
Buffer.BlockCopy(data, 0, bytes, prefixLen, data.Length);
return _Convert1by1(code, src, to, bytes);
_Convert1by1(code, src, to, bytes);
}

private NeoCode _ConvertPush(long i, OpCode src, NeoMethod to)
private void _ConvertPushString(string str, OpCode src, NeoMethod to)
{
if (i == 0) return _Convert1by1(VM.OpCode.PUSH0, src, to);
if (i == -1) return _Convert1by1(VM.OpCode.PUSHM1, src, to);
if (i > 0 && i <= 16) return _Convert1by1(VM.OpCode.PUSH0 + (byte)i, src, to);
return _ConvertPush(((BigInteger)i).ToByteArray(), src, to);
var data = Encoding.UTF8.GetBytes(str);
_ConvertPushDataArray(data, src, to);
}

private int _ConvertPushI8WithConv(ILMethod from, long i, OpCode src, NeoMethod to)
Expand All @@ -136,30 +154,30 @@ private int _ConvertPushI8WithConv(ILMethod from, long i, OpCode src, NeoMethod
{
ulong v = (ulong)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;
}
else if (code == CodeEx.Conv_U1)
{
byte v = (byte)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;

}
else if (code == CodeEx.Conv_U2)
{
ushort v = (ushort)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;

}
else if (code == CodeEx.Conv_U4)
{
uint v = (uint)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;

}
Expand All @@ -171,12 +189,12 @@ private int _ConvertPushI8WithConv(ILMethod from, long i, OpCode src, NeoMethod
// Be careful with converting ulong to biginteger
ulong v = (ulong)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;
}
}

_ConvertPush(i, src, to);
_ConvertPushNumber(i, src, to);
return 0;
}

Expand All @@ -190,36 +208,36 @@ private int _ConvertPushI4WithConv(ILMethod from, int i, OpCode src, NeoMethod t
{
ulong v = (uint)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;
}
else if (code == CodeEx.Conv_U1)
{
byte v = (byte)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;

}
else if (code == CodeEx.Conv_U2)
{
ushort v = (ushort)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;

}
else if (code == CodeEx.Conv_U4)
{
uint v = (uint)i;
outv = v;
_ConvertPush(outv.ToByteArray(), src, to);
_ConvertPushNumber(outv, src, to);
return 1;

}
else
{
_ConvertPush(i, src, to);
_ConvertPushNumber(i, src, to);
return 0;
}
}
Expand Down Expand Up @@ -247,29 +265,27 @@ private void _insertSharedStaticVarCode(NeoMethod to)
if (_src is byte[])
{
var bytesrc = (byte[])_src;
_ConvertPush(bytesrc, null, to);
_ConvertPushDataArray(bytesrc, null, to);
}
else if (_src is int intsrc)
{
_ConvertPush(intsrc, null, to);
_ConvertPushNumber(intsrc, null, to);
}
else if (_src is long longsrc)
{
_ConvertPush(longsrc, null, to);
_ConvertPushNumber(longsrc, null, to);
}
else if (_src is bool bsrc)
{
_ConvertPush(bsrc ? 1 : 0, null, to);
_ConvertPushBoolean(bsrc, null, to);
}
else if (_src is string strsrc)
{
var bytesrc = Encoding.UTF8.GetBytes(strsrc);
_ConvertPush(bytesrc, null, to);
_ConvertPushString(strsrc, null, to);
}
else if (_src is BigInteger bisrc)
{
byte[] bytes = bisrc.ToByteArray();
_ConvertPush(bytes, null, to);
_ConvertPushNumber(bisrc, null, to);
}
else
{
Expand Down
48 changes: 24 additions & 24 deletions src/Neo.Compiler.MSIL/MSIL/Conv_Multi.cs
Original file line number Diff line number Diff line change
Expand Up @@ -635,7 +635,7 @@ private int _ConvertCall(OpCode src, NeoMethod to)
}
else if (src.tokenMethod == "System.Char System.String::get_Chars(System.Int32)")
{
_ConvertPush(1, src, to);
_ConvertPushNumber(1, src, to);
_Convert1by1(VM.OpCode.SUBSTR, null, to);
return 0;
}
Expand Down Expand Up @@ -796,16 +796,16 @@ private int _ConvertCall(OpCode src, NeoMethod to)
}
else if (calltype == 4)
{
_ConvertPush(callhash, src, to);
_ConvertPushDataArray(callhash, src, to);
_Insert1(VM.OpCode.SYSCALL, "", to, BitConverter.GetBytes(InteropService.Contract.Call));
}
else if (calltype == 5)
{
var callp = Encoding.UTF8.GetBytes(callname);
_ConvertPush(callp, src, to);
//var callp = Encoding.UTF8.GetBytes(callname);
_ConvertPushString(callname, src, to);

// package the arguments into an array
_ConvertPush(pcount + 1, null, to);
_ConvertPushNumber(pcount + 1, null, to);
_Convert1by1(VM.OpCode.PACK, null, to);

//a syscall
Expand All @@ -820,7 +820,7 @@ private int _ConvertCall(OpCode src, NeoMethod to)
}
else if (calltype == 6)
{
_ConvertPush(callpcount, src, to);
_ConvertPushNumber(callpcount, src, to);
_Convert1by1(VM.OpCode.ROLL, null, to);
_Convert1by1(VM.OpCode.SYSCALL, null, to, BitConverter.GetBytes(InteropService.Contract.Call));
}
Expand Down Expand Up @@ -1078,8 +1078,8 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)
{
char info = BitConverter.ToChar(data, i);
_Convert1by1(VM.OpCode.DUP, null, to);
_ConvertPush(i / 2, null, to);
_ConvertPush(info, null, to);
_ConvertPushNumber(i / 2, null, to);
_ConvertPushNumber(info, null, to);
_Convert1by1(VM.OpCode.SETITEM, null, to);
}
return 3;
Expand All @@ -1090,8 +1090,8 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)
{
var info = BitConverter.ToUInt32(data, i);
_Convert1by1(VM.OpCode.DUP, null, to);
_ConvertPush(i / 4, null, to);
_ConvertPush(info, null, to);
_ConvertPushNumber(i / 4, null, to);
_ConvertPushNumber(info, null, to);
_Convert1by1(VM.OpCode.SETITEM, null, to);
}
return 3;
Expand All @@ -1102,8 +1102,8 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)
{
var info = BitConverter.ToInt32(data, i);
_Convert1by1(VM.OpCode.DUP, null, to);
_ConvertPush(i / 4, null, to);
_ConvertPush(info, null, to);
_ConvertPushNumber(i / 4, null, to);
_ConvertPushNumber(info, null, to);
_Convert1by1(VM.OpCode.SETITEM, null, to);
}
return 3;
Expand All @@ -1114,8 +1114,8 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)
{
var info = BitConverter.ToInt64(data, i);
_Convert1by1(VM.OpCode.DUP, null, to);
_ConvertPush(i / 8, null, to);
_ConvertPush(info, null, to);
_ConvertPushNumber(i / 8, null, to);
_ConvertPushNumber(info, null, to);
_Convert1by1(VM.OpCode.SETITEM, null, to);
}
return 3;
Expand All @@ -1126,8 +1126,8 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)
{
var info = (System.Numerics.BigInteger)BitConverter.ToUInt64(data, i);
_Convert1by1(VM.OpCode.DUP, null, to);
_ConvertPush(i / 8, null, to);
_ConvertPush(info.ToByteArray(), null, to);
_ConvertPushNumber(i / 8, null, to);
_ConvertPushNumber(info, null, to);
_Convert1by1(VM.OpCode.SETITEM, null, to);
}
return 3;
Expand Down Expand Up @@ -1160,7 +1160,7 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)

// System.Byte or System.SByte
var data = method.body_Codes[n2].tokenUnknown as byte[];
this._ConvertPush(data, src, to);
this._ConvertPushDataArray(data, src, to);

return 3;
}
Expand Down Expand Up @@ -1208,7 +1208,7 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)
bool bLdLoc = (_code.code == CodeEx.Ldloc || _code.code == CodeEx.Ldloc_0 || _code.code == CodeEx.Ldloc_1 || _code.code == CodeEx.Ldloc_2 || _code.code == CodeEx.Ldloc_3 || _code.code == CodeEx.Ldloc_S);
if (bLdLoc == false)//It means there's no initialization at all
{
this._ConvertPush(outbyte, src, to);
this._ConvertPushDataArray(outbyte, src, to);
return 0;
}
while (true)
Expand Down Expand Up @@ -1237,7 +1237,7 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)
else if (bLdLoc && !bStelem)
{
//This is not a predictive array initialization, we lost one case for handling
this._ConvertPush(outbyte, src, to);
this._ConvertPushDataArray(outbyte, src, to);
// Two cases here
if (skip == 1)
{
Expand All @@ -1256,7 +1256,7 @@ private int _ConvertNewArr(ILMethod method, OpCode src, NeoMethod to)
}
//Sometimes c# will use the real value for initialization. If the value is byte, it may be an error

this._ConvertPush(outbyte, src, to);
this._ConvertPushDataArray(outbyte, src, to);
return skip;
}
}
Expand All @@ -1266,7 +1266,7 @@ private int _ConvertInitObj(OpCode src, NeoMethod to)
{
var type = (src.tokenUnknown as Mono.Cecil.TypeReference).Resolve();
_Convert1by1(VM.OpCode.NOP, src, to);
_ConvertPush(type.Fields.Count, null, to);
_ConvertPushNumber(type.Fields.Count, null, to);
if (type.IsValueType)
{
_Insert1(VM.OpCode.NEWSTRUCT, null, to);
Expand Down Expand Up @@ -1323,7 +1323,7 @@ private int _ConvertNewObj(OpCode src, NeoMethod to)
}

_Convert1by1(VM.OpCode.NOP, src, to);
_ConvertPush(type.DeclaringType.Fields.Count, null, to);
_ConvertPushNumber(type.DeclaringType.Fields.Count, null, to);
if (type.DeclaringType.IsValueType)
{
_Insert1(VM.OpCode.NEWSTRUCT, null, to);
Expand All @@ -1345,7 +1345,7 @@ private int _ConvertStfld(ILMethod method, OpCode src, NeoMethod to)

//_Convert1by1(VM.OpCode.CLONESTRUCTONLY, src, to);

_ConvertPush(id, null, to);//index
_ConvertPushNumber(id, null, to);//index
_Convert1by1(VM.OpCode.SWAP, null, to);//put item top

_Convert1by1(VM.OpCode.SETITEM, null, to);//moidfy //item //index //array
Expand All @@ -1359,7 +1359,7 @@ private int _ConvertLdfld(OpCode src, NeoMethod to)
var id = type.Fields.IndexOf(field);
if (id < 0)
throw new Exception("impossible.");
_ConvertPush(id, src, to);
_ConvertPushNumber(id, src, to);
_Convert1by1(VM.OpCode.PICKITEM, null, to);

return 0;
Expand Down
Loading