@@ -54,111 +54,26 @@ string parsing. The remaining options are mostly passed through to LLVM with lit
54
54
55
55
## AST
56
56
57
- ` InlineAsm ` is represented as an expression in the AST:
58
-
59
- ``` rust
60
- pub struct InlineAsm {
61
- pub template : Vec <InlineAsmTemplatePiece >,
62
- pub template_strs : Box <[(Symbol , Option <Symbol >, Span )]>,
63
- pub operands : Vec <(InlineAsmOperand , Span )>,
64
- pub clobber_abi : Option <(Symbol , Span )>,
65
- pub options : InlineAsmOptions ,
66
- pub line_spans : Vec <Span >,
67
- }
68
-
69
- pub enum InlineAsmRegOrRegClass {
70
- Reg (Symbol ),
71
- RegClass (Symbol ),
72
- }
73
-
74
- pub enum InlineAsmOperand {
75
- In {
76
- reg : InlineAsmRegOrRegClass ,
77
- expr : P <Expr >,
78
- },
79
- Out {
80
- reg : InlineAsmRegOrRegClass ,
81
- late : bool ,
82
- expr : Option <P <Expr >>,
83
- },
84
- InOut {
85
- reg : InlineAsmRegOrRegClass ,
86
- late : bool ,
87
- expr : P <Expr >,
88
- },
89
- SplitInOut {
90
- reg : InlineAsmRegOrRegClass ,
91
- late : bool ,
92
- in_expr : P <Expr >,
93
- out_expr : Option <P <Expr >>,
94
- },
95
- Const {
96
- anon_const : AnonConst ,
97
- },
98
- Sym {
99
- expr : P <Expr >,
100
- },
101
- }
102
- ```
57
+ ` InlineAsm ` is represented as an expression in the AST with the [ ` ast::InlineAsm ` type] [ inline_asm_ast ] .
103
58
104
59
The ` asm! ` macro is implemented in ` rustc_builtin_macros ` and outputs an ` InlineAsm ` AST node. The
105
60
template string is parsed using ` fmt_macros ` , positional and named operands are resolved to
106
61
explicit operand indices. Since target information is not available to macro invocations,
107
62
validation of the registers and register classes is deferred to AST lowering.
108
63
64
+ [ inline_asm_ast ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/struct.InlineAsm.html
65
+
109
66
## HIR
110
67
111
- ` InlineAsm ` is represented as an expression in the HIR:
112
-
113
- ``` rust
114
- pub struct InlineAsm <'hir > {
115
- pub template : & 'hir [InlineAsmTemplatePiece ],
116
- pub template_strs : & 'hir [(Symbol , Option <Symbol >, Span )],
117
- pub operands : & 'hir [(InlineAsmOperand <'hir >, Span )],
118
- pub options : InlineAsmOptions ,
119
- pub line_spans : & 'hir [Span ],
120
- }
121
-
122
- pub enum InlineAsmRegOrRegClass {
123
- Reg (InlineAsmReg ),
124
- RegClass (InlineAsmRegClass ),
125
- }
126
-
127
- pub enum InlineAsmOperand <'hir > {
128
- In {
129
- reg : InlineAsmRegOrRegClass ,
130
- expr : Expr <'hir >,
131
- },
132
- Out {
133
- reg : InlineAsmRegOrRegClass ,
134
- late : bool ,
135
- expr : Option <Expr <'hir >>,
136
- },
137
- InOut {
138
- reg : InlineAsmRegOrRegClass ,
139
- late : bool ,
140
- expr : Expr <'hir >,
141
- },
142
- SplitInOut {
143
- reg : InlineAsmRegOrRegClass ,
144
- late : bool ,
145
- in_expr : Expr <'hir >,
146
- out_expr : Option <Expr <'hir >>,
147
- },
148
- Const {
149
- anon_const : AnonConst ,
150
- },
151
- Sym {
152
- expr : Expr <'hir >,
153
- },
154
- }
155
- ```
68
+ ` InlineAsm ` is represented as an expression in the HIR with the [ ` hir::InlineAsm ` type] [ inline_asm_hir ] .
156
69
157
70
AST lowering is where ` InlineAsmRegOrRegClass ` is converted from ` Symbol ` s to an actual register or
158
71
register class. If any modifiers are specified for a template string placeholder, these are
159
72
validated against the set allowed for that operand type. Finally, explicit registers for inputs and
160
73
outputs are checked for conflicts (same register used for different operands).
161
74
75
+ [ inline_asm_hir ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/hir/struct.InlineAsm.html
76
+
162
77
## Type checking
163
78
164
79
Each register class has a whitelist of types that it may be used with. After the types of all
@@ -169,152 +84,29 @@ be used for an operand based on the type that was passed into it.
169
84
170
85
## THIR
171
86
172
- ` InlineAsm ` is represented as an expression in the THIR:
173
-
174
- ``` rust
175
- crate enum ExprKind <'tcx > {
176
- // [..]
177
- InlineAsm {
178
- template : & 'tcx [InlineAsmTemplatePiece ],
179
- operands : Box <[InlineAsmOperand <'tcx >]>,
180
- options : InlineAsmOptions ,
181
- line_spans : & 'tcx [Span ],
182
- },
183
- }
184
- crate enum InlineAsmOperand <'tcx > {
185
- In {
186
- reg : InlineAsmRegOrRegClass ,
187
- expr : ExprId ,
188
- },
189
- Out {
190
- reg : InlineAsmRegOrRegClass ,
191
- late : bool ,
192
- expr : Option <ExprId >,
193
- },
194
- InOut {
195
- reg : InlineAsmRegOrRegClass ,
196
- late : bool ,
197
- expr : ExprId ,
198
- },
199
- SplitInOut {
200
- reg : InlineAsmRegOrRegClass ,
201
- late : bool ,
202
- in_expr : ExprId ,
203
- out_expr : Option <ExprId >,
204
- },
205
- Const {
206
- value : & 'tcx Const <'tcx >,
207
- span : Span ,
208
- },
209
- SymFn {
210
- expr : ExprId ,
211
- },
212
- SymStatic {
213
- def_id : DefId ,
214
- },
215
- }
216
- ```
87
+ ` InlineAsm ` is represented as an expression in the THIR with the [ ` InlineAsmExpr ` type] [ inline_asm_thir ] .
217
88
218
89
The only significant change compared to HIR is that ` Sym ` has been lowered to either a ` SymFn `
219
90
whose ` expr ` is a ` Literal ` ZST of the ` fn ` , or a ` SymStatic ` which points to the ` DefId ` of a
220
91
` static ` .
221
92
93
+ [ inline_asm_thir ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/thir/struct.InlineAsmExpr.html
94
+
222
95
## MIR
223
96
224
- ` InlineAsm ` is represented as a ` Terminator ` in the MIR:
225
-
226
- ``` rust
227
- pub enum TerminatorKind <'tcx > {
228
- // [..]
229
-
230
- /// Block ends with an inline assembly block. This is a terminator since
231
- /// inline assembly is allowed to diverge.
232
- InlineAsm {
233
- /// The template for the inline assembly, with placeholders.
234
- template : & 'tcx [InlineAsmTemplatePiece ],
235
-
236
- /// The operands for the inline assembly, as `Operand`s or `Place`s.
237
- operands : Vec <InlineAsmOperand <'tcx >>,
238
-
239
- /// Miscellaneous options for the inline assembly.
240
- options : InlineAsmOptions ,
241
-
242
- /// Source spans for each line of the inline assembly code. These are
243
- /// used to map assembler errors back to the line in the source code.
244
- line_spans : & 'tcx [Span ],
245
-
246
- /// Destination block after the inline assembly returns, unless it is
247
- /// diverging (InlineAsmOptions::NORETURN).
248
- destination : Option <BasicBlock >,
249
- },
250
- }
251
-
252
- pub enum InlineAsmOperand <'tcx > {
253
- In {
254
- reg : InlineAsmRegOrRegClass ,
255
- value : Operand <'tcx >,
256
- },
257
- Out {
258
- reg : InlineAsmRegOrRegClass ,
259
- late : bool ,
260
- place : Option <Place <'tcx >>,
261
- },
262
- InOut {
263
- reg : InlineAsmRegOrRegClass ,
264
- late : bool ,
265
- in_value : Operand <'tcx >,
266
- out_place : Option <Place <'tcx >>,
267
- },
268
- Const {
269
- value : Box <Constant <'tcx >>,
270
- },
271
- SymFn {
272
- value : Box <Constant <'tcx >>,
273
- },
274
- SymStatic {
275
- def_id : DefId ,
276
- },
277
- }
278
- ```
97
+ ` InlineAsm ` is represented as a ` Terminator ` in the MIR with the [ ` TerminatorKind::InlineAsm ` variant] [ inline_asm_mir ]
279
98
280
99
As part of THIR lowering, ` InOut ` and ` SplitInOut ` operands are lowered to a split form with a
281
100
separate ` in_value ` and ` out_place ` .
282
101
283
102
Semantically, the ` InlineAsm ` terminator is similar to the ` Call ` terminator except that it has
284
103
multiple output places where a ` Call ` only has a single return place output.
285
104
105
+ [ inline_asm_mir ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/mir/enum.TerminatorKind.html#variant.InlineAsm
106
+
286
107
## Codegen
287
108
288
- Operands are lowered one more time before being passed to LLVM codegen:
289
-
290
- ``` rust
291
- pub enum InlineAsmOperandRef <'tcx , B : BackendTypes + ? Sized > {
292
- In {
293
- reg : InlineAsmRegOrRegClass ,
294
- value : OperandRef <'tcx , B :: Value >,
295
- },
296
- Out {
297
- reg : InlineAsmRegOrRegClass ,
298
- late : bool ,
299
- place : Option <PlaceRef <'tcx , B :: Value >>,
300
- },
301
- InOut {
302
- reg : InlineAsmRegOrRegClass ,
303
- late : bool ,
304
- in_value : OperandRef <'tcx , B :: Value >,
305
- out_place : Option <PlaceRef <'tcx , B :: Value >>,
306
- },
307
- Const {
308
- string : String ,
309
- },
310
- SymFn {
311
- instance : Instance <'tcx >,
312
- },
313
- SymStatic {
314
- def_id : DefId ,
315
- },
316
- }
317
- ```
109
+ 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 ` .
318
110
319
111
The operands are lowered to LLVM operands and constraint codes as follow:
320
112
- ` out ` and the output part of ` inout ` operands are added first, as required by LLVM. Late output
@@ -339,6 +131,8 @@ Note that LLVM is sometimes rather picky about what types it accepts for certain
339
131
so we sometimes need to insert conversions to/from a supported type. See the target-specific
340
132
ISelLowering.cpp files in LLVM for details of what types are supported for each register class.
341
133
134
+ [ inline_asm_codegen ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustc_codegen_ssa/traits/enum.InlineAsmOperandRef.html
135
+
342
136
## Adding support for new architectures
343
137
344
138
Adding inline assembly support to an architecture is mostly a matter of defining the registers and
0 commit comments