Browse Source

Squashed 'evmjit/' changes from 533531b..035c376

035c376 All jump support code paths tested. Thanks @CJentzsch.
5b4e130 Function rename
30f3e0d Fix evmcc
7b9d495 BLOCKHASH instruction
681adc1 Remove PREVHASH instruction
024639b Create bad jump block on demand
c21237f Remove unnecessary jump dest map. Create jump table block on demand.
ed614c5 Mandatory JUMPDEST for jumps and new static jumps recognition strategy
86553cd Remove terminate() function
5db00ad New CALL/CREATE depth limit semantics
e5d0fb3 Alloc stack elemnent for external function call argument on demand
4f4fc63 Alloc stack elemnent for external function call argument on demand
b6248cc Detemplatify createCall helper
b77a975 Create helper/external functions on demand
9bf0b75 Create helper/external functions on demand

git-subtree-dir: evmjit
git-subtree-split: 035c3760e0
cl-refactor
Gav Wood 10 years ago
parent
commit
1f40799620
  1. 1
      evmcc/evmcc.cpp
  2. 20
      libevmjit-cpp/Env.cpp
  3. 1
      libevmjit-cpp/JitVM.cpp
  4. 7
      libevmjit/BasicBlock.h
  5. 2
      libevmjit/Common.h
  6. 152
      libevmjit/Compiler.cpp
  7. 18
      libevmjit/Compiler.h
  8. 5
      libevmjit/CompilerHelper.cpp
  9. 7
      libevmjit/CompilerHelper.h
  10. 151
      libevmjit/Ext.cpp
  11. 50
      libevmjit/Ext.h
  12. 4
      libevmjit/GasMeter.cpp
  13. 2
      libevmjit/Instruction.h
  14. 8
      libevmjit/Memory.cpp
  15. 23
      libevmjit/Runtime.cpp
  16. 3
      libevmjit/Runtime.h
  17. 1
      libevmjit/RuntimeData.h
  18. 2
      libevmjit/RuntimeManager.cpp
  19. 9
      libevmjit/Utils.cpp
  20. 2
      libevmjit/Utils.h

1
evmcc/evmcc.cpp

@ -190,7 +190,6 @@ int main(int argc, char** argv)
data.set(RuntimeData::CallValue, 0xabcd); data.set(RuntimeData::CallValue, 0xabcd);
data.set(RuntimeData::CallDataSize, 3); data.set(RuntimeData::CallDataSize, 3);
data.set(RuntimeData::GasPrice, 1003); data.set(RuntimeData::GasPrice, 1003);
data.set(RuntimeData::PrevHash, 1003);
data.set(RuntimeData::CoinBase, (u160)Address(101010101010101015)); data.set(RuntimeData::CoinBase, (u160)Address(101010101010101015));
data.set(RuntimeData::TimeStamp, 1005); data.set(RuntimeData::TimeStamp, 1005);
data.set(RuntimeData::Number, 1006); data.set(RuntimeData::Number, 1006);

20
libevmjit-cpp/Env.cpp

@ -42,16 +42,15 @@ extern "C"
*o_value = eth2llvm(u); *o_value = eth2llvm(u);
} }
EXPORT void env_create(ExtVMFace* _env, i256* io_gas, i256* _endowment, byte* _initBeg, uint64_t _initSize, h256* o_address) EXPORT void env_blockhash(ExtVMFace* _env, i256* _number, h256* o_hash)
{ {
if (_env->depth == 1024) *o_hash = _env->blockhash(llvm2eth(*_number));
jit::terminate(jit::ReturnCode::OutOfGas); }
assert(_env->depth < 1024);
EXPORT void env_create(ExtVMFace* _env, i256* io_gas, i256* _endowment, byte* _initBeg, uint64_t _initSize, h256* o_address)
{
auto endowment = llvm2eth(*_endowment); auto endowment = llvm2eth(*_endowment);
if (_env->balance(_env->myAddress) >= endowment && _env->depth < 1024)
if (_env->balance(_env->myAddress) >= endowment)
{ {
_env->subBalance(endowment); _env->subBalance(endowment);
auto gas = llvm2eth(*io_gas); auto gas = llvm2eth(*io_gas);
@ -66,13 +65,8 @@ extern "C"
EXPORT bool env_call(ExtVMFace* _env, i256* io_gas, h256* _receiveAddress, i256* _value, byte* _inBeg, uint64_t _inSize, byte* _outBeg, uint64_t _outSize, h256* _codeAddress) EXPORT bool env_call(ExtVMFace* _env, i256* io_gas, h256* _receiveAddress, i256* _value, byte* _inBeg, uint64_t _inSize, byte* _outBeg, uint64_t _outSize, h256* _codeAddress)
{ {
if (_env->depth == 1024)
jit::terminate(jit::ReturnCode::OutOfGas);
assert(_env->depth < 1024);
auto value = llvm2eth(*_value); auto value = llvm2eth(*_value);
if (_env->balance(_env->myAddress) >= value) if (_env->balance(_env->myAddress) >= value && _env->depth < 1024)
{ {
_env->subBalance(value); _env->subBalance(value);
auto receiveAddress = right160(*_receiveAddress); auto receiveAddress = right160(*_receiveAddress);

1
libevmjit-cpp/JitVM.cpp

@ -20,7 +20,6 @@ bytesConstRef JitVM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t)
m_data.set(RuntimeData::CallValue, _ext.value); m_data.set(RuntimeData::CallValue, _ext.value);
m_data.set(RuntimeData::CallDataSize, _ext.data.size()); m_data.set(RuntimeData::CallDataSize, _ext.data.size());
m_data.set(RuntimeData::GasPrice, _ext.gasPrice); m_data.set(RuntimeData::GasPrice, _ext.gasPrice);
m_data.set(RuntimeData::PrevHash, _ext.previousBlock.hash);
m_data.set(RuntimeData::CoinBase, fromAddress(_ext.currentBlock.coinbaseAddress)); m_data.set(RuntimeData::CoinBase, fromAddress(_ext.currentBlock.coinbaseAddress));
m_data.set(RuntimeData::TimeStamp, _ext.currentBlock.timestamp); m_data.set(RuntimeData::TimeStamp, _ext.currentBlock.timestamp);
m_data.set(RuntimeData::Number, _ext.currentBlock.number); m_data.set(RuntimeData::Number, _ext.currentBlock.number);

7
libevmjit/BasicBlock.h

@ -67,6 +67,9 @@ public:
ProgramCounter begin() { return m_beginInstIdx; } ProgramCounter begin() { return m_beginInstIdx; }
ProgramCounter end() { return m_endInstIdx; } ProgramCounter end() { return m_endInstIdx; }
bool isJumpDest() const { return m_isJumpDest; }
void markAsJumpDest() { m_isJumpDest = true; }
LocalStack& localStack() { return m_stack; } LocalStack& localStack() { return m_stack; }
/// Optimization: propagates values between local stacks in basic blocks /// Optimization: propagates values between local stacks in basic blocks
@ -109,6 +112,10 @@ private:
/// How many items higher is the current stack than the initial one. /// How many items higher is the current stack than the initial one.
/// May be negative. /// May be negative.
int m_tosOffset = 0; int m_tosOffset = 0;
/// Is the basic block a valid jump destination.
/// JUMPDEST is the first instruction of the basic block.
bool m_isJumpDest = false;
}; };
} }

2
libevmjit/Common.h

@ -44,6 +44,8 @@ struct i256
}; };
static_assert(sizeof(i256) == 32, "Wrong i265 size"); static_assert(sizeof(i256) == 32, "Wrong i265 size");
#define UNTESTED assert(false)
} }
} }
} }

