Skip to content

Formatting guidelines for inline assembly #152

Open
@joshtriplett

Description

@joshtriplett

An issue I've observed in several contexts discussing the new asm! syntax for inline assembly: everyone formats asm! statements differently, and we should 1) come up with guidance on how to do so, and 2) implement that guidance in rustfmt.

Notably, this includes how to format both single-line and multi-line assembly statements.

EDIT: I've updated these guidelines to use the new support for multiple template string arguments, implemented in rust-lang/rust#73364 .

With my style team hat on, I would propose the following guidelines:

  • Single-line assembly code should be formatted as a single string argument and treated as any other argument to a format macro.
  • Multi-line assembly code should be formatted with one string argument per line of assembly, indented as separate arguments:
    asm!(
        "instruction 1",
        "instruction 2",
        ...,
    );
  • Common assembly formatting such as \n\t (often seen in inline assembly for other compilers that directly copy the provided string into their assembly output) is not necessary with Rust inline assembly. Focus on keeping the assembly readable. Note that Rust is not prescriptive about the formatting of your assembly, so if you wish to put multiple instructions or directives or labels on one line (and thus within one assembly string), you can do so, and rustfmt will treat each assembly string as a line.
  • Use the opening " of each string as the base for any indentation within the assembly code; for instance, if you want to indent instructions four spaces past labels, include the indentation inside the string before the instructions. That way, Rust formatting can keep the strings aligned and your assembly code will remain aligned within them:
    asm!(
        "1:",
        "    instruction 1",
        "    instruction 2",
        "2:",
        "    instruction 3",
    );
  • Simple asm! with only one assembly string can have the entire asm! including all its arguments on the same line, if the whole thing from asm!( to ); (plus indentation) fits in the line width.
  • Any asm! block that needs breaking across multiple lines, or any asm! block that has multiple assembly strings no matter how short, should always put each argument on its own line, aligned one indentation level past the asm!, with a trailing comma on each, just like a function.
  • options(...) goes on one line if it fits; otherwise, format it as though it were a nested function call to a function named options.
  • Never place any space or line breaks inside of in(reg) or out(reg) or inout(reg) or in("regname") or out("regname") or similar; always treat them as a single atomic unit.
  • If an inout or inlateout pair of expressions are too long to fit on one line, break before (never after) the =>, and indent the => one level further:
    asm!(
        "instruction {}",
        inout(reg) very_long_expression
            => very_long_out_expression,
    )
  • If an in(reg) or out(reg) or lateout(reg) expression is too long, break between the ) and the expression and indent one level, then format from there; however, if the expression can be broken internally, follow same the rules for when to leave the head of the expression on the same line as the in(reg) or similar as if in(reg) were the opener of a function:
    asm!(
        "instruction {}",
        in(reg)
            extremely_long_unbreakable_expression,
        in(reg) function_name()
            .method_name(method_arg)
            .further_chained_method(),
        out(reg) long_function_name(
            long_function_argument_expression,
        ),
    );
  • For named arguments like name = in(reg) expression, line-break it as you would an assignment statement with the same indentation, treating the in(reg) expression as the right-hand side of the assignment, and following all the same rules as above.

Metadata

Metadata

Assignees

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