mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-21 04:06:44 +00:00
VM execution wrapper with similar interface as libevm/VM
This commit is contained in:
parent
9105fb1771
commit
0f4c8eb63f
7 changed files with 85 additions and 14 deletions
|
|
@ -94,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);
|
||||||
|
|
||||||
|
|
@ -110,7 +110,7 @@ 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));
|
auto result = engine.run(std::move(module));
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
@ -72,7 +72,7 @@ void Compiler::createBasicBlocks(const bytes& bytecode)
|
||||||
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 +95,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);
|
||||||
}
|
}
|
||||||
|
|
@ -149,7 +149,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 +214,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());
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,7 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
|
||||||
|
|
||||||
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)
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,8 @@ public:
|
||||||
ExecutionEngine();
|
ExecutionEngine();
|
||||||
|
|
||||||
int run(std::unique_ptr<llvm::Module> module);
|
int run(std::unique_ptr<llvm::Module> module);
|
||||||
|
|
||||||
|
bytes returnData;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
37
libevmjit/VM.cpp
Normal file
37
libevmjit/VM.cpp
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
|
||||||
|
#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);
|
||||||
|
module->dump();
|
||||||
|
|
||||||
|
ExecutionEngine engine;
|
||||||
|
auto exitCode = engine.run(std::move(module));
|
||||||
|
|
||||||
|
switch (exitCode)
|
||||||
|
{
|
||||||
|
case 101:
|
||||||
|
BOOST_THROW_EXCEPTION(BadJumpDestination());
|
||||||
|
case 102:
|
||||||
|
BOOST_THROW_EXCEPTION(OutOfGas());
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::move(engine.returnData);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
32
libevmjit/VM.h
Normal file
32
libevmjit/VM.h
Normal file
|
|
@ -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…
Reference in a new issue