* Fixed bug where void functions cleaned up their mess multiple times
* Compiler improvements
* Fixed Neo APIs naming convention
* Added NOP after syscall for matching AVM files with neo-python.

Imported from CityOfZion/neo-storm (f93a28ef87d272a74f821d45ae0c6735a8c610be).
This commit is contained in:
Anthony De Meulemeester 2018-10-17 19:19:01 +02:00 committed by Roman Khimov
parent f547708e10
commit b97e5aafec
2 changed files with 39 additions and 48 deletions

View file

@ -87,18 +87,13 @@ func (c *codegen) emitLoadLocal(name string) {
} }
func (c *codegen) emitLoadLocalPos(pos int) { func (c *codegen) emitLoadLocalPos(pos int) {
emitOpcode(c.prog, vm.FROMALTSTACK) emitOpcode(c.prog, vm.DUPFROMALTSTACK)
emitOpcode(c.prog, vm.DUP)
emitOpcode(c.prog, vm.TOALTSTACK)
emitInt(c.prog, int64(pos)) emitInt(c.prog, int64(pos))
emitOpcode(c.prog, vm.PICKITEM) emitOpcode(c.prog, vm.PICKITEM)
} }
func (c *codegen) emitStoreLocal(pos int) { func (c *codegen) emitStoreLocal(pos int) {
emitOpcode(c.prog, vm.FROMALTSTACK) emitOpcode(c.prog, vm.DUPFROMALTSTACK)
emitOpcode(c.prog, vm.DUP)
emitOpcode(c.prog, vm.TOALTSTACK)
if pos < 0 { if pos < 0 {
log.Fatalf("invalid position to store local: %d", pos) log.Fatalf("invalid position to store local: %d", pos)
@ -144,6 +139,10 @@ func (c *codegen) convertFuncDecl(file ast.Node, decl *ast.FuncDecl) {
f, ok = c.funcs[decl.Name.Name] f, ok = c.funcs[decl.Name.Name]
if ok { if ok {
// If this function is a syscall we will not convert it to bytecode.
if isSyscall(f) {
return
}
c.setLabel(f.label) c.setLabel(f.label)
} else { } else {
f = c.newFunc(decl) f = c.newFunc(decl)
@ -262,14 +261,13 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
// To be backwards compatible we will put them them in. // To be backwards compatible we will put them them in.
// See issue #65 (https://github.com/CityOfZion/neo-go/issues/65) // See issue #65 (https://github.com/CityOfZion/neo-go/issues/65)
l := c.newLabel() l := c.newLabel()
emitJmp(c.prog, vm.JMP, int16(l)) // emitJmp(c.prog, vm.JMP, int16(l))
c.setLabel(l) c.setLabel(l)
if len(n.Results) > 0 { if len(n.Results) > 0 {
ast.Walk(c, n.Results[0]) ast.Walk(c, n.Results[0])
} }
emitOpcode(c.prog, vm.NOP) // @OPTIMIZE
emitOpcode(c.prog, vm.FROMALTSTACK) emitOpcode(c.prog, vm.FROMALTSTACK)
emitOpcode(c.prog, vm.DROP) // Cleanup the stack. emitOpcode(c.prog, vm.DROP) // Cleanup the stack.
emitOpcode(c.prog, vm.RET) emitOpcode(c.prog, vm.RET)
@ -425,11 +423,6 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
} }
} }
// c# compiler adds a NOP (0x61) before every function call. Dont think its relevant
// and we could easily removed it, but to be consistent with the original compiler I
// will put them in. ^^
emitOpcode(c.prog, vm.NOP)
// Check builtin first to avoid nil pointer on funcScope! // Check builtin first to avoid nil pointer on funcScope!
switch { switch {
case isBuiltin: case isBuiltin:
@ -442,11 +435,6 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor {
emitCall(c.prog, vm.CALL, int16(f.label)) emitCall(c.prog, vm.CALL, int16(f.label))
} }
// If we are not assigning this function to a variable we need to drop
// (cleanup) the top stack item. It's not a void but you get the point \o/.
if _, ok := c.scope.voidCalls[n]; ok {
emitOpcode(c.prog, vm.DROP)
}
return nil return nil
case *ast.SelectorExpr: case *ast.SelectorExpr:
@ -540,7 +528,10 @@ func (c *codegen) convertSyscall(api, name string) {
log.Fatalf("unknown VM syscall api: %s", name) log.Fatalf("unknown VM syscall api: %s", name)
} }
emitSyscall(c.prog, api) emitSyscall(c.prog, api)
emitOpcode(c.prog, vm.NOP) // @OPTIMIZE
// This NOP instruction is basically not needed, but if we do, we have a
// one to one matching avm file with neo-python which is very nice for debugging.
emitOpcode(c.prog, vm.NOP)
} }
func (c *codegen) convertBuiltin(expr *ast.CallExpr) { func (c *codegen) convertBuiltin(expr *ast.CallExpr) {

View file

@ -2,45 +2,45 @@ package compiler
var syscalls = map[string]map[string]string{ var syscalls = map[string]map[string]string{
"storage": { "storage": {
"GetContext": "System.Storage.GetContext", "GetContext": "Neo.Storage.GetContext",
"Put": "System.Storage.Put", "Put": "Neo.Storage.Put",
"Get": "System.Storage.Get", "Get": "Neo.Storage.Get",
"Delete": "System.Storage.Delete", "Delete": "Neo.Storage.Delete",
"Find": "System.Storage.Find", "Find": "Neo.Storage.Find",
}, },
"runtime": { "runtime": {
"GetTrigger": "System.Runtime.GetTrigger", "GetTrigger": "Neo.Runtime.GetTrigger",
"CheckWitness": "System.Runtime.CheckWitness", "CheckWitness": "Neo.Runtime.CheckWitness",
"Notify": "System.Runtime.Notify", "Notify": "Neo.Runtime.Notify",
"Log": "System.Runtime.Log", "Log": "Neo.Runtime.Log",
"GetTime": "System.Runtime.GetTime", "GetTime": "Neo.Runtime.GetTime",
"Serialize": "System.Runtime.Serialize", "Serialize": "Neo.Runtime.Serialize",
"Deserialize": "System.Runtime.Deserialize", "Deserialize": "Neo.Runtime.Deserialize",
}, },
"blockchain": { "blockchain": {
"GetHeight": "System.Blockchain.GetHeight", "GetHeight": "Neo.Blockchain.GetHeight",
"GetHeader": "System.Blockchain.GetHeader", "GetHeader": "Neo.Blockchain.GetHeader",
"GetBlock": "System.Blockchain.GetBlock", "GetBlock": "Neo.Blockchain.GetBlock",
"GetTransaction": "System.Blockchain.GetTransaction", "GetTransaction": "Neo.Blockchain.GetTransaction",
"GetContract": "System.Blockchain.GetContract", "GetContract": "Neo.Blockchain.GetContract",
"GetAccount": "Neo.Blockchain.GetAccount", "GetAccount": "Neo.Blockchain.GetAccount",
"GetValidators": "Neo.Blockchain.GetValidators", "GetValidators": "Neo.Blockchain.GetValidators",
"GetAsset": "Neo.Blockchain.GetAsset", "GetAsset": "Neo.Blockchain.GetAsset",
}, },
"header": { "header": {
"GetIndex": "System.Header.GetIndex", "GetIndex": "Neo.Header.GetIndex",
"GetHash": "System.Header.GetHash", "GetHash": "Neo.Header.GetHash",
"GetPrevHash": "System.Header.GetPrevHash", "GetPrevHash": "Neo.Header.GetPrevHash",
"GetTimestamp": "System.Header.GetTimestamp", "GetTimestamp": "Neo.Header.GetTimestamp",
"GetVersion": "Neo.Header.GetVersion", "GetVersion": "Neo.Header.GetVersion",
"GetMerkleRoot": "Neo.Header.GetMerkleRoot", "GetMerkleRoot": "Neo.Header.GetMerkleRoot",
"GetConsensusData": "Neo.Header.GetConsensusData", "GetConsensusData": "Neo.Header.GetConsensusData",
"GetNextConsensus": "Neo.Header.GetNextConsensus", "GetNextConsensus": "Neo.Header.GetNextConsensus",
}, },
"block": { "block": {
"GetTransactionCount": "System.Block.GetTransactionCount", "GetTransactionCount": "Neo.Block.GetTransactionCount",
"GetTransactions": "System.Block.GetTransactions", "GetTransactions": "Neo.Block.GetTransactions",
"GetTransaction": "System.Block.GetTransaction", "GetTransaction": "Neo.Block.GetTransaction",
}, },
"transaction": { "transaction": {
"GetType": "Neo.Transaction.GetType", "GetType": "Neo.Transaction.GetType",
@ -76,10 +76,10 @@ var syscalls = map[string]map[string]string{
"GetScriptHash": "Neo.Output.GetScriptHash", "GetScriptHash": "Neo.Output.GetScriptHash",
}, },
"engine": { "engine": {
"GetScriptContainer": "System.ExecutionEngine.GetScriptContainer", "GetScriptContainer": "Neo.ExecutionEngine.GetScriptContainer",
"GetCallingScriptHash": "System.ExecutionEngine.GetCallingScriptHash", "GetCallingScriptHash": "Neo.ExecutionEngine.GetCallingScriptHash",
"GetEntryScriptHash": "System.ExecutionEngine.GetEntryScriptHash", "GetEntryScriptHash": "Neo.ExecutionEngine.GetEntryScriptHash",
"GetExecutingScriptHash": "System.ExecutionEngine.GetExecutingScriptHash", "GetExecutingScriptHash": "Neo.ExecutionEngine.GetExecutingScriptHash",
}, },
"iterator": { "iterator": {
"Create": "Neo.Iterator.Create", "Create": "Neo.Iterator.Create",