class Metasm::C::Block

Attributes

anonymous_enums[RW]
decompdata[RW]
outer[RW]
statements[RW]
struct[RW]
symbol[RW]

Public Class Methods

new(outer, statements=[], symbol={}, struct={}) click to toggle source
# File metasm/parse_c.rb, line 38
def initialize(outer, statements=[], symbol={}, struct={})
        @outer = outer
        @statements = statements
        @symbol = symbol
        @struct = struct
end

Public Instance Methods

break_label() click to toggle source
# File metasm/compile_c.rb, line 540
def break_label ; defined?(@break_label) ? @break_label : @outer.break_label end
break_label=(l) click to toggle source
# File metasm/compile_c.rb, line 541
def break_label=(l) @break_label = l end
continue_label() click to toggle source
# File metasm/compile_c.rb, line 538
def continue_label ; defined?(@continue_label) ? @continue_label : @outer.continue_label end
continue_label=(l) click to toggle source
# File metasm/compile_c.rb, line 539
def continue_label=(l) @continue_label = l end
dump(scp, r=[''], dep=[]) click to toggle source

return array of c source lines and array of dependencies (objects)

# File metasm/parse_c.rb, line 3351
def dump(scp, r=[''], dep=[])
        mydefs = @symbol.values.grep(TypeDef) + @struct.values + anonymous_enums.to_a
        todo_rndr = {}
        todo_deps = {}
        mydefs.each { |t| # filter out Enum values
                todo_rndr[t], todo_deps[t] = t.dump_def(self)
        }
        r, dep = dump_reorder(mydefs, todo_rndr, todo_deps, r, dep)
        dep -= @symbol.values + @struct.values
        [r, dep]
end
dump_reorder(mydefs, todo_rndr, todo_deps, r=[''], dep=[]) click to toggle source
# File metasm/parse_c.rb, line 3363
def dump_reorder(mydefs, todo_rndr, todo_deps, r=[''], dep=[])
        val = todo_deps.values.flatten.uniq
        dep |= val
        dep -= mydefs | todo_deps.keys
        todo_deps.each { |k, v| v.delete k }
        ext = val - mydefs
        if ext.length > todo_deps.length
                todo_deps.each_key { |k| todo_deps[k] = todo_deps[k] & mydefs }
        else
                ext.each { |k| todo_deps.each_value { |v| v.delete k } }
        end

        # predeclare structs involved in cyclic dependencies
        dep_cycle = lambda { |ary|
                # sexyness inside (c)
                deps = todo_deps[ary.last]
                if deps.include? ary.first; ary
                elsif (deps-ary).find { |d| deps = dep_cycle[ary + [d]] }; deps
                end
        }
        todo_rndr.keys.grep(Union).find_all { |t| t.name }.sort_by { |t| t.name }.each { |t|
                oldc = nil
                while c = dep_cycle[[t]]
                        break if oldc == c
                        r << "#{t.kind_of?(Struct) ? 'struct' : 'union'} #{t.name};" if not oldc
                        oldc = c
                        c.each { |s|
                                # XXX struct z { struct a* }; struct a { void (*foo)(struct z); };
                                todo_deps[s].delete t unless s.kind_of? Union and
                                        s.members.find { |sm| sm.type.untypedef == t }
                        }
                end
        }

        loop do
                break if todo_rndr.empty?
                todo_now = todo_deps.keys.find_all { |k| todo_deps[k].empty? }
                if todo_now.empty?
                        r << '// dependency problem, this may not compile'
                        todo_now = todo_deps.keys
                end
                todo_now.sort_by { |k| k.name || '0' }.each { |k|
                        if k.kind_of? Variable and k.type.kind_of? Function and k.initializer
                                r << ''
                                r.concat todo_rndr.delete(k)
                        else
                                r.pop if r.last == ''
                                r.concat todo_rndr.delete(k)
                                r.last << ';'
                        end
                        todo_deps.delete k
                }
                todo_deps.each_key { |k| todo_deps[k] -= todo_now }
                r << '' << '' << ''
        end

        @statements.each { |s|
                r << '' if not r.last.empty?
                if s.kind_of? Block
                        r, dep = Statement.dump(s, self, r, dep)
                else
                        r, dep = s.dump(self, r, dep)
                end
        }

        [r, dep]
