diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index a1d3c9989..222db8482 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -51,40 +51,48 @@ Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module) 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); + m_storeWord = createStoreFunc(Type::i256, _module); + m_storeByte = createStoreFunc(Type::Byte, _module); +} + +llvm::Function* Memory::createStoreFunc(llvm::Type* _valueType, llvm::Module* _module) +{ + auto wordValue = _valueType == Type::i256; - 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(); + llvm::Type* storeArgs[] = {Type::i256, _valueType}; + auto name = wordValue ? "store" : "store8"; + auto storeFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, storeArgs, false), llvm::Function::PrivateLinkage, name, _module); - 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); + auto checkBB = llvm::BasicBlock::Create(storeFunc->getContext(), "check", storeFunc); + auto resizeBB = llvm::BasicBlock::Create(storeFunc->getContext(), "resize", storeFunc); + auto storeBB = llvm::BasicBlock::Create(storeFunc->getContext(), "store", storeFunc); - m_builder.SetInsertPoint(checkBB); - llvm::Value* index = m_store->arg_begin(); + llvm::IRBuilder<> builder(checkBB); + llvm::Value* index = storeFunc->arg_begin(); index->setName("index"); - llvm::Value* value = ++m_store->arg_begin(); + llvm::Value* value = ++storeFunc->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); + auto valueSize = _valueType->getPrimitiveSizeInBits() / 8; + auto sizeRequired = builder.CreateAdd(index, builder.getIntN(256, valueSize), "sizeRequired"); + auto size = builder.CreateLoad(m_size, "size"); + auto resizeNeeded = builder.CreateICmpULE(sizeRequired, size, "resizeNeeded"); + builder.CreateCondBr(resizeNeeded, resizeBB, storeBB); // OPT branch weights? + + builder.SetInsertPoint(resizeBB); + builder.CreateStore(sizeRequired, m_size); + auto newData = builder.CreateCall(m_resize, m_size, "newData"); + builder.CreateStore(newData, m_data); + builder.CreateBr(storeBB); + + builder.SetInsertPoint(storeBB); + auto data = builder.CreateLoad(m_data, "data"); + auto ptr = builder.CreateGEP(data, index, "ptr"); + if (wordValue) + ptr = builder.CreateBitCast(ptr, Type::WordPtr, "wordPtr"); + builder.CreateStore(value, ptr); + builder.CreateRetVoid(); + + return storeFunc; } @@ -108,19 +116,15 @@ llvm::Value* Memory::loadWord(llvm::Value* _addr) void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word) { - m_builder.CreateCall2(m_store, _addr, _word); + m_builder.CreateCall2(m_storeWord, _addr, _word); dump(0); } void Memory::storeByte(llvm::Value* _addr, llvm::Value* _word) { - auto byte = m_builder.CreateTrunc(_word, m_builder.getInt8Ty(), "byte"); - auto index = m_builder.CreateTrunc(_addr, m_builder.getInt64Ty(), "index"); - - auto base = m_builder.CreateCall(m_memRequire, index, "base"); - auto ptr = m_builder.CreateGEP(base, index, "ptr"); - m_builder.CreateStore(byte, ptr); + auto byte = m_builder.CreateTrunc(_word, Type::Byte, "byte"); + m_builder.CreateCall2(m_storeByte, _addr, byte); dump(0); } @@ -152,7 +156,6 @@ extern "C" EXPORT uint8_t* mem_resize(i256* _size) { - assert(false); auto size = _size->a; // Trunc to 64-bit auto& memory = Runtime::getMemory(); memory.resize(size); diff --git a/evmcc/Memory.h b/evmcc/Memory.h index a28a3c91e..f1d75e5b3 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -11,6 +11,8 @@ class Memory { public: Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module); + Memory(const Memory&) = delete; + void operator=(Memory) = delete; llvm::Value* loadWord(llvm::Value* _addr); void storeWord(llvm::Value* _addr, llvm::Value* _word); @@ -19,13 +21,17 @@ public: void dump(uint64_t _begin, uint64_t _end = 0); +private: + llvm::Function* createStoreFunc(llvm::Type* _type, llvm::Module* _module); + private: llvm::IRBuilder<>& m_builder; llvm::GlobalVariable* m_data; llvm::GlobalVariable* m_size; - llvm::Function* m_store; + llvm::Function* m_storeWord; + llvm::Function* m_storeByte; llvm::Function* m_resize; llvm::Function* m_memRequire;