Skip to content

Commit 8f6779b

Browse files
committed
create a FunctionCx and properly evaluate consts
1 parent d1efe8c commit 8f6779b

File tree

2 files changed

+86
-79
lines changed

2 files changed

+86
-79
lines changed

compiler/rustc_codegen_ssa/src/mir/mod.rs

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -167,16 +167,37 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
167167

168168
let llfn = cx.get_fn(instance);
169169

170-
if cx.tcx().has_attr(instance.def.def_id(), rustc_span::sym::naked) {
171-
crate::mir::naked_asm::codegen_naked_asm::<Bx>(cx, instance);
172-
return;
173-
}
174-
175170
let mir = cx.tcx().instance_mir(instance.def);
176171

177172
let fn_abi = cx.fn_abi_of_instance(instance, ty::List::empty());
178173
debug!("fn_abi: {:?}", fn_abi);
179174

175+
if cx.tcx().has_attr(instance.def.def_id(), rustc_span::sym::naked) {
176+
let cached_llbbs = IndexVec::new();
177+
178+
let fx: FunctionCx<'_, '_, Bx> = FunctionCx {
179+
instance,
180+
mir,
181+
llfn,
182+
fn_abi,
183+
cx,
184+
personality_slot: None,
185+
cached_llbbs,
186+
unreachable_block: None,
187+
terminate_block: None,
188+
cleanup_kinds: None,
189+
landing_pads: IndexVec::from_elem(None, &mir.basic_blocks),
190+
funclets: IndexVec::from_fn_n(|_| None, mir.basic_blocks.len()),
191+
locals: locals::Locals::empty(),
192+
debug_context: None,
193+
per_local_var_debug_info: None,
194+
caller_location: None,
195+
};
196+
197+
fx.codegen_naked_asm(instance);
198+
return;
199+
}
200+
180201
let debug_context = cx.create_function_debug_context(instance, fn_abi, llfn, mir);
181202

182203
let start_llbb = Bx::append_block(cx, llfn, "start");

compiler/rustc_codegen_ssa/src/mir/naked_asm.rs

Lines changed: 60 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,75 @@
11
use crate::common;
2+
use crate::mir::FunctionCx;
23
use crate::traits::{AsmMethods, BuilderMethods, GlobalAsmOperandRef};
34
use rustc_middle::bug;
4-
use rustc_middle::mir::{Const, InlineAsmOperand};
5+
use rustc_middle::mir::InlineAsmOperand;
56
use rustc_middle::ty;
67
use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
78
use rustc_middle::ty::{Instance, TyCtxt};
89

910
use rustc_span::sym;
1011
use rustc_target::asm::InlineAsmArch;
1112

