diff --git a/evmjit/libevmjit/interface.cpp b/evmjit/libevmjit/interface.cpp index 6a729f3d00..eef92d00fd 100644 --- a/evmjit/libevmjit/interface.cpp +++ b/evmjit/libevmjit/interface.cpp @@ -5,14 +5,12 @@ extern "C" { -int evmjit_run(void* _data, void* _env) +evmjit_result evmjit_run(void* _data, void* _env) { using namespace dev::eth::jit; auto data = static_cast(_data); - std::cerr << "GAS: " << data->elems[RuntimeData::Gas].a << "\n"; - ExecutionEngine engine; auto codePtr = data->code; @@ -20,30 +18,17 @@ int evmjit_run(void* _data, void* _env) bytes bytecode; bytecode.insert(bytecode.end(), codePtr, codePtr + codeSize); - auto result = engine.run(bytecode, data, static_cast(_env)); - return static_cast(result); + auto returnCode = engine.run(bytecode, data, static_cast(_env)); + evmjit_result result = {static_cast(returnCode), 0, nullptr}; + if (returnCode == ReturnCode::Return && !engine.returnData.empty()) + { + // TODO: Optimized returning data. Allocating memory on client side by callback function might be a good idea + result.returnDataSize = engine.returnData.size(); + result.returnData = std::malloc(result.returnDataSize); + std::memcpy(result.returnData, engine.returnData.data(), result.returnDataSize); + } + + return result; } -// Runtime callback functions - implementations must be provided by external language (Go, C++, Python) -void evm_jit_rt_sload(evm_jit_rt* _rt, i256* _index, i256* _ret); -void evm_jit_rt_sstore(evm_jit_rt* _rt, i256* _index, i256* _value); -void evm_jit_rt_balance(evm_jit_rt* _rt, h256* _address, i256* _ret); -// And so on... - -evm_jit* evm_jit_create(evm_jit_rt*) -{ - printf("EVM JIT create"); - - int* a = nullptr; - *a = 1; - - return nullptr; -} - -evm_jit_return_code evm_jit_execute(evm_jit* _jit); - -void evm_jit_get_return_data(evm_jit* _jit, char* _return_data_offset, size_t* _return_data_size); - -void evm_jit_destroy(evm_jit* _jit); - } diff --git a/evmjit/libevmjit/interface.h b/evmjit/libevmjit/interface.h index 1515fed861..5d9307ab2b 100644 --- a/evmjit/libevmjit/interface.h +++ b/evmjit/libevmjit/interface.h @@ -1,10 +1,19 @@ #include +#include #ifdef __cplusplus extern "C" { #endif -int evmjit_run(void* _data, void* _env); +typedef struct evmjit_result +{ + int32_t returnCode; + uint64_t returnDataSize; + void* returnData; + +} evmjit_result; + +evmjit_result evmjit_run(void* _data, void* _env); // JIT object opaque type typedef struct evm_jit evm_jit; diff --git a/vm/vm_jit.go b/vm/vm_jit.go index 6cbee96d60..4ce3531958 100644 --- a/vm/vm_jit.go +++ b/vm/vm_jit.go @@ -8,6 +8,7 @@ import "github.com/ethereum/go-ethereum/state" /* #include "../evmjit/libevmjit/interface.h" +#include #cgo LDFLAGS: -L/home/chfast/go/src/github.com/ethereum/go-ethereum/evmjit/build/libevmjit -levmjit */ @@ -146,18 +147,24 @@ func (self *JitVm) Run(me, caller ContextRef, code []byte, value, gas, price *bi data.callData = getDataPtr(callData) data.code = getDataPtr(code) - r := C.evmjit_run(unsafe.Pointer(&data), unsafe.Pointer(self)) + result := C.evmjit_run(unsafe.Pointer(&data), unsafe.Pointer(self)) //fmt.Printf("JIT result: %d\n", r) - if r >= 100 { + if result.returnCode >= 100 { err = errors.New("OOG from JIT") - gas.SetInt64(0) // Set gas to 0, JIT do not bother + gas.SetInt64(0) // Set gas to 0, JIT does not bother } else { gasLeft := llvm2big(&data.elems[Gas]) // TODO: Set value directly to gas instance gas.Set(gasLeft) + if result.returnCode == 1 { // RETURN + returnData := llvm2bytes((*byte)(result.returnData), uint64(result.returnDataSize)) + ret = make([]byte, len(returnData)) + copy(ret, returnData) + C.free(result.returnData) + } } - return ret, err + return } func (self *JitVm) Printf(format string, v ...interface{}) VirtualMachine {