Browse Source

Trying to implement "exceptions" with longjmp (does not work on Windows 64bit at least)

cl-refactor
Paweł Bylica 10 years ago
parent
commit
7fcf24d3ac
  1. 14
      evmcc/Compiler.cpp
  2. 4
      evmcc/ExecutionEngine.cpp
  3. 15
      evmcc/GasMeter.cpp
  4. 2
      evmcc/GasMeter.h

14
evmcc/Compiler.cpp

@ -199,16 +199,20 @@ 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());
GasMeter gasMeter(builder, module.get(), jmpBuf);
Memory memory(builder, module.get(), gasMeter);
Ext ext(builder, module.get());
// Jump to first instruction
// Create exception landing with setjmp and jump to first instruction
auto setjmpFunc = llvm::Intrinsic::getDeclaration(module.get(), llvm::Intrinsic::eh_sjlj_setjmp);
auto jmpBufTy = llvm::ArrayType::get(builder.getInt64Ty(), 5);
auto jmpBuf = new llvm::GlobalVariable(*module, jmpBufTy, false, llvm::GlobalVariable::PrivateLinkage, llvm::UndefValue::get(jmpBufTy), "jmpBuf");
auto setjmpRet = builder.CreateCall(setjmpFunc, builder.CreateBitCast(jmpBuf, Type::BytePtr));
auto setjmpRet = builder.CreateCall(setjmpFunc, jmpBuf);
auto isNormalFlow = builder.CreateICmpEQ(setjmpRet, builder.getInt32(0));
builder.CreateCondBr(isNormalFlow, basicBlocks.begin()->second, m_outOfGasBlock->llvm());

4
evmcc/ExecutionEngine.cpp

@ -121,7 +121,9 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
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 << "]\n";
}
}
std::cout << "RETURN CODE: " << (int)returnCode << std::endl;
return static_cast<int>(returnCode);
}

15
evmcc/GasMeter.cpp

@ -3,6 +3,7 @@
#include <llvm/IR/GlobalVariable.h>
#include <llvm/IR/Function.h>
#include <llvm/IR/IntrinsicInst.h>
#include <libevmface/Instruction.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_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);
InsertPointGuard guard(m_builder);
auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "check", m_gasCheckFunc);
auto outOfGasBB = llvm::BasicBlock::Create(_builder.getContext(), "outOfGas", m_gasCheckFunc);
auto updateBB = llvm::BasicBlock::Create(_builder.getContext(), "update", m_gasCheckFunc);
auto checkBB = llvm::BasicBlock::Create(_builder.getContext(), "Check", m_gasCheckFunc);
auto outOfGasBB = llvm::BasicBlock::Create(_builder.getContext(), "OutOfGas", m_gasCheckFunc);
auto updateBB = llvm::BasicBlock::Create(_builder.getContext(), "Update", m_gasCheckFunc);
m_builder.SetInsertPoint(checkBB);
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.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);
gas = m_builder.CreateSub(gas, cost);

2
evmcc/GasMeter.h

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

Loading…
Cancel
Save