blob: 2a082555b74a9fc21b5570117f5537ec15affecf [file] [log] [blame]
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +00001# 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
commit-queue@webkit.org782c20b2012-07-14 00:44:47 +000024require "config"
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +000025require "ast"
26
27#
28# node.resolveSettings(settings)
29#
30# Construct a new AST that does not have any IfThenElse nodes by
31# substituting concrete boolean values for each Setting.
32#
33
34class Node
35 def resolveSettings(settings)
36 mapChildren {
37 | child |
38 child.resolveSettings(settings)
39 }
40 end
41end
42
43class True
44 def resolveSettings(settings)
45 self
46 end
47end
48
49class False
50 def resolveSettings(settings)
51 self
52 end
53end
54
55class Setting
56 def resolveSettings(settings)
57 settings[@name].asNode
58 end
59end
60
61class And
62 def resolveSettings(settings)
63 (@left.resolveSettings(settings).value and @right.resolveSettings(settings).value).asNode
64 end
65end
66
67class Or
68 def resolveSettings(settings)
69 (@left.resolveSettings(settings).value or @right.resolveSettings(settings).value).asNode
70 end
71end
72
73class Not
74 def resolveSettings(settings)
75 (not @child.resolveSettings(settings).value).asNode
76 end
77end
78
79class IfThenElse
80 def resolveSettings(settings)
81 if @predicate.resolveSettings(settings).value
82 @thenCase.resolveSettings(settings)
83 else
84 @elseCase.resolveSettings(settings)
85 end
86 end
87end
88
89class Sequence
90 def resolveSettings(settings)
91 newList = []
92 @list.each {
93 | item |
94 item = item.resolveSettings(settings)
95 if item.is_a? Sequence
96 newList += item.list
97 else
98 newList << item
99 end
100 }
101 Sequence.new(codeOrigin, newList)
102 end
103end
104
105#
106# node.demacroify(macros)
107# node.substitute(mapping)
108#
109# demacroify() constructs a new AST that does not have any Macro
110# nodes, while substitute() replaces Variable nodes with the given
111# nodes in the mapping.
112#
113
114class Node
115 def demacroify(macros)
116 mapChildren {
117 | child |
118 child.demacroify(macros)
119 }
120 end
121
122 def substitute(mapping)
123 mapChildren {
124 | child |
125 child.substitute(mapping)
126 }
127 end
128
129 def substituteLabels(mapping)
130 mapChildren {
131 | child |
132 child.substituteLabels(mapping)
133 }
134 end
135end
136
137class Macro
138 def substitute(mapping)
139 myMapping = {}
140 mapping.each_pair {
141 | key, value |
142 unless @variables.include? key
143 myMapping[key] = value
144 end
145 }
146 mapChildren {
147 | child |
148 child.substitute(myMapping)
149 }
150 end
151end
152
153class Variable
154 def substitute(mapping)
155 if mapping[self]
156 mapping[self]
157 else
158 self
159 end
160 end
161end
162
163class LocalLabel
164 def substituteLabels(mapping)
165 if mapping[self]
166 mapping[self]
167 else
168 self
169 end
170 end
171end
172
173class Sequence
174 def substitute(constants)
175 newList = []
176 myConstants = constants.dup
177 @list.each {
178 | item |
179 if item.is_a? ConstDecl
180 myConstants[item.variable] = item.value.substitute(myConstants)
181 else
182 newList << item.substitute(myConstants)
183 end
184 }
185 Sequence.new(codeOrigin, newList)
186 end
187
188 def renameLabels(comment)
189 mapping = {}
190
191 @list.each {
192 | item |
193 if item.is_a? LocalLabel
194 mapping[item] = LocalLabel.unique(if comment then comment + "_" else "" end + item.cleanName)
195 end
196 }
197
198 substituteLabels(mapping)
199 end
200
201 def demacroify(macros)
202 myMacros = macros.dup
203 @list.each {
204 | item |
205 if item.is_a? Macro
206 myMacros[item.name] = item
207 end
208 }
209 newList = []
210 @list.each {
211 | item |
212 if item.is_a? Macro
213 # Ignore.
214 elsif item.is_a? MacroCall
215 mapping = {}
216 myMyMacros = myMacros.dup
217 raise "Could not find macro #{item.name} at #{item.codeOriginString}" unless myMacros[item.name]
218 raise "Argument count mismatch for call to #{item.name} at #{item.codeOriginString}" unless item.operands.size == myMacros[item.name].variables.size
219 item.operands.size.times {
220 | idx |
221 if item.operands[idx].is_a? Variable and myMacros[item.operands[idx].name]
222 myMyMacros[myMacros[item.name].variables[idx].name] = myMacros[item.operands[idx].name]
223 mapping[myMacros[item.name].variables[idx].name] = nil
224 elsif item.operands[idx].is_a? Macro
225 myMyMacros[myMacros[item.name].variables[idx].name] = item.operands[idx]
226 mapping[myMacros[item.name].variables[idx].name] = nil
227 else
228 myMyMacros[myMacros[item.name].variables[idx]] = nil
229 mapping[myMacros[item.name].variables[idx]] = item.operands[idx]
230 end
231 }
commit-queue@webkit.orge602eca2012-07-19 20:53:22 +0000232 if item.annotation
233 newList << Instruction.new(item.codeOrigin, "localAnnotation", [], item.annotation)
234 end
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +0000235 newList += myMacros[item.name].body.substitute(mapping).demacroify(myMyMacros).renameLabels(item.name).list
236 else
237 newList << item.demacroify(myMacros)
238 end
239 }
240 Sequence.new(codeOrigin, newList).substitute({})
241 end
242end
243
244#
245# node.resolveOffsets(offsets, sizes)
246#
247# Construct a new AST that has offset values instead of symbolic
248# offsets.
249#
250
251class Node
keith_miller@apple.com628e2ca2017-07-30 03:01:12 +0000252 def resolveOffsets(constantsMap)
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +0000253 mapChildren {
254 | child |
keith_miller@apple.com628e2ca2017-07-30 03:01:12 +0000255 child.resolveOffsets(constantsMap)
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +0000256 }
257 end
258end
259
260class StructOffset
keith_miller@apple.com628e2ca2017-07-30 03:01:12 +0000261 def resolveOffsets(constantsMap)
262 if constantsMap[self]
263 Immediate.new(codeOrigin, constantsMap[self])
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +0000264 else
keith_miller@apple.com628e2ca2017-07-30 03:01:12 +0000265 puts "Could not find #{self.inspect} in #{constantsMap.keys.inspect}"
266 puts "sizes = #{constantsMap.inspect}"
267 raise
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +0000268 end
269 end
270end
271
272class Sizeof
keith_miller@apple.com628e2ca2017-07-30 03:01:12 +0000273 def resolveOffsets(constantsMap)
274 if constantsMap[self]
275 Immediate.new(codeOrigin, constantsMap[self])
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +0000276 else
keith_miller@apple.com628e2ca2017-07-30 03:01:12 +0000277 puts "Could not find #{self.inspect} in #{constantsMap.keys.inspect}"
278 puts "sizes = #{constantsMap.inspect}"
279 raise
280 end
281 end
282end
283
284class ConstExpr
285 def resolveOffsets(constantsMap)
286 if constantsMap[self]
287 Immediate.new(codeOrigin, constantsMap[self])
288 else
289 puts "Could not find #{self.inspect} in #{constantsMap.keys.inspect}"
290 puts "sizes = #{constantsMap.inspect}"
291 raise
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +0000292 end
293 end
294end
295
296#
297# node.fold
298#
299# Resolve constant references and compute arithmetic expressions.
300#
301
302class Node
303 def fold
304 mapChildren {
305 | child |
306 child.fold
307 }
308 end
309end
310
311class AddImmediates
312 def fold
313 @left = @left.fold
314 @right = @right.fold
fpizlo@apple.combd60cf62017-09-27 05:05:27 +0000315
316 return right.plusOffset(@left.value) if @left.is_a? Immediate and @right.is_a? LabelReference
317 return left.plusOffset(@right.value) if @left.is_a? LabelReference and @right.is_a? Immediate
318
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +0000319 return self unless @left.is_a? Immediate
320 return self unless @right.is_a? Immediate
321 Immediate.new(codeOrigin, @left.value + @right.value)
322 end
323end
324
325class SubImmediates
326 def fold
327 @left = @left.fold
328 @right = @right.fold
fpizlo@apple.combd60cf62017-09-27 05:05:27 +0000329
330 return left.plusOffset(-@right.value) if @left.is_a? LabelReference and @right.is_a? Immediate
331
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +0000332 return self unless @left.is_a? Immediate
333 return self unless @right.is_a? Immediate
334 Immediate.new(codeOrigin, @left.value - @right.value)
335 end
336end
337
338class MulImmediates
339 def fold
340 @left = @left.fold
341 @right = @right.fold
342 return self unless @left.is_a? Immediate
343 return self unless @right.is_a? Immediate
344 Immediate.new(codeOrigin, @left.value * @right.value)
345 end
346end
347
348class NegImmediate
349 def fold
350 @child = @child.fold
351 return self unless @child.is_a? Immediate
352 Immediate.new(codeOrigin, -@child.value)
353 end
354end
355
fpizlo@apple.com685a4202012-03-11 00:33:20 +0000356class OrImmediates
357 def fold
358 @left = @left.fold
359 @right = @right.fold
360 return self unless @left.is_a? Immediate
361 return self unless @right.is_a? Immediate
362 Immediate.new(codeOrigin, @left.value | @right.value)
363 end
364end
365
366class AndImmediates
367 def fold
368 @left = @left.fold
369 @right = @right.fold
370 return self unless @left.is_a? Immediate
371 return self unless @right.is_a? Immediate
372 Immediate.new(codeOrigin, @left.value & @right.value)
373 end
374end
375
376class XorImmediates
377 def fold
378 @left = @left.fold
379 @right = @right.fold
380 return self unless @left.is_a? Immediate
381 return self unless @right.is_a? Immediate
382 Immediate.new(codeOrigin, @left.value ^ @right.value)
383 end
384end
385
386class BitnotImmediate
387 def fold
388 @child = @child.fold
389 return self unless @child.is_a? Immediate
390 Immediate.new(codeOrigin, ~@child.value)
391 end
392end
393
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +0000394#
395# node.resolveAfterSettings(offsets, sizes)
396#
397# Compile assembly against a set of offsets.
398#
399
400class Node
keith_miller@apple.com628e2ca2017-07-30 03:01:12 +0000401 def resolve(constantsMap)
402 demacroify({}).resolveOffsets(constantsMap).fold
fpizlo@apple.com7bbcaab2012-02-22 05:23:19 +0000403 end
404end
405
fpizlo@apple.com685a4202012-03-11 00:33:20 +0000406#
407# node.validate
408#
409# Checks that the node is ready for backend compilation.
410#
411
412class Node
413 def validate
414 raise "Unresolved #{dump} at #{codeOriginString}"
415 end
416
417 def validateChildren
418 children.each {
419 | node |
420 node.validate
421 }
422 end
423end
424
425class Sequence
426 def validate
427 validateChildren
dbates@webkit.org98f0de02013-10-15 22:16:39 +0000428
429 # Further verify that this list contains only instructions, labels, and skips.
430 @list.each {
431 | node |
432 unless node.is_a? Instruction or
433 node.is_a? Label or
434 node.is_a? LocalLabel or
435 node.is_a? Skip
436 raise "Unexpected #{node.inspect} at #{node.codeOrigin}"
437 end
438 }
fpizlo@apple.com685a4202012-03-11 00:33:20 +0000439 end
440end
441
442class Immediate
443 def validate
444 end
445end
446
msaboff@apple.com2935ca82014-08-12 03:20:04 +0000447class StringLiteral
448 def validate
449 end
450end
451
fpizlo@apple.com685a4202012-03-11 00:33:20 +0000452class RegisterID
453 def validate
454 end
455end
456
457class FPRegisterID
458 def validate
459 end
460end
461
462class Address
463 def validate
464 validateChildren
465 end
466end
467
468class BaseIndex
469 def validate
470 validateChildren
471 end
472end
473
474class AbsoluteAddress
475 def validate
476 validateChildren
477 end
478end
479
480class Instruction
481 def validate
482 validateChildren
483 end
484end
485
msaboff@apple.com8f8907e2014-04-10 22:33:59 +0000486class SubImmediates
487 def validate
488 raise "Invalid operand #{left.dump} to immediate subtraction" unless left.immediateOperand?
489 raise "Invalid operand #{right.dump} to immediate subtraction" unless right.immediateOperand?
490 end
491end
492
fpizlo@apple.com685a4202012-03-11 00:33:20 +0000493class Error
494 def validate
495 end
496end
497
498class Label
499 def validate
500 end
501end
502
503class LocalLabel
504 def validate
505 end
506end
507
508class LabelReference
509 def validate
510 end
511end
512
513class LocalLabelReference
514 def validate
515 end
516end
517
518class Skip
519 def validate
520 end
521end
522