Skip to content

Possible Undefined Behavior due to Thin LTO imports #104377

@TimNN

Description

@TimNN

As part of Thin LTO, functions from one module (or codegen unit, in Rust terms) get imported into other modules. I've observed incompatible definitions/declarations get imported:

Assume we start with (in pseudo-LL) in some module X:

define void @outer(ptr noundef %0) {
  call void @inner(ptr noundef %0)
}

define void @inner(ptr noundef %0) { ... }

Dead argument elimination comes along and does:

define void @outer(ptr noundef %0) {
  call void @inner(ptr poison)  ; `noundef` is gone.
}

define void @inner(ptr %0) { ... }  ; `noundef` is gone.

So far so good. But now Thin LTO comes along and runs on a module Y that doesn't contain or reference @outer at all. Maybe it already contains a

declare void @inner(ptr noundef %0)

or maybe that gets (transitively) imported from some module Z. Now suppose that @outer also gets (transitively) imported. Suddenly we have in Y:

define void @outer(ptr noundef %0) {
  call void @inner(ptr poison)  ; Passing `poison` to `noundef` parameter!
}

declare void @inner(ptr noundef %0)

I have no idea of whether this is a (fundamental) problem with LLVM or with how Rust implements (Thin) LTO.


Note: I've so far only reproduced this with rustc compiled against LLVM HEAD, but wanted a tracking issue for further investigations.

Background: https://reviews.llvm.org/D133036 causes proc_macro to get miscompiled, leading to rustc segfaults. The patch got submitted once a few weeks ago and then rolled back. I noticed at the time, and wanted to preemptively figure out what's going on.

That patch eliminates function calls where undef (or poison) is passed to a parameter when that parameter is marked noundef. In the example above, it would eliminate the call to @inner.

cc @nikic

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions