From 5152596cbd4787f93e064aec139b4b7ee5b27f9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Fri, 16 Jan 2015 18:02:36 +0100 Subject: [PATCH] JUMPI fix: an additional item was left on stack when condition is false --- libevmjit/BasicBlock.h | 6 ++++++ libevmjit/Compiler.cpp | 26 +++++++++++++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/libevmjit/BasicBlock.h b/libevmjit/BasicBlock.h index 3591a6f544..cda4f89bda 100644 --- a/libevmjit/BasicBlock.h +++ b/libevmjit/BasicBlock.h @@ -66,6 +66,9 @@ public: bool isJumpDest() const { return m_isJumpDest; } + llvm::Value* getJumpTarget() const { return m_jumpTarget; } + void setJumpTarget(llvm::Value* _jumpTarget) { m_jumpTarget = _jumpTarget; } + LocalStack& localStack() { return m_stack; } /// Optimization: propagates values between local stacks in basic blocks @@ -112,6 +115,9 @@ private: /// Is the basic block a valid jump destination. /// JUMPDEST is the first instruction of the basic block. bool const m_isJumpDest = false; + + /// If block finishes with dynamic jump target index is stored here + llvm::Value* m_jumpTarget = nullptr; }; } diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index 39d4804911..1d00fd2252 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -100,7 +100,7 @@ llvm::BasicBlock* Compiler::getJumpTableBlock() m_jumpTableBlock.reset(new BasicBlock("JumpTable", m_mainFunc, m_builder, true)); InsertPointGuard g{m_builder}; m_builder.SetInsertPoint(m_jumpTableBlock->llvm()); - auto dest = m_jumpTableBlock->localStack().pop(); + auto dest = m_builder.CreatePHI(Type::Word, 8, "target"); auto switchInstr = m_builder.CreateSwitch(dest, getBadJumpBlock()); for (auto&& p : m_basicBlocks) { @@ -165,6 +165,26 @@ std::unique_ptr Compiler::compile(bytes const& _bytecode, std::str removeDeadBlocks(); + // Link jump table target index + if (m_jumpTableBlock) + { + auto phi = llvm::cast(&m_jumpTableBlock->llvm()->getInstList().front()); + for (auto predIt = llvm::pred_begin(m_jumpTableBlock->llvm()); predIt != llvm::pred_end(m_jumpTableBlock->llvm()); ++predIt) + { + BasicBlock* pred = nullptr; + for (auto&& p : m_basicBlocks) + { + if (p.second.llvm() == *predIt) + { + pred = &p.second; + break; + } + } + + phi->addIncoming(pred->getJumpTarget(), pred->llvm()); + } + } + dumpCFGifRequired("blocks-init.dot"); if (m_options.optimizeStack) @@ -565,7 +585,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode } else { - stack.push(target); + _basicBlock.setJumpTarget(target); m_builder.CreateBr(getJumpTableBlock()); } } @@ -581,7 +601,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode } else { - stack.push(target); + _basicBlock.setJumpTarget(target); m_builder.CreateCondBr(cond, getJumpTableBlock(), _nextBasicBlock); } }