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; auto beginInstIdx = *it;
++it; ++it;
@ -153,27 +162,21 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode)
for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) 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 std::cerr << "Bad JUMP at PC " << it->first
<< ": " << it->second << " is not a valid PC\n"; << ": " << it->second << " is not a valid PC\n";
m_directJumpTargets[it->first] = m_badJumpBlock.get(); 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) 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 // 1. this is not the first instruction in the block
// 2. m_directJumpTargets[currentPC] is defined (meaning that the previous instruction is a PUSH) // 2. m_directJumpTargets[currentPC] is defined (meaning that the previous instruction is a PUSH)
// Otherwise generate a indirect jump (a switch). // Otherwise generate a indirect jump (a switch).
BasicBlock* targetBlock = nullptr;
if (currentPC != basicBlock.begin()) if (currentPC != basicBlock.begin())
{ {
auto pairIter = m_directJumpTargets.find(currentPC); auto pairIter = m_directJumpTargets.find(currentPC);
if (pairIter != m_directJumpTargets.end()) if (pairIter != m_directJumpTargets.end())
{ {
auto targetBlock = pairIter->second; targetBlock = pairIter->second;
}
// The target address is computed at compile time, }
// just pop it without looking...
stack.pop();
if (inst == Instruction::JUMP) if (inst == Instruction::JUMP)
{ {
if (targetBlock)
{
// The target address is computed at compile time,
// just pop it without looking...
stack.pop();
builder.CreateBr(targetBlock->llvm()); 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 else // JUMPI
{ {
auto top = stack.pop(); stack.swap(1);
auto val = stack.pop();
auto zero = ConstantInt::get(Type::i256, 0); auto zero = ConstantInt::get(Type::i256, 0);
auto cond = builder.CreateICmpNE(top, zero, "nonzero"); auto cond = builder.CreateICmpNE(val, zero, "nonzero");
// Assume the basic blocks are properly ordered: // Assume the basic blocks are properly ordered:
auto nextBBIter = basicBlockPairIt; auto nextBBIter = basicBlockPairIt;
++nextBBIter; ++nextBBIter;
assert (nextBBIter != basicBlocks.end()); assert (nextBBIter != basicBlocks.end());
auto& followBlock = nextBBIter->second; auto& followBlock = nextBBIter->second;
if (targetBlock)
{
stack.pop();
builder.CreateCondBr(cond, targetBlock->llvm(), followBlock.llvm()); builder.CreateCondBr(cond, targetBlock->llvm(), followBlock.llvm());
} }
break; else
{
builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), followBlock.llvm());
} }
} }
if (inst == Instruction::JUMPI)
{
std::cerr << "Indirect JUMPI is not supported yet (at PC "
<< currentPC << ")\n";
std::exit(1);
}
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; break;
} }
@ -869,7 +870,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
} }
else else
{ {
builder.CreateRet(builder.getInt64(0)); builder.CreateBr(m_badJumpBlock->llvm());
} }
linkBasicBlocks(); linkBasicBlocks();

View file

@ -30,7 +30,7 @@ private:
/// @TODO Handle overflow /// @TODO Handle overflow
uint64_t m_blockCost = 0; uint64_t m_blockCost = 0;
llvm::IRBuilder<>& m_builder; llvm::IRBuilder<>& m_builder;
llvm::CallInst* m_checkCall; llvm::CallInst* m_checkCall = nullptr;
llvm::GlobalVariable* m_gas; llvm::GlobalVariable* m_gas;
llvm::Function* m_gasCheckFunc; 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 (asm
27 999
37
MUL
JUMP 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,7 +4,7 @@
8 ;; 0 8 ;; 0
6 ;; 2 6 ;; 2
ADD ;; 4 ADD ;; 4
JUMP ;; 5 JUMP ;; 5 --> 14
STOP ;; 6 STOP ;; 6
JUMPDEST ;; 7 JUMPDEST ;; 7
1 ;; 8 1 ;; 8

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
)