source: trunk/lib_c/cpp2c/passes.rb @ 4051

Last change on this file since 4051 was 3396, checked in by linmengl, 6 years ago

handle bitblock_iterator.hpp correctly now

File size: 4.7 KB
RevLine 
[3393]1class BasePass 
2        def t line
3                line
4        end
5
6        def output_header outfile, options
7        end
8
9        def output_tail outfile, options
10        end
11
12        def translate options
13                infile_buff = []
14                File.open(options[:input], "r") do |infile|                     
15                        while (line = infile.gets)
16                                infile_buff << line
17                        end
18                end
19
20                File.open(options[:output], "w") do |outfile|                   
21                        output_header outfile, options
22
23                        for line in infile_buff
24                                newline = self.t line
25                                outfile.puts(newline) if newline != "<empty>"
26                        end                     
27                       
28                        output_tail outfile, options
29                end
30
31                if options[:del_origin]
32                        puts `rm #{options[:input]}`   
33                end             
34        end
35end
36
37# Add some info in the header of output
38class OutputInfoPass < BasePass
39        def output_header outfile, options
40                outfile.puts "/* GENERATED CODE, DON'T MODIFY."
41                outfile.puts " * Use IDISA C support, by cpp2c.rb */"
42                outfile.puts ""
43        end
44end
45
46# Port IDISA calls
47# e.g
48#       simd<64>::add(a, b) => simd_add_{{{64}}}(a, b)
49#       simd<64>::srli<63>(a) => simd_srli_{{{64}}}(63, a)
50#   esimd<BLOCK_SIZE/2>::mergel => esimd_mergel_{{{BLOCK_SIZE/2}}}
51class IDISAPass < BasePass     
52        def basic_t line
53                # format_2: opPattern = 0
54                #       class_name<fw>::op(data_type arg, ...)
55                f2 = /(simd\d*|hsimd\d*|esimd\d*|mvmd\d*|bitblock\d*)\<([^>]*)\>::(\w*)\(/
56                m = line.match f2
57                if m
58                        calling = "#{m[1]}_#{m[3]}_{{{#{m[2]}}}}("
59                        line.gsub!(m[0], calling)
60                end
61
62                # format_3: opPattern = 1
63                #       class_name<fw>::op<x>(data_type arg, ...)               
64                f3 = /(simd\d*|hsimd\d*|esimd\d*|mvmd\d*|bitblock\d*)\<([^>]*)\>::(\w*)\<([^>]*)\>\(/
65                m = line.match f3
66                if m
67                        calling = "#{m[1]}_#{m[3]}_{{{#{m[2]}}}}(#{m[4]}, "
68                        line.gsub! m[0], calling
69                end
70
71                # format_4: opPattern = 3
72                #       class_name::op(data_type arg, ...)
73                f4 = /(bitblock\d*)::(\w*)\(/
74                m = line.match f4
75                if m
76                        calling = "#{m[1]}_#{m[2]}("
77                        line.gsub! m[0], calling
78                end
79
80                # format_5: opPattern = 4
81                #       class_name::op<x>(data_type arg, ...)           
82                f5 = /(bitblock\d*)::(\w*)\<([^>]*)\>\(/
83                m = line.match f5
84                if m
85                        calling = "#{m[1]}_#{m[2]}(#{m[3]}, "
86                        line.gsub! m[0], calling
87                end
88
89                # remove redundant comma, e.g. simd_op(, 1) into simd_op(1)
90                line.gsub! /(?<=\(),\s(?=\w+)/, ""
91                # cont. bitblock_srli(sh, ) into bitlblock_srli()
92                line.gsub! /(?<=[\s\w]),\s+(?=\))/, ""
93
94                # Another hack here. simd128 class is basically simd in IDISA C
95                line.gsub! /\b(simd|hsimd|mvmd|esimd)128/, "\\1"
96
97                line
98        end
99
100        def t line
101                begin
102                        last = line.clone
103                        line = self.basic_t line
104                end while last != line
105                line
106        end
107end
108
109# Port all cpp lines started with '#', like '#include', '#ifndef'
110class SharpPass < BasePass
111        def t line
112                if line =~ /^\#/
113                        line.gsub!(/_HPP/, "_H")
114                        line.gsub!("idisa.hpp", "idisa128_c.h")
115                        line.gsub!("idisa128.hpp", "idisa128_c.h")
116                        line.gsub!(/.hpp\"/, ".h\"")
117                end
118
119                line
120        end
121end
122
[3396]123# use #if #else #end to wrap KEYs as field width
[3393]124# e.g.
125#   #define Carry0 simd<BLOCK_SIZE>::constant<0>()
126#   #define Carry1 simd<BLOCK_SIZE>::constant<1>()
127# After this pass, will become:
128#       #if (BLOCK_SIZE == 128)
129#           #define Carry0 simd_constant_128(0)
130#           #define Carry1 simd_constant_128(1)
131#       #else
132#           #define Carry0 simd_constant_256(0)
133#           #define Carry1 simd_constant_256(1)
134#       #endif
135class ConditionWrapPass < BasePass
136        # e.g. key = "BLOCK_SIZE", values = [128, 256]
137        def initialize key, values             
138                @key = key
[3396]139                @reg_key = Regexp.escape(key)
[3393]140                @values = values
141        end
142
143        def output_header outfile, options
144                @line_store = ""
145        end
146
147        def dump
148                return "" if @line_store == ""
149
150                res = ""               
151                @values.each_with_index do |v, i| 
152                        if i == 0
153                                res += "#if (#{@key} == #{v}) \n"
154                        elsif i == @values.size - 1
[3396]155                                res += "#else //#{@key} == #{v}\n"
[3393]156                        else
157                                res += "#elif (#{@key} == #{v})\n"
158                        end
159
[3396]160                        res += @line_store.gsub /(\{\{\{[^}]*)#{@reg_key}/, "\\1#{v}"
[3393]161                end
162                res += "#endif\n"
163
164                @line_store = ""
165                res
166        end
167
168        def output_tail outfile, options               
[3396]169                res = dump
170                outfile.puts res if res != ""
[3393]171        end
172
173        def t line
[3396]174                if line =~ /\{\{\{.*#{@reg_key}/
[3393]175                        @line_store += line
176                        "<empty>"
177                else
178                        dump + line
179                end
180        end     
181end
182
[3396]183# Slightly different wrap, use "if" insted of "#if"
184# In order to enable "sizeof()" as wrap condition
185class ConditionWrapPass1 < ConditionWrapPass
186        def dump
187                return "" if @line_store == ""
188
189                res = ""               
190                @values.each_with_index do |v, i| 
191                        if i == 0
192                                res += "if (#{@key} == #{v}) {\n"
193                        elsif i == @values.size - 1
194                                res += "} else { //#{@key} == #{v}\n"
195                        else
196                                res += "} else if (#{@key} == #{v}) {\n"
197                        end
198
199                        res += @line_store.gsub /(\{\{\{[^}]*)#{@reg_key}/, "\\1#{v}"
200                end
201                res += "}\n"
202
203                @line_store = ""
204                res
205        end
206end
207
[3393]208# Eval expressions inside {{{ }}}
209# e.g. {{{256 / 2}}} => 128
210class EvaluationPass < BasePass
211        def t line
212                # Eval all the math inside {{{ }}}, I LOVE RUBY!!!!
213                line.gsub(/\{\{\{([^\{\}]*)\}\}\}/) { eval($1) }
214        end
215end
Note: See TracBrowser for help on using the repository browser.