mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-21 20:26:41 +00:00
Merge branch 'develop-evmcc' of https://github.com/imapp-pl/ethereum into develop-evmcc
This commit is contained in:
commit
097b7ae1eb
8 changed files with 288 additions and 224 deletions
|
|
@ -1 +1 @@
|
|||
600160026001600a590090600160115900016000546001601ff2
|
||||
600560026001600c59505000906001601559505000036000546001601ff2
|
||||
|
|
|
|||
|
|
@ -1,20 +1,26 @@
|
|||
(asm
|
||||
1 ;; 0
|
||||
5 ;; 0
|
||||
2 ;; 2
|
||||
1 ;; 4
|
||||
10 ;; 6
|
||||
12 ;; 6
|
||||
JUMPI ;; 8
|
||||
STOP ;; 9
|
||||
|
||||
POP ;; 9
|
||||
POP ;; 10
|
||||
STOP ;; 11
|
||||
|
||||
;; stack = 2,1
|
||||
SWAP1 ;; 10
|
||||
1 ;; 11
|
||||
17 ;; 13
|
||||
JUMPI ;; 15
|
||||
STOP ;; 16
|
||||
SWAP1 ;; 12
|
||||
1 ;; 13
|
||||
21 ;; 15
|
||||
JUMPI ;; 17
|
||||
|
||||
POP ;; 18
|
||||
POP ;; 19
|
||||
STOP ;; 20
|
||||
|
||||
;; stack = 1,2
|
||||
ADD ;; 17
|
||||
SUB ;; 21
|
||||
0
|
||||
MSTORE
|
||||
1
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
600160026001600a59009090600160125900016000546001601ff2
|
||||
600260056001600c5950500090906001601659505000036000546001601ff2
|
||||
|
|
|
|||
|
|
@ -1,21 +1,27 @@
|
|||
(asm
|
||||
1 ;; 0
|
||||
2 ;; 2
|
||||
2 ;; 0
|
||||
5 ;; 2
|
||||
1 ;; 4
|
||||
10 ;; 6
|
||||
12 ;; 6
|
||||
JUMPI ;; 8
|
||||
STOP ;; 9
|
||||
|
||||
POP ;; 9
|
||||
POP ;; 10
|
||||
STOP ;; 11
|
||||
|
||||
;; stack = 2,1
|
||||
SWAP1 ;; 10
|
||||
SWAP1 ;; 11
|
||||
1 ;; 12
|
||||
18 ;; 14
|
||||
JUMPI ;; 16
|
||||
STOP ;; 17
|
||||
SWAP1 ;; 12
|
||||
SWAP1 ;; 13
|
||||
1 ;; 14
|
||||
22 ;; 16
|
||||
JUMPI ;; 18
|
||||
|
||||
POP ;; 19
|
||||
POP ;; 20
|
||||
STOP ;; 21
|
||||
|
||||
;; stack = 2,1
|
||||
ADD ;; 18
|
||||
SUB ;; 22
|
||||
0
|
||||
MSTORE
|
||||
1
|
||||
|
|
|
|||
|
|
@ -5,9 +5,11 @@
|
|||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
#include <llvm/IR/CFG.h>
|
||||
#include <llvm/IR/Function.h>
|
||||
#include <llvm/IR/Instructions.h>
|
||||
#include <llvm/IR/IRBuilder.h>
|
||||
#include <llvm/Support/raw_os_ostream.h>
|
||||
|
||||
#include "Type.h"
|
||||
|
||||
|
|
@ -24,17 +26,18 @@ BasicBlock::BasicBlock(ProgramCounter _beginInstIdx, ProgramCounter _endInstIdx,
|
|||
m_beginInstIdx(_beginInstIdx),
|
||||
m_endInstIdx(_endInstIdx),
|
||||
m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), {NamePrefix, std::to_string(_beginInstIdx)}, _mainFunc)),
|
||||
m_stack(_builder)
|
||||
m_stack(_builder, m_llvmBB)
|
||||
{}
|
||||
|
||||
BasicBlock::BasicBlock(std::string _name, llvm::Function* _mainFunc, llvm::IRBuilder<>& _builder) :
|
||||
m_beginInstIdx(0),
|
||||
m_endInstIdx(0),
|
||||
m_llvmBB(llvm::BasicBlock::Create(_mainFunc->getContext(), _name, _mainFunc)),
|
||||
m_stack(_builder)
|
||||
m_stack(_builder, m_llvmBB)
|
||||
{}
|
||||
|
||||
BasicBlock::LocalStack::LocalStack(llvm::IRBuilder<>& _builder) :
|
||||
BasicBlock::LocalStack::LocalStack(llvm::IRBuilder<>& _builder, llvm::BasicBlock* _llvmBB) :
|
||||
m_llvmBB(_llvmBB),
|
||||
m_builder(_builder),
|
||||
m_initialStack(),
|
||||
m_currentStack(),
|
||||
|
|
@ -82,7 +85,7 @@ void BasicBlock::LocalStack::swap(size_t _index)
|
|||
|
||||
void BasicBlock::LocalStack::synchronize(Stack& _evmStack)
|
||||
{
|
||||
auto blockTerminator = m_builder.GetInsertBlock()->getTerminator();
|
||||
auto blockTerminator = m_llvmBB->getTerminator();
|
||||
assert(blockTerminator != nullptr);
|
||||
m_builder.SetInsertPoint(blockTerminator);
|
||||
|
||||
|
|
@ -182,44 +185,190 @@ void BasicBlock::LocalStack::set(size_t _index, llvm::Value* _word)
|
|||
}
|
||||
|
||||
|
||||
|
||||
void BasicBlock::linkLocalStacks(std::vector<BasicBlock*> basicBlocks, llvm::IRBuilder<>& _builder)
|
||||
{
|
||||
struct BBInfo
|
||||
{
|
||||
BasicBlock& bblock;
|
||||
std::vector<BBInfo*> predecessors;
|
||||
size_t inputItems;
|
||||
size_t outputItems;
|
||||
std::vector<llvm::PHINode*> phisToRewrite;
|
||||
|
||||
BBInfo(BasicBlock& _bblock) :
|
||||
bblock(_bblock),
|
||||
predecessors(),
|
||||
inputItems(0),
|
||||
outputItems(0)
|
||||
{
|
||||
auto& initialStack = bblock.localStack().m_initialStack;
|
||||
for (auto it = initialStack.begin();
|
||||
it != initialStack.end() && *it != nullptr;
|
||||
++it, ++inputItems);
|
||||
|
||||
//if (bblock.localStack().m_tosOffset > 0)
|
||||
// outputItems = bblock.localStack().m_tosOffset;
|
||||
auto& exitStack = bblock.localStack().m_currentStack;
|
||||
for (auto it = exitStack.rbegin();
|
||||
it != exitStack.rend() && *it != nullptr;
|
||||
++it, ++outputItems);
|
||||
}
|
||||
};
|
||||
|
||||
std::map<llvm::BasicBlock*, BBInfo> cfg;
|
||||
|
||||
// Create nodes in cfg
|
||||
for (auto bb : basicBlocks)
|
||||
cfg.emplace(bb->llvm(), *bb);
|
||||
|
||||
// Create edges in cfg: for each bb info fill the list
|
||||
// of predecessor infos.
|
||||
for (auto& pair : cfg)
|
||||
{
|
||||
auto bb = pair.first;
|
||||
auto& info = pair.second;
|
||||
|
||||
for (auto predIt = llvm::pred_begin(bb); predIt != llvm::pred_end(bb); ++predIt)
|
||||
{
|
||||
auto predInfoEntry = cfg.find(*predIt);
|
||||
if (predInfoEntry != cfg.end())
|
||||
info.predecessors.push_back(&predInfoEntry->second);
|
||||
}
|
||||
}
|
||||
|
||||
// Iteratively compute inputs and outputs of each block, until reaching fixpoint.
|
||||
bool valuesChanged = true;
|
||||
while (valuesChanged)
|
||||
{
|
||||
if (getenv("EVMCC_DEBUG_BLOCKS"))
|
||||
{
|
||||
for (auto& pair: cfg)
|
||||
std::cerr << pair.second.bblock.llvm()->getName().str()
|
||||
<< ": in " << pair.second.inputItems
|
||||
<< ", out " << pair.second.outputItems
|
||||
<< "\n";
|
||||
}
|
||||
|
||||
valuesChanged = false;
|
||||
for (auto& pair : cfg)
|
||||
{
|
||||
auto& info = pair.second;
|
||||
|
||||
if (info.predecessors.empty())
|
||||
info.inputItems = 0; // no consequences for other blocks, so leave valuesChanged false
|
||||
|
||||
for (auto predInfo : info.predecessors)
|
||||
{
|
||||
if (predInfo->outputItems < info.inputItems)
|
||||
{
|
||||
info.inputItems = predInfo->outputItems;
|
||||
valuesChanged = true;
|
||||
}
|
||||
else if (predInfo->outputItems > info.inputItems)
|
||||
{
|
||||
predInfo->outputItems = info.inputItems;
|
||||
valuesChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Propagate values between blocks.
|
||||
for (auto& entry : cfg)
|
||||
{
|
||||
auto& info = entry.second;
|
||||
auto& bblock = info.bblock;
|
||||
|
||||
llvm::BasicBlock::iterator fstNonPhi(bblock.llvm()->getFirstNonPHI());
|
||||
auto phiIter = bblock.localStack().m_initialStack.begin();
|
||||
for (size_t index = 0; index < info.inputItems; ++index, ++phiIter)
|
||||
{
|
||||
assert(llvm::isa<llvm::PHINode>(*phiIter));
|
||||
auto phi = llvm::cast<llvm::PHINode>(*phiIter);
|
||||
|
||||
for (auto predIt : info.predecessors)
|
||||
{
|
||||
auto& predExitStack = predIt->bblock.localStack().m_currentStack;
|
||||
auto value = *(predExitStack.end() - 1 - index);
|
||||
phi->addIncoming(value, predIt->bblock.llvm());
|
||||
}
|
||||
|
||||
// Move phi to the front
|
||||
if (llvm::BasicBlock::iterator(phi) != bblock.llvm()->begin())
|
||||
{
|
||||
phi->removeFromParent();
|
||||
_builder.SetInsertPoint(bblock.llvm(), bblock.llvm()->begin());
|
||||
_builder.Insert(phi);
|
||||
}
|
||||
}
|
||||
|
||||
// The items pulled directly from predecessors block must be removed
|
||||
// from the list of items that has to be popped from the initial stack.
|
||||
auto& initialStack = bblock.localStack().m_initialStack;
|
||||
initialStack.erase(initialStack.begin(), initialStack.begin() + info.inputItems);
|
||||
// Initial stack shrinks, so the size difference grows:
|
||||
bblock.localStack().m_tosOffset += info.inputItems;
|
||||
}
|
||||
|
||||
// We must account for the items that were pushed directly to successor
|
||||
// blocks and thus should not be on the list of items to be pushed onto
|
||||
// to EVM stack
|
||||
for (auto& entry : cfg)
|
||||
{
|
||||
auto& info = entry.second;
|
||||
auto& bblock = info.bblock;
|
||||
|
||||
auto& exitStack = bblock.localStack().m_currentStack;
|
||||
exitStack.erase(exitStack.end() - info.outputItems, exitStack.end());
|
||||
bblock.localStack().m_tosOffset -= info.outputItems;
|
||||
}
|
||||
}
|
||||
|
||||
void BasicBlock::dump()
|
||||
{
|
||||
std::cerr << "Initial stack:\n";
|
||||
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_stack.m_initialStack)
|
||||
{
|
||||
if (val == nullptr)
|
||||
std::cerr << " ?\n";
|
||||
out << " ?";
|
||||
else if (llvm::isa<llvm::Instruction>(val))
|
||||
val->dump();
|
||||
out << *val;
|
||||
else
|
||||
{
|
||||
std::cerr << " ";
|
||||
val->dump();
|
||||
}
|
||||
}
|
||||
std::cerr << " ...\n";
|
||||
out << " " << *val;
|
||||
|
||||
std::cerr << "Instructions:\n";
|
||||
out << (_dotOutput ? "\\l" : "\n");
|
||||
}
|
||||
|
||||
out << (_dotOutput ? "| " : "Instructions:\n");
|
||||
for (auto ins = m_llvmBB->begin(); ins != m_llvmBB->end(); ++ins)
|
||||
ins->dump();
|
||||
out << *ins << (_dotOutput ? "\\l" : "\n");
|
||||
|
||||
std::cerr << "Current stack (offset = "
|
||||
<< m_stack.m_tosOffset << "):\n";
|
||||
if (! _dotOutput)
|
||||
out << "Current stack (offset = " << m_stack.m_tosOffset << "):\n";
|
||||
else
|
||||
out << "|";
|
||||
|
||||
for (auto val = m_stack.m_currentStack.rbegin(); val != m_stack.m_currentStack.rend(); ++val)
|
||||
{
|
||||
if (*val == nullptr)
|
||||
std::cerr << " ?\n";
|
||||
out << " ?";
|
||||
else if (llvm::isa<llvm::Instruction>(*val))
|
||||
(*val)->dump();
|
||||
out << **val;
|
||||
else
|
||||
{
|
||||
std::cerr << " ";
|
||||
(*val)->dump();
|
||||
out << " " << **val;
|
||||
out << (_dotOutput ? "\\l" : "\n");
|
||||
}
|
||||
|
||||
}
|
||||
std::cerr << " ...\n----------------------------------------\n";
|
||||
if (! _dotOutput)
|
||||
out << " ...\n----------------------------------------\n";
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
LocalStack(llvm::IRBuilder<>& _builder);
|
||||
LocalStack(llvm::IRBuilder<>& _builder, llvm::BasicBlock* _llvmBB);
|
||||
LocalStack(LocalStack const&) = delete;
|
||||
void operator=(LocalStack const&) = delete;
|
||||
friend BasicBlock;
|
||||
|
|
@ -55,6 +55,8 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
llvm::BasicBlock* m_llvmBB;
|
||||
|
||||
llvm::IRBuilder<>& m_builder;
|
||||
|
||||
/**
|
||||
|
|
@ -99,9 +101,14 @@ public:
|
|||
|
||||
LocalStack& localStack() { return m_stack; }
|
||||
|
||||
/// Optimization: propagates values between local stacks in basic blocks
|
||||
/// to avoid excessive pushing/popping on the EVM stack.
|
||||
static void linkLocalStacks(std::vector<BasicBlock*> _basicBlocks, llvm::IRBuilder<>& _builder);
|
||||
|
||||
/// Prints local stack and block instructions to stderr.
|
||||
/// Useful for calling in a debugger session.
|
||||
void dump();
|
||||
void dump(std::ostream& os, bool _dotOutput = false);
|
||||
|
||||
private:
|
||||
ProgramCounter const m_beginInstIdx;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
|
||||
#include "Compiler.h"
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include <boost/dynamic_bitset.hpp>
|
||||
|
||||
#include <llvm/IR/Module.h>
|
||||
#include <llvm/IR/CFG.h>
|
||||
#include <llvm/ADT/PostOrderIterator.h>
|
||||
#include <llvm/IR/CFG.h>
|
||||
#include <llvm/IR/Module.h>
|
||||
#include <llvm/IR/IntrinsicInst.h>
|
||||
|
||||
#include <libevmface/Instruction.h>
|
||||
|
|
@ -190,9 +192,6 @@ std::unique_ptr<llvm::Module> Compiler::compile(bytesConstRef bytecode)
|
|||
++iterCopy;
|
||||
auto nextBasicBlock = (iterCopy != basicBlocks.end()) ? iterCopy->second.llvm() : nullptr;
|
||||
compileBasicBlock(basicBlock, bytecode, memory, ext, gasMeter, nextBasicBlock);
|
||||
if (getenv("EVMCC_DEBUG_BLOCKS"))
|
||||
basicBlock.dump();
|
||||
basicBlock.localStack().synchronize(stack);
|
||||
}
|
||||
|
||||
// Code for special blocks:
|
||||
|
|
@ -208,9 +207,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(bytesConstRef bytecode)
|
|||
m_builder.SetInsertPoint(m_jumpTableBlock->llvm());
|
||||
if (m_indirectJumpTargets.size() > 0)
|
||||
{
|
||||
// auto& stack = m_jumpTableBlock->getStack();
|
||||
|
||||
auto dest = m_jumpTableBlock->localStack().pop(); //m_jumpTableBlock->localGet(0); // stack.pop();
|
||||
auto dest = m_jumpTableBlock->localStack().pop();
|
||||
auto switchInstr = m_builder.CreateSwitch(dest, m_badJumpBlock->llvm(),
|
||||
m_indirectJumpTargets.size());
|
||||
for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it)
|
||||
|
|
@ -225,8 +222,51 @@ std::unique_ptr<llvm::Module> Compiler::compile(bytesConstRef bytecode)
|
|||
m_builder.CreateBr(m_badJumpBlock->llvm());
|
||||
}
|
||||
|
||||
removeDeadBlocks();
|
||||
|
||||
if (getenv("EVMCC_DEBUG_BLOCKS"))
|
||||
{
|
||||
std::ofstream ofs("blocks-init.dot");
|
||||
dumpBasicBlockGraph(ofs);
|
||||
ofs.close();
|
||||
std::cerr << "\n\nAfter dead block elimination \n\n";
|
||||
dump();
|
||||
}
|
||||
|
||||
if (getenv("EVMCC_OPTIMIZE_STACK"))
|
||||
{
|
||||
std::vector<BasicBlock*> blockList;
|
||||
for (auto& entry : basicBlocks)
|
||||
blockList.push_back(&entry.second);
|
||||
|
||||
if (m_jumpTableBlock != nullptr)
|
||||
blockList.push_back(m_jumpTableBlock.get());
|
||||
|
||||
BasicBlock::linkLocalStacks(blockList, m_builder);
|
||||
|
||||
if (getenv("EVMCC_DEBUG_BLOCKS"))
|
||||
{
|
||||
std::ofstream ofs("blocks-opt.dot");
|
||||
dumpBasicBlockGraph(ofs);
|
||||
ofs.close();
|
||||
std::cerr << "\n\nAfter stack optimization \n\n";
|
||||
dump();
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& entry : basicBlocks)
|
||||
entry.second.localStack().synchronize(stack);
|
||||
if (m_jumpTableBlock != nullptr)
|
||||
m_jumpTableBlock->localStack().synchronize(stack);
|
||||
linkBasicBlocks();
|
||||
|
||||
if (getenv("EVMCC_DEBUG_BLOCKS"))
|
||||
{
|
||||
std::ofstream ofs("blocks-sync.dot");
|
||||
dumpBasicBlockGraph(ofs);
|
||||
ofs.close();
|
||||
std::cerr << "\n\nAfter stack synchronization \n\n";
|
||||
dump();
|
||||
}
|
||||
|
||||
return module;
|
||||
}
|
||||
|
|
@ -879,7 +919,8 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode,
|
|||
}
|
||||
|
||||
|
||||
void Compiler::linkBasicBlocks() // Stack& stack)
|
||||
|
||||
void Compiler::removeDeadBlocks()
|
||||
{
|
||||
// Remove dead basic blocks
|
||||
auto sthErased = false;
|
||||
|
|
@ -907,187 +948,33 @@ void Compiler::linkBasicBlocks() // Stack& stack)
|
|||
m_jumpTableBlock->llvm()->eraseFromParent();
|
||||
m_jumpTableBlock.reset();
|
||||
}
|
||||
|
||||
/*
|
||||
struct BBInfo
|
||||
{
|
||||
BasicBlock& bblock;
|
||||
std::vector<BBInfo*> predecessors;
|
||||
size_t inputItems;
|
||||
size_t outputItems;
|
||||
std::vector<llvm::PHINode*> phisToRewrite;
|
||||
|
||||
BBInfo(BasicBlock& _bblock)
|
||||
: bblock(_bblock),
|
||||
predecessors(),
|
||||
inputItems(_bblock.getStack().initialSize()),
|
||||
outputItems(_bblock.getStack().size())
|
||||
{}
|
||||
};
|
||||
|
||||
std::map<llvm::BasicBlock*, BBInfo> cfg;
|
||||
|
||||
// Create nodes in cfg
|
||||
for (auto& pair : this->basicBlocks)
|
||||
{
|
||||
auto& bb = pair.second;
|
||||
cfg.emplace(bb.llvm(), bb);
|
||||
}
|
||||
|
||||
// Insert jump table block into cfg
|
||||
if (m_jumpTableBlock)
|
||||
cfg.emplace(m_jumpTableBlock->llvm(), *m_jumpTableBlock);
|
||||
|
||||
auto& entryBlock = m_mainFunc->getEntryBlock();
|
||||
|
||||
// Create edges in cfg
|
||||
for (auto& pair : cfg)
|
||||
{
|
||||
auto bbPtr = pair.first;
|
||||
auto& bbInfo = pair.second;
|
||||
|
||||
for (auto predIt = llvm::pred_begin(bbPtr); predIt != llvm::pred_end(bbPtr); ++predIt)
|
||||
{
|
||||
if (*predIt != &entryBlock)
|
||||
{
|
||||
auto predInfoEntry = cfg.find(*predIt);
|
||||
assert(predInfoEntry != cfg.end());
|
||||
bbInfo.predecessors.push_back(&predInfoEntry->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Iteratively compute inputs and outputs of each block, until reaching fixpoint.
|
||||
bool valuesChanged = true;
|
||||
while (valuesChanged)
|
||||
{
|
||||
valuesChanged = false;
|
||||
for (auto& pair : cfg)
|
||||
{
|
||||
auto& bbInfo = pair.second;
|
||||
|
||||
if (bbInfo.predecessors.empty())
|
||||
bbInfo.inputItems = 0; // no consequences for other blocks, so leave valuesChanged false
|
||||
|
||||
for (auto predInfo : bbInfo.predecessors)
|
||||
{
|
||||
if (predInfo->outputItems < bbInfo.inputItems)
|
||||
{
|
||||
bbInfo.inputItems = predInfo->outputItems;
|
||||
valuesChanged = true;
|
||||
}
|
||||
else if (predInfo->outputItems > bbInfo.inputItems)
|
||||
{
|
||||
predInfo->outputItems = bbInfo.inputItems;
|
||||
valuesChanged = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// std::map<llvm::Instruction*, llvm::Value*> phiReplacements;
|
||||
// std::vector<llvm::Instruction*> phiNodesToRewrite;
|
||||
|
||||
// Propagate values between blocks.
|
||||
for (auto& pair : cfg)
|
||||
{
|
||||
auto llbb = pair.first;
|
||||
auto& bbInfo = pair.second;
|
||||
auto& bblock = bbInfo.bblock;
|
||||
|
||||
// Complete phi nodes for the top bbInfo.inputItems placeholder values
|
||||
auto instrIter = llbb->begin();
|
||||
for (size_t valueIdx = 0; valueIdx < bbInfo.inputItems; ++instrIter, ++valueIdx)
|
||||
{
|
||||
auto phi = llvm::cast<llvm::PHINode>(instrIter);
|
||||
for (auto predIt : bbInfo.predecessors)
|
||||
{
|
||||
assert(valueIdx < predIt->bblock.getStack().size());
|
||||
auto value = predIt->bblock.getStack().get(valueIdx);
|
||||
phi->addIncoming(value, predIt->bblock.llvm());
|
||||
}
|
||||
}
|
||||
|
||||
// Turn the remaining phi nodes into stack.pop's.
|
||||
// m_builder.SetInsertPoint(llbb, llvm::BasicBlock::iterator(llbb->getFirstNonPHI()));
|
||||
for (; llvm::isa<llvm::PHINode>(*instrIter); ++instrIter)
|
||||
{
|
||||
auto phi = llvm::cast<llvm::PHINode>(instrIter);
|
||||
// auto value = stack.popWord();
|
||||
// Don't delete the phi node yet. It may still be stored in a local stack of some block.
|
||||
// phiReplacements[phi] = value;
|
||||
bbInfo.phisToRewrite.push_back(phi);
|
||||
}
|
||||
|
||||
// Emit stack push's at the end of the block, just before the terminator;
|
||||
m_builder.SetInsertPoint(llbb, -- llbb->end());
|
||||
auto localStackSize = bblock.getStack().size();
|
||||
assert(localStackSize >= bbInfo.outputItems);
|
||||
for (size_t i = 0; i < localStackSize - bbInfo.outputItems; ++i)
|
||||
stack.pushWord(bblock.getStack().get(localStackSize - 1 - i));
|
||||
}
|
||||
|
||||
for (auto& entry : cfg)
|
||||
{
|
||||
// Where was the last stack.pop() inserted
|
||||
auto lastPopIt = entry.first->begin();
|
||||
|
||||
for (auto phi : entry.second.phisToRewrite)
|
||||
{
|
||||
// Insert stack.pop() before the first use of phi,
|
||||
// then replace all uses of phi with the popped val.
|
||||
|
||||
if (phi->use_begin() == phi->use_end())
|
||||
{
|
||||
// For a phi with no uses, insert pop just after the previous one
|
||||
}
|
||||
std::cout << "*** PHI node " << phi->getName().str() << " has no uses!\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(llvm::isa<llvm::Instruction>(phi->use_begin()->getUser()));
|
||||
|
||||
m_builder.SetInsertPoint(*phi->use_begin());
|
||||
auto popVal = stack.popWord();
|
||||
phi->replaceAllUsesWith(popVal);
|
||||
phi->eraseFromParent();
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void Compiler::dumpBasicBlockGraph(std::ostream& out)
|
||||
{
|
||||
out << "digraph BB {\n"
|
||||
<< " node [shape=record];\n"
|
||||
<< " node [shape=record, fontname=Courier, fontsize=10];\n"
|
||||
<< " entry [share=record, label=\"entry block\"];\n";
|
||||
/*
|
||||
|
||||
std::vector<BasicBlock*> blocks;
|
||||
for (auto& pair : this->basicBlocks)
|
||||
for (auto& pair : basicBlocks)
|
||||
blocks.push_back(&pair.second);
|
||||
if (m_jumpTableBlock)
|
||||
blocks.push_back(m_jumpTableBlock.get());
|
||||
if (m_badJumpBlock)
|
||||
blocks.push_back(m_badJumpBlock.get());
|
||||
|
||||
std::map<BasicBlock*,int> phiNodesPerBlock;
|
||||
// std::map<BasicBlock*,int> phiNodesPerBlock;
|
||||
|
||||
// Output nodes
|
||||
for (auto bb : blocks)
|
||||
{
|
||||
std::string blockName = bb->llvm()->getName();
|
||||
|
||||
int numOfPhiNodes = 0;
|
||||
auto firstNonPhiPtr = bb->llvm()->getFirstNonPHI();
|
||||
for (auto instrIter = bb->llvm()->begin(); &*instrIter != firstNonPhiPtr; ++instrIter, ++numOfPhiNodes);
|
||||
phiNodesPerBlock[bb] = numOfPhiNodes;
|
||||
std::ostringstream oss;
|
||||
bb->dump(oss, true);
|
||||
|
||||
auto initStackSize = bb->getStack().initialSize();
|
||||
auto endStackSize = bb->getStack().size();
|
||||
|
||||
out << " \"" << blockName << "\" [shape=record, label=\""
|
||||
<< initStackSize << "|" << blockName << "|" << endStackSize
|
||||
<< "\"];\n";
|
||||
out << " \"" << blockName << "\" [shape=record, label=\" { " << blockName << "|" << oss.str() << "} \"];\n";
|
||||
}
|
||||
|
||||
// Output edges
|
||||
|
|
@ -1100,14 +987,21 @@ void Compiler::dumpBasicBlockGraph(std::ostream& out)
|
|||
{
|
||||
out << " \"" << (*it)->getName().str() << "\" -> \"" << blockName << "\" ["
|
||||
<< ((m_jumpTableBlock.get() && *it == m_jumpTableBlock.get()->llvm()) ? "style = dashed, " : "")
|
||||
<< "label = \""
|
||||
<< phiNodesPerBlock[bb]
|
||||
<< "\"];\n";
|
||||
//<< "label = \""
|
||||
//<< phiNodesPerBlock[bb]
|
||||
<< "];\n";
|
||||
}
|
||||
}
|
||||
|
||||
out << "}\n";
|
||||
*/
|
||||
}
|
||||
|
||||
void Compiler::dump()
|
||||
{
|
||||
for (auto& entry : basicBlocks)
|
||||
entry.second.dump();
|
||||
if (m_jumpTableBlock != nullptr)
|
||||
m_jumpTableBlock->dump();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,8 +33,10 @@ private:
|
|||
|
||||
void compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock);
|
||||
|
||||
void linkBasicBlocks(); //class Stack& stack);
|
||||
void removeDeadBlocks();
|
||||
|
||||
/// Dump all basic blocks to stderr. Useful in a debugging session.
|
||||
void dump();
|
||||
|
||||
llvm::IRBuilder<> m_builder;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue