@@ -103,70 +103,60 @@ 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 slot_size = Size :: from_bytes ( 0 ) ;
107
106
let mut clobbered_regs = Vec :: new ( ) ;
108
107
let mut inputs = Vec :: new ( ) ;
109
108
let mut outputs = Vec :: new ( ) ;
110
109
111
- let mut new_slot = |reg_class : InlineAsmRegClass | {
112
- let reg_size = reg_class
113
- . supported_types ( InlineAsmArch :: X86_64 )
114
- . iter ( )
115
- . map ( |( ty, _) | ty. size ( ) )
116
- . max ( )
117
- . unwrap ( ) ;
118
- let align = rustc_target:: abi:: Align :: from_bytes ( reg_size. bytes ( ) ) . unwrap ( ) ;
119
- slot_size = slot_size. align_to ( align) ;
120
- let offset = slot_size;
121
- slot_size += reg_size;
122
- offset
123
- } ;
124
-
125
110
let mut asm_gen = InlineAssemblyGenerator {
126
111
tcx : fx. tcx ,
127
112
arch : InlineAsmArch :: X86_64 ,
128
113
template,
129
114
operands,
130
115
options,
131
116
registers : Vec :: new ( ) ,
117
+ stack_slots_clobber : Vec :: new ( ) ,
118
+ stack_slots_input : Vec :: new ( ) ,
119
+ stack_slots_output : Vec :: new ( ) ,
120
+ stack_slot_size : Size :: from_bytes ( 0 ) ,
132
121
} ;
133
122
asm_gen. allocate_registers ( ) ;
123
+ asm_gen. allocate_stack_slots ( ) ;
134
124
135
125
// FIXME overlap input and output slots to save stack space
136
126
for ( i, operand) in operands. iter ( ) . enumerate ( ) {
137
127
match * operand {
138
128
InlineAsmOperand :: In { reg, ref value } => {
139
129
let reg = asm_gen. registers [ i] . unwrap ( ) ;
140
- clobbered_regs. push ( ( reg, new_slot ( reg . reg_class ( ) ) ) ) ;
130
+ clobbered_regs. push ( ( reg, asm_gen . stack_slots_clobber [ i ] . unwrap ( ) ) ) ;
141
131
inputs. push ( (
142
132
reg,
143
- new_slot ( reg . reg_class ( ) ) ,
133
+ asm_gen . stack_slots_input [ i ] . unwrap ( ) ,
144
134
crate :: base:: codegen_operand ( fx, value) . load_scalar ( fx) ,
145
135
) ) ;
146
136
}
147
137
InlineAsmOperand :: Out { reg, late : _, place } => {
148
138
let reg = asm_gen. registers [ i] . unwrap ( ) ;
149
- clobbered_regs. push ( ( reg, new_slot ( reg . reg_class ( ) ) ) ) ;
139
+ clobbered_regs. push ( ( reg, asm_gen . stack_slots_clobber [ i ] . unwrap ( ) ) ) ;
150
140
if let Some ( place) = place {
151
141
outputs. push ( (
152
142
reg,
153
- new_slot ( reg . reg_class ( ) ) ,
143
+ asm_gen . stack_slots_output [ i ] . unwrap ( ) ,
154
144
crate :: base:: codegen_place ( fx, place) ,
155
145
) ) ;
156
146
}
157
147
}
158
148
InlineAsmOperand :: InOut { reg, late : _, ref in_value, out_place } => {
159
149
let reg = asm_gen. registers [ i] . unwrap ( ) ;
160
- clobbered_regs. push ( ( reg, new_slot ( reg . reg_class ( ) ) ) ) ;
150
+ clobbered_regs. push ( ( reg, asm_gen . stack_slots_clobber [ i ] . unwrap ( ) ) ) ;
161
151
inputs. push ( (
162
152
reg,
163
- new_slot ( reg . reg_class ( ) ) ,
153
+ asm_gen . stack_slots_input [ i ] . unwrap ( ) ,
164
154
crate :: base:: codegen_operand ( fx, in_value) . load_scalar ( fx) ,
165
155
) ) ;
166
156
if let Some ( out_place) = out_place {
167
157
outputs. push ( (
168
158
reg,
169
- new_slot ( reg . reg_class ( ) ) ,
159
+ asm_gen . stack_slots_output [ i ] . unwrap ( ) ,
170
160
crate :: base:: codegen_place ( fx, out_place) ,
171
161
) ) ;
172
162
}
@@ -184,7 +174,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
184
174
let generated_asm = asm_gen. generate_asm_wrapper ( & asm_name, clobbered_regs, & inputs, & outputs) ;
185
175
fx. cx . global_asm . push_str ( & generated_asm) ;
186
176
187
- call_inline_asm ( fx, & asm_name, slot_size , inputs, outputs) ;
177
+ call_inline_asm ( fx, & asm_name, asm_gen . stack_slot_size , inputs, outputs) ;
188
178
}
189
179
190
180
struct InlineAssemblyGenerator < ' a , ' tcx > {
@@ -194,6 +184,10 @@ struct InlineAssemblyGenerator<'a, 'tcx> {
194
184
operands : & ' a [ InlineAsmOperand < ' tcx > ] ,
195
185
options : InlineAsmOptions ,
196
186
registers : Vec < Option < InlineAsmReg > > ,
187
+ stack_slots_clobber : Vec < Option < Size > > ,
188
+ stack_slots_input : Vec < Option < Size > > ,
189
+ stack_slots_output : Vec < Option < Size > > ,
190
+ stack_slot_size : Size ,
197
191
}
198
192
199
193
impl < ' tcx > InlineAssemblyGenerator < ' _ , ' tcx > {
@@ -317,6 +311,59 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
317
311
self . registers = regs;
318
312
}
319
313
314
+ fn allocate_stack_slots ( & mut self ) {
315
+ let mut slot_size = Size :: from_bytes ( 0 ) ;
316
+ let mut slots_clobber = vec ! [ None ; self . operands. len( ) ] ;
317
+ let mut slots_input = vec ! [ None ; self . operands. len( ) ] ;
318
+ let mut slots_output = vec ! [ None ; self . operands. len( ) ] ;
319
+
320
+ let mut new_slot = |reg_class : InlineAsmRegClass | {
321
+ let reg_size = reg_class
322
+ . supported_types ( InlineAsmArch :: X86_64 )
323
+ . iter ( )
324
+ . map ( |( ty, _) | ty. size ( ) )
325
+ . max ( )
326
+ . unwrap ( ) ;
327
+ let align = rustc_target:: abi:: Align :: from_bytes ( reg_size. bytes ( ) ) . unwrap ( ) ;
328
+ slot_size = slot_size. align_to ( align) ;
329
+ let offset = slot_size;
330
+ slot_size += reg_size;
331
+ offset
332
+ } ;
333
+
334
+ // FIXME overlap input and output slots to save stack space
335
+ for ( i, operand) in self . operands . iter ( ) . enumerate ( ) {
336
+ match * operand {
337
+ InlineAsmOperand :: In { reg, .. } => {
338
+ slots_clobber[ i] = Some ( new_slot ( reg. reg_class ( ) ) ) ;
339
+ slots_input[ i] = Some ( new_slot ( reg. reg_class ( ) ) ) ;
340
+ }
341
+ InlineAsmOperand :: Out { reg, place, .. } => {
342
+ slots_clobber[ i] = Some ( new_slot ( reg. reg_class ( ) ) ) ;
343
+ if place. is_some ( ) {
344
+ slots_output[ i] = Some ( new_slot ( reg. reg_class ( ) ) ) ;
345
+ }
346
+ }
347
+ InlineAsmOperand :: InOut { reg, out_place, .. } => {
348
+ slots_clobber[ i] = Some ( new_slot ( reg. reg_class ( ) ) ) ;
349
+ let slot = new_slot ( reg. reg_class ( ) ) ;
350
+ slots_input[ i] = Some ( slot) ;
351
+ if out_place. is_some ( ) {
352
+ slots_output[ i] = Some ( slot) ;
353
+ }
354
+ }
355
+ InlineAsmOperand :: Const { value : _ } => ( ) ,
356
+ InlineAsmOperand :: SymFn { value : _ } => ( ) ,
357
+ InlineAsmOperand :: SymStatic { def_id : _ } => ( ) ,
358
+ }
359
+ }
360
+
361
+ self . stack_slots_clobber = slots_clobber;
362
+ self . stack_slots_input = slots_input;
363
+ self . stack_slots_output = slots_output;
364
+ self . stack_slot_size = slot_size;
365
+ }
366
+
320
367
fn generate_asm_wrapper (
321
368
& self ,
322
369
asm_name : & str ,
0 commit comments