xref: /llvm-project/libc/cmake/modules/CheckCompilerFeatures.cmake (revision 81ce796095c8e2ededa5d9df1c963cf08a75a6f1)
1# ------------------------------------------------------------------------------
2# Compiler features definition and flags
3# ------------------------------------------------------------------------------
4
5set(
6  ALL_COMPILER_FEATURES
7    "builtin_ceil_floor_rint_trunc"
8    "builtin_fmax_fmin"
9    "builtin_fmaxf16_fminf16"
10    "builtin_round"
11    "builtin_roundeven"
12    "float16"
13    "float128"
14    "fixed_point"
15)
16
17# Making sure ALL_COMPILER_FEATURES is sorted.
18list(SORT ALL_COMPILER_FEATURES)
19
20# Compiler features that are unavailable on GPU targets with the in-tree Clang.
21set(
22  CPU_ONLY_COMPILER_FEATURES
23    "float128"
24)
25
26# Function to check whether the compiler supports the provided set of features.
27# Usage:
28# compiler_supports(
29#   <output variable>
30#   <list of cpu features>
31# )
32function(compiler_supports output_var features)
33  _intersection(var "${LIBC_CPU_FEATURES}" "${features}")
34  if("${var}" STREQUAL "${features}")
35    set(${output_var} TRUE PARENT_SCOPE)
36  else()
37    unset(${output_var} PARENT_SCOPE)
38  endif()
39endfunction()
40
41# ------------------------------------------------------------------------------
42# Internal helpers and utilities.
43# ------------------------------------------------------------------------------
44
45# Computes the intersection between two lists.
46function(_intersection output_var list1 list2)
47  foreach(element IN LISTS list1)
48    if("${list2}" MATCHES "(^|;)${element}(;|$)")
49      list(APPEND tmp "${element}")
50    endif()
51  endforeach()
52  set(${output_var} ${tmp} PARENT_SCOPE)
53endfunction()
54
55set(AVAILABLE_COMPILER_FEATURES "")
56
57# Try compile a C file to check if flag is supported.
58foreach(feature IN LISTS ALL_COMPILER_FEATURES)
59  set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
60  set(compile_options ${LIBC_COMPILE_OPTIONS_NATIVE})
61  set(link_options "")
62  if(${feature} STREQUAL "fixed_point")
63    list(APPEND compile_options "-ffixed-point")
64  elseif(${feature} MATCHES "^builtin_")
65    set(compile_options ${LIBC_COMPILE_OPTIONS_DEFAULT})
66    set(link_options -nostdlib)
67    # The compiler might handle calls to rounding builtins by generating calls
68    # to the respective libc math functions, in which case we cannot use these
69    # builtins in our implementations of these functions. We check that this is
70    # not the case by trying to link an executable, since linking would fail due
71    # to unresolved references with -nostdlib if calls to libc functions were
72    # generated.
73    set(CMAKE_TRY_COMPILE_TARGET_TYPE EXECUTABLE)
74  endif()
75
76  if(LIBC_TARGET_OS_IS_GPU)
77    # CUDA shouldn't be required to build the libc, only to test it, so we can't
78    # try to build CUDA binaries here. Since GPU builds are always compiled with
79    # the in-tree Clang, we just hardcode which compiler features are available
80    # when targeting GPUs.
81    if(feature IN_LIST CPU_ONLY_COMPILER_FEATURES)
82      set(has_feature FALSE)
83    else()
84      set(has_feature TRUE)
85    endif()
86  else()
87    try_compile(
88      has_feature
89      ${CMAKE_CURRENT_BINARY_DIR}/compiler_features
90      SOURCES ${LIBC_SOURCE_DIR}/cmake/modules/compiler_features/check_${feature}.cpp
91      COMPILE_DEFINITIONS -I${LIBC_SOURCE_DIR} ${compile_options}
92      LINK_OPTIONS ${link_options}
93    )
94  endif()
95
96  if(has_feature)
97    list(APPEND AVAILABLE_COMPILER_FEATURES ${feature})
98    if(${feature} STREQUAL "float16")
99      set(LIBC_TYPES_HAS_FLOAT16 TRUE)
100    elseif(${feature} STREQUAL "float128")
101      set(LIBC_TYPES_HAS_FLOAT128 TRUE)
102    elseif(${feature} STREQUAL "fixed_point")
103      set(LIBC_COMPILER_HAS_FIXED_POINT TRUE)
104    elseif(${feature} STREQUAL "builtin_ceil_floor_rint_trunc")
105      set(LIBC_COMPILER_HAS_BUILTIN_CEIL_FLOOR_RINT_TRUNC TRUE)
106    elseif(${feature} STREQUAL "builtin_fmax_fmin")
107      set(LIBC_COMPILER_HAS_BUILTIN_FMAX_FMIN TRUE)
108    elseif(${feature} STREQUAL "builtin_fmaxf16_fminf16")
109      set(LIBC_COMPILER_HAS_BUILTIN_FMAXF16_FMINF16 TRUE)
110    elseif(${feature} STREQUAL "builtin_round")
111      set(LIBC_COMPILER_HAS_BUILTIN_ROUND TRUE)
112    elseif(${feature} STREQUAL "builtin_roundeven")
113      set(LIBC_COMPILER_HAS_BUILTIN_ROUNDEVEN TRUE)
114    endif()
115  endif()
116endforeach()
117
118message(STATUS "Compiler features available: ${AVAILABLE_COMPILER_FEATURES}")
119
120### Compiler Feature Detection ###
121
122# clang-8+, gcc-12+
123check_cxx_compiler_flag("-ftrivial-auto-var-init=pattern" LIBC_CC_SUPPORTS_PATTERN_INIT)
124
125# clang-6+, gcc-13+
126check_cxx_compiler_flag("-nostdlib++" LIBC_CC_SUPPORTS_NOSTDLIBPP)
127
128# clang-3.0+
129check_cxx_compiler_flag("-nostdlibinc" LIBC_CC_SUPPORTS_NOSTDLIBINC)
130