From 04309bcaf6fb9a40da1c5027f3d329e73dfe8fb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 25 Feb 2015 14:29:47 +0100 Subject: [PATCH] Move Array helper to separated compilation unit --- libevmjit/Array.cpp | 233 ++++++++++++++++++++++++++++++++++++++++++++ libevmjit/Array.h | 62 ++++++++++++ libevmjit/Stack.cpp | 204 -------------------------------------- libevmjit/Stack.h | 46 +-------- 4 files changed, 296 insertions(+), 249 deletions(-) create mode 100644 libevmjit/Array.cpp create mode 100644 libevmjit/Array.h diff --git a/libevmjit/Array.cpp b/libevmjit/Array.cpp new file mode 100644 index 000000000..bd874a9dc --- /dev/null +++ b/libevmjit/Array.cpp @@ -0,0 +1,233 @@ +#include "Array.h" + +#include "preprocessor/llvm_includes_start.h" +#include +#include "preprocessor/llvm_includes_end.h" + +#include "RuntimeManager.h" +#include "Runtime.h" +#include "Utils.h" + +#include // DEBUG only + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +static const auto c_reallocStep = 1; +static const auto c_reallocMultipier = 2; + +llvm::Value* LazyFunction::call(llvm::IRBuilder<>& _builder, std::initializer_list const& _args) +{ + if (!m_func) + m_func = m_creator(); + + return _builder.CreateCall(m_func, {_args.begin(), _args.size()}); +} + +llvm::Function* Array::createArrayPushFunc() +{ + llvm::Type* argTypes[] = {m_array->getType(), Type::Word}; + auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::PrivateLinkage, "array.push", getModule()); + func->setDoesNotThrow(); + func->setDoesNotCapture(1); + + llvm::Type* reallocArgTypes[] = {Type::BytePtr, Type::Size}; + auto reallocFunc = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, reallocArgTypes, false), llvm::Function::ExternalLinkage, "ext_realloc", getModule()); + reallocFunc->setDoesNotThrow(); + reallocFunc->setDoesNotAlias(0); + reallocFunc->setDoesNotCapture(1); + + auto arrayPtr = &func->getArgumentList().front(); + arrayPtr->setName("arrayPtr"); + auto value = arrayPtr->getNextNode(); + value->setName("value"); + + InsertPointGuard guard{m_builder}; + auto entryBB = llvm::BasicBlock::Create(m_builder.getContext(), "Entry", func); + auto reallocBB = llvm::BasicBlock::Create(m_builder.getContext(), "Realloc", func); + auto pushBB = llvm::BasicBlock::Create(m_builder.getContext(), "Push", func); + + m_builder.SetInsertPoint(entryBB); + auto dataPtr = m_builder.CreateStructGEP(arrayPtr, 0, "dataPtr"); + auto sizePtr = m_builder.CreateStructGEP(arrayPtr, 1, "sizePtr"); + auto capPtr = m_builder.CreateStructGEP(arrayPtr, 2, "capPtr"); + auto data = m_builder.CreateLoad(dataPtr, "data"); + auto size = m_builder.CreateLoad(sizePtr, "size"); + auto cap = m_builder.CreateLoad(capPtr, "cap"); + auto reallocReq = m_builder.CreateICmpEQ(cap, size, "reallocReq"); + m_builder.CreateCondBr(reallocReq, reallocBB, pushBB); + + m_builder.SetInsertPoint(reallocBB); + auto newCap = m_builder.CreateNUWAdd(cap, m_builder.getInt64(c_reallocStep), "newCap"); + //newCap = m_builder.CreateNUWMul(newCap, m_builder.getInt64(c_reallocMultipier)); + auto reallocSize = m_builder.CreateShl(newCap, 5, "reallocSize"); // size in bytes: newCap * 32 + auto bytes = m_builder.CreateBitCast(data, Type::BytePtr, "bytes"); + auto newBytes = m_builder.CreateCall2(reallocFunc, bytes, reallocSize, "newBytes"); + auto newData = m_builder.CreateBitCast(newBytes, Type::WordPtr, "newData"); + m_builder.CreateStore(newData, dataPtr); + m_builder.CreateStore(newCap, capPtr); + m_builder.CreateBr(pushBB); + + m_builder.SetInsertPoint(pushBB); + auto dataPhi = m_builder.CreatePHI(Type::WordPtr, 2, "dataPhi"); + dataPhi->addIncoming(data, entryBB); + dataPhi->addIncoming(newData, reallocBB); + auto newElemPtr = m_builder.CreateGEP(dataPhi, size, "newElemPtr"); + m_builder.CreateStore(value, newElemPtr); + auto newSize = m_builder.CreateNUWAdd(size, m_builder.getInt64(1), "newSize"); + m_builder.CreateStore(newSize, sizePtr); + m_builder.CreateRetVoid(); + + return func; +} + +llvm::Function* Array::createArraySetFunc() +{ + llvm::Type* argTypes[] = {m_array->getType(), Type::Size, Type::Word}; + auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::PrivateLinkage, "array.set", getModule()); + func->setDoesNotThrow(); + func->setDoesNotCapture(1); + + auto arrayPtr = &func->getArgumentList().front(); + arrayPtr->setName("arrayPtr"); + auto index = arrayPtr->getNextNode(); + index->setName("index"); + auto value = index->getNextNode(); + value->setName("value"); + + InsertPointGuard guard{m_builder}; + m_builder.SetInsertPoint(llvm::BasicBlock::Create(m_builder.getContext(), {}, func)); + auto dataPtr = m_builder.CreateStructGEP(arrayPtr, 0, "dataPtr"); + auto data = m_builder.CreateLoad(dataPtr, "data"); + auto valuePtr = m_builder.CreateGEP(data, index, "valuePtr"); + m_builder.CreateStore(value, valuePtr); + m_builder.CreateRetVoid(); + return func; +} + +llvm::Function* Array::createArrayGetFunc() +{ + llvm::Type* argTypes[] = {m_array->getType(), Type::Size}; + auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Word, argTypes, false), llvm::Function::PrivateLinkage, "array.get", getModule()); + func->setDoesNotThrow(); + func->setDoesNotCapture(1); + + auto arrayPtr = &func->getArgumentList().front(); + arrayPtr->setName("arrayPtr"); + auto index = arrayPtr->getNextNode(); + index->setName("index"); + + InsertPointGuard guard{m_builder}; + m_builder.SetInsertPoint(llvm::BasicBlock::Create(m_builder.getContext(), {}, func)); + auto dataPtr = m_builder.CreateStructGEP(arrayPtr, 0, "dataPtr"); + auto data = m_builder.CreateLoad(dataPtr, "data"); + auto valuePtr = m_builder.CreateGEP(data, index, "valuePtr"); + auto value = m_builder.CreateLoad(valuePtr, "value"); + m_builder.CreateRet(value); + return func; +} + +llvm::Function* Array::createFreeFunc() +{ + auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, m_array->getType(), false), llvm::Function::PrivateLinkage, "array.free", getModule()); + func->setDoesNotThrow(); + func->setDoesNotCapture(1); + + auto freeFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::BytePtr, false), llvm::Function::ExternalLinkage, "ext_free", getModule()); + freeFunc->setDoesNotThrow(); + freeFunc->setDoesNotCapture(1); + + auto arrayPtr = &func->getArgumentList().front(); + arrayPtr->setName("arrayPtr"); + + InsertPointGuard guard{m_builder}; + m_builder.SetInsertPoint(llvm::BasicBlock::Create(m_builder.getContext(), {}, func)); + auto dataPtr = m_builder.CreateStructGEP(arrayPtr, 0, "dataPtr"); + auto data = m_builder.CreateLoad(dataPtr, "data"); + auto mem = m_builder.CreateBitCast(data, Type::BytePtr, "mem"); + m_builder.CreateCall(freeFunc, mem); + m_builder.CreateRetVoid(); + return func; +} + +Array::Array(llvm::IRBuilder<>& _builder, char const* _name) : + CompilerHelper(_builder), + m_pushFunc([this](){ return createArrayPushFunc(); }), + m_setFunc([this](){ return createArraySetFunc(); }), + m_getFunc([this](){ return createArrayGetFunc(); }), + m_freeFunc([this](){ return createFreeFunc(); }) +{ + llvm::Type* elementTys[] = {Type::WordPtr, Type::Size, Type::Size}; + static auto arrayTy = llvm::StructType::create(elementTys, "Array"); + + m_array = m_builder.CreateAlloca(arrayTy, nullptr, _name); + m_builder.CreateStore(llvm::ConstantAggregateZero::get(arrayTy), m_array); +} + +void Array::pop(llvm::Value* _count) +{ + auto sizePtr = m_builder.CreateStructGEP(m_array, 1, "sizePtr"); + auto size = m_builder.CreateLoad(sizePtr, "size"); + auto newSize = m_builder.CreateNUWSub(size, _count, "newSize"); + m_builder.CreateStore(newSize, sizePtr); +} + +llvm::Value* Array::size() +{ + auto sizePtr = m_builder.CreateStructGEP(m_array, 1, "sizePtr"); + return m_builder.CreateLoad(sizePtr, "array.size"); +} + +} +} +} + +namespace +{ + struct AllocatedMemoryWatchdog + { + std::set allocatedMemory; + + ~AllocatedMemoryWatchdog() + { + if (!allocatedMemory.empty()) + DLOG(mem) << allocatedMemory.size() << " MEM LEAKS!\n"; + } + }; + + AllocatedMemoryWatchdog watchdog; +} + +extern "C" +{ + using namespace dev::eth::jit; + + EXPORT void* ext_realloc(void* _data, size_t _size) + { + //std::cerr << "REALLOC: " << _data << " [" << _size << "]" << std::endl; + auto newData = std::realloc(_data, _size); + if (_data != newData) + { + DLOG(mem) << "REALLOC: " << _data << " -> " << newData << " [" << _size << "]\n"; + watchdog.allocatedMemory.erase(_data); + watchdog.allocatedMemory.insert(newData); + } + return newData; + } + + EXPORT void ext_free(void* _data) + { + std::free(_data); + if (_data) + { + DLOG(mem) << "FREE : " << _data << "\n"; + watchdog.allocatedMemory.erase(_data); + } + } + +} // extern "C" + diff --git a/libevmjit/Array.h b/libevmjit/Array.h new file mode 100644 index 000000000..cadeab7c9 --- /dev/null +++ b/libevmjit/Array.h @@ -0,0 +1,62 @@ +#pragma once + +#include + +#include "CompilerHelper.h" + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +class LazyFunction +{ +public: + using Creator = std::function; + + LazyFunction(Creator _creator) : + m_creator(_creator) + {} + + llvm::Value* call(llvm::IRBuilder<>& _builder, std::initializer_list const& _args); + +private: + llvm::Function* m_func = nullptr; + Creator m_creator; +}; + +class Array : public CompilerHelper +{ +public: + Array(llvm::IRBuilder<>& _builder, char const* _name); + + void push(llvm::Value* _value) { m_pushFunc.call(m_builder, {m_array, _value}); } + void set(llvm::Value* _index, llvm::Value* _value) { m_setFunc.call(m_builder, {m_array, _index, _value}); } + llvm::Value* get(llvm::Value* _index) { return m_getFunc.call(m_builder, {m_array, _index}); } + void pop(llvm::Value* _count); + llvm::Value* size(); + void free() { m_freeFunc.call(m_builder, {m_array}); } + + llvm::Value* getPointerTo() const { return m_array; } + +private: + llvm::Value* m_array = nullptr; + + LazyFunction m_pushFunc; + LazyFunction m_setFunc; + LazyFunction m_getFunc; + LazyFunction m_freeFunc; + + llvm::Function* createArrayPushFunc(); + llvm::Function* createArraySetFunc(); + llvm::Function* createArrayGetFunc(); + llvm::Function* createFreeFunc(); +}; + +} +} +} + + diff --git a/libevmjit/Stack.cpp b/libevmjit/Stack.cpp index dd279ec7b..85bd98fdd 100644 --- a/libevmjit/Stack.cpp +++ b/libevmjit/Stack.cpp @@ -17,171 +17,6 @@ namespace eth namespace jit { -static const auto c_reallocStep = 1; -static const auto c_reallocMultipier = 2; - -llvm::Value* LazyFunction::call(llvm::IRBuilder<>& _builder, std::initializer_list const& _args) -{ - if (!m_func) - m_func = m_creator(); - - return _builder.CreateCall(m_func, {_args.begin(), _args.size()}); -} - -llvm::Function* Array::createArrayPushFunc() -{ - llvm::Type* argTypes[] = {m_array->getType(), Type::Word}; - auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::PrivateLinkage, "array.push", getModule()); - func->setDoesNotThrow(); - func->setDoesNotCapture(1); - - llvm::Type* reallocArgTypes[] = {Type::BytePtr, Type::Size}; - auto reallocFunc = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, reallocArgTypes, false), llvm::Function::ExternalLinkage, "ext_realloc", getModule()); - reallocFunc->setDoesNotThrow(); - reallocFunc->setDoesNotAlias(0); - reallocFunc->setDoesNotCapture(1); - - auto arrayPtr = &func->getArgumentList().front(); - arrayPtr->setName("arrayPtr"); - auto value = arrayPtr->getNextNode(); - value->setName("value"); - - InsertPointGuard guard{m_builder}; - auto entryBB = llvm::BasicBlock::Create(m_builder.getContext(), "Entry", func); - auto reallocBB = llvm::BasicBlock::Create(m_builder.getContext(), "Realloc", func); - auto pushBB = llvm::BasicBlock::Create(m_builder.getContext(), "Push", func); - - m_builder.SetInsertPoint(entryBB); - auto dataPtr = m_builder.CreateStructGEP(arrayPtr, 0, "dataPtr"); - auto sizePtr = m_builder.CreateStructGEP(arrayPtr, 1, "sizePtr"); - auto capPtr = m_builder.CreateStructGEP(arrayPtr, 2, "capPtr"); - auto data = m_builder.CreateLoad(dataPtr, "data"); - auto size = m_builder.CreateLoad(sizePtr, "size"); - auto cap = m_builder.CreateLoad(capPtr, "cap"); - auto reallocReq = m_builder.CreateICmpEQ(cap, size, "reallocReq"); - m_builder.CreateCondBr(reallocReq, reallocBB, pushBB); - - m_builder.SetInsertPoint(reallocBB); - auto newCap = m_builder.CreateNUWAdd(cap, m_builder.getInt64(c_reallocStep), "newCap"); - //newCap = m_builder.CreateNUWMul(newCap, m_builder.getInt64(c_reallocMultipier)); - auto reallocSize = m_builder.CreateShl(newCap, 5, "reallocSize"); // size in bytes: newCap * 32 - auto bytes = m_builder.CreateBitCast(data, Type::BytePtr, "bytes"); - auto newBytes = m_builder.CreateCall2(reallocFunc, bytes, reallocSize, "newBytes"); - auto newData = m_builder.CreateBitCast(newBytes, Type::WordPtr, "newData"); - m_builder.CreateStore(newData, dataPtr); - m_builder.CreateStore(newCap, capPtr); - m_builder.CreateBr(pushBB); - - m_builder.SetInsertPoint(pushBB); - auto dataPhi = m_builder.CreatePHI(Type::WordPtr, 2, "dataPhi"); - dataPhi->addIncoming(data, entryBB); - dataPhi->addIncoming(newData, reallocBB); - auto newElemPtr = m_builder.CreateGEP(dataPhi, size, "newElemPtr"); - m_builder.CreateStore(value, newElemPtr); - auto newSize = m_builder.CreateNUWAdd(size, m_builder.getInt64(1), "newSize"); - m_builder.CreateStore(newSize, sizePtr); - m_builder.CreateRetVoid(); - - return func; -} - -llvm::Function* Array::createArraySetFunc() -{ - llvm::Type* argTypes[] = {m_array->getType(), Type::Size, Type::Word}; - auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::PrivateLinkage, "array.set", getModule()); - func->setDoesNotThrow(); - func->setDoesNotCapture(1); - - auto arrayPtr = &func->getArgumentList().front(); - arrayPtr->setName("arrayPtr"); - auto index = arrayPtr->getNextNode(); - index->setName("index"); - auto value = index->getNextNode(); - value->setName("value"); - - InsertPointGuard guard{m_builder}; - m_builder.SetInsertPoint(llvm::BasicBlock::Create(m_builder.getContext(), {}, func)); - auto dataPtr = m_builder.CreateStructGEP(arrayPtr, 0, "dataPtr"); - auto data = m_builder.CreateLoad(dataPtr, "data"); - auto valuePtr = m_builder.CreateGEP(data, index, "valuePtr"); - m_builder.CreateStore(value, valuePtr); - m_builder.CreateRetVoid(); - return func; -} - -llvm::Function* Array::createArrayGetFunc() -{ - llvm::Type* argTypes[] = {m_array->getType(), Type::Size}; - auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Word, argTypes, false), llvm::Function::PrivateLinkage, "array.get", getModule()); - func->setDoesNotThrow(); - func->setDoesNotCapture(1); - - auto arrayPtr = &func->getArgumentList().front(); - arrayPtr->setName("arrayPtr"); - auto index = arrayPtr->getNextNode(); - index->setName("index"); - - InsertPointGuard guard{m_builder}; - m_builder.SetInsertPoint(llvm::BasicBlock::Create(m_builder.getContext(), {}, func)); - auto dataPtr = m_builder.CreateStructGEP(arrayPtr, 0, "dataPtr"); - auto data = m_builder.CreateLoad(dataPtr, "data"); - auto valuePtr = m_builder.CreateGEP(data, index, "valuePtr"); - auto value = m_builder.CreateLoad(valuePtr, "value"); - m_builder.CreateRet(value); - return func; -} - -llvm::Function* Array::createFreeFunc() -{ - auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, m_array->getType(), false), llvm::Function::PrivateLinkage, "array.free", getModule()); - func->setDoesNotThrow(); - func->setDoesNotCapture(1); - - auto freeFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::BytePtr, false), llvm::Function::ExternalLinkage, "ext_free", getModule()); - freeFunc->setDoesNotThrow(); - freeFunc->setDoesNotCapture(1); - - auto arrayPtr = &func->getArgumentList().front(); - arrayPtr->setName("arrayPtr"); - - InsertPointGuard guard{m_builder}; - m_builder.SetInsertPoint(llvm::BasicBlock::Create(m_builder.getContext(), {}, func)); - auto dataPtr = m_builder.CreateStructGEP(arrayPtr, 0, "dataPtr"); - auto data = m_builder.CreateLoad(dataPtr, "data"); - auto mem = m_builder.CreateBitCast(data, Type::BytePtr, "mem"); - m_builder.CreateCall(freeFunc, mem); - m_builder.CreateRetVoid(); - return func; -} - -Array::Array(llvm::IRBuilder<>& _builder, char const* _name) : - CompilerHelper(_builder), - m_pushFunc([this](){ return createArrayPushFunc(); }), - m_setFunc([this](){ return createArraySetFunc(); }), - m_getFunc([this](){ return createArrayGetFunc(); }), - m_freeFunc([this](){ return createFreeFunc(); }) -{ - llvm::Type* elementTys[] = {Type::WordPtr, Type::Size, Type::Size}; - static auto arrayTy = llvm::StructType::create(elementTys, "Array"); - - m_array = m_builder.CreateAlloca(arrayTy, nullptr, _name); - m_builder.CreateStore(llvm::ConstantAggregateZero::get(arrayTy), m_array); -} - -void Array::pop(llvm::Value* _count) -{ - auto sizePtr = m_builder.CreateStructGEP(m_array, 1, "sizePtr"); - auto size = m_builder.CreateLoad(sizePtr, "size"); - auto newSize = m_builder.CreateNUWSub(size, _count, "newSize"); - m_builder.CreateStore(newSize, sizePtr); -} - -llvm::Value* Array::size() -{ - auto sizePtr = m_builder.CreateStructGEP(m_array, 1, "sizePtr"); - return m_builder.CreateLoad(sizePtr, "array.size"); -} - Stack::Stack(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager): CompilerHelper(_builder), m_runtimeManager(_runtimeManager), @@ -344,22 +179,6 @@ void Stack::push(llvm::Value* _value) } } -namespace -{ - struct AllocatedMemoryWatchdog - { - std::set allocatedMemory; - - ~AllocatedMemoryWatchdog() - { - if (!allocatedMemory.empty()) - DLOG(mem) << allocatedMemory.size() << " MEM LEAKS!\n"; - } - }; - - AllocatedMemoryWatchdog watchdog; -} - extern "C" { using namespace dev::eth::jit; @@ -386,28 +205,5 @@ extern "C" } } - EXPORT void* ext_realloc(void* _data, size_t _size) - { - //std::cerr << "REALLOC: " << _data << " [" << _size << "]" << std::endl; - auto newData = std::realloc(_data, _size); - if (_data != newData) - { - DLOG(mem) << "REALLOC: " << _data << " -> " << newData << " [" << _size << "]\n"; - watchdog.allocatedMemory.erase(_data); - watchdog.allocatedMemory.insert(newData); - } - return newData; - } - - EXPORT void ext_free(void* _data) - { - std::free(_data); - if (_data) - { - DLOG(mem) << "FREE : " << _data << "\n"; - watchdog.allocatedMemory.erase(_data); - } - } - } // extern "C" diff --git a/libevmjit/Stack.h b/libevmjit/Stack.h index ac64d427e..3c526f0d3 100644 --- a/libevmjit/Stack.h +++ b/libevmjit/Stack.h @@ -2,7 +2,7 @@ #include -#include "CompilerHelper.h" +#include "Array.h" namespace dev { @@ -12,50 +12,6 @@ namespace jit { class RuntimeManager; -class LazyFunction -{ -public: - using Creator = std::function; - - LazyFunction(Creator _creator) : - m_creator(_creator) - {} - - llvm::Value* call(llvm::IRBuilder<>& _builder, std::initializer_list const& _args); - -private: - llvm::Function* m_func = nullptr; - Creator m_creator; -}; - -class Array : public CompilerHelper -{ -public: - Array(llvm::IRBuilder<>& _builder, char const* _name); - - void push(llvm::Value* _value) { m_pushFunc.call(m_builder, {m_array, _value}); } - void set(llvm::Value* _index, llvm::Value* _value) { m_setFunc.call(m_builder, {m_array, _index, _value}); } - llvm::Value* get(llvm::Value* _index) { return m_getFunc.call(m_builder, {m_array, _index}); } - void pop(llvm::Value* _count); - llvm::Value* size(); - void free() { m_freeFunc.call(m_builder, {m_array}); } - - llvm::Value* getPointerTo() const { return m_array; } - -private: - llvm::Value* m_array = nullptr; - - LazyFunction m_pushFunc; - LazyFunction m_setFunc; - LazyFunction m_getFunc; - LazyFunction m_freeFunc; - - llvm::Function* createArrayPushFunc(); - llvm::Function* createArraySetFunc(); - llvm::Function* createArrayGetFunc(); - llvm::Function* createFreeFunc(); -}; - class Stack : public CompilerHelper { public: