#include #include namespace bast { struct infix_tag {}; struct infix_state { std::vector< bexpr_ptr > stack; void swap( int i, int j ) { std::swap( stack[ i ], stack[ j ] ); } void push( bexpr_ptr b ) { stack.push_back( b ); } bexpr_ptr &top() { return stack.back(); } const bexpr_ptr &top() const { return stack.back(); } void pop() { stack.pop_back(); } }; template< builtin_type t > struct op< std::enable_if_t< bitvec_type< t >::value, infix_tag >, t > { using state_t = infix_state; static step push_word( state_t &state, word w ) { auto l = brq::make_refcount< bexpr_node >( w ); state.push( l ); return next; } static step push_half( state_t &state, half h ) { return push_word( state, h ); } static step apply( state_t &state, word opcode ) { using namespace bast::opcodes; auto pop = [&]() { auto x = state.top(); state.pop(); return x; }; switch ( opcode ) { case gen_drop<>: pop(); break; case gen_dup<>: { auto a = pop(); state.push( a ); state.push( a ); break; } case bv_zero<>: { auto n = brq::make_refcount< bexpr_node >( 0 ); state.push( n ); break; } case bv_const<>: case bv_zext_b<>: case bv_zext_h<>: case bv_zext_w<>: case bv_sext_b<>: case bv_sext_h<>: case bv_sext_w<>: case bv_trunc_h<>: case bv_trunc_w<>: case bv_trunc_d<>: case bv_guard_zero<>: case bv_guard_nonzero<>: case bv_assert_zero<>: case bv_assert_nonzero<>: { auto a = pop(); auto n = brq::make_refcount< bexpr_node >( opcode, a ); state.push( n ); break; } case bv_add<>: case bv_sub<>: case bv_mul<>: case bv_sdiv<>: case bv_udiv<>: case bv_srem<>: case bv_urem<>: case bv_and<>: case bv_or<>: case bv_xor<>: case bv_neg<>: case bv_shl<>: case bv_lshr<>: case bv_ashr<>: case bv_eq<>: case bv_neq<>: case bv_ule<>: case bv_ult<>: case bv_ugt<>: case bv_uge<>: case bv_sle<>: case bv_slt<>: case bv_sgt<>: case bv_sge<>: { auto b = pop(), a = pop(); auto n = brq::make_refcount< bexpr_node >( opcode, a, b ); state.push( n ); break; } } return next; } }; using infix_eval = eval< infix_tag, infix_state, brq::unit_t >; } // namespace bast