mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
core/vm: Add support for AoT compilation of WASM precompiles
This commit is contained in:
parent
94db4dc329
commit
cc5bed4b21
6 changed files with 504 additions and 8 deletions
233
core/vm/aot.go
Normal file
233
core/vm/aot.go
Normal file
|
|
@ -0,0 +1,233 @@
|
||||||
|
// Copyright 2019 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
// Copyright (c) 2018 Timo Savola. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package vm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/core/vm/aot"
|
||||||
|
|
||||||
|
"github.com/tsavola/wag"
|
||||||
|
"github.com/tsavola/wag/buffer"
|
||||||
|
"github.com/tsavola/wag/compile"
|
||||||
|
"github.com/tsavola/wag/object/debug/dump"
|
||||||
|
"github.com/tsavola/wag/wa"
|
||||||
|
)
|
||||||
|
|
||||||
|
const linearMemoryAddressSpace = 8 * 1024 * 1024 * 1024
|
||||||
|
const signalStackReserve = 8192
|
||||||
|
const goStackVectorOffset = -4 * 8
|
||||||
|
|
||||||
|
type importFunc struct {
|
||||||
|
index int
|
||||||
|
params int
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeMem(size int, prot, extraFlags int) (mem []byte, err error) {
|
||||||
|
if size > 0 {
|
||||||
|
mem, err = syscall.Mmap(-1, 0, size, prot, syscall.MAP_PRIVATE|syscall.MAP_ANONYMOUS|extraFlags)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func memAddr(mem []byte) uintptr {
|
||||||
|
return (*reflect.SliceHeader)(unsafe.Pointer(&mem)).Data
|
||||||
|
}
|
||||||
|
|
||||||
|
func alignSize(size, alignment int) int {
|
||||||
|
return (size + (alignment - 1)) &^ (alignment - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GrowMemory(size int32) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// AoTContract
|
||||||
|
type AoTContract struct {
|
||||||
|
Code []byte
|
||||||
|
Num int
|
||||||
|
ImportVector []byte
|
||||||
|
ImportFuncs map[string]importFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAoTContract(code []byte, num int) *AoTContract {
|
||||||
|
ret := &AoTContract{Code: code, Num: num}
|
||||||
|
ret.ImportFuncs = make(map[string]importFunc)
|
||||||
|
ret.ImportVector = make([]byte, (5+4)*8)
|
||||||
|
|
||||||
|
binary.LittleEndian.PutUint64(ret.ImportVector[0:], aot.ImportUseGas())
|
||||||
|
binary.LittleEndian.PutUint64(ret.ImportVector[8:], aot.ImportCallDataCopy())
|
||||||
|
binary.LittleEndian.PutUint64(ret.ImportVector[16:], aot.ImportGetCallDataSize())
|
||||||
|
binary.LittleEndian.PutUint64(ret.ImportVector[24:], aot.ImportFinish())
|
||||||
|
binary.LittleEndian.PutUint64(ret.ImportVector[32:], aot.ImportRevert())
|
||||||
|
ret.ImportFuncs["useGas"] = importFunc{-9, 1}
|
||||||
|
ret.ImportFuncs["callDataCopy"] = importFunc{-8, 3}
|
||||||
|
ret.ImportFuncs["getCallDataSize"] = importFunc{-7, 0}
|
||||||
|
ret.ImportFuncs["finish"] = importFunc{-6, 2}
|
||||||
|
ret.ImportFuncs["revert"] = importFunc{-5, 2}
|
||||||
|
|
||||||
|
binary.LittleEndian.PutUint64(ret.ImportVector[56:], aot.ImportGrowMemoryHandler())
|
||||||
|
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ac *AoTContract) ResolveFunc(module, field string, sig wa.FuncType) (index int, err error) {
|
||||||
|
if module != "ethereum" {
|
||||||
|
err = fmt.Errorf("import function's module is unknown: %s %s", module, field)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
i := ac.ImportFuncs[field]
|
||||||
|
if i.index == 0 {
|
||||||
|
err = fmt.Errorf("import function not supported: %s", field)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(sig.Params) != i.params {
|
||||||
|
err = fmt.Errorf("%s: import function has wrong number of parameters: import signature has %d, syscall wrapper has %d", field, len(sig.Params), i.params)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
index = i.index
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ac *AoTContract) ResolveGlobal(module, field string, t wa.Type) (init uint64, err error) {
|
||||||
|
err = fmt.Errorf("imported global not supported: %s %s", module, field)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ac *AoTContract) RequiredGas(code []byte) uint64 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ac *AoTContract) Run(input []byte, contract *Contract) ([]byte, error) {
|
||||||
|
var (
|
||||||
|
textSize = compile.DefaultMaxTextSize
|
||||||
|
stackSize = wa.PageSize
|
||||||
|
entry = "main"
|
||||||
|
dumpText = false
|
||||||
|
)
|
||||||
|
|
||||||
|
progReader := bytes.NewReader(input)
|
||||||
|
|
||||||
|
vecSize := alignSize(len(ac.ImportVector), os.Getpagesize())
|
||||||
|
|
||||||
|
vecTextMem, err := makeMem(vecSize+textSize, syscall.PROT_READ|syscall.PROT_WRITE, 0)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
vecMem := vecTextMem[:vecSize]
|
||||||
|
copy(vecMem[vecSize-len(ac.ImportVector):], ac.ImportVector)
|
||||||
|
|
||||||
|
contractData := make([]byte, 8+8+8+len(input) /* original rsp + gas + size + data */)
|
||||||
|
binary.LittleEndian.PutUint64(contractData[8:], contract.Gas)
|
||||||
|
binary.LittleEndian.PutUint64(contractData[16:], uint64(len(input)))
|
||||||
|
copy(contractData[24:], input)
|
||||||
|
cdAddr := uint64(memAddr(contractData))
|
||||||
|
binary.LittleEndian.PutUint64(vecTextMem[vecSize-4*8:], cdAddr)
|
||||||
|
|
||||||
|
textMem := vecTextMem[vecSize:]
|
||||||
|
textAddr := memAddr(textMem)
|
||||||
|
textBuf := buffer.NewStatic(textMem[:0], len(textMem))
|
||||||
|
|
||||||
|
config := &wag.Config{
|
||||||
|
Text: textBuf,
|
||||||
|
MemoryAlignment: os.Getpagesize(),
|
||||||
|
Entry: entry,
|
||||||
|
}
|
||||||
|
obj, err := wag.Compile(config, progReader, ac)
|
||||||
|
if dumpText && len(obj.Text) > 0 {
|
||||||
|
e := dump.Text(os.Stdout, obj.Text, textAddr, obj.FuncAddrs, &obj.Names)
|
||||||
|
if err == nil {
|
||||||
|
err = e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
binary.LittleEndian.PutUint64(ac.ImportVector[40:], uint64(obj.InitialMemorySize))
|
||||||
|
|
||||||
|
globalsMemory, err := makeMem(obj.MemoryOffset+linearMemoryAddressSpace, syscall.PROT_NONE, 0)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = syscall.Mprotect(globalsMemory[:obj.MemoryOffset+obj.InitialMemorySize], syscall.PROT_READ|syscall.PROT_WRITE)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(globalsMemory, obj.GlobalsMemory)
|
||||||
|
|
||||||
|
memoryAddr := memAddr(globalsMemory) + uintptr(obj.MemoryOffset)
|
||||||
|
|
||||||
|
if err := syscall.Mprotect(vecMem, syscall.PROT_READ); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := syscall.Mprotect(textMem, syscall.PROT_READ|syscall.PROT_EXEC); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
stackMem, err := makeMem(stackSize, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_STACK)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
stackOffset := stackSize - len(obj.StackFrame)
|
||||||
|
copy(stackMem[stackOffset:], obj.StackFrame)
|
||||||
|
|
||||||
|
stackAddr := memAddr(stackMem)
|
||||||
|
stackLimit := stackAddr + signalStackReserve
|
||||||
|
stackPtr := stackAddr + uintptr(stackOffset)
|
||||||
|
|
||||||
|
if stackLimit >= stackPtr {
|
||||||
|
log.Fatal("stack is too small for starting program")
|
||||||
|
}
|
||||||
|
|
||||||
|
retaddr, retsize := aot.Exec(textAddr, stackLimit, memoryAddr, stackPtr)
|
||||||
|
|
||||||
|
gasLeft := binary.LittleEndian.Uint64(contractData[8:])
|
||||||
|
if gasLeft == 0xffffffffffffffff {
|
||||||
|
fmt.Println("Out of gas")
|
||||||
|
return nil, ErrOutOfGas
|
||||||
|
} else {
|
||||||
|
fmt.Println("gas left: ", gasLeft, "result: ", globalsMemory[retaddr+obj.MemoryOffset:retaddr+obj.MemoryOffset+retsize])
|
||||||
|
contract.Gas = gasLeft
|
||||||
|
if retsize == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
retData := make([]byte, retsize)
|
||||||
|
copy(retData, globalsMemory[retaddr+obj.MemoryOffset:retaddr+obj.MemoryOffset+retsize])
|
||||||
|
return retData, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO cleanup all protected memory areas
|
||||||
|
}
|
||||||
24
core/vm/aot/eei.go
Normal file
24
core/vm/aot/eei.go
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
// Copyright 2019 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
package aot
|
||||||
|
|
||||||
|
func ImportGetCallDataSize() uint64
|
||||||
|
func ImportUseGas() uint64
|
||||||
|
func ImportCallDataCopy() uint64
|
||||||
|
func ImportFinish() uint64
|
||||||
|
func ImportRevert() uint64
|
||||||
|
func ImportGrowMemoryHandler() uint64
|
||||||
153
core/vm/aot/eei_amd64.s
Normal file
153
core/vm/aot/eei_amd64.s
Normal file
|
|
@ -0,0 +1,153 @@
|
||||||
|
// Copyright 2019 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
TEXT ·ImportGetCallDataSize(SB),$0-8
|
||||||
|
LEAQ ethereumGetCallDataSize<>(SB), AX
|
||||||
|
MOVQ AX, ret+0(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ethereumGetCallDataSize<>(SB),NOSPLIT,$0
|
||||||
|
// Get pointer to the contract info area into r13
|
||||||
|
MOVQ -0x20(R15), R13
|
||||||
|
MOVQ 0x10(R13), AX
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·ImportUseGas(SB),$0-8
|
||||||
|
LEAQ ethereumUseGas<>(SB), AX
|
||||||
|
MOVQ AX, ret+0(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ethereumUseGas<>(SB),NOSPLIT,$0
|
||||||
|
// Get pointer to the contract info area into r13
|
||||||
|
MOVQ -0x20(R15), R13
|
||||||
|
|
||||||
|
MOVQ 8(SP), AX // Gas required
|
||||||
|
MOVQ 0x8(R13), CX // Gas left
|
||||||
|
CMPQ AX, CX
|
||||||
|
JA oog
|
||||||
|
|
||||||
|
SUBQ AX, CX
|
||||||
|
MOVQ CX, 0x8(R13)
|
||||||
|
XORQ AX, AX
|
||||||
|
XORQ CX, CX
|
||||||
|
RET
|
||||||
|
|
||||||
|
oog:
|
||||||
|
// Set gas value to -1
|
||||||
|
XORQ AX, AX
|
||||||
|
NOTQ AX
|
||||||
|
MOVQ AX, 0x8(R13)
|
||||||
|
// Recover the saved value of the stack
|
||||||
|
MOVQ -0x20(R15), SI
|
||||||
|
MOVQ (SI), SP
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·ImportCallDataCopy(SB),$0-8
|
||||||
|
LEAQ ethereumCallDataCopy<>(SB), AX
|
||||||
|
MOVQ AX, ret+0(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ethereumCallDataCopy<>(SB),NOSPLIT,$0
|
||||||
|
// Get pointer to the contract info area into r13
|
||||||
|
MOVQ -0x20(R15), R13
|
||||||
|
|
||||||
|
// Get pointer to input data
|
||||||
|
MOVQ R13, SI
|
||||||
|
ADDQ $0x18, SI // start of input buffer
|
||||||
|
MOVQ 0x10(SP), AX // rax = input data offset
|
||||||
|
ADDQ AX, SI
|
||||||
|
|
||||||
|
// Load and check the size of data to be
|
||||||
|
// copied to the destination buffer
|
||||||
|
MOVQ 0x8(SP), CX // rcx = number of bytes
|
||||||
|
ADDQ CX, AX // rax = input buffer + nbytes
|
||||||
|
MOVQ 0x10(R13), R12 // r12 = max size
|
||||||
|
CMPQ AX, R12
|
||||||
|
JA eei_error
|
||||||
|
|
||||||
|
// Load address of the destination buffer
|
||||||
|
MOVQ 0x18(SP), DI
|
||||||
|
ADDQ R14, DI
|
||||||
|
|
||||||
|
copy:
|
||||||
|
MOVB (SI), AX
|
||||||
|
MOVB AX, (DI)
|
||||||
|
ADDQ $1, SI
|
||||||
|
ADDQ $1, DI
|
||||||
|
LOOP copy
|
||||||
|
RET
|
||||||
|
|
||||||
|
eei_error:
|
||||||
|
// Recover the saved value of the stack
|
||||||
|
MOVQ -0x20(R15), SI
|
||||||
|
MOVQ (SI), SP
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·ImportFinish(SB),$0-8
|
||||||
|
LEAQ ethereumFinish<>(SB), AX
|
||||||
|
MOVQ AX, ret+0(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
// Voir si je peux mettre $0-16 et ret+0(FP), ret+8(FP)
|
||||||
|
TEXT ethereumFinish<>(SB),NOSPLIT,$0
|
||||||
|
// Get both arguments from the stack, before it
|
||||||
|
// is changed back to its previous value
|
||||||
|
MOVQ 8(SP), AX
|
||||||
|
MOVQ 16(SP), CX
|
||||||
|
|
||||||
|
// Recover the saved value of the stack
|
||||||
|
MOVQ -0x20(R15), SI
|
||||||
|
MOVQ (SI), SP
|
||||||
|
|
||||||
|
// Store the buffer addresses and size at
|
||||||
|
// the location where go expects both parameters
|
||||||
|
// to be stored, on the initial stack.
|
||||||
|
MOVQ CX, 0x28(SP)
|
||||||
|
MOVQ AX, 0x30(SP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·ImportRevert(SB),$0-8
|
||||||
|
LEAQ ethereumRevert<>(SB), AX
|
||||||
|
MOVQ AX, ret+0(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ethereumRevert<>(SB),NOSPLIT,$0
|
||||||
|
// Get both arguments from the stack, before it
|
||||||
|
// is changed back to its previous value
|
||||||
|
MOVQ 8(SP), AX
|
||||||
|
MOVQ 16(SP), CX
|
||||||
|
|
||||||
|
// Recover the saved value of the stack
|
||||||
|
MOVQ -0x20(R15), SI
|
||||||
|
MOVQ (SI), SP
|
||||||
|
|
||||||
|
// Store the buffer addresses and size at
|
||||||
|
// the location where go expects both parameters
|
||||||
|
// to be stored, on the initial stack.
|
||||||
|
MOVQ CX, 0x28(SP)
|
||||||
|
MOVQ AX, 0x30(SP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT ·ImportGrowMemoryHandler(SB),$0-8
|
||||||
|
LEAQ growMemoryHandler<>(SB), AX
|
||||||
|
MOVQ AX, ret+0(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT growMemoryHandler<>(SB),NOSPLIT,$0-8
|
||||||
|
//CALL main·GrowMemory+0(FP)
|
||||||
|
RET
|
||||||
9
core/vm/aot/exec.go
Normal file
9
core/vm/aot/exec.go
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
// Copyright (c) 2018 Timo Savola. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package aot
|
||||||
|
|
||||||
|
func Exec(textBase, stackLimit, memoryBase, stackPtr uintptr) (int, int)
|
||||||
|
func ImportTrapHandler() uint64
|
||||||
|
func ImportGrowMemory() uint64
|
||||||
77
core/vm/aot/exec_amd64.s
Normal file
77
core/vm/aot/exec_amd64.s
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
// Copyright (c) 2018 Timo Savola. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Copyright 2019 The go-ethereum Authors
|
||||||
|
// This file is part of the go-ethereum library.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include "textflag.h"
|
||||||
|
|
||||||
|
// func exec(textBase, stackLimit, memoryBase, stackPtr uintptr)
|
||||||
|
TEXT ·Exec(SB),NOSPLIT,$0-48
|
||||||
|
MOVQ textBase+0(FP), R15
|
||||||
|
MOVQ stackLimit+8(FP), BX
|
||||||
|
MOVQ memoryBase+16(FP), R14
|
||||||
|
MOVQ stackPtr+24(FP), CX
|
||||||
|
|
||||||
|
MOVQ -0x20(R15), DI
|
||||||
|
MOVQ SP, (DI)
|
||||||
|
|
||||||
|
MOVQ CX, SP // stack ptr
|
||||||
|
|
||||||
|
XORL AX, AX
|
||||||
|
XORL CX, CX
|
||||||
|
XORL BP, BP
|
||||||
|
XORL SI, SI
|
||||||
|
XORL DI, DI
|
||||||
|
XORL R8, R8
|
||||||
|
XORL R9, R9
|
||||||
|
XORL R10, R10
|
||||||
|
XORL R11, R11
|
||||||
|
XORL R12, R12
|
||||||
|
XORL R13, R13
|
||||||
|
|
||||||
|
MOVQ R15, DX
|
||||||
|
ADDQ $32, DX // init routine
|
||||||
|
JMP DX
|
||||||
|
|
||||||
|
// func importTrapHandler() uint64
|
||||||
|
TEXT ·ImportTrapHandler(SB),$0-8
|
||||||
|
LEAQ trapHandler<>(SB), AX
|
||||||
|
MOVQ AX, ret+0(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT trapHandler<>(SB),NOSPLIT,$0
|
||||||
|
CMPL AX, $0 // exit trap (lower 32 bits)
|
||||||
|
JE exittrap
|
||||||
|
ADDL $100, AX // 100 + trap id
|
||||||
|
JMP sysexit
|
||||||
|
|
||||||
|
exittrap:
|
||||||
|
SHRQ $32, AX // exit code (higher 32 bits)
|
||||||
|
sysexit:
|
||||||
|
MOVL AX, DI
|
||||||
|
MOVL $231, AX // exit_group syscall
|
||||||
|
SYSCALL
|
||||||
|
|
||||||
|
// func importGrowMemory() uint64
|
||||||
|
TEXT ·ImportGrowMemory(SB),$0-8
|
||||||
|
LEAQ growMemory<>(SB), AX
|
||||||
|
MOVQ AX, ret+0(FP)
|
||||||
|
RET
|
||||||
|
|
||||||
|
TEXT growMemory<>(SB),NOSPLIT,$0
|
||||||
|
HLT // TODO: implementation
|
||||||
|
|
@ -67,14 +67,14 @@ var PrecompiledContractsByzantium = map[common.Address]PrecompiledContract{
|
||||||
// PrecompiledContractsEWASM contains the default set of pre-compiled Ethereum
|
// PrecompiledContractsEWASM contains the default set of pre-compiled Ethereum
|
||||||
// contracts used for Ethereum 1.x release.
|
// contracts used for Ethereum 1.x release.
|
||||||
var PrecompiledContractsEWASM = map[common.Address]PrecompiledContract{
|
var PrecompiledContractsEWASM = map[common.Address]PrecompiledContract{
|
||||||
common.BytesToAddress([]byte{1}): newEWASMPrecompile(ewasmEcrecoverCode, 1),
|
common.BytesToAddress([]byte{1}): NewAoTContract(ewasmEcrecoverCode, 1),
|
||||||
common.BytesToAddress([]byte{2}): newEWASMPrecompile(ewasmSha256HashCode, 2),
|
common.BytesToAddress([]byte{2}): NewAoTContract(ewasmSha256HashCode, 2),
|
||||||
common.BytesToAddress([]byte{3}): newEWASMPrecompile(ewasmRipemd160hashCode, 3),
|
common.BytesToAddress([]byte{3}): NewAoTContract(ewasmRipemd160hashCode, 3),
|
||||||
common.BytesToAddress([]byte{4}): newEWASMPrecompile(ewasmIdentityCode, 4),
|
common.BytesToAddress([]byte{4}): NewAoTContract(ewasmIdentityCode, 4),
|
||||||
common.BytesToAddress([]byte{5}): newEWASMPrecompile(ewasmExpmodCode, 5),
|
common.BytesToAddress([]byte{5}): NewAoTContract(ewasmExpmodCode, 5),
|
||||||
common.BytesToAddress([]byte{6}): newEWASMPrecompile(ewasmEcaddCode, 6),
|
common.BytesToAddress([]byte{6}): NewAoTContract(ewasmEcaddCode, 6),
|
||||||
common.BytesToAddress([]byte{7}): newEWASMPrecompile(ewasmEcmulCode, 7),
|
common.BytesToAddress([]byte{7}): NewAoTContract(ewasmEcmulCode, 7),
|
||||||
common.BytesToAddress([]byte{8}): newEWASMPrecompile(ewasmEcpairingCode, 8),
|
common.BytesToAddress([]byte{8}): NewAoTContract(ewasmEcpairingCode, 8),
|
||||||
}
|
}
|
||||||
|
|
||||||
// RunPrecompiledContract runs and evaluates the output of a precompiled contract.
|
// RunPrecompiledContract runs and evaluates the output of a precompiled contract.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue