diff --git a/evmcc/BasicBlock.cpp b/evmcc/BasicBlock.cpp index 487de0239..e5cdf386f 100644 --- a/evmcc/BasicBlock.cpp +++ b/evmcc/BasicBlock.cpp @@ -2,6 +2,7 @@ #include "BasicBlock.h" #include +#include namespace evmcc { @@ -11,7 +12,41 @@ const char* BasicBlock::NamePrefix = "Instr."; BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc) : m_beginInstIdx(_beginInstIdx), m_endInstIdx(_endInstIdx), - m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)) + m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)), + m_stack(m_llvmBB) {} + +void BasicBlock::Stack::push(llvm::Value* _value) +{ + m_backend.push_back(_value); +} + +llvm::Value* BasicBlock::Stack::pop() +{ + if (m_backend.empty()) + { + // Create PHI node + auto i256Ty = llvm::Type::getIntNTy(m_llvmBB->getContext(), 256); + if (m_llvmBB->empty()) + return llvm::PHINode::Create(i256Ty, 0, {}, m_llvmBB); + return llvm::PHINode::Create(i256Ty, 0, {}, m_llvmBB->getFirstNonPHI()); + } + + auto top = m_backend.back(); + m_backend.pop_back(); + return top; +} + +void BasicBlock::Stack::dup(size_t _index) +{ + m_backend.push_back(get(_index)); +} + +void BasicBlock::Stack::swap(size_t _index) +{ + assert(_index != 0); + std::swap(get(0), get(_index)); +} + } \ No newline at end of file diff --git a/evmcc/BasicBlock.h b/evmcc/BasicBlock.h index ef53169d8..500ddb95b 100644 --- a/evmcc/BasicBlock.h +++ b/evmcc/BasicBlock.h @@ -6,13 +6,47 @@ namespace evmcc { -using ProgramCounter = uint64_t; +using ProgramCounter = uint64_t; // TODO: Rename class BasicBlock { public: - using State = std::vector; + class Stack + { + public: + /// Pushes value on stack + void push(llvm::Value* _value); + /// Pops and returns top value + llvm::Value* pop(); + + /// Gets _index'th value from top (counting from 0) + llvm::Value*& get(size_t _index) { return *(m_backend.rbegin() + _index); } + + /// Duplicates _index'th value on stack. + void dup(size_t _index); + + /// Swaps _index'th value on stack with a value on stack top. + /// @param _index Index of value to be swaped. Cannot be 0. + void swap(size_t _index); + + /// Size of the stack + size_t size() const { return m_backend.size(); } + + private: + Stack(llvm::BasicBlock* _llvmBB) : m_llvmBB(_llvmBB) {} + Stack(const Stack&) = delete; + void operator=(const Stack&) = delete; + friend BasicBlock; + + private: + std::vector m_backend; + + /// LLVM Basic Block where phi nodes are inserted + llvm::BasicBlock* const m_llvmBB; + }; + + /// Basic block name prefix. The rest is beging instruction index. static const char* NamePrefix; explicit BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc); @@ -23,18 +57,19 @@ public: operator llvm::BasicBlock*() { return m_llvmBB; } llvm::BasicBlock* llvm() { return m_llvmBB; } - State& getState() { return m_state; } + Stack& getStack() { return m_stack; } ProgramCounter begin() { return m_beginInstIdx; } ProgramCounter end() { return m_endInstIdx; } private: - ProgramCounter m_beginInstIdx; - ProgramCounter m_endInstIdx; - llvm::BasicBlock* m_llvmBB; + ProgramCounter const m_beginInstIdx; + ProgramCounter const m_endInstIdx; + llvm::BasicBlock* const m_llvmBB; - /// Basic black state vector - current/end values and their positions - State m_state; + /// Basic black state vector (stack) - current/end values and their positions on stack + /// @internal Must be AFTER m_llvmBB + Stack m_stack; }; } \ No newline at end of file diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 9d29a166d..c46dd72c5 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -7,7 +7,6 @@ #include #include "Memory.h" -#include "Stack.h" #include "Ext.h" namespace evmcc @@ -187,9 +186,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt) { auto& basicBlock = basicBlockPairIt->second; - - BBStack stack; - stack.setBasicBlock(basicBlock); + auto& stack = basicBlock.getStack(); builder.SetInsertPoint(basicBlock); for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC) @@ -799,8 +796,8 @@ void Compiler::linkBasicBlocks() for (auto predIt = llvm::pred_begin(llvmBB); predIt != llvm::pred_end(llvmBB); ++predIt) { auto& predBB = findBasicBlock(*predIt); - assert(valueIdx < predBB.getState().size()); // TODO: Report error - phi->addIncoming(*(predBB.getState().rbegin() + valueIdx), predBB); + assert(valueIdx < predBB.getStack().size()); // TODO: Report error + phi->addIncoming(predBB.getStack().get(valueIdx), predBB); } } } diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp deleted file mode 100644 index fc359f103..000000000 --- a/evmcc/Stack.cpp +++ /dev/null @@ -1,59 +0,0 @@ - -#include "Stack.h" - -#include - -#include - -#include "BasicBlock.h" - -namespace evmcc -{ - -void BBStack::push(llvm::Value* _value) -{ - m_block->getState().push_back(_value); -} - -llvm::Value* BBStack::pop() -{ - auto&& state = m_block->getState(); - if (state.empty()) - { - // Create PHI node - auto i256Ty = llvm::Type::getIntNTy(m_block->llvm()->getContext(), 256); - auto llvmBB = m_block->llvm(); - if (llvmBB->empty()) - return llvm::PHINode::Create(i256Ty, 0, {}, m_block->llvm()); - return llvm::PHINode::Create(i256Ty, 0, {}, llvmBB->getFirstNonPHI()); - } - - auto top = state.back(); - state.pop_back(); - return top; -} - -void BBStack::setBasicBlock(BasicBlock& _newBlock) -{ - // Current block keeps end state - // Just update pointer to current block - // New block should have empty state - assert(_newBlock.getState().empty()); - m_block = &_newBlock; -} - -void BBStack::dup(size_t _index) -{ - auto&& state = m_block->getState(); - auto value = *(state.rbegin() + _index); - state.push_back(value); -} - -void BBStack::swap(size_t _index) -{ - assert(_index != 0); - auto&& state = m_block->getState(); - std::swap(*state.rbegin(), *(state.rbegin() + _index)); -} - -} diff --git a/evmcc/Stack.h b/evmcc/Stack.h deleted file mode 100644 index 4b81986b0..000000000 --- a/evmcc/Stack.h +++ /dev/null @@ -1,47 +0,0 @@ - -#pragma once - -#include - -namespace evmcc -{ -class BasicBlock; - -/** - Stack adapter for Basic Block - - Transforms stack to SSA: tracks values and their positions on the imaginary stack used inside a basic block. - TODO: Integrate into BasicBlock class - */ -class BBStack -{ -public: - BBStack() = default; - BBStack(const BBStack&) = delete; - void operator=(const BBStack&) = delete; - - /** - Changes current basic block (if any) with a new one with empty state. - */ - void setBasicBlock(BasicBlock& _newBlock); - - void push(llvm::Value* _value); - llvm::Value* pop(); - - /** - Duplicates _index'th value on stack. - */ - void dup(size_t _index); - - /** - Swaps _index'th value on stack with a value on stack top. - @param _index Index of value to be swaped. Cannot be 0. - */ - void swap(size_t _index); - -private: - BasicBlock* m_block = nullptr; ///< Current basic block -}; - - -} \ No newline at end of file diff --git a/windows/evmcc.vcxproj b/windows/evmcc.vcxproj index 8226abb6c..ecf23fa05 100644 --- a/windows/evmcc.vcxproj +++ b/windows/evmcc.vcxproj @@ -26,7 +26,6 @@ - @@ -36,7 +35,6 @@ - diff --git a/windows/evmcc.vcxproj.filters b/windows/evmcc.vcxproj.filters index 05f375ac5..29ff77ba5 100644 --- a/windows/evmcc.vcxproj.filters +++ b/windows/evmcc.vcxproj.filters @@ -4,7 +4,6 @@ - @@ -14,7 +13,6 @@ -