From 995089dc5a63bac826d037f2c80ed71e3efbeaf4 Mon Sep 17 00:00:00 2001 From: Harry Pierson Date: Tue, 26 May 2020 16:46:04 -0700 Subject: [PATCH 01/12] WIP --- src/Neo.Compiler.MSIL/Compiler.cs | 10 +- src/Neo.Compiler.MSIL/DebugExport.cs | 138 ++++++++++++++++++++++ src/Neo.Compiler.MSIL/FuncExport.cs | 4 +- src/Neo.Compiler.MSIL/MSIL/Conv_Common.cs | 1 + src/Neo.Compiler.MSIL/MSIL/ILModule.cs | 2 + src/Neo.Compiler.MSIL/NeoModule.cs | 1 + src/Neo.Compiler.MSIL/Program.cs | 44 ++++++- 7 files changed, 195 insertions(+), 5 deletions(-) create mode 100644 src/Neo.Compiler.MSIL/DebugExport.cs diff --git a/src/Neo.Compiler.MSIL/Compiler.cs b/src/Neo.Compiler.MSIL/Compiler.cs index a4078bc63..ad96a9c8d 100644 --- a/src/Neo.Compiler.MSIL/Compiler.cs +++ b/src/Neo.Compiler.MSIL/Compiler.cs @@ -159,7 +159,10 @@ private static void ExtractFileAndReferences(string filename, string extension, /// Assembly public static Assembly CompileVBFiles(string[] filenames, string[] references, bool releaseMode = true) { - var tree = filenames.Select(u => VisualBasicSyntaxTree.ParseText(File.ReadAllText(u))).ToArray(); + var tree = filenames.Select(u => VisualBasicSyntaxTree.ParseText( + File.ReadAllText(u), + path: u, + encoding: System.Text.Encoding.UTF8)).ToArray(); var op = new VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary, optimizationLevel: releaseMode ? OptimizationLevel.Release : OptimizationLevel.Debug); return Assembly.Create(VisualBasicCompilation.Create("SmartContract", tree, CreateReferences(references), op)); } @@ -173,7 +176,10 @@ public static Assembly CompileVBFiles(string[] filenames, string[] references, b /// Assembly public static Assembly CompileCSFiles(string[] filenames, string[] references, bool releaseMode = true) { - var tree = filenames.Select(u => CSharpSyntaxTree.ParseText(File.ReadAllText(u))).ToArray(); + var tree = filenames.Select(u => CSharpSyntaxTree.ParseText( + File.ReadAllText(u), + path: u, + encoding: System.Text.Encoding.UTF8)).ToArray(); var op = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary, optimizationLevel: releaseMode ? OptimizationLevel.Release : OptimizationLevel.Debug); return Assembly.Create(CSharpCompilation.Create("SmartContract", tree, CreateReferences(references), op)); } diff --git a/src/Neo.Compiler.MSIL/DebugExport.cs b/src/Neo.Compiler.MSIL/DebugExport.cs new file mode 100644 index 000000000..0cf5e7f6b --- /dev/null +++ b/src/Neo.Compiler.MSIL/DebugExport.cs @@ -0,0 +1,138 @@ +using Mono.Cecil.Cil; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using vmtool; + +namespace Neo.Compiler +{ + public static class DebugExport + { + private static MyJson.JsonNode_Array GetSequencePoints(IEnumerable codes, IReadOnlyDictionary docMap, IReadOnlyDictionary addrMap) + { + var points = codes + .Where(code => code.sequencePoint != null) + .Select(code => (code.addr, code.sequencePoint)); + + var outjson = new MyJson.JsonNode_Array(); + + foreach (var (address, sequencePoint) in points) + { + var value = string.Format("{0}[{1}]{2}:{3}-{4}:{5}", + addrMap?[address] ?? address, + docMap[sequencePoint.Document.Url], + sequencePoint.StartLine, + sequencePoint.StartColumn, + sequencePoint.EndLine, + sequencePoint.EndColumn); + outjson.Add(new MyJson.JsonNode_ValueString(value)); + } + + return outjson; + } + + private static string ConvertType(string type) + { + if (type == "System.Object") + return string.Empty; + + return FuncExport.ConvType(type); + } + + private static MyJson.JsonNode_Array ConvertParamList(IList @params) + { + var paramsJson = new MyJson.JsonNode_Array(); + foreach (var param in @params) + { + var value = string.Format("{0},{1}", param.name, ConvertType(param.type)); + paramsJson.Add(new MyJson.JsonNode_ValueString(value)); + } + + return paramsJson; + } + + private static MyJson.JsonNode_Array GetMethods(NeoModule module, IReadOnlyDictionary docMap, IReadOnlyDictionary addrMap) + { + var outjson = new MyJson.JsonNode_Array(); + + foreach (var method in module.mapMethods.Values) + { + if (method.body_Codes.Values.Count == 0) + { + continue; + } + + var name = string.Format("{0},{1}", + method._namespace, method.displayName); + + var range = string.Format("{0}-{1}", + method.body_Codes.Values.First().addr, + method.body_Codes.Values.Last().addr); + + var methodJson = new MyJson.JsonNode_Object(); + methodJson.SetDictValue("id", method.name); + methodJson.SetDictValue("name", name); + methodJson.SetDictValue("range", range); + methodJson.SetDictValue("params", ConvertParamList(method.paramtypes)); + methodJson.SetDictValue("return", ConvertType(method.returntype)); + methodJson.SetDictValue("variables", ConvertParamList(method.body_Variables)); + methodJson.SetDictValue("sequence-points", GetSequencePoints(method.body_Codes.Values, docMap, addrMap)); + outjson.Add(methodJson); + } + return outjson; + } + + private static MyJson.JsonNode_Array GetEvents(NeoModule module) + { + var outjson = new MyJson.JsonNode_Array(); + foreach (var @event in module.mapEvents.Values) + { + var name = string.Format("{0},{1}", + @event._namespace, @event.displayName); + + var eventJson = new MyJson.JsonNode_Object(); + eventJson.SetDictValue("id", @event.name); + eventJson.SetDictValue("name", name); + eventJson.SetDictValue("params", ConvertParamList(@event.paramtypes)); + outjson.Add(eventJson); + } + return outjson; + } + + private static IReadOnlyDictionary GetDocumentMap(NeoModule module) + { + return module.mapMethods.Values + .SelectMany(m => m.body_Codes.Values) + .Where(code => code.sequencePoint != null) + .Select(code => code.sequencePoint.Document.Url) + .Distinct() + .Select((d, i) => (d, i)) + .ToDictionary(t => t.d, t => t.i); + } + + private static MyJson.JsonNode_Array GetDocuments(IReadOnlyDictionary docMap) + { + var outjson = new MyJson.JsonNode_Array(); + foreach (var doc in docMap.OrderBy(kvp => kvp.Value)) + { + Debug.Assert(outjson.Count == doc.Value); + outjson.Add(new MyJson.JsonNode_ValueString(doc.Key)); + } + return outjson; + } + + public static MyJson.JsonNode_Object Export(NeoModule am, IReadOnlyDictionary addrMap) + { + var docMap = GetDocumentMap(am); + + var outjson = new MyJson.JsonNode_Object(); + // outjson.SetDictValue("entrypoint", am.mainMethod); + outjson.SetDictValue("documents", GetDocuments(docMap)); + outjson.SetDictValue("methods", GetMethods(am, docMap, addrMap)); + outjson.SetDictValue("events", GetEvents(am)); + return outjson; + } + } +} diff --git a/src/Neo.Compiler.MSIL/FuncExport.cs b/src/Neo.Compiler.MSIL/FuncExport.cs index f8d611c69..4c145372c 100644 --- a/src/Neo.Compiler.MSIL/FuncExport.cs +++ b/src/Neo.Compiler.MSIL/FuncExport.cs @@ -8,7 +8,7 @@ namespace vmtool { public class FuncExport { - static string ConvType(string _type) + public static string ConvType(string _type) { switch (_type) { @@ -57,7 +57,7 @@ static string ConvType(string _type) case "System.Object": return "ByteArray"; } - if (_type.Contains("[]")) + if (_type?.Contains("[]") ?? false) return "Array"; return "Unknown:" + _type; diff --git a/src/Neo.Compiler.MSIL/MSIL/Conv_Common.cs b/src/Neo.Compiler.MSIL/MSIL/Conv_Common.cs index b726c2a71..7668c9da7 100644 --- a/src/Neo.Compiler.MSIL/MSIL/Conv_Common.cs +++ b/src/Neo.Compiler.MSIL/MSIL/Conv_Common.cs @@ -78,6 +78,7 @@ private NeoCode Convert1by1(VM.OpCode code, OpCode src, NeoMethod to, byte[] dat _code.debugline = src.debugline; _code.debugILAddr = src.addr; _code.debugILCode = src.code.ToString(); + _code.sequencePoint = src.sequencePoint; } addr++; diff --git a/src/Neo.Compiler.MSIL/MSIL/ILModule.cs b/src/Neo.Compiler.MSIL/MSIL/ILModule.cs index 9f73b799f..01aefdffd 100644 --- a/src/Neo.Compiler.MSIL/MSIL/ILModule.cs +++ b/src/Neo.Compiler.MSIL/MSIL/ILModule.cs @@ -265,6 +265,7 @@ public ILMethod(ILType type, Mono.Cecil.MethodDefinition method, ILogger logger { c.debugcode = sp.Document.Url; c.debugline = sp.StartLine; + c.sequencePoint = sp; } c.InitToken(code.Operand); this.body_Codes.Add(c.addr, c); @@ -535,6 +536,7 @@ public class OpCode public CodeEx code; public int debugline = -1; public string debugcode; + public Mono.Cecil.Cil.SequencePoint sequencePoint; public object tokenUnknown; public int tokenAddr_Index; //public int tokenAddr; diff --git a/src/Neo.Compiler.MSIL/NeoModule.cs b/src/Neo.Compiler.MSIL/NeoModule.cs index baabc086b..a776d00a2 100644 --- a/src/Neo.Compiler.MSIL/NeoModule.cs +++ b/src/Neo.Compiler.MSIL/NeoModule.cs @@ -178,6 +178,7 @@ public class NeoCode public int srcaddr; public int[] srcaddrswitch; public string srcfunc; + public Mono.Cecil.Cil.SequencePoint sequencePoint; public override string ToString() { diff --git a/src/Neo.Compiler.MSIL/Program.cs b/src/Neo.Compiler.MSIL/Program.cs index 049837159..b8bf3cc25 100644 --- a/src/Neo.Compiler.MSIL/Program.cs +++ b/src/Neo.Compiler.MSIL/Program.cs @@ -152,6 +152,7 @@ public static int Compile(Options options) byte[] bytes; int bSucc = 0; string jsonstr = null; + string debugstr = null; NeoModule module = null; // Convert and build @@ -183,6 +184,18 @@ public static int Compile(Options options) log.Log("gen abi Error:" + err.ToString()); } + try + { + var outjson = DebugExport.Export(module, addrConvTable); + StringBuilder sb = new StringBuilder(); + outjson.ConvertToStringWithFormat(sb, 0); + debugstr = sb.ToString(); + log.Log("gen debug succ"); + } + catch (Exception err) + { + log.Log("gen debug Error:" + err.ToString()); + } } catch (Exception err) { @@ -235,6 +248,35 @@ public static int Compile(Options options) return -1; } + try + { + string debugname = onlyname + ".debug.json"; + string debugzip = onlyname + ".nefdbgnfo"; + + File.Delete(debugname); + File.WriteAllText(debugname, debugstr); + log.Log("write:" + debugname); + bSucc++; + + // var tempName = Path.GetTempFileName(); + // File.Delete(tempName); + // File.WriteAllText(tempName, debugstr); + + // File.Delete(debugzip); + // using (var archive = ZipFile.Open(debugzip, ZipArchiveMode.Create)) + // { + // archive.CreateEntryFromFile(tempName, Path.GetFileName(debugname)); + // } + // File.Delete(tempName); + // log.Log("write:" + debugzip); + // bSucc = true; + } + catch (Exception err) + { + log.Log("Write debug Error:" + err.ToString()); + return -1; + } + try { var features = module == null ? ContractFeatures.NoProperty : module.attributes @@ -275,7 +317,7 @@ public static int Compile(Options options) { } - if (bSucc == 3) + if (bSucc == 4) { log.Log("SUCC"); return 0; From 7e4da0a89d039750d3b7e93342ca9258814cdb38 Mon Sep 17 00:00:00 2001 From: Harry Pierson Date: Wed, 10 Jun 2020 17:26:42 -0700 Subject: [PATCH 02/12] add hash to debug info --- src/Neo.Compiler.MSIL/DebugExport.cs | 9 +++++---- src/Neo.Compiler.MSIL/FuncExport.cs | 15 ++++++++++----- src/Neo.Compiler.MSIL/Program.cs | 2 +- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/Neo.Compiler.MSIL/DebugExport.cs b/src/Neo.Compiler.MSIL/DebugExport.cs index 0cf5e7f6b..3a23ca570 100644 --- a/src/Neo.Compiler.MSIL/DebugExport.cs +++ b/src/Neo.Compiler.MSIL/DebugExport.cs @@ -123,15 +123,16 @@ private static MyJson.JsonNode_Array GetDocuments(IReadOnlyDictionary addrMap) + public static MyJson.JsonNode_Object Export(NeoModule module, byte[] script, IReadOnlyDictionary addrMap) { - var docMap = GetDocumentMap(am); + var docMap = GetDocumentMap(module); var outjson = new MyJson.JsonNode_Object(); + outjson.SetDictValue("hash", FuncExport.ComputeHash(script)); // outjson.SetDictValue("entrypoint", am.mainMethod); outjson.SetDictValue("documents", GetDocuments(docMap)); - outjson.SetDictValue("methods", GetMethods(am, docMap, addrMap)); - outjson.SetDictValue("events", GetEvents(am)); + outjson.SetDictValue("methods", GetMethods(module, docMap, addrMap)); + outjson.SetDictValue("events", GetEvents(module)); return outjson; } } diff --git a/src/Neo.Compiler.MSIL/FuncExport.cs b/src/Neo.Compiler.MSIL/FuncExport.cs index 4c145372c..873e1dfaa 100644 --- a/src/Neo.Compiler.MSIL/FuncExport.cs +++ b/src/Neo.Compiler.MSIL/FuncExport.cs @@ -63,23 +63,28 @@ public static string ConvType(string _type) return "Unknown:" + _type; } - public static MyJson.JsonNode_Object Export(NeoModule module, byte[] script) + public static string ComputeHash(byte[] script) { var sha256 = System.Security.Cryptography.SHA256.Create(); byte[] hash256 = sha256.ComputeHash(script); var ripemd160 = new Neo.Cryptography.RIPEMD160Managed(); var hash = ripemd160.ComputeHash(hash256); - var outjson = new MyJson.JsonNode_Object(); - - //hash StringBuilder sb = new StringBuilder(); sb.Append("0x"); foreach (var b in hash.Reverse().ToArray()) { sb.Append(b.ToString("x02")); } - outjson.SetDictValue("hash", sb.ToString()); + return sb.ToString(); + } + + public static MyJson.JsonNode_Object Export(NeoModule module, byte[] script, Dictionary addrConvTable) + { + var outjson = new MyJson.JsonNode_Object(); + + //hash + outjson.SetDictValue("hash", ComputeHash(script)); //entrypoint var entryPoint = "main"; diff --git a/src/Neo.Compiler.MSIL/Program.cs b/src/Neo.Compiler.MSIL/Program.cs index b8bf3cc25..98f015656 100644 --- a/src/Neo.Compiler.MSIL/Program.cs +++ b/src/Neo.Compiler.MSIL/Program.cs @@ -186,7 +186,7 @@ public static int Compile(Options options) try { - var outjson = DebugExport.Export(module, addrConvTable); + var outjson = DebugExport.Export(module, bytes, addrConvTable); StringBuilder sb = new StringBuilder(); outjson.ConvertToStringWithFormat(sb, 0); debugstr = sb.ToString(); From 5b8c7d0a2d47280803bea6b908c2720962478fb8 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 29 May 2020 17:02:03 +0200 Subject: [PATCH 03/12] fixup --- src/Neo.Compiler.MSIL/DebugExport.cs | 7 ++++--- src/Neo.Compiler.MSIL/FuncExport.cs | 2 +- src/Neo.Compiler.MSIL/Program.cs | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/Neo.Compiler.MSIL/DebugExport.cs b/src/Neo.Compiler.MSIL/DebugExport.cs index 3a23ca570..7014275c3 100644 --- a/src/Neo.Compiler.MSIL/DebugExport.cs +++ b/src/Neo.Compiler.MSIL/DebugExport.cs @@ -1,6 +1,7 @@ using Mono.Cecil.Cil; using System; using System.Collections.Generic; +using System.Collections.Immutable; using System.Diagnostics; using System.Linq; using System.Text; @@ -123,15 +124,15 @@ private static MyJson.JsonNode_Array GetDocuments(IReadOnlyDictionary addrMap) + public static MyJson.JsonNode_Object Export(NeoModule module, byte[] script) { var docMap = GetDocumentMap(module); var outjson = new MyJson.JsonNode_Object(); outjson.SetDictValue("hash", FuncExport.ComputeHash(script)); - // outjson.SetDictValue("entrypoint", am.mainMethod); + outjson.SetDictValue("entrypoint", module.mainMethod); outjson.SetDictValue("documents", GetDocuments(docMap)); - outjson.SetDictValue("methods", GetMethods(module, docMap, addrMap)); + outjson.SetDictValue("methods", GetMethods(module, docMap, null)); outjson.SetDictValue("events", GetEvents(module)); return outjson; } diff --git a/src/Neo.Compiler.MSIL/FuncExport.cs b/src/Neo.Compiler.MSIL/FuncExport.cs index 873e1dfaa..6b26d4840 100644 --- a/src/Neo.Compiler.MSIL/FuncExport.cs +++ b/src/Neo.Compiler.MSIL/FuncExport.cs @@ -79,7 +79,7 @@ public static string ComputeHash(byte[] script) return sb.ToString(); } - public static MyJson.JsonNode_Object Export(NeoModule module, byte[] script, Dictionary addrConvTable) + public static MyJson.JsonNode_Object Export(NeoModule module, byte[] script) { var outjson = new MyJson.JsonNode_Object(); diff --git a/src/Neo.Compiler.MSIL/Program.cs b/src/Neo.Compiler.MSIL/Program.cs index 98f015656..be2e50bc1 100644 --- a/src/Neo.Compiler.MSIL/Program.cs +++ b/src/Neo.Compiler.MSIL/Program.cs @@ -186,7 +186,7 @@ public static int Compile(Options options) try { - var outjson = DebugExport.Export(module, bytes, addrConvTable); + var outjson = DebugExport.Export(module, bytes); StringBuilder sb = new StringBuilder(); outjson.ConvertToStringWithFormat(sb, 0); debugstr = sb.ToString(); From 75b61eaa35902a0163af08ef28b8802c8f0e682f Mon Sep 17 00:00:00 2001 From: Harry Pierson Date: Thu, 11 Jun 2020 09:58:14 -0700 Subject: [PATCH 04/12] don't emit hidden sequence points --- src/Neo.Compiler.MSIL/MSIL/ILModule.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo.Compiler.MSIL/MSIL/ILModule.cs b/src/Neo.Compiler.MSIL/MSIL/ILModule.cs index 01aefdffd..27daac55d 100644 --- a/src/Neo.Compiler.MSIL/MSIL/ILModule.cs +++ b/src/Neo.Compiler.MSIL/MSIL/ILModule.cs @@ -261,7 +261,7 @@ public ILMethod(ILType type, Mono.Cecil.MethodDefinition method, ILogger logger }; var sp = method.DebugInformation.GetSequencePoint(code); - if (sp != null) + if (sp != null && !sp.IsHidden) { c.debugcode = sp.Document.Url; c.debugline = sp.StartLine; From 8bd4248d40a9e4a8742035f0c84674aaf5909321 Mon Sep 17 00:00:00 2001 From: Harry Pierson Date: Thu, 11 Jun 2020 12:15:37 -0700 Subject: [PATCH 05/12] include local variables in debug info --- src/Neo.Compiler.MSIL/DebugExport.cs | 2 +- src/Neo.Compiler.MSIL/MSIL/ILModule.cs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Neo.Compiler.MSIL/DebugExport.cs b/src/Neo.Compiler.MSIL/DebugExport.cs index 7014275c3..bbd45c2bb 100644 --- a/src/Neo.Compiler.MSIL/DebugExport.cs +++ b/src/Neo.Compiler.MSIL/DebugExport.cs @@ -78,7 +78,7 @@ private static MyJson.JsonNode_Array GetMethods(NeoModule module, IReadOnlyDicti methodJson.SetDictValue("range", range); methodJson.SetDictValue("params", ConvertParamList(method.paramtypes)); methodJson.SetDictValue("return", ConvertType(method.returntype)); - methodJson.SetDictValue("variables", ConvertParamList(method.body_Variables)); + methodJson.SetDictValue("variables", ConvertParamList(method.method.body_Variables)); methodJson.SetDictValue("sequence-points", GetSequencePoints(method.body_Codes.Values, docMap, addrMap)); outjson.Add(methodJson); } diff --git a/src/Neo.Compiler.MSIL/MSIL/ILModule.cs b/src/Neo.Compiler.MSIL/MSIL/ILModule.cs index 27daac55d..5c9c44dc6 100644 --- a/src/Neo.Compiler.MSIL/MSIL/ILModule.cs +++ b/src/Neo.Compiler.MSIL/MSIL/ILModule.cs @@ -247,7 +247,9 @@ public ILMethod(ILType type, Mono.Cecil.MethodDefinition method, ILogger logger { foreach (var v in bodyNative.Variables) { - var indexname = v.VariableType.Name + ":" + v.Index; + var indexname = method.DebugInformation.TryGetName(v, out var varname) + ? varname + : v.VariableType.Name + ":" + v.Index; this.body_Variables.Add(new NeoParam(indexname, v.VariableType.FullName)); } } From cad3d71fc8b73245c84d225cb5ac8ec065dc6059 Mon Sep 17 00:00:00 2001 From: Harry Pierson Date: Thu, 18 Jun 2020 16:16:00 -0700 Subject: [PATCH 06/12] global tool support --- .../Neo.Compiler.MSIL.csproj | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj b/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj index 580e06251..c0dccc083 100644 --- a/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj +++ b/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj @@ -5,10 +5,8 @@ Neo.Compiler.MSIL 3.0.0-preview2 The Neo Project - netcoreapp3.1;netstandard2.1 Exe neon - Neo.Compiler.MSIL NEO;Blockchain;Smart Contract;Compiler https://github.com/neo-project/neo-devpack-dotnet MIT @@ -21,6 +19,24 @@ true + + + + Exe + Neo.Neon + true + netcoreapp3.1 + + + + Neo.Compiler.MSIL + netstandard2.0 + + From be2db60422b763c12f517e05843b8a1d75f80758 Mon Sep 17 00:00:00 2001 From: Harry Pierson Date: Thu, 18 Jun 2020 16:17:48 -0700 Subject: [PATCH 07/12] fix netstandard2.1 --- src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj b/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj index c0dccc083..fe554541f 100644 --- a/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj +++ b/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj @@ -34,7 +34,7 @@ Neo.Compiler.MSIL - netstandard2.0 + netstandard2.1 From d5231713232f355762e902d4c57a42d75f0af8cc Mon Sep 17 00:00:00 2001 From: Harry Pierson Date: Fri, 19 Jun 2020 11:22:17 -0700 Subject: [PATCH 08/12] fixup merge --- src/Neo.Compiler.MSIL/DebugExport.cs | 14 ++++++------- src/Neo.Compiler.MSIL/FuncExport.cs | 2 +- src/Neo.Compiler.MSIL/Program.cs | 30 ++++++++++++---------------- 3 files changed, 21 insertions(+), 25 deletions(-) diff --git a/src/Neo.Compiler.MSIL/DebugExport.cs b/src/Neo.Compiler.MSIL/DebugExport.cs index bbd45c2bb..51a0282e6 100644 --- a/src/Neo.Compiler.MSIL/DebugExport.cs +++ b/src/Neo.Compiler.MSIL/DebugExport.cs @@ -11,7 +11,7 @@ namespace Neo.Compiler { public static class DebugExport { - private static MyJson.JsonNode_Array GetSequencePoints(IEnumerable codes, IReadOnlyDictionary docMap, IReadOnlyDictionary addrMap) + private static MyJson.JsonNode_Array GetSequencePoints(IEnumerable codes, IReadOnlyDictionary docMap, IReadOnlyDictionary addrConvTable) { var points = codes .Where(code => code.sequencePoint != null) @@ -22,7 +22,7 @@ private static MyJson.JsonNode_Array GetSequencePoints(IEnumerable code foreach (var (address, sequencePoint) in points) { var value = string.Format("{0}[{1}]{2}:{3}-{4}:{5}", - addrMap?[address] ?? address, + addrConvTable?[address] ?? address, docMap[sequencePoint.Document.Url], sequencePoint.StartLine, sequencePoint.StartColumn, @@ -54,7 +54,7 @@ private static MyJson.JsonNode_Array ConvertParamList(IList @params) return paramsJson; } - private static MyJson.JsonNode_Array GetMethods(NeoModule module, IReadOnlyDictionary docMap, IReadOnlyDictionary addrMap) + private static MyJson.JsonNode_Array GetMethods(NeoModule module, IReadOnlyDictionary docMap, IReadOnlyDictionary addrConvTable) { var outjson = new MyJson.JsonNode_Array(); @@ -79,7 +79,7 @@ private static MyJson.JsonNode_Array GetMethods(NeoModule module, IReadOnlyDicti methodJson.SetDictValue("params", ConvertParamList(method.paramtypes)); methodJson.SetDictValue("return", ConvertType(method.returntype)); methodJson.SetDictValue("variables", ConvertParamList(method.method.body_Variables)); - methodJson.SetDictValue("sequence-points", GetSequencePoints(method.body_Codes.Values, docMap, addrMap)); + methodJson.SetDictValue("sequence-points", GetSequencePoints(method.body_Codes.Values, docMap, addrConvTable)); outjson.Add(methodJson); } return outjson; @@ -124,15 +124,15 @@ private static MyJson.JsonNode_Array GetDocuments(IReadOnlyDictionary addrConvTable) { var docMap = GetDocumentMap(module); var outjson = new MyJson.JsonNode_Object(); outjson.SetDictValue("hash", FuncExport.ComputeHash(script)); - outjson.SetDictValue("entrypoint", module.mainMethod); + // outjson.SetDictValue("entrypoint", module.mainMethod); outjson.SetDictValue("documents", GetDocuments(docMap)); - outjson.SetDictValue("methods", GetMethods(module, docMap, null)); + outjson.SetDictValue("methods", GetMethods(module, docMap, addrConvTable)); outjson.SetDictValue("events", GetEvents(module)); return outjson; } diff --git a/src/Neo.Compiler.MSIL/FuncExport.cs b/src/Neo.Compiler.MSIL/FuncExport.cs index 8da9ed074..89e831f8b 100644 --- a/src/Neo.Compiler.MSIL/FuncExport.cs +++ b/src/Neo.Compiler.MSIL/FuncExport.cs @@ -81,7 +81,7 @@ public static string ComputeHash(byte[] script) return sb.ToString(); } - public static MyJson.JsonNode_Object Export(NeoModule module, byte[] script) + public static MyJson.JsonNode_Object Export(NeoModule module, byte[] script, Dictionary addrConvTable) { var outjson = new MyJson.JsonNode_Object(); diff --git a/src/Neo.Compiler.MSIL/Program.cs b/src/Neo.Compiler.MSIL/Program.cs index 8edb6eea7..881e708e7 100644 --- a/src/Neo.Compiler.MSIL/Program.cs +++ b/src/Neo.Compiler.MSIL/Program.cs @@ -7,6 +7,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.IO.Compression; using System.Linq; using System.Reflection; using System.Text; @@ -196,7 +197,7 @@ public static int Compile(Options options) try { - var outjson = DebugExport.Export(module, bytes); + var outjson = DebugExport.Export(module, bytes, addrConvTable); StringBuilder sb = new StringBuilder(); outjson.ConvertToStringWithFormat(sb, 0); debugstr = sb.ToString(); @@ -263,23 +264,18 @@ public static int Compile(Options options) string debugname = onlyname + ".debug.json"; string debugzip = onlyname + ".nefdbgnfo"; - File.Delete(debugname); - File.WriteAllText(debugname, debugstr); - log.Log("write:" + debugname); - bSucc++; + var tempName = Path.GetTempFileName(); + File.Delete(tempName); + File.WriteAllText(tempName, debugstr); - // var tempName = Path.GetTempFileName(); - // File.Delete(tempName); - // File.WriteAllText(tempName, debugstr); - - // File.Delete(debugzip); - // using (var archive = ZipFile.Open(debugzip, ZipArchiveMode.Create)) - // { - // archive.CreateEntryFromFile(tempName, Path.GetFileName(debugname)); - // } - // File.Delete(tempName); - // log.Log("write:" + debugzip); - // bSucc = true; + File.Delete(debugzip); + using (var archive = ZipFile.Open(debugzip, ZipArchiveMode.Create)) + { + archive.CreateEntryFromFile(tempName, Path.GetFileName(debugname)); + } + File.Delete(tempName); + log.Log("write:" + debugzip); + bSucc++; } catch (Exception err) { From f7084bf36227c1ccd5e76acc3ba82a90d47bf14d Mon Sep 17 00:00:00 2001 From: Harry Pierson Date: Fri, 19 Jun 2020 11:51:04 -0700 Subject: [PATCH 09/12] fix null ref issues --- src/Neo.Compiler.MSIL/DebugExport.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Neo.Compiler.MSIL/DebugExport.cs b/src/Neo.Compiler.MSIL/DebugExport.cs index 51a0282e6..8b9a00bb1 100644 --- a/src/Neo.Compiler.MSIL/DebugExport.cs +++ b/src/Neo.Compiler.MSIL/DebugExport.cs @@ -22,7 +22,7 @@ private static MyJson.JsonNode_Array GetSequencePoints(IEnumerable code foreach (var (address, sequencePoint) in points) { var value = string.Format("{0}[{1}]{2}:{3}-{4}:{5}", - addrConvTable?[address] ?? address, + addrConvTable.TryGetValue(address, out var newAddress) ? newAddress : address, docMap[sequencePoint.Document.Url], sequencePoint.StartLine, sequencePoint.StartColumn, @@ -42,8 +42,9 @@ private static string ConvertType(string type) return FuncExport.ConvType(type); } - private static MyJson.JsonNode_Array ConvertParamList(IList @params) + private static MyJson.JsonNode_Array ConvertParamList(IEnumerable @params) { + @params ??= Enumerable.Empty(); var paramsJson = new MyJson.JsonNode_Array(); foreach (var param in @params) { @@ -78,7 +79,7 @@ private static MyJson.JsonNode_Array GetMethods(NeoModule module, IReadOnlyDicti methodJson.SetDictValue("range", range); methodJson.SetDictValue("params", ConvertParamList(method.paramtypes)); methodJson.SetDictValue("return", ConvertType(method.returntype)); - methodJson.SetDictValue("variables", ConvertParamList(method.method.body_Variables)); + methodJson.SetDictValue("variables", ConvertParamList(method.method?.body_Variables)); methodJson.SetDictValue("sequence-points", GetSequencePoints(method.body_Codes.Values, docMap, addrConvTable)); outjson.Add(methodJson); } @@ -124,9 +125,10 @@ private static MyJson.JsonNode_Array GetDocuments(IReadOnlyDictionary addrConvTable) + public static MyJson.JsonNode_Object Export(NeoModule module, byte[] script, IReadOnlyDictionary addrConvTable) { var docMap = GetDocumentMap(module); + addrConvTable ??= ImmutableDictionary.Empty; var outjson = new MyJson.JsonNode_Object(); outjson.SetDictValue("hash", FuncExport.ComputeHash(script)); From 41657db57ed7613107d752cb60bccd73becbcdcd Mon Sep 17 00:00:00 2001 From: Harry Pierson Date: Fri, 19 Jun 2020 11:51:12 -0700 Subject: [PATCH 10/12] debug info unit test --- .../UnitTest_DebugInfo.cs | 33 +++++++++++++++++++ .../Utils/BuildScript.cs | 12 +++++++ 2 files changed, 45 insertions(+) create mode 100644 tests/Neo.Compiler.MSIL.UnitTests/UnitTest_DebugInfo.cs diff --git a/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_DebugInfo.cs b/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_DebugInfo.cs new file mode 100644 index 000000000..08819ca3b --- /dev/null +++ b/tests/Neo.Compiler.MSIL.UnitTests/UnitTest_DebugInfo.cs @@ -0,0 +1,33 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Neo.Compiler.MSIL.UnitTests.Utils; +using System; +using System.Linq; + +namespace Neo.Compiler.MSIL +{ + [TestClass] + public class UnitTest_DebugInfo + { + [TestMethod] + public void Test_DebugInfo() + { + var testengine = new TestEngine(); + testengine.AddEntryScript("./TestClasses/Contract_Event.cs"); + var debugInfo = testengine.ScriptEntry.debugInfo; + Assert.IsTrue(debugInfo.HaveDictItem("hash")); + Assert.AreEqual(debugInfo["hash"].type, MyJson.JsonType.Value_String); + Assert.IsTrue(debugInfo.HaveDictItem("documents")); + Assert.AreEqual(debugInfo["documents"].type, MyJson.JsonType.Array); + Assert.IsTrue(debugInfo["documents"].AsList().Count == 1); + Assert.IsTrue(debugInfo["documents"].AsList().All(n => n.type == MyJson.JsonType.Value_String)); + Assert.IsTrue(debugInfo.HaveDictItem("methods")); + Assert.AreEqual(debugInfo["methods"].type, MyJson.JsonType.Array); + Assert.AreEqual(debugInfo["methods"].AsList().Count, 1); + Assert.AreEqual(debugInfo["methods"].AsList()[0].asDict()["name"].AsString(), "Neo.Compiler.MSIL.UnitTests.TestClasses.Contract_Event,main"); + Assert.IsTrue(debugInfo.HaveDictItem("events")); + Assert.AreEqual(debugInfo["events"].type, MyJson.JsonType.Array); + Assert.AreEqual(debugInfo["events"].AsList().Count, 1); + Assert.AreEqual(debugInfo["events"].AsList()[0].asDict()["name"].AsString(), "Neo.Compiler.MSIL.UnitTests.TestClasses.Contract_Event,transfer"); + } + } +} diff --git a/tests/Neo.Compiler.MSIL.UnitTests/Utils/BuildScript.cs b/tests/Neo.Compiler.MSIL.UnitTests/Utils/BuildScript.cs index 97c6b737a..f395e0b35 100644 --- a/tests/Neo.Compiler.MSIL.UnitTests/Utils/BuildScript.cs +++ b/tests/Neo.Compiler.MSIL.UnitTests/Utils/BuildScript.cs @@ -18,6 +18,7 @@ public class BuildScript public byte[] finalNEF { get; private set; } public MyJson.JsonNode_Object finialABI { get; private set; } public string finalManifest { get; private set; } + public MyJson.JsonNode_Object debugInfo { get; private set; } public BuildScript() { @@ -86,6 +87,17 @@ public void Build(Stream fs, Stream fspdb, bool optimizer) return; } + try + { + debugInfo = DebugExport.Export(converterIL.outModule, finalNEF, addrConvTable); + } + catch (Exception err) + { + log.Log("Gen debugInfo Error:" + err.ToString()); + this.Error = err; + return; + } + try { var features = converterIL.outModule == null ? ContractFeatures.NoProperty : converterIL.outModule.attributes From 4723e07eddbbc28467a5dac7867acf2e00886e62 Mon Sep 17 00:00:00 2001 From: Harry Pierson Date: Fri, 19 Jun 2020 12:00:34 -0700 Subject: [PATCH 11/12] fix null deref in FuncExport.ConvType --- src/Neo.Compiler.MSIL/FuncExport.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo.Compiler.MSIL/FuncExport.cs b/src/Neo.Compiler.MSIL/FuncExport.cs index 89e831f8b..5c12bbb34 100644 --- a/src/Neo.Compiler.MSIL/FuncExport.cs +++ b/src/Neo.Compiler.MSIL/FuncExport.cs @@ -59,7 +59,7 @@ public static string ConvType(string _type) } if (_type?.Contains("[]") ?? false) return "Array"; - if (_type.Contains("Neo.SmartContract.Framework.Services.Neo.Enumerator")) + if (_type?.Contains("Neo.SmartContract.Framework.Services.Neo.Enumerator") ?? false) return "InteropInterface"; return "Unknown:" + _type; From 2e2678bd8112cddc72972a7799109ed6f5e54b6b Mon Sep 17 00:00:00 2001 From: Harry Pierson Date: Tue, 23 Jun 2020 07:44:06 -0700 Subject: [PATCH 12/12] use TargetFramework --- src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj b/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj index 7fe933b88..379429c96 100644 --- a/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj +++ b/src/Neo.Compiler.MSIL/Neo.Compiler.MSIL.csproj @@ -34,7 +34,7 @@ Neo.Compiler.MSIL - netstandard2.1 + netstandard2.1