| # Copyright (C) 1999-2022 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: |
| # "/* Assembly" for assembly code, |
| # "// 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 { |
| "*/* Assembly*" { set src ${basename}[pid].S } |
| "*! 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 loongarch*-*-*] } { |
| return [check_no_compiler_messages hard_float assembly { |
| #if (defined __loongarch_soft_float) |
| #error __loongarch_soft_float |
| #endif |
| }] |
| } |
| |
| 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 and VxWorks. |
| if { [istarget *-*-vxworks*] |
| || [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 *-*-vxworks*] |
| || [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 and VxWorks. |
| if { [istarget *-*-aix*] |
| || [istarget *-*-vxworks*]} { |
| 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] |
| } |
|