Class: Crokus::RandomGen

Inherits:
Object
  • Object
show all
Defined in:
lib/crokus/cfg_random_gen.rb

Constant Summary collapse

ARITH =
{
  :add => "+",
  :sub => "-",
  :mul => "*",
  :div => "/",
  #:shift_r => ">>",
  #:shift_l => "<<",
}
COMP =
{
  :gt  => ">",
  :gte => ">=",
  :lt  => "<",
  :lte => "<=",
  :eq  => "==",
  :neq => "!="

}
COMPA =
[:gt,:lt,:eq,:neq,:gte,:lte]
ACCUM =
[:add_assign,:sub_assign,:mul_assign,:div_assign]
LOGIC =
[:or,:and,:xor]
MINUS =
Token.new [:sub,"-",[0,0]]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = {}) ⇒ RandomGen

Returns a new instance of RandomGen.



19
20
21
# File 'lib/crokus/cfg_random_gen.rb', line 19

def initialize options={}
  @options=options
end

Instance Attribute Details

#cfgObject

Returns the value of attribute cfg.



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

def cfg
  @cfg
end

#optionsObject

Returns the value of attribute options.



16
17
18
# File 'lib/crokus/cfg_random_gen.rb', line 16

def options
  @options
end

Instance Method Details

#create_assignObject



208
209
210
211
212
# File 'lib/crokus/cfg_random_gen.rb', line 208

def create_assign
  lhs=create_assignee
  rhs=create_expression()
  Assign.new(lhs,ASSIGN,rhs)
end

#create_assigneeObject



214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/crokus/cfg_random_gen.rb', line 214

def create_assignee
  if @params["nb_int_arrays"]>0
    case r=rand(0..10)
    when 0..3
      name,size=@cfg.infos["internal_arrays"].sample.first
      var=@readables.sample
      @readables.rotate!
      abs_func=Ident.new(Token.create "abs")
      return Indexed.new(name,FunCall.new(abs_func,[Binary.new(var,MOD,size)]))
    end
  end
  assignee=@vars.first
  @vars.rotate!
  return assignee
end

#create_binary_expression(depth) ⇒ Object



242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/crokus/cfg_random_gen.rb', line 242

def create_binary_expression depth
  if depth <= 1
    lhs=create_unary_expression
    rhs=create_unary_expression
  else
    lhs=create_binary_expression(depth-1)
    rhs=create_binary_expression(depth-1)
  end
  op=create_binary_op
  if op.val=="/" and lhs.to_s=="0"
    return create_binary_expression(depth)
  else
    return Parenth.new(Binary.new(lhs,op,rhs))
  end
end

#create_binary_opObject



282
283
284
285
286
287
288
# File 'lib/crokus/cfg_random_gen.rb', line 282

def create_binary_op
  kind,val=ARITH.sample
  if @params["accept_integer_division"]==false and kind==:div
    return create_binary_op # retry
  end
  Token.new([kind,val,[0,0]])
end

#create_cfgObject



109
110
111
112
113
114
# File 'lib/crokus/cfg_random_gen.rb', line 109

def create_cfg
  puts " |-->[+] building cfg"
  while @cfg.size < @params["nb_basic_blocks"]
    rec_create_bbs
  end
end

#create_cond_opObject



290
291
292
293
# File 'lib/crokus/cfg_random_gen.rb', line 290

def create_cond_op
  kind,val=COMP.sample
  Token.new([kind,val,[0,0]])
end

#create_conditionObject



230
231
232
233
234
235
# File 'lib/crokus/cfg_random_gen.rb', line 230

def create_condition
  lhs=create_expression()
  op =create_cond_op()
  rhs=create_expression()
  Binary.new(lhs,op,rhs)
end

#create_expressionObject



237
238
239
240
# File 'lib/crokus/cfg_random_gen.rb', line 237

