diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 26b23bff0..3a0da880d 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -188,12 +188,12 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) createBasicBlocks(bytecode); // Init runtime structures. - auto globalStack = Stack(builder, module.get()); + auto extStack = Stack(builder, module.get()); auto memory = Memory(builder, module.get()); auto ext = Ext(builder, module.get()); BasicBlock* currentBlock = entryBlock; - BBStack stack; // Stack for current block + BBStack stack(extStack); // Stack for current block for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc) { @@ -212,7 +212,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) mainFunc->getBasicBlockList().push_back(nextBlock); builder.SetInsertPoint(nextBlock); currentBlock = nextBlock; - stack = BBStack(); // Reset stack + assert(stack.empty()); // Stack should be empty } assert(currentBlock != nullptr); @@ -579,6 +579,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) // The target address is computed at compile time, // just pop it without looking... stack.pop(); + stack.reset(); auto targetBlock = jumpTargets[currentPC]; builder.CreateBr(targetBlock); @@ -598,6 +599,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto top = stack.pop(); auto zero = ConstantInt::get(Types.word256, 0); auto cond = builder.CreateICmpNE(top, zero, "nonzero"); + stack.reset(); auto targetBlock = jumpTargets[currentPC]; auto followBlock = basicBlocks[currentPC + 1]; builder.CreateCondBr(cond, targetBlock, followBlock); @@ -764,6 +766,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) ret = builder.CreateOr(ret, size); builder.CreateRet(ret); + stack.clear(); currentBlock = nullptr; break; } @@ -777,6 +780,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) case Instruction::STOP: { builder.CreateRet(builder.getInt64(0)); + stack.clear(); currentBlock = nullptr; break; } diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index 6983b9cda..6d9d85a4c 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -103,7 +103,7 @@ int ExecutionEngine::run(std::unique_ptr _module) std::cout << "RETURN [ "; for (dev::bytes::const_iterator it = Runtime::getMemory().cbegin() + index, end = it + size; it != end; ++it) std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)*it << " "; - std::cout << "]"; + std::cout << "]\n"; return 10; } diff --git a/evmcc/Stack.cpp b/evmcc/Stack.cpp index 6a4cf4d61..b4fb2cd23 100644 --- a/evmcc/Stack.cpp +++ b/evmcc/Stack.cpp @@ -20,6 +20,10 @@ namespace evmcc { +BBStack::BBStack(Stack& _extStack) + : m_extStack(_extStack) +{} + void BBStack::push(llvm::Value* _value) { m_state.push_back(_value); @@ -27,11 +31,31 @@ void BBStack::push(llvm::Value* _value) llvm::Value* BBStack::pop() { + if (m_state.empty()) + return m_extStack.pop(); + auto top = m_state.back(); m_state.pop_back(); return top; } +void BBStack::reset() +{ + for (auto&& value : m_state) + m_extStack.push(value); + m_state.clear(); +} + +void BBStack::clear() +{ + m_state.clear(); +} + +bool BBStack::empty() const +{ + return m_state.empty(); +} + void BBStack::dup(size_t _index) { auto value = *(m_state.rbegin() + _index); diff --git a/evmcc/Stack.h b/evmcc/Stack.h index 6336f3412..c420ad0bb 100644 --- a/evmcc/Stack.h +++ b/evmcc/Stack.h @@ -36,15 +36,31 @@ private: class BBStack { public: - //BBStack(llvm::IRBuilder<>& _builder, llvm::Module* _module); + BBStack(Stack& _extStack); void push(llvm::Value* _value); llvm::Value* pop(); void dup(size_t _index); void swap(size_t _index); + /** + Resets stack on basic block change. + Values left on local stack are pushed on external stack. + Local stack is empty after this operation and compilation of new basic block can be started. + */ + void reset(); + + /** + Dumps values on stack. + */ + void clear(); + + /// Debug only + bool empty() const; + private: std::vector m_state; ///< Basic black state vector - current values and their positions + Stack& m_extStack; ///< External (global) stack }; diff --git a/evmcc/bytecode/stackjump.evm b/evmcc/bytecode/stackjump.evm new file mode 100644 index 000000000..baddec42e --- /dev/null +++ b/evmcc/bytecode/stackjump.evm @@ -0,0 +1 @@ +600460066009601358600a036000545b6000f260005401600958 \ No newline at end of file