Assembled the module ports, which no check had ever compiled - #672
Merged
fdesbiens merged 1 commit intoAug 28, 2026
Merged
Conversation
scripts/check_clang.sh globbed ports_module/*/gnu/src, which does not exist --
the module ports keep their assembly in module_manager/src. The [ -d ] guard
skipped it in silence, so 116 assembly files across nine Arm module ports were
assembled by no check, with either compiler, in the script whose own comments
state three times that "a port that is simply absent from the count reads as
covered". Stage 1 goes from 724 of 724 to 840 of 840; the feature-macro stage
had the same gap and goes from 412 files to 469.
Correcting the path exposed five defects, and only one of them was a build
failure. The other four assembled cleanly and did the wrong thing, because GAS
runs the C preprocessor on .S and not on .s:
ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.s, the only .s in a
directory of twenty-one .S, ignored all four of its own feature macros. It
wrote the caller's LR into the protection structure on every unprotect -- a
store guarded by TX_MPCORE_DEBUG_ENABLE -- sent an unconditional SEV, and
returned through both BX lr and MOV pc, lr. Its cortex_a5_smp and
cortex_a9_smp siblings are .S.
ports_module/cortex_m33/.../tx_thread_stack_build.s emitted both arms of an
#ifdef TX_SINGLE_MODE_SECURE, so the non-secure LR value overwrote the secure
one and the secure build got the wrong frame.
ports_module/cortex_m23/.../tx_thread_context_{save,restore}.S carried the
POP {r0, lr} that check_clang.sh's own comment describes as the reason the
feature-macro stage exists. The 16-bit Thumb POP takes r0-r7 and pc only.
The identical fix already sits in ports/cortex_m23/gnu/src; the module copy
never got it because nothing scanned it.
ports_module/cortex_m23/.../tx_thread_secure_stack_initialize.S used MOV
rather than MOVS for an 8-bit immediate, latent behind TX_SINGLE_MODE_SECURE.
Both siblings in the same directory already use MOVS.
ports_module/cortex_a7/gnu/module_manager/src is the one that failed to
assemble, on GCC 14.3 as well as on LLVM: #define SYS_MODE was never
expanded, so #SYS_MODE reached the assembler as an undefined symbol.
Twenty-nine .s files under gnu trees are renamed to .S. Every one of them is
already named .S by the build scripts that compile it, so this repairs those
scripts rather than churning them -- ports_module/cortex_a7's build_threadx.bat
names all eighteen with a capital S, and works today only on a case-insensitive
filesystem. Renaming rather than converting the #defines to GNU assignments is
what fixes the #ifdef blocks as well as the constants; the assignments would
have fixed two files and left twenty-seven silently ignoring their macros.
Files with no preprocessor directives are left as .s: they are not broken, and
check_ports.sh gains a check that keeps them that way. Only the gnu trees are
checked there -- the IAR, Arm Compiler 5 and Keil assemblers preprocess .s
themselves, and about three hundred files in this repository rely on that.
Verified with both toolchains on the same tree: 840 of 840 assembled by
ATfE 22.1.0 and by arm-gnu-toolchain 14.3.rel1, all five stages of
check_clang.sh green, and check_ports.sh green including the reproducibility
check. The new check was shown to fail by planting a copy of the file it was
written for.
No regression test accompanies this. The assembly it covers is executed by no
host test, and the check itself going from 724 files to 840 is the coverage
AGENTS.md asks for -- together with the new check_ports.sh section, which is
what stops the class recurring.
Assisted-by: Claude Code (Opus 5) <noreply@anthropic.com>
fdesbiens
added a commit
to prashit-vora/threadx
that referenced
this pull request
Aug 28, 2026
Two lines named assembly sources that eclipse-threadx#672 renamed. That change moved twenty-nine files under gnu trees from .s to .S, because GAS runs the C preprocessor on .S and not on .s: in a .s file every # line is a comment, so a #define is never substituted and an #if/#else pair emits both arms. Four files were silently doing the wrong thing as a result, including ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.s, which ignored all four of its own feature macros. These scripts had worked around the same defect with -x assembler-with-cpp rather than hitting it, which was correct when they were written. With the rename the flag is redundant and the lowercase names no longer resolve, so cortex_a5_smp/build_threadx.sh failed with "cc1: fatal error: tx_initialize_low_level.s: No such file or directory". The other seven references to those two files across these three scripts already named them with a capital S. Verified with the pinned Arm GNU 14.3.rel1 rather than the 13.2 that a distro package supplies: build_threadx.sh and build_threadx_sample.sh both succeed for a5, a7 and a9, all three link a sample_threadx.out, and scripts/check_gcc.sh passes end to end with its example stage reading 45 of 45, up from 42. Assisted-by: Claude Opus 5 <noreply@anthropic.com>
This was referenced Aug 28, 2026
fdesbiens
added a commit
that referenced
this pull request
Sep 9, 2026
…689) * Compiled the module manager C sources, which no check had ever built #672 corrected this script's assembly glob and brought the module ports into the count, but only their assembly. Their C stayed outside every check: 27 files of portable module manager under common_modules, plus the per-port code under ports_module/<core>/gnu/module_manager/src. By this script's own standard -- a port simply absent from the count reads as covered -- 293 files across nine Arm module ports were compiled by nothing, with either compiler. Each module port ships its own tx_port.h and txm_module_port.h carrying the control-block extensions the dispatch code needs, so a port is compiled against its own headers rather than the base port's. Two details the ports themselves dictate: An SMP port's control blocks come from common_smp. Pairing cortex_a35_smp with the single-core headers hid _tx_thread_smp_protect and _tx_thread_smp_unprotect behind implicit declarations and lost tx_thread_smp_core_executing from TX_THREAD, so fourteen files reported errors for a port that builds correctly. The TrustZone ports carry cmse_nonsecure_entry, which needs -mcmse to be honoured rather than ignored. tx_thread_secure_stack.c also carries GCC's optimize attribute, which clang does not implement; that divergence is suppressed by name, for a file GCC builds cleanly. All nine ports compile: 293 of 293. Verified that the stage fails as intended by injecting a defect into a throwaway worktree -- a defect in common_modules is reported under every port, one in a port's own source only under that port. Assisted-by: Claude Code (Opus 5) * Ran the module manager stage against the sources that reach it Three corrections to the new stage, all found by running it against dev rather than against the tree it was written on. The workflows did not trigger on common_modules. Both check_clang.yml and check_gcc.yml list ports_module but not common_modules, and the portable module manager under it is the larger half of what the stage compiles -- 28 of the 31 to 37 files each port builds, plus two include directories. A change there left the stage unrun, which is the same "absent from the count reads as covered" that the stage exists to close. Both lists gain common_modules, and they stay identical to each other as the comment in each asks. A deliberate deprecation notice read as a build failure. Since this PR was opened, txm_module_manager_absolute_load.c gained a #pragma message steering callers to the extended entry point. The stage treats any compiler output as a failure, so that one notice failed every port: nine failures on a tree where nothing is wrong. Pragma messages are now waived for the stage, because a notice to callers is not a defect in the file that carries it. That failure also printed nothing. Both C stages report by grepping the output for "error:", so a diagnostic that is not an error produced a bare FAIL line with no reason under it, and the only way to learn the reason was to reproduce the compile by hand. Both stages now fall back to showing what the compiler actually said. The TrustZone attribute waiver is narrowed to the one file that needs it. tx_thread_secure_stack.c carries GCC's optimize attribute, which clang does not implement; it is the only file among the 300-odd this stage compiles that does. Waiving the warning for the whole port would have swallowed a stray unknown attribute anywhere else in it. Verified with the same toolchain CI uses, ATfE 22.1.0: the full script passes, and every port compiles every file. cortex_a35 31/31 cortex_a35_smp 31/31 cortex_a7 34/34 cortex_m0+ 33/33 cortex_m23 37/37 cortex_m3 33/33 cortex_m33 37/37 cortex_m4 33/33 cortex_m7 33/33 The counts are each one higher than this PR first reported, because txm_module_manager_absolute_load_extended.c has landed since. The stage picked it up with no edit, which is what globbing the directories was for. Assisted-by: Claude Code (Opus 5) <noreply@anthropic.com> --------- Co-authored-by: r <r@r>
fdesbiens
added a commit
that referenced
this pull request
Sep 9, 2026
* ports: add Linux build scripts for Cortex-A5 SMP * ports: fix Cortex-A5 SMP sample linking on Linux * ports: add Linux build scripts for Cortex-A7 and A9 SMP * ports: fix Cortex-A7 SMP assembly source path * wip: add ATFE selection to Armv7 SMP scripts * ports: complete Armv7 SMP Linux toolchain support * ports: add local startup for Armv7 SMP samples * ports: add license headers to Armv7 SMP scripts * Dropped the preprocessing flag the file extension now carries Two lines named assembly sources that #672 renamed. That change moved twenty-nine files under gnu trees from .s to .S, because GAS runs the C preprocessor on .S and not on .s: in a .s file every # line is a comment, so a #define is never substituted and an #if/#else pair emits both arms. Four files were silently doing the wrong thing as a result, including ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.s, which ignored all four of its own feature macros. These scripts had worked around the same defect with -x assembler-with-cpp rather than hitting it, which was correct when they were written. With the rename the flag is redundant and the lowercase names no longer resolve, so cortex_a5_smp/build_threadx.sh failed with "cc1: fatal error: tx_initialize_low_level.s: No such file or directory". The other seven references to those two files across these three scripts already named them with a capital S. Verified with the pinned Arm GNU 14.3.rel1 rather than the 13.2 that a distro package supplies: build_threadx.sh and build_threadx_sample.sh both succeed for a5, a7 and a9, all three link a sample_threadx.out, and scripts/check_gcc.sh passes end to end with its example stage reading 45 of 45, up from 42. Assisted-by: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Frédéric Desbiens <frederic.desbiens@eclipse-foundation.org>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
scripts/check_clang.sh:214globbedports_module/*/gnu/src, which does not exist — the module ports keep their assembly inmodule_manager/src. The[ -d ]guard skipped it in silence, so 116 assembly files across nine Arm module ports were assembled by no check, with either compiler — in the script whose own comments state three times that "a port that is simply absent from the count reads as covered".The feature-macro stage had the same gap for the same reason.
gnuportWhat the corrected path exposed
Five defects. Only one of them was a build failure; the other four assembled cleanly and did the wrong thing, because GAS runs the C preprocessor on
.Sand not on.s. In a.sfile every#line is a comment, so a#defineconstant is never substituted, an#ifdefblock is assembled whatever the macro says, and an#if/#elsepair emits both branches.ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.s— the worst of the five, and it is not a module port at all. The only.sin a directory of twenty-one.S. It ignored all four of its own feature macros: wrote the caller's LR into the protection structure on every unprotect (a store guarded byTX_MPCORE_DEBUG_ENABLE), sent an unconditionalSEV, disabled FIQ whether or notTX_ENABLE_FIQ_SUPPORTwas set, and returned through bothBX lrandMOV pc, lr. Itscortex_a5_smpandcortex_a9_smpsiblings are.S.ports_module/cortex_m33/.../tx_thread_stack_build.s— emitted both arms of#ifdef TX_SINGLE_MODE_SECURE, so the non-secure LR value overwrote the secure one and a secure build got the wrong initial frame.ports_module/cortex_m23/.../tx_thread_context_{save,restore}.S— carried thePOP {r0, lr}thatcheck_clang.sh's ownFEATURE_MACROScomment cites as the reason that stage exists. The 16-bit ThumbPOPtakes r0–r7 and pc only. The identical fix, comment and all, already sits inports/cortex_m23/gnu/src; the module copy never got it because nothing scanned it.ports_module/cortex_m23/.../tx_thread_secure_stack_initialize.S—MOVrather thanMOVSfor an 8-bit immediate, latent behindTX_SINGLE_MODE_SECURE. Both siblings in the same directory already useMOVS. GCC quietly widened it to a 4-bytemovw; LLVM rejects it.ports_module/cortex_a7/gnu/module_manager/src— the one that actually failed to assemble, on GCC 14.3 as well as on LLVM:#define SYS_MODE 0x1Fwas never expanded, so#SYS_MODEreached the assembler as an undefined symbol. The Cortex-A7 GNU module manager has never assembled with the project's own default compiler.The fix, and why renaming rather than converting the
#definesTwenty-nine
.sfiles undergnutrees become.S.Every one of them is already named
.Sby the build scripts that compile it, so this repairs those scripts rather than churning them.ports_module/cortex_a7/gnu/example_build/build_threadx.batnames all eighteenmodule_manager/srcfiles with a capital S, and works today only on a case-insensitive filesystem.Converting the
#defines to GNU=assignments — the other candidate fix — would have made two files assemble and left twenty-seven silently ignoring their macros. The#ifdefblocks are the larger half of the defect and only the rename addresses them.Files carrying no preprocessor directives are left as
.s: they are not broken.check_ports.shgains a fourth check that keeps them that way, in the file whose header says each check exists because a real defect reached the repository through it. Only thegnutrees are checked — the IAR, Arm Compiler 5 and Keil assemblers preprocess.sthemselves, and around three hundred files here rely on that.Verification
Both toolchains, same tree:
check_clang.shwith ATfE 22.1.0: 840 of 840 assembled, 469 macro-guarded files, 185 of 185 C sources for each of nine cores, 42 of 42 script example builds, 5 of 5 CMake images. All five stages green.arm-gnu-toolchain 14.3.rel1(arm-none-eabiandaarch64-none-elf): 840 of 840.check_ports.shgreen including the reproducibility check, which is what proves none of the renamed files is generated fromports_arch/.Regression tests
None accompanies this, deliberately. The assembly it covers is executed by no host test. The check going from 724 files to 840 is the coverage
AGENTS.mdasks for, together with the newcheck_ports.shsection — which is what stops the class recurring rather than just this instance.Why now
scripts/check_gcc.shis next, and it mirrors this script stage for stage. Written against the old glob it would inherit the same hole; written against the corrected one it fails on the Cortex-A7 pair on its first run. Landing this first makes its stage 1 green by construction. PR #639 is also a Cortex-R52 module port — it lands inports_module/and, as things stood, would have been assembled by nothing at all.