[Qt]REGRESSION(r92254): It made 2 tests timeout
[WebKit-https.git] / Source / JavaScriptCore / 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 "ast"
25 require "backends"
26 require "parser"
27 require "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
38 def 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} + ["X86", "ARMv7"]).uniq)
57     
58     settingsCombinations
59 end
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
69 def 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
89 end
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
105 def 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     }
121 end
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
130 def 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(" && ")
139 end
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
148 def isASTErroneous(ast)
149     not ast.filter(Error).empty?
150 end
151
152 #
153 # assertConfiguration(concreteSettings)
154 #
155 # Emits a check that asserts that we're using the given configuration.
156 #
157
158 def assertConfiguration(concreteSettings)
159     $output.puts cppSettingsTest(concreteSettings)
160     $output.puts "#else"
161     $output.puts "#error \"Configuration mismatch.\""
162     $output.puts "#endif"
163 end
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
173 def 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"
185 end
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
195 def 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     }
202 end
203
204
205