about summary refs log tree commit diff stats
path: root/miasm2/expression
diff options
context:
space:
mode:
Diffstat (limited to 'miasm2/expression')
-rw-r--r--miasm2/expression/expression.py103
-rw-r--r--miasm2/expression/expression_helper.py2
-rw-r--r--miasm2/expression/modint.py2
-rw-r--r--miasm2/expression/simplifications_common.py9
-rw-r--r--miasm2/expression/simplifications_cond.py10
5 files changed, 68 insertions, 58 deletions
diff --git a/miasm2/expression/expression.py b/miasm2/expression/expression.py
index e134e503..85471e05 100644
--- a/miasm2/expression/expression.py
+++ b/miasm2/expression/expression.py
@@ -30,7 +30,8 @@
 
 import itertools
 from operator import itemgetter
-from miasm2.expression.modint import *
+from miasm2.expression.modint import mod_size2uint, is_modint, size2mask, \
+    define_uint
 from miasm2.core.graph import DiGraph
 import warnings
 
@@ -143,10 +144,6 @@ class Expr(object):
             Expr.args2expr[(cls, args)] = expr
         return expr
 
-    def __new__(cls, *args, **kwargs):
-        expr = object.__new__(cls, *args, **kwargs)
-        return expr
-
     def get_is_canon(self):
         return self in Expr.canon_exprs
 
@@ -187,23 +184,18 @@ class Expr(object):
             self.__hash = self._exprhash()
         return self.__hash
 
-    def pre_eq(self, other):
-        """Return True if ids are equal;
-        False if instances are obviously not equal
-        None if we cannot simply decide"""
-
-        if id(self) == id(other):
+    def __eq__(self, other):
+        if self is other:
             return True
+        elif self.use_singleton:
+            # In case of Singleton, pointer comparison is sufficient
+            # Avoid computation of hash and repr
+            return False
+
         if self.__class__ is not other.__class__:
             return False
         if hash(self) != hash(other):
             return False
-        return None
-
-    def __eq__(self, other):
-        res = self.pre_eq(other)
-        if res is not None:
-            return res
         return repr(self) == repr(other)
 
     def __ne__(self, a):
@@ -246,8 +238,7 @@ class Expr(object):
         return ExprOp("**",self, a)
 
     def __invert__(self):
-        s = self.size
-        return ExprOp('^', self, ExprInt(mod_size2uint[s](size2mask(s))))
+        return ExprOp('^', self, self.mask)
 
     def copy(self):
         "Deep copy of the expression"
@@ -398,25 +389,12 @@ class ExprInt(Expr):
     __slots__ = Expr.__slots__ + ["__arg"]
 
 
