From 8b4709452948607b8e087f1fee95ce942ee79628 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 24 Oct 2014 15:19:32 +0200 Subject: [PATCH 01/17] Introducing RuntimeData struct - a data that will be provided to running program --- libevmjit/Compiler.cpp | 5 ++++- libevmjit/ExecutionEngine.cpp | 2 +- libevmjit/Runtime.cpp | 9 +++++++++ libevmjit/Runtime.h | 12 ++++++++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 1b408d6fe..0128c76d5 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -17,6 +17,7 @@ #include "GasMeter.h" #include "Utils.h" #include "Endianness.h" +#include "Runtime.h" namespace dev { @@ -163,7 +164,9 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) auto module = std::make_unique("main", m_builder.getContext()); // Create main function - m_mainFunc = llvm::Function::Create(llvm::FunctionType::get(Type::MainReturn, false), llvm::Function::ExternalLinkage, "main", module.get()); + llvm::Type* mainFuncArgTypes[] = {m_builder.getInt32Ty(), RuntimeData::getType()->getPointerTo()}; // 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()); // Create the basic blocks. auto entryBlock = llvm::BasicBlock::Create(m_builder.getContext(), "entry", m_mainFunc); diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index af5f96ac7..e537d0517 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -108,7 +108,7 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV if (r == 0) { rt_jmpBuf = &buf; - auto result = exec->runFunction(entryFunc, {}); + auto result = exec->runFunction(entryFunc, {{}, llvm::GenericValue(runtime.getDataPtr())}); returnCode = static_cast(result.IntVal.getZExtValue()); } else diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 448d25f92..900b109fa 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -12,6 +12,15 @@ namespace eth namespace jit { +llvm::StructType* RuntimeData::getType() +{ + llvm::Type* elems[] = + { + Type::i256, + }; + return llvm::StructType::create(elems, "RuntimeData"); +} + static Runtime* g_runtime; extern "C" diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 165f47e06..8cee63fa1 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -21,6 +21,13 @@ namespace eth namespace jit { +struct RuntimeData +{ + static llvm::StructType* getType(); + + i256 gas; +}; + using StackImpl = std::vector; using MemoryImpl = bytes; @@ -33,12 +40,17 @@ public: Runtime(const Runtime&) = delete; void operator=(const Runtime&) = delete; + RuntimeData* getDataPtr() { return &m_data; } + static StackImpl& getStack(); static MemoryImpl& getMemory(); static ExtVMFace& getExt(); static u256 getGas(); private: + + /// @internal Must be the first element to asure Runtime* === RuntimeData* + RuntimeData m_data; StackImpl m_stack; MemoryImpl m_memory; ExtVMFace& m_ext; From c87717aa781f9fd05258dea49876afd8e14229d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 24 Oct 2014 16:20:29 +0200 Subject: [PATCH 02/17] Export runtime data to global variable in main function --- libevmjit/Compiler.cpp | 1 + libevmjit/CompilerHelper.cpp | 8 ++++++++ libevmjit/CompilerHelper.h | 3 +++ libevmjit/Runtime.cpp | 28 ++++++++++++++++++++++++---- libevmjit/Runtime.h | 12 ++++++++++++ 5 files changed, 48 insertions(+), 4 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 0128c76d5..14952163f 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -175,6 +175,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) createBasicBlocks(bytecode); // Init runtime structures. + RuntimeManager runtimeManager(m_builder); GasMeter gasMeter(m_builder); Memory memory(m_builder, gasMeter); Ext ext(m_builder); diff --git a/libevmjit/CompilerHelper.cpp b/libevmjit/CompilerHelper.cpp index 3bdf38641..b919043f2 100644 --- a/libevmjit/CompilerHelper.cpp +++ b/libevmjit/CompilerHelper.cpp @@ -21,6 +21,14 @@ llvm::Module* CompilerHelper::getModule() return m_builder.GetInsertBlock()->getParent()->getParent(); } +llvm::Function* CompilerHelper::getMainFunction() +{ + assert(m_builder.GetInsertBlock()); + auto mainFunc = m_builder.GetInsertBlock()->getParent(); + assert(mainFunc && mainFunc->getName() == "main"); + return mainFunc; +} + } } } diff --git a/libevmjit/CompilerHelper.h b/libevmjit/CompilerHelper.h index e284398a3..23bbcbd11 100644 --- a/libevmjit/CompilerHelper.h +++ b/libevmjit/CompilerHelper.h @@ -23,6 +23,9 @@ protected: /// Reference to the IR module being compiled llvm::Module* getModule(); + /// Reference to the main module function + llvm::Function* getMainFunction(); + /// Reference to parent compiler IR builder llvm::IRBuilder<>& m_builder; }; diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 900b109fa..4d800535c 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -1,6 +1,9 @@ #include "Runtime.h" +#include +#include + #include #include "Type.h" @@ -14,11 +17,16 @@ namespace jit llvm::StructType* RuntimeData::getType() { - llvm::Type* elems[] = + static llvm::StructType* type = nullptr; + if (!type) { - Type::i256, - }; - return llvm::StructType::create(elems, "RuntimeData"); + llvm::Type* elems[] = + { + Type::i256, + }; + type = llvm::StructType::create(elems, "RuntimeData"); + } + return type; } static Runtime* g_runtime; @@ -61,6 +69,18 @@ u256 Runtime::getGas() return llvm2eth(gas); } + +RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder) +{ + auto dataPtrType = RuntimeData::getType()->getPointerTo(); + m_dataPtr = new llvm::GlobalVariable(*getModule(), dataPtrType, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(dataPtrType), "rt"); + + // Export data + auto mainFunc = getMainFunction(); + llvm::Value* dataPtr = &mainFunc->getArgumentList().back(); + m_builder.CreateStore(dataPtr, m_dataPtr); +} + } } } diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 8cee63fa1..d9984966e 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -5,6 +5,7 @@ #include +#include "CompilerHelper.h" #include "Utils.h" @@ -56,6 +57,17 @@ private: ExtVMFace& m_ext; }; +class RuntimeManager: public CompilerHelper +{ +public: + RuntimeManager(llvm::IRBuilder<>& _builder); + + llvm::Value* getGas(); + +private: + llvm::GlobalVariable* m_dataPtr; +}; + } } } From fcf5400c3ab76f427dd04f1a2807bdd8d3efd1ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 10:35:44 +0100 Subject: [PATCH 03/17] Place current gas counter value in RuntimeData --- libevmjit/Compiler.cpp | 8 ++++---- libevmjit/Compiler.h | 2 +- libevmjit/ExecutionEngine.cpp | 2 +- libevmjit/GasMeter.cpp | 21 +++++++-------------- libevmjit/GasMeter.h | 8 ++++---- libevmjit/Runtime.cpp | 25 ++++++++++++++++++------- libevmjit/Runtime.h | 3 ++- 7 files changed, 37 insertions(+), 32 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 339f73959..ddfe2497e 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -178,7 +178,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) // Init runtime structures. RuntimeManager runtimeManager(m_builder); - GasMeter gasMeter(m_builder); + GasMeter gasMeter(m_builder, runtimeManager); Memory memory(m_builder, gasMeter); Ext ext(m_builder); Stack stack(m_builder); @@ -191,7 +191,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) auto iterCopy = basicBlockPairIt; ++iterCopy; auto nextBasicBlock = (iterCopy != basicBlocks.end()) ? iterCopy->second.llvm() : nullptr; - compileBasicBlock(basicBlock, bytecode, memory, ext, gasMeter, nextBasicBlock); + compileBasicBlock(basicBlock, bytecode, runtimeManager, memory, ext, gasMeter, nextBasicBlock); } // Code for special blocks: @@ -272,7 +272,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) } -void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) +void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, RuntimeManager& _runtimeManager, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) { m_builder.SetInsertPoint(basicBlock.llvm()); auto& stack = basicBlock.localStack(); @@ -680,7 +680,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::GAS: { - stack.push(gasMeter.getGas()); + stack.push(_runtimeManager.getGas()); break; } diff --git a/libevmjit/Compiler.h b/libevmjit/Compiler.h index afd5aef72..d543b9b1d 100644 --- a/libevmjit/Compiler.h +++ b/libevmjit/Compiler.h @@ -31,7 +31,7 @@ private: void createBasicBlocks(bytesConstRef bytecode); - void compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); + void compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, class RuntimeManager& _runtimeManager, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); void removeDeadBlocks(); diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index e537d0517..5d5af553e 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -115,7 +115,7 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV returnCode = static_cast(r); // Return remaining gas - _gas = returnCode == ReturnCode::OutOfGas ? 0 : Runtime::getGas(); + _gas = returnCode == ReturnCode::OutOfGas ? 0 : runtime.getGas(); std::cout << "Max stack size: " << Stack::maxStackSize << std::endl; diff --git a/libevmjit/GasMeter.cpp b/libevmjit/GasMeter.cpp index 6eb8eb6eb..317b204fc 100644 --- a/libevmjit/GasMeter.cpp +++ b/libevmjit/GasMeter.cpp @@ -10,6 +10,7 @@ #include "Type.h" #include "Ext.h" +#include "Runtime.h" namespace dev { @@ -79,12 +80,11 @@ bool isCostBlockEnd(Instruction _inst) } -GasMeter::GasMeter(llvm::IRBuilder<>& _builder) : - CompilerHelper(_builder) +GasMeter::GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager) : + CompilerHelper(_builder), + m_runtimeManager(_runtimeManager) { auto module = getModule(); - m_gas = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas"); - m_gas->setUnnamedAddr(true); // Address is not important m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", module); InsertPointGuard guard(m_builder); @@ -96,7 +96,7 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder) : m_builder.SetInsertPoint(checkBB); llvm::Value* cost = m_gasCheckFunc->arg_begin(); cost->setName("cost"); - llvm::Value* gas = m_builder.CreateLoad(m_gas, "gas"); + auto gas = m_runtimeManager.getGas(); auto isOutOfGas = m_builder.CreateICmpUGT(cost, gas, "isOutOfGas"); m_builder.CreateCondBr(isOutOfGas, outOfGasBB, updateBB); @@ -111,7 +111,7 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder) : m_builder.SetInsertPoint(updateBB); gas = m_builder.CreateSub(gas, cost); - m_builder.CreateStore(gas, m_gas); + m_runtimeManager.setGas(gas); m_builder.CreateRetVoid(); } @@ -153,9 +153,7 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu void GasMeter::giveBack(llvm::Value* _gas) { - llvm::Value* gasCounter = m_builder.CreateLoad(m_gas, "gas"); - gasCounter = m_builder.CreateAdd(gasCounter, _gas); - m_builder.CreateStore(gasCounter, m_gas); + m_runtimeManager.setGas(m_builder.CreateAdd(m_runtimeManager.getGas(), _gas)); } void GasMeter::commitCostBlock(llvm::Value* _additionalCost) @@ -191,11 +189,6 @@ void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilde _builder.CreateCall(m_gasCheckFunc, cost); } -llvm::Value* GasMeter::getGas() -{ - return m_builder.CreateLoad(m_gas, "gas"); -} - } } } diff --git a/libevmjit/GasMeter.h b/libevmjit/GasMeter.h index 521e7080a..82007fc00 100644 --- a/libevmjit/GasMeter.h +++ b/libevmjit/GasMeter.h @@ -11,11 +11,12 @@ namespace eth { namespace jit { +class RuntimeManager; class GasMeter : public CompilerHelper { public: - GasMeter(llvm::IRBuilder<>& _builder); + GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager); /// Count step cost of instruction void count(Instruction _inst); @@ -33,16 +34,15 @@ public: /// Generate code that checks the cost of additional memory used by program void checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder); - llvm::Value* getGas(); - private: /// Cumulative gas cost of a block of instructions /// @TODO Handle overflow uint64_t m_blockCost = 0; llvm::CallInst* m_checkCall = nullptr; - llvm::GlobalVariable* m_gas; llvm::Function* m_gasCheckFunc; + + RuntimeManager& m_runtimeManager; }; } diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 4d800535c..e37729e5b 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -31,17 +31,12 @@ llvm::StructType* RuntimeData::getType() static Runtime* g_runtime; -extern "C" -{ -EXPORT i256 gas; -} - Runtime::Runtime(u256 _gas, ExtVMFace& _ext): m_ext(_ext) { assert(!g_runtime); g_runtime = this; - gas = eth2llvm(_gas); + m_data.gas = eth2llvm(_gas); } Runtime::~Runtime() @@ -66,7 +61,7 @@ ExtVMFace& Runtime::getExt() u256 Runtime::getGas() { - return llvm2eth(gas); + return llvm2eth(m_data.gas); } @@ -81,6 +76,22 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_bui m_builder.CreateStore(dataPtr, m_dataPtr); } +llvm::Value* RuntimeManager::getGas() +{ + //auto gasPtr = m_builder.CreateConstGEP2_64(m_dataPtr, 0, 0); + auto rt = m_builder.CreateLoad(m_dataPtr); + auto gasPtr = m_builder.CreateStructGEP(rt, 0); + return m_builder.CreateLoad(gasPtr, "gas"); +} + +void RuntimeManager::setGas(llvm::Value* _gas) +{ + //auto gasPtr = m_builder.CreateStructGEP(m_dataPtr, 0); + auto rt = m_builder.CreateLoad(m_dataPtr); + auto gasPtr = m_builder.CreateStructGEP(rt, 0); + m_builder.CreateStore(_gas, gasPtr); +} + } } } diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index d9984966e..418555c04 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -46,7 +46,7 @@ public: static StackImpl& getStack(); static MemoryImpl& getMemory(); static ExtVMFace& getExt(); - static u256 getGas(); + u256 getGas(); private: @@ -63,6 +63,7 @@ public: RuntimeManager(llvm::IRBuilder<>& _builder); llvm::Value* getGas(); + void setGas(llvm::Value* _gas); private: llvm::GlobalVariable* m_dataPtr; From 9ec1ea526ac13e24853fedb2b969e473ddaa06f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 11:45:07 +0100 Subject: [PATCH 04/17] Access memory structure through runtime structure [#81470252] --- libevmjit/Compiler.cpp | 2 +- libevmjit/ExecutionEngine.cpp | 2 +- libevmjit/Ext.cpp | 9 ++--- libevmjit/Memory.cpp | 68 +++++++++++++++-------------------- libevmjit/Memory.h | 7 ++-- libevmjit/Runtime.cpp | 34 +++++++++++------- libevmjit/Runtime.h | 5 ++- 7 files changed, 66 insertions(+), 61 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index ddfe2497e..c3c09384b 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -179,7 +179,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); + Memory memory(m_builder, gasMeter, runtimeManager); Ext ext(m_builder); Stack stack(m_builder); diff --git a/libevmjit/ExecutionEngine.cpp b/libevmjit/ExecutionEngine.cpp index 5d5af553e..f7f30614c 100644 --- a/libevmjit/ExecutionEngine.cpp +++ b/libevmjit/ExecutionEngine.cpp @@ -121,7 +121,7 @@ int ExecutionEngine::run(std::unique_ptr _module, u256& _gas, ExtV if (returnCode == ReturnCode::Return) { - returnData = Memory::getReturnData().toVector(); // TODO: It might be better to place is in Runtime interface + returnData = runtime.getReturnData().toVector(); // TODO: It might be better to place is in Runtime interface std::cout << "RETURN [ "; for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 045d25b62..07023c674 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -306,7 +306,8 @@ EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256* 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); + //auto&& initRef = bytesConstRef(Runtime::getMemory().data() + initOff, initSize); + bytesConstRef initRef; OnOpFunc onOp{}; // TODO: Handle that thing h256 address = ext.create(endowment, &gas, initRef, onOp); *_address = address; @@ -332,8 +333,8 @@ EXPORT void ext_call(i256* _gas, h256* _receiveAddress, i256* _value, i256* _inO 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(); //Runtime::getMemory().data() + inOff, inSize); + auto&& outRef = bytesConstRef(); // Runtime::getMemory().data() + outOff, outSize); OnOpFunc onOp{}; // TODO: Handle that thing auto codeAddress = right160(*_codeAddress); ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, codeAddress); @@ -347,7 +348,7 @@ EXPORT void ext_sha3(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(); // Runtime::getMemory().data() + inOff, inSize); auto hash = sha3(dataRef); *_ret = *reinterpret_cast(&hash); } diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index 23d027ba4..8d7674885 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -15,6 +15,7 @@ #include "Runtime.h" #include "GasMeter.h" #include "Endianness.h" +#include "Runtime.h" namespace dev { @@ -23,7 +24,7 @@ namespace eth namespace jit { -Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter): +Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter, RuntimeManager& _runtimeManager): CompilerHelper(_builder) { auto module = getModule(); @@ -45,18 +46,19 @@ Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter): m_returnDataSize = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataSize"); m_returnDataSize->setUnnamedAddr(true); // Address is not important - m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), llvm::Function::ExternalLinkage, "mem_resize", module); + llvm::Type* resizeArgs[] = {RuntimeData::getType()->getPointerTo(), Type::WordPtr}; + m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, resizeArgs, false), llvm::Function::ExternalLinkage, "mem_resize", module); llvm::AttrBuilder attrBuilder; attrBuilder.addAttribute(llvm::Attribute::NoAlias).addAttribute(llvm::Attribute::NoCapture).addAttribute(llvm::Attribute::NonNull).addAttribute(llvm::Attribute::ReadOnly); m_resize->setAttributes(llvm::AttributeSet::get(m_resize->getContext(), 1, attrBuilder)); - m_require = createRequireFunc(_gasMeter); + m_require = createRequireFunc(_gasMeter, _runtimeManager); m_loadWord = createFunc(false, Type::i256, _gasMeter); m_storeWord = createFunc(true, Type::i256, _gasMeter); m_storeByte = createFunc(true, Type::Byte, _gasMeter); } -llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter) +llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager) { auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "mem.require", getModule()); @@ -83,7 +85,7 @@ llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter) _gasMeter.checkMemory(newWords, m_builder); // Resize m_builder.CreateStore(sizeRequired, m_size); - auto newData = m_builder.CreateCall(m_resize, m_size, "newData"); + auto newData = m_builder.CreateCall2(m_resize, _runtimeManager.getRuntimePtr(), m_size, "newData"); m_builder.CreateStore(newData, m_data); m_builder.CreateBr(returnBB); @@ -232,48 +234,36 @@ extern "C" using namespace dev::eth::jit; -EXPORT i256 mem_returnDataOffset; -EXPORT i256 mem_returnDataSize; - -EXPORT uint8_t* mem_resize(i256* _size) +EXPORT uint8_t* mem_resize(Runtime* _rt, i256* _size) { auto size = _size->a; // Trunc to 64-bit - auto& memory = Runtime::getMemory(); + auto& memory = _rt->getMemory(); memory.resize(size); return memory.data(); } EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end) { - if (_end == 0) - _end = Runtime::getMemory().size(); - - std::cerr << "MEMORY: active size: " << std::dec - << Runtime::getMemory().size() / 32 << " words\n"; - std::cerr << "MEMORY: dump from " << std::dec - << _begin << " to " << _end << ":"; - if (_end <= _begin) - return; - - _begin = _begin / 16 * 16; - for (size_t i = _begin; i < _end; i++) - { - if ((i - _begin) % 16 == 0) - std::cerr << '\n' << std::dec << i << ": "; - - auto b = Runtime::getMemory()[i]; - std::cerr << std::hex << std::setw(2) << static_cast(b) << ' '; - } - std::cerr << std::endl; + //if (_end == 0) + // _end = Runtime::getMemory().size(); + + //std::cerr << "MEMORY: active size: " << std::dec + // << Runtime::getMemory().size() / 32 << " words\n"; + //std::cerr << "MEMORY: dump from " << std::dec + // << _begin << " to " << _end << ":"; + //if (_end <= _begin) + // return; + + //_begin = _begin / 16 * 16; + //for (size_t i = _begin; i < _end; i++) + //{ + // if ((i - _begin) % 16 == 0) + // std::cerr << '\n' << std::dec << i << ": "; + + // auto b = Runtime::getMemory()[i]; + // std::cerr << std::hex << std::setw(2) << static_cast(b) << ' '; + //} + //std::cerr << std::endl; } } // extern "C" - -dev::bytesConstRef dev::eth::jit::Memory::getReturnData() -{ - // TODO: Handle large indexes - auto offset = static_cast(llvm2eth(mem_returnDataOffset)); - auto size = static_cast(llvm2eth(mem_returnDataSize)); - auto& memory = Runtime::getMemory(); - return {memory.data() + offset, size}; -} diff --git a/libevmjit/Memory.h b/libevmjit/Memory.h index 2ab09c127..d92538247 100644 --- a/libevmjit/Memory.h +++ b/libevmjit/Memory.h @@ -10,11 +10,12 @@ namespace eth { namespace jit { +class RuntimeManager; class Memory : public CompilerHelper { public: - Memory(llvm::IRBuilder<>& _builder, class GasMeter& _gasMeter); + Memory(llvm::IRBuilder<>& _builder, class GasMeter& _gasMeter, RuntimeManager& _runtimeManager); llvm::Value* loadWord(llvm::Value* _addr); void storeWord(llvm::Value* _addr, llvm::Value* _word); @@ -31,13 +32,13 @@ public: void require(llvm::Value* _offset, llvm::Value* _size); void registerReturnData(llvm::Value* _index, llvm::Value* _size); - static bytesConstRef getReturnData(); + bytesConstRef getReturnData(); void dump(uint64_t _begin, uint64_t _end = 0); private: llvm::Function* createFunc(bool _isStore, llvm::Type* _type, GasMeter& _gasMeter); - llvm::Function* createRequireFunc(GasMeter& _gasMeter); + llvm::Function* createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager); private: llvm::GlobalVariable* m_data; diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index e37729e5b..37e414b17 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -29,7 +29,7 @@ llvm::StructType* RuntimeData::getType() return type; } -static Runtime* g_runtime; +static Runtime* g_runtime; // FIXME: Remove Runtime::Runtime(u256 _gas, ExtVMFace& _ext): m_ext(_ext) @@ -49,11 +49,6 @@ StackImpl& Runtime::getStack() return g_runtime->m_stack; } -MemoryImpl& Runtime::getMemory() -{ - return g_runtime->m_memory; -} - ExtVMFace& Runtime::getExt() { return g_runtime->m_ext; @@ -64,6 +59,19 @@ u256 Runtime::getGas() return llvm2eth(m_data.gas); } +extern "C" { + EXPORT i256 mem_returnDataOffset; // FIXME: Dis-globalize + EXPORT i256 mem_returnDataSize; +} + +bytesConstRef Runtime::getReturnData() +{ + // TODO: Handle large indexes + auto offset = static_cast(llvm2eth(mem_returnDataOffset)); + auto size = static_cast(llvm2eth(mem_returnDataSize)); + return{getMemory().data() + offset, size}; +} + RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder) { @@ -76,19 +84,21 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_bui m_builder.CreateStore(dataPtr, m_dataPtr); } +llvm::Value* RuntimeManager::getRuntimePtr() +{ + // TODO: If in main function - get it from param + return m_builder.CreateLoad(m_dataPtr); +} + llvm::Value* RuntimeManager::getGas() { - //auto gasPtr = m_builder.CreateConstGEP2_64(m_dataPtr, 0, 0); - auto rt = m_builder.CreateLoad(m_dataPtr); - auto gasPtr = m_builder.CreateStructGEP(rt, 0); + auto gasPtr = m_builder.CreateStructGEP(getRuntimePtr(), 0); return m_builder.CreateLoad(gasPtr, "gas"); } void RuntimeManager::setGas(llvm::Value* _gas) { - //auto gasPtr = m_builder.CreateStructGEP(m_dataPtr, 0); - auto rt = m_builder.CreateLoad(m_dataPtr); - auto gasPtr = m_builder.CreateStructGEP(rt, 0); + auto gasPtr = m_builder.CreateStructGEP(getRuntimePtr(), 0); m_builder.CreateStore(_gas, gasPtr); } diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 418555c04..87f43f786 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -44,9 +44,10 @@ public: RuntimeData* getDataPtr() { return &m_data; } static StackImpl& getStack(); - static MemoryImpl& getMemory(); + MemoryImpl& getMemory() { return m_memory; } static ExtVMFace& getExt(); u256 getGas(); + bytesConstRef getReturnData(); private: @@ -62,6 +63,8 @@ class RuntimeManager: public CompilerHelper public: RuntimeManager(llvm::IRBuilder<>& _builder); + llvm::Value* getRuntimePtr(); + llvm::Value* getGas(); void setGas(llvm::Value* _gas); From f81971bae852f5aea0b3dfda60a9357b96a9622d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 12:16:33 +0100 Subject: [PATCH 05/17] Add Type::RuntimePtr predefined LLVM type --- libevmjit/Type.cpp | 4 ++++ libevmjit/Type.h | 2 ++ 2 files changed, 6 insertions(+) diff --git a/libevmjit/Type.cpp b/libevmjit/Type.cpp index baf458dbd..5021473ff 100644 --- a/libevmjit/Type.cpp +++ b/libevmjit/Type.cpp @@ -3,6 +3,8 @@ #include +#include "Runtime.h" + namespace dev { namespace eth @@ -18,6 +20,7 @@ llvm::IntegerType* Type::Byte; llvm::PointerType* Type::BytePtr; llvm::Type* Type::Void; llvm::IntegerType* Type::MainReturn; +llvm::PointerType* Type::RuntimePtr; void Type::init(llvm::LLVMContext& _context) { @@ -30,6 +33,7 @@ void Type::init(llvm::LLVMContext& _context) BytePtr = Byte->getPointerTo(); Void = llvm::Type::getVoidTy(_context); MainReturn = llvm::Type::getInt32Ty(_context); + RuntimePtr = RuntimeData::getType()->getPointerTo(); } llvm::ConstantInt* Constant::get(uint64_t _n) diff --git a/libevmjit/Type.h b/libevmjit/Type.h index 16a13c373..86915cd9e 100644 --- a/libevmjit/Type.h +++ b/libevmjit/Type.h @@ -30,6 +30,8 @@ struct Type /// Main function return type static llvm::IntegerType* MainReturn; + static llvm::PointerType* RuntimePtr; + static void init(llvm::LLVMContext& _context); }; From 0d4ca779ff7f4ad455d08fc0820d4a2552cf0dcc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 12:17:04 +0100 Subject: [PATCH 06/17] Access stack structure through runtime structure [#81470252] --- libevmjit/Compiler.cpp | 2 +- libevmjit/Runtime.cpp | 4 ---- libevmjit/Runtime.h | 2 +- libevmjit/Stack.cpp | 44 ++++++++++++++++++++++++------------------ libevmjit/Stack.h | 4 +++- 5 files changed, 30 insertions(+), 26 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index c3c09384b..b20d5ae9c 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -181,7 +181,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) GasMeter gasMeter(m_builder, runtimeManager); Memory memory(m_builder, gasMeter, runtimeManager); Ext ext(m_builder); - Stack stack(m_builder); + Stack stack(m_builder, runtimeManager); m_builder.CreateBr(basicBlocks.begin()->second); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 37e414b17..a41d5e296 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -44,10 +44,6 @@ Runtime::~Runtime() g_runtime = nullptr; } -StackImpl& Runtime::getStack() -{ - return g_runtime->m_stack; -} ExtVMFace& Runtime::getExt() { diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 87f43f786..dc617b777 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -43,7 +43,7 @@ public: RuntimeData* getDataPtr() { return &m_data; } - static StackImpl& getStack(); + StackImpl& getStack() { return m_stack; } MemoryImpl& getMemory() { return m_memory; } static ExtVMFace& getExt(); u256 getGas(); diff --git a/libevmjit/Stack.cpp b/libevmjit/Stack.cpp index 89044bea8..6c287dc6a 100644 --- a/libevmjit/Stack.cpp +++ b/libevmjit/Stack.cpp @@ -14,8 +14,9 @@ namespace eth namespace jit { -Stack::Stack(llvm::IRBuilder<>& _builder) - : CompilerHelper(_builder) +Stack::Stack(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager) + : CompilerHelper(_builder), + m_runtimeManager(_runtimeManager) { m_arg = m_builder.CreateAlloca(Type::i256, nullptr, "stack.arg"); @@ -23,11 +24,16 @@ Stack::Stack(llvm::IRBuilder<>& _builder) using Linkage = GlobalValue::LinkageTypes; auto module = getModule(); - m_push = Function::Create(FunctionType::get(m_builder.getVoidTy(), Type::WordPtr, false), Linkage::ExternalLinkage, "stack_push", module); - m_pop = Function::Create(FunctionType::get(m_builder.getVoidTy(), Type::Size, false), Linkage::ExternalLinkage, "stack_pop", module); - llvm::Type* getSetArgTypes[] = {Type::Size, Type::WordPtr}; - m_get = Function::Create(FunctionType::get(m_builder.getVoidTy(), ArrayRef(getSetArgTypes), false), Linkage::ExternalLinkage, "stack_get", module); - m_set = Function::Create(FunctionType::get(m_builder.getVoidTy(), ArrayRef(getSetArgTypes), false), Linkage::ExternalLinkage, "stack_set", module); + + llvm::Type* pushArgTypes[] = {Type::RuntimePtr, Type::WordPtr}; + m_push = Function::Create(FunctionType::get(Type::Void, pushArgTypes, false), Linkage::ExternalLinkage, "stack_push", module); + + llvm::Type* popArgTypes[] = {Type::RuntimePtr, Type::Size}; + m_pop = Function::Create(FunctionType::get(Type::Void, popArgTypes, false), Linkage::ExternalLinkage, "stack_pop", module); + + llvm::Type* getSetArgTypes[] = {Type::RuntimePtr, Type::Size, Type::WordPtr}; + m_get = Function::Create(FunctionType::get(Type::Void, getSetArgTypes, false), Linkage::ExternalLinkage, "stack_get", module); + m_set = Function::Create(FunctionType::get(Type::Void, getSetArgTypes, false), Linkage::ExternalLinkage, "stack_set", module); } Stack::~Stack() @@ -35,25 +41,25 @@ Stack::~Stack() llvm::Value* Stack::get(size_t _index) { - m_builder.CreateCall2(m_get, llvm::ConstantInt::get(Type::Size, _index, false), m_arg); + m_builder.CreateCall3(m_get, m_runtimeManager.getRuntimePtr(), llvm::ConstantInt::get(Type::Size, _index, false), m_arg); return m_builder.CreateLoad(m_arg); } void Stack::set(size_t _index, llvm::Value* _value) { m_builder.CreateStore(_value, m_arg); - m_builder.CreateCall2(m_set, llvm::ConstantInt::get(Type::Size, _index, false), m_arg); + m_builder.CreateCall3(m_set, m_runtimeManager.getRuntimePtr(), llvm::ConstantInt::get(Type::Size, _index, false), m_arg); } void Stack::pop(size_t _count) { - m_builder.CreateCall(m_pop, llvm::ConstantInt::get(Type::Size, _count, false)); + m_builder.CreateCall2(m_pop, m_runtimeManager.getRuntimePtr(), llvm::ConstantInt::get(Type::Size, _count, false)); } void Stack::push(llvm::Value* _value) { m_builder.CreateStore(_value, m_arg); - m_builder.CreateCall(m_push, m_arg); + m_builder.CreateCall2(m_push, m_runtimeManager.getRuntimePtr(), m_arg); } @@ -70,27 +76,27 @@ using namespace dev::eth::jit; extern std::jmp_buf* rt_jmpBuf; -EXPORT void stack_pop(uint64_t _count) +EXPORT void stack_pop(Runtime* _rt, uint64_t _count) { - auto& stack = Runtime::getStack(); + auto& stack = _rt->getStack(); if (stack.size() < _count) longjmp(*rt_jmpBuf, static_cast(ReturnCode::StackTooSmall)); stack.erase(stack.end() - _count, stack.end()); } -EXPORT void stack_push(i256* _word) +EXPORT void stack_push(Runtime* _rt, i256* _word) { - auto& stack = Runtime::getStack(); + auto& stack = _rt->getStack(); stack.push_back(*_word); if (stack.size() > Stack::maxStackSize) Stack::maxStackSize = stack.size(); } -EXPORT void stack_get(uint64_t _index, i256* _ret) +EXPORT void stack_get(Runtime* _rt, uint64_t _index, i256* _ret) { - auto& stack = Runtime::getStack(); + 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)); @@ -98,9 +104,9 @@ EXPORT void stack_get(uint64_t _index, i256* _ret) *_ret = *(stack.rbegin() + _index); } -EXPORT void stack_set(uint64_t _index, i256* _word) +EXPORT void stack_set(Runtime* _rt, uint64_t _index, i256* _word) { - auto& stack = Runtime::getStack(); + 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)); diff --git a/libevmjit/Stack.h b/libevmjit/Stack.h index 2380b2a15..db9032ec4 100644 --- a/libevmjit/Stack.h +++ b/libevmjit/Stack.h @@ -10,12 +10,13 @@ namespace eth { namespace jit { +class RuntimeManager; class Stack : public CompilerHelper { public: - Stack(llvm::IRBuilder<>& builder); + Stack(llvm::IRBuilder<>& builder, RuntimeManager& runtimeManager); virtual ~Stack(); llvm::Value* get(size_t _index); @@ -26,6 +27,7 @@ public: static size_t maxStackSize; private: + RuntimeManager& m_runtimeManager; llvm::Function* m_push; llvm::Function* m_pop; From 5d3afa175606067fae4c37e441b80a295386a99d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 12:19:02 +0100 Subject: [PATCH 07/17] Use Type::RuntimePtr instead of RuntimeData::getType->getPointerTo() --- libevmjit/Compiler.cpp | 2 +- libevmjit/Memory.cpp | 2 +- libevmjit/Runtime.cpp | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index b20d5ae9c..5061dabb0 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -166,7 +166,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) auto module = std::make_unique("main", m_builder.getContext()); // Create main function - llvm::Type* mainFuncArgTypes[] = {m_builder.getInt32Ty(), RuntimeData::getType()->getPointerTo()}; // There must be int in first place because LLVM does not support other signatures + 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()); diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index 8d7674885..fa5a2b0dd 100644 --- a/libevmjit/Memory.cpp +++ b/libevmjit/Memory.cpp @@ -46,7 +46,7 @@ Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter, RuntimeManager& 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[] = {RuntimeData::getType()->getPointerTo(), Type::WordPtr}; + 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; attrBuilder.addAttribute(llvm::Attribute::NoAlias).addAttribute(llvm::Attribute::NoCapture).addAttribute(llvm::Attribute::NonNull).addAttribute(llvm::Attribute::ReadOnly); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index a41d5e296..e09db52c9 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -71,8 +71,7 @@ bytesConstRef Runtime::getReturnData() RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder) { - auto dataPtrType = RuntimeData::getType()->getPointerTo(); - m_dataPtr = new llvm::GlobalVariable(*getModule(), dataPtrType, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(dataPtrType), "rt"); + m_dataPtr = new llvm::GlobalVariable(*getModule(), Type::RuntimePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::RuntimePtr), "rt"); // Export data auto mainFunc = getMainFunction(); From 7ec7977fc457952f9a8ec8b4f50542ca7619f154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 12:42:32 +0100 Subject: [PATCH 08/17] Introducing RuntimeHelper - a compiler helper that depends on runtime data [#81470252] --- libevmjit/CompilerHelper.cpp | 8 ++++++++ libevmjit/CompilerHelper.h | 17 +++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/libevmjit/CompilerHelper.cpp b/libevmjit/CompilerHelper.cpp index b919043f2..c2d612c66 100644 --- a/libevmjit/CompilerHelper.cpp +++ b/libevmjit/CompilerHelper.cpp @@ -3,6 +3,8 @@ #include +#include "Runtime.h" + namespace dev { namespace eth @@ -29,6 +31,12 @@ llvm::Function* CompilerHelper::getMainFunction() return mainFunc; } + +RuntimeHelper::RuntimeHelper(RuntimeManager& _runtimeManager): + CompilerHelper(_runtimeManager.getBuilder()), + m_runtimeManager(_runtimeManager) +{} + } } } diff --git a/libevmjit/CompilerHelper.h b/libevmjit/CompilerHelper.h index 23bbcbd11..cf83d70cd 100644 --- a/libevmjit/CompilerHelper.h +++ b/libevmjit/CompilerHelper.h @@ -10,6 +10,7 @@ namespace eth { namespace jit { +class RuntimeManager; /// Base class for compiler helpers like Memory, GasMeter, etc. class CompilerHelper @@ -28,6 +29,22 @@ protected: /// Reference to parent compiler IR builder llvm::IRBuilder<>& m_builder; + llvm::IRBuilder<>& getBuilder() { return m_builder; } + + friend class RuntimeHelper; +}; + + +/// Compiler helper that depends on runtime data +class RuntimeHelper : public CompilerHelper +{ +protected: + RuntimeHelper(RuntimeManager& _runtimeManager); + + RuntimeManager& getRuntimeManager() { return m_runtimeManager; } + +private: + RuntimeManager& m_runtimeManager; }; From c7ccf546fcc75360d30b710f4c5f2bce66fd5bb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 14:18:39 +0100 Subject: [PATCH 09/17] Moving ADDRESS data from Ext to Runtime [#81470252] --- libevmjit/Compiler.cpp | 6 +++--- libevmjit/Ext.cpp | 8 +++----- libevmjit/Ext.h | 5 ++--- libevmjit/Runtime.cpp | 33 +++++++++++++++++++++++---------- libevmjit/Runtime.h | 19 +++++++++++++++---- 5 files changed, 46 insertions(+), 25 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 5061dabb0..26d5c6f19 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -180,7 +180,7 @@ std::unique_ptr Compiler::compile(bytesConstRef bytecode) RuntimeManager runtimeManager(m_builder); GasMeter gasMeter(m_builder, runtimeManager); Memory memory(m_builder, gasMeter, runtimeManager); - Ext ext(m_builder); + Ext ext(runtimeManager); Stack stack(m_builder, runtimeManager); m_builder.CreateBr(basicBlocks.begin()->second); @@ -686,7 +686,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::ADDRESS: { - auto value = ext.address(); + auto value = _runtimeManager.get(RuntimeData::Address); stack.push(value); break; } @@ -873,7 +873,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto receiveAddress = codeAddress; if (inst == Instruction::CALLCODE) - receiveAddress = ext.address(); + receiveAddress = _runtimeManager.get(RuntimeData::Address); auto ret = ext.call(gas, receiveAddress, value, inOff, inSize, outOff, outSize, codeAddress); gasMeter.giveBack(gas); diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 07023c674..2e38aef27 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -44,10 +44,10 @@ struct ExtData const byte* code; }; -Ext::Ext(llvm::IRBuilder<>& _builder): - CompilerHelper(_builder) +Ext::Ext(RuntimeManager& _runtimeManager): + RuntimeHelper(_runtimeManager) { - auto&& ctx = _builder.getContext(); + auto&& ctx = m_builder.getContext(); auto module = getModule(); auto i256Ty = m_builder.getIntNTy(256); @@ -126,7 +126,6 @@ Value* Ext::getDataElem(unsigned _index, const Twine& _name) return m_builder.CreateLoad(valuePtr); } -Value* Ext::address() { return getDataElem(0, "address"); } Value* Ext::caller() { return getDataElem(1, "caller"); } Value* Ext::origin() { return getDataElem(2, "origin"); } Value* Ext::callvalue() { return getDataElem(3, "callvalue"); } @@ -243,7 +242,6 @@ using namespace dev::eth::jit; EXPORT void ext_init(ExtData* _extData) { auto&& ext = Runtime::getExt(); - _extData->address = eth2llvm(fromAddress(ext.myAddress)); _extData->caller = eth2llvm(fromAddress(ext.caller)); _extData->origin = eth2llvm(fromAddress(ext.origin)); _extData->callvalue = eth2llvm(ext.value); diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index 361b6e47e..6d8501d29 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -12,15 +12,14 @@ namespace eth namespace jit { -class Ext : public CompilerHelper +class Ext : public RuntimeHelper { public: - Ext(llvm::IRBuilder<>& _builder); + Ext(RuntimeManager& _runtimeManager); llvm::Value* store(llvm::Value* _index); void setStore(llvm::Value* _index, llvm::Value* _value); - llvm::Value* address(); llvm::Value* caller(); llvm::Value* origin(); llvm::Value* callvalue(); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index e09db52c9..bf231cc10 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -22,7 +22,7 @@ llvm::StructType* RuntimeData::getType() { llvm::Type* elems[] = { - Type::i256, + llvm::ArrayType::get(Type::i256, _size) }; type = llvm::StructType::create(elems, "RuntimeData"); } @@ -36,7 +36,8 @@ Runtime::Runtime(u256 _gas, ExtVMFace& _ext): { assert(!g_runtime); g_runtime = this; - m_data.gas = eth2llvm(_gas); + set(RuntimeData::Gas, _gas); + set(RuntimeData::Address, fromAddress(_ext.myAddress)); } Runtime::~Runtime() @@ -44,15 +45,20 @@ Runtime::~Runtime() g_runtime = nullptr; } +void Runtime::set(RuntimeData::Index _index, u256 _value) +{ + m_data.elems[_index] = eth2llvm(_value); +} + ExtVMFace& Runtime::getExt() { return g_runtime->m_ext; } -u256 Runtime::getGas() +u256 Runtime::getGas() const { - return llvm2eth(m_data.gas); + return llvm2eth(m_data.elems[RuntimeData::Gas]); } extern "C" { @@ -60,12 +66,12 @@ extern "C" { EXPORT i256 mem_returnDataSize; } -bytesConstRef Runtime::getReturnData() +bytesConstRef Runtime::getReturnData() const { // TODO: Handle large indexes auto offset = static_cast(llvm2eth(mem_returnDataOffset)); auto size = static_cast(llvm2eth(mem_returnDataSize)); - return{getMemory().data() + offset, size}; + return {m_memory.data() + offset, size}; } @@ -85,16 +91,23 @@ llvm::Value* RuntimeManager::getRuntimePtr() return m_builder.CreateLoad(m_dataPtr); } +llvm::Value* RuntimeManager::get(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, "dataElemPtr"); + return m_builder.CreateLoad(ptr); +} + llvm::Value* RuntimeManager::getGas() { - auto gasPtr = m_builder.CreateStructGEP(getRuntimePtr(), 0); - return m_builder.CreateLoad(gasPtr, "gas"); + return get(RuntimeData::Gas); } void RuntimeManager::setGas(llvm::Value* _gas) { - auto gasPtr = m_builder.CreateStructGEP(getRuntimePtr(), 0); - m_builder.CreateStore(_gas, gasPtr); + llvm::Value* idxList[] = {m_builder.getInt32(0), m_builder.getInt32(0), m_builder.getInt32(RuntimeData::Gas)}; + auto ptr = m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, "gasPtr"); + m_builder.CreateStore(_gas, ptr); } } diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index dc617b777..8b2efe8ed 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -24,9 +24,17 @@ namespace jit struct RuntimeData { - static llvm::StructType* getType(); + enum Index: unsigned + { + Gas, + Address, + + _size + }; + + i256 elems[_size]; - i256 gas; + static llvm::StructType* getType(); }; using StackImpl = std::vector; @@ -46,10 +54,12 @@ public: StackImpl& getStack() { return m_stack; } MemoryImpl& getMemory() { return m_memory; } static ExtVMFace& getExt(); - u256 getGas(); - bytesConstRef getReturnData(); + + u256 getGas() const; + bytesConstRef getReturnData() const; private: + void set(RuntimeData::Index _index, u256 _value); /// @internal Must be the first element to asure Runtime* === RuntimeData* RuntimeData m_data; @@ -65,6 +75,7 @@ public: llvm::Value* getRuntimePtr(); + llvm::Value* get(RuntimeData::Index _index); llvm::Value* getGas(); void setGas(llvm::Value* _gas); From 669612cdcf3b6e5e833564a473b60468b65d71a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 14:30:36 +0100 Subject: [PATCH 10/17] Add name to data indices [#81470252] --- libevmjit/Runtime.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index bf231cc10..779ffe8a9 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -29,6 +29,19 @@ llvm::StructType* RuntimeData::getType() return type; } +namespace +{ +llvm::Twine getName(RuntimeData::Index _index) +{ + switch (_index) + { + default: return "data"; + case RuntimeData::Gas: return "gas"; + case RuntimeData::Address: return "address"; + } +} +} + static Runtime* g_runtime; // FIXME: Remove Runtime::Runtime(u256 _gas, ExtVMFace& _ext): @@ -94,8 +107,8 @@ llvm::Value* RuntimeManager::getRuntimePtr() llvm::Value* RuntimeManager::get(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, "dataElemPtr"); - return m_builder.CreateLoad(ptr); + auto ptr = m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, getName(_index) + "Ptr"); + return m_builder.CreateLoad(ptr, getName(_index)); } llvm::Value* RuntimeManager::getGas() From ae89279c1af56ee01b7b76eff7691cc73ff4fc50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 14:42:47 +0100 Subject: [PATCH 11/17] Moving ORIGIN, CALLER & CALLVALUE data from Ext to Runtime [#81470252] --- libevmjit/Compiler.cpp | 6 +++--- libevmjit/Ext.cpp | 36 +++++++++++------------------------- libevmjit/Ext.h | 3 --- libevmjit/Runtime.cpp | 12 +++++++++--- libevmjit/Runtime.h | 3 +++ 5 files changed, 26 insertions(+), 34 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 26d5c6f19..ccdc21e39 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -701,21 +701,21 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::CALLER: { - auto value = ext.caller(); + auto value = _runtimeManager.get(RuntimeData::Caller); stack.push(value); break; } case Instruction::ORIGIN: { - auto value = ext.origin(); + auto value = _runtimeManager.get(RuntimeData::Origin); stack.push(value); break; } case Instruction::CALLVALUE: { - auto value = ext.callvalue(); + auto value = _runtimeManager.get(RuntimeData::CallValue); stack.push(value); break; } diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 2e38aef27..741bd9993 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -27,10 +27,6 @@ inline u256 fromAddress(Address _a) struct ExtData { - i256 address; - i256 caller; - i256 origin; - i256 callvalue; i256 calldatasize; i256 gasprice; i256 prevhash; @@ -65,10 +61,6 @@ Ext::Ext(RuntimeManager& _runtimeManager): m_arg8 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); Type* elements[] = { - i256Ty, // i256 address; - i256Ty, // i256 caller; - i256Ty, // i256 origin; - i256Ty, // i256 callvalue; i256Ty, // i256 calldatasize; i256Ty, // i256 gasprice; i256Ty, // i256 prevhash; @@ -126,20 +118,17 @@ Value* Ext::getDataElem(unsigned _index, const Twine& _name) return m_builder.CreateLoad(valuePtr); } -Value* Ext::caller() { return getDataElem(1, "caller"); } -Value* Ext::origin() { return getDataElem(2, "origin"); } -Value* Ext::callvalue() { return getDataElem(3, "callvalue"); } -Value* Ext::calldatasize() { return getDataElem(4, "calldatasize"); } -Value* Ext::gasprice() { return getDataElem(5, "gasprice"); } -Value* Ext::prevhash() { return getDataElem(6, "prevhash"); } -Value* Ext::coinbase() { return getDataElem(7, "coinbase"); } -Value* Ext::timestamp() { return getDataElem(8, "timestamp"); } -Value* Ext::number() { return getDataElem(9, "number"); } -Value* Ext::difficulty() { return getDataElem(10, "difficulty"); } -Value* Ext::gaslimit() { return getDataElem(11, "gaslimit"); } -Value* Ext::codesize() { return getDataElem(12, "codesize"); } -Value* Ext::calldata() { return getDataElem(13, "calldata"); } -Value* Ext::code() { return getDataElem(14, "code"); } +Value* Ext::calldatasize() { return getDataElem(0, "calldatasize"); } +Value* Ext::gasprice() { return getDataElem(1, "gasprice"); } +Value* Ext::prevhash() { return getDataElem(2, "prevhash"); } +Value* Ext::coinbase() { return getDataElem(3, "coinbase"); } +Value* Ext::timestamp() { return getDataElem(4, "timestamp"); } +Value* Ext::number() { return getDataElem(5, "number"); } +Value* Ext::difficulty() { return getDataElem(6, "difficulty"); } +Value* Ext::gaslimit() { return getDataElem(7, "gaslimit"); } +Value* Ext::codesize() { return getDataElem(8, "codesize"); } +Value* Ext::calldata() { return getDataElem(9, "calldata"); } +Value* Ext::code() { return getDataElem(10, "code"); } Value* Ext::calldataload(Value* _index) { @@ -242,9 +231,6 @@ using namespace dev::eth::jit; EXPORT void ext_init(ExtData* _extData) { auto&& ext = Runtime::getExt(); - _extData->caller = eth2llvm(fromAddress(ext.caller)); - _extData->origin = eth2llvm(fromAddress(ext.origin)); - _extData->callvalue = eth2llvm(ext.value); _extData->gasprice = eth2llvm(ext.gasPrice); _extData->calldatasize = eth2llvm(ext.data.size()); _extData->prevhash = eth2llvm(ext.previousBlock.hash); diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index 6d8501d29..5585f9d05 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -20,9 +20,6 @@ public: llvm::Value* store(llvm::Value* _index); void setStore(llvm::Value* _index, llvm::Value* _value); - llvm::Value* caller(); - llvm::Value* origin(); - llvm::Value* callvalue(); llvm::Value* calldatasize(); llvm::Value* gasprice(); llvm::Value* prevhash(); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 779ffe8a9..374398b69 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -35,9 +35,12 @@ llvm::Twine getName(RuntimeData::Index _index) { switch (_index) { - default: return "data"; - case RuntimeData::Gas: return "gas"; - case RuntimeData::Address: return "address"; + default: return "data"; + case RuntimeData::Gas: return "gas"; + case RuntimeData::Address: return "address"; + case RuntimeData::Caller: return "caller"; + case RuntimeData::Origin: return "origin"; + case RuntimeData::CallValue: return "callvalue"; } } } @@ -51,6 +54,9 @@ Runtime::Runtime(u256 _gas, ExtVMFace& _ext): g_runtime = this; set(RuntimeData::Gas, _gas); set(RuntimeData::Address, fromAddress(_ext.myAddress)); + set(RuntimeData::Caller, fromAddress(_ext.caller)); + set(RuntimeData::Origin, fromAddress(_ext.origin)); + set(RuntimeData::CallValue, _ext.value); } Runtime::~Runtime() diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 8b2efe8ed..3300b4106 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -28,6 +28,9 @@ struct RuntimeData { Gas, Address, + Caller, + Origin, + CallValue, _size }; From 6facdd0df6ba67c0ee0b48ec2905a06ce644aac5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 15:05:21 +0100 Subject: [PATCH 12/17] Moving the rest word-size data from Ext to Runtime [#81470252] --- libevmjit/Compiler.cpp | 24 ++++++++++++------------ libevmjit/Ext.cpp | 40 ++-------------------------------------- libevmjit/Ext.h | 9 --------- libevmjit/Runtime.cpp | 18 ++++++++++++++++++ libevmjit/Runtime.h | 9 +++++++++ 5 files changed, 41 insertions(+), 59 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index ccdc21e39..e711fe706 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -722,14 +722,14 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, case Instruction::CALLDATASIZE: { - auto value = ext.calldatasize(); + auto value = _runtimeManager.get(RuntimeData::CallDataSize); stack.push(value); break; } case Instruction::CODESIZE: { - auto value = ext.codesize(); + auto value = _runtimeManager.get(RuntimeData::CodeSize); stack.push(value); break; } @@ -749,7 +749,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto reqBytes = stack.pop(); auto srcPtr = ext.calldata(); - auto srcSize = ext.calldatasize(); + auto srcSize = _runtimeManager.get(RuntimeData::CallDataSize); memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); break; @@ -762,7 +762,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto reqBytes = stack.pop(); auto srcPtr = ext.code(); // TODO: Code & its size are constants, feature #80814234 - auto srcSize = ext.codesize(); + auto srcSize = _runtimeManager.get(RuntimeData::CodeSize); memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); break; @@ -791,50 +791,50 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, } case Instruction::GASPRICE: - { - auto value = ext.gasprice(); + { + auto value = _runtimeManager.get(RuntimeData::GasPrice); stack.push(value); break; } case Instruction::PREVHASH: { - auto value = ext.prevhash(); + auto value = _runtimeManager.get(RuntimeData::PrevHash); stack.push(value); break; } case Instruction::COINBASE: { - auto value = ext.coinbase(); + auto value = _runtimeManager.get(RuntimeData::CoinBase); stack.push(value); break; } case Instruction::TIMESTAMP: { - auto value = ext.timestamp(); + auto value = _runtimeManager.get(RuntimeData::TimeStamp); stack.push(value); break; } case Instruction::NUMBER: { - auto value = ext.number(); + auto value = _runtimeManager.get(RuntimeData::Number); stack.push(value); break; } case Instruction::DIFFICULTY: { - auto value = ext.difficulty(); + auto value = _runtimeManager.get(RuntimeData::Difficulty); stack.push(value); break; } case Instruction::GASLIMIT: { - auto value = ext.gaslimit(); + auto value = _runtimeManager.get(RuntimeData::GasLimit); stack.push(value); break; } diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 741bd9993..1adaf741c 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -27,15 +27,6 @@ inline u256 fromAddress(Address _a) struct ExtData { - i256 calldatasize; - i256 gasprice; - i256 prevhash; - i256 coinbase; - i256 timestamp; - i256 number; - i256 difficulty; - i256 gaslimit; - i256 codesize; const byte* calldata; const byte* code; }; @@ -61,15 +52,6 @@ Ext::Ext(RuntimeManager& _runtimeManager): m_arg8 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); Type* elements[] = { - i256Ty, // i256 calldatasize; - i256Ty, // i256 gasprice; - i256Ty, // i256 prevhash; - i256Ty, // i256 coinbase; - i256Ty, // i256 timestamp; - i256Ty, // i256 number; - i256Ty, // i256 difficulty; - i256Ty, // i256 gaslimit; - i256Ty, // i256 codesize i8PtrTy, // byte* calldata i8PtrTy, // byte* code @@ -118,17 +100,8 @@ Value* Ext::getDataElem(unsigned _index, const Twine& _name) return m_builder.CreateLoad(valuePtr); } -Value* Ext::calldatasize() { return getDataElem(0, "calldatasize"); } -Value* Ext::gasprice() { return getDataElem(1, "gasprice"); } -Value* Ext::prevhash() { return getDataElem(2, "prevhash"); } -Value* Ext::coinbase() { return getDataElem(3, "coinbase"); } -Value* Ext::timestamp() { return getDataElem(4, "timestamp"); } -Value* Ext::number() { return getDataElem(5, "number"); } -Value* Ext::difficulty() { return getDataElem(6, "difficulty"); } -Value* Ext::gaslimit() { return getDataElem(7, "gaslimit"); } -Value* Ext::codesize() { return getDataElem(8, "codesize"); } -Value* Ext::calldata() { return getDataElem(9, "calldata"); } -Value* Ext::code() { return getDataElem(10, "code"); } +Value* Ext::calldata() { return getDataElem(0, "calldata"); } +Value* Ext::code() { return getDataElem(1, "code"); } Value* Ext::calldataload(Value* _index) { @@ -231,15 +204,6 @@ using namespace dev::eth::jit; EXPORT void ext_init(ExtData* _extData) { auto&& ext = Runtime::getExt(); - _extData->gasprice = eth2llvm(ext.gasPrice); - _extData->calldatasize = eth2llvm(ext.data.size()); - _extData->prevhash = eth2llvm(ext.previousBlock.hash); - _extData->coinbase = eth2llvm(fromAddress(ext.currentBlock.coinbaseAddress)); - _extData->timestamp = eth2llvm(ext.currentBlock.timestamp); - _extData->number = eth2llvm(ext.currentBlock.number); - _extData->difficulty = eth2llvm(ext.currentBlock.difficulty); - _extData->gaslimit = eth2llvm(ext.currentBlock.gasLimit); - _extData->codesize = eth2llvm(ext.code.size()); _extData->calldata = ext.data.data(); _extData->code = ext.code.data(); } diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index 5585f9d05..62938f3cb 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -20,15 +20,6 @@ public: llvm::Value* store(llvm::Value* _index); void setStore(llvm::Value* _index, llvm::Value* _value); - llvm::Value* calldatasize(); - llvm::Value* gasprice(); - llvm::Value* prevhash(); - llvm::Value* coinbase(); - llvm::Value* timestamp(); - llvm::Value* number(); - llvm::Value* difficulty(); - llvm::Value* gaslimit(); - llvm::Value* codesize(); llvm::Value* calldata(); llvm::Value* code(); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 374398b69..42d2fe52f 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -41,6 +41,15 @@ llvm::Twine getName(RuntimeData::Index _index) case RuntimeData::Caller: return "caller"; case RuntimeData::Origin: return "origin"; case RuntimeData::CallValue: return "callvalue"; + case RuntimeData::CallDataSize: return "calldatasize"; + case RuntimeData::GasPrice: return "gasprice"; + case RuntimeData::PrevHash: return "prevhash"; + case RuntimeData::CoinBase: return "coinbase"; + case RuntimeData::TimeStamp: return "timestamp"; + case RuntimeData::Number: return "number"; + case RuntimeData::Difficulty: return "difficulty"; + case RuntimeData::GasLimit: return "gaslimit"; + case RuntimeData::CodeSize: return "codesize"; } } } @@ -57,6 +66,15 @@ Runtime::Runtime(u256 _gas, ExtVMFace& _ext): set(RuntimeData::Caller, fromAddress(_ext.caller)); set(RuntimeData::Origin, fromAddress(_ext.origin)); set(RuntimeData::CallValue, _ext.value); + set(RuntimeData::CallDataSize, _ext.data.size()); + set(RuntimeData::GasPrice, _ext.gasPrice); + set(RuntimeData::PrevHash, _ext.previousBlock.hash); + set(RuntimeData::CoinBase, fromAddress(_ext.currentBlock.coinbaseAddress)); + set(RuntimeData::TimeStamp, _ext.currentBlock.timestamp); + set(RuntimeData::Number, _ext.currentBlock.number); + set(RuntimeData::Difficulty, _ext.currentBlock.difficulty); + set(RuntimeData::GasLimit, _ext.currentBlock.gasLimit); + set(RuntimeData::CodeSize, _ext.code.size()); // TODO: Use constant } Runtime::~Runtime() diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 3300b4106..478c212b1 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -31,6 +31,15 @@ struct RuntimeData Caller, Origin, CallValue, + CallDataSize, + GasPrice, + PrevHash, + CoinBase, + TimeStamp, + Number, + Difficulty, + GasLimit, + CodeSize, _size }; From 356f6609d58cdd52fe6ac04fcbb1603c7169016c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 15:21:47 +0100 Subject: [PATCH 13/17] Group instructions that access runtime data [#81470252] --- libevmjit/Compiler.cpp | 103 ++++++----------------------------------- libevmjit/Runtime.cpp | 22 +++++++++ libevmjit/Runtime.h | 1 + 3 files changed, 36 insertions(+), 90 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index e711fe706..7f6aba051 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -679,57 +679,29 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, } case Instruction::GAS: - { - stack.push(_runtimeManager.getGas()); - break; - } - case Instruction::ADDRESS: - { - auto value = _runtimeManager.get(RuntimeData::Address); - stack.push(value); - break; - } - - case Instruction::BALANCE: - { - auto address = stack.pop(); - auto value = ext.balance(address); - stack.push(value); - break; - } - case Instruction::CALLER: - { - auto value = _runtimeManager.get(RuntimeData::Caller); - stack.push(value); - break; - } - case Instruction::ORIGIN: - { - auto value = _runtimeManager.get(RuntimeData::Origin); - stack.push(value); - break; - } - case Instruction::CALLVALUE: - { - auto value = _runtimeManager.get(RuntimeData::CallValue); - stack.push(value); - break; - } - case Instruction::CALLDATASIZE: + case Instruction::CODESIZE: + case Instruction::GASPRICE: + case Instruction::PREVHASH: + case Instruction::COINBASE: + case Instruction::TIMESTAMP: + case Instruction::NUMBER: + case Instruction::DIFFICULTY: + case Instruction::GASLIMIT: { - auto value = _runtimeManager.get(RuntimeData::CallDataSize); - stack.push(value); + // Pushes an element of runtime data on stack + stack.push(_runtimeManager.get(inst)); break; } - case Instruction::CODESIZE: + case Instruction::BALANCE: { - auto value = _runtimeManager.get(RuntimeData::CodeSize); + auto address = stack.pop(); + auto value = ext.balance(address); stack.push(value); break; } @@ -790,55 +762,6 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, break; } - case Instruction::GASPRICE: - { - auto value = _runtimeManager.get(RuntimeData::GasPrice); - stack.push(value); - break; - } - - case Instruction::PREVHASH: - { - auto value = _runtimeManager.get(RuntimeData::PrevHash); - stack.push(value); - break; - } - - case Instruction::COINBASE: - { - auto value = _runtimeManager.get(RuntimeData::CoinBase); - stack.push(value); - break; - } - - case Instruction::TIMESTAMP: - { - auto value = _runtimeManager.get(RuntimeData::TimeStamp); - stack.push(value); - break; - } - - case Instruction::NUMBER: - { - auto value = _runtimeManager.get(RuntimeData::Number); - stack.push(value); - break; - } - - case Instruction::DIFFICULTY: - { - auto value = _runtimeManager.get(RuntimeData::Difficulty); - stack.push(value); - break; - } - - case Instruction::GASLIMIT: - { - auto value = _runtimeManager.get(RuntimeData::GasLimit); - stack.push(value); - break; - } - case Instruction::CREATE: { auto endowment = stack.pop(); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 42d2fe52f..21fcfaddb 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -135,6 +135,28 @@ llvm::Value* RuntimeManager::get(RuntimeData::Index _index) return m_builder.CreateLoad(ptr, getName(_index)); } +llvm::Value* RuntimeManager::get(Instruction _inst) +{ + switch (_inst) + { + default: assert(false); return nullptr; + case Instruction::GAS: return get(RuntimeData::Gas); + case Instruction::ADDRESS: return get(RuntimeData::Address); + case Instruction::CALLER: return get(RuntimeData::Caller); + case Instruction::ORIGIN: return get(RuntimeData::Origin); + case Instruction::CALLVALUE: return get(RuntimeData::CallValue); + case Instruction::CALLDATASIZE: return get(RuntimeData::CallDataSize); + case Instruction::GASPRICE: return get(RuntimeData::GasPrice); + case Instruction::PREVHASH: return get(RuntimeData::PrevHash); + case Instruction::COINBASE: return get(RuntimeData::CoinBase); + case Instruction::TIMESTAMP: return get(RuntimeData::TimeStamp); + case Instruction::NUMBER: return get(RuntimeData::Number); + case Instruction::DIFFICULTY: return get(RuntimeData::Difficulty); + case Instruction::GASLIMIT: return get(RuntimeData::GasLimit); + case Instruction::CODESIZE: return get(RuntimeData::CodeSize); + } +} + llvm::Value* RuntimeManager::getGas() { return get(RuntimeData::Gas); diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 478c212b1..a4bb89427 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -88,6 +88,7 @@ public: llvm::Value* getRuntimePtr(); llvm::Value* get(RuntimeData::Index _index); + llvm::Value* get(Instruction _inst); llvm::Value* getGas(); void setGas(llvm::Value* _gas); From f12620d6d8d0a3e9d91432267dc23e88f1c052df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 16:00:41 +0100 Subject: [PATCH 14/17] Moving CALLDATA data from Ext to Runtime [#81470252] --- libevmjit/Compiler.cpp | 2 +- libevmjit/Ext.cpp | 4 +--- libevmjit/Ext.h | 1 - libevmjit/Runtime.cpp | 10 +++++++++- libevmjit/Runtime.h | 4 +++- 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 7f6aba051..a872a0097 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -720,7 +720,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto srcIdx = stack.pop(); auto reqBytes = stack.pop(); - auto srcPtr = ext.calldata(); + auto srcPtr = _runtimeManager.getCallData(); auto srcSize = _runtimeManager.get(RuntimeData::CallDataSize); memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 1adaf741c..b75cd3195 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -52,7 +52,6 @@ Ext::Ext(RuntimeManager& _runtimeManager): m_arg8 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); Type* elements[] = { - i8PtrTy, // byte* calldata i8PtrTy, // byte* code }; @@ -100,8 +99,7 @@ Value* Ext::getDataElem(unsigned _index, const Twine& _name) return m_builder.CreateLoad(valuePtr); } -Value* Ext::calldata() { return getDataElem(0, "calldata"); } -Value* Ext::code() { return getDataElem(1, "code"); } +Value* Ext::code() { return getDataElem(0, "code"); } Value* Ext::calldataload(Value* _index) { diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index 62938f3cb..f798ec549 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -20,7 +20,6 @@ public: llvm::Value* store(llvm::Value* _index); void setStore(llvm::Value* _index, llvm::Value* _value); - llvm::Value* calldata(); llvm::Value* code(); llvm::Value* balance(llvm::Value* _address); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 21fcfaddb..523d5ea90 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -22,7 +22,8 @@ llvm::StructType* RuntimeData::getType() { llvm::Type* elems[] = { - llvm::ArrayType::get(Type::i256, _size) + llvm::ArrayType::get(Type::i256, _size), + Type::BytePtr }; type = llvm::StructType::create(elems, "RuntimeData"); } @@ -75,6 +76,7 @@ Runtime::Runtime(u256 _gas, ExtVMFace& _ext): set(RuntimeData::Difficulty, _ext.currentBlock.difficulty); set(RuntimeData::GasLimit, _ext.currentBlock.gasLimit); set(RuntimeData::CodeSize, _ext.code.size()); // TODO: Use constant + m_data.callData = _ext.data.data(); } Runtime::~Runtime() @@ -157,6 +159,12 @@ llvm::Value* RuntimeManager::get(Instruction _inst) } } +llvm::Value* RuntimeManager::getCallData() +{ + auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 1, "calldataPtr"); + return getBuilder().CreateLoad(ptr, "calldata"); +} + llvm::Value* RuntimeManager::getGas() { return get(RuntimeData::Gas); diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index a4bb89427..d8f1a2624 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -45,6 +45,7 @@ struct RuntimeData }; i256 elems[_size]; + byte const* callData; static llvm::StructType* getType(); }; @@ -89,7 +90,8 @@ public: llvm::Value* get(RuntimeData::Index _index); llvm::Value* get(Instruction _inst); - llvm::Value* getGas(); + llvm::Value* getGas(); // TODO: Remove + llvm::Value* getCallData(); void setGas(llvm::Value* _gas); private: From 13fb431c54a1790a7f0ceef2f35a0734aa1eec02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 16:13:38 +0100 Subject: [PATCH 15/17] Moving CODE data from Ext to Runtime [#81470252] --- libevmjit/Compiler.cpp | 2 +- libevmjit/Ext.cpp | 19 ------------------- libevmjit/Ext.h | 5 ----- libevmjit/Runtime.cpp | 8 ++++++++ libevmjit/Runtime.h | 2 ++ 5 files changed, 11 insertions(+), 25 deletions(-) diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index a872a0097..600551c29 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -733,7 +733,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, auto srcIdx = stack.pop(); auto reqBytes = stack.pop(); - auto srcPtr = ext.code(); // TODO: Code & its size are constants, feature #80814234 + auto srcPtr = _runtimeManager.getCode(); // TODO: Code & its size are constants, feature #80814234 auto srcSize = _runtimeManager.get(RuntimeData::CodeSize); memory.copyBytes(srcPtr, srcSize, srcIdx, destMemIdx, reqBytes); diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index b75cd3195..6659425ea 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -51,17 +51,8 @@ Ext::Ext(RuntimeManager& _runtimeManager): m_arg7 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg7"); m_arg8 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); - Type* elements[] = { - i8PtrTy, // byte* code - - }; - auto extDataTy = StructType::create(elements, "ext.Data"); - - m_data = m_builder.CreateAlloca(extDataTy, nullptr, "ext.data"); - using llvm::types::i; using Linkage = llvm::GlobalValue::LinkageTypes; - m_init = Function::Create(FunctionType::get(m_builder.getVoidTy(), extDataTy->getPointerTo(), false), Linkage::ExternalLinkage, "ext_init", module); 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); m_calldataload = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_calldataload", module); @@ -75,8 +66,6 @@ Ext::Ext(RuntimeManager& _runtimeManager): m_exp = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_exp", module); m_codeAt = Function::Create(TypeBuilder*(i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_codeAt", module); m_codesizeAt = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_codesizeAt", module); - - m_builder.CreateCall(m_init, m_data); } llvm::Value* Ext::store(llvm::Value* _index) @@ -93,14 +82,6 @@ void Ext::setStore(llvm::Value* _index, llvm::Value* _value) m_builder.CreateCall(m_setStore, m_args); // Uses native endianness } -Value* Ext::getDataElem(unsigned _index, const Twine& _name) -{ - auto valuePtr = m_builder.CreateStructGEP(m_data, _index, _name); - return m_builder.CreateLoad(valuePtr); -} - -Value* Ext::code() { return getDataElem(0, "code"); } - Value* Ext::calldataload(Value* _index) { m_builder.CreateStore(_index, m_args[0]); diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index f798ec549..e7200e95a 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -20,8 +20,6 @@ public: llvm::Value* store(llvm::Value* _index); void setStore(llvm::Value* _index, llvm::Value* _value); - llvm::Value* code(); - llvm::Value* balance(llvm::Value* _address); void suicide(llvm::Value* _address); llvm::Value* calldataload(llvm::Value* _index); @@ -33,8 +31,6 @@ public: llvm::Value* codeAt(llvm::Value* _addr); llvm::Value* codesizeAt(llvm::Value* _addr); -private: - llvm::Value* getDataElem(unsigned _index, const llvm::Twine& _name = ""); private: llvm::Value* m_args[2]; @@ -46,7 +42,6 @@ private: llvm::Value* m_arg7; llvm::Value* m_arg8; llvm::Value* m_data; - llvm::Function* m_init; llvm::Function* m_store; llvm::Function* m_setStore; llvm::Function* m_calldataload; diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 523d5ea90..489034a17 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -23,6 +23,7 @@ llvm::StructType* RuntimeData::getType() llvm::Type* elems[] = { llvm::ArrayType::get(Type::i256, _size), + Type::BytePtr, Type::BytePtr }; type = llvm::StructType::create(elems, "RuntimeData"); @@ -77,6 +78,7 @@ Runtime::Runtime(u256 _gas, ExtVMFace& _ext): set(RuntimeData::GasLimit, _ext.currentBlock.gasLimit); set(RuntimeData::CodeSize, _ext.code.size()); // TODO: Use constant m_data.callData = _ext.data.data(); + m_data.code = _ext.code.data(); } Runtime::~Runtime() @@ -165,6 +167,12 @@ llvm::Value* RuntimeManager::getCallData() return getBuilder().CreateLoad(ptr, "calldata"); } +llvm::Value* RuntimeManager::getCode() +{ + auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 2, "codePtr"); + return getBuilder().CreateLoad(ptr, "code"); +} + llvm::Value* RuntimeManager::getGas() { return get(RuntimeData::Gas); diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index d8f1a2624..7eb7c2d38 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -46,6 +46,7 @@ struct RuntimeData i256 elems[_size]; byte const* callData; + byte const* code; static llvm::StructType* getType(); }; @@ -92,6 +93,7 @@ public: llvm::Value* get(Instruction _inst); llvm::Value* getGas(); // TODO: Remove llvm::Value* getCallData(); + llvm::Value* getCode(); void setGas(llvm::Value* _gas); private: From df144a7e2e911c3fe3fc53c18dcd88a4c1785992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 16:16:02 +0100 Subject: [PATCH 16/17] Old bswap intrinsic removed --- libevmjit/Ext.cpp | 1 - libevmjit/Ext.h | 1 - 2 files changed, 2 deletions(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 6659425ea..853b8cd94 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -61,7 +61,6 @@ Ext::Ext(RuntimeManager& _runtimeManager): m_create = Function::Create(TypeBuilder*, i<256>*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_create", module); Type* args[] = {i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy}; m_call = Function::Create(FunctionType::get(m_builder.getVoidTy(), args, false), Linkage::ExternalLinkage, "ext_call", module); - m_bswap = Intrinsic::getDeclaration(module, Intrinsic::bswap, i256Ty); m_sha3 = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_sha3", module); m_exp = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_exp", module); m_codeAt = Function::Create(TypeBuilder*(i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_codeAt", module); diff --git a/libevmjit/Ext.h b/libevmjit/Ext.h index e7200e95a..fe62f43c6 100644 --- a/libevmjit/Ext.h +++ b/libevmjit/Ext.h @@ -49,7 +49,6 @@ private: llvm::Function* m_suicide; llvm::Function* m_create; llvm::Function* m_call; - llvm::Function* m_bswap; llvm::Function* m_sha3; llvm::Function* m_exp; llvm::Function* m_codeAt; From 18ccc108a0a91bb8f920b5ea742f65814e0c4805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Mon, 27 Oct 2014 16:46:53 +0100 Subject: [PATCH 17/17] Using RuntimeData pointer in ext functions [#81470252] --- libevmjit/Ext.cpp | 111 ++++++++++++++++++++---------------------- libevmjit/Runtime.cpp | 6 --- libevmjit/Runtime.h | 2 +- 3 files changed, 53 insertions(+), 66 deletions(-) diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index 853b8cd94..170086dae 100644 --- a/libevmjit/Ext.cpp +++ b/libevmjit/Ext.cpp @@ -8,10 +8,9 @@ #include #include "Runtime.h" +#include "Type.h" #include "Endianness.h" -using namespace llvm; - namespace dev { namespace eth @@ -51,26 +50,27 @@ Ext::Ext(RuntimeManager& _runtimeManager): m_arg7 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg7"); m_arg8 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); - using llvm::types::i; using Linkage = llvm::GlobalValue::LinkageTypes; - 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); - m_calldataload = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_calldataload", module); - m_balance = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_balance", module); - m_suicide = Function::Create(TypeBuilder*), true>::get(ctx), Linkage::ExternalLinkage, "ext_suicide", module); - m_create = Function::Create(TypeBuilder*, i<256>*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_create", module); - Type* args[] = {i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy, i256PtrTy}; - m_call = Function::Create(FunctionType::get(m_builder.getVoidTy(), args, false), Linkage::ExternalLinkage, "ext_call", module); - m_sha3 = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_sha3", module); - m_exp = Function::Create(TypeBuilder*, i<256>*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_exp", module); - m_codeAt = Function::Create(TypeBuilder*(i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_codeAt", module); - m_codesizeAt = Function::Create(TypeBuilder*, i<256>*), true>::get(ctx), Linkage::ExternalLinkage, "ext_codesizeAt", module); + + llvm::Type* argsTypes[] = {Type::RuntimePtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr}; + + m_store = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_store", module); + m_setStore = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_setStore", module); + m_calldataload = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_calldataload", module); + m_balance = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_balance", module); + m_suicide = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 2}, false), Linkage::ExternalLinkage, "ext_suicide", module); + m_create = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 5}, false), Linkage::ExternalLinkage, "ext_create", module); + 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_codesizeAt = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_codesizeAt", module); } llvm::Value* Ext::store(llvm::Value* _index) { m_builder.CreateStore(_index, m_args[0]); - m_builder.CreateCall(m_store, m_args); // Uses native endianness + m_builder.CreateCall3(m_store, getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]); // Uses native endianness return m_builder.CreateLoad(m_args[1]); } @@ -78,40 +78,40 @@ 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); // Uses native endianness + m_builder.CreateCall3(m_setStore, getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]); // Uses native endianness } -Value* Ext::calldataload(Value* _index) +llvm::Value* Ext::calldataload(llvm::Value* _index) { m_builder.CreateStore(_index, m_args[0]); - m_builder.CreateCall(m_calldataload, m_args); + m_builder.CreateCall3(m_calldataload, getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]); auto ret = m_builder.CreateLoad(m_args[1]); return Endianness::toNative(m_builder, ret); } -Value* Ext::balance(Value* _address) +llvm::Value* Ext::balance(llvm::Value* _address) { auto address = Endianness::toBE(m_builder, _address); m_builder.CreateStore(address, m_args[0]); - m_builder.CreateCall(m_balance, m_args); + m_builder.CreateCall3(m_balance, getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]); return m_builder.CreateLoad(m_args[1]); } -void Ext::suicide(Value* _address) +void Ext::suicide(llvm::Value* _address) { auto address = Endianness::toBE(m_builder, _address); m_builder.CreateStore(address, m_args[0]); - m_builder.CreateCall(m_suicide, m_args[0]); + m_builder.CreateCall2(m_suicide, getRuntimeManager().getRuntimePtr(), m_args[0]); } -Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize) +llvm::Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize) { m_builder.CreateStore(_endowment, m_args[0]); m_builder.CreateStore(_initOff, m_arg2); m_builder.CreateStore(_initSize, m_arg3); - Value* args[] = {m_args[0], m_arg2, m_arg3, m_args[1]}; + llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_arg3, m_args[1]}; m_builder.CreateCall(m_create, args); - Value* address = m_builder.CreateLoad(m_args[1]); + llvm::Value* address = m_builder.CreateLoad(m_args[1]); address = Endianness::toNative(m_builder, address); return address; } @@ -129,7 +129,7 @@ llvm::Value* Ext::call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::V auto codeAddress = Endianness::toBE(m_builder, _codeAddress); m_builder.CreateStore(codeAddress, m_arg8); - llvm::Value* args[] = {m_args[0], m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_args[1]}; + 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); _gas = m_builder.CreateLoad(m_args[0]); // Return gas return m_builder.CreateLoad(m_args[1]); @@ -139,9 +139,9 @@ 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[] = {m_args[0], m_arg2, m_args[1]}; + llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]}; m_builder.CreateCall(m_sha3, args); - Value* hash = m_builder.CreateLoad(m_args[1]); + llvm::Value* hash = m_builder.CreateLoad(m_args[1]); hash = Endianness::toNative(m_builder, hash); return hash; } @@ -150,7 +150,7 @@ llvm::Value* Ext::exp(llvm::Value* _left, llvm::Value* _right) { m_builder.CreateStore(_left, m_args[0]); m_builder.CreateStore(_right, m_arg2); - llvm::Value* args[] = {m_args[0], m_arg2, m_args[1]}; + llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]}; m_builder.CreateCall(m_exp, args); return m_builder.CreateLoad(m_args[1]); } @@ -159,14 +159,14 @@ llvm::Value* Ext::codeAt(llvm::Value* _addr) { auto addr = Endianness::toBE(m_builder, _addr); m_builder.CreateStore(addr, m_args[0]); - return m_builder.CreateCall(m_codeAt, m_args[0]); + return m_builder.CreateCall2(m_codeAt, getRuntimeManager().getRuntimePtr(), m_args[0]); } llvm::Value* Ext::codesizeAt(llvm::Value* _addr) { auto addr = Endianness::toBE(m_builder, _addr); m_builder.CreateStore(addr, m_args[0]); - llvm::Value* args[] = {m_args[0], m_args[1]}; + llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]}; m_builder.CreateCall(m_codesizeAt, args); return m_builder.CreateLoad(m_args[1]); } @@ -179,51 +179,44 @@ extern "C" using namespace dev::eth::jit; -EXPORT void ext_init(ExtData* _extData) -{ - auto&& ext = Runtime::getExt(); - _extData->calldata = ext.data.data(); - _extData->code = ext.code.data(); -} - -EXPORT void ext_store(i256* _index, i256* _value) +EXPORT void ext_store(Runtime* _rt, i256* _index, i256* _value) { auto index = llvm2eth(*_index); - auto value = Runtime::getExt().store(index); // Interface uses native endianness + auto value = _rt->getExt().store(index); // Interface uses native endianness *_value = eth2llvm(value); } -EXPORT void ext_setStore(i256* _index, i256* _value) +EXPORT void ext_setStore(Runtime* _rt, i256* _index, i256* _value) { auto index = llvm2eth(*_index); auto value = llvm2eth(*_value); - Runtime::getExt().setStore(index, value); // Interface uses native endianness + _rt->getExt().setStore(index, value); // Interface uses native endianness } -EXPORT void ext_calldataload(i256* _index, i256* _value) +EXPORT void ext_calldataload(Runtime* _rt, i256* _index, i256* _value) { auto index = static_cast(llvm2eth(*_index)); assert(index + 31 > index); // TODO: Handle large index auto b = reinterpret_cast(_value); for (size_t i = index, j = 0; i <= index + 31; ++i, ++j) - b[j] = i < Runtime::getExt().data.size() ? Runtime::getExt().data[i] : 0; // Keep Big Endian + b[j] = i < _rt->getExt().data.size() ? _rt->getExt().data[i] : 0; // Keep Big Endian // TODO: It all can be done by adding padding to data or by using min() algorithm without branch } -EXPORT void ext_balance(h256* _address, i256* _value) +EXPORT void ext_balance(Runtime* _rt, h256* _address, i256* _value) { - auto u = Runtime::getExt().balance(right160(*_address)); + auto u = _rt->getExt().balance(right160(*_address)); *_value = eth2llvm(u); } -EXPORT void ext_suicide(h256* _address) +EXPORT void ext_suicide(Runtime* _rt, h256* _address) { - Runtime::getExt().suicide(right160(*_address)); + _rt->getExt().suicide(right160(*_address)); } -EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256* _address) +EXPORT void ext_create(Runtime* _rt, i256* _endowment, i256* _initOff, i256* _initSize, h256* _address) { - auto&& ext = Runtime::getExt(); + auto&& ext = _rt->getExt(); auto endowment = llvm2eth(*_endowment); if (ext.balance(ext.myAddress) >= endowment) @@ -244,9 +237,9 @@ EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256* -EXPORT void ext_call(i256* _gas, h256* _receiveAddress, i256* _value, i256* _inOff, i256* _inSize, i256* _outOff, i256* _outSize, h256* _codeAddress, i256* _ret) +EXPORT void ext_call(Runtime* _rt, i256* _gas, h256* _receiveAddress, i256* _value, i256* _inOff, i256* _inSize, i256* _outOff, i256* _outSize, h256* _codeAddress, i256* _ret) { - auto&& ext = Runtime::getExt(); + auto&& ext = _rt->getExt(); auto value = llvm2eth(*_value); auto ret = false; @@ -270,7 +263,7 @@ EXPORT void ext_call(i256* _gas, h256* _receiveAddress, i256* _value, i256* _inO _ret->a = ret ? 1 : 0; } -EXPORT void ext_sha3(i256* _inOff, i256* _inSize, i256* _ret) +EXPORT void ext_sha3(Runtime* _rt, i256* _inOff, i256* _inSize, i256* _ret) { auto inOff = static_cast(llvm2eth(*_inOff)); auto inSize = static_cast(llvm2eth(*_inSize)); @@ -279,7 +272,7 @@ EXPORT void ext_sha3(i256* _inOff, i256* _inSize, i256* _ret) *_ret = *reinterpret_cast(&hash); } -EXPORT void ext_exp(i256* _left, i256* _right, i256* _ret) +EXPORT void ext_exp(Runtime* _rt, i256* _left, i256* _right, i256* _ret) { bigint left = llvm2eth(*_left); bigint right = llvm2eth(*_right); @@ -287,17 +280,17 @@ EXPORT void ext_exp(i256* _left, i256* _right, i256* _ret) *_ret = eth2llvm(ret); } -EXPORT unsigned char* ext_codeAt(h256* _addr256) +EXPORT unsigned char* ext_codeAt(Runtime* _rt, h256* _addr256) //FIXME: Check endianess { - auto&& ext = Runtime::getExt(); + auto&& ext = _rt->getExt(); auto addr = right160(*_addr256); auto& code = ext.codeAt(addr); return const_cast(code.data()); } -EXPORT void ext_codesizeAt(h256* _addr256, i256* _ret) +EXPORT void ext_codesizeAt(Runtime* _rt, h256* _addr256, i256* _ret) //FIXME: Check endianess { - auto&& ext = Runtime::getExt(); + auto&& ext = _rt->getExt(); auto addr = right160(*_addr256); auto& code = ext.codeAt(addr); *_ret = eth2llvm(u256(code.size())); diff --git a/libevmjit/Runtime.cpp b/libevmjit/Runtime.cpp index 489034a17..4b9464293 100644 --- a/libevmjit/Runtime.cpp +++ b/libevmjit/Runtime.cpp @@ -91,12 +91,6 @@ void Runtime::set(RuntimeData::Index _index, u256 _value) m_data.elems[_index] = eth2llvm(_value); } - -ExtVMFace& Runtime::getExt() -{ - return g_runtime->m_ext; -} - u256 Runtime::getGas() const { return llvm2eth(m_data.elems[RuntimeData::Gas]); diff --git a/libevmjit/Runtime.h b/libevmjit/Runtime.h index 7eb7c2d38..ec912849a 100644 --- a/libevmjit/Runtime.h +++ b/libevmjit/Runtime.h @@ -67,7 +67,7 @@ public: StackImpl& getStack() { return m_stack; } MemoryImpl& getMemory() { return m_memory; } - static ExtVMFace& getExt(); + ExtVMFace& getExt() { return m_ext; } u256 getGas() const; bytesConstRef getReturnData() const;