@@ -6,12 +6,37 @@ use std::fmt::Write;
6
6
7
7
use rustc_ast:: ast:: { InlineAsmOptions , InlineAsmTemplatePiece } ;
8
8
use rustc_middle:: mir:: InlineAsmOperand ;
9
+ use rustc_middle:: ty:: SymbolName ;
9
10
use rustc_span:: sym;
10
11
use rustc_target:: asm:: * ;
11
12
13
+ enum CInlineAsmOperand < ' tcx > {
14
+ In {
15
+ reg : InlineAsmRegOrRegClass ,
16
+ value : CValue < ' tcx > ,
17
+ } ,
18
+ Out {
19
+ reg : InlineAsmRegOrRegClass ,
20
+ late : bool ,
21
+ place : Option < CPlace < ' tcx > > ,
22
+ } ,
23
+ InOut {
24
+ reg : InlineAsmRegOrRegClass ,
25
+ _late : bool ,
26
+ in_value : CValue < ' tcx > ,
27
+ out_place : Option < CPlace < ' tcx > > ,
28
+ } ,
29
+ Const {
30
+ value : String ,
31
+ } ,
32
+ Symbol {
33
+ symbol : SymbolName < ' tcx > ,
34
+ } ,
35
+ }
36
+
12
37
pub ( crate ) fn codegen_inline_asm < ' tcx > (
13
38
fx : & mut FunctionCx < ' _ , ' _ , ' tcx > ,
14
- _span : Span ,
39
+ span : Span ,
15
40
template : & [ InlineAsmTemplatePiece ] ,
16
41
operands : & [ InlineAsmOperand < ' tcx > ] ,
17
42
options : InlineAsmOptions ,
@@ -198,6 +223,59 @@ pub(crate) fn codegen_inline_asm<'tcx>(
198
223
}
199
224
}
200
225
226
+ let operands = operands
227
+ . into_iter ( )
228
+ . map ( |operand| match * operand {
229
+ InlineAsmOperand :: In { reg, ref value } => {
230
+ CInlineAsmOperand :: In { reg, value : crate :: base:: codegen_operand ( fx, value) }
231
+ }
232
+ InlineAsmOperand :: Out { reg, late, ref place } => CInlineAsmOperand :: Out {
233
+ reg,
234
+ late,
235
+ place : place. map ( |place| crate :: base:: codegen_place ( fx, place) ) ,
236
+ } ,
237
+ InlineAsmOperand :: InOut { reg, late, ref in_value, ref out_place } => {
238
+ CInlineAsmOperand :: InOut {
239
+ reg,
240
+ _late : late,
241
+ in_value : crate :: base:: codegen_operand ( fx, in_value) ,
242
+ out_place : out_place. map ( |place| crate :: base:: codegen_place ( fx, place) ) ,
243
+ }
244
+ }
245
+ InlineAsmOperand :: Const { ref value } => {
246
+ let ( const_value, ty) = crate :: constant:: eval_mir_constant ( fx, & * value)
247
+ . unwrap_or_else ( || span_bug ! ( span, "asm const cannot be resolved" ) ) ;
248
+ let value = rustc_codegen_ssa:: common:: asm_const_to_str (
249
+ fx. tcx ,
250
+ span,
251
+ const_value,
252
+ fx. layout_of ( ty) ,
253
+ ) ;
254
+ CInlineAsmOperand :: Const { value }
255
+ }
256
+ InlineAsmOperand :: SymFn { ref value } => {
257
+ let literal = fx. monomorphize ( value. literal ) ;
258
+ if let ty:: FnDef ( def_id, substs) = * literal. ty ( ) . kind ( ) {
259
+ let instance = ty:: Instance :: resolve_for_fn_ptr (
260
+ fx. tcx ,
261
+ ty:: ParamEnv :: reveal_all ( ) ,
262
+ def_id,
263
+ substs,
264
+ )
265
+ . unwrap ( ) ;
266
+ CInlineAsmOperand :: Symbol { symbol : fx. tcx . symbol_name ( instance) }
267
+ } else {
268
+ span_bug ! ( span, "invalid type for asm sym (fn)" ) ;
269
+ }
270
+ }
271
+ InlineAsmOperand :: SymStatic { def_id } => {
272
+ assert ! ( fx. tcx. is_static( def_id) ) ;
273
+ let instance = Instance :: mono ( fx. tcx , def_id) . polymorphize ( fx. tcx ) ;
274
+ CInlineAsmOperand :: Symbol { symbol : fx. tcx . symbol_name ( instance) }
275
+ }
276
+ } )
277
+ . collect :: < Vec < _ > > ( ) ;
278
+
201
279
let mut inputs = Vec :: new ( ) ;
202
280
let mut outputs = Vec :: new ( ) ;
203
281
@@ -206,7 +284,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
206
284
arch : fx. tcx . sess . asm_arch . unwrap ( ) ,
207
285
enclosing_def_id : fx. instance . def_id ( ) ,
208
286
template,
209
- operands,
287
+ operands : & operands ,
210
288
options,
211
289
registers : Vec :: new ( ) ,
212
290
stack_slots_clobber : Vec :: new ( ) ,
@@ -229,36 +307,22 @@ pub(crate) fn codegen_inline_asm<'tcx>(
229
307
fx. cx . global_asm . push_str ( & generated_asm) ;
230
308
231
309
for ( i, operand) in operands. iter ( ) . enumerate ( ) {
232
- match * operand {
233
- InlineAsmOperand :: In { reg : _, ref value } => {
234
- inputs. push ( (
235
- asm_gen. stack_slots_input [ i] . unwrap ( ) ,
236
- crate :: base:: codegen_operand ( fx, value) . load_scalar ( fx) ,
237
- ) ) ;
238
- }
239
- InlineAsmOperand :: Out { reg : _, late : _, place } => {
310
+ match operand {
311
+ CInlineAsmOperand :: In { reg : _, value } => {
312
+ inputs. push ( ( asm_gen. stack_slots_input [ i] . unwrap ( ) , value. load_scalar ( fx) ) ) ;
313
+ }
314
+ CInlineAsmOperand :: Out { reg : _, late : _, place } => {
240
315
if let Some ( place) = place {
241
- outputs. push ( (
242
- asm_gen. stack_slots_output [ i] . unwrap ( ) ,
243
- crate :: base:: codegen_place ( fx, place) ,
244
- ) ) ;
316
+ outputs. push ( ( asm_gen. stack_slots_output [ i] . unwrap ( ) , place. clone ( ) ) ) ;
245
317
}
246
318
}
247
- InlineAsmOperand :: InOut { reg : _, late : _, ref in_value, out_place } => {
248
- inputs. push ( (
249
- asm_gen. stack_slots_input [ i] . unwrap ( ) ,
250
- crate :: base:: codegen_operand ( fx, in_value) . load_scalar ( fx) ,
251
- ) ) ;
319
+ CInlineAsmOperand :: InOut { reg : _, _late : _, in_value, out_place } => {
320
+ inputs. push ( ( asm_gen. stack_slots_input [ i] . unwrap ( ) , in_value. load_scalar ( fx) ) ) ;
252
321
if let Some ( out_place) = out_place {
253
- outputs. push ( (
254
- asm_gen. stack_slots_output [ i] . unwrap ( ) ,
255
- crate :: base:: codegen_place ( fx, out_place) ,
256
- ) ) ;
322
+ outputs. push ( ( asm_gen. stack_slots_output [ i] . unwrap ( ) , out_place. clone ( ) ) ) ;
257
323
}
258
324
}
259
- InlineAsmOperand :: Const { value : _ } => todo ! ( ) ,
260
- InlineAsmOperand :: SymFn { value : _ } => todo ! ( ) ,
261
- InlineAsmOperand :: SymStatic { def_id : _ } => todo ! ( ) ,
325
+ CInlineAsmOperand :: Const { value : _ } | CInlineAsmOperand :: Symbol { symbol : _ } => { }
262
326
}
263
327
}
264
328
@@ -280,7 +344,7 @@ struct InlineAssemblyGenerator<'a, 'tcx> {
280
344
arch : InlineAsmArch ,
281
345
enclosing_def_id : DefId ,
282
346
template : & ' a [ InlineAsmTemplatePiece ] ,
283
- operands : & ' a [ InlineAsmOperand < ' tcx > ] ,
347
+ operands : & ' a [ CInlineAsmOperand < ' tcx > ] ,
284
348
options : InlineAsmOptions ,
285
349
registers : Vec < Option < InlineAsmReg > > ,
286
350
stack_slots_clobber : Vec < Option < Size > > ,
@@ -304,18 +368,20 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
304
368
// Add explicit registers to the allocated set.
305
369
for ( i, operand) in self . operands . iter ( ) . enumerate ( ) {
306
370
match * operand {
307
- InlineAsmOperand :: In { reg : InlineAsmRegOrRegClass :: Reg ( reg) , .. } => {
371
+ CInlineAsmOperand :: In { reg : InlineAsmRegOrRegClass :: Reg ( reg) , .. } => {
308
372
regs[ i] = Some ( reg) ;
309
373
allocated. entry ( reg) . or_default ( ) . 0 = true ;
310
374
}
311
- InlineAsmOperand :: Out {
312
- reg : InlineAsmRegOrRegClass :: Reg ( reg) , late : true , ..
375
+ CInlineAsmOperand :: Out {
376
+ reg : InlineAsmRegOrRegClass :: Reg ( reg) ,
377
+ late : true ,
378
+ ..
313
379
} => {
314
380
regs[ i] = Some ( reg) ;
315
381
allocated. entry ( reg) . or_default ( ) . 1 = true ;
316
382
}
317
- InlineAsmOperand :: Out { reg : InlineAsmRegOrRegClass :: Reg ( reg) , .. }
318
- | InlineAsmOperand :: InOut { reg : InlineAsmRegOrRegClass :: Reg ( reg) , .. } => {
383
+ CInlineAsmOperand :: Out { reg : InlineAsmRegOrRegClass :: Reg ( reg) , .. }
384
+ | CInlineAsmOperand :: InOut { reg : InlineAsmRegOrRegClass :: Reg ( reg) , .. } => {
319
385
regs[ i] = Some ( reg) ;
320
386
allocated. insert ( reg, ( true , true ) ) ;
321
387
}
@@ -326,12 +392,12 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
326
392
// Allocate out/inout/inlateout registers first because they are more constrained.
327
393
for ( i, operand) in self . operands . iter ( ) . enumerate ( ) {
328
394
match * operand {
329
- InlineAsmOperand :: Out {
395
+ CInlineAsmOperand :: Out {
330
396
reg : InlineAsmRegOrRegClass :: RegClass ( class) ,
331
397
late : false ,
332
398
..
333
399
}
334
- | InlineAsmOperand :: InOut {
400
+ | CInlineAsmOperand :: InOut {
335
401
reg : InlineAsmRegOrRegClass :: RegClass ( class) , ..
336
402
} => {
337
403
let mut alloc_reg = None ;
@@ -360,7 +426,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
360
426
// Allocate in/lateout.
361
427
for ( i, operand) in self . operands . iter ( ) . enumerate ( ) {
362
428
match * operand {
363
- InlineAsmOperand :: In { reg : InlineAsmRegOrRegClass :: RegClass ( class) , .. } => {
429
+ CInlineAsmOperand :: In { reg : InlineAsmRegOrRegClass :: RegClass ( class) , .. } => {
364
430
let mut alloc_reg = None ;
365
431
for & reg in & map[ & class] {
366
432
let mut used = false ;
@@ -380,7 +446,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
380
446
regs[ i] = Some ( reg) ;
381
447
allocated. entry ( reg) . or_default ( ) . 0 = true ;
382
448
}
383
- InlineAsmOperand :: Out {
449
+ CInlineAsmOperand :: Out {
384
450
reg : InlineAsmRegOrRegClass :: RegClass ( class) ,
385
451
late : true ,
386
452
..
@@ -455,7 +521,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
455
521
// Allocate stack slots for inout
456
522
for ( i, operand) in self . operands . iter ( ) . enumerate ( ) {
457
523
match * operand {
458
- InlineAsmOperand :: InOut { reg, out_place : Some ( _) , .. } => {
524
+ CInlineAsmOperand :: InOut { reg, out_place : Some ( _) , .. } => {
459
525
let slot = new_slot ( reg. reg_class ( ) ) ;
460
526
slots_input[ i] = Some ( slot) ;
461
527
slots_output[ i] = Some ( slot) ;
@@ -470,8 +536,8 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
470
536
// Allocate stack slots for input
471
537
for ( i, operand) in self . operands . iter ( ) . enumerate ( ) {
472
538
match * operand {
473
- InlineAsmOperand :: In { reg, .. }
474
- | InlineAsmOperand :: InOut { reg, out_place : None , .. } => {
539
+ CInlineAsmOperand :: In { reg, .. }
540
+ | CInlineAsmOperand :: InOut { reg, out_place : None , .. } => {
475
541
slots_input[ i] = Some ( new_slot ( reg. reg_class ( ) ) ) ;
476
542
}
477
543
_ => ( ) ,
@@ -487,7 +553,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
487
553
// Allocate stack slots for output
488
554
for ( i, operand) in self . operands . iter ( ) . enumerate ( ) {
489
555
match * operand {
490
- InlineAsmOperand :: Out { reg, place : Some ( _) , .. } => {
556
+ CInlineAsmOperand :: Out { reg, place : Some ( _) , .. } => {
491
557
slots_output[ i] = Some ( new_slot ( reg. reg_class ( ) ) ) ;
492
558
}
493
559
_ => ( ) ,
@@ -549,13 +615,23 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
549
615
generated_asm. push_str ( s) ;
550
616
}
551
617
InlineAsmTemplatePiece :: Placeholder { operand_idx, modifier, span : _ } => {
552
- if self . options . contains ( InlineAsmOptions :: ATT_SYNTAX ) {
553
- generated_asm. push ( '%' ) ;
618
+ match self . operands [ * operand_idx] {
619
+ CInlineAsmOperand :: In { .. }
620
+ | CInlineAsmOperand :: Out { .. }
621
+ | CInlineAsmOperand :: InOut { .. } => {
622
+ if self . options . contains ( InlineAsmOptions :: ATT_SYNTAX ) {
623
+ generated_asm. push ( '%' ) ;
624
+ }
625
+ self . registers [ * operand_idx]
626
+ . unwrap ( )
627
+ . emit ( & mut generated_asm, self . arch , * modifier)
628
+ . unwrap ( ) ;
629
+ }
630
+ CInlineAsmOperand :: Const { ref value } => {
631
+ generated_asm. push_str ( value) ;
632
+ }
633
+ CInlineAsmOperand :: Symbol { symbol } => generated_asm. push_str ( symbol. name ) ,
554
634
}
555
- self . registers [ * operand_idx]
556
- . unwrap ( )
557
- . emit ( & mut generated_asm, self . arch , * modifier)
558
- . unwrap ( ) ;
559
635
}
560
636
}
561
637
}
0 commit comments