Skip to content

Deduplication of functions containing inline assembly contradicts Reference's documentation about code-patching. #116857

Closed
rust-lang/reference
#1441
@zachs18

Description

@zachs18

(I'm not sure if this should be considered a codegen bug (i.e. the Reference is correct) or a documentation bug (i.e. the codegen is correct). This issue assumes it is a codegen bug. If this is determined to be a documentation bug, then I can instead report this on the rust-lang/reference repo).

I tried this code:

#![no_std]
use core::arch::asm;
pub fn foo() {
    unsafe { asm!("nop"); }
}
pub fn bar() {
    unsafe { asm!("nop"); }
}

View the resulting assembly using either godbolt.org or cargo-show-asm.

I expected to see this happen: foo and bar are not deduplicated, due to the Rust Reference's documentation that

The compiler cannot assume that the instructions in the asm are the ones that will actually end up executed.
This effectively means that the compiler must treat the asm! as a black box and only take the interface specification into account, not the instructions themselves.
Runtime code patching is allowed, via target-specific mechanisms.

# expected output for --target x86_64-unknown-linux-gnu
example::foo:
  push rax
  
  nop
  
  pop rax
  ret

example::bar:
  push rax
  
  nop
  
  pop rax
  ret

Instead, this happened: When compiled with optimizations (-Copt-level=2 or above), foo and bar are deduplicated (godbolt link)

# actual output for --target x86_64-unknown-linux-gnu
example::bar:
  push rax
  
  nop
  
  pop rax
  ret

Notes:

  • This only happens when the asm invocations are exactly the same, thus a workaround is to add spaces to the asm template string to make them different.
  • Different extern "ABI" and #[no_mangle] do not inherently prevent deduplication.
  • Different #[link_section = "..."]s work to prevent deduplication (if the functions are given the same #[link_section = "..."] then they are still deduplicated).

Meta

Happens on nightly (2023-10-16), stable (1.73.0), and 1.59.0 (when inline asm was stabilized) (and probably all versions between).

rustc --version --verbose:

rustc 1.75.0-nightly (49691b1f7 2023-10-16)
binary: rustc
commit-hash: 49691b1f70d71dd7b8349c332b7f277ee527bf08
commit-date: 2023-10-16
host: x86_64-unknown-linux-gnu
release: 1.75.0-nightly
LLVM version: 17.0.2

rustc 1.73.0 (cc66ad468 2023-10-03)
binary: rustc
commit-hash: cc66ad468955717ab92600c770da8c1601a4ff33
commit-date: 2023-10-03
host: x86_64-unknown-linux-gnu
release: 1.73.0
LLVM version: 17.0.2

(no backtrace)

@rustbot label +A-inline-assembly

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-codegenArea: Code generationA-inline-assemblyArea: Inline assembly (`asm!(…)`)C-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.T-opsemRelevant to the opsem team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions