]> git.saurik.com Git - apple/javascriptcore.git/blame - offlineasm/settings.rb
JavaScriptCore-1097.13.tar.gz
[apple/javascriptcore.git] / offlineasm / settings.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"
25require "backends"
26require "parser"
27require "transform"
28
29#
30# computeSettingsCombinations(ast) -> settingsCombiations
31#
32# Computes an array of settings maps, where a settings map constitutes
33# a configuration for the assembly code being generated. The map
34# contains key value pairs where keys are settings names (strings) and
35# the values are booleans (true for enabled, false for disabled).
36#
37
38def computeSettingsCombinations(ast)
39 settingsCombinations = []
40
41 def settingsCombinator(settingsCombinations, mapSoFar, remaining)
42 if remaining.empty?
43 settingsCombinations << mapSoFar
44 return
45 end
46
47 newMap = mapSoFar.dup
48 newMap[remaining[0]] = true
49 settingsCombinator(settingsCombinations, newMap, remaining[1..-1])
50
51 newMap = mapSoFar.dup
52 newMap[remaining[0]] = false
53 settingsCombinator(settingsCombinations, newMap, remaining[1..-1])
54 end
55
56 settingsCombinator(settingsCombinations, {}, (ast.filter(Setting).uniq.collect{|v| v.name} + BACKENDS).uniq)
57
58 settingsCombinations
59end
60
61#
62# forSettings(concreteSettings, ast) {
63# | concreteSettings, lowLevelAST, backend | ... }
64#
65# Determines if the settings combination is valid, and if so, calls
66# the block with the information you need to generate code.
67#
68
69def forSettings(concreteSettings, ast)
70 # Check which architectures this combinator claims to support.
71 numClaimedBackends = 0
72 selectedBackend = nil
73 BACKENDS.each {
74 | backend |
75 isSupported = concreteSettings[backend]
76 raise unless isSupported != nil
77 numClaimedBackends += if isSupported then 1 else 0 end
78 if isSupported
79 selectedBackend = backend
80 end
81 }
82
83 return if numClaimedBackends > 1
84
85 # Resolve the AST down to a low-level form (no macros or conditionals).
86 lowLevelAST = ast.resolveSettings(concreteSettings)
87
88 yield concreteSettings, lowLevelAST, selectedBackend
89end
90
91#
92# forEachValidSettingsCombination(ast) {
93# | concreteSettings, ast, backend, index | ... }
94#
95# forEachValidSettingsCombination(ast, settingsCombinations) {
96# | concreteSettings, ast, backend, index | ... }
97#
98# Executes the given block for each valid settings combination in the
99# settings map. The ast passed into the block is resolved
100# (ast.resolve) against the settings.
101#
102# The first form will call computeSettingsCombinations(ast) for you.
103#
104
105def forEachValidSettingsCombination(ast, *optionalSettingsCombinations)
106 raise if optionalSettingsCombinations.size > 1
107
108 if optionalSettingsCombinations.empty?
109 settingsCombinations = computeSettingsCombinations(ast)
110 else
111 settingsCombinations = optionalSettingsCombiations[0]
112 end
113
114 settingsCombinations.each_with_index {
115 | concreteSettings, index |
116 forSettings(concreteSettings, ast) {
117 | concreteSettings_, lowLevelAST, backend |
118 yield concreteSettings, lowLevelAST, backend, index
119 }
120 }
121end
122
123#
124# cppSettingsTest(concreteSettings)
125#
126# Returns the C++ code used to test if we are in a configuration that
127# corresponds to the given concrete settings.
128#
129
130def cppSettingsTest(concreteSettings)
131 "#if " + concreteSettings.to_a.collect{
132 | pair |
133 (if pair[1]
134 ""
135 else
136 "!"
137 end) + "OFFLINE_ASM_" + pair[0]
138 }.join(" && ")
139end
140
141#
142# isASTErroneous(ast)
143#
144# Tests to see if the AST claims that there is an error - i.e. if the
145# user's code, after settings resolution, has Error nodes.
146#
147
148def isASTErroneous(ast)
149 not ast.filter(Error).empty?
150end
151
152#
153# assertConfiguration(concreteSettings)
154#
155# Emits a check that asserts that we're using the given configuration.
156#
157
158def assertConfiguration(concreteSettings)
159 $output.puts cppSettingsTest(concreteSettings)
160 $output.puts "#else"
161 $output.puts "#error \"Configuration mismatch.\""
162 $output.puts "#endif"
163end
164
165#
166# emitCodeInConfiguration(concreteSettings, ast, backend) {
167# | concreteSettings, ast, backend | ... }
168#
169# Emits all relevant guards to see if the configuration holds and
170# calls the block if the configuration is not erroneous.
171#
172
173def emitCodeInConfiguration(concreteSettings, ast, backend)
174 $output.puts cppSettingsTest(concreteSettings)
175
176 if isASTErroneous(ast)
177 $output.puts "#error \"Invalid configuration.\""
178 elsif not WORKING_BACKENDS.include? backend
179 $output.puts "#error \"This backend is not supported yet.\""
180 else
181 yield concreteSettings, ast, backend
182 end
183
184 $output.puts "#endif"
185end
186
187#
188# emitCodeInAllConfigurations(ast) {
189# | concreteSettings, ast, backend, index | ... }
190#
191# Emits guard codes for all valid configurations, and calls the block
192# for those configurations that are valid and not erroneous.
193#
194
195def emitCodeInAllConfigurations(ast)
196 forEachValidSettingsCombination(ast) {
197 | concreteSettings, lowLevelAST, backend, index |
198 $output.puts cppSettingsTest(concreteSettings)
199 yield concreteSettings, lowLevelAST, backend, index
200 $output.puts "#endif"
201 }
202end
203
204
205