@@ -103,7 +103,6 @@ pub(crate) fn codegen_inline_asm<'tcx>(
103
103
crate :: trap:: trap_unimplemented ( fx, "Alloca is not supported" ) ;
104
104
}
105
105
106
- let mut clobbered_regs = Vec :: new ( ) ;
107
106
let mut inputs = Vec :: new ( ) ;
108
107
let mut outputs = Vec :: new ( ) ;
109
108
@@ -122,40 +121,37 @@ pub(crate) fn codegen_inline_asm<'tcx>(
122
121
asm_gen. allocate_registers ( ) ;
123
122
asm_gen. allocate_stack_slots ( ) ;
124
123
124
+ let inline_asm_index = fx. inline_asm_index ;
125
+ fx. inline_asm_index += 1 ;
126
+ let asm_name = format ! ( "{}__inline_asm_{}" , fx. symbol_name, inline_asm_index) ;
127
+
128
+ let generated_asm = asm_gen. generate_asm_wrapper ( & asm_name) ;
129
+ fx. cx . global_asm . push_str ( & generated_asm) ;
130
+
125
131
// FIXME overlap input and output slots to save stack space
126
132
for ( i, operand) in operands. iter ( ) . enumerate ( ) {
127
133
match * operand {
128
- InlineAsmOperand :: In { reg, ref value } => {
129
- let reg = asm_gen. registers [ i] . unwrap ( ) ;
130
- clobbered_regs. push ( ( reg, asm_gen. stack_slots_clobber [ i] . unwrap ( ) ) ) ;
134
+ InlineAsmOperand :: In { reg : _, ref value } => {
131
135
inputs. push ( (
132
- reg,
133
136
asm_gen. stack_slots_input [ i] . unwrap ( ) ,
134
137
crate :: base:: codegen_operand ( fx, value) . load_scalar ( fx) ,
135
138
) ) ;
136
139
}
137
- InlineAsmOperand :: Out { reg, late : _, place } => {
138
- let reg = asm_gen. registers [ i] . unwrap ( ) ;
139
- clobbered_regs. push ( ( reg, asm_gen. stack_slots_clobber [ i] . unwrap ( ) ) ) ;
140
+ InlineAsmOperand :: Out { reg : _, late : _, place } => {
140
141
if let Some ( place) = place {
141
142
outputs. push ( (
142
- reg,
143
143
asm_gen. stack_slots_output [ i] . unwrap ( ) ,
144
144
crate :: base:: codegen_place ( fx, place) ,
145
145
) ) ;
146
146
}
147
147
}
148
- InlineAsmOperand :: InOut { reg, late : _, ref in_value, out_place } => {
149
- let reg = asm_gen. registers [ i] . unwrap ( ) ;
150
- clobbered_regs. push ( ( reg, asm_gen. stack_slots_clobber [ i] . unwrap ( ) ) ) ;
148
+ InlineAsmOperand :: InOut { reg : _, late : _, ref in_value, out_place } => {
151
149
inputs. push ( (
152
- reg,
153
150
asm_gen. stack_slots_input [ i] . unwrap ( ) ,
154
151
crate :: base:: codegen_operand ( fx, in_value) . load_scalar ( fx) ,
155
152
) ) ;
156
153
if let Some ( out_place) = out_place {
157
154
outputs. push ( (
158
- reg,
159
155
asm_gen. stack_slots_output [ i] . unwrap ( ) ,
160
156
crate :: base:: codegen_place ( fx, out_place) ,
161
157
) ) ;
@@ -167,13 +163,6 @@ pub(crate) fn codegen_inline_asm<'tcx>(
167
163
}
168
164
}
169
165
170
- let inline_asm_index = fx. inline_asm_index ;
171
- fx. inline_asm_index += 1 ;
172
- let asm_name = format ! ( "{}__inline_asm_{}" , fx. symbol_name, inline_asm_index) ;
173
-
174
- let generated_asm = asm_gen. generate_asm_wrapper ( & asm_name, clobbered_regs, & inputs, & outputs) ;
175
- fx. cx . global_asm . push_str ( & generated_asm) ;
176
-
177
166
call_inline_asm ( fx, & asm_name, asm_gen. stack_slot_size , inputs, outputs) ;
178
167
}
179
168
@@ -364,13 +353,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
364
353
self . stack_slot_size = slot_size;
365
354
}
366
355
367
- fn generate_asm_wrapper (
368
- & self ,
369
- asm_name : & str ,
370
- clobbered_regs : Vec < ( InlineAsmReg , Size ) > ,
371
- inputs : & [ ( InlineAsmReg , Size , Value ) ] ,
372
- outputs : & [ ( InlineAsmReg , Size , CPlace < ' _ > ) ] ,
373
- ) -> String {
356
+ fn generate_asm_wrapper ( & self , asm_name : & str ) -> String {
374
357
let mut generated_asm = String :: new ( ) ;
375
358
writeln ! ( generated_asm, ".globl {}" , asm_name) . unwrap ( ) ;
376
359
writeln ! ( generated_asm, ".type {},@function" , asm_name) . unwrap ( ) ;
@@ -384,14 +367,24 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
384
367
// Save clobbered registers
385
368
if !self . options . contains ( InlineAsmOptions :: NORETURN ) {
386
369
// FIXME skip registers saved by the calling convention
387
- for & ( reg, offset) in & clobbered_regs {
388
- save_register ( & mut generated_asm, self . arch , reg, offset) ;
370
+ for ( reg, slot) in self
371
+ . registers
372
+ . iter ( )
373
+ . zip ( self . stack_slots_clobber . iter ( ) . copied ( ) )
374
+ . filter_map ( |( r, s) | r. zip ( s) )
375
+ {
376
+ save_register ( & mut generated_asm, self . arch , reg, slot) ;
389
377
}
390
378
}
391
379
392
380
// Write input registers
393
- for & ( reg, offset, _value) in inputs {
394
- restore_register ( & mut generated_asm, self . arch , reg, offset) ;
381
+ for ( reg, slot) in self
382
+ . registers
383
+ . iter ( )
384
+ . zip ( self . stack_slots_input . iter ( ) . copied ( ) )
385
+ . filter_map ( |( r, s) | r. zip ( s) )
386
+ {
387
+ restore_register ( & mut generated_asm, self . arch , reg, slot) ;
395
388
}
396
389
397
390
if self . options . contains ( InlineAsmOptions :: ATT_SYNTAX ) {
@@ -414,19 +407,29 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
414
407
}
415
408
generated_asm. push ( '\n' ) ;
416
409
417
- if self . options . contains ( InlineAsmOptions :: ATT_SYNTAX ) {
410
+ if is_x86 && self . options . contains ( InlineAsmOptions :: ATT_SYNTAX ) {
418
411
generated_asm. push_str ( ".intel_syntax noprefix\n " ) ;
419
412
}
420
413
421
414
if !self . options . contains ( InlineAsmOptions :: NORETURN ) {
422
415
// Read output registers
423
- for & ( reg, offset, _place) in outputs {
424
- save_register ( & mut generated_asm, self . arch , reg, offset) ;
416
+ for ( reg, slot) in self
417
+ . registers
418
+ . iter ( )
419
+ . zip ( self . stack_slots_output . iter ( ) . copied ( ) )
420
+ . filter_map ( |( r, s) | r. zip ( s) )
421
+ {
422
+ save_register ( & mut generated_asm, self . arch , reg, slot) ;
425
423
}
426
424
427
425
// Restore clobbered registers
428
- for & ( reg, offset) in clobbered_regs. iter ( ) . rev ( ) {
429
- restore_register ( & mut generated_asm, self . arch , reg, offset) ;
426
+ for ( reg, slot) in self
427
+ . registers
428
+ . iter ( )
429
+ . zip ( self . stack_slots_clobber . iter ( ) . copied ( ) )
430
+ . filter_map ( |( r, s) | r. zip ( s) )
431
+ {
432
+ restore_register ( & mut generated_asm, self . arch , reg, slot) ;
430
433
}
431
434
432
435
generated_asm. push_str ( " pop rbp\n " ) ;
@@ -448,8 +451,8 @@ fn call_inline_asm<'tcx>(
448
451
fx : & mut FunctionCx < ' _ , ' _ , ' tcx > ,
449
452
asm_name : & str ,
450
453
slot_size : Size ,
451
- inputs : Vec < ( InlineAsmReg , Size , Value ) > ,
452
- outputs : Vec < ( InlineAsmReg , Size , CPlace < ' tcx > ) > ,
454
+ inputs : Vec < ( Size , Value ) > ,
455
+ outputs : Vec < ( Size , CPlace < ' tcx > ) > ,
453
456
) {
454
457
let stack_slot = fx. bcx . func . create_stack_slot ( StackSlotData {
455
458
kind : StackSlotKind :: ExplicitSlot ,
@@ -476,14 +479,14 @@ fn call_inline_asm<'tcx>(
476
479
fx. add_comment ( inline_asm_func, asm_name) ;
477
480
}
478
481
479
- for ( _reg , offset, value) in inputs {
482
+ for ( offset, value) in inputs {
480
483
fx. bcx . ins ( ) . stack_store ( value, stack_slot, i32:: try_from ( offset. bytes ( ) ) . unwrap ( ) ) ;
481
484
}
482
485
483
486
let stack_slot_addr = fx. bcx . ins ( ) . stack_addr ( fx. pointer_type , stack_slot, 0 ) ;
484
487
fx. bcx . ins ( ) . call ( inline_asm_func, & [ stack_slot_addr] ) ;
485
488
486
- for ( _reg , offset, place) in outputs {
489
+ for ( offset, place) in outputs {
487
490
let ty = fx. clif_type ( place. layout ( ) . ty ) . unwrap ( ) ;
488
491
let value = fx. bcx . ins ( ) . stack_load ( ty, stack_slot, i32:: try_from ( offset. bytes ( ) ) . unwrap ( ) ) ;
489
492
place. write_cvalue ( fx, CValue :: by_val ( value, place. layout ( ) ) ) ;
0 commit comments