Browse Source

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

cl-refactor
artur-zawlocki 10 years ago
parent
commit
b01a75af0b
  1. 1
      evmcc/bytecode/if1.evm
  2. 12
      evmcc/evmcc.cpp
  3. 21
      evmcc/lll/if1.asm
  4. 5
      evmcc/lll/if1.lll
  5. 0
      evmcc/test/arith/arith1.evm
  6. 0
      evmcc/test/arith/arith1.lll
  7. 0
      evmcc/test/arith/fib1.evm
  8. 0
      evmcc/test/arith/fib1.lll
  9. 0
      evmcc/test/ext/ext_test.evm
  10. 0
      evmcc/test/ext/ext_test.lll
  11. 0
      evmcc/test/ext/store_test.evm
  12. 0
      evmcc/test/ext/store_test.lll
  13. 0
      evmcc/test/jump/for1.evm
  14. 0
      evmcc/test/jump/for1.lll
  15. 0
      evmcc/test/jump/for2.evm
  16. 0
      evmcc/test/jump/for2.lll
  17. 0
      evmcc/test/jump/when1.asm
  18. 0
      evmcc/test/jump/when1.evm
  19. 0
      evmcc/test/jump/when1.lll
  20. 0
      evmcc/test/kv.evm
  21. 0
      evmcc/test/kv.lll
  22. 0
      evmcc/test/mem/byte.evm
  23. 0
      evmcc/test/mem/byte.lll
  24. 0
      evmcc/test/mem/mem2.evm
  25. 0
      evmcc/test/mem/mem2.lll
  26. 0
      evmcc/test/mem/memtest1.evm
  27. 0
      evmcc/test/mem/memtest1.lll
  28. 0
      evmcc/test/ret/return1.evm
  29. 0
      evmcc/test/ret/return1.lll
  30. 0
      evmcc/test/ret/return2.evm
  31. 0
      evmcc/test/ret/return2.lll
  32. 0
      evmcc/test/ret/return_test.evm
  33. 0
      evmcc/test/ret/return_test.lll
  34. 0
      evmcc/test/stack/push_test.evm
  35. 0
      evmcc/test/stack/push_test.lll
  36. 0
      evmcc/test/stack/stack_test.evm
  37. 0
      evmcc/test/stack/stack_test.lll
  38. 0
      evmcc/test/stack/stackjump.evm
  39. 0
      evmcc/test/stack/stackjump.lll
  40. 0
      libevmjit/BasicBlock.cpp
  41. 0
      libevmjit/BasicBlock.h
  42. 47
      libevmjit/Compiler.cpp
  43. 8
      libevmjit/Compiler.h
  44. 0
      libevmjit/CompilerHelper.cpp
  45. 0
      libevmjit/CompilerHelper.h
  46. 40
      libevmjit/ExecutionEngine.cpp
  47. 5
      libevmjit/ExecutionEngine.h
  48. 2
      libevmjit/Ext.cpp
  49. 0
      libevmjit/Ext.h
  50. 32
      libevmjit/GasMeter.cpp
  51. 0
      libevmjit/GasMeter.h
  52. 0
      libevmjit/Memory.cpp
  53. 0
      libevmjit/Memory.h
  54. 6
      libevmjit/Runtime.cpp
  55. 4
      libevmjit/Runtime.h
  56. 0
      libevmjit/Type.cpp
  57. 0
      libevmjit/Type.h
  58. 0
      libevmjit/Utils.cpp
  59. 0
      libevmjit/Utils.h
  60. 36
      libevmjit/VM.cpp
  61. 32
      libevmjit/VM.h

1
evmcc/bytecode/if1.evm

@ -1 +0,0 @@
600160805460006080530b6016596003608054601b586002608054

12
evmcc/evmcc.cpp

