return $alias_available_saved
}
+###############################
+# proc check_ifunc_available { }
+###############################
+
+# Determine if the target toolchain supports the ifunc attribute.
+
+# Returns 1 if the target supports ifunc. Returns 0 if the target
+# does not support ifunc.
+
+proc check_ifunc_available { } {
+ global ifunc_available_saved
+ global tool
+
+ if [info exists ifunc_available_saved] {
+ verbose "check_ifunc_available returning saved $ifunc_available_saved" 2
+ } else {
+ set src ifunc[pid].c
+ set obj ifunc[pid].o
+ verbose "check_ifunc_available compiling testfile $src" 2
+ set f [open $src "w"]
+ puts $f "#endif"
+ puts $f "#ifdef __cplusplus\nextern \"C\"\n#endif"
+ puts $f "void g() {}"
+ puts $f "void f() __attribute__((ifunc(\"g\")));"
+ close $f
+ set lines [${tool}_target_compile $src $obj object ""]
+ file delete $src
+ remote_file build delete $obj
+
+ if [string match "" $lines] then {
+ set ifunc_available_saved 1
+ } else {
+ set ifunc_available_saved 0
+ }
+
+ verbose "check_ifunc_available returning $ifunc_available_saved" 2
+ }
+
+ return $ifunc_available_saved
+}
+
# Returns true if --gc-sections is supported on the target.
proc check_gc_sections_available { } {
}]
}
+# Add to FLAGS all the target-specific flags needed to use thread-local storage.
+
+proc add_options_for_tls { flags } {
+ # On Solaris 8 and 9, __tls_get_addr/___tls_get_addr only lives in
+ # libthread, so always pass -pthread for native TLS.
+ # Need to duplicate native TLS check from
+ # check_effective_target_tls_native to avoid recursion.
+ if { [istarget *-*-solaris2.\[89\]*] &&
+ [check_no_messages_and_pattern tls_native "!emutls" assembly {
+ __thread int i;
+ int f (void) { return i; }
+ void g (int j) { i = j; }
+ }] } {
+ return "$flags -pthread"
+ }
+ return $flags
+}
+
# Return 1 if thread local storage (TLS) is supported, 0 otherwise.
proc check_effective_target_tls {} {
}]
}
+# 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.
+ global target_triplet
+ if { [regexp ".*-.*-vxworks.*" $target_triplet] } {
+ 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 1 if -ffunction-sections is supported, 0 otherwise.
+
+proc check_effective_target_function_sections {} {
+ # Darwin has its own scheme and silently accepts -ffunction-sections.
+ global target_triplet
+ if { [regexp ".*-.*-darwin.*" $target_triplet] } {
+ return 0
+ }
+
+ return [check_no_compiler_messages functionsections assembly {
+ void foo (void) { }
+ } "-ffunction-sections"]
+}
+
# Return 1 if compilation with -fgraphite is error-free for trivial
# code, 0 otherwise.
} "-static"]
}
+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 supports executing 750CL paired-single instructions, 0
# otherwise. Cache the result.
}]
}
+# 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 x86_64-*-*] || [istarget i?86-*-*]) } {
+ expr 0
+ } elseif { [istarget i?86-*-solaris2*] } {
+ # The Solaris 2 kernel doesn't save and restore SSE registers
+ # before Solaris 9 4/04. Before that, executables die with SIGILL.
+ check_runtime_nocache sse_os_support_available {
+ int main ()
+ {
+ __asm__ volatile ("movss %xmm2,%xmm1");
+ return 0;
+ }
+ } "-msse"
+ } else {
+ expr 1
+ }
+ }]
+}
+
+# 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 x86_64-*-*] || [istarget i?86-*-*]) } {
+ 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 !(edx & bit_SSE);
+ return 1;
+ }
+ } ""
+ }
+ }]
+}
+
# Return 1 if the target supports executing SSE2 instructions, 0
# otherwise. Cache the result.
#include "cpuid.h"
int main ()
{
- unsigned int eax, ebx, ecx, edx = 0;
+ unsigned int eax, ebx, ecx, edx;
if (__get_cpuid (1, &eax, &ebx, &ecx, &edx))
return !(edx & bit_SSE2);
return 1;
}]
}
+# 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 x86_64-*-*] || [istarget i?86-*-*]) } {
+ 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 ((ecx & (bit_AVX | bit_OSXSAVE))
+ != (bit_AVX | bit_OSXSAVE));
+ return 1;
+ }
+ } ""
+ }
+ }]
+}
+
+# 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 AVX executables, 0 otherwise.
+
+proc check_effective_target_avx_runtime { } {
+ if { [check_effective_target_avx]
+ && [check_avx_hw_available] } {
+ return 1
+ }
+ return 0
+}
+
# Return 1 if the target supports executing VSX instructions, 0
# otherwise. Cache the result.
}]
}
+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.
|| [istarget sparc*-*-*]
|| [istarget alpha*-*-*]
|| [istarget ia64-*-*]
- || [check_effective_target_arm32] } {
+ || [check_effective_target_arm32]
+ || ([istarget mips*-*-*]
+ && [check_effective_target_mips_loongson]) } {
set et_vect_int_saved 1
}
}
}]
}
+# Return 1 if this is an ARM target that only supports aligned vector accesses
+proc check_effective_target_arm_vect_no_misalign { } {
+ return [check_no_compiler_messages arm_vect_no_misalign assembly {
+ #if !defined(__arm__) \
+ || (defined(__ARMEL__) \
+ && (!defined(__thumb__) || defined(__thumb2__)))
+ #error FOO
+ #endif
+ }]
+}
+
+
# Return 1 if this is an ARM target supporting -mfpu=vfp
# -mfloat-abi=softfp. Some multilibs may be incompatible with these
# options.
|| [istarget ia64-*-*]
|| [istarget i?86-*-*]
|| [istarget x86_64-*-*]
- || [check_effective_target_arm32] } {
+ || [check_effective_target_arm32]
+ || ([istarget mips*-*-*]
+ && [check_effective_target_mips_loongson]) } {
set et_vect_shift_saved 1
}
}
} else {
set et_vect_double_saved 0
if { [istarget i?86-*-*]
- || [istarget x86_64-*-*]
- || [istarget spu-*-*] } {
+ || [istarget x86_64-*-*] } {
+ if { [check_no_compiler_messages vect_double assembly {
+ #ifdef __tune_atom__
+ # error No double vectorizer support.
+ #endif
+ }] } {
+ set et_vect_double_saved 1
+ } else {
+ set et_vect_double_saved 0
+ }
+ } elseif { [istarget spu-*-*] } {
set et_vect_double_saved 1
}
}
set et_vect_no_int_max_saved 0
if { [istarget sparc*-*-*]
|| [istarget spu-*-*]
- || [istarget alpha*-*-*] } {
+ || [istarget alpha*-*-*]
+ || ([istarget mips*-*-*]
+ && [check_effective_target_mips_loongson]) } {
set et_vect_no_int_max_saved 1
}
}
} else {
set et_vect_perm_saved 0
if { [istarget powerpc*-*-*]
- || [istarget spu-*-*] } {
+ || [istarget spu-*-*]
+ || [istarget i?86-*-*]
+ || [istarget x86_64-*-*] } {
set et_vect_perm_saved 1
}
}
return $et_vect_perm_saved
}
+# Return 1 if the target plus current options supports vector permutation
+# on byte-sized elements, 0 otherwise.
+#
+# This won't change for different subtargets so cache the result.
+
+proc check_effective_target_vect_perm_byte { } {
+ global et_vect_perm_byte
+
+ if [info exists et_vect_perm_byte_saved] {
+ verbose "check_effective_target_vect_perm_byte: using cached result" 2
+ } else {
+ set et_vect_perm_byte_saved 0
+ if { [istarget powerpc*-*-*]
+ || [istarget spu-*-*] } {
+ set et_vect_perm_byte_saved 1
+ }
+ }
+ verbose "check_effective_target_vect_perm_byte: returning $et_vect_perm_byte_saved" 2
+ return $et_vect_perm_byte_saved
+}
+
+# Return 1 if the target plus current options supports vector permutation
+# on short-sized elements, 0 otherwise.
+#
+# This won't change for different subtargets so cache the result.
+
+proc check_effective_target_vect_perm_short { } {
+ global et_vect_perm_short
+
+ if [info exists et_vect_perm_short_saved] {
+ verbose "check_effective_target_vect_perm_short: using cached result" 2
+ } else {
+ set et_vect_perm_short_saved 0
+ if { [istarget powerpc*-*-*]
+ || [istarget spu-*-*] } {
+ set et_vect_perm_short_saved 1
+ }
+ }
+ verbose "check_effective_target_vect_perm_short: returning $et_vect_perm_short_saved" 2
+ return $et_vect_perm_short_saved
+}
+
# Return 1 if the target plus current options supports a vector
# widening summation of *short* args into *int* result, 0 otherwise.
#
if { ([istarget powerpc*-*-*] && ![istarget powerpc-*-linux*paired*])
|| [istarget i?86-*-*]
|| [istarget x86_64-*-*]
- || [istarget spu-*-*] } {
+ || [istarget spu-*-*]
+ || ([istarget arm*-*-*] && [check_effective_target_arm_neon]) } {
set et_vect_pack_trunc_saved 1
}
}
if { ([istarget powerpc*-*-*] && ![istarget powerpc-*paired*])
|| [istarget i?86-*-*]
|| [istarget x86_64-*-*]
- || [istarget spu-*-*] } {
+ || [istarget spu-*-*]
+ || ([istarget arm*-*-*] && [check_effective_target_arm_neon]) } {
set et_vect_unpack_saved 1
}
}
if { [istarget mipsisa64*-*-*]
|| [istarget sparc*-*-*]
|| [istarget ia64-*-*]
- || [check_effective_target_arm32] } {
+ || [check_effective_target_arm_vect_no_misalign]
+ || ([istarget mips*-*-*]
+ && [check_effective_target_mips_loongson]) } {
set et_vect_no_align_saved 1
}
}
return $et_vector_alignment_reachable_for_64bit_saved
}
+# Return 1 if the target only requires element alignment for vector accesses
+
+proc check_effective_target_vect_element_align { } {
+ global et_vect_element_align
+
+ if [info exists et_vect_element_align] {
+ verbose "check_effective_target_vect_element_align: using cached result" 2
+ } else {
+ set et_vect_element_align 0
+ if { [istarget arm*-*-*]
+ || [check_effective_target_vect_hw_misalign] } {
+ set et_vect_element_align 1
+ }
+ }
+
+ verbose "check_effective_target_vect_element_align: returning $et_vect_element_align" 2
+ return $et_vect_element_align
+}
+
# Return 1 if the target supports vector conditional operations, 0 otherwise.
proc check_effective_target_vect_condition { } {
|| [istarget spu-*-*]
|| [istarget i?86-*-*]
|| [istarget x86_64-*-*]
- || [istarget powerpc*-*-*]
- || [check_effective_target_arm32] } {
+ || [istarget powerpc*-*-*]
+ || [check_effective_target_arm32]
+ || ([istarget mips*-*-*]
+ && [check_effective_target_mips_loongson]) } {
set et_vect_short_mult_saved 1
}
}
|| [istarget i?86-*-*]
|| [istarget x86_64-*-*]
|| [istarget alpha*-*-*]
+ || [istarget arm*-*-linux-gnueabi]
|| [istarget bfin*-*linux*]
+ || [istarget hppa*-*linux*]
|| [istarget s390*-*-*]
|| [istarget powerpc*-*-*]
|| [istarget sparc64-*-*]
|| [istarget i?86-*-*]
|| [istarget x86_64-*-*]
|| [istarget alpha*-*-*]
+ || [istarget arm*-*-linux-gnueabi]
+ || [istarget hppa*-*linux*]
|| [istarget s390*-*-*]
|| [istarget powerpc*-*-*]
|| [istarget sparc64-*-*]
} else {
switch $arg {
"vmx_hw" { set selected [check_vmx_hw_available] }
+ "vsx_hw" { set selected [check_vsx_hw_available] }
+ "ppc_recip_hw" { set selected [check_ppc_recip_hw_available] }
"named_sections" { set selected [check_named_sections_available] }
"gc_sections" { set selected [check_gc_sections_available] }
"cxa_atexit" { set selected [check_cxa_atexit_available] }
# These have different names for their check_* procs.
switch $arg {
"vmx_hw" { return 1 }
+ "vsx_hw" { return 1 }
+ "ppc_recip_hw" { return 1 }
"named_sections" { return 1 }
"gc_sections" { return 1 }
"cxa_atexit" { return 1 }
return $flags
}
+# Add to FLAGS the flags needed to enable 128-bit vectors.
+
+proc add_options_for_quad_vectors { flags } {
+ if [is-effective-target arm_neon_ok] {
+ return "$flags -mvectorize-with-neon-quad"
+ }
+
+ return $flags
+}
+
# Return 1 if the target provides a full C99 runtime.
proc check_effective_target_c99_runtime { } {
# Return 1 if the target supports automatic stack alignment.
proc check_effective_target_automatic_stack_alignment { } {
- if { [istarget i?86*-*-*]
- || [istarget x86_64-*-*] } then {
- return 1
- } else {
- return 0
+ # Ordinarily x86 supports automatic stack alignment ...
+ if { [istarget i?86*-*-*] || [istarget x86_64-*-*] } then {
+ if { [istarget *-*-mingw*] || [istarget *-*-cygwin*] } {
+ # ... except Win64 SEH doesn't. Succeed for Win32 though.
+ return [check_effective_target_ilp32];
+ }
+ return 1;
}
+ return 0;
}
# Return 1 if avx instructions can be compiled.
} "-O2 -mavx" ]
}
+# Return 1 if sse instructions can be compiled.
+proc check_effective_target_sse { } {
+ return [check_no_compiler_messages sse object {
+ int main ()
+ {
+ __builtin_ia32_stmxcsr ();
+ return 0;
+ }
+ } "-O2 -msse" ]
+}
+
# Return 1 if sse2 instructions can be compiled.
proc check_effective_target_sse2 { } {
return [check_no_compiler_messages sse2 object {
} "-O2 -msse2" ]
}
+# Return 1 if F16C instructions can be compiled.
+
+proc check_effective_target_f16c { } {
+ return [check_no_compiler_messages f16c object {
+ #include "immintrin.h"
+ float
+ foo (unsigned short val)
+ {
+ return _cvtsh_ss (val);
+ }
+ } "-O2 -mf16c" ]
+}
+
# Return 1 if C wchar_t type is compatible with char16_t.
proc check_effective_target_wchar_t_char16_t_compatible { } {
}]
}
+# Return 1 if GNU as is used.
+
+proc check_effective_target_gas { } {
+ global use_gas_saved
+ global tool
+
+ if {![info exists use_gas_saved]} {
+ # Check if the as used by gcc is GNU as.
+ set gcc_as [lindex [${tool}_target_compile "-print-prog-name=as" "" "none" ""] 0]
+ # Provide /dev/null as input, otherwise gas times out reading from
+ # stdin.
+ set status [remote_exec host "$gcc_as" "-v /dev/null"]
+ set as_output [lindex $status 1]
+ if { [ string first "GNU" $as_output ] >= 0 } {
+ set use_gas_saved 1
+ } else {
+ set use_gas_saved 0
+ }
+ }
+ return $use_gas_saved
+}
+
# Return 1 if the compiler has been configure with link-time optimization
# (LTO) support.
return [info exists ENABLE_LTO]
}
+# Return 1 if this target supports the -fsplit-stack option, 0
+# otherwise.
+
+proc check_effective_target_split_stack {} {
+ return [check_no_compiler_messages split_stack object {
+ void foo (void) { }
+ } "-fsplit-stack"]
+}
+
# Return 1 if the language for the compiler under test is C.
proc check_effective_target_c { } {
}
return 0
}
+
+# Return 1 if expensive testcases should be run.
+
+proc check_effective_target_run_expensive_tests { } {
+ if { [getenv GCC_TEST_RUN_EXPENSIVE] != "" } {
+ return 1
+ }
+ return 0
+}