about summary refs log tree commit diff
path: root/compiler/rustc_codegen_llvm
diff options
context:
space:
mode:
authorHans Kratz <hans@appfour.com>2021-07-19 09:27:18 +0200
committerHans Kratz <hans@appfour.com>2021-08-04 23:36:13 +0200
commite4106581de25d31d94695372b299aa2c8b0bce8e (patch)
tree0590f3fbe8487cb8240f89f2e6ee05402030354b /compiler/rustc_codegen_llvm
parent60a523de9207d0465a32cee5fd96820b116ff64c (diff)
downloadrust-e4106581de25d31d94695372b299aa2c8b0bce8e.tar.gz
rust-e4106581de25d31d94695372b299aa2c8b0bce8e.zip
Replace on-the-fly llvm field index calculation with cache
Diffstat (limited to 'compiler/rustc_codegen_llvm')
-rw-r--r--compiler/rustc_codegen_llvm/src/context.rs6
-rw-r--r--compiler/rustc_codegen_llvm/src/type_of.rs25
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<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
     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<FxHashMap<TyAndLayout<'tcx>, Vec<u32>>>,
+
     pub coverage_cx: Option<coverageinfo::CrateCoverageContext<'ll, 'tcx>>,
     pub dbg_cx: Option<debuginfo::CrateDebugContext<'ll, 'tcx>>,
 
@@ -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)
-            }
+            },
         }
     }