|
|
@ -23,42 +23,39 @@ namespace jit |
|
|
|
static const char* jumpDestName = "JmpDst."; |
|
|
|
static const char* basicBlockName = "Instr."; |
|
|
|
|
|
|
|
BasicBlock::BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest) : |
|
|
|
BasicBlock::BasicBlock(instr_idx _firstInstrIdx, code_iterator _begin, code_iterator _end, llvm::Function* _mainFunc, bool isJumpDest): |
|
|
|
m_firstInstrIdx{_firstInstrIdx}, |
|
|
|
m_begin(_begin), |
|
|
|
m_end(_end), |
|
|
|
m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {isJumpDest ? jumpDestName : basicBlockName, std::to_string(_firstInstrIdx)}, _mainFunc)), |
|
|
|
m_builder(_builder), |
|
|
|
m_isJumpDest(isJumpDest) |
|
|
|
{} |
|
|
|
|
|
|
|
BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder, bool isJumpDest) : |
|
|
|
BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, bool isJumpDest): |
|
|
|
m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)), |
|
|
|
m_builder(_builder), |
|
|
|
m_isJumpDest(isJumpDest) |
|
|
|
{} |
|
|
|
|
|
|
|
LocalStack::LocalStack(BasicBlock& _owner, Stack& _globalStack) : |
|
|
|
m_bblock(_owner), |
|
|
|
LocalStack::LocalStack(Stack& _globalStack): |
|
|
|
m_global(_globalStack) |
|
|
|
{} |
|
|
|
|
|
|
|
void LocalStack::push(llvm::Value* _value) |
|
|
|
{ |
|
|
|
assert(_value->getType() == Type::Word); |
|
|
|
m_bblock.m_currentStack.push_back(_value); |
|
|
|
m_maxSize = std::max(m_maxSize, m_bblock.m_currentStack.size()); |
|
|
|
m_currentStack.push_back(_value); |
|
|
|
m_maxSize = std::max(m_maxSize, m_currentStack.size()); // FIXME: This is wrong too. + add min size;
|
|
|
|
} |
|
|
|
|
|
|
|
llvm::Value* LocalStack::pop() |
|
|
|
{ |
|
|
|
auto item = get(0); |
|
|
|
assert(!m_bblock.m_currentStack.empty() || !m_bblock.m_initialStack.empty()); |
|
|
|
assert(!m_currentStack.empty() || !m_initialStack.empty()); |
|
|
|
|
|
|
|
if (m_bblock.m_currentStack.size() > 0) |
|
|
|
m_bblock.m_currentStack.pop_back(); |
|
|
|
if (m_currentStack.size() > 0) |
|
|
|
m_currentStack.pop_back(); |
|
|
|
else |
|
|
|
++m_bblock.m_globalPops; |
|
|
|
++m_globalPops; |
|
|
|
|
|
|
|
return item; |
|
|
|
} |
|
|
@ -87,15 +84,13 @@ void LocalStack::swap(size_t _index) |
|
|
|
|
|
|
|
llvm::Value* LocalStack::get(size_t _index) |
|
|
|
{ |
|
|
|
auto& currentStack = m_bblock.m_currentStack; |
|
|
|
if (_index < currentStack.size()) |
|
|
|
return *(currentStack.rbegin() + _index); // count from back
|
|
|
|
if (_index < m_currentStack.size()) |
|
|
|
return *(m_currentStack.rbegin() + _index); // count from back
|
|
|
|
|
|
|
|
auto& initialStack = m_bblock.m_initialStack; |
|
|
|
auto idx = _index - currentStack.size() + m_bblock.m_globalPops; |
|
|
|
if (idx >= initialStack.size()) |
|
|
|
initialStack.resize(idx + 1); |
|
|
|
auto& item = initialStack[idx]; |
|
|
|
auto idx = _index - m_currentStack.size() + m_globalPops; |
|
|
|
if (idx >= m_initialStack.size()) |
|
|
|
m_initialStack.resize(idx + 1); |
|
|
|
auto& item = m_initialStack[idx]; |
|
|
|
|
|
|
|
if (!item) |
|
|
|
item = m_global.get(idx); |
|
|
@ -105,104 +100,50 @@ llvm::Value* LocalStack::get(size_t _index) |
|
|
|
|
|
|
|
void LocalStack::set(size_t _index, llvm::Value* _word) |
|
|
|
{ |
|
|
|
auto& currentStack = m_bblock.m_currentStack; |
|
|
|
if (_index < currentStack.size()) |
|
|
|
if (_index < m_currentStack.size()) |
|
|
|
{ |
|
|
|
*(currentStack.rbegin() + _index) = _word; |
|
|
|
*(m_currentStack.rbegin() + _index) = _word; |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
auto& initialStack = m_bblock.m_initialStack; |
|
|
|
auto idx = _index - currentStack.size() + m_bblock.m_globalPops; |
|
|
|
assert(idx < initialStack.size()); |
|
|
|
initialStack[idx] = _word; |
|
|
|
auto idx = _index - m_currentStack.size() + m_globalPops; |
|
|
|
assert(idx < m_initialStack.size()); |
|
|
|
m_initialStack[idx] = _word; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void BasicBlock::synchronizeLocalStack(Stack& _evmStack) |
|
|
|
void LocalStack::finalize(llvm::IRBuilder<>& _builder, llvm::BasicBlock& _bb) |
|
|
|
{ |
|
|
|
auto blockTerminator = m_llvmBB->getTerminator(); |
|
|
|
auto blockTerminator = _bb.getTerminator(); |
|
|
|
assert(blockTerminator); |
|
|
|
if (blockTerminator->getOpcode() != llvm::Instruction::Ret) |
|
|
|
{ |
|
|
|
// Not needed in case of ret instruction. Ret invalidates the stack.
|
|
|
|
m_builder.SetInsertPoint(blockTerminator); |
|
|
|
_builder.SetInsertPoint(blockTerminator); |
|
|
|
|
|
|
|
// Update items fetched from global stack ignoring the poped ones
|
|
|
|
assert(m_globalPops <= m_initialStack.size()); // pop() always does get()
|
|
|
|
for (auto i = m_globalPops; i < m_initialStack.size(); ++i) |
|
|
|
{ |
|
|
|
if (m_initialStack[i]) |
|
|
|
_evmStack.set(i, m_initialStack[i]); |
|
|
|
m_global.set(i, m_initialStack[i]); |
|
|
|
} |
|
|
|
|
|
|
|
// Add new items
|
|
|
|
for (auto& item: m_currentStack) |
|
|
|
{ |
|
|
|
if (m_globalPops) // Override poped global items
|
|
|
|
_evmStack.set(--m_globalPops, item); // using pops counter as the index
|
|
|
|
if (m_globalPops) // Override poped global items
|
|
|
|
m_global.set(--m_globalPops, item); // using pops counter as the index
|
|
|
|
else |
|
|
|
_evmStack.push(item); |
|
|
|
m_global.push(item); |
|
|
|
} |
|
|
|
|
|
|
|
// Pop not overriden items
|
|
|
|
if (m_globalPops) |
|
|
|
_evmStack.pop(m_globalPops); |
|
|
|
m_global.pop(m_globalPops); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void BasicBlock::dump() |
|
|
|
{ |
|
|
|
dump(std::cerr, false); |
|
|
|
} |
|
|
|
|
|
|
|
void BasicBlock::dump(std::ostream& _out, bool _dotOutput) |
|
|
|
{ |
|
|
|
llvm::raw_os_ostream out(_out); |
|
|
|
|
|
|
|
out << (_dotOutput ? "" : "Initial stack:\n"); |
|
|
|
for (auto val : m_initialStack) |
|
|
|
{ |
|
|
|
if (val == nullptr) |
|
|
|
out << " ?"; |
|
|
|
else if (llvm::isa<llvm::ExtractValueInst>(val)) |
|
|
|
out << " " << val->getName(); |
|
|
|
else if (llvm::isa<llvm::Instruction>(val)) |
|
|
|
out << *val; |
|
|
|
else |
|
|
|
out << " " << *val; |
|
|
|
|
|
|
|
out << (_dotOutput ? "\\l" : "\n"); |
|
|
|
} |
|
|
|
|
|
|
|
out << (_dotOutput ? "| " : "Instructions:\n"); |
|
|
|
for (auto ins = m_llvmBB->begin(); ins != m_llvmBB->end(); ++ins) |
|
|
|
out << *ins << (_dotOutput ? "\\l" : "\n"); |
|
|
|
|
|
|
|
if (! _dotOutput) |
|
|
|
out << "Current stack:\n"; |
|
|
|
else |
|
|
|
out << "|"; |
|
|
|
|
|
|
|
for (auto val = m_currentStack.rbegin(); val != m_currentStack.rend(); ++val) |
|
|
|
{ |
|
|
|
if (*val == nullptr) |
|
|
|
out << " ?"; |
|
|
|
else if (llvm::isa<llvm::ExtractValueInst>(*val)) |
|
|
|
out << " " << (*val)->getName(); |
|
|
|
else if (llvm::isa<llvm::Instruction>(*val)) |
|
|
|
out << **val; |
|
|
|
else |
|
|
|
out << " " << **val; |
|
|
|
out << (_dotOutput ? "\\l" : "\n"); |
|
|
|
} |
|
|
|
|
|
|
|
if (! _dotOutput) |
|
|
|
out << " ...\n----------------------------------------\n"; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|