Skip to content

xtensa: build: add support for build with upstream llvm clang with binutils backend#108765

Draft
lgirdwood wants to merge 10 commits into
zephyrproject-rtos:mainfrom
lgirdwood:clang-dev
Draft

xtensa: build: add support for build with upstream llvm clang with binutils backend#108765
lgirdwood wants to merge 10 commits into
zephyrproject-rtos:mainfrom
lgirdwood:clang-dev

Conversation

@lgirdwood
Copy link
Copy Markdown

Still very much early WIP that requires more testing and development but Zephyr and SOF now booting on qemu ACE 30 simulator and ztests passing. Will stay draft atm, but a heads up for any other xtensa users interested in llvm clang.

This PR does need more effort, but end result could be that Zephyr SDK only requires 1 xtensa compiler as clang can support different xtensa configs on the command line.

This work currently uses GNU binutils for assembly and linking as binutils is already fully ISA configured for each xtensa target based on the Cadence GPL overlay patches, i.e. its ready to go for testing a working front end. Subsequent work can help complete llvm linker/assembler support so that binutils no longer required.

This uses the LLVM patches here: llvm/llvm-project@main...lgirdwood:llvm-project:upstream/dev

@cgturner1 fyi - I will try and keep this ticking along, but its best effort atm.

@lgirdwood
Copy link
Copy Markdown
Author

SOF PR for anyone interested: thesofproject/sof#10759

lrgirdwo added 10 commits May 27, 2026 14:41
Binutils 2.39+ emits warnings for object files missing the
.note.GNU-stack section and for LOAD segments with RWX permissions.
When linking precompiled libgcc/compiler-rt objects (e.g.
_udivmoddi4.o) that were built without .note.GNU-stack, ld.bfd
prints a warning for every link.

Add --no-warn-execstack and --no-warn-rwx-segments to the baremetal
linker property so these are silenced without changing the underlying
permissions.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
-mno-global-merge is only recognised by Clang on ARM and ARM64.
On other architectures (e.g. Xtensa, RISC-V, x86) Clang emits

  warning: argument unused during compilation: '-mno-global-merge'

for every translation unit. Set the property to an empty string on
non-ARM targets so the flag is not passed.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Adds an LLVM toolchain configuration that drives Clang for Xtensa
cores while reusing the GNU assembler and linker shipped with the
Zephyr SDK.

cmake/toolchain/llvm/target.cmake selects the appropriate target
triple per ARCH (arm/arm64/x86/riscv/xtensa) and, for Xtensa,
configures:

  * the cross-compile prefix and -B paths so Clang can locate the
    SDK's GNU as / ld.bfd
  * include paths to the SDK's libgcc and target headers
  * compiler flags required for SOF/HiFi (-D__XCC__,
    -fno-integrated-as, -Wa,--text-section-literals, -Wa,--longcalls,
    -gdwarf-4)
  * a generated GCC specs file that strips picolibc.ld auto-inclusion
    (incompatible with Zephyr's MEMORY layout)
  * an LLEXT shared-library link wrapper

cmake/toolchain/llvm/generic.cmake honours LLVM_TOOLCHAIN_PATH and
unconditionally advertises picolibc/newlib support so Kconfig sees
TOOLCHAIN_HAS_PICOLIBC / TOOLCHAIN_HAS_NEWLIB during the early dts
phase, regardless of when ZEPHYR_SDK_INSTALL_DIR is resolved.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
When the LLVM toolchain compiles Xtensa code with Clang, link steps
must still be driven by the SDK's xtensa-*-gcc so the correct
multilib and linker scripts are picked up. If the toolchain layer
defines XTENSA_GCC, use it as the launcher in
CMAKE_{ASM,C,CXX}_LINK_EXECUTABLE instead of the default
<CMAKE_*_COMPILER>.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
soc_cpus_active and mp_resume_entry() are normally provided by the
SMP path. When CONFIG_SMP=n the symbols are still referenced by
power.c, causing link failures. Provide minimal CONFIG_SMP=n
definitions so single-CPU configurations link.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
The picolibc shipped in the Zephyr SDK is built with GCC. On Xtensa
windowed targets the va_list ABI used by Clang is not compatible
with the GCC-built __d_vfprintf, so calling picolibc's vfprintf with
a Clang-constructed va_list misformats arguments and can crash.

Disable the picolibc-specific cbvprintf path under __clang__ so
Zephyr falls back to its own cbvprintf_complete / cbvprintf_nano
implementation, compiled by the same compiler as the caller.
Picolibc is still used for headers and libm.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
The non-Espressif branch of XTENSA_CONFIG_HAL_INCLUDE_DIR pointed at
$ZEPHYR_XTENSA_MODULE_DIR/zephyr/soc/${CONFIG_SOC}, but the HAL
overlay headers actually live under the SoC's toolchain-name
subdirectory (e.g. intel_ace30_ptl_zephyr-elf), not the SOC kconfig
name. This works as long as the two strings match but breaks for
SoCs where CONFIG_SOC and CONFIG_SOC_TOOLCHAIN_NAME differ, such as
intel_ace30_ptl (CONFIG_SOC=ace30_ptl, toolchain name
intel_ace30_ptl_zephyr-elf), causing the LLVM toolchain build to
miss "defs.h" and friends.

Switch to CONFIG_SOC_TOOLCHAIN_NAME so the include path tracks the
SDK directory layout regardless of the SoC kconfig name.
Update the default XTENSA_CORE_ID from intel_ace30_ptl to
intel_ace30_adsp to match the standardized vendor_id_adsp naming
convention used by the upstream LLVM Xtensa backend.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
CAVS-generation Intel ADSP SOC config headers (TGL/ICL/CNL/APL) carry
an '#if !defined __XCC__' guard that rejects the proprietary XCC
compiler.  We define -D__XCC__ so SOF audio headers (format.h, fft.h,
etc.) enter their '#ifdef __XCC__' HiFi feature-detection branches, but
that inadvertently triggers the rejection guard.

Add -D__XCC_CLANG__ alongside -D__XCC__.  The hal/xtensa SOC headers
for CAVS targets are widened to '#if !defined __XCC__ || defined(__XCC_CLANG__)'
so LLVM Clang is allowed through.

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Clang (and GCC with -fcf-protection) emits .note.GNU-stack sections in
object files to signal stack executability requirements.  The ACE
linker script (ace-link-mirrored.ld) already discards these via a
/DISCARD/ entry, but the CAVS counterpart (xtensa-cavs-linker.ld) did
not, causing ld.bfd to emit:

  warning: orphan section '.note.GNU-stack' from '...' being placed
  in section '.note.GNU-stack'

Add the matching /DISCARD/ entry to silence the warning on CAVS 1.5/2.5
targets (e.g. intel_adsp/cavs25, Tiger Lake).

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
@sonarqubecloud
Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants