mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-19 03:10:48 +00:00
Runtime class that inits and keeps stack, memory and ExtVM interface
This commit is contained in:
parent
320add062e
commit
7bee86aa4b
8 changed files with 114 additions and 66 deletions
|
|
@ -351,9 +351,9 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
|||
/*
|
||||
if (byteNum < 32) - use select
|
||||
{
|
||||
value <<= byteNum*8
|
||||
value >>= 31*8
|
||||
push value
|
||||
value <<= byteNum*8
|
||||
value >>= 31*8
|
||||
push value
|
||||
}
|
||||
else push 0
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -13,8 +13,7 @@
|
|||
#include <llvm/Support/PrettyStackTrace.h>
|
||||
#include <llvm/Support/Host.h>
|
||||
|
||||
#include "Ext.h"
|
||||
#include "Memory.h"
|
||||
#include "Runtime.h"
|
||||
|
||||
namespace evmcc
|
||||
{
|
||||
|
|
@ -69,8 +68,7 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
|
|||
_module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module
|
||||
exec->finalizeObject();
|
||||
|
||||
auto&& memory = Memory::init();
|
||||
|
||||
// Create fake ExtVM interface
|
||||
auto ext = std::make_unique<dev::eth::ExtVMFace>();
|
||||
ext->myAddress = dev::Address(1122334455667788);
|
||||
ext->caller = dev::Address(0xfacefacefaceface);
|
||||
|
|
@ -85,7 +83,9 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
|
|||
ext->currentBlock.gasLimit = 1008;
|
||||
std::string calldata = "Hello the Beautiful World of Ethereum!";
|
||||
ext->data = calldata;
|
||||
Ext::init(std::move(ext));
|
||||
|
||||
// Init runtime
|
||||
Runtime runtime(std::move(ext));
|
||||
|
||||
auto entryFunc = module->getFunction("main");
|
||||
if (!entryFunc)
|
||||
|
|
@ -101,7 +101,7 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
|
|||
auto size = 0xFFFFFFFF & intResult;
|
||||
|
||||
std::cout << "RETURN [ ";
|
||||
for (dev::bytes::const_iterator it = memory.cbegin() + index, end = it + size; it != end; ++it)
|
||||
for (dev::bytes::const_iterator it = Runtime::getMemory().cbegin() + index, end = it + size; it != end; ++it)
|
||||
std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)*it << " ";
|
||||
std::cout << "]";
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#include <llvm/IR/TypeBuilder.h>
|
||||
#include <llvm/IR/IntrinsicInst.h>
|
||||
|
||||
#include "Utils.h"
|
||||
#include "Runtime.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define EXPORT __declspec(dllexport)
|
||||
|
|
@ -27,13 +27,6 @@ inline dev::u256 fromAddress(dev::Address _a)
|
|||
return (dev::u160)_a;
|
||||
}
|
||||
|
||||
std::unique_ptr<dev::eth::ExtVMFace> g_ext;
|
||||
|
||||
void Ext::init(std::unique_ptr<dev::eth::ExtVMFace> _ext)
|
||||
{
|
||||
g_ext = std::move(_ext);
|
||||
}
|
||||
|
||||
struct ExtData
|
||||
{
|
||||
i256 address;
|
||||
|
|
@ -147,25 +140,26 @@ extern "C"
|
|||
|
||||
EXPORT void ext_init(ExtData* _extData)
|
||||
{
|
||||
_extData->address = eth2llvm(fromAddress(g_ext->myAddress));
|
||||
_extData->caller = eth2llvm(fromAddress(g_ext->caller));
|
||||
_extData->origin = eth2llvm(fromAddress(g_ext->origin));
|
||||
_extData->callvalue = eth2llvm(g_ext->value);
|
||||
_extData->gasprice = eth2llvm(g_ext->gasPrice);
|
||||
_extData->calldatasize = eth2llvm(g_ext->data.size());
|
||||
_extData->prevhash = eth2llvm(g_ext->previousBlock.hash);
|
||||
_extData->coinbase = eth2llvm(fromAddress(g_ext->currentBlock.coinbaseAddress));
|
||||
_extData->timestamp = eth2llvm(g_ext->currentBlock.timestamp);
|
||||
_extData->number = eth2llvm(g_ext->currentBlock.number);
|
||||
_extData->difficulty = eth2llvm(g_ext->currentBlock.difficulty);
|
||||
_extData->gaslimit = eth2llvm(g_ext->currentBlock.gasLimit);
|
||||
//_extData->calldata = g_ext->data.data();
|
||||
auto&& ext = Runtime::getExt();
|
||||
_extData->address = eth2llvm(fromAddress(ext.myAddress));
|
||||
_extData->caller = eth2llvm(fromAddress(ext.caller));
|
||||
_extData->origin = eth2llvm(fromAddress(ext.origin));
|
||||
_extData->callvalue = eth2llvm(ext.value);
|
||||
_extData->gasprice = eth2llvm(ext.gasPrice);
|
||||
_extData->calldatasize = eth2llvm(ext.data.size());
|
||||
_extData->prevhash = eth2llvm(ext.previousBlock.hash);
|
||||
_extData->coinbase = eth2llvm(fromAddress(ext.currentBlock.coinbaseAddress));
|
||||
_extData->timestamp = eth2llvm(ext.currentBlock.timestamp);
|
||||
_extData->number = eth2llvm(ext.currentBlock.number);
|
||||
_extData->difficulty = eth2llvm(ext.currentBlock.difficulty);
|
||||
_extData->gaslimit = eth2llvm(ext.currentBlock.gasLimit);
|
||||
//_extData->calldata = ext.data.data();
|
||||
}
|
||||
|
||||
EXPORT void ext_store(i256* _index, i256* _value)
|
||||
{
|
||||
auto index = llvm2eth(*_index);
|
||||
auto value = g_ext->store(index);
|
||||
auto value = Runtime::getExt().store(index);
|
||||
*_value = eth2llvm(value);
|
||||
}
|
||||
|
||||
|
|
@ -173,7 +167,7 @@ EXPORT void ext_setStore(i256* _index, i256* _value)
|
|||
{
|
||||
auto index = llvm2eth(*_index);
|
||||
auto value = llvm2eth(*_value);
|
||||
g_ext->setStore(index, value);
|
||||
Runtime::getExt().setStore(index, value);
|
||||
}
|
||||
|
||||
EXPORT void ext_calldataload(i256* _index, i256* _value)
|
||||
|
|
@ -182,13 +176,13 @@ EXPORT void ext_calldataload(i256* _index, i256* _value)
|
|||
assert(index + 31 > index); // TODO: Handle large index
|
||||
auto b = reinterpret_cast<byte*>(_value);
|
||||
for (size_t i = index, j = 31; i <= index + 31; ++i, --j)
|
||||
b[j] = i < g_ext->data.size() ? g_ext->data[i] : 0;
|
||||
b[j] = i < Runtime::getExt().data.size() ? Runtime::getExt().data[i] : 0;
|
||||
// TODO: It all can be done by adding padding to data or by using min() algorithm without branch
|
||||
}
|
||||
|
||||
EXPORT void ext_balance(h256* _address, i256* _value)
|
||||
{
|
||||
auto u = g_ext->balance(dev::right160(*_address));
|
||||
auto u = Runtime::getExt().balance(dev::right160(*_address));
|
||||
*_value = eth2llvm(u);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#include <libdevcore/Common.h>
|
||||
|
||||
#include "Utils.h"
|
||||
#include "Runtime.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define EXPORT __declspec(dllexport)
|
||||
|
|
@ -21,11 +21,6 @@
|
|||
namespace evmcc
|
||||
{
|
||||
|
||||
using MemoryImpl = dev::bytes;
|
||||
|
||||
static MemoryImpl* evmccrt_memory;
|
||||
|
||||
|
||||
Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* module)
|
||||
: m_builder(_builder)
|
||||
{
|
||||
|
|
@ -48,15 +43,6 @@ Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* module)
|
|||
"evmccrt_memory_dump", module);
|
||||
}
|
||||
|
||||
const dev::bytes& Memory::init()
|
||||
{
|
||||
evmccrt_memory = new MemoryImpl();
|
||||
std::cerr << "MEMORY: create(), initial size = " << evmccrt_memory->size()
|
||||
<< std::endl;
|
||||
|
||||
return *evmccrt_memory;
|
||||
}
|
||||
|
||||
|
||||
llvm::Value* Memory::loadWord(llvm::Value* _addr)
|
||||
{
|
||||
|
|
@ -132,29 +118,30 @@ extern "C"
|
|||
EXPORT uint8_t* evmccrt_memory_require(uint64_t _index)
|
||||
{
|
||||
uint64_t requiredSize = (_index / 32 + 1) * 32;
|
||||
auto&& memory = Runtime::getMemory();
|
||||
|
||||
if (evmccrt_memory->size() < requiredSize)
|
||||
if (memory.size() < requiredSize)
|
||||
{
|
||||
std::cerr << "MEMORY: current size: " << std::dec
|
||||
<< evmccrt_memory->size() << " bytes, required size: "
|
||||
<< memory.size() << " bytes, required size: "
|
||||
<< requiredSize << " bytes"
|
||||
<< std::endl;
|
||||
|
||||
evmccrt_memory->resize(requiredSize);
|
||||
memory.resize(requiredSize);
|
||||
}
|
||||
|
||||
return evmccrt_memory->data();
|
||||
return memory.data();
|
||||
}
|
||||
|
||||
EXPORT uint64_t evmccrt_memory_size()
|
||||
{
|
||||
return evmccrt_memory->size() / 32;
|
||||
return Runtime::getMemory().size() / 32;
|
||||
}
|
||||
|
||||
EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end)
|
||||
{
|
||||
if (_end == 0)
|
||||
_end = evmccrt_memory->size();
|
||||
_end = Runtime::getMemory().size();
|
||||
|
||||
std::cerr << "MEMORY: active size: " << std::dec
|
||||
<< evmccrt_memory_size() << " words\n";
|
||||
|
|
@ -169,7 +156,7 @@ EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end)
|
|||
if ((i - _begin) % 16 == 0)
|
||||
std::cerr << '\n' << std::dec << i << ": ";
|
||||
|
||||
uint8_t b = (*evmccrt_memory)[i];
|
||||
auto b = Runtime::getMemory()[i];
|
||||
std::cerr << std::hex << std::setw(2) << static_cast<int>(b) << ' ';
|
||||
}
|
||||
std::cerr << std::endl;
|
||||
|
|
|
|||
|
|
@ -12,8 +12,6 @@ class Memory
|
|||
public:
|
||||
Memory(llvm::IRBuilder<>& _builder, llvm::Module* module);
|
||||
|
||||
static const dev::bytes& init();
|
||||
|
||||
llvm::Value* loadWord(llvm::Value* _addr);
|
||||
void storeWord(llvm::Value* _addr, llvm::Value* _word);
|
||||
void storeByte(llvm::Value* _addr, llvm::Value* _byte);
|
||||
|
|
|
|||
36
evmcc/Runtime.cpp
Normal file
36
evmcc/Runtime.cpp
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
#include "Runtime.h"
|
||||
|
||||
namespace evmcc
|
||||
{
|
||||
|
||||
static Runtime* g_runtime;
|
||||
|
||||
Runtime::Runtime(std::unique_ptr<dev::eth::ExtVMFace> _ext)
|
||||
: m_ext(std::move(_ext))
|
||||
{
|
||||
assert(!g_runtime);
|
||||
g_runtime = this;
|
||||
}
|
||||
|
||||
Runtime::~Runtime()
|
||||
{
|
||||
g_runtime = nullptr;
|
||||
}
|
||||
|
||||
StackImpl& Runtime::getStack()
|
||||
{
|
||||
return g_runtime->m_stack;
|
||||
}
|
||||
|
||||
MemoryImpl& Runtime::getMemory()
|
||||
{
|
||||
return g_runtime->m_memory;
|
||||
}
|
||||
|
||||
dev::eth::ExtVMFace& Runtime::getExt()
|
||||
{
|
||||
return *g_runtime->m_ext;
|
||||
}
|
||||
|
||||
}
|
||||
35
evmcc/Runtime.h
Normal file
35
evmcc/Runtime.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <libevm/ExtVMFace.h>
|
||||
|
||||
#include "Utils.h"
|
||||
|
||||
namespace evmcc
|
||||
{
|
||||
|
||||
using StackImpl = std::vector<i256>;
|
||||
using MemoryImpl = dev::bytes;
|
||||
|
||||
class Runtime
|
||||
{
|
||||
public:
|
||||
Runtime(std::unique_ptr<dev::eth::ExtVMFace> _ext);
|
||||
~Runtime();
|
||||
|
||||
Runtime(const Runtime&) = delete;
|
||||
void operator=(const Runtime&) = delete;
|
||||
|
||||
static StackImpl& getStack();
|
||||
static MemoryImpl& getMemory();
|
||||
static dev::eth::ExtVMFace& getExt();
|
||||
|
||||
private:
|
||||
StackImpl m_stack;
|
||||
MemoryImpl m_memory;
|
||||
std::unique_ptr<dev::eth::ExtVMFace> m_ext;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
#include <llvm/IR/Function.h>
|
||||
|
||||
#include "Utils.h"
|
||||
#include "Runtime.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define EXPORT __declspec(dllexport)
|
||||
|
|
@ -20,9 +20,6 @@
|
|||
namespace evmcc
|
||||
{
|
||||
|
||||
using StackImpl = std::vector<i256>;
|
||||
|
||||
|
||||
Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module)
|
||||
: m_builder(_builder)
|
||||
{
|
||||
|
|
@ -115,7 +112,8 @@ extern "C"
|
|||
|
||||
EXPORT void* evmccrt_stack_create()
|
||||
{
|
||||
auto stack = new StackImpl;
|
||||
// TODO: Simplify stack pointer passing
|
||||
auto stack = &Runtime::getStack();
|
||||
std::cerr << "STACK create\n";
|
||||
return stack;
|
||||
}
|
||||
|
|
@ -130,7 +128,7 @@ EXPORT void evmccrt_stack_pop(StackImpl* _stack, i256* _outWord)
|
|||
{
|
||||
assert(!_stack->empty());
|
||||
auto word = &_stack->back();
|
||||
debugStack("pop", *word);
|
||||
//debugStack("pop", *word);
|
||||
_stack->pop_back();
|
||||
*_outWord = *word;
|
||||
}
|
||||
|
|
@ -139,7 +137,7 @@ EXPORT void evmccrt_stack_get(StackImpl* _stack, uint32_t _index, i256* _outWord
|
|||
{
|
||||
assert(_index < _stack->size());
|
||||
auto word = _stack->rbegin() + _index;
|
||||
debugStack("get", *word, _index);
|
||||
//debugStack("get", *word, _index);
|
||||
*_outWord = *word;
|
||||
}
|
||||
|
||||
|
|
@ -147,7 +145,7 @@ EXPORT void evmccrt_stack_set(StackImpl* _stack, uint32_t _index, i256* _word)
|
|||
{
|
||||
assert(_index < _stack->size());
|
||||
*(_stack->rbegin() + _index) = *_word;
|
||||
debugStack("set", *_word, _index);
|
||||
//debugStack("set", *_word, _index);
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
|
|
|||
Loading…
Reference in a new issue