From 64e374890c5be3a6034722458cfa15087ecd526f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 09:23:28 +0100 Subject: [PATCH 01/15] Move jmpbuf to Runtime [#81470252] --- libevmjit/ExecutionEngine.cpp | 8 ++------ libevmjit/GasMeter.cpp | 3 +-- libevmjit/Runtime.cpp | 10 +++++++++- libevmjit/Runtime.h | 8 +++++++- libevmjit/Stack.cpp | 8 +++----- 5 files changed, 22 insertions(+), 15 deletions(-) diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index 068237af6..efa039f2b 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -35,8 +35,6 @@ ExecutionEngine::ExecutionEngine() } -extern "C" { EXPORT std::jmp_buf* rt_jmpBuf; } - int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtVMFace* _ext) { auto module = _module.get(); // Keep ownership of the module in _module @@ -102,21 +100,19 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV _ext->code = decltype(_ext->code)(fakecode, 8); } - // Init runtime - Runtime runtime(_gas, *_ext); - auto entryFunc = module->getFunction("main"); if (!entryFunc) BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("main function not found")); ReturnCode returnCode; std::jmp_buf buf; + Runtime runtime(_gas, *_ext, buf); auto r = setjmp(buf); if (r == 0) { + auto executionStartTime = std::chrono::high_resolution_clock::now(); - rt_jmpBuf = &buf; auto result = exec->runFunction(entryFunc, {{}, llvm::GenericValue(runtime.getDataPtr())}); returnCode = static_cast(result.IntVal.getZExtValue()); diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 317b204fc..897044cbe 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -103,10 +103,9 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager) m_builder.SetInsertPoint(outOfGasBB); //auto longjmpFunc = llvm::Intrinsic::getDeclaration(_module, llvm::Intrinsic::eh_sjlj_longjmp); - auto extJmpBuf = new llvm::GlobalVariable(*module, Type::BytePtr, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "rt_jmpBuf"); llvm::Type* args[] = {Type::BytePtr, m_builder.getInt32Ty()}; auto longjmpNative = llvm::Function::Create(llvm::FunctionType::get(Type::Void, args, false), llvm::Function::ExternalLinkage, "longjmp", module); - m_builder.CreateCall2(longjmpNative, m_builder.CreateLoad(extJmpBuf), Constant::get(ReturnCode::OutOfGas)); + m_builder.CreateCall2(longjmpNative, m_runtimeManager.getJmpBuf(), Constant::get(ReturnCode::OutOfGas)); m_builder.CreateUnreachable(); m_builder.SetInsertPoint(updateBB); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 4b9464293..0be5a5b70 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -24,6 +24,7 @@ llvm::StructType* RuntimeData::getType() { llvm::ArrayType::get(Type::i256, _size), Type::BytePtr, + Type::BytePtr, Type::BytePtr }; type = llvm::StructType::create(elems, "RuntimeData"); @@ -58,7 +59,7 @@ llvm::Twine getName(RuntimeData::Index _index) static Runtime* g_runtime; // FIXME: Remove -Runtime::Runtime(u256 _gas, ExtVMFace& _ext): +Runtime::Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf): m_ext(_ext) { assert(!g_runtime); @@ -79,6 +80,7 @@ Runtime::Runtime(u256 _gas, ExtVMFace& _ext): set(RuntimeData::CodeSize, _ext.code.size()); // TODO: Use constant m_data.callData = _ext.data.data(); m_data.code = _ext.code.data(); + m_data.jmpBuf = _jmpBuf; } Runtime::~Runtime() @@ -167,6 +169,12 @@ llvm::Value* RuntimeManager::getCode() return getBuilder().CreateLoad(ptr, "code"); } +llvm::Value* RuntimeManager::getJmpBuf() +{ + auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 3, "jmpbufPtr"); + return getBuilder().CreateLoad(ptr, "jmpbuf"); +} + llvm::Value* RuntimeManager::getGas() { return get(RuntimeData::Gas); diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index ec912849a..43fafb4d9 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -41,12 +41,16 @@ struct RuntimeData GasLimit, CodeSize, + ReturnDataOffset = CallValue, // Reuse 2 fields for return data reference + ReturnDataSize = CallDataSize, + _size }; i256 elems[_size]; byte const* callData; byte const* code; + decltype(&jmp_buf{}[0]) jmpBuf; static llvm::StructType* getType(); }; @@ -57,7 +61,7 @@ using MemoryImpl = bytes; class Runtime { public: - Runtime(u256 _gas, ExtVMFace& _ext); + Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf); ~Runtime(); Runtime(const Runtime&) = delete; @@ -71,6 +75,7 @@ public: u256 getGas() const; bytesConstRef getReturnData() const; + decltype(&jmp_buf{}[0]) getJmpBuf() { return m_data.jmpBuf; } private: void set(RuntimeData::Index _index, u256 _value); @@ -94,6 +99,7 @@ public: llvm::Value* getGas(); // TODO: Remove llvm::Value* getCallData(); llvm::Value* getCode(); + llvm::Value* getJmpBuf(); void setGas(llvm::Value* _gas); private: diff --git a/libevmjit/Stack.cpp b/libevmjit/Stack.cpp index 6c287dc6a..144cd5d54 100644 --- a/libevmjit/Stack.cpp +++ b/libevmjit/Stack.cpp @@ -74,13 +74,11 @@ extern "C" using namespace dev::eth::jit; -extern std::jmp_buf* rt_jmpBuf; - EXPORT void stack_pop(Runtime* _rt, uint64_t _count) { auto& stack = _rt->getStack(); if (stack.size() < _count) - longjmp(*rt_jmpBuf, static_cast(ReturnCode::StackTooSmall)); + longjmp(_rt->getJmpBuf(), static_cast(ReturnCode::StackTooSmall)); stack.erase(stack.end() - _count, stack.end()); } @@ -99,7 +97,7 @@ EXPORT void stack_get(Runtime* _rt, uint64_t _index, i256* _ret) auto& stack = _rt->getStack(); // TODO: encode _index and stack size in the return code if (stack.size() <= _index) - longjmp(*rt_jmpBuf, static_cast(ReturnCode::StackTooSmall)); + longjmp(_rt->getJmpBuf(), static_cast(ReturnCode::StackTooSmall)); *_ret = *(stack.rbegin() + _index); } @@ -109,7 +107,7 @@ EXPORT void stack_set(Runtime* _rt, uint64_t _index, i256* _word) auto& stack = _rt->getStack(); // TODO: encode _index and stack size in the return code if (stack.size() <= _index) - longjmp(*rt_jmpBuf, static_cast(ReturnCode::StackTooSmall)); + longjmp(_rt->getJmpBuf(), static_cast(ReturnCode::StackTooSmall)); *(stack.rbegin() + _index) = *_word; } From 6d428d860206ab7e76fb99431853f012a58eb50b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 10:21:50 +0100 Subject: [PATCH 02/15] Fix ReturnData::Index::_size --- libevmjit/Runtime.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 43fafb4d9..c2b21e4ca 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -41,10 +41,10 @@ struct RuntimeData GasLimit, CodeSize, - ReturnDataOffset = CallValue, // Reuse 2 fields for return data reference - ReturnDataSize = CallDataSize, + _size, - _size + ReturnDataOffset = CallValue, // Reuse 2 fields for return data reference + ReturnDataSize = CallDataSize }; i256 elems[_size]; From fd7b6da60610dcac6abd0b718b1f4aa030cd83e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 10:27:41 +0100 Subject: [PATCH 03/15] Move return data reference to Runtime [#81470252] --- libevmjit/Compiler.cpp | 5 +++-- libevmjit/Memory.cpp | 18 ++---------------- libevmjit/Memory.h | 12 ++---------- libevmjit/Runtime.cpp | 33 +++++++++++++++++++++++---------- libevmjit/Runtime.h | 5 +++++ 5 files changed, 35 insertions(+), 38 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index dd73ff1e5..3aac68cd8 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -182,7 +182,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) // Init runtime structures. RuntimeManager runtimeManager(m_builder); GasMeter gasMeter(m_builder, runtimeManager); - Memory memory(m_builder, gasMeter, runtimeManager); + Memory memory(runtimeManager, gasMeter); Ext ext(runtimeManager); Stack stack(m_builder, runtimeManager); @@ -817,7 +817,8 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto index = stack.pop(); auto size = stack.pop(); - memory.registerReturnData(index, size); + memory.require(index, size); + _runtimeManager.registerReturnData(index, size); m_builder.CreateRet(Constant::get(ReturnCode::Return)); break; diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index fa5a2b0dd..b7b3d8497 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -24,8 +24,8 @@ namespace eth namespace jit { -Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter, RuntimeManager& _runtimeManager): - CompilerHelper(_builder) +Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter): + RuntimeHelper(_runtimeManager) { auto module = getModule(); auto i64Ty = m_builder.getInt64Ty(); @@ -40,12 +40,6 @@ Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter, RuntimeManager& m_size = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, Constant::get(0), "mem.size"); m_size->setUnnamedAddr(true); // Address is not important - m_returnDataOffset = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataOffset"); - m_returnDataOffset->setUnnamedAddr(true); // Address is not important - - m_returnDataSize = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataSize"); - m_returnDataSize->setUnnamedAddr(true); // Address is not important - llvm::Type* resizeArgs[] = {Type::RuntimePtr, Type::WordPtr}; m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, resizeArgs, false), llvm::Function::ExternalLinkage, "mem_resize", module); llvm::AttrBuilder attrBuilder; @@ -180,14 +174,6 @@ void Memory::require(llvm::Value* _offset, llvm::Value* _size) require(sizeRequired); } -void Memory::registerReturnData(llvm::Value* _index, llvm::Value* _size) -{ - require(_index, _size); // Make sure that memory is allocated and count gas - - m_builder.CreateStore(_index, m_returnDataOffset); - m_builder.CreateStore(_size, m_returnDataSize); -} - void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx, llvm::Value* _destMemIdx, llvm::Value* _reqBytes) { diff --git a/libevmjit/Memory.h b/libevmjit/Memory.h index d92538247..d8c1e4b72 100644 --- a/libevmjit/Memory.h +++ b/libevmjit/Memory.h @@ -10,12 +10,11 @@ namespace eth { namespace jit { -class RuntimeManager; -class Memory : public CompilerHelper +class Memory : public RuntimeHelper { public: - Memory(llvm::IRBuilder<>& _builder, class GasMeter& _gasMeter, RuntimeManager& _runtimeManager); + Memory(RuntimeManager& _runtimeManager, class GasMeter& _gasMeter); llvm::Value* loadWord(llvm::Value* _addr); void storeWord(llvm::Value* _addr, llvm::Value* _word); @@ -31,9 +30,6 @@ public: /// Requires the amount of memory to for data defined by offset and size. And counts gas fee for that memory. void require(llvm::Value* _offset, llvm::Value* _size); - void registerReturnData(llvm::Value* _index, llvm::Value* _size); - bytesConstRef getReturnData(); - void dump(uint64_t _begin, uint64_t _end = 0); private: @@ -44,10 +40,6 @@ private: llvm::GlobalVariable* m_data; llvm::GlobalVariable* m_size; - /// @TODO: m_data and m_size could be used - llvm::GlobalVariable* m_returnDataOffset; - llvm::GlobalVariable* m_returnDataSize; - llvm::Function* m_resize; llvm::Function* m_require; llvm::Function* m_loadWord; diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 0be5a5b70..b9dd63ea2 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -98,16 +98,14 @@ u256 Runtime::getGas() const return llvm2eth(m_data.elems[RuntimeData::Gas]); } -extern "C" { - EXPORT i256 mem_returnDataOffset; // FIXME: Dis-globalize - EXPORT i256 mem_returnDataSize; -} - bytesConstRef Runtime::getReturnData() const { // TODO: Handle large indexes - auto offset = static_cast(llvm2eth(mem_returnDataOffset)); - auto size = static_cast(llvm2eth(mem_returnDataSize)); + auto offset = static_cast(llvm2eth(m_data.elems[RuntimeData::ReturnDataOffset])); + auto size = static_cast(llvm2eth(m_data.elems[RuntimeData::ReturnDataSize])); + + assert(offset + size <= m_memory.size()); + // TODO: Handle invalid data access by returning empty ref return {m_memory.data() + offset, size}; } @@ -128,11 +126,26 @@ llvm::Value* RuntimeManager::getRuntimePtr() return m_builder.CreateLoad(m_dataPtr); } -llvm::Value* RuntimeManager::get(RuntimeData::Index _index) +llvm::Value* RuntimeManager::getPtr(RuntimeData::Index _index) { llvm::Value* idxList[] = {m_builder.getInt32(0), m_builder.getInt32(0), m_builder.getInt32(_index)}; - auto ptr = m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, getName(_index) + "Ptr"); - return m_builder.CreateLoad(ptr, getName(_index)); + return m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, getName(_index) + "Ptr"); +} + +llvm::Value* RuntimeManager::get(RuntimeData::Index _index) +{ + return m_builder.CreateLoad(getPtr(_index), getName(_index)); +} + +void RuntimeManager::set(RuntimeData::Index _index, llvm::Value* _value) +{ + m_builder.CreateStore(_value, getPtr(_index)); +} + +void RuntimeManager::registerReturnData(llvm::Value* _offset, llvm::Value* _size) +{ + set(RuntimeData::ReturnDataOffset, _offset); + set(RuntimeData::ReturnDataSize, _size); } llvm::Value* RuntimeManager::get(Instruction _inst) diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index c2b21e4ca..f516912eb 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -102,7 +102,12 @@ public: llvm::Value* getJmpBuf(); void setGas(llvm::Value* _gas); + void registerReturnData(llvm::Value* _index, llvm::Value* _size); + private: + llvm::Value* getPtr(RuntimeData::Index _index); + void set(RuntimeData::Index _index, llvm::Value* _value); + llvm::GlobalVariable* m_dataPtr; }; From e273299a09d91ee880e70a62061a672cb7185111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 10:32:10 +0100 Subject: [PATCH 04/15] Change some runtime names --- libevmjit/Compiler.cpp | 1 + libevmjit/Runtime.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 3aac68cd8..cfa9349c6 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -172,6 +172,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) llvm::Type* mainFuncArgTypes[] = {m_builder.getInt32Ty(), Type::RuntimePtr}; // There must be int in first place because LLVM does not support other signatures auto mainFuncType = llvm::FunctionType::get(Type::MainReturn, mainFuncArgTypes, false); m_mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, "main", module.get()); + m_mainFunc->arg_begin()->getNextNode()->setName("rt"); // Create the basic blocks. auto entryBlock = llvm::BasicBlock::Create(m_builder.getContext(), "entry", m_mainFunc); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index b9dd63ea2..233ce2a39 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -27,7 +27,7 @@ llvm::StructType* RuntimeData::getType() Type::BytePtr, Type::BytePtr }; - type = llvm::StructType::create(elems, "RuntimeData"); + type = llvm::StructType::create(elems, "Runtime"); } return type; } From 6a16efad92850f613e4643a93a9da8bdf44789fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 10:43:18 +0100 Subject: [PATCH 05/15] Get Runtime pointer from main function argument if available --- libevmjit/CompilerHelper.cpp | 6 ++++-- libevmjit/Runtime.cpp | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libevmjit/CompilerHelper.cpp b/libevmjit/CompilerHelper.cpp index c2d612c66..c4835c32e 100644 --- a/libevmjit/CompilerHelper.cpp +++ b/libevmjit/CompilerHelper.cpp @@ -27,8 +27,10 @@ llvm::Function* CompilerHelper::getMainFunction() { assert(m_builder.GetInsertBlock()); auto mainFunc = m_builder.GetInsertBlock()->getParent(); - assert(mainFunc && mainFunc->getName() == "main"); - return mainFunc; + assert(mainFunc); + if (mainFunc->getName() == "main") + return mainFunc; + return nullptr; } diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 233ce2a39..86966e2b1 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -122,8 +122,9 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_bui llvm::Value* RuntimeManager::getRuntimePtr() { - // TODO: If in main function - get it from param - return m_builder.CreateLoad(m_dataPtr); + if (auto mainFunc = getMainFunction()) + return mainFunc->arg_begin()->getNextNode(); // Runtime is the second parameter of main function + return m_builder.CreateLoad(m_dataPtr, "rt"); } llvm::Value* RuntimeManager::getPtr(RuntimeData::Index _index) From 0eb8311aa1f380e443e2da63f1bd49bf21c34928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 11:24:50 +0100 Subject: [PATCH 06/15] Restore correct memory access in Ext functions --- libevmjit/Ext.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 170086dae..bf7947408 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -225,8 +225,7 @@ EXPORT void ext_create(Runtime* _rt, i256* _endowment, i256* _initOff, i256* _in u256 gas; // TODO: Handle gas auto initOff = static_cast(llvm2eth(*_initOff)); auto initSize = static_cast(llvm2eth(*_initSize)); - //auto&& initRef = bytesConstRef(Runtime::getMemory().data() + initOff, initSize); - bytesConstRef initRef; + auto&& initRef = bytesConstRef(_rt->getMemory().data() + initOff, initSize); OnOpFunc onOp{}; // TODO: Handle that thing h256 address = ext.create(endowment, &gas, initRef, onOp); *_address = address; @@ -252,8 +251,8 @@ EXPORT void ext_call(Runtime* _rt, i256* _gas, h256* _receiveAddress, i256* _val auto inSize = static_cast(llvm2eth(*_inSize)); auto outOff = static_cast(llvm2eth(*_outOff)); auto outSize = static_cast(llvm2eth(*_outSize)); - auto&& inRef = bytesConstRef(); //Runtime::getMemory().data() + inOff, inSize); - auto&& outRef = bytesConstRef(); // Runtime::getMemory().data() + outOff, outSize); + auto&& inRef = bytesConstRef(_rt->getMemory().data() + inOff, inSize); + auto&& outRef = bytesConstRef(_rt->getMemory().data() + outOff, outSize); OnOpFunc onOp{}; // TODO: Handle that thing auto codeAddress = right160(*_codeAddress); ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, codeAddress); @@ -267,7 +266,7 @@ EXPORT void ext_sha3(Runtime* _rt, i256* _inOff, i256* _inSize, i256* _ret) { auto inOff = static_cast(llvm2eth(*_inOff)); auto inSize = static_cast(llvm2eth(*_inSize)); - auto dataRef = bytesConstRef(); // Runtime::getMemory().data() + inOff, inSize); + auto dataRef = bytesConstRef(_rt->getMemory().data() + inOff, inSize); auto hash = sha3(dataRef); *_ret = *reinterpret_cast(&hash); } From 0da6823484bf542bd00da191efc4934455918000 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 11:37:15 +0100 Subject: [PATCH 07/15] Fix EXTCODECOPY --- libevmjit/Ext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index bf7947408..003b0ae08 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -63,7 +63,7 @@ Ext::Ext(RuntimeManager& _runtimeManager): m_call = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argsTypes, false), Linkage::ExternalLinkage, "ext_call", module); m_sha3 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 4}, false), Linkage::ExternalLinkage, "ext_sha3", module); m_exp = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 4}, false), Linkage::ExternalLinkage, "ext_exp", module); - m_codeAt = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), Linkage::ExternalLinkage, "ext_codeAt", module); + m_codeAt = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, {argsTypes, 2}, false), Linkage::ExternalLinkage, "ext_codeAt", module); m_codesizeAt = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_codesizeAt", module); } From c7ba567f9ae516efcc6eaa9171e3fee95b121cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 12:26:45 +0100 Subject: [PATCH 08/15] Merge branch 'develop' into develop-evmcc Conflicts: libevm/ExtVMFace.h libevm/VM.h test/vm.cpp test/vm.h windows/LibEthereum.vcxproj.filters --- libevmjit/Compiler.cpp | 4 ++-- libevmjit/Ext.cpp | 2 +- libevmjit/GasMeter.cpp | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 17d1decc2..0b9fb5b7b 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -369,14 +369,14 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, break; } - case Instruction::NEG: + /*case Instruction::NEG: { auto top = stack.pop(); auto zero = Constant::get(0); auto res = m_builder.CreateSub(zero, top); stack.push(res); break; - } + }*/ case Instruction::LT: { diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 003b0ae08..34c1ebf5e 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -227,7 +227,7 @@ EXPORT void ext_create(Runtime* _rt, i256* _endowment, i256* _initOff, i256* _in auto initSize = static_cast(llvm2eth(*_initSize)); auto&& initRef = bytesConstRef(_rt->getMemory().data() + initOff, initSize); OnOpFunc onOp{}; // TODO: Handle that thing - h256 address = ext.create(endowment, &gas, initRef, onOp); + h256 address(ext.create(endowment, &gas, initRef, onOp), h256::AlignRight); *_address = address; } else diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 897044cbe..b71fd8286 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -31,7 +31,7 @@ uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure return 0; case Instruction::SSTORE: - return static_cast(c_sstoreGas); + return static_cast(c_sstoreResetGas); // FIXME: Check store gas case Instruction::SLOAD: return static_cast(c_sloadGas); @@ -133,7 +133,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(c_sstoreGas); + static const auto sstoreCost = static_cast(c_sstoreResetGas); // FIXME: Check store gas // [ADD] if oldValue == 0 and newValue != 0 => 2*cost // [DEL] if oldValue != 0 and newValue == 0 => 0 From 5a923d63567afd34afe196b545e07641da19af6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 12:28:23 +0100 Subject: [PATCH 09/15] Ignore opOp callback silently --- libevmjit/VM.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index 9a76c5bcb..56121941e 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -13,9 +13,8 @@ namespace eth namespace jit { -bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps) +bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) { - assert(!_onOp); // Parameter ignored assert(_steps == (uint64_t)-1); // Parameter ignored auto module = Compiler().compile(_ext.code); From 31c9dd3fcfe53050a0ca49d9b27327233a1a4c89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 12:30:05 +0100 Subject: [PATCH 10/15] Ignore opOp callback silently --- libevmjit/VM.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index 56121941e..dd54dd0e5 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -15,8 +15,6 @@ namespace jit bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) { - assert(_steps == (uint64_t)-1); // Parameter ignored - auto module = Compiler().compile(_ext.code); ExecutionEngine engine; From ac38bf9ac18ff8fa4374f1ab1d66173906de4b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 18:04:01 +0100 Subject: [PATCH 11/15] Add raiseException helper to RuntimeManager [#81563132] --- libevmjit/GasMeter.cpp | 6 +----- libevmjit/GasMeter.h | 2 +- libevmjit/Runtime.cpp | 7 +++++++ libevmjit/Runtime.h | 8 ++++++-- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index b71fd8286..7294fa2f7 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -101,11 +101,7 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager) m_builder.CreateCondBr(isOutOfGas, outOfGasBB, updateBB); m_builder.SetInsertPoint(outOfGasBB); - - //auto longjmpFunc = llvm::Intrinsic::getDeclaration(_module, llvm::Intrinsic::eh_sjlj_longjmp); - llvm::Type* args[] = {Type::BytePtr, m_builder.getInt32Ty()}; - auto longjmpNative = llvm::Function::Create(llvm::FunctionType::get(Type::Void, args, false), llvm::Function::ExternalLinkage, "longjmp", module); - m_builder.CreateCall2(longjmpNative, m_runtimeManager.getJmpBuf(), Constant::get(ReturnCode::OutOfGas)); + _runtimeManager.raiseException(ReturnCode::OutOfGas); m_builder.CreateUnreachable(); m_builder.SetInsertPoint(updateBB); diff --git a/libevmjit/GasMeter.h b/libevmjit/GasMeter.h index 82007fc00..dcfde92a3 100644 --- a/libevmjit/GasMeter.h +++ b/libevmjit/GasMeter.h @@ -13,7 +13,7 @@ namespace jit { class RuntimeManager; -class GasMeter : public CompilerHelper +class GasMeter : public CompilerHelper // TODO: Use RuntimeHelper { public: GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 86966e2b1..a93f191a9 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -113,6 +113,8 @@ bytesConstRef Runtime::getReturnData() const RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder) { m_dataPtr = new llvm::GlobalVariable(*getModule(), Type::RuntimePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::RuntimePtr), "rt"); + llvm::Type* args[] = {Type::BytePtr, m_builder.getInt32Ty()}; + m_longjmp = llvm::Function::Create(llvm::FunctionType::get(Type::Void, args, false), llvm::Function::ExternalLinkage, "longjmp", getModule()); // Export data auto mainFunc = getMainFunction(); @@ -149,6 +151,11 @@ void RuntimeManager::registerReturnData(llvm::Value* _offset, llvm::Value* _size set(RuntimeData::ReturnDataSize, _size); } +void RuntimeManager::raiseException(ReturnCode _returnCode) +{ + m_builder.CreateCall2(m_longjmp, getJmpBuf(), Constant::get(_returnCode)); +} + llvm::Value* RuntimeManager::get(Instruction _inst) { switch (_inst) diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index f516912eb..ad2002674 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -7,6 +7,7 @@ #include "CompilerHelper.h" #include "Utils.h" +#include "Type.h" #ifdef _MSC_VER @@ -99,16 +100,19 @@ public: llvm::Value* getGas(); // TODO: Remove llvm::Value* getCallData(); llvm::Value* getCode(); - llvm::Value* getJmpBuf(); void setGas(llvm::Value* _gas); void registerReturnData(llvm::Value* _index, llvm::Value* _size); + void raiseException(ReturnCode _returnCode); + private: llvm::Value* getPtr(RuntimeData::Index _index); void set(RuntimeData::Index _index, llvm::Value* _value); + llvm::Value* getJmpBuf(); - llvm::GlobalVariable* m_dataPtr; + llvm::GlobalVariable* m_dataPtr = nullptr; + llvm::Function* m_longjmp = nullptr; }; } From 6da6f3dc52c88014ce80a49a0a64b22e294ca7fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 18:15:58 +0100 Subject: [PATCH 12/15] Handle bad instructions (BadInstruction exception) [#81563132] --- evmcc/test/except/badinst1.evm | 1 + libevmjit/Compiler.cpp | 5 +++++ libevmjit/Type.h | 3 ++- libevmjit/VM.cpp | 11 +++++++---- 4 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 evmcc/test/except/badinst1.evm diff --git a/evmcc/test/except/badinst1.evm b/evmcc/test/except/badinst1.evm new file mode 100644 index 000000000..69aadac5e --- /dev/null +++ b/evmcc/test/except/badinst1.evm @@ -0,0 +1 @@ +4a diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 0b9fb5b7b..02c8db715 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -816,6 +816,11 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, break; } + default: // Invalid instruction - runtime exception + { + _runtimeManager.raiseException(ReturnCode::BadInstruction); + } + } } diff --git a/libevmjit/Type.h b/libevmjit/Type.h index 86915cd9e..b432f0813 100644 --- a/libevmjit/Type.h +++ b/libevmjit/Type.h @@ -43,7 +43,8 @@ enum class ReturnCode BadJumpDestination = 101, OutOfGas = 102, - StackTooSmall = 103 + StackTooSmall = 103, + BadInstruction = 104, }; struct Constant diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index dd54dd0e5..0907682d2 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -5,6 +5,7 @@ #include "ExecutionEngine.h" #include "Compiler.h" +#include "Type.h" namespace dev { @@ -20,14 +21,16 @@ bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) ExecutionEngine engine; auto exitCode = engine.run(std::move(module), m_gas, &_ext); - switch (exitCode) + switch (static_cast(exitCode)) { - case 101: + case ReturnCode::BadJumpDestination: BOOST_THROW_EXCEPTION(BadJumpDestination()); - case 102: + case ReturnCode::OutOfGas: BOOST_THROW_EXCEPTION(OutOfGas()); - case 103: + case ReturnCode::StackTooSmall: BOOST_THROW_EXCEPTION(StackTooSmall(1,0)); + case ReturnCode::BadInstruction: + BOOST_THROW_EXCEPTION(BadInstruction()); } m_output = std::move(engine.returnData); From 2493ef5f9e0e7f12e942428ac3c3fcedf39943c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 20:20:21 +0100 Subject: [PATCH 13/15] Call helper --- libevmjit/CompilerHelper.h | 7 +++++++ libevmjit/GasMeter.cpp | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/libevmjit/CompilerHelper.h b/libevmjit/CompilerHelper.h index cf83d70cd..c2257bf51 100644 --- a/libevmjit/CompilerHelper.h +++ b/libevmjit/CompilerHelper.h @@ -31,6 +31,13 @@ protected: llvm::IRBuilder<>& m_builder; llvm::IRBuilder<>& getBuilder() { return m_builder; } + template + llvm::CallInst* call(llvm::Function* _func, _Args*... _args) + { + llvm::Value* args[] = {_args...}; + return m_builder.CreateCall(_func, args); + } + friend class RuntimeHelper; }; diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 7294fa2f7..20ee30e9a 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -143,7 +143,7 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu auto isDel = m_builder.CreateAnd(oldValueIsntZero, newValueIsZero, "isDel"); auto cost = m_builder.CreateSelect(isAdd, Constant::get(2 * sstoreCost), Constant::get(sstoreCost), "cost"); cost = m_builder.CreateSelect(isDel, Constant::get(0), cost, "cost"); - m_builder.CreateCall(m_gasCheckFunc, cost); + call(m_gasCheckFunc, cost); } void GasMeter::giveBack(llvm::Value* _gas) From 4684c6f36353b753fb1015769d1b46454a15930f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Tue, 28 Oct 2014 20:36:03 +0100 Subject: [PATCH 14/15] Using call helper --- libevmjit/CompilerHelper.h | 4 ++-- libevmjit/Ext.cpp | 17 ++++++----------- libevmjit/GasMeter.cpp | 2 +- 3 files changed, 9 insertions(+), 14 deletions(-) diff --git a/libevmjit/CompilerHelper.h b/libevmjit/CompilerHelper.h index c2257bf51..19315fe4a 100644 --- a/libevmjit/CompilerHelper.h +++ b/libevmjit/CompilerHelper.h @@ -32,10 +32,10 @@ protected: llvm::IRBuilder<>& getBuilder() { return m_builder; } template - llvm::CallInst* call(llvm::Function* _func, _Args*... _args) + llvm::CallInst* createCall(llvm::Function* _func, _Args*... _args) { llvm::Value* args[] = {_args...}; - return m_builder.CreateCall(_func, args); + return getBuilder().CreateCall(_func, args); } friend class RuntimeHelper; diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 34c1ebf5e..0da9c8809 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -109,8 +109,7 @@ llvm::Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::V m_builder.CreateStore(_endowment, m_args[0]); m_builder.CreateStore(_initOff, m_arg2); m_builder.CreateStore(_initSize, m_arg3); - llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_arg3, m_args[1]}; - m_builder.CreateCall(m_create, args); + createCall(m_create, getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_arg3, m_args[1]); llvm::Value* address = m_builder.CreateLoad(m_args[1]); address = Endianness::toNative(m_builder, address); return address; @@ -128,9 +127,7 @@ llvm::Value* Ext::call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::V m_builder.CreateStore(_outSize, m_arg7); auto codeAddress = Endianness::toBE(m_builder, _codeAddress); m_builder.CreateStore(codeAddress, m_arg8); - - llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_args[1]}; - m_builder.CreateCall(m_call, args); + createCall(m_call, getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_args[1]); _gas = m_builder.CreateLoad(m_args[0]); // Return gas return m_builder.CreateLoad(m_args[1]); } @@ -139,8 +136,7 @@ llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize) { m_builder.CreateStore(_inOff, m_args[0]); m_builder.CreateStore(_inSize, m_arg2); - llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]}; - m_builder.CreateCall(m_sha3, args); + createCall(m_sha3, getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]); llvm::Value* hash = m_builder.CreateLoad(m_args[1]); hash = Endianness::toNative(m_builder, hash); return hash; @@ -148,10 +144,10 @@ llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize) llvm::Value* Ext::exp(llvm::Value* _left, llvm::Value* _right) { + // TODO: Move ext to Arith256 m_builder.CreateStore(_left, m_args[0]); m_builder.CreateStore(_right, m_arg2); - llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]}; - m_builder.CreateCall(m_exp, args); + createCall(m_exp, getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]); return m_builder.CreateLoad(m_args[1]); } @@ -166,8 +162,7 @@ llvm::Value* Ext::codesizeAt(llvm::Value* _addr) { auto addr = Endianness::toBE(m_builder, _addr); m_builder.CreateStore(addr, m_args[0]); - llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]}; - m_builder.CreateCall(m_codesizeAt, args); + createCall(m_codesizeAt, getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]); return m_builder.CreateLoad(m_args[1]); } diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 20ee30e9a..149944f28 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -143,7 +143,7 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu auto isDel = m_builder.CreateAnd(oldValueIsntZero, newValueIsZero, "isDel"); auto cost = m_builder.CreateSelect(isAdd, Constant::get(2 * sstoreCost), Constant::get(sstoreCost), "cost"); cost = m_builder.CreateSelect(isDel, Constant::get(0), cost, "cost"); - call(m_gasCheckFunc, cost); + createCall(m_gasCheckFunc, cost); } void GasMeter::giveBack(llvm::Value* _gas) From 65eaa13c17eb5c10dc5b17c2ffab0118910850f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Wed, 29 Oct 2014 10:30:00 +0100 Subject: [PATCH 15/15] Remove global Runtime pointer --- libevmjit/Runtime.cpp | 9 --------- libevmjit/Runtime.h | 1 - 2 files changed, 10 deletions(-) diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index a93f191a9..3efd78a26 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -57,13 +57,9 @@ llvm::Twine getName(RuntimeData::Index _index) } } -static Runtime* g_runtime; // FIXME: Remove - Runtime::Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf): m_ext(_ext) { - assert(!g_runtime); - g_runtime = this; set(RuntimeData::Gas, _gas); set(RuntimeData::Address, fromAddress(_ext.myAddress)); set(RuntimeData::Caller, fromAddress(_ext.caller)); @@ -83,11 +79,6 @@ Runtime::Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf): m_data.jmpBuf = _jmpBuf; } -Runtime::~Runtime() -{ - g_runtime = nullptr; -} - void Runtime::set(RuntimeData::Index _index, u256 _value) { m_data.elems[_index] = eth2llvm(_value); diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index ad2002674..418652c40 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -63,7 +63,6 @@ class Runtime { public: Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf); - ~Runtime(); Runtime(const Runtime&) = delete; void operator=(const Runtime&) = delete;