From e4106581de25d31d94695372b299aa2c8b0bce8e Mon Sep 17 00:00:00 2001 From: Hans Kratz Date: Mon, 19 Jul 2021 09:27:18 +0200 Subject: [PATCH] Replace on-the-fly llvm field index calculation with cache --- compiler/rustc_codegen_llvm/src/context.rs | 6 ++++++ compiler/rustc_codegen_llvm/src/type_of.rs | 25 +++++++--------------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 59259857b4b..52de4bcd737 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -79,6 +79,11 @@ pub struct CodegenCx<'ll, 'tcx> { pub pointee_infos: RefCell, Size), Option>>, pub isize_ty: &'ll Type, + /// Cache for the mapping from source index to llvm index for struct fields, + /// necessary because the mapping depends on padding and thus depens on + /// TyAndLayout. + pub field_projection_cache: RefCell, Vec>>, + pub coverage_cx: Option>, pub dbg_cx: Option>, @@ -308,6 +313,7 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { 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 91d4cfdd77b..ad969658895 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -98,6 +98,7 @@ fn struct_llfields<'a, 'tcx>( let mut offset = Size::ZERO; let mut prev_effective_align = layout.align.abi; let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2); + let mut projection = vec![0; field_count]; for i in layout.fields.index_by_increasing_offset() { let target_offset = layout.fields.offset(i as usize); let field = layout.field(cx, i); @@ -122,6 +123,7 @@ fn struct_llfields<'a, 'tcx>( result.push(cx.type_padding_filler(padding, padding_align)); debug!(" padding before: {:?}", padding); } + projection[i] = result.len() as u32; result.push(field.llvm_type(cx)); offset = target_offset + field.size; prev_effective_align = effective_field_align; @@ -143,6 +145,7 @@ fn struct_llfields<'a, 'tcx>( } else { debug!("struct_llfields: offset: {:?} stride: {:?}", offset, layout.size); } + cx.field_projection_cache.borrow_mut().insert(layout, projection); (result, packed) } @@ -356,24 +359,12 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { FieldsShape::Array { .. } => index as u64, - FieldsShape::Arbitrary { .. } => { - let mut llvm_index = 0; - let mut offset = Size::ZERO; - for i in self.fields.index_by_increasing_offset() { - let target_offset = self.fields.offset(i as usize); - let field = self.field(cx, i); - let padding = target_offset - offset; - if padding != Size::ZERO { - llvm_index += 1; - } - if i == index { - return llvm_index; - } - offset = target_offset + field.size; - llvm_index += 1; + FieldsShape::Arbitrary { .. } => match cx.field_projection_cache.borrow().get(self) { + Some(projection) => projection[index] as u64, + None => { + bug!("TyAndLayout::llvm_field_index({:?}): field projection not cached", self) } - bug!("TyAndLayout::llvm_field_index({:?}): index {} out of range", self, index) - } + }, } }