mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-21 04:06:44 +00:00
Merge branch 'develop-evmcc' of https://github.com/imapp-pl/ethereum into develop-evmcc
This commit is contained in:
commit
293f0de7a9
15 changed files with 126 additions and 64 deletions
|
|
@ -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,28 +162,22 @@ 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(&basicBlocks.find(*it)->second);
|
||||||
m_indirectJumpTargets.push_back(m_finalBlock.get());
|
|
||||||
else
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inst == Instruction::JUMPI)
|
if (inst == Instruction::JUMP)
|
||||||
{
|
{
|
||||||
std::cerr << "Indirect JUMPI is not supported yet (at PC "
|
if (targetBlock)
|
||||||
<< currentPC << ")\n";
|
{
|
||||||
std::exit(1);
|
// 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;
|
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();
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,9 @@ 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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
evmcc/test/jump/badindirect1.evm
Normal file
1
evmcc/test/jump/badindirect1.evm
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
601b602502585d
|
||||||
9
evmcc/test/jump/badindirect1.lll
Normal file
9
evmcc/test/jump/badindirect1.lll
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
;; Indirect jump out of code
|
||||||
|
|
||||||
|
(asm
|
||||||
|
27
|
||||||
|
37
|
||||||
|
MUL
|
||||||
|
JUMP
|
||||||
|
JUMPDEST
|
||||||
|
)
|
||||||
1
evmcc/test/jump/badindirect2.evm
Normal file
1
evmcc/test/jump/badindirect2.evm
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
60016003600302596000600058
|
||||||
12
evmcc/test/jump/badindirect2.lll
Normal file
12
evmcc/test/jump/badindirect2.lll
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
;; Indirect jump into data
|
||||||
|
|
||||||
|
(asm
|
||||||
|
1 ;; 0
|
||||||
|
3
|
||||||
|
3
|
||||||
|
MUL ;; 6
|
||||||
|
JUMPI ;; 7
|
||||||
|
0 ;; 8
|
||||||
|
0
|
||||||
|
JUMP
|
||||||
|
)
|
||||||
|
|
@ -1 +1 @@
|
||||||
601b602502585d
|
6103e758
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
)
|
)
|
||||||
1
evmcc/test/jump/badjump2.evm
Normal file
1
evmcc/test/jump/badjump2.evm
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
6004586000600058
|
||||||
9
evmcc/test/jump/badjump2.lll
Normal file
9
evmcc/test/jump/badjump2.lll
Normal 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
|
||||||
|
)
|
||||||
|
|
@ -4,14 +4,14 @@
|
||||||
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
|
||||||
0 ;; 10
|
0 ;; 10
|
||||||
MSTORE ;; 12
|
MSTORE ;; 12
|
||||||
STOP ;; 13
|
STOP ;; 13
|
||||||
JUMPDEST ;; 14
|
JUMPDEST ;; 14
|
||||||
2
|
2
|
||||||
0
|
0
|
||||||
MSTORE
|
MSTORE
|
||||||
|
|
|
||||||
1
evmcc/test/jump/indirect3.evm
Normal file
1
evmcc/test/jump/indirect3.evm
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
6001600460050159005d6001600054
|
||||||
14
evmcc/test/jump/indirect3.lll
Normal file
14
evmcc/test/jump/indirect3.lll
Normal 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
|
||||||
|
)
|
||||||
1
evmcc/test/jump/indirect4.evm
Normal file
1
evmcc/test/jump/indirect4.evm
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
60006007600501596001600054005d00
|
||||||
15
evmcc/test/jump/indirect4.lll
Normal file
15
evmcc/test/jump/indirect4.lll
Normal 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
|
||||||
|
)
|
||||||
Loading…
Reference in a new issue