|
|
@ -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<llvm::Module> 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<llvm::Module> 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<ProgramCounter, BasicBlock> basicBlocks; |
|
|
|
/// Maps a program counter pc to a basic block that starts at pc (if any).
|
|
|
|
std::map<ProgramCounter, BasicBlock> basicBlocks = {}; |
|
|
|
|
|
|
|
/**
|
|
|
|
* Maps a pc at which there is a JUMP or JUMPI to the target block of the jump. |
|
|
|
*/ |
|
|
|
std::map<ProgramCounter, llvm::BasicBlock*> m_directJumpTargets; |
|
|
|
/// Maps a pc at which there is a JUMP or JUMPI to the target block of the jump.
|
|
|
|
std::map<ProgramCounter, llvm::BasicBlock*> m_directJumpTargets = {}; |
|
|
|
|
|
|
|
/**
|
|
|
|
* A list of possible blocks to which there may be indirect jumps. |
|
|
|
*/ |
|
|
|
std::vector<BasicBlock*> m_indirectJumpTargets; |
|
|
|
/// A list of possible blocks to which there may be indirect jumps.
|
|
|
|
std::vector<BasicBlock*> m_indirectJumpTargets = {}; |
|
|
|
|
|
|
|
/// Stop basic block - terminates execution with STOP code (0)
|
|
|
|
llvm::BasicBlock* m_stopBB = nullptr; |
|
|
|
|
|
|
|
/**
|
|
|
|
* Block with a jump table. |
|
|
|
*/ |
|
|
|
std::unique_ptr<BasicBlock> m_jumpTableBlock; |
|
|
|
/// Block with a jump table.
|
|
|
|
std::unique_ptr<BasicBlock> m_jumpTableBlock = nullptr; |
|
|
|
|
|
|
|
/**
|
|
|
|
* Default destination for indirect jumps. |
|
|
|
*/ |
|
|
|
std::unique_ptr<BasicBlock> m_badJumpBlock; |
|
|
|
/// Default destination for indirect jumps.
|
|
|
|
std::unique_ptr<BasicBlock> m_badJumpBlock = nullptr; |
|
|
|
|
|
|
|
/// Main program function
|
|
|
|
llvm::Function* m_mainFunc = nullptr; |
|
|
|