diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 38adffd3f9..ea6bf531af 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -39,11 +39,6 @@ Ext::Ext(RuntimeManager& _runtimeManager, Memory& _memoryMan): using Linkage = llvm::GlobalValue::LinkageTypes; - llvm::Type* argsTypes[] = {Type::EnvPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr}; - - m_sload = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "env_sload", module); - m_sstore = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "env_sstore", module); - llvm::Type* sha3ArgsTypes[] = {Type::BytePtr, Type::Size, Type::WordPtr}; m_sha3 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, sha3ArgsTypes, false), Linkage::ExternalLinkage, "env_sha3", module); @@ -64,20 +59,47 @@ Ext::Ext(RuntimeManager& _runtimeManager, Memory& _memoryMan): m_calldataload = llvm::Function::Create(llvm::FunctionType::get(Type::Void, callDataLoadArgsTypes, false), Linkage::ExternalLinkage, "ext_calldataload", module); } -llvm::Function* Ext::getBalanceFunc() + +using FuncDesc = std::tuple; + +llvm::FunctionType* getFunctionType(llvm::Type* _returnType, std::initializer_list const& _argsTypes) { - if (!m_balance) + return llvm::FunctionType::get(_returnType, llvm::ArrayRef{_argsTypes.begin(), _argsTypes.size()}, false); +} + +std::array::value> const& getEnvFuncDescs() +{ + static std::array::value> descs{{ + FuncDesc{"env_sload", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})}, + FuncDesc{"env_sstore", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})}, + FuncDesc{"env_balance", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})}, + }}; + + return descs; +} + +llvm::Function* createFunc(EnvFunc _id, llvm::Module* _module) +{ + auto&& desc = getEnvFuncDescs()[static_cast(_id)]; + return llvm::Function::Create(std::get<1>(desc), llvm::Function::ExternalLinkage, std::get<0>(desc), _module); +} + +template +llvm::CallInst* Ext::createCall(EnvFunc _funcId, _Args*... _args) +{ + auto& func = m_funcs[static_cast(_funcId)]; + if (!func) { - llvm::Type* argsTypes[] = {Type::EnvPtr, Type::WordPtr, Type::WordPtr}; - m_balance = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argsTypes, false), llvm::Function::ExternalLinkage, "env_balance", getModule()); + func = createFunc(_funcId, getModule()); } - return m_balance; + llvm::Value* args[] = {_args...}; + return getBuilder().CreateCall(func, args); } llvm::Value* Ext::sload(llvm::Value* _index) { m_builder.CreateStore(_index, m_args[0]); - m_builder.CreateCall3(m_sload, getRuntimeManager().getEnvPtr(), m_args[0], m_args[1]); // Uses native endianness + createCall(EnvFunc::sload, getRuntimeManager().getEnvPtr(), m_args[0], m_args[1]); // Uses native endianness return m_builder.CreateLoad(m_args[1]); } @@ -85,7 +107,7 @@ void Ext::sstore(llvm::Value* _index, llvm::Value* _value) { m_builder.CreateStore(_index, m_args[0]); m_builder.CreateStore(_value, m_args[1]); - m_builder.CreateCall3(m_sstore, getRuntimeManager().getEnvPtr(), m_args[0], m_args[1]); // Uses native endianness + createCall(EnvFunc::sstore, getRuntimeManager().getEnvPtr(), m_args[0], m_args[1]); // Uses native endianness } llvm::Value* Ext::calldataload(llvm::Value* _index) @@ -100,7 +122,7 @@ llvm::Value* Ext::balance(llvm::Value* _address) { auto address = Endianness::toBE(m_builder, _address); m_builder.CreateStore(address, m_args[0]); - createCall(getBalanceFunc(), getRuntimeManager().getEnvPtr(), m_args[0], m_args[1]); + createCall(EnvFunc::balance, getRuntimeManager().getEnvPtr(), m_args[0], m_args[1]); return m_builder.CreateLoad(m_args[1]); } diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index be71dc1ffb..964198e5d6 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -18,6 +18,21 @@ struct MemoryRef llvm::Value* size; }; +template +struct sizeOf +{ + static const size_t value = static_cast(_EnumT::_size); +}; + +enum class EnvFunc +{ + sload, + sstore, + balance, + + _size +}; + class Ext : public RuntimeHelper { public: @@ -49,8 +64,6 @@ private: llvm::Value* m_arg8; llvm::Value* m_size; llvm::Value* m_data = nullptr; - llvm::Function* m_sload; - llvm::Function* m_sstore; llvm::Function* m_calldataload; llvm::Function* m_balance = nullptr; llvm::Function* m_create; @@ -59,7 +72,12 @@ private: llvm::Function* m_getExtCode; llvm::Function* m_log; - llvm::Function* getBalanceFunc(); + std::array::value> m_funcs = {}; + + template + llvm::CallInst* createCall(EnvFunc _funcId, _Args*... _args); + + using CompilerHelper::createCall; };