09 - EmbCC Toolchain Profile¶
Status: Compiler capability review refreshed against EmbLinkOs/EmbCC at a3c3ef4c81f9de977b8741ed16072cadca921788, 2026-10-14, superseding the 387eb23 snapshot. The ten-item review names current manuals, implementation/regression evidence and scoped local checks, and separates them from upstream-reported RTOS experiments. The consequence lines remain RTOS design rules unless explicitly amended; a compiler improvement does not silently relax them. Current EmbCC RTOS integration is incomplete and is not a configured CI leg.
1. What EmbCC is¶
EmbCC is a C and C++ compiler written in C99 with its own preprocessor, per-target assemblers, linker (embld), archiver (embar), SVD tool (embsvd), debugger (embdbg) and additional firmware tools. It targets embedded systems and hosted/bare-metal operating-system programs; one compiler handles each supported target. Runtime, C-library and supported C++ runtime builds exist upstream, including a separate AVR library. They must be built/installed for the selected target; their availability does not introduce a libc dependency into the RTOS kernel. (README.md, docs/manual/targets.md, docs/manual/getting-started.md)
2. Targets that matter to EmbLinkRTOS¶
Family |
Triples |
Notes for the RTOS |
|---|---|---|
Cortex-M, Armv6-M |
|
Thumb-1 lowering; divide, 64-bit multiply, and atomics are |
Cortex-M, Armv7-M |
|
Reference port target |
Cortex-M, Armv7E-M |
|
Hard-float objects do not link with soft-float ones; one |
Cortex-M, Armv8-M Mainline/Baseline |
|
Stack-limit assembly and M23 selection are implemented. Secure-side |
RISC-V |
|
ISA/ABI options include F/D and hard-float runtimes upstream; the current RTOS port uses its own RV32IMAC scope. Consult |
AVR |
|
|
MIPS32 |
|
A candidate fifth architecture port; not planned |
Hosts |
|
C++ supported on x86-64 and AArch64 only |
The RTOS reference targets above are little-endian; EmbCC also has other, including big-endian, targets outside this scope. C++ is implemented on Cortex-M/32-bit ARM and RV32 with -fno-exceptions; AVR C++ remains refused. Use current docs/manual/targets.md and docs/manual/cxx.md, plus regression fixtures, rather than older contradictory C-only rows in docs/internals/status.md.
Consequence. EmbCC supplies compiler targets for the reference architecture families. Each RTOS compiler/port combination still needs its own storage, linking, ABI and executed conformance evidence. GCC/Clang remain the active matrix; a target’s existence does not establish an EmbCC CI job or qualify a port.
3. Language level¶
One dialect: C17 plus GNU extensions plus part of C23;
-std=is accepted and ignored,__STDC_VERSION__is201710L._Static_assert,_Generic,_Noreturnsupported;_Alignaspartial;_Atomicfor integer and pointer types only;<stdatomic.h>and__atomic_*/__sync_*builtins provided. (docs/manual/c-language.md)_Thread_localand__threadcompile to one shared instance on every embedded target, without an error. (docs/internals/status.md§Thread-local storage)__STDC_HOSTED__is 1 even with-ffreestanding. Empty parameter list()always means no parameters. A non-void function that can reach its closing brace is an error. Block-scope tags and typedefs stay visible to the end of the translation unit. (docs/manual/c-language.md)
Consequences.
The C11 minimum of ADR-023 is enforced by the GCC and Clang legs of the matrix with
-std=c11 -pedantic; EmbCC cannot enforce it.The kernel and every port never use
_Thread_localor__thread. Per-thread data is kernel TLS slots only (KRN-THR-013, KRN-THR-014). A static-analysis rule bans the keywords tree-wide.The kernel does not test
__STDC_HOSTED__.
4. Attributes and builtins¶
Supported where the RTOS needs them: naked (Cortex-M, RISC-V, MIPS32, AVR), interrupt (Cortex-M: accepted, no code change; AVR: implemented; RISC-V: refused), signal (AVR), section (static storage), used, weak, alias (functions), aligned (including typedefs and supported over-aligned locals), packed, constructor (including priorities), noreturn, always_inline, pcs. Provided builtins include __builtin_memcpy/memset/memmove/memcmp, __builtin_trap, __builtin_expect, the atomics, __builtin_sqrt, __builtin_fabs. (docs/manual/extensions.md)
Some extensions remain refused, including cleanup, weakref and ifunc; consult current docs/manual/extensions.md for exact attribute/builtin diagnostics. Automatic storage cannot have a linker section. The old refusal of constructor priorities and typedef alignment is no longer a compiler limitation.
Consequences.
Device and subsystem initialization order remains a generated table (DRV-001), never constructor priorities, although the compiler now implements them.
No scope-guard macros built on
cleanup.Alignment remains on object declarations and struct definitions, never typedefs, as the RTOS portability policy. EmbCC now supports typedef alignment; the storage-member alignment correction of M1 remains necessary independently of that earlier compiler restriction.
Register-file-wide bit operations use the
emb_arch_layer (clz,ctz,popcount) with compiler-portability fallbacks; the exact__builtin_clzfamily availability is verified by a probe at configure time.
5. Inline assembly and naked functions¶
Inline asm is assembled by EmbCC’s own assembler per target with a fixed instruction vocabulary (documented per target). Labels are not accepted inside inline asm; branch targets are
.+N. Onlyr/m/i-style constraints; callee-saved registers may not be named or clobbered in a template (r4-r11 on Cortex-M, s0-s11 on RISC-V, r2-r17 and Y on AVR). An asm output wider than a register is refused.Cortex-M vocabulary includes
mrs/msron the kernel registers and Armv8-M stack limits; barriers, masking, sleep, context-save and FPU sequences; and nowldrd/strd,clrexand byte/halfword exclusives on applicable cores. Core-specific restrictions still apply; usedocs/manual/inline-asm.mdand the encoding/RTOS goldens before relying on another instruction.RISC-V vocabulary covers CSR access by name or number,
mret/sret/wfi/ecall/fence, loads, stores, ALU, branches. Missing in inline asm:lr/sc/amo*(the compiler emits them for C atomics),la/call/tailpseudo-instructions, floating point..Sfiles use the same assembler and do acceptcall.AVR vocabulary is the whole AVR5 set, including
in/out,cli/sei,push/pop,reti,sleep,wdr,lpm.A
nakedfunction body is assembled as a file-scope block: it may hold labels, literal pools, and zero-argument calls into C; it may not hold other statements or asm outputs. FreeRTOS’s Cortex-M3, M4F, M7, M33 non-secure, and RISC-V ports compile unmodified and run on QEMU. (docs/manual/inline-asm.md,docs/manual/embedded.md§An RTOS kernel)
Consequences.
The architecture-port contract (02 §2) is implementable on all three EmbCC embedded families in C plus inline asm, with the context switch and first-thread launch as
nakedfunctions and the RISC-V trap entry as a.Sfile.Every critical-section primitive is
static inline __attribute__((always_inline))with a"memory"clobber (the inliner otherwise declines functions containing inline asm).Kernel atomics are C11 atomics through the portability layer, never hand-written
lr/scorldrex/strextemplates, so one source serves EmbCC, GCC, and Clang.No labels in inline asm: any multi-block assembly sequence lives in a
.Sfile or anakedfunction.
6. Atomics and width limits¶
Target |
Atomic load/store |
Atomic read-modify-write |
|---|---|---|
Cortex-M Armv7-M, Armv8-M |
1 to 4 bytes |
1 to 4 bytes inline ( |
Cortex-M Armv6-M |
1 to 4 bytes |
1 to 4 bytes via |
RV32 |
1 to 4 bytes |
1, 2 and 4 bytes; subword RMW operates on the aligned containing word |
RV64 |
1 to 8 bytes |
1, 2, 4 and 8 bytes |
AVR |
1 to 8 bytes, masking as needed |
1 to 8 bytes inline with saved/restored SREG masking; not lock-free |
Eight-byte atomics on 32-bit targets now call sized __atomic_*_8 runtime helpers. The default weak helpers mask privileged local interrupts: they are not a multicore/DMA or unprivileged atomicity solution. AVR’s wide operations are inline masking sequences. Computed goto is now implemented upstream; the kernel prohibition remains policy. __int128 still does not exist on 32-bit targets. (docs/manual/targets.md, docs/manual/embedded.md, docs/manual/extensions.md)
Consequences.
64-bit kernel time remains read/written under a critical section or a sequence lock, never as an atomic 64-bit object (KRN-TIM-016); helper availability does not change this protocol.
Kernel atomic state is word-sized. Flags packed into bytes are manipulated as words or under a critical section.
The tiny profile’s atomics are interrupt masking by definition; the portability layer makes that explicit rather than relying on compiler fallbacks.
No computed-goto dispatch anywhere in the kernel.
7. Linking, sections, and images¶
embldlinks ARM, RV32, RV64, MIPS32, AVR, and x86-64 objects; AArch64 needs an external linker. Static links only, no PLT,ET_EXEC, W^X segments.Without a script:
-Ttext,-Tdata,-Tstack(RISC-V entry stub),--rom-limit,-e,--gc-sections,-Map,--print-memory-usage;.vectors/.isr_vectorplaced first; orphan sections bracketed by__start_NAME/__stop_NAMEor__NAME_start/__NAME_end.GNU ld linker scripts (
-T) now include AVR support. The supported subset includesMEMORY,SECTIONS,KEEP,PROVIDE,ALIGN,AT>,(NOLOAD),/DISCARD/,ASSERT,INCLUDE,REGION_ALIAS,EXTERN, sorting, fill and expression functions. AVR scripts must respect the separate program/data address spaces.PHDRS,OVERLAYandINSERTremain refused; check the current linker manual for the exact subset.-ffunction-sections,-fdata-sections,--gc-sections,-fstack-usage(GCC-format.sufiles) andembcc inspect callgraphare available. LTO, PIC and stack-protector assumptions remain excluded from RTOS builds.-fshort-enumsis now available for C but remains prohibited by the RTOS ABI policy.-fsanitize=undefinedtraps in place.-Osexists;-O0code may not fit the ATmega328P. DWARF 4 now includes AVR functions/globals/lines, but no AVR.debug_frame; optimized debug builds can grow substantially. (docs/manual/tools/embld.md,docs/manual/targets.md,docs/manual/invoking.md)
Consequences.
HW-006 still targets a GNU ld script plus an AVR compatibility
embldoption set (-Ttext/-Tdata/--rom-limit) from the same region model. Current EmbCC can consume the AVR script, so the option set is a retained design/compatibility target, not a missing-linker-script workaround. The generator remains planned; removing the second output requires a separate reviewed amendment.Kernel registries (device tables, trace points, log sites, partition tables) are orphan or named sections bracketed by linker symbols; this works identically under
embldand GNU ld.Deferred-format logging (ADR-009) targets strings as symbols whose address is the identifier, placed in a
NOLOADdummy region. AVR linker scripts are now available; the tiny plain-text backend remains a footprint/design choice, not proof that deferred logging has been implemented or qualified on AVR.Stack sizing methodology (KRN-MEM-009) uses
-fstack-usageplus the call graph on all three compilers.Footprint claims are made at
-Osand-O2;-O0is a debug configuration only.Reproducible builds (BLD-004) are helped by EmbCC:
-grecords no directory, and output is deterministic by design.
8. Startup, vectors, and interrupts per target¶
Target |
Startup |
Vector table |
Handlers |
|---|---|---|---|
Cortex-M |
C |
|
Ordinary C functions (hardware saves the caller-saved set); |
RISC-V |
C |
|
Trap entry in |
AVR |
|
26 |
|
(docs/manual/embedded.md)
Consequence. The architecture-port contract documents the startup form per target as above; SoC startup on Cortex-M stays in C.
9. Tools around the compiler¶
Tool |
What it is |
Use in EmbLinkRTOS |
|---|---|---|
|
The linker (see §7) |
Reference linker for EmbCC builds |
|
DWARF 4 reader, symbolizer, crash analyzer, TUI and GDB remote client, now including AVR register layout |
AVR tool support is available; RTOS-awareness via the planned debug descriptor and full target sessions still need their own evidence |
|
CMSIS-SVD reader with nested clusters/arrays/derivedFrom; device header, startup/linker outputs and structured |
HW-004 can build on the implemented JSON export; mapping it to curated RTOS SoC YAML/schema remains an unimplemented adapter |
|
Flash client through GDB servers (OpenOCD, pyOCD, J-Link, Black Magic Probe, QEMU) |
Available upstream; RTOS board/programmer integration remains to be tested |
|
NASM-syntax x86-64 assembler; archiver; ELF and EMBX reader; listing and index tools |
Build support |
EmbBuild |
A typed-manifest build ( |
Answers Q20: EmbBuild exists as a format and walker, not an IDE build system. The CMake reference build (BLD-001) gains a target that emits an |
EMBX |
EmbLinkOS’s native, capability-carrying executable format, written by |
Design input for partitions: the per-partition manifest of granted capabilities (03 §8) should use EmbLinkOS’s capability vocabulary where the concepts coincide, so tooling can be shared; MCU boot images stay MCUboot-compatible (ADR-008) |
QEMU harnesses |
|
Added to the CI emulation layer alongside Renode (SIM-002) |
EmbFlash is now developed upstream; the 2026-10-07 absence is obsolete. Existing OpenOCD/pyOCD, picotool/UF2 and avrdude workflows remain useful. The RTOS emb facade (BLD-005), board-specific flashing and HIL integration remain planned and must be verified separately.
10. Gaps to track in EmbCC¶
The original ten-item compiler backlog is implemented upstream within its stated scope: (1) Armv8-M stack limits, (2) AVR scripts, (3) AVR __flash/program-memory support, (4) AVR DWARF, (5) AVR debugger layout, (6) small RV32/AVR atomics, (7) soft-float CMSE, (8) M23/Baseline, (9) SVD clusters/arrays/JSON, and (10) Cortex-M/RV32 C++ without exceptions. The closure matrix and local evidence preserve each item’s identity and remaining limits; do not erase the historical snapshot or infer complete RTOS qualification.
The layout-marker correction supplies EMB_LAYOUT_MARKER and verifies storage/assertion/kernel-archive compilation on eight configurations, with byte-identical native headers against GCC. The subsequent Linux native integration supplies explicit experimental EmbCC-kernel/GCC-host presets, a layout guard and local executed conformance/model evidence. All-EmbCC POSIX host compilation remains blocked by glibc header compatibility; AVR flash/registration macros, RTOS YAML adaptation, C++ header/runtime checks and pinned compiler/port conformance jobs remain separate work. Compiler TLS remains a shared embedded instance; default wide-atomic helpers are privileged local-mask operations. CMSE FPU/stack-crossing restrictions, AVR C++ refusal, debug unwinding/size limits and unrun physical measurements remain explicit.
11. Toolchain matrix for 1.0¶
Architecture |
EmbCC |
GCC |
Clang |
|---|---|---|---|
native (host) |
Experimental Linux x86-64 EmbCC kernel / GCC POSIX host passes local layout, conformance and model checks; all-EmbCC host compatibility and pinned compiler CI remain open. Upstream macOS experiments remain scoped reports |
yes |
yes |
avr |
Compiler/script/flash/debug capabilities available; full RTOS run unqualified |
avr-gcc |
Clang AVR (experimental) |
cortex_m |
Compiler M0+/M3/M4/M4F/M7/M23/M33 targets; upstream M3/M4 RTOS experiments are scoped reports, not current CI qualification |
arm-none-eabi-gcc |
Clang with |
riscv |
RV32/RV64 compiler targets; upstream RV32 RTOS experiment reported, current RTOS compiler leg unqualified |
riscv-none-elf-gcc |
Clang |
Every leg builds the same sources. Compiler-specific attribute and builtin spellings live only in include/emb/compiler/ (BLD-002). Differences recorded here are the first contents of that directory’s EmbCC header.