11 changed files with 265 additions and 208 deletions
@ -0,0 +1,51 @@ |
|||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <csetjmp> |
||||
|
|
||||
|
#include "Utils.h" |
||||
|
|
||||
|
|
||||
|
namespace dev |
||||
|
{ |
||||
|
namespace eth |
||||
|
{ |
||||
|
namespace jit |
||||
|
{ |
||||
|
|
||||
|
using jmpBufRef = decltype(&jmp_buf{}[0]); |
||||
|
|
||||
|
struct RuntimeData |
||||
|
{ |
||||
|
enum Index |
||||
|
{ |
||||
|
Gas, |
||||
|
Address, |
||||
|
Caller, |
||||
|
Origin, |
||||
|
CallValue, |
||||
|
CallDataSize, |
||||
|
GasPrice, |
||||
|
PrevHash, |
||||
|
CoinBase, |
||||
|
TimeStamp, |
||||
|
Number, |
||||
|
Difficulty, |
||||
|
GasLimit, |
||||
|
CodeSize, |
||||
|
|
||||
|
_size, |
||||
|
|
||||
|
ReturnDataOffset = CallValue, // Reuse 2 fields for return data reference
|
||||
|
ReturnDataSize = CallDataSize |
||||
|
}; |
||||
|
|
||||
|
i256 elems[_size]; |
||||
|
byte const* callData; |
||||
|
byte const* code; |
||||
|
jmpBufRef jmpBuf; |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,159 @@ |
|||||
|
|
||||
|
#include "RuntimeManager.h" |
||||
|
|
||||
|
#include <llvm/IR/GlobalVariable.h> |
||||
|
#include <llvm/IR/Function.h> |
||||
|
#include <llvm/IR/IntrinsicInst.h> |
||||
|
|
||||
|
#include "RuntimeData.h" |
||||
|
#include "Instruction.h" |
||||
|
|
||||
|
namespace dev |
||||
|
{ |
||||
|
namespace eth |
||||
|
{ |
||||
|
namespace jit |
||||
|
{ |
||||
|
|
||||
|
llvm::StructType* RuntimeManager::getRuntimeDataType() |
||||
|
{ |
||||
|
static llvm::StructType* type = nullptr; |
||||
|
if (!type) |
||||
|
{ |
||||
|
llvm::Type* elems[] = |
||||
|
{ |
||||
|
llvm::ArrayType::get(Type::Word, RuntimeData::_size), |
||||
|
Type::BytePtr, |
||||
|
Type::BytePtr, |
||||
|
Type::BytePtr |
||||
|
}; |
||||
|
type = llvm::StructType::create(elems, "Runtime"); |
||||
|
} |
||||
|
return type; |
||||
|
} |
||||
|
|
||||
|
namespace |
||||
|
{ |
||||
|
llvm::Twine getName(RuntimeData::Index _index) |
||||
|
{ |
||||
|
switch (_index) |
||||
|
{ |
||||
|
default: return "data"; |
||||
|
case RuntimeData::Gas: return "gas"; |
||||
|
case RuntimeData::Address: return "address"; |
||||
|
case RuntimeData::Caller: return "caller"; |
||||
|
case RuntimeData::Origin: return "origin"; |
||||
|
case RuntimeData::CallValue: return "callvalue"; |
||||
|
case RuntimeData::CallDataSize: return "calldatasize"; |
||||
|
case RuntimeData::GasPrice: return "gasprice"; |
||||
|
case RuntimeData::PrevHash: return "prevhash"; |
||||
|
case RuntimeData::CoinBase: return "coinbase"; |
||||
|
case RuntimeData::TimeStamp: return "timestamp"; |
||||
|
case RuntimeData::Number: return "number"; |
||||
|
case RuntimeData::Difficulty: return "difficulty"; |
||||
|
case RuntimeData::GasLimit: return "gaslimit"; |
||||
|
case RuntimeData::CodeSize: return "codesize"; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
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"); |
||||
|
m_longjmp = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::longjmp); |
||||
|
|
||||
|
// Export data
|
||||
|
auto mainFunc = getMainFunction(); |
||||
|
llvm::Value* dataPtr = &mainFunc->getArgumentList().back(); |
||||
|
m_builder.CreateStore(dataPtr, m_dataPtr); |
||||
|
} |
||||
|
|
||||
|
llvm::Value* RuntimeManager::getRuntimePtr() |
||||
|
{ |
||||
|
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::getPtr(RuntimeData::Index _index) |
||||
|
{ |
||||
|
llvm::Value* idxList[] = {m_builder.getInt32(0), m_builder.getInt32(0), m_builder.getInt32(_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) |
||||
|
{ |
||||
|
switch (_inst) |
||||
|
{ |
||||
|
default: assert(false); return nullptr; |
||||
|
case Instruction::GAS: return get(RuntimeData::Gas); |
||||
|
case Instruction::ADDRESS: return get(RuntimeData::Address); |
||||
|
case Instruction::CALLER: return get(RuntimeData::Caller); |
||||
|
case Instruction::ORIGIN: return get(RuntimeData::Origin); |
||||
|
case Instruction::CALLVALUE: return get(RuntimeData::CallValue); |
||||
|
case Instruction::CALLDATASIZE: return get(RuntimeData::CallDataSize); |
||||
|
case Instruction::GASPRICE: return get(RuntimeData::GasPrice); |
||||
|
case Instruction::PREVHASH: return get(RuntimeData::PrevHash); |
||||
|
case Instruction::COINBASE: return get(RuntimeData::CoinBase); |
||||
|
case Instruction::TIMESTAMP: return get(RuntimeData::TimeStamp); |
||||
|
case Instruction::NUMBER: return get(RuntimeData::Number); |
||||
|
case Instruction::DIFFICULTY: return get(RuntimeData::Difficulty); |
||||
|
case Instruction::GASLIMIT: return get(RuntimeData::GasLimit); |
||||
|
case Instruction::CODESIZE: return get(RuntimeData::CodeSize); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
llvm::Value* RuntimeManager::getCallData() |
||||
|
{ |
||||
|
auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 1, "calldataPtr"); |
||||
|
return getBuilder().CreateLoad(ptr, "calldata"); |
||||
|
} |
||||
|
|
||||
|
llvm::Value* RuntimeManager::getCode() |
||||
|
{ |
||||
|
auto ptr = getBuilder().CreateStructGEP(getRuntimePtr(), 2, "codePtr"); |
||||
|
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); |
||||
|
} |
||||
|
|
||||
|
void RuntimeManager::setGas(llvm::Value* _gas) |
||||
|
{ |
||||
|
llvm::Value* idxList[] = {m_builder.getInt32(0), m_builder.getInt32(0), m_builder.getInt32(RuntimeData::Gas)}; |
||||
|
auto ptr = m_builder.CreateInBoundsGEP(getRuntimePtr(), idxList, "gasPtr"); |
||||
|
m_builder.CreateStore(_gas, ptr); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
@ -0,0 +1,46 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include "CompilerHelper.h" |
||||
|
#include "Type.h" |
||||
|
#include "RuntimeData.h" |
||||
|
#include "Instruction.h" |
||||
|
|
||||
|
namespace dev |
||||
|
{ |
||||
|
namespace eth |
||||
|
{ |
||||
|
namespace jit |
||||
|
{ |
||||
|
|
||||
|
class RuntimeManager: public CompilerHelper |
||||
|
{ |
||||
|
public: |
||||
|
RuntimeManager(llvm::IRBuilder<>& _builder); |
||||
|
|
||||
|
llvm::Value* getRuntimePtr(); |
||||
|
|
||||
|
llvm::Value* get(RuntimeData::Index _index); |
||||
|
llvm::Value* get(Instruction _inst); |
||||
|
llvm::Value* getGas(); // TODO: Remove
|
||||
|
llvm::Value* getCallData(); |
||||
|
llvm::Value* getCode(); |
||||
|
void setGas(llvm::Value* _gas); |
||||
|
|
||||
|
void registerReturnData(llvm::Value* _index, llvm::Value* _size); |
||||
|
|
||||
|
void raiseException(ReturnCode _returnCode); |
||||
|
|
||||
|
static llvm::StructType* getRuntimeDataType(); |
||||
|
|
||||
|
private: |
||||
|
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; |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
} |
Loading…
Reference in new issue