Skip to content

teensylc: -flto=auto overflows Thumb-1 PC-relative offset limit on Cortex-M0+ #301

@zackees

Description

@zackees

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions