crokus 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ef8bbae26ccb8fc2b32c8dd40bf6635272055ba5e158a0ed9b7e22aead35018a
4
- data.tar.gz: 922d2ce547b6875e8cb99364f0ca5ba2edfd0c066cd888065bb84149a07a32c3
3
+ metadata.gz: 852a2b5bdf274b42fa37edba80142da8b481cad7203637a5b86ab7a5b83f7b10
4
+ data.tar.gz: f199ddb9ac49df0c8bb5a456c332677ccb2cbd21baa469d0cee514d400b4ae78
5
5
  SHA512:
6
- metadata.gz: 72bc1089bcbc9edb53afb4e3bada17d4daa19b5e174c22516be36755e10478facadf68a6651edf6e9eb4c8574ad8fa82203b73b1a7c947f117080bcb3296755e
7
- data.tar.gz: ca37c64d365528a95548ce2517d3f92bdd90ad62f071609695aebdb6b64e21f8e0b9ea6e525b495d7ec4d77ac5c24ae08e7d23a129aa87551d141edc8b860d91
6
+ metadata.gz: ec54d76cffdfeeb764fcc06463fd67b01b88dd642246496f6d6de07d5462113e3fda0e34af0bf60750552397e14be4d6cd1d36eec0a6fd8d27ed88cdd27ea1f3
7
+ data.tar.gz: 602f8152c74bda51fde3c991fa969192d3a2c542688650b822158fdcfab654d7ac62cb869b9243d3d512b880c168938d8e9848388cb2f5c097f0c46a853b7502
@@ -0,0 +1,199 @@
1
+ module Crokus
2
+
3
+ class PrinterC
4
+
5
+ attr_accessor :cfg
6
+
7
+ def initialize
8
+ @visited=[]
9
+ @prp=PrettyPrinter.new
10
+ end
11
+
12
+ def print cfg
13
+ puts " |-->[+] generating C code from cfg '#{cfg.name}'"
14
+ @cfg=cfg
15
+ code=Code.new
16
+ code << "//"+"-"*60
17
+ code << "// automatically generated by Crokus compiler"
18
+ code << "// date : #{Time.now.strftime("%a %d,%B %Y - %H:%M:%S")}"
19
+ code << "//"+"-"*60
20
+ code.newline
21
+ code << "#include <stdio.h>"
22
+ code << "#include <stdlib.h>"
23
+ code.newline
24
+ io=[decl_inputs,decl_outputs].join(',')
25
+ code << "int #{cfg.name}(#{io}){"
26
+ code.indent=2
27
+ code << decl_vars()
28
+ code << decl_loop_indexes()
29
+ code << decl_arrays()
30
+ code << visit_rec(cfg.starter)
31
+ code << output_assigns()
32
+ code << "return 0;"
33
+ code.indent=0
34
+ code << "}"
35
+ code.newline
36
+ code << main(cfg)
37
+ puts code.finalize
38
+ code.save_as "#{cfg.name}.c"
39
+ end
40
+
41
+ def main cfg
42
+ code=Code.new
43
+ code << "int main(void){"
44
+ code.indent=2
45
+ inputs,outputs=[],[]
46
+ cfg.infos["inputs"].each do |input|
47
+ code << "int #{input} = #{rand 0..255};"
48
+ inputs << input
49
+ end
50
+ cfg.infos["outputs"].each do |output|
51
+ code << "int #{output};"
52
+ outputs << "&#{output}"
53
+ end
54
+ params=[inputs,outputs].flatten.join(',')
55
+ code << "#{cfg.name}(#{params});"
56
+ cfg.infos["outputs"].each do |output|
57
+ code << "printf(\"#{output} = %d\\n\",#{output});"
58
+ end
59
+ code << "return 0;"
60
+ code.indent=0
61
+ code << "}"
62
+ code
63
+ end
64
+
65
+ def decl_inputs
66
+ if h=cfg.infos["inputs"]
67
+ return h.map{|ident| "int #{ident}"}
68
+ end
69
+ end
70
+
71
+ def decl_outputs
72
+ if h=cfg.infos["outputs"]
73
+ return h.map{|ident| "int *#{ident}"}
74
+ end
75
+ end
76
+
77
+ def decl_vars
78
+ code=Code.new
79
+ if h=cfg.infos["int_vars"]
80
+ h.each{|ident| code << "int #{ident} = #{rand(0..255)};"}
81
+ end
82
+ code.newline
83
+ code
84
+ end
85
+
86
+ def decl_loop_indexes
87
+ code=Code.new
88
+ if cfg.infos["loop_indexes"]
89
+ code << "// loop indexes"
90
+ cfg.infos["loop_indexes"].each do |index|
91
+ code << "int #{index};"
92
+ end
93
+ code.newline
94
+ end
95
+ code
96
+ end
97
+
98
+ def decl_arrays
99
+ code=Code.new
100
+ cfg.infos["internal_arrays"].each do |h|
101
+ name,size_lit=h.first
102
+ size_int=size_lit.to_s.to_i
103
+ init=Array.new(size_int){rand(255)}.join(",")
104
+ size=size_lit.accept(@prp)
105
+ code << "int #{name}[#{size}] ={#{init}};"
106
+ end
107
+ code.newline
108
+ code
109
+ end
110
+
111
+ def output_assigns
112
+ code=Code.new
113
+ code.newline
114
+ code << "//------- output assignments ------"
115
+ if ary=cfg.infos["output_assigns"]
116
+ ary.each{|h|
117
+ out,expr=h.first
118
+ rhs=expr.accept(@prp)
119
+ code << "*#{out} = #{rhs};"
120
+ }
121
+ end
122
+ code
123
+ end
124
+
125
+ def visit_rec bb
126
+ unless bb.nil? or @visited.include?(bb)
127
+ if bb.infos[:start_if]
128
+ gen_if(bb)
129
+ elsif bb.infos[:start_while]
130
+ gen_while(bb)
131
+ elsif bb.infos[:start_for]
132
+ gen_for(bb)
133
+ else
134
+ gen_plain(bb)
135
+ end
136
+ end
137
+ end
138
+
139
+ def gen_plain bb
140
+ code=Code.new
141
+ @visited << bb
142
+ #code << "// bb #{bb.label}"
143
+ bb.stmts.each{|assign|
144
+ code << assign.accept(@prp)
145
+ }
146
+ code << visit_rec(bb.nextBranch)
147
+ code
148
+ end
149
+
150
+ def gen_if bb
151
+ code=Code.new
152
+ @visited << bb
153
+ #code << "// bb 'if' #{bb.label}"
154
+ bb.stmts.each{|stmt| code << stmt.accept(@prp)}
155
+ cond=bb.infos[:cond].accept(@prp)
156
+ code << "if (#{cond}){"
157
+ code.indent=2
158
+ code << visit_rec(bb.trueBranch)
159
+ code.indent=0
160
+ code << "}"
161
+ code << "else {"
162
+ code.indent=2
163
+ code << visit_rec(bb.falseBranch)
164
+ code.indent=0
165
+ code << "}"
166
+ code
167
+ end
168
+
169
+ def gen_while bb
170
+ code=Code.new
171
+ @visited << bb
172
+ bb.stmts.each{|stmt| code << stmt.accept(@prp)}
173
+ cond=bb.infos[:cond].accept(@prp)
174
+ code << "while (#{cond}){"
175
+ code.indent=2
176
+ code << visit_rec(bb.trueBranch)
177
+ code.indent=0
178
+ code << "}"
179
+ code << visit_rec(bb.falseBranch)
180
+ code
181
+ end
182
+
183
+ def gen_for bb
184
+ code=Code.new
185
+ @visited << bb
186
+ #code << "// bb 'for' #{bb.label}"
187
+ bb.stmts.each{|stmt| code << stmt.accept(@prp)}
188
+ index=bb.infos["loop_index"]
189
+ index_bound=bb.infos["loop_index_bound"]
190
+ code << "for(#{index}=0;#{index} < #{index_bound};#{index}++){"
191
+ code.indent=2
192
+ code << visit_rec(bb.trueBranch)
193
+ code.indent=0
194
+ code << "}"
195
+ code << visit_rec(bb.falseBranch)
196
+ code
197
+ end
198
+ end
199
+ end
@@ -0,0 +1,312 @@
1
+ require 'yaml'
2
+ require 'distribution'
3
+
4
+ require_relative 'cfg_printer_c'
5
+
6
+ class Hash
7
+ def sample
8
+ k=keys.sample
9
+ [k,self[k]]
10
+ end
11
+ end
12
+
13
+ module Crokus
14
+
15
+ class RandomGen
16
+ attr_accessor :cfg
17
+
18
+ def run params
19
+ puts "[+] running random C generation"
20
+ puts " |-->[+] reading parameters file '#{params}'"
21
+ @params=YAML.load(File.read(params))
22
+ init_cfg
23
+ init_random_generators
24
+ create_inputs
25
+ create_outputs
26
+ create_variables
27
+ create_internal_arrays
28
+ create_output_assigns
29
+ create_cfg
30
+ gen_dot # to see the structure, before hacking the content
31
+ populate_all
32
+ generate_c
33
+ #print_infos
34
+ end
35
+
36
+
37
+ def print_infos
38
+ puts " |-->[+] infos about CFG :"
39
+ puts " |-->[+] #basic blocks : #{@cfg.size}"
40
+ end
41
+
42
+ def gen_dot
43
+ @cfg.print verbose=false
44
+ end
45
+
46
+ def init_cfg
47
+ @cfg=CFG.new(@params["name"])
48
+ @current=@cfg.starter
49
+ end
50
+
51
+ def init_random_generators
52
+ puts " |-->[+] init parameterized random generators"
53
+ @rng={}
54
+ @params.each do |key,val|
55
+ if key.start_with? "avg_"
56
+ name=key[4..-1]
57
+ @rng[name]=Distribution::Normal.rng(mean=val,sigma=0.5) #sigma=1 ?
58
+ end
59
+ end
60
+ end
61
+
62
+ def register_readables ary
63
+ @readables||=[]
64
+ @readables << ary
65
+ @readables.flatten!
66
+ end
67
+
68
+ def create_inputs
69
+ name="in_0"
70
+ @inputs=(1..@params["nb_inputs"]).map{|idx| Ident.new(Token.create name=name.succ)}
71
+ register_readables @inputs
72
+ @cfg.infos["inputs"]=@inputs
73
+ end
74
+
75
+ def create_outputs
76
+ name="out_0"
77
+ @outputs=(1..@params["nb_outputs"]).map{|idx| Ident.new(Token.create name=name.succ)}
78
+ @cfg.infos["outputs"]=@outputs
79
+ end
80
+
81
+ def create_variables
82
+ name="`" # succ is 'a'
83
+ @vars=(1..@params["nb_int_vars"]).map{|idx| Ident.new(Token.create name=name.succ)}
84
+ register_readables @vars
85
+ @cfg.infos["int_vars"]=@vars
86
+ end
87
+
88
+ def create_output_assigns
89
+ @cfg.infos["output_assigns"]||=[]
90
+ @outputs.each do |ident|
91
+ @cfg.infos["output_assigns"] << {ident => create_expression}
92
+ end
93
+ end
94
+
95
+ def create_internal_arrays
96
+ @cfg.infos["internal_arrays"]||=[]
97
+ (1..@params["nb_int_arrays"]).each do |idx|
98
+ size=@rng["size_int_arrays"].call.to_i
99
+ size=IntLit.new(Token.create(size.to_s))
100
+ @cfg.infos["internal_arrays"] << {Ident.new(Token.create("t#{idx}")) => size}
101
+ end
102
+ end
103
+
104
+ def create_cfg
105
+ puts " |-->[+] building cfg"
106
+ while @cfg.size < @params["nb_basic_blocks"]
107
+ rec_create_bbs
108
+ end
109
+ end
110
+
111
+ def rec_create_bbs level=0
112
+ if @cfg.size < @params["nb_basic_blocks"]
113
+ type = [:plain,:if,:while,:for].sample
114
+ case type
115
+ when :plain
116
+ gen_plain_block(level)
117
+ when :if
118
+ gen_if_block(level)
119
+ when :while
120
+ gen_while_block(level) if @params["accept_while_loops"]
121
+ when :for
122
+ gen_for_block(level)
123
+ else
124
+ raise "unknown cfg type : #{type}"
125
+ end
126
+ end
127
+ end
128
+
129
+ def gen_plain_block level
130
+ @cfg << bb=BasicBlock.new
131
+ @current.to bb
132
+ @current=bb
133
+ end
134
+
135
+ def gen_if_block level
136
+ @current.infos[:cond]=create_condition
137
+ @current.infos[:start_if]=true
138
+ @cfg << trueBranch =BasicBlock.new
139
+ @cfg << falseBranch=BasicBlock.new
140
+ @cfg << mergeBranch=BasicBlock.new
141
+ @current.to trueBranch
142
+ @current.to falseBranch
143
+
144
+ @current=trueBranch
145
+ rec_create_bbs(level+1)
146
+ @current.to mergeBranch
147
+
148
+ @current=falseBranch
149
+ rec_create_bbs(level+1)
150
+ @current.to mergeBranch
151
+
152
+ @current=mergeBranch
153
+ end
154
+
155
+ def gen_while_block level
156
+ @cfg << cond_bb = BasicBlock.new(:start_while => true)
157
+ cond_bb.infos[:cond]=create_condition
158
+ @cfg << trueBranch = BasicBlock.new
159
+ @cfg << falseBranch = BasicBlock.new
160
+ @current.to cond_bb
161
+ cond_bb.to trueBranch
162
+ cond_bb.to falseBranch
163
+ @current = trueBranch
164
+ rec_create_bbs(level+1)
165
+ @current.to cond_bb
166
+ @current=falseBranch
167
+ end
168
+
169
+ def gen_for_block level
170
+ @cfg << cond_bb = BasicBlock.new(:start_for => true)
171
+ @index||="idx_0"
172
+ @index=@index.succ
173
+ loop_index=Ident.new Token.create @index
174
+ cond_bb.infos["loop_index"]=loop_index
175
+ @cfg.infos["loop_indexes"]||=[]
176
+ @cfg.infos["loop_indexes"] << loop_index
177
+ cond_bb.infos["loop_index_bound"]=@rng["forloop_iterations"].call.to_i
178
+ @cfg << trueBranch = BasicBlock.new
179
+ @cfg << falseBranch = BasicBlock.new
180
+ @cfg << postBranch = BasicBlock.new(:loop_body_end => true)
181
+ @current.to cond_bb
182
+ cond_bb.to trueBranch
183
+ cond_bb.to falseBranch
184
+ @current= trueBranch
185
+ rec_create_bbs(level+1)
186
+ @current.to postBranch
187
+ @current=postBranch
188
+ @current.to cond_bb
189
+ @current=falseBranch
190
+ end
191
+
192
+ def populate_all
193
+ puts " |-->[+] populate cfg"
194
+ @cfg.each{|bb| populate bb}
195
+ end
196
+
197
+ def populate bb
198
+ @rng["assigns_per_bbs"].call.to_i.times do
199
+ bb << create_assign
200
+ end
201
+ end
202
+
203
+ def create_assign
204
+ lhs=create_assignee
205
+ rhs=create_expression()
206
+ Assign.new(lhs,ASSIGN,rhs)
207
+ end
208
+
209
+ def create_assignee
210
+ if @params["nb_int_arrays"]>0
211
+ case r=rand(0..10)
212
+ when 0..3
213
+ name,size=@cfg.infos["internal_arrays"].sample.first
214
+ var=@readables.sample
215
+ @readables.rotate!
216
+ abs_func=Ident.new(Token.create "abs")
217
+ return Indexed.new(name,FunCall.new(abs_func,[Binary.new(var,MOD,size)]))
218
+ end
219
+ end
220
+ assignee=@vars.first
221
+ @vars.rotate!
222
+ return assignee
223
+ end
224
+
225
+ def create_condition
226
+ lhs=create_expression()
227
+ op =create_cond_op()
228
+ rhs=create_expression()
229
+ Binary.new(lhs,op,rhs)
230
+ end
231
+
232
+ def create_expression
233
+ depth=@rng["assigns_expression_depth"].call.to_i
234
+ return create_binary_expression(depth)
235
+ end
236
+
237
+ def create_binary_expression depth
238
+ if depth <= 1
239
+ lhs=create_unary_expression
240
+ rhs=create_unary_expression
241
+ else
242
+ lhs=create_binary_expression(depth-1)
243
+ rhs=create_binary_expression(depth-1)
244
+ end
245
+ op=create_binary_op
246
+ if op.val=="/" and lhs.to_s=="0"
247
+ return create_binary_expression(depth)
248
+ else
249
+ return Parenth.new(Binary.new(lhs,op,rhs))
250
+ end
251
+ end
252
+
253
+ ARITH={
254
+ :add => "+",
255
+ :sub => "-",
256
+ :mul => "*",
257
+ :div => "/",
258
+ #:shift_r => ">>",
259
+ #:shift_l => "<<",
260
+ }
261
+
262
+ COMP={
263
+ :gt => ">",
264
+ :gte => ">=",
265
+ :lt => "<",
266
+ :lte => "<=",
267
+ :eq => "==",
268
+ :neq => "!="
269
+
270
+ }
271
+
272
+ COMPA=[:gt,:lt,:eq,:neq,:gte,:lte]
273
+ ACCUM=[:add_assign,:sub_assign,:mul_assign,:div_assign]
274
+ LOGIC=[:or,:and,:xor]
275
+ MINUS=Token.new [:sub,"-",[0,0]]
276
+
277
+ def create_binary_op
278
+ kind,val=ARITH.sample
279
+ if @params["accept_integer_division"]==false and kind==:div
280
+ return create_binary_op # retry
281
+ end
282
+ Token.new([kind,val,[0,0]])
283
+ end
284
+
285
+ def create_cond_op
286
+ kind,val=COMP.sample
287
+ Token.new([kind,val,[0,0]])
288
+ end
289
+
290
+ def create_unary_expression
291
+ r=rand(0..10)
292
+ case r
293
+ when 1
294
+ return IntLit.new Token.create rand(0..255).to_s
295
+ when 2
296
+ return Parenth.new(Unary.new(MINUS,@readables.sample))
297
+ when 3
298
+ name,size=@cfg.infos["internal_arrays"].sample.first
299
+ var=@readables.sample
300
+ abs_func=Ident.new(Token.create "abs")
301
+ index=FunCall.new(abs_func,[Binary.new(var,MOD,size)])
302
+ return Indexed.new(name,index) #eg : t[abs(a % 4)]
303
+ else
304
+ return @readables.sample
305
+ end
306
+ end
307
+
308
+ def generate_c
309
+ PrinterC.new.print(cfg)
310
+ end
311
+ end
312
+ end
@@ -1,3 +1,3 @@
1
1
  module Crokus
2
- VERSION="0.0.3"
2
+ VERSION="0.0.4"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: crokus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean-Christophe Le Lann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-03 00:00:00.000000000 Z
11
+ date: 2019-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: distribution
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - '='
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.7.3
27
+ - !ruby/object:Gem::Dependency
28
+ name: colorize
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 0.8.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 0.8.1
27
41
  description: Crokus is developped in Ruby and aims at providing simple basis for C
28
42
  transformations. It has been use for teaching purposes and applied to Electronic
29
43
  System Level experiments.
@@ -41,6 +55,8 @@ files:
41
55
  - lib/crokus/cfg_builder.rb
42
56
  - lib/crokus/cfg_cleaner.rb
43
57
  - lib/crokus/cfg_printer.rb
58
+ - lib/crokus/cfg_printer_c.rb
59
+ - lib/crokus/cfg_random_gen.rb
44
60
  - lib/crokus/cleaner.rb
45
61
  - lib/crokus/code.rb
46
62
  - lib/crokus/compiler.rb