mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-20 03:36:44 +00:00
Change the way compiled program returns
This commit is contained in:
parent
8fb6de09e4
commit
7a89751433
4 changed files with 45 additions and 57 deletions
|
|
@ -190,10 +190,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
|||
IRBuilder<> builder(context);
|
||||
|
||||
// Create main function
|
||||
const auto i32Ty = builder.getInt32Ty();
|
||||
//Type* retTypeElems[] = {i32Ty, i32Ty};
|
||||
//auto retType = StructType::create(retTypeElems, "MemRef", true);
|
||||
m_mainFunc = Function::Create(FunctionType::get(builder.getInt64Ty(), false), Function::ExternalLinkage, "main", module.get());
|
||||
m_mainFunc = Function::Create(FunctionType::get(Type::MainReturn, false), Function::ExternalLinkage, "main", module.get());
|
||||
|
||||
// Create the basic blocks.
|
||||
auto entryBlock = llvm::BasicBlock::Create(context, "entry", m_mainFunc);
|
||||
|
|
@ -797,13 +794,9 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
|||
auto index = stack.pop();
|
||||
auto size = stack.pop();
|
||||
|
||||
auto ret = builder.CreateTrunc(index, builder.getInt64Ty());
|
||||
ret = builder.CreateShl(ret, 32);
|
||||
size = builder.CreateTrunc(size, i32Ty);
|
||||
size = builder.CreateZExt(size, builder.getInt64Ty());
|
||||
ret = builder.CreateOr(ret, size);
|
||||
memory.registerReturnData(index, size);
|
||||
|
||||
builder.CreateRet(ret);
|
||||
builder.CreateRet(Constant::get(ReturnCode::Return));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -815,7 +808,7 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
|||
}
|
||||
case Instruction::STOP:
|
||||
{
|
||||
builder.CreateRet(builder.getInt64(0));
|
||||
builder.CreateRet(Constant::get(ReturnCode::Stop));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -847,11 +840,11 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
|||
// Note: Right now the codegen for special blocks depends only on createBasicBlock(),
|
||||
// not on the codegen for 'regular' blocks. But it has to be done before linkBasicBlocks().
|
||||
builder.SetInsertPoint(m_finalBlock->llvm());
|
||||
builder.CreateRet(builder.getInt64(0));
|
||||
builder.CreateRet(Constant::get(ReturnCode::Stop));
|
||||
|
||||
// TODO: throw an exception or something
|
||||
builder.SetInsertPoint(m_badJumpBlock->llvm());
|
||||
builder.CreateRet(builder.getInt64(0));
|
||||
builder.CreateRet(Constant::get(ReturnCode::BadJumpDestination));
|
||||
|
||||
builder.SetInsertPoint(m_jumpTableBlock->llvm());
|
||||
if (m_indirectJumpTargets.size() > 0)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@
|
|||
#include <llvm/Support/Host.h>
|
||||
|
||||
#include "Runtime.h"
|
||||
#include "Memory.h"
|
||||
#include "Type.h"
|
||||
|
||||
namespace evmcc
|
||||
{
|
||||
|
|
@ -97,13 +99,13 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
|
|||
|
||||
auto result = exec->runFunction(entryFunc, {});
|
||||
gas = static_cast<decltype(gas)>(Runtime::getGas());
|
||||
if (auto intResult = result.IntVal.getZExtValue())
|
||||
auto returnCode = static_cast<ReturnCode>(result.IntVal.getZExtValue());
|
||||
if (returnCode == ReturnCode::Return)
|
||||
{
|
||||
auto index = intResult >> 32;
|
||||
auto size = 0xFFFFFFFF & intResult;
|
||||
auto&& returnData = Memory::getReturnData();
|
||||
|
||||
std::cout << "RETURN [ ";
|
||||
for (dev::bytes::const_iterator it = Runtime::getMemory().cbegin() + index, end = it + size; 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 << "]\n";
|
||||
|
||||
|
|
|
|||
|
|
@ -21,20 +21,8 @@ namespace evmcc
|
|||
Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _gasMeter):
|
||||
m_builder(_builder)
|
||||
{
|
||||
auto voidTy = m_builder.getVoidTy();
|
||||
auto i64Ty = m_builder.getInt64Ty();
|
||||
|
||||
auto memRequireTy = llvm::FunctionType::get(m_builder.getInt8PtrTy(), i64Ty, false);
|
||||
m_memRequire = llvm::Function::Create(memRequireTy,
|
||||
llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
||||
"evmccrt_memory_require", _module);
|
||||
|
||||
auto memSizeTy = llvm::FunctionType::get(i64Ty, false);
|
||||
m_memSize = llvm::Function::Create(memSizeTy,
|
||||
llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
||||
"evmccrt_memory_size", _module);
|
||||
|
||||
std::vector<llvm::Type*> argTypes = {i64Ty, i64Ty};
|
||||
llvm::Type* argTypes[] = {i64Ty, i64Ty};
|
||||
auto dumpTy = llvm::FunctionType::get(m_builder.getVoidTy(), llvm::ArrayRef<llvm::Type*>(argTypes), false);
|
||||
m_memDump = llvm::Function::Create(dumpTy, llvm::GlobalValue::LinkageTypes::ExternalLinkage,
|
||||
"evmccrt_memory_dump", _module);
|
||||
|
|
@ -45,6 +33,12 @@ Memory::Memory(llvm::IRBuilder<>& _builder, llvm::Module* _module, GasMeter& _ga
|
|||
m_size = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::PrivateLinkage, m_builder.getIntN(256, 0), "mem.size");
|
||||
m_size->setUnnamedAddr(true); // Address is not important
|
||||
|
||||
m_returnDataOffset = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataOffset");
|
||||
m_returnDataOffset->setUnnamedAddr(true); // Address is not important
|
||||
|
||||
m_returnDataSize = new llvm::GlobalVariable(*_module, Type::i256, false, llvm::GlobalVariable::ExternalLinkage, nullptr, "mem_returnDataSize");
|
||||
m_returnDataSize->setUnnamedAddr(true); // Address is not important
|
||||
|
||||
m_resize = llvm::Function::Create(llvm::FunctionType::get(Type::BytePtr, Type::WordPtr, false), llvm::Function::ExternalLinkage, "mem_resize", _module);
|
||||
m_loadWord = createFunc(false, Type::i256, _module, _gasMeter);
|
||||
m_storeWord = createFunc(true, Type::i256, _module, _gasMeter);
|
||||
|
|
@ -137,6 +131,12 @@ llvm::Value* Memory::getSize()
|
|||
return m_builder.CreateLoad(m_size);
|
||||
}
|
||||
|
||||
void Memory::registerReturnData(llvm::Value* _index, llvm::Value* _size)
|
||||
{
|
||||
m_builder.CreateStore(_index, m_returnDataOffset);
|
||||
m_builder.CreateStore(_size, m_returnDataSize);
|
||||
}
|
||||
|
||||
void Memory::dump(uint64_t _begin, uint64_t _end)
|
||||
{
|
||||
if (getenv("EVMCC_DEBUG_MEMORY") == nullptr)
|
||||
|
|
@ -155,6 +155,9 @@ extern "C"
|
|||
{
|
||||
using namespace evmcc;
|
||||
|
||||
EXPORT i256 mem_returnDataOffset;
|
||||
EXPORT i256 mem_returnDataSize;
|
||||
|
||||
EXPORT uint8_t* mem_resize(i256* _size)
|
||||
{
|
||||
auto size = _size->a; // Trunc to 64-bit
|
||||
|
|
@ -163,37 +166,13 @@ EXPORT uint8_t* mem_resize(i256* _size)
|
|||
return memory.data();
|
||||
}
|
||||
|
||||
// Resizes memory to contain at least _index + 1 bytes and returns the base address.
|
||||
EXPORT uint8_t* evmccrt_memory_require(uint64_t _index)
|
||||
{
|
||||
uint64_t requiredSize = (_index / 32 + 1) * 32;
|
||||
auto&& memory = Runtime::getMemory();
|
||||
|
||||
if (memory.size() < requiredSize)
|
||||
{
|
||||
std::cerr << "MEMORY: current size: " << std::dec
|
||||
<< memory.size() << " bytes, required size: "
|
||||
<< requiredSize << " bytes"
|
||||
<< std::endl;
|
||||
|
||||
memory.resize(requiredSize);
|
||||
}
|
||||
|
||||
return memory.data();
|
||||
}
|
||||
|
||||
EXPORT uint64_t evmccrt_memory_size()
|
||||
{
|
||||
return Runtime::getMemory().size() / 32;
|
||||
}
|
||||
|
||||
EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end)
|
||||
{
|
||||
if (_end == 0)
|
||||
_end = Runtime::getMemory().size();
|
||||
|
||||
std::cerr << "MEMORY: active size: " << std::dec
|
||||
<< evmccrt_memory_size() << " words\n";
|
||||
<< Runtime::getMemory().size() / 32 << " words\n";
|
||||
std::cerr << "MEMORY: dump from " << std::dec
|
||||
<< _begin << " to " << _end << ":";
|
||||
if (_end <= _begin)
|
||||
|
|
@ -212,3 +191,12 @@ EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end)
|
|||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
dev::bytesConstRef evmcc::Memory::getReturnData()
|
||||
{
|
||||
// TODO: Handle large indexes
|
||||
auto offset = static_cast<size_t>(llvm2eth(mem_returnDataOffset));
|
||||
auto size = static_cast<size_t>(llvm2eth(mem_returnDataSize));
|
||||
auto& memory = Runtime::getMemory();
|
||||
return {memory.data() + offset, size};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ public:
|
|||
void storeByte(llvm::Value* _addr, llvm::Value* _byte);
|
||||
llvm::Value* getSize();
|
||||
|
||||
void registerReturnData(llvm::Value* _index, llvm::Value* _size);
|
||||
static dev::bytesConstRef getReturnData();
|
||||
|
||||
void dump(uint64_t _begin, uint64_t _end = 0);
|
||||
|
||||
private:
|
||||
|
|
@ -31,14 +34,16 @@ private:
|
|||
llvm::GlobalVariable* m_data;
|
||||
llvm::GlobalVariable* m_size;
|
||||
|
||||
/// @TODO: m_data and m_size could be used
|
||||
llvm::GlobalVariable* m_returnDataOffset;
|
||||
llvm::GlobalVariable* m_returnDataSize;
|
||||
|
||||
llvm::Function* m_loadWord;
|
||||
llvm::Function* m_storeWord;
|
||||
llvm::Function* m_storeByte;
|
||||
llvm::Function* m_resize;
|
||||
|
||||
llvm::Function* m_memRequire;
|
||||
llvm::Function* m_memDump;
|
||||
llvm::Function* m_memSize;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue