diff options
author | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-24 16:36:50 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2012-02-24 16:36:50 +0100 |
commit | ad0d549d4cc13433f77c1ac8f0ab379c83d93f28 (patch) | |
tree | b34b0daceb7c8e7fdde4b4ec43650ab7caadb0a9 /Source/JavaScriptCore/offlineasm/settings.rb | |
parent | 03e12282df9aa1e1fb05a8b90f1cfc2e08764cec (diff) | |
download | qtwebkit-ad0d549d4cc13433f77c1ac8f0ab379c83d93f28.tar.gz |
Imported WebKit commit bb52bf3c0119e8a128cd93afe5572413a8617de9 (http://svn.webkit.org/repository/webkit/trunk@108790)
Diffstat (limited to 'Source/JavaScriptCore/offlineasm/settings.rb')
-rw-r--r-- | Source/JavaScriptCore/offlineasm/settings.rb | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/offlineasm/settings.rb b/Source/JavaScriptCore/offlineasm/settings.rb new file mode 100644 index 000000000..34598181c --- /dev/null +++ b/Source/JavaScriptCore/offlineasm/settings.rb @@ -0,0 +1,205 @@ +# Copyright (C) 2011 Apple Inc. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +# THE POSSIBILITY OF SUCH DAMAGE. + +require "ast" +require "backends" +require "parser" +require "transform" + +# +# computeSettingsCombinations(ast) -> settingsCombiations +# +# Computes an array of settings maps, where a settings map constitutes +# a configuration for the assembly code being generated. The map +# contains key value pairs where keys are settings names (strings) and +# the values are booleans (true for enabled, false for disabled). +# + +def computeSettingsCombinations(ast) + settingsCombinations = [] + + def settingsCombinator(settingsCombinations, mapSoFar, remaining) + if remaining.empty? + settingsCombinations << mapSoFar + return + end + + newMap = mapSoFar.dup + newMap[remaining[0]] = true + settingsCombinator(settingsCombinations, newMap, remaining[1..-1]) + + newMap = mapSoFar.dup + newMap[remaining[0]] = false + settingsCombinator(settingsCombinations, newMap, remaining[1..-1]) + end + + settingsCombinator(settingsCombinations, {}, (ast.filter(Setting).uniq.collect{|v| v.name} + ["X86", "ARMv7"]).uniq) + + settingsCombinations +end + +# +# forSettings(concreteSettings, ast) { +# | concreteSettings, lowLevelAST, backend | ... } +# +# Determines if the settings combination is valid, and if so, calls +# the block with the information you need to generate code. +# + +def forSettings(concreteSettings, ast) + # Check which architectures this combinator claims to support. + numClaimedBackends = 0 + selectedBackend = nil + BACKENDS.each { + | backend | + isSupported = concreteSettings[backend] + raise unless isSupported != nil + numClaimedBackends += if isSupported then 1 else 0 end + if isSupported + selectedBackend = backend + end + } + + return if numClaimedBackends > 1 + + # Resolve the AST down to a low-level form (no macros or conditionals). + lowLevelAST = ast.resolveSettings(concreteSettings) + + yield concreteSettings, lowLevelAST, selectedBackend +end + +# +# forEachValidSettingsCombination(ast) { +# | concreteSettings, ast, backend, index | ... } +# +# forEachValidSettingsCombination(ast, settingsCombinations) { +# | concreteSettings, ast, backend, index | ... } +# +# Executes the given block for each valid settings combination in the +# settings map. The ast passed into the block is resolved +# (ast.resolve) against the settings. +# +# The first form will call computeSettingsCombinations(ast) for you. +# + +def forEachValidSettingsCombination(ast, *optionalSettingsCombinations) + raise if optionalSettingsCombinations.size > 1 + + if optionalSettingsCombinations.empty? + settingsCombinations = computeSettingsCombinations(ast) + else + settingsCombinations = optionalSettingsCombiations[0] + end + + settingsCombinations.each_with_index { + | concreteSettings, index | + forSettings(concreteSettings, ast) { + | concreteSettings_, lowLevelAST, backend | + yield concreteSettings, lowLevelAST, backend, index + } + } +end + +# +# cppSettingsTest(concreteSettings) +# +# Returns the C++ code used to test if we are in a configuration that +# corresponds to the given concrete settings. +# + +def cppSettingsTest(concreteSettings) + "#if " + concreteSettings.to_a.collect{ + | pair | + (if pair[1] + "" + else + "!" + end) + "OFFLINE_ASM_" + pair[0] + }.join(" && ") +end + +# +# isASTErroneous(ast) +# +# Tests to see if the AST claims that there is an error - i.e. if the +# user's code, after settings resolution, has Error nodes. +# + +def isASTErroneous(ast) + not ast.filter(Error).empty? +end + +# +# assertConfiguration(concreteSettings) +# +# Emits a check that asserts that we're using the given configuration. +# + +def assertConfiguration(concreteSettings) + $output.puts cppSettingsTest(concreteSettings) + $output.puts "#else" + $output.puts "#error \"Configuration mismatch.\"" + $output.puts "#endif" +end + +# +# emitCodeInConfiguration(concreteSettings, ast, backend) { +# | concreteSettings, ast, backend | ... } +# +# Emits all relevant guards to see if the configuration holds and +# calls the block if the configuration is not erroneous. +# + +def emitCodeInConfiguration(concreteSettings, ast, backend) + $output.puts cppSettingsTest(concreteSettings) + + if isASTErroneous(ast) + $output.puts "#error \"Invalid configuration.\"" + elsif not WORKING_BACKENDS.include? backend + $output.puts "#error \"This backend is not supported yet.\"" + else + yield concreteSettings, ast, backend + end + + $output.puts "#endif" +end + +# +# emitCodeInAllConfigurations(ast) { +# | concreteSettings, ast, backend, index | ... } +# +# Emits guard codes for all valid configurations, and calls the block +# for those configurations that are valid and not erroneous. +# + +def emitCodeInAllConfigurations(ast) + forEachValidSettingsCombination(ast) { + | concreteSettings, lowLevelAST, backend, index | + $output.puts cppSettingsTest(concreteSettings) + yield concreteSettings, lowLevelAST, backend, index + $output.puts "#endif" + } +end + + + |