diff --git a/evmcc/Compiler.cpp b/evmcc/Compiler.cpp index 4b22c0241..796db093e 100644 --- a/evmcc/Compiler.cpp +++ b/evmcc/Compiler.cpp @@ -61,6 +61,7 @@ llvm::BasicBlock* Compiler::getOrCreateBasicBlockAtPC(ProgramCounter pc) void Compiler::createBasicBlocks(const dev::bytes& bytecode) { getOrCreateBasicBlockAtPC(0); + getOrCreateBasicBlockAtPC(bytecode.size()); for (auto curr = bytecode.cbegin(); curr != bytecode.cend(); ++curr) { @@ -147,6 +148,18 @@ void Compiler::createBasicBlocks(const dev::bytes& bytecode) 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: break; } @@ -178,12 +191,9 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) auto memory = Memory(builder, module.get()); auto ext = Ext(builder, module.get()); - auto userRet = false; - auto finished = false; - 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; @@ -286,6 +296,15 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) 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: { auto lhs = stack.pop(); @@ -306,6 +325,36 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) 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: { auto top = stack.pop(); @@ -682,36 +731,32 @@ std::unique_ptr Compiler::compile(const dev::bytes& bytecode) ret = builder.CreateOr(ret, size); builder.CreateRet(ret); - finished = true; - userRet = true; + currentBlock = nullptr; break; } case Instruction::STOP: { - finished = true; + builder.CreateRet(builder.getInt64(0)); + currentBlock = nullptr; break; } } } - // Generate final basic block (may be jumped to). + // Generate the final basic block. auto finalPC = bytecode.size(); auto it = basicBlocks.find(finalPC); - if (it != basicBlocks.end()) - { - auto finalBlock = it->second; + assert(it != basicBlocks.end()); + auto finalBlock = it->second; - if (currentBlock != nullptr) - builder.CreateBr(finalBlock); - - mainFunc->getBasicBlockList().push_back(finalBlock); - builder.SetInsertPoint(finalBlock); - } + if (currentBlock != nullptr) + builder.CreateBr(finalBlock); - if (!userRet) - builder.CreateRet(builder.getInt64(0)); + mainFunc->getBasicBlockList().push_back(finalBlock); + builder.SetInsertPoint(finalBlock); + builder.CreateRet(builder.getInt64(0)); return module; } diff --git a/evmcc/bytecode/return1.evm b/evmcc/bytecode/return1.evm new file mode 100644 index 000000000..8092cb007 --- /dev/null +++ b/evmcc/bytecode/return1.evm @@ -0,0 +1 @@ +600160805460006080530b601b59600160005460206000f2602a58602760005460206000f26002608054 diff --git a/evmcc/lll/return1.lll b/evmcc/lll/return1.lll new file mode 100644 index 000000000..159d15ca3 --- /dev/null +++ b/evmcc/lll/return1.lll @@ -0,0 +1,6 @@ +;; code should return 39 +;; i should remain 1 +{ + [i] 1 + ( if (> @i 0) { (return 39) [i] 2 } (return 1) ) +} \ No newline at end of file