From 4a4e9e3cf81e8c85880d8da521ab16f253c93392 Mon Sep 17 00:00:00 2001 From: Hans Kratz Date: Thu, 5 Aug 2021 19:14:55 +0200 Subject: [PATCH] Store field remapping information together with the LLVM type in a new TypeLowering struct instead of an extra cache. --- compiler/rustc_codegen_llvm/src/context.rs | 22 ++++++--- compiler/rustc_codegen_llvm/src/type_of.rs | 54 ++++++++++++++-------- 2 files changed, 50 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index b088b6e730b..d28a579ff10 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -74,15 +74,15 @@ pub struct CodegenCx<'ll, 'tcx> { /// See for details pub used_statics: RefCell>, - pub lltypes: RefCell, Option), &'ll Type>>, + /// Mapping of non-scalar types to llvm types and field remapping if needed. + pub type_lowering: RefCell, Option), TypeLowering<'ll>>>, + + /// Mapping of scalar types to llvm types. pub scalar_lltypes: RefCell, &'ll Type>>, + pub pointee_infos: RefCell, Size), Option>>, pub isize_ty: &'ll Type, - /// Cache for the mapping from source index to llvm index for struct fields, - /// only present if synthetic fields are inserted for padding. - pub field_projection_cache: RefCell, Vec>>, - pub coverage_cx: Option>, pub dbg_cx: Option>, @@ -96,6 +96,15 @@ pub struct CodegenCx<'ll, 'tcx> { local_gen_sym_counter: Cell, } +pub struct TypeLowering<'ll> { + /// Associated LLVM type + pub lltype: &'ll Type, + + /// If padding is used the slice maps fields from source order + /// to llvm order. + pub field_remapping: Option>, +} + fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode { match tls_model { TlsModel::GeneralDynamic => llvm::ThreadLocalMode::GeneralDynamic, @@ -308,11 +317,10 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { const_globals: Default::default(), statics_to_rauw: RefCell::new(Vec::new()), used_statics: RefCell::new(Vec::new()), - lltypes: Default::default(), + type_lowering: Default::default(), scalar_lltypes: Default::default(), pointee_infos: Default::default(), isize_ty, - field_projection_cache: Default::default(), coverage_cx, dbg_cx, eh_personality: Cell::new(None), diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index 79bf51929e9..24669bec965 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -1,5 +1,6 @@ use crate::abi::FnAbi; use crate::common::*; +use crate::context::TypeLowering; use crate::type_::Type; use rustc_codegen_ssa::traits::*; use rustc_middle::bug; @@ -17,6 +18,7 @@ fn uncached_llvm_type<'a, 'tcx>( cx: &CodegenCx<'a, 'tcx>, layout: TyAndLayout<'tcx>, defer: &mut Option<(&'a Type, TyAndLayout<'tcx>)>, + field_remapping: &mut Option>, ) -> &'a Type { match layout.abi { Abi::Scalar(_) => bug!("handled elsewhere"), @@ -75,7 +77,8 @@ fn uncached_llvm_type<'a, 'tcx>( FieldsShape::Array { count, .. } => cx.type_array(layout.field(cx, 0).llvm_type(cx), count), FieldsShape::Arbitrary { .. } => match name { None => { - let (llfields, packed) = struct_llfields(cx, layout); + let (llfields, packed, new_field_remapping) = struct_llfields(cx, layout); + *field_remapping = new_field_remapping; cx.type_struct(&llfields, packed) } Some(ref name) => { @@ -90,7 +93,7 @@ fn uncached_llvm_type<'a, 'tcx>( fn struct_llfields<'a, 'tcx>( cx: &CodegenCx<'a, 'tcx>, layout: TyAndLayout<'tcx>, -) -> (Vec<&'a Type>, bool) { +) -> (Vec<&'a Type>, bool, Option>) { debug!("struct_llfields: {:#?}", layout); let field_count = layout.fields.count(); @@ -147,11 +150,8 @@ fn struct_llfields<'a, 'tcx>( } else { debug!("struct_llfields: offset: {:?} stride: {:?}", offset, layout.size); } - if padding_used { - cx.field_projection_cache.borrow_mut().insert(layout, projection); - } - (result, packed) + (result, packed, padding_used.then_some(projection.into_boxed_slice())) } impl<'a, 'tcx> CodegenCx<'a, 'tcx> { @@ -243,8 +243,8 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type { Variants::Single { index } => Some(index), _ => None, }; - if let Some(&llty) = cx.lltypes.borrow().get(&(self.ty, variant_index)) { - return llty; + if let Some(ref llty) = cx.type_lowering.borrow().get(&(self.ty, variant_index)) { + return llty.lltype; } debug!("llvm_type({:#?})", self); @@ -256,6 +256,7 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type { let normal_ty = cx.tcx.erase_regions(self.ty); let mut defer = None; + let mut field_remapping = None; let llty = if self.ty != normal_ty { let mut layout = cx.layout_of(normal_ty); if let Some(v) = variant_index { @@ -263,17 +264,21 @@ fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type { } layout.llvm_type(cx) } else { - uncached_llvm_type(cx, *self, &mut defer) + uncached_llvm_type(cx, *self, &mut defer, &mut field_remapping) }; debug!("--> mapped {:#?} to llty={:?}", self, llty); - cx.lltypes.borrow_mut().insert((self.ty, variant_index), llty); + cx.type_lowering + .borrow_mut() + .insert((self.ty, variant_index), TypeLowering { lltype: llty, field_remapping: None }); if let Some((llty, layout)) = defer { - let (llfields, packed) = struct_llfields(cx, layout); - cx.set_struct_body(llty, &llfields, packed) + let (llfields, packed, new_field_remapping) = struct_llfields(cx, layout); + cx.set_struct_body(llty, &llfields, packed); + field_remapping = new_field_remapping; } - + cx.type_lowering.borrow_mut().get_mut(&(self.ty, variant_index)).unwrap().field_remapping = + field_remapping; llty } @@ -363,12 +368,23 @@ fn llvm_field_index<'a>(&self, cx: &CodegenCx<'a, 'tcx>, index: usize) -> u64 { FieldsShape::Array { .. } => index as u64, - // Look up llvm field index in projection cache if present. If no projection cache - // is present no padding is used and the llvm field index matches the memory index. - FieldsShape::Arbitrary { .. } => match cx.field_projection_cache.borrow().get(self) { - Some(projection) => projection[index] as u64, - None => self.fields.memory_index(index) as u64, - }, + FieldsShape::Arbitrary { .. } => { + let variant_index = match self.variants { + Variants::Single { index } => Some(index), + _ => None, + }; + + // Look up llvm field if indexes do not match memory order due to padding. If + // `field_remapping` is `None` no padding was used and the llvm field index + // matches the memory index. + match cx.type_lowering.borrow().get(&(self.ty, variant_index)) { + Some(TypeLowering { field_remapping: Some(ref prj), .. }) => prj[index] as u64, + Some(_) => self.fields.memory_index(index) as u64, + None => { + bug!("TyAndLayout::llvm_field_index({:?}): type info not found", self) + } + } + } } } -- 2.44.0