mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-20 11:46:44 +00:00
Make the Stack an integral part of BasicBlock
This commit is contained in:
parent
58c5950731
commit
dafa5bc890
5 changed files with 82 additions and 121 deletions
|
|
@ -2,6 +2,7 @@
|
|||
#include "BasicBlock.h"
|
||||
|
||||
#include <llvm/IR/Function.h>
|
||||
#include <llvm/IR/Instructions.h>
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -6,13 +6,47 @@
|
|||
namespace evmcc
|
||||
{
|
||||
|
||||
using ProgramCounter = uint64_t;
|
||||
using ProgramCounter = uint64_t; // TODO: Rename
|
||||
|
||||
class BasicBlock
|
||||
{
|
||||
public:
|
||||
using State = std::vector<llvm::Value*>;
|
||||
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<llvm::Value*> 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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -7,7 +7,6 @@
|
|||
#include <libevmface/Instruction.h>
|
||||
|
||||
#include "Memory.h"
|
||||
#include "Stack.h"
|
||||
#include "Ext.h"
|
||||
|
||||
namespace evmcc
|
||||
|
|
@ -187,9 +186,7 @@ std::unique_ptr<llvm::Module> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,59 +0,0 @@
|
|||
|
||||
#include "Stack.h"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <llvm/IR/Instructions.h>
|
||||
|
||||
#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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,47 +0,0 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <llvm/IR/Value.h>
|
||||
|
||||
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
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in a new issue