|
@ -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,25 +731,24 @@ 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) |
|
@ -708,9 +756,6 @@ std::unique_ptr<llvm::Module> Compiler::compile(const dev::bytes& bytecode) |
|
|
|
|
|
|
|
|
mainFunc->getBasicBlockList().push_back(finalBlock); |
|
|
mainFunc->getBasicBlockList().push_back(finalBlock); |
|
|
builder.SetInsertPoint(finalBlock); |
|
|
builder.SetInsertPoint(finalBlock); |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (!userRet) |
|
|
|
|
|
builder.CreateRet(builder.getInt64(0)); |
|
|
builder.CreateRet(builder.getInt64(0)); |
|
|
|
|
|
|
|
|
return module; |
|
|
return module; |
|
|