def create_expression
  depth=@rng["assigns_expression_depth"].call.to_i
  return create_binary_expression(depth)
end

#create_inputsObject



73
74
75
76
77
78
# File 'lib/crokus/cfg_random_gen.rb', line 73

def create_inputs
  name="in_0"
  @inputs=(1..@params["nb_inputs"]).map{|idx| Ident.new(Token.create name=name.succ)}
  register_readables @inputs
  @cfg.infos["inputs"]=@inputs
end

#create_internal_arraysObject



100
101
102
103
104
105
106
107
# File 'lib/crokus/cfg_random_gen.rb', line 100

def create_internal_arrays
  @cfg.infos["internal_arrays"]||=[]
  (1..@params["nb_int_arrays"]).each do |idx|
    size=@rng["size_int_arrays"].call.to_i
    size=IntLit.new(Token.create(size.to_s))
    @cfg.infos["internal_arrays"] << {Ident.new(Token.create("t#{idx}")) => size}
  end
end

#create_output_assignsObject



93
94
95
96
97
98
# File 'lib/crokus/cfg_random_gen.rb', line 93

def create_output_assigns
  @cfg.infos["output_assigns"]||=[]
  @outputs.each do |ident|
    @cfg.infos["output_assigns"] << {ident => create_expression}
  end
end

#create_outputsObject



80
81
82
83
84
# File 'lib/crokus/cfg_random_gen.rb', line 80

def create_outputs
  name="out_0"
  @outputs=(1..@params["nb_outputs"]).map{|idx| Ident.new(Token.create name=name.succ)}
  @cfg.infos["outputs"]=@outputs
end

#create_unary_expressionObject



295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# File 'lib/crokus/cfg_random_gen.rb', line 295

def create_unary_expression
  r=rand(0..10)
  case r
  when 1
    return IntLit.new Token.create rand(0..255).to_s
  when 2
    return Parenth.new(Unary.new(MINUS,@readables.sample))
  when 3
    name,size=@cfg.infos["internal_arrays"].sample.first
    var=@readables.sample
    abs_func=Ident.new(Token.create "abs")
    index=FunCall.new(abs_func,[Binary.new(var,MOD,size)])
    return Indexed.new(name,index) #eg : t[abs(a % 4)]
  else
    return @readables.sample
  end
end

#create_variablesObject



86
87
88
89
90
91
# File 'lib/crokus/cfg_random_gen.rb', line 86

def create_variables
  name="`" # succ is 'a'
  @vars=(1..@params["nb_int_vars"]).map{|idx| Ident.new(Token.create name=name.succ)}
  register_readables @vars
  @cfg.infos["int_vars"]=@vars
end

#gen_dotObject



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

def gen_dot
  @cfg.print verbose=false
end

#gen_for_block(level) ⇒ Object



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/crokus/cfg_random_gen.rb', line 174

def gen_for_block level
  @cfg << cond_bb     = BasicBlock.new(:start_for => true)
  @index||="idx_0"
  @index=@index.succ
  loop_index=Ident.new Token.create @index
  cond_bb.infos["loop_index"]=loop_index
  @cfg.infos["loop_indexes"]||=[]
  @cfg.infos["loop_indexes"] << loop_index
  cond_bb.infos["loop_index_bound"]=@rng["forloop_iterations"].call.to_i
  @cfg << trueBranch  = BasicBlock.new
  @cfg << falseBranch = BasicBlock.new
  @cfg << postBranch  = BasicBlock.new(:loop_body_end => true)
  @current.to cond_bb
  cond_bb.to trueBranch
  cond_bb.to falseBranch
  @current= trueBranch
  rec_create_bbs(level+1)
  @current.to postBranch
  @current=postBranch
  @current.to cond_bb
  @current=falseBranch
end

#gen_if_block(level) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/crokus/cfg_random_gen.rb', line 140

def gen_if_block level
  @current.infos[:cond]=create_condition
  @current.infos[:start_if]=true
  @cfg << trueBranch =BasicBlock.new
  @cfg << falseBranch=BasicBlock.new
  @cfg << mergeBranch=BasicBlock.new
  @current.to trueBranch
  @current.to falseBranch

  @current=trueBranch
  rec_create_bbs(level+1)
  @current.to mergeBranch

  @current=falseBranch
  rec_create_bbs(level+1)
  @current.to mergeBranch

  @current=mergeBranch
end

#gen_plain_block(level) ⇒ Object



134
135
136
137
138
# File 'lib/crokus/cfg_random_gen.rb', line 134

def gen_plain_block level
  @cfg << bb=BasicBlock.new
  @current.to bb
  @current=bb
end

#gen_while_block(level) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/crokus/cfg_random_gen.rb', line 160

def gen_while_block level
  @cfg << cond_bb     = BasicBlock.new(:start_while => true)
  cond_bb.infos[:cond]=create_condition
  @cfg << trueBranch  = BasicBlock.new
  @cfg << falseBranch = BasicBlock.new
  @current.to cond_bb
  cond_bb.to trueBranch
  cond_bb.to falseBranch
  @current = trueBranch
  rec_create_bbs(level+1)
  @current.to cond_bb
  @current=falseBranch
end

#generate_cObject



313
314
315
# File 'lib/crokus/cfg_random_gen.rb', line 313

def generate_c
  PrinterC.new(options).print(cfg)
end

#init_cfgObject



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

def init_cfg
  @cfg=CFG.new(@params["name"])
  @current=@cfg.starter
end

#init_random_generatorsObject



56
57
58
59
60
61
62
63
64
65
# File 'lib/crokus/cfg_random_gen.rb', line 56

def init_random_generators
  puts " |-->[+] init parameterized random generators"
  @rng={}
  @params.each do |key,val|
    if key.start_with? "avg_"
      name=key[4..-1]
      @rng[name]=Distribution::Normal.rng(mean=val,sigma=0.5) #sigma=1 ?
    end
  end
end

#populate(bb) ⇒ Object



202
203
204
205
206
# File 'lib/crokus/cfg_random_gen.rb', line 202

def populate bb
  @rng["assigns_per_bbs"].call.to_i.times do
    bb << create_assign
  end
end

#populate_allObject



197
198
199
200
# File 'lib/crokus/cfg_random_gen.rb', line 197

def populate_all
  puts " |-->[+] populate cfg"
  @cfg.each{|bb| populate bb}
end


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

def print_infos
  puts " |-->[+] infos about CFG :"
  puts "      |-->[+] #basic blocks : #{@cfg.size}"
end

#rec_create_bbs(level = 0) ⇒ Object



116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/crokus/cfg_random_gen.rb', line 116

def rec_create_bbs level=0
  if @cfg.size < @params["nb_basic_blocks"]
    type = [:plain,:if,:while,:for].sample
    case type
    when :plain
      gen_plain_block(level)
    when :if
      gen_if_block(level)
    when :while
      gen_while_block(level) if @params["accept_while_loops"]
    when :for
      gen_for_block(level)
    else
      raise "unknown cfg type : #{type}"
    end
  end
end

#register_readables(ary) ⇒ Object



67
68
69
70
71
# File 'lib/crokus/cfg_random_gen.rb', line 67

def register_readables ary
  @readables||=[]
  @readables << ary
  @readables.flatten!
end

#run(params) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/crokus/cfg_random_gen.rb', line 23

def run params
  puts "[+] running random C code generation"
  puts " |-->[+] reading parameters file '#{params}'"
  @params=YAML.load(File.read(params))
  init_cfg
  init_random_generators
  create_inputs
  create_outputs
  create_variables
  create_internal_arrays
  create_output_assigns
  create_cfg
  gen_dot # to see the structure, before hacking the content
  populate_all
  generate_c
  print_infos
end