@@ -128,7 +128,6 @@ pub(crate) fn codegen_inline_asm<'tcx>(
128
128
let generated_asm = asm_gen. generate_asm_wrapper ( & asm_name) ;
129
129
fx. cx . global_asm . push_str ( & generated_asm) ;
130
130
131
- // FIXME overlap input and output slots to save stack space
132
131
for ( i, operand) in operands. iter ( ) . enumerate ( ) {
133
132
match * operand {
134
133
InlineAsmOperand :: In { reg : _, ref value } => {
@@ -306,19 +305,19 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
306
305
let mut slots_input = vec ! [ None ; self . operands. len( ) ] ;
307
306
let mut slots_output = vec ! [ None ; self . operands. len( ) ] ;
308
307
309
- let mut new_slot = |reg_class : InlineAsmRegClass | {
308
+ let new_slot_fn = |slot_size : & mut Size , reg_class : InlineAsmRegClass | {
310
309
let reg_size = reg_class
311
310
. supported_types ( InlineAsmArch :: X86_64 )
312
311
. iter ( )
313
312
. map ( |( ty, _) | ty. size ( ) )
314
313
. max ( )
315
314
. unwrap ( ) ;
316
315
let align = rustc_target:: abi:: Align :: from_bytes ( reg_size. bytes ( ) ) . unwrap ( ) ;
317
- slot_size = slot_size. align_to ( align) ;
318
- let offset = slot_size;
319
- slot_size += reg_size;
316
+ let offset = slot_size. align_to ( align) ;
317
+ * slot_size = offset + reg_size;
320
318
offset
321
319
} ;
320
+ let mut new_slot = |x| new_slot_fn ( & mut slot_size, x) ;
322
321
323
322
// Allocate stack slots for saving clobbered registers
324
323
let abi_clobber =
@@ -346,30 +345,50 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
346
345
}
347
346
}
348
347
349
- // FIXME overlap input and output slots to save stack space
348
+ // Allocate stack slots for inout
350
349
for ( i, operand) in self . operands . iter ( ) . enumerate ( ) {
351
350
match * operand {
352
- InlineAsmOperand :: In { reg, .. } => {
353
- slots_input[ i] = Some ( new_slot ( reg. reg_class ( ) ) ) ;
354
- }
355
- InlineAsmOperand :: Out { reg, place, .. } => {
356
- if place. is_some ( ) {
357
- slots_output[ i] = Some ( new_slot ( reg. reg_class ( ) ) ) ;
358
- }
359
- }
360
- InlineAsmOperand :: InOut { reg, out_place, .. } => {
351
+ InlineAsmOperand :: InOut { reg, out_place : Some ( _) , .. } => {
361
352
let slot = new_slot ( reg. reg_class ( ) ) ;
362
353
slots_input[ i] = Some ( slot) ;
363
- if out_place. is_some ( ) {
364
- slots_output[ i] = Some ( slot) ;
365
- }
354
+ slots_output[ i] = Some ( slot) ;
355
+ }
356
+ _ => ( ) ,
357
+ }
358
+ }
359
+
360
+ let slot_size_before_input = slot_size;
361
+ let mut new_slot = |x| new_slot_fn ( & mut slot_size, x) ;
362
+
363
+ // Allocate stack slots for input
364
+ for ( i, operand) in self . operands . iter ( ) . enumerate ( ) {
365
+ match * operand {
366
+ InlineAsmOperand :: In { reg, .. }
367
+ | InlineAsmOperand :: InOut { reg, out_place : None , .. } => {
368
+ slots_input[ i] = Some ( new_slot ( reg. reg_class ( ) ) ) ;
369
+ }
370
+ _ => ( ) ,
371
+ }
372
+ }
373
+
374
+ // Reset slot size to before input so that input and output operands can overlap
375
+ // and save some memory.
376
+ let slot_size_after_input = slot_size;
377
+ slot_size = slot_size_before_input;
378
+ let mut new_slot = |x| new_slot_fn ( & mut slot_size, x) ;
379
+
380
+ // Allocate stack slots for output
381
+ for ( i, operand) in self . operands . iter ( ) . enumerate ( ) {
382
+ match * operand {
383
+ InlineAsmOperand :: Out { reg, place : Some ( _) , .. } => {
384
+ slots_output[ i] = Some ( new_slot ( reg. reg_class ( ) ) ) ;
366
385
}
367
- InlineAsmOperand :: Const { value : _ } => ( ) ,
368
- InlineAsmOperand :: SymFn { value : _ } => ( ) ,
369
- InlineAsmOperand :: SymStatic { def_id : _ } => ( ) ,
386
+ _ => ( ) ,
370
387
}
371
388
}
372
389
390
+ slot_size = slot_size. max ( slot_size_after_input) ;
391
+
373
392
self . stack_slots_clobber = slots_clobber;
374
393
self . stack_slots_input = slots_input;
375
394
self . stack_slots_output = slots_output;
0 commit comments