Browse Source

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

Conflicts:
	test/vm.cpp
cl-refactor
artur-zawlocki 10 years ago
parent
commit
a3871e5137
  1. 1
      evmcc/test/except/badinst1.evm
  2. 15
      libevmjit/Compiler.cpp
  3. 6
      libevmjit/CompilerHelper.cpp
  4. 7
      libevmjit/CompilerHelper.h
  5. 8
      libevmjit/ExecutionEngine.cpp
  6. 30
      libevmjit/Ext.cpp
  7. 13
      libevmjit/GasMeter.cpp
  8. 2
      libevmjit/GasMeter.h
  9. 18
      libevmjit/Memory.cpp
  10. 12
      libevmjit/Memory.h
  11. 66
      libevmjit/Runtime.cpp
  12. 22
      libevmjit/Runtime.h
  13. 8
      libevmjit/Stack.cpp
  14. 3
      libevmjit/Type.h
  15. 16
      libevmjit/VM.cpp

1
evmcc/test/except/badinst1.evm

@ -0,0 +1 @@
4a

15
libevmjit/Compiler.cpp

@ -176,6 +176,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(bytesConstRef bytecode)
llvm::Type* mainFuncArgTypes[] = {m_builder.getInt32Ty(), Type::RuntimePtr}; // There must be int in first place because LLVM does not support other signatures
auto mainFuncType = llvm::FunctionType::get(Type::MainReturn, mainFuncArgTypes, false);
m_mainFunc = llvm::Function::Create(mainFuncType, llvm::Function::ExternalLinkage, "main", module.get());
m_mainFunc->arg_begin()->getNextNode()->setName("rt");
// Create the basic blocks.
auto entryBlock = llvm::BasicBlock::Create(m_builder.getContext(), "entry", m_mainFunc);
@ -186,7 +187,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(bytesConstRef bytecode)
// Init runtime structures.
RuntimeManager runtimeManager(m_builder);
GasMeter gasMeter(m_builder, runtimeManager);
Memory memory(m_builder, gasMeter, runtimeManager);
Memory memory(runtimeManager, gasMeter);
Ext ext(runtimeManager);
Stack stack(m_builder, runtimeManager);
Arith256 arith(m_builder);
@ -371,14 +372,14 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode,
break;
}
case Instruction::NEG:
/*case Instruction::NEG:
{
auto top = stack.pop();
auto zero = Constant::get(0);
auto res = m_builder.CreateSub(zero, top);
stack.push(res);
break;
}
}*/
case Instruction::LT:
{
@ -796,7 +797,8 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode,
auto index = stack.pop();
auto size = stack.pop();
memory.registerReturnData(index, size);
memory.require(index, size);
_runtimeManager.registerReturnData(index, size);
m_builder.CreateRet(Constant::get(ReturnCode::Return));
break;
@ -814,6 +816,11 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode,
break;
}
default: // Invalid instruction - runtime exception
{
_runtimeManager.raiseException(ReturnCode::BadInstruction);
}
}
}

6
libevmjit/CompilerHelper.cpp

@ -27,8 +27,10 @@ llvm::Function* CompilerHelper::getMainFunction()
{
assert(m_builder.GetInsertBlock());
auto mainFunc = m_builder.GetInsertBlock()->getParent();
assert(mainFunc && mainFunc->getName() == "main");
return mainFunc;
assert(mainFunc);
if (mainFunc->getName() == "main")
return mainFunc;
return nullptr;
}

7
libevmjit/CompilerHelper.h

@ -31,6 +31,13 @@ protected:
llvm::IRBuilder<>& m_builder;
llvm::IRBuilder<>& getBuilder() { return m_builder; }
template<typename ..._Args>
llvm::CallInst* createCall(llvm::Function* _func, _Args*... _args)
{
llvm::Value* args[] = {_args...};
return getBuilder().CreateCall(_func, args);
}
friend class RuntimeHelper;
};

8
libevmjit/ExecutionEngine.cpp

