diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 8c64c3fe2..5a84d32fc 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -199,22 +199,12 @@ std::unique_ptr 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) { diff --git a/evmcc/ExecutionEngine.cpp b/evmcc/ExecutionEngine.cpp index aeb720903..a5ed3681a 100644 --- a/evmcc/ExecutionEngine.cpp +++ b/evmcc/ExecutionEngine.cpp @@ -1,6 +1,8 @@ #include "ExecutionEngine.h" +#include + #include #include #include @@ -27,6 +29,8 @@ ExecutionEngine::ExecutionEngine() } +extern "C" { EXPORT std::jmp_buf* rt_jmpBuf; } + int ExecutionEngine::run(std::unique_ptr _module) { @@ -101,17 +105,17 @@ int ExecutionEngine::run(std::unique_ptr _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(result.IntVal.getZExtValue()); } - catch (const dev::eth::OutOfGas&) - { - returnCode = ReturnCode::OutOfGas; - } + else + returnCode = static_cast(r); gas = static_cast(Runtime::getGas()); diff --git a/evmcc/GasMeter.cpp b/evmcc/GasMeter.cpp index 0d0927563..adf7f407a 100644 --- a/evmcc/GasMeter.cpp +++ b/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); diff --git a/evmcc/GasMeter.h b/evmcc/GasMeter.h index 5af117900..099ce004e 100644 --- a/evmcc/GasMeter.h +++ b/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;