end
function() click to toggle source
# File metasm/compile_c.rb, line 546
def function ; defined?(@function) ? @function : @outer.function end
function=(f) click to toggle source
# File metasm/compile_c.rb, line 547
def function=(f) @function = f end
nonauto_label() click to toggle source
# File metasm/compile_c.rb, line 545
def nonauto_label ; defined?(@nonauto_label) ? @nonauto_label : @outer.nonauto_label end
nonauto_label=(l) click to toggle source
# File metasm/compile_c.rb, line 544
def nonauto_label=(l) @nonauto_label = l end
precompile(compiler, scope=nil) click to toggle source

precompile all statements, then simplifies symbols/structs types

# File metasm/compile_c.rb, line 451
def precompile(compiler, scope=nil)
        stmts = @statements.dup
        @statements.clear
        stmts.each { |st|
                compiler.curexpr = st
                st.precompile(compiler, self)
        }

        # cleanup declarations
        @symbol.delete_if { |n, s| not s.kind_of? Variable }
        @struct.delete_if { |n, s| not s.kind_of? Union }
        @symbol.each_value { |var|
                CExpression.precompile_type(compiler, self, var, true)
        }
        @struct.each_value { |var|
                next if not var.members
                var.members.each { |m|
                        CExpression.precompile_type(compiler, self, m, true)
                }
        }
        scope.statements << self if scope and not @statements.empty?
end
precompile_make_block(scope) click to toggle source

noop

# File metasm/compile_c.rb, line 536
def precompile_make_block(scope) self end
precompile_optimize() click to toggle source

removes unused labels, and in-place goto (goto toto; toto:)

# File metasm/compile_c.rb, line 475
def precompile_optimize
        list = []
        precompile_optimize_inner(list, 1)
        precompile_optimize_inner(list, 2)
end
precompile_optimize_inner(list, step) click to toggle source

step 1: list used labels/unused goto step 2: remove unused labels

# File metasm/compile_c.rb, line 483
def precompile_optimize_inner(list, step)
        lastgoto = nil
        hadref = false
        walk = lambda { |expr|
                next if not expr.kind_of? CExpression
                # gcc's unary && support
                if not expr.op and not expr.lexpr and expr.rexpr.kind_of? Label
                        list << expr.rexpr.name
                else
                        walk[expr.lexpr]
                        if expr.rexpr.kind_of? ::Array
                                expr.rexpr.each { |r| walk[r] }
                        else
                                walk[expr.rexpr]
                        end
                end
        }
        @statements.dup.each { |s|
                lastgoto = nil if not s.kind_of? Label
                case s
                when Block
                        s.precompile_optimize_inner(list, step)
                        @statements.delete s if step == 2 and s.statements.empty?
                when CExpression; walk[s] if step == 1
                when Label
                        case step
                        when 1
                                if lastgoto and lastgoto.target == s.name
                                        list << lastgoto
                                        list.delete s.name if not hadref
                                end
                        when 2; @statements.delete s if not list.include? s.name
                        end
                when Goto, If
                        s.kind_of?(If) ? g = s.bthen : g = s
                        case step
                        when 1
                                hadref = list.include? g.target
                                lastgoto = g
                                list << g.target
                        when 2
                                if list.include? g
                                        idx = @statements.index s
                                        @statements.delete s
                                        @statements[idx, 0] = s.test if s != g and not s.test.constant?
                                end
                        end
                end
        }
        list
end
return_label() click to toggle source
# File metasm/compile_c.rb, line 542
def return_label ; defined?(@return_label) ? @return_label : @outer.return_label end
return_label=(l) click to toggle source
# File metasm/compile_c.rb, line 543
def return_label=(l) @return_label = l end
struct_ancestors() click to toggle source
# File metasm/parse_c.rb, line 45
def struct_ancestors
        @outer ? @outer.struct_ancestors.merge(@struct) : @struct
end
symbol_ancestors() click to toggle source
# File metasm/parse_c.rb, line 49
def symbol_ancestors
        @outer ? @outer.symbol_ancestors.merge(@symbol) : @symbol
end
to_s() click to toggle source
# File metasm/parse_c.rb, line 3348
def to_s() dump(nil)[0].join("\n") end