mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-21 20:26:41 +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 "BasicBlock.h"
|
||||||
|
|
||||||
#include <llvm/IR/Function.h>
|
#include <llvm/IR/Function.h>
|
||||||
|
#include <llvm/IR/Instructions.h>
|
||||||
|
|
||||||
namespace evmcc
|
namespace evmcc
|
||||||
{
|
{
|
||||||
|
|
@ -11,7 +12,41 @@ const char* BasicBlock::NamePrefix = "Instr.";
|
||||||
BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc) :
|
BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc) :
|
||||||
m_beginInstIdx(_beginInstIdx),
|
m_beginInstIdx(_beginInstIdx),
|
||||||
m_endInstIdx(_endInstIdx),
|
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
|
namespace evmcc
|
||||||
{
|
{
|
||||||
|
|
||||||
using ProgramCounter = uint64_t;
|
using ProgramCounter = uint64_t; // TODO: Rename
|
||||||
|
|
||||||
class BasicBlock
|
class BasicBlock
|
||||||
{
|
{
|
||||||
public:
|
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;
|
static const char* NamePrefix;
|
||||||
|
|
||||||
explicit BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc);
|
explicit BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx, llvm::Function* _mainFunc);
|
||||||
|
|
@ -23,18 +57,19 @@ public:
|
||||||
operator llvm::BasicBlock*() { return m_llvmBB; }
|
operator llvm::BasicBlock*() { return m_llvmBB; }
|
||||||
llvm::BasicBlock* llvm() { 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 begin() { return m_beginInstIdx; }
|
||||||
ProgramCounter end() { return m_endInstIdx; }
|
ProgramCounter end() { return m_endInstIdx; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ProgramCounter m_beginInstIdx;
|
ProgramCounter const m_beginInstIdx;
|
||||||
ProgramCounter m_endInstIdx;
|
ProgramCounter const m_endInstIdx;
|
||||||
llvm::BasicBlock* m_llvmBB;
|
llvm::BasicBlock* const m_llvmBB;
|
||||||
|
|
||||||
/// Basic black state vector - current/end values and their positions
|
/// Basic black state vector (stack) - current/end values and their positions on stack
|
||||||
State m_state;
|
/// @internal Must be AFTER m_llvmBB
|
||||||
|
Stack m_stack;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
#include <libevmface/Instruction.h>
|
#include <libevmface/Instruction.h>
|
||||||
|
|
||||||
#include "Memory.h"
|
#include "Memory.h"
|
||||||
#include "Stack.h"
|
|
||||||
#include "Ext.h"
|
#include "Ext.h"
|
||||||
|
|
||||||
namespace evmcc
|
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)
|
for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt)
|
||||||
{
|
{
|
||||||
auto& basicBlock = basicBlockPairIt->second;
|
auto& basicBlock = basicBlockPairIt->second;
|
||||||
|
auto& stack = basicBlock.getStack();
|
||||||
BBStack stack;
|
|
||||||
stack.setBasicBlock(basicBlock);
|
|
||||||
builder.SetInsertPoint(basicBlock);
|
builder.SetInsertPoint(basicBlock);
|
||||||
|
|
||||||
for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC)
|
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)
|
for (auto predIt = llvm::pred_begin(llvmBB); predIt != llvm::pred_end(llvmBB); ++predIt)
|
||||||
{
|
{
|
||||||
auto& predBB = findBasicBlock(*predIt);
|
auto& predBB = findBasicBlock(*predIt);
|
||||||
assert(valueIdx < predBB.getState().size()); // TODO: Report error
|
assert(valueIdx < predBB.getStack().size()); // TODO: Report error
|
||||||
phi->addIncoming(*(predBB.getState().rbegin() + valueIdx), predBB);
|
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