metasm/main.rb in metasm-1.0.3 vs metasm/main.rb in metasm-1.0.4
- old
+ new
@@ -325,16 +325,20 @@
# superclass for classes similar to Expression
# must define #bind, #reduce_rec, #match_rec, #externals
class ExpressionType
def +(o) Expression[self, :+, o].reduce end
def -(o) Expression[self, :-, o].reduce end
+ # if the expression is constrained, this holds the mask of the maximum value
+ # (eg int16 => 0xffff)
+ attr_accessor :max_bits_mask
end
# handle immediate values, and arbitrary arithmetic/logic expression involving variables
# boolean values are treated as in C : true is 1, false is 0
# TODO replace #type with #size => bits + #type => [:signed/:unsigned/:any/:floating]
# TODO handle floats
+# TODO ternary operator ?
class Expression < ExpressionType
INT_SIZE = {}
INT_MIN = {}
INT_MAX = {}
@@ -381,11 +385,11 @@
end
# checks if a given Expression/Integer is in the type range
# returns true if it is, false if it overflows, and nil if cannot be determined (eg unresolved variable)
def self.in_range?(val, type)
- val = val.reduce if val.kind_of? self
+ val = val.reduce if val.kind_of?(self)
return unless val.kind_of?(::Numeric)
if INT_MIN[type]
val == val.to_i and
val >= INT_MIN[type] and val <= INT_MAX[type]
@@ -488,35 +492,33 @@
@@reduce_lambda = nil
# returns a simplified copy of self
# can return an +Expression+ or a +Numeric+, may return self
# see +reduce_rec+ for simplifications description
- # if given a block, it will temporarily overwrite the global @@reduce_lambda XXX THIS IS NOT THREADSAFE
- def reduce(&b)
- old_rp, @@reduce_lambda = @@reduce_lambda, b if b
- case e = reduce_rec
+ # if given a block, will use it instead of @@reduce_lambda
+ def reduce(&cb)
+ cb ||= @@reduce_lambda
+ case e = reduce_rec(cb)
when Expression, Numeric; e
else Expression[e]
end
- ensure
- @@reduce_lambda = old_rp if b
end
# resolves logic operations (true || false, etc)
# computes numeric operations (1 + 3)
# expands substractions to addition of the opposite
# reduces double-oppositions (-(-1) => 1)
# reduces addition of 0 and unary +
# canonicalize additions: put variables in the lhs, descend addition tree in the rhs => (a + (b + (c + 12)))
# make formal reduction if finds somewhere in addition tree (a) and (-a)
- def reduce_rec
- l = @lexpr.kind_of?(ExpressionType) ? @lexpr.reduce_rec : @lexpr
- r = @rexpr.kind_of?(ExpressionType) ? @rexpr.reduce_rec : @rexpr
+ def reduce_rec(cb = @@reduce_lambda)
+ l = @lexpr.kind_of?(ExpressionType) ? @lexpr.reduce_rec(cb) : @lexpr
+ r = @rexpr.kind_of?(ExpressionType) ? @rexpr.reduce_rec(cb) : @rexpr
- if @@reduce_lambda
- l = @@reduce_lambda[l] || l if not @lexpr.kind_of? Expression
- r = @@reduce_lambda[r] || r if not @rexpr.kind_of? Expression
+ if cb
+ l = cb[l] || l if l and not @lexpr.kind_of?(Expression)
+ r = cb[r] || r if r and not @rexpr.kind_of?(Expression)
end
v =
if r.kind_of?(::Numeric) and (not l or l.kind_of?(::Numeric))
case @op
@@ -538,11 +540,11 @@
end ? 1 : 0
else
l.send(@op, r)
end
elsif rp = @@reduce_op[@op]
- rp[self, l, r]
+ rp[self, l, r, cb]
end
ret = case v
when nil
# no dup if no new value
@@ -550,200 +552,200 @@
((r == @rexpr and l == @lexpr) ? self : Expression.new(@op, r, l))
when Expression
(v.lexpr == :unknown or v.rexpr == :unknown) ? :unknown : v
else v
end
- if @@reduce_lambda and ret.kind_of? ExpressionType and newret = @@reduce_lambda[ret] and newret != ret
- if newret.kind_of? ExpressionType
- ret = newret.reduce_rec
+ if cb and ret.kind_of?(ExpressionType) and newret = cb[ret] and newret != ret
+ if newret.kind_of?(ExpressionType)
+ ret = newret.reduce_rec(cb)
else
ret = newret
end
end
ret
end
@@reduce_op = {
- :+ => lambda { |e, l, r| e.reduce_op_plus(l, r) },
- :- => lambda { |e, l, r| e.reduce_op_minus(l, r) },
- :'&&' => lambda { |e, l, r| e.reduce_op_andand(l, r) },
- :'||' => lambda { |e, l, r| e.reduce_op_oror(l, r) },
- :>> => lambda { |e, l, r| e.reduce_op_shr(l, r) },
- :<< => lambda { |e, l, r| e.reduce_op_shl(l, r) },
- :'!' => lambda { |e, l, r| e.reduce_op_not(l, r) },
- :== => lambda { |e, l, r| e.reduce_op_eql(l, r) },
- :'!=' => lambda { |e, l, r| e.reduce_op_neq(l, r) },
- :^ => lambda { |e, l, r| e.reduce_op_xor(l, r) },
- :& => lambda { |e, l, r| e.reduce_op_and(l, r) },
- :| => lambda { |e, l, r| e.reduce_op_or(l, r) },
- :* => lambda { |e, l, r| e.reduce_op_times(l, r) },
- :/ => lambda { |e, l, r| e.reduce_op_div(l, r) },
- :% => lambda { |e, l, r| e.reduce_op_mod(l, r) },
+ :+ => lambda { |e, l, r, cb| e.reduce_op_plus(l, r, cb) },
+ :- => lambda { |e, l, r, cb| e.reduce_op_minus(l, r, cb) },
+ :'&&' => lambda { |e, l, r, cb| e.reduce_op_andand(l, r, cb) },
+ :'||' => lambda { |e, l, r, cb| e.reduce_op_oror(l, r, cb) },
+ :>> => lambda { |e, l, r, cb| e.reduce_op_shr(l, r, cb) },
+ :<< => lambda { |e, l, r, cb| e.reduce_op_shl(l, r, cb) },
+ :'!' => lambda { |e, l, r, cb| e.reduce_op_not(l, r, cb) },
+ :== => lambda { |e, l, r, cb| e.reduce_op_eql(l, r, cb) },
+ :'!=' => lambda { |e, l, r, cb| e.reduce_op_neq(l, r, cb) },
+ :^ => lambda { |e, l, r, cb| e.reduce_op_xor(l, r, cb) },
+ :& => lambda { |e, l, r, cb| e.reduce_op_and(l, r, cb) },
+ :| => lambda { |e, l, r, cb| e.reduce_op_or(l, r, cb) },
+ :* => lambda { |e, l, r, cb| e.reduce_op_times(l, r, cb) },
+ :/ => lambda { |e, l, r, cb| e.reduce_op_div(l, r, cb) },
+ :% => lambda { |e, l, r, cb| e.reduce_op_mod(l, r, cb) },
}
def self.reduce_op
@@reduce_op
end
- def reduce_op_plus(l, r)
+ def reduce_op_plus(l, r, cb)
if not l; r # +x => x
elsif r == 0; l # x+0 => x
elsif l == :unknown or r == :unknown; :unknown
elsif l.kind_of?(::Numeric)
if r.kind_of? Expression and r.op == :+
# 1+(x+y) => x+(y+1)
- Expression[r.lexpr, :+, [r.rexpr, :+, l]].reduce_rec
+ Expression[r.lexpr, :+, [r.rexpr, :+, l]].reduce_rec(cb)
else
# 1+a => a+1
- Expression[r, :+, l].reduce_rec
+ Expression[r, :+, l].reduce_rec(cb)
end
# (a+b)+foo => a+(b+foo)
- elsif l.kind_of? Expression and l.op == :+; Expression[l.lexpr, :+, [l.rexpr, :+, r]].reduce_rec
+ elsif l.kind_of? Expression and l.op == :+; Expression[l.lexpr, :+, [l.rexpr, :+, r]].reduce_rec(cb)
elsif l.kind_of? Expression and r.kind_of? Expression and l.op == :% and r.op == :% and l.rexpr.kind_of?(::Integer) and l.rexpr == r.rexpr
- Expression[[l.lexpr, :+, r.lexpr], :%, l.rexpr].reduce_rec
+ Expression[[l.lexpr, :+, r.lexpr], :%, l.rexpr].reduce_rec(cb)
elsif l.kind_of? Expression and l.op == :- and not l.lexpr
- reduce_rec_add_rec(r, l.rexpr)
+ reduce_rec_add_rec(r, l.rexpr, cb)
elsif l.kind_of? Expression and r.kind_of? Expression and l.op == :& and r.op == :& and l.rexpr.kind_of?(::Integer) and r.rexpr.kind_of?(::Integer) and l.rexpr & r.rexpr == 0
# (a&0xf0)+(b&0x0f) => (a&0xf0)|(b&0x0f)
- Expression[l, :|, r].reduce_rec
+ Expression[l, :|, r].reduce_rec(cb)
else
- reduce_rec_add_rec(r, Expression.new(:-, l, nil))
+ reduce_rec_add_rec(r, Expression.new(:-, l, nil), cb)
end
end
- def reduce_rec_add_rec(cur, neg_l)
+ def reduce_rec_add_rec(cur, neg_l, cb)
if neg_l == cur
# -l found
0
elsif cur.kind_of?(Expression) and cur.op == :+
# recurse
- if newl = reduce_rec_add_rec(cur.lexpr, neg_l)
- Expression[newl, cur.op, cur.rexpr].reduce_rec
- elsif newr = reduce_rec_add_rec(cur.rexpr, neg_l)
- Expression[cur.lexpr, cur.op, newr].reduce_rec
+ if newl = reduce_rec_add_rec(cur.lexpr, neg_l, cb)
+ Expression[newl, cur.op, cur.rexpr].reduce_rec(cb)
+ elsif newr = reduce_rec_add_rec(cur.rexpr, neg_l, cb)
+ Expression[cur.lexpr, cur.op, newr].reduce_rec(cb)
end
end
end
- def reduce_op_minus(l, r)
+ def reduce_op_minus(l, r, cb)
if l == :unknown or r == :unknown; :unknown
elsif not l and r.kind_of? Expression and (r.op == :- or r.op == :+)
if r.op == :- # no lexpr (reduced)
# -(-x) => x
r.rexpr
else # :+ and lexpr (r is reduced)
# -(a+b) => (-a)+(-b)
- Expression.new(:+, Expression.new(:-, r.rexpr, nil), Expression.new(:-, r.lexpr, nil)).reduce_rec
+ Expression.new(:+, Expression.new(:-, r.rexpr, nil), Expression.new(:-, r.lexpr, nil)).reduce_rec(cb)
end
elsif l.kind_of? Expression and l.op == :+ and l.lexpr == r
# shortcircuit for a common occurence [citation needed]
# (a+b)-a
l.rexpr
elsif l
# a-b => a+(-b)
- Expression[l, :+, [:-, r]].reduce_rec
+ Expression[l, :+, [:-, r]].reduce_rec(cb)
end
end
- def reduce_op_andand(l, r)
+ def reduce_op_andand(l, r, cb)
if l == 0 # shortcircuit eval
0
elsif l == 1
- Expression[r, :'!=', 0].reduce_rec
+ Expression[r, :'!=', 0].reduce_rec(cb)
elsif r == 0
0 # XXX l could be a special ExprType with sideeffects ?
end
end
- def reduce_op_oror(l, r)
+ def reduce_op_oror(l, r, cb)
if l.kind_of?(::Numeric) and l != 0 # shortcircuit eval
1
elsif l == 0
- Expression[r, :'!=', 0].reduce_rec
+ Expression[r, :'!=', 0].reduce_rec(cb)
elsif r == 0
- Expression[l, :'!=', 0].reduce_rec
+ Expression[l, :'!=', 0].reduce_rec(cb)
end
end
- def reduce_op_shr(l, r)
+ def reduce_op_shr(l, r, cb)
if l == 0; 0
elsif r == 0; l
elsif l.kind_of? Expression and l.op == :>>
- Expression[l.lexpr, :>>, [l.rexpr, :+, r]].reduce_rec
+ Expression[l.lexpr, :>>, [l.rexpr, :+, r]].reduce_rec(cb)
elsif r.kind_of? Integer and l.kind_of? Expression and [:&, :|, :^].include? l.op
# (a | b) << i => (a<<i | b<<i)
- Expression[[l.lexpr, :>>, r], l.op, [l.rexpr, :>>, r]].reduce_rec
+ Expression[[l.lexpr, :>>, r], l.op, [l.rexpr, :>>, r]].reduce_rec(cb)
end
end
- def reduce_op_shl(l, r)
+ def reduce_op_shl(l, r, cb)
if l == 0; 0
elsif r == 0; l
elsif l.kind_of? Expression and l.op == :<<
- Expression[l.lexpr, :<<, [l.rexpr, :+, r]].reduce_rec
+ Expression[l.lexpr, :<<, [l.rexpr, :+, r]].reduce_rec(cb)
elsif l.kind_of? Expression and l.op == :>> and r.kind_of? Integer and l.rexpr.kind_of? Integer
# (a >> 1) << 1 == a & 0xfffffe
if r == l.rexpr
- Expression[l.lexpr, :&, (-1 << r)].reduce_rec
+ Expression[l.lexpr, :&, (-1 << r)].reduce_rec(cb)
elsif r > l.rexpr
- Expression[[l.lexpr, :<<, r-l.rexpr], :&, (-1 << r)].reduce_rec
+ Expression[[l.lexpr, :<<, r-l.rexpr], :&, (-1 << r)].reduce_rec(cb)
else
- Expression[[l.lexpr, :>>, l.rexpr-r], :&, (-1 << r)].reduce_rec
+ Expression[[l.lexpr, :>>, l.rexpr-r], :&, (-1 << r)].reduce_rec(cb)
end
- elsif r.kind_of? Integer and l.kind_of? Expression and [:&, :|, :^].include? l.op
+ elsif r.kind_of?(::Integer) and l.kind_of?(Expression) and [:&, :|, :^].include?(l.op)
# (a | b) << i => (a<<i | b<<i)
- Expression[[l.lexpr, :<<, r], l.op, [l.rexpr, :<<, r]].reduce_rec
+ Expression[[l.lexpr, :<<, r], l.op, [l.rexpr, :<<, r]].reduce_rec(cb)
end
end
NEG_OP = {:'==' => :'!=', :'!=' => :'==', :< => :>=, :> => :<=, :<= => :>, :>= => :<}
- def reduce_op_not(l, r)
+ def reduce_op_not(l, r, cb)
if r.kind_of? Expression and nop = NEG_OP[r.op]
- Expression[r.lexpr, nop, r.rexpr].reduce_rec
+ Expression[r.lexpr, nop, r.rexpr].reduce_rec(cb)
end
end
- def reduce_op_eql(l, r)
+ def reduce_op_eql(l, r, cb)
if l == r; 1
elsif r == 0 and l.kind_of? Expression and nop = NEG_OP[l.op]
- Expression[l.lexpr, nop, l.rexpr].reduce_rec
+ Expression[l.lexpr, nop, l.rexpr].reduce_rec(cb)
elsif r == 1 and l.kind_of? Expression and NEG_OP[l.op]
l
elsif r == 0 and l.kind_of? Expression and l.op == :+
if l.rexpr.kind_of? Expression and l.rexpr.op == :- and not l.rexpr.lexpr
- Expression[l.lexpr, :==, l.rexpr.rexpr].reduce_rec
+ Expression[l.lexpr, :==, l.rexpr.rexpr].reduce_rec(cb)
elsif l.rexpr.kind_of?(::Integer)
- Expression[l.lexpr, :==, -l.rexpr].reduce_rec
+ Expression[l.lexpr, :==, -l.rexpr].reduce_rec(cb)
end
end
end
- def reduce_op_neq(l, r)
+ def reduce_op_neq(l, r, cb)
if l == r; 0
end
end
- def reduce_op_xor(l, r)
+ def reduce_op_xor(l, r, cb)
if l == :unknown or r == :unknown; :unknown
elsif l == 0; r
elsif r == 0; l
elsif l == r; 0
elsif r == 1 and l.kind_of? Expression and NEG_OP[l.op]
- Expression[nil, :'!', l].reduce_rec
+ Expression[nil, :'!', l].reduce_rec(cb)
elsif l.kind_of?(::Numeric)
if r.kind_of? Expression and r.op == :^
# 1^(x^y) => x^(y^1)
- Expression[r.lexpr, :^, [r.rexpr, :^, l]].reduce_rec
+ Expression[r.lexpr, :^, [r.rexpr, :^, l]].reduce_rec(cb)
else
# 1^a => a^1
- Expression[r, :^, l].reduce_rec
+ Expression[r, :^, l].reduce_rec(cb)
end
elsif l.kind_of? Expression and l.op == :^
# (a^b)^c => a^(b^c)
- Expression[l.lexpr, :^, [l.rexpr, :^, r]].reduce_rec
+ Expression[l.lexpr, :^, [l.rexpr, :^, r]].reduce_rec(cb)
elsif r.kind_of? Expression and r.op == :^
if r.rexpr == l
# a^(a^b) => b
r.lexpr
elsif r.lexpr == l
@@ -757,61 +759,63 @@
while not found and tr.kind_of?(Expression) and tr.op == :^
found = true if tr.lexpr == l or tr.rexpr == l
tr = tr.rexpr
end
if found
- Expression[r.lexpr, :^, [l, :^, r.rexpr]].reduce_rec
+ Expression[r.lexpr, :^, [l, :^, r.rexpr]].reduce_rec(cb)
end
end
elsif l.kind_of?(Expression) and l.op == :& and l.rexpr.kind_of?(::Integer) and (l.rexpr & (l.rexpr+1)) == 0
if r.kind_of?(::Integer) and r & l.rexpr == r
# (a&0xfff)^12 => (a^12)&0xfff
- Expression[[l.lexpr, :^, r], :&, l.rexpr].reduce_rec
+ Expression[[l.lexpr, :^, r], :&, l.rexpr].reduce_rec(cb)
elsif r.kind_of?(Expression) and r.op == :& and r.rexpr.kind_of?(::Integer) and r.rexpr == l.rexpr
# (a&0xfff)^(b&0xfff) => (a^b)&0xfff
- Expression[[l.lexpr, :^, r.lexpr], :&, l.rexpr].reduce_rec
+ Expression[[l.lexpr, :^, r.lexpr], :&, l.rexpr].reduce_rec(cb)
end
end
end
- def reduce_op_and(l, r)
+ def reduce_op_and(l, r, cb)
if l == 0 or r == 0; 0
elsif r == 1 and l.kind_of?(Expression) and [:'==', :'!=', :<, :>, :<=, :>=].include?(l.op)
l
elsif l == r; l
- elsif l.kind_of?(Integer); Expression[r, :&, l].reduce_rec
- elsif l.kind_of?(Expression) and l.op == :&; Expression[l.lexpr, :&, [l.rexpr, :&, r]].reduce_rec
+ elsif l.kind_of?(Integer); Expression[r, :&, l].reduce_rec(cb)
+ elsif l.kind_of?(Expression) and l.op == :&; Expression[l.lexpr, :&, [l.rexpr, :&, r]].reduce_rec(cb)
elsif l.kind_of?(Expression) and [:|, :^].include?(l.op) and r.kind_of?(Integer) and (l.op == :| or (r & (r+1)) != 0)
# (a ^| b) & i => (a&i ^| b&i)
- Expression[[l.lexpr, :&, r], l.op, [l.rexpr, :&, r]].reduce_rec
+ Expression[[l.lexpr, :&, r], l.op, [l.rexpr, :&, r]].reduce_rec(cb)
+ elsif r.kind_of?(::Integer) and l.kind_of?(ExpressionType) and r == l.max_bits_mask
+ l
elsif r.kind_of?(::Integer) and l.kind_of?(Expression) and (r & (r+1)) == 0
# foo & 0xffff
case l.op
when :+, :^
if l.lexpr.kind_of?(Expression) and l.lexpr.op == :& and
l.lexpr.rexpr.kind_of?(::Integer) and l.lexpr.rexpr & r == r
# ((a&m) + b) & m => (a+b) & m
- Expression[[l.lexpr.lexpr, l.op, l.rexpr], :&, r].reduce_rec
+ Expression[[l.lexpr.lexpr, l.op, l.rexpr], :&, r].reduce_rec(cb)
elsif l.rexpr.kind_of?(Expression) and l.rexpr.op == :& and
l.rexpr.rexpr.kind_of?(::Integer) and l.rexpr.rexpr & r == r
# (a + (b&m)) & m => (a+b) & m
- Expression[[l.lexpr, l.op, l.rexpr.lexpr], :&, r].reduce_rec
+ Expression[[l.lexpr, l.op, l.rexpr.lexpr], :&, r].reduce_rec(cb)
else
Expression[l, :&, r]
end
when :|
# rol/ror composition
- reduce_rec_composerol l, r
+ reduce_rec_composerol(l, r, cb)
else
Expression[l, :&, r]
end
end
end
# a check to see if an Expr is the composition of two rotations (rol eax, 4 ; rol eax, 6 => rol eax, 10)
# this is a bit too ugly to stay in the main reduce_rec body.
- def reduce_rec_composerol(e, mask)
+ def reduce_rec_composerol(e, mask, cb)
m = Expression[['var', :sh_op, 'amt'], :|, ['var', :inv_sh_op, 'inv_amt']]
if vars = e.match(m, 'var', :sh_op, 'amt', :inv_sh_op, 'inv_amt') and vars[:sh_op] == {:>> => :<<, :<< => :>>}[vars[:inv_sh_op]] and
((vars['amt'].kind_of?(::Integer) and vars['inv_amt'].kind_of?(::Integer) and ampl = vars['amt'] + vars['inv_amt']) or
(vars['amt'].kind_of? Expression and vars['amt'].op == :% and vars['amt'].rexpr.kind_of?(::Integer) and
vars['inv_amt'].kind_of? Expression and vars['inv_amt'].op == :% and vars['amt'].rexpr == vars['inv_amt'].rexpr and ampl = vars['amt'].rexpr)) and
@@ -827,54 +831,54 @@
ivars[:sh_op], ivars[:inv_sh_op] = ivars[:inv_sh_op], ivars[:sh_op]
ivars['amt'], ivars['inv_amt'] = ivars['inv_amt'], ivars['amt']
end
amt = Expression[[vars['amt'], :+, ivars['amt']], :%, ampl]
invamt = Expression[[vars['inv_amt'], :+, ivars['inv_amt']], :%, ampl]
- Expression[[[[ivars['var'], :&, mask], vars[:sh_op], amt], :|, [[ivars['var'], :&, mask], vars[:inv_sh_op], invamt]], :&, mask].reduce_rec
+ Expression[[[[ivars['var'], :&, mask], vars[:sh_op], amt], :|, [[ivars['var'], :&, mask], vars[:inv_sh_op], invamt]], :&, mask].reduce_rec(cb)
else
Expression[e, :&, mask]
end
end
- def reduce_op_or(l, r)
+ def reduce_op_or(l, r, cb)
if l == 0; r
elsif r == 0; l
elsif l == -1 or r == -1; -1
elsif l == r; l
- elsif l.kind_of? Integer; Expression[r, :|, l].reduce_rec
+ elsif l.kind_of? Integer; Expression[r, :|, l].reduce_rec(cb)
elsif l.kind_of? Expression and l.op == :|
# (a|b)|c => a|(b|c)
- Expression[l.lexpr, :|, [l.rexpr, :|, r]].reduce_rec
+ Expression[l.lexpr, :|, [l.rexpr, :|, r]].reduce_rec(cb)
elsif l.kind_of? Expression and l.op == :& and r.kind_of? Expression and r.op == :& and l.lexpr == r.lexpr
# (a&b)|(a&c) => a&(b|c)
- Expression[l.lexpr, :&, [l.rexpr, :|, r.rexpr]].reduce_rec
+ Expression[l.lexpr, :&, [l.rexpr, :|, r.rexpr]].reduce_rec(cb)
end
end
- def reduce_op_times(l, r)
+ def reduce_op_times(l, r, cb)
if l == 0 or r == 0; 0
elsif l == 1; r
elsif r == 1; l
- elsif r.kind_of? Integer; Expression[r, :*, l].reduce_rec
- elsif r.kind_of? Expression and r.op == :*; Expression[[l, :*, r.lexpr], :*, r.rexpr].reduce_rec
- elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :* and r.lexpr.kind_of? Integer; Expression[l*r.lexpr, :*, r.rexpr].reduce_rec # XXX need & regsize..
- elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :+ and r.rexpr.kind_of? Integer; Expression[[l, :*, r.lexpr], :+, l*r.rexpr].reduce_rec
+ elsif r.kind_of? Integer; Expression[r, :*, l].reduce_rec(cb)
+ elsif r.kind_of? Expression and r.op == :*; Expression[[l, :*, r.lexpr], :*, r.rexpr].reduce_rec(cb)
+ elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :* and r.lexpr.kind_of? Integer; Expression[l*r.lexpr, :*, r.rexpr].reduce_rec(cb) # XXX need & regsize..
+ elsif l.kind_of? Integer and r.kind_of? Expression and r.op == :+ and r.rexpr.kind_of? Integer; Expression[[l, :*, r.lexpr], :+, l*r.rexpr].reduce_rec(cb)
end
end
- def reduce_op_div(l, r)
+ def reduce_op_div(l, r, cb)
if r == 0
elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :+ and l.rexpr.kind_of? Integer and l.rexpr % r == 0
- Expression[[l.lexpr, :/, r], :+, l.rexpr/r].reduce_rec
+ Expression[[l.lexpr, :/, r], :+, l.rexpr/r].reduce_rec(cb)
elsif r.kind_of? Integer and l.kind_of? Expression and l.op == :* and l.lexpr % r == 0
- Expression[l.lexpr/r, :*, l.rexpr].reduce_rec
+ Expression[l.lexpr/r, :*, l.rexpr].reduce_rec(cb)
end
end
- def reduce_op_mod(l, r)
+ def reduce_op_mod(l, r, cb)
if r.kind_of?(Integer) and r != 0 and (r & (r-1) == 0)
- Expression[l, :&, r-1].reduce_rec
+ Expression[l, :&, r-1].reduce_rec(cb)
end
end
# a pattern-matching method
@@ -939,15 +943,16 @@
# An Expression with a custom string representation
# used to show #define constants, struct offsets, func local vars, etc
class ExpressionString < ExpressionType
attr_accessor :expr, :str, :type, :hide_str
- def reduce; expr.reduce; end
- def reduce_rec; expr.reduce_rec; end
+ def reduce(&b); expr.reduce(&b); end
+ def reduce_rec(cb=@@reduce_lambda); expr.reduce_rec(cb); end
def bind(*a); expr.bind(*a); end
def externals; expr.externals; end
def expr_externals; expr.expr_externals; end
def match_rec(*a); expr.match_rec(*a); end
+ def max_bits_mask; expr.max_bits_mask; end
def initialize(expr, str, type=nil)
@expr = Expression[expr]
@str = str
@type = type
end