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