Browse Source

Working longjmp solution

[#80660432]
cl-refactor
Paweł Bylica 10 years ago
parent
commit
ec2013d5c9
  1. 14
      evmcc/Compiler.cpp
  2. 16
      evmcc/ExecutionEngine.cpp
  3. 9
      evmcc/GasMeter.cpp
  4. 2
      evmcc/GasMeter.h

14
evmcc/Compiler.cpp

@ -199,22 +199,12 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& 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.
GasMeter gasMeter(builder, module.get(), jmpBuf);
GasMeter gasMeter(builder, module.get());
Memory memory(builder, module.get(), gasMeter);
Ext ext(builder, module.get());
// Create exception landing with setjmp and jump to first instruction
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());
builder.CreateBr(basicBlocks.begin()->second);
for (auto basicBlockPairIt = basicBlocks.begin(); basicBlockPairIt != basicBlocks.end(); ++basicBlockPairIt)
{

16
evmcc/ExecutionEngine.cpp

@ -1,6 +1,8 @@
#include "ExecutionEngine.h"
#include <csetjmp>
#include <llvm/IR/LLVMContext.h>
#include <llvm/IR/Module.h>
#include <llvm/ADT/Triple.h>
@ -27,6 +29,8 @@ ExecutionEngine::ExecutionEngine()
}
extern "C" { EXPORT std::jmp_buf* rt_jmpBuf; }
int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
{
@ -101,17 +105,17 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
exit(1);
}
ReturnCode returnCode;
try
std::jmp_buf buf;
auto r = setjmp(buf);
if (r == 0)
{
rt_jmpBuf = &buf;
auto result = exec->runFunction(entryFunc, {});
returnCode = static_cast<ReturnCode>(result.IntVal.getZExtValue());
}
catch (const dev::eth::OutOfGas&)
{
returnCode = ReturnCode::OutOfGas;
}
else
returnCode = static_cast<ReturnCode>(r);
gas = static_cast<decltype(gas)>(Runtime::getGas());

9
evmcc/GasMeter.cpp

@ -78,7 +78,7 @@ bool isCostBlockEnd(Instruction _inst)
}
GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module, llvm::Value* _jmpBuf) :
GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module) :
m_builder(_builder)
{
m_gas = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "gas");
@ -102,8 +102,11 @@ GasMeter::GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module, llvm::Val
m_builder.SetInsertPoint(outOfGasBB);
auto longjmpFunc = llvm::Intrinsic::getDeclaration(_module, llvm::Intrinsic::eh_sjlj_longjmp);
m_builder.CreateCall(longjmpFunc, _jmpBuf);
//auto longjmpFunc = llvm::Intrinsic::getDeclaration(_module, llvm::Intrinsic::eh_sjlj_longjmp);
auto extJmpBuf = new llvm::GlobalVariable(*_module, Type::BytePtr, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "rt_jmpBuf");
llvm::Type* args[] = {Type::BytePtr, m_builder.getInt32Ty()};
auto longjmpNative = llvm::Function::Create(llvm::FunctionType::get(Type::Void, args, false), llvm::Function::ExternalLinkage, "longjmp", _module);
m_builder.CreateCall2(longjmpNative, m_builder.CreateLoad(extJmpBuf), Constant::get(ReturnCode::OutOfGas));
m_builder.CreateUnreachable();
m_builder.SetInsertPoint(updateBB);

2
evmcc/GasMeter.h

@ -11,7 +11,7 @@ namespace evmcc
class GasMeter
{
public:
GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module, llvm::Value* _jmpBuf);
GasMeter(llvm::IRBuilder<>& _builder, llvm::Module* _module);
GasMeter(const GasMeter&) = delete;
void operator=(GasMeter) = delete;

Loading…
Cancel
Save