Skip to content

Commit 1c47a64

Browse files
committed
Split up TypeId into pointer sized fields for CTFE to use as opaque ids
1 parent dfa62d1 commit 1c47a64

File tree

20 files changed

+152
-148
lines changed

20 files changed

+152
-148
lines changed

compiler/rustc_codegen_cranelift/src/constant.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,17 @@ 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!(),
178+
GlobalAlloc::Type { .. } => {
179+
let data_id = data_id_for_alloc_id(
180+
&mut fx.constants_cx,
181+
fx.module,
182+
alloc_id,
183+
Mutability::Not,
184+
);
185+
let local_data_id =
186+
fx.module.declare_data_in_func(data_id, &mut fx.bcx.func);
187+
fx.bcx.ins().global_value(fx.pointer_type, local_data_id)
188+
}
180189
GlobalAlloc::Static(def_id) => {
181190
assert!(fx.tcx.is_static(def_id));
182191
let data_id = data_id_for_static(
@@ -362,7 +371,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
362371
GlobalAlloc::Memory(alloc) => alloc,
363372
GlobalAlloc::Function { .. }
364373
| GlobalAlloc::Static(_)
365-
| GlobalAlloc::Type(_)
374+
| GlobalAlloc::Type { .. }
366375
| GlobalAlloc::VTable(..) => {
367376
unreachable!()
368377
}
@@ -475,7 +484,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant
475484
.map(|principal| tcx.instantiate_bound_regions_with_erased(principal)),
476485
),
477486
// TODO
478-
GlobalAlloc::Type(_ty) => todo!(),
487+
GlobalAlloc::Type { .. } => todo!(),
479488
GlobalAlloc::Static(def_id) => {
480489
if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::THREAD_LOCAL)
481490
{

compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
812812
dest.write_cvalue(fx, val);
813813
}
814814

815-
sym::needs_drop | sym::type_id | sym::type_name | sym::variant_count => {
815+
sym::needs_drop | sym::type_name | sym::variant_count => {
816816
intrinsic_args!(fx, args => (); intrinsic);
817817

818818
let const_val = fx

compiler/rustc_codegen_gcc/src/common.rs

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
use gccjit::{LValue, RValue, ToRValue, Type};
2-
use rustc_abi as abi;
3-
use rustc_abi::HasDataLayout;
42
use rustc_abi::Primitive::Pointer;
3+
use rustc_abi::{self as abi, Align, HasDataLayout, Size};
54
use rustc_codegen_ssa::traits::{
65
BaseTypeCodegenMethods, ConstCodegenMethods, MiscCodegenMethods, StaticCodegenMethods,
76
};
7+
use rustc_const_eval::interpret::{AllocInit, Allocation, alloc_range};
88
use rustc_middle::mir::Mutability;
99
use rustc_middle::mir::interpret::{ConstAllocation, GlobalAlloc, Scalar};
1010
use rustc_middle::ty::layout::LayoutOf;
@@ -303,8 +303,30 @@ 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!(),
306+
GlobalAlloc::Type { ty: type_id_ty, segment } => {
307+
let type_id = self.tcx.type_id_hash(type_id_ty).as_u128();
308+
let mut alloc: Allocation = Allocation::new(
309+
Size::from_bytes(16),
310+
Align::from_bytes(8).unwrap(),
311+
AllocInit::Uninit,
312+
(),
313+
);
314+
alloc
315+
.write_scalar(
316+
&self.tcx,
317+
alloc_range(Size::ZERO, Size::from_bytes(16)),
318+
Scalar::from_u128(type_id),
319+
)
320+
.unwrap();
321+
let pointer_size = self.tcx.data_layout.pointer_size;
322+
let offset = pointer_size * u64::from(segment);
323+
let value = alloc
324+
.read_scalar(&self.tcx, alloc_range(offset, pointer_size), false)
325+
.unwrap();
326+
let data = value.to_bits(pointer_size).unwrap() as u64;
327+
let val = self.const_usize(data);
328+
return self.context.new_cast(None, val, ty);
329+
}
308330
GlobalAlloc::Static(def_id) => {
309331
assert!(self.tcx.is_static(def_id));
310332
self.get_static(def_id).get_address(None)

compiler/rustc_codegen_gcc/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ extern crate rustc_apfloat;
4141
extern crate rustc_ast;
4242
extern crate rustc_attr_data_structures;
4343
extern crate rustc_codegen_ssa;
44+
extern crate rustc_const_eval;
4445
extern crate rustc_data_structures;
4546
extern crate rustc_errors;
4647
extern crate rustc_fluent_macro;

compiler/rustc_codegen_llvm/src/common.rs

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::borrow::Borrow;
44

55
use libc::{c_char, c_uint};
66
use rustc_abi::Primitive::Pointer;
7-
use rustc_abi::{self as abi, Align, HasDataLayout, Size};
7+
use rustc_abi::{self as abi, Align, HasDataLayout as _, Size};
88
use rustc_ast::Mutability;
99
use rustc_codegen_ssa::common::TypeKind;
1010
use rustc_codegen_ssa::traits::*;
@@ -319,17 +319,16 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
319319
)))
320320
.unwrap_memory();
321321
let init = const_alloc_to_llvm(self, alloc.inner(), /*static*/ false);
322-
let value = self.static_addr_of_impl(init, alloc.inner().align, None);
323-
value
322+
self.static_addr_of_impl(init, alloc.inner().align, None)
324323
}
325324
GlobalAlloc::Static(def_id) => {
326325
assert!(self.tcx.is_static(def_id));
327326
assert!(!self.tcx.is_thread_local_static(def_id));
328327
self.get_static(def_id)
329328
}
330-
GlobalAlloc::Type(ty) => {
329+
GlobalAlloc::Type { ty, segment } => {
331330
let type_id = self.tcx.type_id_hash(ty).as_u128();
332-
let mut alloc = Allocation::new(
331+
let mut alloc: Allocation = Allocation::new(
333332
Size::from_bytes(16),
334333
Align::from_bytes(8).unwrap(),
335334
AllocInit::Uninit,
@@ -342,17 +341,13 @@ impl<'ll, 'tcx> ConstCodegenMethods for CodegenCx<'ll, 'tcx> {
342341
Scalar::from_u128(type_id),
343342
)
344343
.unwrap();
345-
alloc.mutability = Mutability::Not;
346-
let init = const_alloc_to_llvm(self, &alloc, /*static*/ false);
347-
self.static_addr_of_impl(init, alloc.align, None)
348-
}
349-
GlobalAlloc::PartialHash(ty) => {
350-
assert!(matches!(layout.primitive(), Pointer(_)));
351-
let bytes = self.tcx.type_id_hash(ty).truncate().as_u64().to_be_bytes();
352-
let bits = self.tcx.data_layout.pointer_size.bits();
353-
let mask = u64::MAX >> (64 - bits);
354-
// It doesn't matter which bits we pick as long as the scheme is the same with the same compiler.
355-
let llval = self.const_usize(u64::from_be_bytes(bytes) & mask);
344+
let pointer_size = self.tcx.data_layout.pointer_size;
345+
let offset = pointer_size * u64::from(segment);
346+
let value = alloc
347+
.read_scalar(&self.tcx, alloc_range(offset, pointer_size), false)
348+
.unwrap();
349+
let data = value.to_bits(pointer_size).unwrap() as u64;
350+
let llval = self.const_usize(data);
356351
return unsafe { llvm::LLVMConstIntToPtr(llval, llty) };
357352
}
358353
};

compiler/rustc_codegen_ssa/src/mir/intrinsic.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
150150
}
151151
value
152152
}
153-
sym::needs_drop | sym::type_id | sym::type_name | sym::variant_count => {
153+
sym::needs_drop | sym::type_name | sym::variant_count => {
154154
let value = bx.tcx().const_eval_instance(bx.typing_env(), instance, span).unwrap();
155155
OperandRef::from_const(bx, value, result.layout.ty).immediate_or_packed_pair(bx)
156156
}

compiler/rustc_codegen_ssa/src/mir/operand.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
185185
offset: Size,
186186
) -> Self {
187187
let alloc_align = alloc.inner().align;
188-
assert!(alloc_align >= layout.align.abi);
188+
assert!(alloc_align >= layout.align.abi, "{alloc_align:?} < {:?}", layout.align.abi);
189189

190190
let read_scalar = |start, size, s: abi::Scalar, ty| {
191191
match alloc.0.read_scalar(

compiler/rustc_const_eval/src/const_eval/machine.rs

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -405,18 +405,34 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> {
405405
}
406406
sym::type_id_eq => {
407407
let a = ecx.project_field(&args[0], FieldIdx::ZERO)?;
408-
let a = ecx.deref_pointer(&a)?;
409-
let (a, offset) = a.ptr().into_parts();
410-
assert_eq!(offset, Size::ZERO);
411-
let a = a.unwrap().alloc_id();
412-
let GlobalAlloc::Type(a) = ecx.tcx.global_alloc(a) else { bug!() };
413408
let b = ecx.project_field(&args[1], FieldIdx::ZERO)?;
414-
let b = ecx.deref_pointer(&b)?;
415-
let (b, offset) = b.ptr().into_parts();
416-
assert_eq!(offset, Size::ZERO);
417-
let b = b.unwrap().alloc_id();
418-
let GlobalAlloc::Type(b) = ecx.tcx.global_alloc(b) else { bug!() };
419-
ecx.write_scalar(Scalar::from_bool(a == b), dest)?;
409+
let mut eq = true;
410+
for index in 0..(16 / ecx.tcx.data_layout.pointer_size.bytes()) {
411+
let a = ecx.project_index(&a, index)?;
412+
let a = ecx.deref_pointer(&a)?;
413+
let (a, offset) = a.ptr().into_parts();
414+
assert_eq!(offset, Size::ZERO);
415+
let a = a.unwrap().alloc_id();
416+
let GlobalAlloc::Type { ty: a, segment: a_segment } = ecx.tcx.global_alloc(a)
417+
else {
418+
bug!()
419+
};
420+
let b = ecx.project_index(&b, index)?;
421+
let b = ecx.deref_pointer(&b)?;
422+
let (b, offset) = b.ptr().into_parts();
423+
assert_eq!(offset, Size::ZERO);
424+
let b = b.unwrap().alloc_id();
425+
let GlobalAlloc::Type { ty: b, segment: b_segment } = ecx.tcx.global_alloc(b)
426+
else {
427+
bug!()
428+
};
429+
430+
eq &= a == b && a_segment == b_segment;
431+
if !eq {
432+
break;
433+
}
434+
}
435+
ecx.write_scalar(Scalar::from_bool(eq), dest)?;
420436
}
421437
sym::const_allocate => {
422438
let size = ecx.read_scalar(&args[0])?.to_target_usize(ecx)?;

compiler/rustc_const_eval/src/interpret/intrinsics.rs

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_abi::Size;
88
use rustc_apfloat::ieee::{Double, Half, Quad, Single};
99
use rustc_ast::Mutability;
1010
use rustc_hir::def_id::DefId;
11-
use rustc_middle::mir::interpret::{AllocId, AllocInit, CtfeProvenance, alloc_range};
11+
use rustc_middle::mir::interpret::{AllocId, AllocInit, alloc_range};
1212
use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic};
1313
use rustc_middle::ty::layout::{LayoutOf as _, TyAndLayout, ValidityRequirement};
1414
use rustc_middle::ty::{GenericArgsRef, Ty, TyCtxt};
@@ -33,24 +33,17 @@ pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAll
3333
}
3434

3535
pub(crate) fn alloc_type_id<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> AllocId {
36-
let ptr_size = tcx.data_layout.pointer_size;
36+
let size = Size::from_bytes(16);
3737
let align = tcx.data_layout.pointer_align;
38-
39-
let mut alloc = Allocation::new(ptr_size * 2, *align, AllocInit::Uninit, ());
40-
// Write a pointer pointing to the hash. At ctfe time this is an opaque pointer that you cannot deref
41-
let ptr = tcx.reserve_and_set_type_id_alloc(ty);
42-
let ptr = Pointer::new(CtfeProvenance::from(ptr), Size::ZERO);
43-
alloc
44-
.write_scalar(&tcx, alloc_range(Size::ZERO, ptr_size), Scalar::from_pointer(ptr, &tcx))
45-
.unwrap();
46-
47-
// Write a pointer that is not actually a pointer but will just get replaced by the first `pointer_size` bytes of the hash
48-
// in codegen. It is a pointer in CTFE so no one can access the bits.
49-
let ptr = tcx.reserve_and_set_type_id_partial_hash(ty);
50-
let ptr = Pointer::new(CtfeProvenance::from(ptr), Size::ZERO);
51-
alloc
52-
.write_scalar(&tcx, alloc_range(ptr_size, ptr_size), Scalar::from_pointer(ptr, &tcx))
53-
.unwrap();
38+
let mut alloc = Allocation::new(size, *align, AllocInit::Uninit, ());
39+
let ptr_size = tcx.data_layout.pointer_size;
40+
for step in 0..size.bytes() / ptr_size.bytes() {
41+
let offset = ptr_size * step;
42+
let alloc_id = tcx.reserve_and_set_type_id_alloc(ty, step.try_into().unwrap());
43+
let ptr = Pointer::new(alloc_id.into(), Size::ZERO);
44+
let val = Scalar::from_pointer(ptr, &tcx);
45+
alloc.write_scalar(&tcx, alloc_range(offset, ptr_size), val).unwrap();
46+
}
5447

5548
alloc.mutability = Mutability::Not;
5649

compiler/rustc_const_eval/src/interpret/memory.rs

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -346,20 +346,13 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
346346
kind = "vtable",
347347
)
348348
}
349-
Some(GlobalAlloc::Type(..)) => {
349+
Some(GlobalAlloc::Type { .. }) => {
350350
err_ub_custom!(
351351
fluent::const_eval_invalid_dealloc,
352352
alloc_id = alloc_id,
353353
kind = "typeid",
354354
)
355355
}
356-
Some(GlobalAlloc::PartialHash(..)) => {
357-
err_ub_custom!(
358-
fluent::const_eval_invalid_dealloc,
359-
alloc_id = alloc_id,
360-
kind = "partial_hash",
361-
)
362-
}
363356
Some(GlobalAlloc::Static(..) | GlobalAlloc::Memory(..)) => {
364357
err_ub_custom!(
365358
fluent::const_eval_invalid_dealloc,
@@ -629,9 +622,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
629622
}
630623
Some(GlobalAlloc::Function { .. }) => throw_ub!(DerefFunctionPointer(id)),
631624
Some(GlobalAlloc::VTable(..)) => throw_ub!(DerefVTablePointer(id)),
632-
Some(GlobalAlloc::Type(..)) | Some(GlobalAlloc::PartialHash(..)) => {
633-
throw_ub!(DerefTypeIdPointer(id))
634-
}
625+
Some(GlobalAlloc::Type { .. }) => throw_ub!(DerefTypeIdPointer(id)),
635626
None => throw_ub!(PointerUseAfterFree(id, CheckInAllocMsg::MemoryAccess)),
636627
Some(GlobalAlloc::Static(def_id)) => {
637628
assert!(self.tcx.is_static(def_id));
@@ -908,8 +899,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
908899
let (size, align) = global_alloc.size_and_align(*self.tcx, self.typing_env);
909900
let mutbl = global_alloc.mutability(*self.tcx, self.typing_env);
910901
let kind = match global_alloc {
911-
GlobalAlloc::Type(_)
912-
| GlobalAlloc::PartialHash(_)
902+
GlobalAlloc::Type { .. }
913903
| GlobalAlloc::Static { .. }
914904
| GlobalAlloc::Memory { .. } => AllocKind::LiveData,
915905
GlobalAlloc::Function { .. } => bug!("We already checked function pointers above"),
@@ -1221,11 +1211,8 @@ impl<'a, 'tcx, M: Machine<'tcx>> std::fmt::Debug for DumpAllocs<'a, 'tcx, M> {
12211211
Some(GlobalAlloc::VTable(ty, dyn_ty)) => {
12221212
write!(fmt, " (vtable: impl {dyn_ty} for {ty})")?;
12231213
}
1224-
Some(GlobalAlloc::Type(ty)) => {
1225-
write!(fmt, " (typeid for {ty})")?;
1226-
}
1227-
Some(GlobalAlloc::PartialHash(ty)) => {
1228-
write!(fmt, " (partial hash of {ty})")?;
1214+
Some(GlobalAlloc::Type { ty, segment }) => {
1215+
write!(fmt, " (typeid segment {segment } for {ty})")?;
12291216
}
12301217
Some(GlobalAlloc::Static(did)) => {
12311218
write!(fmt, " (static: {})", self.ecx.tcx.def_path_str(did))?;

compiler/rustc_const_eval/src/interpret/validity.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -604,9 +604,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValidityVisitor<'rt, 'tcx, M> {
604604
}
605605
}
606606
// These are controlled by rustc and not available for CTFE
607-
GlobalAlloc::Type(_) | GlobalAlloc::PartialHash(_) => {
608-
skip_recursive_check = true
609-
}
607+
GlobalAlloc::Type { .. } => skip_recursive_check = true,
610608
_ => (),
611609
}
612610

0 commit comments

Comments
 (0)