Skip to content

Commit 7434df3

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 7e7aa77 commit 7434df3

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
);
@@ -940,7 +939,7 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
940939
.unwrap_or(string.len());
941940
}
942941
}
943-
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => {
942+
InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => {
944943
match operands[operand_idx] {
945944
GlobalAsmOperandRef::Const { value, ty } => {
946945
match value {
@@ -950,7 +949,6 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
950949
// here unlike normal inline assembly.
951950
let string = rustc_codegen_ssa::common::asm_const_to_str(
952951
self.tcx,
953-
span,
954952
int,
955953
self.layout_of(ty),
956954
);

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
);
@@ -442,7 +441,6 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
442441
// here unlike normal inline assembly.
443442
let string = rustc_codegen_ssa::common::asm_const_to_str(
444443
self.tcx,
445-
span,
446444
int,
447445
self.layout_of(ty),
448446
);

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
@@ -1444,7 +1444,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
14441444
const_value
14451445
)
14461446
};
1447-
InlineAsmOperandRef::Const { value: scalar, ty: value.ty() }
1447+
InlineAsmOperandRef::Const {
1448+
value: common::asm_const_ptr_clean(bx.tcx(), scalar),
1449+
ty: value.ty(),
1450+
}
14481451
}
14491452
mir::InlineAsmOperand::SymFn { ref value } => {
14501453
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)