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

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

add cpp2c.rb script offically, add testing framework

File size: 4.1 KB
Line 
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
123# use #if #else #end to wrap KEYs
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
139                @values = values
140        end
141
142        def output_header outfile, options
143                @line_store = ""
144        end
145
146        def dump
147                return "" if @line_store == ""
148
149                res = ""               
150                @values.each_with_index do |v, i| 
151                        if i == 0
152                                res += "#if (#{@key} == #{v}) \n"
153                        elsif i == @values.size - 1
154                                res += "#else\n"
155                        else
156                                res += "#elif (#{@key} == #{v})\n"
157                        end
158
159                        res += @line_store.gsub /(\{\{\{[^}]*)#{@key}/, "\\1#{v}"
160                end
161                res += "#endif\n"
162
163                @line_store = ""
164                res
165        end
166
167        def output_tail outfile, options               
168                outfile.puts dump
169        end
170
171        def t line
172                if line =~ /\{\{\{.*#{@key}\b/
173                        @line_store += line
174                        "<empty>"
175                else
176                        dump + line
177                end
178        end     
179end
180
181# Eval expressions inside {{{ }}}
182# e.g. {{{256 / 2}}} => 128
183class EvaluationPass < BasePass
184        def t line
185                # Eval all the math inside {{{ }}}, I LOVE RUBY!!!!
186                line.gsub(/\{\{\{([^\{\}]*)\}\}\}/) { eval($1) }
187        end
188end
Note: See TracBrowser for help on using the repository browser.