-    def __init__(self, num, size=None):
+    def __init__(self, arg, size):
         """Create an ExprInt from a modint or num/size
-        @arg: modint or num
-        @size: (optionnal) int size"""
-
+        @arg: 'intable' number
+        @size: int size"""
         super(ExprInt, self).__init__()
-
-        if is_modint(num):
-            self.__arg = num
-            self.__size = self.arg.size
-            if size is not None and num.size != size:
-                raise RuntimeError("size must match modint size")
-        elif size is not None:
-            if size not in mod_size2uint:
-                define_uint(size)
-            self.__arg = mod_size2uint[size](num)
-            self.__size = self.arg.size
-        else:
-            raise ValueError('arg must by modint or (int,size)! %s' % num)
+        # Work is done in __new__
 
     size = property(lambda self: self.__size)
     arg = property(lambda self: self.__arg)
@@ -427,10 +405,29 @@ class ExprInt(Expr):
     def __setstate__(self, state):
         self.__init__(*state)
 
-    def __new__(cls, arg, size=None):
-        if size is None:
-            size = arg.size
-        return Expr.get_object(cls, (arg, size))
+    def __new__(cls, arg, size):
+        """Create an ExprInt from a modint or num/size
+        @arg: 'intable' number
+        @size: int size"""
+
+        if is_modint(arg):
+            assert size == arg.size
+        # Avoid a common blunder
+        assert not isinstance(arg, ExprInt)
+
+        # Ensure arg is always a moduint
+        arg = int(arg)
+        if size not in mod_size2uint:
+            define_uint(size)
+        arg = mod_size2uint[size](arg)
+
+        # Get the Singleton instance
+        expr = Expr.get_object(cls, (arg, size))
+
+        # Save parameters (__init__ is called with parameters unchanged)
+        expr.__arg = arg
+        expr.__size = expr.__arg.size
+        return expr
 
     def __get_int(self):
         "Return self integer representation"
@@ -466,7 +463,7 @@ class ExprInt(Expr):
         return self
 
     def copy(self):
-        return ExprInt(self.__arg)
+        return ExprInt(self.__arg, self.__size)
 
     def depth(self):
         return 1
@@ -1321,28 +1318,40 @@ def canonize_expr_list_compose(l):
 
 
 def ExprInt1(i):
-    return ExprInt(uint1(i))
+    warnings.warn('DEPRECATION WARNING: use ExprInt(i, 1) instead of '\
+                  'ExprInt1(i))')
+    return ExprInt(i, 1)
 
 
 def ExprInt8(i):
-    return ExprInt(uint8(i))
+    warnings.warn('DEPRECATION WARNING: use ExprInt(i, 8) instead of '\
+                  'ExprInt8(i))')
+    return ExprInt(i, 8)
 
 
 def ExprInt16(i):
-    return ExprInt(uint16(i))
+    warnings.warn('DEPRECATION WARNING: use ExprInt(i, 16) instead of '\
+                  'ExprInt16(i))')
+    return ExprInt(i, 16)
 
 
 def ExprInt32(i):
-    return ExprInt(uint32(i))
+    warnings.warn('DEPRECATION WARNING: use ExprInt(i, 32) instead of '\
+                  'ExprInt32(i))')
+    return ExprInt(i, 32)
 
 
 def ExprInt64(i):
-    return ExprInt(uint64(i))
+    warnings.warn('DEPRECATION WARNING: use ExprInt(i, 64) instead of '\
+                  'ExprInt64(i))')
+    return ExprInt(i, 64)
 
 
 def ExprInt_from(e, i):
     "Generate ExprInt with size equal to expression"
-    return ExprInt(mod_size2uint[e.size](i))
+    warnings.warn('DEPRECATION WARNING: use ExprInt(i, expr.size) instead of'\
+                  'ExprInt_from(expr, i))')
+    return ExprInt(i, e.size)
 
 
 def get_expr_ids_visit(e, ids):
diff --git a/miasm2/expression/expression_helper.py b/miasm2/expression/expression_helper.py
index 36e5f1d5..1e718faa 100644
--- a/miasm2/expression/expression_helper.py
+++ b/miasm2/expression/expression_helper.py
@@ -521,7 +521,7 @@ class CondConstraintNotZero(CondConstraint):
     operator = "!="
 
     def to_constraint(self):
-        cst1, cst2 = m2_expr.ExprInt1(0), m2_expr.ExprInt1(1)
+        cst1, cst2 = m2_expr.ExprInt(0, 1), m2_expr.ExprInt(1, 1)
         return m2_expr.ExprAff(cst1, m2_expr.ExprCond(self.expr, cst1, cst2))
 
 
diff --git a/miasm2/expression/modint.py b/miasm2/expression/modint.py
index b6a0e4ee..51a2620e 100644
--- a/miasm2/expression/modint.py
+++ b/miasm2/expression/modint.py
@@ -224,7 +224,7 @@ def define_uint(size):
     return cls
 
 def define_common_int():
-    "Define common int: ExprInt1, ExprInt2, .."
+    "Define common int"
     common_int = xrange(1, 257)
 
     for i in common_int:
diff --git a/miasm2/expression/simplifications_common.py b/miasm2/expression/simplifications_common.py
index 503a0e77..01db7597 100644
--- a/miasm2/expression/simplifications_common.py
+++ b/miasm2/expression/simplifications_common.py
@@ -3,6 +3,7 @@
 # ----------------------------- #
 
 
+from miasm2.expression.modint import mod_size2int, mod_size2uint
 from miasm2.expression.expression import *
 from miasm2.expression.expression_helper import *
 
@@ -103,7 +104,7 @@ def simp_cst_propagation(e_s, e):
 
     # -(int) => -int
     if op == '-' and len(args) == 1 and args[0].is_int():
-        return ExprInt(-args[0].arg)
+        return ExprInt(-int(args[0]), e.size)
     # A op 0 =>A
     if op in ['+', '|', "^", "<<", ">>", "<<<", ">>>"] and len(args) > 1:
         if args[-1].is_int(0):
@@ -237,7 +238,7 @@ def simp_cst_propagation(e_s, e):
 
     # parity(int) => int
     if op == 'parity' and args[0].is_int():
-        return ExprInt1(parity(args[0].arg))
+        return ExprInt(parity(int(args[0])), 1)
 
     # (-a) * b * (-c) * (-d) => (-a) * b * c * d
     if op == "*" and len(args) > 1:
@@ -580,8 +581,8 @@ def simp_cond(e_s, e):
     # eval exprcond src1/src2 with satifiable/unsatisfiable condition
     # propagation
     if (not e.cond.is_int()) and e.cond.size == 1:
-        src1 = e.src1.replace_expr({e.cond: ExprInt1(1)})
-        src2 = e.src2.replace_expr({e.cond: ExprInt1(0)})
+        src1 = e.src1.replace_expr({e.cond: ExprInt(1, 1)})
+        src2 = e.src2.replace_expr({e.cond: ExprInt(0, 1)})
         if src1 != e.src1 or src2 != e.src2:
             return ExprCond(e.cond, src1, src2)
 
diff --git a/miasm2/expression/simplifications_cond.py b/miasm2/expression/simplifications_cond.py
index 03bf6166..0d194d9a 100644
--- a/miasm2/expression/simplifications_cond.py
+++ b/miasm2/expression/simplifications_cond.py
@@ -169,7 +169,7 @@ def expr_simp_inverse(expr_simp, e):
 def expr_simp_equal(expr_simp, e):
     """(x - y)?(0:1) == (x == y)"""
 
-    to_match = m2_expr.ExprCond(jok1 + jok2, m2_expr.ExprInt1(0), m2_expr.ExprInt1(1))
+    to_match = m2_expr.ExprCond(jok1 + jok2, m2_expr.ExprInt(0, 1), m2_expr.ExprInt(1, 1))
     r = __MatchExprWrap(e,
                         to_match,
                         [jok1, jok2])
@@ -188,13 +188,13 @@ def exec_inf_unsigned(expr_simp, e):
     arg1, arg2 = e.args
 
     if isinstance(arg1, m2_expr.ExprInt) and isinstance(arg2, m2_expr.ExprInt):
-        return m2_expr.ExprInt1(1) if (arg1.arg < arg2.arg) else m2_expr.ExprInt1(0)
+        return m2_expr.ExprInt(1, 1) if (arg1.arg < arg2.arg) else m2_expr.ExprInt(0, 1)
     else:
         return e
 
 
 def __comp_signed(arg1, arg2):
-    """Return ExprInt1(1) if arg1 <s arg2 else ExprInt1(0)
+    """Return ExprInt(1, 1) if arg1 <s arg2 else ExprInt(0, 1)
     @arg1, @arg2: ExprInt"""
 
     val1 = int(arg1)
@@ -205,7 +205,7 @@ def __comp_signed(arg1, arg2):
     if val2 >> (arg2.size - 1) == 1:
         val2 = - ((int(arg2.mask) ^ val2) + 1)
 
-    return m2_expr.ExprInt1(1) if (val1 < val2) else m2_expr.ExprInt1(0)
+    return m2_expr.ExprInt(1, 1) if (val1 < val2) else m2_expr.ExprInt(0, 1)
 
 def exec_inf_signed(expr_simp, e):
     "Compute x <s y"
@@ -228,6 +228,6 @@ def exec_equal(expr_simp, e):
 
     arg1, arg2 = e.args
     if isinstance(arg1, m2_expr.ExprInt) and isinstance(arg2, m2_expr.ExprInt):
-        return m2_expr.ExprInt1(1) if (arg1.arg == arg2.arg) else m2_expr.ExprInt1(0)
+        return m2_expr.ExprInt(1, 1) if (arg1.arg == arg2.arg) else m2_expr.ExprInt(0, 1)
     else:
         return e