From 1c9fb4acb726a851106b1a471e9e7136218470af Mon Sep 17 00:00:00 2001 From: artur-zawlocki Date: Mon, 3 Nov 2014 10:31:09 +0000 Subject: [PATCH] 1) JUMP/I semantics updated. 2) Members of BasicBlock::LocalStack pulled out to BasicBlock --- libevmjit/BasicBlock.cpp | 142 ++++++++++++++++++++------------------- libevmjit/BasicBlock.h | 59 +++++++--------- libevmjit/Compiler.cpp | 15 ++--- 3 files changed, 102 insertions(+), 114 deletions(-) diff --git a/libevmjit/BasicBlock.cpp b/libevmjit/BasicBlock.cpp index 0c604f1b3..1cc0e13fd 100644 --- a/libevmjit/BasicBlock.cpp +++ b/libevmjit/BasicBlock.cpp @@ -26,38 +26,36 @@ BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, m_beginInstIdx(_beginInstIdx), m_endInstIdx(_endInstIdx), m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)), - m_stack(_builder, m_llvmBB) + m_stack(*this), + m_builder(_builder) {} BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder) : m_beginInstIdx(0), m_endInstIdx(0), m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)), - m_stack(_builder, m_llvmBB) + m_stack(*this), + m_builder(_builder) {} -BasicBlock::LocalStack::LocalStack(llvm::IRBuilder<>& _builder, llvm::BasicBlock* _llvmBB) : - m_llvmBB(_llvmBB), - m_builder(_builder), - m_initialStack(), - m_currentStack(), - m_tosOffset(0) +BasicBlock::LocalStack::LocalStack(BasicBlock& _owner) : + m_bblock(_owner) {} void BasicBlock::LocalStack::push(llvm::Value* _value) { - m_currentStack.push_back(_value); - m_tosOffset += 1; + m_bblock.m_currentStack.push_back(_value); + m_bblock.m_tosOffset += 1; } llvm::Value* BasicBlock::LocalStack::pop() { auto result = get(0); - if (m_currentStack.size() > 0) - m_currentStack.pop_back(); + if (m_bblock.m_currentStack.size() > 0) + m_bblock.m_currentStack.pop_back(); - m_tosOffset -= 1; + m_bblock.m_tosOffset -= 1; return result; } @@ -83,7 +81,56 @@ void BasicBlock::LocalStack::swap(size_t _index) set(0, val); } -void BasicBlock::LocalStack::synchronize(Stack& _evmStack) +std::vector::iterator BasicBlock::LocalStack::getItemIterator(size_t _index) +{ + auto& currentStack = m_bblock.m_currentStack; + if (_index < currentStack.size()) + return currentStack.end() - _index - 1; + + // Need to map more elements from the EVM stack + auto nNewItems = 1 + _index - currentStack.size(); + currentStack.insert(currentStack.begin(), nNewItems, nullptr); + + return currentStack.end() - _index - 1; +} + +llvm::Value* BasicBlock::LocalStack::get(size_t _index) +{ + auto& initialStack = m_bblock.m_initialStack; + auto itemIter = getItemIterator(_index); + + if (*itemIter == nullptr) + { + // Need to fetch a new item from the EVM stack + assert(static_cast(_index) >= m_bblock.m_tosOffset); + size_t initialIdx = _index - m_bblock.m_tosOffset; + if (initialIdx >= initialStack.size()) + { + auto nNewItems = 1 + initialIdx - initialStack.size(); + initialStack.insert(initialStack.end(), nNewItems, nullptr); + } + + assert(initialStack[initialIdx] == nullptr); + // Create a dummy value. + std::string name = "get_" + boost::lexical_cast(_index); + initialStack[initialIdx] = m_bblock.m_builder.CreatePHI(Type::Word, 0, name); + *itemIter = initialStack[initialIdx]; + } + + return *itemIter; +} + +void BasicBlock::LocalStack::set(size_t _index, llvm::Value* _word) +{ + auto itemIter = getItemIterator(_index); + *itemIter = _word; +} + + + + + +void BasicBlock::synchronizeLocalStack(Stack& _evmStack) { auto blockTerminator = m_llvmBB->getTerminator(); assert(blockTerminator != nullptr); @@ -141,51 +188,6 @@ void BasicBlock::LocalStack::synchronize(Stack& _evmStack) m_tosOffset = 0; } -std::vector::iterator BasicBlock::LocalStack::getItemIterator(size_t _index) -{ - if (_index < m_currentStack.size()) - return m_currentStack.end() - _index - 1; - - // Need to map more elements from the EVM stack - auto nNewItems = 1 + _index - m_currentStack.size(); - m_currentStack.insert(m_currentStack.begin(), nNewItems, nullptr); - - return m_currentStack.end() - _index - 1; -} - -llvm::Value* BasicBlock::LocalStack::get(size_t _index) -{ - auto itemIter = getItemIterator(_index); - - if (*itemIter == nullptr) - { - // Need to fetch a new item from the EVM stack - assert(static_cast(_index) >= m_tosOffset); - size_t initialIdx = _index - m_tosOffset; - if (initialIdx >= m_initialStack.size()) - { - auto nNewItems = 1 + initialIdx - m_initialStack.size(); - m_initialStack.insert(m_initialStack.end(), nNewItems, nullptr); - } - - assert(m_initialStack[initialIdx] == nullptr); - // Create a dummy value. - std::string name = "get_" + boost::lexical_cast(_index); - m_initialStack[initialIdx] = m_builder.CreatePHI(Type::Word, 0, name); - *itemIter = m_initialStack[initialIdx]; - } - - return *itemIter; -} - -void BasicBlock::LocalStack::set(size_t _index, llvm::Value* _word) -{ - auto itemIter = getItemIterator(_index); - *itemIter = _word; -} - - - void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRBuilder<>& _builder) { struct BBInfo @@ -202,14 +204,14 @@ void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRB inputItems(0), outputItems(0) { - auto& initialStack = bblock.localStack().m_initialStack; + auto& initialStack = bblock.m_initialStack; for (auto it = initialStack.begin(); it != initialStack.end() && *it != nullptr; ++it, ++inputItems); //if (bblock.localStack().m_tosOffset > 0) // outputItems = bblock.localStack().m_tosOffset; - auto& exitStack = bblock.localStack().m_currentStack; + auto& exitStack = bblock.m_currentStack; for (auto it = exitStack.rbegin(); it != exitStack.rend() && *it != nullptr; ++it, ++outputItems); @@ -281,7 +283,7 @@ void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRB auto& bblock = info.bblock; llvm::BasicBlock::iterator fstNonPhi(bblock.llvm()->getFirstNonPHI()); - auto phiIter = bblock.localStack().m_initialStack.begin(); + auto phiIter = bblock.m_initialStack.begin(); for (size_t index = 0; index < info.inputItems; ++index, ++phiIter) { assert(llvm::isa(*phiIter)); @@ -289,7 +291,7 @@ void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRB for (auto predIt : info.predecessors) { - auto& predExitStack = predIt->bblock.localStack().m_currentStack; + auto& predExitStack = predIt->bblock.m_currentStack; auto value = *(predExitStack.end() - 1 - index); phi->addIncoming(value, predIt->bblock.llvm()); } @@ -305,10 +307,10 @@ void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRB // The items pulled directly from predecessors block must be removed // from the list of items that has to be popped from the initial stack. - auto& initialStack = bblock.localStack().m_initialStack; + auto& initialStack = bblock.m_initialStack; initialStack.erase(initialStack.begin(), initialStack.begin() + info.inputItems); // Initial stack shrinks, so the size difference grows: - bblock.localStack().m_tosOffset += info.inputItems; + bblock.m_tosOffset += info.inputItems; } // We must account for the items that were pushed directly to successor @@ -319,9 +321,9 @@ void BasicBlock::linkLocalStacks(std::vector basicBlocks, llvm::IRB auto& info = entry.second; auto& bblock = info.bblock; - auto& exitStack = bblock.localStack().m_currentStack; + auto& exitStack = bblock.m_currentStack; exitStack.erase(exitStack.end() - info.outputItems, exitStack.end()); - bblock.localStack().m_tosOffset -= info.outputItems; + bblock.m_tosOffset -= info.outputItems; } } @@ -335,7 +337,7 @@ void BasicBlock::dump(std::ostream& _out, bool _dotOutput) llvm::raw_os_ostream out(_out); out << (_dotOutput ? "" : "Initial stack:\n"); - for (auto val : m_stack.m_initialStack) + for (auto val : m_initialStack) { if (val == nullptr) out << " ?"; @@ -352,11 +354,11 @@ void BasicBlock::dump(std::ostream& _out, bool _dotOutput) out << *ins << (_dotOutput ? "\\l" : "\n"); if (! _dotOutput) - out << "Current stack (offset = " << m_stack.m_tosOffset << "):\n"; + out << "Current stack (offset = " << m_tosOffset << "):\n"; else out << "|"; - for (auto val = m_stack.m_currentStack.rbegin(); val != m_stack.m_currentStack.rend(); ++val) + for (auto val = m_currentStack.rbegin(); val != m_currentStack.rend(); ++val) { if (*val == nullptr) out << " ?"; diff --git a/libevmjit/BasicBlock.h b/libevmjit/BasicBlock.h index ffa9ca109..f0643f342 100644 --- a/libevmjit/BasicBlock.h +++ b/libevmjit/BasicBlock.h @@ -21,7 +21,6 @@ public: class LocalStack { public: - /// Pushes value on stack void push(llvm::Value* _value); @@ -35,12 +34,8 @@ public: /// @param _index Index of value to be swaped. Must be > 0. void swap(size_t _index); - /// Synchronize current local stack with the EVM stack. - void synchronize(Stack& _evmStack); - private: - - LocalStack(llvm::IRBuilder<>& _builder, llvm::BasicBlock* _llvmBB); + LocalStack(BasicBlock& _owner); LocalStack(LocalStack const&) = delete; void operator=(LocalStack const&) = delete; friend BasicBlock; @@ -54,34 +49,7 @@ public: std::vector::iterator getItemIterator(size_t _index); private: - - llvm::BasicBlock* m_llvmBB; - - llvm::IRBuilder<>& m_builder; - - /** - * This stack contains LLVM values that correspond to items found at - * the EVM stack when the current basic block starts executing. - * Location 0 corresponds to the top of the EVM stack, location 1 is - * the item below the top and so on. The stack grows as the code - * accesses more items on the EVM stack but once a value is put on - * the stack, it will never be replaced. - */ - std::vector m_initialStack; - - /** - * This stack tracks the contents of the EVM stack as the current basic - * block executes. It may grow on both sides, as the code pushes items on - * top of the stack or changes existing items. - */ - std::vector m_currentStack; - - /** - * How many items higher is the current stack than the initial one. - * May be negative. - */ - int m_tosOffset; - + BasicBlock& m_bblock; }; /// Basic block name prefix. The rest is beging instruction index. @@ -105,6 +73,9 @@ public: /// to avoid excessive pushing/popping on the EVM stack. static void linkLocalStacks(std::vector _basicBlocks, llvm::IRBuilder<>& _builder); + /// Synchronize current local stack with the EVM stack. + void synchronizeLocalStack(Stack& _evmStack); + /// Prints local stack and block instructions to stderr. /// Useful for calling in a debugger session. void dump(); @@ -113,11 +84,31 @@ public: private: ProgramCounter const m_beginInstIdx; ProgramCounter const m_endInstIdx; + llvm::BasicBlock* const m_llvmBB; /// Basic black state vector (stack) - current/end values and their positions on stack /// @internal Must be AFTER m_llvmBB LocalStack m_stack; + + llvm::IRBuilder<>& m_builder; + + /// This stack contains LLVM values that correspond to items found at + /// the EVM stack when the current basic block starts executing. + /// Location 0 corresponds to the top of the EVM stack, location 1 is + /// the item below the top and so on. The stack grows as the code + /// accesses more items on the EVM stack but once a value is put on + /// the stack, it will never be replaced. + std::vector m_initialStack = {}; + + /// This stack tracks the contents of the EVM stack as the basic block + /// executes. It may grow on both sides, as the code pushes items on + /// top of the stack or changes existing items. + std::vector m_currentStack = {}; + + /// How many items higher is the current stack than the initial one. + /// May be negative. + int m_tosOffset = 0; }; } diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 51b1ee403..295f3a131 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -81,12 +81,9 @@ void Compiler::createBasicBlocks(bytesConstRef _bytecode) case Instruction::JUMPDEST: { - // A basic block starts at the next instruction. - if (currentPC + 1 < _bytecode.size()) - { - splitPoints.insert(currentPC + 1); - indirectJumpTargets.push_back(currentPC + 1); - } + // A basic block starts here. + splitPoints.insert(currentPC); + indirectJumpTargets.push_back(currentPC); break; } @@ -98,9 +95,7 @@ void Compiler::createBasicBlocks(bytesConstRef _bytecode) { // Create a basic block starting at the following instruction. if (curr + 1 < _bytecode.end()) - { splitPoints.insert(currentPC + 1); - } break; } @@ -234,9 +229,9 @@ std::unique_ptr Compiler::compile(bytesConstRef _bytecode) } for (auto& entry : basicBlocks) - entry.second.localStack().synchronize(stack); + entry.second.synchronizeLocalStack(stack); if (m_jumpTableBlock) - m_jumpTableBlock->localStack().synchronize(stack); + m_jumpTableBlock->synchronizeLocalStack(stack); dumpCFGifRequired("blocks-sync.dot");