From 5470faf9ecc92da19cde1a993fd9d28cff782b4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 13 Oct 2014 10:57:12 +0200 Subject: [PATCH] Count gas for additional memory [#79942174] --- evmcc/Compiler.cpp | 4 ++-- evmcc/GasMeter.cpp | 7 +++++++ evmcc/GasMeter.h | 3 +++ evmcc/Memory.cpp | 22 ++++++++++++++++------ evmcc/Memory.h | 5 +++-- 5 files changed, 31 insertions(+), 10 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 806592287..e532ce9f5 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -196,9 +196,9 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) createBasicBlocks(bytecode); // Init runtime structures. - auto memory = Memory(builder, module.get()); - auto ext = Ext(builder, module.get()); GasMeter gasMeter(builder, module.get()); + Memory memory(builder, module.get(), gasMeter); + Ext ext(builder, module.get()); // Jump to first instruction builder.CreateBr(basicBlocks.begin()->second); diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 013205ee6..eed9fa0ad 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -114,4 +114,11 @@ void GasMeter::check(Instruction _inst) } } +void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder) +{ + // Memory uses other builder, but that can be changes later + auto cost = _builder.CreateMul(_additionalMemoryInWords, _builder.getIntN(256, static_cast(c_memoryGas)), "memcost"); + _builder.CreateCall(m_gasCheckFunc, cost); +} + } \ No newline at end of file diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index 057391102..73f0d6e1c 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -18,6 +18,9 @@ public: void check(dev::eth::Instruction _inst); + /// Generate code that checks the cost of additional memory used by program + void checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder); + private: /// Cumulative gas cost of a block of instructions /// @TODO Handle overflow diff --git a/evmcc/Memory.cpp b/evmcc/Memory.cpp index ba787614e..fa21237b7 100644 --- a/evmcc/Memory.cpp +++ b/evmcc/Memory.cpp @@ -13,6 +13,7 @@ #include "Type.h" #include "Runtime.h" +#include "GasMeter.h" #ifdef _MSC_VER #define EXPORT __declspec(dllexport) @@ -23,8 +24,8 @@ namespace evmcc { -Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module) - : m_builder(_builder) +Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _gasMeter): + m_builder(_builder) { auto voidTy = m_builder.getVoidTy(); auto i64Ty = m_builder.getInt64Ty(); @@ -51,12 +52,12 @@ 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_loadWord = createFunc(false, Type::i256, _module); - m_storeWord = createFunc(true, Type::i256, _module); - m_storeByte = createFunc(true, Type::Byte, _module); + m_loadWord = createFunc(false, Type::i256, _module, _gasMeter); + m_storeWord = createFunc(true, Type::i256, _module, _gasMeter); + m_storeByte = createFunc(true, Type::Byte, _module, _gasMeter); } -llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm::Module* _module) +llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm::Module* _module, GasMeter& _gasMeter) { auto isWord = _valueType == Type::i256; @@ -69,6 +70,7 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm:: auto resizeBB = llvm::BasicBlock::Create(func->getContext(), "resize", func); auto accessBB = llvm::BasicBlock::Create(func->getContext(), "access", func); + // BB "check" llvm::IRBuilder<> builder(checkBB); llvm::Value* index = func->arg_begin(); index->setName("index"); @@ -78,12 +80,20 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, llvm:: auto resizeNeeded = builder.CreateICmpULE(size, sizeRequired, "resizeNeeded"); builder.CreateCondBr(resizeNeeded, resizeBB, accessBB); // OPT branch weights? + // BB "resize" builder.SetInsertPoint(resizeBB); + // Check gas first + auto wordsRequired = builder.CreateUDiv(builder.CreateAdd(sizeRequired, builder.getIntN(256, 31)), builder.getIntN(256, 32), "wordsRequired"); + auto words = builder.CreateUDiv(builder.CreateAdd(size, builder.getIntN(256, 31)), builder.getIntN(256, 32), "words"); + auto newWords = builder.CreateSub(wordsRequired, words, "addtionalWords"); + _gasMeter.checkMemory(newWords, builder); + // Resize builder.CreateStore(sizeRequired, m_size); auto newData = builder.CreateCall(m_resize, m_size, "newData"); builder.CreateStore(newData, m_data); builder.CreateBr(accessBB); + // BB "access" builder.SetInsertPoint(accessBB); auto data = builder.CreateLoad(m_data, "data"); auto ptr = builder.CreateGEP(data, index, "ptr"); diff --git a/evmcc/Memory.h b/evmcc/Memory.h index 2166abd14..ed7273c5c 100644 --- a/evmcc/Memory.h +++ b/evmcc/Memory.h @@ -6,11 +6,12 @@ namespace evmcc { +class GasMeter; class Memory { public: - Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module); + Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _gasMeter); Memory(const Memory&) = delete; void operator=(Memory) = delete; @@ -22,7 +23,7 @@ public: void dump(uint64_t _begin, uint64_t _end = 0); private: - llvm::Function* createFunc(bool _isStore, llvm::Type* _type, llvm::Module* _module); + llvm::Function* createFunc(bool _isStore, llvm::Type* _type, llvm::Module* _module, GasMeter& _gasMeter); private: llvm::IRBuilder<>& m_builder;