diff --git a/evmcc/test/mem/mstore1.evm b/evmcc/test/mem/mstore1.evm new file mode 100644 index 000000000..ba6141ab1 --- /dev/null +++ b/evmcc/test/mem/mstore1.evm @@ -0,0 +1 @@ +6001600054 diff --git a/evmcc/test/mem/mstore1.lll b/evmcc/test/mem/mstore1.lll new file mode 100644 index 000000000..2d2ca32b5 --- /dev/null +++ b/evmcc/test/mem/mstore1.lll @@ -0,0 +1,6 @@ + +(asm ;; [] +1 +0 +MSTORE ;; [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1] +) \ No newline at end of file diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 35e88f045..a88797413 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -34,16 +34,18 @@ Compiler::Compiler(): void Compiler::createBasicBlocks(bytesConstRef bytecode) { std::set<ProgramCounter> splitPoints; // Sorted collections of instruction indices where basic blocks start/end - splitPoints.insert(0); // First basic block std::map<ProgramCounter, ProgramCounter> directJumpTargets; std::vector<ProgramCounter> indirectJumpTargets; - boost::dynamic_bitset<> validJumpTargets(bytecode.size()); + boost::dynamic_bitset<> validJumpTargets(std::max(bytecode.size(), size_t(1))); + + splitPoints.insert(0); // First basic block + validJumpTargets[0] = true; for (auto curr = bytecode.begin(); curr != bytecode.end(); ++curr) { ProgramCounter currentPC = curr - bytecode.begin(); - validJumpTargets[currentPC] = 1; + validJumpTargets[currentPC] = true; auto inst = static_cast<Instruction>(*curr); switch (inst) @@ -473,6 +475,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, memory.require(inOff, inSize); auto hash = ext.sha3(inOff, inSize); stack.push(hash); + break; } case Instruction::POP: diff --git a/libevmjit/Endianness.cpp b/libevmjit/Endianness.cpp index 7de7b9514..f0da5f9d4 100644 --- a/libevmjit/Endianness.cpp +++ b/libevmjit/Endianness.cpp @@ -12,9 +12,10 @@ namespace eth namespace jit { -llvm::Value* Endianness::toBE(llvm::IRBuilder<>& _builder, llvm::Value* _word) +llvm::Value* Endianness::bswap(llvm::IRBuilder<>& _builder, llvm::Value* _word) { // TODO: Native is Little Endian + assert(_word->getType() == Type::i256); 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 index 7b449b4d8..9234961c1 100644 --- a/libevmjit/Endianness.h +++ b/libevmjit/Endianness.h @@ -14,7 +14,12 @@ class Endianness { public: - static llvm::Value* toBE(llvm::IRBuilder<>& _builder, llvm::Value* _word); + static llvm::Value* toBE(llvm::IRBuilder<>& _builder, llvm::Value* _word) { return bswap(_builder, _word); } + + static llvm::Value* toNative(llvm::IRBuilder<>& _builder, llvm::Value* _word) { return bswap(_builder, _word); } + +private: + static llvm::Value* bswap(llvm::IRBuilder<>& _builder, llvm::Value* _word); }; } diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index 5390d82dd..9ff4bed99 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -70,13 +70,7 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module, u256& _gas, ExtV auto exec = std::unique_ptr<llvm::ExecutionEngine>(builder.create()); if (!exec) - { - if (!errorMsg.empty()) - std::cerr << "error creating EE: " << errorMsg << std::endl; - else - std::cerr << "unknown error creating llvm::ExecutionEngine" << std::endl; - exit(1); - } + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment(errorMsg)); _module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module exec->finalizeObject(); @@ -106,10 +100,7 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module, u256& _gas, ExtV auto entryFunc = module->getFunction("main"); if (!entryFunc) - { - std::cerr << "main function not found\n"; - exit(1); - } + BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("main function not found")); ReturnCode returnCode; std::jmp_buf buf; diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 5c4bb7c59..26ed962b2 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -310,7 +310,7 @@ EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256* auto initOff = static_cast<size_t>(llvm2eth(*_initOff)); auto initSize = static_cast<size_t>(llvm2eth(*_initSize)); auto&& initRef = bytesConstRef(Runtime::getMemory().data() + initOff, initSize); - auto&& onOp = bytesConstRef(); // TODO: Handle that thing + OnOpFunc onOp{}; // TODO: Handle that thing h256 address = ext.create(endowment, &gas, initRef, onOp); *_address = address; } diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index ac7f47d19..6eb8eb6eb 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -30,26 +30,26 @@ uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure return 0; case Instruction::SSTORE: - return static_cast<uint64_t>(FeeStructure::c_sstoreGas); + return static_cast<uint64_t>(c_sstoreGas); case Instruction::SLOAD: - return static_cast<uint64_t>(FeeStructure::c_sloadGas); + return static_cast<uint64_t>(c_sloadGas); case Instruction::SHA3: - return static_cast<uint64_t>(FeeStructure::c_sha3Gas); + return static_cast<uint64_t>(c_sha3Gas); case Instruction::BALANCE: - return static_cast<uint64_t>(FeeStructure::c_sha3Gas); + return static_cast<uint64_t>(c_sha3Gas); case Instruction::CALL: case Instruction::CALLCODE: - return static_cast<uint64_t>(FeeStructure::c_callGas); + return static_cast<uint64_t>(c_callGas); case Instruction::CREATE: - return static_cast<uint64_t>(FeeStructure::c_createGas); + return static_cast<uint64_t>(c_createGas); default: // Assumes instruction code is valid - return static_cast<uint64_t>(FeeStructure::c_stepGas); + return static_cast<uint64_t>(c_stepGas); } } @@ -134,7 +134,7 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu { assert(!m_checkCall); // Everything should've been commited before - static const auto sstoreCost = static_cast<uint64_t>(FeeStructure::c_sstoreGas); + static const auto sstoreCost = static_cast<uint64_t>(c_sstoreGas); // [ADD] if oldValue == 0 and newValue != 0 => 2*cost // [DEL] if oldValue != 0 and newValue == 0 => 0 @@ -187,7 +187,7 @@ void GasMeter::commitCostBlock(llvm::Value* _additionalCost) void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder) { // Memory uses other builder, but that can be changes later - auto cost = _builder.CreateMul(_additionalMemoryInWords, Constant::get(static_cast<uint64_t>(FeeStructure::c_memoryGas)), "memcost"); + auto cost = _builder.CreateMul(_additionalMemoryInWords, Constant::get(static_cast<uint64_t>(c_memoryGas)), "memcost"); _builder.CreateCall(m_gasCheckFunc, cost); } diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index d370a7f72..23d027ba4 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -14,6 +14,7 @@ #include "Type.h" #include "Runtime.h" #include "GasMeter.h" +#include "Endianness.h" namespace dev { @@ -117,12 +118,15 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMet { llvm::Value* value = ++func->arg_begin(); value->setName("value"); + if (isWord) + value = Endianness::toBE(m_builder, value); m_builder.CreateStore(value, ptr); m_builder.CreateRetVoid(); } else { - auto ret = m_builder.CreateLoad(ptr); + llvm::Value* ret = m_builder.CreateLoad(ptr); + ret = Endianness::toNative(m_builder, ret); m_builder.CreateRet(ret); }