Browse Source

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

cl-refactor
Paweł Bylica 10 years ago
parent
commit
501bbeec0c
  1. 103
      evmcc/Compiler.cpp
  2. 4
      evmcc/GasMeter.h
  3. 1
      evmcc/test/jump/badindirect1.evm
  4. 9
      evmcc/test/jump/badindirect1.lll
  5. 1
      evmcc/test/jump/badindirect2.evm
  6. 12
      evmcc/test/jump/badindirect2.lll
  7. 2
      evmcc/test/jump/badjump1.evm
  8. 7
      evmcc/test/jump/badjump1.lll
  9. 1
      evmcc/test/jump/badjump2.evm
  10. 9
      evmcc/test/jump/badjump2.lll
  11. 4
      evmcc/test/jump/indirect2.lll
  12. 1
      evmcc/test/jump/indirect3.evm
  13. 14
      evmcc/test/jump/indirect3.lll
  14. 1
      evmcc/test/jump/indirect4.evm
  15. 15
      evmcc/test/jump/indirect4.lll

103
evmcc/Compiler.cpp

@ -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;
targetBlock = pairIter->second;
}
}
if (inst == Instruction::JUMP)
{
if (targetBlock)
{
// 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;
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());
}
}
if (inst == Instruction::JUMPI)
else // JUMPI
{
std::cerr << "Indirect JUMPI is not supported yet (at PC "
<< currentPC << ")\n";
std::exit(1);
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();

4
evmcc/GasMeter.h

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

1
evmcc/test/jump/badindirect1.evm

@ -0,0 +1 @@
601b602502585d

9
evmcc/test/jump/badindirect1.lll

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

1
evmcc/test/jump/badindirect2.evm

@ -0,0 +1 @@
60016003600302596000600058

12
evmcc/test/jump/badindirect2.lll

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

2
evmcc/test/jump/badjump1.evm

@ -1 +1 @@
601b602502585d
6103e758

7
evmcc/test/jump/badjump1.lll

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

1
evmcc/test/jump/badjump2.evm

@ -0,0 +1 @@
6004586000600058

9
evmcc/test/jump/badjump2.lll

@ -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
evmcc/test/jump/indirect2.lll

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

1
evmcc/test/jump/indirect3.evm

@ -0,0 +1 @@
6001600460050159005d6001600054

14
evmcc/test/jump/indirect3.lll

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

@ -0,0 +1 @@
60006007600501596001600054005d00

15
evmcc/test/jump/indirect4.lll

@ -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…
Cancel
Save