From 3942b2ed2899773f1d170de77966bbbdf3911efe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 3 Oct 2014 13:19:35 +0200 Subject: [PATCH] CREATE instruction. Still needs some work with ExtVM interface. [#79510898] --- evmcc/Compiler.cpp | 11 +++++++++++ evmcc/Ext.cpp | 39 ++++++++++++++++++++++++++++++++++++- evmcc/Ext.h | 4 ++++ evmcc/bytecode/ext_test.evm | 2 +- evmcc/lll/ext_test.lll | 7 +++++++ 5 files changed, 61 insertions(+), 2 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 0c0076a80..acb7be26d 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -712,6 +712,17 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) stack.push(value); break; } + + case Instruction::CREATE: + { + auto endowment = stack.pop(); + auto initOff = stack.pop(); + auto initSize = stack.pop(); + + auto address = ext.create(endowment, initOff, initSize); + stack.push(address); + break; + } case Instruction::RETURN: { diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 0ec9c532a..4ef0dc3f8 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -17,6 +17,7 @@ using namespace llvm; using llvm::types::i; using Linkage = llvm::GlobalValue::LinkageTypes; using dev::h256; +using dev::u256; namespace evmcc { @@ -52,6 +53,8 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* module) auto i256Ty = m_builder.getIntNTy(256); m_args[0] = m_builder.CreateAlloca(i256Ty, nullptr, "ext.index"); m_args[1] = m_builder.CreateAlloca(i256Ty, nullptr, "ext.value"); + m_arg2 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg2"); + m_arg3 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg3"); Type* elements[] = { i256Ty, // i256 address; @@ -77,8 +80,10 @@ Ext::Ext(llvm::IRBuilder<>& _builder, llvm::Module* 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_create = Function::Create(TypeBuilder*, i<256>*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_create", module); m_bswap = Intrinsic::getDeclaration(module, Intrinsic::bswap, i256Ty); + m_builder.CreateCall(m_init, m_data); } @@ -129,12 +134,24 @@ Value* Ext::bswap(Value* _value) Value* Ext::balance(Value* _address) { - auto address = bswap(_address); // to BigEndian // TODO: I don't get it. It seems not needed + auto address = bswap(_address); // to BE m_builder.CreateStore(address, m_args[0]); m_builder.CreateCall(m_balance, m_args); return m_builder.CreateLoad(m_args[1]); } +Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize) +{ + m_builder.CreateStore(_endowment, m_args[0]); + m_builder.CreateStore(_initOff, m_arg2); + m_builder.CreateStore(_initSize, m_arg3); + Value* args[] = {m_args[0], m_arg2, m_arg3, m_args[1]}; + m_builder.CreateCall(m_create, args); + Value* address = m_builder.CreateLoad(m_args[1]); + address = bswap(address); // to LE + return address; +} + extern "C" { @@ -186,6 +203,26 @@ EXPORT void ext_balance(h256* _address, i256* _value) *_value = eth2llvm(u); } +EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256* _address) +{ + auto&& ext = Runtime::getExt(); + auto endowment = llvm2eth(*_endowment); + auto initOff = static_cast(llvm2eth(*_initOff)); + auto initSize = static_cast(llvm2eth(*_initSize)); + + if (ext.balance(ext.myAddress) >= endowment) + { + ext.subBalance(endowment); + u256 gas; // TODO: Handle gas + auto&& initRef = dev::bytesConstRef(Runtime::getMemory().data() + initOff, initSize); + auto&& onOp = dev::bytesConstRef(); // TODO: Handle that thing + h256 address = ext.create(endowment, &gas, initRef, onOp); + *_address = address; + } + else + *_address = {}; +} + } } diff --git a/evmcc/Ext.h b/evmcc/Ext.h index c44e5899b..aa6016253 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -34,6 +34,7 @@ public: llvm::Value* balance(llvm::Value* _address); llvm::Value* calldataload(llvm::Value* _index); + llvm::Value* create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize); private: llvm::Value* getDataElem(unsigned _index, const llvm::Twine& _name = ""); @@ -44,12 +45,15 @@ private: llvm::IRBuilder<>& m_builder; llvm::Value* m_args[2]; + llvm::Value* m_arg2; + llvm::Value* m_arg3; llvm::Value* m_data; llvm::Function* m_init; llvm::Function* m_store; llvm::Function* m_setStore; llvm::Function* m_calldataload; llvm::Function* m_balance; + llvm::Function* m_create; llvm::Function* m_bswap; }; diff --git a/evmcc/bytecode/ext_test.evm b/evmcc/bytecode/ext_test.evm index d1e373df0..97ef267d6 100644 --- a/evmcc/bytecode/ext_test.evm +++ b/evmcc/bytecode/ext_test.evm @@ -1 +1 @@ -5a3031333234363a4041424344455a36600035602635601335380060016002f2 +5a3031333234363a4041424344455a36600035602635601335387f1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff600054602060006000f00060016002f2 diff --git a/evmcc/lll/ext_test.lll b/evmcc/lll/ext_test.lll index 1a1dde653..60a8bc332 100644 --- a/evmcc/lll/ext_test.lll +++ b/evmcc/lll/ext_test.lll @@ -23,6 +23,13 @@ CALLDATALOAD 19 CALLDATALOAD CODESIZE +0x1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff +0 +MSTORE +32 +0 +0 +CREATE STOP 1 2