]> git.saurik.com Git - apple/javascriptcore.git/blob - offlineasm/transform.rb
JavaScriptCore-1097.3.tar.gz
[apple/javascriptcore.git] / 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 class OrImmediates
332 def fold
333 @left = @left.fold
334 @right = @right.fold
335 return self unless @left.is_a? Immediate
336 return self unless @right.is_a? Immediate
337 Immediate.new(codeOrigin, @left.value | @right.value)
338 end
339 end
340
341 class AndImmediates
342 def fold
343 @left = @left.fold
344 @right = @right.fold
345 return self unless @left.is_a? Immediate
346 return self unless @right.is_a? Immediate
347 Immediate.new(codeOrigin, @left.value & @right.value)
348 end
349 end
350
351 class XorImmediates
352 def fold
353 @left = @left.fold
354 @right = @right.fold
355 return self unless @left.is_a? Immediate
356 return self unless @right.is_a? Immediate
357 Immediate.new(codeOrigin, @left.value ^ @right.value)
358 end
359 end
360
361 class BitnotImmediate
362 def fold
363 @child = @child.fold
364 return self unless @child.is_a? Immediate
365 Immediate.new(codeOrigin, ~@child.value)
366 end
367 end
368
369 #
370 # node.resolveAfterSettings(offsets, sizes)
371 #
372 # Compile assembly against a set of offsets.
373 #
374
375 class Node
376 def resolve(offsets, sizes)
377 demacroify({}).resolveOffsets(offsets, sizes).fold
378 end
379 end
380
381 #
382 # node.validate
383 #
384 # Checks that the node is ready for backend compilation.
385 #
386
387 class Node
388 def validate
389 raise "Unresolved #{dump} at #{codeOriginString}"
390 end
391
392 def validateChildren
393 children.each {
394 | node |
395 node.validate
396 }
397 end
398 end
399
400 class Sequence
401 def validate
402 validateChildren
403 end
404 end
405
406 class Immediate
407 def validate
408 end
409 end
410
411 class RegisterID
412 def validate
413 end
414 end
415
416 class FPRegisterID
417 def validate
418 end
419 end
420
421 class Address
422 def validate
423 validateChildren
424 end
425 end
426
427 class BaseIndex
428 def validate
429 validateChildren
430 end
431 end
432
433 class AbsoluteAddress
434 def validate
435 validateChildren
436 end
437 end
438
439 class Instruction
440 def validate
441 validateChildren
442 end
443 end
444
445 class Error
446 def validate
447 end
448 end
449
450 class Label
451 def validate
452 end
453 end
454
455 class LocalLabel
456 def validate
457 end
458 end
459
460 class LabelReference
461 def validate
462 end
463 end
464
465 class LocalLabelReference
466 def validate
467 end
468 end
469
470 class Skip
471 def validate
472 end
473 end
474