mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-20 19:56:44 +00:00
Merge branch 'develop-evmcc' of github.com:imapp-pl/ethereum into develop-evmcc
Conflicts: evmcc/Compiler.cpp
This commit is contained in:
commit
b730bdc511
8 changed files with 108 additions and 35 deletions
|
|
@ -160,12 +160,15 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
||||||
IRBuilder<> builder(context);
|
IRBuilder<> builder(context);
|
||||||
|
|
||||||
// Create main function
|
// Create main function
|
||||||
auto mainFuncType = FunctionType::get(llvm::Type::getInt32Ty(context), false);
|
const auto i32Ty = builder.getInt32Ty();
|
||||||
|
Type* retTypeElems[] = {i32Ty, i32Ty};
|
||||||
|
auto retType = StructType::create(retTypeElems, "MemRef", true);
|
||||||
|
auto mainFuncType = FunctionType::get(builder.getInt64Ty(), false);
|
||||||
auto mainFunc = Function::Create(mainFuncType, Function::ExternalLinkage, "main", module.get());
|
auto mainFunc = Function::Create(mainFuncType, Function::ExternalLinkage, "main", module.get());
|
||||||
|
|
||||||
// Init stack and memory
|
// Init stack and memory
|
||||||
auto stack = Stack(builder, module.get());
|
auto stack = Stack(builder, module.get());
|
||||||
auto memory = Memory(builder, module.get());
|
auto memory = Memory(builder);
|
||||||
|
|
||||||
auto ext = Ext(builder);
|
auto ext = Ext(builder);
|
||||||
|
|
||||||
|
|
@ -174,6 +177,9 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
||||||
basicBlocks[0] = entryBlock;
|
basicBlocks[0] = entryBlock;
|
||||||
createBasicBlocks(bytecode);
|
createBasicBlocks(bytecode);
|
||||||
|
|
||||||
|
auto userRet = false;
|
||||||
|
auto finished = false;
|
||||||
|
|
||||||
BasicBlock* currentBlock = nullptr;
|
BasicBlock* currentBlock = nullptr;
|
||||||
|
|
||||||
for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc)
|
for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc)
|
||||||
|
|
@ -509,10 +515,47 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Instruction::CODESIZE:
|
||||||
|
{
|
||||||
|
auto value = builder.getIntN(256, bytecode.size());
|
||||||
|
stack.push(value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Instruction::RETURN:
|
||||||
|
{
|
||||||
|
auto index = stack.pop();
|
||||||
|
auto size = stack.pop();
|
||||||
|
|
||||||
|
// MCJIT does not support returning structs
|
||||||
|
//auto index32 = builder.CreateTrunc(index, i32Ty, "index32");
|
||||||
|
//auto size32 = builder.CreateTrunc(size, i32Ty, "size32");
|
||||||
|
//auto ret = builder.CreateInsertValue(UndefValue::get(retType), index32, 0, "ret");
|
||||||
|
//ret = builder.CreateInsertValue(ret, size32, 1, "ret");
|
||||||
|
|
||||||
|
auto ret = builder.CreateTrunc(index, builder.getInt64Ty());
|
||||||
|
ret = builder.CreateShl(ret, 32);
|
||||||
|
size = builder.CreateTrunc(size, i32Ty);
|
||||||
|
size = builder.CreateZExt(size, builder.getInt64Ty());
|
||||||
|
ret = builder.CreateOr(ret, size);
|
||||||
|
|
||||||
|
builder.CreateRet(ret);
|
||||||
|
finished = true;
|
||||||
|
userRet = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Instruction::STOP:
|
||||||
|
{
|
||||||
|
finished = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.CreateRet(ConstantInt::get(Type::getInt32Ty(context), 0));
|
if (!userRet)
|
||||||
|
builder.CreateRet(builder.getInt64(0));
|
||||||
|
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
#include <llvm/Support/Host.h>
|
#include <llvm/Support/Host.h>
|
||||||
|
|
||||||
#include "Ext.h"
|
#include "Ext.h"
|
||||||
|
#include "Memory.h"
|
||||||
|
|
||||||
namespace evmcc
|
namespace evmcc
|
||||||
{
|
{
|
||||||
|
|
@ -68,6 +69,8 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
|
||||||
_module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module
|
_module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module
|
||||||
exec->finalizeObject();
|
exec->finalizeObject();
|
||||||
|
|
||||||
|
auto&& memory = Memory::init();
|
||||||
|
|
||||||
auto ext = std::make_unique<dev::eth::ExtVMFace>();
|
auto ext = std::make_unique<dev::eth::ExtVMFace>();
|
||||||
ext->myAddress = dev::Address(1122334455667788);
|
ext->myAddress = dev::Address(1122334455667788);
|
||||||
ext->caller = dev::Address(0xfacefacefaceface);
|
ext->caller = dev::Address(0xfacefacefaceface);
|
||||||
|
|
@ -86,8 +89,19 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = exec->runFunction(entryFunc, {});
|
auto result = exec->runFunction(entryFunc, {});
|
||||||
auto intResult = result.IntVal.getZExtValue();
|
if (auto intResult = result.IntVal.getZExtValue())
|
||||||
return intResult;
|
{
|
||||||
|
auto index = intResult >> 32;
|
||||||
|
auto size = 0xFFFFFFFF & intResult;
|
||||||
|
|
||||||
|
std::cout << "RETURN [ ";
|
||||||
|
for (dev::bytes::const_iterator it = memory.cbegin() + index, end = it + size; it != end; ++it)
|
||||||
|
std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)*it << " ";
|
||||||
|
std::cout << "]";
|
||||||
|
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
#include <libdevcore/Common.h>
|
#include <libdevcore/Common.h>
|
||||||
|
|
||||||
|
#include "Utils.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define EXPORT __declspec(dllexport)
|
#define EXPORT __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
|
|
@ -19,44 +21,42 @@
|
||||||
namespace evmcc
|
namespace evmcc
|
||||||
{
|
{
|
||||||
|
|
||||||
struct i256
|
|
||||||
{
|
|
||||||
uint64_t a;
|
|
||||||
uint64_t b;
|
|
||||||
uint64_t c;
|
|
||||||
uint64_t d;
|
|
||||||
};
|
|
||||||
static_assert(sizeof(i256) == 32, "Wrong i256 size");
|
|
||||||
|
|
||||||
using MemoryImpl = dev::bytes;
|
using MemoryImpl = dev::bytes;
|
||||||
|
|
||||||
|
static MemoryImpl* evmccrt_memory;
|
||||||
|
|
||||||
Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module)
|
|
||||||
|
Memory::Memory(llvm::IRBuilder<>& _builder)
|
||||||
: m_builder(_builder)
|
: m_builder(_builder)
|
||||||
{
|
{
|
||||||
auto voidTy = m_builder.getVoidTy();
|
auto voidTy = m_builder.getVoidTy();
|
||||||
auto i64Ty = m_builder.getInt64Ty();
|
auto i64Ty = m_builder.getInt64Ty();
|
||||||
|
auto module = _builder.GetInsertBlock()->getParent()->getParent();
|
||||||
auto memoryCreate = llvm::Function::Create(llvm::FunctionType::get(voidTy, false),
|
|
||||||
llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
|
||||||
"evmccrt_memory_create", _module);
|
|
||||||
m_builder.CreateCall(memoryCreate);
|
|
||||||
|
|
||||||
|
|
||||||
auto memRequireTy = llvm::FunctionType::get(m_builder.getInt8PtrTy(), i64Ty, false);
|
auto memRequireTy = llvm::FunctionType::get(m_builder.getInt8PtrTy(), i64Ty, false);
|
||||||
m_memRequire = llvm::Function::Create(memRequireTy,
|
m_memRequire = llvm::Function::Create(memRequireTy,
|
||||||
llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
||||||
"evmccrt_memory_require", _module);
|
"evmccrt_memory_require", module);
|
||||||
|
|
||||||
auto memSizeTy = llvm::FunctionType::get(i64Ty, false);
|
auto memSizeTy = llvm::FunctionType::get(i64Ty, false);
|
||||||
m_memSize = llvm::Function::Create(memSizeTy,
|
m_memSize = llvm::Function::Create(memSizeTy,
|
||||||
llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
||||||
"evmccrt_memory_size", _module);
|
"evmccrt_memory_size", module);
|
||||||
|
|
||||||
std::vector<llvm::Type*> argTypes = {i64Ty, i64Ty};
|
std::vector<llvm::Type*> argTypes = {i64Ty, i64Ty};
|
||||||
auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef<llvm::Type*>(argTypes), false);
|
auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef<llvm::Type*>(argTypes), false);
|
||||||
m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
||||||
"evmccrt_memory_dump", _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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -130,15 +130,6 @@ extern "C"
|
||||||
{
|
{
|
||||||
using namespace evmcc;
|
using namespace evmcc;
|
||||||
|
|
||||||
EXPORT MemoryImpl* evmccrt_memory;
|
|
||||||
|
|
||||||
EXPORT void evmccrt_memory_create(void)
|
|
||||||
{
|
|
||||||
evmccrt_memory = new MemoryImpl();
|
|
||||||
std::cerr << "MEMORY: create(), initial size = " << evmccrt_memory->size()
|
|
||||||
<< std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Resizes memory to contain at least _index + 1 bytes and returns the base address.
|
// Resizes memory to contain at least _index + 1 bytes and returns the base address.
|
||||||
EXPORT uint8_t* evmccrt_memory_require(uint64_t _index)
|
EXPORT uint8_t* evmccrt_memory_require(uint64_t _index)
|
||||||
{
|
{
|
||||||
|
|
@ -154,7 +145,7 @@ EXPORT uint8_t* evmccrt_memory_require(uint64_t _index)
|
||||||
evmccrt_memory->resize(requiredSize);
|
evmccrt_memory->resize(requiredSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
return &(*evmccrt_memory)[0];
|
return evmccrt_memory->data();
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT uint64_t evmccrt_memory_size()
|
EXPORT uint64_t evmccrt_memory_size()
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,17 @@
|
||||||
|
|
||||||
#include <llvm/IR/IRBuilder.h>
|
#include <llvm/IR/IRBuilder.h>
|
||||||
|
|
||||||
|
#include <libdevcore/Common.h>
|
||||||
|
|
||||||
namespace evmcc
|
namespace evmcc
|
||||||
{
|
{
|
||||||
|
|
||||||
class Memory
|
class Memory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module);
|
Memory(llvm::IRBuilder<>& _builder);
|
||||||
|
|
||||||
|
static const dev::bytes& init();
|
||||||
|
|
||||||
llvm::Value* loadWord(llvm::Value* _addr);
|
llvm::Value* loadWord(llvm::Value* _addr);
|
||||||
void storeWord(llvm::Value* _addr, llvm::Value* _word);
|
void storeWord(llvm::Value* _addr, llvm::Value* _word);
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
30333234363a600035602635601335
|
30333234363a600035602635601335380060016002f2
|
||||||
|
|
|
||||||
1
evmcc/bytecode/return_test.evm
Normal file
1
evmcc/bytecode/return_test.evm
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
60016064546002608454600360a45460606064f2
|
||||||
|
|
@ -12,4 +12,9 @@ CALLDATALOAD
|
||||||
CALLDATALOAD
|
CALLDATALOAD
|
||||||
19
|
19
|
||||||
CALLDATALOAD
|
CALLDATALOAD
|
||||||
|
CODESIZE
|
||||||
|
STOP
|
||||||
|
1
|
||||||
|
2
|
||||||
|
RETURN
|
||||||
)
|
)
|
||||||
15
evmcc/lll/return_test.lll
Normal file
15
evmcc/lll/return_test.lll
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
(asm
|
||||||
|
1
|
||||||
|
100
|
||||||
|
MSTORE
|
||||||
|
2
|
||||||
|
132
|
||||||
|
MSTORE
|
||||||
|
3
|
||||||
|
164
|
||||||
|
MSTORE
|
||||||
|
96
|
||||||
|
100
|
||||||
|
RETURN
|
||||||
|
)
|
||||||
Loading…
Reference in a new issue