--- /dev/null
+# Copyright (C) 1997, 1999, 2000, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+# If the target does not match the required effective target, skip this test.
+
+proc dg-require-effective-target { args } {
+ set args [lreplace $args 0 0]
+ if { ![is-effective-target [lindex $args 0]] } {
+ upvar dg-do-what dg-do-what
+ set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"]
+ }
+}
+
+# Check the flags with which the test will be run against options in
+# a test directive that will skip or xfail that test. The DejaGnu proc
+# check_conditional_xfail will look at the options in compiler_flags, so
+# set that up for this test based on flags we know about.
+
+proc check_test_flags { args } {
+ global compiler_flags
+ upvar 2 dg-extra-tool-flags extra_tool_flags
+
+ # Pull the args out of the enclosing list.
+ set args [lindex $args 0]
+
+ # Start the list with a dummy tool name so the list will match "*"
+ # if there are no flags.
+ set compiler_flags " toolname "
+ append compiler_flags $extra_tool_flags
+ set dest [target_info name]
+ if [board_info $dest exists multilib_flags] {
+ append compiler_flags "[board_info $dest multilib_flags] "
+ }
+
+ set answer [check_conditional_xfail $args]
+
+ # Any value in this variable originally was left over from an earlier test.
+ set compiler_flags ""
+
+ verbose "check_test_flags: $args $answer" 2
+ return $answer
+}
+
+# Skip the test (report it as UNSUPPORTED) if the target list and
+# included flags are matched and the excluded flags are not matched.
+#
+# The first argument is the line number of the dg-skip-if directive
+# within the test file. Remaining arguments are as for xfail lists:
+# message { targets } { include } { exclude }
+#
+# This tests against multilib flags plus either the default flags for this
+# group of tests or flags specified with a previous dg-options command.
+
+proc dg-skip-if { args } {
+ set args [lreplace $args 0 0]
+
+ set selector [list target [lindex $args 1]]
+ if { [dg-process-target $selector] == "S" } {
+ # The target list matched; now check the flags. The DejaGnu proc
+ # check_conditional_xfail will look at the options in compiler_flags,
+ # so set that up for this test based on flags we know about. Start
+ # the list with a dummy tool name so the list will match "*" if
+ # there are no flags.
+
+ global compiler_flags
+ upvar dg-extra-tool-flags extra_tool_flags
+
+ set compiler_flags " toolname "
+ append compiler_flags $extra_tool_flags
+ set dest [target_info name]
+ if [board_info $dest exists multilib_flags] {
+ append compiler_flags "[board_info $dest multilib_flags] "
+ }
+
+ # The target list might be an effective-target keyword, so replace
+ # the original list with "*-*-*".
+ if [check_conditional_xfail [lreplace $args 1 1 "*-*-*"]] {
+ upvar dg-do-what dg-do-what
+ set dg-do-what [list [lindex ${dg-do-what} 0] "N" "P"]
+ }
+
+ # Any value in this variable was left over from an earlier test.
+ set compiler_flags ""
+ }
+}
+
+# Like check_conditional_xfail, but callable from a dg test.
+
+proc dg-xfail-if { args } {
+ # Don't change anything if we're already skipping the test.
+ upvar dg-do-what dg-do-what
+ if { [lindex ${dg-do-what} 1] == "N" } {
+ return
+ }
+
+ set args [lreplace $args 0 0]
+ set selector [list target [lindex $args 1]]
+ if { [dg-process-target $selector] == "S" } {
+ global compiler_conditional_xfail_data
+ set compiler_conditional_xfail_data [lreplace $args 1 1 "*-*-*"]
+ }
+}
+
+# Intercept the call to the DejaGnu version of dg-process-target to
+# support use of an effective-target keyword in place of a list of
+# target triplets to xfail or skip a test.
+#
+# selector is one of:
+# xfail target-triplet-1 ...
+# xfail effective-target-keyword
+# xfail selector-expression
+# target target-triplet-1 ...
+# target effective-target-keyword
+# target selector-expression
+#
+# For a target list the result is "S" if the target is selected, "N" otherwise.
+# For an xfail list the result is "F" if the target is affected, "P" otherwise.
+#
+# A selector expression appears within curly braces and uses a single logical
+# operator: !, &&, or ||. An operand is another selector expression, an
+# effective-target keyword, or a list of target triplets within quotes or
+# curly braces.
+
+if { [info procs saved-dg-process-target] == [list] } {
+ rename dg-process-target saved-dg-process-target
+
+ # Evaluate an operand within a selector expression.
+ proc selector_opd { op } {
+ set selector "target"
+ lappend selector $op
+ set answer [ expr { [dg-process-target $selector] == "S" } ]
+ verbose "selector_opd: `$op' $answer" 2
+ return $answer
+ }
+
+ # Evaluate a target triplet list within a selector expression.
+ # Unlike other operands, this needs to be expanded from a list to
+ # the same string as "target".
+ proc selector_list { op } {
+ set selector "target [join $op]"
+ set answer [ expr { [dg-process-target $selector] == "S" } ]
+ verbose "selector_list: `$op' $answer" 2
+ return $answer
+ }
+
+ # Evaluate a selector expression.
+ proc selector_expression { exp } {
+ if { [llength $exp] == 2 } {
+ if [string match "!" [lindex $exp 0]] {
+ set op1 [lindex $exp 1]
+ set answer [expr { ! [selector_opd $op1] }]
+ } else {
+ # Assume it's a list of target triplets.
+ set answer [selector_list $exp]
+ }
+ } elseif { [llength $exp] == 3 } {
+ set op1 [lindex $exp 0]
+ set opr [lindex $exp 1]
+ set op2 [lindex $exp 2]
+ if [string match "&&" $opr] {
+ set answer [expr { [selector_opd $op1] && [selector_opd $op2] }]
+ } elseif [string match "||" $opr] {
+ set answer [expr { [selector_opd $op1] || [selector_opd $op2] }]
+ } else {
+ # Assume it's a list of target triplets.
+ set answer [selector_list $exp]
+ }
+ } else {
+ # Assume it's a list of target triplets.
+ set answer [selector_list $exp]
+ }
+
+ verbose "selector_expression: `$exp' $answer" 2
+ return $answer
+ }
+
+ proc dg-process-target { args } {
+ verbose "replacement dg-process-target: `$args'" 2
+
+ # Extract the 'what' keyword from the argument list.
+ set selector [string trim [lindex $args 0]]
+ if [regexp "^xfail " $selector] {
+ set what "xfail"
+ } elseif [regexp "^target " $selector] {
+ set what "target"
+ } else {
+ error "syntax error in target selector \"$selector\""
+ }
+
+ # Extract the rest of the list, which might be a keyword.
+ regsub "^${what}" $selector "" rest
+ set rest [string trim $rest]
+
+ if [is-effective-target-keyword $rest] {
+ # The selector is an effective target keyword.
+ if [is-effective-target $rest] {
+ return [expr { $what == "xfail" ? "F" : "S" }]
+ } else {
+ return [expr { $what == "xfail" ? "P" : "N" }]
+ }
+ }
+
+ if [string match "{*}" $rest] {
+ if [selector_expression [lindex $rest 0]] {
+ return [expr { $what == "xfail" ? "F" : "S" }]
+ } else {
+ return [expr { $what == "xfail" ? "P" : "N" }]
+ }
+ }
+
+ # The selector is not an effective-target keyword, so process
+ # the list of target triplets.
+ return [saved-dg-process-target $selector]
+ }
+}
return $vmx_hw_available_saved
}
+
+# Return 1 if -fpic and -fPIC are supported, as in no warnings or errors
+# emitted, 0 otherwise. Whether a shared library can actually be built is
+# out of scope for this test.
+#
+# When the target name changes, replace the cached result.
+
+proc check_effective_target_fpic { } {
+ global et_fpic_saved
+ global et_fpic_target_name
+
+ if { ![info exists et_fpic_target_name] } {
+ set et_fpic_target_name ""
+ }
+
+ # If the target has changed since we set the cached value, clear it.
+ set current_target [current_target_name]
+ if { $current_target != $et_fpic_target_name } {
+ verbose "check_effective_target_fpic: `$et_fpic_target_name'" 2
+ set et_fpic_target_name $current_target
+ if [info exists et_fpic_saved] {
+ verbose "check_effective_target_fpic: removing cached result" 2
+ unset et_fpic_saved
+ }
+ }
+
+ if [info exists et_fpic_saved] {
+ verbose "check_effective_target_fpic: using cached result" 2
+ } else {
+ verbose "check_effective_target_fpic: compiling source" 2
+
+ # Note that M68K has a multilib that supports -fpic but not
+ # -fPIC, so we need to check both. We test with a program that
+ # requires GOT references.
+ set et_fpic_saved [string match "" [get_compiler_messages fpic object {
+ extern int foo (void); extern int bar;
+ int baz (void) { return foo () + bar; }
+ } "-fpic"]]
+
+ if { $et_fpic_saved != 0 } {
+ set et_fpic_saved [string match "" [get_compiler_messages fpic object {
+ extern int foo (void); extern int bar;
+ int baz (void) { return foo () + bar; }
+ } "-fPIC"]]
+ }
+ }
+ verbose "check_effective_target_fpic: returning $et_fpic_saved" 2
+ return $et_fpic_saved
+}
+
+# Return 1 if we're generating 32-bit code using default options, 0
+# otherwise.
+#
+# When the target name changes, replace the cached result.
+
+proc check_effective_target_ilp32 { } {
+ global et_ilp32_saved
+ global et_ilp32_target_name
+
+ if { ![info exists et_ilp32_target_name] } {
+ set et_ilp32_target_name ""
+ }
+
+ # If the target has changed since we set the cached value, clear it.
+ set current_target [current_target_name]
+ if { $current_target != $et_ilp32_target_name } {
+ verbose "check_effective_target_ilp32: `$et_ilp32_target_name' `$current_target'" 2
+ set et_ilp32_target_name $current_target
+ if { [info exists et_ilp32_saved] } {
+ verbose "check_effective_target_ilp32: removing cached result" 2
+ unset et_ilp32_saved
+ }
+ }
+
+ if [info exists et_ilp32_saved] {
+ verbose "check-effective_target_ilp32: using cached result" 2
+ } else {
+ verbose "check_effective_target_ilp32: compiling source" 2
+ set et_ilp32_saved [string match "" [get_compiler_messages ilp32 object {
+ int dummy[(sizeof (int) == 4 && sizeof (void *) == 4 && sizeof (long) == 4 ) ? 1 : -1];
+ }]]
+ }
+ verbose "check_effective_target_ilp32: returning $et_ilp32_saved" 2
+ return $et_ilp32_saved
+}
+
+# Return 1 if we're generating 64-bit code using default options, 0
+# otherwise.
+#
+# When the target name changes, replace the cached result.
+
+proc check_effective_target_lp64 { } {
+ global et_lp64_saved
+ global et_lp64_target_name
+
+ if { ![info exists et_lp64_target_name] } {
+ set et_lp64_target_name ""
+ }
+
+ # If the target has changed since we set the cached value, clear it.
+ set current_target [current_target_name]
+ if { $current_target != $et_lp64_target_name } {
+ verbose "check_effective_target_lp64: `$et_lp64_target_name' `$current_target'" 2
+ set et_lp64_target_name $current_target
+ if [info exists et_lp64_saved] {
+ verbose "check_effective_target_lp64: removing cached result" 2
+ unset et_lp64_saved
+ }
+ }
+
+ if [info exists et_lp64_saved] {
+ verbose "check_effective_target_lp64: using cached result" 2
+ } else {
+ verbose "check_effective_target_lp64: compiling source" 2
+ set et_lp64_saved [string match "" [get_compiler_messages lp64 object {
+ int dummy[(sizeof (int) == 4 && sizeof (void *) == 8 && sizeof (long) == 8 ) ? 1 : -1];
+ }]]
+ }
+ verbose "check_effective_target_lp64: returning $et_lp64_saved" 2
+ return $et_lp64_saved
+}
+
+# Return 1 if the target matches the effective target 'arg', 0 otherwise.
+# This can be used with any check_* proc that takes no argument and
+# returns only 1 or 0. It could be used with check_* procs that take
+# arguments with keywords that pass particular arguments.
+
+proc is-effective-target { arg } {
+ set selected 0
+ if { [info procs check_effective_target_${arg}] != [list] } {
+ set selected [check_effective_target_${arg}]
+ } else {
+ switch $arg {
+ "vmx_hw" { set selected [check_vmx_hw_available] }
+ "named_sections" { set selected [check_named_sections_available] }
+ "gc_sections" { set selected [check_gc_sections_available] }
+ default { error "unknown effective target keyword `$arg'" }
+ }
+ }
+ verbose "is-effective-target: $arg $selected" 2
+ return $selected
+}
+
+# Return 1 if the argument is an effective-target keyword, 0 otherwise.
+
+proc is-effective-target-keyword { arg } {
+ if { [info procs check_effective_target_${arg}] != [list] } {
+ return 1
+ } else {
+ # These have different names for their check_* procs.
+ switch $arg {
+ "vmx_hw" { return 1 }
+ "named_sections" { return 1 }
+ "gc_sections" { return 1 }
+ default { return 0 }
+ }
+ }
+}