Class: Crokus::CFGBuilder

Inherits:
Transformer show all
Defined in:
lib/crokus/cfg_builder.rb

Instance Attribute Summary

Attributes inherited from Transformer

#code

Instance Method Summary collapse

Methods inherited from Transformer

#transform, #visitAddressOf, #visitArrayOf, #visitArrayOrStructInit, #visitArrow, #visitBinary, #visitCase, #visitCastedExpr, #visitCasting, #visitCharLit, #visitCommaStmt, #visitCondExpr, #visitDecl, #visitDefine, #visitDeref, #visitDesignUnit, #visitDotted, #visitFloatLit, #visitFormalArg, #visitFunctionProto, #visitGoto, #visitIdent, #visitInclude, #visitIndexed, #visitIntLit, #visitLabelledStmt, #visitParenth, #visitPointerTo, #visitSizeof, #visitStrLit, #visitStruct, #visitToken, #visitType, #visitTypedef, #visitUnary

Constructor Details

#initializeCFGBuilder

Returns a new instance of CFGBuilder.



12
13
14
15
# File 'lib/crokus/cfg_builder.rb', line 12

def initialize
  @ind=-2
  @verbose=false
end

Instance Method Details

#build(ast) ⇒ Object



17
18
19
# File 'lib/crokus/cfg_builder.rb', line 17

def build ast
  ast.accept(self)
end

#visitAssign(assign, args = nil) ⇒ Object

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



39
40
41
# File 'lib/crokus/cfg_builder.rb', line 39

def visitAssign assign,args=nil
  @current << assign
end

#visitBody(body, args = nil) ⇒ Object



35
36
37
# 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) ⇒ Object



77
78
79
80
81
82
# 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) ⇒ Object



84
85
86
87
88
89
# 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) ⇒ Object



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
# 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) ⇒ Object



111
112
113
# File 'lib/crokus/cfg_builder.rb', line 111

def visitElse else_,args=nil
  else_.body.accept(self)
end

#visitFor(for_, args = nil) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# 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) ⇒ Object



131
132
133
# File 'lib/crokus/cfg_builder.rb', line 131

def visitFunCall fcall,args=nil
  @current << fcall
end

#visitFunction(func, args = nil) ⇒ Object



21
22
23
24
25
26
27
28
29
30
31
32
33
# 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) ⇒ Object



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# 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) ⇒ Object



43
44
45
# File 'lib/crokus/cfg_builder.rb', line 43

def visitLabeledStmt assign,args=nil
  @current << assign
end

#visitPostFixAccu(accu, args = nil) ⇒ Object



51
52
53
# File 'lib/crokus/cfg_builder.rb', line 51

def visitPostFixAccu accu,args=nil
  @current << accu
end

#visitPreFixAccu(accu, args = nil) ⇒ Object



47
48
49
# File 'lib/crokus/cfg_builder.rb', line 47

def visitPreFixAccu accu,args=nil
  @current << accu
end

#visitReturn(ret, args = nil) ⇒ Object



157
158
159
# File 'lib/crokus/cfg_builder.rb', line 157

def visitReturn ret,args=nil
  @current << ret
end

#visitSwitch(switch, args = nil) ⇒ Object



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# 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) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# 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