152
libevmjit/Compiler.cpp

@ -5,8 +5,6 @@
#include <fstream> #include <fstream>
#include <chrono> #include <chrono>
#include <boost/dynamic_bitset.hpp>
#include <llvm/ADT/PostOrderIterator.h> #include <llvm/ADT/PostOrderIterator.h>
#include <llvm/IR/CFG.h> #include <llvm/IR/CFG.h>
#include <llvm/IR/Module.h> #include <llvm/IR/Module.h>
@ -42,19 +40,17 @@ Compiler::Compiler(Options const& _options):
void Compiler::createBasicBlocks(bytes const& _bytecode) void Compiler::createBasicBlocks(bytes const& _bytecode)
{ {
// FIXME: Simplify this algorithm. All can be done in one pass
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
std::map<ProgramCounter, ProgramCounter> directJumpTargets;
std::vector<ProgramCounter> indirectJumpTargets; std::vector<ProgramCounter> indirectJumpTargets;
boost::dynamic_bitset<> validJumpTargets(std::max(_bytecode.size(), size_t(1)));
splitPoints.insert(0); // First basic block splitPoints.insert(0); // First basic block
validJumpTargets[0] = true;
for (auto curr = _bytecode.begin(); curr != _bytecode.end(); ++curr) for (auto curr = _bytecode.begin(); curr != _bytecode.end(); ++curr)
{ {
ProgramCounter currentPC = curr - _bytecode.begin(); ProgramCounter currentPC = curr - _bytecode.begin();
validJumpTargets[currentPC] = true;
auto inst = Instruction(*curr); auto inst = Instruction(*curr);
switch (inst) switch (inst)
@ -62,21 +58,7 @@ void Compiler::createBasicBlocks(bytes const& _bytecode)
case Instruction::ANY_PUSH: case Instruction::ANY_PUSH:
{ {
auto val = readPushData(curr, _bytecode.end()); readPushData(curr, _bytecode.end());
auto next = curr + 1;
if (next == _bytecode.end())
break;
auto nextInst = Instruction(*next);
if (nextInst == Instruction::JUMP || nextInst == Instruction::JUMPI)
{
// Create a block for the JUMP target.
ProgramCounter targetPC = val.ult(_bytecode.size()) ? val.getZExtValue() : _bytecode.size();
splitPoints.insert(targetPC);
ProgramCounter jumpPC = (next - _bytecode.begin());
directJumpTargets[jumpPC] = targetPC;
}
break; break;
} }
@ -105,15 +87,6 @@ void Compiler::createBasicBlocks(bytes const& _bytecode)
} }
} }
// 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();) for (auto it = splitPoints.cbegin(); it != splitPoints.cend();)
{ {
auto beginInstIdx = *it; auto beginInstIdx = *it;
@ -123,33 +96,39 @@ void Compiler::createBasicBlocks(bytes const& _bytecode)
} }
m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc); m_stopBB = llvm::BasicBlock::Create(m_mainFunc->getContext(), "Stop", m_mainFunc);
m_badJumpBlock = std::unique_ptr<BasicBlock>(new BasicBlock("BadJumpBlock", m_mainFunc, m_builder));
m_jumpTableBlock = std::unique_ptr<BasicBlock>(new BasicBlock("JumpTableBlock", m_mainFunc, m_builder));
for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it) for (auto it = indirectJumpTargets.cbegin(); it != indirectJumpTargets.cend(); ++it)
{ basicBlocks.find(*it)->second.markAsJumpDest();
if (it->second >= _bytecode.size()) }
{
// Jumping out of code means STOP
m_directJumpTargets[it->first] = m_stopBB;
continue;
}
auto blockIter = basicBlocks.find(it->second); llvm::BasicBlock* Compiler::getJumpTableBlock()
if (blockIter != basicBlocks.end()) {
{ if (!m_jumpTableBlock)
m_directJumpTargets[it->first] = blockIter->second.llvm(); {
} m_jumpTableBlock.reset(new BasicBlock("JumpTable", m_mainFunc, m_builder));
else InsertPointGuard g{m_builder};
m_builder.SetInsertPoint(m_jumpTableBlock->llvm());
auto dest = m_jumpTableBlock->localStack().pop();
auto switchInstr = m_builder.CreateSwitch(dest, getBadJumpBlock());
for (auto&& p : basicBlocks)
{ {
clog(JIT) << "Bad JUMP at PC " << it->first if (p.second.isJumpDest())
<< ": " << it->second << " is not a valid PC"; switchInstr->addCase(Constant::get(p.first), p.second.llvm());
m_directJumpTargets[it->first] = m_badJumpBlock->llvm();
} }
} }
return m_jumpTableBlock->llvm();
}
for (auto it = indirectJumpTargets.cbegin(); it != indirectJumpTargets.cend(); ++it) llvm::BasicBlock* Compiler::getBadJumpBlock()
m_indirectJumpTargets.push_back(&basicBlocks.find(*it)->second); {
if (!m_badJumpBlock)
{
m_badJumpBlock.reset(new BasicBlock("BadJump", m_mainFunc, m_builder));
InsertPointGuard g{m_builder};
m_builder.SetInsertPoint(m_badJumpBlock->llvm());
m_builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination));
}
return m_badJumpBlock->llvm();
} }
std::unique_ptr<llvm::Module> Compiler::compile(bytes const& _bytecode, std::string const& _id) std::unique_ptr<llvm::Module> Compiler::compile(bytes const& _bytecode, std::string const& _id)
@ -192,25 +171,6 @@ std::unique_ptr<llvm::Module> Compiler::compile(bytes const& _bytecode, std::str
m_builder.SetInsertPoint(m_stopBB); m_builder.SetInsertPoint(m_stopBB);
m_builder.CreateRet(Constant::get(ReturnCode::Stop)); m_builder.CreateRet(Constant::get(ReturnCode::Stop));
m_builder.SetInsertPoint(m_badJumpBlock->llvm());
m_builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination));
m_builder.SetInsertPoint(m_jumpTableBlock->llvm());
if (m_indirectJumpTargets.size() > 0)
{
auto dest = m_jumpTableBlock->localStack().pop();
auto switchInstr = m_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 = Constant::get(bb->begin());
switchInstr->addCase(dest, bb->llvm());
}
}
else
m_builder.CreateBr(m_badJumpBlock->llvm());
removeDeadBlocks(); removeDeadBlocks();
dumpCFGifRequired("blocks-init.dot"); dumpCFGifRequired("blocks-init.dot");
@ -596,16 +556,21 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode
case Instruction::JUMP: case Instruction::JUMP:
case Instruction::JUMPI: case Instruction::JUMPI:
{ {
// Generate direct jump iff:
// 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).
llvm::BasicBlock* targetBlock = nullptr; llvm::BasicBlock* targetBlock = nullptr;
if (currentPC != _basicBlock.begin()) auto target = stack.pop();
if (auto constant = llvm::dyn_cast<llvm::ConstantInt>(target))
{ {
auto pairIter = m_directJumpTargets.find(currentPC); auto&& c = constant->getValue();
if (pairIter != m_directJumpTargets.end()) if (c.ult(_bytecode.size()))
targetBlock = pairIter->second; {
auto v = c.getZExtValue();
auto it = basicBlocks.find(v);
if (it != basicBlocks.end() && it->second.isJumpDest())
targetBlock = it->second.llvm();
}
if (!targetBlock)
targetBlock = getBadJumpBlock();
} }
if (inst == Instruction::JUMP) if (inst == Instruction::JUMP)
@ -614,28 +579,30 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _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();
m_builder.CreateBr(targetBlock); m_builder.CreateBr(targetBlock);
} }
else else
m_builder.CreateBr(m_jumpTableBlock->llvm()); {
stack.push(target);
m_builder.CreateBr(getJumpTableBlock());
}
} }
else // JUMPI else // JUMPI
{ {
stack.swap(1);
auto val = stack.pop(); auto val = stack.pop();
auto zero = Constant::get(0); auto zero = Constant::get(0);
auto cond = m_builder.CreateICmpNE(val, zero, "nonzero"); auto cond = m_builder.CreateICmpNE(val, zero, "nonzero");
if (targetBlock) if (targetBlock)
{ {
stack.pop();
m_builder.CreateCondBr(cond, targetBlock, _nextBasicBlock); m_builder.CreateCondBr(cond, targetBlock, _nextBasicBlock);
} }
else else
m_builder.CreateCondBr(cond, m_jumpTableBlock->llvm(), _nextBasicBlock); {
stack.push(target);
m_builder.CreateCondBr(cond, getJumpTableBlock(), _nextBasicBlock);
}
} }
break; break;
} }
@ -666,7 +633,6 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode
case Instruction::CALLDATASIZE: case Instruction::CALLDATASIZE:
case Instruction::CODESIZE: case Instruction::CODESIZE:
case Instruction::GASPRICE: case Instruction::GASPRICE:
case Instruction::PREVHASH:
case Instruction::COINBASE: case Instruction::COINBASE:
case Instruction::TIMESTAMP: case Instruction::TIMESTAMP:
case Instruction::NUMBER: case Instruction::NUMBER:
@ -678,6 +644,14 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode
break; break;
} }
case Instruction::BLOCKHASH:
{
auto number = stack.pop();
auto hash = _ext.blockhash(number);
stack.push(hash);
break;
}
case Instruction::BALANCE: case Instruction::BALANCE:
{ {
auto address = stack.pop(); auto address = stack.pop();
@ -835,6 +809,7 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode
default: // Invalid instruction - runtime exception default: // Invalid instruction - runtime exception
{ {
// TODO: Replace with return statement
_runtimeManager.raiseException(ReturnCode::BadInstruction); _runtimeManager.raiseException(ReturnCode::BadInstruction);
} }
@ -871,13 +846,6 @@ void Compiler::removeDeadBlocks()
} }
} }
while (sthErased); while (sthErased);
// Remove jump table block if no predecessors
if (llvm::pred_begin(m_jumpTableBlock->llvm()) == llvm::pred_end(m_jumpTableBlock->llvm()))
{
m_jumpTableBlock->llvm()->eraseFromParent();
m_jumpTableBlock.reset();
}
} }
void Compiler::dumpCFGifRequired(std::string const& _dotfilePath) void Compiler::dumpCFGifRequired(std::string const& _dotfilePath)

