blob: 1c8b1ebb86e8769e40fe88af3a4c651990dbb2a1 [file] [log] [blame]
# Copyright (C) 1999-2021 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 3 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 GCC; see the file COPYING3. If not see
# <http://www.gnu.org/licenses/>.
# Please email any bugs, comments, and/or additions to this file to:
# gcc-patches@gcc.gnu.org
# This file defines procs for determining features supported by the target.
# Try to compile the code given by CONTENTS into an output file of
# type TYPE, where TYPE is as for target_compile. Return a list
# whose first element contains the compiler messages and whose
# second element is the name of the output file.
#
# BASENAME is a prefix to use for source and output files.
# If ARGS is not empty, its first element is a string that
# should be added to the command line.
#
# Assume by default that CONTENTS is C code.
# Otherwise, code should contain:
# "// C++" for c++,
# "// D" for D,
# "! Fortran" for Fortran code,
# "/* ObjC", for ObjC
# "// ObjC++" for ObjC++
# and "// Go" for Go
# If the tool is ObjC/ObjC++ then we overide the extension to .m/.mm to
# allow for ObjC/ObjC++ specific flags.
proc check_compile {basename type contents args} {
global tool
verbose "check_compile tool: $tool for $basename"
# Save additional_sources to avoid compiling testsuite's sources
# against check_compile's source.
global additional_sources
if [info exists additional_sources] {
set tmp_additional_sources "$additional_sources"
set additional_sources ""
}
if { [llength $args] > 0 } {
set options [list "additional_flags=[lindex $args 0]"]
} else {
set options ""
}
switch -glob -- $contents {
"*! Fortran*" { set src ${basename}[pid].f90 }
"*// C++*" { set src ${basename}[pid].cc }
"*// D*" { set src ${basename}[pid].d }
"*// ObjC++*" { set src ${basename}[pid].mm }
"*/* ObjC*" { set src ${basename}[pid].m }
"*// Go*" { set src ${basename}[pid].go }
default {
switch -- $tool {
"objc" { set src ${basename}[pid].m }
"obj-c++" { set src ${basename}[pid].mm }
default { set src ${basename}[pid].c }
}
}
}
set compile_type $type
switch -glob $type {
assembly { set output ${basename}[pid].s }
object { set output ${basename}[pid].o }
executable { set output ${basename}[pid].exe }
"rtl-*" {
set output ${basename}[pid].s
lappend options "additional_flags=-fdump-$type"
set compile_type assembly
}
}
set f [open $src "w"]
puts $f $contents
close $f
global compiler_flags
set save_compiler_flags $compiler_flags
set lines [${tool}_target_compile $src $output $compile_type "$options"]
set compiler_flags $save_compiler_flags
file delete $src
set scan_output $output
# Don't try folding this into the switch above; calling "glob" before the
# file is created won't work.
if [regexp "rtl-(.*)" $type dummy rtl_type] {
set scan_output "[glob $src.\[0-9\]\[0-9\]\[0-9\]r.$rtl_type]"
file delete $output
}
# Restore additional_sources.
if [info exists additional_sources] {
set additional_sources "$tmp_additional_sources"
}
return [list $lines $scan_output]
}
proc current_target_name { } {
global target_info
if [info exists target_info(target,name)] {
set answer $target_info(target,name)
} else {
set answer ""
}
return $answer
}
# Implement an effective-target check for property PROP by invoking
# the Tcl command ARGS and seeing if it returns true.
proc check_cached_effective_target { prop args } {
global et_cache
set target [current_target_name]
if {![info exists et_cache($prop,$target)]} {
verbose "check_cached_effective_target $prop: checking $target" 2
if {[string is true -strict $args] || [string is false -strict $args]} {
error {check_cached_effective_target condition already evaluated; did you pass [...] instead of the expected {...}?}
} else {
set code [catch {uplevel eval $args} result]
if {$code != 0 && $code != 2} {
return -code $code $result
}
set et_cache($prop,$target) $result
}
}
set value $et_cache($prop,$target)
verbose "check_cached_effective_target $prop: returning $value for $target" 2
return $value
}
# Implements a version of check_cached_effective_target that also takes et_index
# into account when creating the key for the cache.
proc check_cached_effective_target_indexed { prop args } {
global et_index
set key "$et_index $prop"
verbose "check_cached_effective_target_index $prop: returning $key" 2
return [check_cached_effective_target $key [list uplevel eval $args]]
}
# Clear effective-target cache. This is useful after testing
# effective-target features and overriding TEST_ALWAYS_FLAGS and/or
# ALWAYS_CXXFLAGS.
# If one changes ALWAYS_CXXFLAGS or TEST_ALWAYS_FLAGS then they should
# do a clear_effective_target_cache at the end as the target cache can
# make decisions based upon the flags, and those decisions need to be
# redone when the flags change. An example of this is the
# asan_init/asan_finish pair.
proc clear_effective_target_cache { } {
global et_cache
array unset et_cache
}
# Like check_compile, but delete the output file and return true if the
# compiler printed no messages.
proc check_no_compiler_messages_nocache {args} {
set result [eval check_compile $args]
set lines [lindex $result 0]
set output [lindex $result 1]
remote_file build delete $output
return [string match "" $lines]
}
# Like check_no_compiler_messages_nocache, but cache the result.
# PROP is the property we're checking, and doubles as a prefix for
# temporary filenames.
proc check_no_compiler_messages {prop args} {
return [check_cached_effective_target $prop {
eval [list check_no_compiler_messages_nocache $prop] $args
}]
}
# Like check_compile, but return true if the compiler printed no
# messages and if the contents of the output file satisfy PATTERN.
# If PATTERN has the form "!REGEXP", the contents satisfy it if they
# don't match regular expression REGEXP, otherwise they satisfy it
# if they do match regular expression PATTERN. (PATTERN can start
# with something like "[!]" if the regular expression needs to match
# "!" as the first character.)
#
# Delete the output file before returning. The other arguments are
# as for check_compile.
proc check_no_messages_and_pattern_nocache {basename pattern args} {
global tool
set result [eval [list check_compile $basename] $args]
set lines [lindex $result 0]
set output [lindex $result 1]
set ok 0
if { [string match "" $lines] } {
set chan [open "$output"]
set invert [regexp {^!(.*)} $pattern dummy pattern]
set ok [expr { [regexp $pattern [read $chan]] != $invert }]
close $chan
}
remote_file build delete $output
return $ok
}
# Like check_no_messages_and_pattern_nocache, but cache the result.
# PROP is the property we're checking, and doubles as a prefix for
# temporary filenames.
proc check_no_messages_and_pattern {prop pattern args} {
return [check_cached_effective_target $prop {
eval [list check_no_messages_and_pattern_nocache $prop $pattern] $args
}]
}
# Try to compile and run an executable from code CONTENTS. Return true
# if the compiler reports no messages and if execution "passes" in the
# usual DejaGNU sense. The arguments are as for check_compile, with
# TYPE implicitly being "executable".
proc check_runtime_nocache {basename contents args} {
global tool
set result [eval [list check_compile $basename executable $contents] $args]
set lines [lindex $result 0]
set output [lindex $result 1]
set ok 0
if { [string match "" $lines] } {
# No error messages, everything is OK.
set result [remote_load target "./$output" "" ""]
set status [lindex $result 0]
verbose "check_runtime_nocache $basename: status is <$status>" 2
if { $status == "pass" } {
set ok 1
}
}
remote_file build delete $output
return $ok
}
# Like check_runtime_nocache, but cache the result. PROP is the
# property we're checking, and doubles as a prefix for temporary
# filenames.
proc check_runtime {prop args} {
global tool
return [check_cached_effective_target $prop {
eval [list check_runtime_nocache $prop] $args
}]
}
# Return 1 if GCC was configured with $pattern.
proc check_configured_with { pattern } {
global tool
set options [list "additional_flags=-v"]
set gcc_output [${tool}_target_compile "" "" "none" $options]
if { [ regexp "Configured with: \[^\n\]*$pattern" $gcc_output ] } {
verbose "Matched: $pattern" 2
return 1
}
verbose "Failed to match: $pattern" 2
return 0
}
###############################
# proc check_weak_available { }
###############################
# weak symbols are only supported in some configs/object formats
# this proc returns 1 if they're supported, 0 if they're not, or -1 if unsure
proc check_weak_available { } {
global target_cpu
# All mips targets should support it
if { [ string first "mips" $target_cpu ] >= 0 } {
return 1
}
# All AIX targets should support it
if { [istarget *-*-aix*] } {
return 1
}
# All solaris2 targets should support it
if { [istarget *-*-solaris2*] } {
return 1
}
# Windows targets Cygwin and MingW32 support it
if { [istarget *-*-cygwin*] || [istarget *-*-mingw*] } {
return 1
}
# HP-UX 10.X doesn't support it
if { [istarget hppa*-*-hpux10*] } {
return 0
}
# nvptx (nearly) supports it
if { [istarget nvptx-*-*] } {
return 1
}
# pdp11 doesn't support it
if { [istarget pdp11*-*-*] } {
return 0
}
# VxWorks hardly supports it (vx7 RTPs only)
if { [istarget *-*-vxworks*] } {
return 0
}
# ELF and ECOFF support it. a.out does with gas/gld but may also with
# other linkers, so we should try it
set objformat [gcc_target_object_format]
switch $objformat {
elf { return 1 }
ecoff { return 1 }
a.out { return 1 }
mach-o { return 1 }
som { return 1 }
unknown { return -1 }
default { return 0 }
}
}
# return 1 if weak undefined symbols are supported.
proc check_effective_target_weak_undefined { } {
if { [istarget hppa*-*-hpux*] } {
return 0
}
return [check_runtime weak_undefined {
extern void foo () __attribute__((weak));
int main (void) { if (foo) return 1; return 0; }
} ""]
}
###############################
# proc check_weak_override_available { }
###############################
# Like check_weak_available, but return 0 if weak symbol definitions
# cannot be overridden.
proc check_weak_override_available { } {
if { [istarget *-*-mingw*] } {
return 0
}
return [check_weak_available]
}
# The "noinit" attribute is only supported by some targets.
# This proc returns 1 if it's supported, 0 if it's not.
proc check_effective_target_noinit { } {
if { [istarget arm*-*-eabi]
|| [istarget msp430-*-*] } {
return 1
}
return 0
}
# The "persistent" attribute is only supported by some targets.
# This proc returns 1 if it's supported, 0 if it's not.
proc check_effective_target_persistent { } {
if { [istarget arm*-*-eabi]
|| [istarget msp430-*-*] } {
return 1
}
return 0
}
###############################
# proc check_visibility_available { what_kind }
###############################
# The visibility attribute is only support in some object formats
# This proc returns 1 if it is supported, 0 if not.
# The argument is the kind of visibility, default/protected/hidden/internal.
proc check_visibility_available { what_kind } {
if [string match "" $what_kind] { set what_kind "hidden" }
return [check_no_compiler_messages visibility_available_$what_kind object "
void f() __attribute__((visibility(\"$what_kind\")));
void f() {}
"]
}
###############################
# proc check_alias_available { }
###############################
# Determine if the target toolchain supports the alias attribute.
# Returns 2 if the target supports aliases. Returns 1 if the target
# only supports weak aliased. Returns 0 if the target does not
# support aliases at all. Returns -1 if support for aliases could not
# be determined.
proc check_alias_available { } {
global tool
return [check_cached_effective_target alias_available {
set src alias[pid].c
set obj alias[pid].o
verbose "check_alias_available compiling testfile $src" 2
set f [open $src "w"]
# Compile a small test program. The definition of "g" is
# necessary to keep the Solaris assembler from complaining
# about the program.
puts $f "#ifdef __cplusplus\nextern \"C\"\n#endif\n"
puts $f "void g() {} void f() __attribute__((alias(\"g\")));"
close $f
set lines [${tool}_target_compile $src $obj object ""]
file delete $src
remote_file build delete $obj
if [string match "" $lines] then {
# No error messages, everything is OK.
return 2
} else {
if [regexp "alias definitions not supported" $lines] {
verbose "check_alias_available target does not support aliases" 2
set objformat [gcc_target_object_format]
if { $objformat == "elf" } {
verbose "check_alias_available but target uses ELF format, so it ought to" 2
return -1
} else {
return 0
}
} else {
if [regexp "only weak aliases are supported" $lines] {
verbose "check_alias_available target supports only weak aliases" 2
return 1
} else {
return -1
}
}
}
}]
}
# Returns 1 if the target toolchain supports strong aliases, 0 otherwise.
proc check_effective_target_alias { } {
if { [check_alias_available] < 2 } {
return 0
} else {
return 1
}
}
# Returns 1 if the target toolchain supports ifunc, 0 otherwise.
proc check_ifunc_available { } {
return [check_no_compiler_messages ifunc_available object {
#ifdef __cplusplus
extern "C" {
#endif
extern void f_ ();
typedef void F (void);
F* g (void) { return &f_; }
void f () __attribute__ ((ifunc ("g")));
#ifdef __cplusplus
}
#endif
}]
}
# Returns true if --gc-sections is supported on the target.
proc check_gc_sections_available { } {
global tool
return [check_cached_effective_target gc_sections_available {
# Some targets don't support gc-sections despite whatever's
# advertised by ld's options.
if { [istarget alpha*-*-*]
|| [istarget ia64-*-*] } {
return 0
}
# elf2flt uses -q (--emit-relocs), which is incompatible with
# --gc-sections.
if { [board_info target exists ldflags]
&& [regexp " -elf2flt\[ =\]" " [board_info target ldflags] "] } {
return 0
}
# VxWorks kernel modules are relocatable objects linked with -r,
# while RTP executables are linked with -q (--emit-relocs).
# Both of these options are incompatible with --gc-sections.
if { [istarget *-*-vxworks*] } {
return 0
}
# Check if the ld used by gcc supports --gc-sections.
set options [list "additional_flags=-print-prog-name=ld"]
set gcc_ld [lindex [${tool}_target_compile "" "" "none" $options] 0]
set ld_output [remote_exec host "$gcc_ld" "--help"]
if { [ string first "--gc-sections" $ld_output ] >= 0 } {
return 1
} else {
return 0
}
}]
}
# Returns 1 if "dot" is supported on the host.
proc check_dot_available { } {
verbose "check_dot_available" 2
set status [remote_exec host "dot" "-V"]
verbose " status: $status" 2
if { [lindex $status 0] != 0 } {
return 0
}
return 1
}
# Return 1 if according to target_info struct and explicit target list
# target is supposed to support trampolines.
proc check_effective_target_trampolines { } {
if [target_info exists gcc,no_trampolines] {
return 0
}
if { [istarget avr-*-*]
|| [istarget msp430-*-*]
|| [istarget nvptx-*-*]
|| [istarget hppa2.0w-hp-hpux11.23]
|| [istarget hppa64-hp-hpux11.23]
|| [istarget pru-*-*]
|| [istarget bpf-*-*] } {
return 0;
}
return 1
}
# Return 1 if target has limited stack size.
proc check_effective_target_stack_size { } {
if [target_info exists gcc,stack_size] {
return 1
}
return 0
}
# Return the value attribute of an effective target, otherwise return 0.
proc dg-effective-target-value { effective_target } {
if { "$effective_target" == "stack_size" } {
if [check_effective_target_stack_size] {
return [target_info gcc,stack_size]
}
}
return 0
}
# Return 1 if signal.h is supported.
proc check_effective_target_signal { } {
if [target_info exists gcc,signal_suppress] {
return 0
}
return 1
}
# Return 1 if according to target_info struct and explicit target list
# target disables -fdelete-null-pointer-checks. Targets should return 0
# if they simply default to -fno-delete-null-pointer-checks but obey
# -fdelete-null-pointer-checks when passed explicitly (and tests that
# depend on this option should do that).
proc check_effective_target_keeps_null_pointer_checks { } {
if [target_info exists keeps_null_pointer_checks] {
return 1
}
if { [istarget msp430-*-*] || [istarget cr16-*-*] } {
return 1;
}
return 0
}
# Return the autofdo profile wrapper
# Linux by default allows 516KB of perf event buffers
# in /proc/sys/kernel/perf_event_mlock_kb
# Each individual perf tries to grab it
# This causes problems with parallel test suite runs. Instead
# limit us to 8 pages (32K), which should be good enough
# for the small test programs. With the default settings
# this allows parallelism of 16 and higher of parallel gcc-auto-profile
proc profopt-perf-wrapper { } {
global srcdir
return "$srcdir/../config/i386/gcc-auto-profile -m8 "
}
# Return true if profiling is supported on the target.
proc check_profiling_available { test_what } {
verbose "Profiling argument is <$test_what>" 1
# These conditions depend on the argument so examine them before
# looking at the cache variable.
# Tree profiling requires TLS runtime support.
if { $test_what == "-fprofile-generate" } {
if { ![check_effective_target_tls_runtime] } {
return 0
}
}
if { $test_what == "-fauto-profile" } {
if { !([istarget i?86-*-linux*] || [istarget x86_64-*-linux*]) } {
verbose "autofdo only supported on linux"
return 0
}
# not cross compiling?
if { ![isnative] } {
verbose "autofdo not supported for non native builds"
return 0
}
set event [profopt-perf-wrapper]
if {$event == "" } {
verbose "autofdo not supported"
return 0
}
global srcdir
set status [remote_exec host "$srcdir/../config/i386/gcc-auto-profile" "-m8 true -v >/dev/null"]
if { [lindex $status 0] != 0 } {
verbose "autofdo not supported because perf does not work"
return 0
}
# no good way to check this in advance -- check later instead.
#set status [remote_exec host "create_gcov" "2>/dev/null"]
#if { [lindex $status 0] != 255 } {
# verbose "autofdo not supported due to missing create_gcov"
# return 0
#}
}
# Support for -p on solaris2 relies on mcrt1.o which comes with the
# vendor compiler. We cannot reliably predict the directory where the
# vendor compiler (and thus mcrt1.o) is installed so we can't
# necessarily find mcrt1.o even if we have it.
if { [istarget *-*-solaris2*] && $test_what == "-p" } {
return 0
}
# We don't yet support profiling for MIPS16.
if { [istarget mips*-*-*]
&& ![check_effective_target_nomips16]
&& ($test_what == "-p" || $test_what == "-pg") } {
return 0
}
# MinGW does not support -p.
if { [istarget *-*-mingw*] && $test_what == "-p" } {
return 0
}
# cygwin does not support -p.
if { [istarget *-*-cygwin*] && $test_what == "-p" } {
return 0
}
# uClibc does not have gcrt1.o.
if { [check_effective_target_uclibc]
&& ($test_what == "-p" || $test_what == "-pg") } {
return 0
}
# Now examine the cache variable.
set profiling_working \
[check_cached_effective_target profiling_available {
# Some targets don't have any implementation of __bb_init_func or are
# missing other needed machinery.
if {[istarget aarch64*-*-elf]
|| [istarget am3*-*-linux*]
|| [istarget amdgcn-*-*]
|| [istarget arm*-*-eabi*]
|| [istarget arm*-*-elf]
|| [istarget arm*-*-symbianelf*]
|| [istarget avr-*-*]
|| [istarget bfin-*-*]
|| [istarget cris-*-*]
|| [istarget csky-*-elf*]
|| [istarget fido-*-elf]
|| [istarget h8300-*-*]
|| [istarget lm32-*-*]
|| [istarget m32c-*-elf]
|| [istarget m68k-*-elf]
|| [istarget m68k-*-uclinux*]
|| [istarget mips*-*-elf*]
|| [istarget mmix-*-*]
|| [istarget mn10300-*-elf*]
|| [istarget moxie-*-elf*]
|| [istarget msp430-*-*]
|| [istarget nds32*-*-elf]
|| [istarget nios2-*-elf]
|| [istarget nvptx-*-*]
|| [istarget powerpc-*-eabi*]
|| [istarget powerpc-*-elf]
|| [istarget pru-*-*]
|| [istarget rx-*-*]
|| [istarget tic6x-*-elf]
|| [istarget visium-*-*]
|| [istarget xstormy16-*]
|| [istarget xtensa*-*-elf]
|| [istarget *-*-rtems*]
|| [istarget *-*-vxworks*] } {
return 0
} else {
return 1
}
}]
# -pg link test result can't be cached since it may change between
# runs.
if { $profiling_working == 1
&& ![check_no_compiler_messages_nocache profiling executable {
int main() { return 0; } } "-pg"] } {
set profiling_working 0
}
return $profiling_working
}
# Check to see if a target is "freestanding". This is as per the definition
# in Section 4 of C99 standard. Effectively, it is a target which supports no
# extra headers or libraries other than what is considered essential.
proc check_effective_target_freestanding { } {
if { [istarget nvptx-*-*] } {
return 1
}
return 0
}
# Check to see that file I/O functions are available.
proc check_effective_target_fileio { } {
return [check_no_compiler_messages fileio_available executable {
#include <stdio.h>
int main() {
char *n = tmpnam (NULL);
FILE *f = fopen (n, "w");
fclose (f);
remove (n);
return 0;
} } ""]
}
# Return 1 if target has packed layout of structure members by
# default, 0 otherwise. Note that this is slightly different than
# whether the target has "natural alignment": both attributes may be
# false.
proc check_effective_target_default_packed { } {
return [check_no_compiler_messages default_packed assembly {
struct x { char a; long b; } c;
int s[sizeof (c) == sizeof (char) + sizeof (long) ? 1 : -1];
}]
}
# Return 1 if target has PCC_BITFIELD_TYPE_MATTERS defined. See
# documentation, where the test also comes from.
proc check_effective_target_pcc_bitfield_type_matters { } {
# PCC_BITFIELD_TYPE_MATTERS isn't just about unnamed or empty
# bitfields, but let's stick to the example code from the docs.
return [check_no_compiler_messages pcc_bitfield_type_matters assembly {
struct foo1 { char x; char :0; char y; };
struct foo2 { char x; int :0; char y; };
int s[sizeof (struct foo1) != sizeof (struct foo2) ? 1 : -1];
}]
}
# Add to FLAGS all the target-specific flags needed to use thread-local storage.
proc add_options_for_tls { flags } {
# On Solaris 9, __tls_get_addr/___tls_get_addr only lives in
# libthread, so always pass -pthread for native TLS. Same for AIX.
# Need to duplicate native TLS check from
# check_effective_target_tls_native to avoid recursion.
if { ([istarget powerpc-ibm-aix*]) &&
[check_no_messages_and_pattern tls_native "!emutls" assembly {
__thread int i;
int f (void) { return i; }
void g (int j) { i = j; }
}] } {
return "-pthread [g++_link_flags [get_multilibs "-pthread"] ] $flags "
}
return $flags
}
# Return 1 if indirect jumps are supported, 0 otherwise.
proc check_effective_target_indirect_jumps {} {
if { [istarget nvptx-*-*] || [istarget bpf-*-*] } {
return 0
}
return 1
}
# Return 1 if nonlocal goto is supported, 0 otherwise.
proc check_effective_target_nonlocal_goto {} {
if { [istarget nvptx-*-*] || [istarget bpf-*-*] } {
return 0
}
return 1
}
# Return 1 if global constructors are supported, 0 otherwise.
proc check_effective_target_global_constructor {} {
if { [istarget nvptx-*-*]
|| [istarget amdgcn-*-*]
|| [istarget bpf-*-*] } {
return 0
}
return 1
}
# Return 1 if taking label values is supported, 0 otherwise.
proc check_effective_target_label_values {} {
if { [istarget nvptx-*-*] || [target_info exists gcc,no_label_values] } {
return 0
}
return 1
}
# Return 1 if builtin_return_address and builtin_frame_address are
# supported, 0 otherwise.
proc check_effective_target_return_address {} {
if { [istarget nvptx-*-*] } {
return 0
}
# No notion of return address in eBPF.
if { [istarget bpf-*-*] } {
return 0
}
# It could be supported on amdgcn, but isn't yet.
if { [istarget amdgcn*-*-*] } {
return 0
}
return 1
}
# Return 1 if the assembler does not verify function types against
# calls, 0 otherwise. Such verification will typically show up problems
# with K&R C function declarations.
proc check_effective_target_untyped_assembly {} {
if { [istarget nvptx-*-*] } {
return 0
}
return 1
}
# Return 1 if alloca is supported, 0 otherwise.
proc check_effective_target_alloca {} {
if { [istarget nvptx-*-*] } {
return [check_no_compiler_messages alloca assembly {
void f (void*);
void g (int n) { f (__builtin_alloca (n)); }
}]
}
return 1
}
# Return 1 if thread local storage (TLS) is supported, 0 otherwise.
proc check_effective_target_tls {} {
return [check_no_compiler_messages tls assembly {
__thread int i;
int f (void) { return i; }
void g (int j) { i = j; }
}]
}
# Return 1 if *native* thread local storage (TLS) is supported, 0 otherwise.
proc check_effective_target_tls_native {} {
# VxWorks uses emulated TLS machinery, but with non-standard helper
# functions, so we fail to automatically detect it.
if { [istarget *-*-vxworks*] } {
return 0
}
return [check_no_messages_and_pattern tls_native "!emutls" assembly {
__thread int i;
int f (void) { return i; }
void g (int j) { i = j; }
}]
}
# Return 1 if *emulated* thread local storage (TLS) is supported, 0 otherwise.
proc check_effective_target_tls_emulated {} {
# VxWorks uses emulated TLS machinery, but with non-standard helper
# functions, so we fail to automatically detect it.
if { [istarget *-*-vxworks*] } {
return 1
}
return [check_no_messages_and_pattern tls_emulated "emutls" assembly {
__thread int i;
int f (void) { return i; }
void g (int j) { i = j; }
}]
}
# Return 1 if TLS executables can run correctly, 0 otherwise.
proc check_effective_target_tls_runtime {} {
return [check_runtime tls_runtime {
__thread int thr __attribute__((tls_model("global-dynamic"))) = 0;
int main (void) { return thr; }
} [add_options_for_tls ""]]
}
# Return 1 if atomic compare-and-swap is supported on 'int'
proc check_effective_target_cas_char {} {
return [check_no_compiler_messages cas_char assembly {
#ifndef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1
#error unsupported
#endif
} ""]
}
proc check_effective_target_cas_int {} {
return [check_no_compiler_messages cas_int assembly {
#if __INT_MAX__ == 0x7fff && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
/* ok */
#elif __INT_MAX__ == 0x7fffffff && __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
/* ok */
#else
#error unsupported
#endif
} ""]
}
# Return 1 if -ffunction-sections is supported, 0 otherwise.
proc check_effective_target_function_sections {} {
# Darwin has its own scheme and silently accepts -ffunction-sections.
if { [istarget *-*-darwin*] } {
return 0
}
return [check_no_compiler_messages functionsections assembly {
void foo (void) { }
} "-ffunction-sections"]
}
# Return 1 if instruction scheduling is available, 0 otherwise.
proc check_effective_target_scheduling {} {
return [check_no_compiler_messages scheduling object {
void foo (void) { }
} "-fschedule-insns"]
}
# Return 1 if trapping arithmetic is available, 0 otherwise.
proc check_effective_target_trapping {} {
return [check_no_compiler_messages trapping object {
int add (int a, int b) { return a + b; }
} "-ftrapv"]
}
# Return 1 if compilation with -fgraphite is error-free for trivial
# code, 0 otherwise.
proc check_effective_target_fgraphite {} {
return [check_no_compiler_messages fgraphite object {
void foo (void) { }
} "-O1 -fgraphite"]
}
# Return 1 if compiled with --enable-offload-targets=
# This affects host compilation as ENABLE_OFFLOAD then evaluates to true.
proc check_effective_target_offloading_enabled {} {
return [check_configured_with "--enable-offload-targets"]
}
# Return 1 if compilation with -fopenacc is error-free for trivial
# code, 0 otherwise.
proc check_effective_target_fopenacc {} {
# nvptx/amdgcn can be built with the device-side bits of openacc, but it
# does not make sense to test it as an openacc host.
if [istarget nvptx-*-*] { return 0 }
if [istarget amdgcn-*-*] { return 0 }
return [check_no_compiler_messages fopenacc object {
void foo (void) { }
} "-fopenacc"]
}
# Return 1 if compilation with -fopenmp is error-free for trivial
# code, 0 otherwise.
proc check_effective_target_fopenmp {} {
# nvptx/amdgcn can be built with the device-side bits of libgomp, but it
# does not make sense to test it as an openmp host.
if [istarget nvptx-*-*] { return 0 }
if [istarget amdgcn-*-*] { return 0 }
return [check_no_compiler_messages fopenmp object {
void foo (void) { }
} "-fopenmp"]
}
# Return 1 if compilation with -fgnu-tm is error-free for trivial
# code, 0 otherwise.
proc check_effective_target_fgnu_tm {} {
return [check_no_compiler_messages fgnu_tm object {
void foo (void) { }
} "-fgnu-tm"]
}
# Return 1 if the target supports mmap, 0 otherwise.
proc check_effective_target_mmap {} {
return [check_function_available "mmap"]
}
# Return 1 if the target supports sysconf, 0 otherwise.
proc check_effective_target_sysconf {} {
return [check_function_available "sysconf"]
}
# Return 1 if the target supports dlopen, 0 otherwise.
proc check_effective_target_dlopen {} {
return [check_no_compiler_messages dlopen executable {
#include <dlfcn.h>
int main(void) { dlopen ("dummy.so", RTLD_NOW); }
} [add_options_for_dlopen ""]]
}
proc add_options_for_dlopen { flags } {
return "$flags -ldl"
}
# Return 1 if the target supports clone, 0 otherwise.
proc check_effective_target_clone {} {
return [check_function_available "clone"]
}
# Return 1 if the target supports setrlimit, 0 otherwise.
proc check_effective_target_setrlimit {} {
# Darwin has non-posix compliant RLIMIT_AS
if { [istarget *-*-darwin*] } {
return 0
}
return [check_function_available "setrlimit"]
}
# Return 1 if the target supports gettimeofday, 0 otherwise.
proc check_effective_target_gettimeofday {} {
return [check_function_available "gettimeofday"]
}
# Return 1 if the target supports swapcontext, 0 otherwise.
proc check_effective_target_swapcontext {} {
return [check_no_compiler_messages swapcontext executable {
#include <ucontext.h>
int main (void)
{
ucontext_t orig_context,child_context;
if (swapcontext(&child_context, &orig_context) < 0) { }
}
}]
}
# Return 1 if the target supports POSIX threads, 0 otherwise.
proc check_effective_target_pthread {} {
return [check_no_compiler_messages pthread object {
#include <pthread.h>
void foo (void) { }
} "-pthread"]
}
# Return 1 if compilation with -gstabs is error-free for trivial
# code, 0 otherwise.
proc check_effective_target_stabs {} {
return [check_no_compiler_messages stabs object {
void foo (void) { }
} "-gstabs"]
}
# Return 1 if compilation with -mpe-aligned-commons is error-free
# for trivial code, 0 otherwise.
proc check_effective_target_pe_aligned_commons {} {
if { [istarget *-*-cygwin*] || [istarget *-*-mingw*] } {
return [check_no_compiler_messages pe_aligned_commons object {
int foo;
} "-mpe-aligned-commons"]
}
return 0
}
# Return 1 if the target supports -static
proc check_effective_target_static {} {
if { [istarget arm*-*-uclinuxfdpiceabi] } {
return 0;
}
return [check_no_compiler_messages static executable {
int main (void) { return 0; }
} "-static"]
}
# Return 1 if the target supports -fstack-protector
proc check_effective_target_fstack_protector {} {
return [check_runtime fstack_protector {
#include <string.h>
int main (int argc, char *argv[]) {
char buf[64];
return !strcpy (buf, strrchr (argv[0], '/'));
}
} "-fstack-protector"]
}
# Return 1 if the target supports -fstack-check or -fstack-check=$stack_kind
proc check_stack_check_available { stack_kind } {
if [string match "" $stack_kind] then {
set stack_opt "-fstack-check"
} else { set stack_opt "-fstack-check=$stack_kind" }
return [check_no_compiler_messages stack_check_$stack_kind executable {
int main (void) { return 0; }
} "$stack_opt"]
}
# Return 1 if compilation with -freorder-blocks-and-partition is error-free
# for trivial code, 0 otherwise. As some targets (ARM for example) only
# warn when -fprofile-use is also supplied we test that combination too.
proc check_effective_target_freorder {} {
if { [check_no_compiler_messages freorder object {
void foo (void) { }
} "-freorder-blocks-and-partition"]
&& [check_no_compiler_messages fprofile_use_freorder object {
void foo (void) { }
} "-fprofile-use -freorder-blocks-and-partition -Wno-missing-profile"] } {
return 1
}
return 0
}
# 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.
proc check_effective_target_fpic { } {
# 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.
foreach arg {fpic fPIC} {
if [check_no_compiler_messages $arg object {
extern int foo (void); extern int bar;
int baz (void) { return foo () + bar; }
} "-$arg"] {
return 1
}
}
return 0
}
# On AArch64, if -fpic is not supported, then we will fall back to -fPIC
# silently. So, we can't rely on above "check_effective_target_fpic" as it
# assumes compiler will give warning if -fpic not supported. Here we check
# whether binutils supports those new -fpic relocation modifiers, and assume
# -fpic is supported if there is binutils support. GCC configuration will
# enable -fpic for AArch64 in this case.
#
# "check_effective_target_aarch64_small_fpic" is dedicated for checking small
# memory model -fpic relocation types.
proc check_effective_target_aarch64_small_fpic { } {
if { [istarget aarch64*-*-*] } {
return [check_no_compiler_messages aarch64_small_fpic object {
void foo (void) { asm ("ldr x0, [x2, #:gotpage_lo15:globalsym]"); }
}]
} else {
return 0
}
}
# On AArch64, instruction sequence for TLS LE under -mtls-size=32 will utilize
# the relocation modifier "tprel_g0_nc" together with MOVK, it's only supported
# in binutils since 2015-03-04 as PR gas/17843.
#
# This test directive make sure binutils support all features needed by TLS LE
# under -mtls-size=32 on AArch64.
proc check_effective_target_aarch64_tlsle32 { } {
if { [istarget aarch64*-*-*] } {
return [check_no_compiler_messages aarch64_tlsle32 object {
void foo (void) { asm ("movk x1,#:tprel_g0_nc:t1"); }
}]
} else {
return 0
}
}
# Return 1 if -shared is supported, as in no warnings or errors
# emitted, 0 otherwise.
proc check_effective_target_shared { } {
# 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.
return [check_no_compiler_messages shared executable {
extern int foo (void); extern int bar;
int baz (void) { return foo () + bar; }
} "-shared -fpic"]
}
# Return 1 if -pie, -fpie and -fPIE are supported, 0 otherwise.
proc check_effective_target_pie { } {
if { [istarget *-*-darwin\[912\]*]
|| [istarget *-*-dragonfly*]
|| [istarget *-*-freebsd*]
|| [istarget *-*-linux*]
|| [istarget arm*-*-uclinuxfdpiceabi]
|| [istarget *-*-gnu*]
|| [istarget *-*-amdhsa]} {
return 1;
}
if { [istarget *-*-solaris2.1\[1-9\]*] } {
# Full PIE support was added in Solaris 11.3, but gcc errors out
# if missing, so check for that.
return [check_no_compiler_messages pie executable {
int main (void) { return 0; }
} "-pie -fpie"]
}
return 0
}
# Return true if the target supports -mpaired-single (as used on MIPS).
proc check_effective_target_mpaired_single { } {
return [check_no_compiler_messages mpaired_single object {
void foo (void) { }
} "-mpaired-single"]
}
# Return true if the target has access to FPU instructions.
proc check_effective_target_hard_float { } {
if { [istarget mips*-*-*] } {
return [check_no_compiler_messages hard_float assembly {
#if (defined __mips_soft_float || defined __mips16)
#error __mips_soft_float || __mips16
#endif
}]
}
# This proc is actually checking the availabilty of FPU
# support for doubles, so on the RX we must fail if the
# 64-bit double multilib has been selected.
if { [istarget rx-*-*] } {
return 0
# return [check_no_compiler_messages hard_float assembly {
#if defined __RX_64_BIT_DOUBLES__
#error __RX_64_BIT_DOUBLES__
#endif
# }]
}
# The generic test doesn't work for C-SKY because some cores have
# hard float for single precision only.
if { [istarget csky*-*-*] } {
return [check_no_compiler_messages hard_float assembly {
#if defined __csky_soft_float__
#error __csky_soft_float__
#endif
}]
}
# The generic test equates hard_float with "no call for adding doubles".
return [check_no_messages_and_pattern hard_float "!\\(call" rtl-expand {
double a (double b, double c) { return b + c; }
}]
}
# Return true if the target is a 64-bit MIPS target.
proc check_effective_target_mips64 { } {
return [check_no_compiler_messages mips64 assembly {
#ifndef __mips64
#error !__mips64
#endif
}]
}
# Return true if the target is a MIPS target that does not produce
# MIPS16 code.
proc check_effective_target_nomips16 { } {
return [check_no_compiler_messages nomips16 object {
#ifndef __mips
#error !__mips
#else
/* A cheap way of testing for -mflip-mips16. */
void foo (void) { asm ("addiu $20,$20,1"); }
void bar (void) { asm ("addiu $20,$20,1"); }
#endif
}]
}
# Add the options needed for MIPS16 function attributes. At the moment,
# we don't support MIPS16 PIC.
proc add_options_for_mips16_attribute { flags } {
return "$flags -mno-abicalls -fno-pic -DMIPS16=__attribute__((mips16))"
}
# Return true if we can force a mode that allows MIPS16 code generation.
# We don't support MIPS16 PIC, and only support MIPS16 -mhard-float
# for o32 and o64.
proc check_effective_target_mips16_attribute { } {
return [check_no_compiler_messages mips16_attribute assembly {
#ifdef PIC
#error PIC
#endif
#if defined __mips_hard_float \
&& (!defined _ABIO32 || _MIPS_SIM != _ABIO32) \
&& (!defined _ABIO64 || _MIPS_SIM != _ABIO64)
#error __mips_hard_float && (!_ABIO32 || !_ABIO64)
#endif
} [add_options_for_mips16_attribute ""]]
}
# Return 1 if the target supports long double larger than double when
# using the new ABI, 0 otherwise.
proc check_effective_target_mips_newabi_large_long_double { } {
return [check_no_compiler_messages mips_newabi_large_long_double object {
int dummy[sizeof(long double) > sizeof(double) ? 1 : -1];
} "-mabi=64"]
}
# Return true if the target is a MIPS target that has access
# to the LL and SC instructions.
proc check_effective_target_mips_llsc { } {
if { ![istarget mips*-*-*] } {
return 0
}
# Assume that these instructions are always implemented for
# non-elf* targets, via emulation if necessary.
if { ![istarget *-*-elf*] } {
return 1
}
# Otherwise assume LL/SC support for everything but MIPS I.
return [check_no_compiler_messages mips_llsc assembly {
#if __mips == 1
#error __mips == 1
#endif
}]
}
# Return true if the target is a MIPS target that uses in-place relocations.
proc check_effective_target_mips_rel { } {
if { ![istarget mips*-*-*] } {
return 0
}
return [check_no_compiler_messages mips_rel object {
#if (defined _ABIN32 && _MIPS_SIM == _ABIN32) \
|| (defined _ABI64 && _MIPS_SIM == _ABI64)
#error _ABIN32 && (_ABIN32 || _ABI64)
#endif
}]
}
# Return true if the target is a MIPS target that uses the EABI.
proc check_effective_target_mips_eabi { } {
if { ![istarget mips*-*-*] } {
return 0
}
return [check_no_compiler_messages mips_eabi object {
#ifndef __mips_eabi
#error !__mips_eabi
#endif
}]
}
# Return 1 if the current multilib does not generate PIC by default.
proc check_effective_target_nonpic { } {
return [check_no_compiler_messages nonpic assembly {
#if __PIC__
#error __PIC__
#endif
}]
}
# Return 1 if the current multilib generates PIE by default.
proc check_effective_target_pie_enabled { } {
return [check_no_compiler_messages pie_enabled assembly {
#ifndef __PIE__
#error unsupported
#endif
}]
}
# Return 1 if the target generates -fstack-protector by default.
proc check_effective_target_fstack_protector_enabled {} {
return [ check_no_compiler_messages fstack_protector_enabled assembly {
#if !defined(__SSP__) && !defined(__SSP_ALL__) && \
!defined(__SSP_STRONG__) && !defined(__SSP_EXPICIT__)
#error unsupported
#endif
}]
}
# Return 1 if the target does not use a status wrapper.
proc check_effective_target_unwrapped { } {
if { [target_info needs_status_wrapper] != "" \
&& [target_info needs_status_wrapper] != "0" } {
return 0
}
return 1
}
# Return true if iconv is supported on the target. In particular IBM1047.
proc check_iconv_available { test_what } {
global libiconv
# If the tool configuration file has not set libiconv, try "-liconv"
if { ![info exists libiconv] } {
set libiconv "-liconv"
}
set test_what [lindex $test_what 1]
return [check_runtime_nocache $test_what [subst {
#include <iconv.h>
int main (void)
{
iconv_t cd;
cd = iconv_open ("$test_what", "UTF-8");
if (cd == (iconv_t) -1)
return 1;
return 0;
}
}] $libiconv]
}
# Return true if the atomic library is supported on the target.
proc check_effective_target_libatomic_available { } {
return [check_no_compiler_messages libatomic_available executable {
int main (void) { return 0; }
} "-latomic"]
}
# Return 1 if an ASCII locale is supported on this host, 0 otherwise.
proc check_ascii_locale_available { } {
return 1
}
# Return true if named sections are supported on this target.
proc check_named_sections_available { } {
return [check_no_compiler_messages named_sections assembly {
int __attribute__ ((section("whatever"))) foo;
}]
}
# Return true if the "naked" function attribute is supported on this target.
proc check_effective_target_naked_functions { } {
return [check_no_compiler_messages naked_functions assembly {
void f() __attribute__((naked));
}]
}
# Return 1 if the target supports Fortran real kinds larger than real(8),
# 0 otherwise.
#
# When the target name changes, replace the cached result.
proc check_effective_target_fortran_large_real { } {
return [check_no_compiler_messages fortran_large_real executable {
! Fortran
integer,parameter :: k = selected_real_kind (precision (0.0_8) + 1)
real(kind=k) :: x
x = cos (x)
end
}]
}
# Return 1 if the target supports Fortran real kind real(16),
# 0 otherwise. Contrary to check_effective_target_fortran_large_real
# this checks for Real(16) only; the other returned real(10) if
# both real(10) and real(16) are available.
#
# When the target name changes, replace the cached result.
proc check_effective_target_fortran_real_16 { } {
return [check_no_compiler_messages fortran_real_16 executable {
! Fortran
real(kind=16) :: x
x = cos (x)
end
}]
}
# Return 1 if the target supports Fortran real kind 10,
# 0 otherwise. Contrary to check_effective_target_fortran_large_real
# this checks for real(10) only.
#
# When the target name changes, replace the cached result.
proc check_effective_target_fortran_real_10 { } {
return [check_no_compiler_messages fortran_real_10 executable {
! Fortran
real(kind=10) :: x
x = cos (x)
end
}]
}
# Return 1 if the target supports Fortran real kind C_FLOAT128,
# 0 otherwise. This differs from check_effective_target_fortran_real_16
# because _Float128 has the additional requirement that it be the
# 128-bit IEEE encoding; even if _Float128 is available in C, it may not
# have a corresponding Fortran kind on targets (PowerPC) that use some
# other encoding for long double/TFmode/real(16).
proc check_effective_target_fortran_real_c_float128 { } {
return [check_no_compiler_messages fortran_real_c_float128 executable {
! Fortran
use iso_c_binding
real(kind=c_float128) :: x
x = cos (x)
end
}]
}
# Return 1 if the target supports Fortran's IEEE modules,
# 0 otherwise.
#
# When the target name changes, replace the cached result.
proc check_effective_target_fortran_ieee { flags } {
return [check_no_compiler_messages fortran_ieee executable {
! Fortran
use, intrinsic :: ieee_features
end
} $flags ]
}
# Return 1 if the target supports SQRT for the largest floating-point
# type. (Some targets lack the libm support for this FP type.)
# On most targets, this check effectively checks either whether sqrtl is
# available or on __float128 systems whether libquadmath is installed,
# which provides sqrtq.
#
# When the target name changes, replace the cached result.
proc check_effective_target_fortran_largest_fp_has_sqrt { } {
return [check_no_compiler_messages fortran_largest_fp_has_sqrt executable {
! Fortran
use iso_fortran_env, only: real_kinds
integer,parameter:: maxFP = real_kinds(ubound(real_kinds,dim=1))
real(kind=maxFP), volatile :: x
x = 2.0_maxFP
x = sqrt (x)
end
}]
}
# Return 1 if the target supports Fortran integer kinds larger than
# integer(8), 0 otherwise.
#
# When the target name changes, replace the cached result.
proc check_effective_target_fortran_large_int { } {
return [check_no_compiler_messages fortran_large_int executable {
! Fortran
integer,parameter :: k = selected_int_kind (range (0_8) + 1)
integer(kind=k) :: i
end
}]
}
# Return 1 if the target supports Fortran integer(16), 0 otherwise.
#
# When the target name changes, replace the cached result.
proc check_effective_target_fortran_integer_16 { } {
return [check_no_compiler_messages fortran_integer_16 executable {
! Fortran
integer(16) :: i
end
}]
}
# Return 1 if we can statically link libgfortran, 0 otherwise.
#
# When the target name changes, replace the cached result.
proc check_effective_target_static_libgfortran { } {
return [check_no_compiler_messages static_libgfortran executable {
! Fortran
print *, 'test'
end
} "-static"]
}
# Return 1 if we can use the -rdynamic option, 0 otherwise.
proc check_effective_target_rdynamic { } {
return [check_no_compiler_messages rdynamic executable {
int main() { return 0; }
} "-rdynamic"]
}
proc check_linker_plugin_available { } {
return [check_no_compiler_messages_nocache linker_plugin executable {
int main() { return 0; }
} "-flto -fuse-linker-plugin"]
}
# Return 1 if the target OS supports running SSE executables, 0
# otherwise. Cache the result.
proc check_sse_os_support_available { } {
return [check_cached_effective_target sse_os_support_available {
# If this is not the right target then we can skip the test.
if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
expr 0
} else {
expr 1
}
}]
}
# Return 1 if the target OS supports running AVX executables, 0
# otherwise. Cache the result.
proc check_avx_os_support_available { } {
return [check_cached_effective_target avx_os_support_available {
# If this is not the right target then we can skip the test.
if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
expr 0
} else {
# Check that OS has AVX and SSE saving enabled.
check_runtime_nocache avx_os_support_available {
int main ()
{
unsigned int eax, edx;
asm ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (0));
return (eax & 0x06) != 0x06;
}
} ""
}
}]
}
# Return 1 if the target OS supports running AVX executables, 0
# otherwise. Cache the result.
proc check_avx512_os_support_available { } {
return [check_cached_effective_target avx512_os_support_available {
# If this is not the right target then we can skip the test.
if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
expr 0
} else {
# Check that OS has AVX512, AVX and SSE saving enabled.
check_runtime_nocache avx512_os_support_available {
int main ()
{
unsigned int eax, edx;
asm ("xgetbv" : "=a" (eax), "=d" (edx) : "c" (0));
return (eax & 0xe6) != 0xe6;
}
} ""
}
}]
}
# Return 1 if the target supports executing SSE instructions, 0
# otherwise. Cache the result.
proc check_sse_hw_available { } {
return [check_cached_effective_target sse_hw_available {
# If this is not the right target then we can skip the test.
if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
expr 0
} else {
check_runtime_nocache sse_hw_available {
#include "cpuid.h"
int main ()
{
unsigned int eax, ebx, ecx, edx;
if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
return 1;
return !(edx & bit_SSE);
}
} ""
}
}]
}
# Return 1 if the target supports executing SSE2 instructions, 0
# otherwise. Cache the result.
proc check_sse2_hw_available { } {
return [check_cached_effective_target sse2_hw_available {
# If this is not the right target then we can skip the test.
if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
expr 0
} else {
check_runtime_nocache sse2_hw_available {
#include "cpuid.h"
int main ()
{
unsigned int eax, ebx, ecx, edx;
if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
return 1;
return !(edx & bit_SSE2);
}
} ""
}
}]
}
# Return 1 if the target supports executing SSE4 instructions, 0
# otherwise. Cache the result.
proc check_sse4_hw_available { } {
return [check_cached_effective_target sse4_hw_available {
# If this is not the right target then we can skip the test.
if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
expr 0
} else {
check_runtime_nocache sse4_hw_available {
#include "cpuid.h"
int main ()
{
unsigned int eax, ebx, ecx, edx;
if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
return 1;
return !(ecx & bit_SSE4_2);
}
} ""
}
}]
}
# Return 1 if the target supports executing AVX instructions, 0
# otherwise. Cache the result.
proc check_avx_hw_available { } {
return [check_cached_effective_target avx_hw_available {
# If this is not the right target then we can skip the test.
if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
expr 0
} else {
check_runtime_nocache avx_hw_available {
#include "cpuid.h"
int main ()
{
unsigned int eax, ebx, ecx, edx;
if (!__get_cpuid (1, &eax, &ebx, &ecx, &edx))
return 1;
return ((ecx & (bit_AVX | bit_OSXSAVE))
!= (bit_AVX | bit_OSXSAVE));
}
} ""
}
}]
}
# Return 1 if the target supports executing AVX2 instructions, 0
# otherwise. Cache the result.
proc check_avx2_hw_available { } {
return [check_cached_effective_target avx2_hw_available {
# If this is not the right target then we can skip the test.
if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
expr 0
} else {
check_runtime_nocache avx2_hw_available {
#include <stddef.h>
#include "cpuid.h"
int main ()
{
unsigned int eax, ebx, ecx, edx;
if (__get_cpuid_max (0, NULL) < 7)
return 1;
__cpuid (1, eax, ebx, ecx, edx);
if (!(ecx & bit_OSXSAVE))
return 1;
__cpuid_count (7, 0, eax, ebx, ecx, edx);
return !(ebx & bit_AVX2);
}
} ""
}
}]
}
# Return 1 if the target supports executing AVX512 foundation instructions, 0
# otherwise. Cache the result.
proc check_avx512f_hw_available { } {
return [check_cached_effective_target avx512f_hw_available {
# If this is not the right target then we can skip the test.
if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
expr 0
} else {
check_runtime_nocache avx512f_hw_available {
#include <stddef.h>
#include "cpuid.h"
int main ()
{
unsigned int eax, ebx, ecx, edx;
if (__get_cpuid_max (0, NULL) < 7)
return 1;
__cpuid (1, eax, ebx, ecx, edx);
if (!(ecx & bit_OSXSAVE))
return 1;
__cpuid_count (7, 0, eax, ebx, ecx, edx);
return !(ebx & bit_AVX512F);
}
} ""
}
}]
}
# Return 1 if the target supports running SSE executables, 0 otherwise.
proc check_effective_target_sse_runtime { } {
if { [check_effective_target_sse]
&& [check_sse_hw_available]
&& [check_sse_os_support_available] } {
return 1
}
return 0
}
# Return 1 if the target supports running SSE2 executables, 0 otherwise.
proc check_effective_target_sse2_runtime { } {
if { [check_effective_target_sse2]
&& [check_sse2_hw_available]
&& [check_sse_os_support_available] } {
return 1
}
return 0
}
# Return 1 if the target supports running SSE4 executables, 0 otherwise.
proc check_effective_target_sse4_runtime { } {
if { [check_effective_target_sse4]
&& [check_sse4_hw_available]
&& [check_sse_os_support_available] } {
return 1
}
return 0
}
# Return 1 if the target supports running AVX executables, 0 otherwise.
proc check_effective_target_avx_runtime { } {
if { [check_effective_target_avx]
&& [check_avx_hw_available]
&& [check_avx_os_support_available] } {
return 1
}
return 0
}
# Return 1 if the target supports running AVX2 executables, 0 otherwise.
proc check_effective_target_avx2_runtime { } {
if { [check_effective_target_avx2]
&& [check_avx2_hw_available]
&& [check_avx_os_support_available] } {
return 1
}
return 0
}
# Return 1 if the target supports running AVX512f executables, 0 otherwise.
proc check_effective_target_avx512f_runtime { } {
if { [check_effective_target_avx512f]
&& [check_avx512f_hw_available]
&& [check_avx512_os_support_available] } {
return 1
}
return 0
}
# Return 1 if bmi2 instructions can be compiled.
proc check_effective_target_bmi2 { } {
if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
return 0
}
return [check_no_compiler_messages bmi2 object {
unsigned int
_bzhi_u32 (unsigned int __X, unsigned int __Y)
{
return __builtin_ia32_bzhi_si (__X, __Y);
}
} "-mbmi2" ]
}
# Return 1 if the target supports executing MIPS Paired-Single instructions,
# 0 otherwise. Cache the result.
proc check_mpaired_single_hw_available { } {
return [check_cached_effective_target mpaired_single_hw_available {
# If this is not the right target then we can skip the test.
if { !([istarget mips*-*-*]) } {
expr 0
} else {
check_runtime_nocache mpaired_single_hw_available {
int main()
{
asm volatile ("pll.ps $f2,$f4,$f6");
return 0;
}
} ""
}
}]
}
# Return 1 if the target supports executing Loongson vector instructions,
# 0 otherwise. Cache the result.
proc check_mips_loongson_mmi_hw_available { } {
return [check_cached_effective_target mips_loongson_mmi_hw_available {
# If this is not the right target then we can skip the test.
if { !([istarget mips*-*-*]) } {
expr 0
} else {
check_runtime_nocache mips_loongson_mmi_hw_available {
#include <loongson-mmiintrin.h>
int main()
{
asm volatile ("paddw $f2,$f4,$f6");
return 0;
}
} "-mloongson-mmi"
}
}]
}
# Return 1 if the target supports executing MIPS MSA instructions, 0
# otherwise. Cache the result.
proc check_mips_msa_hw_available { } {
return [check_cached_effective_target mips_msa_hw_available {
# If this is not the right target then we can skip the test.
if { !([istarget mips*-*-*]) } {
expr 0
} else {
check_runtime_nocache mips_msa_hw_available {
#if !defined(__mips_msa)
#error "MSA NOT AVAIL"
#else
#if !(((__mips == 64) || (__mips == 32)) && (__mips_isa_rev >= 2))
#error "MSA NOT AVAIL FOR ISA REV < 2"
#endif
#if !defined(__mips_hard_float)
#error "MSA HARD_FLOAT REQUIRED"
#endif
#if __mips_fpr != 64
#error "MSA 64-bit FPR REQUIRED"
#endif
#include <msa.h>
int main()
{
v8i16 v = __builtin_msa_ldi_h (0);
v[0] = 0;
return v[0];
}
#endif
} "-mmsa"
}
}]
}
# Return 1 if the target supports running MIPS Paired-Single
# executables, 0 otherwise.
proc check_effective_target_mpaired_single_runtime { } {
if { [check_effective_target_mpaired_single]
&& [check_mpaired_single_hw_available] } {
return 1
}
return 0
}
# Return 1 if the target supports running Loongson executables, 0 otherwise.
proc check_effective_target_mips_loongson_mmi_runtime { } {
if { [check_effective_target_mips_loongson_mmi]
&& [check_mips_loongson_mmi_hw_available] } {
return 1
}
return 0
}
# Return 1 if the target supports running MIPS MSA executables, 0 otherwise.
proc check_effective_target_mips_msa_runtime { } {
if { [check_effective_target_mips_msa]
&& [check_mips_msa_hw_available] } {
return 1
}
return 0
}
# Return 1 if we are compiling for 64-bit PowerPC but we do not use direct
# move instructions for moves from GPR to FPR.
proc check_effective_target_powerpc64_no_dm { } {
# The "mulld" checks if we are generating PowerPC64 code. The "lfd"
# checks if we do not use direct moves, but use the old-fashioned
# slower move-via-the-stack.
return [check_no_messages_and_pattern powerpc64_no_dm \
{\mmulld\M.*\mlfd} assembly {
double f(long long x) { return x*x; }
} {-O2}]
}
# Return 1 if the target supports the __builtin_cpu_supports built-in,
# including having a new enough library to support the test. Cache the result.
# Require at least a power7 to run on.
proc check_ppc_cpu_supports_hw_available { } {
return [check_cached_effective_target ppc_cpu_supports_hw_available {
# Some simulators are known to not support VSX/power8 instructions.
# For now, disable on Darwin
if { [istarget powerpc-*-eabi]
|| [istarget powerpc*-*-eabispe]
|| [istarget *-*-darwin*]} {
expr 0
} else {
set options "-mvsx"
check_runtime_nocache ppc_cpu_supports_hw_available {
int main()
{
#ifdef __MACH__
asm volatile ("xxlor vs0,vs0,vs0");
#else
asm volatile ("xxlor 0,0,0");
#endif
if (!__builtin_cpu_supports ("vsx"))
return 1;
return 0;
}
} $options
}
}]
}
# Return 1 if the target supports executing 750CL paired-single instructions, 0
# otherwise. Cache the result.
proc check_750cl_hw_available { } {
return [check_cached_effective_target 750cl_hw_available {
# If this is not the right target then we can skip the test.
if { ![istarget powerpc-*paired*] } {
expr 0
} else {
check_runtime_nocache 750cl_hw_available {
int main()
{
#ifdef __MACH__
asm volatile ("ps_mul v0,v0,v0");
#else
asm volatile ("ps_mul 0,0,0");
#endif
return 0;
}
} "-mpaired"
}
}]
}
# Return 1 if the target supports executing power8 vector instructions, 0
# otherwise. Cache the result.
proc check_p8vector_hw_available { } {
return [check_cached_effective_target p8vector_hw_available {
# Some simulators are known to not support VSX/power8 instructions.
# For now, disable on Darwin
if { [istarget powerpc-*-eabi]
|| [istarget powerpc*-*-eabispe]
|| [istarget *-*-darwin*]} {
expr 0
} else {
set options "-mpower8-vector"
check_runtime_nocache p8vector_hw_available {
int main()
{
#ifdef __MACH__
asm volatile ("xxlorc vs0,vs0,vs0");
#else
asm volatile ("xxlorc 0,0,0");
#endif
return 0;
}
} $options
}
}]
}
# Return 1 if the target supports executing power9 vector instructions, 0
# otherwise. Cache the result.
proc check_p9vector_hw_available { } {
return [check_cached_effective_target p9vector_hw_available {
# Some simulators are known to not support VSX/power8/power9
# instructions. For now, disable on Darwin.
if { [istarget powerpc-*-eabi]
|| [istarget powerpc*-*-eabispe]
|| [istarget *-*-darwin*]} {
expr 0
} else {
set options "-mpower9-vector"
check_runtime_nocache p9vector_hw_available {
int main()
{
long e = -1;
vector double v = (vector double) { 0.0, 0.0 };
asm ("xsxexpdp %0,%1" : "+r" (e) : "wa" (v));
return e;
}
} $options
}
}]
}
# Return 1 if the PowerPC target generates PC-relative instructions
# automatically for targets that support PC-relative instructions.
proc check_effective_target_powerpc_pcrel { } {
return [check_no_messages_and_pattern powerpc_pcrel \
{\mpla\M} assembly {
static unsigned short s;
unsigned short *p_foo (void) { return &s; }
} {-O2 -mcpu=power10}]
}
# Return 1 if the PowerPC target generates prefixed instructions automatically
# for targets that support prefixed instructions.
proc check_effective_target_powerpc_prefixed_addr { } {
return [check_no_messages_and_pattern powerpc_prefixed_addr \
{\mplwz\M} assembly {
unsigned int foo (unsigned int *p) { return p[0x12345]; }
} {-O2 -mcpu=power10}]
}
# Return 1 if the target supports executing power9 modulo instructions, 0
# otherwise. Cache the result.
proc check_p9modulo_hw_available { } {
return [check_cached_effective_target p9modulo_hw_available {
# Some simulators are known to not support VSX/power8/power9
# instructions. For now, disable on Darwin.
if { [istarget powerpc-*-eabi]
|| [istarget powerpc*-*-eabispe]
|| [istarget *-*-darwin*]} {
expr 0
} else {
set options "-mmodulo"
check_runtime_nocache p9modulo_hw_available {
int main()
{
int i = 5, j = 3, r = -1;
asm ("modsw %0,%1,%2" : "+r" (r) : "r" (i), "r" (j));
return (r == 2);
}
} $options
}
}]
}
# Return 1 if the target supports executing power10 instructions, 0 otherwise.
# Cache the result. It is assumed that if a simulator does not support the
# power10 instructions, that it will generate an error and this test will fail.
proc check_power10_hw_available { } {
return [check_cached_effective_target power10_hw_available {
check_runtime_nocache power10_hw_available {
int main()
{
/* Set e first and use +r to check if pli actually works. */
long e = -1;
asm ("pli %0,%1" : "+r" (e) : "n" (0x12345));
if (e == 0x12345)
return 0;
return 1;
}
} "-mcpu=power10"
}]
}
# Return 1 if the target supports executing MMA instructions, 0 otherwise.
# Cache the result. It is assumed that if a simulator does not support the
# MMA instructions, that it will generate an error and this test will fail.
proc check_ppc_mma_hw_available { } {
return [check_cached_effective_target ppc_mma_hw_available {
check_runtime_nocache ppc_mma_hw_available {
#include <altivec.h>
typedef double v4sf_t __attribute__ ((vector_size (16)));
int main()
{
__vector_quad acc0;
v4sf_t result[4];
result[0][0] = 1.0;
__builtin_mma_xxsetaccz (&acc0);
__builtin_mma_disassemble_acc (result, &acc0);
if (result[0][0] != 0.0)
return 1;
return 0;
}
} "-mcpu=power10"
}]
}
# Return 1 if the target supports executing __float128 on PowerPC via software
# emulation, 0 otherwise. Cache the result.
proc check_ppc_float128_sw_available { } {
return [check_cached_effective_target ppc_float128_sw_available {
# Some simulators are known to not support VSX/power8/power9
# instructions. For now, disable on Darwin.
if { [istarget powerpc-*-eabi]
|| [istarget powerpc*-*-eabispe]
|| [istarget *-*-darwin*]} {
expr 0
} else {
set options "-mfloat128 -mvsx"
check_runtime_nocache ppc_float128_sw_available {
volatile __float128 x = 1.0q;
volatile __float128 y = 2.0q;
int main()
{
__float128 z = x + y;
return (z != 3.0q);
}
} $options
}
}]
}
# Return 1 if the target supports executing __float128 on PowerPC via power9
# hardware instructions, 0 otherwise. Cache the result.
proc check_ppc_float128_hw_available { } {
return [check_cached_effective_target ppc_float128_hw_available {
# Some simulators are known to not support VSX/power8/power9
# instructions. For now, disable on Darwin.
if { [istarget powerpc-*-eabi]
|| [istarget powerpc*-*-eabispe]
|| [istarget *-*-darwin*]} {
expr 0
} else {
set options "-mfloat128 -mvsx -mfloat128-hardware -mpower9-vector"
check_runtime_nocache ppc_float128_hw_available {
volatile __float128 x = 1.0q;
volatile __float128 y = 2.0q;
int main()
{
__float128 z = x + y;
__float128 w = -1.0q;
__asm__ ("xsaddqp %0,%1,%2" : "+v" (w) : "v" (x), "v" (y));
return ((z != 3.0q) || (z != w));
}
} $options
}
}]
}
# See if the __ieee128 keyword is understood.
proc check_effective_target_ppc_ieee128_ok { } {
return [check_cached_effective_target ppc_ieee128_ok {
# disable on AIX.
if { [istarget *-*-aix*] } {
expr 0
} else {
set options "-mfloat128"
check_runtime_nocache ppc_ieee128_ok {
int main()
{
__ieee128 a;
return 0;
}
} $options
}
}]
}
# Check if GCC and GLIBC supports explicitly specifying that the long double
# format uses the IBM 128-bit extended double format. Under little endian
# PowerPC Linux, you need GLIBC 2.32 or later to be able to use a different
# long double format for running a program than the system default.
proc check_effective_target_long_double_ibm128 { } {
return [check_runtime_nocache long_double_ibm128 {
#include <string.h>
#include <stdio.h>
/* use volatile to prevent optimization. */
volatile __ibm128 a = (__ibm128) 3.0;
volatile long double one = 1.0L;
volatile long double two = 2.0L;
volatile long double b;
char buffer[20];
int main()
{
__ibm128 a2;
long double b2;
if (sizeof (long double) != 16)
return 1;
b = one + two;
/* eliminate removing volatile cast warning. */
a2 = a;
b2 = b;
if (memcmp (&a2, &b2, 16) != 0)
return 1;
sprintf (buffer, "%lg", b);
return strcmp (buffer, "3") != 0;
}
} [add_options_for_long_double_ibm128 ""]]
}
# Return the appropriate options to specify that long double uses the IBM
# 128-bit format on PowerPC.
proc add_options_for_long_double_ibm128 { flags } {
if { [istarget powerpc*-*-*] } {
return "$flags -mlong-double-128 -Wno-psabi -mabi=ibmlongdouble"
}
return "$flags"
}
# Check if GCC and GLIBC supports explicitly specifying that the long double
# format uses the IEEE 128-bit format. Under little endian PowerPC Linux, you
# need GLIBC 2.32 or later to be able to use a different long double format for
# running a program than the system default.
proc check_effective_target_long_double_ieee128 { } {
return [check_runtime_nocache long_double_ieee128 {
#include <string.h>
#include <stdio.h>
/* use volatile to prevent optimization. */
volatile _Float128 a = 3.0f128;
volatile long double one = 1.0L;
volatile long double two = 2.0L;
volatile long double b;
char buffer[20];
int main()
{
_Float128 a2;
long double b2;
if (sizeof (long double) != 16)
return 1;
b = one + two;
/* eliminate removing volatile cast warning. */
a2 = a;
b2 = b;
if (memcmp (&a2, &b2, 16) != 0)
return 1;
sprintf (buffer, "%lg", b);
return strcmp (buffer, "3") != 0;
}
} [add_options_for_long_double_ieee128 ""]]
}
# Return the appropriate options to specify that long double uses the IBM
# 128-bit format on PowerPC.
proc add_options_for_long_double_ieee128 { flags } {
if { [istarget powerpc*-*-*] } {
return "$flags -mlong-double-128 -Wno-psabi -mabi=ieeelongdouble"
}
return "$flags"
}
# Check if GCC and GLIBC supports explicitly specifying that the long double
# format uses the IEEE 64-bit. Under little endian PowerPC Linux, you need
# GLIBC 2.32 or later to be able to use a different long double format for
# running a program than the system default.
proc check_effective_target_long_double_64bit { } {
return [check_runtime_nocache long_double_64bit {
#include <string.h>
#include <stdio.h>
/* use volatile to prevent optimization. */
volatile double a = 3.0;
volatile long double one = 1.0L;
volatile long double two = 2.0L;
volatile long double b;
char buffer[20];
int main()
{
double a2;
long double b2;
if (sizeof (long double) != 8)
return 1;
b = one + two;
/* eliminate removing volatile cast warning. */
a2 = a;
b2 = b;
if (memcmp (&a2, &b2, 16) != 0)
return 1;
sprintf (buffer, "%lg", b);
return strcmp (buffer, "3") != 0;
}
} [add_options_for_ppc_long_double_override_64bit ""]]
}
# Return the appropriate options to specify that long double uses the IEEE
# 64-bit format on PowerPC.
proc add_options_for_long_double_64bit { flags } {
if { [istarget powerpc*-*-*] } {
return "$flags -mlong-double-64"
}
return "$flags"
}
# Return 1 if the target supports executing VSX instructions, 0
# otherwise. Cache the result.
proc check_vsx_hw_available { } {
return [check_cached_effective_target vsx_hw_available {
# Some simulators are known to not support VSX instructions.
# For now, disable on Darwin
if { [istarget powerpc-*-eabi]
|| [istarget powerpc*-*-eabispe]
|| [istarget *-*-darwin*]} {
expr 0
} else {
set options "-mvsx"
check_runtime_nocache vsx_hw_available {
int main()
{
#ifdef __MACH__
asm volatile ("xxlor vs0,vs0,vs0");
#else
asm volatile ("xxlor 0,0,0");
#endif
return 0;
}
} $options
}
}]
}
# Return 1 if the target supports executing AltiVec instructions, 0
# otherwise. Cache the result.
proc check_vmx_hw_available { } {
return [check_cached_effective_target vmx_hw_available {
# Some simulators are known to not support VMX instructions.
if { [istarget powerpc-*-eabi] || [istarget powerpc*-*-eabispe] } {
expr 0
} else {
# Most targets don't require special flags for this test case, but
# Darwin does. Just to be sure, make sure VSX is not enabled for
# the altivec tests.
if { [istarget *-*-darwin*]
|| [istarget *-*-aix*] } {
set options "-maltivec -mno-vsx"
} else {
set options "-mno-vsx"
}
check_runtime_nocache vmx_hw_available {
int main()
{
#ifdef __MACH__
asm volatile ("vor v0,v0,v0");
#else
asm volatile ("vor 0,0,0");
#endif
return 0;
}
} $options
}
}]
}
proc check_ppc_recip_hw_available { } {
return [check_cached_effective_target ppc_recip_hw_available {
# Some simulators may not support FRE/FRES/FRSQRTE/FRSQRTES
# For now, disable on Darwin
if { [istarget powerpc-*-eabi] || [istarget powerpc*-*-eabispe] || [istarget *-*-darwin*]} {
expr 0
} else {
set options "-mpowerpc-gfxopt -mpowerpc-gpopt -mpopcntb"
check_runtime_nocache ppc_recip_hw_available {
volatile double d_recip, d_rsqrt, d_four = 4.0;
volatile float f_recip, f_rsqrt, f_four = 4.0f;
int main()
{
asm volatile ("fres %0,%1" : "=f" (f_recip) : "f" (f_four));
asm volatile ("fre %0,%1" : "=d" (d_recip) : "d" (d_four));
asm volatile ("frsqrtes %0,%1" : "=f" (f_rsqrt) : "f" (f_four));
asm volatile ("frsqrte %0,%1" : "=f" (d_rsqrt) : "d" (d_four));
return 0;
}
} $options
}
}]
}
# Return 1 if the target supports executing AltiVec and Cell PPU
# instructions, 0 otherwise. Cache the result.
proc check_effective_target_cell_hw { } {
return [check_cached_effective_target cell_hw_available {
# Some simulators are known to not support VMX and PPU instructions.
if { [istarget powerpc-*-eabi*] } {
expr 0
} else {
# Most targets don't require special flags for this test
# case, but Darwin and AIX do.
if { [istarget *-*-darwin*]
|| [istarget *-*-aix*] } {
set options "-maltivec -mcpu=cell"
} else {
set options "-mcpu=cell"
}
check_runtime_nocache cell_hw_available {
int main()
{
#ifdef __MACH__
asm volatile ("vor v0,v0,v0");
asm volatile ("lvlx v0,r0,r0");
#else
asm volatile ("vor 0,0,0");
asm volatile ("lvlx 0,0,0");
#endif
return 0;
}
} $options
}
}]
}
# Return 1 if the target supports executing 64-bit instructions, 0
# otherwise. Cache the result.
proc check_effective_target_powerpc64 { } {
global powerpc64_available_saved
global tool
if [info exists powerpc64_available_saved] {
verbose "check_effective_target_powerpc64 returning saved $powerpc64_available_saved" 2
} else {
set powerpc64_available_saved 0
# Some simulators are known to not support powerpc64 instructions.
if { [istarget powerpc-*-eabi*] || [istarget powerpc-ibm-aix*] } {
verbose "check_effective_target_powerpc64 returning 0" 2
return $powerpc64_available_saved
}
# Set up, compile, and execute a test program containing a 64-bit
# instruction. Include the current process ID in the file
# names to prevent conflicts with invocations for multiple
# testsuites.
set src ppc[pid].c
set exe ppc[pid].x
set f [open $src "w"]
puts $f "int main() {"
puts $f "#ifdef __MACH__"
puts $f " asm volatile (\"extsw r0,r0\");"
puts $f "#else"
puts $f " asm volatile (\"extsw 0,0\");"
puts $f "#endif"
puts $f " return 0; }"
close $f
set opts "additional_flags=-mcpu=G5"
verbose "check_effective_target_powerpc64 compiling testfile $src" 2
set lines [${tool}_target_compile $src $exe executable "$opts"]
file delete $src
if [string match "" $lines] then {
# No error message, compilation succeeded.
set result [${tool}_load "./$exe" "" ""]
set status [lindex $result 0]
remote_file build delete $exe
verbose "check_effective_target_powerpc64 testfile status is <$status>" 2
if { $status == "pass" } then {
set powerpc64_available_saved 1
}
} else {
verbose "check_effective_target_powerpc64 testfile compilation failed" 2
}
}
return $powerpc64_available_saved
}
# GCC 3.4.0 for powerpc64-*-linux* included an ABI fix for passing
# complex float arguments. This affects gfortran tests that call cabsf
# in libm built by an earlier compiler. Return 0 if libm uses the same
# argument passing as the compiler under test, 1 otherwise.
proc check_effective_target_broken_cplxf_arg { } {
# Skip the work for targets known not to be affected.
if { ![istarget powerpc*-*-linux*] || ![is-effective-target lp64] } {
return 0
}
return [check_cached_effective_target broken_cplxf_arg {
check_runtime_nocache broken_cplxf_arg {
#include <complex.h>
extern void abort (void);
float fabsf (float);
float cabsf (_Complex float);
int main ()
{
_Complex float cf;
float f;
cf = 3 + 4.0fi;
f = cabsf (cf);
if (fabsf (f - 5.0) > 0.0001)
/* Yes, it's broken. */
return 0;
/* All fine, not broken. */
return 1;
}
} "-lm"
}]
}
# Return 1 is this is a TI C6X target supporting C67X instructions
proc check_effective_target_ti_c67x { } {
return [check_no_compiler_messages ti_c67x assembly {
#if !defined(_TMS320C6700)
#error !_TMS320C6700
#endif
}]
}
# Return 1 is this is a TI C6X target supporting C64X+ instructions
proc check_effective_target_ti_c64xp { } {
return [check_no_compiler_messages ti_c64xp assembly {
#if !defined(_TMS320C6400_PLUS)
#error !_TMS320C6400_PLUS
#endif
}]
}
# Check if a -march=... option is given, as part of (earlier) options.
proc check_effective_target_march_option { } {
return [check-flags [list "" { *-*-* } { "-march=*" } { "" } ]]
}
proc check_alpha_max_hw_available { } {
return [check_runtime alpha_max_hw_available {
int main() { return __builtin_alpha_amask(1<<8) != 0; }
}]
}
# Returns true iff the FUNCTION is available on the target system.
# (This is essentially a Tcl implementation of Autoconf's
# AC_CHECK_FUNC.)
proc check_function_available { function } {
return [check_no_compiler_messages ${function}_available \
executable [subst {
#ifdef __cplusplus
extern "C"
#endif
char $function ();
int main () { $function (); }
}] "-fno-builtin" ]
}
# Returns true iff "fork" is available on the target system.
proc check_fork_available {} {
if { [istarget *-*-vxworks*] } {
# VxWorks doesn't have fork but our way to test can't
# tell as we're doing partial links for kernel modules.
return 0
}
return [check_function_available "fork"]
}
# Returns true iff "mkfifo" is available on the target system.
proc check_mkfifo_available {} {
if { [istarget *-*-cygwin*] } {
# Cygwin has mkfifo, but support is incomplete.
return 0
}
return [check_function_available "mkfifo"]
}
# Returns true iff "__cxa_atexit" is used on the target system.
proc check_cxa_atexit_available { } {
return [check_cached_effective_target cxa_atexit_available {
if { [istarget hppa*-*-hpux10*] } {
# HP-UX 10 doesn't have __cxa_atexit but subsequent test passes.
expr 0
} elseif { [istarget *-*-vxworks] } {
# vxworks doesn't have __cxa_atexit but subsequent test passes.
expr 0
} else {
check_runtime_nocache cxa_atexit_available {
// C++
#include <stdlib.h>
static unsigned int count;
struct X
{
X() { count = 1; }
~X()
{
if (count != 3)
exit(1);
count = 4;
}
};
void f()
{
static X x;
}
struct Y
{
Y() { f(); count = 2; }
~Y()
{
if (count != 2)
exit(1);
count = 3;
}
};
Y y;
int main() { return 0; }
}
}
}]
}
proc check_effective_target_objc2 { } {
return [check_no_compiler_messages objc2 object {
#ifdef __OBJC2__
int dummy[1];
#else
#error !__OBJC2__
#endif
}]
}
proc check_effective_target_next_runtime { } {
return [check_no_compiler_messages objc2 object {
#ifdef __NEXT_RUNTIME__
int dummy[1];
#else
#error !__NEXT_RUNTIME__
#endif
}]
}
# Return 1 if we're generating code for big-endian memory order.
proc check_effective_target_be { } {
return [check_no_compiler_messages be object {
int dummy[__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ? 1 : -1];
}]
}
# Return 1 if we're generating code for little-endian memory order.
proc check_effective_target_le { } {
return [check_no_compiler_messages le object {
int dummy[__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ ? 1 : -1];
}]
}
# Return 1 if we're generating 32-bit code using default options, 0
# otherwise.
proc check_effective_target_ilp32 { } {
return [check_no_compiler_messages ilp32 object {
int dummy[sizeof (int) == 4
&& sizeof (void *) == 4
&& sizeof (long) == 4 ? 1 : -1];
}]
}
# Return 1 if we're generating ia32 code using default options, 0
# otherwise.
proc check_effective_target_ia32 { } {
return [check_no_compiler_messages ia32 object {
int dummy[sizeof (int) == 4
&& sizeof (void *) == 4
&& sizeof (long) == 4 ? 1 : -1] = { __i386__ };
}]
}
# Return 1 if we're generating x32 code using default options, 0
# otherwise.
proc check_effective_target_x32 { } {
return [check_no_compiler_messages x32 object {
int dummy[sizeof (int) == 4
&& sizeof (void *) == 4
&& sizeof (long) == 4 ? 1 : -1] = { __x86_64__ };
}]
}
# Return 1 if we're generating 32-bit integers using default
# options, 0 otherwise.
proc check_effective_target_int32 { } {
return [check_no_compiler_messages int32 object {
int dummy[sizeof (int) == 4 ? 1 : -1];
}]
}
# Return 1 if we're generating 32-bit or larger integers using default
# options, 0 otherwise.
proc check_effective_target_int32plus { } {
return [check_no_compiler_messages int32plus object {
int dummy[sizeof (int) >= 4 ? 1 : -1];
}]
}
# Return 1 if we're generating 64-bit long long using default options,
# 0 otherwise.
proc check_effective_target_longlong64 { } {
return [check_no_compiler_messages longlong64 object {
int dummy[sizeof (long long) == 8 ? 1 : -1];
}]
}
# Return 1 if we're generating 32-bit or larger pointers using default
# options, 0 otherwise.
proc check_effective_target_ptr32plus { } {
# The msp430 has 16-bit or 20-bit pointers. The 20-bit pointer is stored
# in a 32-bit slot when in memory, so sizeof(void *) returns 4, but it
# cannot really hold a 32-bit address, so we always return false here.
if { [istarget msp430-*-*] } {
return 0
}
return [check_no_compiler_messages ptr32plus object {
int dummy[sizeof (void *) >= 4 ? 1 : -1];
}]
}
# Return 1 if we support 16-bit or larger array and structure sizes
# using default options, 0 otherwise.
# This implies at least a 20-bit address space, as no targets have an address
# space between 16 and 20 bits.
proc check_effective_target_size20plus { } {
return [check_no_compiler_messages size20plus object {
char dummy[65537L];
}]
}
# Return 1 if target supports function pointers, 0 otherwise.
proc check_effective_target_function_pointers { } {
if { [istarget pru-*-*] } {
return [check_no_compiler_messages func_ptr_avail assembly {
#ifdef __PRU_EABI_GNU__
#error unsupported
#endif
}]
}
return 1
}
# Return 1 if target supports arbitrarily large return values, 0 otherwise.
proc check_effective_target_large_return_values { } {
if { [istarget pru-*-*] } {
return [check_no_compiler_messages large_return_values assembly {
#ifdef __PRU_EABI_GNU__
#error unsupported
#endif
}]
}
return 1
}
# Return 1 if we support 20-bit or larger array and structure sizes
# using default options, 0 otherwise.
# This implies at least a 24-bit address space, as no targets have an address
# space between 20 and 24 bits.
proc check_effective_target_size24plus { } {
return [check_no_compiler_messages size24plus object {
char dummy[524289L];
}]
}
# Return 1 if we support 24-bit or larger array and structure sizes
# using default options, 0 otherwise.
# This implies at least a 32-bit address space, as no targets have an address
# space between 24 and 32 bits.
proc check_effective_target_size32plus { } {
return [check_no_compiler_messages size32plus object {
char dummy[16777217L];
}]
}
# Returns 1 if we're generating 16-bit or smaller integers with the
# default options, 0 otherwise.
proc check_effective_target_int16 { } {
return [check_no_compiler_messages int16 object {
int dummy[sizeof (int) < 4 ? 1 : -1];
}]
}
# Return 1 if we're generating 64-bit code using default options, 0
# otherwise.
proc check_effective_target_lp64 { } {
return [check_no_compiler_messages lp64 object {
int dummy[sizeof (int) == 4
&& sizeof (void *) == 8
&& sizeof (long) == 8 ? 1 : -1];
}]
}
# Return 1 if we're generating 64-bit code using default llp64 options,
# 0 otherwise.
proc check_effective_target_llp64 { } {
return [check_no_compiler_messages llp64 object {
int dummy[sizeof (int) == 4
&& sizeof (void *) == 8
&& sizeof (long long) == 8
&& sizeof (long) == 4 ? 1 : -1];
}]
}
# Return 1 if long and int have different sizes,
# 0 otherwise.
proc check_effective_target_long_neq_int { } {
return [check_no_compiler_messages long_ne_int object {
int dummy[sizeof (int) != sizeof (long) ? 1 : -1];
}]
}
# Return 1 if int size is equal to float size,
# 0 otherwise.
proc check_effective_target_int_eq_float { } {
return [check_no_compiler_messages int_eq_float object {
int dummy[sizeof (int) >= sizeof (float) ? 1 : -1];
}]
}
# Return 1 if short size is equal to int size,
# 0 otherwise.
proc check_effective_target_short_eq_int { } {
return [check_no_compiler_messages short_eq_int object {
int dummy[sizeof (short) == sizeof (int) ? 1 : -1];
}]
}
# Return 1 if pointer size is equal to short size,
# 0 otherwise.
proc check_effective_target_ptr_eq_short { } {
return [check_no_compiler_messages ptr_eq_short object {
int dummy[sizeof (void *) == sizeof (short) ? 1 : -1];
}]
}
# Return 1 if pointer size is equal to long size,
# 0 otherwise.
proc check_effective_target_ptr_eq_long { } {
# sizeof (void *) == 4 for msp430-elf -mlarge which is equal to
# sizeof (long). Avoid false positive.
if { [istarget msp430-*-*] } {
return 0
}
return [check_no_compiler_messages ptr_eq_long object {
int dummy[sizeof (void *) == sizeof (long) ? 1 : -1];
}]
}
# Return 1 if the target supports long double larger than double,
# 0 otherwise.
proc check_effective_target_large_long_double { } {
return [check_no_compiler_messages large_long_double object {
int dummy[sizeof(long double) > sizeof(double) ? 1 : -1];
}]
}
# Return 1 if the target supports double larger than float,
# 0 otherwise.
proc check_effective_target_large_double { } {
return [check_no_compiler_messages large_double object {
int dummy[sizeof(double) > sizeof(float) ? 1 : -1];
}]
}
# Return 1 if the target supports long double of 128 bits,
# 0 otherwise.
proc check_effective_target_longdouble128 { } {
return [check_no_compiler_messages longdouble128 object {
int dummy[sizeof(long double) == 16 ? 1 : -1];
}]
}
# Return 1 if the target supports long double of 64 bits,
# 0 otherwise.
proc check_effective_target_longdouble64 { } {
return [check_no_compiler_messages longdouble64 object {
int dummy[sizeof(long double) == 8 ? 1 : -1];
}]
}
# Return 1 if the target supports double of 64 bits,
# 0 otherwise.
proc check_effective_target_double64 { } {
return [check_no_compiler_messages double64 object {
int dummy[sizeof(double) == 8 ? 1 : -1];
}]
}
# Return 1 if the target supports double of at least 64 bits,
# 0 otherwise.
proc check_effective_target_double64plus { } {
return [check_no_compiler_messages double64plus object {
int dummy[sizeof(double) >= 8 ? 1 : -1];
}]
}
# Return 1 if the target supports 'w' suffix on floating constant
# 0 otherwise.
proc check_effective_target_has_w_floating_suffix { } {
set opts ""
if [check_effective_target_c++] {
append opts "-std=gnu++03"
}
return [check_no_compiler_messages w_fp_suffix object {
float dummy = 1.0w;
} "$opts"]
}
# Return 1 if the target supports 'q' suffix on floating constant
# 0 otherwise.
proc check_effective_target_has_q_floating_suffix { } {
set opts ""
if [check_effective_target_c++] {
append opts "-std=gnu++03"
}
return [check_no_compiler_messages q_fp_suffix object {
float dummy = 1.0q;
} "$opts"]
}
# Return 1 if the target supports the _FloatN / _FloatNx type
# indicated in the function name, 0 otherwise.
proc check_effective_target_float16 {} {
return [check_no_compiler_messages_nocache float16 object {
_Float16 foo (_Float16 x) { return x; }
} [add_options_for_float16 ""]]
}
proc check_effective_target_float32 {} {
return [check_no_compiler_messages_nocache float32 object {
_Float32 x;
} [add_options_for_float32 ""]]
}
proc check_effective_target_float64 {} {
return [check_no_compiler_messages_nocache float64 object {
_Float64 x;
} [add_options_for_float64 ""]]
}
proc check_effective_target_float128 {} {
return [check_no_compiler_messages_nocache float128 object {
_Float128 x;
} [add_options_for_float128 ""]]
}
proc check_effective_target_float32x {} {
return [check_no_compiler_messages_nocache float32x object {
_Float32x x;
} [add_options_for_float32x ""]]
}
proc check_effective_target_float64x {} {
return [check_no_compiler_messages_nocache float64x object {
_Float64x x;
} [add_options_for_float64x ""]]
}
proc check_effective_target_float128x {} {
return [check_no_compiler_messages_nocache float128x object {
_Float128x x;
} [add_options_for_float128x ""]]
}
# Likewise, but runtime support for any special options used as well
# as compile-time support is required.
proc check_effective_target_float16_runtime {} {
return [check_effective_target_float16]
}
proc check_effective_target_float32_runtime {} {
return [check_effective_target_float32]
}
proc check_effective_target_float64_runtime {} {
return [check_effective_target_float64]
}
proc check_effective_target_float128_runtime {} {
if { ![check_effective_target_float128] } {
return 0
}
if { [istarget powerpc*-*-*] } {
return [check_effective_target_base_quadfloat_support]
}
return 1
}
proc check_effective_target_float32x_runtime {} {
return [check_effective_target_float32x]
}
proc check_effective_target_float64x_runtime {} {
if { ![check_effective_target_float64x] } {
return 0
}
if { [istarget powerpc*-*-*] } {
return [check_effective_target_base_quadfloat_support]
}
return 1
}
proc check_effective_target_float128x_runtime {} {
return [check_effective_target_float128x]
}
# Return 1 if the target hardware supports any options added for
# _FloatN and _FloatNx types, 0 otherwise.
proc check_effective_target_floatn_nx_runtime {} {
if { [istarget powerpc*-*-aix*] } {
return 0
}
if { [istarget powerpc*-*-*] } {
return [check_effective_target_base_quadfloat_support]
}
return 1
}
# Add options needed to use the _FloatN / _FloatNx type indicated in