[Qt]REGRESSION(r92254): It made 2 tests timeout
[WebKit-https.git] / Source / JavaScriptCore / offlineasm / transform.rb
1 # Copyright (C) 2011 Apple Inc. All rights reserved.
2 #
3 # Redistribution and use in source and binary forms, with or without
4 # modification, are permitted provided that the following conditions
5 # are met:
6 # 1. Redistributions of source code must retain the above copyright
7 #    notice, this list of conditions and the following disclaimer.
8 # 2. Redistributions in binary form must reproduce the above copyright
9 #    notice, this list of conditions and the following disclaimer in the
10 #    documentation and/or other materials provided with the distribution.
11 #
12 # THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
13 # AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
14 # THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
15 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
16 # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
17 # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
18 # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
19 # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
20 # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
21 # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
22 # THE POSSIBILITY OF SUCH DAMAGE.
23
24 require "ast"
25
26 #
27 # node.resolveSettings(settings)
28 #
29 # Construct a new AST that does not have any IfThenElse nodes by
30 # substituting concrete boolean values for each Setting.
31 #
32
33 class Node
34     def resolveSettings(settings)
35         mapChildren {
36             | child |
37             child.resolveSettings(settings)
38         }
39     end
40 end
41
42 class True
43     def resolveSettings(settings)
44         self
45     end
46 end
47
48 class False
49     def resolveSettings(settings)
50         self
51     end
52 end
53
54 class Setting
55     def resolveSettings(settings)
56         settings[@name].asNode
57     end
58 end
59
60 class And
61     def resolveSettings(settings)
62         (@left.resolveSettings(settings).value and @right.resolveSettings(settings).value).asNode
63     end
64 end
65
66 class Or
67     def resolveSettings(settings)
68         (@left.resolveSettings(settings).value or @right.resolveSettings(settings).value).asNode
69     end
70 end
71
72 class Not
73     def resolveSettings(settings)
74         (not @child.resolveSettings(settings).value).asNode
75     end
76 end
77
78 class IfThenElse
79     def resolveSettings(settings)
80         if @predicate.resolveSettings(settings).value
81             @thenCase.resolveSettings(settings)
82         else
83             @elseCase.resolveSettings(settings)
84         end
85     end
86 end
87
88 class Sequence
89     def resolveSettings(settings)
90         newList = []
91         @list.each {
92             | item |
93             item = item.resolveSettings(settings)
94             if item.is_a? Sequence
95                 newList += item.list
96             else
97                 newList << item
98             end
99         }
100         Sequence.new(codeOrigin, newList)
101     end
102 end
103
104 #
105 # node.demacroify(macros)
106 # node.substitute(mapping)
107 #
108 # demacroify() constructs a new AST that does not have any Macro
109 # nodes, while substitute() replaces Variable nodes with the given
110 # nodes in the mapping.
111 #
112
113 class Node
114     def demacroify(macros)
115         mapChildren {
116             | child |
117             child.demacroify(macros)
118         }
119     end
120     
121     def substitute(mapping)
122         mapChildren {
123             | child |
124             child.substitute(mapping)
125         }
126     end
127     
128     def substituteLabels(mapping)
129         mapChildren {
130             | child |
131             child.substituteLabels(mapping)
132         }
133     end
134 end
135
136 class Macro
137     def substitute(mapping)
138         myMapping = {}
139         mapping.each_pair {
140             | key, value |
141             unless @variables.include? key
142                 myMapping[key] = value
143             end
144         }
145         mapChildren {
146             | child |
147             child.substitute(myMapping)
148         }
149     end
150 end
151
152 class Variable
153     def substitute(mapping)
154         if mapping[self]
155             mapping[self]
156         else
157             self
158         end
159     end
160 end
161
162 class LocalLabel
163     def substituteLabels(mapping)
164         if mapping[self]
165             mapping[self]
166         else
167             self
168         end
169     end
170 end
171
172 class Sequence
173     def substitute(constants)
174         newList = []
175         myConstants = constants.dup
176         @list.each {
177             | item |
178             if item.is_a? ConstDecl
179                 myConstants[item.variable] = item.value.substitute(myConstants)
180             else
181                 newList << item.substitute(myConstants)
182             end
183         }
184         Sequence.new(codeOrigin, newList)
185     end
186     
187     def renameLabels(comment)
188         mapping = {}
189         
190         @list.each {
191             | item |
192             if item.is_a? LocalLabel
193                 mapping[item] = LocalLabel.unique(if comment then comment + "_" else "" end + item.cleanName)
194             end
195         }
196         
197         substituteLabels(mapping)
198     end
199     
200     def demacroify(macros)
201         myMacros = macros.dup
202         @list.each {
203             | item |
204             if item.is_a? Macro
205                 myMacros[item.name] = item
206             end
207         }
208         newList = []
209         @list.each {
210             | item |
211             if item.is_a? Macro
212                 # Ignore.
213             elsif item.is_a? MacroCall
214                 mapping = {}
215                 myMyMacros = myMacros.dup
216                 raise "Could not find macro #{item.name} at #{item.codeOriginString}" unless myMacros[item.name]
217                 raise "Argument count mismatch for call to #{item.name} at #{item.codeOriginString}" unless item.operands.size == myMacros[item.name].variables.size
218                 item.operands.size.times {
219                     | idx |
220                     if item.operands[idx].is_a? Variable and myMacros[item.operands[idx].name]
221                         myMyMacros[myMacros[item.name].variables[idx].name] = myMacros[item.operands[idx].name]
222                         mapping[myMacros[item.name].variables[idx].name] = nil
223                     elsif item.operands[idx].is_a? Macro
224                         myMyMacros[myMacros[item.name].variables[idx].name] = item.operands[idx]
225                         mapping[myMacros[item.name].variables[idx].name] = nil
226                     else
227                         myMyMacros[myMacros[item.name].variables[idx]] = nil
228                         mapping[myMacros[item.name].variables[idx]] = item.operands[idx]
229                     end
230                 }
231                 newList += myMacros[item.name].body.substitute(mapping).demacroify(myMyMacros).renameLabels(item.name).list
232             else
233                 newList << item.demacroify(myMacros)
234             end
235         }
236         Sequence.new(codeOrigin, newList).substitute({})
237     end
238 end
239
240 #
241 # node.resolveOffsets(offsets, sizes)
242 #
243 # Construct a new AST that has offset values instead of symbolic
244 # offsets.
245 #
246
247 class Node
248     def resolveOffsets(offsets, sizes)
249         mapChildren {
250             | child |
251             child.resolveOffsets(offsets, sizes)
252         }
253     end
254 end
255
256 class StructOffset
257     def resolveOffsets(offsets, sizes)
258         if offsets[self]
259             Immediate.new(codeOrigin, offsets[self])
260         else
261             self
262         end
263     end
264 end
265
266 class Sizeof
267     def resolveOffsets(offsets, sizes)
268         if sizes[self]
269             Immediate.new(codeOrigin, sizes[self])
270         else
271             puts "Could not find #{self.inspect} in #{sizes.keys.inspect}"
272             puts "sizes = #{sizes.inspect}"
273             self
274         end
275     end
276 end
277
278 #
279 # node.fold
280 #
281 # Resolve constant references and compute arithmetic expressions.
282 #
283
284 class Node
285     def fold
286         mapChildren {
287             | child |
288             child.fold
289         }
290     end
291 end
292
293 class AddImmediates
294     def fold
295         @left = @left.fold
296         @right = @right.fold
297         return self unless @left.is_a? Immediate
298         return self unless @right.is_a? Immediate
299         Immediate.new(codeOrigin, @left.value + @right.value)
300     end
301 end
302
303 class SubImmediates
304     def fold
305         @left = @left.fold
306         @right = @right.fold
307         return self unless @left.is_a? Immediate
308         return self unless @right.is_a? Immediate
309         Immediate.new(codeOrigin, @left.value - @right.value)
310     end
311 end
312
313 class MulImmediates
314     def fold
315         @left = @left.fold
316         @right = @right.fold
317         return self unless @left.is_a? Immediate
318         return self unless @right.is_a? Immediate
319         Immediate.new(codeOrigin, @left.value * @right.value)
320     end
321 end
322
323 class NegImmediate
324     def fold
325         @child = @child.fold
326         return self unless @child.is_a? Immediate
327         Immediate.new(codeOrigin, -@child.value)
328     end
329 end
330
331 #
332 # node.resolveAfterSettings(offsets, sizes)
333 #
334 # Compile assembly against a set of offsets.
335 #
336
337 class Node
338     def resolve(offsets, sizes)
339         demacroify({}).resolveOffsets(offsets, sizes).fold
340     end
341 end
342