Skip to content

Commit 7af11f8

Browse files
committed
Support codegen of asm const pointers without provenance
CTFE pointers created via type ID, `without_provenance` or pointers to const ZSTs can now be codegenned with all 3 backends. These pointers are generated in the same way as integers.
1 parent 2e0afcf commit 7af11f8

File tree

8 files changed

+47
-16
lines changed

8 files changed

+47
-16
lines changed

compiler/rustc_codegen_cranelift/src/global_asm.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ fn codegen_global_asm_inner<'tcx>(
114114
ConstScalar::Int(int) => {
115115
let string = rustc_codegen_ssa::common::asm_const_to_str(
116116
tcx,
117-
span,
118117
int,
119118
FullyMonomorphizedLayoutCx(tcx).layout_of(ty),
120119
);

compiler/rustc_codegen_cranelift/src/inline_asm.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,6 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
104104

105105
let value = rustc_codegen_ssa::common::asm_const_to_str(
106106
fx.tcx,
107-
span,
108107
scalar.assert_scalar_int(),
109108
fx.layout_of(ty),
110109
);

compiler/rustc_codegen_gcc/src/asm.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
453453
template_str.push_str(escaped_char);
454454
}
455455
}
456-
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span } => {
456+
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span: _ } => {
457457
let mut push_to_template = |modifier, gcc_idx| {
458458
use std::fmt::Write;
459459

@@ -501,7 +501,6 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
501501
// Const operands get injected directly into the template
502502
let string = rustc_codegen_ssa::common::asm_const_to_str(
503503
self.tcx,
504-
span,
505504
int,
506505
self.layout_of(ty),
507506
);
@@ -909,7 +908,7 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
909908
.unwrap_or(string.len());
910909
}
911910
}
912-
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => {
911+
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => {
913912
match operands[operand_idx] {
914913
GlobalAsmOperandRef::Const { value, ty } => {
915914
match value {
@@ -919,7 +918,6 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
919918
// here unlike normal inline assembly.
920919
let string = rustc_codegen_ssa::common::asm_const_to_str(
921920
self.tcx,
922-
span,
923921
int,
924922
self.layout_of(ty),
925923
);

compiler/rustc_codegen_llvm/src/asm.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
197197
template_str.push_str(s)
198198
}
199199
}
200-
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span } => {
200+
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span: _ } => {
201201
match operands[operand_idx] {
202202
InlineAsmOperandRef::In { reg, .. }
203203
| InlineAsmOperandRef::Out { reg, .. }
@@ -218,7 +218,6 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
218218
// Const operands get injected directly into the template
219219
let string = rustc_codegen_ssa::common::asm_const_to_str(
220220
self.tcx,
221-
span,
222221
int,
223222
self.layout_of(ty),
224223
);
@@ -430,7 +429,7 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
430429
for piece in template {
431430
match *piece {
432431
InlineAsmTemplatePiece::String(ref s) => template_str.push_str(s),
433-
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => {
432+
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => {
434433
match operands[operand_idx] {
435434
GlobalAsmOperandRef::Const { value, ty } => {
436435
match value {
@@ -440,7 +439,6 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
440439
// here unlike normal inline assembly.
441440
let string = rustc_codegen_ssa::common::asm_const_to_str(
442441
self.tcx,
443-
span,
444442
int,
445443
self.layout_of(ty),
446444
);

compiler/rustc_codegen_ssa/src/base.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,10 @@ where
418418
const_value
419419
)
420420
};
421-
GlobalAsmOperandRef::Const { value: scalar, ty }
421+
GlobalAsmOperandRef::Const {
422+
value: common::asm_const_ptr_clean(cx.tcx(), scalar),
423+
ty,
424+
}
422425
}
423426
Err(ErrorHandled::Reported { .. }) => {
424427
// An error has already been reported and

compiler/rustc_codegen_ssa/src/common.rs

Lines changed: 30 additions & 3 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::bug;
6+
use rustc_middle::mir::interpret::{GlobalAlloc, PointerArithmetic, Scalar};
57
use rustc_middle::ty::layout::TyAndLayout;
68
use rustc_middle::ty::{self, Instance, ScalarInt, TyCtxt};
7-
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};
@@ -148,7 +149,6 @@ pub(crate) fn shift_mask_val<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
148149

149150
pub fn asm_const_to_str<'tcx>(
150151
tcx: TyCtxt<'tcx>,
151-
sp: Span,
152152
scalar: ScalarInt,
153153
ty_and_layout: TyAndLayout<'tcx>,
154154
) -> String {
@@ -163,7 +163,34 @@ pub fn asm_const_to_str<'tcx>(
163163
ty::IntTy::I128 => (value as i128).to_string(),
164164
ty::IntTy::Isize => unreachable!(),
165165
},
166-
_ => span_bug!(sp, "asm const has bad type {}", ty_and_layout.ty),
166+
// For unsigned integers or pointers without provenance, just print the unsigned value
167+
_ => value.to_string(),
168+
}
169+
}
170+
171+
/// "Clean" a const pointer by removing values where the resulting ASM will not be
172+
/// `<symbol> + <offset>`.
173+
///
174+
/// These values are converted to `ScalarInt`.
175+
pub fn asm_const_ptr_clean<'tcx>(tcx: TyCtxt<'tcx>, scalar: Scalar) -> Scalar {
176+
let Scalar::Ptr(ptr, _) = scalar else {
177+
return scalar;
178+
};
179+
let (prov, offset) = ptr.prov_and_relative_offset();
180+
let global_alloc = tcx.global_alloc(prov.alloc_id());
181+
match global_alloc {
182+
GlobalAlloc::TypeId { .. } => {
183+
// `TypeId` provenances are not a thing in codegen. Just erase and replace with scalar offset.
184+
Scalar::from_u64(offset.bytes())
185+
}
186+
GlobalAlloc::Memory(alloc) if alloc.inner().len() == 0 => {
187+
// ZST const allocations don't actually get global defined when lowered.
188+
// Turn them into integer without provenances now.
189+
let val = alloc.inner().align.bytes().wrapping_add(offset.bytes());
190+
Scalar::from_target_usize(tcx.truncate_to_target_usize(val), &tcx)
191+
}
192+
// Other types of `GlobalAlloc` are fine.
193+
_ => scalar,
167194
}
168195
}
169196

compiler/rustc_codegen_ssa/src/mir/block.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1276,7 +1276,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
12761276
const_value
12771277
)
12781278
};
1279-
InlineAsmOperandRef::Const { value: scalar, ty: value.ty() }
1279+
InlineAsmOperandRef::Const {
1280+
value: common::asm_const_ptr_clean(bx.tcx(), scalar),
1281+
ty: value.ty(),
1282+
}
12801283
}
12811284
mir::InlineAsmOperand::SymFn { ref value } => {
12821285
let const_ = self.monomorphize(value.const_);

compiler/rustc_codegen_ssa/src/mir/naked_asm.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use rustc_span::sym;
1010
use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
1111
use rustc_target::spec::{Arch, BinaryFormat};
1212

13+
use crate::common;
1314
use crate::mir::AsmCodegenMethods;
1415
use crate::traits::GlobalAsmOperandRef;
1516

@@ -84,7 +85,10 @@ fn inline_to_global_operand<'a, 'tcx, Cx: LayoutOf<'tcx, LayoutOfResult = TyAndL
8485
)
8586
};
8687

87-
GlobalAsmOperandRef::Const { value: scalar, ty: mono_type }
88+
GlobalAsmOperandRef::Const {
89+
value: common::asm_const_ptr_clean(cx.tcx(), scalar),
90+
ty: mono_type,
91+
}
8892
}
8993
InlineAsmOperand::SymFn { value } => {
9094
let mono_type = instance.instantiate_mir_and_normalize_erasing_regions(

0 commit comments

Comments
 (0)