Symptom
Every FastLED teensyLC release build on master fails:
.lto-tmp/ccWj7t00.s:193: Error: invalid offset, value too big (0x000004CC)
.lto-tmp/ccWj7t00.s:206: Error: invalid offset, value too big (0x00000498)
lto-wrapper: fatal error: make returned 2 exit status
ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status
Root cause
Teensy LC = MKL26Z64 = Cortex-M0+ = Thumb-1 only. Thumb-1 PC-relative loads (ldr Rd, [PC, #imm]) have an immediate-offset limit of about 1 KB (10-bit immediate, word-aligned → max 0x3FC).
crates/fbuild-build/src/teensy/configs/teensylc.json declares:
"profiles": {
"release": {
"compile_flags": ["-Os", "-flto=auto", "-fno-fat-lto-objects"],
"link_flags": ["-Os", "-flto=auto", "-fuse-linker-plugin"]
},
...
}
LTO rearranges literal pools across translation units, and on Thumb-1 the rearranged offsets routinely exceed 0x400. Modern GCC's assembler catches this at the .lto-tmp/*.s step rather than producing wrong code.
This is Thumb-1-specific: every other Teensy MCU (3.0/3.1/3.2 = MK20DX, 3.5 = MK64FX, 3.6 = MK66FX, 4.x = IMXRT1062) is Cortex-M3 or later — all Thumb-2 — and Thumb-2's wider 12-bit PC-relative offsets don't hit this wall. So the fix is targeted to teensylc only.
Fix (this PR)
crates/fbuild-build/src/teensy/configs/teensylc.json: drop -flto=auto and -fno-fat-lto-objects / -fuse-linker-plugin from the release profile. Keep -Os for size. Reference config (configs/reference/teensylc.json) doesn't list -flto either, so test_linker_flags_match_platformio_reference continues to pass.
All 38 cargo test -p fbuild-build --lib teensy:: tests pass after the change.
Affected workflows
- FastLED
teensyLC — every example.
Why not "fix LTO instead"
Thumb-1's offset limit is hardware. The only way to keep LTO on M0+ would be to bound the size of literal pools per TU — GCC doesn't expose a knob for that, and even if it did, the spec window where it works would be narrow and fragile. Industry norm for Cortex-M0/M0+ embedded toolchains is "no LTO" — Teensyduino itself doesn't enable it on LC.
Filed during a coordinated CI-green sweep; fix PR landing immediately.
Symptom
Every FastLED
teensyLCrelease build on master fails:Root cause
Teensy LC = MKL26Z64 = Cortex-M0+ = Thumb-1 only. Thumb-1 PC-relative loads (
ldr Rd, [PC, #imm]) have an immediate-offset limit of about 1 KB (10-bit immediate, word-aligned → max 0x3FC).crates/fbuild-build/src/teensy/configs/teensylc.jsondeclares:LTO rearranges literal pools across translation units, and on Thumb-1 the rearranged offsets routinely exceed 0x400. Modern GCC's assembler catches this at the
.lto-tmp/*.sstep rather than producing wrong code.This is Thumb-1-specific: every other Teensy MCU (3.0/3.1/3.2 = MK20DX, 3.5 = MK64FX, 3.6 = MK66FX, 4.x = IMXRT1062) is Cortex-M3 or later — all Thumb-2 — and Thumb-2's wider 12-bit PC-relative offsets don't hit this wall. So the fix is targeted to teensylc only.
Fix (this PR)
crates/fbuild-build/src/teensy/configs/teensylc.json: drop-flto=autoand-fno-fat-lto-objects/-fuse-linker-pluginfrom the release profile. Keep-Osfor size. Reference config (configs/reference/teensylc.json) doesn't list-fltoeither, sotest_linker_flags_match_platformio_referencecontinues to pass.All 38
cargo test -p fbuild-build --lib teensy::tests pass after the change.Affected workflows
teensyLC— every example.Why not "fix LTO instead"
Thumb-1's offset limit is hardware. The only way to keep LTO on M0+ would be to bound the size of literal pools per TU — GCC doesn't expose a knob for that, and even if it did, the spec window where it works would be narrow and fragile. Industry norm for Cortex-M0/M0+ embedded toolchains is "no LTO" — Teensyduino itself doesn't enable it on LC.
Filed during a coordinated CI-green sweep; fix PR landing immediately.