|
|
@ -83,11 +83,27 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module): |
|
|
|
m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas"); |
|
|
|
m_gas->setUnnamedAddr(true); // Address is not important
|
|
|
|
|
|
|
|
m_rtExit = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::MainReturn, false), llvm::Function::ExternalLinkage, "rt_exit", _module); |
|
|
|
|
|
|
|
m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", _module); |
|
|
|
InsertPointGuard guard(m_builder); |
|
|
|
m_builder.SetInsertPoint(llvm::BasicBlock::Create(_builder.getContext(), {}, m_gasCheckFunc)); |
|
|
|
|
|
|
|
auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "check", m_gasCheckFunc); |
|
|
|
auto outOfGasBB = llvm::BasicBlock::Create(_builder.getContext(), "outOfGas", m_gasCheckFunc); |
|
|
|
auto updateBB = llvm::BasicBlock::Create(_builder.getContext(), "update", m_gasCheckFunc); |
|
|
|
|
|
|
|
m_builder.SetInsertPoint(checkBB); |
|
|
|
llvm::Value* cost = m_gasCheckFunc->arg_begin(); |
|
|
|
llvm::Value* gas = m_builder.CreateLoad(m_gas); |
|
|
|
cost->setName("cost"); |
|
|
|
llvm::Value* gas = m_builder.CreateLoad(m_gas, "gas"); |
|
|
|
auto isOutOfGas = m_builder.CreateICmpUGT(cost, gas, "isOutOfGas"); |
|
|
|
m_builder.CreateCondBr(isOutOfGas, outOfGasBB, updateBB); |
|
|
|
|
|
|
|
m_builder.SetInsertPoint(outOfGasBB); |
|
|
|
m_builder.CreateCall(m_rtExit, Constant::get(ReturnCode::OutOfGas)); |
|
|
|
m_builder.CreateRetVoid(); |
|
|
|
|
|
|
|
m_builder.SetInsertPoint(updateBB); |
|
|
|
gas = m_builder.CreateSub(gas, cost); |
|
|
|
m_builder.CreateStore(gas, m_gas); |
|
|
|
m_builder.CreateRetVoid(); |
|
|
|