diff --git a/libevmjit/Compiler.cpp b/libevmjit/Compiler.cpp index d181f0191..39c9edc7c 100644 --- a/libevmjit/Compiler.cpp +++ b/libevmjit/Compiler.cpp @@ -758,8 +758,8 @@ void Compiler::compileBasicBlock(BasicBlock& _basicBlock, bytesConstRef _bytecod _gasMeter.commitCostBlock(gas); // Require memory for in and out buffers - memory.require(outOff, outSize); // Out buffer first as we guess it will be after the in one - memory.require(inOff, inSize); + _memory.require(outOff, outSize); // Out buffer first as we guess it will be after the in one + _memory.require(inOff, inSize); auto receiveAddress = codeAddress; if (inst == Instruction::CALLCODE) diff --git a/libevmjit/Compiler.h b/libevmjit/Compiler.h index d58745a06..12b7f6e0e 100644 --- a/libevmjit/Compiler.h +++ b/libevmjit/Compiler.h @@ -18,55 +18,70 @@ class Compiler { public: - using ProgramCounter = uint64_t; + struct Options + { + /// Optimize stack operations between basic blocks + bool optimizeStack; + + /// Rewrite switch instructions to sequences of branches + bool rewriteSwitchToBranches; - Compiler(); + /// Dump CFG as a .dot file for graphviz + bool dumpCFG; - std::unique_ptr compile(bytesConstRef bytecode); + Options(): + optimizeStack(true), + rewriteSwitchToBranches(true), + dumpCFG(false) + {} + }; + + using ProgramCounter = uint64_t; - void dumpBasicBlockGraph(std::ostream& out); + Compiler(Options const& _options); + std::unique_ptr compile(bytesConstRef _bytecode); private: - void createBasicBlocks(bytesConstRef bytecode); + void createBasicBlocks(bytesConstRef _bytecode); - void compileBasicBlock(BasicBlock& basicBlock, bytesConstRef bytecode, class RuntimeManager& _runtimeManager, class Arith256& arith, class Memory& memory, class Ext& ext, class GasMeter& gasMeter, llvm::BasicBlock* nextBasicBlock); + void compileBasicBlock(BasicBlock& _basicBlock, bytesConstRef _bytecode, class RuntimeManager& _runtimeManager, class Arith256& _arith, class Memory& _memory, class Ext& _ext, class GasMeter& _gasMeter, llvm::BasicBlock* _nextBasicBlock); void removeDeadBlocks(); - /// Dump all basic blocks to stderr. Useful in a debugging session. + /// Dumps basic block graph in graphviz format to a file, if option dumpCFG is enabled. + void dumpCFGifRequired(std::string const& _dotfilePath); + + /// Dumps basic block graph in graphviz format to a stream. + void dumpCFGtoStream(std::ostream& _out); + + /// Dumps all basic blocks to stderr. Useful in a debugging session. void dump(); + /// Compiler options + Options const& m_options; + + /// Helper class for generating IR llvm::IRBuilder<> m_builder; - /** - * Maps a program counter pc to a basic block that starts at pc (if any). - */ - std::map basicBlocks; + /// Maps a program counter pc to a basic block that starts at pc (if any). + std::map basicBlocks = {}; - /** - * Maps a pc at which there is a JUMP or JUMPI to the target block of the jump. - */ - std::map m_directJumpTargets; + /// Maps a pc at which there is a JUMP or JUMPI to the target block of the jump. + std::map m_directJumpTargets = {}; - /** - * A list of possible blocks to which there may be indirect jumps. - */ - std::vector m_indirectJumpTargets; + /// A list of possible blocks to which there may be indirect jumps. + std::vector m_indirectJumpTargets = {}; /// Stop basic block - terminates execution with STOP code (0) llvm::BasicBlock* m_stopBB = nullptr; - /** - * Block with a jump table. - */ - std::unique_ptr m_jumpTableBlock; + /// Block with a jump table. + std::unique_ptr m_jumpTableBlock = nullptr; - /** - * Default destination for indirect jumps. - */ - std::unique_ptr m_badJumpBlock; + /// Default destination for indirect jumps. + std::unique_ptr m_badJumpBlock = nullptr; /// Main program function llvm::Function* m_mainFunc = nullptr; diff --git a/libevmjit/VM.cpp b/libevmjit/VM.cpp index b42b09499..f60dbe783 100644 --- a/libevmjit/VM.cpp +++ b/libevmjit/VM.cpp @@ -16,7 +16,8 @@ namespace jit bytesConstRef VM::go(ExtVMFace& _ext, OnOpFunc const&, uint64_t) { - auto module = Compiler().compile(_ext.code); + Compiler::Options defaultOptions; + auto module = Compiler(defaultOptions).compile(_ext.code); ExecutionEngine engine; auto exitCode = engine.run(std::move(module), m_gas, &_ext);