Skip to content

Commit bb3c7d7

Browse files
committed
Auto merge of #156023 - jhpratt:rollup-sZeK85e, r=jhpratt
Rollup of 19 pull requests Successful merges: - rust-lang/rust#155237 (Disentangle AST crates and error crates) - rust-lang/rust#155249 (Fix: On wasm targets, call `panic_in_cleanup` if panic occurs in cleanup) - rust-lang/rust#155853 (Use `_mcount` as the mcount symbol name on RISC-V Linux GNU targets) - rust-lang/rust#155919 (simplify `ast_fragments!`) - rust-lang/rust#155939 (Add feature gate for view_types experiment) - rust-lang/rust#155954 (rustdoc: preserve parent doc cfg for `macro_export` macros) - rust-lang/rust#155974 (add `c_variadic_experimental_arch` feature) - rust-lang/rust#155991 (Catch unwinds from the global ctxt callback to complete queries profiling data in more cases) - rust-lang/rust#156003 (Pass Session to optimize_and_codegen_fat_lto) - rust-lang/rust#153566 (Add suggestion for E0401 on inner const items) - rust-lang/rust#154610 (Suggest public re-exports when a private module makes an import path inaccessible) - rust-lang/rust#155523 (Reorganize `tests/ui/issues/` - 02) - rust-lang/rust#155821 (c-variadic: document `Clone` and `Drop` instances and require `VaArgSafe: Copy`) - rust-lang/rust#155980 (Move `feature*` methods from `parse` mod to `errors` mod.) - rust-lang/rust#155987 (Make lifting infallible) - rust-lang/rust#155988 (tests/run-make/print-cfg: add Android target_env case) - rust-lang/rust#156000 (Fix ICE when using -Zinstrument-mcount and -Clinker-flavor=lld) - rust-lang/rust#156002 (Allow to use `Diagnostic` directly in `SharedContext::emit_lint`) - rust-lang/rust#156015 (rustc-dev-guide subtree update)
2 parents 854e053 + d0e684e commit bb3c7d7

20 files changed

Lines changed: 381 additions & 269 deletions

ci/sembr/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ struct Cli {
1515
/// Modify files that do not comply
1616
overwrite: bool,
1717
/// Applies to lines that are to be split
18-
#[arg(long, default_value_t = 80)]
18+
#[arg(long, default_value_t = 100)]
1919
line_length_limit: usize,
2020
}
2121

rust-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
cf1817bc6ecd2d14ca492247c804bad31948dd56
1+
f53b654a8882fd5fc036c4ca7a4ff41ce32497a6

src/asm.md

Lines changed: 73 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@
33
## Overview
44

55
Inline assembly in rustc mostly revolves around taking an `asm!` macro invocation and plumbing it
6-
through all of the compiler layers down to LLVM codegen. Throughout the various stages, an
7-
`InlineAsm` generally consists of 3 components:
6+
through all of the compiler layers down to LLVM codegen.
7+
Throughout the various stages,
8+
an `InlineAsm` generally consists of 3 components:
89

9-
- The template string, which is stored as an array of `InlineAsmTemplatePiece`. Each piece
10-
represents either a literal or a placeholder for an operand (just like format strings).
10+
- The template string, which is stored as an array of `InlineAsmTemplatePiece`.
11+
Each piece represents either a literal or a placeholder for an operand
12+
(just like format strings).
1113

1214
```rust
1315
pub enum InlineAsmTemplatePiece {
@@ -16,23 +18,29 @@ represents either a literal or a placeholder for an operand (just like format st
1618
}
1719
```
1820

19-
- The list of operands to the `asm!` (`in`, `[late]out`, `in[late]out`, `sym`, `const`). These are
20-
represented differently at each stage of lowering, but follow a common pattern:
21-
- `in`, `out` and `inout` all have an associated register class (`reg`) or explicit register
22-
(`"eax"`).
23-
- `inout` has 2 forms: one with a single expression that is both read from and written to, and
24-
one with two separate expressions for the input and output parts.
21+
- The list of operands to the `asm!` (`in`, `[late]out`, `in[late]out`, `sym`, `const`).
22+
These are represented differently at each stage of lowering,
23+
but follow a common pattern:
24+
- `in`, `out`, and `inout` all have an associated register class (`reg`)
25+
or explicit register (`"eax"`).
26+
- `inout` has 2 forms:
27+
one with a single expression that is both read from and written to,
28+
and one with two separate expressions for the input and output parts.
2529
- `out` and `inout` have a `late` flag (`lateout` / `inlateout`) to indicate that the register
26-
allocator is allowed to reuse an input register for this output.
27-
- `out` and the split variant of `inout` allow `_` to be specified for an output, which means
28-
that the output is discarded. This is used to allocate scratch registers for assembly code.
29-
- `const` refers to an anonymous constants and generally works like an inline const.
30-
- `sym` is a bit special since it only accepts a path expression, which must point to a `static`
31-
or a `fn`.
32-
33-
- The options set at the end of the `asm!` macro. The only ones that are of particular interest to
34-
rustc are `NORETURN` which makes `asm!` return `!` instead of `()`, and `RAW` which disables format
35-
string parsing. The remaining options are mostly passed through to LLVM with little processing.
30+
allocator is allowed to reuse an input register for this output.
31+
- `out` and the split variant of `inout` allow `_` to be specified for an output,
32+
which means that the output is discarded.
33+
This is used to allocate scratch registers for assembly code.
34+
- `const` refers to an anonymous constants,
35+
and generally works like an inline const.
36+
- `sym` is a bit special since it only accepts a path expression,
37+
which must point to a `static` or a `fn`.
38+
39+
- The options set at the end of the `asm!` macro.
40+
The only ones that are of particular interest to
41+
rustc are `NORETURN` which makes `asm!` return `!` instead of `()`,
42+
and `RAW` which disables format string parsing.
43+
The remaining options are mostly passed through to LLVM with little processing.
3644

3745
```rust
3846
bitflags::bitflags! {
@@ -54,9 +62,10 @@ string parsing. The remaining options are mostly passed through to LLVM with lit
5462

5563
`InlineAsm` is represented as an expression in the AST with the [`ast::InlineAsm` type][inline_asm_ast].
5664

57-
The `asm!` macro is implemented in `rustc_builtin_macros` and outputs an `InlineAsm` AST node. The
58-
template string is parsed using `fmt_macros`, positional and named operands are resolved to
59-
explicit operand indices. Since target information is not available to macro invocations,
65+
The `asm!` macro is implemented in `rustc_builtin_macros` and outputs an `InlineAsm` AST node.
66+
The template string is parsed using `fmt_macros`,
67+
positional and named operands are resolved to explicit operand indices.
68+
Since target information is not available to macro invocations,
6069
validation of the registers and register classes is deferred to AST lowering.
6170

6271
[inline_asm_ast]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/struct.InlineAsm.html
@@ -66,27 +75,31 @@ validation of the registers and register classes is deferred to AST lowering.
6675
`InlineAsm` is represented as an expression in the HIR with the [`hir::InlineAsm` type][inline_asm_hir].
6776

6877
AST lowering is where `InlineAsmRegOrRegClass` is converted from `Symbol`s to an actual register or
69-
register class. If any modifiers are specified for a template string placeholder, these are
70-
validated against the set allowed for that operand type. Finally, explicit registers for inputs and
78+
register class.
79+
If any modifiers are specified for a template string placeholder, these are
80+
validated against the set allowed for that operand type.
81+
Finally, explicit registers for inputs and
7182
outputs are checked for conflicts (same register used for different operands).
7283

7384
[inline_asm_hir]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.InlineAsm.html
7485

7586
## Type checking
7687

77-
Each register class has a whitelist of types that it may be used with. After the types of all
78-
operands have been determined, the `intrinsicck` pass will check that these types are in the
79-
whitelist. It also checks that split `inout` operands have compatible types and that `const`
80-
operands are integers or floats. Suggestions are emitted where needed if a template modifier should
88+
Each register class has an allowlist of types that it may be used with.
89+
After the types of all operands have been determined,
90+
the `intrinsicck` pass will check that these types are in the allowlist.
91+
It also checks that split `inout` operands have compatible types and that `const`
92+
operands are integers or floats.
93+
Suggestions are emitted where needed if a template modifier should
8194
be used for an operand based on the type that was passed into it.
8295

8396
## THIR
8497

8598
`InlineAsm` is represented as an expression in the THIR with the [`InlineAsmExpr` type][inline_asm_thir].
8699

87100
The only significant change compared to HIR is that `Sym` has been lowered to either a `SymFn`
88-
whose `expr` is a `Literal` ZST of the `fn`, or a `SymStatic` which points to the `DefId` of a
89-
`static`.
101+
whose `expr` is a `Literal` ZST of the `fn`,
102+
or a `SymStatic` which points to the `DefId` of a `static`.
90103

91104
[inline_asm_thir]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/thir/struct.InlineAsmExpr.html
92105

@@ -104,50 +117,59 @@ multiple output places where a `Call` only has a single return place output.
104117

105118
## Codegen
106119

107-
Operands are lowered one more time before being passed to LLVM codegen, this is represented by the [`InlineAsmOperandRef` type][inline_asm_codegen] from `rustc_codegen_ssa`.
120+
Operands are lowered one more time before being passed to LLVM codegen.
121+
This is represented by the [`InlineAsmOperandRef` type][inline_asm_codegen] from `rustc_codegen_ssa`.
108122

109123
The operands are lowered to LLVM operands and constraint codes as follows:
110-
- `out` and the output part of `inout` operands are added first, as required by LLVM. Late output
111-
operands have a `=` prefix added to their constraint code, non-late output operands have a `=&`
112-
prefix added to their constraint code.
124+
- `out` and the output part of `inout` operands are added first, as required by LLVM.
125+
Late output operands have a `=` prefix added to their constraint code,
126+
and non-late output operands have a `=&` prefix added to their constraint code.
113127
- `in` operands are added normally.
114128
- `inout` operands are tied to the matching output operand.
115-
- `sym` operands are passed as function pointers or pointers, using the `"s"` constraint.
129+
- `sym` operands are passed as function pointers or pointers,
130+
using the `"s"` constraint.
116131
- `const` operands are formatted to a string and directly inserted in the template string.
117132

118133
The template string is converted to LLVM form:
119134
- `$` characters are escaped as `$$`.
120135
- `const` operands are converted to strings and inserted directly.
121-
- Placeholders are formatted as `${X:M}` where `X` is the operand index and `M` is the modifier
122-
character. Modifiers are converted from the Rust form to the LLVM form.
136+
- Placeholders are formatted as `${X:M}`,
137+
where `X` is the operand index and `M` is the modifier character.
138+
Modifiers are converted from the Rust form to the LLVM form.
123139

124-
The various options are converted to clobber constraints or LLVM attributes, refer to the
125-
[RFC](https://github.com/Amanieu/rfcs/blob/inline-asm/text/0000-inline-asm.md#mapping-to-llvm-ir)
126-
for more details.
140+
The various options are converted to clobber constraints or LLVM attributes;
141+
refer to the [RFC] for more details.
127142

128143
Note that LLVM is sometimes rather picky about what types it accepts for certain constraint codes
129-
so we sometimes need to insert conversions to/from a supported type. See the target-specific
130-
ISelLowering.cpp files in LLVM for details of what types are supported for each register class.
144+
so we sometimes need to insert conversions to/from a supported type.
145+
See the target-specific ISelLowering.cpp files in LLVM
146+
for details of what types are supported for each register class.
131147

132148
[inline_asm_codegen]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/traits/enum.InlineAsmOperandRef.html
149+
[RFC]: https://github.com/Amanieu/rfcs/blob/inline-asm/text/0000-inline-asm.md#mapping-to-llvm-ir
133150

134151
## Adding support for new architectures
135152

136153
Adding inline assembly support to an architecture is mostly a matter of defining the registers and
137-
register classes for that architecture. All the definitions for register classes are located in
154+
register classes for that architecture.
155+
All the definitions for register classes are located in
138156
`compiler/rustc_target/asm/`.
139157

140158
Additionally you will need to implement lowering of these register classes to LLVM constraint codes
141159
in `compiler/rustc_codegen_llvm/asm.rs`.
142160

143161
When adding a new architecture, make sure to cross-reference with the LLVM source code:
144-
- LLVM has restrictions on which types can be used with a particular constraint code. Refer to the
145-
`getRegForInlineAsmConstraint` function in `lib/Target/${ARCH}/${ARCH}ISelLowering.cpp`.
146-
- LLVM reserves certain registers for its internal use, which causes them to not be saved/restored
147-
properly around inline assembly blocks. These registers are listed in the `getReservedRegs`
148-
function in `lib/Target/${ARCH}/${ARCH}RegisterInfo.cpp`. Any "conditionally" reserved register
149-
such as the frame/base pointer must always be treated as reserved for Rust purposes because we
150-
can't know ahead of time whether a function will require a frame/base pointer.
162+
- LLVM has restrictions on which types can be used with a particular constraint code.
163+
Refer to the `getRegForInlineAsmConstraint` function
164+
in `lib/Target/${ARCH}/${ARCH}ISelLowering.cpp`.
165+
- LLVM reserves certain registers for its internal use,
166+
which causes them to not be saved/restored properly around inline assembly blocks.
167+
These registers are listed in the `getReservedRegs`
168+
function in `lib/Target/${ARCH}/${ARCH}RegisterInfo.cpp`.
169+
Any "conditionally" reserved register,
170+
such as the frame/base pointer,
171+
must always be treated as reserved for Rust purposes because we
172+
can't know ahead of time whether a function will require a frame/base pointer.
151173

152174
## Tests
153175

0 commit comments

Comments
 (0)