Browse Source

Merge branch 'develop-evmcc' of github.com:imapp-pl/ethereum into develop-evmcc

cl-refactor
artur-zawlocki 10 years ago
parent
commit
a1a195bce3
  1. 6
      evmcc/Compiler.cpp
  2. 12
      evmcc/ExecutionEngine.cpp
  3. 44
      evmcc/Ext.cpp
  4. 31
      evmcc/Memory.cpp
  5. 2
      evmcc/Memory.h
  6. 36
      evmcc/Runtime.cpp
  7. 35
      evmcc/Runtime.h
  8. 71
      evmcc/Stack.cpp
  9. 2
      evmcc/Stack.h

6
evmcc/Compiler.cpp

@ -400,9 +400,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
*/

12
evmcc/ExecutionEngine.cpp

@ -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 << "]";

44
evmcc/Ext.cpp

@ -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);
}

31
evmcc/Memory.cpp

@ -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;

2
evmcc/Memory.h

@ -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

@ -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

@ -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;
};
}

71
evmcc/Stack.cpp

@ -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)
{
@ -32,18 +29,14 @@ Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module)
auto i256PtrTy = i256Ty->getPointerTo();
auto voidTy = m_builder.getVoidTy();
auto stackCreate = llvm::Function::Create(llvm::FunctionType::get(stackPtrTy, false),
llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_create", _module);
llvm::Type* argsTypes[] = {stackPtrTy, i256PtrTy};
auto funcType = llvm::FunctionType::get(voidTy, argsTypes, false);
auto funcType = llvm::FunctionType::get(voidTy, i256PtrTy, false);
m_stackPush = llvm::Function::Create(funcType,
llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_push", _module);
m_stackPop = llvm::Function::Create(funcType,
llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_pop", _module);
llvm::Type* getArgsTypes[] = {stackPtrTy, m_builder.getInt32Ty(), i256PtrTy};
llvm::Type* getArgsTypes[] = {m_builder.getInt32Ty(), i256PtrTy};
auto getFuncType = llvm::FunctionType::get(voidTy, getArgsTypes, false);
m_stackGet = llvm::Function::Create(getFuncType,
llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_get", _module);
@ -51,37 +44,36 @@ Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module)
m_stackSet = llvm::Function::Create(getFuncType,
llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_set", _module);
m_args[0] = m_builder.CreateCall(stackCreate, "stack.ptr");
m_args[1] = m_builder.CreateAlloca(i256Ty, nullptr, "stack.val");
m_stackVal = m_builder.CreateAlloca(i256Ty, nullptr, "stack.val");
}
void Stack::push(llvm::Value* _value)
{
m_builder.CreateStore(_value, m_args[1]); // copy value to memory
m_builder.CreateCall(m_stackPush, m_args);
m_builder.CreateStore(_value, m_stackVal); // copy value to memory
m_builder.CreateCall(m_stackPush, m_stackVal);
}
llvm::Value* Stack::pop()
{
m_builder.CreateCall(m_stackPop, m_args);
return m_builder.CreateLoad(m_args[1]);
m_builder.CreateCall(m_stackPop, m_stackVal);
return m_builder.CreateLoad(m_stackVal);
}
llvm::Value* Stack::get(uint32_t _index)
{
llvm::Value* args[] = {m_args[0], m_builder.getInt32(_index), m_args[1]};
llvm::Value* args[] = {m_builder.getInt32(_index), m_stackVal};
m_builder.CreateCall(m_stackGet, args);
return m_builder.CreateLoad(m_args[1]);
return m_builder.CreateLoad(m_stackVal);
}
void Stack::set(uint32_t _index, llvm::Value* _value)
{
m_builder.CreateStore(_value, m_args[1]); // copy value to memory
llvm::Value* args[] = {m_args[0], m_builder.getInt32(_index), m_args[1]};
m_builder.CreateStore(_value, m_stackVal); // copy value to memory
llvm::Value* args[] = {m_builder.getInt32(_index), m_stackVal};
m_builder.CreateCall(m_stackSet, args);
}
@ -113,41 +105,34 @@ extern "C"
{
using namespace evmcc;
EXPORT void* evmccrt_stack_create()
{
auto stack = new StackImpl;
std::cerr << "STACK create\n";
return stack;
}
EXPORT void evmccrt_stack_push(StackImpl* _stack, i256* _word)
EXPORT void evmccrt_stack_push(i256* _word)
{
debugStack("push", *_word);
_stack->push_back(*_word);
//debugStack("push", *_word);
Runtime::getStack().push_back(*_word);
}
EXPORT void evmccrt_stack_pop(StackImpl* _stack, i256* _outWord)
EXPORT void evmccrt_stack_pop(i256* _outWord)
{
assert(!_stack->empty());
auto word = &_stack->back();
debugStack("pop", *word);
_stack->pop_back();
assert(!Runtime::getStack().empty());
auto word = &Runtime::getStack().back();
//debugStack("pop", *word);
Runtime::getStack().pop_back();
*_outWord = *word;
}
EXPORT void evmccrt_stack_get(StackImpl* _stack, uint32_t _index, i256* _outWord)
EXPORT void evmccrt_stack_get(uint32_t _index, i256* _outWord)
{
assert(_index < _stack->size());
auto word = _stack->rbegin() + _index;
debugStack("get", *word, _index);
assert(_index < Runtime::getStack().size());
auto word = Runtime::getStack().rbegin() + _index;
//debugStack("get", *word, _index);
*_outWord = *word;
}
EXPORT void evmccrt_stack_set(StackImpl* _stack, uint32_t _index, i256* _word)
EXPORT void evmccrt_stack_set(uint32_t _index, i256* _word)
{
assert(_index < _stack->size());
*(_stack->rbegin() + _index) = *_word;
debugStack("set", *_word, _index);
assert(_index < Runtime::getStack().size());
*(Runtime::getStack().rbegin() + _index) = *_word;
//debugStack("set", *_word, _index);
}
} // extern "C"

2
evmcc/Stack.h

@ -19,7 +19,7 @@ public:
private:
llvm::IRBuilder<>& m_builder;
llvm::Value* m_args[2];
llvm::Value* m_stackVal;
llvm::Function* m_stackPush;
llvm::Function* m_stackPop;
llvm::Function* m_stackGet;

Loading…
Cancel
Save