diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index bb4d65971..aa7202634 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -502,6 +502,14 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::BALANCE: + { + auto address = stack.pop(); + auto value = ext.balance(address); + stack.push(value); + break; + } + case Instruction::CALLER: { auto value = ext.caller(); diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index e3bb17af6..6ae84a286 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -3,6 +3,7 @@ #include #include +#include #include "Utils.h" @@ -15,6 +16,7 @@ using namespace llvm; using llvm::types::i; using Linkage = llvm::GlobalValue::LinkageTypes; +using dev::h256; namespace evmcc { @@ -69,6 +71,8 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) m_store = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_store", module); m_setStore = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_setStore", module); m_calldataload = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_calldataload", module); + m_balance = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_balance", module); + m_bswap = Intrinsic::getDeclaration(module, Intrinsic::bswap, i256Ty); m_builder.CreateCall(m_init, m_data); } @@ -107,6 +111,19 @@ Value* Ext::calldataload(Value* _index) return m_builder.CreateLoad(m_args[1]); } +Value* Ext::bswap(Value* _value) +{ + return m_builder.CreateCall(m_bswap, _value); +} + +Value* Ext::balance(Value* _address) +{ + auto address = bswap(_address); // to BigEndian // TODO: I don't get it. It seems not needed + m_builder.CreateStore(address, m_args[0]); + m_builder.CreateCall(m_balance, m_args); + return m_builder.CreateLoad(m_args[1]); +} + extern "C" { @@ -145,6 +162,12 @@ EXPORT void ext_calldataload(i256* _index, i256* _value) // TODO: It all can be done by adding padding to data or by using min() algorithm without branch } +EXPORT void ext_balance(h256* _address, i256* _value) +{ + auto u = g_ext->balance(dev::right160(*_address)); + *_value = eth2llvm(u); +} + } } diff --git a/evmcc/Ext.h b/evmcc/Ext.h index 8c08acdfe..138028927 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -26,11 +26,14 @@ public: llvm::Value* calldatasize(); llvm::Value* gasprice(); + llvm::Value* balance(llvm::Value* _address); llvm::Value* calldataload(llvm::Value* _index); private: llvm::Value* getDataElem(unsigned _index, const llvm::Twine& _name = ""); + llvm::Value* bswap(llvm::Value*); + private: llvm::IRBuilder<>& m_builder; @@ -40,6 +43,8 @@ private: llvm::Function* m_store; llvm::Function* m_setStore; llvm::Function* m_calldataload; + llvm::Function* m_balance; + llvm::Function* m_bswap; }; diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/bytecode/ext_test.evm index 5bcc94ba1..cdd04807f 100644 --- a/evmcc/bytecode/ext_test.evm +++ b/evmcc/bytecode/ext_test.evm @@ -1 +1 @@ -30333234363a600035602635601335380060016002f2 +3031333234363a600035602635601335380060016002f2 diff --git a/evmcc/lll/ext_test.lll b/evmcc/lll/ext_test.lll index f32bfb440..b0f3a4adb 100644 --- a/evmcc/lll/ext_test.lll +++ b/evmcc/lll/ext_test.lll @@ -1,6 +1,7 @@ (asm ADDRESS +BALANCE CALLER ORIGIN CALLVALUE