Files
rust/tests/pretty
Jonathan Brouwer 774370ab2f Rollup merge of #154088 - aytey:fix-asm-operand-ordering, r=davidtwco
Reorder inline asm operands in pretty printer to satisfy grammar constraints

After macro expansion, named `asm!` operands are converted to positional operands and the template string uses numeric indices. However, the pretty printer previously emitted operands in their original AST order, which could place positional (formerly named) register-class operands after explicit register operands. This violates the `asm!` grammar rule that positional arguments cannot follow explicit register arguments, causing the expanded output from `rustc -Zunpretty=expanded` to fail to reparse.

When reordering is needed, the fix partitions operands into non-explicit and explicit register groups, emits non-explicit operands first, then explicit register operands, and remaps template placeholder indices (`{N}`) to match the new positions. When operands are already correctly ordered, the original code path is used unchanged.

## Example

**before** (`rustc 1.96.0-nightly (3b1b0ef4d 2026-03-11)`):

```rust
#![feature(prelude_import)]
#![no_std]
extern crate std;
#[prelude_import]
use ::std::prelude::rust_2015::*;
//@ pretty-mode:expanded
//@ pp-exact:asm-operand-order.pp
//@ only-x86_64

use std::arch::asm;

pub fn main() {
    unsafe {
        asm!("{1}", out("rax") _, in(reg) 4);
        asm!("{1}", out("rax") _, in(reg) 4, options(nostack));
        asm!("{1} {2}", out("rax") _, in(reg) 4, in(reg) 5);
    }
}
```

**after** (this branch):

```rust
#![feature(prelude_import)]
#![no_std]
extern crate std;
#[prelude_import]
use ::std::prelude::rust_2015::*;
//@ pretty-mode:expanded
//@ pp-exact:asm-operand-order.pp
//@ only-x86_64

use std::arch::asm;

pub fn main() {
    unsafe {
        asm!("{0}", in(reg) 4, out("rax") _);
        asm!("{0}", in(reg) 4, out("rax") _, options(nostack));
        asm!("{0} {1}", in(reg) 4, in(reg) 5, out("rax") _);
    }
}
```
Notice the operand reordering: in the before, explicit register operands (`out("rax")`) appear before positional operands (`in(reg)`), violating the grammar (E0662). The template references are also wrong (`{1}` instead of `{0}`). The after moves positional operands first and renumbers the template references accordingly.
2026-03-26 15:20:10 +01:00
..
2026-01-13 08:47:48 +01:00
2024-02-22 16:04:05 +00:00
2025-04-03 21:41:58 +00:00
2024-02-22 16:04:05 +00:00
2026-02-22 20:20:33 +01:00
2025-02-24 14:31:19 +01:00
2025-04-03 21:41:58 +00:00
2023-01-11 09:32:08 +00:00
2024-02-22 16:04:05 +00:00
2023-01-11 09:32:08 +00:00
2026-02-22 20:20:33 +01:00
2025-04-15 11:14:23 +02:00
2024-08-18 19:46:53 +02:00
2025-03-21 09:35:31 +01:00
2024-02-22 16:04:05 +00:00