|
3 | 3 | use std::cmp::Ordering; |
4 | 4 |
|
5 | 5 | use cranelift_module::*; |
| 6 | +use rustc_abi::Align; |
| 7 | +use rustc_const_eval::interpret::{AllocInit, Allocation, alloc_range}; |
6 | 8 | use rustc_data_structures::fx::FxHashSet; |
7 | 9 | use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; |
8 | 10 | use rustc_middle::mir::interpret::{AllocId, GlobalAlloc, Scalar, read_target_uint}; |
@@ -175,8 +177,13 @@ pub(crate) fn codegen_const_value<'tcx>( |
175 | 177 | fx.module.declare_data_in_func(data_id, &mut fx.bcx.func); |
176 | 178 | fx.bcx.ins().global_value(fx.pointer_type, local_data_id) |
177 | 179 | } |
178 | | - // TODO: generate pointer to allocation containing the actual type id hash u128 value |
179 | | - GlobalAlloc::Type(_) => todo!(), |
| 180 | + GlobalAlloc::Type { ty: type_id_ty, segment } => { |
| 181 | + return CValue::const_val( |
| 182 | + fx, |
| 183 | + layout, |
| 184 | + type_id_segment(fx.tcx, type_id_ty, segment), |
| 185 | + ); |
| 186 | + } |
180 | 187 | GlobalAlloc::Static(def_id) => { |
181 | 188 | assert!(fx.tcx.is_static(def_id)); |
182 | 189 | let data_id = data_id_for_static( |
@@ -214,6 +221,23 @@ pub(crate) fn codegen_const_value<'tcx>( |
214 | 221 | } |
215 | 222 | } |
216 | 223 |
|
| 224 | +fn type_id_segment<'tcx>(tcx: TyCtxt<'tcx>, type_id_ty: Ty<'tcx>, segment: u8) -> ScalarInt { |
| 225 | + let type_id = tcx.type_id_hash(type_id_ty).as_u128(); |
| 226 | + let mut alloc: Allocation = |
| 227 | + Allocation::new(Size::from_bytes(16), Align::from_bytes(8).unwrap(), AllocInit::Uninit, ()); |
| 228 | + alloc |
| 229 | + .write_scalar( |
| 230 | + &tcx, |
| 231 | + alloc_range(Size::ZERO, Size::from_bytes(16)), |
| 232 | + Scalar::from_u128(type_id), |
| 233 | + ) |
| 234 | + .unwrap(); |
| 235 | + let pointer_size = tcx.data_layout.pointer_size; |
| 236 | + let offset = pointer_size * u64::from(segment); |
| 237 | + let value = alloc.read_scalar(&tcx, alloc_range(offset, pointer_size), false).unwrap(); |
| 238 | + value.to_scalar_int().unwrap() |
| 239 | +} |
| 240 | + |
217 | 241 | fn pointer_for_allocation<'tcx>( |
218 | 242 | fx: &mut FunctionCx<'_, '_, 'tcx>, |
219 | 243 | alloc_id: AllocId, |
@@ -362,7 +386,7 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant |
362 | 386 | GlobalAlloc::Memory(alloc) => alloc, |
363 | 387 | GlobalAlloc::Function { .. } |
364 | 388 | | GlobalAlloc::Static(_) |
365 | | - | GlobalAlloc::Type(_) |
| 389 | + | GlobalAlloc::Type { .. } |
366 | 390 | | GlobalAlloc::VTable(..) => { |
367 | 391 | unreachable!() |
368 | 392 | } |
@@ -474,8 +498,18 @@ fn define_all_allocs(tcx: TyCtxt<'_>, module: &mut dyn Module, cx: &mut Constant |
474 | 498 | .principal() |
475 | 499 | .map(|principal| tcx.instantiate_bound_regions_with_erased(principal)), |
476 | 500 | ), |
477 | | - // TODO |
478 | | - GlobalAlloc::Type(_ty) => todo!(), |
| 501 | + GlobalAlloc::Type { ty, segment } => { |
| 502 | + let val = type_id_segment(tcx, ty, segment); |
| 503 | + let Init::Bytes { contents } = &mut data.init else { unreachable!() }; |
| 504 | + let start = offset.bytes_usize(); |
| 505 | + let ptr_size = tcx.data_layout.pointer_size; |
| 506 | + let src = val.to_bits(ptr_size); |
| 507 | + let src = u128::to_le_bytes(src); |
| 508 | + let len = ptr_size.bytes_usize(); |
| 509 | + assert!(src[len..].iter().all(|b| *b == 0)); |
| 510 | + contents[start..(start + len)].copy_from_slice(&src[..len]); |
| 511 | + continue; |
| 512 | + } |
479 | 513 | GlobalAlloc::Static(def_id) => { |
480 | 514 | if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::THREAD_LOCAL) |
481 | 515 | { |
|
0 commit comments