@ -12,9 +12,8 @@
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libdevcore/CommonIO.h> #include <libdevcore/CommonIO.h>
#include <libevmface/Instruction.h> #include <libevmface/Instruction.h>
#include <libevmjit/Compiler.h>
#include "Compiler.h" #include <libevmjit/ExecutionEngine.h>
#include "ExecutionEngine.h"
void show_usage() void show_usage()
@ -95,7 +94,7 @@ int main(int argc, char** argv)
if (opt_compile) if (opt_compile)
{ {
auto compiler = eth::jit::Compiler(); auto compiler = eth::jit::Compiler();
auto module = compiler.compile(bytecode); auto module = compiler.compile({bytecode.data(), bytecode.size()});
llvm::raw_os_ostream out(std::cout); llvm::raw_os_ostream out(std::cout);
module->print(out, nullptr); module->print(out, nullptr);
@ -111,9 +110,10 @@ int main(int argc, char** argv)
if (opt_interpret) if (opt_interpret)
{ {
auto engine = eth::jit::ExecutionEngine(); auto engine = eth::jit::ExecutionEngine();
auto module = eth::jit::Compiler().compile(bytecode); auto module = eth::jit::Compiler().compile({bytecode.data(), bytecode.size()});
module->dump(); module->dump();
auto result = engine.run(std::move(module)); u256 gas = 10000;
auto result = engine.run(std::move(module), gas);
return result; return result;
} }

21
evmcc/lll/if1.asm

@ -1,21 +0,0 @@
.code:
PUSH 1
PUSH 128
MSTORE
PUSH 0
PUSH 128
MLOAD
GT
PUSH [tag0]
JUMPI
PUSH 3
PUSH 128
MSTORE
PUSH [tag1]
JUMP
tag0:
PUSH 2
PUSH 128
MSTORE
tag1:

5
evmcc/lll/if1.lll

@ -1,5 +0,0 @@
{
[i] 1
( if (> @i 0) [i] 2 [i] 3 )
}

0
evmcc/bytecode/arithmetic_test.evm → evmcc/test/arith/arith1.evm

0
evmcc/lll/arithmetic_test.lll → evmcc/test/arith/arith1.lll

0
evmcc/bytecode/fib1.evm → evmcc/test/arith/fib1.evm

0
evmcc/lll/fib1.lll → evmcc/test/arith/fib1.lll

0
evmcc/bytecode/ext_test.evm → evmcc/test/ext/ext_test.evm

0
evmcc/lll/ext_test.lll → evmcc/test/ext/ext_test.lll

0
evmcc/bytecode/store_test.evm → evmcc/test/ext/store_test.evm

0
evmcc/lll/store_test.lll → evmcc/test/ext/store_test.lll

0
evmcc/bytecode/for1.evm → evmcc/test/jump/for1.evm

0
evmcc/lll/for1.lll → evmcc/test/jump/for1.lll

0
evmcc/bytecode/for2.evm → evmcc/test/jump/for2.evm

0
evmcc/lll/for2.lll → evmcc/test/jump/for2.lll

0
evmcc/lll/when1.asm → evmcc/test/jump/when1.asm

0
evmcc/bytecode/when1.evm → evmcc/test/jump/when1.evm

0
evmcc/lll/when1.lll → evmcc/test/jump/when1.lll

0
evmcc/bytecode/kv.evm → evmcc/test/kv.evm

0
evmcc/lll/kv.lll → evmcc/test/kv.lll

0
evmcc/bytecode/byte.evm → evmcc/test/mem/byte.evm

0
evmcc/lll/byte.lll → evmcc/test/mem/byte.lll

0
evmcc/bytecode/mem2.evm → evmcc/test/mem/mem2.evm

0
evmcc/lll/mem2.lll → evmcc/test/mem/mem2.lll

0
evmcc/bytecode/memtest1.evm → evmcc/test/mem/memtest1.evm

0
evmcc/lll/memtest1.lll → evmcc/test/mem/memtest1.lll

0
evmcc/bytecode/return1.evm → evmcc/test/ret/return1.evm

0
evmcc/lll/return1.lll → evmcc/test/ret/return1.lll

0
evmcc/bytecode/return2.evm → evmcc/test/ret/return2.evm

0
evmcc/lll/return2.lll → evmcc/test/ret/return2.lll

0
evmcc/bytecode/return_test.evm → evmcc/test/ret/return_test.evm

0
evmcc/lll/return_test.lll → evmcc/test/ret/return_test.lll

0
evmcc/bytecode/push_test.evm → evmcc/test/stack/push_test.evm

0
evmcc/lll/push_test.lll → evmcc/test/stack/push_test.lll

0
evmcc/bytecode/stack_test.evm → evmcc/test/stack/stack_test.evm

0
evmcc/lll/stack_test.lll → evmcc/test/stack/stack_test.lll

0
evmcc/bytecode/stackjump.evm → evmcc/test/stack/stackjump.evm

0
evmcc/lll/stackjump.lll → evmcc/test/stack/stackjump.lll

0
evmcc/BasicBlock.cpp → libevmjit/BasicBlock.cpp

0
evmcc/BasicBlock.h → libevmjit/BasicBlock.h

47
evmcc/Compiler.cpp → libevmjit/Compiler.cpp

@ -29,7 +29,7 @@ Compiler::Compiler():
Type::init(m_builder.getContext()); Type::init(m_builder.getContext());
} }
void Compiler::createBasicBlocks(const bytes& bytecode) void Compiler::createBasicBlocks(bytesConstRef bytecode)
{ {
std::set<ProgramCounter> splitPoints; // Sorted collections of instruction indices where basic blocks start/end std::set<ProgramCounter> splitPoints; // Sorted collections of instruction indices where basic blocks start/end
splitPoints.insert(0); // First basic block splitPoints.insert(0); // First basic block
@ -38,9 +38,9 @@ void Compiler::createBasicBlocks(const bytes& bytecode)
std::vector<ProgramCounter> indirectJumpTargets; std::vector<ProgramCounter> indirectJumpTargets;
boost::dynamic_bitset<> validJumpTargets(bytecode.size()); boost::dynamic_bitset<> validJumpTargets(bytecode.size());
for (auto curr = bytecode.cbegin(); curr != bytecode.cend(); ++curr) for (auto curr = bytecode.begin(); curr != bytecode.end(); ++curr)
{ {
ProgramCounter currentPC = curr - bytecode.cbegin(); ProgramCounter currentPC = curr - bytecode.begin();
validJumpTargets[currentPC] = 1; validJumpTargets[currentPC] = 1;
auto inst = static_cast<Instruction>(*curr); auto inst = static_cast<Instruction>(*curr);
@ -51,7 +51,7 @@ void Compiler::createBasicBlocks(const bytes& bytecode)
{ {
auto numBytes = static_cast<size_t>(inst) - static_cast<size_t>(Instruction::PUSH1) + 1; auto numBytes = static_cast<size_t>(inst) - static_cast<size_t>(Instruction::PUSH1) + 1;
auto next = curr + numBytes + 1; auto next = curr + numBytes + 1;
if (next >= bytecode.cend()) if (next >= bytecode.end())
break; break;
auto nextInst = static_cast<Instruction>(*next); auto nextInst = static_cast<Instruction>(*next);
@ -67,12 +67,10 @@ void Compiler::createBasicBlocks(const bytes& bytecode)
} }
// Create a block for the JUMP target. // Create a block for the JUMP target.
ProgramCounter targetPC = val.convert_to<ProgramCounter>(); ProgramCounter targetPC = val < bytecode.size() ? val.convert_to<ProgramCounter>() : bytecode.size();
if (targetPC > bytecode.size())
targetPC = bytecode.size();
splitPoints.insert(targetPC); splitPoints.insert(targetPC);
ProgramCounter jumpPC = (next - bytecode.cbegin()); ProgramCounter jumpPC = (next - bytecode.begin());
directJumpTargets[jumpPC] = targetPC; directJumpTargets[jumpPC] = targetPC;
} }
@ -95,7 +93,7 @@ void Compiler::createBasicBlocks(const bytes& bytecode)
case Instruction::SUICIDE: case Instruction::SUICIDE:
{ {
// Create a basic block starting at the following instruction. // Create a basic block starting at the following instruction.
if (curr + 1 < bytecode.cend()) if (curr + 1 < bytecode.end())
{ {
splitPoints.insert(currentPC + 1); splitPoints.insert(currentPC + 1);
} }
@ -130,16 +128,23 @@ void Compiler::createBasicBlocks(const 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())
{
// Jumping out of code means STOP
m_directJumpTargets[it->first] = m_stopBB;
continue;
}
auto blockIter = basicBlocks.find(it->second); auto blockIter = basicBlocks.find(it->second);
if (blockIter != basicBlocks.end()) if (blockIter != basicBlocks.end())
{ {
m_directJumpTargets[it->first] = &(blockIter->second); m_directJumpTargets[it->first] = blockIter->second.llvm();
} }
else 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->llvm();
} }
} }
@ -149,7 +154,7 @@ void Compiler::createBasicBlocks(const bytes& bytecode)
} }
} }
std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode) std::unique_ptr<llvm::Module> Compiler::compile(bytesConstRef bytecode)
{ {
auto module = std::make_unique<llvm::Module>("main", m_builder.getContext()); auto module = std::make_unique<llvm::Module>("main", m_builder.getContext());
@ -214,7 +219,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const bytes& bytecode)
} }
void Compiler::compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock) void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, Memory& memory, Ext& ext, GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock)
{ {
auto& stack = basicBlock.getStack(); auto& stack = basicBlock.getStack();
m_builder.SetInsertPoint(basicBlock.llvm()); m_builder.SetInsertPoint(basicBlock.llvm());
@ -567,7 +572,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, const 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; llvm::BasicBlock* targetBlock = nullptr;
if (currentPC != basicBlock.begin()) if (currentPC != basicBlock.begin())
{ {
auto pairIter = m_directJumpTargets.find(currentPC); auto pairIter = m_directJumpTargets.find(currentPC);
@ -584,7 +589,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode,
// The target address is computed at compile time, // The target address is computed at compile time,
// just pop it without looking... // just pop it without looking...
stack.pop(); stack.pop();
m_builder.CreateBr(targetBlock->llvm()); m_builder.CreateBr(targetBlock);
} }
else else
{ {
@ -606,7 +611,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode,
if (targetBlock) if (targetBlock)
{ {
stack.pop(); stack.pop();
m_builder.CreateCondBr(cond, targetBlock->llvm(), nextBasicBlock); m_builder.CreateCondBr(cond, targetBlock, nextBasicBlock);
} }
else else
{ {
@ -923,10 +928,18 @@ void Compiler::linkBasicBlocks()
for (auto it = llvm::po_ext_begin(bb.second.llvm(), visitSet), for (auto it = llvm::po_ext_begin(bb.second.llvm(), visitSet),
end = llvm::po_ext_end(bb.second.llvm(), visitSet); it != end; ++it) end = llvm::po_ext_end(bb.second.llvm(), visitSet); it != end; ++it)
{ {
std::cerr << it->getName().str() << std::endl; // TODO: Use logger
//std::cerr << it->getName().str() << std::endl;
completePhiNodes(*it); completePhiNodes(*it);
} }
} }
// Remove jump table block if not predecessors
if (llvm::pred_begin(m_jumpTableBlock->llvm()) == llvm::pred_end(m_jumpTableBlock->llvm()))
{
m_jumpTableBlock->llvm()->eraseFromParent();
m_jumpTableBlock.reset();
}
} }
void Compiler::dumpBasicBlockGraph(std::ostream& out) void Compiler::dumpBasicBlockGraph(std::ostream& out)

8
evmcc/Compiler.h → libevmjit/Compiler.h

@ -22,16 +22,16 @@ public:
Compiler(); Compiler();
std::unique_ptr<llvm::Module> compile(const bytes& bytecode); std::unique_ptr<llvm::Module> compile(bytesConstRef bytecode);
void dumpBasicBlockGraph(std::ostream& out); void dumpBasicBlockGraph(std::ostream& out);
private: private:
void createBasicBlocks(const bytes& bytecode); void createBasicBlocks(bytesConstRef bytecode);
void compileBasicBlock(BasicBlock& basicBlock, const bytes& bytecode, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); void compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock);
void linkBasicBlocks(); void linkBasicBlocks();
@ -46,7 +46,7 @@ private:
/** /**
* Maps a pc at which there is a JUMP or JUMPI to the target block of the jump. * Maps a pc at which there is a JUMP or JUMPI to the target block of the jump.
*/ */
std::map<ProgramCounter, BasicBlock*> m_directJumpTargets; std::map<ProgramCounter, llvm::BasicBlock*> m_directJumpTargets;
/** /**
* A list of possible blocks to which there may be indirect jumps. * A list of possible blocks to which there may be indirect jumps.

0
evmcc/CompilerHelper.cpp → libevmjit/CompilerHelper.cpp

0
evmcc/CompilerHelper.h → libevmjit/CompilerHelper.h

40
evmcc/ExecutionEngine.cpp → libevmjit/ExecutionEngine.cpp

@ -36,7 +36,7 @@ ExecutionEngine::ExecutionEngine()
extern "C" { EXPORT std::jmp_buf* rt_jmpBuf; } extern "C" { EXPORT std::jmp_buf* rt_jmpBuf; }
int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module) int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module, u256& _gas, ExtVMFace* _ext)
{ {
auto module = _module.get(); // Keep ownership of the module in _module auto module = _module.get(); // Keep ownership of the module in _module
@ -81,26 +81,28 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
exec->finalizeObject(); exec->finalizeObject();
// Create fake ExtVM interface // Create fake ExtVM interface
auto ext = std::make_unique<ExtVMFace>(); if (!_ext)
ext->myAddress = Address(1122334455667788); {
ext->caller = Address(0xfacefacefaceface); _ext = new ExtVMFace;
ext->origin = Address(101010101010101010); _ext->myAddress = Address(1122334455667788);
ext->value = 0xabcd; _ext->caller = Address(0xfacefacefaceface);
ext->gasPrice = 1002; _ext->origin = Address(101010101010101010);
ext->previousBlock.hash = u256(1003); _ext->value = 0xabcd;
ext->currentBlock.coinbaseAddress = Address(1004); _ext->gasPrice = 1002;
ext->currentBlock.timestamp = 1005; _ext->previousBlock.hash = u256(1003);
ext->currentBlock.number = 1006; _ext->currentBlock.coinbaseAddress = Address(1004);
ext->currentBlock.difficulty = 1007; _ext->currentBlock.timestamp = 1005;
ext->currentBlock.gasLimit = 1008; _ext->currentBlock.number = 1006;
_ext->currentBlock.difficulty = 1007;
_ext->currentBlock.gasLimit = 1008;
std::string calldata = "Hello the Beautiful World of Ethereum!"; std::string calldata = "Hello the Beautiful World of Ethereum!";
ext->data = calldata; _ext->data = calldata;
unsigned char fakecode[] = {0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0xe, 0xf}; unsigned char fakecode[] = {0x0d, 0x0e, 0x0a, 0x0d, 0x0b, 0x0e, 0xe, 0xf};
ext->code = decltype(ext->code)(fakecode, 8); _ext->code = decltype(_ext->code)(fakecode, 8);
}
// Init runtime // Init runtime
uint64_t gas = 100; Runtime runtime(_gas, *_ext);
Runtime runtime(gas, std::move(ext));
auto entryFunc = module->getFunction("main"); auto entryFunc = module->getFunction("main");
if (!entryFunc) if (!entryFunc)
@ -121,11 +123,11 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
else else
returnCode = static_cast<ReturnCode>(r); returnCode = static_cast<ReturnCode>(r);
gas = static_cast<decltype(gas)>(Runtime::getGas()); _gas = Runtime::getGas();
if (returnCode == ReturnCode::Return) if (returnCode == ReturnCode::Return)
{ {
auto&& returnData = Memory::getReturnData(); // TODO: It might be better to place is in Runtime interface returnData = Memory::getReturnData().toVector(); // TODO: It might be better to place is in Runtime interface
std::cout << "RETURN [ "; std::cout << "RETURN [ ";
for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it) for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it)

5
evmcc/ExecutionEngine.h → libevmjit/ExecutionEngine.h

@ -4,6 +4,7 @@
#include <llvm/IR/Module.h> #include <llvm/IR/Module.h>
#include <libdevcore/Common.h> #include <libdevcore/Common.h>
#include <libevm/ExtVMFace.h>
namespace dev namespace dev
{ {
@ -17,7 +18,9 @@ class ExecutionEngine
public: public:
ExecutionEngine(); ExecutionEngine();
int run(std::unique_ptr<llvm::Module> module); int run(std::unique_ptr<llvm::Module> module, u256& _gas, ExtVMFace* _ext = nullptr);
bytes returnData;
}; };
} }

2
evmcc/Ext.cpp → libevmjit/Ext.cpp

@ -61,7 +61,7 @@ Ext::Ext(llvm::IRBuilder<>& _builder):
m_arg5 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg5"); m_arg5 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg5");
m_arg6 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg6"); m_arg6 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg6");
m_arg7 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg7"); m_arg7 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg7");
m_arg7 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8"); m_arg8 = m_builder.CreateAlloca(i256Ty, nullptr, "ext.arg8");
Type* elements[] = { Type* elements[] = {
i256Ty, // i256 address; i256Ty, // i256 address;

0
evmcc/Ext.h → libevmjit/Ext.h

32
evmcc/GasMeter.cpp → libevmjit/GasMeter.cpp

@ -30,26 +30,26 @@ uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure
return 0; return 0;
case Instruction::SSTORE: case Instruction::SSTORE:
return static_cast<uint64_t>(c_sstoreGas); return static_cast<uint64_t>(FeeStructure::c_sstoreGas);
case Instruction::SLOAD: case Instruction::SLOAD:
return static_cast<uint64_t>(c_sloadGas); return static_cast<uint64_t>(FeeStructure::c_sloadGas);
case Instruction::SHA3: case Instruction::SHA3:
return static_cast<uint64_t>(c_sha3Gas); return static_cast<uint64_t>(FeeStructure::c_sha3Gas);
case Instruction::BALANCE: case Instruction::BALANCE:
return static_cast<uint64_t>(c_sha3Gas); return static_cast<uint64_t>(FeeStructure::c_sha3Gas);
case Instruction::CALL: case Instruction::CALL:
case Instruction::CALLCODE: case Instruction::CALLCODE:
return static_cast<uint64_t>(c_callGas); return static_cast<uint64_t>(FeeStructure::c_callGas);
case Instruction::CREATE: case Instruction::CREATE:
return static_cast<uint64_t>(c_createGas); return static_cast<uint64_t>(FeeStructure::c_createGas);
default: // Assumes instruction code is valid default: // Assumes instruction code is valid
return static_cast<uint64_t>(c_stepGas); return static_cast<uint64_t>(FeeStructure::c_stepGas);
} }
} }
@ -134,7 +134,7 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu
{ {
assert(!m_checkCall); // Everything should've been commited before assert(!m_checkCall); // Everything should've been commited before
static const auto sstoreCost = static_cast<uint64_t>(c_sstoreGas); static const auto sstoreCost = static_cast<uint64_t>(FeeStructure::c_sstoreGas);
// [ADD] if oldValue == 0 and newValue != 0 => 2*cost // [ADD] if oldValue == 0 and newValue != 0 => 2*cost
// [DEL] if oldValue != 0 and newValue == 0 => 0 // [DEL] if oldValue != 0 and newValue == 0 => 0
@ -165,19 +165,21 @@ void GasMeter::commitCostBlock(llvm::Value* _additionalCost)
// If any uncommited block // If any uncommited block
if (m_checkCall) if (m_checkCall)
{ {
if (m_blockCost == 0 && !_additionalCost) // Do not check 0 if (m_blockCost == 0) // Do not check 0
{ {
m_checkCall->eraseFromParent(); // Remove the gas check call m_checkCall->eraseFromParent(); // Remove the gas check call
m_checkCall = nullptr;
return; return;
} }
llvm::Value* cost = Constant::get(m_blockCost); m_checkCall->setArgOperand(0, Constant::get(m_blockCost)); // Update block cost in gas check call
if (_additionalCost)
cost = m_builder.CreateAdd(cost, _additionalCost);
m_checkCall->setArgOperand(0, cost); // Update block cost in gas check call
m_checkCall = nullptr; // End cost-block m_checkCall = nullptr; // End cost-block
m_blockCost = 0; m_blockCost = 0;
if (_additionalCost)
{
m_builder.CreateCall(m_gasCheckFunc, _additionalCost);
}
} }
assert(m_blockCost == 0); assert(m_blockCost == 0);
} }
@ -185,7 +187,7 @@ void GasMeter::commitCostBlock(llvm::Value* _additionalCost)
void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder) void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder)
{ {
// Memory uses other builder, but that can be changes later // Memory uses other builder, but that can be changes later
auto cost = _builder.CreateMul(_additionalMemoryInWords, Constant::get(static_cast<uint64_t>(c_memoryGas)), "memcost"); auto cost = _builder.CreateMul(_additionalMemoryInWords, Constant::get(static_cast<uint64_t>(FeeStructure::c_memoryGas)), "memcost");
_builder.CreateCall(m_gasCheckFunc, cost); _builder.CreateCall(m_gasCheckFunc, cost);
} }

0
evmcc/GasMeter.h → libevmjit/GasMeter.h

0
evmcc/Memory.cpp → libevmjit/Memory.cpp

0
evmcc/Memory.h → libevmjit/Memory.h

6
evmcc/Runtime.cpp → libevmjit/Runtime.cpp

@ -19,8 +19,8 @@ extern "C"
EXPORT i256 gas; EXPORT i256 gas;
} }
Runtime::Runtime(u256 _gas, std::unique_ptr<ExtVMFace> _ext): Runtime::Runtime(u256 _gas, ExtVMFace& _ext):
m_ext(std::move(_ext)) m_ext(_ext)
{ {
assert(!g_runtime); assert(!g_runtime);
g_runtime = this; g_runtime = this;
@ -44,7 +44,7 @@ MemoryImpl& Runtime::getMemory()
ExtVMFace& Runtime::getExt() ExtVMFace& Runtime::getExt()
{ {
return *g_runtime->m_ext; return g_runtime->m_ext;
} }
u256 Runtime::getGas() u256 Runtime::getGas()

4
evmcc/Runtime.h → libevmjit/Runtime.h

@ -27,7 +27,7 @@ using MemoryImpl = bytes;
class Runtime class Runtime
{ {
public: public:
Runtime(u256 _gas, std::unique_ptr<ExtVMFace> _ext); Runtime(u256 _gas, ExtVMFace& _ext);
~Runtime(); ~Runtime();
Runtime(const Runtime&) = delete; Runtime(const Runtime&) = delete;
@ -41,7 +41,7 @@ public:
private: private:
StackImpl m_stack; StackImpl m_stack;
MemoryImpl m_memory; MemoryImpl m_memory;
std::unique_ptr<ExtVMFace> m_ext; ExtVMFace& m_ext;
}; };
} }

0
evmcc/Type.cpp → libevmjit/Type.cpp

0
evmcc/Type.h → libevmjit/Type.h

0
evmcc/Utils.cpp → libevmjit/Utils.cpp

0
evmcc/Utils.h → libevmjit/Utils.h

36
libevmjit/VM.cpp

@ -0,0 +1,36 @@
#include "VM.h"
#include <libevm/VM.h>
#include "ExecutionEngine.h"
#include "Compiler.h"
namespace dev
{
namespace eth
{
namespace jit
{
bytes VM::go(ExtVMFace& _ext)
{
auto module = Compiler().compile(_ext.code);
ExecutionEngine engine;
auto exitCode = engine.run(std::move(module), m_gas, &_ext);
switch (exitCode)
{
case 101:
BOOST_THROW_EXCEPTION(BadJumpDestination());
case 102:
BOOST_THROW_EXCEPTION(OutOfGas());
}
return std::move(engine.returnData);
}
}
}
}

32
libevmjit/VM.h

@ -0,0 +1,32 @@
#pragma once
#include <libdevcore/Common.h>
#include <libevm/ExtVMFace.h>
namespace dev
{
namespace eth
{
namespace jit
{
class VM
{
public:
/// Construct VM object.
explicit VM(u256 _gas = 0): m_gas(_gas) {}
void reset(u256 _gas = 0) { m_gas = _gas; }
bytes go(ExtVMFace& _ext);
u256 gas() const { return m_gas; }
private:
u256 m_gas = 0;
};
}
}
}
Loading…
Cancel
Save