/// See <https://llvm.org/docs/LangRef.html#the-llvm-used-global-variable> for details
pub used_statics: RefCell<Vec<&'ll Value>>,
- pub lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), &'ll Type>>,
+ /// Mapping of non-scalar types to llvm types and field remapping if needed.
+ pub type_lowering: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), TypeLowering<'ll>>>,
+
+ /// Mapping of scalar types to llvm types.
pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, &'ll Type>>,
+
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,
- /// only present if synthetic fields are inserted for padding.
- 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>>,
local_gen_sym_counter: Cell<usize>,
}
+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<Box<[u32]>>,
+}
+
fn to_llvm_tls_model(tls_model: TlsModel) -> llvm::ThreadLocalMode {
match tls_model {
TlsModel::GeneralDynamic => llvm::ThreadLocalMode::GeneralDynamic,
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),
use crate::abi::FnAbi;
use crate::common::*;
+use crate::context::TypeLowering;
use crate::type_::Type;
use rustc_codegen_ssa::traits::*;
use rustc_middle::bug;
cx: &CodegenCx<'a, 'tcx>,
layout: TyAndLayout<'tcx>,
defer: &mut Option<(&'a Type, TyAndLayout<'tcx>)>,
+ field_remapping: &mut Option<Box<[u32]>>,
) -> &'a Type {
match layout.abi {
Abi::Scalar(_) => bug!("handled elsewhere"),
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) => {
fn struct_llfields<'a, 'tcx>(
cx: &CodegenCx<'a, 'tcx>,
layout: TyAndLayout<'tcx>,
-) -> (Vec<&'a Type>, bool) {
+) -> (Vec<&'a Type>, bool, Option<Box<[u32]>>) {
debug!("struct_llfields: {:#?}", layout);
let field_count = layout.fields.count();
} 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> {
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);
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 {
}
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
}
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)
+ }
+ }
+ }
}
}