mirror of
https://github.com/eclipse-threadx/threadx.git
synced 2026-10-06 06:59:08 +08:00
The gnu ports are only ever built with GNU tooling, and GNU as accepts several non-canonical forms that LLVM's assembler rejects. Nothing noticed, because nothing built them with anything else. This matters beyond clang itself: Arm Toolchain for Embedded is LLVM based and is the successor to Arm Compiler 6, so these are the code paths ac6 users move onto. Seven files needed changing, none of which alters the emitted code: LDREX and STREX take no offset in A32 state; the #imm form is Thumb-2 only. GNU as drops the redundant zero, LLVM rejects it. Removed from the Cortex-A5, A7 and A9 SMP protect routines. ARMv8-M Baseline has no flag-preserving MOV immediate, so GNU as already emits MOVS. Writing MOVS in the two Cortex-M23 sources says what the assembler was doing anyway. One of them sits in a branch only compiled for the single mode secure configurations, which is why it had never surfaced. The Cortex-M0 schedule routine wrote LDR r0, =#0x10000000 with a stray hash, which its own sibling file already wrote correctly. The Cortex-M0 system return routine selected the numbered subsection .text 32, which makes LLVM place the constant pool beyond the range a Thumb-1 PC relative load can reach. Plain .text fixes it and GNU accepts either form. The reason is recorded in the file, since 32 files pair a numbered subsection with a literal pool load and the rest only escape because Thumb-2 and A32 have far more range. Add scripts/check_clang.sh, which assembles every Arm gnu port source and compiles the common C sources for one core per architecture profile, and a clang_check workflow that installs Arm Toolchain for Embedded and runs it. The toolchain version is pinned and checksum verified, for the same reason the runner image is pinned. The port directory to target mapping in that script is explicit rather than prefix matched. Prefix matching is what makes cortex_a5 also match cortex_a53 and cortex_a55, which are AArch64, and assembling those as ARM32 produces hundreds of misleading errors; that mistake cost real time while measuring this, so the reason is recorded next to the table. Verified with Arm Toolchain for Embedded 22.1.0: 711 of 711 assembly sources assemble and 185 of 185 C sources compile for all eight profiles, against 6 assembly failures before the change. arm-none-eabi-gcc still assembles all 315 ARM32 sources, so nothing regressed for GNU. The check was confirmed to fail when any one of the fixes is reverted. Assisted-by: Claude Code (Opus 5) <noreply@anthropic.com>
206 lines
7.6 KiB
Bash
Executable File
206 lines
7.6 KiB
Bash
Executable File
#!/bin/bash
|
|
##############################################################################
|
|
# Copyright (C) 2026 Eclipse ThreadX contributors
|
|
#
|
|
# This program and the accompanying materials are made available under the
|
|
# terms of the MIT License which is available at
|
|
# https://opensource.org/licenses/MIT.
|
|
#
|
|
# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5).
|
|
# The AI-generated portions may be considered public domain (CC0-1.0)
|
|
# and not subject to the project's licence. The human contributor has
|
|
# reviewed and verified that the code is correct.
|
|
#
|
|
# SPDX-License-Identifier: MIT and CC0-1.0
|
|
##############################################################################
|
|
|
|
# Builds the Arm ports with an LLVM based toolchain: every assembly source of
|
|
# every Arm gnu port, and the common C sources for one core per architecture
|
|
# profile. Compilation only, no linking, so no target C library is required
|
|
# beyond whatever the toolchain ships.
|
|
#
|
|
# scripts/check_clang.sh # clang from PATH
|
|
# scripts/check_clang.sh --clang /path/to/clang
|
|
# CLANG=/path/to/clang scripts/check_clang.sh
|
|
#
|
|
# Options:
|
|
# --clang <path> Compiler to use; defaults to $CLANG then to clang.
|
|
# --asm-only Skip the C sources.
|
|
# --quiet Print only failures and the summary.
|
|
#
|
|
# Exit status is 0 when everything builds and 1 otherwise.
|
|
#
|
|
# Why this exists: the gnu ports are only ever built with GNU tooling, and GNU
|
|
# as accepts several non-canonical forms that LLVM's assembler rejects. Those
|
|
# forms accumulated unnoticed. This check also covers Arm Toolchain for
|
|
# Embedded, which is LLVM based and is the successor to Arm Compiler 6, so the
|
|
# ac6 code paths are exercised here as well.
|
|
#
|
|
# Arm Toolchain for Embedded releases:
|
|
# https://github.com/arm/arm-toolchain/releases
|
|
|
|
set -u
|
|
|
|
cd "$(dirname "$(realpath "$0")")/.."
|
|
|
|
CC="${CLANG:-clang}"
|
|
asm_only=0
|
|
quiet=0
|
|
|
|
while [ "$#" -gt 0 ]; do
|
|
case "$1" in
|
|
--clang) [ "$#" -ge 2 ] || { echo "Error: --clang needs a path" >&2; exit 2; }; CC="$2"; shift 2 ;;
|
|
--asm-only) asm_only=1; shift ;;
|
|
--quiet) quiet=1; shift ;;
|
|
-h|--help) sed -n '17,33p' "$0"; exit 0 ;;
|
|
*) echo "Error: unknown option '$1'" >&2; exit 2 ;;
|
|
esac
|
|
done
|
|
|
|
say() { [ "$quiet" -eq 1 ] || echo "$@"; }
|
|
fail() { echo " FAIL: $*"; }
|
|
|
|
if ! command -v "$CC" >/dev/null 2>&1 && [ ! -x "$CC" ]; then
|
|
echo "Error: compiler '$CC' not found."
|
|
echo "Pass --clang <path>, set CLANG, or install Arm Toolchain for Embedded:"
|
|
echo " https://github.com/arm/arm-toolchain/releases"
|
|
exit 1
|
|
fi
|
|
|
|
say ""
|
|
say "Using: $("$CC" --version | head -1)"
|
|
|
|
# Each port directory is mapped explicitly to a target triple and CPU. Do not
|
|
# replace this with prefix matching: cortex_a5* also matches cortex_a53 and
|
|
# cortex_a55, which are AArch64, and assembling those as ARM32 produces a flood
|
|
# of misleading errors.
|
|
declare -A PORT_TARGET=(
|
|
[cortex_m0]="arm-none-eabi cortex-m0 -mthumb"
|
|
[cortex_m0+]="arm-none-eabi cortex-m0plus -mthumb"
|
|
[cortex_m3]="arm-none-eabi cortex-m3 -mthumb"
|
|
[cortex_m4]="arm-none-eabi cortex-m4 -mthumb"
|
|
[cortex_m7]="arm-none-eabi cortex-m7 -mthumb"
|
|
[cortex_m23]="arm-none-eabi cortex-m23 -mthumb"
|
|
[cortex_m33]="arm-none-eabi cortex-m33 -mthumb"
|
|
[cortex_m55]="arm-none-eabi cortex-m55 -mthumb -mfloat-abi=hard"
|
|
[cortex_m85]="arm-none-eabi cortex-m85 -mthumb -mfloat-abi=hard"
|
|
[cortex_a5]="arm-none-eabi cortex-a5"
|
|
[cortex_a7]="arm-none-eabi cortex-a7"
|
|
[cortex_a8]="arm-none-eabi cortex-a8"
|
|
[cortex_a9]="arm-none-eabi cortex-a9"
|
|
[cortex_a12]="arm-none-eabi cortex-a12"
|
|
[cortex_a15]="arm-none-eabi cortex-a15"
|
|
[cortex_a17]="arm-none-eabi cortex-a17"
|
|
[cortex_a5_smp]="arm-none-eabi cortex-a5"
|
|
[cortex_a7_smp]="arm-none-eabi cortex-a7"
|
|
[cortex_a9_smp]="arm-none-eabi cortex-a9"
|
|
[cortex_r4]="arm-none-eabi cortex-r4"
|
|
[cortex_r5]="arm-none-eabi cortex-r5"
|
|
[cortex_r52]="arm-none-eabi cortex-r52"
|
|
[cortex_a34]="aarch64-none-elf cortex-a34"
|
|
[cortex_a35]="aarch64-none-elf cortex-a35"
|
|
[cortex_a53]="aarch64-none-elf cortex-a53"
|
|
[cortex_a55]="aarch64-none-elf cortex-a55"
|
|
[cortex_a57]="aarch64-none-elf cortex-a57"
|
|
[cortex_a65]="aarch64-none-elf cortex-a65"
|
|
[cortex_a65ae]="aarch64-none-elf cortex-a65ae"
|
|
[cortex_a72]="aarch64-none-elf cortex-a72"
|
|
[cortex_a73]="aarch64-none-elf cortex-a73"
|
|
[cortex_a75]="aarch64-none-elf cortex-a75"
|
|
[cortex_a76]="aarch64-none-elf cortex-a76"
|
|
[cortex_a76ae]="aarch64-none-elf cortex-a76ae"
|
|
[cortex_a77]="aarch64-none-elf cortex-a77"
|
|
[cortex_a34_smp]="aarch64-none-elf cortex-a34"
|
|
[cortex_a35_smp]="aarch64-none-elf cortex-a35"
|
|
[cortex_a53_smp]="aarch64-none-elf cortex-a53"
|
|
[cortex_a55_smp]="aarch64-none-elf cortex-a55"
|
|
[cortex_a57_smp]="aarch64-none-elf cortex-a57"
|
|
[cortex_a65_smp]="aarch64-none-elf cortex-a65"
|
|
[cortex_a65ae_smp]="aarch64-none-elf cortex-a65ae"
|
|
[cortex_a72_smp]="aarch64-none-elf cortex-a72"
|
|
[cortex_a73_smp]="aarch64-none-elf cortex-a73"
|
|
[cortex_a75_smp]="aarch64-none-elf cortex-a75"
|
|
[cortex_a76_smp]="aarch64-none-elf cortex-a76"
|
|
[cortex_a76ae_smp]="aarch64-none-elf cortex-a76ae"
|
|
[cortex_a77_smp]="aarch64-none-elf cortex-a77"
|
|
[cortex_a78_smp]="aarch64-none-elf cortex-a78"
|
|
)
|
|
|
|
# One core per architecture profile for the C sources. Compiling all of them
|
|
# for every core would multiply the run time without adding coverage, since the
|
|
# port headers differ by profile rather than by core.
|
|
C_CORES="cortex_m0 cortex_m4 cortex_m23 cortex_m33 cortex_m55 cortex_a7 cortex_a53 cortex_r5"
|
|
|
|
failures=0
|
|
skipped=""
|
|
|
|
# --------------------------------------------------------------------------
|
|
say ""
|
|
say "== Assembly sources of every Arm gnu port =="
|
|
|
|
total=0
|
|
for dir in ports/*/gnu/src ports_smp/*/gnu/src ports_module/*/gnu/src; do
|
|
[ -d "$dir" ] || continue
|
|
core="$(echo "$dir" | cut -d/ -f2)"
|
|
spec="${PORT_TARGET[$core]:-}"
|
|
if [ -z "$spec" ]; then
|
|
skipped="$skipped $core"
|
|
continue
|
|
fi
|
|
# shellcheck disable=SC2086
|
|
set -- $spec
|
|
target="$1"; cpu="$2"; shift 2; extra="$*"
|
|
|
|
for src in "$dir"/*.S "$dir"/*.s; do
|
|
[ -f "$src" ] || continue
|
|
total=$((total + 1))
|
|
output="$("$CC" --target="$target" -mcpu="$cpu" $extra -c "$src" -o /dev/null 2>&1)"
|
|
if [ -n "$output" ]; then
|
|
fail "$src"
|
|
echo "$output" | sed 's/^/ /'
|
|
failures=$((failures + 1))
|
|
fi
|
|
done
|
|
done
|
|
say " $((total - failures)) of $total assembled"
|
|
if [ -n "$skipped" ]; then
|
|
say " not Arm, skipped:$(echo $skipped | tr ' ' '\n' | sort -u | tr '\n' ' ')"
|
|
fi
|
|
|
|
# --------------------------------------------------------------------------
|
|
if [ "$asm_only" -eq 0 ]; then
|
|
say ""
|
|
say "== Common C sources, one core per architecture profile =="
|
|
|
|
for core in $C_CORES; do
|
|
spec="${PORT_TARGET[$core]:-}"
|
|
[ -n "$spec" ] || continue
|
|
# shellcheck disable=SC2086
|
|
set -- $spec
|
|
target="$1"; cpu="$2"; shift 2; extra="$*"
|
|
|
|
count=0; bad=0
|
|
for src in common/src/*.c; do
|
|
count=$((count + 1))
|
|
output="$("$CC" --target="$target" -mcpu="$cpu" $extra \
|
|
-Iports/"$core"/gnu/inc -Icommon/inc -c "$src" -o /dev/null 2>&1)"
|
|
if [ -n "$output" ]; then
|
|
fail "$core: $src"
|
|
echo "$output" | grep "error:" | head -3 | sed 's/^/ /'
|
|
bad=$((bad + 1)); failures=$((failures + 1))
|
|
fi
|
|
done
|
|
say " $core: $((count - bad)) of $count compiled"
|
|
done
|
|
fi
|
|
|
|
# --------------------------------------------------------------------------
|
|
say ""
|
|
if [ "$failures" -eq 0 ]; then
|
|
say "All LLVM toolchain checks passed."
|
|
exit 0
|
|
fi
|
|
|
|
echo "$failures LLVM toolchain check(s) failed."
|
|
exit 1
|