mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-21 20:26:41 +00:00
Merge branch 'develop-evmcc' of github.com:imapp-pl/ethereum into develop-evmcc
Conflicts: libevmjit/Compiler.cpp
This commit is contained in:
commit
937fbaa56a
9 changed files with 38 additions and 27 deletions
1
evmcc/test/mem/mstore1.evm
Normal file
1
evmcc/test/mem/mstore1.evm
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
6001600054
|
||||||
6
evmcc/test/mem/mstore1.lll
Normal file
6
evmcc/test/mem/mstore1.lll
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
(asm ;; []
|
||||||
|
1
|
||||||
|
0
|
||||||
|
MSTORE ;; [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1]
|
||||||
|
)
|
||||||
|
|
@ -34,16 +34,18 @@ Compiler::Compiler():
|
||||||
void Compiler::createBasicBlocks(bytesConstRef bytecode)
|
void Compiler::createBasicBlocks(bytesConstRef bytecode)
|
||||||
{
|
{
|
||||||
std::set<ProgramCounter> splitPoints; // Sorted collections of instruction indices where basic blocks start/end
|
std::set<ProgramCounter> splitPoints; // Sorted collections of instruction indices where basic blocks start/end
|
||||||
splitPoints.insert(0); // First basic block
|
|
||||||
|
|
||||||
std::map<ProgramCounter, ProgramCounter> directJumpTargets;
|
std::map<ProgramCounter, ProgramCounter> directJumpTargets;
|
||||||
std::vector<ProgramCounter> indirectJumpTargets;
|
std::vector<ProgramCounter> indirectJumpTargets;
|
||||||
boost::dynamic_bitset<> validJumpTargets(bytecode.size());
|
boost::dynamic_bitset<> validJumpTargets(std::max(bytecode.size(), size_t(1)));
|
||||||
|
|
||||||
|
splitPoints.insert(0); // First basic block
|
||||||
|
validJumpTargets[0] = true;
|
||||||
|
|
||||||
for (auto curr = bytecode.begin(); curr != bytecode.end(); ++curr)
|
for (auto curr = bytecode.begin(); curr != bytecode.end(); ++curr)
|
||||||
{
|
{
|
||||||
ProgramCounter currentPC = curr - bytecode.begin();
|
ProgramCounter currentPC = curr - bytecode.begin();
|
||||||
validJumpTargets[currentPC] = 1;
|
validJumpTargets[currentPC] = true;
|
||||||
|
|
||||||
auto inst = static_cast<Instruction>(*curr);
|
auto inst = static_cast<Instruction>(*curr);
|
||||||
switch (inst)
|
switch (inst)
|
||||||
|
|
@ -473,6 +475,7 @@ void Compiler::compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode,
|
||||||
memory.require(inOff, inSize);
|
memory.require(inOff, inSize);
|
||||||
auto hash = ext.sha3(inOff, inSize);
|
auto hash = ext.sha3(inOff, inSize);
|
||||||
stack.push(hash);
|
stack.push(hash);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Instruction::POP:
|
case Instruction::POP:
|
||||||
|
|
|
||||||
|
|
@ -12,9 +12,10 @@ namespace eth
|
||||||
namespace jit
|
namespace jit
|
||||||
{
|
{
|
||||||
|
|
||||||
llvm::Value* Endianness::toBE(llvm::IRBuilder<>& _builder, llvm::Value* _word)
|
llvm::Value* Endianness::bswap(llvm::IRBuilder<>& _builder, llvm::Value* _word)
|
||||||
{
|
{
|
||||||
// TODO: Native is Little Endian
|
// TODO: Native is Little Endian
|
||||||
|
assert(_word->getType() == Type::i256);
|
||||||
auto bswap = llvm::Intrinsic::getDeclaration(_builder.GetInsertBlock()->getParent()->getParent(), llvm::Intrinsic::bswap, Type::i256);
|
auto bswap = llvm::Intrinsic::getDeclaration(_builder.GetInsertBlock()->getParent()->getParent(), llvm::Intrinsic::bswap, Type::i256);
|
||||||
return _builder.CreateCall(bswap, _word);
|
return _builder.CreateCall(bswap, _word);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,12 @@ class Endianness
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static llvm::Value* toBE(llvm::IRBuilder<>& _builder, llvm::Value* _word);
|
static llvm::Value* toBE(llvm::IRBuilder<>& _builder, llvm::Value* _word) { return bswap(_builder, _word); }
|
||||||
|
|
||||||
|
static llvm::Value* toNative(llvm::IRBuilder<>& _builder, llvm::Value* _word) { return bswap(_builder, _word); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
static llvm::Value* bswap(llvm::IRBuilder<>& _builder, llvm::Value* _word);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -70,13 +70,7 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module, u256& _gas, ExtV
|
||||||
|
|
||||||
auto exec = std::unique_ptr<llvm::ExecutionEngine>(builder.create());
|
auto exec = std::unique_ptr<llvm::ExecutionEngine>(builder.create());
|
||||||
if (!exec)
|
if (!exec)
|
||||||
{
|
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment(errorMsg));
|
||||||
if (!errorMsg.empty())
|
|
||||||
std::cerr << "error creating EE: " << errorMsg << std::endl;
|
|
||||||
else
|
|
||||||
std::cerr << "unknown error creating llvm::ExecutionEngine" << std::endl;
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
_module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module
|
_module.release(); // Successfully created llvm::ExecutionEngine takes ownership of the module
|
||||||
exec->finalizeObject();
|
exec->finalizeObject();
|
||||||
|
|
||||||
|
|
@ -106,10 +100,7 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module, u256& _gas, ExtV
|
||||||
|
|
||||||
auto entryFunc = module->getFunction("main");
|
auto entryFunc = module->getFunction("main");
|
||||||
if (!entryFunc)
|
if (!entryFunc)
|
||||||
{
|
BOOST_THROW_EXCEPTION(Exception() << errinfo_comment("main function not found"));
|
||||||
std::cerr << "main function not found\n";
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnCode returnCode;
|
ReturnCode returnCode;
|
||||||
std::jmp_buf buf;
|
std::jmp_buf buf;
|
||||||
|
|
|
||||||
|
|
@ -310,7 +310,7 @@ EXPORT void ext_create(i256* _endowment, i256* _initOff, i256* _initSize, h256*
|
||||||
auto initOff = static_cast<size_t>(llvm2eth(*_initOff));
|
auto initOff = static_cast<size_t>(llvm2eth(*_initOff));
|
||||||
auto initSize = static_cast<size_t>(llvm2eth(*_initSize));
|
auto initSize = static_cast<size_t>(llvm2eth(*_initSize));
|
||||||
auto&& initRef = bytesConstRef(Runtime::getMemory().data() + initOff, initSize);
|
auto&& initRef = bytesConstRef(Runtime::getMemory().data() + initOff, initSize);
|
||||||
auto&& onOp = bytesConstRef(); // TODO: Handle that thing
|
OnOpFunc onOp{}; // TODO: Handle that thing
|
||||||
h256 address = ext.create(endowment, &gas, initRef, onOp);
|
h256 address = ext.create(endowment, &gas, initRef, onOp);
|
||||||
*_address = address;
|
*_address = address;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,26 +30,26 @@ uint64_t getStepCost(Instruction inst) // TODO: Add this function to FeeSructure
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case Instruction::SSTORE:
|
case Instruction::SSTORE:
|
||||||
return static_cast<uint64_t>(FeeStructure::c_sstoreGas);
|
return static_cast<uint64_t>(c_sstoreGas);
|
||||||
|
|
||||||
case Instruction::SLOAD:
|
case Instruction::SLOAD:
|
||||||
return static_cast<uint64_t>(FeeStructure::c_sloadGas);
|
return static_cast<uint64_t>(c_sloadGas);
|
||||||
|
|
||||||
case Instruction::SHA3:
|
case Instruction::SHA3:
|
||||||
return static_cast<uint64_t>(FeeStructure::c_sha3Gas);
|
return static_cast<uint64_t>(c_sha3Gas);
|
||||||
|
|
||||||
case Instruction::BALANCE:
|
case Instruction::BALANCE:
|
||||||
return static_cast<uint64_t>(FeeStructure::c_sha3Gas);
|
return static_cast<uint64_t>(c_sha3Gas);
|
||||||
|
|
||||||
case Instruction::CALL:
|
case Instruction::CALL:
|
||||||
case Instruction::CALLCODE:
|
case Instruction::CALLCODE:
|
||||||
return static_cast<uint64_t>(FeeStructure::c_callGas);
|
return static_cast<uint64_t>(c_callGas);
|
||||||
|
|
||||||
case Instruction::CREATE:
|
case Instruction::CREATE:
|
||||||
return static_cast<uint64_t>(FeeStructure::c_createGas);
|
return static_cast<uint64_t>(c_createGas);
|
||||||
|
|
||||||
default: // Assumes instruction code is valid
|
default: // Assumes instruction code is valid
|
||||||
return static_cast<uint64_t>(FeeStructure::c_stepGas);
|
return static_cast<uint64_t>(c_stepGas);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -134,7 +134,7 @@ void GasMeter::countSStore(Ext& _ext, llvm::Value* _index, llvm::Value* _newValu
|
||||||
{
|
{
|
||||||
assert(!m_checkCall); // Everything should've been commited before
|
assert(!m_checkCall); // Everything should've been commited before
|
||||||
|
|
||||||
static const auto sstoreCost = static_cast<uint64_t>(FeeStructure::c_sstoreGas);
|
static const auto sstoreCost = static_cast<uint64_t>(c_sstoreGas);
|
||||||
|
|
||||||
// [ADD] if oldValue == 0 and newValue != 0 => 2*cost
|
// [ADD] if oldValue == 0 and newValue != 0 => 2*cost
|
||||||
// [DEL] if oldValue != 0 and newValue == 0 => 0
|
// [DEL] if oldValue != 0 and newValue == 0 => 0
|
||||||
|
|
@ -187,7 +187,7 @@ void GasMeter::commitCostBlock(llvm::Value* _additionalCost)
|
||||||
void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder)
|
void GasMeter::checkMemory(llvm::Value* _additionalMemoryInWords, llvm::IRBuilder<>& _builder)
|
||||||
{
|
{
|
||||||
// Memory uses other builder, but that can be changes later
|
// Memory uses other builder, but that can be changes later
|
||||||
auto cost = _builder.CreateMul(_additionalMemoryInWords, Constant::get(static_cast<uint64_t>(FeeStructure::c_memoryGas)), "memcost");
|
auto cost = _builder.CreateMul(_additionalMemoryInWords, Constant::get(static_cast<uint64_t>(c_memoryGas)), "memcost");
|
||||||
_builder.CreateCall(m_gasCheckFunc, cost);
|
_builder.CreateCall(m_gasCheckFunc, cost);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
#include "Type.h"
|
#include "Type.h"
|
||||||
#include "Runtime.h"
|
#include "Runtime.h"
|
||||||
#include "GasMeter.h"
|
#include "GasMeter.h"
|
||||||
|
#include "Endianness.h"
|
||||||
|
|
||||||
namespace dev
|
namespace dev
|
||||||
{
|
{
|
||||||
|
|
@ -117,12 +118,15 @@ llvm::Function* Memory::createFunc(bool _isStore, llvm::Type* _valueType, GasMet
|
||||||
{
|
{
|
||||||
llvm::Value* value = ++func->arg_begin();
|
llvm::Value* value = ++func->arg_begin();
|
||||||
value->setName("value");
|
value->setName("value");
|
||||||
|
if (isWord)
|
||||||
|
value = Endianness::toBE(m_builder, value);
|
||||||
m_builder.CreateStore(value, ptr);
|
m_builder.CreateStore(value, ptr);
|
||||||
m_builder.CreateRetVoid();
|
m_builder.CreateRetVoid();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto ret = m_builder.CreateLoad(ptr);
|
llvm::Value* ret = m_builder.CreateLoad(ptr);
|
||||||
|
ret = Endianness::toNative(m_builder, ret);
|
||||||
m_builder.CreateRet(ret);
|
m_builder.CreateRet(ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue