diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index ab16c50f1..00f2fb00b 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -247,6 +247,22 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) break; } + case Instruction::SLOAD: + { + auto index = stack.pop(); + auto value = ext.store(index); + stack.push(value); + break; + } + + case Instruction::SSTORE: + { + auto index = stack.pop(); + auto value = stack.pop(); + ext.setStore(index, value); + break; + } + } } diff --git a/evmcc/Ext.cpp b/evmcc/Ext.cpp index 1384694be..35606f67f 100644 --- a/evmcc/Ext.cpp +++ b/evmcc/Ext.cpp @@ -4,6 +4,8 @@ #include #include +#include "Utils.h" + #ifdef _MSC_VER #define EXPORT __declspec(dllexport) #else @@ -30,21 +32,42 @@ Ext::Ext(llvm::IRBuilder<>& _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); + m_args[0] = m_builder.CreateAlloca(m_builder.getIntNTy(256), nullptr, "ext.index"); + m_args[1] = m_builder.CreateAlloca(m_builder.getIntNTy(256), nullptr, "ext.value"); + + 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); } -extern "C" +llvm::Value* Ext::store(llvm::Value* _index) { + m_builder.CreateStore(_index, m_args[0]); + m_builder.CreateCall(m_store, m_args); + return m_builder.CreateLoad(m_args[1]); +} -EXPORT void ext_store(void* _index, void* _value) +void Ext::setStore(llvm::Value* _index, llvm::Value* _value) { - + m_builder.CreateStore(_index, m_args[0]); + m_builder.CreateStore(_value, m_args[1]); + m_builder.CreateCall(m_setStore, m_args); } -EXPORT void ext_setStore(void* _index, void* _value) +extern "C" { +EXPORT void ext_store(i256* _index, i256* _value) +{ + auto index = llvm2eth(*_index); + auto value = g_ext->store(index); + *_value = eth2llvm(value); +} + +EXPORT void ext_setStore(i256* _index, i256* _value) +{ + auto index = llvm2eth(*_index); + auto value = llvm2eth(*_value); + g_ext->setStore(index, value); } } diff --git a/evmcc/Ext.h b/evmcc/Ext.h index f1c88d849..4de1c6645 100644 --- a/evmcc/Ext.h +++ b/evmcc/Ext.h @@ -1,4 +1,6 @@ +#pragma once + #include #include @@ -14,8 +16,15 @@ public: Ext(llvm::IRBuilder<>& _builder); static void init(std::unique_ptr _ext); + llvm::Value* store(llvm::Value* _index); + void setStore(llvm::Value* _index, llvm::Value* _value); + private: llvm::IRBuilder<>& m_builder; + + llvm::Value* m_args[2]; + llvm::Function* m_store; + llvm::Function* m_setStore; }; diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index aa02a846e..877b192d9 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -9,6 +9,8 @@ #include +#include "Utils.h" + #ifdef _MSC_VER #define EXPORT __declspec(dllexport) #else @@ -18,15 +20,6 @@ namespace evmcc { -struct i256 -{ - uint64_t a; - uint64_t b; - uint64_t c; - uint64_t d; -}; -static_assert(sizeof(i256) == 32, "Wrong i265 size"); - using StackImpl = std::vector; diff --git a/evmcc/Utils.cpp b/evmcc/Utils.cpp new file mode 100644 index 000000000..cef08a283 --- /dev/null +++ b/evmcc/Utils.cpp @@ -0,0 +1,34 @@ + +#include "Utils.h" + +namespace evmcc +{ + +dev::u256 llvm2eth(i256 _i) +{ + dev::u256 u = 0; + u |= _i.d; + u <<= 64; + u |= _i.c; + u <<= 64; + u |= _i.b; + u <<= 64; + u |= _i.a; + return u; +} + +i256 eth2llvm(dev::u256 _u) +{ + i256 i; + dev::u256 mask = 0xFFFFFFFFFFFFFFFF; + i.a = static_cast(_u & mask); + _u >>= 64; + i.b = static_cast(_u & mask); + _u >>= 64; + i.c = static_cast(_u & mask); + _u >>= 64; + i.d = static_cast(_u & mask); + return i; +} + +} \ No newline at end of file diff --git a/evmcc/Utils.h b/evmcc/Utils.h new file mode 100644 index 000000000..065698448 --- /dev/null +++ b/evmcc/Utils.h @@ -0,0 +1,24 @@ + +#pragma once + +#include + +#include + +namespace evmcc +{ + +/// Representation of 256-bit value binary compatible with LLVM i256 +struct i256 +{ + uint64_t a; + uint64_t b; + uint64_t c; + uint64_t d; +}; +static_assert(sizeof(i256) == 32, "Wrong i265 size"); + +dev::u256 llvm2eth(i256); +i256 eth2llvm(dev::u256); + +} \ No newline at end of file diff --git a/evmcc/bytecode/store_test.evm b/evmcc/bytecode/store_test.evm new file mode 100644 index 000000000..54c9419b5 --- /dev/null +++ b/evmcc/bytecode/store_test.evm @@ -0,0 +1 @@ +607b607c60015760005760015660005603 diff --git a/evmcc/lll/stack_test.lll b/evmcc/lll/stack_test.lll index e6581563c..fdf83594c 100644 --- a/evmcc/lll/stack_test.lll +++ b/evmcc/lll/stack_test.lll @@ -1,24 +1,8 @@ (asm -60666666666606 -7077777777777707 -DUP1 -DUP3 -DUP1 -DUP5 -DUP2 -DUP5 -POP -POP -POP -POP -POP -POP -POP -1111 -2222 -DUP2 -DUP2 -SWAP3 -SWAP1 +123 +SSTORE +SLOAD +123 +SUB ) \ No newline at end of file diff --git a/evmcc/lll/store_test.lll b/evmcc/lll/store_test.lll new file mode 100644 index 000000000..c40471c40 --- /dev/null +++ b/evmcc/lll/store_test.lll @@ -0,0 +1,14 @@ + +(asm +123 +124 +1 +SSTORE +0 +SSTORE +1 +SLOAD +0 +SLOAD +SUB +) \ No newline at end of file diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index d10235ee3..7959c5a1b 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -23,13 +23,17 @@ + + + + {D51A4898-BD9E-4961-BCAE-1FE7F854BB4D} diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index 7b0ee824a..99c43b89b 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -6,11 +6,15 @@ + + + + \ No newline at end of file