Browse Source

Make the Stack an integral part of BasicBlock

cl-refactor
Paweł Bylica 10 years ago
parent
commit
0ec77d681c
  1. 37
      evmcc/BasicBlock.cpp
  2. 51
      evmcc/BasicBlock.h
  3. 9
      evmcc/Compiler.cpp
  4. 59
      evmcc/Stack.cpp
  5. 47
      evmcc/Stack.h
  6. 2
      windows/evmcc.vcxproj
  7. 2
      windows/evmcc.vcxproj.filters

37
evmcc/BasicBlock.cpp

@ -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));
}
}

51
evmcc/BasicBlock.h

@ -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;
};
}

9
evmcc/Compiler.cpp

@ -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);
}
}
}

59
evmcc/Stack.cpp

@ -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));
}
}

47
evmcc/Stack.h

@ -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
};
}

2
windows/evmcc.vcxproj

@ -26,7 +26,6 @@
<ClCompile Include="..\evmcc\Ext.cpp" />
<ClCompile Include="..\evmcc\Memory.cpp" />
<ClCompile Include="..\evmcc\Runtime.cpp" />
<ClCompile Include="..\evmcc\Stack.cpp" />
<ClCompile Include="..\evmcc\Utils.cpp" />
</ItemGroup>
<ItemGroup>
@ -36,7 +35,6 @@
<ClInclude Include="..\evmcc\Ext.h" />
<ClInclude Include="..\evmcc\Memory.h" />
<ClInclude Include="..\evmcc\Runtime.h" />
<ClInclude Include="..\evmcc\Stack.h" />
<ClInclude Include="..\evmcc\Utils.h" />
</ItemGroup>
<PropertyGroup Label="Globals">

2
windows/evmcc.vcxproj.filters

@ -4,7 +4,6 @@
<ClCompile Include="..\evmcc\evmcc.cpp" />
<ClCompile Include="..\evmcc\Compiler.cpp" />
<ClCompile Include="..\evmcc\ExecutionEngine.cpp" />
<ClCompile Include="..\evmcc\Stack.cpp" />
<ClCompile Include="..\evmcc\Ext.cpp" />
<ClCompile Include="..\evmcc\Memory.cpp" />
<ClCompile Include="..\evmcc\Utils.cpp" />
@ -14,7 +13,6 @@
<ItemGroup>
<ClInclude Include="..\evmcc\Compiler.h" />
<ClInclude Include="..\evmcc\ExecutionEngine.h" />
<ClInclude Include="..\evmcc\Stack.h" />
<ClInclude Include="..\evmcc\Ext.h" />
<ClInclude Include="..\evmcc\Memory.h" />
<ClInclude Include="..\evmcc\Utils.h" />

Loading…
Cancel
Save