source: webkit/trunk/Source/JavaScriptCore/offlineasm/settings.rb

Last change on this file was 237219, checked in by [email protected], 7 years ago

Unreviewed revert Fujii's revert in r237214 with new WinCairo build fix.

File size: 7.6 KB
Line 
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 "config"
25require "ast"
26require "backends"
27require "parser"
28require "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
39def 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 nonBackendSettings = ast.filter(Setting).uniq.collect{ |v| v.name }
58 nonBackendSettings.delete_if {
59 | setting |
60 isBackend? setting
61 }
62
63 allBackendsFalse = {}
64 BACKENDS.each {
65 | backend |
66 allBackendsFalse[backend] = false
67 }
68
69 # This will create entries for invalid backends. That's fine. It's necessary
70 # because it ensures that generate_offsets_extractor (which knows about valid
71 # backends) has settings indices that are compatible with what asm will see
72 # (asm doesn't know about valid backends).
73 BACKENDS.each {
74 | backend |
75 map = allBackendsFalse.clone
76 map[backend] = true
77 settingsCombinator(settingsCombinations, map, nonBackendSettings)
78 }
79
80 settingsCombinations
81end
82
83#
84# forSettings(concreteSettings, ast) {
85# | concreteSettings, lowLevelAST, backend | ... }
86#
87# Determines if the settings combination is valid, and if so, calls
88# the block with the information you need to generate code.
89#
90
91def forSettings(concreteSettings, ast)
92 # Check which architectures this combinator claims to support.
93 selectedBackend = nil
94 BACKENDS.each {
95 | backend |
96 if concreteSettings[backend]
97 raise if selectedBackend
98 selectedBackend = backend
99 end
100 }
101
102 return unless isValidBackend? selectedBackend
103
104 # Resolve the AST down to a low-level form (no macros or conditionals).
105 lowLevelAST = ast.resolveSettings(concreteSettings)
106
107 yield concreteSettings, lowLevelAST, selectedBackend
108end
109
110#
111# forEachValidSettingsCombination(ast) {
112# | concreteSettings, ast, backend, index | ... }
113#
114# forEachValidSettingsCombination(ast, settingsCombinations) {
115# | concreteSettings, ast, backend, index | ... }
116#
117# Executes the given block for each valid settings combination in the
118# settings map. The ast passed into the block is resolved
119# (ast.resolve) against the settings.
120#
121# The first form will call computeSettingsCombinations(ast) for you.
122#
123
124def forEachValidSettingsCombination(ast, *optionalSettingsCombinations)
125 raise if optionalSettingsCombinations.size > 1
126
127 if optionalSettingsCombinations.empty?
128 settingsCombinations = computeSettingsCombinations(ast)
129 else
130 settingsCombinations = optionalSettingsCombiations[0]
131 end
132
133 settingsCombinations.each_with_index {
134 | concreteSettings, index |
135 forSettings(concreteSettings, ast) {
136 | concreteSettings_, lowLevelAST, backend |
137 yield concreteSettings, lowLevelAST, backend, index
138 }
139 }
140end
141
142#
143# cppSettingsTest(concreteSettings)
144#
145# Returns the C++ code used to test if we are in a configuration that
146# corresponds to the given concrete settings.
147#
148
149def cppSettingsTest(concreteSettings)
150 "#if " + concreteSettings.to_a.collect{
151 | pair |
152 (if pair[1]
153 ""
154 else
155 "!"
156 end) + "OFFLINE_ASM_" + pair[0]
157 }.join(" && ")
158end
159
160#
161# isASTErroneous(ast)
162#
163# Tests to see if the AST claims that there is an error - i.e. if the
164# user's code, after settings resolution, has Error nodes.
165#
166
167def isASTErroneous(ast)
168 not ast.demacroify({}).filter(Error).empty?
169end
170
171#
172# assertConfiguration(concreteSettings)
173#
174# Emits a check that asserts that we're using the given configuration.
175#
176
177def assertConfiguration(concreteSettings)
178 $output.puts cppSettingsTest(concreteSettings)
179 $output.puts "#else"
180 $output.puts "#error \"Configuration mismatch.\""
181 $output.puts "#endif"
182end
183
184#
185# emitCodeInConfiguration(concreteSettings, ast, backend) {
186# | concreteSettings, ast, backend | ... }
187#
188# Emits all relevant guards to see if the configuration holds and
189# calls the block if the configuration is not erroneous.
190#
191
192def emitCodeInConfiguration(concreteSettings, ast, backend)
193 Label.resetReferenced
194
195 if !$emitWinAsm
196 $output.puts cppSettingsTest(concreteSettings)
197 else
198 if backend == "X86_WIN"
199 $output.puts ".MODEL FLAT, C"
200 end
201 $output.puts "INCLUDE #{File.basename($output.path)}.sym"
202 $output.puts "_TEXT SEGMENT"
203 end
204
205 if isASTErroneous(ast)
206 $output.puts "#error \"Invalid configuration. Error at: #{ast.filter(Error)[0].codeOrigin}\""
207 elsif not WORKING_BACKENDS.include? backend
208 $output.puts "#error \"This backend is not supported yet.\""
209 else
210 yield concreteSettings, ast, backend
211 end
212
213 if !$emitWinAsm
214 $output.puts "#endif"
215 else
216 $output.puts "_TEXT ENDS"
217 $output.puts "END"
218
219 # Write symbols needed by MASM
220 File.open("#{File.basename($output.path)}.sym", "w") {
221 | outp |
222 Label.forReferencedExtern {
223 | name |
224 outp.puts "EXTERN #{name[1..-1]} : near"
225 }
226 }
227 end
228end
229
230#
231# emitCodeInAllConfigurations(ast) {
232# | concreteSettings, ast, backend, index | ... }
233#
234# Emits guard codes for all valid configurations, and calls the block
235# for those configurations that are valid and not erroneous.
236#
237
238def emitCodeInAllConfigurations(ast)
239 forEachValidSettingsCombination(ast) {
240 | concreteSettings, lowLevelAST, backend, index |
241 $output.puts cppSettingsTest(concreteSettings)
242 yield concreteSettings, lowLevelAST, backend, index
243 $output.puts "#endif"
244 }
245end
246
247
248
Note: See TracBrowser for help on using the repository browser.