@ -35,8 +35,6 @@ ExecutionEngine::ExecutionEngine()
}
extern "C" { EXPORT std::jmp_buf* rt_jmpBuf; }
int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module, u256& _gas, ExtVMFace* _ext)
{
auto module = _module.get(); // Keep ownership of the module in _module
@ -102,21 +100,19 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module, u256& _gas, ExtV
_ext->code = decltype(_ext->code)(fakecode, 8);
}
// Init runtime
Runtime runtime(_gas, *_ext);
auto entryFunc = module->getFunction("main");
if (!entryFunc)
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("main function not found"));
ReturnCode returnCode;
std::jmp_buf buf;
Runtime runtime(_gas, *_ext, buf);
auto r = setjmp(buf);
if (r == 0)
{
auto executionStartTime = std::chrono::high_resolution_clock::now();
rt_jmpBuf = &buf;
auto result = exec->runFunction(entryFunc, {{}, llvm::GenericValue(runtime.getDataPtr())});
returnCode = static_cast<ReturnCode>(result.IntVal.getZExtValue());

30
libevmjit/Ext.cpp

@ -63,7 +63,7 @@ Ext::Ext(RuntimeManager& _runtimeManager):
m_call = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argsTypes, false), Linkage::ExternalLinkage, "ext_call", module);
m_sha3 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 4}, false), Linkage::ExternalLinkage, "ext_sha3", module);
m_exp = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 4}, false), Linkage::ExternalLinkage, "ext_exp", module);
m_codeAt = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), Linkage::ExternalLinkage, "ext_codeAt", module);
m_codeAt = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, {argsTypes, 2}, false), Linkage::ExternalLinkage, "ext_codeAt", module);
m_codesizeAt = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "ext_codesizeAt", module);
}
@ -109,8 +109,7 @@ llvm::Value* Ext::create(llvm::Value* _endowment, llvm::Value* _initOff, llvm::V
m_builder.CreateStore(_endowment, m_args[0]);
m_builder.CreateStore(_initOff, m_arg2);
m_builder.CreateStore(_initSize, m_arg3);
llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_arg3, m_args[1]};
m_builder.CreateCall(m_create, args);
createCall(m_create, getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_arg3, m_args[1]);
llvm::Value* address = m_builder.CreateLoad(m_args[1]);
address = Endianness::toNative(m_builder, address);
return address;
@ -128,9 +127,7 @@ llvm::Value* Ext::call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::V
m_builder.CreateStore(_outSize, m_arg7);
auto codeAddress = Endianness::toBE(m_builder, _codeAddress);
m_builder.CreateStore(codeAddress, m_arg8);
llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_args[1]};
m_builder.CreateCall(m_call, args);
createCall(m_call, getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_arg3, m_arg4, m_arg5, m_arg6, m_arg7, m_arg8, m_args[1]);
_gas = m_builder.CreateLoad(m_args[0]); // Return gas
return m_builder.CreateLoad(m_args[1]);
}
@ -139,8 +136,7 @@ llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize)
{
m_builder.CreateStore(_inOff, m_args[0]);
m_builder.CreateStore(_inSize, m_arg2);
llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]};
m_builder.CreateCall(m_sha3, args);
createCall(m_sha3, getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]);
llvm::Value* hash = m_builder.CreateLoad(m_args[1]);
hash = Endianness::toNative(m_builder, hash);
return hash;
@ -148,10 +144,10 @@ llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize)
llvm::Value* Ext::exp(llvm::Value* _left, llvm::Value* _right)
{
// TODO: Move ext to Arith256
m_builder.CreateStore(_left, m_args[0]);
m_builder.CreateStore(_right, m_arg2);
llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]};
m_builder.CreateCall(m_exp, args);
createCall(m_exp, getRuntimeManager().getRuntimePtr(), m_args[0], m_arg2, m_args[1]);
return m_builder.CreateLoad(m_args[1]);
}
@ -166,8 +162,7 @@ llvm::Value* Ext::codesizeAt(llvm::Value* _addr)
{
auto addr = Endianness::toBE(m_builder, _addr);
m_builder.CreateStore(addr, m_args[0]);
llvm::Value* args[] = {getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]};
m_builder.CreateCall(m_codesizeAt, args);
createCall(m_codesizeAt, getRuntimeManager().getRuntimePtr(), m_args[0], m_args[1]);
return m_builder.CreateLoad(m_args[1]);
}
@ -225,10 +220,9 @@ EXPORT void ext_create(Runtime* _rt, i256* _endowment, i256* _initOff, i256* _in
u256 gas; // TODO: Handle gas
auto initOff = static_cast<size_t>(llvm2eth(*_initOff));
auto initSize = static_cast<size_t>(llvm2eth(*_initSize));
//auto&& initRef = bytesConstRef(Runtime::getMemory().data() + initOff, initSize);
bytesConstRef initRef;
auto&& initRef = bytesConstRef(_rt->getMemory().data() + initOff, initSize);
OnOpFunc onOp{}; // TODO: Handle that thing
h256 address = ext.create(endowment, &gas, initRef, onOp);
h256 address(ext.create(endowment, &gas, initRef, onOp), h256::AlignRight);
*_address = address;
}
else
@ -252,8 +246,8 @@ EXPORT void ext_call(Runtime* _rt, i256* _gas, h256* _receiveAddress, i256* _val
auto inSize = static_cast<size_t>(llvm2eth(*_inSize));
auto outOff = static_cast<size_t>(llvm2eth(*_outOff));
auto outSize = static_cast<size_t>(llvm2eth(*_outSize));
auto&& inRef = bytesConstRef(); //Runtime::getMemory().data() + inOff, inSize);
auto&& outRef = bytesConstRef(); // Runtime::getMemory().data() + outOff, outSize);
auto&& inRef = bytesConstRef(_rt->getMemory().data() + inOff, inSize);
auto&& outRef = bytesConstRef(_rt->getMemory().data() + outOff, outSize);
OnOpFunc onOp{}; // TODO: Handle that thing
auto codeAddress = right160(*_codeAddress);
ret = ext.call(receiveAddress, value, inRef, &gas, outRef, onOp, {}, codeAddress);
@ -267,7 +261,7 @@ EXPORT void ext_sha3(Runtime* _rt, i256* _inOff, i256* _inSize, i256* _ret)
{
auto inOff = static_cast<size_t>(llvm2eth(*_inOff));
auto inSize = static_cast<size_t>(llvm2eth(*_inSize));
auto dataRef = bytesConstRef(); // Runtime::getMemory().data() + inOff, inSize);
auto dataRef = bytesConstRef(_rt->getMemory().data() + inOff, inSize);
auto hash = sha3(dataRef);
*_ret = *reinterpret_cast<i256*>(&hash);
}

13
libevmjit/GasMeter.cpp

@ -31,7 +31,7 @@ uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure
return 0;
case Instruction::SSTORE:
return static_cast<uint64_t>(c_sstoreGas);
return static_cast<uint64_t>(c_sstoreResetGas); // FIXME: Check store gas
case Instruction::SLOAD:
return static_cast<uint64_t>(c_sloadGas);
@ -101,12 +101,7 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager)
m_builder.CreateCondBr(isOutOfGas, outOfGasBB, updateBB);
m_builder.SetInsertPoint(outOfGasBB);
//auto longjmpFunc = llvm::Intrinsic::getDeclaration(_module, llvm::Intrinsic::eh_sjlj_longjmp);
auto extJmpBuf = new llvm::GlobalVariable(*module, Type::BytePtr, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "rt_jmpBuf");
llvm::Type* args[] = {Type::BytePtr, m_builder.getInt32Ty()};
auto longjmpNative = llvm::Function::Create(llvm::FunctionType::get(Type::Void, args, false), llvm::Function::ExternalLinkage, "longjmp", module);
m_builder.CreateCall2(longjmpNative, m_builder.CreateLoad(extJmpBuf), Constant::get(ReturnCode::OutOfGas));
_runtimeManager.raiseException(ReturnCode::OutOfGas);
m_builder.CreateUnreachable();
m_builder.SetInsertPoint(updateBB);
@ -134,7 +129,7 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu
{
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>(c_sstoreResetGas); // FIXME: Check store gas
// [ADD] if oldValue == 0 and newValue != 0 => 2*cost
// [DEL] if oldValue != 0 and newValue == 0 => 0
@ -148,7 +143,7 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu
auto isDel = m_builder.CreateAnd(oldValueIsntZero, newValueIsZero, "isDel");
auto cost = m_builder.CreateSelect(isAdd, Constant::get(2 * sstoreCost), Constant::get(sstoreCost), "cost");
cost = m_builder.CreateSelect(isDel, Constant::get(0), cost, "cost");
m_builder.CreateCall(m_gasCheckFunc, cost);
createCall(m_gasCheckFunc, cost);
}
void GasMeter::giveBack(llvm::Value* _gas)

