├── neoj ├── ILogger.cs ├── JVM │ ├── Converter_Ext.cs │ ├── java.cecil │ │ └── loader │ │ │ ├── TypeWarper.cs │ │ │ ├── attribute.cs │ │ │ └── BigEndianBinaryReader.cs │ ├── Converter_Common.cs │ ├── JAVAModule.cs │ └── Converter_Mutli.cs ├── ConvOption.cs ├── neoj.csproj ├── Program.cs └── NeoModule.cs ├── neon ├── ILogger.cs ├── ConvOption.cs ├── neon.csproj ├── Debugger │ ├── NeoDebugMap.cs │ ├── DebugInfo.cs │ └── NeoDisassembler.cs ├── base58.cs ├── FuncExport.cs ├── Program.cs ├── NeoModule.cs └── MSIL │ ├── CctorSubVM.cs │ ├── Conv_Common.cs │ └── ILModule.cs ├── neoa ├── ASM │ ├── Label.cs │ ├── CompilerException.cs │ ├── InstructionName.cs │ ├── AddressTable.cs │ ├── Semanteme.cs │ └── Instruction.cs ├── Program.cs └── neoa.csproj ├── LICENSE ├── neo-compiler.sln └── .gitignore /neoj/ILogger.cs: -------------------------------------------------------------------------------- 1 | namespace Neo.Compiler 2 | { 3 | public interface ILogger 4 | { 5 | void Log(string log); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /neon/ILogger.cs: -------------------------------------------------------------------------------- 1 | namespace Neo.Compiler 2 | { 3 | public interface ILogger 4 | { 5 | void Log(string log); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /neoa/ASM/Label.cs: -------------------------------------------------------------------------------- 1 | namespace Neo.Compiler.ASM 2 | { 3 | internal class Label : Semanteme 4 | { 5 | public string Name; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /neoj/JVM/Converter_Ext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Neo.Compiler.JVM 8 | { 9 | public partial class ModuleConverter 10 | { 11 | 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /neoa/ASM/CompilerException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Neo.Compiler.ASM 4 | { 5 | public class CompilerException : Exception 6 | { 7 | public CompilerException(uint lineNumber, string message) 8 | : base($"ERROR: {message} in line {lineNumber}.") 9 | { 10 | } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /neoj/ConvOption.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Neo.Compiler 8 | { 9 | public class ConvOption 10 | { 11 | public bool useNep8 = false;//將call 升級為callI 12 | public static ConvOption Default 13 | { 14 | get 15 | { 16 | return new ConvOption(); 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /neon/ConvOption.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Neo.Compiler 8 | { 9 | public class ConvOption 10 | { 11 | public bool useNep8 = false;//將call 升級為callI 12 | public static ConvOption Default 13 | { 14 | get 15 | { 16 | return new ConvOption(); 17 | } 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /neoj/JVM/java.cecil/loader/TypeWarper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace javaloader 6 | { 7 | static class StringConstants 8 | { 9 | internal static readonly string CLINIT = ""; 10 | internal static readonly string INIT = ""; 11 | internal static readonly string SIG_VOID = "()V"; 12 | internal static readonly string FINALIZE = "finalize"; 13 | internal static readonly string CLONE = "clone"; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /neoa/Program.cs: -------------------------------------------------------------------------------- 1 | using Neo.Compiler.ASM; 2 | using System.IO; 3 | 4 | namespace Neo.Compiler 5 | { 6 | internal class Program 7 | { 8 | public static void Main(string[] args) 9 | { 10 | if (args.Length == 0) return; 11 | if (!File.Exists(args[0])) return; 12 | var lines = File.ReadAllLines(args[0]); 13 | var semantemes = Semanteme.ProcessLines(lines); 14 | var table = new AddressTable(semantemes); 15 | var script = table.ToScript(); 16 | string out_path = args.Length >= 2 ? args[1] : Path.ChangeExtension(args[0], "avm"); 17 | File.WriteAllBytes(out_path, script); 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /neoa/neoa.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2016-2017 The Neo Project 5 | Neo.Compiler.ASM 6 | 2.0.3 7 | The Neo Project 8 | netcoreapp1.0 9 | neoa 10 | Exe 11 | Neo.Compiler.ASM 12 | 1.0.4 13 | Neo.Compiler 14 | The Neo Project 15 | Neo.Compiler.ASM 16 | Neo.Compiler.ASM 17 | 18 | 19 | 20 | RELEASE;NETCOREAPP1_0 21 | none 22 | False 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /neoj/neoj.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2016-2017 The Neo Project 5 | Neo.Compiler.JVM 6 | 2.0.3 7 | The Neo Project 8 | Exe 9 | netcoreapp1.1 10 | anycpu 11 | neoj 12 | Neo.Compiler.JVM 13 | win10-x64 14 | 1.0.4 15 | Neo.Compiler 16 | The Neo Project 17 | Neo.Compiler.JVM 18 | Neo.Compiler.JVM 19 | 20 | 21 | 22 | RELEASE;NETCOREAPP1_1 23 | none 24 | False 25 | 26 | 27 | 28 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /neon/neon.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 2016-2017 The Neo Project 5 | Neo.Compiler.MSIL 6 | 2.3.0.9 7 | The Neo Project 8 | netcoreapp2.0 9 | anycpu 10 | neon 11 | Exe 12 | Neo.Compiler.MSIL 13 | win10-x64 14 | Neo.Compiler 15 | The Neo Project 16 | Neo.Compiler.MSIL 17 | Neo.Compiler.MSIL 18 | 19 | 20 | 21 | RELEASE;NETCOREAPP1_0 22 | none 23 | False 24 | true 25 | 26 | 27 | 28 | true 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /neoa/ASM/InstructionName.cs: -------------------------------------------------------------------------------- 1 | namespace Neo.Compiler.ASM 2 | { 3 | internal enum InstructionName : byte 4 | { 5 | PUSH, 6 | NOP, 7 | JMP, 8 | JMPIF, 9 | JMPIFNOT, 10 | CALL, 11 | RET, 12 | APPCALL, 13 | SYSCALL, 14 | TAILCALL, 15 | DUPFROMALTSTACK, 16 | TOALTSTACK, 17 | FROMALTSTACK, 18 | XDROP, 19 | XSWAP, 20 | XTUCK, 21 | DEPTH, 22 | DROP, 23 | DUP, 24 | NIP, 25 | OVER, 26 | PICK, 27 | ROLL, 28 | ROT, 29 | SWAP, 30 | TUCK, 31 | CAT, 32 | SUBSTR, 33 | LEFT, 34 | RIGHT, 35 | SIZE, 36 | INVERT, 37 | AND, 38 | OR, 39 | XOR, 40 | EQUAL, 41 | INC, 42 | DEC, 43 | SIGN, 44 | NEGATE, 45 | ABS, 46 | NOT, 47 | NZ, 48 | ADD, 49 | SUB, 50 | MUL, 51 | DIV, 52 | MOD, 53 | SHL, 54 | SHR, 55 | BOOLAND, 56 | BOOLOR, 57 | NUMEQUAL, 58 | NUMNOTEQUAL, 59 | LT, 60 | GT, 61 | LTE, 62 | GTE, 63 | MIN, 64 | MAX, 65 | WITHIN, 66 | SHA1, 67 | SHA256, 68 | HASH160, 69 | HASH256, 70 | CHECKSIG, 71 | CHECKMULTISIG, 72 | ARRAYSIZE, 73 | PACK, 74 | UNPACK, 75 | PICKITEM, 76 | SETITEM, 77 | NEWARRAY, 78 | NEWSTRUCT, 79 | THROW, 80 | THROWIFNOT, 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /neo-compiler.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.15 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "neoa", "neoa\neoa.csproj", "{3D326E22-666D-4EB0-9324-225B0CCA6349}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "neon", "neon\neon.csproj", "{161C0944-29EB-4BFA-AEF0-60CC598C556F}" 9 | EndProject 10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "neoj", "neoj\neoj.csproj", "{5FB7A952-6EAC-4BF9-AD23-AF957EF21925}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {3D326E22-666D-4EB0-9324-225B0CCA6349}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {3D326E22-666D-4EB0-9324-225B0CCA6349}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {3D326E22-666D-4EB0-9324-225B0CCA6349}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {3D326E22-666D-4EB0-9324-225B0CCA6349}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {161C0944-29EB-4BFA-AEF0-60CC598C556F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {161C0944-29EB-4BFA-AEF0-60CC598C556F}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {161C0944-29EB-4BFA-AEF0-60CC598C556F}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {161C0944-29EB-4BFA-AEF0-60CC598C556F}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {5FB7A952-6EAC-4BF9-AD23-AF957EF21925}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {5FB7A952-6EAC-4BF9-AD23-AF957EF21925}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {5FB7A952-6EAC-4BF9-AD23-AF957EF21925}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {5FB7A952-6EAC-4BF9-AD23-AF957EF21925}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | EndGlobal 35 | -------------------------------------------------------------------------------- /neoj/JVM/java.cecil/loader/attribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace javaloader 6 | { 7 | [Flags] 8 | public enum Modifiers : ushort 9 | { 10 | Public = 0x0001, 11 | Private = 0x0002, 12 | Protected = 0x0004, 13 | Static = 0x0008, 14 | Final = 0x0010, 15 | Super = 0x0020, 16 | Synchronized = 0x0020, 17 | Volatile = 0x0040, 18 | Bridge = 0x0040, 19 | Transient = 0x0080, 20 | VarArgs = 0x0080, 21 | Native = 0x0100, 22 | Interface = 0x0200, 23 | Abstract = 0x0400, 24 | Strictfp = 0x0800, 25 | Synthetic = 0x1000, 26 | Annotation = 0x2000, 27 | Enum = 0x4000, 28 | 29 | // Masks 30 | AccessMask = Public | Private | Protected 31 | } 32 | 33 | 34 | [AttributeUsage(AttributeTargets.Method)] 35 | public sealed class AnnotationDefaultAttribute : Attribute 36 | { 37 | public const byte TAG_ENUM = (byte)'e'; 38 | public const byte TAG_CLASS = (byte)'c'; 39 | public const byte TAG_ANNOTATION = (byte)'@'; 40 | public const byte TAG_ARRAY = (byte)'['; 41 | public const byte TAG_ERROR = (byte)'?'; 42 | private object defaultValue; 43 | 44 | // element_value encoding: 45 | // primitives: 46 | // boxed values 47 | // string: 48 | // string 49 | // enum: 50 | // new object[] { (byte)'e', "", "" } 51 | // class: 52 | // new object[] { (byte)'c', "" } 53 | // annotation: 54 | // new object[] { (byte)'@', "", ("name", (element_value))* } 55 | // array: 56 | // new object[] { (byte)'[', (element_value)* } 57 | // error: 58 | // new object[] { (byte)'?', "", "" } 59 | public AnnotationDefaultAttribute(object defaultValue) 60 | { 61 | this.defaultValue = defaultValue; 62 | } 63 | 64 | public object Value 65 | { 66 | get 67 | { 68 | return defaultValue; 69 | } 70 | } 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /neon/Debugger/NeoDebugMap.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | 5 | namespace Neo.Compiler.Debugger 6 | { 7 | public class DebugMapEntry 8 | { 9 | public string url; 10 | public int line; 11 | 12 | public int startOfs; 13 | public int endOfs; 14 | 15 | public override string ToString() 16 | { 17 | return "Line "+this.line+" at "+url; 18 | } 19 | } 20 | 21 | public class NeoMapFile 22 | { 23 | private List _entries = new List(); 24 | public IEnumerable Entries { get { return _entries; } } 25 | 26 | public string contractName { get; private set; } 27 | 28 | public IEnumerable FileNames => _fileNames; 29 | private HashSet _fileNames = new HashSet(); 30 | 31 | /// 32 | /// Calculates the source code line that maps to the specificed script offset. 33 | /// 34 | public int ResolveLine(int ofs, out string filePath) 35 | { 36 | foreach (var entry in this.Entries) 37 | { 38 | if (ofs >= entry.startOfs && ofs <= entry.endOfs) 39 | { 40 | filePath = entry.url; 41 | return entry.line; 42 | } 43 | } 44 | 45 | throw new Exception("Offset cannot be mapped"); 46 | } 47 | 48 | /// 49 | /// Calculates the script offset that maps to the specificed source code line 50 | /// 51 | public int ResolveStartOffset(int line, string filePath) 52 | { 53 | foreach (var entry in this.Entries) 54 | { 55 | if (entry.line == line && entry.url == filePath) 56 | { 57 | return entry.startOfs; 58 | } 59 | } 60 | 61 | throw new Exception("Line cannot be mapped"); 62 | } 63 | 64 | public int ResolveEndOffset(int line, string filePath) 65 | { 66 | foreach (var entry in this.Entries) 67 | { 68 | if (entry.line == line && entry.url == filePath) 69 | { 70 | return entry.endOfs; 71 | } 72 | } 73 | 74 | throw new Exception("Line cannot be mapped"); 75 | } 76 | 77 | } 78 | 79 | } 80 | -------------------------------------------------------------------------------- /neon/base58.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Numerics; 5 | using System.Security.Cryptography; 6 | using System.Text; 7 | using System.Threading.Tasks; 8 | 9 | namespace NEO.AllianceOfThinWallet.Cryptography 10 | { 11 | public static class Base58 12 | { 13 | /// 14 | /// base58编码的字母表 15 | /// 16 | public const string Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; 17 | 18 | /// 19 | /// 解码 20 | /// 21 | /// 要解码的字符串 22 | /// 返回解码后的字节数组 23 | public static byte[] Decode(string input) 24 | { 25 | BigInteger bi = BigInteger.Zero; 26 | for (int i = input.Length - 1; i >= 0; i--) 27 | { 28 | int index = Alphabet.IndexOf(input[i]); 29 | if (index == -1) 30 | throw new FormatException(); 31 | bi += index * BigInteger.Pow(58, input.Length - 1 - i); 32 | } 33 | byte[] bytes = bi.ToByteArray(); 34 | Array.Reverse(bytes); 35 | bool stripSignByte = bytes.Length > 1 && bytes[0] == 0 && bytes[1] >= 0x80; 36 | int leadingZeros = 0; 37 | for (int i = 0; i < input.Length && input[i] == Alphabet[0]; i++) 38 | { 39 | leadingZeros++; 40 | } 41 | byte[] tmp = new byte[bytes.Length - (stripSignByte ? 1 : 0) + leadingZeros]; 42 | Array.Copy(bytes, stripSignByte ? 1 : 0, tmp, leadingZeros, tmp.Length - leadingZeros); 43 | return tmp; 44 | } 45 | 46 | /// 47 | /// 编码 48 | /// 49 | /// 要编码的字节数组 50 | /// 返回编码后的字符串 51 | public static string Encode(byte[] input) 52 | { 53 | BigInteger value = new BigInteger(new byte[1].Concat(input).Reverse().ToArray()); 54 | StringBuilder sb = new StringBuilder(); 55 | while (value >= 58) 56 | { 57 | BigInteger mod = value % 58; 58 | sb.Insert(0, Alphabet[(int)mod]); 59 | value /= 58; 60 | } 61 | sb.Insert(0, Alphabet[(int)value]); 62 | foreach (byte b in input) 63 | { 64 | if (b == 0) 65 | sb.Insert(0, Alphabet[0]); 66 | else 67 | break; 68 | } 69 | return sb.ToString(); 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /neoa/ASM/AddressTable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace Neo.Compiler.ASM 5 | { 6 | internal class AddressTable 7 | { 8 | private readonly List itable = new List(); 9 | private readonly Dictionary ltable = new Dictionary(); 10 | 11 | public AddressTable(IEnumerable semantemes) 12 | { 13 | foreach (Semanteme semanteme in semantemes) 14 | { 15 | if (semanteme is Instruction) 16 | { 17 | Instruction instruction = (Instruction)semanteme; 18 | instruction.Process(); 19 | } 20 | semanteme.BaseAddress = itable.Count == 0 ? 0 : itable[itable.Count - 1].BaseAddress + (uint)itable[itable.Count - 1].Code.Length; 21 | if (semanteme is Instruction) 22 | { 23 | itable.Add((Instruction)semanteme); 24 | } 25 | else 26 | { 27 | Label label = (Label)semanteme; 28 | if (ltable.ContainsKey(label.Name)) 29 | throw new CompilerException(label.LineNumber, "duplicate label"); 30 | ltable.Add(label.Name, label); 31 | } 32 | } 33 | foreach (Instruction instruction in itable) 34 | { 35 | switch (instruction.Name) 36 | { 37 | case InstructionName.JMP: 38 | case InstructionName.JMPIF: 39 | case InstructionName.JMPIFNOT: 40 | case InstructionName.CALL: 41 | if (!ltable.ContainsKey(instruction.Arguments[0])) 42 | throw new CompilerException(instruction.LineNumber, "invalid label"); 43 | int offset = (int)ltable[instruction.Arguments[0]].BaseAddress - (int)instruction.BaseAddress; 44 | if (offset < short.MinValue || offset > short.MaxValue) 45 | throw new CompilerException(instruction.LineNumber, "long jump"); 46 | instruction.Code = instruction.ProcessJump((short)offset); 47 | break; 48 | } 49 | } 50 | } 51 | 52 | public byte[] ToScript() 53 | { 54 | if (itable.Count == 0) return new byte[0]; 55 | byte[] script = new byte[itable[itable.Count - 1].BaseAddress + itable[itable.Count - 1].Code.Length]; 56 | foreach (Instruction instruction in itable) 57 | Buffer.BlockCopy(instruction.Code, 0, script, (int)instruction.BaseAddress, instruction.Code.Length); 58 | return script; 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /neoa/ASM/Semanteme.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace Neo.Compiler.ASM 6 | { 7 | internal abstract class Semanteme 8 | { 9 | public uint LineNumber; 10 | public uint BaseAddress; 11 | 12 | public static IEnumerable ProcessLines(IEnumerable lines) 13 | { 14 | bool isInComment = false; 15 | uint lineNumber = 0; 16 | foreach (string line in lines) 17 | { 18 | string pline = line; 19 | ++lineNumber; 20 | int index; 21 | if (isInComment) 22 | { 23 | index = pline.IndexOf("*/"); 24 | if (index == -1) continue; 25 | pline = pline.Substring(index + 2); 26 | } 27 | index = 0; 28 | while (true) 29 | { 30 | index = pline.IndexOf("/*", index); 31 | if (index == -1) break; 32 | int index2 = pline.IndexOf("*/", index + 2); 33 | if (index2 >= 0) 34 | { 35 | pline = pline.Substring(0, index) + pline.Substring(index2 + 2); 36 | } 37 | else 38 | { 39 | pline = pline.Substring(0, index); 40 | isInComment = true; 41 | break; 42 | } 43 | } 44 | index = pline.IndexOf("//"); 45 | if (index >= 0) pline = pline.Substring(0, index); 46 | pline = pline.Trim(); 47 | index = pline.IndexOf(':'); 48 | if (index >= 0) 49 | { 50 | yield return new Label 51 | { 52 | LineNumber = lineNumber, 53 | Name = pline.Substring(0, index) 54 | }; 55 | pline = pline.Substring(index + 1).Trim(); 56 | } 57 | if (!string.IsNullOrEmpty(pline)) 58 | { 59 | string[] words = pline.Split(new[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries); 60 | InstructionName name; 61 | if (!Enum.TryParse(words[0], true, out name)) 62 | throw new CompilerException(lineNumber, "syntax error"); 63 | yield return new Instruction 64 | { 65 | LineNumber = lineNumber, 66 | Name = name, 67 | Arguments = words.Skip(1).ToArray() 68 | }; 69 | } 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /neoj/Program.cs: -------------------------------------------------------------------------------- 1 | using Neo.Compiler.JVM; 2 | using System; 3 | using System.Reflection; 4 | 5 | namespace Neo.Compiler 6 | { 7 | public class Program 8 | { 9 | //Console.WriteLine("helo ha:"+args[0]); //普通输出 10 | //Console.WriteLine(" 这是一个严重的问题。");//警告输出,黄字 11 | //Console.WriteLine(" 这是ee一个严重的问题。");//警告输出,带文件名行号 12 | //Console.WriteLine(" 这是一个严重的问题。");//错误输出,红字 13 | //Console.WriteLine(" 这是ee一个严重的问题。");//错误输出,带文件名 14 | //Console.WriteLine("SUCC");//输出这个表示编译成功 15 | //控制台输出约定了特别的语法 16 | public static void Main(string[] args) 17 | { 18 | 19 | //set console 20 | Console.OutputEncoding = System.Text.Encoding.UTF8; 21 | var log = new DefLogger(); 22 | log.Log("Neo.Compiler.JVM console app v" + Assembly.GetEntryAssembly().GetName().Version); 23 | if (args.Length == 0) 24 | { 25 | log.Log("need one param for .class filename."); 26 | return; 27 | } 28 | string filename = args[0]; 29 | string onlyname = System.IO.Path.GetFileNameWithoutExtension(filename); 30 | string extension = System.IO.Path.GetExtension(filename); 31 | //javaloader.ClassFile classFile = null; 32 | JavaModule module = new JavaModule(); 33 | 34 | 35 | byte[] bytes = null; 36 | bool bSucc = false; 37 | //convert and build 38 | try 39 | { 40 | var path = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName; 41 | path = System.IO.Path.GetDirectoryName(path); 42 | module.LoadJar(System.IO.Path.Combine(path, "org.neo.smartcontract.framework.jar")); 43 | 44 | if (extension == ".jar") 45 | { 46 | module.LoadJar(filename); 47 | } 48 | else 49 | { 50 | module.LoadClass(filename); 51 | } 52 | 53 | var conv = new ModuleConverter(log); 54 | 55 | NeoModule am = conv.Convert(module); 56 | bytes = am.Build(); 57 | log.Log("convert succ"); 58 | } 59 | catch (Exception err) 60 | { 61 | log.Log("Convert Error:" + err.ToString()); 62 | return; 63 | } 64 | //write bytes 65 | try 66 | { 67 | 68 | string bytesname = onlyname + ".avm"; 69 | 70 | System.IO.File.Delete(bytesname); 71 | System.IO.File.WriteAllBytes(bytesname, bytes); 72 | log.Log("write:" + bytesname); 73 | bSucc = true; 74 | } 75 | catch (Exception err) 76 | { 77 | log.Log("Write Bytes Error:" + err.ToString()); 78 | return; 79 | } 80 | 81 | 82 | if (bSucc) 83 | { 84 | log.Log("SUCC"); 85 | } 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /neon/Debugger/DebugInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Reflection; 3 | using System.Text; 4 | 5 | namespace Neo.Compiler.Debugger 6 | { 7 | public static class DebugInfo 8 | { 9 | public static MyJson.JsonNode_Object ExportDebugInfo(string avmName, NeoModule module) 10 | { 11 | var outjson = new MyJson.JsonNode_Object(); 12 | 13 | var debugMap = new List(); 14 | DebugMapEntry currentDebugEntry = null; 15 | 16 | var fileMap = new Dictionary(); 17 | 18 | List bytes = new List(); 19 | 20 | foreach (var c in module.total_Codes.Values) 21 | { 22 | if (c.debugcode != null && c.debugline > 0 && c.debugline < 2000) 23 | { 24 | var previousDebugEntry = currentDebugEntry; 25 | 26 | currentDebugEntry = new DebugMapEntry(); 27 | if (previousDebugEntry != null) 28 | { 29 | currentDebugEntry.startOfs = previousDebugEntry.endOfs + 1; 30 | currentDebugEntry.endOfs = bytes.Count; 31 | } 32 | else 33 | { 34 | currentDebugEntry.startOfs = 0; 35 | currentDebugEntry.endOfs = bytes.Count; 36 | } 37 | currentDebugEntry.url = c.debugcode; 38 | currentDebugEntry.line = c.debugline; 39 | 40 | if (!fileMap.ContainsKey(c.debugcode)) 41 | { 42 | fileMap[c.debugcode] = fileMap.Count + 1; 43 | } 44 | 45 | debugMap.Add(currentDebugEntry); 46 | } 47 | else 48 | if (currentDebugEntry != null) 49 | { 50 | currentDebugEntry.endOfs = bytes.Count; 51 | } 52 | bytes.Add((byte)c.code); 53 | if (c.bytes != null) 54 | for (var i = 0; i < c.bytes.Length; i++) 55 | { 56 | bytes.Add(c.bytes[i]); 57 | } 58 | 59 | } 60 | 61 | string compilerName = System.AppDomain.CurrentDomain.FriendlyName.ToLowerInvariant(); 62 | var version = Assembly.GetEntryAssembly().GetName().Version.ToString(); 63 | 64 | var avmInfo = new MyJson.JsonNode_Object(); 65 | avmInfo.Add("name", new MyJson.JsonNode_ValueString(avmName)); 66 | //avmInfo.Add("hash", new MyJson.JsonNode_ValueString(hash)); 67 | 68 | var compilerInfo = new MyJson.JsonNode_Object(); 69 | compilerInfo.Add("name", new MyJson.JsonNode_ValueString(compilerName)); 70 | compilerInfo.Add("version", new MyJson.JsonNode_ValueString(version)); 71 | 72 | var fileInfo = new MyJson.JsonNode_Array(); 73 | foreach (var entry in fileMap) 74 | { 75 | var fileEntry = new MyJson.JsonNode_Object(); 76 | fileEntry.Add("id", new MyJson.JsonNode_ValueNumber(entry.Value)); 77 | fileEntry.Add("url", new MyJson.JsonNode_ValueString(entry.Key)); 78 | fileInfo.AddArrayValue(fileEntry); 79 | } 80 | 81 | var mapInfo = new MyJson.JsonNode_Array(); 82 | foreach (var entry in debugMap) 83 | { 84 | if (!fileMap.ContainsKey(entry.url)) 85 | { 86 | continue; 87 | } 88 | 89 | var fileID = fileMap[entry.url]; 90 | 91 | var mapEntry = new MyJson.JsonNode_Object(); 92 | mapEntry.Add("start", new MyJson.JsonNode_ValueNumber(entry.startOfs)); 93 | mapEntry.Add("end", new MyJson.JsonNode_ValueNumber(entry.endOfs)); 94 | mapEntry.Add("file", new MyJson.JsonNode_ValueNumber(fileID)); 95 | mapEntry.Add("line", new MyJson.JsonNode_ValueNumber(entry.line)); 96 | mapInfo.AddArrayValue(mapEntry); 97 | } 98 | 99 | outjson["avm"] = avmInfo; 100 | outjson["compiler"] = compilerInfo; 101 | outjson["files"] = fileInfo; 102 | outjson["map"] = mapInfo; 103 | 104 | return outjson; 105 | } 106 | 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | ## 4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 5 | 6 | # User-specific files 7 | *.suo 8 | *.user 9 | *.userosscache 10 | *.sln.docstates 11 | 12 | # User-specific files (MonoDevelop/Xamarin Studio) 13 | *.userprefs 14 | 15 | # Build results 16 | [Dd]ebug/ 17 | [Dd]ebugPublic/ 18 | [Rr]elease/ 19 | [Rr]eleases/ 20 | x64/ 21 | x86/ 22 | bld/ 23 | [Bb]in/ 24 | [Oo]bj/ 25 | [Ll]og/ 26 | 27 | # Visual Studio 2015 cache/options directory 28 | .vs/ 29 | # Uncomment if you have tasks that create the project's static files in wwwroot 30 | #wwwroot/ 31 | 32 | # MSTest test Results 33 | [Tt]est[Rr]esult*/ 34 | [Bb]uild[Ll]og.* 35 | 36 | # NUNIT 37 | *.VisualState.xml 38 | TestResult.xml 39 | 40 | # Build Results of an ATL Project 41 | [Dd]ebugPS/ 42 | [Rr]eleasePS/ 43 | dlldata.c 44 | 45 | # .NET Core 46 | project.lock.json 47 | project.fragment.lock.json 48 | artifacts/ 49 | **/Properties/launchSettings.json 50 | 51 | *_i.c 52 | *_p.c 53 | *_i.h 54 | *.ilk 55 | *.meta 56 | *.obj 57 | *.pch 58 | *.pdb 59 | *.pgc 60 | *.pgd 61 | *.rsp 62 | *.sbr 63 | *.tlb 64 | *.tli 65 | *.tlh 66 | *.tmp 67 | *.tmp_proj 68 | *.log 69 | *.vspscc 70 | *.vssscc 71 | .builds 72 | *.pidb 73 | *.svclog 74 | *.scc 75 | 76 | # Chutzpah Test files 77 | _Chutzpah* 78 | 79 | # Visual C++ cache files 80 | ipch/ 81 | *.aps 82 | *.ncb 83 | *.opendb 84 | *.opensdf 85 | *.sdf 86 | *.cachefile 87 | *.VC.db 88 | *.VC.VC.opendb 89 | 90 | # Visual Studio profiler 91 | *.psess 92 | *.vsp 93 | *.vspx 94 | *.sap 95 | 96 | # TFS 2012 Local Workspace 97 | $tf/ 98 | 99 | # Guidance Automation Toolkit 100 | *.gpState 101 | 102 | # ReSharper is a .NET coding add-in 103 | _ReSharper*/ 104 | *.[Rr]e[Ss]harper 105 | *.DotSettings.user 106 | 107 | # JustCode is a .NET coding add-in 108 | .JustCode 109 | 110 | # TeamCity is a build add-in 111 | _TeamCity* 112 | 113 | # DotCover is a Code Coverage Tool 114 | *.dotCover 115 | 116 | # Visual Studio code coverage results 117 | *.coverage 118 | *.coveragexml 119 | 120 | # NCrunch 121 | _NCrunch_* 122 | .*crunch*.local.xml 123 | nCrunchTemp_* 124 | 125 | # MightyMoose 126 | *.mm.* 127 | AutoTest.Net/ 128 | 129 | # Web workbench (sass) 130 | .sass-cache/ 131 | 132 | # Installshield output folder 133 | [Ee]xpress/ 134 | 135 | # DocProject is a documentation generator add-in 136 | DocProject/buildhelp/ 137 | DocProject/Help/*.HxT 138 | DocProject/Help/*.HxC 139 | DocProject/Help/*.hhc 140 | DocProject/Help/*.hhk 141 | DocProject/Help/*.hhp 142 | DocProject/Help/Html2 143 | DocProject/Help/html 144 | 145 | # Click-Once directory 146 | publish/ 147 | 148 | # Publish Web Output 149 | *.[Pp]ublish.xml 150 | *.azurePubxml 151 | # TODO: Comment the next line if you want to checkin your web deploy settings 152 | # but database connection strings (with potential passwords) will be unencrypted 153 | *.pubxml 154 | *.publishproj 155 | 156 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 157 | # checkin your Azure Web App publish settings, but sensitive information contained 158 | # in these scripts will be unencrypted 159 | PublishScripts/ 160 | 161 | # NuGet Packages 162 | *.nupkg 163 | # The packages folder can be ignored because of Package Restore 164 | **/packages/* 165 | # except build/, which is used as an MSBuild target. 166 | !**/packages/build/ 167 | # Uncomment if necessary however generally it will be regenerated when needed 168 | #!**/packages/repositories.config 169 | # NuGet v3's project.json files produces more ignorable files 170 | *.nuget.props 171 | *.nuget.targets 172 | 173 | # Microsoft Azure Build Output 174 | csx/ 175 | *.build.csdef 176 | 177 | # Microsoft Azure Emulator 178 | ecf/ 179 | rcf/ 180 | 181 | # Windows Store app package directories and files 182 | AppPackages/ 183 | BundleArtifacts/ 184 | Package.StoreAssociation.xml 185 | _pkginfo.txt 186 | 187 | # Visual Studio cache files 188 | # files ending in .cache can be ignored 189 | *.[Cc]ache 190 | # but keep track of directories ending in .cache 191 | !*.[Cc]ache/ 192 | 193 | # Others 194 | ClientBin/ 195 | ~$* 196 | *~ 197 | *.dbmdl 198 | *.dbproj.schemaview 199 | *.jfm 200 | *.pfx 201 | *.publishsettings 202 | orleans.codegen.cs 203 | 204 | # Since there are multiple workflows, uncomment next line to ignore bower_components 205 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 206 | #bower_components/ 207 | 208 | # RIA/Silverlight projects 209 | Generated_Code/ 210 | 211 | # Backup & report files from converting an old project file 212 | # to a newer Visual Studio version. Backup files are not needed, 213 | # because we have git ;-) 214 | _UpgradeReport_Files/ 215 | Backup*/ 216 | UpgradeLog*.XML 217 | UpgradeLog*.htm 218 | 219 | # SQL Server files 220 | *.mdf 221 | *.ldf 222 | *.ndf 223 | 224 | # Business Intelligence projects 225 | *.rdl.data 226 | *.bim.layout 227 | *.bim_*.settings 228 | 229 | # Microsoft Fakes 230 | FakesAssemblies/ 231 | 232 | # GhostDoc plugin setting file 233 | *.GhostDoc.xml 234 | 235 | # Node.js Tools for Visual Studio 236 | .ntvs_analysis.dat 237 | node_modules/ 238 | 239 | # Typescript v1 declaration files 240 | typings/ 241 | 242 | # Visual Studio 6 build log 243 | *.plg 244 | 245 | # Visual Studio 6 workspace options file 246 | *.opt 247 | 248 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 249 | *.vbw 250 | 251 | # Visual Studio LightSwitch build output 252 | **/*.HTMLClient/GeneratedArtifacts 253 | **/*.DesktopClient/GeneratedArtifacts 254 | **/*.DesktopClient/ModelManifest.xml 255 | **/*.Server/GeneratedArtifacts 256 | **/*.Server/ModelManifest.xml 257 | _Pvt_Extensions 258 | 259 | # Paket dependency manager 260 | .paket/paket.exe 261 | paket-files/ 262 | 263 | # FAKE - F# Make 264 | .fake/ 265 | 266 | # JetBrains Rider 267 | .idea/ 268 | *.sln.iml 269 | 270 | # CodeRush 271 | .cr/ 272 | 273 | # Python Tools for Visual Studio (PTVS) 274 | __pycache__/ 275 | *.pyc 276 | 277 | # Cake - Uncomment if you are using it 278 | # tools/** 279 | # !tools/packages.config 280 | 281 | # Telerik's JustMock configuration file 282 | *.jmconfig 283 | 284 | # BizTalk build output 285 | *.btp.cs 286 | *.btm.cs 287 | *.odx.cs 288 | *.xsd.cs 289 | -------------------------------------------------------------------------------- /neon/FuncExport.cs: -------------------------------------------------------------------------------- 1 | using Neo.Compiler; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | 8 | namespace vmtool 9 | { 10 | 11 | public class FuncExport 12 | { 13 | static string ConvType(string _type) 14 | { 15 | switch (_type) 16 | { 17 | case "__Signature": 18 | return "Signature"; 19 | 20 | case "System.Boolean": 21 | return "Boolean"; 22 | 23 | case "System.Byte": 24 | case "System.SByte": 25 | case "System.Int16": 26 | case "System.UInt16": 27 | case "System.Int32": 28 | case "System.UInt32": 29 | case "System.Int64": 30 | case "System.UInt64": 31 | case "System.Numerics.BigInteger": 32 | return "Integer"; 33 | 34 | case "__Hash160": 35 | return "Hash160"; 36 | 37 | case "__Hash256": 38 | return "Hash256"; 39 | 40 | case "System.Byte[]": 41 | return "ByteArray"; 42 | 43 | case "__PublicKey": 44 | return "PublicKey"; 45 | 46 | case "System.String": 47 | return "String"; 48 | 49 | case "System.Object[]": 50 | return "Array"; 51 | 52 | case "__InteropInterface": 53 | case "IInteropInterface": 54 | return "InteropInterface"; 55 | 56 | case "System.Void": 57 | return "Void"; 58 | 59 | case "System.Object": 60 | return "Any"; 61 | } 62 | if (_type.Contains("[]")) 63 | return "Array"; 64 | 65 | return "Unknown:" + _type; 66 | } 67 | public static MyJson.JsonNode_Object Export(NeoModule module,byte[] script) 68 | { 69 | var sha256 = System.Security.Cryptography.SHA256.Create(); 70 | byte[] hash256 = sha256.ComputeHash(script); 71 | var ripemd160 = new Neo.Cryptography.RIPEMD160Managed(); 72 | var hash = ripemd160.ComputeHash(hash256); 73 | 74 | var outjson = new MyJson.JsonNode_Object(); 75 | 76 | //hash 77 | StringBuilder sb = new StringBuilder(); 78 | sb.Append("0x"); 79 | foreach (var b in hash.Reverse().ToArray()) 80 | { 81 | sb.Append(b.ToString("x02")); 82 | } 83 | outjson.SetDictValue("hash", sb.ToString()); 84 | 85 | //entrypoint 86 | outjson.SetDictValue("entrypoint", "Main"); 87 | var mainmethod = module.mapMethods[module.mainMethod]; 88 | if (mainmethod != null) 89 | { 90 | var name = mainmethod.displayName; 91 | outjson.SetDictValue("entrypoint", name); 92 | } 93 | //functions 94 | var funcsigns = new MyJson.JsonNode_Array(); 95 | outjson["functions"] = funcsigns; 96 | 97 | List names = new List(); 98 | 99 | foreach (var function in module.mapMethods) 100 | { 101 | var mm = function.Value; 102 | if (mm.inSmartContract == false) 103 | continue; 104 | if (mm.isPublic == false) 105 | continue; 106 | var ps = mm.name.Split(new char[] { ' ', '(' }, StringSplitOptions.RemoveEmptyEntries); 107 | var funcsign = new MyJson.JsonNode_Object(); 108 | 109 | funcsigns.Add(funcsign); 110 | var funcname = ps[1]; 111 | if (funcname.IndexOf("::") > 0) 112 | { 113 | var sps = funcname.Split(new string[] { "::" }, StringSplitOptions.RemoveEmptyEntries); 114 | funcname = sps.Last(); 115 | } 116 | funcsign.SetDictValue("name", function.Value.displayName); 117 | if(names.Contains(function.Value.displayName)) 118 | { 119 | throw new Exception("abi not allow same name functions"); 120 | } 121 | names.Add(function.Value.displayName); 122 | MyJson.JsonNode_Array funcparams = new MyJson.JsonNode_Array(); 123 | funcsign["parameters"] = funcparams; 124 | if (mm.paramtypes != null) 125 | { 126 | foreach (var v in mm.paramtypes) 127 | { 128 | var ptype = ConvType(v.type); 129 | var item = new MyJson.JsonNode_Object(); 130 | funcparams.Add(item); 131 | 132 | item.SetDictValue("name", v.name); 133 | item.SetDictValue("type", ptype); 134 | } 135 | } 136 | 137 | var rtype = ConvType(mm.returntype); 138 | funcsign.SetDictValue("returntype", rtype); 139 | } 140 | 141 | //events 142 | var eventsigns = new MyJson.JsonNode_Array(); 143 | outjson["events"] = eventsigns; 144 | foreach (var events in module.mapEvents) 145 | { 146 | var mm = events.Value; 147 | 148 | var ps = mm.name.Split(new char[] { ' ', '(' }, StringSplitOptions.RemoveEmptyEntries); 149 | var funcsign = new MyJson.JsonNode_Object(); 150 | 151 | eventsigns.Add(funcsign); 152 | 153 | funcsign.SetDictValue("name", events.Value.displayName); 154 | MyJson.JsonNode_Array funcparams = new MyJson.JsonNode_Array(); 155 | funcsign["parameters"] = funcparams; 156 | if (mm.paramtypes != null) 157 | { 158 | foreach (var v in mm.paramtypes) 159 | { 160 | var ptype = ConvType(v.type); 161 | var item = new MyJson.JsonNode_Object(); 162 | funcparams.Add(item); 163 | 164 | item.SetDictValue("name", v.name); 165 | item.SetDictValue("type", ptype); 166 | } 167 | } 168 | var rtype = ConvType(mm.returntype); 169 | funcsign.SetDictValue("returntype", rtype); 170 | } 171 | 172 | return outjson; 173 | } 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /neoj/JVM/java.cecil/loader/BigEndianBinaryReader.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace javaloader 4 | { 5 | public class BigEndianBinaryReader 6 | { 7 | private byte[] buf; 8 | private int pos; 9 | private int end; 10 | 11 | internal BigEndianBinaryReader(byte[] buf, int offset, int length) 12 | { 13 | this.buf = buf; 14 | this.pos = offset; 15 | this.end = checked(offset + length); 16 | if (offset < 0 || length < 0 || buf.Length - offset < length) 17 | { 18 | throw new Exception("Truncated class file"); 19 | } 20 | } 21 | 22 | internal BigEndianBinaryReader Section(uint length) 23 | { 24 | BigEndianBinaryReader br = new BigEndianBinaryReader(buf, pos, checked((int)length)); 25 | Skip(length); 26 | return br; 27 | } 28 | 29 | internal bool IsAtEnd 30 | { 31 | get 32 | { 33 | return pos == end; 34 | } 35 | } 36 | 37 | internal int Position 38 | { 39 | get 40 | { 41 | return pos; 42 | } 43 | } 44 | 45 | internal void Skip(uint count) 46 | { 47 | if (end - pos < count) 48 | { 49 | throw new Exception("Truncated class file"); 50 | } 51 | checked 52 | { 53 | pos += (int)count; 54 | } 55 | } 56 | 57 | internal byte ReadByte() 58 | { 59 | if (pos == end) 60 | { 61 | throw new Exception("Truncated class file"); 62 | } 63 | return buf[pos++]; 64 | } 65 | 66 | internal sbyte ReadSByte() 67 | { 68 | if (pos == end) 69 | { 70 | throw new Exception("Truncated class file"); 71 | } 72 | return (sbyte)buf[pos++]; 73 | } 74 | 75 | internal double ReadDouble() 76 | { 77 | return BitConverter.Int64BitsToDouble(ReadInt64()); 78 | } 79 | 80 | internal short ReadInt16() 81 | { 82 | if (end - pos < 2) 83 | { 84 | throw new Exception("Truncated class file"); 85 | } 86 | short s = (short)((buf[pos] << 8) + buf[pos + 1]); 87 | pos += 2; 88 | return s; 89 | } 90 | 91 | internal int ReadInt32() 92 | { 93 | if (end - pos < 4) 94 | { 95 | throw new Exception("Truncated class file"); 96 | } 97 | int i = (int)((buf[pos] << 24) + (buf[pos + 1] << 16) + (buf[pos + 2] << 8) + buf[pos + 3]); 98 | pos += 4; 99 | return i; 100 | } 101 | 102 | internal long ReadInt64() 103 | { 104 | if (end - pos < 8) 105 | { 106 | throw new Exception("Truncated class file"); 107 | } 108 | uint i1 = (uint)((buf[pos] << 24) + (buf[pos + 1] << 16) + (buf[pos + 2] << 8) + buf[pos + 3]); 109 | uint i2 = (uint)((buf[pos + 4] << 24) + (buf[pos + 5] << 16) + (buf[pos + 6] << 8) + buf[pos + 7]); 110 | long l = (((long)i1) << 32) + i2; 111 | pos += 8; 112 | return l; 113 | } 114 | 115 | internal float ReadSingle() 116 | { 117 | return BitConverter.ToSingle(BitConverter.GetBytes(ReadInt32()), 0); 118 | } 119 | 120 | internal string ReadString() 121 | { 122 | int len = ReadUInt16(); 123 | if (end - pos < len) 124 | { 125 | throw new Exception( " (Truncated class file)"); 126 | } 127 | // special code path for ASCII strings (which occur *very* frequently) 128 | for (int j = 0; j < len; j++) 129 | { 130 | if (buf[pos + j] == 0 || buf[pos + j] >= 128) 131 | { 132 | // NOTE we *cannot* use System.Text.UTF8Encoding, because this is *not* compatible 133 | // (esp. for embedded nulls) 134 | char[] ch = new char[len]; 135 | int l = 0; 136 | for (int i = 0; i < len; i++) 137 | { 138 | int c = buf[pos + i]; 139 | int char2, char3; 140 | switch (c >> 4) 141 | { 142 | case 0: 143 | if (c == 0) 144 | { 145 | throw new Exception( " (Illegal UTF8 string in constant pool)"); 146 | } 147 | break; 148 | case 1: 149 | case 2: 150 | case 3: 151 | case 4: 152 | case 5: 153 | case 6: 154 | case 7: 155 | // 0xxxxxxx 156 | break; 157 | case 12: 158 | case 13: 159 | // 110x xxxx 10xx xxxx 160 | char2 = buf[pos + ++i]; 161 | if ((char2 & 0xc0) != 0x80 || i >= len) 162 | { 163 | throw new Exception( " (Illegal UTF8 string in constant pool)"); 164 | } 165 | c = (((c & 0x1F) << 6) | (char2 & 0x3F)); 166 | break; 167 | case 14: 168 | // 1110 xxxx 10xx xxxx 10xx xxxx 169 | char2 = buf[pos + ++i]; 170 | char3 = buf[pos + ++i]; 171 | if ((char2 & 0xc0) != 0x80 || (char3 & 0xc0) != 0x80 || i >= len) 172 | { 173 | throw new Exception( " (Illegal UTF8 string in constant pool)"); 174 | } 175 | c = (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)); 176 | break; 177 | default: 178 | throw new Exception( " (Illegal UTF8 string in constant pool)"); 179 | } 180 | ch[l++] = (char)c; 181 | } 182 | pos += len; 183 | return new String(ch, 0, l); 184 | } 185 | } 186 | string s = System.Text.ASCIIEncoding.ASCII.GetString(buf, pos, len); 187 | pos += len; 188 | return s; 189 | } 190 | 191 | internal ushort ReadUInt16() 192 | { 193 | if (end - pos < 2) 194 | { 195 | throw new Exception("Truncated class file"); 196 | } 197 | ushort s = (ushort)((buf[pos] << 8) + buf[pos + 1]); 198 | pos += 2; 199 | return s; 200 | } 201 | 202 | internal uint ReadUInt32() 203 | { 204 | if (end - pos < 4) 205 | { 206 | throw new Exception("Truncated class file"); 207 | } 208 | uint i = (uint)((buf[pos] << 24) + (buf[pos + 1] << 16) + (buf[pos + 2] << 8) + buf[pos + 3]); 209 | pos += 4; 210 | return i; 211 | } 212 | } 213 | } -------------------------------------------------------------------------------- /neon/Program.cs: -------------------------------------------------------------------------------- 1 | using Neo.Compiler.Debugger; 2 | using Neo.Compiler.MSIL; 3 | using System; 4 | using System.IO; 5 | using System.Reflection; 6 | using System.Text; 7 | 8 | namespace Neo.Compiler 9 | { 10 | public class Program 11 | { 12 | //Console.WriteLine("helo ha:"+args[0]); //普通输出 13 | //Console.WriteLine(" 这是一个严重的问题。");//警告输出,黄字 14 | //Console.WriteLine(" 这是ee一个严重的问题。");//警告输出,带文件名行号 15 | //Console.WriteLine(" 这是一个严重的问题。");//错误输出,红字 16 | //Console.WriteLine(" 这是ee一个严重的问题。");//错误输出,带文件名 17 | //Console.WriteLine("SUCC");//输出这个表示编译成功 18 | //控制台输出约定了特别的语法 19 | public static void Main(string[] args) 20 | { 21 | 22 | //set console 23 | Console.OutputEncoding = System.Text.Encoding.UTF8; 24 | var log = new DefLogger(); 25 | log.Log("Neo.Compiler.MSIL console app v" + Assembly.GetEntryAssembly().GetName().Version); 26 | 27 | bool bCompatible = false; 28 | bool bDebug = false; 29 | string filename = null; 30 | for (var i = 0; i < args.Length; i++) 31 | { 32 | if (args[i][0] == '-') 33 | { 34 | if (args[i] == "--compatible") 35 | { 36 | bCompatible = true; 37 | } 38 | else 39 | if (args[i] == "--debug") 40 | { 41 | bDebug = true; 42 | } 43 | 44 | //other option 45 | } 46 | else 47 | { 48 | filename = args[i]; 49 | } 50 | } 51 | 52 | if (filename == null) 53 | { 54 | log.Log("need one param for DLL filename."); 55 | log.Log("[--compatible] disable nep8 function"); 56 | log.Log("[--debug] generate debugger info"); 57 | log.Log("Example:neon abc.dll --compatible"); 58 | return; 59 | } 60 | if (bCompatible) 61 | { 62 | log.Log("use --compatible no nep8"); 63 | } 64 | string onlyname = System.IO.Path.GetFileNameWithoutExtension(filename); 65 | string filepdb = onlyname + ".pdb"; 66 | var path = Path.GetDirectoryName(filename); 67 | if (!string.IsNullOrEmpty(path)) 68 | { 69 | try 70 | { 71 | Directory.SetCurrentDirectory(path); 72 | } 73 | catch 74 | { 75 | log.Log("Could not find path: " + path); 76 | Environment.Exit(-1); 77 | } 78 | } 79 | 80 | ILModule mod = new ILModule(); 81 | System.IO.Stream fs = null; 82 | System.IO.Stream fspdb = null; 83 | 84 | //open file 85 | try 86 | { 87 | fs = System.IO.File.OpenRead(filename); 88 | 89 | if (System.IO.File.Exists(filepdb)) 90 | { 91 | fspdb = System.IO.File.OpenRead(filepdb); 92 | } 93 | 94 | } 95 | catch (Exception err) 96 | { 97 | log.Log("Open File Error:" + err.ToString()); 98 | return; 99 | } 100 | //load module 101 | try 102 | { 103 | mod.LoadModule(fs, fspdb); 104 | } 105 | catch (Exception err) 106 | { 107 | log.Log("LoadModule Error:" + err.ToString()); 108 | return; 109 | } 110 | byte[] bytes = null; 111 | bool bSucc = false; 112 | string jsonstr = null; 113 | string debugmapstr = null; 114 | //convert and build 115 | try 116 | { 117 | var conv = new ModuleConverter(log); 118 | ConvOption option = new ConvOption(); 119 | option.useNep8 = !bCompatible; 120 | NeoModule am = conv.Convert(mod, option); 121 | bytes = am.Build(); 122 | log.Log("convert succ"); 123 | 124 | 125 | try 126 | { 127 | var outjson = vmtool.FuncExport.Export(am, bytes); 128 | StringBuilder sb = new StringBuilder(); 129 | outjson.ConvertToStringWithFormat(sb, 0); 130 | jsonstr = sb.ToString(); 131 | log.Log("gen abi succ"); 132 | } 133 | catch (Exception err) 134 | { 135 | log.Log("gen abi Error:" + err.ToString()); 136 | } 137 | 138 | if (bDebug) 139 | { 140 | try 141 | { 142 | var outjson = DebugInfo.ExportDebugInfo(onlyname, am); 143 | StringBuilder sb = new StringBuilder(); 144 | outjson.ConvertToStringWithFormat(sb, 0); 145 | debugmapstr = sb.ToString(); 146 | log.Log("gen debug map succ"); 147 | } 148 | catch (Exception err) 149 | { 150 | log.Log("gen debug map Error:" + err.ToString()); 151 | } 152 | } 153 | 154 | } 155 | catch (Exception err) 156 | { 157 | log.Log("Convert Error:" + err.ToString()); 158 | return; 159 | } 160 | //write bytes 161 | try 162 | { 163 | 164 | string bytesname = onlyname + ".avm"; 165 | 166 | System.IO.File.Delete(bytesname); 167 | System.IO.File.WriteAllBytes(bytesname, bytes); 168 | log.Log("write:" + bytesname); 169 | bSucc = true; 170 | } 171 | catch (Exception err) 172 | { 173 | log.Log("Write Bytes Error:" + err.ToString()); 174 | return; 175 | } 176 | try 177 | { 178 | 179 | string abiname = onlyname + ".abi.json"; 180 | 181 | System.IO.File.Delete(abiname); 182 | System.IO.File.WriteAllText(abiname, jsonstr); 183 | log.Log("write:" + abiname); 184 | bSucc = true; 185 | } 186 | catch (Exception err) 187 | { 188 | log.Log("Write abi Error:" + err.ToString()); 189 | return; 190 | } 191 | 192 | if (bDebug) 193 | { 194 | try 195 | { 196 | string debugname = onlyname + ".debug.json"; 197 | 198 | System.IO.File.Delete(debugname); 199 | System.IO.File.WriteAllText(debugname, debugmapstr); 200 | log.Log("write:" + debugname); 201 | bSucc = true; 202 | } 203 | catch (Exception err) 204 | { 205 | log.Log("Write debug Error:" + err.ToString()); 206 | return; 207 | } 208 | } 209 | 210 | try 211 | { 212 | fs.Dispose(); 213 | if (fspdb != null) 214 | fspdb.Dispose(); 215 | } 216 | catch 217 | { 218 | 219 | } 220 | 221 | if (bSucc) 222 | { 223 | log.Log("SUCC"); 224 | } 225 | } 226 | } 227 | } 228 | -------------------------------------------------------------------------------- /neoj/JVM/Converter_Common.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Numerics; 3 | 4 | namespace Neo.Compiler.JVM 5 | { 6 | public partial class ModuleConverter 7 | { 8 | private NeoCode _Insert1(VM.OpCode code, string comment, NeoMethod to, byte[] data = null) 9 | { 10 | NeoCode _code = new NeoCode(); 11 | int startaddr = addr; 12 | _code.addr = addr; 13 | { 14 | _code.debugcode = comment; 15 | _code.debugline = 0; 16 | } 17 | 18 | addr++; 19 | 20 | _code.code = code; 21 | 22 | if (data != null) 23 | { 24 | _code.bytes = data; 25 | addr += _code.bytes.Length; 26 | } 27 | to.body_Codes[startaddr] = _code; 28 | return _code; 29 | } 30 | 31 | private NeoCode _InsertPush(byte[] data, string comment, NeoMethod to) 32 | { 33 | if (data.Length == 0) return _Insert1(VM.OpCode.PUSH0, comment, to); 34 | if (data.Length <= 75) return _Insert1((VM.OpCode)data.Length, comment, to, data); 35 | byte prefixLen; 36 | VM.OpCode code; 37 | if (data.Length <= byte.MaxValue) 38 | { 39 | prefixLen = sizeof(byte); 40 | code = VM.OpCode.PUSHDATA1; 41 | } 42 | else if (data.Length <= ushort.MaxValue) 43 | { 44 | prefixLen = sizeof(ushort); 45 | code = VM.OpCode.PUSHDATA2; 46 | } 47 | else 48 | { 49 | prefixLen = sizeof(uint); 50 | code = VM.OpCode.PUSHDATA4; 51 | } 52 | byte[] bytes = new byte[data.Length + prefixLen]; 53 | Buffer.BlockCopy(BitConverter.GetBytes(data.Length), 0, bytes, 0, prefixLen); 54 | Buffer.BlockCopy(data, 0, bytes, prefixLen, data.Length); 55 | return _Insert1(code, comment, to, bytes); 56 | } 57 | 58 | private NeoCode _InsertPush(int i, string comment, NeoMethod to) 59 | { 60 | if (i == 0) return _Insert1(VM.OpCode.PUSH0, comment, to); 61 | if (i == -1) return _Insert1(VM.OpCode.PUSHM1, comment, to); 62 | if (i > 0 && i <= 16) return _Insert1((VM.OpCode)(byte)i + 0x50, comment, to); 63 | return _InsertPush(((BigInteger)i).ToByteArray(), comment, to); 64 | } 65 | 66 | private NeoCode _Convert1by1(VM.OpCode code, OpCode src, NeoMethod to, byte[] data = null) 67 | { 68 | NeoCode _code = new NeoCode(); 69 | int startaddr = addr; 70 | _code.addr = addr; 71 | if (src != null) 72 | { 73 | addrconv[src.addr] = addr; 74 | _code.debugcode = src.debugcode; 75 | _code.debugline = src.debugline; 76 | _code.debugILAddr = src.addr; 77 | _code.debugILCode = src.code.ToString(); 78 | } 79 | 80 | 81 | addr++; 82 | 83 | _code.code = code; 84 | 85 | if (data != null) 86 | { 87 | _code.bytes = data; 88 | addr += _code.bytes.Length; 89 | } 90 | to.body_Codes[startaddr] = _code; 91 | return _code; 92 | } 93 | 94 | private NeoCode _ConvertPush(byte[] data, OpCode src, NeoMethod to) 95 | { 96 | if (data.Length == 0) return _Convert1by1(VM.OpCode.PUSH0, src, to); 97 | //if (data.Length <= 75) return _Convert1by1((VM.OpCode)data.Length, src, to, data); 98 | byte prefixLen; 99 | VM.OpCode code; 100 | if (data.Length <= byte.MaxValue) 101 | { 102 | prefixLen = sizeof(byte); 103 | code = VM.OpCode.PUSHDATA1; 104 | } 105 | else if (data.Length <= ushort.MaxValue) 106 | { 107 | prefixLen = sizeof(ushort); 108 | code = VM.OpCode.PUSHDATA2; 109 | } 110 | else 111 | { 112 | prefixLen = sizeof(uint); 113 | code = VM.OpCode.PUSHDATA4; 114 | } 115 | byte[] bytes = new byte[data.Length + prefixLen]; 116 | Buffer.BlockCopy(BitConverter.GetBytes(data.Length), 0, bytes, 0, prefixLen); 117 | Buffer.BlockCopy(data, 0, bytes, prefixLen, data.Length); 118 | return _Convert1by1(code, src, to, bytes); 119 | } 120 | 121 | private NeoCode _ConvertPush(long i, OpCode src, NeoMethod to) 122 | { 123 | if (i == 0) return _Convert1by1(VM.OpCode.PUSH0, src, to); 124 | if (i == -1) return _Convert1by1(VM.OpCode.PUSHM1, src, to); 125 | if (i > 0 && i <= 16) return _Convert1by1((VM.OpCode)(byte)i + 0x50, src, to); 126 | return _ConvertPush(((BigInteger)i).ToByteArray(), src, to); 127 | } 128 | 129 | private void _insertBeginCode(JavaMethod from, NeoMethod to) 130 | { 131 | //压入槽位栈 132 | _InsertPush(from.MaxVariableIndex + 1, "begincode", to); 133 | _Insert1(VM.OpCode.NEWARRAY, "", to); 134 | _Insert1(VM.OpCode.TOALTSTACK, "", to); 135 | 136 | for (var i = 0; i < from.paramTypes.Count; i++) 137 | { 138 | int pos = 0; 139 | if (from.method.IsStatic) 140 | { 141 | pos = from.argTable[i]; 142 | } 143 | else 144 | {//非静态0号是this 145 | pos = from.argTable[i + 1]; 146 | } 147 | _Insert1(VM.OpCode.DUPFROMALTSTACK, "init param:" + i, to); 148 | _InsertPush(pos, "", to); 149 | _InsertPush(2, "", to); 150 | _Insert1(VM.OpCode.ROLL, "", to); 151 | _Insert1(VM.OpCode.SETITEM, "", to); 152 | } 153 | ////初始化临时槽位位置 154 | //to.addVariablesCount = from.addLocal_VariablesCount; 155 | //for (var i = 0; i < from.addLocal_VariablesCount; i++) 156 | //{ 157 | // //to.body_Variables.Add(new JavaParam(src.name, src.type)); 158 | // _InsertPush(0, "body_Variables init", to); 159 | //} 160 | } 161 | 162 | private void _insertEndCode(JavaMethod from, NeoMethod to, OpCode src) 163 | { 164 | //占位不谢 165 | //_Convert1by1(VM.OpCode.NOP, src, to); 166 | 167 | ////移除临时槽位 168 | ////drop body_Variables 169 | //for (var i = 0; i < from.addLocal_VariablesCount; i++) 170 | //{ 171 | // _Insert1(VM.OpCode.DEPTH, "body_Variables drop", to, null); 172 | // _Insert1(VM.OpCode.DEC, null, to, null); 173 | 174 | // //push olddepth 175 | // _Insert1(VM.OpCode.FROMALTSTACK, null, to); 176 | // _Insert1(VM.OpCode.DUP, null, to); 177 | // _Insert1(VM.OpCode.TOALTSTACK, null, to); 178 | // //(d-1)-olddepth 179 | // _Insert1(VM.OpCode.SUB, null, to); 180 | 181 | // _Insert1(VM.OpCode.XDROP, null, to, null); 182 | //} 183 | ////移除参数槽位 184 | //for (var i = 0; i < from.paramTypes.Count; i++) 185 | //{ 186 | // //d 187 | // _Insert1(VM.OpCode.DEPTH, "param drop", to, null); 188 | 189 | // //push olddepth 190 | // _Insert1(VM.OpCode.FROMALTSTACK, null, to); 191 | // _Insert1(VM.OpCode.DUP, null, to); 192 | // _Insert1(VM.OpCode.DEC, null, to);//深度-1 193 | // _Insert1(VM.OpCode.TOALTSTACK, null, to); 194 | 195 | // //(d)-olddepth 196 | // _Insert1(VM.OpCode.SUB, null, to); 197 | 198 | // _Insert1(VM.OpCode.XDROP, null, to, null); 199 | 200 | //} 201 | 202 | //移除深度临时栈 203 | _Insert1(VM.OpCode.FROMALTSTACK, "", to); 204 | _Insert1(VM.OpCode.DROP, "", to); 205 | } 206 | } 207 | } 208 | -------------------------------------------------------------------------------- /neoa/ASM/Instruction.cs: -------------------------------------------------------------------------------- 1 | using Neo.VM; 2 | using System; 3 | using System.Globalization; 4 | using System.Numerics; 5 | using System.Text; 6 | 7 | namespace Neo.Compiler.ASM 8 | { 9 | internal class Instruction : Semanteme 10 | { 11 | private const string ERR_INCORRECT_NUMBER = "incorrect number of arguments"; 12 | private const string ERR_INVALID_ARGUMENT = "invalid argument"; 13 | private const string ERR_SYNTAX_ERROR = "syntax error"; 14 | 15 | public InstructionName Name; 16 | public string[] Arguments; 17 | public byte[] Code; 18 | 19 | private byte MakeScriptOp() 20 | { 21 | return (byte)(OpCode)Enum.Parse(typeof(OpCode), Name.ToString()); 22 | } 23 | 24 | private byte[] ParseHex(string hex) 25 | { 26 | if (hex == null || hex.Length == 0) 27 | return new byte[0]; 28 | if (hex.Length % 2 == 1) 29 | throw new CompilerException(LineNumber, ERR_INVALID_ARGUMENT); 30 | if (hex.StartsWith("0x")) hex = hex.Substring(2); 31 | byte[] result = new byte[hex.Length / 2]; 32 | for (int i = 0; i < result.Length; i++) 33 | result[i] = byte.Parse(hex.Substring(i * 2, 2), NumberStyles.AllowHexSpecifier); 34 | return result; 35 | } 36 | 37 | public void Process() 38 | { 39 | switch (Name) 40 | { 41 | case InstructionName.PUSH: 42 | Code = ProcessPush(); 43 | break; 44 | case InstructionName.NOP: 45 | case InstructionName.RET: 46 | case InstructionName.DUPFROMALTSTACK: 47 | case InstructionName.TOALTSTACK: 48 | case InstructionName.FROMALTSTACK: 49 | case InstructionName.XDROP: 50 | case InstructionName.XSWAP: 51 | case InstructionName.XTUCK: 52 | case InstructionName.DEPTH: 53 | case InstructionName.DROP: 54 | case InstructionName.DUP: 55 | case InstructionName.NIP: 56 | case InstructionName.OVER: 57 | case InstructionName.PICK: 58 | case InstructionName.ROLL: 59 | case InstructionName.ROT: 60 | case InstructionName.SWAP: 61 | case InstructionName.TUCK: 62 | case InstructionName.CAT: 63 | case InstructionName.SUBSTR: 64 | case InstructionName.LEFT: 65 | case InstructionName.RIGHT: 66 | case InstructionName.SIZE: 67 | case InstructionName.INVERT: 68 | case InstructionName.AND: 69 | case InstructionName.OR: 70 | case InstructionName.XOR: 71 | case InstructionName.EQUAL: 72 | case InstructionName.INC: 73 | case InstructionName.DEC: 74 | case InstructionName.SIGN: 75 | case InstructionName.NEGATE: 76 | case InstructionName.ABS: 77 | case InstructionName.NOT: 78 | case InstructionName.NZ: 79 | case InstructionName.ADD: 80 | case InstructionName.SUB: 81 | case InstructionName.MUL: 82 | case InstructionName.DIV: 83 | case InstructionName.MOD: 84 | case InstructionName.SHL: 85 | case InstructionName.SHR: 86 | case InstructionName.BOOLAND: 87 | case InstructionName.BOOLOR: 88 | case InstructionName.NUMEQUAL: 89 | case InstructionName.NUMNOTEQUAL: 90 | case InstructionName.LT: 91 | case InstructionName.GT: 92 | case InstructionName.LTE: 93 | case InstructionName.GTE: 94 | case InstructionName.MIN: 95 | case InstructionName.MAX: 96 | case InstructionName.WITHIN: 97 | case InstructionName.SHA1: 98 | case InstructionName.SHA256: 99 | case InstructionName.HASH160: 100 | case InstructionName.HASH256: 101 | case InstructionName.CHECKSIG: 102 | case InstructionName.CHECKMULTISIG: 103 | case InstructionName.ARRAYSIZE: 104 | case InstructionName.PACK: 105 | case InstructionName.UNPACK: 106 | case InstructionName.PICKITEM: 107 | case InstructionName.SETITEM: 108 | case InstructionName.NEWARRAY: 109 | case InstructionName.NEWSTRUCT: 110 | case InstructionName.THROW: 111 | case InstructionName.THROWIFNOT: 112 | Code = ProcessOthers(); 113 | break; 114 | case InstructionName.JMP: 115 | case InstructionName.JMPIF: 116 | case InstructionName.JMPIFNOT: 117 | case InstructionName.CALL: 118 | Code = ProcessJump(); 119 | break; 120 | case InstructionName.APPCALL: 121 | case InstructionName.TAILCALL: 122 | Code = ProcessAppCall(); 123 | break; 124 | case InstructionName.SYSCALL: 125 | Code = ProcessSysCall(); 126 | break; 127 | default: 128 | throw new CompilerException(LineNumber, ERR_SYNTAX_ERROR); 129 | } 130 | } 131 | 132 | private byte[] ProcessAppCall() 133 | { 134 | if (Arguments.Length != 1) throw new CompilerException(LineNumber, ERR_INCORRECT_NUMBER); 135 | byte[] hash = ParseHex(Arguments[0]); 136 | if (hash.Length != 20) throw new CompilerException(LineNumber, ERR_INVALID_ARGUMENT); 137 | byte[] result = new byte[21]; 138 | result[0] = MakeScriptOp(); 139 | Buffer.BlockCopy(hash, 0, result, 1, 20); 140 | return result; 141 | } 142 | 143 | internal byte[] ProcessJump(short offset = 0) 144 | { 145 | if (Arguments.Length != 1) throw new CompilerException(LineNumber, ERR_INCORRECT_NUMBER); 146 | byte[] data = BitConverter.GetBytes(offset); 147 | byte[] result = new byte[3]; 148 | result[0] = MakeScriptOp(); 149 | Buffer.BlockCopy(data, 0, result, 1, sizeof(short)); 150 | return result; 151 | } 152 | 153 | private byte[] ProcessOthers() 154 | { 155 | if (Arguments.Length != 0) throw new CompilerException(LineNumber, ERR_INCORRECT_NUMBER); 156 | return new[] { MakeScriptOp() }; 157 | } 158 | 159 | private byte[] ProcessPush() 160 | { 161 | if (Arguments.Length != 1) throw new CompilerException(LineNumber, ERR_INCORRECT_NUMBER); 162 | BigInteger bi; 163 | if (BigInteger.TryParse(Arguments[0], out bi)) 164 | using (ScriptBuilder sb = new ScriptBuilder()) 165 | return sb.EmitPush(bi).ToArray(); 166 | else if (string.Compare(Arguments[0], "true", true) == 0) 167 | return new[] { (byte)OpCode.PUSHT }; 168 | else if (string.Compare(Arguments[0], "false", true) == 0) 169 | return new[] { (byte)OpCode.PUSHF }; 170 | else if (Arguments[0].StartsWith("0x")) 171 | using (ScriptBuilder sb = new ScriptBuilder()) 172 | return sb.EmitPush(ParseHex(Arguments[0])).ToArray(); 173 | else 174 | throw new CompilerException(LineNumber, ERR_INVALID_ARGUMENT); 175 | } 176 | 177 | private byte[] ProcessSysCall() 178 | { 179 | if (Arguments.Length != 1) throw new CompilerException(LineNumber, ERR_INCORRECT_NUMBER); 180 | byte[] data = Encoding.ASCII.GetBytes(Arguments[0]); 181 | if (data.Length > 252) throw new CompilerException(LineNumber, ERR_INVALID_ARGUMENT); 182 | byte[] result = new byte[data.Length + 2]; 183 | result[0] = (byte)OpCode.SYSCALL; 184 | result[1] = (byte)data.Length; 185 | Buffer.BlockCopy(data, 0, result, 2, data.Length); 186 | return result; 187 | } 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /neoj/NeoModule.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Security.Cryptography; 3 | using System.Text; 4 | 5 | namespace Neo.Compiler 6 | { 7 | public class NeoModule 8 | { 9 | public NeoModule(ILogger logger) 10 | { 11 | this.logger = logger; 12 | } 13 | ILogger logger; 14 | //小蚁没类型,只有方法 15 | public SortedDictionary total_Codes = new SortedDictionary(); 16 | public byte[] Build() 17 | { 18 | List bytes = new List(); 19 | foreach (var c in this.total_Codes.Values) 20 | { 21 | bytes.Add((byte)c.code); 22 | if (c.bytes != null) 23 | for (var i = 0; i < c.bytes.Length; i++) 24 | { 25 | bytes.Add(c.bytes[i]); 26 | } 27 | } 28 | return bytes.ToArray(); 29 | //将body链接,生成this.code byte[] 30 | //并计算 this.codehash byte[] 31 | } 32 | public string mainMethod; 33 | public ConvOption option; 34 | public Dictionary mapMethods = new Dictionary(); 35 | public Dictionary mapEvents = new Dictionary(); 36 | //public Dictionary codes = new Dictionary(); 37 | //public byte[] GetScript(byte[] script_hash) 38 | //{ 39 | // string strhash = ""; 40 | // foreach (var b in script_hash) 41 | // { 42 | // strhash += b.ToString("X02"); 43 | // } 44 | // return codes[strhash]; 45 | //} 46 | public string GenJson() 47 | { 48 | MyJson.JsonNode_Object json = new MyJson.JsonNode_Object(); 49 | json["__name__"] = new MyJson.JsonNode_ValueString("neomodule."); 50 | 51 | //code 52 | var jsoncode = new MyJson.JsonNode_Array(); 53 | json["code"] = jsoncode; 54 | foreach (var c in this.total_Codes.Values) 55 | { 56 | jsoncode.Add(c.GenJson()); 57 | } 58 | //code bytes 59 | var code = this.Build(); 60 | var codestr = ""; 61 | foreach (var c in code) 62 | { 63 | codestr += c.ToString("X02"); 64 | } 65 | json.SetDictValue("codebin", codestr); 66 | 67 | //calls 68 | MyJson.JsonNode_Object methodinfo = new MyJson.JsonNode_Object(); 69 | json["call"] = methodinfo; 70 | foreach (var m in this.mapMethods) 71 | { 72 | methodinfo[m.Key] = m.Value.GenJson(); 73 | } 74 | 75 | 76 | StringBuilder sb = new StringBuilder(); 77 | json.ConvertToStringWithFormat(sb, 4); 78 | return sb.ToString(); 79 | } 80 | public void FromJson(string json) 81 | { 82 | 83 | } 84 | SHA1 sha1 = SHA1.Create(); 85 | public Dictionary staticfields = new Dictionary(); 86 | 87 | } 88 | public class NeoMethod 89 | { 90 | public string _namespace; 91 | public string name; 92 | public string displayName; 93 | public List paramtypes = new List(); 94 | public string returntype; 95 | public bool isPublic = true; 96 | public bool inSmartContract; 97 | //临时变量 98 | public List body_Variables = new List(); 99 | 100 | //临时记录在此,会合并到一起 101 | public SortedDictionary body_Codes = new SortedDictionary(); 102 | public int funcaddr; 103 | public MyJson.JsonNode_Object GenJson() 104 | { 105 | MyJson.JsonNode_Object json = new MyJson.JsonNode_Object(); 106 | json.SetDictValue("name", this.name); 107 | var sha1 = SHA1.Create(); 108 | 109 | json.SetDictValue("returntype", this.returntype); 110 | 111 | json.SetDictValue("paramcount", this.paramtypes.Count); 112 | MyJson.JsonNode_Array jsonparams = new MyJson.JsonNode_Array(); 113 | json.SetDictValue("params", jsonparams); 114 | for (var i = 0; i < this.paramtypes.Count; i++) 115 | { 116 | MyJson.JsonNode_Object item = new MyJson.JsonNode_Object(); 117 | item.SetDictValue("name", this.paramtypes[i].name); 118 | item.SetDictValue("type", this.paramtypes[i].type); 119 | jsonparams.Add(item); 120 | } 121 | return json; 122 | } 123 | public void FromJson(MyJson.JsonNode_Object json) 124 | { 125 | 126 | } 127 | //public byte[] Build() 128 | //{ 129 | // List bytes = new List(); 130 | // foreach (var c in this.body_Codes.Values) 131 | // { 132 | // bytes.Add((byte)c.code); 133 | // if (c.bytes != null) 134 | // for (var i = 0; i < c.bytes.Length; i++) 135 | // { 136 | // bytes.Add(c.bytes[i]); 137 | // } 138 | // } 139 | // return bytes.ToArray(); 140 | // //将body链接,生成this.code byte[] 141 | // //并计算 this.codehash byte[] 142 | //} 143 | public string lastsfieldname =null;//最后一个加载的静态成员的名字,仅event使用 144 | 145 | public int lastparam = -1;//最后一个加载的参数对应 146 | public int lastCast = -1; 147 | } 148 | public class NeoEvent 149 | { 150 | public string _namespace; 151 | public string name; 152 | public string displayName; 153 | public List paramtypes = new List(); 154 | public string returntype; 155 | } 156 | 157 | public class NeoCode 158 | { 159 | public VM.OpCode code = VM.OpCode.NOP; 160 | public int addr; 161 | public byte[] bytes; 162 | public string debugcode; 163 | public int debugline = -1; 164 | public int debugILAddr = -1; 165 | public string debugILCode; 166 | public bool needfix = false;//lateparse tag 167 | public bool needfixfunc = false; 168 | public int srcaddr; 169 | public int[] srcaddrswitch; 170 | public string srcfunc; 171 | public override string ToString() 172 | { 173 | //string info = "AL_" + addr.ToString("X04") + " " + code.ToString(); 174 | //if (bytes != null) 175 | // info += " len=" + bytes.Length; 176 | //if (debugcode != null && debugline >= 0) 177 | //{ 178 | // info += " " + debugcode + "(" + debugline + ")"; 179 | //} 180 | 181 | string info = "" + addr.ToString("X04") + " " + code.ToString(); 182 | for (var j = 0; j < 16 - code.ToString().Length; j++) 183 | { 184 | info += " "; 185 | } 186 | info += "["; 187 | if (bytes != null) 188 | { 189 | foreach (var c in bytes) 190 | { 191 | info += c.ToString("X02"); 192 | } 193 | } 194 | info += "]"; 195 | 196 | if (debugcode != null && debugline >= 0) 197 | { 198 | info += "//" + debugcode + "(" + debugline + ")"; 199 | } 200 | return info; 201 | } 202 | public MyJson.JsonNode_ValueString GenJson() 203 | { 204 | MyJson.JsonNode_Object json = new MyJson.JsonNode_Object(); 205 | string info = "" + addr.ToString("X04") + " " + code.ToString(); 206 | for (var j = 0; j < 16 - code.ToString().Length; j++) 207 | { 208 | info += " "; 209 | } 210 | info += "["; 211 | if (bytes != null) 212 | { 213 | foreach (var c in bytes) 214 | { 215 | info += c.ToString("X02"); 216 | } 217 | } 218 | info += "]"; 219 | 220 | if (debugILCode != null && debugILAddr >= 0) 221 | { 222 | info += ""; 223 | } 224 | if (debugcode != null && debugline >= 0) 225 | { 226 | info += "//" + debugcode + "(" + debugline + ")"; 227 | } 228 | return new MyJson.JsonNode_ValueString(info); 229 | } 230 | public void FromJson(MyJson.JsonNode_Object json) 231 | { 232 | 233 | } 234 | } 235 | public class NeoParam 236 | { 237 | public NeoParam(string name, string type) 238 | { 239 | this.name = name; 240 | this.type = type; 241 | } 242 | public string name 243 | { 244 | get; 245 | private set; 246 | } 247 | public string type 248 | { 249 | get; 250 | private set; 251 | } 252 | public override string ToString() 253 | { 254 | return type + " " + name; 255 | } 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /neon/NeoModule.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Security.Cryptography; 3 | using System.Text; 4 | 5 | namespace Neo.Compiler 6 | { 7 | public class NeoModule 8 | { 9 | public NeoModule(ILogger logger) 10 | { 11 | this.logger = logger; 12 | } 13 | ILogger logger; 14 | //小蚁没类型,只有方法 15 | public SortedDictionary total_Codes = new SortedDictionary(); 16 | public byte[] Build() 17 | { 18 | List bytes = new List(); 19 | foreach (var c in this.total_Codes.Values) 20 | { 21 | bytes.Add((byte)c.code); 22 | if (c.bytes != null) 23 | for (var i = 0; i < c.bytes.Length; i++) 24 | { 25 | bytes.Add(c.bytes[i]); 26 | } 27 | } 28 | return bytes.ToArray(); 29 | //将body链接,生成this.code byte[] 30 | //并计算 this.codehash byte[] 31 | } 32 | public string mainMethod; 33 | public ConvOption option; 34 | public Dictionary mapMethods = new Dictionary(); 35 | public Dictionary mapEvents = new Dictionary(); 36 | //public Dictionary codes = new Dictionary(); 37 | //public byte[] GetScript(byte[] script_hash) 38 | //{ 39 | // string strhash = ""; 40 | // foreach (var b in script_hash) 41 | // { 42 | // strhash += b.ToString("X02"); 43 | // } 44 | // return codes[strhash]; 45 | //} 46 | public string GenJson() 47 | { 48 | MyJson.JsonNode_Object json = new MyJson.JsonNode_Object(); 49 | json["__name__"] = new MyJson.JsonNode_ValueString("neomodule."); 50 | 51 | //code 52 | var jsoncode = new MyJson.JsonNode_Array(); 53 | json["code"] = jsoncode; 54 | foreach (var c in this.total_Codes.Values) 55 | { 56 | jsoncode.Add(c.GenJson()); 57 | } 58 | //code bytes 59 | var code = this.Build(); 60 | var codestr = ""; 61 | foreach (var c in code) 62 | { 63 | codestr += c.ToString("X02"); 64 | } 65 | json.SetDictValue("codebin", codestr); 66 | 67 | //calls 68 | MyJson.JsonNode_Object methodinfo = new MyJson.JsonNode_Object(); 69 | json["call"] = methodinfo; 70 | foreach (var m in this.mapMethods) 71 | { 72 | methodinfo[m.Key] = m.Value.GenJson(); 73 | } 74 | 75 | 76 | StringBuilder sb = new StringBuilder(); 77 | json.ConvertToStringWithFormat(sb, 4); 78 | return sb.ToString(); 79 | } 80 | public void FromJson(string json) 81 | { 82 | 83 | } 84 | SHA1 sha1 = SHA1.Create(); 85 | public Dictionary staticfields = new Dictionary(); 86 | 87 | } 88 | public class NeoMethod 89 | { 90 | public string _namespace; 91 | public string name; 92 | public string displayName; 93 | public List paramtypes = new List(); 94 | public string returntype; 95 | public bool isPublic = true; 96 | public bool inSmartContract; 97 | //临时变量 98 | public List body_Variables = new List(); 99 | 100 | //临时记录在此,会合并到一起 101 | public SortedDictionary body_Codes = new SortedDictionary(); 102 | public int funcaddr; 103 | public MyJson.JsonNode_Object GenJson() 104 | { 105 | MyJson.JsonNode_Object json = new MyJson.JsonNode_Object(); 106 | json.SetDictValue("name", this.name); 107 | var sha1 = SHA1.Create(); 108 | 109 | json.SetDictValue("returntype", this.returntype); 110 | 111 | json.SetDictValue("paramcount", this.paramtypes.Count); 112 | MyJson.JsonNode_Array jsonparams = new MyJson.JsonNode_Array(); 113 | json.SetDictValue("params", jsonparams); 114 | for (var i = 0; i < this.paramtypes.Count; i++) 115 | { 116 | MyJson.JsonNode_Object item = new MyJson.JsonNode_Object(); 117 | item.SetDictValue("name", this.paramtypes[i].name); 118 | item.SetDictValue("type", this.paramtypes[i].type); 119 | jsonparams.Add(item); 120 | } 121 | return json; 122 | } 123 | public void FromJson(MyJson.JsonNode_Object json) 124 | { 125 | 126 | } 127 | //public byte[] Build() 128 | //{ 129 | // List bytes = new List(); 130 | // foreach (var c in this.body_Codes.Values) 131 | // { 132 | // bytes.Add((byte)c.code); 133 | // if (c.bytes != null) 134 | // for (var i = 0; i < c.bytes.Length; i++) 135 | // { 136 | // bytes.Add(c.bytes[i]); 137 | // } 138 | // } 139 | // return bytes.ToArray(); 140 | // //将body链接,生成this.code byte[] 141 | // //并计算 this.codehash byte[] 142 | //} 143 | public string lastsfieldname =null;//最后一个加载的静态成员的名字,仅event使用 144 | 145 | public int lastparam = -1;//最后一个加载的参数对应 146 | public int lastCast = -1; 147 | } 148 | public class NeoEvent 149 | { 150 | public string _namespace; 151 | public string name; 152 | public string displayName; 153 | public List paramtypes = new List(); 154 | public string returntype; 155 | } 156 | 157 | public class NeoCode 158 | { 159 | public VM.OpCode code = VM.OpCode.NOP; 160 | public int addr; 161 | public byte[] bytes; 162 | public string debugcode; 163 | public int debugline = -1; 164 | public int debugILAddr = -1; 165 | public string debugILCode; 166 | public bool needfix = false;//lateparse tag 167 | public bool needfixfunc = false; 168 | public int srcaddr; 169 | public int[] srcaddrswitch; 170 | public string srcfunc; 171 | public override string ToString() 172 | { 173 | //string info = "AL_" + addr.ToString("X04") + " " + code.ToString(); 174 | //if (bytes != null) 175 | // info += " len=" + bytes.Length; 176 | //if (debugcode != null && debugline >= 0) 177 | //{ 178 | // info += " " + debugcode + "(" + debugline + ")"; 179 | //} 180 | 181 | string info = "" + addr.ToString("X04") + " " + code.ToString(); 182 | for (var j = 0; j < 16 - code.ToString().Length; j++) 183 | { 184 | info += " "; 185 | } 186 | info += "["; 187 | if (bytes != null) 188 | { 189 | foreach (var c in bytes) 190 | { 191 | info += c.ToString("X02"); 192 | } 193 | } 194 | info += "]"; 195 | 196 | if (debugcode != null && debugline >= 0) 197 | { 198 | info += "//" + debugcode + "(" + debugline + ")"; 199 | } 200 | return info; 201 | } 202 | public MyJson.JsonNode_ValueString GenJson() 203 | { 204 | MyJson.JsonNode_Object json = new MyJson.JsonNode_Object(); 205 | string info = "" + addr.ToString("X04") + " " + code.ToString(); 206 | for (var j = 0; j < 16 - code.ToString().Length; j++) 207 | { 208 | info += " "; 209 | } 210 | info += "["; 211 | if (bytes != null) 212 | { 213 | foreach (var c in bytes) 214 | { 215 | info += c.ToString("X02"); 216 | } 217 | } 218 | info += "]"; 219 | 220 | if (debugILCode != null && debugILAddr >= 0) 221 | { 222 | info += ""; 223 | } 224 | if (debugcode != null && debugline >= 0) 225 | { 226 | info += "//" + debugcode + "(" + debugline + ")"; 227 | } 228 | return new MyJson.JsonNode_ValueString(info); 229 | } 230 | public void FromJson(MyJson.JsonNode_Object json) 231 | { 232 | 233 | } 234 | } 235 | public class NeoParam 236 | { 237 | public NeoParam(string name, string type) 238 | { 239 | this.name = name; 240 | this.type = type; 241 | } 242 | public string name 243 | { 244 | get; 245 | private set; 246 | } 247 | public string type 248 | { 249 | get; 250 | private set; 251 | } 252 | public override string ToString() 253 | { 254 | return type + " " + name; 255 | } 256 | } 257 | } 258 | -------------------------------------------------------------------------------- /neon/MSIL/CctorSubVM.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading.Tasks; 6 | 7 | namespace Neo.Compiler.MSIL 8 | { 9 | class CctorSubVM 10 | { 11 | static Stack calcStack; 12 | public static object Dup(object src) 13 | { 14 | if (src.GetType() == typeof(byte[])) 15 | { 16 | byte[] _src = (byte[])src; 17 | return _src; 18 | } 19 | else if (src.GetType() == typeof(int)) 20 | { 21 | int v = (int)src; 22 | return v; 23 | } 24 | else if (src.GetType() == typeof(string)) 25 | { 26 | string v = (string)src; 27 | string v2 = v; 28 | return v2; 29 | } 30 | else if (src.GetType() == typeof(Boolean)) 31 | { 32 | Boolean v = (Boolean)src; 33 | return v; 34 | } 35 | else 36 | { 37 | return null; 38 | } 39 | } 40 | public static byte[] HexString2Bytes(string str) 41 | { 42 | byte[] outd = new byte[str.Length / 2]; 43 | for (var i = 0; i < str.Length / 2; i++) 44 | { 45 | outd[i] = byte.Parse(str.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber); 46 | } 47 | return outd; 48 | } 49 | public static void Parse(ILMethod from, NeoModule to) 50 | { 51 | calcStack = new Stack(); 52 | bool bEnd = false; 53 | foreach (var src in from.body_Codes.Values) 54 | { 55 | if (bEnd) 56 | break; 57 | 58 | switch (src.code) 59 | { 60 | case CodeEx.Ret: 61 | bEnd = true; 62 | break; 63 | case CodeEx.Ldc_I4_M1: 64 | calcStack.Push((int)-1); 65 | break; 66 | case CodeEx.Ldc_I4_0: 67 | calcStack.Push((int)0); 68 | break; 69 | case CodeEx.Ldc_I4_1: 70 | calcStack.Push((int)1); 71 | break; 72 | case CodeEx.Ldc_I4_2: 73 | calcStack.Push((int)2); 74 | break; 75 | case CodeEx.Ldc_I4_3: 76 | calcStack.Push((int)3); 77 | break; 78 | case CodeEx.Ldc_I4_4: 79 | calcStack.Push((int)4); 80 | break; 81 | case CodeEx.Ldc_I4_5: 82 | calcStack.Push((int)5); 83 | break; 84 | case CodeEx.Ldc_I4_6: 85 | calcStack.Push((int)6); 86 | break; 87 | case CodeEx.Ldc_I4_7: 88 | calcStack.Push((int)7); 89 | break; 90 | case CodeEx.Ldc_I4_8: 91 | calcStack.Push((int)8); 92 | break; 93 | case CodeEx.Ldc_I4: 94 | case CodeEx.Ldc_I4_S: 95 | calcStack.Push((int)src.tokenI32); 96 | break; 97 | case CodeEx.Ldc_I8: 98 | calcStack.Push((long)src.tokenI64); 99 | break; 100 | case CodeEx.Newarr: 101 | { 102 | if (src.tokenType == "System.Byte") 103 | { 104 | var count = (int)calcStack.Pop(); 105 | byte[] data = new byte[count]; 106 | calcStack.Push(data); 107 | } 108 | else 109 | { 110 | throw new Exception("only byte[] can be defined in here."); 111 | } 112 | } 113 | break; 114 | case CodeEx.Dup: 115 | { 116 | var _src = calcStack.Peek(); 117 | var _dest = Dup(_src); 118 | calcStack.Push(_dest); 119 | } 120 | break; 121 | case CodeEx.Ldtoken: 122 | { 123 | calcStack.Push(src.tokenUnknown); 124 | } 125 | break; 126 | case CodeEx.Ldstr: 127 | { 128 | calcStack.Push(src.tokenStr); 129 | } 130 | break; 131 | case CodeEx.Call: 132 | { 133 | var m = src.tokenUnknown as Mono.Cecil.MethodReference; 134 | if (m.DeclaringType.FullName == "System.Runtime.CompilerServices.RuntimeHelpers" && m.Name == "InitializeArray") 135 | { 136 | var p1 = (byte[])calcStack.Pop(); 137 | var p2 = (byte[])calcStack.Pop(); 138 | for (var i = 0; i < p2.Length; i++) 139 | { 140 | p2[i] = p1[i]; 141 | } 142 | } 143 | else if (m.DeclaringType.FullName == "System.Numerics.BigInteger" && m.Name == "op_Implicit") 144 | { 145 | var type = m.Parameters[0].ParameterType.FullName; 146 | if (type == "System.UInt64") 147 | { 148 | var p = (ulong)(long)calcStack.Pop(); 149 | calcStack.Push(new System.Numerics.BigInteger(p).ToByteArray()); 150 | } 151 | else if (type == "System.UInt32") 152 | { 153 | var p = (ulong)(int)calcStack.Pop(); 154 | calcStack.Push(new System.Numerics.BigInteger(p).ToByteArray()); 155 | } 156 | else if (type == "System.Int64") 157 | { 158 | var p = (long)calcStack.Pop(); 159 | calcStack.Push(new System.Numerics.BigInteger(p).ToByteArray()); 160 | } 161 | else 162 | { 163 | var p =(int)calcStack.Pop(); 164 | calcStack.Push(new System.Numerics.BigInteger(p).ToByteArray()); 165 | } 166 | } 167 | else 168 | { 169 | foreach (var attr in m.Resolve().CustomAttributes) 170 | { 171 | if (attr.AttributeType.FullName == "Neo.SmartContract.Framework.NonemitWithConvertAttribute") 172 | { 173 | var text = (string)calcStack.Pop(); 174 | var value = (int)attr.ConstructorArguments[0].Value; 175 | var type = attr.ConstructorArguments[0].Type.Resolve(); 176 | string attrname = ""; 177 | foreach (var f in type.Fields) 178 | { 179 | if (f.Constant != null && (int)f.Constant == value) 180 | { 181 | attrname = f.Name; 182 | break; 183 | } 184 | } 185 | if (attrname == "ToScriptHash")//AddressString2ScriptHashBytes to bytes 186 | { 187 | var bytes = NEO.AllianceOfThinWallet.Cryptography.Base58.Decode(text); 188 | var hash = bytes.Skip(1).Take(20).ToArray(); 189 | calcStack.Push(hash); 190 | } 191 | else if (attrname == "HexToBytes")//HexString2Bytes to bytes[] 192 | { 193 | if (text.IndexOf("0x") == 0) text = text.Substring(2); 194 | var hex = HexString2Bytes(text); 195 | calcStack.Push(hex); 196 | } 197 | } 198 | } 199 | } 200 | } 201 | break; 202 | case CodeEx.Stsfld: 203 | { 204 | var field = src.tokenUnknown as Mono.Cecil.FieldReference; 205 | var fname = field.DeclaringType.FullName + "::" + field.Name; 206 | to.staticfields[fname] = calcStack.Pop(); 207 | } 208 | break; 209 | case CodeEx.Stelem_I1: 210 | { 211 | var v =(byte)(int)calcStack.Pop(); 212 | var index =(int)calcStack.Pop(); 213 | var array = calcStack.Pop() as byte[]; 214 | array[index] = v; 215 | } 216 | break; 217 | } 218 | } 219 | 220 | } 221 | } 222 | } 223 | -------------------------------------------------------------------------------- /neon/MSIL/Conv_Common.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Numerics; 3 | 4 | namespace Neo.Compiler.MSIL 5 | { 6 | /// 7 | /// 从ILCode 向小蚁 VM 转换的转换器 8 | /// 9 | public partial class ModuleConverter 10 | { 11 | private NeoCode _Insert1(VM.OpCode code, string comment, NeoMethod to, byte[] data = null) 12 | { 13 | NeoCode _code = new NeoCode(); 14 | int startaddr = addr; 15 | _code.addr = addr; 16 | { 17 | _code.debugcode = comment; 18 | _code.debugline = 0; 19 | } 20 | 21 | addr++; 22 | 23 | _code.code = code; 24 | 25 | if (data != null) 26 | { 27 | _code.bytes = data; 28 | addr += _code.bytes.Length; 29 | } 30 | to.body_Codes[startaddr] = _code; 31 | return _code; 32 | } 33 | 34 | private NeoCode _InsertPush(byte[] data, string comment, NeoMethod to) 35 | { 36 | if (data.Length == 0) return _Insert1(VM.OpCode.PUSH0, comment, to); 37 | if (data.Length <= 75) return _Insert1((VM.OpCode)data.Length, comment, to, data); 38 | byte prefixLen; 39 | VM.OpCode code; 40 | if (data.Length <= byte.MaxValue) 41 | { 42 | prefixLen = sizeof(byte); 43 | code = VM.OpCode.PUSHDATA1; 44 | } 45 | else if (data.Length <= ushort.MaxValue) 46 | { 47 | prefixLen = sizeof(ushort); 48 | code = VM.OpCode.PUSHDATA2; 49 | } 50 | else 51 | { 52 | prefixLen = sizeof(uint); 53 | code = VM.OpCode.PUSHDATA4; 54 | } 55 | byte[] bytes = new byte[data.Length + prefixLen]; 56 | Buffer.BlockCopy(BitConverter.GetBytes(data.Length), 0, bytes, 0, prefixLen); 57 | Buffer.BlockCopy(data, 0, bytes, prefixLen, data.Length); 58 | return _Insert1(code, comment, to, bytes); 59 | } 60 | 61 | private NeoCode _InsertPush(int i, string comment, NeoMethod to) 62 | { 63 | if (i == 0) return _Insert1(VM.OpCode.PUSH0, comment, to); 64 | if (i == -1) return _Insert1(VM.OpCode.PUSHM1, comment, to); 65 | if (i > 0 && i <= 16) return _Insert1((VM.OpCode)(byte)i + 0x50, comment, to); 66 | return _InsertPush(((BigInteger)i).ToByteArray(), comment, to); 67 | } 68 | 69 | private NeoCode _Convert1by1(VM.OpCode code, OpCode src, NeoMethod to, byte[] data = null) 70 | { 71 | NeoCode _code = new NeoCode(); 72 | int startaddr = addr; 73 | _code.addr = addr; 74 | if (src != null) 75 | { 76 | addrconv[src.addr] = addr; 77 | _code.debugcode = src.debugcode; 78 | _code.debugline = src.debugline; 79 | _code.debugILAddr = src.addr; 80 | _code.debugILCode = src.code.ToString(); 81 | } 82 | 83 | 84 | addr++; 85 | 86 | _code.code = code; 87 | 88 | if (data != null) 89 | { 90 | _code.bytes = data; 91 | addr += _code.bytes.Length; 92 | } 93 | to.body_Codes[startaddr] = _code; 94 | return _code; 95 | } 96 | 97 | private NeoCode _ConvertPush(byte[] data, OpCode src, NeoMethod to) 98 | { 99 | if (data.Length == 0) return _Convert1by1(VM.OpCode.PUSH0, src, to); 100 | if (data.Length <= 75) return _Convert1by1((VM.OpCode)data.Length, src, to, data); 101 | byte prefixLen; 102 | VM.OpCode code; 103 | if (data.Length <= byte.MaxValue) 104 | { 105 | prefixLen = sizeof(byte); 106 | code = VM.OpCode.PUSHDATA1; 107 | } 108 | else if (data.Length <= ushort.MaxValue) 109 | { 110 | prefixLen = sizeof(ushort); 111 | code = VM.OpCode.PUSHDATA2; 112 | } 113 | else 114 | { 115 | prefixLen = sizeof(uint); 116 | code = VM.OpCode.PUSHDATA4; 117 | } 118 | byte[] bytes = new byte[data.Length + prefixLen]; 119 | Buffer.BlockCopy(BitConverter.GetBytes(data.Length), 0, bytes, 0, prefixLen); 120 | Buffer.BlockCopy(data, 0, bytes, prefixLen, data.Length); 121 | return _Convert1by1(code, src, to, bytes); 122 | } 123 | 124 | private NeoCode _ConvertPush(long i, OpCode src, NeoMethod to) 125 | { 126 | if (i == 0) return _Convert1by1(VM.OpCode.PUSH0, src, to); 127 | if (i == -1) return _Convert1by1(VM.OpCode.PUSHM1, src, to); 128 | if (i > 0 && i <= 16) return _Convert1by1((VM.OpCode)(byte)i + 0x50, src, to); 129 | return _ConvertPush(((BigInteger)i).ToByteArray(), src, to); 130 | } 131 | private int _ConvertPushI8WithConv(ILMethod from, long i, OpCode src, NeoMethod to) 132 | { 133 | var next = from.GetNextCodeAddr(src.addr); 134 | var code = from.body_Codes[next].code; 135 | BigInteger outv; 136 | if (code == CodeEx.Conv_U || code == CodeEx.Conv_U8) 137 | //code == CodeEx.Conv_U1 || code ==CodeEx.Conv_U2 || code==CodeEx.Conv_U4|| code== CodeEx.Conv_U8) 138 | { 139 | ulong v = (ulong)i; 140 | outv = v; 141 | _ConvertPush(outv.ToByteArray(), src, to); 142 | return 1; 143 | } 144 | else if (code == CodeEx.Conv_U1) 145 | { 146 | byte v = (byte)i; 147 | outv = v; 148 | _ConvertPush(outv.ToByteArray(), src, to); 149 | return 1; 150 | 151 | } 152 | else if (code == CodeEx.Conv_U2) 153 | { 154 | ushort v = (ushort)i; 155 | outv = v; 156 | _ConvertPush(outv.ToByteArray(), src, to); 157 | return 1; 158 | 159 | } 160 | else if (code == CodeEx.Conv_U4) 161 | { 162 | uint v = (uint)i; 163 | outv = v; 164 | _ConvertPush(outv.ToByteArray(), src, to); 165 | return 1; 166 | 167 | } 168 | else if (code == CodeEx.Call) 169 | { 170 | var call = from.body_Codes[next]; 171 | if (call.tokenMethod == "System.Numerics.BigInteger System.Numerics.BigInteger::op_Implicit(System.UInt64)") 172 | {//如果是ulong转型到biginteger,需要注意 173 | ulong v = (ulong)i; 174 | outv = v; 175 | _ConvertPush(outv.ToByteArray(), src, to); 176 | return 1; 177 | } 178 | } 179 | 180 | 181 | { 182 | _ConvertPush(i, src, to); 183 | return 0; 184 | } 185 | 186 | } 187 | private int _ConvertPushI4WithConv(ILMethod from, int i, OpCode src, NeoMethod to) 188 | { 189 | var next = from.GetNextCodeAddr(src.addr); 190 | var code = from.body_Codes[next].code; 191 | BigInteger outv; 192 | if (code == CodeEx.Conv_U || code == CodeEx.Conv_U8) 193 | //code == CodeEx.Conv_U1 || code ==CodeEx.Conv_U2 || code==CodeEx.Conv_U4|| code== CodeEx.Conv_U8) 194 | { 195 | ulong v = (uint)i; 196 | outv = v; 197 | _ConvertPush(outv.ToByteArray(), src, to); 198 | return 1; 199 | } 200 | else if (code == CodeEx.Conv_U1) 201 | { 202 | byte v = (byte)i; 203 | outv = v; 204 | _ConvertPush(outv.ToByteArray(), src, to); 205 | return 1; 206 | 207 | } 208 | else if (code == CodeEx.Conv_U2) 209 | { 210 | ushort v = (ushort)i; 211 | outv = v; 212 | _ConvertPush(outv.ToByteArray(), src, to); 213 | return 1; 214 | 215 | } 216 | else if (code == CodeEx.Conv_U4) 217 | { 218 | uint v = (uint)i; 219 | outv = v; 220 | _ConvertPush(outv.ToByteArray(), src, to); 221 | return 1; 222 | 223 | } 224 | else 225 | { 226 | _ConvertPush(i, src, to); 227 | return 0; 228 | } 229 | 230 | } 231 | private void _insertBeginCode(ILMethod from, NeoMethod to) 232 | { 233 | ////压入深度临时栈 234 | //_Insert1(VM.OpCode.DEPTH, "record depth.", to); 235 | //_Insert1(VM.OpCode.TOALTSTACK, "", to); 236 | 237 | ////初始化临时槽位位置 238 | //foreach (var src in from.body_Variables) 239 | //{ 240 | // to.body_Variables.Add(new ILParam(src.name, src.type)); 241 | // _InsertPush(0, "body_Variables init", to); 242 | //} 243 | 244 | //新玩法,用一个数组,应该能减少指令数量 245 | _InsertPush(from.paramtypes.Count + from.body_Variables.Count, "begincode", to); 246 | _Insert1(VM.OpCode.NEWARRAY, "", to); 247 | _Insert1(VM.OpCode.TOALTSTACK, "", to); 248 | //移动参数槽位 249 | for (var i = 0; i < from.paramtypes.Count; i++) 250 | { 251 | //getarray 252 | _Insert1(VM.OpCode.FROMALTSTACK, "set param:" + i, to); 253 | _Insert1(VM.OpCode.DUP, null, to); 254 | _Insert1(VM.OpCode.TOALTSTACK, null, to); 255 | 256 | _InsertPush(i, "", to); //Array pos 257 | 258 | _InsertPush(2, "", to); //Array item 259 | _Insert1(VM.OpCode.ROLL, null, to); 260 | 261 | _Insert1(VM.OpCode.SETITEM, null, to); 262 | } 263 | } 264 | 265 | private void _insertEndCode(ILMethod from, NeoMethod to, OpCode src) 266 | { 267 | ////占位不谢 268 | _Convert1by1(VM.OpCode.NOP, src, to); 269 | 270 | ////移除临时槽位 271 | ////drop body_Variables 272 | //for (var i = 0; i < from.body_Variables.Count; i++) 273 | //{ 274 | // _Insert1(VM.OpCode.DEPTH, "body_Variables drop", to, null); 275 | // _Insert1(VM.OpCode.DEC, null, to, null); 276 | 277 | // //push olddepth 278 | // _Insert1(VM.OpCode.FROMALTSTACK, null, to); 279 | // _Insert1(VM.OpCode.DUP, null, to); 280 | // _Insert1(VM.OpCode.TOALTSTACK, null, to); 281 | // //(d-1)-olddepth 282 | // _Insert1(VM.OpCode.SUB, null, to); 283 | 284 | // _Insert1(VM.OpCode.XDROP, null, to, null); 285 | //} 286 | ////移除参数槽位 287 | //for (var i = 0; i < from.paramtypes.Count; i++) 288 | //{ 289 | // //d 290 | // _Insert1(VM.OpCode.DEPTH, "param drop", to, null); 291 | 292 | // //push olddepth 293 | // _Insert1(VM.OpCode.FROMALTSTACK, null, to); 294 | // _Insert1(VM.OpCode.DUP, null, to); 295 | // _Insert1(VM.OpCode.DEC, null, to);//深度-1 296 | // _Insert1(VM.OpCode.TOALTSTACK, null, to); 297 | 298 | // //(d)-olddepth 299 | // _Insert1(VM.OpCode.SUB, null, to); 300 | 301 | // _Insert1(VM.OpCode.XDROP, null, to, null); 302 | 303 | //} 304 | 305 | //移除深度临时栈 306 | _Insert1(VM.OpCode.FROMALTSTACK, "endcode", to); 307 | _Insert1(VM.OpCode.DROP, "", to); 308 | } 309 | 310 | } 311 | } 312 | -------------------------------------------------------------------------------- /neoj/JVM/JAVAModule.cs: -------------------------------------------------------------------------------- 1 | using ICSharpCode.SharpZipLib.Zip; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.IO; 5 | using static javaloader.ClassFile.Method; 6 | 7 | namespace Neo.Compiler.JVM 8 | { 9 | public class JavaModule 10 | { 11 | public Dictionary classes = new Dictionary(); 12 | public void LoadClass(string filename, string codepath = null) 13 | { 14 | LoadClassByBytes(System.IO.File.ReadAllBytes(filename), codepath); 15 | } 16 | public JavaClass LoadClassByBytes(byte[] data, string srccode = null) 17 | { 18 | var js = new javaloader.ClassFile(data, 0, data.Length); 19 | var _class = new JavaClass(this, js, null); 20 | this.classes[_class.classfile.Name] = _class; 21 | return _class; 22 | } 23 | public void LoadJar(string filename, string codepath = null) 24 | { 25 | string f = System.IO.Path.GetFileName(filename); 26 | //不该基于文件名,而是类的名字 27 | //if (f == "org.neo.smartcontract.framework.jar") 28 | //{ 29 | // bskip = true; 30 | //} 31 | using (var zipStream = new ZipInputStream(File.OpenRead(filename))) 32 | { 33 | ZipEntry ent = null; 34 | 35 | while ((ent = zipStream.GetNextEntry()) != null) 36 | { 37 | var extname = System.IO.Path.GetExtension(ent.Name); 38 | if (ent.IsFile && extname == ".class") 39 | { 40 | byte[] data = null; 41 | using ( 42 | MemoryStream ms = new MemoryStream()) 43 | { 44 | byte[] buf = new byte[2048]; 45 | int size = buf.Length; 46 | while (size > 0) 47 | { 48 | size = zipStream.Read(buf, 0, buf.Length); 49 | if (size > 0) 50 | ms.Write(buf, 0, size); 51 | } 52 | data = ms.ToArray(); 53 | } 54 | var cc = LoadClassByBytes(data, codepath); 55 | var bskip = cc.classfile.Name.IndexOf("org.neo.") == 0 || cc.classfile.Name.IndexOf("src.org.neo.") == 0; 56 | cc.skip = bskip; 57 | } 58 | 59 | } 60 | } 61 | 62 | 63 | 64 | } 65 | 66 | 67 | 68 | } 69 | public class JavaClass 70 | { 71 | public Dictionary ConstValues = new Dictionary(); 72 | public bool IsEnum = false; 73 | void _InitConsts(Instruction[] Instructions) 74 | { 75 | int lastv = -1; 76 | foreach (var c in Instructions) 77 | { 78 | if (c.NormalizedOpCode == javaloader.NormalizedByteCode.__iconst) 79 | { 80 | lastv = c.Arg1; 81 | } 82 | else if (c.NormalizedOpCode == javaloader.NormalizedByteCode.__invokespecial) 83 | { 84 | continue; 85 | } 86 | else if (c.NormalizedOpCode == javaloader.NormalizedByteCode.__putstatic) 87 | { 88 | var p1 = c.Arg1; 89 | if (this.classfile.constantpool[p1] is javaloader.ClassFile.ConstantPoolItemFieldref && 90 | lastv >= 0) 91 | { 92 | var fref = (javaloader.ClassFile.ConstantPoolItemFieldref)this.classfile.constantpool[p1]; 93 | this.ConstValues[fref.Name] = new System.Numerics.BigInteger(lastv).ToByteArray(); 94 | } 95 | } 96 | else 97 | { 98 | lastv = -1; 99 | } 100 | } 101 | } 102 | public JavaModule module; 103 | public JavaClass(JavaModule module, javaloader.ClassFile classfile, string[] srcfile = null) 104 | { 105 | this.module = module; 106 | this.classfile = classfile; 107 | if (this.classfile.IsEnum) 108 | { 109 | this.IsEnum = true; 110 | foreach (var m in this.classfile.Methods) 111 | { 112 | if (m.Name == javaloader.StringConstants.CLINIT) 113 | { 114 | _InitConsts(m.Instructions); 115 | } 116 | } 117 | } 118 | this.srcfile = srcfile; 119 | if (this.srcfile == null) 120 | this.srcfile = new string[0]; 121 | foreach (var f in this.classfile.Fields) 122 | { 123 | this.fields.Add(f.Name, f.Signature); 124 | } 125 | bool isKtObj = false; 126 | if (this.classfile.SourceFileAttribute.Contains(".kt")) 127 | { 128 | var sign = "L" + this.classfile.Name + ";"; 129 | foreach (var f in this.classfile.Fields) 130 | { 131 | if (f.Name == "INSTANCE" && f.IsStatic && f.Signature == sign) 132 | { 133 | isKtObj = true; 134 | break; 135 | } 136 | } 137 | } 138 | foreach (var m in this.classfile.Methods) 139 | { 140 | 141 | bool bskip = false; 142 | if (m.IsStatic == false && isKtObj == false) 143 | { 144 | bskip = true; 145 | //静态成员不要,除非是kotlin 的 object 对象,相当于静态 146 | 147 | } 148 | 149 | if (m.Annotations != null) 150 | { 151 | object[] info = m.Annotations[0] as object[]; 152 | if (info[1] as string == "Lorg/neo/smartcontract/framework/Appcall;" || 153 | info[1] as string == "Lorg/neo/smartcontract/framework/Syscall;" || 154 | info[1] as string == "Lorg/neo/smartcontract/framework/OpCode;" || 155 | info[1] as string == "Lorg/neo/smartcontract/framework/Nonemit;") 156 | { 157 | //continue; 158 | bskip = true; 159 | } 160 | //if(m.Annotations[0]) 161 | } 162 | if (m.Name == "") 163 | bskip = true; 164 | var nm = new JavaMethod(this, m); 165 | nm.skip = bskip; 166 | //if (bskip == false && methods.ContainsKey(m.Name)) 167 | //{ 168 | // throw new Exception("already have a func named:" + classfile.Name + "." + m.Name); 169 | //} 170 | this.methods[m.Name + m.Signature] = nm; 171 | } 172 | this.superClass = this.classfile.SuperClass; 173 | } 174 | public bool skip = false; 175 | public string[] srcfile; 176 | public string superClass; 177 | public javaloader.ClassFile classfile; 178 | public Dictionary fields = new Dictionary(); 179 | public Dictionary methods = new Dictionary(); 180 | 181 | } 182 | public class JavaMethod 183 | { 184 | public bool skip = false; 185 | public JavaClass DeclaringType; 186 | public javaloader.ClassFile.Method method; 187 | public string returnType; 188 | public List paramTypes = new List(); 189 | public Dictionary body_Codes = new Dictionary(); 190 | public List body_Variables = new List(); 191 | 192 | public int MaxVariableIndex = 0; 193 | //public int addLocal_VariablesCount = 0; 194 | //不做表转换了,直接按最大索引给 195 | public Dictionary argTable;// new List();//index->arg index 196 | //public Dictionary localTable;//index->localIndex; 197 | 198 | public JavaMethod(JavaClass type, javaloader.ClassFile.Method method) 199 | { 200 | this.DeclaringType = type; 201 | this.method = method; 202 | //method.LocalVariableTableAttribute 203 | this.argTable = new Dictionary(); 204 | //this.localTable = new Dictionary(); 205 | if (method.ArgMap != null) 206 | for (var i = 0; i < method.ArgMap.Length; i++) 207 | { 208 | var ind = method.ArgMap[i]; 209 | if (ind >= 0) 210 | this.argTable[ind] = i; 211 | } 212 | scanTypes(method.Signature, out this.returnType, this.paramTypes); 213 | Dictionary local = new Dictionary(); 214 | 215 | if (this.method.LocalVariableTableAttribute != null) 216 | foreach (var lv in this.method.LocalVariableTableAttribute) 217 | { 218 | var ind = lv.index; 219 | if (this.argTable.ContainsValue(ind) == false) 220 | { 221 | 222 | var desc = lv.name + ";" + lv.descriptor; 223 | if (local.ContainsKey(ind)) 224 | { 225 | local[ind] = local[ind] + "||" + desc; 226 | } 227 | else 228 | { 229 | local[ind] = desc; 230 | } 231 | } 232 | this.MaxVariableIndex = Math.Max(ind + 1, this.MaxVariableIndex); 233 | } 234 | //for (var i = 0; i < local.Count; i++) 235 | //{ 236 | // this.localTable[local.Keys.ToArray()[i]] = i; 237 | //} 238 | 239 | { 240 | this.body_Variables = new List(); 241 | 242 | //var addLocal_VariablesCount = this.method.MaxLocals - this.paramTypes.Count; 243 | //if (addLocal_VariablesCount < local.Count) 244 | //{ 245 | // throw new Exception("not impossible."); 246 | //} 247 | //for (var i = 0; i < addLocal_VariablesCount; i++) 248 | //{ 249 | // this.body_Variables.Add(new Param("_noname", "")); 250 | //} 251 | 252 | for (var i = 0; i < MaxVariableIndex; i++) 253 | { 254 | this.body_Variables.Add(new NeoParam("_noname", "")); 255 | } 256 | foreach (var lv in local) 257 | { 258 | this.body_Variables[lv.Key - this.paramTypes.Count] = new NeoParam("local", lv.Value); 259 | } 260 | } 261 | if (this.method.Instructions != null) 262 | for (var i = 0; i < this.method.Instructions.Length; i++) 263 | { 264 | Instruction code = this.method.Instructions[i]; 265 | var opcode = new OpCode(); 266 | 267 | opcode.InitToken(this, code); 268 | this.body_Codes[code.PC] = opcode; 269 | } 270 | // this.method.LocalVariableTableAttribute 271 | 272 | } 273 | static string getTypeString(string sign, ref int i) 274 | { 275 | if (sign[i] == '[') //for array 276 | { 277 | i++; 278 | return "[" + getTypeString(sign, ref i); 279 | } 280 | else if (sign[i] == 'V') 281 | { 282 | return "void"; 283 | } 284 | else if (sign[i] == 'I') //a int 285 | { 286 | return "int"; 287 | } 288 | else if (sign[i] == 'J') //a long 289 | { 290 | return "long"; 291 | } 292 | else if (sign[i] == 'B') 293 | { 294 | return "byte"; 295 | } 296 | else if (sign[i] == 'S') 297 | { 298 | return "short"; 299 | } 300 | else if (sign[i] == 'Z') 301 | { 302 | return "boolean"; 303 | } 304 | else if (sign[i] == 'F') 305 | { 306 | return "float"; 307 | } 308 | else if (sign[i] == 'D') 309 | { 310 | return "double"; 311 | } 312 | else if (sign[i] == 'C') 313 | { 314 | return "char"; 315 | } 316 | else if (sign[i] == 'L')//a long string 317 | { 318 | var i2 = sign.IndexOf(';', i); 319 | 320 | var type = sign.Substring(i + 1, i2 - i - 1); 321 | 322 | i = i2; 323 | return type; 324 | } 325 | else 326 | { 327 | throw new Exception("not parsed sign."); 328 | } 329 | } 330 | public static void scanTypes(string sign, out string returnType, List paramTypes) 331 | { 332 | returnType = ""; 333 | bool forreturn = false; 334 | for (var i = 0; i < sign.Length; i++) 335 | { 336 | 337 | if (sign[i] == '(') //beginparam 338 | { 339 | continue; 340 | } 341 | else if (sign[i] == ')')//endparam 342 | { 343 | forreturn = true; 344 | continue; 345 | } 346 | else 347 | { 348 | string type = getTypeString(sign, ref i); 349 | if (forreturn) 350 | { 351 | returnType = type; 352 | return; 353 | } 354 | else 355 | { 356 | paramTypes.Add(type); 357 | continue; 358 | } 359 | 360 | } 361 | } 362 | } 363 | //void scanTypes(string sign) 364 | //{ 365 | // bool forreturn = false; 366 | // for (var i = 0; i < sign.Length; i++) 367 | // { 368 | 369 | // if (sign[i] == '(') //beginparam 370 | // { 371 | // continue; 372 | // } 373 | // else if (sign[i] == ')')//endparam 374 | // { 375 | // forreturn = true; 376 | // continue; 377 | // } 378 | // else 379 | // { 380 | // string type = getTypeString(sign, ref i); 381 | // if (forreturn) 382 | // { 383 | // returnType = type; 384 | // return; 385 | // } 386 | // else 387 | // { 388 | // paramTypes.Add(type); 389 | // continue; 390 | // } 391 | 392 | // } 393 | // } 394 | //} 395 | public int GetLastCodeAddr(int srcaddr) 396 | { 397 | int last = -1; 398 | foreach (var key in this.body_Codes.Keys) 399 | { 400 | if (key == srcaddr) 401 | { 402 | 403 | return last; 404 | } 405 | last = key; 406 | } 407 | return last; 408 | } 409 | public int GetNextCodeAddr(int srcaddr) 410 | { 411 | bool bskip = false; 412 | foreach (var key in this.body_Codes.Keys) 413 | { 414 | if (key == srcaddr) 415 | { 416 | bskip = true; 417 | continue; 418 | } 419 | if (bskip) 420 | { 421 | return key; 422 | } 423 | 424 | } 425 | return -1; 426 | } 427 | } 428 | 429 | public class OpCode 430 | { 431 | public javaloader.NormalizedByteCode code; 432 | public override string ToString() 433 | { 434 | var info = "IL_" + addr.ToString("X04") + " " + code + " "; 435 | if (this.tokenValueType == TokenValueType.Method) 436 | info += tokenMethod; 437 | if (this.tokenValueType == TokenValueType.String) 438 | info += tokenStr; 439 | 440 | if (debugline >= 0) 441 | { 442 | info += "(" + debugline + ")"; 443 | } 444 | return info; 445 | } 446 | public enum TokenValueType 447 | { 448 | Nothing, 449 | Addr,//地址 450 | AddrArray, 451 | String, 452 | Type, 453 | Field, 454 | Method, 455 | I32, 456 | I64, 457 | OTher, 458 | } 459 | public TokenValueType tokenValueType = TokenValueType.Nothing; 460 | public int addr; 461 | public int debugline = -1; 462 | public string debugcode; 463 | public int arg1; 464 | public int arg2; 465 | 466 | public object tokenUnknown; 467 | public int tokenAddr_Index; 468 | //public int tokenAddr; 469 | public int[] tokenAddr_Switch; 470 | public string tokenType; 471 | public string tokenField; 472 | public string tokenMethod; 473 | public int tokenI32; 474 | public Int64 tokenI64; 475 | public float tokenR32; 476 | public double tokenR64; 477 | public string tokenStr; 478 | public void InitToken(JavaMethod method, Instruction ins) 479 | { 480 | this.code = ins.NormalizedOpCode; 481 | this.arg1 = ins.Arg1; 482 | this.arg2 = ins.Arg2; 483 | this.addr = ins.PC; 484 | if (method.method.LineNumberTableAttribute == null || method.method.LineNumberTableAttribute.TryGetValue(this.addr, out this.debugline) == false) 485 | { 486 | this.debugline = -1; 487 | } 488 | if (this.debugline >= 0) 489 | { 490 | if (this.debugline - 1 < method.DeclaringType.srcfile.Length) 491 | this.debugcode = method.DeclaringType.srcfile[this.debugline - 1]; 492 | } 493 | switch (code) 494 | { 495 | case javaloader.NormalizedByteCode.__iconst: 496 | this.tokenI32 = this.arg1; 497 | break; 498 | //case javaloader.NormalizedByteCode.__newarray: 499 | // var c = method.DeclaringType.classfile.constantpool[this.arg1]; 500 | // break; 501 | case javaloader.NormalizedByteCode.__astore: 502 | break; 503 | default: 504 | this.tokenUnknown = ins; 505 | this.tokenValueType = TokenValueType.Nothing; 506 | break; 507 | } 508 | } 509 | 510 | } 511 | } 512 | -------------------------------------------------------------------------------- /neon/Debugger/NeoDisassembler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Text; 5 | using Neo.VM; 6 | 7 | namespace Neo.Compiler.Debugger 8 | { 9 | public class DisassembleEntry 10 | { 11 | public int startOfs; 12 | public int endOfs; 13 | public string name; 14 | public OpCode opcode; 15 | public byte[] data; 16 | public string comment; 17 | } 18 | 19 | public struct DisassembleLocation 20 | { 21 | public string fileName; 22 | public int line; 23 | } 24 | 25 | public class DisassembleException : Exception 26 | { 27 | public DisassembleException(string msg) : base(msg) 28 | { 29 | 30 | } 31 | } 32 | 33 | public class AVMDisassemble 34 | { 35 | private List _lines; 36 | public IEnumerable lines { get { return _lines; } } 37 | 38 | public AVMDisassemble(List lines) 39 | { 40 | this._lines = lines; 41 | } 42 | 43 | public int ResolveLine(int ofs) 44 | { 45 | int i = 0; 46 | foreach (var line in lines) 47 | { 48 | if (ofs >= line.startOfs && ofs <= line.endOfs) 49 | { 50 | return i; 51 | } 52 | 53 | i++; 54 | } 55 | 56 | throw new Exception("Offset cannot be mapped"); 57 | } 58 | 59 | public int ResolveOffset(int line) 60 | { 61 | if (line < 0 || line >= _lines.Count) 62 | { 63 | throw new Exception("Line cannot be mapped"); 64 | } 65 | 66 | return _lines[line].startOfs; 67 | } 68 | 69 | public override string ToString() 70 | { 71 | var sb = new StringBuilder(); 72 | //sb.AppendLine(FormattingUtils.OutputLine("Offset", "Opcode", "Comment")); 73 | foreach (var entry in this.lines) 74 | { 75 | string opStr = entry.name; 76 | string hintStr = entry.comment; 77 | 78 | if (!string.IsNullOrEmpty(hintStr)) 79 | { 80 | hintStr = "// " + hintStr; 81 | } 82 | 83 | sb.AppendLine(opStr.PadRight(8, ' ') + hintStr); 84 | } 85 | 86 | return sb.ToString(); 87 | } 88 | } 89 | 90 | public static class NeoDisassembler 91 | { 92 | private static Dictionary hints = null; 93 | 94 | private static void InitHints() 95 | { 96 | if (hints != null) 97 | { 98 | return; 99 | } 100 | 101 | hints = new Dictionary(); 102 | // Constants 103 | hints[OpCode.PUSH0] = "An empty array of bytes is pushed onto the stack."; 104 | hints[OpCode.PUSHF] = hints[OpCode.PUSH0]; 105 | hints[OpCode.PUSHBYTES1] = /*0x01-0x4B*/ "The next opcode bytes is data to be pushed onto the stack"; 106 | hints[OpCode.PUSHBYTES75] = ""; 107 | hints[OpCode.PUSHDATA1] = "The next byte contains the number of bytes to be pushed onto the stack."; 108 | hints[OpCode.PUSHDATA2] = "The next two bytes contain the number of bytes to be pushed onto the stack."; 109 | hints[OpCode.PUSHDATA4] = "The next four bytes contain the number of bytes to be pushed onto the stack."; 110 | hints[OpCode.PUSHM1] = "The number -1 is pushed onto the stack."; 111 | hints[OpCode.PUSH1] = "The number 1 is pushed onto the stack."; 112 | hints[OpCode.PUSHT] = hints[OpCode.PUSH1]; 113 | hints[OpCode.PUSH2] = "The number 2 is pushed onto the stack."; 114 | hints[OpCode.PUSH3] = "The number 3 is pushed onto the stack."; 115 | hints[OpCode.PUSH4] = "The number 4 is pushed onto the stack."; 116 | hints[OpCode.PUSH5] = "The number 5 is pushed onto the stack."; 117 | hints[OpCode.PUSH6] = "The number 6 is pushed onto the stack."; 118 | hints[OpCode.PUSH7] = "The number 7 is pushed onto the stack."; 119 | hints[OpCode.PUSH8] = "The number 8 is pushed onto the stack."; 120 | hints[OpCode.PUSH9] = "The number 9 is pushed onto the stack."; 121 | hints[OpCode.PUSH10] = "The number 10 is pushed onto the stack."; 122 | hints[OpCode.PUSH11] = "The number 11 is pushed onto the stack."; 123 | hints[OpCode.PUSH12] = "The number 12 is pushed onto the stack."; 124 | hints[OpCode.PUSH13] = "The number 13 is pushed onto the stack."; 125 | hints[OpCode.PUSH14] = "The number 14 is pushed onto the stack."; 126 | hints[OpCode.PUSH15] = "The number 15 is pushed onto the stack."; 127 | hints[OpCode.PUSH16] = "The number 16 is pushed onto the stack."; 128 | 129 | 130 | // Flow control 131 | hints[OpCode.NOP] = "Does nothing."; 132 | hints[OpCode.JMP] = ""; 133 | hints[OpCode.JMPIF] = ""; 134 | hints[OpCode.JMPIFNOT] = ""; 135 | hints[OpCode.CALL] = ""; 136 | hints[OpCode.RET] = ""; 137 | hints[OpCode.APPCALL] = ""; 138 | hints[OpCode.SYSCALL] = ""; 139 | hints[OpCode.TAILCALL] = ""; 140 | 141 | 142 | // Stack 143 | hints[OpCode.DUPFROMALTSTACK] = ""; 144 | hints[OpCode.TOALTSTACK] = "Puts the input onto the top of the alt stack. Removes it from the main stack."; 145 | hints[OpCode.FROMALTSTACK] = "Puts the input onto the top of the main stack. Removes it from the alt stack."; 146 | hints[OpCode.XDROP] = ""; 147 | hints[OpCode.XSWAP] = ""; 148 | hints[OpCode.XTUCK] = ""; 149 | hints[OpCode.DEPTH] = "Puts the number of stack items onto the stack."; 150 | hints[OpCode.DROP] = "Removes the top stack item."; 151 | hints[OpCode.DUP] = "Duplicates the top stack item."; 152 | hints[OpCode.NIP] = "Removes the second-to-top stack item."; 153 | hints[OpCode.OVER] = "Copies the second-to-top stack item to the top."; 154 | hints[OpCode.PICK] = "The item in back in the stack is copied to the top."; 155 | hints[OpCode.ROLL] = "The item in back in the stack is moved to the top."; 156 | hints[OpCode.ROT] = "The top three items on the stack are rotated to the left."; 157 | hints[OpCode.SWAP] = "The top two items on the stack are swapped."; 158 | hints[OpCode.TUCK] = "The item at the top of the stack is copied and inserted before the second-to-top item."; 159 | 160 | 161 | // Splice 162 | hints[OpCode.CAT] = "Concatenates two strings."; 163 | hints[OpCode.SUBSTR] = "Returns a section of a string."; 164 | hints[OpCode.LEFT] = "Keeps only characters left of the specified point in a string."; 165 | hints[OpCode.RIGHT] = "Keeps only characters right of the specified point in a string."; 166 | hints[OpCode.SIZE] = "Returns the length of the input string."; 167 | 168 | 169 | // Bitwise logic 170 | hints[OpCode.INVERT] = "Flips all of the bits in the input."; 171 | hints[OpCode.AND] = "Boolean and between each bit in the inputs."; 172 | hints[OpCode.OR] = "Boolean or between each bit in the inputs."; 173 | hints[OpCode.XOR] = "Boolean exclusive or between each bit in the inputs."; 174 | hints[OpCode.EQUAL] = "Returns 1 if the inputs are exactly equal, 0 otherwise."; 175 | //OP_EQUALVERIFY = 0x88, // Same as OP_EQUAL, but runs OP_VERIFY afterward. 176 | //OP_RESERVED1 = 0x89, // Transaction is invalid unless occuring in an unexecuted OP_IF branch 177 | //OP_RESERVED2 = 0x8A, // Transaction is invalid unless occuring in an unexecuted OP_IF branch 178 | 179 | 180 | // Arithmetic 181 | // Note: Arithmetic inputs are limited to signed 32-bit integers, but may overflow their output. 182 | hints[OpCode.INC] = "1 is added to the input."; 183 | hints[OpCode.DEC] = "1 is subtracted from the input."; 184 | hints[OpCode.SIGN] = ""; 185 | hints[OpCode.NEGATE] = "The sign of the input is flipped."; 186 | hints[OpCode.ABS] = "The input is made positive."; 187 | hints[OpCode.NOT] = "If the input is 0 or 1, it is flipped. Otherwise the output will be 0."; 188 | hints[OpCode.NZ] = "Returns 0 if the input is 0. 1 otherwise."; 189 | hints[OpCode.ADD] = "a is added to b."; 190 | hints[OpCode.SUB] = "b is subtracted from a."; 191 | hints[OpCode.MUL] = "a is multiplied by b."; 192 | hints[OpCode.DIV] = "a is divided by b."; 193 | hints[OpCode.MOD] = "Returns the remainder after dividing a by b."; 194 | hints[OpCode.SHL] = "Shifts a left b bits, preserving sign."; 195 | hints[OpCode.SHR] = "Shifts a right b bits, preserving sign."; 196 | hints[OpCode.BOOLAND] = "If both a and b are not 0, the output is 1. Otherwise 0."; 197 | hints[OpCode.BOOLOR] = "If a or b is not 0, the output is 1. Otherwise 0."; 198 | hints[OpCode.NUMEQUAL] = "Returns 1 if the numbers are equal, 0 otherwise."; 199 | hints[OpCode.NUMNOTEQUAL] = "Returns 1 if the numbers are not equal, 0 otherwise."; 200 | hints[OpCode.LT] = "Returns 1 if a is less than b, 0 otherwise."; 201 | hints[OpCode.GT] = "Returns 1 if a is greater than b, 0 otherwise."; 202 | hints[OpCode.LTE] = "Returns 1 if a is less than or equal to b, 0 otherwise."; 203 | hints[OpCode.GTE] = "Returns 1 if a is greater than or equal to b, 0 otherwise."; 204 | hints[OpCode.MIN] = "Returns the smaller of a and b."; 205 | hints[OpCode.MAX] = "Returns the larger of a and b."; 206 | hints[OpCode.WITHIN] = "Returns 1 if x is within the specified range (left-inclusive), 0 otherwise."; 207 | 208 | 209 | // Crypto 210 | //hints[OpCode.RIPEMD160 = 0xA6, // The input is hashed using RIPEMD-160. 211 | hints[OpCode.SHA1] = ""; // The input is hashed using SHA-1. 212 | hints[OpCode.SHA256] = ""; // The input is hashed using SHA-256. 213 | hints[OpCode.HASH160] = ""; 214 | hints[OpCode.HASH256] = ""; 215 | hints[OpCode.CHECKSIG] = ""; 216 | hints[OpCode.CHECKMULTISIG] = ""; 217 | 218 | 219 | // Array 220 | hints[OpCode.ARRAYSIZE] = ""; 221 | hints[OpCode.PACK] = ""; 222 | hints[OpCode.UNPACK] = ""; 223 | hints[OpCode.PICKITEM] = "Pops index and array from stack, then push the item in the array index to the stack"; 224 | hints[OpCode.SETITEM] = "Pops newItem, index and array from stack, then copy the newItem to the array value at index"; 225 | hints[OpCode.NEWARRAY] = "Pops size from stack and creates a new array with that size, and pushes the array into the stack"; 226 | hints[OpCode.NEWSTRUCT] = "用作值類型"; 227 | 228 | 229 | // Exceptions 230 | hints[OpCode.THROW] = ""; 231 | hints[OpCode.THROWIFNOT] = ""; 232 | } 233 | 234 | public static byte[] ReadVarBytes(this BinaryReader reader, int max = 0X7fffffc7) 235 | { 236 | return reader.ReadBytes((int)reader.ReadVarInt((ulong)max)); 237 | } 238 | 239 | 240 | public static ulong ReadVarInt(this BinaryReader reader, ulong max = ulong.MaxValue) 241 | { 242 | byte fb = reader.ReadByte(); 243 | ulong value; 244 | if (fb == 0xFD) 245 | value = reader.ReadUInt16(); 246 | else if (fb == 0xFE) 247 | value = reader.ReadUInt32(); 248 | else if (fb == 0xFF) 249 | value = reader.ReadUInt64(); 250 | else 251 | value = fb; 252 | if (value > max) throw new FormatException(); 253 | return value; 254 | } 255 | 256 | public static AVMDisassemble Disassemble(byte[] script) 257 | { 258 | InitHints(); 259 | 260 | var output = new List(); 261 | 262 | using (var stream = new MemoryStream(script)) 263 | { 264 | using (var reader = new BinaryReader(stream)) 265 | { 266 | while (reader.BaseStream.Position != reader.BaseStream.Length) 267 | { 268 | var entry = new DisassembleEntry(); 269 | output.Add(entry); 270 | 271 | entry.startOfs = (int)reader.BaseStream.Position; 272 | 273 | var opcode = (OpCode)reader.ReadByte(); 274 | 275 | entry.opcode = opcode; 276 | entry.name = opcode.ToString(); 277 | 278 | entry.comment = hints.ContainsKey(opcode) ? hints[opcode] : ""; 279 | 280 | if (opcode >= OpCode.PUSHBYTES1 && opcode <= OpCode.PUSHBYTES75) 281 | { 282 | var len = (byte)opcode; 283 | entry.data = reader.ReadBytes(len); 284 | entry.name = "PUSHBYTES" + len; 285 | entry.comment = "Pushes " + len + " bytes into the stack: $$"; 286 | } 287 | else 288 | switch (opcode) 289 | { 290 | // Push value 291 | //case OpCode.PUSH0: 292 | 293 | case OpCode.PUSHDATA1: 294 | { 295 | var len = reader.ReadByte(); 296 | entry.data = reader.ReadBytes(len); 297 | entry.comment = "Pushes " + len + " bytes into the stack: $$"; 298 | break; 299 | } 300 | 301 | case OpCode.PUSHDATA2: 302 | { 303 | var len = reader.ReadUInt16(); 304 | entry.data = reader.ReadBytes(len); 305 | entry.comment = "Pushes " + len + " bytes into the stack: $$"; 306 | break; 307 | } 308 | 309 | 310 | case OpCode.PUSHDATA4: 311 | { 312 | var len = reader.ReadInt32(); 313 | entry.data = reader.ReadBytes(len); 314 | entry.comment = "Pushes " + len + " bytes into the stack: $$"; 315 | break; 316 | } 317 | 318 | /*case OpCode.PUSHM1: 319 | case OpCode.PUSH1: 320 | case OpCode.PUSH2: 321 | case OpCode.PUSH3: 322 | case OpCode.PUSH4: 323 | case OpCode.PUSH5: 324 | case OpCode.PUSH6: 325 | case OpCode.PUSH7: 326 | case OpCode.PUSH8: 327 | case OpCode.PUSH9: 328 | case OpCode.PUSH10: 329 | case OpCode.PUSH11: 330 | case OpCode.PUSH12: 331 | case OpCode.PUSH13: 332 | case OpCode.PUSH14: 333 | case OpCode.PUSH15: 334 | case OpCode.PUSH16:*/ 335 | 336 | // Control 337 | //case OpCode.NOP: 338 | 339 | case OpCode.CALL: 340 | case OpCode.JMP: 341 | case OpCode.JMPIF: 342 | case OpCode.JMPIFNOT: 343 | { 344 | int offset = reader.ReadInt16(); 345 | //offset = context.InstructionPointer + offset - 3; 346 | break; 347 | } 348 | 349 | 350 | /*case OpCode.CALL: 351 | InvocationStack.Push(context.Clone()); 352 | context.InstructionPointer += 2; 353 | ExecuteOp(OpCode.JMP, CurrentContext); 354 | break;*/ 355 | 356 | /*case OpCode.RET: 357 | InvocationStack.Pop().Dispose(); 358 | if (InvocationStack.Count == 0) 359 | State |= VMState.HALT; 360 | break;*/ 361 | 362 | case OpCode.APPCALL: 363 | case OpCode.TAILCALL: 364 | { 365 | byte[] script_hash = reader.ReadBytes(20); 366 | entry.data = script_hash; 367 | entry.comment = "Calls script with hash: $XX"; 368 | break; 369 | } 370 | 371 | case OpCode.SYSCALL: 372 | { 373 | entry.data = reader.ReadVarBytes(252); 374 | entry.comment = "System call with data: $$"; 375 | break; 376 | } 377 | 378 | // Stack ops 379 | /*case OpCode.DUPFROMALTSTACK: 380 | case OpCode.TOALTSTACK: 381 | case OpCode.FROMALTSTACK: 382 | case OpCode.XDROP: 383 | case OpCode.XSWAP: 384 | case OpCode.XTUCK: 385 | case OpCode.DEPTH: 386 | case OpCode.DROP: 387 | case OpCode.DUP: 388 | case OpCode.NIP: 389 | case OpCode.OVER: 390 | case OpCode.PICK: 391 | case OpCode.ROLL: 392 | case OpCode.ROT: 393 | case OpCode.SWAP: 394 | case OpCode.TUCK: 395 | case OpCode.CAT: 396 | case OpCode.SUBSTR: 397 | case OpCode.LEFT: 398 | case OpCode.RIGHT: 399 | case OpCode.SIZE: 400 | */ 401 | 402 | 403 | // Bitwise logic 404 | /*case OpCode.INVERT: 405 | case OpCode.AND: 406 | case OpCode.OR: 407 | case OpCode.XOR: 408 | case OpCode.EQUAL: 409 | | */ 410 | 411 | 412 | 413 | // Numeric 414 | /*case OpCode.INC: 415 | case OpCode.DEC: 416 | case OpCode.SIGN: 417 | case OpCode.NEGATE: 418 | case OpCode.ABS: 419 | case OpCode.NOT: 420 | case OpCode.NZ: 421 | case OpCode.ADD: 422 | case OpCode.SUB: 423 | case OpCode.MUL: 424 | case OpCode.DIV: 425 | case OpCode.MOD: 426 | case OpCode.SHL: 427 | case OpCode.SHR: 428 | case OpCode.BOOLAND: 429 | case OpCode.BOOLOR: 430 | case OpCode.NUMEQUAL: 431 | case OpCode.NUMNOTEQUAL: 432 | case OpCode.LT: 433 | case OpCode.GT: 434 | case OpCode.LTE: 435 | case OpCode.GTE: 436 | case OpCode.MIN: 437 | case OpCode.MAX: 438 | case OpCode.WITHIN: 439 | */ 440 | 441 | // Crypto 442 | /* 443 | case OpCode.SHA1: 444 | case OpCode.SHA256: 445 | case OpCode.HASH160: 446 | case OpCode.HASH256: 447 | case OpCode.CHECKSIG: 448 | case OpCode.CHECKMULTISIG: 449 | case OpCode.ARRAYSIZE: 450 | case OpCode.PACK: 451 | case OpCode.UNPACK: 452 | case OpCode.PICKITEM: 453 | case OpCode.SETITEM: 454 | case OpCode.NEWARRAY: 455 | case OpCode.NEWSTRUCT: 456 | */ 457 | 458 | // Exceptions 459 | /*case OpCode.THROW: 460 | case OpCode.THROWIFNOT: 461 | */ 462 | 463 | default: 464 | { 465 | if (!Enum.IsDefined(typeof(OpCode), opcode)) 466 | { 467 | var s = ((byte)opcode).ToString(); 468 | throw new DisassembleException("Invalid opcode " + s); 469 | } 470 | 471 | break; 472 | } 473 | } 474 | 475 | entry.endOfs = (int)(reader.BaseStream.Position-1); 476 | } 477 | } 478 | } 479 | 480 | return new AVMDisassemble(output); 481 | } 482 | 483 | } 484 | } 485 | -------------------------------------------------------------------------------- /neon/MSIL/ILModule.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | /// 5 | /// 这个文件负责 IL dll的解析,核心解析是使用mono.cecil,这里进行了一些预先整理 6 | /// 使用时更便捷 7 | /// 8 | namespace Neo.Compiler.MSIL 9 | { 10 | public class ILModule 11 | { 12 | public Mono.Cecil.ModuleDefinition module = null; 13 | public List moduleref = new List(); 14 | public Dictionary mapType = new Dictionary(); 15 | public ILModule() 16 | { 17 | 18 | } 19 | public void LoadModule(System.IO.Stream dllStream, System.IO.Stream pdbStream) 20 | { 21 | this.module = Mono.Cecil.ModuleDefinition.ReadModule(dllStream); 22 | 23 | if (pdbStream != null) 24 | { 25 | var debugInfoLoader = new Mono.Cecil.Pdb.PdbReaderProvider(); 26 | 27 | module.ReadSymbols(debugInfoLoader.GetSymbolReader(module, pdbStream)); 28 | } 29 | 30 | if (module.HasAssemblyReferences) 31 | { 32 | foreach (var ar in module.AssemblyReferences) 33 | { 34 | if (moduleref.Contains(ar.Name) == false) 35 | moduleref.Add(ar.Name); 36 | if (moduleref.Contains(ar.FullName) == false) 37 | moduleref.Add(ar.FullName); 38 | } 39 | } 40 | //mapModule[module.Name] = module; 41 | if (module.HasTypes) 42 | { 43 | foreach (var t in module.Types) 44 | { 45 | if (t.FullName.Contains(".My."))//vb 系统类不要 46 | continue; 47 | 48 | mapType[t.FullName] = new ILType(this, t); 49 | if (t.HasNestedTypes) 50 | { 51 | foreach (var nt in t.NestedTypes) 52 | { 53 | mapType[nt.FullName] = new ILType(this, nt); 54 | 55 | } 56 | } 57 | 58 | } 59 | } 60 | } 61 | 62 | } 63 | public class ILType 64 | { 65 | Mono.Cecil.TypeDefinition type; 66 | public Dictionary fields = new Dictionary(); 67 | public Dictionary methods = new Dictionary(); 68 | public ILType(ILModule module, Mono.Cecil.TypeDefinition type) 69 | { 70 | this.type = type; 71 | foreach (Mono.Cecil.FieldDefinition f in type.Fields) 72 | { 73 | this.fields.Add(f.Name, new ILField(this, f)); 74 | } 75 | foreach (Mono.Cecil.MethodDefinition m in type.Methods) 76 | { 77 | if (m.IsStatic == false) 78 | { 79 | var method = new ILMethod(this, null); 80 | method.fail = "只能导出static 函数"; 81 | methods[m.FullName] = method; 82 | } 83 | else 84 | { 85 | var method = new ILMethod(this, m); 86 | if (methods.ContainsKey(m.FullName)) 87 | { 88 | throw new Exception("already have a func named:" + type.FullName + "::" + m.Name); 89 | } 90 | methods[m.FullName] = method; 91 | } 92 | } 93 | } 94 | 95 | } 96 | 97 | public class ILField 98 | { 99 | public ILField(ILType type, Mono.Cecil.FieldDefinition field) 100 | { 101 | this.type = field.FieldType.FullName; 102 | this.name = field.Name; 103 | this.displayName = this.name; 104 | this.field = field; 105 | foreach (var ev in field.DeclaringType.Events) 106 | { 107 | if (ev.Name == field.Name && ev.EventType.FullName == field.FieldType.FullName) 108 | { 109 | this.isEvent = true; 110 | Mono.Collections.Generic.Collection ca = ev.CustomAttributes; 111 | foreach (var attr in ca) 112 | { 113 | if (attr.AttributeType.Name == "DisplayNameAttribute") 114 | { 115 | this.displayName = (string)attr.ConstructorArguments[0].Value; 116 | } 117 | } 118 | var eventtype = field.FieldType as Mono.Cecil.TypeDefinition; 119 | if (eventtype == null) 120 | { 121 | try 122 | { 123 | eventtype = field.FieldType.Resolve(); 124 | } 125 | catch 126 | { 127 | throw new Exception("can't parese event type from:" + field.FieldType.FullName + ".maybe it is System.Action which is defined in mscorlib.dll,copy this dll in."); 128 | } 129 | } 130 | if (eventtype != null) 131 | { 132 | foreach (var m in eventtype.Methods) 133 | { 134 | if (m.Name == "Invoke") 135 | { 136 | this.returntype = m.ReturnType.FullName; 137 | try 138 | { 139 | var _type = m.ReturnType.Resolve(); 140 | foreach (var i in _type.Interfaces) 141 | { 142 | if (i.Name == "IApiInterface") 143 | { 144 | this.returntype = "IInteropInterface"; 145 | } 146 | } 147 | } 148 | catch (Exception err) 149 | { 150 | 151 | } 152 | foreach (var src in m.Parameters) 153 | { 154 | string paramtype = src.ParameterType.FullName; 155 | if (src.ParameterType.IsGenericParameter) 156 | { 157 | var gtype = src.ParameterType as Mono.Cecil.GenericParameter; 158 | 159 | var srcgtype = field.FieldType as Mono.Cecil.GenericInstanceType; 160 | var rtype = srcgtype.GenericArguments[gtype.Position]; 161 | paramtype = rtype.FullName; 162 | try 163 | { 164 | var _type = rtype.Resolve(); 165 | foreach (var i in _type.Interfaces) 166 | { 167 | if (i.Name == "IApiInterface") 168 | { 169 | paramtype = "IInteropInterface"; 170 | } 171 | } 172 | } 173 | catch (Exception err) 174 | { 175 | 176 | } 177 | } 178 | this.paramtypes.Add(new NeoParam(src.Name, paramtype)); 179 | 180 | } 181 | } 182 | } 183 | } 184 | break; 185 | } 186 | } 187 | } 188 | public bool isEvent = false; 189 | public string type; 190 | public string name; 191 | public string displayName; 192 | public string returntype; 193 | public List paramtypes = new List(); 194 | public override string ToString() 195 | { 196 | return type; 197 | } 198 | public Mono.Cecil.FieldDefinition field; 199 | } 200 | 201 | public class ILMethod 202 | { 203 | public ILMethod(ILType type, Mono.Cecil.MethodDefinition method) 204 | { 205 | this.method = method; 206 | if (method != null) 207 | { 208 | returntype = method.ReturnType.FullName; 209 | if (method.HasParameters) 210 | { 211 | hasParam = true; 212 | foreach (var p in method.Parameters) 213 | { 214 | string paramtype = p.ParameterType.FullName; 215 | try 216 | { 217 | var _type = p.ParameterType.Resolve(); 218 | foreach (var i in _type.Interfaces) 219 | { 220 | if (i.Name == "IApiInterface") 221 | { 222 | paramtype = "IInteropInterface"; 223 | } 224 | } 225 | } 226 | catch (Exception err) 227 | { 228 | 229 | } 230 | this.paramtypes.Add(new NeoParam(p.Name, paramtype)); 231 | } 232 | } 233 | if (method.HasBody) 234 | { 235 | var bodyNative = method.Body; 236 | if (bodyNative.HasVariables) 237 | { 238 | foreach (var v in bodyNative.Variables) 239 | { 240 | this.body_Variables.Add(new NeoParam(v.Name, v.VariableType.FullName)); 241 | } 242 | } 243 | for (int i = 0; i < bodyNative.Instructions.Count; i++) 244 | { 245 | var code = bodyNative.Instructions[i]; 246 | OpCode c = new OpCode(); 247 | c.code = (CodeEx)(int)code.OpCode.Code; 248 | c.addr = code.Offset; 249 | if (code.SequencePoint != null) 250 | { 251 | c.debugcode = code.SequencePoint.Document.Url; 252 | c.debugline = code.SequencePoint.StartLine; 253 | } 254 | c.InitToken(code.Operand); 255 | this.body_Codes.Add(c.addr, c); 256 | } 257 | } 258 | } 259 | } 260 | 261 | public string returntype; 262 | public List paramtypes = new List(); 263 | public bool hasParam = false; 264 | public Mono.Cecil.MethodDefinition method; 265 | public List body_Variables = new List(); 266 | public SortedDictionary body_Codes = new SortedDictionary(); 267 | public string fail = null; 268 | public int GetNextCodeAddr(int srcaddr) 269 | { 270 | bool bskip = false; 271 | foreach (var key in this.body_Codes.Keys) 272 | { 273 | if (key == srcaddr) 274 | { 275 | bskip = true; 276 | continue; 277 | } 278 | if (bskip) 279 | { 280 | return key; 281 | } 282 | 283 | } 284 | return -1; 285 | } 286 | } 287 | 288 | public enum CodeEx 289 | { 290 | Nop, 291 | Break, 292 | Ldarg_0, 293 | Ldarg_1, 294 | Ldarg_2, 295 | Ldarg_3, 296 | Ldloc_0, 297 | Ldloc_1, 298 | Ldloc_2, 299 | Ldloc_3, 300 | Stloc_0, 301 | Stloc_1, 302 | Stloc_2, 303 | Stloc_3, 304 | Ldarg_S, 305 | Ldarga_S, 306 | Starg_S, 307 | Ldloc_S, 308 | Ldloca_S, 309 | Stloc_S, 310 | Ldnull, 311 | Ldc_I4_M1, 312 | Ldc_I4_0, 313 | Ldc_I4_1, 314 | Ldc_I4_2, 315 | Ldc_I4_3, 316 | Ldc_I4_4, 317 | Ldc_I4_5, 318 | Ldc_I4_6, 319 | Ldc_I4_7, 320 | Ldc_I4_8, 321 | Ldc_I4_S, 322 | Ldc_I4, 323 | Ldc_I8, 324 | Ldc_R4, 325 | Ldc_R8, 326 | Dup, 327 | Pop, 328 | Jmp, 329 | Call, 330 | Calli, 331 | Ret, 332 | Br_S, 333 | Brfalse_S, 334 | Brtrue_S, 335 | Beq_S, 336 | Bge_S, 337 | Bgt_S, 338 | Ble_S, 339 | Blt_S, 340 | Bne_Un_S, 341 | Bge_Un_S, 342 | Bgt_Un_S, 343 | Ble_Un_S, 344 | Blt_Un_S, 345 | Br, 346 | Brfalse, 347 | Brtrue, 348 | Beq, 349 | Bge, 350 | Bgt, 351 | Ble, 352 | Blt, 353 | Bne_Un, 354 | Bge_Un, 355 | Bgt_Un, 356 | Ble_Un, 357 | Blt_Un, 358 | Switch, 359 | Ldind_I1, 360 | Ldind_U1, 361 | Ldind_I2, 362 | Ldind_U2, 363 | Ldind_I4, 364 | Ldind_U4, 365 | Ldind_I8, 366 | Ldind_I, 367 | Ldind_R4, 368 | Ldind_R8, 369 | Ldind_Ref, 370 | Stind_Ref, 371 | Stind_I1, 372 | Stind_I2, 373 | Stind_I4, 374 | Stind_I8, 375 | Stind_R4, 376 | Stind_R8, 377 | Add, 378 | Sub, 379 | Mul, 380 | Div, 381 | Div_Un, 382 | Rem, 383 | Rem_Un, 384 | And, 385 | Or, 386 | Xor, 387 | Shl, 388 | Shr, 389 | Shr_Un, 390 | Neg, 391 | Not, 392 | Conv_I1, 393 | Conv_I2, 394 | Conv_I4, 395 | Conv_I8, 396 | Conv_R4, 397 | Conv_R8, 398 | Conv_U4, 399 | Conv_U8, 400 | Callvirt, 401 | Cpobj, 402 | Ldobj, 403 | Ldstr, 404 | Newobj, 405 | Castclass, 406 | Isinst, 407 | Conv_R_Un, 408 | Unbox, 409 | Throw, 410 | Ldfld, 411 | Ldflda, 412 | Stfld, 413 | Ldsfld, 414 | Ldsflda, 415 | Stsfld, 416 | Stobj, 417 | Conv_Ovf_I1_Un, 418 | Conv_Ovf_I2_Un, 419 | Conv_Ovf_I4_Un, 420 | Conv_Ovf_I8_Un, 421 | Conv_Ovf_U1_Un, 422 | Conv_Ovf_U2_Un, 423 | Conv_Ovf_U4_Un, 424 | Conv_Ovf_U8_Un, 425 | Conv_Ovf_I_Un, 426 | Conv_Ovf_U_Un, 427 | Box, 428 | Newarr, 429 | Ldlen, 430 | Ldelema, 431 | Ldelem_I1, 432 | Ldelem_U1, 433 | Ldelem_I2, 434 | Ldelem_U2, 435 | Ldelem_I4, 436 | Ldelem_U4, 437 | Ldelem_I8, 438 | Ldelem_I, 439 | Ldelem_R4, 440 | Ldelem_R8, 441 | Ldelem_Ref, 442 | Stelem_I, 443 | Stelem_I1, 444 | Stelem_I2, 445 | Stelem_I4, 446 | Stelem_I8, 447 | Stelem_R4, 448 | Stelem_R8, 449 | Stelem_Ref, 450 | Ldelem_Any, 451 | Stelem_Any, 452 | Unbox_Any, 453 | Conv_Ovf_I1, 454 | Conv_Ovf_U1, 455 | Conv_Ovf_I2, 456 | Conv_Ovf_U2, 457 | Conv_Ovf_I4, 458 | Conv_Ovf_U4, 459 | Conv_Ovf_I8, 460 | Conv_Ovf_U8, 461 | Refanyval, 462 | Ckfinite, 463 | Mkrefany, 464 | Ldtoken, 465 | Conv_U2, 466 | Conv_U1, 467 | Conv_I, 468 | Conv_Ovf_I, 469 | Conv_Ovf_U, 470 | Add_Ovf, 471 | Add_Ovf_Un, 472 | Mul_Ovf, 473 | Mul_Ovf_Un, 474 | Sub_Ovf, 475 | Sub_Ovf_Un, 476 | Endfinally, 477 | Leave, 478 | Leave_S, 479 | Stind_I, 480 | Conv_U, 481 | Arglist, 482 | Ceq, 483 | Cgt, 484 | Cgt_Un, 485 | Clt, 486 | Clt_Un, 487 | Ldftn, 488 | Ldvirtftn, 489 | Ldarg, 490 | Ldarga, 491 | Starg, 492 | Ldloc, 493 | Ldloca, 494 | Stloc, 495 | Localloc, 496 | Endfilter, 497 | Unaligned, 498 | Volatile, 499 | Tail, 500 | Initobj, 501 | Constrained, 502 | Cpblk, 503 | Initblk, 504 | No, 505 | Rethrow, 506 | Sizeof, 507 | Refanytype, 508 | Readonly, 509 | } 510 | 511 | public class OpCode 512 | { 513 | public override string ToString() 514 | { 515 | var info = "IL_" + addr.ToString("X04") + " " + code + " "; 516 | if (this.tokenValueType == TokenValueType.Method) 517 | info += tokenMethod; 518 | if (this.tokenValueType == TokenValueType.String) 519 | info += tokenStr; 520 | 521 | if (debugline >= 0) 522 | { 523 | info += "(" + debugline + ")"; 524 | } 525 | return info; 526 | } 527 | public enum TokenValueType 528 | { 529 | Nothing, 530 | Addr,//地址 531 | AddrArray, 532 | String, 533 | Type, 534 | Field, 535 | Method, 536 | I32, 537 | I64, 538 | OTher, 539 | } 540 | public TokenValueType tokenValueType = TokenValueType.Nothing; 541 | public int addr; 542 | public CodeEx code; 543 | public int debugline = -1; 544 | public string debugcode; 545 | public object tokenUnknown; 546 | public int tokenAddr_Index; 547 | //public int tokenAddr; 548 | public int[] tokenAddr_Switch; 549 | public string tokenType; 550 | public string tokenField; 551 | public string tokenMethod; 552 | public int tokenI32; 553 | public Int64 tokenI64; 554 | public float tokenR32; 555 | public double tokenR64; 556 | public string tokenStr; 557 | public void InitToken(object _p) 558 | { 559 | this.tokenUnknown = _p; 560 | switch (code) 561 | { 562 | case CodeEx.Leave: 563 | case CodeEx.Leave_S: 564 | case CodeEx.Br: 565 | case CodeEx.Br_S: 566 | case CodeEx.Brtrue: 567 | case CodeEx.Brtrue_S: 568 | case CodeEx.Brfalse: 569 | case CodeEx.Brfalse_S: 570 | //比较流程控制 571 | case CodeEx.Beq: 572 | case CodeEx.Beq_S: 573 | case CodeEx.Bne_Un: 574 | case CodeEx.Bne_Un_S: 575 | case CodeEx.Bge: 576 | case CodeEx.Bge_S: 577 | case CodeEx.Bge_Un: 578 | case CodeEx.Bge_Un_S: 579 | case CodeEx.Bgt: 580 | case CodeEx.Bgt_S: 581 | case CodeEx.Bgt_Un: 582 | case CodeEx.Bgt_Un_S: 583 | case CodeEx.Ble: 584 | case CodeEx.Ble_S: 585 | case CodeEx.Ble_Un: 586 | case CodeEx.Ble_Un_S: 587 | case CodeEx.Blt: 588 | case CodeEx.Blt_S: 589 | case CodeEx.Blt_Un: 590 | case CodeEx.Blt_Un_S: 591 | //this.tokenAddr = ((Mono.Cecil.Cil.Instruction)_p).Offset; 592 | this.tokenAddr_Index = ((Mono.Cecil.Cil.Instruction)_p).Offset; 593 | this.tokenValueType = TokenValueType.Addr; 594 | break; 595 | case CodeEx.Isinst: 596 | case CodeEx.Constrained: 597 | case CodeEx.Box: 598 | case CodeEx.Initobj: 599 | case CodeEx.Castclass: 600 | case CodeEx.Newarr: 601 | this.tokenType = (_p as Mono.Cecil.TypeReference).FullName; 602 | this.tokenValueType = TokenValueType.Type; 603 | this.tokenUnknown = _p; 604 | break; 605 | case CodeEx.Ldfld: 606 | case CodeEx.Ldflda: 607 | case CodeEx.Ldsfld: 608 | case CodeEx.Ldsflda: 609 | case CodeEx.Stfld: 610 | case CodeEx.Stsfld: 611 | this.tokenField = (_p as Mono.Cecil.FieldReference).FullName; 612 | this.tokenUnknown = _p; 613 | this.tokenValueType = TokenValueType.Field; 614 | break; 615 | case CodeEx.Call: 616 | case CodeEx.Callvirt: 617 | case CodeEx.Newobj: 618 | case CodeEx.Ldftn: 619 | case CodeEx.Ldvirtftn: 620 | 621 | this.tokenMethod = (_p as Mono.Cecil.MethodReference).FullName; 622 | this.tokenUnknown = _p; 623 | this.tokenValueType = TokenValueType.Method; 624 | break; 625 | case CodeEx.Ldc_I4: 626 | this.tokenI32 = (int)_p; 627 | this.tokenValueType = TokenValueType.I32; 628 | break; 629 | case CodeEx.Ldc_I4_S: 630 | this.tokenI32 = (int)Convert.ToDecimal(_p); 631 | this.tokenValueType = TokenValueType.I32; 632 | break; 633 | case CodeEx.Ldc_I4_M1: 634 | this.tokenI32 = -1; 635 | this.tokenValueType = TokenValueType.I32; 636 | break; 637 | case CodeEx.Ldc_I4_0: 638 | this.tokenI32 = 0; 639 | this.tokenValueType = TokenValueType.I32; 640 | break; 641 | case CodeEx.Ldc_I4_1: 642 | this.tokenI32 = 1; 643 | this.tokenValueType = TokenValueType.I32; 644 | break; 645 | case CodeEx.Ldc_I4_2: 646 | this.tokenI32 = 2; 647 | this.tokenValueType = TokenValueType.I32; 648 | break; 649 | case CodeEx.Ldc_I4_3: 650 | this.tokenI32 = 3; 651 | this.tokenValueType = TokenValueType.I32; 652 | break; 653 | case CodeEx.Ldc_I4_4: 654 | this.tokenI32 = 4; 655 | this.tokenValueType = TokenValueType.I32; 656 | break; 657 | case CodeEx.Ldc_I4_5: 658 | this.tokenI32 = 5; 659 | this.tokenValueType = TokenValueType.I32; 660 | break; 661 | case CodeEx.Ldc_I4_6: 662 | this.tokenI32 = 6; 663 | this.tokenValueType = TokenValueType.I32; 664 | break; 665 | case CodeEx.Ldc_I4_7: 666 | this.tokenI32 = 7; 667 | this.tokenValueType = TokenValueType.I32; 668 | break; 669 | case CodeEx.Ldc_I4_8: 670 | this.tokenI32 = 8; 671 | this.tokenValueType = TokenValueType.I32; 672 | break; 673 | case CodeEx.Ldc_I8: 674 | this.tokenI64 = (Int64)_p; 675 | this.tokenValueType = TokenValueType.I64; 676 | break; 677 | case CodeEx.Ldc_R4: 678 | this.tokenR32 = (float)_p; 679 | this.tokenValueType = TokenValueType.OTher; 680 | break; 681 | case CodeEx.Ldc_R8: 682 | this.tokenR64 = (double)_p; 683 | this.tokenValueType = TokenValueType.OTher; 684 | break; 685 | 686 | case CodeEx.Ldstr: 687 | this.tokenStr = _p as string; 688 | this.tokenValueType = TokenValueType.String; 689 | break; 690 | 691 | case CodeEx.Stloc_0: 692 | 693 | break; 694 | case CodeEx.Ldloca: 695 | case CodeEx.Ldloca_S: 696 | case CodeEx.Ldloc_S: 697 | case CodeEx.Stloc_S: 698 | this.tokenI32 = ((Mono.Cecil.Cil.VariableDefinition)_p).Index; 699 | this.tokenValueType = TokenValueType.I32; 700 | 701 | //this.tokenUnknown = _p; 702 | break; 703 | case CodeEx.Ldloc: 704 | case CodeEx.Stloc: 705 | this.tokenI32 = (int)_p; 706 | this.tokenValueType = TokenValueType.I32; 707 | 708 | break; 709 | case CodeEx.Ldloc_0: 710 | this.tokenI32 = 0; 711 | this.tokenValueType = TokenValueType.I32; 712 | 713 | break; 714 | case CodeEx.Ldloc_1: 715 | this.tokenI32 = 1; 716 | this.tokenValueType = TokenValueType.I32; 717 | 718 | break; 719 | case CodeEx.Ldloc_2: 720 | this.tokenI32 = 2; 721 | this.tokenValueType = TokenValueType.I32; 722 | 723 | break; 724 | case CodeEx.Ldloc_3: 725 | this.tokenI32 = 3; 726 | this.tokenValueType = TokenValueType.I32; 727 | 728 | break; 729 | 730 | case CodeEx.Ldarga: 731 | case CodeEx.Ldarga_S: 732 | case CodeEx.Starg: 733 | case CodeEx.Starg_S: 734 | this.tokenI32 = (_p as Mono.Cecil.ParameterDefinition).Index; 735 | this.tokenValueType = TokenValueType.I32; 736 | 737 | break; 738 | case CodeEx.Switch: 739 | { 740 | Mono.Cecil.Cil.Instruction[] e = _p as Mono.Cecil.Cil.Instruction[]; 741 | tokenAddr_Switch = new int[e.Length]; 742 | for (int i = 0; i < e.Length; i++) 743 | { 744 | tokenAddr_Switch[i] = (e[i].Offset); 745 | } 746 | this.tokenValueType = TokenValueType.AddrArray; 747 | 748 | } 749 | break; 750 | case CodeEx.Ldarg: 751 | this.tokenI32 = (int)_p; 752 | this.tokenValueType = TokenValueType.I32; 753 | 754 | break; 755 | case CodeEx.Ldarg_S: 756 | this.tokenI32 = (_p as Mono.Cecil.ParameterReference).Index; 757 | this.tokenValueType = TokenValueType.I32; 758 | 759 | break; 760 | case CodeEx.Volatile: 761 | case CodeEx.Ldind_I1: 762 | case CodeEx.Ldind_U1: 763 | case CodeEx.Ldind_I2: 764 | case CodeEx.Ldind_U2: 765 | case CodeEx.Ldind_I4: 766 | case CodeEx.Ldind_U4: 767 | case CodeEx.Ldind_I8: 768 | case CodeEx.Ldind_I: 769 | case CodeEx.Ldind_R4: 770 | case CodeEx.Ldind_R8: 771 | case CodeEx.Ldind_Ref: 772 | this.tokenValueType = TokenValueType.Nothing; 773 | break; 774 | 775 | case CodeEx.Ldtoken: 776 | var def = (_p as Mono.Cecil.FieldDefinition); 777 | this.tokenUnknown = def.InitialValue; 778 | this.tokenValueType = TokenValueType.Nothing; 779 | break; 780 | default: 781 | this.tokenUnknown = _p; 782 | this.tokenValueType = TokenValueType.Nothing; 783 | break; 784 | } 785 | } 786 | } 787 | 788 | } 789 | -------------------------------------------------------------------------------- /neoj/JVM/Converter_Mutli.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Neo.Compiler.JVM 7 | { 8 | public partial class ModuleConverter 9 | { 10 | private void _ConvertStLoc(JavaMethod method, OpCode src, NeoMethod to, int pos) 11 | { 12 | //push d 13 | var c = _Convert1by1(VM.OpCode.DUPFROMALTSTACK, src, to); 14 | if (c.debugcode == null) 15 | { 16 | c.debugcode = "from StLoc -> 6 code"; 17 | c.debugline = 0; 18 | } 19 | _InsertPush(pos, "", to);//add index 20 | 21 | _InsertPush(2, "", to); 22 | _Insert1(VM.OpCode.ROLL, "", to); 23 | _Insert1(VM.OpCode.SETITEM, "", to); 24 | } 25 | private void _ConvertLdLoc(JavaMethod method, OpCode src, NeoMethod to, int pos) 26 | { 27 | if (method.method.IsStatic == false && pos == 0) 28 | {//忽略非静态函数取this的操作 29 | return; 30 | } 31 | //push d 32 | var c = _Convert1by1(VM.OpCode.DUPFROMALTSTACK, src, to); 33 | if (c.debugcode == null) 34 | { 35 | c.debugcode = "from LdLoc -> 5 code"; 36 | c.debugline = 0; 37 | } 38 | _InsertPush(pos, "", to);//add index 39 | 40 | 41 | //pick 42 | _Convert1by1(VM.OpCode.PICKITEM, null, to); 43 | } 44 | //private void _ConvertLdLocA(OpCode src, AntsMethod to, int pos) 45 | //{ 46 | // _ConvertPush(pos, src, to); 47 | //} 48 | private void _ConvertLdArg(OpCode src, NeoMethod to, int pos) 49 | { 50 | //push d 51 | var c = _Convert1by1(VM.OpCode.DEPTH, src, to); 52 | if (c.debugcode == null) 53 | { 54 | c.debugcode = "from LdArg -> 5 code"; 55 | c.debugline = 0; 56 | } 57 | //push n 58 | _ConvertPush(pos, null, to);//翻转取参数顺序 59 | //_Convert1by1(VM.OpCode.PUSHDATA1, null, to, int2Pushdata1bytes(to.paramtypes.Count - 1 - pos)); 60 | //d+n 61 | _Convert1by1(VM.OpCode.ADD, null, to); 62 | 63 | //push olddepth 64 | _Convert1by1(VM.OpCode.FROMALTSTACK, null, to); 65 | _Convert1by1(VM.OpCode.DUP, null, to); 66 | _Convert1by1(VM.OpCode.TOALTSTACK, null, to); 67 | //(d+n)-olddepth 68 | _Convert1by1(VM.OpCode.SUB, null, to); 69 | 70 | //pick 71 | _Convert1by1(VM.OpCode.PICK, null, to); 72 | } 73 | public bool IsNonCall(JavaMethod method) 74 | { 75 | if (method != null) 76 | if (method.method.Annotations != null) 77 | { 78 | 79 | object[] op = method.method.Annotations[0] as object[]; 80 | if (op[1] as string == "Lorg/neo/smartcontract/framework/Nonemit;") 81 | { 82 | return true; 83 | } 84 | } 85 | 86 | return false; 87 | } 88 | public bool IsOpCall(JavaMethod method, OpCode src, out string callname) 89 | { 90 | if (method != null) 91 | if (method.method.Annotations != null) 92 | { 93 | 94 | object[] op = method.method.Annotations[0] as object[]; 95 | if (op[1] as string == "Lorg/neo/smartcontract/framework/OpCode;") 96 | { 97 | if (op[2] as string == "value") 98 | { 99 | var info = op[3] as object[]; 100 | callname = info[2] as string; 101 | return true; 102 | } 103 | 104 | 105 | } 106 | } 107 | 108 | 109 | //m.Annotations 110 | 111 | callname = ""; 112 | return false; 113 | } 114 | public bool IsSysCall(JavaMethod method, OpCode src, out string callname) 115 | { 116 | if (method != null) 117 | if (method.method.Annotations != null) 118 | { 119 | 120 | object[] op = method.method.Annotations[0] as object[]; 121 | if (op[1] as string == "Lorg/neo/smartcontract/framework/Syscall;") 122 | { 123 | if (op[2] as string == "value") 124 | { 125 | var info = op[3] as string; 126 | callname = info; 127 | return true; 128 | } 129 | 130 | 131 | } 132 | } 133 | 134 | 135 | //m.Annotations 136 | 137 | callname = ""; 138 | return false; 139 | } 140 | public bool IsAppCall(JavaMethod method, OpCode src, out byte[] callhash) 141 | { 142 | if (method != null) 143 | if (method.method.Annotations != null) 144 | { 145 | 146 | object[] op = method.method.Annotations[0] as object[]; 147 | if (op[1] as string == "Lorg/neo/smartcontract/framework/Appcall;") 148 | { 149 | if (op[2] as string == "value") 150 | { 151 | var info = op[3] as string; 152 | if (info.Length < 40) 153 | { 154 | throw new Exception("appcall hash is too short."); 155 | } 156 | byte[] bytes = new byte[20]; 157 | 158 | for (var i = 0; i < 20; i++) 159 | { 160 | bytes[i] = byte.Parse(info.Substring(i * 2, 2), System.Globalization.NumberStyles.AllowHexSpecifier); 161 | } 162 | //string hexhash 需要反序 163 | callhash = bytes.Reverse().ToArray(); 164 | return true; 165 | } 166 | 167 | 168 | } 169 | } 170 | 171 | 172 | //m.Annotations 173 | 174 | callhash = null; 175 | return false; 176 | } 177 | private int _ConvertCall(JavaMethod method, OpCode src, NeoMethod to) 178 | { 179 | _Convert1by1(VM.OpCode.NOP, src, to); 180 | var cc = method.DeclaringType.classfile.constantpool; 181 | var c = cc[src.arg1] as javaloader.ClassFile.ConstantPoolItemMethodref; 182 | var name = c.Class + "::" + c.Name; 183 | 184 | List paramTypes = new List(); 185 | string returntype; 186 | JavaMethod.scanTypes(c.Signature, out returntype, paramTypes); 187 | 188 | 189 | JavaClass javaclass = null; 190 | JavaMethod _javamethod = null; 191 | 192 | if (this.srcModule.classes.ContainsKey(c.Class)) 193 | { 194 | javaclass = this.srcModule.classes[c.Class]; 195 | if (javaclass.methods.ContainsKey(c.Name + c.Signature)) 196 | { 197 | _javamethod = javaclass.methods[c.Name + c.Signature]; 198 | } 199 | else 200 | { 201 | while (javaclass != null) 202 | { 203 | if (this.srcModule.classes.ContainsKey(javaclass.superClass)) 204 | { 205 | javaclass = this.srcModule.classes[javaclass.superClass]; 206 | if (javaclass.methods.ContainsKey(c.Name + c.Signature)) 207 | { 208 | _javamethod = javaclass.methods[c.Name + c.Signature]; 209 | break; 210 | } 211 | } 212 | else 213 | { 214 | javaclass = null; 215 | } 216 | } 217 | } 218 | } 219 | int calltype = 0; 220 | string callname = ""; 221 | byte[] callhash = null; 222 | VM.OpCode callcode = VM.OpCode.NOP; 223 | if (IsNonCall(_javamethod)) 224 | { 225 | return 0; 226 | } 227 | else if (IsOpCall(_javamethod, src, out callname)) 228 | { 229 | if (System.Enum.TryParse(callname, out callcode)) 230 | { 231 | calltype = 2; 232 | } 233 | else 234 | { 235 | throw new Exception("Can not find OpCall:" + callname); 236 | } 237 | } 238 | else if (IsSysCall(_javamethod, src, out callname)) 239 | { 240 | calltype = 3; 241 | } 242 | else if (IsAppCall(_javamethod, src, out callhash)) 243 | { 244 | calltype = 4; 245 | } 246 | else if (this.outModule.mapMethods.ContainsKey(c.Class + "::" + c.Name + c.Signature)) 247 | {//this is a call 248 | calltype = 1; 249 | } 250 | else 251 | { 252 | 253 | if (name == "java.io.PrintStream::println") 254 | {//drop 1; 255 | Console.WriteLine("logstr."); 256 | _Convert1by1(VM.OpCode.DROP, src, to); 257 | return 0; 258 | } 259 | else if (name == "java.math.BigInteger::") 260 | {//do nothing 261 | if (c.Signature == "([B)V") 262 | { 263 | return 0; 264 | } 265 | else if (c.Signature == "(Ljava/lang/String;)V") 266 | { 267 | throw new Exception("not support new BigInteger(string)"); 268 | } 269 | } 270 | else if (name == "java.math.BigInteger::add") 271 | { 272 | _Convert1by1(VM.OpCode.ADD, src, to); 273 | return 0; 274 | } 275 | else if (name == "java.math.BigInteger::subtract") 276 | { 277 | _Convert1by1(VM.OpCode.SUB, src, to); 278 | return 0; 279 | } 280 | else if (name == "java.math.BigInteger::multiply") 281 | { 282 | _Convert1by1(VM.OpCode.MUL, src, to); 283 | return 0; 284 | } 285 | else if (name == "java.math.BigInteger::divide") 286 | { 287 | _Convert1by1(VM.OpCode.DIV, src, to); 288 | return 0; 289 | } 290 | else if (name == "java.math.BigInteger::mod") 291 | { 292 | _Convert1by1(VM.OpCode.MOD, src, to); 293 | return 0; 294 | } 295 | else if (name == "java.math.BigInteger::compareTo") 296 | { 297 | //need parse 298 | _Convert1by1(VM.OpCode.SUB, src, to); 299 | _Convert1by1(VM.OpCode.SIGN, null, to); 300 | //_Convert1by1(VM.OpCode.DEC, src, to); 301 | return 0; 302 | } 303 | // todo: what about java.lang.String::contentEquals? 304 | else if (name == "java.math.BigInteger::equals" || 305 | name == "java.lang.String::equals" || 306 | name == "kotlin.jvm.internal.Intrinsics::areEqual") 307 | { 308 | _Convert1by1(VM.OpCode.NUMEQUAL, src, to); 309 | //_Convert1by1(VM.OpCode.DEC, src, to); 310 | return 0; 311 | } 312 | else if (name == "java.math.BigInteger::valueOf" || 313 | name == "java.math.BigInteger::intValue" || 314 | name == "java.lang.Boolean::valueOf" || 315 | name == "java.lang.Character::valueOf" || 316 | name == "java.lang.String::valueOf" || 317 | name == "java.lang.Long::valueOf" || 318 | name == "java.lang.Integer::valueOf" || 319 | name == "java.lang.Byte::valueOf" || 320 | name == "java.math.BigInteger::toByteArray") 321 | { 322 | //donothing 323 | return 0; 324 | } 325 | else if (name == "java.lang.Boolean::booleanValue" || 326 | name == "java.lang.Integer::integerValue" || 327 | name == "java.lang.Long::longValue" || 328 | name == "java.math.BigInteger::longValue") 329 | { 330 | _Convert1by1(VM.OpCode.NOP, src, to); 331 | return 0; 332 | } 333 | else if (name == "java.lang.String::hashCode") 334 | { 335 | //java switch 的编译方式很奇怪 336 | return 0; 337 | } 338 | else if (name == "java.lang.String::charAt") 339 | { 340 | _ConvertPush(1, src, to); 341 | _Convert1by1(VM.OpCode.SUBSTR, null, to); 342 | return 0; 343 | } 344 | else if (name == "java.lang.String::length") 345 | { 346 | _Convert1by1(VM.OpCode.SIZE, null, to); 347 | return 0; 348 | } 349 | else if (c.Class == "java.lang.StringBuilder") 350 | { 351 | return _ConvertStringBuilder(c.Name, null, to); 352 | } 353 | else if (name == "java.util.Arrays::equals" || 354 | name == "kotlin.jvm.internal.Intrinsics::areEqual") 355 | { 356 | _Convert1by1(VM.OpCode.EQUAL, null, to); 357 | return 0; 358 | } 359 | else if (name == "kotlin.jvm.internal.Intrinsics::checkParameterIsNotNull") 360 | { 361 | _Convert1by1(VM.OpCode.DROP, null, to); 362 | _Convert1by1(VM.OpCode.DROP, null, to); 363 | return 0; 364 | } 365 | else if (name == "kotlin.jvm.internal.Intrinsics::throwNpe") 366 | { 367 | _Convert1by1(VM.OpCode.THROW, src, to); 368 | return 0; 369 | } 370 | } 371 | 372 | if (calltype == 0) 373 | { 374 | throw new Exception("unknown call:" + name); 375 | } 376 | var pcount = paramTypes.Count; 377 | 378 | if (calltype == 2) 379 | { 380 | //opcode call 381 | } 382 | else 383 | {//翻转参数入栈顺序 384 | _Convert1by1(VM.OpCode.NOP, src, to); 385 | if (pcount <= 1) 386 | { 387 | 388 | } 389 | else if (pcount == 2) 390 | { 391 | _Insert1(VM.OpCode.SWAP, "swap 2 param", to); 392 | } 393 | else if (pcount == 3) 394 | { 395 | _InsertPush(2, "swap 0 and 2 param", to); 396 | _Insert1(VM.OpCode.XSWAP, "", to); 397 | } 398 | else 399 | { 400 | for (var i = 0; i < pcount / 2; i++) 401 | { 402 | int saveto = (pcount - 1 - i); 403 | _InsertPush(saveto, "load" + saveto, to); 404 | _Insert1(VM.OpCode.PICK, "", to); 405 | 406 | _InsertPush(i + 1, "load" + i + 1, to); 407 | _Insert1(VM.OpCode.PICK, "", to); 408 | 409 | 410 | _InsertPush(saveto + 2, "save to" + saveto + 2, to); 411 | _Insert1(VM.OpCode.XSWAP, "", to); 412 | _Insert1(VM.OpCode.DROP, "", to); 413 | 414 | _InsertPush(i + 1, "save to" + i + 1, to); 415 | _Insert1(VM.OpCode.XSWAP, "", to); 416 | _Insert1(VM.OpCode.DROP, "", to); 417 | 418 | } 419 | } 420 | } 421 | if (calltype == 1) 422 | { 423 | var _c = _Convert1by1(VM.OpCode.CALL, null, to, new byte[] { 5, 0 }); 424 | _c.needfixfunc = true; 425 | _c.srcfunc = name + c.Signature; 426 | return 0; 427 | } 428 | else if (calltype == 2) 429 | { 430 | _Convert1by1(callcode, null, to); 431 | return 0; 432 | } 433 | else if (calltype == 3) 434 | { 435 | var bytes = Encoding.UTF8.GetBytes(callname); 436 | if (bytes.Length > 252) throw new Exception("string is too long"); 437 | byte[] outbytes = new byte[bytes.Length + 1]; 438 | outbytes[0] = (byte)bytes.Length; 439 | Array.Copy(bytes, 0, outbytes, 1, bytes.Length); 440 | //bytes.Prepend 函数在 dotnet framework 4.6 编译不过 441 | _Convert1by1(VM.OpCode.SYSCALL, null, to, outbytes); 442 | return 0; 443 | } 444 | else if (calltype == 4) 445 | { 446 | _Convert1by1(VM.OpCode.APPCALL, null, to, callhash); 447 | 448 | } 449 | 450 | return 0; 451 | } 452 | 453 | private int _ConvertNewArray(JavaMethod method, OpCode src, NeoMethod to) 454 | { 455 | int skipcount = 0; 456 | if (src.arg1 != 8) 457 | { 458 | //this.logger.Log("_ConvertNewArray::not support type " + src.arg1 + " for array."); 459 | _Convert1by1(VM.OpCode.NEWARRAY, src, to); 460 | return 0; 461 | } 462 | //bytearray 463 | var code = to.body_Codes.Last().Value; 464 | //we need a number 465 | if (code.code > VM.OpCode.PUSH16) 466 | { 467 | throw new Exception("_ConvertNewArr::not support var lens for new byte[?]."); 468 | } 469 | var number = getNumber(code); 470 | 471 | //移除上一条指令 472 | to.body_Codes.Remove(code.addr); 473 | this.addr = code.addr; 474 | 475 | OpCode next = src; 476 | int dupcount = 0; 477 | int pcount = 0; 478 | int[] buf = new int[] { 0, 0, 0 }; 479 | byte[] outbuf = new byte[number]; 480 | do 481 | { 482 | int n = method.GetNextCodeAddr(next.addr); 483 | next = method.body_Codes[n]; 484 | if (next.code == javaloader.NormalizedByteCode.__invokestatic) 485 | { 486 | var i = method.DeclaringType.classfile.constantpool[next.arg1] as javaloader.ClassFile.ConstantPoolItemMethodref; 487 | var callname = i.Class + "::" + i.Name; 488 | if (callname == "java.lang.Integer::valueOf") 489 | { 490 | //nothing 491 | skipcount++; 492 | } 493 | else 494 | { 495 | throw new Exception("can not parse this new array code chain." + next.code); 496 | } 497 | } 498 | else if (next.code == javaloader.NormalizedByteCode.__invokevirtual) 499 | { 500 | var i = method.DeclaringType.classfile.constantpool[next.arg1] as javaloader.ClassFile.ConstantPoolItemMethodref; 501 | var callname = i.Class + "::" + i.Name; 502 | if (callname == "java.lang.Byte::byteValue") 503 | { 504 | skipcount++; 505 | } 506 | else 507 | { 508 | throw new Exception("can not parse this new array code chain." + next.code); 509 | } 510 | } 511 | else if (next.code == javaloader.NormalizedByteCode.__checkcast) 512 | { 513 | //nothing 514 | skipcount++; 515 | } 516 | else if (next.code == javaloader.NormalizedByteCode.__dup) 517 | { 518 | dupcount++; 519 | skipcount++; 520 | } 521 | else if (next.code == javaloader.NormalizedByteCode.__iconst) 522 | { 523 | buf[pcount] = next.arg1; 524 | pcount++; 525 | skipcount++; 526 | } 527 | else if (next.code == javaloader.NormalizedByteCode.__bastore) 528 | { 529 | dupcount--; 530 | var v = (byte)buf[pcount - 1]; 531 | var i = buf[pcount - 2]; 532 | //while (outbuf.Count <= i) 533 | // outbuf.Add(0); 534 | outbuf[i] = v; 535 | pcount -= 2; 536 | skipcount++; 537 | } 538 | else if (next.code == javaloader.NormalizedByteCode.__astore) 539 | { 540 | _ConvertPush(outbuf.ToArray(), src, to); 541 | return skipcount; 542 | } 543 | else 544 | { 545 | throw new Exception("can not parse this new array code chain."); 546 | } 547 | } 548 | while (next != null); 549 | 550 | return 0; 551 | } 552 | private int _ConvertNew(JavaMethod method, OpCode src, NeoMethod to) 553 | { 554 | var c = method.DeclaringType.classfile.constantpool[src.arg1] as javaloader.ClassFile.ConstantPoolItemClass; 555 | if (c.Name == "java.lang.StringBuilder") 556 | { 557 | _ConvertPush(1, src, to); 558 | _Insert1(VM.OpCode.NEWARRAY, "", to); 559 | } 560 | else if (c.Name == "java.math.BigInteger") 561 | { 562 | var next = method.GetNextCodeAddr(src.addr); 563 | if (method.body_Codes[next].code == javaloader.NormalizedByteCode.__dup) 564 | { 565 | return 1; 566 | } 567 | else 568 | { 569 | return 0; 570 | } 571 | } 572 | else 573 | { 574 | throw new Exception("new not supported type." + c.Name); 575 | } 576 | return 0; 577 | } 578 | private int _ConvertIfNonNull(JavaMethod method, OpCode src, NeoMethod to) 579 | { 580 | int nm = method.GetLastCodeAddr(src.addr);//上一指令 581 | int n = method.GetNextCodeAddr(src.addr); 582 | int n2 = method.GetNextCodeAddr(n); 583 | var codenext = method.body_Codes[n]; 584 | 585 | if (nm >= 0 && n >= 0 && n2 >= 0 586 | && method.body_Codes[nm].code == javaloader.NormalizedByteCode.__dup //上一条是dup指令 587 | && src.arg1 == n2 - src.addr //刚好跳过throw 指令 588 | && codenext.code == javaloader.NormalizedByteCode.__invokestatic 589 | ) 590 | { 591 | var cc = method.DeclaringType.classfile.constantpool; 592 | var c = cc[codenext.arg1] as javaloader.ClassFile.ConstantPoolItemMethodref; 593 | var name = c.Class + "::" + c.Name; 594 | if (name == "kotlin.jvm.internal.Intrinsics::throwNpe") 595 | {//识别到套路 596 | var _code = to.body_Codes.Last().Value; 597 | //移除上一条指令 598 | to.body_Codes.Remove(_code.addr); 599 | this.addr = _code.addr; 600 | 601 | return 1; 602 | } 603 | } 604 | var codenextnext = method.body_Codes[n2]; 605 | _ConvertPush(0, src, to);//和0比较 606 | _Convert1by1(VM.OpCode.NUMNOTEQUAL, null, to); 607 | var code = _Convert1by1(VM.OpCode.JMPIF, null, to, new byte[] { 0, 0 }); 608 | code.needfix = true; 609 | code.srcaddr = src.addr + src.arg1; 610 | return 0; 611 | } 612 | private int _ConvertStringBuilder(string callname, OpCode src, NeoMethod to) 613 | { 614 | if (callname == "") 615 | { 616 | _Convert1by1(VM.OpCode.SWAP, null, to); 617 | _Convert1by1(VM.OpCode.DUP, null, to); 618 | 619 | _ConvertPush(0, null, to); 620 | _ConvertPush(3, null, to); 621 | _Convert1by1(VM.OpCode.ROLL, null, to); 622 | _Convert1by1(VM.OpCode.SETITEM, null, to); 623 | return 0; 624 | } 625 | if (callname == "append") 626 | { 627 | _Convert1by1(VM.OpCode.SWAP, null, to);//把对象数组换上来 628 | _Convert1by1(VM.OpCode.DUP, null, to); 629 | _ConvertPush(0, null, to); 630 | _Convert1by1(VM.OpCode.PICKITEM, null, to); 631 | 632 | _ConvertPush(2, null, to); 633 | _Convert1by1(VM.OpCode.ROLL, null, to); 634 | _Convert1by1(VM.OpCode.SWAP, null, to);//把对象数组换上来 635 | _Convert1by1(VM.OpCode.CAT, null, to); 636 | 637 | _ConvertPush(0, null, to); 638 | _Convert1by1(VM.OpCode.SWAP, null, to);//把对象数组换上来 639 | _Convert1by1(VM.OpCode.SETITEM, null, to); 640 | return 0; 641 | } 642 | if (callname == "toString") 643 | { 644 | _ConvertPush(0, null, to); 645 | _Convert1by1(VM.OpCode.PICKITEM, null, to); 646 | return 0; 647 | } 648 | return 0; 649 | } 650 | //private int _ConvertNewArr(ILMethod method, OpCode src, AntsMethod to) 651 | //{ 652 | // var code = to.body_Codes.Last().Value; 653 | // //we need a number 654 | // if (code.code > VM.OpCode.PUSH16) 655 | // { 656 | // this.logger.Log("_ConvertNewArr::not support var lens for array."); 657 | // return 0; 658 | // } 659 | // var number = getNumber(code); 660 | 661 | // //移除上一条指令 662 | // to.body_Codes.Remove(code.addr); 663 | // this.addr--; 664 | // if (code.bytes != null) 665 | // this.addr -= code.bytes.Length; 666 | 667 | // var type = src.tokenType; 668 | // if (type != "System.Byte") 669 | // { 670 | // this.logger.Log("_ConvertNewArr::not support type " + type + " for array."); 671 | // } 672 | // else 673 | // { 674 | // int n = method.GetNextCodeAddr(src.addr); 675 | // int n2 = method.GetNextCodeAddr(n); 676 | // int n3 = method.GetNextCodeAddr(n2); 677 | // if (method.body_Codes[n].code == CodeEx.Dup && method.body_Codes[n2].code == CodeEx.Ldtoken && method.body_Codes[n3].code == CodeEx.Call) 678 | // {//這是在初始化數組 679 | 680 | // var data = method.body_Codes[n2].tokenUnknown as byte[]; 681 | // this._ConvertPush(data, src, to); 682 | 683 | // return 3; 684 | 685 | // } 686 | // else 687 | // { 688 | // this._ConvertPush(new byte[number], src, to); 689 | // } 690 | // } 691 | 692 | 693 | 694 | // return 0; 695 | 696 | //} 697 | //private int _ConvertInitObj(OpCode src, AntsMethod to) 698 | //{ 699 | // var type = (src.tokenUnknown as Mono.Cecil.TypeReference).Resolve(); 700 | // _Convert1by1(VM.OpCode.NOP, src, to);//空白 701 | // _ConvertPush(type.Fields.Count, null, to);//插入个数量 702 | // _Insert1(VM.OpCode.ARRAYNEW, null, to); 703 | // //然後要將計算棧上的第一個值,寫入第二個值對應的pos 704 | // _Convert1by1(VM.OpCode.SWAP, null, to);//replace n to top 705 | 706 | // //push d 707 | // _Convert1by1(VM.OpCode.DEPTH, null, to); 708 | 709 | // _Convert1by1(VM.OpCode.DEC, null, to);//d 多了一位,剪掉 710 | // _Convert1by1(VM.OpCode.SWAP, null, to);//把n拿上來 711 | // //push n 712 | // //_ConvertPush(pos, null, to);有n了 713 | // //d-n-1 714 | // _Convert1by1(VM.OpCode.SUB, null, to); 715 | // _Convert1by1(VM.OpCode.DEC, null, to); 716 | 717 | // //push olddepth 718 | // _Convert1by1(VM.OpCode.FROMALTSTACK, null, to); 719 | // _Convert1by1(VM.OpCode.DUP, null, to); 720 | // _Convert1by1(VM.OpCode.TOALTSTACK, null, to); 721 | // //(d-n-1)-olddepth 722 | // _Convert1by1(VM.OpCode.SUB, null, to); 723 | 724 | // //swap d-n-1 and top 725 | // _Convert1by1(VM.OpCode.XSWAP, null, to); 726 | // //drop top 727 | // _Convert1by1(VM.OpCode.DROP, null, to); 728 | // return 0; 729 | //} 730 | //private int _ConvertStfld(OpCode src, AntsMethod to) 731 | //{ 732 | // var field = (src.tokenUnknown as Mono.Cecil.FieldReference).Resolve(); 733 | // var type = field.DeclaringType; 734 | // var id = type.Fields.IndexOf(field); 735 | // if (id < 0) 736 | // throw new Exception("impossible."); 737 | // _Convert1by1(VM.OpCode.NOP, src, to);//空白 738 | 739 | // _Convert1by1(VM.OpCode.SWAP, null, to);//把n拿上來 n 和 item 740 | // //push d 741 | // _Convert1by1(VM.OpCode.DEPTH, src, to); 742 | // _Convert1by1(VM.OpCode.DEC, null, to);//d 多了一位,剪掉 743 | // _Convert1by1(VM.OpCode.SWAP, null, to);//把n拿上來 744 | 745 | // //push n 746 | // //_ConvertPush(pos, null, to);有n了 747 | // //d-n-1 748 | // _Convert1by1(VM.OpCode.SUB, null, to); 749 | // _Convert1by1(VM.OpCode.DEC, null, to); 750 | 751 | // //push olddepth 752 | // _Convert1by1(VM.OpCode.FROMALTSTACK, null, to); 753 | // _Convert1by1(VM.OpCode.DUP, null, to); 754 | // _Convert1by1(VM.OpCode.TOALTSTACK, null, to); 755 | // //(d-n-1)-olddepth 756 | // _Convert1by1(VM.OpCode.SUB, null, to); 757 | 758 | // //pick 759 | // _Convert1by1(VM.OpCode.PICK, null, to); 760 | 761 | 762 | // _Convert1by1(VM.OpCode.SWAP, null, to);//把item 拿上來 763 | // _ConvertPush(id, null, to); 764 | // _Convert1by1(VM.OpCode.ARRAYSETITEM, null, to);//修改值 765 | // return 0; 766 | //} 767 | 768 | //private int _ConvertLdfld(OpCode src, AntsMethod to) 769 | //{ 770 | // var field = (src.tokenUnknown as Mono.Cecil.FieldReference).Resolve(); 771 | // var type = field.DeclaringType; 772 | // var id = type.Fields.IndexOf(field); 773 | // if (id < 0) 774 | // throw new Exception("impossible."); 775 | // _ConvertPush(id, src, to); 776 | // _Convert1by1(VM.OpCode.PICKITEM, null, to);//修改值 777 | 778 | // return 0; 779 | //} 780 | } 781 | 782 | } 783 | --------------------------------------------------------------------------------