[CI] check libc freestanding in compiler-rt - #217972
Conversation
d7d901f to
3376b95
Compare
3376b95 to
584453b
Compare
| @@ -0,0 +1,25 @@ | |||
| # Copy the manifest's libc headers into DEST, preserving their paths, so | |||
There was a problem hiding this comment.
libc-isolation tools (.sh) and manifests should stay inside libc/utils.
The export-libc-shared.cmake should stay in llvm-project/cmake/Modules, maybe merge it with llvm-project/cmake/Modules/FindLibcCommonUtils.cmake?
There was a problem hiding this comment.
Can you also generate manifest for shared/math?
| if: github.repository_owner == 'llvm' | ||
| runs-on: ubuntu-24.04 | ||
| container: | ||
| image: ghcr.io/llvm/libc-ubuntu-24.04 |
|
|
||
| - name: Extract the shared subset | ||
| run: | | ||
| d="compiler-rt/lib/builtins/libc-isolation" |
There was a problem hiding this comment.
A more descriptive variable name might be nice.
| run: | | ||
| cmake \ | ||
| --build build-iso \ | ||
| --parallel \ |
There was a problem hiding this comment.
This probably isn't necessary to say explicitly?
| - name: Manifest matches the live header closure | ||
| shell: bash | ||
| run: | | ||
| d="compiler-rt/lib/builtins/libc-isolation" |
There was a problem hiding this comment.
More descriptive variable name?
| persist-credentials: false | ||
|
|
||
| - name: Manifest matches the live header closure | ||
| shell: bash |
There was a problem hiding this comment.
This should be the default?
| if: github.repository_owner == 'llvm' | ||
| runs-on: ubuntu-24.04 | ||
| container: | ||
| image: ghcr.io/llvm/libc-ubuntu-24.04 |
|
@llvm/pr-subscribers-github-workflow Author: hulxv (hulxv) ChangesAdd a job to check the isolation of the libc in compiler-rt by building against a specific set of headers Part of #197824 Full diff: https://github.com/llvm/llvm-project/pull/217972.diff 6 Files Affected:
diff --git a/.github/workflows/compiler-rt-libc-builtins-tests.yml b/.github/workflows/compiler-rt-libc-builtins-tests.yml
index 51fff1fdf1eb9..c9c8d304a6b1e 100644
--- a/.github/workflows/compiler-rt-libc-builtins-tests.yml
+++ b/.github/workflows/compiler-rt-libc-builtins-tests.yml
@@ -52,3 +52,62 @@ jobs:
--build build \
--parallel \
--target check-builtins
+
+ # Build the libc-backed builtins against only the extracted shared subset, so
+ # the build fails if they ever reach into the rest of libc.
+ isolation:
+ name: builtins isolation (subset-only build)
+ if: github.repository_owner == 'llvm'
+ runs-on: ubuntu-24.04
+ container:
+ image: ghcr.io/llvm/libc-ubuntu-24.04
+
+ steps:
+ - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
+ with:
+ persist-credentials: false
+
+ - name: Manifest matches the live header closure
+ shell: bash
+ run: |
+ d="compiler-rt/lib/builtins/libc-isolation"
+ if ! diff -u \
+ <(grep -v '^#' "$d/libc-shared-manifest.txt") \
+ <(CXX=clang++-23 bash "$d/libc-shared-closure.sh"); then
+ echo "::error::libc-shared-manifest.txt is stale. Regenerate it with:"
+ echo " CXX=clang++-23 $d/regen-manifest.sh"
+ exit 1
+ fi
+
+ - name: Extract the shared subset
+ run: |
+ d="compiler-rt/lib/builtins/libc-isolation"
+ cmake \
+ -DLIBC_ROOT="$PWD/libc" \
+ -DDEST="$PWD/libc-shared-subset" \
+ -DMANIFEST="$PWD/$d/libc-shared-manifest.txt" \
+ -P "$d/export-libc-shared.cmake"
+
+ - name: Configure CMake against the subset only
+ run: |
+ cmake \
+ -B build-iso \
+ -S runtimes \
+ -DLLVM_ENABLE_RUNTIMES=compiler-rt \
+ -G Ninja \
+ -DCMAKE_C_COMPILER=clang-23 \
+ -DCMAKE_CXX_COMPILER=clang++-23 \
+ -DCMAKE_BUILD_TYPE=Release \
+ -DLLVM_ENABLE_ASSERTIONS=ON \
+ -DCOMPILER_RT_STANDALONE_BUILD=ON \
+ -DCOMPILER_RT_USE_LIBC_MATH=ON \
+ -DCOMPILER_RT_LIBC_SHARED_INCLUDE_ROOT="$PWD/libc-shared-subset" \
+ -DLLVM_EXTERNAL_LIT=$(which lit-23) \
+ -DCOMPILER_RT_INCLUDE_TESTS=ON
+
+ - name: Build and test builtins against the subset
+ run: |
+ cmake \
+ --build build-iso \
+ --parallel \
+ --target check-builtins
diff --git a/compiler-rt/lib/builtins/CMakeLists.txt b/compiler-rt/lib/builtins/CMakeLists.txt
index e7827f2201b43..d830b8ce1b9a7 100644
--- a/compiler-rt/lib/builtins/CMakeLists.txt
+++ b/compiler-rt/lib/builtins/CMakeLists.txt
@@ -267,6 +267,15 @@ set(x86_80_BIT_SOURCES
option(COMPILER_RT_USE_LIBC_MATH
"Use LLVM libc math routines for floating-point builtins" OFF)
+# libc include root; point at an isolated subset (see libc-isolation/) to prove
+# the builtins build against that subset alone. Empty = the in-tree libc.
+set(COMPILER_RT_LIBC_SHARED_INCLUDE_ROOT "" CACHE PATH
+ "Include root for the libc-backed builtins (default: the LLVM-libc source tree)")
+
+# Where compiler-rt-export-libc-shared writes that subset (per the manifest).
+set(COMPILER_RT_LIBC_SHARED_EXPORT_DIR "" CACHE PATH
+ "Destination for the extracted LLVM-libc shared subset (see libc-isolation/)")
+
# Swap the legacy soft-float <name>.c builtin in <list> for the libc-backed
# <name>.cpp implementation (which delegates to LIBC_NAMESPACE::shared::*).
macro(use_libc_builtin list_var name)
@@ -282,9 +291,26 @@ if(COMPILER_RT_USE_LIBC_MATH)
get_target_property(_libc_include_dirs llvm-libc-common-utilities
INTERFACE_INCLUDE_DIRECTORIES)
+ set(_libc_root ${_libc_include_dirs})
+
+ if(COMPILER_RT_LIBC_SHARED_INCLUDE_ROOT)
+ set(_libc_include_dirs ${COMPILER_RT_LIBC_SHARED_INCLUDE_ROOT})
+ endif()
+
include_directories(SYSTEM ${_libc_include_dirs})
add_definitions(-DCOMPILER_RT_USE_LIBC_MATH)
+ if(COMPILER_RT_LIBC_SHARED_EXPORT_DIR)
+ add_custom_target(compiler-rt-export-libc-shared
+ COMMAND ${CMAKE_COMMAND}
+ -DLIBC_ROOT=${_libc_root}
+ -DDEST=${COMPILER_RT_LIBC_SHARED_EXPORT_DIR}
+ -DMANIFEST=${CMAKE_CURRENT_SOURCE_DIR}/libc-isolation/libc-shared-manifest.txt
+ -P ${CMAKE_CURRENT_SOURCE_DIR}/libc-isolation/export-libc-shared.cmake
+ VERBATIM
+ COMMENT "Exporting LLVM-libc shared subset to ${COMPILER_RT_LIBC_SHARED_EXPORT_DIR}")
+ endif()
+
use_libc_builtin(GENERIC_SOURCES adddf3)
use_libc_builtin(GENERIC_SOURCES addsf3)
use_libc_builtin(GENERIC_TF_SOURCES addtf3)
diff --git a/compiler-rt/lib/builtins/libc-isolation/export-libc-shared.cmake b/compiler-rt/lib/builtins/libc-isolation/export-libc-shared.cmake
new file mode 100644
index 0000000000000..1ee4ab9a91245
--- /dev/null
+++ b/compiler-rt/lib/builtins/libc-isolation/export-libc-shared.cmake
@@ -0,0 +1,25 @@
+# Copy the manifest's libc headers into DEST, preserving their paths, so
+# compiler-rt can build the libc-backed builtins against that subset alone.
+#
+# cmake -DLIBC_ROOT=<libc> -DDEST=<dir> -DMANIFEST=<file> -P export-libc-shared.cmake
+
+if(NOT LIBC_ROOT OR NOT DEST OR NOT MANIFEST)
+ message(FATAL_ERROR "set LIBC_ROOT, DEST and MANIFEST")
+endif()
+
+file(STRINGS "${MANIFEST}" _lines)
+set(_count 0)
+foreach(_rel IN LISTS _lines)
+ string(STRIP "${_rel}" _rel)
+ if(_rel STREQUAL "" OR _rel MATCHES "^#")
+ continue()
+ endif()
+ if(NOT EXISTS "${LIBC_ROOT}/${_rel}")
+ message(FATAL_ERROR "manifest lists a missing file: ${LIBC_ROOT}/${_rel}")
+ endif()
+ get_filename_component(_dstdir "${DEST}/${_rel}" DIRECTORY)
+ file(MAKE_DIRECTORY "${_dstdir}")
+ configure_file("${LIBC_ROOT}/${_rel}" "${DEST}/${_rel}" COPYONLY)
+ math(EXPR _count "${_count} + 1")
+endforeach()
+message(STATUS "export-libc-shared: copied ${_count} files into ${DEST}")
diff --git a/compiler-rt/lib/builtins/libc-isolation/libc-shared-closure.sh b/compiler-rt/lib/builtins/libc-isolation/libc-shared-closure.sh
new file mode 100755
index 0000000000000..e367a0601d874
--- /dev/null
+++ b/compiler-rt/lib/builtins/libc-isolation/libc-shared-closure.sh
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+# Print the libc headers the compiler-rt libc-backed builtins include, one
+# libc-root-relative path per line, sorted. Used to regenerate the manifest and
+# to drift-check it in CI. Run from the llvm-project root; override with CXX=.
+set -euo pipefail
+
+CXX="${CXX:-clang++}"
+LIBC_ROOT="${LIBC_ROOT:-libc}"
+
+tmp="$(mktemp -d)"
+trap 'rm -rf "$tmp"' EXIT
+printf '#include "shared/builtins.h"\n' > "$tmp/probe.cpp"
+
+"$CXX" -std=c++17 \
+ -DLIBC_NAMESPACE=__llvm_libc_common_utils \
+ -DLIBC_MATH=12 \
+ -I "$LIBC_ROOT" -I "$LIBC_ROOT/include" \
+ -MM -MG "$tmp/probe.cpp" 2>/dev/null \
+ | tr ' \\' '\n\n' \
+ | grep -E "^$LIBC_ROOT/" \
+ | LIBC_ROOT="$LIBC_ROOT" python3 -c '
+import os, sys
+libc = os.path.abspath(os.environ["LIBC_ROOT"])
+seen = set()
+for line in sys.stdin:
+ p = line.strip()
+ if not p:
+ continue
+ rel = os.path.relpath(os.path.normpath(os.path.abspath(p)), libc)
+ if not rel.startswith(".."):
+ seen.add(rel)
+for rel in sorted(seen):
+ print(rel)
+'
diff --git a/compiler-rt/lib/builtins/libc-isolation/libc-shared-manifest.txt b/compiler-rt/lib/builtins/libc-isolation/libc-shared-manifest.txt
new file mode 100644
index 0000000000000..76e78823f746a
--- /dev/null
+++ b/compiler-rt/lib/builtins/libc-isolation/libc-shared-manifest.txt
@@ -0,0 +1,227 @@
+# Auto-generated by regen-manifest.sh -- do not edit by hand.
+# The libc headers the compiler-rt libc-backed builtins include,
+# libc-root-relative. Regenerate after changing those includes.
+hdr/errno_macros.h
+hdr/fenv_macros.h
+hdr/float_macros.h
+hdr/limits_macros.h
+hdr/math_macros.h
+hdr/stdint_proxy.h
+hdr/types/fenv_t.h
+hdr/types/size_t.h
+include/llvm-libc-macros/cfloat128-macros.h
+include/llvm-libc-macros/cfloat16-macros.h
+include/llvm-libc-macros/float-macros.h
+include/llvm-libc-macros/float16-macros.h
+include/llvm-libc-macros/stdfix-macros.h
+include/llvm-libc-types/cfloat128.h
+include/llvm-libc-types/cfloat16.h
+include/llvm-libc-types/float128.h
+shared/builtins.h
+shared/builtins/adddf3.h
+shared/builtins/addsf3.h
+shared/builtins/addtf3.h
+shared/builtins/divdf3.h
+shared/builtins/divsf3.h
+shared/builtins/divtf3.h
+shared/builtins/extenddftf2.h
+shared/builtins/extendsfdf2.h
+shared/builtins/extendsftf2.h
+shared/builtins/extendxftf2.h
+shared/builtins/fixdfdi.h
+shared/builtins/fixdfsi.h
+shared/builtins/fixdfti.h
+shared/builtins/fixsfdi.h
+shared/builtins/fixsfsi.h
+shared/builtins/fixsfti.h
+shared/builtins/fixunsdfdi.h
+shared/builtins/fixunsdfsi.h
+shared/builtins/fixunsdfti.h
+shared/builtins/fixunssfdi.h
+shared/builtins/fixunssfsi.h
+shared/builtins/fixunssfti.h
+shared/builtins/floatdidf.h
+shared/builtins/floatdisf.h
+shared/builtins/floatsidf.h
+shared/builtins/floatsisf.h
+shared/builtins/floattidf.h
+shared/builtins/floattisf.h
+shared/builtins/floatundidf.h
+shared/builtins/floatundisf.h
+shared/builtins/floatunsidf.h
+shared/builtins/floatunsisf.h
+shared/builtins/floatuntidf.h
+shared/builtins/floatuntisf.h
+shared/builtins/gesf2.h
+shared/builtins/lesf2.h
+shared/builtins/muldf3.h
+shared/builtins/mulsf3.h
+shared/builtins/multf3.h
+shared/builtins/negdf2.h
+shared/builtins/negsf2.h
+shared/builtins/subdf3.h
+shared/builtins/subsf3.h
+shared/builtins/subtf3.h
+shared/builtins/truncdfsf2.h
+shared/builtins/trunctfdf2.h
+shared/builtins/trunctfsf2.h
+shared/builtins/trunctfxf2.h
+shared/builtins/unordsf2.h
+shared/libc_common.h
+src/__support/CPP/algorithm.h
+src/__support/CPP/array.h
+src/__support/CPP/bit.h
+src/__support/CPP/iterator.h
+src/__support/CPP/limits.h
+src/__support/CPP/optional.h
+src/__support/CPP/type_traits.h
+src/__support/CPP/type_traits/add_lvalue_reference.h
+src/__support/CPP/type_traits/add_pointer.h
+src/__support/CPP/type_traits/add_rvalue_reference.h
+src/__support/CPP/type_traits/aligned_storage.h
+src/__support/CPP/type_traits/always_false.h
+src/__support/CPP/type_traits/bool_constant.h
+src/__support/CPP/type_traits/conditional.h
+src/__support/CPP/type_traits/decay.h
+src/__support/CPP/type_traits/enable_if.h
+src/__support/CPP/type_traits/false_type.h
+src/__support/CPP/type_traits/has_unique_object_representations.h
+src/__support/CPP/type_traits/integral_constant.h
+src/__support/CPP/type_traits/invoke.h
+src/__support/CPP/type_traits/invoke_result.h
+src/__support/CPP/type_traits/is_arithmetic.h
+src/__support/CPP/type_traits/is_array.h
+src/__support/CPP/type_traits/is_assignable.h
+src/__support/CPP/type_traits/is_base_of.h
+src/__support/CPP/type_traits/is_class.h
+src/__support/CPP/type_traits/is_complex.h
+src/__support/CPP/type_traits/is_const.h
+src/__support/CPP/type_traits/is_constant_evaluated.h
+src/__support/CPP/type_traits/is_constructible.h
+src/__support/CPP/type_traits/is_convertible.h
+src/__support/CPP/type_traits/is_copy_assignable.h
+src/__support/CPP/type_traits/is_copy_constructible.h
+src/__support/CPP/type_traits/is_destructible.h
+src/__support/CPP/type_traits/is_enum.h
+src/__support/CPP/type_traits/is_fixed_point.h
+src/__support/CPP/type_traits/is_floating_point.h
+src/__support/CPP/type_traits/is_function.h
+src/__support/CPP/type_traits/is_integral.h
+src/__support/CPP/type_traits/is_lvalue_reference.h
+src/__support/CPP/type_traits/is_member_pointer.h
+src/__support/CPP/type_traits/is_move_assignable.h
+src/__support/CPP/type_traits/is_move_constructible.h
+src/__support/CPP/type_traits/is_null_pointer.h
+src/__support/CPP/type_traits/is_object.h
+src/__support/CPP/type_traits/is_pointer.h
+src/__support/CPP/type_traits/is_reference.h
+src/__support/CPP/type_traits/is_rvalue_reference.h
+src/__support/CPP/type_traits/is_same.h
+src/__support/CPP/type_traits/is_scalar.h
+src/__support/CPP/type_traits/is_signed.h
+src/__support/CPP/type_traits/is_trivially_constructible.h
+src/__support/CPP/type_traits/is_trivially_copyable.h
+src/__support/CPP/type_traits/is_trivially_destructible.h
+src/__support/CPP/type_traits/is_union.h
+src/__support/CPP/type_traits/is_unsigned.h
+src/__support/CPP/type_traits/is_void.h
+src/__support/CPP/type_traits/make_signed.h
+src/__support/CPP/type_traits/make_unsigned.h
+src/__support/CPP/type_traits/remove_all_extents.h
+src/__support/CPP/type_traits/remove_cv.h
+src/__support/CPP/type_traits/remove_cvref.h
+src/__support/CPP/type_traits/remove_extent.h
+src/__support/CPP/type_traits/remove_reference.h
+src/__support/CPP/type_traits/true_type.h
+src/__support/CPP/type_traits/type_identity.h
+src/__support/CPP/type_traits/void_t.h
+src/__support/CPP/utility.h
+src/__support/CPP/utility/declval.h
+src/__support/CPP/utility/forward.h
+src/__support/CPP/utility/in_place.h
+src/__support/CPP/utility/integer_sequence.h
+src/__support/CPP/utility/move.h
+src/__support/FPUtil/BasicOperations.h
+src/__support/FPUtil/FEnvImpl.h
+src/__support/FPUtil/FPBits.h
+src/__support/FPUtil/cast.h
+src/__support/FPUtil/comparison_operations.h
+src/__support/FPUtil/dyadic_float.h
+src/__support/FPUtil/generic/add_sub.h
+src/__support/FPUtil/generic/div.h
+src/__support/FPUtil/generic/mul.h
+src/__support/FPUtil/multiply_add.h
+src/__support/FPUtil/rounding_mode.h
+src/__support/big_int.h
+src/__support/builtins/adddf3.h
+src/__support/builtins/addsf3.h
+src/__support/builtins/addtf3.h
+src/__support/builtins/cmp_helper.h
+src/__support/builtins/divdf3.h
+src/__support/builtins/divsf3.h
+src/__support/builtins/divtf3.h
+src/__support/builtins/extenddftf2.h
+src/__support/builtins/extendsfdf2.h
+src/__support/builtins/extendsftf2.h
+src/__support/builtins/extendxftf2.h
+src/__support/builtins/fixdfdi.h
+src/__support/builtins/fixdfsi.h
+src/__support/builtins/fixdfti.h
+src/__support/builtins/fixint_helper.h
+src/__support/builtins/fixsfdi.h
+src/__support/builtins/fixsfsi.h
+src/__support/builtins/fixsfti.h
+src/__support/builtins/fixunsdfdi.h
+src/__support/builtins/fixunsdfsi.h
+src/__support/builtins/fixunsdfti.h
+src/__support/builtins/fixunssfdi.h
+src/__support/builtins/fixunssfsi.h
+src/__support/builtins/fixunssfti.h
+src/__support/builtins/floatdidf.h
+src/__support/builtins/floatdisf.h
+src/__support/builtins/floatint_helper.h
+src/__support/builtins/floatsidf.h
+src/__support/builtins/floatsisf.h
+src/__support/builtins/floattidf.h
+src/__support/builtins/floattisf.h
+src/__support/builtins/floatundidf.h
+src/__support/builtins/floatundisf.h
+src/__support/builtins/floatunsidf.h
+src/__support/builtins/floatunsisf.h
+src/__support/builtins/floatuntidf.h
+src/__support/builtins/floatuntisf.h
+src/__support/builtins/fpconvert_helper.h
+src/__support/builtins/gesf2.h
+src/__support/builtins/lesf2.h
+src/__support/builtins/muldf3.h
+src/__support/builtins/mulsf3.h
+src/__support/builtins/multf3.h
+src/__support/builtins/negdf2.h
+src/__support/builtins/negsf2.h
+src/__support/builtins/subdf3.h
+src/__support/builtins/subsf3.h
+src/__support/builtins/subtf3.h
+src/__support/builtins/truncdfsf2.h
+src/__support/builtins/trunctfdf2.h
+src/__support/builtins/trunctfsf2.h
+src/__support/builtins/trunctfxf2.h
+src/__support/builtins/unordsf2.h
+src/__support/common.h
+src/__support/libc_assert.h
+src/__support/libc_errno.h
+src/__support/macros/attributes.h
+src/__support/macros/config.h
+src/__support/macros/hardening.h
+src/__support/macros/macro-utils.h
+src/__support/macros/optimization.h
+src/__support/macros/properties/architectures.h
+src/__support/macros/properties/compiler.h
+src/__support/macros/properties/complex_types.h
+src/__support/macros/properties/cpu_features.h
+src/__support/macros/properties/os.h
+src/__support/macros/properties/types.h
+src/__support/macros/sanitizer.h
+src/__support/math_extras.h
+src/__support/number_pair.h
+src/__support/sign.h
+src/__support/uint128.h
diff --git a/compiler-rt/lib/builtins/libc-isolation/regen-manifest.sh b/compiler-rt/lib/builtins/libc-isolation/regen-manifest.sh
new file mode 100755
index 0000000000000..9524817720cb5
--- /dev/null
+++ b/compiler-rt/lib/builtins/libc-isolation/regen-manifest.sh
@@ -0,0 +1,16 @@
+#!/usr/bin/env bash
+# Regenerate libc-shared-manifest.txt from the live header closure.
+# Run from the llvm-project root; override with CXX=.
+set -euo pipefail
+
+here="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+manifest="$here/libc-shared-manifest.txt"
+
+{
+ echo "# Auto-generated by regen-manifest.sh -- do not edit by hand."
+ echo "# The libc headers the compiler-rt libc-backed builtins include,"
+ echo "# libc-root-relative. Regenerate after changing those includes."
+ bash "$here/libc-shared-closure.sh"
+} > "$manifest"
+
+echo "wrote $(grep -vc '^#' "$manifest") entries to $manifest"
|
Add a job to check the isolation of the libc in compiler-rt by building against a specific set of headers
Part of #197824