mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-19 19:30:44 +00:00
- fixes for RETURN and STOP
- codegen for SLT, SGT, EQ and NEG
This commit is contained in:
parent
320add062e
commit
f075b7b227
3 changed files with 71 additions and 19 deletions
|
|
@ -61,6 +61,7 @@ llvm::BasicBlock* Compiler::getOrCreateBasicBlockAtPC(ProgramCounter pc)
|
||||||
void Compiler::createBasicBlocks(const dev::bytes& bytecode)
|
void Compiler::createBasicBlocks(const dev::bytes& bytecode)
|
||||||
{
|
{
|
||||||
getOrCreateBasicBlockAtPC(0);
|
getOrCreateBasicBlockAtPC(0);
|
||||||
|
getOrCreateBasicBlockAtPC(bytecode.size());
|
||||||
|
|
||||||
for (auto curr = bytecode.cbegin(); curr != bytecode.cend(); ++curr)
|
for (auto curr = bytecode.cbegin(); curr != bytecode.cend(); ++curr)
|
||||||
{
|
{
|
||||||
|
|
@ -147,6 +148,18 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode)
|
||||||
std::exit(1);
|
std::exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Instruction::RETURN:
|
||||||
|
case Instruction::STOP:
|
||||||
|
{
|
||||||
|
// Create a basic block starting at the following instruction.
|
||||||
|
if (curr + 1 < bytecode.cend())
|
||||||
|
{
|
||||||
|
ProgramCounter nextPC = (curr + 1 - bytecode.cbegin());
|
||||||
|
getOrCreateBasicBlockAtPC(nextPC);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -178,12 +191,9 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
||||||
auto memory = Memory(builder, module.get());
|
auto memory = Memory(builder, module.get());
|
||||||
auto ext = Ext(builder, module.get());
|
auto ext = Ext(builder, module.get());
|
||||||
|
|
||||||
auto userRet = false;
|
|
||||||
auto finished = false;
|
|
||||||
|
|
||||||
BasicBlock* currentBlock = entryBlock;
|
BasicBlock* currentBlock = entryBlock;
|
||||||
|
|
||||||
for (auto pc = bytecode.cbegin(); pc != bytecode.cend() && !finished; ++pc)
|
for (auto pc = bytecode.cbegin(); pc != bytecode.cend(); ++pc)
|
||||||
{
|
{
|
||||||
using dev::eth::Instruction;
|
using dev::eth::Instruction;
|
||||||
|
|
||||||
|
|
@ -286,6 +296,15 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Instruction::NEG:
|
||||||
|
{
|
||||||
|
auto top = stack.pop();
|
||||||
|
auto zero = ConstantInt::get(Types.word256, 0);
|
||||||
|
auto res = builder.CreateSub(zero, top);
|
||||||
|
stack.push(res);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Instruction::LT:
|
case Instruction::LT:
|
||||||
{
|
{
|
||||||
auto lhs = stack.pop();
|
auto lhs = stack.pop();
|
||||||
|
|
@ -306,6 +325,36 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Instruction::SLT:
|
||||||
|
{
|
||||||
|
auto lhs = stack.pop();
|
||||||
|
auto rhs = stack.pop();
|
||||||
|
auto res1 = builder.CreateICmpSLT(lhs, rhs);
|
||||||
|
auto res256 = builder.CreateZExt(res1, Types.word256);
|
||||||
|
stack.push(res256);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Instruction::SGT:
|
||||||
|
{
|
||||||
|
auto lhs = stack.pop();
|
||||||
|
auto rhs = stack.pop();
|
||||||
|
auto res1 = builder.CreateICmpSGT(lhs, rhs);
|
||||||
|
auto res256 = builder.CreateZExt(res1, Types.word256);
|
||||||
|
stack.push(res256);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case Instruction::EQ:
|
||||||
|
{
|
||||||
|
auto lhs = stack.pop();
|
||||||
|
auto rhs = stack.pop();
|
||||||
|
auto res1 = builder.CreateICmpEQ(lhs, rhs);
|
||||||
|
auto res256 = builder.CreateZExt(res1, Types.word256);
|
||||||
|
stack.push(res256);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Instruction::NOT:
|
case Instruction::NOT:
|
||||||
{
|
{
|
||||||
auto top = stack.pop();
|
auto top = stack.pop();
|
||||||
|
|
@ -682,36 +731,32 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode)
|
||||||
ret = builder.CreateOr(ret, size);
|
ret = builder.CreateOr(ret, size);
|
||||||
|
|
||||||
builder.CreateRet(ret);
|
builder.CreateRet(ret);
|
||||||
finished = true;
|
currentBlock = nullptr;
|
||||||
userRet = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case Instruction::STOP:
|
case Instruction::STOP:
|
||||||
{
|
{
|
||||||
finished = true;
|
builder.CreateRet(builder.getInt64(0));
|
||||||
|
currentBlock = nullptr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate final basic block (may be jumped to).
|
// Generate the final basic block.
|
||||||
auto finalPC = bytecode.size();
|
auto finalPC = bytecode.size();
|
||||||
auto it = basicBlocks.find(finalPC);
|
auto it = basicBlocks.find(finalPC);
|
||||||
if (it != basicBlocks.end())
|
assert(it != basicBlocks.end());
|
||||||
{
|
auto finalBlock = it->second;
|
||||||
auto finalBlock = it->second;
|
|
||||||
|
|
||||||
if (currentBlock != nullptr)
|
if (currentBlock != nullptr)
|
||||||
builder.CreateBr(finalBlock);
|
builder.CreateBr(finalBlock);
|
||||||
|
|
||||||
mainFunc->getBasicBlockList().push_back(finalBlock);
|
mainFunc->getBasicBlockList().push_back(finalBlock);
|
||||||
builder.SetInsertPoint(finalBlock);
|
builder.SetInsertPoint(finalBlock);
|
||||||
}
|
builder.CreateRet(builder.getInt64(0));
|
||||||
|
|
||||||
if (!userRet)
|
|
||||||
builder.CreateRet(builder.getInt64(0));
|
|
||||||
|
|
||||||
return module;
|
return module;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
1
evmcc/bytecode/return1.evm
Normal file
1
evmcc/bytecode/return1.evm
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
600160805460006080530b601b59600160005460206000f2602a58602760005460206000f26002608054
|
||||||
6
evmcc/lll/return1.lll
Normal file
6
evmcc/lll/return1.lll
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
;; code should return 39
|
||||||
|
;; i should remain 1
|
||||||
|
{
|
||||||
|
[i] 1
|
||||||
|
( if (> @i 0) { (return 39) [i] 2 } (return 1) )
|
||||||
|
}
|
||||||
Loading…
Reference in a new issue