← board

A C call to an external variadic on ESP riscv32 loses its arguments

Found 2026-09-24 (frankS) while bringing up feature-c-esp-conformance-coverage.

Repro (HEAD after the ESP C entry stub landed)

extern int esp_rom_printf(const char *fmt, ...);
int main(void){ esp_rom_printf("ROM %d\n", 5); return 0; }

tools/esp_run.sh --chip esp32c3 r.c boots, IDF logs Returned from app_main(), and nothing is printed. Controls in the same session, same binary: printf("hi %d\n", 42) (crtl's printf) prints hi 42; a Pascal esp_rom_printf(fmt: string; v: Integer); external; (non-variadic declaration) prints fine in examples/esp32/dns-c3. So the stub, the link and the ROM routine all work; the variadic call to a foreign definition does not.

Measured vs inferred

Scope to check

Whether the same holds on hosted targets for a C call into a --dynlib or -l library's variadic (x86-64/aarch64 printf from libc when crtl is not the provider) -- if so this is not ESP-specific and belongs in backlog-core. xtensa cannot be checked yet: variadic C on the windowed ABI is refused.

2026-09-24 (frankS): FIXED -- and the inference above was wrong

The "Measured vs inferred" section above guessed the arguments went into a .bss va block. They did not: the .bss stores it saw are crtl's errstr table initialisation in main, and the call itself loads a0/a1/a2 correctly. The fault is the FORMAT POINTER, which was const_str + 8 + 8.