18
libevmjit/Compiler.h

@ -47,6 +47,10 @@ private:
void compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock); void compileBasicBlock(BasicBlock& _basicBlock, bytes const& _bytecode, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock);
llvm::BasicBlock* getJumpTableBlock();
llvm::BasicBlock* getBadJumpBlock();
void removeDeadBlocks(); void removeDeadBlocks();
/// Dumps basic block graph in graphviz format to a file, if option dumpCFG is enabled. /// Dumps basic block graph in graphviz format to a file, if option dumpCFG is enabled.
@ -65,22 +69,16 @@ private:
llvm::IRBuilder<> m_builder; llvm::IRBuilder<> m_builder;
/// Maps a program counter pc to a basic block that starts at pc (if any). /// Maps a program counter pc to a basic block that starts at pc (if any).
std::map<ProgramCounter, BasicBlock> basicBlocks = {}; std::map<ProgramCounter, BasicBlock> basicBlocks;
/// Maps a pc at which there is a JUMP or JUMPI to the target block of the jump.
std::map<ProgramCounter, llvm::BasicBlock*> m_directJumpTargets = {};
/// A list of possible blocks to which there may be indirect jumps.
std::vector<BasicBlock*> m_indirectJumpTargets = {};
/// Stop basic block - terminates execution with STOP code (0) /// Stop basic block - terminates execution with STOP code (0)
llvm::BasicBlock* m_stopBB = nullptr; llvm::BasicBlock* m_stopBB = nullptr;
/// Block with a jump table. /// Block with a jump table.
std::unique_ptr<BasicBlock> m_jumpTableBlock = nullptr; std::unique_ptr<BasicBlock> m_jumpTableBlock;
/// Default destination for indirect jumps. /// Destination for invalid jumps
std::unique_ptr<BasicBlock> m_badJumpBlock = nullptr; std::unique_ptr<BasicBlock> m_badJumpBlock;
/// Main program function /// Main program function
llvm::Function* m_mainFunc = nullptr; llvm::Function* m_mainFunc = nullptr;