2
libevmjit/GasMeter.h

@ -13,7 +13,7 @@ namespace jit
{
class RuntimeManager;
class GasMeter : public CompilerHelper
class GasMeter : public CompilerHelper // TODO: Use RuntimeHelper
{
public:
GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager);

18
libevmjit/Memory.cpp

@ -24,8 +24,8 @@ namespace eth
namespace jit
{
Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter, RuntimeManager& _runtimeManager):
CompilerHelper(_builder)
Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter):
RuntimeHelper(_runtimeManager)
{
auto module = getModule();
auto i64Ty = m_builder.getInt64Ty();
@ -40,12 +40,6 @@ Memory::Memory(llvm::IRBuilder<>& _builder, GasMeter& _gasMeter, RuntimeManager&
m_size = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, Constant::get(0), "mem.size");
m_size->setUnnamedAddr(true); // Address is not important
m_returnDataOffset = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataOffset");
m_returnDataOffset->setUnnamedAddr(true); // Address is not important
m_returnDataSize = new llvm::GlobalVariable(*module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataSize");
m_returnDataSize->setUnnamedAddr(true); // Address is not important
llvm::Type* resizeArgs[] = {Type::RuntimePtr, Type::WordPtr};
m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, resizeArgs, false), llvm::Function::ExternalLinkage, "mem_resize", module);
llvm::AttrBuilder attrBuilder;
@ -180,14 +174,6 @@ void Memory::require(llvm::Value* _offset, llvm::Value* _size)
require(sizeRequired);
}
void Memory::registerReturnData(llvm::Value* _index, llvm::Value* _size)
{
require(_index, _size); // Make sure that memory is allocated and count gas
m_builder.CreateStore(_index, m_returnDataOffset);
m_builder.CreateStore(_size, m_returnDataSize);
}
void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx,
llvm::Value* _destMemIdx, llvm::Value* _reqBytes)
{

12
libevmjit/Memory.h

@ -10,12 +10,11 @@ namespace eth
{
namespace jit
{
class RuntimeManager;
class Memory : public CompilerHelper
class Memory : public RuntimeHelper
{
public:
Memory(llvm::IRBuilder<>& _builder, class GasMeter& _gasMeter, RuntimeManager& _runtimeManager);
Memory(RuntimeManager& _runtimeManager, class GasMeter& _gasMeter);
llvm::Value* loadWord(llvm::Value* _addr);
void storeWord(llvm::Value* _addr, llvm::Value* _word);
@ -31,9 +30,6 @@ public:
/// Requires the amount of memory to for data defined by offset and size. And counts gas fee for that memory.
void require(llvm::Value* _offset, llvm::Value* _size);
void registerReturnData(llvm::Value* _index, llvm::Value* _size);
bytesConstRef getReturnData();
void dump(uint64_t _begin, uint64_t _end = 0);
private:
@ -44,10 +40,6 @@ private:
llvm::GlobalVariable* m_data;
llvm::GlobalVariable* m_size;
/// @TODO: m_data and m_size could be used
llvm::GlobalVariable* m_returnDataOffset;
llvm::GlobalVariable* m_returnDataSize;
llvm::Function* m_resize;
llvm::Function* m_require;
llvm::Function* m_loadWord;

66
libevmjit/Runtime.cpp

@ -24,9 +24,10 @@ llvm::StructType* RuntimeData::getType()
{
llvm::ArrayType::get(Type::i256, _size),
Type::BytePtr,
Type::BytePtr,
Type::BytePtr
};
type = llvm::StructType::create(elems, "RuntimeData");
type = llvm::StructType::create(elems, "Runtime");
}
return type;
}
@ -56,13 +57,9 @@ llvm::Twine getName(RuntimeData::Index _index)
}
}
static Runtime* g_runtime; // FIXME: Remove
Runtime::Runtime(u256 _gas, ExtVMFace& _ext):
Runtime::Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf):
m_ext(_ext)
{
assert(!g_runtime);
g_runtime = this;
set(RuntimeData::Gas, _gas);
set(RuntimeData::Address, fromAddress(_ext.myAddress));
set(RuntimeData::Caller, fromAddress(_ext.caller));
@ -79,11 +76,7 @@ Runtime::Runtime(u256 _gas, ExtVMFace& _ext):
set(RuntimeData::CodeSize, _ext.code.size()); // TODO: Use constant
m_data.callData = _ext.data.data();
m_data.code = _ext.code.data();
}
Runtime::~Runtime()
{
g_runtime = nullptr;
m_data.jmpBuf = _jmpBuf;
}
void Runtime::set(RuntimeData::Index _index, u256 _value)
@ -96,16 +89,14 @@ u256 Runtime::getGas() const
return llvm2eth(m_data.elems[RuntimeData::Gas]);
}
extern "C" {
EXPORT i256 mem_returnDataOffset; // FIXME: Dis-globalize
EXPORT i256 mem_returnDataSize;
}
bytesConstRef Runtime::getReturnData() const
{
// TODO: Handle large indexes
auto offset = static_cast<size_t>(llvm2eth(mem_returnDataOffset));
auto size = static_cast<size_t>(llvm2eth(mem_returnDataSize));
auto offset = static_cast<size_t>(llvm2eth(m_data.elems[RuntimeData::ReturnDataOffset]));
auto size = static_cast<size_t>(llvm2eth(m_data.elems[RuntimeData::ReturnDataSize]));
assert(offset + size <= m_memory.size());
// TODO: Handle invalid data access by returning empty ref
return {m_memory.data() + offset, size};
}
@ -113,6 +104,8 @@ bytesConstRef Runtime::getReturnData() const
RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder)
{
m_dataPtr = new llvm::GlobalVariable(*getModule(), Type::RuntimePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::RuntimePtr), "rt");
llvm::Type* args[] = {Type::BytePtr, m_builder.getInt32Ty()};
m_longjmp = llvm::Function::Create(llvm::FunctionType::get(Type::Void, args, false), llvm::Function::ExternalLinkage, "longjmp", getModule());
// Export data
auto mainFunc = getMainFunction();
@ -122,15 +115,36 @@ RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_bui
llvm::Value* RuntimeManager::getRuntimePtr()
{
// TODO: If in main function - get it from param
return m_builder.CreateLoad(m_dataPtr);
if (auto mainFunc = getMainFunction())
return mainFunc->arg_begin()->getNextNode(); // Runtime is the second parameter of main function
return m_builder.CreateLoad(m_dataPtr, "rt");
}
llvm::Value* RuntimeManager::get(RuntimeData::Index _index)
llvm::Value* RuntimeManager::getPtr(RuntimeData::Index _index)
{
llvm::Value* idxList[] = {m_builder.getInt32(0), m_builder.getInt32(0), m_builder.getInt32(_index)};
auto ptr = m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, getName(_index) + "Ptr");
return m_builder.CreateLoad(ptr, getName(_index));
return m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, getName(_index) + "Ptr");
}
llvm::Value* RuntimeManager::get(RuntimeData::Index _index)
{
return m_builder.CreateLoad(getPtr(_index), getName(_index));
}
void RuntimeManager::set(RuntimeData::Index _index, llvm::Value* _value)
{
m_builder.CreateStore(_value, getPtr(_index));
}
void RuntimeManager::registerReturnData(llvm::Value* _offset, llvm::Value* _size)
{
set(RuntimeData::ReturnDataOffset, _offset);
set(RuntimeData::ReturnDataSize, _size);
}
void RuntimeManager::raiseException(ReturnCode _returnCode)
{
m_builder.CreateCall2(m_longjmp, getJmpBuf(), Constant::get(_returnCode));
}
llvm::Value* RuntimeManager::get(Instruction _inst)
@ -167,6 +181,12 @@ llvm::Value* RuntimeManager::getCode()
return getBuilder().CreateLoad(ptr, "code");
}
llvm::Value* RuntimeManager::getJmpBuf()
{
auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 3, "jmpbufPtr");
return getBuilder().CreateLoad(ptr, "jmpbuf");
}
llvm::Value* RuntimeManager::getGas()
{
return get(RuntimeData::Gas);

22
libevmjit/Runtime.h

@ -7,6 +7,7 @@
#include "CompilerHelper.h"
#include "Utils.h"
#include "Type.h"
#ifdef _MSC_VER
@ -41,12 +42,16 @@ struct RuntimeData
GasLimit,
CodeSize,
_size
_size,
ReturnDataOffset = CallValue, // Reuse 2 fields for return data reference
ReturnDataSize = CallDataSize
};
i256 elems[_size];
byte const* callData;
byte const* code;
decltype(&jmp_buf{}[0]) jmpBuf;
static llvm::StructType* getType();
};
@ -57,8 +62,7 @@ using MemoryImpl = bytes;
class Runtime
{
public:
Runtime(u256 _gas, ExtVMFace& _ext);
~Runtime();
Runtime(u256 _gas, ExtVMFace& _ext, jmp_buf _jmpBuf);
Runtime(const Runtime&) = delete;
void operator=(const Runtime&) = delete;
@ -71,6 +75,7 @@ public:
u256 getGas() const;
bytesConstRef getReturnData() const;
decltype(&jmp_buf{}[0]) getJmpBuf() { return m_data.jmpBuf; }
private:
void set(RuntimeData::Index _index, u256 _value);
@ -96,8 +101,17 @@ public:
llvm::Value* getCode();
void setGas(llvm::Value* _gas);
void registerReturnData(llvm::Value* _index, llvm::Value* _size);
void raiseException(ReturnCode _returnCode);
private:
llvm::GlobalVariable* m_dataPtr;
llvm::Value* getPtr(RuntimeData::Index _index);
void set(RuntimeData::Index _index, llvm::Value* _value);
llvm::Value* getJmpBuf();
llvm::GlobalVariable* m_dataPtr = nullptr;
llvm::Function* m_longjmp = nullptr;
};
}

