Skip to content

wip: build: add support for llvm clang#10759

Draft
lgirdwood wants to merge 9 commits into
thesofproject:mainfrom
lgirdwood:clang-upstream
Draft

wip: build: add support for llvm clang#10759
lgirdwood wants to merge 9 commits into
thesofproject:mainfrom
lgirdwood:clang-upstream

Conversation

@lgirdwood
Copy link
Copy Markdown
Member

Just a heads up for anyone interested in llvm clang support to build SOF xtensa targets. Its still very early WIP with lots of work still to do but end result should be a single xtensa clang compiler for all SOF targets for CI, twister etc. Opens door to other non C based languages long term.

Needs zephyrproject-rtos/zephyr#108765

and

llvm/llvm-project@main...lgirdwood:llvm-project:upstream/dev

lrgirdwo added 7 commits May 8, 2026 14:20
Add --llvm-clang LLVM_BUILD_DIR flag to xtensa-build-zephyr.py for
building SOF with a custom LLVM/Clang toolchain instead of xt-clang
or Zephyr SDK GCC.

When specified, the script:
- Auto-generates a platform-specific clang wrapper script that:
  - Filters GCC-only flags (-fno-reorder-functions, -fno-defer-pop,
    --param=*, -fstrict-overflow)
  - Translates -mlongcalls to -mlong-calls
  - Adds --target for the Xtensa SoC triple
  - Adds -fno-integrated-as (GCC external assembler)
  - Adds -B paths for GCC assembler/linker from Zephyr SDK
  - Adds -I path for SoC-specific core-isa.h
- Forces ZEPHYR_TOOLCHAIN_VARIANT=zephyr for GCC assembler/linker
- Overrides CMAKE_C_COMPILER and CMAKE_ASM_COMPILER

Usage:
  scripts/xtensa-build-zephyr.py --llvm-clang ~/llvm-project/build ptl

Signed-off-by: Liam Girdwood <liam.r.girdwood@linux.intel.com>
Switch from ZEPHYR_TOOLCHAIN_VARIANT=zephyr with wrapper script overrides
to ZEPHYR_TOOLCHAIN_VARIANT=llvm which has native Xtensa Clang support.

The llvm variant (cmake/toolchain/llvm/target.cmake) handles:
- Compiler detection via LLVM_TOOLCHAIN_PATH
- GCC assembler/linker integration via CROSS_COMPILE
- Correct -B paths for assembler and linker discovery
- LLEXT shared library link wrapper

This eliminates the need for the wrapper script and symlink dance
that was required with the zephyr variant to override find_program().

Signed-off-by: Liam Girdwood <liam.r.girdwood@intel.com>
- llext_link_helper.py: Treat .rodata as readonly even when marked
  writable by the Clang/objcopy LLEXT pipeline, and place readonly
  sections BEFORE .text so Xtensa l32r instructions (which can only
  reach backwards up to 256KB) can access .rodata literals.
- zephyr/CMakeLists.txt: Make -mtext-section-literals conditional via
  check_c_compiler_flag (Clang doesn't support it), and force the
  Zephyr SDK GCC linker for the LLEXT shared library link step.

Signed-off-by: Liam Girdwood <liam.r.girdwood@intel.com>
Disable the Intel UAOL DAI driver/usage when building with Clang to
work around build failures. UAOL is gated off in the board Kconfig
default and the corresponding DAI dispatch arms are stubbed out with
'#if 0' until a proper Clang-compatible fix lands.

Signed-off-by: Liam Girdwood <liam.r.girdwood@intel.com>
The LOG_CORE_ID_PREFIX default produces logging output paths that
trigger Clang build issues. Disable the board-level default until a
proper fix is in place.

Signed-off-by: Liam Girdwood <liam.r.girdwood@intel.com>
Add intel_adsp_ace30_ptl_llvm_qemu.conf overlay config for single-core
LLVM QEMU testing. Applied on top of the base intel_adsp_ace30_ptl.conf
via -DEXTRA_CONF_FILE=.

Key overrides:
- CONFIG_CORE_COUNT=1, CONFIG_SMP=n: avoids SMP sync hang in QEMU
- CONFIG_LLEXT=n: missing TIE headers (xt_FP.h) in LLVM
- CONFIG_FORMAT_CONVERT_HIFI3=n: same TIE dependency
- CONFIG_USERSPACE=n, CONFIG_PM=n: reduces single-core init complexity
- CONFIG_LOG_MODE_DEFERRED=y: avoids z_cbvprintf_impl crash path

Signed-off-by: Liam Girdwood <liam.r.girdwood@intel.com>
@lgirdwood lgirdwood changed the title wip: buiild: add support for llvm clang wip: build: add support for llvm clang May 8, 2026
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This script was far too long from the beginning. I wonder if it would be possible to move some of the things it's doing directly to west. Perfect solution would be setting some environments and calling west in workflow.
Soon it will be a wrapper on west having over 2K lines of code. My local script has 250 with comments :)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the script has a lot of convenience - 2k lines is not a problem, especially today.