5
libevmjit/CompilerHelper.cpp

@ -35,6 +35,11 @@ llvm::Function* CompilerHelper::getMainFunction()
return nullptr; return nullptr;
} }
llvm::CallInst* CompilerHelper::createCall(llvm::Function* _func, std::initializer_list<llvm::Value*> const& _args)
{
return getBuilder().CreateCall(_func, {_args.begin(), _args.size()});
}
RuntimeHelper::RuntimeHelper(RuntimeManager& _runtimeManager): RuntimeHelper::RuntimeHelper(RuntimeManager& _runtimeManager):
CompilerHelper(_runtimeManager.getBuilder()), CompilerHelper(_runtimeManager.getBuilder()),

7
libevmjit/CompilerHelper.h

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

151
libevmjit/Ext.cpp

@ -24,113 +24,132 @@ Ext::Ext(RuntimeManager& _runtimeManager, Memory& _memoryMan):
RuntimeHelper(_runtimeManager), RuntimeHelper(_runtimeManager),
m_memoryMan(_memoryMan) m_memoryMan(_memoryMan)
{ {
auto module = getModule();
m_args[0] = m_builder.CreateAlloca(Type::Word, nullptr, "ext.index");
m_args[1] = m_builder.CreateAlloca(Type::Word, nullptr, "ext.value");
m_arg2 = m_builder.CreateAlloca(Type::Word, nullptr, "ext.arg2");
m_arg3 = m_builder.CreateAlloca(Type::Word, nullptr, "ext.arg3");
m_arg4 = m_builder.CreateAlloca(Type::Word, nullptr, "ext.arg4");
m_arg5 = m_builder.CreateAlloca(Type::Word, nullptr, "ext.arg5");
m_arg6 = m_builder.CreateAlloca(Type::Word, nullptr, "ext.arg6");
m_arg7 = m_builder.CreateAlloca(Type::Word, nullptr, "ext.arg7");
m_arg8 = m_builder.CreateAlloca(Type::Word, nullptr, "ext.arg8");
m_size = m_builder.CreateAlloca(Type::Size, nullptr, "env.size"); m_size = m_builder.CreateAlloca(Type::Size, nullptr, "env.size");
}
using Linkage = llvm::GlobalValue::LinkageTypes;
llvm::Type* argsTypes[] = {Type::EnvPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr};
m_sload = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "env_sload", module);
m_sstore = llvm::Function::Create(llvm::FunctionType::get(Type::Void, {argsTypes, 3}, false), Linkage::ExternalLinkage, "env_sstore", module);
llvm::Type* sha3ArgsTypes[] = {Type::BytePtr, Type::Size, Type::WordPtr};
m_sha3 = llvm::Function::Create(llvm::FunctionType::get(Type::Void, sha3ArgsTypes, false), Linkage::ExternalLinkage, "env_sha3", module);
llvm::Type* createArgsTypes[] = {Type::EnvPtr, Type::WordPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::WordPtr};
m_create = llvm::Function::Create(llvm::FunctionType::get(Type::Void, createArgsTypes, false), Linkage::ExternalLinkage, "env_create", module);
llvm::Type* callArgsTypes[] = {Type::EnvPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::BytePtr, Type::Size, Type::WordPtr}; using FuncDesc = std::tuple<char const*, llvm::FunctionType*>;
m_call = llvm::Function::Create(llvm::FunctionType::get(Type::Bool, callArgsTypes, false), Linkage::ExternalLinkage, "env_call", module);
llvm::Type* logArgsTypes[] = {Type::EnvPtr, Type::BytePtr, Type::Size, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr}; llvm::FunctionType* getFunctionType(llvm::Type* _returnType, std::initializer_list<llvm::Type*> const& _argsTypes)
m_log = llvm::Function::Create(llvm::FunctionType::get(Type::Void, logArgsTypes, false), Linkage::ExternalLinkage, "env_log", module); {
return llvm::FunctionType::get(_returnType, llvm::ArrayRef<llvm::Type*>{_argsTypes.begin(), _argsTypes.size()}, false);
}
llvm::Type* getExtCodeArgsTypes[] = {Type::EnvPtr, Type::WordPtr, Type::Size->getPointerTo()}; std::array<FuncDesc, sizeOf<EnvFunc>::value> const& getEnvFuncDescs()
m_getExtCode = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, getExtCodeArgsTypes, false), Linkage::ExternalLinkage, "env_getExtCode", module); {
static std::array<FuncDesc, sizeOf<EnvFunc>::value> descs{{
FuncDesc{"env_sload", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})},
FuncDesc{"env_sstore", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})},
FuncDesc{"env_sha3", getFunctionType(Type::Void, {Type::BytePtr, Type::Size, Type::WordPtr})},
FuncDesc{"env_balance", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})},
FuncDesc{"env_create", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::WordPtr})},
FuncDesc{"env_call", getFunctionType(Type::Bool, {Type::EnvPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::BytePtr, Type::Size, Type::BytePtr, Type::Size, Type::WordPtr})},
FuncDesc{"env_log", getFunctionType(Type::Void, {Type::EnvPtr, Type::BytePtr, Type::Size, Type::WordPtr, Type::WordPtr, Type::WordPtr, Type::WordPtr})},
FuncDesc{"env_blockhash", getFunctionType(Type::Void, {Type::EnvPtr, Type::WordPtr, Type::WordPtr})},
FuncDesc{"env_getExtCode", getFunctionType(Type::BytePtr, {Type::EnvPtr, Type::WordPtr, Type::Size->getPointerTo()})},
FuncDesc{"ext_calldataload", getFunctionType(Type::Void, {Type::RuntimeDataPtr, Type::WordPtr, Type::WordPtr})},
}};
return descs;
}
// Helper function, not client Env interface llvm::Function* createFunc(EnvFunc _id, llvm::Module* _module)
llvm::Type* callDataLoadArgsTypes[] = {Type::RuntimeDataPtr, Type::WordPtr, Type::WordPtr}; {
m_calldataload = llvm::Function::Create(llvm::FunctionType::get(Type::Void, callDataLoadArgsTypes, false), Linkage::ExternalLinkage, "ext_calldataload", module); auto&& desc = getEnvFuncDescs()[static_cast<size_t>(_id)];
return llvm::Function::Create(std::get<1>(desc), llvm::Function::ExternalLinkage, std::get<0>(desc), _module);
} }
llvm::Function* Ext::getBalanceFunc() llvm::Value* Ext::getArgAlloca()
{ {
if (!m_balance) auto& a = m_argAllocas[m_argCounter++];
if (!a)
{ {
llvm::Type* argsTypes[] = {Type::EnvPtr, Type::WordPtr, Type::WordPtr}; // FIXME: Improve order and names
m_balance = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argsTypes, false), llvm::Function::ExternalLinkage, "env_balance", getModule()); InsertPointGuard g{getBuilder()};
getBuilder().SetInsertPoint(getMainFunction()->front().getFirstNonPHI());
a = getBuilder().CreateAlloca(Type::Word, nullptr, "arg");
} }
return m_balance;
return a;
}
llvm::Value* Ext::byPtr(llvm::Value* _value)
{
auto a = getArgAlloca();
getBuilder().CreateStore(_value, a);
return a;
}
llvm::CallInst* Ext::createCall(EnvFunc _funcId, std::initializer_list<llvm::Value*> const& _args)
{
auto& func = m_funcs[static_cast<size_t>(_funcId)];
if (!func)
func = createFunc(_funcId, getModule());
m_argCounter = 0;
return getBuilder().CreateCall(func, {_args.begin(), _args.size()});
} }
llvm::Value* Ext::sload(llvm::Value* _index) llvm::Value* Ext::sload(llvm::Value* _index)
{ {
m_builder.CreateStore(_index, m_args[0]); auto ret = getArgAlloca();
m_builder.CreateCall3(m_sload, getRuntimeManager().getEnvPtr(), m_args[0], m_args[1]); // Uses native endianness createCall(EnvFunc::sload, {getRuntimeManager().getEnvPtr(), byPtr(_index), ret}); // Uses native endianness
return m_builder.CreateLoad(m_args[1]); return m_builder.CreateLoad(ret);
} }
void Ext::sstore(llvm::Value* _index, llvm::Value* _value) void Ext::sstore(llvm::Value* _index, llvm::Value* _value)
{ {
m_builder.CreateStore(_index, m_args[0]); createCall(EnvFunc::sstore, {getRuntimeManager().getEnvPtr(), byPtr(_index), byPtr(_value)}); // Uses native endianness
m_builder.CreateStore(_value, m_args[1]);
m_builder.CreateCall3(m_sstore, getRuntimeManager().getEnvPtr(), m_args[0], m_args[1]); // Uses native endianness
} }
llvm::Value* Ext::calldataload(llvm::Value* _index) llvm::Value* Ext::calldataload(llvm::Value* _index)
{ {
m_builder.CreateStore(_index, m_args[0]); auto ret = getArgAlloca();
createCall(m_calldataload, getRuntimeManager().getDataPtr(), m_args[0], m_args[1]); createCall(EnvFunc::calldataload, {getRuntimeManager().getDataPtr(), byPtr(_index), ret});
auto ret = m_builder.CreateLoad(m_args[1]); ret = m_builder.CreateLoad(ret);
return Endianness::toNative(m_builder, ret); return Endianness::toNative(m_builder, ret);
} }
llvm::Value* Ext::balance(llvm::Value* _address) llvm::Value* Ext::balance(llvm::Value* _address)
{ {
auto address = Endianness::toBE(m_builder, _address); auto address = Endianness::toBE(m_builder, _address);
m_builder.CreateStore(address, m_args[0]); auto ret = getArgAlloca();
createCall(getBalanceFunc(), getRuntimeManager().getEnvPtr(), m_args[0], m_args[1]); createCall(EnvFunc::balance, {getRuntimeManager().getEnvPtr(), byPtr(address), ret});
return m_builder.CreateLoad(m_args[1]); return m_builder.CreateLoad(ret);
}
llvm::Value* Ext::blockhash(llvm::Value* _number)
{
auto hash = getArgAlloca();
createCall(EnvFunc::blockhash, {getRuntimeManager().getEnvPtr(), byPtr(_number), hash});
hash = m_builder.CreateLoad(hash);
return Endianness::toNative(getBuilder(), hash);
} }
llvm::Value* Ext::create(llvm::Value*& _gas, llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize) llvm::Value* Ext::create(llvm::Value*& _gas, llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize)
{ {
m_builder.CreateStore(_gas, m_args[0]); auto gas = byPtr(_gas);
m_builder.CreateStore(_endowment, m_arg2); auto ret = getArgAlloca();
auto begin = m_memoryMan.getBytePtr(_initOff); auto begin = m_memoryMan.getBytePtr(_initOff);
auto size = m_builder.CreateTrunc(_initSize, Type::Size, "size"); auto size = m_builder.CreateTrunc(_initSize, Type::Size, "size");
createCall(m_create, getRuntimeManager().getEnvPtr(), m_args[0], m_arg2, begin, size, m_args[1]); createCall(EnvFunc::create, {getRuntimeManager().getEnvPtr(), gas, byPtr(_endowment), begin, size, ret});
_gas = m_builder.CreateLoad(m_args[0]); // Return gas _gas = m_builder.CreateLoad(gas); // Return gas
llvm::Value* address = m_builder.CreateLoad(m_args[1]); llvm::Value* address = m_builder.CreateLoad(ret);
address = Endianness::toNative(m_builder, address); address = Endianness::toNative(m_builder, address);
return address; return address;
} }
llvm::Value* Ext::call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress) llvm::Value* Ext::call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress)
{ {
m_builder.CreateStore(_gas, m_args[0]); auto gas = byPtr(_gas);
auto receiveAddress = Endianness::toBE(m_builder, _receiveAddress); auto receiveAddress = Endianness::toBE(m_builder, _receiveAddress);
m_builder.CreateStore(receiveAddress, m_arg2);
m_builder.CreateStore(_value, m_arg3);
auto inBeg = m_memoryMan.getBytePtr(_inOff); auto inBeg = m_memoryMan.getBytePtr(_inOff);
auto inSize = m_builder.CreateTrunc(_inSize, Type::Size, "in.size"); auto inSize = m_builder.CreateTrunc(_inSize, Type::Size, "in.size");
auto outBeg = m_memoryMan.getBytePtr(_outOff); auto outBeg = m_memoryMan.getBytePtr(_outOff);
auto outSize = m_builder.CreateTrunc(_outSize, Type::Size, "out.size"); auto outSize = m_builder.CreateTrunc(_outSize, Type::Size, "out.size");
auto codeAddress = Endianness::toBE(m_builder, _codeAddress); auto codeAddress = Endianness::toBE(m_builder, _codeAddress);
m_builder.CreateStore(codeAddress, m_arg8); auto ret = createCall(EnvFunc::call, {getRuntimeManager().getEnvPtr(), gas, byPtr(receiveAddress), byPtr(_value), inBeg, inSize, outBeg, outSize, byPtr(codeAddress)});
auto ret = createCall(m_call, getRuntimeManager().getEnvPtr(), m_args[0], m_arg2, m_arg3, inBeg, inSize, outBeg, outSize, m_arg8); _gas = m_builder.CreateLoad(gas); // Return gas
_gas = m_builder.CreateLoad(m_args[0]); // Return gas
return m_builder.CreateZExt(ret, Type::Word, "ret"); return m_builder.CreateZExt(ret, Type::Word, "ret");
} }
@ -138,8 +157,9 @@ llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize)
{ {
auto begin = m_memoryMan.getBytePtr(_inOff); auto begin = m_memoryMan.getBytePtr(_inOff);
auto size = m_builder.CreateTrunc(_inSize, Type::Size, "size"); auto size = m_builder.CreateTrunc(_inSize, Type::Size, "size");
createCall(m_sha3, begin, size, m_args[1]); auto ret = getArgAlloca();
llvm::Value* hash = m_builder.CreateLoad(m_args[1]); createCall(EnvFunc::sha3, {begin, size, ret});
llvm::Value* hash = m_builder.CreateLoad(ret);
hash = Endianness::toNative(m_builder, hash); hash = Endianness::toNative(m_builder, hash);
return hash; return hash;
} }
@ -147,8 +167,7 @@ llvm::Value* Ext::sha3(llvm::Value* _inOff, llvm::Value* _inSize)
MemoryRef Ext::getExtCode(llvm::Value* _addr) MemoryRef Ext::getExtCode(llvm::Value* _addr)
{ {
auto addr = Endianness::toBE(m_builder, _addr); auto addr = Endianness::toBE(m_builder, _addr);
m_builder.CreateStore(addr, m_args[0]); auto code = createCall(EnvFunc::getExtCode, {getRuntimeManager().getEnvPtr(), byPtr(addr), m_size});
auto code = createCall(m_getExtCode, getRuntimeManager().getEnvPtr(), m_args[0], m_size);
auto codeSize = m_builder.CreateLoad(m_size); auto codeSize = m_builder.CreateLoad(m_size);
auto codeSize256 = m_builder.CreateZExt(codeSize, Type::Word); auto codeSize256 = m_builder.CreateZExt(codeSize, Type::Word);
return {code, codeSize256}; return {code, codeSize256};
@ -158,7 +177,7 @@ void Ext::log(llvm::Value* _memIdx, llvm::Value* _numBytes, std::array<llvm::Val
{ {
auto begin = m_memoryMan.getBytePtr(_memIdx); auto begin = m_memoryMan.getBytePtr(_memIdx);
auto size = m_builder.CreateTrunc(_numBytes, Type::Size, "size"); auto size = m_builder.CreateTrunc(_numBytes, Type::Size, "size");
llvm::Value* args[] = {getRuntimeManager().getEnvPtr(), begin, size, m_arg2, m_arg3, m_arg4, m_arg5}; llvm::Value* args[] = {getRuntimeManager().getEnvPtr(), begin, size, getArgAlloca(), getArgAlloca(), getArgAlloca(), getArgAlloca()};
auto topicArgPtr = &args[3]; auto topicArgPtr = &args[3];
for (auto&& topic : _topics) for (auto&& topic : _topics)
@ -170,7 +189,7 @@ void Ext::log(llvm::Value* _memIdx, llvm::Value* _numBytes, std::array<llvm::Val
++topicArgPtr; ++topicArgPtr;
} }
m_builder.CreateCall(m_log, args); createCall(EnvFunc::log, {args[0], args[1], args[2], args[3], args[4], args[5], args[6]}); // TODO: use std::initializer_list<>
} }
} }

50
libevmjit/Ext.h

@ -18,6 +18,28 @@ struct MemoryRef
llvm::Value* size; llvm::Value* size;
}; };
template<typename _EnumT>
struct sizeOf
{
static const size_t value = static_cast<size_t>(_EnumT::_size);
};
enum class EnvFunc
{
sload,
sstore,
sha3,
balance,
create,
call,
log,
blockhash,
getExtCode,
calldataload, // Helper function, not client Env interface
_size
};
class Ext : public RuntimeHelper class Ext : public RuntimeHelper
{ {
public: public:
@ -30,6 +52,7 @@ public:
llvm::Value* calldataload(llvm::Value* _index); llvm::Value* calldataload(llvm::Value* _index);
llvm::Value* create(llvm::Value*& _gas, llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize); llvm::Value* create(llvm::Value*& _gas, llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize);
llvm::Value* call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress); llvm::Value* call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::Value* _value, llvm::Value* _inOff, llvm::Value* _inSize, llvm::Value* _outOff, llvm::Value* _outSize, llvm::Value* _codeAddress);
llvm::Value* blockhash(llvm::Value* _number);
llvm::Value* sha3(llvm::Value* _inOff, llvm::Value* _inSize); llvm::Value* sha3(llvm::Value* _inOff, llvm::Value* _inSize);
MemoryRef getExtCode(llvm::Value* _addr); MemoryRef getExtCode(llvm::Value* _addr);
@ -39,27 +62,16 @@ public:
private: private:
Memory& m_memoryMan; Memory& m_memoryMan;
llvm::Value* m_args[2];
llvm::Value* m_arg2;
llvm::Value* m_arg3;
llvm::Value* m_arg4;
llvm::Value* m_arg5;
llvm::Value* m_arg6;
llvm::Value* m_arg7;
llvm::Value* m_arg8;
llvm::Value* m_size; llvm::Value* m_size;
llvm::Value* m_data = nullptr; llvm::Value* m_data = nullptr;
llvm::Function* m_sload;
llvm::Function* m_sstore; std::array<llvm::Function*, sizeOf<EnvFunc>::value> m_funcs = {};
llvm::Function* m_calldataload; std::array<llvm::Value*, 8> m_argAllocas = {};
llvm::Function* m_balance = nullptr; size_t m_argCounter = 0;
llvm::Function* m_create;
llvm::Function* m_call; llvm::CallInst* createCall(EnvFunc _funcId, std::initializer_list<llvm::Value*> const& _args);
llvm::Function* m_sha3; llvm::Value* getArgAlloca();
llvm::Function* m_getExtCode; llvm::Value* byPtr(llvm::Value* _value);
llvm::Function* m_log;
llvm::Function* getBalanceFunc();
}; };