8
libevmjit/Stack.cpp

@ -74,13 +74,11 @@ extern "C"
using namespace dev::eth::jit;
extern std::jmp_buf* rt_jmpBuf;
EXPORT void stack_pop(Runtime* _rt, uint64_t _count)
{
auto& stack = _rt->getStack();
if (stack.size() < _count)
longjmp(*rt_jmpBuf, static_cast<uint64_t>(ReturnCode::StackTooSmall));
longjmp(_rt->getJmpBuf(), static_cast<uint64_t>(ReturnCode::StackTooSmall));
stack.erase(stack.end() - _count, stack.end());
}
@ -99,7 +97,7 @@ EXPORT void stack_get(Runtime* _rt, uint64_t _index, i256* _ret)
auto& stack = _rt->getStack();
// TODO: encode _index and stack size in the return code
if (stack.size() <= _index)
longjmp(*rt_jmpBuf, static_cast<uint64_t>(ReturnCode::StackTooSmall));
longjmp(_rt->getJmpBuf(), static_cast<uint64_t>(ReturnCode::StackTooSmall));
*_ret = *(stack.rbegin() + _index);
}
@ -109,7 +107,7 @@ EXPORT void stack_set(Runtime* _rt, uint64_t _index, i256* _word)
auto& stack = _rt->getStack();
// TODO: encode _index and stack size in the return code
if (stack.size() <= _index)
longjmp(*rt_jmpBuf, static_cast<uint64_t>(ReturnCode::StackTooSmall));
longjmp(_rt->getJmpBuf(), static_cast<uint64_t>(ReturnCode::StackTooSmall));
*(stack.rbegin() + _index) = *_word;
}

