diff --git a/libevm/ExtVMFace.h b/libevm/ExtVMFace.h index 1b0f9eaf5..eeae720f3 100644 --- a/libevm/ExtVMFace.h +++ b/libevm/ExtVMFace.h @@ -57,37 +57,37 @@ public: ExtVMFace(Address _myAddress, Address _caller, Address _origin, u256 _value, u256 _gasPrice, bytesConstRef _data, bytesConstRef _code, BlockInfo const& _previousBlock, BlockInfo const& _currentBlock, unsigned _depth); /// Get the code at the given location in code ROM. - byte getCode(u256 _n) const { return _n < code.size() ? code[(unsigned)_n] : 0; } + virtual byte getCode(u256 _n) const { return _n < code.size() ? code[(unsigned)_n] : 0; } /// Read storage location. - u256 store(u256) { return 0; } + virtual u256 store(u256) { return 0; } /// Write a value in storage. - void setStore(u256, u256) {} + virtual void setStore(u256, u256) {} /// Read address's balance. - u256 balance(Address) { return 0; } + virtual u256 balance(Address) { return 0; } /// Read address's code. - bytes const& codeAt(Address) { return NullBytes; } + virtual bytes const& codeAt(Address) { return NullBytes; } /// Subtract amount from account's balance. - void subBalance(u256) {} + virtual void subBalance(u256) {} /// Determine account's TX count. - u256 txCount(Address) { return 0; } + virtual u256 txCount(Address) { return 0; } /// Suicide the associated contract and give proceeds to the given address. - void suicide(Address) { suicides.insert(myAddress); } + virtual void suicide(Address) { suicides.insert(myAddress); } /// Create a new (contract) account. - h160 create(u256, u256*, bytesConstRef, bytesConstRef) { return h160(); } + virtual h160 create(u256, u256*, bytesConstRef, bytesConstRef) { return h160(); } /// Make a new message call. - bool call(Address, u256, bytesConstRef, u256*, bytesRef, OnOpFunc const&, Address, Address) { return false; } + virtual bool call(Address, u256, bytesConstRef, u256*, bytesRef, OnOpFunc const&, Address, Address) { return false; } /// Revert any changes made (by any of the other calls). - void revert() {} + virtual void revert() {} Address myAddress; ///< Address associated with executing code (a contract, or contract-to-be). Address caller; ///< Address which sent the message (either equal to origin or a contract). diff --git a/libevmjit/BasicBlock.cpp b/libevmjit/BasicBlock.cpp index 02c85165d..736e0a572 100644 --- a/libevmjit/BasicBlock.cpp +++ b/libevmjit/BasicBlock.cpp @@ -32,6 +32,7 @@ BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc) : void BasicBlock::Stack::push(llvm::Value* _value) { + assert(_value->getType() == Type::i256); m_backend.push_back(_value); } diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index f3e912125..34970c602 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -15,6 +15,7 @@ #include "Ext.h" #include "GasMeter.h" #include "Utils.h" +#include "Endianness.h" namespace dev { @@ -420,21 +421,11 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, const auto byteNum = stack.pop(); auto value = stack.pop(); - /* - if (byteNum < 32) - use select - { - value <<= byteNum*8 - value >>= 31*8 - push value - } - else push 0 - */ - - // TODO: Shifting by 0 gives wrong results as of this bug http://llvm.org/bugs/show_bug.cgi?id=16439 - - auto shbits = m_builder.CreateShl(byteNum, Constant::get(3)); - value = m_builder.CreateShl(value, shbits); - value = m_builder.CreateLShr(value, Constant::get(31 * 8)); + // + value = Endianness::toBE(m_builder, value); + auto bytes = m_builder.CreateBitCast(value, llvm::VectorType::get(Type::Byte, 32), "bytes"); + auto byte = m_builder.CreateExtractElement(bytes, byteNum, "byte"); + value = m_builder.CreateZExt(byte, Type::i256); auto byteNumValid = m_builder.CreateICmpULT(byteNum, Constant::get(32)); value = m_builder.CreateSelect(byteNumValid, value, Constant::get(0)); diff --git a/libevmjit/Endianness.cpp b/libevmjit/Endianness.cpp new file mode 100644 index 000000000..7de7b9514 --- /dev/null +++ b/libevmjit/Endianness.cpp @@ -0,0 +1,24 @@ + +#include "Endianness.h" + +#include + +#include "Type.h" + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +llvm::Value* Endianness::toBE(llvm::IRBuilder<>& _builder, llvm::Value* _word) +{ + // TODO: Native is Little Endian + auto bswap = llvm::Intrinsic::getDeclaration(_builder.GetInsertBlock()->getParent()->getParent(), llvm::Intrinsic::bswap, Type::i256); + return _builder.CreateCall(bswap, _word); +} + +} +} +} diff --git a/libevmjit/Endianness.h b/libevmjit/Endianness.h new file mode 100644 index 000000000..7b449b4d8 --- /dev/null +++ b/libevmjit/Endianness.h @@ -0,0 +1,22 @@ + +#pragma once + +#include + +namespace dev +{ +namespace eth +{ +namespace jit +{ + +class Endianness +{ +public: + + static llvm::Value* toBE(llvm::IRBuilder<>& _builder, llvm::Value* _word); +}; + +} +} +} diff --git a/windows/LibEvmJit.vcxproj b/windows/LibEvmJit.vcxproj index 1c71bb082..f516edf4f 100644 --- a/windows/LibEvmJit.vcxproj +++ b/windows/LibEvmJit.vcxproj @@ -126,6 +126,7 @@ + @@ -139,6 +140,7 @@ + diff --git a/windows/LibEvmJit.vcxproj.filters b/windows/LibEvmJit.vcxproj.filters index a2008f971..593ce8195 100644 --- a/windows/LibEvmJit.vcxproj.filters +++ b/windows/LibEvmJit.vcxproj.filters @@ -39,6 +39,9 @@ libevmjit + + libevmjit + @@ -74,5 +77,8 @@ libevmjit + + libevmjit + \ No newline at end of file