Skip to content

Commit 88f7ac0

Browse files
committed
Delay stringification of const to backend
1 parent 4224bd8 commit 88f7ac0

File tree

9 files changed

+111
-58
lines changed

9 files changed

+111
-58
lines changed

compiler/rustc_codegen_cranelift/src/global_asm.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,14 @@ fn codegen_global_asm_inner<'tcx>(
107107
InlineAsmTemplatePiece::String(ref s) => global_asm.push_str(s),
108108
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => {
109109
match operands[operand_idx] {
110-
GlobalAsmOperandRef::Const { ref string } => {
111-
global_asm.push_str(string);
110+
GlobalAsmOperandRef::Const { value, ty } => {
111+
let string = rustc_codegen_ssa::common::asm_const_to_str(
112+
tcx,
113+
span,
114+
value,
115+
FullyMonomorphizedLayoutCx(tcx).layout_of(ty),
116+
);
117+
global_asm.push_str(&string);
112118
}
113119
GlobalAsmOperandRef::SymFn { instance } => {
114120
if cfg!(not(feature = "inline_asm_sym")) {

compiler/rustc_codegen_cranelift/src/inline_asm.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,18 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
9494
}
9595
InlineAsmOperand::Const { ref value } => {
9696
let (const_value, ty) = crate::constant::eval_mir_constant(fx, value);
97+
let mir::ConstValue::Scalar(scalar) = const_value else {
98+
span_bug!(
99+
span,
100+
"expected Scalar for promoted asm const, but got {:#?}",
101+
const_value
102+
)
103+
};
104+
97105
let value = rustc_codegen_ssa::common::asm_const_to_str(
98106
fx.tcx,
99107
span,
100-
const_value,
108+
scalar,
101109
fx.layout_of(ty),
102110
);
103111
CInlineAsmOperand::Const { value }

compiler/rustc_codegen_gcc/src/asm.rs

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use rustc_codegen_ssa::traits::{
1212
};
1313
use rustc_middle::bug;
1414
use rustc_middle::ty::Instance;
15+
use rustc_middle::ty::layout::LayoutOf;
1516
use rustc_span::Span;
1617
use rustc_target::asm::*;
1718

@@ -303,8 +304,9 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
303304
}
304305
}
305306

306-
InlineAsmOperandRef::Const { ref string } => {
307-
constants_len += string.len() + att_dialect as usize;
307+
InlineAsmOperandRef::Const { .. } => {
308+
// We don't know the size at this point, just some estimate.
309+
constants_len += 20;
308310
}
309311

310312
InlineAsmOperandRef::SymFn { instance } => {
@@ -453,7 +455,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
453455
template_str.push_str(escaped_char);
454456
}
455457
}
456-
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span: _ } => {
458+
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span } => {
457459
let mut push_to_template = |modifier, gcc_idx| {
458460
use std::fmt::Write;
459461

@@ -511,8 +513,15 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
511513
template_str.push_str(name);
512514
}
513515

514-
InlineAsmOperandRef::Const { ref string } => {
515-
template_str.push_str(string);
516+
InlineAsmOperandRef::Const { value, ty } => {
517+
// Const operands get injected directly into the template
518+
let string = rustc_codegen_ssa::common::asm_const_to_str(
519+
self.tcx,
520+
span,
521+
value,
522+
self.layout_of(ty),
523+
);
524+
template_str.push_str(&string);
516525
}
517526

518527
InlineAsmOperandRef::Label { label } => {
@@ -891,13 +900,19 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
891900
.unwrap_or(string.len());
892901
}
893902
}
894-
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => {
903+
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => {
895904
match operands[operand_idx] {
896-
GlobalAsmOperandRef::Const { ref string } => {
905+
GlobalAsmOperandRef::Const { value, ty } => {
897906
// Const operands get injected directly into the
898907
// template. Note that we don't need to escape %
899908
// here unlike normal inline assembly.
900-
template_str.push_str(string);
909+
let string = rustc_codegen_ssa::common::asm_const_to_str(
910+
self.tcx,
911+
span,
912+
value,
913+
self.layout_of(ty),
914+
);
915+
template_str.push_str(&string);
901916
}
902917

903918
GlobalAsmOperandRef::SymFn { instance } => {

compiler/rustc_codegen_llvm/src/asm.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
189189
template_str.push_str(s)
190190
}
191191
}
192-
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span: _ } => {
192+
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span } => {
193193
match operands[operand_idx] {
194194
InlineAsmOperandRef::In { reg, .. }
195195
| InlineAsmOperandRef::Out { reg, .. }
@@ -204,9 +204,15 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
204204
template_str.push_str(&format!("${{{}}}", op_idx[&operand_idx]));
205205
}
206206
}
207-
InlineAsmOperandRef::Const { ref string } => {
207+
InlineAsmOperandRef::Const { value, ty } => {
208208
// Const operands get injected directly into the template
209-
template_str.push_str(string);
209+
let string = rustc_codegen_ssa::common::asm_const_to_str(
210+
self.tcx,
211+
span,
212+
value,
213+
self.layout_of(ty),
214+
);
215+
template_str.push_str(&string);
210216
}
211217
InlineAsmOperandRef::SymFn { .. }
212218
| InlineAsmOperandRef::SymStatic { .. } => {
@@ -400,13 +406,19 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
400406
for piece in template {
401407
match *piece {
402408
InlineAsmTemplatePiece::String(ref s) => template_str.push_str(s),
403-
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => {
409+
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => {
404410
match operands[operand_idx] {
405-
GlobalAsmOperandRef::Const { ref string } => {
411+
GlobalAsmOperandRef::Const { value, ty } => {
406412
// Const operands get injected directly into the
407413
// template. Note that we don't need to escape $
408414
// here unlike normal inline assembly.
409-
template_str.push_str(string);
415+
let string = rustc_codegen_ssa::common::asm_const_to_str(
416+
self.tcx,
417+
span,
418+
value,
419+
self.layout_of(ty),
420+
);
421+
template_str.push_str(&string);
410422
}
411423
GlobalAsmOperandRef::SymFn { instance } => {
412424
let llval = self.get_fn(instance);

compiler/rustc_codegen_ssa/src/base.rs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
2121
use rustc_middle::middle::dependency_format::Dependencies;
2222
use rustc_middle::middle::exported_symbols::{self, SymbolExportKind};
2323
use rustc_middle::middle::lang_items;
24-
use rustc_middle::mir::BinOp;
25-
use rustc_middle::mir::interpret::ErrorHandled;
24+
use rustc_middle::mir::interpret::{ErrorHandled, Scalar};
2625
use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem, MonoItemPartitions};
26+
use rustc_middle::mir::{BinOp, ConstValue};
2727
use rustc_middle::query::Providers;
2828
use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout};
29-
use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
29+
use rustc_middle::ty::{self, Instance, Ty, TyCtxt, UintTy};
3030
use rustc_middle::{bug, span_bug};
3131
use rustc_session::Session;
3232
use rustc_session::config::{self, CrateType, EntryFnType};
@@ -411,20 +411,23 @@ where
411411
Ok(const_value) => {
412412
let ty =
413413
cx.tcx().typeck_body(anon_const.body).node_type(anon_const.hir_id);
414-
let string = common::asm_const_to_str(
415-
cx.tcx(),
416-
*op_sp,
417-
const_value,
418-
cx.layout_of(ty),
419-
);
420-
GlobalAsmOperandRef::Const { string }
414+
let ConstValue::Scalar(scalar) = const_value else {
415+
span_bug!(
416+
*op_sp,
417+
"expected Scalar for promoted asm const, but got {:#?}",
418+
const_value
419+
)
420+
};
421+
GlobalAsmOperandRef::Const { value: scalar, ty }
421422
}
422423
Err(ErrorHandled::Reported { .. }) => {
423424
// An error has already been reported and
424425
// compilation is guaranteed to fail if execution
425-
// hits this path. So an empty string instead of
426-
// a stringified constant value will suffice.
427-
GlobalAsmOperandRef::Const { string: String::new() }
426+
// hits this path. So anything will suffice.
427+
GlobalAsmOperandRef::Const {
428+
value: Scalar::from_u32(0),
429+
ty: Ty::new_uint(cx.tcx(), UintTy::U32),
430+
}
428431
}
429432
Err(ErrorHandled::TooGeneric(_)) => {
430433
span_bug!(*op_sp, "asm const cannot be resolved; too generic")

compiler/rustc_codegen_ssa/src/common.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@
22

33
use rustc_hir::LangItem;
44
use rustc_hir::attrs::PeImportNameType;
5+
use rustc_middle::mir::interpret::Scalar;
56
use rustc_middle::ty::layout::TyAndLayout;
67
use rustc_middle::ty::{self, Instance, TyCtxt};
7-
use rustc_middle::{bug, mir, span_bug};
8+
use rustc_middle::{bug, span_bug};
89
use rustc_session::cstore::{DllCallingConvention, DllImport};
910
use rustc_span::Span;
1011
use rustc_target::spec::{Abi, Env, Os, Target};
@@ -149,12 +150,9 @@ pub(crate) fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
149150
pub fn asm_const_to_str<'tcx>(
150151
tcx: TyCtxt<'tcx>,
151152
sp: Span,
152-
const_value: mir::ConstValue,
153+
scalar: Scalar,
153154
ty_and_layout: TyAndLayout<'tcx>,
154155
) -> String {
155-
let mir::ConstValue::Scalar(scalar) = const_value else {
156-
span_bug!(sp, "expected Scalar for promoted asm const, but got {:#?}", const_value)
157-
};
158156
let value = scalar.assert_scalar_int().to_bits(ty_and_layout.size);
159157
match ty_and_layout.ty.kind() {
160158
ty::Uint(_) => value.to_string(),

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1268,13 +1268,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
12681268
}
12691269
mir::InlineAsmOperand::Const { ref value } => {
12701270
let const_value = self.eval_mir_constant(value);
1271-
let string = common::asm_const_to_str(
1272-
bx.tcx(),
1273-
span,
1274-
const_value,
1275-
bx.layout_of(value.ty()),
1276-
);
1277-
InlineAsmOperandRef::Const { string }
1271+
let mir::ConstValue::Scalar(scalar) = const_value else {
1272+
span_bug!(
1273+
span,
1274+
"expected Scalar for promoted asm const, but got {:#?}",
1275+
const_value
1276+
)
1277+
};
1278+
InlineAsmOperandRef::Const { value: scalar, ty: value.ty() }
12781279
}
12791280
mir::InlineAsmOperand::SymFn { ref value } => {
12801281
let const_ = self.monomorphize(value.const_);

compiler/rustc_codegen_ssa/src/mir/naked_asm.rs

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind};
22
use rustc_hir::attrs::{InstructionSetAttr, Linkage};
33
use rustc_middle::mir::mono::{MonoItemData, Visibility};
4-
use rustc_middle::mir::{InlineAsmOperand, START_BLOCK};
4+
use rustc_middle::mir::{self, InlineAsmOperand, START_BLOCK};
55
use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
66
use rustc_middle::ty::{Instance, Ty, TyCtxt, TypeVisitableExt};
7-
use rustc_middle::{bug, ty};
7+
use rustc_middle::{bug, span_bug, ty};
88
use rustc_span::sym;
99
use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
1010
use rustc_target::spec::{Arch, BinaryFormat};
1111

12-
use crate::common;
1312
use crate::mir::AsmCodegenMethods;
1413
use crate::traits::GlobalAsmOperandRef;
1514

@@ -76,15 +75,15 @@ fn inline_to_global_operand<'a, 'tcx, Cx: LayoutOf<'tcx, LayoutOfResult = TyAndL
7675
cx.typing_env(),
7776
ty::EarlyBinder::bind(value.ty()),
7877
);
78+
let mir::ConstValue::Scalar(scalar) = const_value else {
79+
span_bug!(
80+
value.span,
81+
"expected Scalar for promoted asm const, but got {:#?}",
82+
const_value
83+
)
84+
};
7985

80-
let string = common::asm_const_to_str(
81-
cx.tcx(),
82-
value.span,
83-
const_value,
84-
cx.layout_of(mono_type),
85-
);
86-
87-
GlobalAsmOperandRef::Const { string }
86+
GlobalAsmOperandRef::Const { value: scalar, ty: mono_type }
8887
}
8988
InlineAsmOperand::SymFn { value } => {
9089
let mono_type = instance.instantiate_mir_and_normalize_erasing_regions(

compiler/rustc_codegen_ssa/src/traits/asm.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
22
use rustc_hir::def_id::DefId;
3-
use rustc_middle::ty::Instance;
3+
use rustc_middle::mir::interpret::Scalar;
4+
use rustc_middle::ty::{Instance, Ty};
45
use rustc_span::Span;
56
use rustc_target::asm::InlineAsmRegOrRegClass;
67

@@ -26,7 +27,9 @@ pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> {
2627
out_place: Option<PlaceRef<'tcx, B::Value>>,
2728
},
2829
Const {
29-
string: String,
30+
value: Scalar,
31+
/// Type of the constant. This is needed to extract width and signedness.
32+
ty: Ty<'tcx>,
3033
},
3134
SymFn {
3235
instance: Instance<'tcx>,
@@ -41,9 +44,17 @@ pub enum InlineAsmOperandRef<'tcx, B: BackendTypes + ?Sized> {
4144

4245
#[derive(Debug)]
4346
pub enum GlobalAsmOperandRef<'tcx> {
44-
Const { string: String },
45-
SymFn { instance: Instance<'tcx> },
46-
SymStatic { def_id: DefId },
47+
Const {
48+
value: Scalar,
49+
/// Type of the constant. This is needed to extract width and signedness.
50+
ty: Ty<'tcx>,
51+
},
52+
SymFn {
53+
instance: Instance<'tcx>,
54+
},
55+
SymStatic {
56+
def_id: DefId,
57+
},
4758
}
4859

4960
pub trait AsmBuilderMethods<'tcx>: BackendTypes {

0 commit comments

Comments
 (0)