Skip to content

Commit 49ab24e

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 85bc9f8 commit 49ab24e

8 files changed

Lines changed: 46 additions & 15 deletions

File tree

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
@@ -106,7 +106,6 @@ pub(crate) fn codegen_inline_asm_terminator<'tcx>(
106106

107107
let value = rustc_codegen_ssa::common::asm_const_to_str(
108108
fx.tcx,
109-
span,
110109
scalar.assert_scalar_int(),
111110
fx.layout_of(ty),
112111
);

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
);
@@ -943,7 +942,7 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
943942
.unwrap_or(string.len());
944943
}
945944
}
946-
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => {
945+
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => {
947946
match operands[operand_idx] {
948947
GlobalAsmOperandRef::Const { value, ty } => {
949948
match value {
@@ -953,7 +952,6 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
953952
// here unlike normal inline assembly.
954953
let string = rustc_codegen_ssa::common::asm_const_to_str(
955954
self.tcx,
956-
span,
957955
int,
958956
self.layout_of(ty),
959957
);

compiler/rustc_codegen_llvm/src/asm.rs

Lines changed: 1 addition & 3 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
);
@@ -443,7 +442,6 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
443442
// here unlike normal inline assembly.
444443
let string = rustc_codegen_ssa::common::asm_const_to_str(
445444
self.tcx,
446-
span,
447445
int,
448446
self.layout_of(ty),
449447
);

compiler/rustc_codegen_ssa/src/base.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,10 @@ where
425425
const_value
426426
)
427427
};
428-
GlobalAsmOperandRef::Const { value: scalar, ty }
428+
GlobalAsmOperandRef::Const {
429+
value: common::asm_const_ptr_clean(cx.tcx(), scalar),
430+
ty,
431+
}
429432
}
430433
Err(ErrorHandled::Reported { .. }) => {
431434
// 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, DllImportSymbolType};
910
use rustc_span::Span;
1011
use rustc_target::spec::{CfgAbi, 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
@@ -1448,7 +1448,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
14481448
const_value
14491449
)
14501450
};
1451-
InlineAsmOperandRef::Const { value: scalar, ty: value.ty() }
1451+
InlineAsmOperandRef::Const {
1452+
value: common::asm_const_ptr_clean(bx.tcx(), scalar),
1453+
ty: value.ty(),
1454+
}
14521455
}
14531456
mir::InlineAsmOperand::SymFn { ref value } => {
14541457
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
@@ -11,6 +11,7 @@ use rustc_span::sym;
1111
use rustc_target::callconv::{ArgAbi, FnAbi, PassMode};
1212
use rustc_target::spec::{Arch, BinaryFormat, Env, Os};
1313

14+
use crate::common;
1415
use crate::mir::AsmCodegenMethods;
1516
use crate::traits::GlobalAsmOperandRef;
1617

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

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

0 commit comments

Comments
 (0)