4
libevmjit/GasMeter.cpp

@ -119,7 +119,7 @@ void GasMeter::count(Instruction _inst)
if (!m_checkCall) if (!m_checkCall)
{ {
// Create gas check call with mocked block cost at begining of current cost-block // Create gas check call with mocked block cost at begining of current cost-block
m_checkCall = createCall(m_gasCheckFunc, m_runtimeManager.getRuntimePtr(), llvm::UndefValue::get(Type::Word)); m_checkCall = createCall(m_gasCheckFunc, {m_runtimeManager.getRuntimePtr(), llvm::UndefValue::get(Type::Word)});
} }
m_blockCost += getStepCost(_inst); m_blockCost += getStepCost(_inst);
@ -127,7 +127,7 @@ void GasMeter::count(Instruction _inst)
void GasMeter::count(llvm::Value* _cost) void GasMeter::count(llvm::Value* _cost)
{ {
createCall(m_gasCheckFunc, m_runtimeManager.getRuntimePtr(), _cost); createCall(m_gasCheckFunc, {m_runtimeManager.getRuntimePtr(), _cost});
} }
void GasMeter::countExp(llvm::Value* _exponent) void GasMeter::countExp(llvm::Value* _exponent)

2
libevmjit/Instruction.h

@ -58,7 +58,7 @@ enum class Instruction: uint8_t
EXTCODESIZE, ///< get external code size (from another contract) EXTCODESIZE, ///< get external code size (from another contract)
EXTCODECOPY, ///< copy external code (from another contract) EXTCODECOPY, ///< copy external code (from another contract)
PREVHASH = 0x40, ///< get hash of most recent complete block BLOCKHASH = 0x40, ///< get hash of most recent complete block
COINBASE, ///< get the block's coinbase address COINBASE, ///< get the block's coinbase address
TIMESTAMP, ///< get the block's timestamp TIMESTAMP, ///< get the block's timestamp
NUMBER, ///< get the block's number NUMBER, ///< get the block's number

