#ifndef EMPATHY_EXECUTE_VM_H
#define EMPATHY_EXECUTE_VM_H
namespace empathy::execute
{
class VM
{
public:
optional< Value > execute( CFG& cfg );
optional< Value > execute( ptr< BasicBlock > bb );
optional< Value > execute( const llr::Instruction& instr );
optional< Value > execute( const ptr< CFG >& ic );
optional< Value > execute( const llr::GetArg& ga );
optional< Value > execute( const llr::Call& call );
optional< Value > execute( const llr::CreateTemporary& ct );
optional< Value > execute( const llr::GetTemporary& gt );
optional< Value > execute( const llr::Phi& p );
optional< Value > execute( const llr::And& bo );
optional< Value > execute( const llr::Or& bo );
optional< Value > execute( const llr::Xor& bo );
optional< Value > execute( const llr::Shl& bo );
optional< Value > execute( const llr::LShr& bo );
optional< Value > execute( const llr::AShr& bo );
template< typename T >
optional< Value > execute( const T& )
{
return nullopt;
}
ptr< BasicBlock > execute( const llr::Terminator& terminator );
ptr< BasicBlock > execute( const llr::Ret& r );
ptr< BasicBlock > execute( const llr::Branch& b );
ptr< BasicBlock > execute( const llr::CondBranch& cb );
private:
static optional< Value > ExecuteBuiltinFuncCall( const Value& func, const Term& args );
template< typename F >
optional< Value > executeLogicBinOp( const llr::BinaryOp& bo, F&& func );
template< typename F >
optional< Value > executeBinOp( const llr::BinaryOp& bo, F&& func );
Frame m_frame;
// Used to interpret Phi instructions.
ptr< BasicBlock > m_pPreviousBB;
// To avoid compile time code to get stuck, we have a limitation on the
// total number of call and loop instructions that we are willing to execute
// before giving up.
static uint32_t ms_remainingBranchInstExecutions;
};
}
#endif