diff --git a/evmjit/libevmjit/GasMeter.cpp b/evmjit/libevmjit/GasMeter.cpp index 34dff5a69..5b748650d 100644 --- a/evmjit/libevmjit/GasMeter.cpp +++ b/evmjit/libevmjit/GasMeter.cpp @@ -125,7 +125,7 @@ void GasMeter::count(Instruction _inst) m_blockCost += getStepCost(_inst); } -void GasMeter::count(llvm::Value* _cost, llvm::Value* _jmpBuf) +void GasMeter::count(llvm::Value* _cost, llvm::Value* _jmpBuf, llvm::Value* _gasPtr) { if (_cost->getType() == Type::Word) { @@ -136,7 +136,7 @@ void GasMeter::count(llvm::Value* _cost, llvm::Value* _jmpBuf) } assert(_cost->getType() == Type::Gas); - createCall(m_gasCheckFunc, {m_runtimeManager.getGasPtr(), _cost, _jmpBuf ? _jmpBuf : m_runtimeManager.getJmpBuf()}); + createCall(m_gasCheckFunc, {_gasPtr ? _gasPtr : m_runtimeManager.getGasPtr(), _cost, _jmpBuf ? _jmpBuf : m_runtimeManager.getJmpBuf()}); } void GasMeter::countExp(llvm::Value* _exponent) @@ -215,10 +215,10 @@ void GasMeter::commitCostBlock() assert(m_blockCost == 0); } -void GasMeter::countMemory(llvm::Value* _additionalMemoryInWords, llvm::Value* _jmpBuf) +void GasMeter::countMemory(llvm::Value* _additionalMemoryInWords, llvm::Value* _jmpBuf, llvm::Value* _gasPtr) { static_assert(c_memoryGas == 1, "Memory gas cost has changed. Update GasMeter."); - count(_additionalMemoryInWords, _jmpBuf); + count(_additionalMemoryInWords, _jmpBuf, _gasPtr); } void GasMeter::countCopy(llvm::Value* _copyWords) diff --git a/evmjit/libevmjit/GasMeter.h b/evmjit/libevmjit/GasMeter.h index 550b5474c..aecc07315 100644 --- a/evmjit/libevmjit/GasMeter.h +++ b/evmjit/libevmjit/GasMeter.h @@ -20,7 +20,7 @@ public: void count(Instruction _inst); /// Count additional cost - void count(llvm::Value* _cost, llvm::Value* _jmpBuf = nullptr); + void count(llvm::Value* _cost, llvm::Value* _jmpBuf = nullptr, llvm::Value* _gasPtr = nullptr); /// Calculate & count gas cost for SSTORE instruction void countSStore(class Ext& _ext, llvm::Value* _index, llvm::Value* _newValue); @@ -41,7 +41,7 @@ public: void giveBack(llvm::Value* _gas); /// Generate code that checks the cost of additional memory used by program - void countMemory(llvm::Value* _additionalMemoryInWords, llvm::Value* _jmpBuf); + void countMemory(llvm::Value* _additionalMemoryInWords, llvm::Value* _jmpBuf, llvm::Value* _gasPtr); /// Count addional gas cost for memory copy void countCopy(llvm::Value* _copyWords); diff --git a/evmjit/libevmjit/Memory.cpp b/evmjit/libevmjit/Memory.cpp index bfb48a245..efc0ecf95 100644 --- a/evmjit/libevmjit/Memory.cpp +++ b/evmjit/libevmjit/Memory.cpp @@ -28,18 +28,19 @@ llvm::Function* Memory::getRequireFunc() auto& func = m_require; if (!func) { - llvm::Type* argTypes[] = {Type::RuntimePtr, Type::Word, Type::Word, Type::BytePtr, Array::getType()->getPointerTo()}; + llvm::Type* argTypes[] = {Array::getType()->getPointerTo(), Type::Word, Type::Word, Type::BytePtr, Type::GasPtr}; func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::PrivateLinkage, "mem.require", getModule()); - auto rt = func->arg_begin(); - rt->setName("rt"); - auto offset = rt->getNextNode(); + + auto mem = &func->getArgumentList().front(); + mem->setName("mem"); + auto offset = mem->getNextNode(); offset->setName("offset"); auto size = offset->getNextNode(); size->setName("size"); auto jmpBuf = size->getNextNode(); jmpBuf->setName("jmpBuf"); - auto mem = jmpBuf->getNextNode(); - mem->setName("mem"); + auto gas = jmpBuf->getNextNode(); + gas->setName("gas"); auto preBB = llvm::BasicBlock::Create(func->getContext(), "Pre", func); auto checkBB = llvm::BasicBlock::Create(func->getContext(), "Check", func); @@ -76,7 +77,7 @@ llvm::Function* Memory::getRequireFunc() sizeRequired = m_builder.CreateMul(wordsRequired, Constant::get(32), "roundedSizeReq"); auto words = m_builder.CreateUDiv(currSize, m_builder.getInt64(32), "words"); // size is always 32*k auto newWords = m_builder.CreateSub(wordsRequired, m_builder.CreateZExt(words, Type::Word), "addtionalWords"); - m_gasMeter.countMemory(newWords, jmpBuf); + m_gasMeter.countMemory(newWords, jmpBuf, gas); // Resize auto extendSize = m_builder.CreateTrunc(sizeRequired, Type::Size, "extendSize"); m_memory.extend(mem, extendSize); @@ -93,8 +94,8 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType) { auto isWord = _valueType == Type::Word; - llvm::Type* storeArgs[] = {Type::RuntimePtr, Type::Word, _valueType, Array::getType()->getPointerTo()}; - llvm::Type* loadArgs[] = {Type::RuntimePtr, Type::Word, Array::getType()->getPointerTo()}; + llvm::Type* storeArgs[] = {Array::getType()->getPointerTo(), Type::Word, _valueType}; + llvm::Type* loadArgs[] = {Array::getType()->getPointerTo(), Type::Word}; auto name = _isStore ? isWord ? "mstore" : "mstore8" : "mload"; auto funcType = _isStore ? llvm::FunctionType::get(Type::Void, storeArgs, false) : llvm::FunctionType::get(Type::Word, loadArgs, false); auto func = llvm::Function::Create(funcType, llvm::Function::PrivateLinkage, name, getModule()); @@ -102,17 +103,15 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType) InsertPointGuard guard(m_builder); // Restores insert point at function exit m_builder.SetInsertPoint(llvm::BasicBlock::Create(func->getContext(), {}, func)); - auto rt = func->arg_begin(); - rt->setName("rt"); - auto index = rt->getNextNode(); + auto mem = &func->getArgumentList().front(); + mem->setName("mem"); + auto index = mem->getNextNode(); index->setName("index"); if (_isStore) { auto valueArg = index->getNextNode(); valueArg->setName("value"); - auto mem = valueArg->getNextNode(); - mem->setName("mem"); auto value = isWord ? Endianness::toBE(m_builder, valueArg) : valueArg; auto memPtr = m_memory.getPtr(mem, m_builder.CreateTrunc(index, Type::Size)); auto valuePtr = m_builder.CreateBitCast(memPtr, _valueType->getPointerTo(), "valuePtr"); @@ -121,8 +120,6 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType) } else { - auto mem = index->getNextNode(); - mem->setName("mem"); auto memPtr = m_memory.getPtr(mem, m_builder.CreateTrunc(index, Type::Size)); llvm::Value* ret = m_builder.CreateLoad(memPtr); ret = Endianness::toNative(m_builder, ret); @@ -160,20 +157,20 @@ llvm::Function* Memory::getStoreByteFunc() llvm::Value* Memory::loadWord(llvm::Value* _addr) { require(_addr, Constant::get(Type::Word->getPrimitiveSizeInBits() / 8)); - return createCall(getLoadWordFunc(), {getRuntimeManager().getRuntimePtr(), _addr, getRuntimeManager().getMem()}); + return createCall(getLoadWordFunc(), {getRuntimeManager().getMem(), _addr}); } void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word) { require(_addr, Constant::get(Type::Word->getPrimitiveSizeInBits() / 8)); - createCall(getStoreWordFunc(), {getRuntimeManager().getRuntimePtr(), _addr, _word, getRuntimeManager().getMem()}); + createCall(getStoreWordFunc(), {getRuntimeManager().getMem(), _addr, _word}); } void Memory::storeByte(llvm::Value* _addr, llvm::Value* _word) { require(_addr, Constant::get(Type::Byte->getPrimitiveSizeInBits() / 8)); auto byte = m_builder.CreateTrunc(_word, Type::Byte, "byte"); - createCall(getStoreByteFunc(), {getRuntimeManager().getRuntimePtr(), _addr, byte, getRuntimeManager().getMem()}); + createCall(getStoreByteFunc(), {getRuntimeManager().getMem(), _addr, byte}); } llvm::Value* Memory::getData() @@ -202,7 +199,7 @@ void Memory::require(llvm::Value* _offset, llvm::Value* _size) if (!constant->getValue()) return; } - createCall(getRequireFunc(), {getRuntimeManager().getRuntimePtr(), _offset, _size, getRuntimeManager().getJmpBuf(), getRuntimeManager().getMem()}); + createCall(getRequireFunc(), {getRuntimeManager().getMem(), _offset, _size, getRuntimeManager().getJmpBuf(), getRuntimeManager().getGasPtr()}); } void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx, diff --git a/evmjit/libevmjit/RuntimeManager.cpp b/evmjit/libevmjit/RuntimeManager.cpp index 3e18c8c18..f6b5df43e 100644 --- a/evmjit/libevmjit/RuntimeManager.cpp +++ b/evmjit/libevmjit/RuntimeManager.cpp @@ -5,6 +5,7 @@ #include "preprocessor/llvm_includes_end.h" #include "Stack.h" +#include "Utils.h" namespace dev { @@ -99,6 +100,8 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder, llvm::Value* _jmpBuf assert(m_dataPtr->getType() == Type::RuntimeDataPtr); m_gasPtr = m_builder.CreateStructGEP(m_dataPtr, 0, "gas"); assert(m_gasPtr->getType() == Type::Gas->getPointerTo()); + m_memPtr = m_builder.CreateStructGEP(rtPtr, 4, "mem"); + assert(m_memPtr->getType() == Array::getType()->getPointerTo()); m_envPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(rtPtr, 1), "env"); assert(m_envPtr->getType() == Type::EnvPtr); } @@ -123,14 +126,6 @@ llvm::Value* RuntimeManager::getDataPtr() return dataPtr; } -llvm::Value* RuntimeManager::getMem() -{ - auto rtPtr = getRuntimePtr(); - auto memPtr = m_builder.CreateStructGEP(rtPtr, 4, "mem"); - assert(memPtr->getType() == Array::getType()->getPointerTo()); - return memPtr; -} - llvm::Value* RuntimeManager::getEnvPtr() { assert(getMainFunction()); // Available only in main function @@ -238,11 +233,14 @@ llvm::Value* RuntimeManager::getGas() llvm::Value* RuntimeManager::getGasPtr() { - if (getMainFunction()) - return m_gasPtr; + assert(getMainFunction()); + return m_gasPtr; +} - // TODO: eliminated this case - return getPtr(RuntimeData::Gas); +llvm::Value* RuntimeManager::getMem() +{ + assert(getMainFunction()); + return m_memPtr; } void RuntimeManager::setGas(llvm::Value* _gas) diff --git a/evmjit/libevmjit/RuntimeManager.h b/evmjit/libevmjit/RuntimeManager.h index 65b63c72b..52298d1d0 100644 --- a/evmjit/libevmjit/RuntimeManager.h +++ b/evmjit/libevmjit/RuntimeManager.h @@ -55,6 +55,7 @@ private: llvm::Value* const m_jmpBuf; llvm::Value* m_dataPtr = nullptr; llvm::Value* m_gasPtr = nullptr; + llvm::Value* m_memPtr = nullptr; llvm::Value* m_envPtr = nullptr; code_iterator m_codeBegin = {};