mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-20 11:46:44 +00:00
Generate mem.store function and dependencies (currently unused)
[#80191662]
This commit is contained in:
parent
7a7d4e33e0
commit
f825a6020f
4 changed files with 73 additions and 5 deletions
|
|
@ -6,10 +6,12 @@
|
|||
#include <cstdint>
|
||||
#include <cassert>
|
||||
|
||||
#include <llvm/IR/GlobalVariable.h>
|
||||
#include <llvm/IR/Function.h>
|
||||
|
||||
#include <libdevcore/Common.h>
|
||||
|
||||
#include "Type.h"
|
||||
#include "Runtime.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
|
@ -21,7 +23,7 @@
|
|||
namespace evmcc
|
||||
{
|
||||
|
||||
Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* module)
|
||||
Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module)
|
||||
: m_builder(_builder)
|
||||
{
|
||||
auto voidTy = m_builder.getVoidTy();
|
||||
|
|
@ -30,17 +32,59 @@ Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* module)
|
|||
auto memRequireTy = llvm::FunctionType::get(m_builder.getInt8PtrTy(), i64Ty, false);
|
||||
m_memRequire = llvm::Function::Create(memRequireTy,
|
||||
llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
||||
"evmccrt_memory_require", module);
|
||||
"evmccrt_memory_require", _module);
|
||||
|
||||
auto memSizeTy = llvm::FunctionType::get(i64Ty, false);
|
||||
m_memSize = llvm::Function::Create(memSizeTy,
|
||||
llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
||||
"evmccrt_memory_size", module);
|
||||
"evmccrt_memory_size", _module);
|
||||
|
||||
std::vector<llvm::Type*> argTypes = {i64Ty, i64Ty};
|
||||
auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef<llvm::Type*>(argTypes), false);
|
||||
m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
||||
"evmccrt_memory_dump", module);
|
||||
"evmccrt_memory_dump", _module);
|
||||
|
||||
m_data = new llvm::GlobalVariable(*_module, Type::BytePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::BytePtr), "mem.data");
|
||||
m_data->setUnnamedAddr(true); // Address is not important
|
||||
|
||||
m_size = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, m_builder.getIntN(256, 0), "mem.size");
|
||||
m_size->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* storeArgs[] = {Type::i256, Type::i256};
|
||||
m_store = llvm::Function::Create(llvm::FunctionType::get(Type::Void, storeArgs, false), llvm::Function::PrivateLinkage, "mem.store", _module);
|
||||
auto origBB = m_builder.GetInsertBlock();
|
||||
auto origPt = m_builder.GetInsertPoint();
|
||||
|
||||
auto checkBB = llvm::BasicBlock::Create(m_store->getContext(), "check", m_store);
|
||||
auto resizeBB = llvm::BasicBlock::Create(m_store->getContext(), "resize", m_store);
|
||||
auto storeBB = llvm::BasicBlock::Create(m_store->getContext(), "store", m_store);
|
||||
|
||||
m_builder.SetInsertPoint(checkBB);
|
||||
llvm::Value* index = m_store->arg_begin();
|
||||
index->setName("index");
|
||||
llvm::Value* value = ++m_store->arg_begin();
|
||||
value->setName("value");
|
||||
auto sizeRequired = m_builder.CreateAdd(index, m_builder.getIntN(256, 32), "sizeRequired");
|
||||
auto size = m_builder.CreateLoad(m_size, "size");
|
||||
auto resizeNeeded = m_builder.CreateICmpULE(sizeRequired, size, "resizeNeeded");
|
||||
m_builder.CreateCondBr(resizeNeeded, resizeBB, storeBB); // OPT branch weights?
|
||||
|
||||
m_builder.SetInsertPoint(resizeBB);
|
||||
m_builder.CreateStore(sizeRequired, m_size);
|
||||
llvm::Value* data = m_builder.CreateCall(m_resize, m_size, "data");
|
||||
m_builder.CreateStore(data, m_data);
|
||||
m_builder.CreateBr(storeBB);
|
||||
|
||||
m_builder.SetInsertPoint(storeBB);
|
||||
data = m_builder.CreateLoad(m_data, "data");
|
||||
auto ptr = m_builder.CreateGEP(data, index, "ptr");
|
||||
ptr = m_builder.CreateBitCast(ptr, Type::WordPtr, "wordPtr");
|
||||
m_builder.CreateStore(value, ptr);
|
||||
m_builder.CreateRetVoid();
|
||||
|
||||
m_builder.SetInsertPoint(origBB, origPt);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -114,6 +158,14 @@ extern "C"
|
|||
{
|
||||
using namespace evmcc;
|
||||
|
||||
EXPORT uint8_t* mem_resize(i256* _size)
|
||||
{
|
||||
auto size = _size->a; // Trunc to 64-bit
|
||||
auto& memory = Runtime::getMemory();
|
||||
memory.resize(size);
|
||||
return memory.data();
|
||||
}
|
||||
|
||||
// Resizes memory to contain at least _index + 1 bytes and returns the base address.
|
||||
EXPORT uint8_t* evmccrt_memory_require(uint64_t _index)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ namespace evmcc
|
|||
class Memory
|
||||
{
|
||||
public:
|
||||
Memory(llvm::IRBuilder<>& _builder, llvm::Module* module);
|
||||
Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module);
|
||||
|
||||
llvm::Value* loadWord(llvm::Value* _addr);
|
||||
void storeWord(llvm::Value* _addr, llvm::Value* _word);
|
||||
|
|
@ -22,6 +22,12 @@ public:
|
|||
private:
|
||||
llvm::IRBuilder<>& m_builder;
|
||||
|
||||
llvm::GlobalVariable* m_data;
|
||||
llvm::GlobalVariable* m_size;
|
||||
|
||||
llvm::Function* m_store;
|
||||
llvm::Function* m_resize;
|
||||
|
||||
llvm::Function* m_memRequire;
|
||||
llvm::Function* m_memDump;
|
||||
llvm::Function* m_memSize;
|
||||
|
|
|
|||
|
|
@ -7,13 +7,19 @@ namespace evmcc
|
|||
{
|
||||
|
||||
llvm::IntegerType* Type::i256;
|
||||
llvm::PointerType* Type::WordPtr;
|
||||
llvm::IntegerType* Type::lowPrecision;
|
||||
llvm::IntegerType* Type::Byte;
|
||||
llvm::PointerType* Type::BytePtr;
|
||||
llvm::Type* Type::Void;
|
||||
|
||||
void Type::init(llvm::LLVMContext& _context)
|
||||
{
|
||||
i256 = llvm::Type::getIntNTy(_context, 256);
|
||||
WordPtr = i256->getPointerTo();
|
||||
lowPrecision = llvm::Type::getInt64Ty(_context);
|
||||
Byte = llvm::Type::getInt8Ty(_context);
|
||||
BytePtr = Byte->getPointerTo();
|
||||
Void = llvm::Type::getVoidTy(_context);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,15 @@ namespace evmcc
|
|||
struct Type
|
||||
{
|
||||
static llvm::IntegerType* i256;
|
||||
static llvm::PointerType* WordPtr;
|
||||
|
||||
/// Type for doing low precision arithmetics where 256-bit precision is not supported by native target
|
||||
/// @TODO: Use 64-bit for now. In 128-bit compiler-rt library functions are required
|
||||
static llvm::IntegerType* lowPrecision;
|
||||
|
||||
static llvm::IntegerType* Byte;
|
||||
static llvm::PointerType* BytePtr;
|
||||
|
||||
static llvm::Type* Void;
|
||||
|
||||
static void init(llvm::LLVMContext& _context);
|
||||
|
|
|
|||
Loading…
Reference in a new issue