3
libevmjit/Type.h

@ -43,7 +43,8 @@ enum class ReturnCode
BadJumpDestination = 101,
OutOfGas = 102,
StackTooSmall = 103
StackTooSmall = 103,
BadInstruction = 104,
};
struct Constant

16
libevmjit/VM.cpp

@ -5,6 +5,7 @@
#include "ExecutionEngine.h"
#include "Compiler.h"
#include "Type.h"
namespace dev
{
@ -13,24 +14,23 @@ namespace eth
namespace jit
{
bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const& _onOp, uint64_t _steps)
bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t)
{
assert(!_onOp); // Parameter ignored
assert(_steps == (uint64_t)-1); // Parameter ignored
auto module = Compiler().compile(_ext.code);
ExecutionEngine engine;
auto exitCode = engine.run(std::move(module), m_gas, &_ext);
switch (exitCode)
switch (static_cast<ReturnCode>(exitCode))
{
case 101:
case ReturnCode::BadJumpDestination:
BOOST_THROW_EXCEPTION(BadJumpDestination());
case 102:
case ReturnCode::OutOfGas:
BOOST_THROW_EXCEPTION(OutOfGas());
case 103:
case ReturnCode::StackTooSmall:
BOOST_THROW_EXCEPTION(StackTooSmall(1,0));
case ReturnCode::BadInstruction:
BOOST_THROW_EXCEPTION(BadInstruction());
}
m_output = std::move(engine.returnData);

Loading…
Cancel
Save