From 7f8848744df95ad5d4351e4936a46ec04a1c8e75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 9 Oct 2014 09:33:31 +0200 Subject: [PATCH] EXP instruction. [Delivers #79736422] --- evmcc/Compiler.cpp | 9 +++++++++ evmcc/Ext.cpp | 18 ++++++++++++++++++ evmcc/Ext.h | 2 ++ evmcc/bytecode/arithmetic_test.evm | 2 +- evmcc/lll/arithmetic_test.lll | 8 ++++++++ 5 files changed, 38 insertions(+), 1 deletion(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index c46dd72c5..880487705 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -274,6 +274,15 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::EXP: + { + auto left = stack.pop(); + auto right = stack.pop(); + auto ret = ext.exp(left, right); + stack.push(ret); + break; + } + case Instruction::NEG: { auto top = stack.pop(); diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 8266bd728..121103354 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -93,6 +93,7 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) m_call = Function::Create(FunctionType::get(m_builder.getVoidTy(), args, false), Linkage::ExternalLinkage, "ext_call", module); m_bswap = Intrinsic::getDeclaration(module, Intrinsic::bswap, i256Ty); m_sha3 = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_sha3", module); + m_exp = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_exp", module); m_builder.CreateCall(m_init, m_data); @@ -196,6 +197,15 @@ llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize) return hash; } +llvm::Value* Ext::exp(llvm::Value* _left, llvm::Value* _right) +{ + m_builder.CreateStore(_left, m_args[0]); + m_builder.CreateStore(_right, m_arg2); + llvm::Value* args[] = {m_args[0], m_arg2, m_args[1]}; + m_builder.CreateCall(m_exp, args); + return m_builder.CreateLoad(m_args[1]); +} + extern "C" { @@ -308,6 +318,14 @@ EXPORT void ext_sha3(i256* _inOff, i256* _inSize, i256* _ret) *_ret = *reinterpret_cast(&hash); } +EXPORT void ext_exp(i256* _left, i256* _right, i256* _ret) +{ + dev::bigint left = llvm2eth(*_left); + dev::bigint right = llvm2eth(*_right); + auto ret = static_cast(boost::multiprecision::powm(left, right, dev::bigint(2) << 256)); + *_ret = eth2llvm(ret); +} + } } diff --git a/evmcc/Ext.h b/evmcc/Ext.h index 7801d0540..302991854 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -39,6 +39,7 @@ public: llvm::Value* call(llvm::Value* _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize); llvm::Value* sha3(llvm::Value* _inOff, llvm::Value* _inSize); + llvm::Value* exp(llvm::Value* _left, llvm::Value* _right); private: llvm::Value* getDataElem(unsigned _index, const llvm::Twine& _name = ""); @@ -66,6 +67,7 @@ private: llvm::Function* m_call; llvm::Function* m_bswap; llvm::Function* m_sha3; + llvm::Function* m_exp; }; diff --git a/evmcc/bytecode/arithmetic_test.evm b/evmcc/bytecode/arithmetic_test.evm index 67e86b310..c7a029f52 100644 --- a/evmcc/bytecode/arithmetic_test.evm +++ b/evmcc/bytecode/arithmetic_test.evm @@ -1 +1 @@ -60016001900160070260050160029004600490066021900560150160030260059007600303 +60016001900160070260050160029004600490066021900560150160030260059007600303600960110860005460086000f2 diff --git a/evmcc/lll/arithmetic_test.lll b/evmcc/lll/arithmetic_test.lll index e2c14d4c7..4757a7420 100644 --- a/evmcc/lll/arithmetic_test.lll +++ b/evmcc/lll/arithmetic_test.lll @@ -26,4 +26,12 @@ SWAP1 SMOD;; 3 3 SUB ;; 0 +9 +17 +EXP ;; 17^9 +0 +MSTORE +8 +0 +RETURN ) \ No newline at end of file