class Crokus::CFGBuilder

Public Class Methods

new() click to toggle source
# File lib/crokus/cfg_builder.rb, line 12
def initialize
  @ind=-2
  @verbose=false
end

Public Instance Methods

build(ast) click to toggle source
# File lib/crokus/cfg_builder.rb, line 17
def build ast
  ast.accept(self)
end
visitAssign(assign,args=nil) click to toggle source

.….……stmts.….….……

# File lib/crokus/cfg_builder.rb, line 39
def visitAssign assign,args=nil
  @current << assign
end
visitBody(body,args=nil) click to toggle source
# File lib/crokus/cfg_builder.rb, line 35
def visitBody body,args=nil
  body.each{|stmt| stmt.accept(self,args)}
end
visitBreak(brk,args=nil) click to toggle source
# File lib/crokus/cfg_builder.rb, line 77
def visitBreak brk,args=nil
  @current << brk
  @current.to @current_break_dest
  @cfg << unreachable = BasicBlock.new
  @current = unreachable
end
visitContinue(cont,args=nil) click to toggle source
# File lib/crokus/cfg_builder.rb, line 84
def visitContinue cont,args=nil
  @current << cont
  @current.to @current_continue_dest
  @cfg << unreachable = BasicBlock.new
  @current = unreachable
end
visitDoWhile(dowhile,args=nil) click to toggle source
# File lib/crokus/cfg_builder.rb, line 161
def visitDoWhile dowhile,args=nil
  @cfg << cond_bb     = BasicBlock.new
  @current_continue_dest = cond_bb # for continue stmt !
  @cfg << trueBranch  = BasicBlock.new
  @cfg << falseBranch = BasicBlock.new

  @current.to trueBranch
  @current = trueBranch
  dowhile.body.accept(self) # may modify @current

  @current.to cond_bb
  @current = cond_bb
  cond=dowhile.cond.accept(self)

  cond_bb << ITE.new(cond,trueBranch,falseBranch)

  cond_bb.to trueBranch
  cond_bb.to falseBranch
  @current = falseBranch
end
visitElse(else_,args=nil) click to toggle source
# File lib/crokus/cfg_builder.rb, line 111
def visitElse else_,args=nil
  else_.body.accept(self)
end
visitFor(for_,args=nil) click to toggle source
# File lib/crokus/cfg_builder.rb, line 135
def visitFor for_,args=nil
  for_.init.each{|stmt| stmt.accept(self)}
  cond=for_.cond.accept(self)
  @cfg << cond_bb     = BasicBlock.new
  @cfg << trueBranch  = BasicBlock.new
  @cfg << falseBranch = BasicBlock.new
  @cfg << postBranch  = BasicBlock.new
  @current_continue_dest = postBranch
  @current_break_dest    = falseBranch
  @current.to cond_bb
  cond_bb << ITE.new(cond,trueBranch,falseBranch)
  cond_bb.to trueBranch
  cond_bb.to falseBranch
  @current= trueBranch
  for_.body.accept(self) #may modify @current identity
  @current.to postBranch
  @current=postBranch
  for_.increment.accept(self)
  @current.to cond_bb
  @current=falseBranch
end
visitFunCall(fcall,args=nil) click to toggle source
# File lib/crokus/cfg_builder.rb, line 131
def visitFunCall fcall,args=nil
  @current << fcall
end
visitFunction(func,args=nil) click to toggle source
# File lib/crokus/cfg_builder.rb, line 21
def visitFunction func,args=nil
  puts " |--[+] visitFunction '#{func.name}'" unless $options[:mute]
  @cfg=CFG.new(func.name)
  @current=@cfg.starter
  func.body.accept(self)
  @cfg.print
  @cfg=CFGCleaner.new.clean(@cfg)
  @cfg=CFGOptimizer.new.clean(@cfg)
  @cfg.name=Ident.new(Token.create "#{@cfg.name}_clean")
  func.cfg=@cfg
  puts " "*5+"|--[+] cfg size for '#{func.name}' : #{@cfg.size}" unless $options[:mute]
  @cfg.print
end
visitIf(if_,args=nil) click to toggle source
# File lib/crokus/cfg_builder.rb, line 91
def visitIf if_,args=nil
  cond=if_.cond.accept(self,:as_expr)
  @cfg << trueBranch =BasicBlock.new
  @cfg << falseBranch=BasicBlock.new
  @cfg << mergeBranch=BasicBlock.new
  @current << ITE.new(cond,trueBranch,falseBranch)

  @current.to trueBranch
  @current.to falseBranch
  #-----------
  @current=trueBranch
  if_.body.accept(self) #may change @current !
  @current.to mergeBranch
  #
  @current=falseBranch
  if_.else.accept(self) if if_.else #may change @current !
  @current.to mergeBranch
  @current=mergeBranch
end
visitLabeledStmt(assign,args=nil) click to toggle source
# File lib/crokus/cfg_builder.rb, line 43
def visitLabeledStmt assign,args=nil
  @current << assign
end
visitPostFixAccu(accu,args=nil) click to toggle source
# File lib/crokus/cfg_builder.rb, line 51
def visitPostFixAccu accu,args=nil
  @current << accu
end
visitPreFixAccu(accu,args=nil) click to toggle source
# File lib/crokus/cfg_builder.rb, line 47
def visitPreFixAccu accu,args=nil
  @current << accu
end
visitReturn(ret,args=nil) click to toggle source
# File lib/crokus/cfg_builder.rb, line 157
def visitReturn ret,args=nil
  @current << ret
end
visitSwitch(switch,args=nil) click to toggle source
# File lib/crokus/cfg_builder.rb, line 55
def visitSwitch switch,args=nil
  @cfg << finalBranch=BasicBlock.new
  @current_break_dest=finalBranch
  for cas in switch.cases
    cond=Binary.new(switch.expr,EQUAL,cas.expr)
    @cfg << trueBranch=BasicBlock.new
    @cfg << falseBranch=BasicBlock.new

    @current << ITE.new(cond,trueBranch,falseBranch)
    @current.to trueBranch
    @current.to falseBranch
    @current = trueBranch
    cas.body.accept(self)
    @current = falseBranch
  end
  if switch.default
    switch.default.accept(self)
    @current.to finalBranch
  end
  @current=finalBranch
end
visitWhile(while_,args=nil) click to toggle source
# File lib/crokus/cfg_builder.rb, line 115
def visitWhile while_,args=nil
  cond=while_.cond.accept(self,:as_expr)
  @cfg << cond_bb     = BasicBlock.new
  @current_cond = cond_bb # for continue stmt !
  @cfg << trueBranch  = BasicBlock.new
  @cfg << falseBranch = BasicBlock.new
  @current.to cond_bb
  cond_bb << ITE.new(cond,trueBranch,falseBranch)
  cond_bb.to trueBranch
  cond_bb.to falseBranch
  @current = trueBranch
  while_.body.accept(self) #may modify identity of @current
  @current.to cond_bb
  @current=falseBranch
end