]> git.saurik.com Git - apple/javascriptcore.git/blame - offlineasm/transform.rb
JavaScriptCore-1097.3.3.tar.gz
[apple/javascriptcore.git] / offlineasm / transform.rb
CommitLineData
6fe7ccc8
A
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
24require "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
33class Node
34 def resolveSettings(settings)
35 mapChildren {
36 | child |
37 child.resolveSettings(settings)
38 }
39 end
40end
41
42class True
43 def resolveSettings(settings)
44 self
45 end
46end
47
48class False
49 def resolveSettings(settings)
50 self
51 end
52end
53
54class Setting
55 def resolveSettings(settings)
56 settings[@name].asNode
57 end
58end
59
60class And
61 def resolveSettings(settings)
62 (@left.resolveSettings(settings).value and @right.resolveSettings(settings).value).asNode
63 end
64end
65
66class Or
67 def resolveSettings(settings)
68 (@left.resolveSettings(settings).value or @right.resolveSettings(settings).value).asNode
69 end
70end
71
72class Not
73 def resolveSettings(settings)
74 (not @child.resolveSettings(settings).value).asNode
75 end
76end
77
78class 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
86end
87
88class 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
102end
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
113class 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
134end
135
136class 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
150end
151
152class Variable
153 def substitute(mapping)
154 if mapping[self]
155 mapping[self]
156 else
157 self
158 end
159 end
160end
161
162class LocalLabel
163 def substituteLabels(mapping)
164 if mapping[self]
165 mapping[self]
166 else
167 self
168 end
169 end
170end
171
172class 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
238end
239
240#
241# node.resolveOffsets(offsets, sizes)
242#
243# Construct a new AST that has offset values instead of symbolic
244# offsets.
245#
246
247class Node
248 def resolveOffsets(offsets, sizes)
249 mapChildren {
250 | child |
251 child.resolveOffsets(offsets, sizes)
252 }
253 end
254end
255
256class StructOffset
257 def resolveOffsets(offsets, sizes)
258 if offsets[self]
259 Immediate.new(codeOrigin, offsets[self])
260 else
261 self
262 end
263 end
264end
265
266class 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
276end
277
278#
279# node.fold
280#
281# Resolve constant references and compute arithmetic expressions.
282#
283
284class Node
285 def fold
286 mapChildren {
287 | child |
288 child.fold
289 }
290 end
291end
292
293class 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
301end
302
303class 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
311end
312
313class 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
321end
322
323class NegImmediate
324 def fold
325 @child = @child.fold
326 return self unless @child.is_a? Immediate
327 Immediate.new(codeOrigin, -@child.value)
328 end
329end
330
331class 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
339end
340
341class 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
349end
350
351class 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
359end
360
361class BitnotImmediate
362 def fold
363 @child = @child.fold
364 return self unless @child.is_a? Immediate
365 Immediate.new(codeOrigin, ~@child.value)
366 end
367end
368
369#
370# node.resolveAfterSettings(offsets, sizes)
371#
372# Compile assembly against a set of offsets.
373#
374
375class Node
376 def resolve(offsets, sizes)
377 demacroify({}).resolveOffsets(offsets, sizes).fold
378 end
379end
380
381#
382# node.validate
383#
384# Checks that the node is ready for backend compilation.
385#
386
387class 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
398end
399
400class Sequence
401 def validate
402 validateChildren
403 end
404end
405
406class Immediate
407 def validate
408 end
409end
410
411class RegisterID
412 def validate
413 end
414end
415
416class FPRegisterID
417 def validate
418 end
419end
420
421class Address
422 def validate
423 validateChildren
424 end
425end
426
427class BaseIndex
428 def validate
429 validateChildren
430 end
431end
432
433class AbsoluteAddress
434 def validate
435 validateChildren
436 end
437end
438
439class Instruction
440 def validate
441 validateChildren
442 end
443end
444
445class Error
446 def validate
447 end
448end
449
450class Label
451 def validate
452 end
453end
454
455class LocalLabel
456 def validate
457 end
458end
459
460class LabelReference
461 def validate
462 end
463end
464
465class LocalLabelReference
466 def validate
467 end
468end
469
470class Skip
471 def validate
472 end
473end
474