mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-21 20:26:41 +00:00
Access memory structure through runtime structure [#81470252]
This commit is contained in:
parent
b579c70643
commit
c388a81cff
7 changed files with 63 additions and 58 deletions
|
|
@ -179,7 +179,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(bytesConstRef bytecode)
|
||||||
// Init runtime structures.
|
// Init runtime structures.
|
||||||
RuntimeManager runtimeManager(m_builder);
|
RuntimeManager runtimeManager(m_builder);
|
||||||
GasMeter gasMeter(m_builder, runtimeManager);
|
GasMeter gasMeter(m_builder, runtimeManager);
|
||||||
Memory memory(m_builder, gasMeter);
|
Memory memory(m_builder, gasMeter, runtimeManager);
|
||||||
Ext ext(m_builder);
|
Ext ext(m_builder);
|
||||||
Stack stack(m_builder);
|
Stack stack(m_builder);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,7 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module, u256& _gas, ExtV
|
||||||
|
|
||||||
if (returnCode == ReturnCode::Return)
|
if (returnCode == ReturnCode::Return)
|
||||||
{
|
{
|
||||||
returnData = Memory::getReturnData().toVector(); // TODO: It might be better to place is in Runtime interface
|
returnData = runtime.getReturnData().toVector(); // TODO: It might be better to place is in Runtime interface
|
||||||
|
|
||||||
std::cout << "RETURN [ ";
|
std::cout << "RETURN [ ";
|
||||||
for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it)
|
for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it)
|
||||||
|
|
|
||||||
|
|
@ -306,7 +306,8 @@ EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256*
|
||||||
u256 gas; // TODO: Handle gas
|
u256 gas; // TODO: Handle gas
|
||||||
auto initOff = static_cast<size_t>(llvm2eth(*_initOff));
|
auto initOff = static_cast<size_t>(llvm2eth(*_initOff));
|
||||||
auto initSize = static_cast<size_t>(llvm2eth(*_initSize));
|
auto initSize = static_cast<size_t>(llvm2eth(*_initSize));
|
||||||
auto&& initRef = bytesConstRef(Runtime::getMemory().data() + initOff, initSize);
|
//auto&& initRef = bytesConstRef(Runtime::getMemory().data() + initOff, initSize);
|
||||||
|
bytesConstRef initRef;
|
||||||
OnOpFunc onOp{}; // TODO: Handle that thing
|
OnOpFunc onOp{}; // TODO: Handle that thing
|
||||||
h256 address = ext.create(endowment, &gas, initRef, onOp);
|
h256 address = ext.create(endowment, &gas, initRef, onOp);
|
||||||
*_address = address;
|
*_address = address;
|
||||||
|
|
@ -332,8 +333,8 @@ EXPORT void ext_call(i256* _gas, h256* _receiveAddress, i256* _value, i256* _inO
|
||||||
auto inSize = static_cast<size_t>(llvm2eth(*_inSize));
|
auto inSize = static_cast<size_t>(llvm2eth(*_inSize));
|
||||||
auto outOff = static_cast<size_t>(llvm2eth(*_outOff));
|
auto outOff = static_cast<size_t>(llvm2eth(*_outOff));
|
||||||
auto outSize = static_cast<size_t>(llvm2eth(*_outSize));
|
auto outSize = static_cast<size_t>(llvm2eth(*_outSize));
|
||||||
auto&& inRef = bytesConstRef(Runtime::getMemory().data() + inOff, inSize);
|
auto&& inRef = bytesConstRef(); //Runtime::getMemory().data() + inOff, inSize);
|
||||||
auto&& outRef = bytesConstRef(Runtime::getMemory().data() + outOff, outSize);
|
auto&& outRef = bytesConstRef(); // Runtime::getMemory().data() + outOff, outSize);
|
||||||
OnOpFunc onOp{}; // TODO: Handle that thing
|
OnOpFunc onOp{}; // TODO: Handle that thing
|
||||||
auto codeAddress = right160(*_codeAddress);
|
auto codeAddress = right160(*_codeAddress);
|
||||||
ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, codeAddress);
|
ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, codeAddress);
|
||||||
|
|
@ -347,7 +348,7 @@ EXPORT void ext_sha3(i256* _inOff, i256* _inSize, i256* _ret)
|
||||||
{
|
{
|
||||||
auto inOff = static_cast<size_t>(llvm2eth(*_inOff));
|
auto inOff = static_cast<size_t>(llvm2eth(*_inOff));
|
||||||
auto inSize = static_cast<size_t>(llvm2eth(*_inSize));
|
auto inSize = static_cast<size_t>(llvm2eth(*_inSize));
|
||||||
auto dataRef = bytesConstRef(Runtime::getMemory().data() + inOff, inSize);
|
auto dataRef = bytesConstRef(); // Runtime::getMemory().data() + inOff, inSize);
|
||||||
auto hash = sha3(dataRef);
|
auto hash = sha3(dataRef);
|
||||||
*_ret = *reinterpret_cast<i256*>(&hash);
|
*_ret = *reinterpret_cast<i256*>(&hash);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@
|
||||||
#include "Runtime.h"
|
#include "Runtime.h"
|
||||||
#include "GasMeter.h"
|
#include "GasMeter.h"
|
||||||
#include "Endianness.h"
|
#include "Endianness.h"
|
||||||
|
#include "Runtime.h"
|
||||||
|
|
||||||
namespace dev
|
namespace dev
|
||||||
{
|
{
|
||||||
|
|
@ -23,7 +24,7 @@ namespace eth
|
||||||
namespace jit
|
namespace jit
|
||||||
{
|
{
|
||||||
|
|
||||||
Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter):
|
Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter, RuntimeManager& _runtimeManager):
|
||||||
CompilerHelper(_builder)
|
CompilerHelper(_builder)
|
||||||
{
|
{
|
||||||
auto module = getModule();
|
auto module = getModule();
|
||||||
|
|
@ -45,18 +46,19 @@ Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter):
|
||||||
m_returnDataSize = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataSize");
|
m_returnDataSize = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataSize");
|
||||||
m_returnDataSize->setUnnamedAddr(true); // Address is not important
|
m_returnDataSize->setUnnamedAddr(true); // Address is not important
|
||||||
|
|
||||||
m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), llvm::Function::ExternalLinkage, "mem_resize", module);
|
llvm::Type* resizeArgs[] = {RuntimeData::getType()->getPointerTo(), Type::WordPtr};
|
||||||
|
m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, resizeArgs, false), llvm::Function::ExternalLinkage, "mem_resize", module);
|
||||||
llvm::AttrBuilder attrBuilder;
|
llvm::AttrBuilder attrBuilder;
|
||||||
attrBuilder.addAttribute(llvm::Attribute::NoAlias).addAttribute(llvm::Attribute::NoCapture).addAttribute(llvm::Attribute::NonNull).addAttribute(llvm::Attribute::ReadOnly);
|
attrBuilder.addAttribute(llvm::Attribute::NoAlias).addAttribute(llvm::Attribute::NoCapture).addAttribute(llvm::Attribute::NonNull).addAttribute(llvm::Attribute::ReadOnly);
|
||||||
m_resize->setAttributes(llvm::AttributeSet::get(m_resize->getContext(), 1, attrBuilder));
|
m_resize->setAttributes(llvm::AttributeSet::get(m_resize->getContext(), 1, attrBuilder));
|
||||||
|
|
||||||
m_require = createRequireFunc(_gasMeter);
|
m_require = createRequireFunc(_gasMeter, _runtimeManager);
|
||||||
m_loadWord = createFunc(false, Type::i256, _gasMeter);
|
m_loadWord = createFunc(false, Type::i256, _gasMeter);
|
||||||
m_storeWord = createFunc(true, Type::i256, _gasMeter);
|
m_storeWord = createFunc(true, Type::i256, _gasMeter);
|
||||||
m_storeByte = createFunc(true, Type::Byte, _gasMeter);
|
m_storeByte = createFunc(true, Type::Byte, _gasMeter);
|
||||||
}
|
}
|
||||||
|
|
||||||
llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter)
|
llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager)
|
||||||
{
|
{
|
||||||
auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "mem.require", getModule());
|
auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "mem.require", getModule());
|
||||||
|
|
||||||
|
|
@ -83,7 +85,7 @@ llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter)
|
||||||
_gasMeter.checkMemory(newWords, m_builder);
|
_gasMeter.checkMemory(newWords, m_builder);
|
||||||
// Resize
|
// Resize
|
||||||
m_builder.CreateStore(sizeRequired, m_size);
|
m_builder.CreateStore(sizeRequired, m_size);
|
||||||
auto newData = m_builder.CreateCall(m_resize, m_size, "newData");
|
auto newData = m_builder.CreateCall2(m_resize, _runtimeManager.getRuntimePtr(), m_size, "newData");
|
||||||
m_builder.CreateStore(newData, m_data);
|
m_builder.CreateStore(newData, m_data);
|
||||||
m_builder.CreateBr(returnBB);
|
m_builder.CreateBr(returnBB);
|
||||||
|
|
||||||
|
|
@ -232,48 +234,36 @@ extern "C"
|
||||||
|
|
||||||
using namespace dev::eth::jit;
|
using namespace dev::eth::jit;
|
||||||
|
|
||||||
EXPORT i256 mem_returnDataOffset;
|
EXPORT uint8_t* mem_resize(Runtime* _rt, i256* _size)
|
||||||
EXPORT i256 mem_returnDataSize;
|
|
||||||
|
|
||||||
EXPORT uint8_t* mem_resize(i256* _size)
|
|
||||||
{
|
{
|
||||||
auto size = _size->a; // Trunc to 64-bit
|
auto size = _size->a; // Trunc to 64-bit
|
||||||
auto& memory = Runtime::getMemory();
|
auto& memory = _rt->getMemory();
|
||||||
memory.resize(size);
|
memory.resize(size);
|
||||||
return memory.data();
|
return memory.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end)
|
EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end)
|
||||||
{
|
{
|
||||||
if (_end == 0)
|
//if (_end == 0)
|
||||||
_end = Runtime::getMemory().size();
|
// _end = Runtime::getMemory().size();
|
||||||
|
|
||||||
std::cerr << "MEMORY: active size: " << std::dec
|
//std::cerr << "MEMORY: active size: " << std::dec
|
||||||
<< Runtime::getMemory().size() / 32 << " words\n";
|
// << Runtime::getMemory().size() / 32 << " words\n";
|
||||||
std::cerr << "MEMORY: dump from " << std::dec
|
//std::cerr << "MEMORY: dump from " << std::dec
|
||||||
<< _begin << " to " << _end << ":";
|
// << _begin << " to " << _end << ":";
|
||||||
if (_end <= _begin)
|
//if (_end <= _begin)
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
_begin = _begin / 16 * 16;
|
//_begin = _begin / 16 * 16;
|
||||||
for (size_t i = _begin; i < _end; i++)
|
//for (size_t i = _begin; i < _end; i++)
|
||||||
{
|
//{
|
||||||
if ((i - _begin) % 16 == 0)
|
// if ((i - _begin) % 16 == 0)
|
||||||
std::cerr << '\n' << std::dec << i << ": ";
|
// std::cerr << '\n' << std::dec << i << ": ";
|
||||||
|
|
||||||
auto b = Runtime::getMemory()[i];
|
// auto b = Runtime::getMemory()[i];
|
||||||
std::cerr << std::hex << std::setw(2) << static_cast<int>(b) << ' ';
|
// std::cerr << std::hex << std::setw(2) << static_cast<int>(b) << ' ';
|
||||||
}
|
//}
|
||||||
std::cerr << std::endl;
|
//std::cerr << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
|
|
||||||
dev::bytesConstRef dev::eth::jit::Memory::getReturnData()
|
|
||||||
{
|
|
||||||
// TODO: Handle large indexes
|
|
||||||
auto offset = static_cast<size_t>(llvm2eth(mem_returnDataOffset));
|
|
||||||
auto size = static_cast<size_t>(llvm2eth(mem_returnDataSize));
|
|
||||||
auto& memory = Runtime::getMemory();
|
|
||||||
return {memory.data() + offset, size};
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -10,11 +10,12 @@ namespace eth
|
||||||
{
|
{
|
||||||
namespace jit
|
namespace jit
|
||||||
{
|
{
|
||||||
|
class RuntimeManager;
|
||||||
|
|
||||||
class Memory : public CompilerHelper
|
class Memory : public CompilerHelper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Memory(llvm::IRBuilder<>& _builder, class GasMeter& _gasMeter);
|
Memory(llvm::IRBuilder<>& _builder, class GasMeter& _gasMeter, RuntimeManager& _runtimeManager);
|
||||||
|
|
||||||
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);
|
||||||
|
|
@ -31,13 +32,13 @@ public:
|
||||||
void require(llvm::Value* _offset, llvm::Value* _size);
|
void require(llvm::Value* _offset, llvm::Value* _size);
|
||||||
|
|
||||||
void registerReturnData(llvm::Value* _index, llvm::Value* _size);
|
void registerReturnData(llvm::Value* _index, llvm::Value* _size);
|
||||||
static bytesConstRef getReturnData();
|
bytesConstRef getReturnData();
|
||||||
|
|
||||||
void dump(uint64_t _begin, uint64_t _end = 0);
|
void dump(uint64_t _begin, uint64_t _end = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
llvm::Function* createFunc(bool _isStore, llvm::Type* _type, GasMeter& _gasMeter);
|
llvm::Function* createFunc(bool _isStore, llvm::Type* _type, GasMeter& _gasMeter);
|
||||||
llvm::Function* createRequireFunc(GasMeter& _gasMeter);
|
llvm::Function* createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
llvm::GlobalVariable* m_data;
|
llvm::GlobalVariable* m_data;
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ llvm::StructType* RuntimeData::getType()
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Runtime* g_runtime;
|
static Runtime* g_runtime; // FIXME: Remove
|
||||||
|
|
||||||
Runtime::Runtime(u256 _gas, ExtVMFace& _ext):
|
Runtime::Runtime(u256 _gas, ExtVMFace& _ext):
|
||||||
m_ext(_ext)
|
m_ext(_ext)
|
||||||
|
|
@ -49,11 +49,6 @@ StackImpl& Runtime::getStack()
|
||||||
return g_runtime->m_stack;
|
return g_runtime->m_stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
MemoryImpl& Runtime::getMemory()
|
|
||||||
{
|
|
||||||
return g_runtime->m_memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
ExtVMFace& Runtime::getExt()
|
ExtVMFace& Runtime::getExt()
|
||||||
{
|
{
|
||||||
return g_runtime->m_ext;
|
return g_runtime->m_ext;
|
||||||
|
|
@ -64,6 +59,19 @@ u256 Runtime::getGas()
|
||||||
return llvm2eth(m_data.gas);
|
return llvm2eth(m_data.gas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
EXPORT i256 mem_returnDataOffset; // FIXME: Dis-globalize
|
||||||
|
EXPORT i256 mem_returnDataSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bytesConstRef Runtime::getReturnData()
|
||||||
|
{
|
||||||
|
// TODO: Handle large indexes
|
||||||
|
auto offset = static_cast<size_t>(llvm2eth(mem_returnDataOffset));
|
||||||
|
auto size = static_cast<size_t>(llvm2eth(mem_returnDataSize));
|
||||||
|
return{getMemory().data() + offset, size};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder)
|
RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder)
|
||||||
{
|
{
|
||||||
|
|
@ -76,19 +84,21 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_bui
|
||||||
m_builder.CreateStore(dataPtr, m_dataPtr);
|
m_builder.CreateStore(dataPtr, m_dataPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
llvm::Value* RuntimeManager::getRuntimePtr()
|
||||||
|
{
|
||||||
|
// TODO: If in main function - get it from param
|
||||||
|
return m_builder.CreateLoad(m_dataPtr);
|
||||||
|
}
|
||||||
|
|
||||||
llvm::Value* RuntimeManager::getGas()
|
llvm::Value* RuntimeManager::getGas()
|
||||||
{
|
{
|
||||||
//auto gasPtr = m_builder.CreateConstGEP2_64(m_dataPtr, 0, 0);
|
auto gasPtr = m_builder.CreateStructGEP(getRuntimePtr(), 0);
|
||||||
auto rt = m_builder.CreateLoad(m_dataPtr);
|
|
||||||
auto gasPtr = m_builder.CreateStructGEP(rt, 0);
|
|
||||||
return m_builder.CreateLoad(gasPtr, "gas");
|
return m_builder.CreateLoad(gasPtr, "gas");
|
||||||
}
|
}
|
||||||
|
|
||||||
void RuntimeManager::setGas(llvm::Value* _gas)
|
void RuntimeManager::setGas(llvm::Value* _gas)
|
||||||
{
|
{
|
||||||
//auto gasPtr = m_builder.CreateStructGEP(m_dataPtr, 0);
|
auto gasPtr = m_builder.CreateStructGEP(getRuntimePtr(), 0);
|
||||||
auto rt = m_builder.CreateLoad(m_dataPtr);
|
|
||||||
auto gasPtr = m_builder.CreateStructGEP(rt, 0);
|
|
||||||
m_builder.CreateStore(_gas, gasPtr);
|
m_builder.CreateStore(_gas, gasPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -44,9 +44,10 @@ public:
|
||||||
RuntimeData* getDataPtr() { return &m_data; }
|
RuntimeData* getDataPtr() { return &m_data; }
|
||||||
|
|
||||||
static StackImpl& getStack();
|
static StackImpl& getStack();
|
||||||
static MemoryImpl& getMemory();
|
MemoryImpl& getMemory() { return m_memory; }
|
||||||
static ExtVMFace& getExt();
|
static ExtVMFace& getExt();
|
||||||
u256 getGas();
|
u256 getGas();
|
||||||
|
bytesConstRef getReturnData();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
@ -62,6 +63,8 @@ class RuntimeManager: public CompilerHelper
|
||||||
public:
|
public:
|
||||||
RuntimeManager(llvm::IRBuilder<>& _builder);
|
RuntimeManager(llvm::IRBuilder<>& _builder);
|
||||||
|
|
||||||
|
llvm::Value* getRuntimePtr();
|
||||||
|
|
||||||
llvm::Value* getGas();
|
llvm::Value* getGas();
|
||||||
void setGas(llvm::Value* _gas);
|
void setGas(llvm::Value* _gas);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue