mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-21 04:06:44 +00:00
Merge branch 'develop-evmcc' of github.com:imapp-pl/ethereum into develop-evmcc
This commit is contained in:
commit
59a392c1c2
5 changed files with 33 additions and 13 deletions
|
|
@ -6,7 +6,7 @@
|
||||||
#include <llvm/IR/IRBuilder.h>
|
#include <llvm/IR/IRBuilder.h>
|
||||||
#include <llvm/IR/CFG.h>
|
#include <llvm/IR/CFG.h>
|
||||||
#include <llvm/ADT/PostOrderIterator.h>
|
#include <llvm/ADT/PostOrderIterator.h>
|
||||||
//#include <llvm/Transforms/Scalar.h>
|
#include <llvm/IR/IntrinsicInst.h>
|
||||||
|
|
||||||
#include <libevmface/Instruction.h>
|
#include <libevmface/Instruction.h>
|
||||||
|
|
||||||
|
|
@ -159,6 +159,7 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode)
|
||||||
m_finalBlock = std::make_unique<BasicBlock>("FinalBlock", m_mainFunc);
|
m_finalBlock = std::make_unique<BasicBlock>("FinalBlock", m_mainFunc);
|
||||||
m_badJumpBlock = std::make_unique<BasicBlock>("BadJumpBlock", m_mainFunc);
|
m_badJumpBlock = std::make_unique<BasicBlock>("BadJumpBlock", m_mainFunc);
|
||||||
m_jumpTableBlock = std::make_unique<BasicBlock>("JumpTableBlock", m_mainFunc);
|
m_jumpTableBlock = std::make_unique<BasicBlock>("JumpTableBlock", m_mainFunc);
|
||||||
|
m_outOfGasBlock = std::make_unique<BasicBlock>("OutOfGas", m_mainFunc);
|
||||||
|
|
||||||
for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it)
|
for (auto it = directJumpTargets.cbegin(); it != directJumpTargets.cend(); ++it)
|
||||||
{
|
{
|
||||||
|
|
@ -195,15 +196,25 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
||||||
// Create the basic blocks.
|
// Create the basic blocks.
|
||||||
auto entryBlock = llvm::BasicBlock::Create(context, "entry", m_mainFunc);
|
auto entryBlock = llvm::BasicBlock::Create(context, "entry", m_mainFunc);
|
||||||
builder.SetInsertPoint(entryBlock);
|
builder.SetInsertPoint(entryBlock);
|
||||||
|
|
||||||
createBasicBlocks(bytecode);
|
createBasicBlocks(bytecode);
|
||||||
|
|
||||||
|
// Prepare jump buffer
|
||||||
|
auto jmpBufStorageTy = llvm::ArrayType::get(Type::Byte, 2048);
|
||||||
|
auto jmpBufStorage = new llvm::GlobalVariable(*module, jmpBufStorageTy, false, llvm::GlobalVariable::PrivateLinkage, llvm::ConstantAggregateZero::get(jmpBufStorageTy), "jmpBuf");
|
||||||
|
jmpBufStorage->setAlignment(16);
|
||||||
|
auto jmpBuf = builder.CreateConstInBoundsGEP2_32(jmpBufStorage, 0, 0);
|
||||||
|
|
||||||
// Init runtime structures.
|
// Init runtime structures.
|
||||||
GasMeter gasMeter(builder, module.get());
|
GasMeter gasMeter(builder, module.get(), jmpBuf);
|
||||||
Memory memory(builder, module.get(), gasMeter);
|
Memory memory(builder, module.get(), gasMeter);
|
||||||
Ext ext(builder, module.get());
|
Ext ext(builder, module.get());
|
||||||
|
|
||||||
// Jump to first instruction
|
// Create exception landing with setjmp and jump to first instruction
|
||||||
builder.CreateBr(basicBlocks.begin()->second);
|
auto setjmpFunc = llvm::Intrinsic::getDeclaration(module.get(), llvm::Intrinsic::eh_sjlj_setjmp);
|
||||||
|
auto setjmpRet = builder.CreateCall(setjmpFunc, jmpBuf);
|
||||||
|
auto isNormalFlow = builder.CreateICmpEQ(setjmpRet, builder.getInt32(0));
|
||||||
|
builder.CreateCondBr(isNormalFlow, basicBlocks.begin()->second, m_outOfGasBlock->llvm());
|
||||||
|
|
||||||
for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt)
|
for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt)
|
||||||
{
|
{
|
||||||
|
|
@ -939,10 +950,12 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
||||||
builder.SetInsertPoint(m_finalBlock->llvm());
|
builder.SetInsertPoint(m_finalBlock->llvm());
|
||||||
builder.CreateRet(Constant::get(ReturnCode::Stop));
|
builder.CreateRet(Constant::get(ReturnCode::Stop));
|
||||||
|
|
||||||
// TODO: throw an exception or something
|
|
||||||
builder.SetInsertPoint(m_badJumpBlock->llvm());
|
builder.SetInsertPoint(m_badJumpBlock->llvm());
|
||||||
builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination));
|
builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination));
|
||||||
|
|
||||||
|
builder.SetInsertPoint(m_outOfGasBlock->llvm());
|
||||||
|
builder.CreateRet(Constant::get(ReturnCode::OutOfGas));
|
||||||
|
|
||||||
builder.SetInsertPoint(m_jumpTableBlock->llvm());
|
builder.SetInsertPoint(m_jumpTableBlock->llvm());
|
||||||
if (m_indirectJumpTargets.size() > 0)
|
if (m_indirectJumpTargets.size() > 0)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,8 @@ private:
|
||||||
*/
|
*/
|
||||||
std::unique_ptr<BasicBlock> m_badJumpBlock;
|
std::unique_ptr<BasicBlock> m_badJumpBlock;
|
||||||
|
|
||||||
|
std::unique_ptr<BasicBlock> m_outOfGasBlock;
|
||||||
|
|
||||||
/// Main program function
|
/// Main program function
|
||||||
llvm::Function* m_mainFunc = nullptr;
|
llvm::Function* m_mainFunc = nullptr;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,9 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
|
||||||
for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it)
|
for (auto it = returnData.begin(), end = returnData.end(); it != end; ++it)
|
||||||
std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)*it << " ";
|
std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)*it << " ";
|
||||||
std::cout << "]\n";
|
std::cout << "]\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::cout << "RETURN CODE: " << (int)returnCode << std::endl;
|
||||||
return static_cast<int>(returnCode);
|
return static_cast<int>(returnCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <llvm/IR/GlobalVariable.h>
|
#include <llvm/IR/GlobalVariable.h>
|
||||||
#include <llvm/IR/Function.h>
|
#include <llvm/IR/Function.h>
|
||||||
|
#include <llvm/IR/IntrinsicInst.h>
|
||||||
|
|
||||||
#include <libevmface/Instruction.h>
|
#include <libevmface/Instruction.h>
|
||||||
#include <libevm/FeeStructure.h>
|
#include <libevm/FeeStructure.h>
|
||||||
|
|
@ -77,7 +78,7 @@ bool isCostBlockEnd(Instruction _inst)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module):
|
GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module, llvm::Value* _jmpBuf) :
|
||||||
m_builder(_builder)
|
m_builder(_builder)
|
||||||
{
|
{
|
||||||
m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas");
|
m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas");
|
||||||
|
|
@ -88,9 +89,9 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module):
|
||||||
m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", _module);
|
m_gasCheckFunc = llvm::Function::Create(llvm::FunctionType::get(Type::Void, Type::i256, false), llvm::Function::PrivateLinkage, "gas.check", _module);
|
||||||
InsertPointGuard guard(m_builder);
|
InsertPointGuard guard(m_builder);
|
||||||
|
|
||||||
auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "check", m_gasCheckFunc);
|
auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "Check", m_gasCheckFunc);
|
||||||
auto outOfGasBB = llvm::BasicBlock::Create(_builder.getContext(), "outOfGas", m_gasCheckFunc);
|
auto outOfGasBB = llvm::BasicBlock::Create(_builder.getContext(), "OutOfGas", m_gasCheckFunc);
|
||||||
auto updateBB = llvm::BasicBlock::Create(_builder.getContext(), "update", m_gasCheckFunc);
|
auto updateBB = llvm::BasicBlock::Create(_builder.getContext(), "Update", m_gasCheckFunc);
|
||||||
|
|
||||||
m_builder.SetInsertPoint(checkBB);
|
m_builder.SetInsertPoint(checkBB);
|
||||||
llvm::Value* cost = m_gasCheckFunc->arg_begin();
|
llvm::Value* cost = m_gasCheckFunc->arg_begin();
|
||||||
|
|
@ -100,8 +101,10 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module):
|
||||||
m_builder.CreateCondBr(isOutOfGas, outOfGasBB, updateBB);
|
m_builder.CreateCondBr(isOutOfGas, outOfGasBB, updateBB);
|
||||||
|
|
||||||
m_builder.SetInsertPoint(outOfGasBB);
|
m_builder.SetInsertPoint(outOfGasBB);
|
||||||
m_builder.CreateCall(m_rtExit, Constant::get(ReturnCode::OutOfGas));
|
|
||||||
m_builder.CreateRetVoid();
|
auto longjmpFunc = llvm::Intrinsic::getDeclaration(_module, llvm::Intrinsic::eh_sjlj_longjmp);
|
||||||
|
m_builder.CreateCall(longjmpFunc, _jmpBuf);
|
||||||
|
m_builder.CreateUnreachable();
|
||||||
|
|
||||||
m_builder.SetInsertPoint(updateBB);
|
m_builder.SetInsertPoint(updateBB);
|
||||||
gas = m_builder.CreateSub(gas, cost);
|
gas = m_builder.CreateSub(gas, cost);
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ namespace evmcc
|
||||||
class GasMeter
|
class GasMeter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* module);
|
GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module, llvm::Value* _jmpBuf);
|
||||||
|
|
||||||
GasMeter(const GasMeter&) = delete;
|
GasMeter(const GasMeter&) = delete;
|
||||||
void operator=(GasMeter) = delete;
|
void operator=(GasMeter) = delete;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue