Merge branch 'develop-evmcc' of https://github.com/imapp-pl/ethereum into develop-evmcc

This commit is contained in:
Paweł Bylica 2014-10-13 16:05:23 +02:00
commit 293f0de7a9
15 changed files with 126 additions and 64 deletions

View file

@ -139,7 +139,16 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode)
}
}
for (auto it = splitPoints.cbegin(); it != splitPoints.cend() && *it < bytecode.size();)
// Remove split points generated from jumps out of code or into data.
for (auto it = splitPoints.cbegin(); it != splitPoints.cend(); )
{
if (*it > bytecode.size() || !validJumpTargets[*it])
it = splitPoints.erase(it);
else
++it;
}
for (auto it = splitPoints.cbegin(); it != splitPoints.cend(); )
{
auto beginInstIdx = *it;
++it;
@ -153,28 +162,22 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode)
for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it)
{
if (it->second >= bytecode.size()) // Jump out of code
auto blockIter = basicBlocks.find(it->second);
if (blockIter != basicBlocks.end())
{
m_directJumpTargets[it->first] = m_finalBlock.get();
m_directJumpTargets[it->first] = &(blockIter->second);
}
else if (!validJumpTargets[it->second]) // Jump into data
else
{
std::cerr << "Bad JUMP at PC " << it->first
<< ": " << it->second << " is not a valid PC\n";
m_directJumpTargets[it->first] = m_badJumpBlock.get();
}
else
{
m_directJumpTargets[it->first] = &basicBlocks.find(it->second)->second;
}
}
for (auto it = indirectJumpTargets.cbegin(); it != indirectJumpTargets.cend(); ++it)
{
if (*it >= bytecode.size())
m_indirectJumpTargets.push_back(m_finalBlock.get());
else
m_indirectJumpTargets.push_back(&basicBlocks.find(*it)->second);
m_indirectJumpTargets.push_back(&basicBlocks.find(*it)->second);
}
}
@ -589,58 +592,56 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
// 1. this is not the first instruction in the block
// 2. m_directJumpTargets[currentPC] is defined (meaning that the previous instruction is a PUSH)
// Otherwise generate a indirect jump (a switch).
BasicBlock* targetBlock = nullptr;
if (currentPC != basicBlock.begin())
{
auto pairIter = m_directJumpTargets.find(currentPC);
if (pairIter != m_directJumpTargets.end())
{
auto targetBlock = pairIter->second;
// The target address is computed at compile time,
// just pop it without looking...
stack.pop();
if (inst == Instruction::JUMP)
{
builder.CreateBr(targetBlock->llvm());
}
else // JUMPI
{
auto top = stack.pop();
auto zero = ConstantInt::get(Type::i256, 0);
auto cond = builder.CreateICmpNE(top, zero, "nonzero");
// Assume the basic blocks are properly ordered:
auto nextBBIter = basicBlockPairIt;
++nextBBIter;
assert (nextBBIter != basicBlocks.end());
auto& followBlock = nextBBIter->second;
builder.CreateCondBr(cond, targetBlock->llvm(), followBlock.llvm());
}
break;
targetBlock = pairIter->second;
}
}
if (inst == Instruction::JUMPI)
if (inst == Instruction::JUMP)
{
std::cerr << "Indirect JUMPI is not supported yet (at PC "
<< currentPC << ")\n";
std::exit(1);
if (targetBlock)
{
// The target address is computed at compile time,
// just pop it without looking...
stack.pop();
builder.CreateBr(targetBlock->llvm());
}
else
{
// FIXME: this get(0) is a temporary workaround to get some of the jump tests running.
stack.get(0);
builder.CreateBr(m_jumpTableBlock->llvm());
}
}
else // JUMPI
{
stack.swap(1);
auto val = stack.pop();
auto zero = ConstantInt::get(Type::i256, 0);
auto cond = builder.CreateICmpNE(val, zero, "nonzero");
// Assume the basic blocks are properly ordered:
auto nextBBIter = basicBlockPairIt;
++nextBBIter;
assert (nextBBIter != basicBlocks.end());
auto& followBlock = nextBBIter->second;
if (targetBlock)
{
stack.pop();
builder.CreateCondBr(cond, targetBlock->llvm(), followBlock.llvm());
}
else
{
builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), followBlock.llvm());
}
}
builder.CreateBr(m_jumpTableBlock->llvm());
/*
// Generate switch for indirect jump.
auto dest = stack.pop();
auto switchInstr = builder.CreateSwitch(dest, m_badJumpBlock->llvm(),
m_indirectJumpTargets.size());
for (auto it = m_indirectJumpTargets.cbegin(); it != m_indirectJumpTargets.cend(); ++it)
{
auto& bb = *it;
auto dest = ConstantInt::get(Type::i256, bb->begin());
switchInstr->addCase(dest, bb->llvm());
}
*/
break;
}
@ -869,7 +870,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
}
else
{
builder.CreateRet(builder.getInt64(0));
builder.CreateBr(m_badJumpBlock->llvm());
}
linkBasicBlocks();

View file

@ -30,9 +30,9 @@ private:
/// @TODO Handle overflow
uint64_t m_blockCost = 0;
llvm::IRBuilder<>& m_builder;
llvm::CallInst* m_checkCall;
llvm::CallInst* m_checkCall = nullptr;
llvm::GlobalVariable* m_gas;
llvm::Function* m_gasCheckFunc;
};
}
}

View file

@ -0,0 +1 @@
601b602502585d

View file

@ -0,0 +1,9 @@
;; Indirect jump out of code
(asm
27
37
MUL
JUMP
JUMPDEST
)

View file

@ -0,0 +1 @@
60016003600302596000600058

View file

@ -0,0 +1,12 @@
;; Indirect jump into data
(asm
1 ;; 0
3
3
MUL ;; 6
JUMPI ;; 7
0 ;; 8
0
JUMP
)

View file

@ -1 +1 @@
601b602502585d
6103e758

View file

@ -1,9 +1,6 @@
;; Bad indirect jump. Should go to BadJumpBlock.
;; Direct jump out of code.
(asm
27
37
MUL
999
JUMP
JUMPDEST
)

View file

@ -0,0 +1 @@
6004586000600058

View file

@ -0,0 +1,9 @@
;; Direct jump into data
(asm
4 ;; 0 0-3
JUMP ;; 2
0 ;; 3 3-4
0 ;; 5 4-7
JUMP ;; 6
)

View file

@ -4,14 +4,14 @@
8 ;; 0
6 ;; 2
ADD ;; 4
JUMP ;; 5
JUMP ;; 5 --> 14
STOP ;; 6
JUMPDEST ;; 7
1 ;; 8
0 ;; 10
MSTORE ;; 12
STOP ;; 13
JUMPDEST ;; 14
JUMPDEST ;; 14
2
0
MSTORE

View file

@ -0,0 +1 @@
6001600460050159005d6001600054

View file

@ -0,0 +1,14 @@
;; Indirect JUMP
(asm
1 ;; 0
4 ;; 2
5 ;; 4
ADD ;; 6
JUMPI ;; 7
STOP ;; 8
JUMPDEST ;; 9
1
0
MSTORE
)

View file

@ -0,0 +1 @@
60006007600501596001600054005d00

View file

@ -0,0 +1,15 @@
;; Indirect JUMP
(asm
0 ;; 0
7 ;; 2
5 ;; 4
ADD ;; 6
JUMPI ;; 7
1 ;; 8
0 ;; 9
MSTORE ;; 10
STOP ;; 11
JUMPDEST ;; 12
STOP
)