diff --git a/CMakeLists.txt b/CMakeLists.txt index 579050b3..362f8a3c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,6 +176,8 @@ if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Release CACHE BOOL "" FORCE) endif() +find_package(Python3 REQUIRED COMPONENTS Interpreter) + if(NOT CMAKE_C_COMPILER_LAUNCHER AND NOT CMAKE_CXX_COMPILER_LAUNCHER) # If ccache is available then use it by default. find_program(CCACHE_EXECUTABLE ccache) @@ -457,7 +459,7 @@ function(add_picolibc directory variant target_triple flags qemu_params variant_ INSTALL_DIR "${LLVM_BINARY_DIR}/${directory}" PREFIX picolibc/${variant} DEPENDS clang lld llvm-ar llvm-config llvm-nm llvm-ranlib llvm-strip - CONFIGURE_COMMAND ${MESON_EXECUTABLE} -Dincludedir=include -Dlibdir=lib -Dspecsdir=none --prefix --cross-file /meson-cross-build.txt ${picolibc_SOURCE_DIR} + CONFIGURE_COMMAND ${MESON_EXECUTABLE} -Dincludedir=include -Dlibdir=lib -Dspecsdir=none -Dmultilib=false --prefix --cross-file /meson-cross-build.txt ${picolibc_SOURCE_DIR} BUILD_COMMAND ninja INSTALL_COMMAND ${MESON_EXECUTABLE} install ${MESON_INSTALL_QUIET} USES_TERMINAL_CONFIGURE TRUE @@ -831,7 +833,7 @@ function(make_config_cfg directory variant flags) ) endfunction() -function(get_compiler_rt_target_triple target_arch) +function(get_compiler_rt_target_triple target_arch flags) if(target_arch STREQUAL "aarch64") set(target_triple "aarch64-none-elf") else() @@ -861,7 +863,7 @@ endfunction() function(add_library_variants) set(variant_args "${ARGN}") while(variant_args) - list(POP_FRONT variant_args target_arch variant_suffix flags qemu_params) + list(POP_FRONT variant_args target_arch variant_suffix compile_flags multilib_flags qemu_params) if(variant_suffix) set(variant "${target_arch}_${variant_suffix}") @@ -884,18 +886,18 @@ function(add_library_variants) set(parent_dir_name arm-none-eabi) endif() - get_compiler_rt_target_triple(${target_arch}) + get_compiler_rt_target_triple("${target_arch}" "${compile_flags}") set(directory "${TARGET_LIBRARIES_DIR}/${parent_dir_name}/${variant}") - set(flags "--target=${target_triple} ${flags}") - make_config_cfg("${directory}" "${variant}" "${flags}") + set(compile_flags "--target=${target_triple} ${compile_flags}") + make_config_cfg("${directory}" "${variant}" "${compile_flags}") set(variant_options) if(NOT PREBUILT_TARGET_LIBRARIES) - add_picolibc("${directory}" "${variant}" "${target_triple}" "${flags}" "${qemu_params}" variant_options) - add_compiler_rt("${directory}" "${variant}" "${target_triple}" "${flags}" "${qemu_params}" "picolibc_${variant}") + add_picolibc("${directory}" "${variant}" "${target_triple}" "${compile_flags}" "${qemu_params}" variant_options) + add_compiler_rt("${directory}" "${variant}" "${target_triple}" "${compile_flags}" "${qemu_params}" "picolibc_${variant}") list(APPEND variant_options ${picolibc_specific_runtimes_options}) - add_libcxx_libcxxabi_libunwind("${directory}" "${variant}" "${target_triple}" "${flags}" "picolibc_${variant}" "${variant_options}") - if(flags MATCHES "-march=armv8") + add_libcxx_libcxxabi_libunwind("${directory}" "${variant}" "${target_triple}" "${compile_flags}" "picolibc_${variant}" "${variant_options}") + if(compile_flags MATCHES "-march=armv8") message("C++ runtime libraries tests disabled for ${variant}") else() add_custom_target(check-llvm-toolchain-runtimes-${variant}) @@ -905,30 +907,52 @@ function(add_library_variants) endif() endif() + string(APPEND multilib_yaml_content "- Dir: ${parent_dir_name}/${variant}\n") + + string(APPEND multilib_yaml_content " Flags:\n") + string(REPLACE " " ";" multilib_flags_list ${multilib_flags}) + foreach(flag ${multilib_flags_list}) + string(APPEND multilib_yaml_content " - ${flag}\n") + endforeach() + install( DIRECTORY "${LLVM_BINARY_DIR}/${directory}/" DESTINATION "${directory}" COMPONENT llvm-toolchain-libs ) endwhile() + set(multilib_yaml_content "${multilib_yaml_content}" PARENT_SCOPE) endfunction() +set(multilib_yaml_content "") + # Define which library variants to build and which flags to use. -# The order is +# The order is add_library_variants( - aarch64 "" "-march=armv8-a" "-M virt -cpu cortex-a57" - armv4t "" "-march=armv4t" "-M musicpal -cpu arm926" - armv5te "" "-march=armv5te" "-M musicpal -cpu arm926" - armv6m soft_nofp "-mfloat-abi=soft -march=armv6m" "-M mps2-an385" - armv7m soft_nofp "-mfloat-abi=soft -march=armv7m+nofp" "-M mps2-an385 -cpu cortex-m3" - armv7em soft_nofp "-mfloat-abi=soft -march=armv7em -mfpu=none" "-M mps2-an386 -cpu cortex-m4" - armv7em hard_fpv4_sp_d16 "-mfloat-abi=hard -march=armv7em -mfpu=fpv4-sp-d16" "-M mps2-an386 -cpu cortex-m4" - armv7em hard_fpv5_d16 "-mfloat-abi=hard -march=armv7em -mfpu=fpv5-d16" "-M mps2-an500 -cpu cortex-m7" - armv8m.main soft_nofp "-mfloat-abi=soft -march=armv8m.main+nofp" "-M mps2-an505 -cpu cortex-m33" - armv8m.main hard_fp "-mfloat-abi=hard -march=armv8m.main+fp" "-M mps2-an505 -cpu cortex-m33" - armv8.1m.main soft_nofp_nomve "-mfloat-abi=soft -march=armv8.1m.main+nofp+nomve" "-M mps3-an547 -cpu cortex-m55" - armv8.1m.main hard_fp "-mfloat-abi=hard -march=armv8.1m.main+fp" "-M mps3-an547 -cpu cortex-m55" - armv8.1m.main hard_nofp_mve "-mfloat-abi=hard -march=armv8.1m.main+nofp+mve" "-M mps3-an547 -cpu cortex-m55" + aarch64 "" "-march=armv8-a" "--target=aarch64-none-unknown-elf" "-M virt -cpu cortex-a57" + armv4t "" "-march=armv4t" "--target=armv4t-none-unknown-eabi -mfpu=none" "-M musicpal -cpu arm926" + armv5te "" "-march=armv5te" "--target=armv5e-none-unknown-eabi -mfpu=none" "-M musicpal -cpu arm926" + armv6m soft_nofp "-mfloat-abi=soft -march=armv6m" "--target=thumbv6m-none-unknown-eabi -mfpu=none" "-M mps2-an385" + armv7m soft_nofp "-mfloat-abi=soft -march=armv7m+nofp" "--target=thumbv7m-none-unknown-eabi -mfpu=none" "-M mps2-an385 -cpu cortex-m3" + armv7em soft_nofp "-mfloat-abi=soft -march=armv7em -mfpu=none" "--target=thumbv7em-none-unknown-eabi -mfpu=none" "-M mps2-an386 -cpu cortex-m4" + armv7em hard_fpv4_sp_d16 "-mfloat-abi=hard -march=armv7em -mfpu=fpv4-sp-d16" "--target=thumbv7em-none-unknown-eabihf -mfpu=fpv4-sp-d16" "-M mps2-an386 -cpu cortex-m4" + armv7em hard_fpv5_d16 "-mfloat-abi=hard -march=armv7em -mfpu=fpv5-d16" "--target=thumbv7em-none-unknown-eabihf -mfpu=fpv5-d16" "-M mps2-an500 -cpu cortex-m7" + armv8m.main soft_nofp "-mfloat-abi=soft -march=armv8m.main+nofp" "--target=thumbv8m.main-none-unknown-eabi -mfpu=none" "-M mps2-an505 -cpu cortex-m33" + armv8m.main hard_fp "-mfloat-abi=hard -march=armv8m.main+fp" "--target=thumbv8m.main-none-unknown-eabihf -mfpu=fpv5-d16" "-M mps2-an505 -cpu cortex-m33" + armv8.1m.main soft_nofp_nomve "-mfloat-abi=soft -march=armv8.1m.main+nofp+nomve" "--target=thumbv8.1m.main-none-unknown-eabi -mfpu=none" "-M mps3-an547 -cpu cortex-m55" + armv8.1m.main hard_fp "-mfloat-abi=hard -march=armv8.1m.main+fp" "--target=thumbv8.1m.main-none-unknown-eabihf -march=thumbv8.1m.main+fp16 -mfpu=fp-armv8-fullfp16-sp-d16" "-M mps3-an547 -cpu cortex-m55" + armv8.1m.main hard_nofp_mve "-mfloat-abi=hard -march=armv8.1m.main+nofp+mve" "--target=thumbv8.1m.main-none-unknown-eabihf -march=thumbv8.1m.main+dsp+mve -mfpu=none" "-M mps3-an547 -cpu cortex-m55" +) + +configure_file( + ${CMAKE_CURRENT_SOURCE_DIR}/cmake/multilib.yaml.in + ${CMAKE_CURRENT_BINARY_DIR}/llvm/${TARGET_LIBRARIES_DIR}/multilib.yaml + @ONLY +) +install( + FILES ${CMAKE_CURRENT_BINARY_DIR}/llvm/${TARGET_LIBRARIES_DIR}/multilib.yaml + DESTINATION ${TARGET_LIBRARIES_DIR} + COMPONENT llvm-toolchain-libs ) install( @@ -1075,12 +1099,15 @@ add_dependencies( +# TODO move this into tests/CMakeLists.txt # Smoke tests # Run tests on the built toolchain. add_custom_target(check-llvm-toolchain) add_dependencies(check-llvm-toolchain check-picolibc) add_dependencies(check-llvm-toolchain check-compiler-rt) +add_subdirectory(tests) +add_dependencies(check-llvm-toolchain check-llvm-toolchain-lit) # Run tests on the packaged and unpacked toolchain. add_custom_target(check-package-llvm-toolchain) diff --git a/cmake/multilib.yaml.in b/cmake/multilib.yaml.in new file mode 100644 index 00000000..a3e3dd85 --- /dev/null +++ b/cmake/multilib.yaml.in @@ -0,0 +1,140 @@ +# +# Copyright (c) 2023, Arm Limited and affiliates. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# If you're reading this file under the name 'multilib.yaml.in' in the +# LLVM-embedded-toolchain-for-Arm source tree, then it's not valid +# YAML in its own right: it's a template that CMakeLists.txt will +# expand into a real 'multilib.yaml' containing a list of library +# variants and the flags that will select them. +# +# If you're reading it under the name 'multilib.yaml' in the build or +# install directory, then that substitution has been done. +# +# Comments in this file mostly make more sense from the +# multilib.yaml.in point of view. + +MultilibVersion: '1.0' + +# The list of library variants is substituted in by CMakeLists.txt, so +# that it can respect the LLVM_TOOLCHAIN_LIBRARY_VARIANTS setting and +# only include the set of libraries actually included in this build. + +Variants: +@multilib_yaml_content@ + +Mappings: + +# Map higher architecture versions to subsets of them, so that a +# compatible library can be found even for architectures we don't have +# specific variants for. + +# v8-M Baseline is a superset of v6-M +- Match: --target=thumbv8m\.base-none-unknown-eabi + Flags: + - --target=thumbv6m-none-unknown-eabi + +# v8.2-M Mainline is a superset of v8.1-M Mainline, in both hard and +# soft float variants. +# +# Also, v8.1-M Mainline is also a superset of v8-M Mainline, which in +# turn is a superset of v7E-M, and then of plain v7-M. We have +# libraries for all those architecture versions, but not for every +# combination of them with FPUs, so in some cases it might be +# necessary to fall back to a lower architecture in order to provide +# the needed FPU support. +- Match: --target=thumbv8\.[2-9]m\.main-none-unknown-eabi + Flags: + - --target=thumbv8.1m.main-none-unknown-eabi + - --target=thumbv8m.main-none-unknown-eabi + - --target=thumbv7em-none-unknown-eabi + - --target=thumbv7m-none-unknown-eabi +- Match: --target=thumbv8\.[2-9]m\.main-none-unknown-eabihf + Flags: + - --target=thumbv8.1m.main-none-unknown-eabihf + - --target=thumbv8m.main-none-unknown-eabihf + - --target=thumbv7em-none-unknown-eabihf + - --target=thumbv7m-none-unknown-eabihf +- Match: --target=thumbv8\.1m\.main-none-unknown-eabi + Flags: + - --target=thumbv8m.main-none-unknown-eabi + - --target=thumbv7em-none-unknown-eabi + - --target=thumbv7m-none-unknown-eabi +- Match: --target=thumbv8\.1m\.main-none-unknown-eabihf + Flags: + - --target=thumbv8m.main-none-unknown-eabihf + - --target=thumbv7em-none-unknown-eabihf + - --target=thumbv7m-none-unknown-eabihf +- Match: --target=thumbv8m\.main-none-unknown-eabi + Flags: + - --target=thumbv7em-none-unknown-eabi + - --target=thumbv7m-none-unknown-eabi +- Match: --target=thumbv8m\.main-none-unknown-eabihf + Flags: + - --target=thumbv7em-none-unknown-eabihf + - --target=thumbv7m-none-unknown-eabihf +- Match: --target=thumbv7em-none-unknown-eabi + Flags: + - --target=thumbv7m-none-unknown-eabi +- Match: --target=thumbv7em-none-unknown-eabihf + Flags: + - --target=thumbv7m-none-unknown-eabihf + +# Higher versions of v8-A, and v9-A, are all supersets of v8-A. (And +# of each other, in the obvious way, but we don't have any libraries +# for those at present, so there's no need to generate all their +# flags.) +- Match: --target=armv(8\.[1-9]|9|9\.[1-9])a-none-unknown-eabi + Flags: + - --target=armv8a-none-unknown-eabi + +# -march extensions +- Match: -march=thumbv8\.[1-9]m\.main.*\+fp16.* + Flags: + - -march=thumbv8.1m.main+fp16 +- Match: -march=thumbv8\.[1-9]m\.main.*\+dsp.*\+mve.* + Flags: + - -march=thumbv8.1m.main+dsp+mve +- Match: -march=thumbv8\.[1-9]m\.main.*\+fp16.*\+lob.*\+mve\.fp.* + Flags: + - -march=thumbv8.1m.main+fp16+lob+mve.fp + +# Hierarchy among FPUs: fpvN-d16 is a superset of fpvN-sp-d16, and +# fpvN-d16 is a superset of fpv[N-1]-d16, for all N. +# +# We don't consider any hardware FP configuration to be compatible +# with -mfpu=none. It would work in most cases to cross-call between +# code compiled for an FPU or no FPU, if you were using the soft float +# ABI. But it wouldn't work in all cases: setjmp needs to know whether +# to save FP registers in the jmp_buf, so a non-FPU-aware setjmp would +# not behave correctly if linked into an otherwise FPU-using +# application. Similarly for exception unwinding. So we don't permit +# selecting an -mfpu=none library as a fallback for any hard-FP +# library. +- Match: -mfpu=fpv5-d16 + Flags: + - -mfpu=fpv4-d16 + - -mfpu=fpv5-sp-d16 + - -mfpu=fpv4-sp-d16 +- Match: -mfpu=fpv5-sp-d16 + Flags: + - -mfpu=fpv4-sp-d16 +- Match: -mfpu=fpv4-d16 + Flags: + - -mfpu=fpv4-sp-d16 +- Match: -mfpu=fp-armv8-fullfp16-d16 + Flags: + - -mfpu=fp-armv8-fullfp16-sp-d16 diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 00000000..8716b5f9 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,30 @@ +if(LLVM_ENABLE_BACKTRACES) + set(ENABLE_BACKTRACES 1) +endif() +llvm_canonicalize_cmake_booleans( + ENABLE_BACKTRACES +) + +configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in + ${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py + MAIN_CONFIG + ${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg.py +) + +list(APPEND LLVM_TOOLCHAIN_TEST_DEPS + llvm-toolchain + FileCheck + count + not +) + +add_lit_testsuite(check-llvm-toolchain-lit + "Running LLVM Embedded Toolchain for Arm regression tests" + ${CMAKE_CURRENT_BINARY_DIR} + DEPENDS ${LLVM_TOOLCHAIN_TEST_DEPS} +) + +add_lit_testsuites(llvm-toolchain-lit ${CMAKE_CURRENT_SOURCE_DIR} + DEPENDS ${LLVM_TOOLCHAIN_TEST_DEPS} +) diff --git a/tests/lit.cfg.py b/tests/lit.cfg.py new file mode 100644 index 00000000..0059a294 --- /dev/null +++ b/tests/lit.cfg.py @@ -0,0 +1,20 @@ +# -*- Python -*- + +import os + +import lit.formats + +from lit.llvm import llvm_config + +# Configuration file for the 'lit' test runner. + +config.name = 'LLVM Embedded Toolchain for Arm' +config.test_format = lit.formats.ShTest(not llvm_config.use_lit_shell) +config.suffixes = ['.test'] +config.excludes = ['CMakeLists.txt', 'Makefile.conf', 'ldscripts', 'smoketests'] +config.test_source_root = os.path.dirname(__file__) + +llvm_config.use_default_substitutions() +llvm_config.use_clang() + +config.environment["CLANG_NO_DEFAULT_CONFIG"] = "1" diff --git a/tests/lit.site.cfg.py.in b/tests/lit.site.cfg.py.in new file mode 100644 index 00000000..ab0a1e1f --- /dev/null +++ b/tests/lit.site.cfg.py.in @@ -0,0 +1,19 @@ +@LIT_SITE_CFG_IN_HEADER@ + +config.llvm_src_root = "@LLVM_SOURCE_DIR@" +config.llvm_obj_root = "@LLVM_BINARY_DIR@" +config.llvm_tools_dir = lit_config.substitute("@LLVM_BINARY_DIR@/bin") +config.llvm_libs_dir = lit_config.substitute("@LLVM_BINARY_DIR@/lib") +config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@" +config.enable_backtrace = @ENABLE_BACKTRACES@ +config.errc_messages = "@LLVM_LIT_ERRC_MESSAGES@" +config.host_triple = "@LLVM_HOST_TRIPLE@" +config.target_triple = "@LLVM_DEFAULT_TARGET_TRIPLE@" +config.python_executable = "@Python3_EXECUTABLE@" +config.test_exec_root = "@CMAKE_CURRENT_BINARY_DIR@" + +import lit.llvm +lit.llvm.initialize(lit_config, config) + +# Let the main config do the real work. +lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg.py") diff --git a/tests/multilib/aarch64.test b/tests/multilib/aarch64.test new file mode 100644 index 00000000..e28b6128 --- /dev/null +++ b/tests/multilib/aarch64.test @@ -0,0 +1,2 @@ +# RUN: %clang -print-multi-directory --target=aarch64-none-elf | FileCheck %s +# CHECK: aarch64-none-elf/aarch64 diff --git a/tests/multilib/armv4t.test b/tests/multilib/armv4t.test new file mode 100644 index 00000000..bba171af --- /dev/null +++ b/tests/multilib/armv4t.test @@ -0,0 +1,2 @@ +# RUN: %clang -print-multi-directory --target=arm-none-eabi | FileCheck %s +# CHECK: arm-none-eabi/armv4t diff --git a/tests/multilib/armv5e.test b/tests/multilib/armv5e.test new file mode 100644 index 00000000..b1f7d95f --- /dev/null +++ b/tests/multilib/armv5e.test @@ -0,0 +1,2 @@ +# RUN: %clang -print-multi-directory --target=armv5e-none-eabi | FileCheck %s +# CHECK: arm-none-eabi/armv5te diff --git a/tests/multilib/armv6m.test b/tests/multilib/armv6m.test new file mode 100644 index 00000000..481c55bb --- /dev/null +++ b/tests/multilib/armv6m.test @@ -0,0 +1,2 @@ +# RUN: %clang -print-multi-directory --target=armv6m-none-eabi | FileCheck %s +# CHECK: arm-none-eabi/armv6m_soft_nofp diff --git a/tests/multilib/armv7em.test b/tests/multilib/armv7em.test new file mode 100644 index 00000000..b8d7c7c0 --- /dev/null +++ b/tests/multilib/armv7em.test @@ -0,0 +1,8 @@ +# RUN: %clang -print-multi-directory --target=armv7em-none-eabi -mfpu=none | FileCheck %s +# CHECK: arm-none-eabi/armv7em_soft_nofp + +# RUN: %clang -print-multi-directory --target=armv7em-none-eabihf -mfpu=fpv4-sp-d16 | FileCheck --check-prefix=FPV4 %s +# FPV4: arm-none-eabi/armv7em_hard_fpv4_sp_d16 + +# RUN: %clang -print-multi-directory --target=armv7em-none-eabihf -mfpu=fpv5-d16 | FileCheck --check-prefix=FPV5 %s +# FPV5: arm-none-eabi/armv7em_hard_fpv5_d16 diff --git a/tests/multilib/armv7m.test b/tests/multilib/armv7m.test new file mode 100644 index 00000000..4bbc5f41 --- /dev/null +++ b/tests/multilib/armv7m.test @@ -0,0 +1,2 @@ +# RUN: %clang -print-multi-directory --target=armv7m-none-eabi | FileCheck %s +# CHECK: arm-none-eabi/armv7m_soft_nofp diff --git a/tests/multilib/armv8.1m.main.test b/tests/multilib/armv8.1m.main.test new file mode 100644 index 00000000..aadce531 --- /dev/null +++ b/tests/multilib/armv8.1m.main.test @@ -0,0 +1,11 @@ +# RUN: %clang -print-multi-directory --target=armv8.1m.main-none-eabi -mfpu=none | FileCheck %s +# CHECK: arm-none-eabi/armv8.1m.main_soft_nofp + +# RUN: %clang -print-multi-directory --target=armv8.1m.main-none-eabihf -march=armv8.1m.main+fp | FileCheck --check-prefix=HARD %s +# HARD: arm-none-eabi/armv8.1m.main_hard_fp + +# RUN: %clang -print-multi-directory --target=armv8.1m.main-none-eabihf -march=armv8.1m.main+nofp+mve | FileCheck --check-prefix=MVE %s +# MVE: arm-none-eabi/armv8.1m.main_hard_nofp_mve + +# RUN: %clang -print-multi-flags-experimental --target=arm-none-eabihf -mcpu=cortex-m55 | FileCheck --check-prefix=CORTEXM55 %s +# CORTEXM55: -march=thumbv8.1m.main+fp16+lob+mve.fp diff --git a/tests/multilib/armv8m.main.test b/tests/multilib/armv8m.main.test new file mode 100644 index 00000000..3da703e8 --- /dev/null +++ b/tests/multilib/armv8m.main.test @@ -0,0 +1,5 @@ +# RUN: %clang -print-multi-directory --target=armv8m.main-none-eabi -mfpu=none | FileCheck %s +# CHECK: arm-none-eabi/armv8m.main_soft_nofp + +# RUN: %clang -print-multi-directory --target=armv8m.main-none-eabihf | FileCheck --check-prefix=HARD %s +# HARD: arm-none-eabi/armv8m.main_hard_fp