Skip to content

Commit 894468a

Browse files
committed
Move stack slot allocation to a new fn
1 parent f16d27a commit 894468a

File tree

1 file changed

+70
-23
lines changed

1 file changed

+70
-23
lines changed

src/inline_asm.rs

Lines changed: 70 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -103,70 +103,60 @@ pub(crate) fn codegen_inline_asm<'tcx>(
103103
crate::trap::trap_unimplemented(fx, "Alloca is not supported");
104104
}
105105

106-
let mut slot_size = Size::from_bytes(0);
107106
let mut clobbered_regs = Vec::new();
108107
let mut inputs = Vec::new();
109108
let mut outputs = Vec::new();
110109

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-
125110
let mut asm_gen = InlineAssemblyGenerator {
126111
tcx: fx.tcx,
127112
arch: InlineAsmArch::X86_64,
128113
template,
129114
operands,
130115
options,
131116
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),
132121
};
133122
asm_gen.allocate_registers();
123+
asm_gen.allocate_stack_slots();
134124

135125
// FIXME overlap input and output slots to save stack space
136126
for (i, operand) in operands.iter().enumerate() {
137127
match *operand {
138128
InlineAsmOperand::In { reg, ref value } => {
139129
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()));
141131
inputs.push((
142132
reg,
143-
new_slot(reg.reg_class()),
133+
asm_gen.stack_slots_input[i].unwrap(),
144134
crate::base::codegen_operand(fx, value).load_scalar(fx),
145135
));
146136
}
147137
InlineAsmOperand::Out { reg, late: _, place } => {
148138
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()));
150140
if let Some(place) = place {
151141
outputs.push((
152142
reg,
153-
new_slot(reg.reg_class()),
143+
asm_gen.stack_slots_output[i].unwrap(),
154144
crate::base::codegen_place(fx, place),
155145
));
156146
}
157147
}
158148
InlineAsmOperand::InOut { reg, late: _, ref in_value, out_place } => {
159149
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()));
161151
inputs.push((
162152
reg,
163-
new_slot(reg.reg_class()),
153+
asm_gen.stack_slots_input[i].unwrap(),
164154
crate::base::codegen_operand(fx, in_value).load_scalar(fx),
165155
));
166156
if let Some(out_place) = out_place {
167157
outputs.push((
168158
reg,
169-
new_slot(reg.reg_class()),
159+
asm_gen.stack_slots_output[i].unwrap(),
170160
crate::base::codegen_place(fx, out_place),
171161
));
172162
}
@@ -184,7 +174,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
184174
let generated_asm = asm_gen.generate_asm_wrapper(&asm_name, clobbered_regs, &inputs, &outputs);
185175
fx.cx.global_asm.push_str(&generated_asm);
186176

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);
188178
}
189179

190180
struct InlineAssemblyGenerator<'a, 'tcx> {
@@ -194,6 +184,10 @@ struct InlineAssemblyGenerator<'a, 'tcx> {
194184
operands: &'a [InlineAsmOperand<'tcx>],
195185
options: InlineAsmOptions,
196186
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,
197191
}
198192

199193
impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
@@ -317,6 +311,59 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
317311
self.registers = regs;
318312
}
319313

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+
320367
fn generate_asm_wrapper(
321368
&self,
322369
asm_name: &str,

0 commit comments

Comments
 (0)