Skip to content

LLVM 21 readonly optimization breaks FFI writes through tag pointers #4925

@SeanTAllen

Description

@SeanTAllen

The LLVM 21 upgrade introduced a bug where FFI functions that write through pointer parameters have their writes optimized away in release builds.

The root cause: genfun_param_attrs maps Pony's tag capability to LLVM's readonly parameter attribute. This tells LLVM the function won't write through the pointer. That's incorrect when the pointer gets passed to an FFI function that does write through it (e.g., getsockname filling in a sockaddr).

This worked before LLVM 21 because older LLVM versions weren't as aggressive about exploiting readonly to eliminate loads. With LLVM 21, after inlining a Pony wrapper around an FFI call, the optimizer sees: memset to zero → call with readonly pointer → load, and concludes the load must return zero.

The symptom: lori's ListenerLocalAddress test fails in release mode because local_address() always returns port 0. It passes with --debug because the optimizer doesn't run.

A temporary fix that moves TK_TAG from the readonly group to the no-attribute group (with trn and ref) is up in #4926. val and box have real immutability/read-only guarantees that make readonly correct. tag only means identity-comparison-only in Pony, which doesn't imply the pointed-to memory won't be written through other paths.

This needs discussion about whether the temporary fix is the right long-term approach, or whether we need something more nuanced.

Metadata

Metadata

Assignees

No one assigned

    Labels

    discuss during syncShould be discussed during an upcoming sync

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions