Skip to content

Commit bac41e4

Browse files
committed
Add opaque TypeId handles for CTFE
1 parent 5b74275 commit bac41e4

File tree

14 files changed

+92
-16
lines changed

14 files changed

+92
-16
lines changed

compiler/rustc_codegen_cranelift/src/constant.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,8 @@ pub(crate) fn codegen_const_value<'tcx>(
175175
fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
176176
fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
177177
}
178+
// TODO: generate pointer to allocation containing the actual type id hash u128 value
179+
GlobalAlloc::Type(_) => todo!(),
178180
GlobalAlloc::Static(def_id) => {
179181
assert!(fx.tcx.is_static(def_id));
180182
let data_id = data_id_for_static(
@@ -360,6 +362,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
360362
GlobalAlloc::Memory(alloc) => alloc,
361363
GlobalAlloc::Function { .. }
362364
| GlobalAlloc::Static(_)
365+
| GlobalAlloc::Type(_)
363366
| GlobalAlloc::VTable(..) => {
364367
unreachable!()
365368
}
@@ -471,6 +474,8 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
471474
.principal()
472475
.map(|principal| tcx.instantiate_bound_regions_with_erased(principal)),
473476
),
477+
// TODO
478+
GlobalAlloc::Type(_ty) => todo!(),
474479
GlobalAlloc::Static(def_id) => {
475480
if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::THREAD_LOCAL)
476481
{

compiler/rustc_codegen_gcc/src/common.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,8 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> {
303303
let init = self.const_data_from_alloc(alloc);
304304
self.static_addr_of(init, alloc.inner().align, None)
305305
}
306+
// TODO: generate pointer to allocation containing the actual type id hash u128 value
307+
GlobalAlloc::Type(_ty) => todo!(),
306308
GlobalAlloc::Static(def_id) => {
307309
assert!(self.tcx.is_static(def_id));
308310
self.get_static(def_id).get_address(None)

compiler/rustc_codegen_llvm/src/common.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,18 @@
33
use std::borrow::Borrow;
44

55
use libc::{c_char, c_uint};
6-
use rustc_abi as abi;
7-
use rustc_abi::HasDataLayout;
86
use rustc_abi::Primitive::Pointer;
7+
use rustc_abi::{self as abi, Align, HasDataLayout, Size};
98
use rustc_ast::Mutability;
109
use rustc_codegen_ssa::common::TypeKind;
1110
use rustc_codegen_ssa::traits::*;
1211
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
1312
use rustc_hashes::Hash128;
1413
use rustc_hir::def_id::DefId;
1514
use rustc_middle::bug;
16-
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
15+
use rustc_middle::mir::interpret::{
16+
AllocInit, Allocation, ConstAllocation, GlobalAlloc, Scalar, alloc_range,
17+
};
1718
use rustc_middle::ty::TyCtxt;
1819
use rustc_session::cstore::DllImport;
1920
use tracing::debug;
@@ -284,7 +285,8 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
284285
self.const_bitcast(llval, llty)
285286
};
286287
} else {
287-
let init = const_alloc_to_llvm(self, alloc, /*static*/ false);
288+
let init =
289+
const_alloc_to_llvm(self, alloc.inner(), /*static*/ false);
288290
let alloc = alloc.inner();
289291
let value = match alloc.mutability {
290292
Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
@@ -316,7 +318,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
316318
}),
317319
)))
318320
.unwrap_memory();
319-
let init = const_alloc_to_llvm(self, alloc, /*static*/ false);
321+
let init = const_alloc_to_llvm(self, alloc.inner(), /*static*/ false);
320322
let value = self.static_addr_of_impl(init, alloc.inner().align, None);
321323
value
322324
}
@@ -325,6 +327,24 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
325327
assert!(!self.tcx.is_thread_local_static(def_id));
326328
self.get_static(def_id)
327329
}
330+
GlobalAlloc::Type(ty) => {
331+
let type_id = self.tcx.type_id_hash(ty).as_u128();
332+
let mut alloc = Allocation::new(
333+
Size::from_bytes(16),
334+
Align::from_bytes(8).unwrap(),
335+
AllocInit::Uninit,
336+
(),
337+
);
338+
alloc
339+
.write_scalar(
340+
&self.tcx,
341+
alloc_range(Size::ZERO, Size::from_bytes(16)),
342+
Scalar::from_u128(type_id),
343+
)
344+
.unwrap();
345+
let init = const_alloc_to_llvm(self, &alloc, /*static*/ false);
346+
self.static_addr_of_impl(init, alloc.align, None)
347+
}
328348
};
329349
let base_addr_space = global_alloc.address_space(self);
330350
let llval = unsafe {
@@ -346,7 +366,7 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
346366
}
347367

348368
fn const_data_from_alloc(&self, alloc: ConstAllocation<'_>) -> Self::Value {
349-
const_alloc_to_llvm(self, alloc, /*static*/ false)
369+
const_alloc_to_llvm(self, alloc.inner(), /*static*/ false)
350370
}
351371

352372
fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value {

compiler/rustc_codegen_llvm/src/consts.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,9 @@ use crate::{base, debuginfo};
2727

2828
pub(crate) fn const_alloc_to_llvm<'ll>(
2929
cx: &CodegenCx<'ll, '_>,
30-
alloc: ConstAllocation<'_>,
30+
alloc: &Allocation,
3131
is_static: bool,
3232
) -> &'ll Value {
33-
let alloc = alloc.inner();
3433
// We expect that callers of const_alloc_to_llvm will instead directly codegen a pointer or
3534
// integer for any &ZST where the ZST is a constant (i.e. not a static). We should never be
3635
// producing empty LLVM allocations as they're just adding noise to binaries and forcing less
@@ -138,7 +137,7 @@ fn codegen_static_initializer<'ll, 'tcx>(
138137
def_id: DefId,
139138
) -> Result<(&'ll Value, ConstAllocation<'tcx>), ErrorHandled> {
140139
let alloc = cx.tcx.eval_static_initializer(def_id)?;
141-
Ok((const_alloc_to_llvm(cx, alloc, /*static*/ true), alloc))
140+
Ok((const_alloc_to_llvm(cx, alloc.inner(), /*static*/ true), alloc))
142141
}
143142

