mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-22 04:36:42 +00:00
JUMPI fix: an additional item was left on stack when condition is false
This commit is contained in:
parent
0f53e2153a
commit
5152596cbd
2 changed files with 29 additions and 3 deletions
|
|
@ -66,6 +66,9 @@ public:
|
||||||
|
|
||||||
bool isJumpDest() const { return m_isJumpDest; }
|
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; }
|
LocalStack& localStack() { return m_stack; }
|
||||||
|
|
||||||
/// Optimization: propagates values between local stacks in basic blocks
|
/// Optimization: propagates values between local stacks in basic blocks
|
||||||
|
|
@ -112,6 +115,9 @@ private:
|
||||||
/// Is the basic block a valid jump destination.
|
/// Is the basic block a valid jump destination.
|
||||||
/// JUMPDEST is the first instruction of the basic block.
|
/// JUMPDEST is the first instruction of the basic block.
|
||||||
bool const m_isJumpDest = false;
|
bool const m_isJumpDest = false;
|
||||||
|
|
||||||
|
/// If block finishes with dynamic jump target index is stored here
|
||||||
|
llvm::Value* m_jumpTarget = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -100,7 +100,7 @@ llvm::BasicBlock* Compiler::getJumpTableBlock()
|
||||||
m_jumpTableBlock.reset(new BasicBlock("JumpTable", m_mainFunc, m_builder, true));
|
m_jumpTableBlock.reset(new BasicBlock("JumpTable", m_mainFunc, m_builder, true));
|
||||||
InsertPointGuard g{m_builder};
|
InsertPointGuard g{m_builder};
|
||||||
m_builder.SetInsertPoint(m_jumpTableBlock->llvm());
|
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());
|
auto switchInstr = m_builder.CreateSwitch(dest, getBadJumpBlock());
|
||||||
for (auto&& p : m_basicBlocks)
|
for (auto&& p : m_basicBlocks)
|
||||||
{
|
{
|
||||||
|
|
@ -165,6 +165,26 @@ std::unique_ptr<llvm::Module> Compiler::compile(bytes const& _bytecode, std::str
|
||||||
|
|
||||||
removeDeadBlocks();
|
removeDeadBlocks();
|
||||||
|
|
||||||
|
// Link jump table target index
|
||||||
|
if (m_jumpTableBlock)
|
||||||
|
{
|
||||||
|
auto phi = llvm::cast<llvm::PHINode>(&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");
|
dumpCFGifRequired("blocks-init.dot");
|
||||||
|
|
||||||
if (m_options.optimizeStack)
|
if (m_options.optimizeStack)
|
||||||
|
|
@ -565,7 +585,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stack.push(target);
|
_basicBlock.setJumpTarget(target);
|
||||||
m_builder.CreateBr(getJumpTableBlock());
|
m_builder.CreateBr(getJumpTableBlock());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -581,7 +601,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
stack.push(target);
|
_basicBlock.setJumpTarget(target);
|
||||||
m_builder.CreateCondBr(cond, getJumpTableBlock(), _nextBasicBlock);
|
m_builder.CreateCondBr(cond, getJumpTableBlock(), _nextBasicBlock);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue