Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 044a3a6

Browse files
committed
Support const and sym operands in inline asm
1 parent 8b48138 commit 044a3a6

File tree

1 file changed

+122
-46
lines changed

1 file changed

+122
-46
lines changed

src/inline_asm.rs

Lines changed: 122 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,37 @@ use std::fmt::Write;
66

77
use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
88
use rustc_middle::mir::InlineAsmOperand;
9+
use rustc_middle::ty::SymbolName;
910
use rustc_span::sym;
1011
use rustc_target::asm::*;
1112

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+
1237
pub(crate) fn codegen_inline_asm<'tcx>(
1338
fx: &mut FunctionCx<'_, '_, 'tcx>,
14-
_span: Span,
39+
span: Span,
1540
template: &[InlineAsmTemplatePiece],
1641
operands: &[InlineAsmOperand<'tcx>],
1742
options: InlineAsmOptions,
@@ -198,6 +223,59 @@ pub(crate) fn codegen_inline_asm<'tcx>(
198223
}
199224
}
200225

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+
201279
let mut inputs = Vec::new();
202280
let mut outputs = Vec::new();
203281

@@ -206,7 +284,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
206284
arch: fx.tcx.sess.asm_arch.unwrap(),
207285
enclosing_def_id: fx.instance.def_id(),
208286
template,
209-
operands,
287+
operands: &operands,
210288
options,
211289
registers: Vec::new(),
212290
stack_slots_clobber: Vec::new(),
@@ -229,36 +307,22 @@ pub(crate) fn codegen_inline_asm<'tcx>(
229307
fx.cx.global_asm.push_str(&generated_asm);
230308

231309
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 } => {
240315
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()));
245317
}
246318
}
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)));
252321
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()));
257323
}
258324
}
259-
InlineAsmOperand::Const { value: _ } => todo!(),
260-
InlineAsmOperand::SymFn { value: _ } => todo!(),
261-
InlineAsmOperand::SymStatic { def_id: _ } => todo!(),
325+
CInlineAsmOperand::Const { value: _ } | CInlineAsmOperand::Symbol { symbol: _ } => {}
262326
}
263327
}
264328

@@ -280,7 +344,7 @@ struct InlineAssemblyGenerator<'a, 'tcx> {
280344
arch: InlineAsmArch,
281345
enclosing_def_id: DefId,
282346
template: &'a [InlineAsmTemplatePiece],
283-
operands: &'a [InlineAsmOperand<'tcx>],
347+
operands: &'a [CInlineAsmOperand<'tcx>],
284348
options: InlineAsmOptions,
285349
registers: Vec<Option<InlineAsmReg>>,
286350
stack_slots_clobber: Vec<Option<Size>>,
@@ -304,18 +368,20 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
304368
// Add explicit registers to the allocated set.
305369
for (i, operand) in self.operands.iter().enumerate() {
306370
match *operand {
307-
InlineAsmOperand::In { reg: InlineAsmRegOrRegClass::Reg(reg), .. } => {
371+
CInlineAsmOperand::In { reg: InlineAsmRegOrRegClass::Reg(reg), .. } => {
308372
regs[i] = Some(reg);
309373
allocated.entry(reg).or_default().0 = true;
310374
}
311-
InlineAsmOperand::Out {
312-
reg: InlineAsmRegOrRegClass::Reg(reg), late: true, ..
375+
CInlineAsmOperand::Out {
376+
reg: InlineAsmRegOrRegClass::Reg(reg),
377+
late: true,
378+
..
313379
} => {
314380
regs[i] = Some(reg);
315381
allocated.entry(reg).or_default().1 = true;
316382
}
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), .. } => {
319385
regs[i] = Some(reg);
320386
allocated.insert(reg, (true, true));
321387
}
@@ -326,12 +392,12 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
326392
// Allocate out/inout/inlateout registers first because they are more constrained.
327393
for (i, operand) in self.operands.iter().enumerate() {
328394
match *operand {
329-
InlineAsmOperand::Out {
395+
CInlineAsmOperand::Out {
330396
reg: InlineAsmRegOrRegClass::RegClass(class),
331397
late: false,
332398
..
333399
}
334-
| InlineAsmOperand::InOut {
400+
| CInlineAsmOperand::InOut {
335401
reg: InlineAsmRegOrRegClass::RegClass(class), ..
336402
} => {
337403
let mut alloc_reg = None;
@@ -360,7 +426,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
360426
// Allocate in/lateout.
361427
for (i, operand) in self.operands.iter().enumerate() {
362428
match *operand {
363-
InlineAsmOperand::In { reg: InlineAsmRegOrRegClass::RegClass(class), .. } => {
429+
CInlineAsmOperand::In { reg: InlineAsmRegOrRegClass::RegClass(class), .. } => {
364430
let mut alloc_reg = None;
365431
for &reg in &map[&class] {
366432
let mut used = false;
@@ -380,7 +446,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
380446
regs[i] = Some(reg);
381447
allocated.entry(reg).or_default().0 = true;
382448
}
383-
InlineAsmOperand::Out {
449+
CInlineAsmOperand::Out {
384450
reg: InlineAsmRegOrRegClass::RegClass(class),
385451
late: true,
386452
..
@@ -455,7 +521,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
455521
// Allocate stack slots for inout
456522
for (i, operand) in self.operands.iter().enumerate() {
457523
match *operand {
458-
InlineAsmOperand::InOut { reg, out_place: Some(_), .. } => {
524+
CInlineAsmOperand::InOut { reg, out_place: Some(_), .. } => {
459525
let slot = new_slot(reg.reg_class());
460526
slots_input[i] = Some(slot);
461527
slots_output[i] = Some(slot);
@@ -470,8 +536,8 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
470536
// Allocate stack slots for input
471537
for (i, operand) in self.operands.iter().enumerate() {
472538
match *operand {
473-
InlineAsmOperand::In { reg, .. }
474-
| InlineAsmOperand::InOut { reg, out_place: None, .. } => {
539+
CInlineAsmOperand::In { reg, .. }
540+
| CInlineAsmOperand::InOut { reg, out_place: None, .. } => {
475541
slots_input[i] = Some(new_slot(reg.reg_class()));
476542
}
477543
_ => (),
@@ -487,7 +553,7 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
487553
// Allocate stack slots for output
488554
for (i, operand) in self.operands.iter().enumerate() {
489555
match *operand {
490-
InlineAsmOperand::Out { reg, place: Some(_), .. } => {
556+
CInlineAsmOperand::Out { reg, place: Some(_), .. } => {
491557
slots_output[i] = Some(new_slot(reg.reg_class()));
492558
}
493559
_ => (),
@@ -549,13 +615,23 @@ impl<'tcx> InlineAssemblyGenerator<'_, 'tcx> {
549615
generated_asm.push_str(s);
550616
}
551617
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),
554634
}
555-
self.registers[*operand_idx]
556-
.unwrap()
557-
.emit(&mut generated_asm, self.arch, *modifier)
558-
.unwrap();
559635
}
560636
}
561637
}

0 commit comments

Comments
 (0)