144143
fn set_global_alignment<'ll>(cx: &CodegenCx<'ll, '_>, gv: &'ll Value, mut align: Align) {

compiler/rustc_const_eval/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ const_eval_dealloc_kind_mismatch =
7878
7979
const_eval_deref_function_pointer =
8080
accessing {$allocation} which contains a function
81+
const_eval_deref_typeid_pointer =
82+
accessing {$allocation} which contains a `TypeId`
8183
const_eval_deref_vtable_pointer =
8284
accessing {$allocation} which contains a vtable
8385
const_eval_division_by_zero =

compiler/rustc_const_eval/src/errors.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,7 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
490490
WriteToReadOnly(_) => const_eval_write_to_read_only,
491491
DerefFunctionPointer(_) => const_eval_deref_function_pointer,
492492
DerefVTablePointer(_) => const_eval_deref_vtable_pointer,
493+
DerefTypeIdPointer(_) => const_eval_deref_typeid_pointer,
493494
InvalidBool(_) => const_eval_invalid_bool,
494495
InvalidChar(_) => const_eval_invalid_char,
495496
InvalidTag(_) => const_eval_invalid_tag,
@@ -603,7 +604,10 @@ impl<'a> ReportErrorExt for UndefinedBehaviorInfo<'a> {
603604
diag.arg("has", has.bytes());
604605
diag.arg("msg", format!("{msg:?}"));
605606
}
606-
WriteToReadOnly(alloc) | DerefFunctionPointer(alloc) | DerefVTablePointer(alloc) => {
607+
WriteToReadOnly(alloc)
608+
| DerefFunctionPointer(alloc)
609+
| DerefVTablePointer(alloc)
610+
| DerefTypeIdPointer(alloc) => {
607611
diag.arg("allocation", alloc);
608612
}
609613
InvalidBool(b) => {

compiler/rustc_const_eval/src/interpret/memory.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
346346
kind = "vtable",
347347
)
348348
}
349+
Some(GlobalAlloc::Type(..)) => {
350+
err_ub_custom!(
351+
fluent::const_eval_invalid_dealloc,
352+
alloc_id = alloc_id,
353+
kind = "typeid",
354+
)
355+
}
349356
Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => {
350357
err_ub_custom!(
351358
fluent::const_eval_invalid_dealloc,
@@ -615,6 +622,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
615622
}
616623
Some(GlobalAlloc::Function { .. }) => throw_ub!(DerefFunctionPointer(id)),
617624
Some(GlobalAlloc::VTable(..)) => throw_ub!(DerefVTablePointer(id)),
625+
// TODO
626+
Some(GlobalAlloc::Type(..)) => throw_ub!(DerefTypeIdPointer(id)),
618627
None => throw_ub!(PointerUseAfterFree(id, CheckInAllocMsg::MemoryAccess)),
619628
Some(GlobalAlloc::Static(def_id)) => {
620629
assert!(self.tcx.is_static(def_id));
@@ -896,7 +905,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
896905
let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env);
897906
let mutbl = global_alloc.mutability(*self.tcx, self.typing_env);
898907
let kind = match global_alloc {
899-
GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => AllocKind::LiveData,
908+
GlobalAlloc::Type(_) | GlobalAlloc::Static { .. } | GlobalAlloc::Memory { .. } => {
909+
AllocKind::LiveData
910+
}
900911
GlobalAlloc::Function { .. } => bug!("We already checked function pointers above"),
901912
GlobalAlloc::VTable { .. } => AllocKind::VTable,
902913
};
@@ -1206,6 +1217,9 @@ impl<'a, 'tcx, M: Machine<'tcx>> std::fmt::Debug for DumpAllocs<'a, 'tcx, M> {
12061217
Some(GlobalAlloc::VTable(ty, dyn_ty)) => {
12071218
write!(fmt, " (vtable: impl {dyn_ty} for {ty})")?;
12081219
}
1220+
Some(GlobalAlloc::Type(ty)) => {
1221+
write!(fmt, " (typeid for {ty})")?;
1222+
}
12091223
Some(GlobalAlloc::Static(did)) => {
12101224
write!(fmt, " (static: {})", self.ecx.tcx.def_path_str(did))?;
12111225
}

compiler/rustc_middle/src/mir/interpret/error.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,8 @@ pub enum UndefinedBehaviorInfo<'tcx> {
355355
DerefFunctionPointer(AllocId),
356356
/// Trying to access the data behind a vtable pointer.
357357
DerefVTablePointer(AllocId),
358+
/// Trying to access the actual type id.
359+
DerefTypeIdPointer(AllocId),
358360
/// Using a non-boolean `u8` as bool.
359361
InvalidBool(u8),
360362
/// Using a non-character `u32` as character.

compiler/rustc_middle/src/mir/interpret/mod.rs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ enum AllocDiscriminant {
103103
Fn,
104104
VTable,
105105
Static,
106+
Type,
106107
}
107108

108109
pub fn specialized_encode_alloc_id<'tcx, E: TyEncoder<'tcx>>(
@@ -127,6 +128,11 @@ pub fn specialized_encode_alloc_id<'tcx, E: TyEncoder<'tcx>>(
127128
ty.encode(encoder);
128129
poly_trait_ref.encode(encoder);
129130
}
131+
GlobalAlloc::Type(ty) => {
132+
trace!("encoding {alloc_id:?} with {ty:#?}");
133+
AllocDiscriminant::Type.encode(encoder);
134+
ty.encode(encoder);
135+
}
130136
GlobalAlloc::Static(did) => {
131137
assert!(!tcx.is_thread_local_static(did));
132138
// References to statics doesn't need to know about their allocations,
@@ -228,6 +234,12 @@ impl<'s> AllocDecodingSession<'s> {
228234
trace!("decoded vtable alloc instance: {ty:?}, {poly_trait_ref:?}");
229235
decoder.interner().reserve_and_set_vtable_alloc(ty, poly_trait_ref, CTFE_ALLOC_SALT)
230236
}
237+
AllocDiscriminant::Type => {
238+
trace!("creating typeid alloc ID");
239+
let ty = Decodable::decode(decoder);
240+
trace!("decoded typid: {ty:?}");
241+
decoder.interner().reserve_and_set_type_id_alloc(ty)
242+
}
231243
AllocDiscriminant::Static => {
232244
trace!("creating extern static alloc ID");
233245
let did = <DefId as Decodable<D>>::decode(decoder);
@@ -258,6 +270,9 @@ pub enum GlobalAlloc<'tcx> {
258270
Static(DefId),
259271
/// The alloc ID points to memory.
260272
Memory(ConstAllocation<'tcx>),
273+
/// A TypeId pointer. For now cannot be turned into a runtime value.
274+
/// TODO: turn into actual TypeId?
275+
Type(Ty<'tcx>),
261276
}
262277

263278
impl<'tcx> GlobalAlloc<'tcx> {
@@ -296,9 +311,10 @@ impl<'tcx> GlobalAlloc<'tcx> {
296311
pub fn address_space(&self, cx: &impl HasDataLayout) -> AddressSpace {
297312
match self {
298313
GlobalAlloc::Function { .. } => cx.data_layout().instruction_address_space,
299-
GlobalAlloc::Static(..) | GlobalAlloc::Memory(..) | GlobalAlloc::VTable(..) => {
300-
AddressSpace::DATA
301-
}
314+
GlobalAlloc::Type(_)
315+
| GlobalAlloc::Static(..)
316+
| GlobalAlloc::Memory(..)
317+
| GlobalAlloc::VTable(..) => AddressSpace::DATA,
302318
}
303319
}
304320

@@ -334,7 +350,7 @@ impl<'tcx> GlobalAlloc<'tcx> {
334350
}
335351
}
336352
GlobalAlloc::Memory(alloc) => alloc.inner().mutability,
337-
GlobalAlloc::Function { .. } | GlobalAlloc::VTable(..) => {
353+
GlobalAlloc::Type(_) | GlobalAlloc::Function { .. } | GlobalAlloc::VTable(..) => {
338354
// These are immutable.
339355
Mutability::Not
340356
}
@@ -380,8 +396,10 @@ impl<'tcx> GlobalAlloc<'tcx> {
380396
GlobalAlloc::Function { .. } => (Size::ZERO, Align::ONE),
381397
GlobalAlloc::VTable(..) => {
382398
// No data to be accessed here. But vtables are pointer-aligned.
383-
return (Size::ZERO, tcx.data_layout.pointer_align.abi);
399+
(Size::ZERO, tcx.data_layout.pointer_align.abi)
384400
}
401+
// TODO make this represent normal type ids somehow
402+
GlobalAlloc::Type(_) => (Size::from_bytes(16), Align::from_bytes(8).unwrap()),
385403
}
386404
}
387405
}
@@ -487,6 +505,11 @@ impl<'tcx> TyCtxt<'tcx> {
487505
self.reserve_and_set_dedup(GlobalAlloc::VTable(ty, dyn_ty), salt)
488506
}
489507

508+
/// Generates an [AllocId] for a [core::mem::type_info::TypeId]. Will get deduplicated.
509+
pub fn reserve_and_set_type_id_alloc(self, ty: Ty<'tcx>) -> AllocId {
510+
self.reserve_and_set_dedup(GlobalAlloc::Type(ty), 0)
511+
}
512+
490513
/// Interns the `Allocation` and return a new `AllocId`, even if there's already an identical
491514
/// `Allocation` with a different `AllocId`.
492515
/// Statics with identical content will still point to the same `Allocation`, i.e.,

compiler/rustc_middle/src/mir/pretty.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1621,6 +1621,7 @@ pub fn write_allocations<'tcx>(
16211621
Some(GlobalAlloc::VTable(ty, dyn_ty)) => {
16221622
write!(w, " (vtable: impl {dyn_ty} for {ty})")?
16231623
}
1624+
Some(GlobalAlloc::Type(ty)) => write!(w, " (typeid for {ty})")?,
16241625
Some(GlobalAlloc::Static(did)) if !tcx.is_foreign_item(did) => {
16251626
write!(w, " (static: {}", tcx.def_path_str(did))?;
16261627
if body.phase <= MirPhase::Runtime(RuntimePhase::PostCleanup)

compiler/rustc_middle/src/ty/print/pretty.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1780,6 +1780,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write {
17801780
}
17811781
Some(GlobalAlloc::Function { .. }) => p!("<function>"),
17821782
Some(GlobalAlloc::VTable(..)) => p!("<vtable>"),
1783+
Some(GlobalAlloc::Type(_)) => p!("<typeid>"),
17831784
None => p!("<dangling pointer>"),
17841785
}
17851786
return Ok(());

compiler/rustc_monomorphize/src/collector.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1219,6 +1219,7 @@ fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoIt
12191219
));
12201220
collect_alloc(tcx, alloc_id, output)
12211221
}
1222+
GlobalAlloc::Type(_) => {}
12221223
}
12231224
}
12241225

compiler/rustc_passes/src/reachable.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,7 @@ impl<'tcx> ReachableContext<'tcx> {
325325
self.visit(args);
326326
}
327327
}
328+
GlobalAlloc::Type(ty) => self.visit(ty),
328329
GlobalAlloc::Memory(alloc) => self.propagate_from_alloc(alloc),
329330
}
330331
}

compiler/rustc_smir/src/rustc_smir/convert/mir.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -752,6 +752,7 @@ impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> {
752752
GlobalAlloc::Static(tables.static_def(*def))
753753
}
754754
mir::interpret::GlobalAlloc::Memory(alloc) => GlobalAlloc::Memory(alloc.stable(tables)),
755+
mir::interpret::GlobalAlloc::Type(_) => todo!(),
755756
}
756757
}
757758
}

0 commit comments

Comments
 (0)