12-
pub fn codegen_naked_asm<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
13-
cx: &'a Bx::CodegenCx,
14-
instance: Instance<'tcx>,
15-
) {
16-
let mir = cx.tcx().instance_mir(instance.def);
17-
18-
let rustc_middle::mir::TerminatorKind::InlineAsm {
19-
template,
20-
ref operands,
21-
options,
22-
line_spans,
23-
targets: _,
24-
unwind: _,
25-
} = mir.basic_blocks.iter().next().unwrap().terminator().kind
26-
else {
27-
bug!("#[naked] functions should always terminate with an asm! block")
28-
};
29-
30-
let operands: Vec<_> = operands
31-
.iter()
32-
.map(|op| crate::mir::naked_asm::inline_to_global_operand::<Bx>(cx, op))
33-
.collect();
34-
35-
let (begin, end) = crate::mir::naked_asm::prefix_and_suffix(cx.tcx(), instance);
13+
impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
14+
pub fn codegen_naked_asm(&self, instance: Instance<'tcx>) {
15+
let cx = &self.cx;
16+
17+
let rustc_middle::mir::TerminatorKind::InlineAsm {
18+
template,
19+
ref operands,
20+
options,
21+
line_spans,
22+
targets: _,
23+
unwind: _,
24+
} = self.mir.basic_blocks.iter().next().unwrap().terminator().kind
25+
else {
26+
bug!("#[naked] functions should always terminate with an asm! block")
27+
};
28+
29+
let operands: Vec<_> =
30+
operands.iter().map(|op| self.inline_to_global_operand(op)).collect();
31+
32+
let (begin, end) = crate::mir::naked_asm::prefix_and_suffix(cx.tcx(), instance);
33+
34+
let mut template_vec = Vec::new();
35+
template_vec.push(rustc_ast::ast::InlineAsmTemplatePiece::String(begin));
36+
template_vec.extend(template.iter().cloned());
37+
template_vec.push(rustc_ast::ast::InlineAsmTemplatePiece::String(end));
38+
39+
cx.codegen_global_asm(&template_vec, &operands, options, line_spans);
40+
}
3641

37-
let mut template_vec = Vec::new();
38-
template_vec.push(rustc_ast::ast::InlineAsmTemplatePiece::String(begin));
39-
template_vec.extend(template.iter().cloned());
40-
template_vec.push(rustc_ast::ast::InlineAsmTemplatePiece::String(end));
42+
fn inline_to_global_operand(&self, op: &InlineAsmOperand<'tcx>) -> GlobalAsmOperandRef<'tcx> {
43+
match op {
44+
InlineAsmOperand::Const { value } => {
45+
let const_value = self.eval_mir_constant(value);
46+
let string = common::asm_const_to_str(
47+
self.cx.tcx(),
48+
value.span,
49+
const_value,
50+
self.cx.layout_of(value.ty()),
51+
);
52+
GlobalAsmOperandRef::Const { string }
53+
}
54+
InlineAsmOperand::SymFn { value } => {
55+
let instance = match value.ty().kind() {
56+
&ty::FnDef(def_id, args) => Instance::new(def_id, args),
57+
_ => bug!("asm sym is not a function"),
58+
};
4159

42-
cx.codegen_global_asm(&template_vec, &operands, options, line_spans);
60+
GlobalAsmOperandRef::SymFn { instance }
61+
}
62+
InlineAsmOperand::SymStatic { def_id } => {
63+
GlobalAsmOperandRef::SymStatic { def_id: *def_id }
64+
}
65+
InlineAsmOperand::In { .. }
66+
| InlineAsmOperand::Out { .. }
67+
| InlineAsmOperand::InOut { .. }
68+
| InlineAsmOperand::Label { .. } => {
69+
bug!("invalid operand type for naked_asm!")
70+
}
71+
}
72+
}
4373
}
4474

4575
enum AsmBinaryFormat {
@@ -179,47 +209,3 @@ fn prefix_and_suffix<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> (Stri
179209

180210
(begin, end)
181211
}
182-
183-
fn inline_to_global_operand<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
184-
cx: &'a Bx::CodegenCx,
185-
op: &InlineAsmOperand<'tcx>,
186-
) -> GlobalAsmOperandRef<'tcx> {
187-
match op {
188-
InlineAsmOperand::Const { value } => match value.const_ {
189-
Const::Ty(_ty, _const_) => todo!(),
190-
Const::Unevaluated(_unevaluated_const, _ty) => todo!(),
191-
Const::Val(const_value, ty) => {
192-
let string = common::asm_const_to_str(
193-
cx.tcx(),
194-
value.span,
195-
const_value.clone(),
196-
cx.layout_of(ty),
197-
);
198-
GlobalAsmOperandRef::Const { string }
199-
}
200-
},
201-
InlineAsmOperand::SymFn { value } => {
202-
let instance = match value.const_ {
203-
// &ty::FnDef(def_id, args) => Instance::new(def_id, args),
204-
// _ => bug!("asm sym is not a function"),
205-
Const::Ty(_ty, _const_) => todo!(),
206-
Const::Unevaluated(_unevaluated_const, _ty) => todo!(),
207-
Const::Val(_, ty) => match ty.kind() {
208-
ty::FnDef(def_id, args) => Instance::new(*def_id, *args),
209-
_ => bug!("asm sym is not a function"),
210-
},
211-
};
212-
213-
GlobalAsmOperandRef::SymFn { instance }
214-
}
215-
InlineAsmOperand::SymStatic { def_id } => {
216-
GlobalAsmOperandRef::SymStatic { def_id: *def_id }
217-
}
218-
InlineAsmOperand::In { .. }
219-
| InlineAsmOperand::Out { .. }
220-
| InlineAsmOperand::InOut { .. }
221-
| InlineAsmOperand::Label { .. } => {
222-
bug!("invalid operand type for naked_asm!")
223-
}
224-
}
225-
}

0 commit comments

Comments
 (0)