From d3f59f6de40f2cb50c50d6add744eabd63e999f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 9 Oct 2014 11:37:19 +0200 Subject: [PATCH 1/6] Introducing GasMeter --- evmcc/Compiler.cpp | 4 +++- evmcc/GasMeter.cpp | 49 ++++++++++++++++++++++++++++++++++++++++++++++ evmcc/GasMeter.h | 9 +++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 evmcc/GasMeter.cpp create mode 100644 evmcc/GasMeter.h diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 880487705d..91bc692eb1 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -12,6 +12,9 @@ namespace evmcc { +using dev::eth::Instruction; +using namespace dev::eth; // We should move all the JIT code into dev::eth namespace + struct { llvm::Type* word8; @@ -191,7 +194,6 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC) { - using dev::eth::Instruction; auto inst = static_cast(bytecode[currentPC]); switch (inst) { diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp new file mode 100644 index 0000000000..3687cfed37 --- /dev/null +++ b/evmcc/GasMeter.cpp @@ -0,0 +1,49 @@ + +#include "GasMeter.h" + +#include +#include + +namespace evmcc +{ + +using namespace dev::eth; // We should move all the JIT code into dev::eth namespace + +namespace +{ + +uint64_t getStepCost(dev::eth::Instruction inst) // TODO: Add this function to FeeSructure +{ + switch (inst) + { + case Instruction::STOP: + case Instruction::SUICIDE: + return 0; + + case Instruction::SSTORE: + return static_cast(c_sstoreGas); + + case Instruction::SLOAD: + return static_cast(c_sloadGas); + + case Instruction::SHA3: + return static_cast(c_sha3Gas); + + case Instruction::BALANCE: + return static_cast(c_sha3Gas); + + case Instruction::CALL: + case Instruction::CALLCODE: + return static_cast(c_callGas); + + case Instruction::CREATE: + return static_cast(c_createGas); + + default: // Assumes instruction code is valid + return static_cast(c_stepGas);; + } +} + +} + +} \ No newline at end of file diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h new file mode 100644 index 0000000000..c234a4ab64 --- /dev/null +++ b/evmcc/GasMeter.h @@ -0,0 +1,9 @@ + +#pragma once + +#include + +namespace evmcc +{ + +} \ No newline at end of file From 28d6dd79309d4f38fb2edaa7d207528db39004c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 9 Oct 2014 12:52:48 +0200 Subject: [PATCH 2/6] Decrement global gas value by instruction step cost [#79942174] --- evmcc/Compiler.cpp | 4 ++++ evmcc/GasMeter.cpp | 22 +++++++++++++++++++++- evmcc/GasMeter.h | 17 +++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 91bc692eb1..7205702779 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -8,6 +8,7 @@ #include "Memory.h" #include "Ext.h" +#include "GasMeter.h" namespace evmcc { @@ -182,6 +183,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) // Init runtime structures. auto memory = Memory(builder, module.get()); auto ext = Ext(builder, module.get()); + GasMeter gasMeter(builder, module.get()); // Jump to first instruction builder.CreateBr(basicBlocks.begin()->second); @@ -195,6 +197,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC) { auto inst = static_cast(bytecode[currentPC]); + gasMeter.check(inst); + switch (inst) { diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 3687cfed37..af08d13b7b 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -1,6 +1,9 @@ #include "GasMeter.h" +#include +#include + #include #include @@ -9,7 +12,7 @@ namespace evmcc using namespace dev::eth; // We should move all the JIT code into dev::eth namespace -namespace +namespace // Helper functions { uint64_t getStepCost(dev::eth::Instruction inst) // TODO: Add this function to FeeSructure @@ -46,4 +49,21 @@ uint64_t getStepCost(dev::eth::Instruction inst) // TODO: Add this function to F } +GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module): + m_builder(_builder) +{ + m_gas = new llvm::GlobalVariable(*_module, m_builder.getIntNTy(256), false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(m_builder.getIntNTy(256)), "gas"); + m_gas->setUnnamedAddr(true); // Address is not important + + //llvm::Function::Create() +} + +void GasMeter::check(Instruction _inst) +{ + auto stepCost = getStepCost(_inst); + auto before = m_builder.CreateLoad(m_gas, "gas.before"); + auto after = m_builder.CreateSub(before, m_builder.getIntN(256, stepCost)); + m_builder.CreateStore(after, m_gas); +} + } \ No newline at end of file diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index c234a4ab64..f50438c9a2 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -1,9 +1,26 @@ #pragma once +#include + #include namespace evmcc { +class GasMeter +{ +public: + GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* module); + + GasMeter(const GasMeter&) = delete; + void operator=(GasMeter) = delete; + + void check(dev::eth::Instruction _inst); + +private: + llvm::IRBuilder<>& m_builder; + llvm::GlobalVariable* m_gas; +}; + } \ No newline at end of file From b7f31afb7a345e599bfaebbd67be3fb34a627a47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 9 Oct 2014 13:17:54 +0200 Subject: [PATCH 3/6] Cleanup LLVM types usage --- evmcc/BasicBlock.cpp | 7 ++++--- evmcc/Compiler.cpp | 36 ++++++++++++++++-------------------- evmcc/GasMeter.cpp | 4 +++- evmcc/Type.cpp | 16 ++++++++++++++++ evmcc/Type.h | 16 ++++++++++++++++ 5 files changed, 55 insertions(+), 24 deletions(-) create mode 100644 evmcc/Type.cpp create mode 100644 evmcc/Type.h diff --git a/evmcc/BasicBlock.cpp b/evmcc/BasicBlock.cpp index e5cdf386fc..de18dbba0a 100644 --- a/evmcc/BasicBlock.cpp +++ b/evmcc/BasicBlock.cpp @@ -4,6 +4,8 @@ #include #include +#include "Type.h" + namespace evmcc { @@ -27,10 +29,9 @@ llvm::Value* BasicBlock::Stack::pop() if (m_backend.empty()) { // Create PHI node - auto i256Ty = llvm::Type::getIntNTy(m_llvmBB->getContext(), 256); if (m_llvmBB->empty()) - return llvm::PHINode::Create(i256Ty, 0, {}, m_llvmBB); - return llvm::PHINode::Create(i256Ty, 0, {}, m_llvmBB->getFirstNonPHI()); + return llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB); + return llvm::PHINode::Create(Type::i256, 0, {}, m_llvmBB->getFirstNonPHI()); } auto top = m_backend.back(); diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 7205702779..d26c7850e0 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -6,6 +6,7 @@ #include +#include "Type.h" #include "Memory.h" #include "Ext.h" #include "GasMeter.h" @@ -20,9 +21,6 @@ struct { llvm::Type* word8; llvm::Type* word8ptr; - llvm::Type* word256; - llvm::Type* word256ptr; - llvm::Type* word256arr; llvm::Type* size; llvm::Type* Void; llvm::Type* WordLowPrecision; @@ -30,12 +28,10 @@ struct Compiler::Compiler() { + Type::init(llvm::getGlobalContext()); auto& context = llvm::getGlobalContext(); Types.word8 = llvm::Type::getInt8Ty(context); Types.word8ptr = llvm::Type::getInt8PtrTy(context); - Types.word256 = llvm::Type::getIntNTy(context, 256); - Types.word256ptr = Types.word256->getPointerTo(); - Types.word256arr = llvm::ArrayType::get(Types.word256, 100); Types.size = llvm::Type::getInt64Ty(context); Types.Void = llvm::Type::getVoidTy(context); @@ -227,7 +223,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); auto res128 = builder.CreateMul(lhs128, rhs128); - auto res256 = builder.CreateZExt(res128, Types.word256); + auto res256 = builder.CreateZExt(res128, Type::i256); stack.push(res256); break; } @@ -239,7 +235,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); auto res128 = builder.CreateUDiv(lhs128, rhs128); - auto res256 = builder.CreateZExt(res128, Types.word256); + auto res256 = builder.CreateZExt(res128, Type::i256); stack.push(res256); break; } @@ -251,7 +247,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); auto res128 = builder.CreateSDiv(lhs128, rhs128); - auto res256 = builder.CreateSExt(res128, Types.word256); + auto res256 = builder.CreateSExt(res128, Type::i256); stack.push(res256); break; } @@ -263,7 +259,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); auto res128 = builder.CreateURem(lhs128, rhs128); - auto res256 = builder.CreateZExt(res128, Types.word256); + auto res256 = builder.CreateZExt(res128, Type::i256); stack.push(res256); break; } @@ -275,7 +271,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); auto res128 = builder.CreateSRem(lhs128, rhs128); - auto res256 = builder.CreateSExt(res128, Types.word256); + auto res256 = builder.CreateSExt(res128, Type::i256); stack.push(res256); break; } @@ -292,7 +288,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) case Instruction::NEG: { auto top = stack.pop(); - auto zero = ConstantInt::get(Types.word256, 0); + auto zero = ConstantInt::get(Type::i256, 0); auto res = builder.CreateSub(zero, top); stack.push(res); break; @@ -303,7 +299,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs = stack.pop(); auto rhs = stack.pop(); auto res1 = builder.CreateICmpULT(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Types.word256); + auto res256 = builder.CreateZExt(res1, Type::i256); stack.push(res256); break; } @@ -313,7 +309,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs = stack.pop(); auto rhs = stack.pop(); auto res1 = builder.CreateICmpUGT(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Types.word256); + auto res256 = builder.CreateZExt(res1, Type::i256); stack.push(res256); break; } @@ -323,7 +319,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs = stack.pop(); auto rhs = stack.pop(); auto res1 = builder.CreateICmpSLT(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Types.word256); + auto res256 = builder.CreateZExt(res1, Type::i256); stack.push(res256); break; } @@ -333,7 +329,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs = stack.pop(); auto rhs = stack.pop(); auto res1 = builder.CreateICmpSGT(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Types.word256); + auto res256 = builder.CreateZExt(res1, Type::i256); stack.push(res256); break; } @@ -343,7 +339,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto lhs = stack.pop(); auto rhs = stack.pop(); auto res1 = builder.CreateICmpEQ(lhs, rhs); - auto res256 = builder.CreateZExt(res1, Types.word256); + auto res256 = builder.CreateZExt(res1, Type::i256); stack.push(res256); break; } @@ -351,9 +347,9 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) case Instruction::NOT: { auto top = stack.pop(); - auto zero = ConstantInt::get(Types.word256, 0); + auto zero = ConstantInt::get(Type::i256, 0); auto iszero = builder.CreateICmpEQ(top, zero, "iszero"); - auto result = builder.CreateZExt(iszero, Types.word256); + auto result = builder.CreateZExt(iszero, Type::i256); stack.push(result); break; } @@ -584,7 +580,7 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) stack.pop(); auto top = stack.pop(); - auto zero = ConstantInt::get(Types.word256, 0); + auto zero = ConstantInt::get(Type::i256, 0); auto cond = builder.CreateICmpNE(top, zero, "nonzero"); auto& targetBlock = basicBlocks.find(jumpTargets[currentPC])->second; auto& followBlock = basicBlocks.find(currentPC + 1)->second; diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index af08d13b7b..4fdfde4696 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -7,6 +7,8 @@ #include #include +#include "Type.h" + namespace evmcc { @@ -52,7 +54,7 @@ uint64_t getStepCost(dev::eth::Instruction inst) // TODO: Add this function to F GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module): m_builder(_builder) { - m_gas = new llvm::GlobalVariable(*_module, m_builder.getIntNTy(256), false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(m_builder.getIntNTy(256)), "gas"); + m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::i256), "gas"); m_gas->setUnnamedAddr(true); // Address is not important //llvm::Function::Create() diff --git a/evmcc/Type.cpp b/evmcc/Type.cpp new file mode 100644 index 0000000000..c66cd6de68 --- /dev/null +++ b/evmcc/Type.cpp @@ -0,0 +1,16 @@ + +#include "Type.h" + +#include + +namespace evmcc +{ + +llvm::Type* Type::i256; + +void Type::init(llvm::LLVMContext& _context) +{ + i256 = llvm::Type::getIntNTy(_context, 256); +} + +} \ No newline at end of file diff --git a/evmcc/Type.h b/evmcc/Type.h new file mode 100644 index 0000000000..0d7f3e428a --- /dev/null +++ b/evmcc/Type.h @@ -0,0 +1,16 @@ + +#pragma once + +#include + +namespace evmcc +{ + +struct Type +{ + static llvm::Type* i256; + + static void init(llvm::LLVMContext& _context); +}; + +} \ No newline at end of file From 97644d660ab0c20e982e60a327c8dd268e0fbeab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 9 Oct 2014 14:44:25 +0200 Subject: [PATCH 4/6] Cleanup LLVM types usage --- evmcc/Compiler.cpp | 36 ++++++++++-------------------------- evmcc/Type.cpp | 2 ++ evmcc/Type.h | 4 ++++ 3 files changed, 16 insertions(+), 26 deletions(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index d26c7850e0..d1fd3eb1a2 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -17,26 +17,10 @@ namespace evmcc using dev::eth::Instruction; using namespace dev::eth; // We should move all the JIT code into dev::eth namespace -struct -{ - llvm::Type* word8; - llvm::Type* word8ptr; - llvm::Type* size; - llvm::Type* Void; - llvm::Type* WordLowPrecision; -} Types; Compiler::Compiler() { Type::init(llvm::getGlobalContext()); - auto& context = llvm::getGlobalContext(); - Types.word8 = llvm::Type::getInt8Ty(context); - Types.word8ptr = llvm::Type::getInt8PtrTy(context); - Types.size = llvm::Type::getInt64Ty(context); - Types.Void = llvm::Type::getVoidTy(context); - - // TODO: Use 64-bit for now. In 128-bit compiler-rt library functions are required - Types.WordLowPrecision = llvm::Type::getIntNTy(context, 64); } void Compiler::createBasicBlocks(const dev::bytes& bytecode) @@ -220,8 +204,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { auto lhs256 = stack.pop(); auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision); auto res128 = builder.CreateMul(lhs128, rhs128); auto res256 = builder.CreateZExt(res128, Type::i256); stack.push(res256); @@ -232,8 +216,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { auto lhs256 = stack.pop(); auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision); auto res128 = builder.CreateUDiv(lhs128, rhs128); auto res256 = builder.CreateZExt(res128, Type::i256); stack.push(res256); @@ -244,8 +228,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { auto lhs256 = stack.pop(); auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision); auto res128 = builder.CreateSDiv(lhs128, rhs128); auto res256 = builder.CreateSExt(res128, Type::i256); stack.push(res256); @@ -256,8 +240,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { auto lhs256 = stack.pop(); auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision); auto res128 = builder.CreateURem(lhs128, rhs128); auto res256 = builder.CreateZExt(res128, Type::i256); stack.push(res256); @@ -268,8 +252,8 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) { auto lhs256 = stack.pop(); auto rhs256 = stack.pop(); - auto lhs128 = builder.CreateTrunc(lhs256, Types.WordLowPrecision); - auto rhs128 = builder.CreateTrunc(rhs256, Types.WordLowPrecision); + auto lhs128 = builder.CreateTrunc(lhs256, Type::lowPrecision); + auto rhs128 = builder.CreateTrunc(rhs256, Type::lowPrecision); auto res128 = builder.CreateSRem(lhs128, rhs128); auto res256 = builder.CreateSExt(res128, Type::i256); stack.push(res256); diff --git a/evmcc/Type.cpp b/evmcc/Type.cpp index c66cd6de68..c19c496443 100644 --- a/evmcc/Type.cpp +++ b/evmcc/Type.cpp @@ -7,10 +7,12 @@ namespace evmcc { llvm::Type* Type::i256; +llvm::Type* Type::lowPrecision; void Type::init(llvm::LLVMContext& _context) { i256 = llvm::Type::getIntNTy(_context, 256); + lowPrecision = llvm::Type::getInt64Ty(_context); } } \ No newline at end of file diff --git a/evmcc/Type.h b/evmcc/Type.h index 0d7f3e428a..425dae3456 100644 --- a/evmcc/Type.h +++ b/evmcc/Type.h @@ -10,6 +10,10 @@ struct Type { static llvm::Type* i256; + /// Type for doing low precision arithmetics where 256-bit precision is not supported by native target + /// @TODO: Use 64-bit for now. In 128-bit compiler-rt library functions are required + static llvm::Type* lowPrecision; + static void init(llvm::LLVMContext& _context); }; From 04cf0cfcea3010a612581e48897711730a1e4e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 9 Oct 2014 15:44:41 +0200 Subject: [PATCH 5/6] Generate gas checking function --- evmcc/GasMeter.cpp | 16 ++++++++++++---- evmcc/GasMeter.h | 1 + evmcc/Type.cpp | 2 ++ evmcc/Type.h | 2 ++ 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 4fdfde4696..2006f319f0 100644 --- a/evmcc/GasMeter.cpp +++ b/evmcc/GasMeter.cpp @@ -57,15 +57,23 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module): m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(Type::i256), "gas"); m_gas->setUnnamedAddr(true); // Address is not important - //llvm::Function::Create() + auto pt = m_builder.GetInsertPoint(); + auto bb = m_builder.GetInsertBlock(); + m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", _module); + auto gasCheckBB = llvm::BasicBlock::Create(_builder.getContext(), {}, m_gasCheckFunc); + m_builder.SetInsertPoint(gasCheckBB); + llvm::Value* cost = m_gasCheckFunc->arg_begin(); + llvm::Value* gas = m_builder.CreateLoad(m_gas); + gas = m_builder.CreateSub(gas, cost); + m_builder.CreateStore(gas, m_gas); + m_builder.CreateRetVoid(); + m_builder.SetInsertPoint(bb, pt); } void GasMeter::check(Instruction _inst) { auto stepCost = getStepCost(_inst); - auto before = m_builder.CreateLoad(m_gas, "gas.before"); - auto after = m_builder.CreateSub(before, m_builder.getIntN(256, stepCost)); - m_builder.CreateStore(after, m_gas); + m_builder.CreateCall(m_gasCheckFunc, m_builder.getIntN(256, stepCost)); } } \ No newline at end of file diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index f50438c9a2..e2ee26a716 100644 --- a/evmcc/GasMeter.h +++ b/evmcc/GasMeter.h @@ -21,6 +21,7 @@ public: private: llvm::IRBuilder<>& m_builder; llvm::GlobalVariable* m_gas; + llvm::Function* m_gasCheckFunc; }; } \ No newline at end of file diff --git a/evmcc/Type.cpp b/evmcc/Type.cpp index c19c496443..b9063569bb 100644 --- a/evmcc/Type.cpp +++ b/evmcc/Type.cpp @@ -8,11 +8,13 @@ namespace evmcc llvm::Type* Type::i256; llvm::Type* Type::lowPrecision; +llvm::Type* Type::Void; void Type::init(llvm::LLVMContext& _context) { i256 = llvm::Type::getIntNTy(_context, 256); lowPrecision = llvm::Type::getInt64Ty(_context); + Void = llvm::Type::getVoidTy(_context); } } \ No newline at end of file diff --git a/evmcc/Type.h b/evmcc/Type.h index 425dae3456..32459dca4c 100644 --- a/evmcc/Type.h +++ b/evmcc/Type.h @@ -14,6 +14,8 @@ struct Type /// @TODO: Use 64-bit for now. In 128-bit compiler-rt library functions are required static llvm::Type* lowPrecision; + static llvm::Type* Void; + static void init(llvm::LLVMContext& _context); }; From e42217d5bca36ac260ca6135a94b225472166595 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Bylica?= Date: Thu, 9 Oct 2014 16:10:12 +0200 Subject: [PATCH 6/6] Disable gas checking for now (does not work and makes IR code hard to read) [#79942174] --- evmcc/Compiler.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index d1fd3eb1a2..9a46313b66 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -177,7 +177,9 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) for (auto currentPC = basicBlock.begin(); currentPC != basicBlock.end(); ++currentPC) { auto inst = static_cast(bytecode[currentPC]); - gasMeter.check(inst); + + // Disable for now + //gasMeter.check(inst); switch (inst) {