public static Neo.ASML.Node.ASMProject Compile(Microsoft.CodeAnalysis.SyntaxNode node) { var proj = new Neo.ASML.Node.ASMProject(); CompileContext context = new CompileContext(); CompileNode(context, proj, node); return(proj); }
public static Neo.ASML.Node.ASMProject Compile(byte[] dll) { var proj = new Neo.ASML.Node.ASMProject(); CompileContext context = new CompileContext(); context.OpenDLL(dll); foreach (var t in context.module.Types) { foreach (var m in t.Methods) { CompileMethod(context, proj, m); } } return(proj); }
static void Main(string[] args) { string srccode = @" static class Program { static int Main() { int a=1; int b=2; return a+b; } } "; //step01 get a c# dll; byte[] dll = GetILDLL(srccode); DumpILDLL(dll); //step02 compile AST->ASMLProject Neo.ASML.Node.ASMProject proj = Compiler.Compile(dll); proj.Dump((str) => Console.WriteLine(str)); //step03 link ASML->machinecode var module = Neo.ASML.Linker.Linker.CreateModule(proj); module.Dump((str) => Console.WriteLine(str)); var machinecode = Neo.ASML.Linker.Linker.Link(module); DumpAVM(machinecode); //run machinecode with neovm var engine = new Neo.VM.ExecutionEngine(); engine.LoadScript(machinecode); engine.Execute(); //show result var calcstack = engine.ResultStack; var v = calcstack.Peek(); Console.WriteLine("retvalue=" + v.GetBigInteger()); }
static void Main(string[] args) { string srccode = @" class Program { static void Main() { int a=1; int b=2; return a+b; } } "; //step01 srccode -> AST var ast = Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree.ParseText(srccode); var root = ast.GetRoot(); DumpAst(root); //step02 compile AST->ASMLProject Neo.ASML.Node.ASMProject proj = Compiler.Compile(root); //step03 link ASML->machinecode var module = Neo.ASML.Linker.Linker.CreateModule(proj); module.Dump((str) => Console.WriteLine(str)); var machinecode = Neo.ASML.Linker.Linker.Link(module); DumpAVM(machinecode); //run machinecode with neovm var engine = new Neo.VM.ExecutionEngine(); engine.LoadScript(machinecode); engine.Execute(); //show result var calcstack = engine.ResultStack; var v = calcstack.Peek(); Console.WriteLine("retvalue=" + v.GetBigInteger()); }
static void CompileMethod(CompileContext context, Neo.ASML.Node.ASMProject proj, Mono.Cecil.MethodDefinition method) { var func = new Neo.ASML.Node.ASMFunction(); func.Name = method.Name; proj.nodes.Add(func); //insert varibletable func.nodes.Insert(0, new Neo.ASML.Node.ASMInstruction() { opcode = Neo.ASML.Node.ASMOpCode.CreatePush(), valuetext = method.Body.Variables.Count.ToString(), commentRight = "//insert varlist code" }); func.nodes.Insert(1, new Neo.ASML.Node.ASMInstruction() { opcode = Neo.ASML.Node.ASMOpCode.Create(Neo.VM.OpCode.NEWARRAY) }); func.nodes.Insert(2, new Neo.ASML.Node.ASMInstruction() { opcode = Neo.ASML.Node.ASMOpCode.Create(Neo.VM.OpCode.TOALTSTACK) }); foreach (var inst in method.Body.Instructions) { switch (inst.OpCode.Code) { case Mono.Cecil.Cil.Code.Nop: func.nodes.Add(new Neo.ASML.Node.ASMInstruction() { opcode = Neo.ASML.Node.ASMOpCode.Create(Neo.VM.OpCode.NOP) }); break; case Mono.Cecil.Cil.Code.Ldc_I4_0: PUSH(func, 0); break; case Mono.Cecil.Cil.Code.Ldc_I4_1: PUSH(func, 1); break; case Mono.Cecil.Cil.Code.Ldc_I4_2: PUSH(func, 2); break; case Mono.Cecil.Cil.Code.Ldloc_0: LDLOC(func, 0); break; case Mono.Cecil.Cil.Code.Ldloc_1: LDLOC(func, 1); break; case Mono.Cecil.Cil.Code.Ldloc_2: LDLOC(func, 2); break; case Mono.Cecil.Cil.Code.Stloc_0: STLOC(func, 0); break; case Mono.Cecil.Cil.Code.Stloc_1: STLOC(func, 1); break; case Mono.Cecil.Cil.Code.Stloc_2: STLOC(func, 2); break; case Mono.Cecil.Cil.Code.Add: func.nodes.Add(new Neo.ASML.Node.ASMInstruction() { opcode = Neo.ASML.Node.ASMOpCode.Create(Neo.VM.OpCode.ADD) }); break; case Mono.Cecil.Cil.Code.Br: case Mono.Cecil.Cil.Code.Br_S: continue; case Mono.Cecil.Cil.Code.Ret: func.nodes.Add(new Neo.ASML.Node.ASMInstruction() { opcode = Neo.ASML.Node.ASMOpCode.Create(Neo.VM.OpCode.FROMALTSTACK), commentRight = "clear variblelist" }); func.nodes.Add(new Neo.ASML.Node.ASMInstruction() { opcode = Neo.ASML.Node.ASMOpCode.Create(Neo.VM.OpCode.DROP) }); func.nodes.Add(new Neo.ASML.Node.ASMInstruction() { opcode = Neo.ASML.Node.ASMOpCode.Create(Neo.VM.OpCode.RET) }); continue; default: throw new Exception("lost IL:" + inst.OpCode.Code); } } }
static void CompileNode(CompileContext context, Neo.ASML.Node.ASMProject project, Microsoft.CodeAnalysis.SyntaxNode node) { if (node is Microsoft.CodeAnalysis.CSharp.Syntax.MethodDeclarationSyntax) { var func = new Neo.ASML.Node.ASMFunction(); var srcmethod = node as Microsoft.CodeAnalysis.CSharp.Syntax.MethodDeclarationSyntax; func.Name = srcmethod.Identifier.ValueText; project.nodes.Add(func); context.variables = new List <string>(); foreach (var op in srcmethod.Body.Statements) { if (op is Microsoft.CodeAnalysis.CSharp.Syntax.LocalDeclarationStatementSyntax) { var localvar = op as Microsoft.CodeAnalysis.CSharp.Syntax.LocalDeclarationStatementSyntax; var vars = localvar.Declaration.Variables; foreach (var _var in vars) { context.variables.Add(_var.Identifier.ValueText); var index = context.variables.IndexOf(_var.Identifier.ValueText); if (_var.Initializer != null) { var v = _var.Initializer.Value.ToString(); func.nodes.Add(new Neo.ASML.Node.ASMComment() { text = "//" + _var.ToString() }); //push setitem func.nodes.Add(new Neo.ASML.Node.ASMInstruction() { opcode = Neo.ASML.Node.ASMOpCode.Create(Neo.VM.OpCode.DUPFROMALTSTACK), commentRight = "//variables array" }); func.nodes.Add(new Neo.ASML.Node.ASMInstruction() { opcode = Neo.ASML.Node.ASMOpCode.CreatePush(), valuetext = index.ToString(), commentRight = "//index" }); //push value CompileExpression(context, func, _var.Initializer.Value, "//value"); func.nodes.Add(new Neo.ASML.Node.ASMInstruction() { opcode = Neo.ASML.Node.ASMOpCode.Create(Neo.VM.OpCode.SETITEM) }); } } //define a local value } if (op is Microsoft.CodeAnalysis.CSharp.Syntax.ReturnStatementSyntax) { var ret = op as Microsoft.CodeAnalysis.CSharp.Syntax.ReturnStatementSyntax; if (ret.Expression != null) { CompileExpression(context, func, ret.Expression, "//" + ret.ToString()); } func.nodes.Add(new Neo.ASML.Node.ASMComment() { text = "//clear and return" }); func.nodes.Add(new Neo.ASML.Node.ASMInstruction() { opcode = Neo.ASML.Node.ASMOpCode.Create(Neo.VM.OpCode.FROMALTSTACK) }); func.nodes.Add(new Neo.ASML.Node.ASMInstruction() { opcode = Neo.ASML.Node.ASMOpCode.Create(Neo.VM.OpCode.DROP) }); func.nodes.Add(new Neo.ASML.Node.ASMInstruction() { opcode = Neo.ASML.Node.ASMOpCode.Create(Neo.VM.OpCode.RET) }); } } var variablecount = context.variables.Count; func.nodes.Insert(0, new Neo.ASML.Node.ASMInstruction() { opcode = Neo.ASML.Node.ASMOpCode.CreatePush(), valuetext = variablecount.ToString(), commentRight = "//insert varlist code" }); func.nodes.Insert(1, new Neo.ASML.Node.ASMInstruction() { opcode = Neo.ASML.Node.ASMOpCode.Create(Neo.VM.OpCode.NEWARRAY) }); func.nodes.Insert(2, new Neo.ASML.Node.ASMInstruction() { opcode = Neo.ASML.Node.ASMOpCode.Create(Neo.VM.OpCode.TOALTSTACK) }); } else { var subnodes = node.ChildNodes(); foreach (var sn in subnodes) { CompileNode(context, project, sn); } } }