8
libevmjit/Memory.cpp

@ -146,18 +146,18 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMet
llvm::Value* Memory::loadWord(llvm::Value* _addr) llvm::Value* Memory::loadWord(llvm::Value* _addr)
{ {
return createCall(m_loadWord, getRuntimeManager().getRuntimePtr(), _addr); return createCall(m_loadWord, {getRuntimeManager().getRuntimePtr(), _addr});
} }
void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word) void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word)
{ {
createCall(m_storeWord, getRuntimeManager().getRuntimePtr(), _addr, _word); createCall(m_storeWord, {getRuntimeManager().getRuntimePtr(), _addr, _word});
} }
void Memory::storeByte(llvm::Value* _addr, llvm::Value* _word) void Memory::storeByte(llvm::Value* _addr, llvm::Value* _word)
{ {
auto byte = m_builder.CreateTrunc(_word, Type::Byte, "byte"); auto byte = m_builder.CreateTrunc(_word, Type::Byte, "byte");
createCall(m_storeByte, getRuntimeManager().getRuntimePtr(), _addr, byte); createCall(m_storeByte, {getRuntimeManager().getRuntimePtr(), _addr, byte});
} }
llvm::Value* Memory::getData() llvm::Value* Memory::getData()
@ -181,7 +181,7 @@ llvm::Value* Memory::getBytePtr(llvm::Value* _index)
void Memory::require(llvm::Value* _offset, llvm::Value* _size) void Memory::require(llvm::Value* _offset, llvm::Value* _size)
{ {
createCall(m_require, getRuntimeManager().getRuntimePtr(), _offset, _size); createCall(m_require, {getRuntimeManager().getRuntimePtr(), _offset, _size});
} }
void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx, void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx,

23
libevmjit/Runtime.cpp

@ -11,29 +11,12 @@ namespace eth
{ {
namespace jit namespace jit
{ {
namespace
{
jmp_buf_ref g_currJmpBuf;
}
jmp_buf_ref Runtime::getCurrJmpBuf()
{
return g_currJmpBuf;
}
Runtime::Runtime(RuntimeData* _data, Env* _env): Runtime::Runtime(RuntimeData* _data, Env* _env) :
m_data(*_data), m_data(*_data),
m_env(*_env), m_env(*_env),
m_currJmpBuf(m_jmpBuf), m_currJmpBuf(m_jmpBuf)
m_prevJmpBuf(g_currJmpBuf) {}
{
g_currJmpBuf = m_jmpBuf;
}
Runtime::~Runtime()
{
g_currJmpBuf = m_prevJmpBuf;
}
bytes Runtime::getReturnData() const // FIXME: Reconsider returning by copy bytes Runtime::getReturnData() const // FIXME: Reconsider returning by copy
{ {

3
libevmjit/Runtime.h

@ -32,7 +32,6 @@ class Runtime
{ {
public: public:
Runtime(RuntimeData* _data, Env* _env); Runtime(RuntimeData* _data, Env* _env);
~Runtime();
Runtime(const Runtime&) = delete; Runtime(const Runtime&) = delete;
void operator=(const Runtime&) = delete; void operator=(const Runtime&) = delete;
@ -43,7 +42,6 @@ public:
bytes getReturnData() const; bytes getReturnData() const;
jmp_buf_ref getJmpBuf() { return m_jmpBuf; } jmp_buf_ref getJmpBuf() { return m_jmpBuf; }
static jmp_buf_ref getCurrJmpBuf();
private: private:
RuntimeData& m_data; ///< Pointer to data. Expected by compiled contract. RuntimeData& m_data; ///< Pointer to data. Expected by compiled contract.
@ -51,7 +49,6 @@ private:
jmp_buf_ref m_currJmpBuf; ///< Pointer to jump buffer. Expected by compiled contract. jmp_buf_ref m_currJmpBuf; ///< Pointer to jump buffer. Expected by compiled contract.
byte* m_memoryData = nullptr; byte* m_memoryData = nullptr;
i256 m_memorySize = {}; i256 m_memorySize = {};
jmp_buf_ref m_prevJmpBuf;
std::jmp_buf m_jmpBuf; std::jmp_buf m_jmpBuf;
StackImpl m_stack; StackImpl m_stack;
MemoryImpl m_memory; MemoryImpl m_memory;

1
libevmjit/RuntimeData.h

@ -21,7 +21,6 @@ struct RuntimeData
CallValue, CallValue,
CallDataSize, CallDataSize,
GasPrice, GasPrice,
PrevHash,
CoinBase, CoinBase,
TimeStamp, TimeStamp,
Number, Number,

2
libevmjit/RuntimeManager.cpp

@ -63,7 +63,6 @@ llvm::Twine getName(RuntimeData::Index _index)
case RuntimeData::CallValue: return "callvalue"; case RuntimeData::CallValue: return "callvalue";
case RuntimeData::CallDataSize: return "calldatasize"; case RuntimeData::CallDataSize: return "calldatasize";
case RuntimeData::GasPrice: return "gasprice"; case RuntimeData::GasPrice: return "gasprice";
case RuntimeData::PrevHash: return "prevhash";
case RuntimeData::CoinBase: return "coinbase"; case RuntimeData::CoinBase: return "coinbase";
case RuntimeData::TimeStamp: return "timestamp"; case RuntimeData::TimeStamp: return "timestamp";
case RuntimeData::Number: return "number"; case RuntimeData::Number: return "number";
@ -154,7 +153,6 @@ llvm::Value* RuntimeManager::get(Instruction _inst)
case Instruction::CALLVALUE: return get(RuntimeData::CallValue); case Instruction::CALLVALUE: return get(RuntimeData::CallValue);
case Instruction::CALLDATASIZE: return get(RuntimeData::CallDataSize); case Instruction::CALLDATASIZE: return get(RuntimeData::CallDataSize);
case Instruction::GASPRICE: return get(RuntimeData::GasPrice); case Instruction::GASPRICE: return get(RuntimeData::GasPrice);
case Instruction::PREVHASH: return get(RuntimeData::PrevHash);
case Instruction::COINBASE: return get(RuntimeData::CoinBase); case Instruction::COINBASE: return get(RuntimeData::CoinBase);
case Instruction::TIMESTAMP: return get(RuntimeData::TimeStamp); case Instruction::TIMESTAMP: return get(RuntimeData::TimeStamp);
case Instruction::NUMBER: return get(RuntimeData::Number); case Instruction::NUMBER: return get(RuntimeData::Number);

9
libevmjit/Utils.cpp

@ -1,8 +1,7 @@
#include <csetjmp> #include <llvm/ADT/APInt.h>
#include "Utils.h" #include "Utils.h"
#include "Instruction.h" #include "Instruction.h"
#include "Runtime.h"
namespace dev namespace dev
{ {
@ -55,12 +54,6 @@ llvm::APInt readPushData(bytes::const_iterator& _curr, bytes::const_iterator _en
return value; return value;
} }
void terminate(ReturnCode _returnCode)
{
auto jmpBuf = Runtime::getCurrJmpBuf();
std::longjmp(jmpBuf, static_cast<int>(_returnCode));
}
} }
} }
} }

2
libevmjit/Utils.h

@ -17,8 +17,6 @@ struct JIT: public NoteChannel { static const char* name() { return "JIT"; } };
u256 llvm2eth(i256); u256 llvm2eth(i256);
i256 eth2llvm(u256); i256 eth2llvm(u256);
void terminate(ReturnCode _returnCode);
} }
} }
} }

Loading…
Cancel
Save