Skip to content

Commit b63e1d3

Browse files
committed
Unify handling of GlobalAlloc inside backend
With the previous commit, now we can see there are some code duplication for the handling of `GlobalAlloc` inside backends. Do some clean up to unify them.
1 parent 24e8d36 commit b63e1d3

File tree

7 files changed

+189
-195
lines changed

7 files changed

+189
-195
lines changed

compiler/rustc_codegen_gcc/src/asm.rs

Lines changed: 15 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_codegen_ssa::mir::operand::OperandValue;
88
use rustc_codegen_ssa::mir::place::PlaceRef;
99
use rustc_codegen_ssa::traits::{
1010
AsmBuilderMethods, AsmCodegenMethods, BaseTypeCodegenMethods, BuilderMethods,
11-
GlobalAsmOperandRef, InlineAsmOperandRef,
11+
GlobalAsmOperandRef, InlineAsmOperandRef, ConstCodegenMethods,
1212
};
1313
use rustc_middle::bug;
1414
use rustc_middle::mir::interpret::{GlobalAlloc, Scalar};
@@ -145,6 +145,9 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
145145
// Clobbers collected from `out("explicit register") _` and `inout("explicit_reg") var => _`
146146
let mut clobbers = vec![];
147147

148+
// Symbols name that needs to be inserted to asm const ptr template string.
149+
let mut const_syms = vec![];
150+
148151
// We're trying to preallocate space for the template
149152
let mut constants_len = 0;
150153

@@ -405,17 +408,8 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
405408
let (prov, offset) = ptr.prov_and_relative_offset();
406409
assert_eq!(offset.bytes(), 0);
407410
let global_alloc = self.tcx.global_alloc(prov.alloc_id());
408-
let val = match global_alloc {
409-
GlobalAlloc::Function { instance } => {
410-
get_fn(self.cx, instance).get_address(None)
411-
}
412-
GlobalAlloc::Static(def_id) => {
413-
self.cx.get_static(def_id).get_address(None)
414-
}
415-
GlobalAlloc::Memory(_)
416-
| GlobalAlloc::VTable(..)
417-
| GlobalAlloc::TypeId { .. } => unreachable!(),
418-
};
411+
let (val, sym) = self.cx.alloc_to_backend(global_alloc).unwrap();
412+
const_syms.push(sym.unwrap());
419413
inputs.push(AsmInOperand { constraint: "X".into(), rust_idx, val });
420414
}
421415
},
@@ -514,27 +508,13 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> {
514508
}
515509

516510
Scalar::Ptr(ptr, _) => {
517-
let (prov, offset) = ptr.prov_and_relative_offset();
511+
let (_, offset) = ptr.prov_and_relative_offset();
518512
assert_eq!(offset.bytes(), 0);
519-
let global_alloc = self.tcx.global_alloc(prov.alloc_id());
520-
let symbol_name = match global_alloc {
521-
GlobalAlloc::Function { instance } => {
522-
// TODO(@Amanieu): Additional mangling is needed on
523-
// some targets to add a leading underscore (Mach-O)
524-
// or byte count suffixes (x86 Windows).
525-
self.tcx.symbol_name(instance)
526-
}
527-
GlobalAlloc::Static(def_id) => {
528-
// TODO(@Amanieu): Additional mangling is needed on
529-
// some targets to add a leading underscore (Mach-O).
530-
let instance = Instance::mono(self.tcx, def_id);
531-
self.tcx.symbol_name(instance)
532-
}
533-
GlobalAlloc::Memory(_)
534-
| GlobalAlloc::VTable(..)
535-
| GlobalAlloc::TypeId { .. } => unreachable!(),
536-
};
537-
template_str.push_str(symbol_name.name);
513+
let instance = const_syms.remove(0);
514+
// TODO(@Amanieu): Additional mangling is needed on
515+
// some targets to add a leading underscore (Mach-O)
516+
// or byte count suffixes (x86 Windows).
517+
template_str.push_str(self.tcx.symbol_name(instance).name);
538518
}
539519
}
540520
}
@@ -953,16 +933,13 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
953933
// or byte count suffixes (x86 Windows).
954934
self.tcx.symbol_name(instance)
955935
}
956-
GlobalAlloc::Static(def_id) => {
936+
_ => {
937+
let (_, syms) = self.alloc_to_backend(global_alloc).unwrap();
957938
// TODO(antoyo): set the global variable as used.
958939
// TODO(@Amanieu): Additional mangling is needed on
959940
// some targets to add a leading underscore (Mach-O).
960-
let instance = Instance::mono(self.tcx, def_id);
961-
self.tcx.symbol_name(instance)
941+
self.tcx.symbol_name(syms.unwrap())
962942
}
963-
GlobalAlloc::Memory(_)
964-
| GlobalAlloc::VTable(..)
965-
| GlobalAlloc::TypeId { .. } => unreachable!(),
966943
};
967944
template_str.push_str(symbol_name.name);
968945
}

compiler/rustc_codegen_gcc/src/common.rs

Lines changed: 68 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use rustc_codegen_ssa::traits::{
66
};
77
use rustc_middle::mir::Mutability;
88
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, PointerArithmetic, Scalar};
9+
use rustc_middle::ty::Instance;
910
use rustc_middle::ty::layout::LayoutOf;
1011

1112
use crate::context::CodegenCx;
@@ -109,7 +110,7 @@ pub fn type_is_pointer(typ: Type<'_>) -> bool {
109110
typ.get_pointee().is_some()
110111
}
111112

112-
impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
113+
impl<'gcc, 'tcx> ConstCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
113114
fn const_null(&self, typ: Type<'gcc>) -> RValue<'gcc> {
114115
if type_is_pointer(typ) { self.context.new_null(typ) } else { self.const_int(typ, 0) }
115116
}
@@ -220,6 +221,63 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
220221
None
221222
}
222223

224+
fn alloc_to_backend(
225+
&self,
226+
global_alloc: GlobalAlloc<'tcx>,
227+
) -> Result<(RValue<'gcc>, Option<Instance<'tcx>>), u64> {
228+
let alloc = match global_alloc {
229+
GlobalAlloc::Function { instance, .. } => {
230+
return Ok((self.get_fn_addr(instance), Some(instance)));
231+
}
232+
GlobalAlloc::Static(def_id) => {
233+
assert!(self.tcx.is_static(def_id));
234+
return Ok((
235+
self.get_static(def_id).get_address(None),
236+
Some(Instance::mono(self.tcx, def_id)),
237+
));
238+
}
239+
GlobalAlloc::TypeId { .. } => {
240+
// Drop the provenance, the offset contains the bytes of the hash, so
241+
// just return 0 as base address.
242+
return Err(0);
243+
}
244+
245+
GlobalAlloc::Memory(alloc) => {
246+
if alloc.inner().len() == 0 {
247+
// For ZSTs directly codegen an aligned pointer.
248+
// This avoids generating a zero-sized constant value and actually needing a
249+
// real address at runtime.
250+
return Err(alloc.inner().align.bytes());
251+
}
252+
253+
alloc
254+
}
255+
256+
GlobalAlloc::VTable(ty, dyn_ty) => {
257+
self.tcx
258+
.global_alloc(self.tcx.vtable_allocation((
259+
ty,
260+
dyn_ty.principal().map(|principal| {
261+
self.tcx.instantiate_bound_regions_with_erased(principal)
262+
}),
263+
)))
264+
.unwrap_memory()
265+
}
266+
};
267+
268+
let init = self.const_data_from_alloc(alloc);
269+
let alloc = alloc.inner();
270+
let value = match alloc.mutability {
271+
Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
272+
_ => self.static_addr_of(init, alloc.align, None),
273+
};
274+
if !self.sess().fewer_names() {
275+
// TODO(antoyo): set value name.
276+
}
277+
278+
Ok((value, None))
279+
}
280+
223281
fn scalar_to_backend(&self, cv: Scalar, layout: abi::Scalar, ty: Type<'gcc>) -> RValue<'gcc> {
224282
let bitsize = if layout.is_bool() { 1 } else { layout.size(self).bits() };
225283
match cv {
@@ -241,56 +299,16 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
241299
Scalar::Ptr(ptr, _size) => {
242300
let (prov, offset) = ptr.prov_and_relative_offset();
243301
let alloc_id = prov.alloc_id();
244-
let base_addr = match self.tcx.global_alloc(alloc_id) {
245-
GlobalAlloc::Memory(alloc) => {
246-
// For ZSTs directly codegen an aligned pointer.
247-
// This avoids generating a zero-sized constant value and actually needing a
248-
// real address at runtime.
249-
if alloc.inner().len() == 0 {
250-
let val = alloc.inner().align.bytes().wrapping_add(offset.bytes());
251-
let val = self.const_usize(self.tcx.truncate_to_target_usize(val));
252-
return if matches!(layout.primitive(), Pointer(_)) {
253-
self.context.new_cast(None, val, ty)
254-
} else {
255-
self.const_bitcast(val, ty)
256-
};
257-
}
258-
259-
let init = self.const_data_from_alloc(alloc);
260-
let alloc = alloc.inner();
261-
let value = match alloc.mutability {
262-
Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
263-
_ => self.static_addr_of(init, alloc.align, None),
302+
let base_addr = match self.alloc_to_backend(self.tcx.global_alloc(alloc_id)) {
303+
Ok((base_addr, _)) => base_addr,
304+
Err(base_addr) => {
305+
let val = base_addr.wrapping_add(offset.bytes());
306+
let val = self.const_usize(self.tcx.truncate_to_target_usize(val));
307+
return if matches!(layout.primitive(), Pointer(_)) {
308+
self.context.new_cast(None, val, ty)
309+
} else {
310+
self.const_bitcast(val, ty)
264311
};
265-
if !self.sess().fewer_names() {
266-
// TODO(antoyo): set value name.
267-
}
268-
value
269-
}
270-
GlobalAlloc::Function { instance, .. } => self.get_fn_addr(instance),
271-
GlobalAlloc::VTable(ty, dyn_ty) => {
272-
let alloc = self
273-
.tcx
274-
.global_alloc(self.tcx.vtable_allocation((
275-
ty,
276-
dyn_ty.principal().map(|principal| {
277-
self.tcx.instantiate_bound_regions_with_erased(principal)
278-
}),
279-
)))
280-
.unwrap_memory();
281-
let init = self.const_data_from_alloc(alloc);
282-
self.static_addr_of(init, alloc.inner().align, None)
283-
}
284-
GlobalAlloc::TypeId { .. } => {
285-
let val = self.const_usize(offset.bytes());
286-
// This is still a variable of pointer type, even though we only use the provenance
287-
// of that pointer in CTFE and Miri. But to make LLVM's type system happy,
288-
// we need an int-to-ptr cast here (it doesn't matter at all which provenance that picks).
289-
return self.context.new_cast(None, val, ty);
290-
}
291-
GlobalAlloc::Static(def_id) => {
292-
assert!(self.tcx.is_static(def_id));
293-
self.get_static(def_id).get_address(None)
294312
}
295313
};
296314
let ptr_type = base_addr.get_type();

compiler/rustc_codegen_llvm/src/asm.rs

Lines changed: 12 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
55
use rustc_codegen_ssa::mir::operand::OperandValue;
66
use rustc_codegen_ssa::traits::*;
77
use rustc_data_structures::fx::FxHashMap;
8-
use rustc_middle::mir::interpret::{GlobalAlloc, Scalar as ConstScalar};
8+
use rustc_middle::mir::interpret::Scalar as ConstScalar;
99
use rustc_middle::ty::Instance;
1010
use rustc_middle::ty::layout::TyAndLayout;
1111
use rustc_middle::{bug, span_bug};
@@ -164,21 +164,10 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
164164
let (prov, offset) = ptr.prov_and_relative_offset();
165165
assert_eq!(offset.bytes(), 0);
166166
let global_alloc = self.tcx.global_alloc(prov.alloc_id());
167-
match global_alloc {
168-
GlobalAlloc::Function { instance } => {
169-
inputs.push(self.cx.get_fn(instance));
170-
op_idx.insert(idx, constraints.len());
171-
constraints.push("s".to_string());
172-
}
173-
GlobalAlloc::Static(def_id) => {
174-
inputs.push(self.cx.get_static(def_id));
175-
op_idx.insert(idx, constraints.len());
176-
constraints.push("s".to_string());
177-
}
178-
GlobalAlloc::Memory(_)
179-
| GlobalAlloc::VTable(..)
180-
| GlobalAlloc::TypeId { .. } => unreachable!(),
181-
}
167+
let (value, _) = self.cx.alloc_to_backend(global_alloc).unwrap();
168+
inputs.push(value);
169+
op_idx.insert(idx, constraints.len());
170+
constraints.push("s".to_string());
182171
}
183172
},
184173
InlineAsmOperandRef::SymStatic { def_id } => {
@@ -236,21 +225,12 @@ impl<'ll, 'tcx> AsmBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
236225
template_str.push_str(&string);
237226
}
238227
ConstScalar::Ptr(ptr, _) => {
239-
let (prov, offset) = ptr.prov_and_relative_offset();
228+
let (_, offset) = ptr.prov_and_relative_offset();
240229
assert_eq!(offset.bytes(), 0);
241-
let global_alloc = self.tcx.global_alloc(prov.alloc_id());
242-
match global_alloc {
243-
GlobalAlloc::Function { .. } | GlobalAlloc::Static(_) => {
244-
// Only emit the raw symbol name
245-
template_str.push_str(&format!(
246-
"${{{}:c}}",
247-
op_idx[&operand_idx]
248-
));
249-
}
250-
GlobalAlloc::Memory(_)
251-
| GlobalAlloc::VTable(..)
252-
| GlobalAlloc::TypeId { .. } => unreachable!(),
253-
}
230+
231+
// Only emit the raw symbol name
232+
template_str
233+
.push_str(&format!("${{{}:c}}", op_idx[&operand_idx]));
254234
}
255235
}
256236
}
@@ -466,18 +446,8 @@ impl<'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'_, 'tcx> {
466446
let (prov, offset) = ptr.prov_and_relative_offset();
467447
assert_eq!(offset.bytes(), 0);
468448
let global_alloc = self.tcx.global_alloc(prov.alloc_id());
469-
let llval = match global_alloc {
470-
GlobalAlloc::Function { instance } => self.get_fn(instance),
471-
GlobalAlloc::Static(def_id) => self
472-
.renamed_statics
473-
.borrow()
474-
.get(&def_id)
475-
.copied()
476-
.unwrap_or_else(|| self.get_static(def_id)),
477-
GlobalAlloc::Memory(_)
478-
| GlobalAlloc::VTable(..)
479-
| GlobalAlloc::TypeId { .. } => unreachable!(),
480-
};
449+
let (llval, sym) = self.alloc_to_backend(global_alloc).unwrap();
450+
assert!(sym.is_some());
481451

482452
self.add_compiler_used_global(llval);
483453
let symbol = llvm::build_string(|s| unsafe {

0 commit comments

Comments
 (0)