Browse Source

Implementing RETURN and STOP instructions

cl-refactor
Paweł Bylica 10 years ago
parent
commit
f41550077a
  1. 48
      evmcc/Compiler.cpp
  2. 10
      evmcc/ExecutionEngine.cpp
  3. 15
      evmcc/Memory.cpp
  4. 2
      evmcc/bytecode/ext_test.evm
  5. 5
      evmcc/lll/ext_test.lll

48
evmcc/Compiler.cpp

@ -49,7 +49,10 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
IRBuilder<> builder(context);
// Create main function
auto mainFuncType = FunctionType::get(llvm::Type::getInt32Ty(context), false);
const auto i32Ty = builder.getInt32Ty();
Type* retTypeElems[] = {i32Ty, i32Ty};
auto retType = StructType::create(retTypeElems, "MemRef", true);
auto mainFuncType = FunctionType::get(builder.getInt64Ty(), false);
auto mainFunc = Function::Create(mainFuncType, Function::ExternalLinkage, "main", module.get());
auto entryBlock = BasicBlock::Create(context, "entry", mainFunc);
@ -61,7 +64,9 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
auto ext = Ext(builder);
for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc)
auto userRet = false;
auto finished = false;
for (auto pc = bytecode.cbegin(); pc != bytecode.cend() && !finished; ++pc)
{
using dev::eth::Instruction;
@ -313,10 +318,47 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
break;
}
case Instruction::CODESIZE:
{
auto value = builder.getIntN(256, bytecode.size());
stack.push(value);
break;
}
case Instruction::RETURN:
{
auto index = stack.pop();
auto size = stack.pop();
// MCJIT does not support returning structs
//auto index32 = builder.CreateTrunc(index, i32Ty, "index32");
//auto size32 = builder.CreateTrunc(size, i32Ty, "size32");
//auto ret = builder.CreateInsertValue(UndefValue::get(retType), index32, 0, "ret");
//ret = builder.CreateInsertValue(ret, size32, 1, "ret");
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);
builder.CreateRet(ret);
finished = true;
userRet = true;
break;
}
case Instruction::STOP:
{
finished = true;
break;
}
}
}
builder.CreateRet(ConstantInt::get(Type::getInt32Ty(context), 0));
if (!userRet)
builder.CreateRet(builder.getInt64(0));
return module;
}

10
evmcc/ExecutionEngine.cpp

@ -86,8 +86,14 @@ int ExecutionEngine::run(std::unique_ptr<llvm::Module> _module)
}
auto result = exec->runFunction(entryFunc, {});
auto intResult = result.IntVal.getZExtValue();
return intResult;
if (auto intResult = result.IntVal.getZExtValue())
{
auto index = intResult >> 32;
auto size = 0xFFFFFFFF & intResult;
// TODO: Get the data from memory
return 10;
}
return 0;
}
}

15
evmcc/Memory.cpp

@ -10,6 +10,8 @@
#include <libdevcore/Common.h>
#include "Utils.h"
#ifdef _MSC_VER
#define EXPORT __declspec(dllexport)
#else
@ -19,15 +21,6 @@
namespace evmcc
{
struct i256
{
uint64_t a;
uint64_t b;
uint64_t c;
uint64_t d;
};
static_assert(sizeof(i256) == 32, "Wrong i256 size");
using MemoryImpl = dev::bytes;
@ -102,7 +95,7 @@ extern "C"
{
using namespace evmcc;
EXPORT MemoryImpl* evmccrt_memory;
static MemoryImpl* evmccrt_memory;
EXPORT void evmccrt_memory_create(void)
{
@ -121,7 +114,7 @@ EXPORT void* evmccrt_memory_require(uint64_t _size)
if (evmccrt_memory->size() < _size)
evmccrt_memory->resize(_size);
return &(*evmccrt_memory)[0];
return evmccrt_memory->data();
}
EXPORT void evmccrt_memory_dump(uint64_t _begin, uint64_t _end)

2
evmcc/bytecode/ext_test.evm

@ -1 +1 @@
30333234363a600035602635601335
30333234363a600035602635601335380060016002f2

5
evmcc/lll/ext_test.lll

@ -12,4 +12,9 @@ CALLDATALOAD
CALLDATALOAD
19
CALLDATALOAD
CODESIZE
STOP
1
2
RETURN
)
Loading…
Cancel
Save