mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-22 04:36:42 +00:00
Merge commit '2332595c9c0d315dc9ecde22d236ae477b931863' into develop
This commit is contained in:
commit
98b265b8a2
7 changed files with 29 additions and 15 deletions
|
|
@ -47,7 +47,7 @@ extern "C"
|
||||||
_env->suicide(right160(*_address));
|
_env->suicide(right160(*_address));
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT void env_create(ExtVMFace* _env, i256* _endowment, byte* _initBeg, uint64_t _initSize, h256* o_address)
|
EXPORT void env_create(ExtVMFace* _env, i256* io_gas, i256* _endowment, byte* _initBeg, uint64_t _initSize, h256* o_address)
|
||||||
{
|
{
|
||||||
assert(_env->depth < 1024); // TODO: Handle call depth
|
assert(_env->depth < 1024); // TODO: Handle call depth
|
||||||
|
|
||||||
|
|
@ -56,9 +56,10 @@ extern "C"
|
||||||
if (_env->balance(_env->myAddress) >= endowment)
|
if (_env->balance(_env->myAddress) >= endowment)
|
||||||
{
|
{
|
||||||
_env->subBalance(endowment);
|
_env->subBalance(endowment);
|
||||||
u256 gas; // TODO: Handle gas
|
auto gas = llvm2eth(*io_gas);
|
||||||
OnOpFunc onOp {}; // TODO: Handle that thing
|
OnOpFunc onOp {}; // TODO: Handle that thing
|
||||||
h256 address(_env->create(endowment, gas, {_initBeg, _initSize}, onOp), h256::AlignRight);
|
h256 address(_env->create(endowment, gas, {_initBeg, _initSize}, onOp), h256::AlignRight);
|
||||||
|
*io_gas = eth2llvm(gas);
|
||||||
*o_address = address;
|
*o_address = address;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
|
||||||
|
|
@ -153,8 +154,13 @@ void Compiler::createBasicBlocks(bytes const& _bytecode)
|
||||||
|
|
||||||
std::unique_ptr<llvm::Module> Compiler::compile(bytes const& _bytecode)
|
std::unique_ptr<llvm::Module> Compiler::compile(bytes const& _bytecode)
|
||||||
{
|
{
|
||||||
|
// TODO: Better hash of code needed, probably SHA3
|
||||||
|
std::string code{reinterpret_cast<char const*>(_bytecode.data()), _bytecode.size()};
|
||||||
|
auto hash = std::hash<std::string>{}(code);
|
||||||
|
auto strHash = std::to_string(hash);
|
||||||
|
|
||||||
auto compilationStartTime = std::chrono::high_resolution_clock::now();
|
auto compilationStartTime = std::chrono::high_resolution_clock::now();
|
||||||
auto module = std::unique_ptr<llvm::Module>(new llvm::Module("main", m_builder.getContext()));
|
auto module = std::unique_ptr<llvm::Module>(new llvm::Module(strHash, m_builder.getContext()));
|
||||||
|
|
||||||
// Create main function
|
// Create main function
|
||||||
auto mainFuncType = llvm::FunctionType::get(Type::MainReturn, Type::RuntimePtr, false);
|
auto mainFuncType = llvm::FunctionType::get(Type::MainReturn, Type::RuntimePtr, false);
|
||||||
|
|
@ -741,7 +747,11 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode
|
||||||
auto initSize = stack.pop();
|
auto initSize = stack.pop();
|
||||||
_memory.require(initOff, initSize);
|
_memory.require(initOff, initSize);
|
||||||
|
|
||||||
auto address = _ext.create(endowment, initOff, initSize);
|
_gasMeter.commitCostBlock();
|
||||||
|
|
||||||
|
auto gas = _runtimeManager.getGas();
|
||||||
|
auto address = _ext.create(gas, endowment, initOff, initSize);
|
||||||
|
_runtimeManager.setGas(gas);
|
||||||
stack.push(address);
|
stack.push(address);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -52,14 +52,11 @@ ReturnCode ExecutionEngine::run(std::unique_ptr<llvm::Module> _module, RuntimeDa
|
||||||
static const auto program = "EVM JIT";
|
static const auto program = "EVM JIT";
|
||||||
llvm::PrettyStackTraceProgram X(1, &program);
|
llvm::PrettyStackTraceProgram X(1, &program);
|
||||||
|
|
||||||
llvm::InitializeNativeTarget();
|
|
||||||
llvm::InitializeNativeTargetAsmPrinter();
|
llvm::InitializeNativeTargetAsmPrinter();
|
||||||
|
|
||||||
llvm::EngineBuilder builder(_module.get());
|
llvm::EngineBuilder builder(_module.get());
|
||||||
builder.setEngineKind(llvm::EngineKind::JIT);
|
builder.setEngineKind(llvm::EngineKind::JIT);
|
||||||
builder.setUseMCJIT(true);
|
builder.setUseMCJIT(true);
|
||||||
std::unique_ptr<llvm::SectionMemoryManager> memoryManager(new llvm::SectionMemoryManager);
|
|
||||||
builder.setMCJITMemoryManager(memoryManager.get());
|
|
||||||
builder.setOptLevel(llvm::CodeGenOpt::None);
|
builder.setOptLevel(llvm::CodeGenOpt::None);
|
||||||
|
|
||||||
auto triple = llvm::Triple(llvm::sys::getProcessTriple());
|
auto triple = llvm::Triple(llvm::sys::getProcessTriple());
|
||||||
|
|
@ -72,7 +69,6 @@ ReturnCode ExecutionEngine::run(std::unique_ptr<llvm::Module> _module, RuntimeDa
|
||||||
if (!exec.engine)
|
if (!exec.engine)
|
||||||
return ReturnCode::LLVMConfigError;
|
return ReturnCode::LLVMConfigError;
|
||||||
_module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module
|
_module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module
|
||||||
memoryManager.release(); // and memory manager
|
|
||||||
|
|
||||||
exec.engine->setObjectCache(Cache::getObjectCache());
|
exec.engine->setObjectCache(Cache::getObjectCache());
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ Ext::Ext(RuntimeManager& _runtimeManager, Memory& _memoryMan):
|
||||||
llvm::Type* sha3ArgsTypes[] = {Type::BytePtr, Type::Size, Type::WordPtr};
|
llvm::Type* sha3ArgsTypes[] = {Type::BytePtr, Type::Size, Type::WordPtr};
|
||||||
m_sha3 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, sha3ArgsTypes, false), Linkage::ExternalLinkage, "env_sha3", module);
|
m_sha3 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, sha3ArgsTypes, false), Linkage::ExternalLinkage, "env_sha3", module);
|
||||||
|
|
||||||
llvm::Type* createArgsTypes[] = {Type::EnvPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::WordPtr};
|
llvm::Type* createArgsTypes[] = {Type::EnvPtr, Type::WordPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::WordPtr};
|
||||||
m_create = llvm::Function::Create(llvm::FunctionType::get(Type::Void, createArgsTypes, false), Linkage::ExternalLinkage, "env_create", module);
|
m_create = llvm::Function::Create(llvm::FunctionType::get(Type::Void, createArgsTypes, false), Linkage::ExternalLinkage, "env_create", module);
|
||||||
|
|
||||||
llvm::Type* callArgsTypes[] = {Type::EnvPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::BytePtr, Type::Size, Type::WordPtr};
|
llvm::Type* callArgsTypes[] = {Type::EnvPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::BytePtr, Type::Size, Type::WordPtr};
|
||||||
|
|
@ -106,12 +106,14 @@ void Ext::suicide(llvm::Value* _address)
|
||||||
m_builder.CreateCall2(m_suicide, getRuntimeManager().getEnv(), m_args[0]);
|
m_builder.CreateCall2(m_suicide, getRuntimeManager().getEnv(), m_args[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize)
|
llvm::Value* Ext::create(llvm::Value*& _gas, llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize)
|
||||||
{
|
{
|
||||||
m_builder.CreateStore(_endowment, m_args[0]);
|
m_builder.CreateStore(_gas, m_args[0]);
|
||||||
|
m_builder.CreateStore(_endowment, m_arg2);
|
||||||
auto begin = m_memoryMan.getBytePtr(_initOff);
|
auto begin = m_memoryMan.getBytePtr(_initOff);
|
||||||
auto size = m_builder.CreateTrunc(_initSize, Type::Size, "size");
|
auto size = m_builder.CreateTrunc(_initSize, Type::Size, "size");
|
||||||
createCall(m_create, getRuntimeManager().getEnv(), m_args[0], begin, size, m_args[1]);
|
createCall(m_create, getRuntimeManager().getEnv(), m_args[0], m_arg2, begin, size, m_args[1]);
|
||||||
|
_gas = m_builder.CreateLoad(m_args[0]); // Return gas
|
||||||
llvm::Value* address = m_builder.CreateLoad(m_args[1]);
|
llvm::Value* address = m_builder.CreateLoad(m_args[1]);
|
||||||
address = Endianness::toNative(m_builder, address);
|
address = Endianness::toNative(m_builder, address);
|
||||||
return address;
|
return address;
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ public:
|
||||||
llvm::Value* balance(llvm::Value* _address);
|
llvm::Value* balance(llvm::Value* _address);
|
||||||
void suicide(llvm::Value* _address);
|
void suicide(llvm::Value* _address);
|
||||||
llvm::Value* calldataload(llvm::Value* _index);
|
llvm::Value* calldataload(llvm::Value* _index);
|
||||||
llvm::Value* create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize);
|
llvm::Value* create(llvm::Value*& _gas, llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize);
|
||||||
llvm::Value* call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress);
|
llvm::Value* call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress);
|
||||||
|
|
||||||
llvm::Value* sha3(llvm::Value* _inOff, llvm::Value* _inSize);
|
llvm::Value* sha3(llvm::Value* _inOff, llvm::Value* _inSize);
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ bool isCostBlockEnd(Instruction _inst)
|
||||||
// Basic block terminators like STOP are not needed on the list
|
// Basic block terminators like STOP are not needed on the list
|
||||||
// as cost will be commited at the end of basic block
|
// as cost will be commited at the end of basic block
|
||||||
|
|
||||||
// CALL & CALLCODE are commited manually
|
// CALL, CALLCODE & CREATE are commited manually
|
||||||
|
|
||||||
switch (_inst)
|
switch (_inst)
|
||||||
{
|
{
|
||||||
|
|
@ -94,7 +94,6 @@ bool isCostBlockEnd(Instruction _inst)
|
||||||
case Instruction::MSTORE8:
|
case Instruction::MSTORE8:
|
||||||
case Instruction::SSTORE:
|
case Instruction::SSTORE:
|
||||||
case Instruction::GAS:
|
case Instruction::GAS:
|
||||||
case Instruction::CREATE:
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
|
||||||
|
|
@ -60,12 +60,18 @@ llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _
|
||||||
auto size = offset->getNextNode();
|
auto size = offset->getNextNode();
|
||||||
size->setName("size");
|
size->setName("size");
|
||||||
|
|
||||||
|
auto preBB = llvm::BasicBlock::Create(func->getContext(), "Pre", func);
|
||||||
auto checkBB = llvm::BasicBlock::Create(func->getContext(), "Check", func);
|
auto checkBB = llvm::BasicBlock::Create(func->getContext(), "Check", func);
|
||||||
auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "Resize", func);
|
auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "Resize", func);
|
||||||
auto returnBB = llvm::BasicBlock::Create(func->getContext(), "Return", func);
|
auto returnBB = llvm::BasicBlock::Create(func->getContext(), "Return", func);
|
||||||
|
|
||||||
InsertPointGuard guard(m_builder); // Restores insert point at function exit
|
InsertPointGuard guard(m_builder); // Restores insert point at function exit
|
||||||
|
|
||||||
|
// BB "Pre": Ignore checks with size 0
|
||||||
|
m_builder.SetInsertPoint(preBB);
|
||||||
|
auto sizeIsZero = m_builder.CreateICmpEQ(size, Constant::get(0));
|
||||||
|
m_builder.CreateCondBr(sizeIsZero, returnBB, checkBB);
|
||||||
|
|
||||||
// BB "Check"
|
// BB "Check"
|
||||||
m_builder.SetInsertPoint(checkBB);
|
m_builder.SetInsertPoint(checkBB);
|
||||||
auto uaddWO = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::uadd_with_overflow, Type::Word);
|
auto uaddWO = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::uadd_with_overflow, Type::Word);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue