Browse Source

Remove global privite pointers to runtime instance and runtime data

cl-refactor
Paweł Bylica 10 years ago
parent
commit
f8ffdfa30c
  1. 16
      libevmjit/Ext.cpp
  2. 18
      libevmjit/GasMeter.cpp
  3. 34
      libevmjit/Memory.cpp
  4. 2
      libevmjit/Memory.h
  5. 41
      libevmjit/RuntimeManager.cpp
  6. 7
      libevmjit/RuntimeManager.h

16
libevmjit/Ext.cpp

@ -69,7 +69,7 @@ Ext::Ext(RuntimeManager& _runtimeManager, Memory& _memoryMan):
llvm::Value* Ext::sload(llvm::Value* _index)
{
m_builder.CreateStore(_index, m_args[0]);
m_builder.CreateCall3(m_sload, getRuntimeManager().getEnv(), m_args[0], m_args[1]); // Uses native endianness
m_builder.CreateCall3(m_sload, getRuntimeManager().getEnvPtr(), m_args[0], m_args[1]); // Uses native endianness
return m_builder.CreateLoad(m_args[1]);
}
@ -77,7 +77,7 @@ void Ext::sstore(llvm::Value* _index, llvm::Value* _value)
{
m_builder.CreateStore(_index, m_args[0]);
m_builder.CreateStore(_value, m_args[1]);
m_builder.CreateCall3(m_sstore, getRuntimeManager().getEnv(), m_args[0], m_args[1]); // Uses native endianness
m_builder.CreateCall3(m_sstore, getRuntimeManager().getEnvPtr(), m_args[0], m_args[1]); // Uses native endianness
}
llvm::Value* Ext::calldataload(llvm::Value* _index)
@ -92,7 +92,7 @@ llvm::Value* Ext::balance(llvm::Value* _address)
{
auto address = Endianness::toBE(m_builder, _address);
m_builder.CreateStore(address, m_args[0]);
m_builder.CreateCall3(m_balance, getRuntimeManager().getEnv(), m_args[0], m_args[1]);
m_builder.CreateCall3(m_balance, getRuntimeManager().getEnvPtr(), m_args[0], m_args[1]);
return m_builder.CreateLoad(m_args[1]);
}
@ -100,7 +100,7 @@ void Ext::suicide(llvm::Value* _address)
{
auto address = Endianness::toBE(m_builder, _address);
m_builder.CreateStore(address, m_args[0]);
m_builder.CreateCall2(m_suicide, getRuntimeManager().getEnv(), m_args[0]);
m_builder.CreateCall2(m_suicide, getRuntimeManager().getEnvPtr(), m_args[0]);
}
llvm::Value* Ext::create(llvm::Value*& _gas, llvm::Value* _endowment, llvm::Value* _initOff, llvm::Value* _initSize)
@ -109,7 +109,7 @@ llvm::Value* Ext::create(llvm::Value*& _gas, llvm::Value* _endowment, llvm::Valu
m_builder.CreateStore(_endowment, m_arg2);
auto begin = m_memoryMan.getBytePtr(_initOff);
auto size = m_builder.CreateTrunc(_initSize, Type::Size, "size");
createCall(m_create, getRuntimeManager().getEnv(), m_args[0], m_arg2, begin, size, m_args[1]);
createCall(m_create, getRuntimeManager().getEnvPtr(), m_args[0], m_arg2, begin, size, m_args[1]);
_gas = m_builder.CreateLoad(m_args[0]); // Return gas
llvm::Value* address = m_builder.CreateLoad(m_args[1]);
address = Endianness::toNative(m_builder, address);
@ -128,7 +128,7 @@ llvm::Value* Ext::call(llvm::Value*& _gas, llvm::Value* _receiveAddress, llvm::V
auto outSize = m_builder.CreateTrunc(_outSize, Type::Size, "out.size");
auto codeAddress = Endianness::toBE(m_builder, _codeAddress);
m_builder.CreateStore(codeAddress, m_arg8);
auto ret = createCall(m_call, getRuntimeManager().getEnv(), m_args[0], m_arg2, m_arg3, inBeg, inSize, outBeg, outSize, m_arg8);
auto ret = createCall(m_call, getRuntimeManager().getEnvPtr(), m_args[0], m_arg2, m_arg3, inBeg, inSize, outBeg, outSize, m_arg8);
_gas = m_builder.CreateLoad(m_args[0]); // Return gas
return m_builder.CreateZExt(ret, Type::Word, "ret");
}
@ -147,7 +147,7 @@ MemoryRef Ext::getExtCode(llvm::Value* _addr)
{
auto addr = Endianness::toBE(m_builder, _addr);
m_builder.CreateStore(addr, m_args[0]);
auto code = createCall(m_getExtCode, getRuntimeManager().getEnv(), m_args[0], m_size);
auto code = createCall(m_getExtCode, getRuntimeManager().getEnvPtr(), m_args[0], m_size);
auto codeSize = m_builder.CreateLoad(m_size);
auto codeSize256 = m_builder.CreateZExt(codeSize, Type::Word);
return {code, codeSize256};
@ -157,7 +157,7 @@ void Ext::log(llvm::Value* _memIdx, llvm::Value* _numBytes, std::array<llvm::Val
{
auto begin = m_memoryMan.getBytePtr(_memIdx);
auto size = m_builder.CreateTrunc(_numBytes, Type::Size, "size");
llvm::Value* args[] = {getRuntimeManager().getEnv(), begin, size, m_arg2, m_arg3, m_arg4, m_arg5};
llvm::Value* args[] = {getRuntimeManager().getEnvPtr(), begin, size, m_arg2, m_arg3, m_arg4, m_arg5};
auto topicArgPtr = &args[3];
for (auto&& topic : _topics)

18
libevmjit/GasMeter.cpp

@ -86,7 +86,8 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager)
{
auto module = getModule();
m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::Word, false), llvm::Function::PrivateLinkage, "gas.check", module);
llvm::Type* gasCheckArgs[] = {Type::RuntimePtr, Type::Word};
m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, gasCheckArgs, false), llvm::Function::PrivateLinkage, "gas.check", module);
InsertPointGuard guard(m_builder);
auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "Check", m_gasCheckFunc);
@ -94,14 +95,17 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, RuntimeManager& _runtimeManager)
auto updateBB = llvm::BasicBlock::Create(_builder.getContext(), "Update", m_gasCheckFunc);
m_builder.SetInsertPoint(checkBB);
llvm::Value* cost = m_gasCheckFunc->arg_begin();
cost->setName("cost");
auto arg = m_gasCheckFunc->arg_begin();
arg->setName("rt");
++arg;
arg->setName("cost");
auto cost = arg;
auto gas = m_runtimeManager.getGas();
auto isOutOfGas = m_builder.CreateICmpUGT(cost, gas, "isOutOfGas");
m_builder.CreateCondBr(isOutOfGas, outOfGasBB, updateBB);
m_builder.SetInsertPoint(outOfGasBB);
_runtimeManager.raiseException(ReturnCode::OutOfGas);
m_runtimeManager.raiseException(ReturnCode::OutOfGas);
m_builder.CreateUnreachable();
m_builder.SetInsertPoint(updateBB);
@ -115,7 +119,7 @@ void GasMeter::count(Instruction _inst)
if (!m_checkCall)
{
// Create gas check call with mocked block cost at begining of current cost-block
m_checkCall = m_builder.CreateCall(m_gasCheckFunc, llvm::UndefValue::get(Type::Word));
m_checkCall = createCall(m_gasCheckFunc, m_runtimeManager.getRuntimePtr(), llvm::UndefValue::get(Type::Word));
}
m_blockCost += getStepCost(_inst);
@ -123,7 +127,7 @@ void GasMeter::count(Instruction _inst)
void GasMeter::count(llvm::Value* _cost)
{
createCall(m_gasCheckFunc, _cost);
createCall(m_gasCheckFunc, m_runtimeManager.getRuntimePtr(), _cost);
}
void GasMeter::countExp(llvm::Value* _exponent)
@ -193,7 +197,7 @@ void GasMeter::commitCostBlock()
return;
}
m_checkCall->setArgOperand(0, Constant::get(m_blockCost)); // Update block cost in gas check call
m_checkCall->setArgOperand(1, Constant::get(m_blockCost)); // Update block cost in gas check call
m_checkCall = nullptr; // End cost-block
m_blockCost = 0;
}

34
libevmjit/Memory.cpp

@ -24,7 +24,7 @@ namespace jit
{
Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter):
RuntimeHelper(_runtimeManager),
RuntimeHelper(_runtimeManager), // TODO: RuntimeHelper not needed
m_gasMeter(_gasMeter)
{
auto module = getModule();
@ -45,17 +45,19 @@ Memory::Memory(RuntimeManager& _runtimeManager, GasMeter& _gasMeter):
attrBuilder.addAttribute(llvm::Attribute::NoAlias).addAttribute(llvm::Attribute::NoCapture).addAttribute(llvm::Attribute::NonNull).addAttribute(llvm::Attribute::ReadOnly);
m_resize->setAttributes(llvm::AttributeSet::get(m_resize->getContext(), 1, attrBuilder));
m_require = createRequireFunc(_gasMeter, _runtimeManager);
m_require = createRequireFunc(_gasMeter);
m_loadWord = createFunc(false, Type::Word, _gasMeter);
m_storeWord = createFunc(true, Type::Word, _gasMeter);
m_storeByte = createFunc(true, Type::Byte, _gasMeter);
}
llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager)
llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter)
{
llvm::Type* argTypes[] = {Type::Word, Type::Word};
llvm::Type* argTypes[] = {Type::RuntimePtr, Type::Word, Type::Word};
auto func = llvm::Function::Create(llvm::FunctionType::get(Type::Void, argTypes, false), llvm::Function::PrivateLinkage, "mem.require", getModule());
auto offset = func->arg_begin();
auto rt = func->arg_begin();
rt->setName("rt");
auto offset = rt->getNextNode();
offset->setName("offset");
auto size = offset->getNextNode();
size->setName("size");
@ -98,7 +100,7 @@ llvm::Function* Memory::createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _
_gasMeter.countMemory(newWords);
// Resize
m_builder.CreateStore(sizeRequired, m_size);
auto newData = m_builder.CreateCall2(m_resize, _runtimeManager.getRuntimePtr(), m_size, "newData");
auto newData = m_builder.CreateCall2(m_resize, rt, m_size, "newData");
m_builder.CreateStore(newData, m_data);
m_builder.CreateBr(returnBB);
@ -112,15 +114,18 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMet
{
auto isWord = _valueType == Type::Word;
llvm::Type* storeArgs[] = {Type::Word, _valueType};
llvm::Type* storeArgs[] = {Type::RuntimePtr, Type::Word, _valueType};
llvm::Type* loadArgs[] = {Type::RuntimePtr, Type::Word};
auto name = _isStore ? isWord ? "mstore" : "mstore8" : "mload";
auto funcType = _isStore ? llvm::FunctionType::get(Type::Void, storeArgs, false) : llvm::FunctionType::get(Type::Word, Type::Word, false);
auto funcType = _isStore ? llvm::FunctionType::get(Type::Void, storeArgs, false) : llvm::FunctionType::get(Type::Word, loadArgs, false);
auto func = llvm::Function::Create(funcType, llvm::Function::PrivateLinkage, name, getModule());
InsertPointGuard guard(m_builder); // Restores insert point at function exit
m_builder.SetInsertPoint(llvm::BasicBlock::Create(func->getContext(), {}, func));
llvm::Value* index = func->arg_begin();
auto rt = func->arg_begin();
rt->setName("rt");
auto index = rt->getNextNode();
index->setName("index");
auto valueSize = _valueType->getPrimitiveSizeInBits() / 8;
@ -130,7 +135,7 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMet
ptr = m_builder.CreateBitCast(ptr, Type::WordPtr, "wordPtr");
if (_isStore)
{
llvm::Value* value = ++func->arg_begin();
llvm::Value* value = index->getNextNode();
value->setName("value");
if (isWord)
value = Endianness::toBE(m_builder, value);
@ -150,19 +155,18 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMet
llvm::Value* Memory::loadWord(llvm::Value* _addr)
{
auto value = m_builder.CreateCall(m_loadWord, _addr);
return value;
return createCall(m_loadWord, getRuntimeManager().getRuntimePtr(), _addr);
}
void Memory::storeWord(llvm::Value* _addr, llvm::Value* _word)
{
m_builder.CreateCall2(m_storeWord, _addr, _word);
createCall(m_storeWord, getRuntimeManager().getRuntimePtr(), _addr, _word);
}
void Memory::storeByte(llvm::Value* _addr, llvm::Value* _word)
{
auto byte = m_builder.CreateTrunc(_word, Type::Byte, "byte");
m_builder.CreateCall2(m_storeByte, _addr, byte);
createCall(m_storeByte, getRuntimeManager().getRuntimePtr(), _addr, byte);
}
llvm::Value* Memory::getData()
@ -183,7 +187,7 @@ llvm::Value* Memory::getBytePtr(llvm::Value* _index)
void Memory::require(llvm::Value* _offset, llvm::Value* _size)
{
m_builder.CreateCall2(m_require, _offset, _size);
createCall(m_require, getRuntimeManager().getRuntimePtr(), _offset, _size);
}
void Memory::copyBytes(llvm::Value* _srcPtr, llvm::Value* _srcSize, llvm::Value* _srcIdx,

2
libevmjit/Memory.h

@ -31,7 +31,7 @@ private:
GasMeter& m_gasMeter;
llvm::Function* createFunc(bool _isStore, llvm::Type* _type, GasMeter& _gasMeter);
llvm::Function* createRequireFunc(GasMeter& _gasMeter, RuntimeManager& _runtimeManager);
llvm::Function* createRequireFunc(GasMeter& _gasMeter);
llvm::GlobalVariable* m_data;
llvm::GlobalVariable* m_size;

41
libevmjit/RuntimeManager.cpp

@ -74,43 +74,38 @@ llvm::Twine getName(RuntimeData::Index _index)
RuntimeManager::RuntimeManager(llvm::IRBuilder<>& _builder): CompilerHelper(_builder)
{
m_rtPtr = new llvm::GlobalVariable(*getModule(), Type::RuntimePtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::RuntimePtr), "rt");
m_dataPtr = new llvm::GlobalVariable(*getModule(), Type::RuntimeDataPtr, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::RuntimeDataPtr), "data");
m_longjmp = llvm::Intrinsic::getDeclaration(getModule(), llvm::Intrinsic::longjmp);
// Export data
auto mainFunc = getMainFunction();
llvm::Value* rtPtr = &mainFunc->getArgumentList().front();
m_builder.CreateStore(rtPtr, m_rtPtr);
auto dataPtr = m_builder.CreateStructGEP(rtPtr, 0, "dataPtr");
auto data = m_builder.CreateLoad(dataPtr, "data");
m_builder.CreateStore(data, m_dataPtr);
auto envPtr = m_builder.CreateStructGEP(rtPtr, 1, "envPtr");
m_env = m_builder.CreateLoad(envPtr, "env");
assert(m_env->getType() == Type::EnvPtr);
// Unpack data
auto rtPtr = getRuntimePtr();
m_dataPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(rtPtr, 0), "data");
assert(m_dataPtr->getType() == Type::RuntimeDataPtr);
m_envPtr = m_builder.CreateLoad(m_builder.CreateStructGEP(rtPtr, 1), "env");
assert(m_envPtr->getType() == Type::EnvPtr);
}
llvm::Value* RuntimeManager::getRuntimePtr()
{
// FIXME: Data ptr
//if (auto mainFunc = getMainFunction())
// return mainFunc->arg_begin(); // Runtime is the parameter of main function
return m_builder.CreateLoad(m_rtPtr, "rt");
// Expect first argument of a function to be a pointer to Runtime
auto func = m_builder.GetInsertBlock()->getParent();
auto rtPtr = &func->getArgumentList().front();
assert(rtPtr->getType() == Type::RuntimePtr);
return rtPtr;
}
llvm::Value* RuntimeManager::getDataPtr()
{
// FIXME: Data ptr
//if (auto mainFunc = getMainFunction())
// return mainFunc->arg_begin(); // Runtime is the parameter of main function
return m_builder.CreateLoad(m_dataPtr, "data");
if (getMainFunction())
return m_dataPtr;
auto rtPtr = getRuntimePtr();
return m_builder.CreateLoad(m_builder.CreateStructGEP(rtPtr, 0), "data");
}
llvm::Value* RuntimeManager::getEnv()
llvm::Value* RuntimeManager::getEnvPtr()
{
assert(getMainFunction()); // Available only in main function
return m_env;
return m_envPtr;
}
llvm::Value* RuntimeManager::getPtr(RuntimeData::Index _index)

7
libevmjit/RuntimeManager.h

@ -19,7 +19,7 @@ public:
llvm::Value* getRuntimePtr();
llvm::Value* getDataPtr();
llvm::Value* getEnv();
llvm::Value* getEnvPtr(); // TODO: Can we make it const?
llvm::Value* get(RuntimeData::Index _index);
llvm::Value* get(Instruction _inst);
@ -40,10 +40,9 @@ private:
void set(RuntimeData::Index _index, llvm::Value* _value);
llvm::Value* getJmpBuf();
llvm::GlobalVariable* m_rtPtr = nullptr;
llvm::GlobalVariable* m_dataPtr = nullptr;
llvm::Function* m_longjmp = nullptr;
llvm::Value* m_env = nullptr;
llvm::Value* m_dataPtr = nullptr;
llvm::Value* m_envPtr = nullptr;
};
}

Loading…
Cancel
Save