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