From 070693bd73b7f342175f86e18b10015d76b60fb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Can=20B=C3=B6l=C3=BCk?= Date: Fri, 31 Jul 2020 02:54:17 +0200 Subject: [PATCH] Minor changes. --- VTIL-Common/math/bitwise.hpp | 2 +- VTIL-Common/math/operable.hpp | 105 ++++++++++--------- VTIL-Common/util/reducable.hpp | 10 +- VTIL-Common/util/type_helpers.hpp | 2 + VTIL-SymEx/directives/directive.hpp | 7 +- VTIL-SymEx/expressions/expression.cpp | 4 +- VTIL-SymEx/expressions/unique_identifier.hpp | 2 +- 7 files changed, 69 insertions(+), 63 deletions(-) diff --git a/VTIL-Common/math/bitwise.hpp b/VTIL-Common/math/bitwise.hpp index 82e77f9..7ee651c 100644 --- a/VTIL-Common/math/bitwise.hpp +++ b/VTIL-Common/math/bitwise.hpp @@ -269,7 +269,7 @@ namespace vtil::math // namespace impl { - // For all N except 0 and 1: + // For all N except 0 / 1 / 64: // template struct integer_resizer diff --git a/VTIL-Common/math/operable.hpp b/VTIL-Common/math/operable.hpp index 85b7bbf..d33f781 100644 --- a/VTIL-Common/math/operable.hpp +++ b/VTIL-Common/math/operable.hpp @@ -61,7 +61,7 @@ namespace vtil::math // Default constructor and the constructor for constant values. // constexpr operable() = default; - template, int> = 0> + template constexpr operable( T value, bitcnt_t bit_count = sizeof( T ) * 8 ) : value( uint64_t( value ), bit_count ) {} // Gets the value represented, and nullopt if value has unknown bits. @@ -128,8 +128,8 @@ namespace vtil::math // Operable concepts. // - template concept CustomOperable = is_custom_operable_v>; - template concept Operable = is_operable_v>; + template concept CustomOperable = is_custom_operable_v>; + template concept Operable = is_operable_v>; // Returns the result of the cross-operation between two types, void if not cross-operable. // @@ -174,6 +174,13 @@ namespace vtil::math } return op; } + + // Declare a common building point for operables so that they can be hooked on demand. + // + template + __forceinline static constexpr R make_operable( T1&& a, math::operator_id op, T2&& b ) { return R{ std::forward( a ), op, std::forward( b ) }; } + template + __forceinline static constexpr R make_operable( math::operator_id op, T1&& a ) { return R{ op, std::forward( a ) }; } }; #undef __max // Seriously stdlib? @@ -182,8 +189,8 @@ namespace vtil::math // Evaluation operations with operable types. // #define DEFINE_EVAL(...) \ -template::type> \ -static constexpr result_t __VA_ARGS__ +template::type> \ +static constexpr R __VA_ARGS__ // Assignment operations with operable types. // - Result type is not used but left there to assert cross-operableness as an enable_if. @@ -192,50 +199,50 @@ static constexpr result_t __VA_ARGS__ template::type> \ static constexpr T1& assn_op ( T1& op, T2&& param ) { return ( op = eval_op ( std::move( op ), std::forward( param ) ) ); } -DEFINE_EVAL( operator~( T1&& a ) { return { vtil::math::operator_id::bitwise_not, std::forward( a ) }; } ); -DEFINE_EVAL( operator&( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::bitwise_and, std::forward( b ) }; } ); -DEFINE_EVAL( operator|( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::bitwise_or, std::forward( b ) }; } ); -DEFINE_EVAL( operator^( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::bitwise_xor, std::forward( b ) }; } ); -DEFINE_EVAL( operator>>( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::shift_right, std::forward( b ) }; } ); -DEFINE_EVAL( operator<<( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::shift_left, std::forward( b ) }; } ); -DEFINE_EVAL( __rotr( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::rotate_right, std::forward( b ) }; } ); -DEFINE_EVAL( __rotl( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::rotate_left, std::forward( b ) }; } ); -DEFINE_EVAL( operator-( T1&& a ) { return { vtil::math::operator_id::negate, std::forward( a ) }; } ); -DEFINE_EVAL( operator+( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::add, std::forward( b ) }; } ); -DEFINE_EVAL( operator-( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::subtract, std::forward( b ) }; } ); -DEFINE_EVAL( mulhi( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::multiply_high), std::forward( b ) }; }); -DEFINE_EVAL( operator*( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::multiply), std::forward( b ) }; } ); -DEFINE_EVAL( operator/( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::divide), std::forward( b ) }; } ); -DEFINE_EVAL( operator%( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::remainder), std::forward( b ) }; } ); -DEFINE_EVAL( umulhi( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::umultiply_high, std::forward( b ) }; } ); -DEFINE_EVAL( umul( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::umultiply, std::forward( b ) }; } ); -DEFINE_EVAL( udiv( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::udivide, std::forward( b ) }; } ); -DEFINE_EVAL( urem( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::uremainder, std::forward( b ) }; } ); -DEFINE_EVAL( __ucast( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::ucast, std::forward( b ) }; } ); -DEFINE_EVAL( __cast( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::cast, std::forward( b ) }; } ); -DEFINE_EVAL( __popcnt( T1&& a ) { return { vtil::math::operator_id::popcnt, std::forward( a ) }; } ); -DEFINE_EVAL( __bsf( T1&& a ) { return { vtil::math::operator_id::bitscan_fwd, std::forward( a ) }; } ); -DEFINE_EVAL( __bsr( T1&& a ) { return { vtil::math::operator_id::bitscan_rev, std::forward( a ) }; } ); -DEFINE_EVAL( __bt( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::bit_test, std::forward( b ) }; } ); -DEFINE_EVAL( __mask( T1&& a ) { return { vtil::math::operator_id::mask, std::forward( a ) }; } ); -DEFINE_EVAL( __bcnt( T1&& a ) { return { vtil::math::operator_id::bit_count, std::forward( a ) }; } ); -DEFINE_EVAL( __if( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::value_if, std::forward( b ) }; } ); -DEFINE_EVAL( __max( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::max_value), std::forward( b ) }; } ); -DEFINE_EVAL( __min( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::min_value), std::forward( b ) }; } ); -DEFINE_EVAL( __umax( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::umax_value, std::forward( b ) }; } ); -DEFINE_EVAL( __umin( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::umin_value, std::forward( b ) }; } ); -DEFINE_EVAL( operator>( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::greater), std::forward( b ) }; } ); -DEFINE_EVAL( operator>=( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::greater_eq), std::forward( b ) }; } ); -DEFINE_EVAL( operator==( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::equal), std::forward( b ) }; } ); -DEFINE_EVAL( operator!=( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::not_equal), std::forward( b ) }; } ); -DEFINE_EVAL( operator<=( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::less_eq), std::forward( b ) }; } ); -DEFINE_EVAL( operator<( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::less), std::forward( b ) }; } ); -DEFINE_EVAL( __ugreat( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::ugreater, std::forward( b ) }; } ); -DEFINE_EVAL( __ugreat_eq( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::ugreater_eq, std::forward( b ) }; } ); -DEFINE_EVAL( __uequal( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::uequal, std::forward( b ) }; } ); -DEFINE_EVAL( __unot_equal( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::unot_equal, std::forward( b ) }; } ); -DEFINE_EVAL( __uless_eq( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::uless_eq, std::forward( b ) }; } ); -DEFINE_EVAL( __uless( T1&& a, T2&& b ) { return { std::forward( a ), vtil::math::operator_id::uless, std::forward( b ) }; } ); +DEFINE_EVAL( operator~( T1&& a ) { return vtil::math::make_operable( vtil::math::operator_id::bitwise_not, std::forward( a ) ); } ); +DEFINE_EVAL( operator&( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::bitwise_and, std::forward( b ) ); } ); +DEFINE_EVAL( operator|( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::bitwise_or, std::forward( b ) ); } ); +DEFINE_EVAL( operator^( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::bitwise_xor, std::forward( b ) ); } ); +DEFINE_EVAL( operator>>( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::shift_right, std::forward( b ) ); } ); +DEFINE_EVAL( operator<<( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::shift_left, std::forward( b ) ); } ); +DEFINE_EVAL( __rotr( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::rotate_right, std::forward( b ) ); } ); +DEFINE_EVAL( __rotl( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::rotate_left, std::forward( b ) ); } ); +DEFINE_EVAL( operator-( T1&& a ) { return vtil::math::make_operable( vtil::math::operator_id::negate, std::forward( a ) ); } ); +DEFINE_EVAL( operator+( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::add, std::forward( b ) ); } ); +DEFINE_EVAL( operator-( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::subtract, std::forward( b ) ); } ); +DEFINE_EVAL( mulhi( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::multiply_high), std::forward( b ) ); }); +DEFINE_EVAL( operator*( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::multiply), std::forward( b ) ); } ); +DEFINE_EVAL( operator/( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::divide), std::forward( b ) ); } ); +DEFINE_EVAL( operator%( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::remainder), std::forward( b ) ); } ); +DEFINE_EVAL( umulhi( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::umultiply_high, std::forward( b ) ); } ); +DEFINE_EVAL( umul( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::umultiply, std::forward( b ) ); } ); +DEFINE_EVAL( udiv( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::udivide, std::forward( b ) ); } ); +DEFINE_EVAL( urem( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::uremainder, std::forward( b ) ); } ); +DEFINE_EVAL( __ucast( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::ucast, std::forward( b ) ); } ); +DEFINE_EVAL( __cast( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::cast, std::forward( b ) ); } ); +DEFINE_EVAL( __popcnt( T1&& a ) { return vtil::math::make_operable( vtil::math::operator_id::popcnt, std::forward( a ) ); } ); +DEFINE_EVAL( __bsf( T1&& a ) { return vtil::math::make_operable( vtil::math::operator_id::bitscan_fwd, std::forward( a ) ); } ); +DEFINE_EVAL( __bsr( T1&& a ) { return vtil::math::make_operable( vtil::math::operator_id::bitscan_rev, std::forward( a ) ); } ); +DEFINE_EVAL( __bt( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::bit_test, std::forward( b ) ); } ); +DEFINE_EVAL( __mask( T1&& a ) { return vtil::math::make_operable( vtil::math::operator_id::mask, std::forward( a ) ); } ); +DEFINE_EVAL( __bcnt( T1&& a ) { return vtil::math::make_operable( vtil::math::operator_id::bit_count, std::forward( a ) ); } ); +DEFINE_EVAL( __if( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::value_if, std::forward( b ) ); } ); +DEFINE_EVAL( __max( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::max_value), std::forward( b ) ); } ); +DEFINE_EVAL( __min( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::min_value), std::forward( b ) ); } ); +DEFINE_EVAL( __umax( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::umax_value, std::forward( b ) ); } ); +DEFINE_EVAL( __umin( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::umin_value, std::forward( b ) ); } ); +DEFINE_EVAL( operator>( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::greater), std::forward( b ) ); } ); +DEFINE_EVAL( operator>=( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::greater_eq), std::forward( b ) ); } ); +DEFINE_EVAL( operator==( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::equal), std::forward( b ) ); } ); +DEFINE_EVAL( operator!=( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::not_equal), std::forward( b ) ); } ); +DEFINE_EVAL( operator<=( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::less_eq), std::forward( b ) ); } ); +DEFINE_EVAL( operator<( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_hint_sign(vtil::math::operator_id::less), std::forward( b ) ); } ); +DEFINE_EVAL( __ugreat( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::ugreater, std::forward( b ) ); } ); +DEFINE_EVAL( __ugreat_eq( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::ugreater_eq, std::forward( b ) ); } ); +DEFINE_EVAL( __uequal( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::uequal, std::forward( b ) ); } ); +DEFINE_EVAL( __unot_equal( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::unot_equal, std::forward( b ) ); } ); +DEFINE_EVAL( __uless_eq( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::uless_eq, std::forward( b ) ); } ); +DEFINE_EVAL( __uless( T1&& a, T2&& b ) { return vtil::math::make_operable( std::forward( a ), vtil::math::operator_id::uless, std::forward( b ) ); } ); DEFINE_ASGN( operator>>=, operator>> ); DEFINE_ASGN( operator<<=, operator<< ); DEFINE_ASGN( operator+=, operator+ ); diff --git a/VTIL-Common/util/reducable.hpp b/VTIL-Common/util/reducable.hpp index b92620b..6077fe4 100644 --- a/VTIL-Common/util/reducable.hpp +++ b/VTIL-Common/util/reducable.hpp @@ -113,7 +113,6 @@ namespace vtil reducable_greq = 1 << 3, reducable_less = 1 << 4, reducable_greater = 1 << 5, - reducable_hash = 1 << 6, reducable_all = 0xFF, }; @@ -167,14 +166,13 @@ namespace vtil template = 0> __forceinline auto operator> ( const T& other ) const { return &other != this && reduce_proxy( ( T& ) *this ) > reduce_proxy( other ); } - // Define VTIL hash using a simple VTIL tuple hasher. - // - template = 0> - __forceinline hash_t hash() const { return make_hash( reduce_proxy( ( const T& ) *this ) ); } - // Define the [const T::reduce()] for the base type just for convinience. // __forceinline auto reduce() const { return reduce_proxy( ( const T& ) *this ); } + + // Define VTIL hash using a simple VTIL tuple hasher. + // + __forceinline hash_t hash() const { return make_hash( reduce() ); } }; // Helper used to create reduced tuples. diff --git a/VTIL-Common/util/type_helpers.hpp b/VTIL-Common/util/type_helpers.hpp index 621d992..a49e27f 100644 --- a/VTIL-Common/util/type_helpers.hpp +++ b/VTIL-Common/util/type_helpers.hpp @@ -62,6 +62,8 @@ namespace vtil // template concept Integral = std::is_integral_v; + template + concept Trivial = std::is_trivial_v; template concept ConvertibleTo = std::is_convertible_v; diff --git a/VTIL-SymEx/directives/directive.hpp b/VTIL-SymEx/directives/directive.hpp index 6af2d43..05770cf 100644 --- a/VTIL-SymEx/directives/directive.hpp +++ b/VTIL-SymEx/directives/directive.hpp @@ -216,9 +216,8 @@ namespace vtil::symbolic::directive // Variable constructor. // - template, int> = 0> - instance( T v ) : - operable( int64_t( v ) ), num_nodes( 1 ) + template + instance( T v, bitcnt_t _discarded_bit_count = 0 ) : operable( ( int64_t ) v , 64 ), num_nodes( 1 ) { for ( auto [out, idx] : zip( signatures, iindices ) ) out = { make_copy( value ).resize( math::narrow_cast( idx + 1 ) ) }; @@ -323,4 +322,4 @@ static bool operator==( vtil::math::operator_id a, vtil::symbolic::directive::di static bool operator==( vtil::symbolic::directive::directive_op_desc a, vtil::symbolic::directive::directive_op_desc b ) { return a.value == b.value; } static bool operator!=( vtil::symbolic::directive::directive_op_desc a, vtil::math::operator_id b ) { return uint8_t( b ) <= vtil::symbolic::directive::directive_op_desc::begin_id && uint8_t( a ) != uint8_t( b ); } static bool operator!=( vtil::math::operator_id a, vtil::symbolic::directive::directive_op_desc b ) { return uint8_t( a ) <= vtil::symbolic::directive::directive_op_desc::begin_id && uint8_t( b ) != uint8_t( a ); } -static bool operator!=( vtil::symbolic::directive::directive_op_desc a, vtil::symbolic::directive::directive_op_desc b ) { return a.value != b.value; } +static bool operator!=( vtil::symbolic::directive::directive_op_desc a, vtil::symbolic::directive::directive_op_desc b ) { return a.value != b.value; } \ No newline at end of file diff --git a/VTIL-SymEx/expressions/expression.cpp b/VTIL-SymEx/expressions/expression.cpp index 3aaa684..8116e1b 100644 --- a/VTIL-SymEx/expressions/expression.cpp +++ b/VTIL-SymEx/expressions/expression.cpp @@ -630,7 +630,7 @@ namespace vtil::symbolic // Append depth, size, and operator information to the hash. // - hash_value = make_hash( hash_value, op, depth, uint8_t( value.size() ) ); + hash_value = combine_hash( hash_value, make_hash( op, depth, uint8_t( value.size() ) ) ); // Punish for mixing bitwise and arithmetic operators. // @@ -734,7 +734,7 @@ namespace vtil::symbolic // If not in debug mode, assume equivalence after total hash reaches 384 bits. // - static constexpr size_t max_depth = 384 / VTIL_HASH_SIZE; + static constexpr size_t max_depth = 256 / VTIL_HASH_SIZE; #ifndef _DEBUG if constexpr ( depth == max_depth ) return true; diff --git a/VTIL-SymEx/expressions/unique_identifier.hpp b/VTIL-SymEx/expressions/unique_identifier.hpp index f3fbe86..3a669c1 100644 --- a/VTIL-SymEx/expressions/unique_identifier.hpp +++ b/VTIL-SymEx/expressions/unique_identifier.hpp @@ -89,7 +89,7 @@ namespace vtil::symbolic // Construct from any other type. // - template, + template, // Must not be an array or [const unique_identifier&]. std::enable_if_t && !std::extent_v, int> = 0> unique_identifier( const T& v, std::string&& name = "" )