From b42ecc34a1a56d12eed9ed2ae1ffce332feb305c Mon Sep 17 00:00:00 2001 From: Tim Hughes Date: Sat, 27 Sep 2014 13:20:19 +0100 Subject: [PATCH 1/9] Fixed size_t to bool warning and internal compiler error with MSVC. --- eth/main.cpp | 8 +++++++- libwebthree/WebThree.h | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/eth/main.cpp b/eth/main.cpp index a9ea43f14..03be8b969 100644 --- a/eth/main.cpp +++ b/eth/main.cpp @@ -300,7 +300,13 @@ int main(int argc, char** argv) cout << credits(); NetworkPreferences netPrefs(listenPort, publicIP, upnp, useLocal); - dev::WebThreeDirect web3("Ethereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), dbPath, false, mode == NodeMode::Full ? set{"eth", "shh"} : set{}, netPrefs); + dev::WebThreeDirect web3( + "Ethereum(++)/" + clientName + "v" + dev::Version + "/" DEV_QUOTED(ETH_BUILD_TYPE) "/" DEV_QUOTED(ETH_BUILD_PLATFORM), + dbPath, + false, + mode == NodeMode::Full ? set{"eth", "shh"} : set(), + netPrefs + ); web3.setIdealPeerCount(peers); eth::Client* c = mode == NodeMode::Full ? web3.ethereum() : nullptr; diff --git a/libwebthree/WebThree.h b/libwebthree/WebThree.h index 06717ee26..cae6fd6f8 100644 --- a/libwebthree/WebThree.h +++ b/libwebthree/WebThree.h @@ -93,7 +93,7 @@ public: void connect(std::string const& _seedHost, unsigned short _port = 30303); /// Is the network subsystem up? - bool haveNetwork() { return peerCount(); } + bool haveNetwork() { return peerCount() != 0; } /// Save peers dev::bytes savePeers(); From e37fd01bc694df11f402c13ccdf0cf51ff0f6848 Mon Sep 17 00:00:00 2001 From: Tim Hughes Date: Sat, 27 Sep 2014 13:23:02 +0100 Subject: [PATCH 2/9] Suppress warnings from boost mpl during moc compile. --- alethzero/MainWin.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/alethzero/MainWin.h b/alethzero/MainWin.h index ce1a9b670..7aee0c376 100644 --- a/alethzero/MainWin.h +++ b/alethzero/MainWin.h @@ -21,6 +21,9 @@ #pragma once +#ifdef Q_MOC_RUN +#define BOOST_MPL_IF_HPP_INCLUDED +#endif #include #include From 2908e7706f2f9319d6b1647a087fbba4e373ecc2 Mon Sep 17 00:00:00 2001 From: Tim Hughes Date: Sat, 27 Sep 2014 13:23:19 +0100 Subject: [PATCH 3/9] Update MSVC projects. --- libdevcore/_libdevcore.cpp | 2 ++ windows/Alethzero.vcxproj | 3 ++- windows/Alethzero.vcxproj.filters | 2 ++ windows/LibEthereum.vcxproj | 30 ++++++++++++++++++++++++++++- windows/LibEthereum.vcxproj.filters | 27 ++++++++++++++++++++++++++ 5 files changed, 62 insertions(+), 2 deletions(-) diff --git a/libdevcore/_libdevcore.cpp b/libdevcore/_libdevcore.cpp index 4160a7602..1b34a5911 100644 --- a/libdevcore/_libdevcore.cpp +++ b/libdevcore/_libdevcore.cpp @@ -6,5 +6,7 @@ #include "FixedHash.cpp" #include "Guards.cpp" #include "Log.cpp" +#include "RangeMask.cpp" #include "RLP.cpp" +#include "Worker.cpp" #endif diff --git a/windows/Alethzero.vcxproj b/windows/Alethzero.vcxproj index d418e5d03..38dbd6265 100644 --- a/windows/Alethzero.vcxproj +++ b/windows/Alethzero.vcxproj @@ -176,6 +176,7 @@ + @@ -307,4 +308,4 @@ - + \ No newline at end of file diff --git a/windows/Alethzero.vcxproj.filters b/windows/Alethzero.vcxproj.filters index e8f008522..ef47bdba0 100644 --- a/windows/Alethzero.vcxproj.filters +++ b/windows/Alethzero.vcxproj.filters @@ -11,6 +11,7 @@ + @@ -31,5 +32,6 @@ Windows + \ No newline at end of file diff --git a/windows/LibEthereum.vcxproj b/windows/LibEthereum.vcxproj index 134171843..db1362363 100644 --- a/windows/LibEthereum.vcxproj +++ b/windows/LibEthereum.vcxproj @@ -49,12 +49,24 @@ true true + + true + true + true + true + true true true true + + true + true + true + true + @@ -90,6 +102,7 @@ + @@ -159,6 +172,7 @@ true + true true @@ -223,6 +237,12 @@ true true + + true + true + true + true + true true @@ -235,6 +255,12 @@ true true + + true + true + true + true + @@ -289,6 +315,7 @@ + @@ -376,6 +403,7 @@ true true + true true @@ -527,4 +555,4 @@ - + \ No newline at end of file diff --git a/windows/LibEthereum.vcxproj.filters b/windows/LibEthereum.vcxproj.filters index b6e2dc070..848b8308d 100644 --- a/windows/LibEthereum.vcxproj.filters +++ b/windows/LibEthereum.vcxproj.filters @@ -178,6 +178,18 @@ libethereum + + libdevcore + + + libdevcore + + + libethereum + + + libwebthree + @@ -390,6 +402,18 @@ libethereum + + libdevcore + + + libdevcore + + + libethereum + + + libwebthree + @@ -422,5 +446,8 @@ {36748e80-c977-4fee-84e6-699c039dff87} + + {d838fece-fc20-42f6-bff5-97c236159b80} + \ No newline at end of file From a9bdd81d49afa84168157a0ca60f6067d68a7dd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 29 Sep 2014 17:17:39 +0200 Subject: [PATCH 4/9] PUSH instruction implementation --- evmcc/Compiler.cpp | 123 +++++++++++++++++++++-------------- evmcc/bytecode/push_test.evm | 1 + evmcc/lll/push_test.lll | 35 ++++++++++ 3 files changed, 110 insertions(+), 49 deletions(-) create mode 100644 evmcc/bytecode/push_test.evm create mode 100644 evmcc/lll/push_test.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 4c3a8a5f2..854492ee3 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -3,6 +3,8 @@ #include +#include + #include "Stack.h" namespace evmcc @@ -37,64 +39,87 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) using namespace llvm; auto& context = getGlobalContext(); - auto module = std::make_unique("main", context); IRBuilder<> builder(context); - // Create globals for memory, memory size, stack and stack top - auto memory = new GlobalVariable(*module, Types.word8ptr, false, - GlobalValue::LinkageTypes::PrivateLinkage, - Constant::getNullValue(Types.word8ptr), "memory"); - auto memSize = new GlobalVariable(*module, Types.size, false, - GlobalValue::LinkageTypes::PrivateLinkage, - ConstantInt::get(Types.size, 0), "memsize"); - auto stack2 = new GlobalVariable(*module, Types.word256arr, false, - GlobalValue::LinkageTypes::PrivateLinkage, - ConstantAggregateZero::get(Types.word256arr), "stack"); - auto stackTop2 = new GlobalVariable(*module, Types.size, false, - GlobalValue::LinkageTypes::PrivateLinkage, - ConstantInt::get(Types.size, 0), "stackTop"); - - // Create value for void* malloc(size_t) - auto mallocVal = Function::Create(FunctionType::get(Types.word8ptr, { Types.size }, false), - GlobalValue::LinkageTypes::ExternalLinkage, "malloc", module.get()); - // Create main function - FunctionType* funcType = FunctionType::get(llvm::Type::getInt32Ty(context), false); - Function* mainFunc = Function::Create(funcType, Function::ExternalLinkage, "main", module.get()); + auto mainFuncType = FunctionType::get(llvm::Type::getInt32Ty(context), false); + auto mainFunc = Function::Create(mainFuncType, Function::ExternalLinkage, "main", module.get()); - BasicBlock* entryBlock = BasicBlock::Create(context, "entry", mainFunc); + auto entryBlock = BasicBlock::Create(context, "entry", mainFunc); builder.SetInsertPoint(entryBlock); - // Initialize memory with call to malloc, update memsize - std::vector mallocMemArgs = { ConstantInt::get(Types.size, 100) }; - auto mallocMemCall = builder.CreateCall(mallocVal, mallocMemArgs, "malloc_mem"); - builder.CreateStore(mallocMemCall, memory); - builder.CreateStore(ConstantInt::get(Types.size, 100), memSize); - + // Init stack auto stack = Stack(builder, module.get()); - uint64_t words[] = { 1, 2, 3, 4 }; - auto val = llvm::APInt(256, 4, words); - auto c = ConstantInt::get(Types.word256, val); - - stack.push(c); - stack.push(ConstantInt::get(Types.word256, 0x1122334455667788)); - - auto top = stack.top(); - stack.push(top); // dup - - stack.pop(); - - - /* - std::vector mallocStackArgs = { ConstantInt::get(sizeTy, 200) }; - auto mallocStackCall = builder.CreateCall(mallocVal, mallocStackArgs, "malloc_stack"); - auto mallocCast = builder.CreatePointerBitCastOrAddrSpaceCast(mallocStackCall, int256ptr); - builder.CreateStore(mallocCast, stackVal); - */ - - builder.CreateRet(ConstantInt::get(Type::getInt32Ty(context), 13)); + for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc) + { + using dev::eth::Instruction; + + auto inst = static_cast(*pc); + switch (inst) + { + case Instruction::PUSH1: + case Instruction::PUSH2: + case Instruction::PUSH3: + case Instruction::PUSH4: + case Instruction::PUSH5: + case Instruction::PUSH6: + case Instruction::PUSH7: + case Instruction::PUSH8: + case Instruction::PUSH9: + case Instruction::PUSH10: + case Instruction::PUSH11: + case Instruction::PUSH12: + case Instruction::PUSH13: + case Instruction::PUSH14: + case Instruction::PUSH15: + case Instruction::PUSH16: + case Instruction::PUSH17: + case Instruction::PUSH18: + case Instruction::PUSH19: + case Instruction::PUSH20: + case Instruction::PUSH21: + case Instruction::PUSH22: + case Instruction::PUSH23: + case Instruction::PUSH24: + case Instruction::PUSH25: + case Instruction::PUSH26: + case Instruction::PUSH27: + case Instruction::PUSH28: + case Instruction::PUSH29: + case Instruction::PUSH30: + case Instruction::PUSH31: + case Instruction::PUSH32: + { + auto numBytes = static_cast(inst) - static_cast(Instruction::PUSH1) + 1; + auto value = llvm::APInt(256, 0); + for (decltype(numBytes) i = 0; i < numBytes; ++i) // TODO: Use pc as iterator + { + ++pc; + value <<= 8; + value |= *pc; + } + auto c = builder.getInt(value); + stack.push(c); + break; + } + } + } + + //uint64_t words[] = { 1, 2, 3, 4 }; + //auto val = llvm::APInt(256, 4, words); + //auto c = ConstantInt::get(Types.word256, val); + + //stack.push(c); + //stack.push(ConstantInt::get(Types.word256, 0x1122334455667788)); + + //auto top = stack.top(); + //stack.push(top); // dup + + //stack.pop(); + + builder.CreateRet(ConstantInt::get(Type::getInt32Ty(context), 0)); return module; } diff --git a/evmcc/bytecode/push_test.evm b/evmcc/bytecode/push_test.evm new file mode 100644 index 000000000..d624cee1d --- /dev/null +++ b/evmcc/bytecode/push_test.evm @@ -0,0 +1 @@ +60656107d26204a0c763026921f4640bc5588eb165372d0f1dca6e661ba1d901961c71670c55f7bc23038e3868056bc75e2d630fffff69021e19e0c9bab24000016a085d1c6e8050f0ea1c71bd6b0688be36543f3c36e638e37a6c03d41f73d55d0d482ae55555376dc76810d0fe03c91964d31c71c6f46e615dd0360c07d931663b14e38e38b16f2da3f99955a3adcf27ebb1caaaaaaa6e7014ccba6a8bb1ed35bd86bf065c71c71c2b7109491c5d4781b79c9009de6bfb8e38e38de8720414a0f6fdec81304d4c563e740bffffffffa573118427b3b4a05bc8a8a4de8459868000000000017406eb15e7331e727940d4ac54b7cdca1c71c71c71bd750567a91c9fefc96ebaa626a22f98c5e638e38e38e37a76032abd16c5b68006e15d5aa307e383f4e55555555555377701a6427bdc4f0d58eab5f48a3ec67f64e21c71c71c71c6f478080dd0a0c9b9ff2c2a0c740b06853a0a980ee38e38e38e38b17903c679cb5e8f2f9cb3b5d6652b0e7334f746faaaaaaaaaaaaa6e7a01b873815917ebb2bf3b890a1af495d6235bae3c71c71c71c71c2b7b07ae4cca96e1a55dfa49c85ad3c3e60e426b92fb8e38e38e38e38de87c036018bf074e292bcc7d6c8bea0f9699443046178bffffffffffffffa57d0e7d34c64a9c85d4460dbbca87196b61618a4bd2168000000000000000017e05b901f48a5b994d6572502bc4ea43140486666416aa1c71c71c71c71c71bd7f047889870c178fc477414ea231d70467a388fffe31b4e638e38e38e38e38e37a diff --git a/evmcc/lll/push_test.lll b/evmcc/lll/push_test.lll new file mode 100644 index 000000000..832daaec1 --- /dev/null +++ b/evmcc/lll/push_test.lll @@ -0,0 +1,35 @@ + +(asm +101 ;; PUSH1 +2002 ;; PUSH2 +303303 ;; PUSH3 +40444404 ;; PUSH4 +50555555505 ;; PUSH5 +60666666666606 +7777777777777777 +888888888888888888 +99999999999999999999 +10000000000000000000001 +10111111111111111111111101 +2022222222222222222222222202 +303333333333333333333333333303 +4044444444444444444444444444444404 +505555555555555555555555555555555505 +60666666666666666666666666666666666606 +7077777777777777777777777777777777777707 +808888888888888888888888888888888888888808 +90999999999999999999999999999999999999999909 +100000000000000000000000000000000000000000000001 +10111111111111111111111111111111111111111111111101 +2022222222222222222222222222222222222222222222222202 +303333333333333333333333333333333333333333333333333303 +40444444444444444444444444444444444444444444444444444404 +50555555555555555555555555555555555555555555555555555555505 +6066666666666666666666666666666666666666666666666666666666606 +707777777777777777777777777777777777777777777777777777777777707 +808888888888888888888888888888888888888888888888888888888888888808 +90999999999999999999999999999999999999999999999999999999999999999909 +100000000000000000000000000000000000000000000000000000000000000000000001 +10111111111111111111111111111111111111111111111111111111111111111111111101 +2022222222222222222222222222222222222222222222222222222222222222222222222202 ;; PUSH32 +) \ No newline at end of file From 646f954ac6985d22d37eceb37a4b139cfd868309 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 30 Sep 2014 09:32:53 +0200 Subject: [PATCH 5/9] POP and DUP* instructions --- evmcc/Compiler.cpp | 42 +++++++++++++++++++++++++---------- evmcc/Stack.cpp | 37 ++++++++++++++++++------------ evmcc/Stack.h | 5 +++-- evmcc/bytecode/stack_test.evm | 1 + evmcc/lll/stack_test.lll | 22 ++++++++++++++++++ 5 files changed, 79 insertions(+), 28 deletions(-) create mode 100644 evmcc/bytecode/stack_test.evm create mode 100644 evmcc/lll/stack_test.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 854492ee3..454c61450 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -59,6 +59,12 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto inst = static_cast(*pc); switch (inst) { + case Instruction::POP: + { + stack.pop(); + break; + } + case Instruction::PUSH1: case Instruction::PUSH2: case Instruction::PUSH3: @@ -104,20 +110,32 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) stack.push(c); break; } - } - } - - //uint64_t words[] = { 1, 2, 3, 4 }; - //auto val = llvm::APInt(256, 4, words); - //auto c = ConstantInt::get(Types.word256, val); - //stack.push(c); - //stack.push(ConstantInt::get(Types.word256, 0x1122334455667788)); - - //auto top = stack.top(); - //stack.push(top); // dup + case Instruction::DUP1: + case Instruction::DUP2: + case Instruction::DUP3: + case Instruction::DUP4: + case Instruction::DUP5: + case Instruction::DUP6: + case Instruction::DUP7: + case Instruction::DUP8: + case Instruction::DUP9: + case Instruction::DUP10: + case Instruction::DUP11: + case Instruction::DUP12: + case Instruction::DUP13: + case Instruction::DUP14: + case Instruction::DUP15: + case Instruction::DUP16: + { + auto index = static_cast(inst) - static_cast(Instruction::DUP1); + auto value = stack.get(index); + stack.push(value); + break; + } - //stack.pop(); + } + } builder.CreateRet(ConstantInt::get(Type::getInt32Ty(context), 0)); diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index d23456de6..4c5a19e8a 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -47,12 +47,14 @@ Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module) m_stackPush = llvm::Function::Create(funcType, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_push", _module); - m_stackTop = llvm::Function::Create(funcType, - llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_top", _module); - m_stackPop = llvm::Function::Create(funcType, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_pop", _module); + llvm::Type* getArgsTypes[] = {stackPtrTy, m_builder.getInt32Ty(), i256PtrTy}; + auto getFuncType = llvm::FunctionType::get(voidTy, getArgsTypes); + m_stackGet = llvm::Function::Create(getFuncType, + llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_get", _module); + m_args[0] = m_builder.CreateCall(stackCreate, "stack.ptr"); m_args[1] = m_builder.CreateAlloca(i256Ty, nullptr, "stack.val"); } @@ -65,20 +67,27 @@ void Stack::push(llvm::Value* _value) } -llvm::Value* Stack::top() +llvm::Value* Stack::pop() { - m_builder.CreateCall(m_stackTop, m_args); + m_builder.CreateCall(m_stackPop, m_args); return m_builder.CreateLoad(m_args[1]); } -llvm::Value* Stack::pop() +llvm::Value* Stack::get(uint32_t _index) { - m_builder.CreateCall(m_stackPop, m_args); + llvm::Value* args[] = {m_args[0], m_builder.getInt32(_index), m_args[1]}; + m_builder.CreateCall(m_stackGet, args); return m_builder.CreateLoad(m_args[1]); } +llvm::Value* Stack::top() +{ + return get(0); +} + + void debugStack(const char* op, const i256& word) { std::cerr << "STACK " << std::setw(4) << std::setfill(' ') << op << ": " @@ -114,24 +123,24 @@ EXPORT void evmccrt_stack_push(void* _stack, void* _pWord) stack->push_back(*word); } -EXPORT void evmccrt_stack_top(void* _stack, void* _pWord) +EXPORT void evmccrt_stack_pop(void* _stack, void* _pWord) { auto stack = static_cast(_stack); assert(!stack->empty()); auto word = &stack->back(); - debugStack("top", *word); + debugStack("pop", *word); auto outWord = static_cast(_pWord); + stack->pop_back(); *outWord = *word; } -EXPORT void evmccrt_stack_pop(void* _stack, void* _pWord) +EXPORT void evmccrt_stack_get(void* _stack, uint32_t _index, void* _pWord) { auto stack = static_cast(_stack); - assert(!stack->empty()); - auto word = &stack->back(); - debugStack("pop", *word); + assert(_index < stack->size()); + auto word = &(*stack)[stack->size() - _index - 1]; + debugStack("get", *word); auto outWord = static_cast(_pWord); - stack->pop_back(); *outWord = *word; } diff --git a/evmcc/Stack.h b/evmcc/Stack.h index e8b6a8e2d..e4d93bd8c 100644 --- a/evmcc/Stack.h +++ b/evmcc/Stack.h @@ -12,15 +12,16 @@ public: Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module); void push(llvm::Value* _value); - llvm::Value* top(); llvm::Value* pop(); + llvm::Value* top(); + llvm::Value* get(uint32_t _index); private: llvm::IRBuilder<>& m_builder; llvm::Value* m_args[2]; llvm::Function* m_stackPush; - llvm::Function* m_stackTop; llvm::Function* m_stackPop; + llvm::Function* m_stackGet; }; } \ No newline at end of file diff --git a/evmcc/bytecode/stack_test.evm b/evmcc/bytecode/stack_test.evm new file mode 100644 index 000000000..6eba9fdca --- /dev/null +++ b/evmcc/bytecode/stack_test.evm @@ -0,0 +1 @@ +65372d0f1dca6e661925338e3e5c2b808280848184505050505050506104576108ae8182 diff --git a/evmcc/lll/stack_test.lll b/evmcc/lll/stack_test.lll new file mode 100644 index 000000000..0edf06624 --- /dev/null +++ b/evmcc/lll/stack_test.lll @@ -0,0 +1,22 @@ + +(asm +60666666666606 +7077777777777707 +DUP1 +DUP3 +DUP1 +DUP5 +DUP2 +DUP5 +POP +POP +POP +POP +POP +POP +POP +1111 +2222 +DUP2 +DUP3 +) \ No newline at end of file From 2eabdb0ceda6891ca2dad79801461f22570562a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 30 Sep 2014 10:05:43 +0200 Subject: [PATCH 6/9] SWAP* instructions --- evmcc/Compiler.cpp | 25 ++++++++++++++++++++ evmcc/Stack.cpp | 43 ++++++++++++++++++++++++++--------- evmcc/Stack.h | 2 ++ evmcc/bytecode/stack_test.evm | 2 +- evmcc/lll/stack_test.lll | 4 +++- 5 files changed, 63 insertions(+), 13 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 454c61450..0b1793244 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -134,6 +134,31 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::SWAP1: + case Instruction::SWAP2: + case Instruction::SWAP3: + case Instruction::SWAP4: + case Instruction::SWAP5: + case Instruction::SWAP6: + case Instruction::SWAP7: + case Instruction::SWAP8: + case Instruction::SWAP9: + case Instruction::SWAP10: + case Instruction::SWAP11: + case Instruction::SWAP12: + case Instruction::SWAP13: + case Instruction::SWAP14: + case Instruction::SWAP15: + case Instruction::SWAP16: + { + auto index = static_cast(inst) - static_cast(Instruction::SWAP1) + 1; + auto loValue = stack.get(index); + auto hiValue = stack.get(0); + stack.set(index, hiValue); + stack.set(0, loValue); + break; + } + } } diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index 4c5a19e8a..f0af2087a 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -55,6 +55,9 @@ Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module) m_stackGet = llvm::Function::Create(getFuncType, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_get", _module); + m_stackSet = llvm::Function::Create(getFuncType, + llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_set", _module); + m_args[0] = m_builder.CreateCall(stackCreate, "stack.ptr"); m_args[1] = m_builder.CreateAlloca(i256Ty, nullptr, "stack.val"); } @@ -82,24 +85,33 @@ llvm::Value* Stack::get(uint32_t _index) } +void Stack::set(uint32_t _index, llvm::Value* _value) +{ + m_builder.CreateStore(_value, m_args[1]); // copy value to memory + llvm::Value* args[] = {m_args[0], m_builder.getInt32(_index), m_args[1]}; + m_builder.CreateCall(m_stackSet, args); +} + + llvm::Value* Stack::top() { return get(0); } -void debugStack(const char* op, const i256& word) +void debugStack(const char* _op, const i256& _word, uint32_t _index = 0) { - std::cerr << "STACK " << std::setw(4) << std::setfill(' ') << op << ": " - << std::dec << word.a - << " HEX: " << std::hex << std::setfill('0'); - if (word.b || word.c || word.d) + std::cerr << "STACK " << std::setw(4) << std::setfill(' ') << _op + << " [" << std::setw(2) << std::setfill('0') << _index << "] " + << std::dec << _word.a + << " HEX: " << std::hex; + if (_word.b || _word.c || _word.d) { - std::cerr << std::setw(16) << word.d << " " - << std::setw(16) << word.c << " " - << std::setw(16) << word.b << " "; + std::cerr << std::setw(16) << _word.d << " " + << std::setw(16) << _word.c << " " + << std::setw(16) << _word.b << " "; } - std::cerr << std::setw(16) << word.a << "\n"; + std::cerr << std::setw(16) << _word.a << "\n"; } } @@ -138,10 +150,19 @@ EXPORT void evmccrt_stack_get(void* _stack, uint32_t _index, void* _pWord) { auto stack = static_cast(_stack); assert(_index < stack->size()); - auto word = &(*stack)[stack->size() - _index - 1]; - debugStack("get", *word); + auto word = stack->rbegin() + _index; + debugStack("get", *word, _index); auto outWord = static_cast(_pWord); *outWord = *word; } +EXPORT void evmccrt_stack_set(void* _stack, uint32_t _index, void* _pWord) +{ + auto stack = static_cast(_stack); + auto word = static_cast(_pWord); + assert(_index < stack->size()); + *(stack->rbegin() + _index) = *word; + debugStack("set", *word, _index); +} + } // extern "C" diff --git a/evmcc/Stack.h b/evmcc/Stack.h index e4d93bd8c..a25de56e6 100644 --- a/evmcc/Stack.h +++ b/evmcc/Stack.h @@ -15,6 +15,7 @@ public: llvm::Value* pop(); llvm::Value* top(); llvm::Value* get(uint32_t _index); + void set(uint32_t _index, llvm::Value* _value); private: llvm::IRBuilder<>& m_builder; @@ -22,6 +23,7 @@ private: llvm::Function* m_stackPush; llvm::Function* m_stackPop; llvm::Function* m_stackGet; + llvm::Function* m_stackSet; }; } \ No newline at end of file diff --git a/evmcc/bytecode/stack_test.evm b/evmcc/bytecode/stack_test.evm index 6eba9fdca..02417c967 100644 --- a/evmcc/bytecode/stack_test.evm +++ b/evmcc/bytecode/stack_test.evm @@ -1 +1 @@ -65372d0f1dca6e661925338e3e5c2b808280848184505050505050506104576108ae8182 +65372d0f1dca6e661925338e3e5c2b808280848184505050505050506104576108ae81819290 diff --git a/evmcc/lll/stack_test.lll b/evmcc/lll/stack_test.lll index 0edf06624..e6581563c 100644 --- a/evmcc/lll/stack_test.lll +++ b/evmcc/lll/stack_test.lll @@ -18,5 +18,7 @@ POP 1111 2222 DUP2 -DUP3 +DUP2 +SWAP3 +SWAP1 ) \ No newline at end of file From 4ec1ebc82cc5d3c63fe29489e9f0ffc56fd84701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 30 Sep 2014 11:26:58 +0200 Subject: [PATCH 7/9] Basic arithmetic, limited precision for MUL, DIV and MOD. --- evmcc/Compiler.cpp | 83 ++++++++++++++++++++++++++++++ evmcc/bytecode/arithmetic_test.evm | 1 + evmcc/bytecode/fib1.evm | 1 + evmcc/lll/arithmetic_test.lll | 29 +++++++++++ evmcc/lll/fib1.lll | 57 ++++++++++++++++++++ 5 files changed, 171 insertions(+) create mode 100644 evmcc/bytecode/arithmetic_test.evm create mode 100644 evmcc/bytecode/fib1.evm create mode 100644 evmcc/lll/arithmetic_test.lll create mode 100644 evmcc/lll/fib1.lll diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 0b1793244..3cd12833f 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -19,6 +19,7 @@ struct llvm::Type* word256arr; llvm::Type* size; llvm::Type* Void; + llvm::Type* WordLowPrecision; } Types; Compiler::Compiler() @@ -31,6 +32,9 @@ Compiler::Compiler() Types.word256arr = llvm::ArrayType::get(Types.word256, 100); Types.size = llvm::Type::getInt64Ty(context); Types.Void = llvm::Type::getVoidTy(context); + + // TODO: Use 64-bit for now. In 128-bit compiler-rt library functions are required + Types.WordLowPrecision = llvm::Type::getIntNTy(context, 64); } @@ -59,6 +63,85 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto inst = static_cast(*pc); switch (inst) { + + case Instruction::ADD: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto result = builder.CreateAdd(lhs, rhs); + stack.push(result); + break; + } + + case Instruction::SUB: + { + auto lhs = stack.pop(); + auto rhs = stack.pop(); + auto result = builder.CreateSub(lhs, rhs); + stack.push(result); + break; + } + + case Instruction::MUL: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto res128 = builder.CreateMul(lhs128, rhs128); + auto res256 = builder.CreateZExt(res128, Types.word256); + stack.push(res256); + break; + } + + case Instruction::DIV: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto res128 = builder.CreateUDiv(lhs128, rhs128); + auto res256 = builder.CreateZExt(res128, Types.word256); + stack.push(res256); + break; + } + + case Instruction::SDIV: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto res128 = builder.CreateSDiv(lhs128, rhs128); + auto res256 = builder.CreateSExt(res128, Types.word256); + stack.push(res256); + break; + } + + case Instruction::MOD: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto res128 = builder.CreateURem(lhs128, rhs128); + auto res256 = builder.CreateZExt(res128, Types.word256); + stack.push(res256); + break; + } + + case Instruction::SMOD: + { + auto lhs256 = stack.pop(); + auto rhs256 = stack.pop(); + auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto res128 = builder.CreateSRem(lhs128, rhs128); + auto res256 = builder.CreateSExt(res128, Types.word256); + stack.push(res256); + break; + } + case Instruction::POP: { stack.pop(); diff --git a/evmcc/bytecode/arithmetic_test.evm b/evmcc/bytecode/arithmetic_test.evm new file mode 100644 index 000000000..67e86b310 --- /dev/null +++ b/evmcc/bytecode/arithmetic_test.evm @@ -0,0 +1 @@ +60016001900160070260050160029004600490066021900560150160030260059007600303 diff --git a/evmcc/bytecode/fib1.evm b/evmcc/bytecode/fib1.evm new file mode 100644 index 000000000..4c141314e --- /dev/null +++ b/evmcc/bytecode/fib1.evm @@ -0,0 +1 @@ +60016001818101818101818101818101818101818101818101818101818101818101818101818101818101818101818101818101818101 diff --git a/evmcc/lll/arithmetic_test.lll b/evmcc/lll/arithmetic_test.lll new file mode 100644 index 000000000..e2c14d4c7 --- /dev/null +++ b/evmcc/lll/arithmetic_test.lll @@ -0,0 +1,29 @@ + +(asm +1 +1 +SWAP1 +ADD ;; 2 +7 +MUL ;; 14 +5 +ADD ;; 19 +2 +SWAP1 +DIV ;; 9 +4 +SWAP1 +MOD ;; 1 +33 +SWAP1 +SDIV;; 0 +21 +ADD ;; 21 +3 +MUL ;; 63 +5 +SWAP1 +SMOD;; 3 +3 +SUB ;; 0 +) \ No newline at end of file diff --git a/evmcc/lll/fib1.lll b/evmcc/lll/fib1.lll new file mode 100644 index 000000000..286bed275 --- /dev/null +++ b/evmcc/lll/fib1.lll @@ -0,0 +1,57 @@ +;; Fibbonacci unrolled + +(asm +1 +1 +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +DUP2 +DUP2 +ADD +) \ No newline at end of file From 72bb2d3e0cdbfb0aed369c1f022496992e66ab6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 30 Sep 2014 11:27:53 +0200 Subject: [PATCH 8/9] Fix stack set/get bad function signature --- evmcc/Stack.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index f0af2087a..aa02a846e 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -51,7 +51,7 @@ Stack::Stack(llvm::IRBuilder<>& _builder, llvm::Module* _module) llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_pop", _module); llvm::Type* getArgsTypes[] = {stackPtrTy, m_builder.getInt32Ty(), i256PtrTy}; - auto getFuncType = llvm::FunctionType::get(voidTy, getArgsTypes); + auto getFuncType = llvm::FunctionType::get(voidTy, getArgsTypes, false); m_stackGet = llvm::Function::Create(getFuncType, llvm::GlobalValue::LinkageTypes::ExternalLinkage, "evmccrt_stack_get", _module); From 6eab61a1aed3c03b2f5b9a157e25f64ed814aadc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 30 Sep 2014 17:11:50 +0200 Subject: [PATCH 9/9] Starting ExtVM binary interface --- evmcc/Compiler.cpp | 3 ++ evmcc/ExecutionEngine.cpp | 5 ++++ evmcc/Ext.cpp | 52 +++++++++++++++++++++++++++++++++++ evmcc/Ext.h | 22 +++++++++++++++ windows/evmcc.vcxproj | 6 ++-- windows/evmcc.vcxproj.filters | 2 ++ 6 files changed, 88 insertions(+), 2 deletions(-) create mode 100644 evmcc/Ext.cpp create mode 100644 evmcc/Ext.h diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 3cd12833f..4237b59aa 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -6,6 +6,7 @@ #include #include "Stack.h" +#include "Ext.h" namespace evmcc { @@ -56,6 +57,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) // Init stack auto stack = Stack(builder, module.get()); + auto ext = Ext(builder); + for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc) { using dev::eth::Instruction; diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index e59d6024a..3b3205af4 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -13,6 +13,8 @@ #include #include +#include "Ext.h" + namespace evmcc { @@ -66,6 +68,9 @@ int ExecutionEngine::run(std::unique_ptr _module) _module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module exec->finalizeObject(); + auto ext = std::make_unique(); + Ext::init(std::move(ext)); + auto entryFunc = module->getFunction("main"); if (!entryFunc) { diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp new file mode 100644 index 000000000..1384694be --- /dev/null +++ b/evmcc/Ext.cpp @@ -0,0 +1,52 @@ + +#include "Ext.h" + +#include +#include + +#ifdef _MSC_VER +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +using namespace llvm; +using llvm::types::i; +using Linkage = llvm::GlobalValue::LinkageTypes; + +namespace evmcc +{ + +std::unique_ptr g_ext; + +void Ext::init(std::unique_ptr _ext) +{ + g_ext = std::move(_ext); +} + +Ext::Ext(llvm::IRBuilder<>& _builder) + : m_builder(_builder) +{ + auto module = m_builder.GetInsertBlock()->getParent()->getParent(); + auto&& ctx = _builder.getContext(); + + Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_store", module); + Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_setStore", module); +} + +extern "C" +{ + +EXPORT void ext_store(void* _index, void* _value) +{ + +} + +EXPORT void ext_setStore(void* _index, void* _value) +{ + +} + +} + +} \ No newline at end of file diff --git a/evmcc/Ext.h b/evmcc/Ext.h new file mode 100644 index 000000000..f1c88d849 --- /dev/null +++ b/evmcc/Ext.h @@ -0,0 +1,22 @@ + +#include + +#include + +namespace evmcc +{ + + + +class Ext +{ +public: + Ext(llvm::IRBuilder<>& _builder); + static void init(std::unique_ptr _ext); + +private: + llvm::IRBuilder<>& m_builder; +}; + + +} \ No newline at end of file diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index 3a1869cd5..d10235ee3 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -22,11 +22,13 @@ + + @@ -136,8 +138,8 @@ Console true - ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;%(AdditionalLibraryDirectories) - LibEthereum.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) + ../../builds/llvm3.5/Debug/lib;../../_build/LibEthereum/x64_Debug;../../_build/LibSecp256k1/x64_Debug;../../_build/LibCryptoPP/x64_Debug;%(AdditionalLibraryDirectories) + LibEthereum.lib;LibSecp256k1.lib;LibCryptoPP.lib;LLVMX86Disassembler.lib;LLVMX86AsmParser.lib;LLVMX86CodeGen.lib;LLVMSelectionDAG.lib;LLVMAsmPrinter.lib;LLVMCodeGen.lib;LLVMScalarOpts.lib;LLVMInstCombine.lib;LLVMTransformUtils.lib;LLVMipa.lib;LLVMAnalysis.lib;LLVMX86Desc.lib;LLVMX86Info.lib;LLVMX86AsmPrinter.lib;LLVMX86Utils.lib;LLVMMCJIT.lib;LLVMTarget.lib;LLVMRuntimeDyld.lib;LLVMObject.lib;LLVMMCParser.lib;LLVMBitReader.lib;LLVMExecutionEngine.lib;LLVMMC.lib;LLVMCore.lib;LLVMSupport.lib;%(AdditionalDependencies) diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index 7db055ebf..7b0ee824a 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -5,10 +5,12 @@ + + \ No newline at end of file