@hliao8
Copy link
Copy Markdown

hliao8 commented May 15, 2026

@lgirdwood I take your patches and can build LLVM. I also build SOF with it and it looks OK. I run in qemu and see lots of code being run to idle. I think this looks OK but not expert on SOF. I am working on some LLVM updates for fun that I will send. Thank you.

@hliao8
Copy link
Copy Markdown

hliao8 commented May 20, 2026

@lgirdwood I made 2 PRs last night for HIFI and FLIX , please check lgirdwood/llvm-project#1
and lgirdwood#1 Thank you.

@lgirdwood
Copy link
Copy Markdown
Member Author

@lgirdwood I made 2 PRs last night for HIFI and FLIX , please check lgirdwood/llvm-project#1 and lgirdwood#1 Thank you.

@hliao8 PRs look OK, let me try on my devices and qemu and get back to you.

hliao8 added 2 commits May 20, 2026 16:16
Zephyr's FindZephyr-sdk.cmake intentionally skips auto-discovery
when ZEPHYR_TOOLCHAIN_VARIANT=llvm, expecting the user to point
ZEPHYR_SDK_INSTALL_DIR at the SDK that provides the GNU Xtensa
binutils / sysroot the LLVM clang driver wraps around.

When neither the user nor the environment supplies that variable
the build fails late with confusing 'string.h: file not found' /
malformed -isystem errors. Auto-detect a zephyr-sdk-* directory
under $HOME, /opt, or /usr/local (highest version wins) and export
ZEPHYR_SDK_INSTALL_DIR before invoking west when the user passes
--llvm-clang.

This keeps the LLVM build flow as one command for the common case
while still respecting any value the user has already exported.

Signed-off-by: Henry Liao <hliao8@proton.me>
The HiFi3 / HiFi4 / HiFi5 sources unconditionally include
<xtensa/config/defs.h>, a header that ships only with the Cadence
xt-clang / xt-gcc toolchains. The LLVM clang toolchain variant uses
the Zephyr SDK GNU Xtensa binutils for assembly/linking but does
not expose that Cadence-internal header, so every HiFi
translation unit fails to find it even though the body of the file
is guarded by SOF_USE_HIFI(...) and is unreachable for the LLVM
build.

Wrap the include in __has_include so the compiler silently skips
it on toolchains that lack the header. The HiFi intrinsics are
already supplied by <xtensa/tie/xt_hifiN.h>, which the LLVM
toolchain does provide.

No functional change for the Cadence toolchain path.

Signed-off-by: Henry Liao <hliao8@proton.me>
@lgirdwood
Copy link
Copy Markdown
Member Author

@lgirdwood I made 2 PRs last night for HIFI and FLIX , please check lgirdwood/llvm-project#1 and lgirdwood#1 Thank you.

@hliao8 PRs look OK, let me try on my devices and qemu and get back to you.

Ok, merged, can build and boot FW, load topologies but something wrong at trigger(). Its definitely in the right direction. I'll take a look at trigger when time permits.

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.

4 participants