diff --git a/libevmjit/Ext.cpp b/libevmjit/Ext.cpp index a4a1fc3508..2b9802bb05 100644 --- a/libevmjit/Ext.cpp +++ b/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& _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; } diff --git a/libevmjit/Memory.cpp b/libevmjit/Memory.cpp index b088fb8084..74e21cbfe0 100644 --- a/libevmjit/Memory.cpp +++ b/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, diff --git a/libevmjit/Memory.h b/libevmjit/Memory.h index 3ccc542858..85b0cb8335 100644 --- a/libevmjit/Memory.h +++ b/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; diff --git a/libevmjit/RuntimeManager.cpp b/libevmjit/RuntimeManager.cpp index 9bb9b36981..b324da6419 100644 --- a/libevmjit/RuntimeManager.cpp +++ b/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) diff --git a/libevmjit/RuntimeManager.h b/libevmjit/RuntimeManager.h index c10c8cd25f..1cff606e3d 100644 --- a/libevmjit/RuntimeManager.h +++ b/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; }; }